Skip to content

Commit d53cd22

Browse files
committed
Solved bug that caused event display to drift wrt ephys display. It was due to incorrect use of mutex.
1 parent 7cf15de commit d53cd22

3 files changed

Lines changed: 109 additions & 99 deletions

File tree

Plugins/LfpDisplayNodeBeta/LfpDisplayCanvas.cpp

Lines changed: 97 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -184,27 +184,42 @@ void LfpDisplayCanvas::update()
184184

185185
for (int i = 0; i <= nChans; i++) // extra channel for events
186186
{
187-
if (processor->getNumInputs() > 0)
188-
{
189-
if (i < nChans)
190-
sampleRate.add(processor->getDataChannel(i)->getSampleRate());
191-
else
192-
{
193-
//Since for now the canvas only supports one event channel, find the first TTL one and use that as sampleRate.
194-
//This is a bit hackish and should be fixed for proper multi-ttl-channel support
195-
for (int c = 0; c < processor->getTotalEventChannels(); c++)
196-
{
197-
if (processor->getEventChannel(c)->getChannelType() == EventChannel::TTL)
198-
{
199-
sampleRate.add(processor->getEventChannel(c)->getSampleRate());
200-
}
201-
}
202-
}
203-
}
204-
else
205-
sampleRate.add(30000);
187+
if (processor->getNumInputs() > 0)
188+
{
189+
if (i < nChans) {
190+
sampleRate.add(processor->getDataChannel(i)->getSampleRate());
191+
}
192+
else
193+
{
194+
//Since for now the canvas only supports one event channel, find the first TTL one and use that as sampleRate.
195+
//This is a bit hackish and should be fixed for proper multi-ttl-channel support
196+
bool got = false;
197+
for (int c = 0; c < processor->getTotalEventChannels(); c++)
198+
{
199+
if (processor->getEventChannel(c)->getChannelType() == EventChannel::TTL)
200+
{
201+
sampleRate.add(processor->getEventChannel(c)->getSampleRate());
202+
got = true;
203+
break;
204+
}
205+
}
206+
if (!got) {
207+
if (i>0) {
208+
sampleRate.add(sampleRate[0]);
209+
printf("DID NOT FIND AN EVENT CHANNEL. GUESSING SAMPLE RATE FROM OTHER CHANNEL: %g Hz\n", sampleRate[i] + 0.0);
210+
} else {
211+
sampleRate.add(30000);
212+
printf("DID NOT FIND AN EVENT CHANNEL. WILDLY GUESSING SAMPLE RATE: %g Hz\n", sampleRate[i] + 0.0);
213+
}
214+
}
215+
}
216+
}
217+
else
218+
{
219+
sampleRate.add(30000);
220+
}
206221

207-
// std::cout << "Sample rate for ch " << i << " = " << sampleRate[i] << std::endl;
222+
// std::cout << "Sample rate for ch " << i << " = " << sampleRate[i] << std::endl;
208223
displayBufferIndex.add(0);
209224
screenBufferIndex.add(0);
210225
lastScreenBufferIndex.add(0);
@@ -221,7 +236,6 @@ void LfpDisplayCanvas::update()
221236
// update channel names
222237
for (int i = 0; i < processor->getNumInputs(); i++)
223238
{
224-
225239
String chName = processor->getDataChannel(i)->getName();
226240

227241
//std::cout << chName << std::endl;
@@ -266,19 +280,15 @@ void LfpDisplayCanvas::setParameter(int param, float val)
266280
void LfpDisplayCanvas::refreshState()
267281
{
268282
// called when the component's tab becomes visible again
269-
270-
for (int i = 0; i <= displayBufferIndex.size(); i++) // include event channel
283+
for (int i = 0; i < displayBufferIndex.size(); i++)
271284
{
272-
273285
displayBufferIndex.set(i, processor->getDisplayBufferIndex(i));
274286
screenBufferIndex.set(i,0);
275287
}
276-
277288
}
278289

279290
void LfpDisplayCanvas::refreshScreenBuffer()
280291
{
281-
282292
for (int i = 0; i < screenBufferIndex.size(); i++)
283293
screenBufferIndex.set(i,0);
284294

@@ -290,24 +300,22 @@ void LfpDisplayCanvas::refreshScreenBuffer()
290300
}
291301

292302
void LfpDisplayCanvas::updateScreenBuffer()
293-
{
294-
303+
{
295304
// copy new samples from the displayBuffer into the screenBuffer
296305
int maxSamples = lfpDisplay->getWidth() - leftmargin;
297306

298-
ScopedLock displayLock(*processor->getMutex());
307+
ScopedLock displayLock(*processor->getMutex());
299308

300309
for (int channel = 0; channel <= nChans; channel++) // pull one extra channel for event display
301310
{
302-
303311
if (screenBufferIndex[channel] >= maxSamples) // wrap around if we reached right edge before
304312
screenBufferIndex.set(channel, 0);
305313

306314
// hold these values locally for each channel - is this a good idea?
307315
int sbi = screenBufferIndex[channel];
308316
int dbi = displayBufferIndex[channel];
309317

310-
lastScreenBufferIndex.set(channel,sbi);
318+
lastScreenBufferIndex.set(channel, sbi);
311319

312320
int index = processor->getDisplayBufferIndex(channel);
313321

@@ -672,21 +680,21 @@ LfpDisplayOptions::LfpDisplayOptions(LfpDisplayCanvas* canvas_, LfpTimescale* ti
672680
selectedChannelType(DataChannel::HEADSTAGE_CHANNEL)
673681
{
674682
//Ranges for neural data
675-
voltageRanges[DataChannel::HEADSTAGE_CHANNEL].add("25");
676-
voltageRanges[DataChannel::HEADSTAGE_CHANNEL].add("50");
677-
voltageRanges[DataChannel::HEADSTAGE_CHANNEL].add("100");
678-
voltageRanges[DataChannel::HEADSTAGE_CHANNEL].add("250");
679-
voltageRanges[DataChannel::HEADSTAGE_CHANNEL].add("400");
680-
voltageRanges[DataChannel::HEADSTAGE_CHANNEL].add("500");
681-
voltageRanges[DataChannel::HEADSTAGE_CHANNEL].add("750");
682-
voltageRanges[DataChannel::HEADSTAGE_CHANNEL].add("1000");
683-
voltageRanges[DataChannel::HEADSTAGE_CHANNEL].add("2000");
684-
voltageRanges[DataChannel::HEADSTAGE_CHANNEL].add("5000");
685-
voltageRanges[DataChannel::HEADSTAGE_CHANNEL].add("10000");
686-
voltageRanges[DataChannel::HEADSTAGE_CHANNEL].add("15000");
687-
selectedVoltageRange[DataChannel::HEADSTAGE_CHANNEL] = 8;
688-
rangeGain[DataChannel::HEADSTAGE_CHANNEL] = 1; //uV
689-
rangeSteps[DataChannel::HEADSTAGE_CHANNEL] = 10;
683+
voltageRanges[DataChannel::HEADSTAGE_CHANNEL].add("25");
684+
voltageRanges[DataChannel::HEADSTAGE_CHANNEL].add("50");
685+
voltageRanges[DataChannel::HEADSTAGE_CHANNEL].add("100");
686+
voltageRanges[DataChannel::HEADSTAGE_CHANNEL].add("250");
687+
voltageRanges[DataChannel::HEADSTAGE_CHANNEL].add("400");
688+
voltageRanges[DataChannel::HEADSTAGE_CHANNEL].add("500");
689+
voltageRanges[DataChannel::HEADSTAGE_CHANNEL].add("750");
690+
voltageRanges[DataChannel::HEADSTAGE_CHANNEL].add("1000");
691+
voltageRanges[DataChannel::HEADSTAGE_CHANNEL].add("2000");
692+
voltageRanges[DataChannel::HEADSTAGE_CHANNEL].add("5000");
693+
voltageRanges[DataChannel::HEADSTAGE_CHANNEL].add("10000");
694+
voltageRanges[DataChannel::HEADSTAGE_CHANNEL].add("15000");
695+
selectedVoltageRange[DataChannel::HEADSTAGE_CHANNEL] = 8;
696+
rangeGain[DataChannel::HEADSTAGE_CHANNEL] = 1; //uV
697+
rangeSteps[DataChannel::HEADSTAGE_CHANNEL] = 10;
690698
rangeUnits.add("uV");
691699
typeNames.add("DATA");
692700

@@ -702,19 +710,19 @@ LfpDisplayOptions::LfpDisplayOptions(LfpDisplayCanvas* canvas_, LfpTimescale* ti
702710
typeButtons.add(tbut);
703711

704712
//Ranges for AUX/accelerometer data
705-
voltageRanges[DataChannel::AUX_CHANNEL].add("25");
706-
voltageRanges[DataChannel::AUX_CHANNEL].add("50");
707-
voltageRanges[DataChannel::AUX_CHANNEL].add("100");
708-
voltageRanges[DataChannel::AUX_CHANNEL].add("250");
709-
voltageRanges[DataChannel::AUX_CHANNEL].add("400");
710-
voltageRanges[DataChannel::AUX_CHANNEL].add("500");
711-
voltageRanges[DataChannel::AUX_CHANNEL].add("750");
712-
voltageRanges[DataChannel::AUX_CHANNEL].add("1000");
713-
voltageRanges[DataChannel::AUX_CHANNEL].add("2000");
713+
voltageRanges[DataChannel::AUX_CHANNEL].add("25");
714+
voltageRanges[DataChannel::AUX_CHANNEL].add("50");
715+
voltageRanges[DataChannel::AUX_CHANNEL].add("100");
716+
voltageRanges[DataChannel::AUX_CHANNEL].add("250");
717+
voltageRanges[DataChannel::AUX_CHANNEL].add("400");
718+
voltageRanges[DataChannel::AUX_CHANNEL].add("500");
719+
voltageRanges[DataChannel::AUX_CHANNEL].add("750");
720+
voltageRanges[DataChannel::AUX_CHANNEL].add("1000");
721+
voltageRanges[DataChannel::AUX_CHANNEL].add("2000");
714722
//voltageRanges[DataChannel::AUX_CHANNEL].add("5000");
715-
selectedVoltageRange[DataChannel::AUX_CHANNEL] = 9;
716-
rangeGain[DataChannel::AUX_CHANNEL] = 0.001; //mV
717-
rangeSteps[DataChannel::AUX_CHANNEL] = 10;
723+
selectedVoltageRange[DataChannel::AUX_CHANNEL] = 9;
724+
rangeGain[DataChannel::AUX_CHANNEL] = 0.001; //mV
725+
rangeSteps[DataChannel::AUX_CHANNEL] = 10;
718726
rangeUnits.add("mV");
719727
typeNames.add("AUX");
720728

@@ -730,16 +738,16 @@ LfpDisplayOptions::LfpDisplayOptions(LfpDisplayCanvas* canvas_, LfpTimescale* ti
730738

731739
//Ranges for ADC data
732740
voltageRanges[DataChannel::ADC_CHANNEL].add("0.01");
733-
voltageRanges[DataChannel::ADC_CHANNEL].add("0.05");
734-
voltageRanges[DataChannel::ADC_CHANNEL].add("0.1");
735-
voltageRanges[DataChannel::ADC_CHANNEL].add("0.5");
736-
voltageRanges[DataChannel::ADC_CHANNEL].add("1.0");
737-
voltageRanges[DataChannel::ADC_CHANNEL].add("2.0");
738-
voltageRanges[DataChannel::ADC_CHANNEL].add("5.0");
739-
voltageRanges[DataChannel::ADC_CHANNEL].add("10.0");
740-
selectedVoltageRange[DataChannel::ADC_CHANNEL] = 8;
741-
rangeGain[DataChannel::ADC_CHANNEL] = 1; //V
742-
rangeSteps[DataChannel::ADC_CHANNEL] = 0.1; //in V
741+
voltageRanges[DataChannel::ADC_CHANNEL].add("0.05");
742+
voltageRanges[DataChannel::ADC_CHANNEL].add("0.1");
743+
voltageRanges[DataChannel::ADC_CHANNEL].add("0.5");
744+
voltageRanges[DataChannel::ADC_CHANNEL].add("1.0");
745+
voltageRanges[DataChannel::ADC_CHANNEL].add("2.0");
746+
voltageRanges[DataChannel::ADC_CHANNEL].add("5.0");
747+
voltageRanges[DataChannel::ADC_CHANNEL].add("10.0");
748+
selectedVoltageRange[DataChannel::ADC_CHANNEL] = 8;
749+
rangeGain[DataChannel::ADC_CHANNEL] = 1; //V
750+
rangeSteps[DataChannel::ADC_CHANNEL] = 0.1; //in V
743751
rangeUnits.add("V");
744752
typeNames.add("ADC");
745753

@@ -753,9 +761,9 @@ LfpDisplayOptions::LfpDisplayOptions(LfpDisplayCanvas* canvas_, LfpTimescale* ti
753761
addAndMakeVisible(tbut);
754762
typeButtons.add(tbut);
755763

756-
selectedVoltageRangeValues[DataChannel::HEADSTAGE_CHANNEL] = voltageRanges[DataChannel::HEADSTAGE_CHANNEL][selectedVoltageRange[DataChannel::HEADSTAGE_CHANNEL] - 1];
757-
selectedVoltageRangeValues[DataChannel::AUX_CHANNEL] = voltageRanges[DataChannel::AUX_CHANNEL][selectedVoltageRange[DataChannel::AUX_CHANNEL] - 1];
758-
selectedVoltageRangeValues[DataChannel::ADC_CHANNEL] = voltageRanges[DataChannel::ADC_CHANNEL][selectedVoltageRange[DataChannel::ADC_CHANNEL] - 1];
764+
selectedVoltageRangeValues[DataChannel::HEADSTAGE_CHANNEL] = voltageRanges[DataChannel::HEADSTAGE_CHANNEL][selectedVoltageRange[DataChannel::HEADSTAGE_CHANNEL] - 1];
765+
selectedVoltageRangeValues[DataChannel::AUX_CHANNEL] = voltageRanges[DataChannel::AUX_CHANNEL][selectedVoltageRange[DataChannel::AUX_CHANNEL] - 1];
766+
selectedVoltageRangeValues[DataChannel::ADC_CHANNEL] = voltageRanges[DataChannel::ADC_CHANNEL][selectedVoltageRange[DataChannel::ADC_CHANNEL] - 1];
759767

760768
showHideOptionsButton = new ShowHideOptionsButton(this);
761769
showHideOptionsButton->addListener(this);
@@ -815,8 +823,8 @@ LfpDisplayOptions::LfpDisplayOptions(LfpDisplayCanvas* canvas_, LfpTimescale* ti
815823

816824

817825
rangeSelection = new ComboBox("Voltage range");
818-
rangeSelection->addItemList(voltageRanges[DataChannel::HEADSTAGE_CHANNEL], 1);
819-
rangeSelection->setSelectedId(selectedVoltageRange[DataChannel::HEADSTAGE_CHANNEL], sendNotification);
826+
rangeSelection->addItemList(voltageRanges[DataChannel::HEADSTAGE_CHANNEL], 1);
827+
rangeSelection->setSelectedId(selectedVoltageRange[DataChannel::HEADSTAGE_CHANNEL], sendNotification);
820828
rangeSelection->setEditableText(true);
821829
rangeSelection->addListener(this);
822830
addAndMakeVisible(rangeSelection);
@@ -947,12 +955,12 @@ LfpDisplayOptions::LfpDisplayOptions(LfpDisplayCanvas* canvas_, LfpTimescale* ti
947955

948956
}
949957

950-
lfpDisplay->setRange(voltageRanges[DataChannel::HEADSTAGE_CHANNEL][selectedVoltageRange[DataChannel::HEADSTAGE_CHANNEL] - 1].getFloatValue()*rangeGain[DataChannel::HEADSTAGE_CHANNEL]
951-
, DataChannel::HEADSTAGE_CHANNEL);
952-
lfpDisplay->setRange(voltageRanges[DataChannel::ADC_CHANNEL][selectedVoltageRange[DataChannel::ADC_CHANNEL] - 1].getFloatValue()*rangeGain[DataChannel::ADC_CHANNEL]
953-
, DataChannel::ADC_CHANNEL);
954-
lfpDisplay->setRange(voltageRanges[DataChannel::AUX_CHANNEL][selectedVoltageRange[DataChannel::AUX_CHANNEL] - 1].getFloatValue()*rangeGain[DataChannel::AUX_CHANNEL]
955-
, DataChannel::AUX_CHANNEL);
958+
lfpDisplay->setRange(voltageRanges[DataChannel::HEADSTAGE_CHANNEL][selectedVoltageRange[DataChannel::HEADSTAGE_CHANNEL] - 1].getFloatValue()*rangeGain[DataChannel::HEADSTAGE_CHANNEL]
959+
, DataChannel::HEADSTAGE_CHANNEL);
960+
lfpDisplay->setRange(voltageRanges[DataChannel::ADC_CHANNEL][selectedVoltageRange[DataChannel::ADC_CHANNEL] - 1].getFloatValue()*rangeGain[DataChannel::ADC_CHANNEL]
961+
, DataChannel::ADC_CHANNEL);
962+
lfpDisplay->setRange(voltageRanges[DataChannel::AUX_CHANNEL][selectedVoltageRange[DataChannel::AUX_CHANNEL] - 1].getFloatValue()*rangeGain[DataChannel::AUX_CHANNEL]
963+
, DataChannel::AUX_CHANNEL);
956964

957965
}
958966

@@ -1717,7 +1725,7 @@ void LfpDisplay::setNumChannels(int numChannels)
17171725

17181726
channelInfo.add(lfpInfo);
17191727

1720-
savedChannelState.add(true);
1728+
savedChannelState.add(true);
17211729

17221730
totalHeight += lfpChan->getChannelHeight();
17231731

@@ -1936,7 +1944,7 @@ void LfpDisplay::setChannelHeight(int r, bool resetSingle)
19361944
singleChan = -1;
19371945
for (int n = 0; n < numChans; n++)
19381946
{
1939-
channelInfo[n]->setEnabledState(savedChannelState[n]);
1947+
channelInfo[n]->setEnabledState(savedChannelState[n]);
19401948
}
19411949
}
19421950

@@ -2065,7 +2073,7 @@ void LfpDisplay::toggleSingleChannel(int chan)
20652073
singleChan = chan;
20662074

20672075
int newHeight = viewport->getHeight();
2068-
channelInfo[chan]->setEnabledState(true);
2076+
channelInfo[chan]->setEnabledState(true);
20692077
channelInfo[chan]->setSingleChannelState(true);
20702078
setChannelHeight(newHeight, false);
20712079
setSize(getWidth(), numChans*getChannelHeight());
@@ -2425,10 +2433,10 @@ void LfpChannelDisplay::pxPaint()
24252433
{
24262434

24272435
//float localHist[samplerange]; // simple histogram
2428-
Array<float> rangeHist; // [samplerange]; // paired range histogram, same as plotting at higher res. and subsampling
2436+
Array<float> rangeHist; // [samplerange]; // paired range histogram, same as plotting at higher res. and subsampling
24292437

2430-
for (int k = 0; k <= samplerange; k++)
2431-
rangeHist.add(0);
2438+
for (int k = 0; k <= samplerange; k++)
2439+
rangeHist.add(0);
24322440

24332441
for (int k = 0; k <= sampleCountThisPixel; k++) // add up paired-range histogram per pixel - for each pair fill intermediate with uniform distr.
24342442
{
@@ -2509,10 +2517,10 @@ void LfpChannelDisplay::pxPaint()
25092517
for (int j = jfrom; j <= jto; j += 1)
25102518
{
25112519

2512-
//uint8* const pu8Pixel = bdSharedLfpDisplay.getPixelPointer( (int)(i),(int)(j));
2513-
//*(pu8Pixel) = 200;
2514-
//*(pu8Pixel+1) = 200;
2515-
//*(pu8Pixel+2) = 200;
2520+
//uint8* const pu8Pixel = bdSharedLfpDisplay.getPixelPointer( (int)(i),(int)(j));
2521+
//*(pu8Pixel) = 200;
2522+
//*(pu8Pixel+1) = 200;
2523+
//*(pu8Pixel+2) = 200;
25162524

25172525
bdLfpChannelBitmap.setPixelColour(i,j,lineColour);
25182526

Plugins/LfpDisplayNodeBeta/LfpDisplayNode.cpp

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,12 @@ void LfpDisplayNode::setParameter (int parameterIndex, float newValue)
162162
ed->canvas->setParameter (parameterIndex, newValue);
163163
}
164164

165+
std::list<int> LfpDisplayNode::eventStateChannels() const {
166+
std::list<int> cc;
167+
for (uint32 id: eventSourceNodes)
168+
cc.push_back(channelForEventSource.find(id)->second);
169+
return cc;
170+
}
165171

166172
void LfpDisplayNode::handleEvent(const EventChannel* eventInfo,
167173
const MidiMessage& event, int samplePosition) {
@@ -192,7 +198,7 @@ void LfpDisplayNode::copyToEventChannel(uint32 src,
192198
int chan = channelForEventSource[src];
193199
int destStart = t0 + displayBufferIndex[chan];
194200
int n = t1 - t0;
195-
while (destStart + n > dispBufSamps) {
201+
while (destStart + n >= dispBufSamps) {
196202
int m = dispBufSamps - destStart;
197203
displayBuffer->copyFrom(chan, destStart, arrayOfOnes, m, value);
198204
n -= m;
@@ -207,22 +213,20 @@ void LfpDisplayNode::finalizeEventChannels() {
207213
uint32 src = eventSourceNodes[i];
208214
int chan = channelForEventSource[src];
209215
int index = displayBufferIndex[chan];
210-
printf("event index %i [%i]\n", index, displayBufferIndex[0]);
211216
int nSamples = getNumSourceSamples(src);
212217
int t0 = 0;
213218
for (EventValueChange const &evc: eventValueChanges[src]) {
214219
int t1 = evc.eventTime;
215-
//printf("T%i-%i: %Li\n", t0, t1, ttlState[src]);
216220
copyToEventChannel(src, t0, t1, ttlState[src]);
217221
if (evc.eventVal>0)
218222
ttlState[src] |= evc.eventVal;
219223
else
220224
ttlState[src] &= ~evc.eventVal;
221225
t0 = t1;
222226
}
223-
//printf("(T%i-%i): %Li\n", t0, nSamples, ttlState[src]);
224227
copyToEventChannel(src, t0, nSamples, ttlState[src]);
225-
displayBufferIndex.set(chan, (index + nSamples) % displayBuffer->getNumSamples());
228+
displayBufferIndex.set(chan, (index + nSamples)
229+
% displayBuffer->getNumSamples());
226230
}
227231
}
228232

@@ -251,11 +255,9 @@ void LfpDisplayNode::process (AudioSampleBuffer& buffer)
251255
//std::cout << "Display node sample count: " << nSamples << std::endl; ///buffer.getNumSamples() << std::endl;
252256

253257
initializeEventChannels();
254-
checkForEvents (); // see if we got any TTL events
258+
checkForEvents(); // see if we got any TTL events
259+
ScopedLock displayLock(displayMutex);
255260
finalizeEventChannels();
256-
257-
ScopedLock displayLock (displayMutex);
258-
259261
for (int chan = 0; chan < buffer.getNumChannels(); ++chan)
260262
copyDataToDisplay(chan, buffer);
261263
}

Plugins/LfpDisplayNodeBeta/LfpDisplayNode.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ class LfpDisplayNode : public GenericProcessor
6666
int getDisplayBufferIndex (int chan) const { return displayBufferIndex[chan]; }
6767

6868
CriticalSection* getMutex() { return &displayMutex; }
69-
69+
std::list<int> eventStateChannels() const;
7070

7171
private:
7272
void initializeEventChannels();

0 commit comments

Comments
 (0)