Skip to content

Commit 1439387

Browse files
authored
Merge pull request #551 from admunkucsd/adding_lfp_filtering
Adding lfp channel selection filtering
2 parents 40f5af3 + d97e5a6 commit 1439387

7 files changed

Lines changed: 123 additions & 25 deletions

File tree

Plugins/LfpDisplayNode/DisplayBuffer.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,8 @@ void DisplayBuffer::addChannel(
6464
ContinuousChannel::Type type,
6565
bool isRecorded,
6666
int group,
67-
float ypos,
67+
float ypos,
68+
String description,
6869
String structure)
6970
{
7071
ChannelMetadata metadata = ChannelMetadata();
@@ -75,6 +76,7 @@ void DisplayBuffer::addChannel(
7576
metadata.structure = structure;
7677
metadata.type = type;
7778
metadata.isRecorded = isRecorded;
79+
metadata.description = description;
7880

7981
channelMetadata.add(metadata);
8082
channelMap[channelNum] = numChannels;

Plugins/LfpDisplayNode/DisplayBuffer.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@ namespace LfpViewer {
6060
ContinuousChannel::Type channelType,
6161
bool isRecorded,
6262
int group = 0,
63-
float ypos = 0,
63+
float ypos = 0,
64+
String description = "",
6465
String structure = "None");
6566

6667
/** Initializes the event channel at the start of each buffer */
@@ -87,10 +88,11 @@ namespace LfpViewer {
8788
String structure = "None";
8889
ContinuousChannel::Type type;
8990
bool isRecorded = false;
91+
String description = "";
9092
};
9193

9294
Array<ChannelMetadata> channelMetadata;
93-
95+
9496
String name;
9597
int id;
9698

@@ -128,4 +130,4 @@ namespace LfpViewer {
128130
};
129131

130132

131-
#endif //__DISPLAYBUFFER_H__
133+
#endif //__DISPLAYBUFFER_H__

Plugins/LfpDisplayNode/LfpDisplay.cpp

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -981,27 +981,38 @@ void LfpDisplay::rebuildDrawableChannelsList()
981981
removeAllChildren(); // start with clean slate
982982

983983
Array<LfpChannelTrack> channelsToDraw; // all visible channels will be added to this array
984-
984+
Array<int> filteredChannels;
985+
if(canvasSplit -> displayBuffer) {
986+
filteredChannels = canvasSplit -> getFilteredChannels();
987+
}
985988
// iterate over all channels and select drawable ones
986-
for (int i = 0, drawableChannelNum = 0; i < channels.size(); i++)
989+
for (int i = 0, drawableChannelNum = 0, filterChannelIndex = 0; i < channels.size(); i++)
987990
{
988-
989991
//std::cout << "Checking for hidden channels" << std::endl;
990-
if (displaySkipAmt == 0 || (i % displaySkipAmt == 0)) // no skips, add all channels
991-
{
992-
channels[i]->setHidden(false);
993-
channelInfo[i]->setHidden(false);
994-
995-
channelInfo[i]->setDrawableChannelNumber(drawableChannelNum++);
996-
channelInfo[i]->resized(); // to update the conditional drawing of enableButton and channel num
997-
998-
channelsToDraw.add(LfpDisplay::LfpChannelTrack{
999-
channels[i],
1000-
channelInfo[i]
1001-
});
992+
int channelNumber = filteredChannels.size() ? canvasSplit->displayBuffer->channelMetadata[i].description.getIntValue(): -1;
993+
//the filter list can have channels that aren't selected for acqusition; this skips those filtered channels
994+
while(filterChannelIndex < filteredChannels.size() && channelNumber > filteredChannels[filterChannelIndex]){
995+
filterChannelIndex++;
996+
}
997+
if(filteredChannels.size() == 0 || (filterChannelIndex < filteredChannels.size() && channelNumber == filteredChannels[filterChannelIndex])) {
998+
if (displaySkipAmt == 0 || ((filteredChannels.size() ? filterChannelIndex : i) % displaySkipAmt == 0)) // no skips, add all channels
999+
{
10021000

1003-
addAndMakeVisible(channels[i]);
1004-
addAndMakeVisible(channelInfo[i]);
1001+
channels[i]->setHidden(false);
1002+
channelInfo[i]->setHidden(false);
1003+
1004+
channelInfo[i]->setDrawableChannelNumber(drawableChannelNum++);
1005+
channelInfo[i]->resized(); // to update the conditional drawing of enableButton and channel num
1006+
1007+
channelsToDraw.add(LfpDisplay::LfpChannelTrack{
1008+
channels[i],
1009+
channelInfo[i]
1010+
});
1011+
1012+
addAndMakeVisible(channels[i]);
1013+
addAndMakeVisible(channelInfo[i]);
1014+
}
1015+
filterChannelIndex++;
10051016
}
10061017
else // skip some channels
10071018
{

Plugins/LfpDisplayNode/LfpDisplayCanvas.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1661,8 +1661,13 @@ void LfpDisplaySplitter::visibleAreaChanged()
16611661
void LfpDisplaySplitter::refresh()
16621662
{
16631663
updateScreenBuffer();
1664-
1665-
lfpDisplay->refresh(); // redraws only the new part of the screen buffer, unless fullredraw is set to true
1664+
if(shouldRebuildChannelList) {
1665+
shouldRebuildChannelList = false;
1666+
lfpDisplay->rebuildDrawableChannelsList(); // calls resized()/refresh() after rebuilding list
1667+
}
1668+
else {
1669+
lfpDisplay->refresh(); // redraws only the new part of the screen buffer, unless fullredraw is set to true
1670+
}
16661671
}
16671672

16681673
void LfpDisplaySplitter::comboBoxChanged(juce::ComboBox *comboBox)

Plugins/LfpDisplayNode/LfpDisplayCanvas.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,11 @@ class LfpDisplaySplitter : public Component,
340340
uint16 selectedStreamId;
341341

342342
void refreshScreenBuffer();
343+
344+
bool shouldRebuildChannelList = false;
345+
346+
void setFilteredChannels(Array<int> channels){filteredChannels = channels;}
347+
Array<int> getFilteredChannels(){return filteredChannels;}
343348

344349
private:
345350

@@ -381,6 +386,8 @@ class LfpDisplaySplitter : public Component,
381386
int displayBufferSize;
382387

383388
int scrollBarThickness;
389+
390+
Array<int> filteredChannels = Array<int>();
384391

385392
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(LfpDisplaySplitter);
386393

Plugins/LfpDisplayNode/LfpDisplayNode.cpp

Lines changed: 67 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,13 +91,14 @@ void LfpDisplayNode::updateSettings()
9191
displayBufferMap[streamId]->sampleRate = channel->getSampleRate();
9292
displayBufferMap[streamId]->name = name;
9393
}
94-
94+
//
9595
displayBufferMap[streamId]->addChannel(channel->getName(), // name
9696
ch, // index
9797
channel->getChannelType(), // type
9898
channel->isRecorded,
9999
0, // group
100-
channel->position.y // ypos
100+
channel->position.y, // ypos
101+
channel-> getDescription()
101102
);
102103
}
103104

@@ -179,6 +180,11 @@ bool LfpDisplayNode::stopAcquisition()
179180
LfpDisplayEditor* editor = (LfpDisplayEditor*) getEditor();
180181
editor->disable();
181182

183+
for(auto split : splitDisplays) {
184+
Array<int> emptyArray = Array<int>();
185+
split -> setFilteredChannels(emptyArray);
186+
}
187+
182188
for (auto buffer : displayBuffers)
183189
buffer->ttlState = 0;
184190

@@ -327,3 +333,62 @@ void LfpDisplayNode::acknowledgeTrigger(int id)
327333
{
328334
latestTrigger.set(id, -1);
329335
}
336+
337+
bool LfpDisplayNode::getIntField(DynamicObject::Ptr payload, String name, int& value, int lowerBound, int upperBound) {
338+
if(!payload->hasProperty(name) || !payload->getProperty(name).isInt())
339+
return false;
340+
int tempVal = payload->getProperty(name);
341+
if((upperBound != INT_MIN && tempVal > upperBound) || (lowerBound != INT_MAX && tempVal < lowerBound))
342+
return false;
343+
value = tempVal;
344+
return true;
345+
}
346+
347+
348+
void LfpDisplayNode::handleBroadcastMessage(String msg) {
349+
var parsedMessage = JSON::parse(msg);
350+
if(!parsedMessage.isObject())
351+
return;
352+
DynamicObject::Ptr jsonMessage = parsedMessage.getDynamicObject();
353+
if(jsonMessage == nullptr)
354+
return;
355+
String pluginName= jsonMessage -> getProperty("plugin");
356+
if(pluginName != "LFPViewer") {
357+
return;
358+
}
359+
String command = jsonMessage -> getProperty("command");
360+
DynamicObject::Ptr payload = jsonMessage -> getProperty("payload").getDynamicObject();
361+
if(command == "filter") {
362+
if(payload.get() == nullptr){
363+
LOGD("Tried to filter in LFPViewer, but could not find a payload");
364+
return;
365+
}
366+
int split, start, rows, cols, colsPerRow, end;
367+
if(!getIntField(payload, "split", split, 0, 2) || !getIntField(payload, "start", start, 0)) {
368+
LOGD("Tried to filter in LFPViewer, but a valid split and start weren't provided");
369+
return;
370+
}
371+
Array<int> channelNames;
372+
//If an end is specificed add channels from start to end
373+
//Else calculate the rectangular selection based on rows and columns
374+
if(getIntField(payload, "end", end, 0)) {
375+
for(int index = 0; index < (end - start); index++) {
376+
channelNames.add(start + index);
377+
}
378+
}
379+
else {
380+
if(!getIntField(payload, "rows", rows, 0) || !getIntField(payload, "cols", cols, 0) || !getIntField(payload, "colsPerRow", colsPerRow, 0)) {
381+
LOGD("Tried to filter by rectangular selection in LFPViewer, but valid row/column/columnsPerRow counts weren't provided");
382+
return;
383+
}
384+
for(int row = 0; row < rows; row++) {
385+
for(int col = 0; col < cols; col++) {
386+
channelNames.add(start + col + row*colsPerRow);
387+
}
388+
}
389+
}
390+
splitDisplays[split] -> setFilteredChannels(channelNames);
391+
splitDisplays[split] -> shouldRebuildChannelList = true;
392+
}
393+
}
394+

Plugins/LfpDisplayNode/LfpDisplayNode.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,12 @@ class LfpDisplayNode : public GenericProcessor
100100
/** Acknowledges receipt of a trigger for a given split display*/
101101
void acknowledgeTrigger(int splitId);
102102

103+
/** Reads from int value from payload, returns if the value was found and is within bounds*/
104+
bool getIntField(DynamicObject::Ptr payload, String name, int& value, int lowerBound = INT_MAX, int upperBound = INT_MIN);
105+
106+
/** Handles messages from other processors during acquisition*/
107+
void handleBroadcastMessage(String msg) override;
108+
103109
private:
104110

105111
/** Initializes trigger channels within a process block*/

0 commit comments

Comments
 (0)