Skip to content

Commit a4e3f64

Browse files
committed
Update LfpViewer to use new channel position and group metadata
1 parent a96ba3d commit a4e3f64

File tree

7 files changed

+162
-26
lines changed

7 files changed

+162
-26
lines changed

Plugins/LfpViewer/DisplayBuffer.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,17 +64,22 @@ void DisplayBuffer::addChannel (
6464
ContinuousChannel::Type type,
6565
bool isRecorded,
6666
int group,
67+
float xpos,
6768
float ypos,
6869
String description,
6970
String structure,
7071
float inputRangeMin,
7172
float inputRangeMax,
72-
String units)
73+
String units,
74+
bool hasGroupMetadata,
75+
bool hasYposMetadata,
76+
bool hasXposMetadata)
7377
{
7478
ChannelMetadata metadata = ChannelMetadata();
7579
metadata.name = name;
7680
metadata.type = type;
7781
metadata.group = group;
82+
metadata.xpos = xpos;
7883
metadata.ypos = ypos;
7984
metadata.structure = structure;
8085
metadata.type = type;
@@ -83,6 +88,9 @@ void DisplayBuffer::addChannel (
8388
metadata.inputRangeMin = inputRangeMin;
8489
metadata.inputRangeMax = inputRangeMax;
8590
metadata.units = units;
91+
metadata.hasGroupMetadata = hasGroupMetadata;
92+
metadata.hasYposMetadata = hasYposMetadata;
93+
metadata.hasXposMetadata = hasXposMetadata;
8694

8795
channelMetadata.add (metadata);
8896
channelMap[channelNum] = numChannels;

Plugins/LfpViewer/DisplayBuffer.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,12 +61,16 @@ class TESTABLE DisplayBuffer : public AudioBuffer<float>
6161
ContinuousChannel::Type channelType,
6262
bool isRecorded,
6363
int group = 0,
64+
float xpos = 0.0f,
6465
float ypos = 0,
6566
String description = "",
6667
String structure = "None",
6768
float inputRangeMin = -5000.0f,
6869
float inputRangeMax = +5000.0f,
69-
String units = "");
70+
String units = "",
71+
bool hasGroupMetadata = false,
72+
bool hasYposMetadata = false,
73+
bool hasXposMetadata = false);
7074

7175
/** Initializes the event channel at the start of each buffer */
7276
void initializeEventChannel (int nSamples);
@@ -89,6 +93,7 @@ class TESTABLE DisplayBuffer : public AudioBuffer<float>
8993
{
9094
String name = "";
9195
int group = 0;
96+
float xpos = 0.0f;
9297
float ypos = 0;
9398
String structure = "None";
9499
ContinuousChannel::Type type;
@@ -97,6 +102,9 @@ class TESTABLE DisplayBuffer : public AudioBuffer<float>
97102
float inputRangeMin = -5000.0f;
98103
float inputRangeMax = +5000.0f;
99104
String units = "";
105+
bool hasGroupMetadata = false;
106+
bool hasYposMetadata = false;
107+
bool hasXposMetadata = false;
100108
};
101109

102110
Array<ChannelMetadata> channelMetadata;

Plugins/LfpViewer/LfpChannelDisplay.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -819,6 +819,18 @@ void LfpChannelDisplay::setDepth (float depth_)
819819
depth = depth_;
820820
}
821821

822+
void LfpChannelDisplay::setXpos (float xpos_)
823+
{
824+
xpos = xpos_;
825+
}
826+
827+
void LfpChannelDisplay::setMetadataPresence (bool hasGroupMetadata_, bool hasYposMetadata_, bool hasXposMetadata_)
828+
{
829+
groupMetadataAvailable = hasGroupMetadata_;
830+
yposMetadataAvailable = hasYposMetadata_;
831+
xposMetadataAvailable = hasXposMetadata_;
832+
}
833+
822834
void LfpChannelDisplay::setRecorded (bool recorded_)
823835
{
824836
isRecorded = recorded_;

Plugins/LfpViewer/LfpChannelDisplay.h

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,12 @@ class LfpChannelDisplay : public Component
8989
/** Sets the channel depth*/
9090
void setDepth (float);
9191

92+
/** Sets the channel x-position */
93+
void setXpos (float);
94+
95+
/** Records which metadata fields were provided for this channel */
96+
void setMetadataPresence (bool hasGroupMetadata_, bool hasYposMetadata_, bool hasXposMetadata_);
97+
9298
/** Sets whether or not the channel is recorded by an upstream Record Node*/
9399
void setRecorded (bool);
94100

@@ -176,6 +182,10 @@ class LfpChannelDisplay : public Component
176182

177183
float getDepth() { return depth; }
178184
int getGroup() { return group; }
185+
float getXpos() const { return xpos; }
186+
bool hasGroupMetadata() const { return groupMetadataAvailable; }
187+
bool hasYposMetadata() const { return yposMetadataAvailable; }
188+
bool hasXposMetadata() const { return xposMetadataAvailable; }
179189

180190
int ifrom, ito, ito_local, ifrom_local;
181191

@@ -195,8 +205,12 @@ class LfpChannelDisplay : public Component
195205
int drawableChan;
196206

197207
String name;
198-
int group;
199-
float depth;
208+
int group = 0;
209+
float depth = 0.0f;
210+
float xpos = 0.0f;
211+
bool groupMetadataAvailable = false;
212+
bool yposMetadataAvailable = false;
213+
bool xposMetadataAvailable = false;
200214
bool isRecorded;
201215

202216
String units;

Plugins/LfpViewer/LfpDisplay.cpp

Lines changed: 83 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,10 @@
4747

4848
#define MS_FROM_START Time::highResolutionTicksToSeconds (Time::getHighResolutionTicks() - start) * 1000
4949

50+
#include <cmath>
5051
#include <math.h>
5152
#include <numeric>
53+
#include <vector>
5254

5355
using namespace LfpViewer;
5456

@@ -258,17 +260,31 @@ void LfpDisplay::setColours()
258260
{
259261
if (colourGrouping.equalsIgnoreCase ("By Shank"))
260262
{
261-
/*
262-
depth ranges of electrodes for multishank configurations:
263-
Shank 1: depth < 10000
264-
Shank 2: 10000 ≤ depth < 20000
265-
Shank 3: 20000 ≤ depth < 30000
266-
Shank 4: depth ≥ 30000
267-
*/
268-
int depth = drawableChannels[i].channel->getDepth();
269-
int colourIdx = depth < 10000 ? 0 : depth < 20000 ? 2 : depth < 30000 ? 4 : 6;
270-
drawableChannels[i].channel->setColour (getColourSchemePtr()->getColourForIndex (colourIdx));
271-
drawableChannels[i].channelInfo->setColour (getColourSchemePtr()->getColourForIndex (colourIdx));
263+
auto* channel = drawableChannels[i].channel;
264+
auto* info = drawableChannels[i].channelInfo;
265+
266+
if (channel->hasGroupMetadata())
267+
{
268+
const int colourIdx = (channel->getGroup() * 2) % 8;
269+
channel->setColour (getColourSchemePtr()->getColourForIndex (colourIdx));
270+
info->setColour (getColourSchemePtr()->getColourForIndex (colourIdx));
271+
}
272+
else
273+
{
274+
/*
275+
Legacy depth-based shank colouring ranges:
276+
Shank 1: depth < 10000
277+
Shank 2: 10000 ≤ depth < 20000
278+
Shank 3: 20000 ≤ depth < 30000
279+
Shank 4: depth ≥ 30000
280+
*/
281+
const int depth = channel->getDepth();
282+
const int colourIdx = depth < 10000 ? 0 : depth < 20000 ? 2
283+
: depth < 30000 ? 4
284+
: 6;
285+
channel->setColour (getColourSchemePtr()->getColourForIndex (colourIdx));
286+
info->setColour (getColourSchemePtr()->getColourForIndex (colourIdx));
287+
}
272288
}
273289
else
274290
{
@@ -281,10 +297,24 @@ void LfpDisplay::setColours()
281297
{
282298
if (colourGrouping.equalsIgnoreCase ("By Shank"))
283299
{
284-
int depth = drawableChannels[0].channel->getDepth();
285-
int colourIdx = depth < 10000 ? 0 : depth < 20000 ? 2 : depth < 30000 ? 4 : 6;
286-
drawableChannels[0].channel->setColour (getColourSchemePtr()->getColourForIndex (colourIdx));
287-
drawableChannels[0].channelInfo->setColour (getColourSchemePtr()->getColourForIndex (colourIdx));
300+
auto* channel = drawableChannels[0].channel;
301+
auto* info = drawableChannels[0].channelInfo;
302+
303+
if (channel->hasGroupMetadata())
304+
{
305+
const int colourIdx = channel->getGroup();
306+
channel->setColour (getColourSchemePtr()->getColourForIndex (colourIdx));
307+
info->setColour (getColourSchemePtr()->getColourForIndex (colourIdx));
308+
}
309+
else
310+
{
311+
const int depth = channel->getDepth();
312+
const int colourIdx = depth < 10000 ? 0 : depth < 20000 ? 2
313+
: depth < 30000 ? 4
314+
: 6;
315+
channel->setColour (getColourSchemePtr()->getColourForIndex (colourIdx));
316+
info->setColour (getColourSchemePtr()->getColourForIndex (colourIdx));
317+
}
288318
}
289319
else
290320
{
@@ -1092,23 +1122,43 @@ void LfpDisplay::rebuildDrawableChannelsList()
10921122
const int numChannels = channelsToDraw.size();
10931123

10941124
std::vector<float> depths (numChannels);
1125+
std::vector<float> xposValues (numChannels);
1126+
std::vector<bool> hasYposMetadata (numChannels);
1127+
std::vector<bool> hasXposMetadata (numChannels);
1128+
std::vector<int> groups (numChannels);
1129+
std::vector<bool> hasGroupMetadata (numChannels);
10951130

10961131
bool allSame = true;
1132+
bool anyYposMetadata = false;
1133+
bool anyXposMetadata = false;
1134+
bool anyGroupMetadata = false;
10971135
float last = channelsToDraw[0].channelInfo->getDepth();
10981136

10991137
for (int i = 0; i < channelsToDraw.size(); i++)
11001138
{
1101-
float depth = channelsToDraw[i].channelInfo->getDepth();
1139+
auto* info = channelsToDraw[i].channelInfo;
1140+
const float depth = info->getDepth();
11021141

11031142
if (depth != last)
11041143
allSame = false;
11051144

11061145
depths[i] = depth;
1107-
1146+
xposValues[i] = info->getXpos();
1147+
hasYposMetadata[i] = info->hasYposMetadata();
1148+
hasXposMetadata[i] = info->hasXposMetadata();
1149+
groups[i] = info->getGroup();
1150+
hasGroupMetadata[i] = info->hasGroupMetadata();
1151+
1152+
anyYposMetadata = anyYposMetadata || hasYposMetadata[i];
1153+
anyXposMetadata = anyXposMetadata || hasXposMetadata[i];
1154+
anyGroupMetadata = anyGroupMetadata || hasGroupMetadata[i];
11081155
last = depth;
11091156
}
11101157

1111-
if (allSame)
1158+
const bool positionMetadataAvailable = anyYposMetadata && anyXposMetadata;
1159+
const bool groupMetadataAvailable = anyGroupMetadata;
1160+
1161+
if (! groupMetadataAvailable && allSame && ! anyYposMetadata)
11121162
{
11131163
LOGD ("No depth info found.");
11141164
}
@@ -1118,7 +1168,21 @@ void LfpDisplay::rebuildDrawableChannelsList()
11181168

11191169
std::iota (V.begin(), V.end(), 0); //Initializing
11201170
sort (V.begin(), V.end(), [&] (int i, int j)
1121-
{ return depths[i] <= depths[j]; });
1171+
{
1172+
const float depthDiff = depths[i] - depths[j];
1173+
const float depthEpsilon = 1.0e-3f;
1174+
1175+
if (groupMetadataAvailable && groups[i] != groups[j])
1176+
return groups[i] < groups[j];
1177+
1178+
if (std::abs (depthDiff) >= depthEpsilon)
1179+
return depths[i] < depths[j];
1180+
1181+
if (positionMetadataAvailable)
1182+
return xposValues[i] < xposValues[j];
1183+
1184+
return i < j; // deterministic fallback
1185+
});
11221186

11231187
Array<LfpChannelTrack> orderedDrawableChannels;
11241188

Plugins/LfpViewer/LfpDisplayCanvas.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,9 @@
2929
#include "LfpDisplayNode.h"
3030
#include "ShowHideOptionsButton.h"
3131

32-
#include <math.h>
3332
#include <algorithm>
3433
#include <cmath>
34+
#include <math.h>
3535

3636
#define MS_FROM_START Time::highResolutionTicksToSeconds (Time::getHighResolutionTicks() - start) * 1000
3737

@@ -992,13 +992,21 @@ void LfpDisplaySplitter::updateSettings()
992992
lfpDisplay->channels[i]->setName (displayBuffer->channelMetadata[i].name);
993993
lfpDisplay->channels[i]->setGroup (displayBuffer->channelMetadata[i].group);
994994
lfpDisplay->channels[i]->setDepth (displayBuffer->channelMetadata[i].ypos);
995+
lfpDisplay->channels[i]->setXpos (displayBuffer->channelMetadata[i].xpos);
996+
lfpDisplay->channels[i]->setMetadataPresence (displayBuffer->channelMetadata[i].hasGroupMetadata,
997+
displayBuffer->channelMetadata[i].hasYposMetadata,
998+
displayBuffer->channelMetadata[i].hasXposMetadata);
995999
lfpDisplay->channels[i]->setRecorded (displayBuffer->channelMetadata[i].isRecorded);
9961000
lfpDisplay->channels[i]->updateType (displayBuffer->channelMetadata[i].type);
9971001
lfpDisplay->channels[i]->setUnits (displayBuffer->channelMetadata[i].units);
9981002

9991003
lfpDisplay->channelInfo[i]->setName (displayBuffer->channelMetadata[i].name);
10001004
lfpDisplay->channelInfo[i]->setGroup (displayBuffer->channelMetadata[i].group);
10011005
lfpDisplay->channelInfo[i]->setDepth (displayBuffer->channelMetadata[i].ypos);
1006+
lfpDisplay->channelInfo[i]->setXpos (displayBuffer->channelMetadata[i].xpos);
1007+
lfpDisplay->channelInfo[i]->setMetadataPresence (displayBuffer->channelMetadata[i].hasGroupMetadata,
1008+
displayBuffer->channelMetadata[i].hasYposMetadata,
1009+
displayBuffer->channelMetadata[i].hasXposMetadata);
10021010
lfpDisplay->channelInfo[i]->setRecorded (displayBuffer->channelMetadata[i].isRecorded);
10031011
lfpDisplay->channelInfo[i]->updateType (displayBuffer->channelMetadata[i].type);
10041012
lfpDisplay->channelInfo[i]->setUnits (displayBuffer->channelMetadata[i].units);

Plugins/LfpViewer/LfpDisplayNode.cpp

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,17 +86,39 @@ void LfpDisplayNode::updateSettings()
8686
displayBufferMap[streamId]->name = name;
8787
}
8888

89+
bool hasGroupMetadata = (! channel->group.name.equalsIgnoreCase ("default"));
90+
91+
float ypos = channel->position.y;
92+
float xpos = channel->position.x;
93+
bool hasYposMetadata = false;
94+
bool hasXposMetadata = false;
95+
96+
const int yposMetadataIndex = channel->findMetadata (MetadataDescriptor::MetadataType::FLOAT, 1, "channel.ypos");
97+
if (yposMetadataIndex >= 0)
98+
{
99+
if (const auto* yposValue = channel->getMetadataValue (yposMetadataIndex))
100+
{
101+
yposValue->getValue (ypos);
102+
hasYposMetadata = true;
103+
hasXposMetadata = true;
104+
}
105+
}
106+
89107
displayBufferMap[streamId]->addChannel (channel->getName(), // name
90108
ch, // index
91109
channel->getChannelType(), // type
92110
channel->isRecorded,
93111
channel->group.number, // group
94-
channel->position.y, // ypos
112+
xpos,
113+
ypos, // ypos
95114
channel->getDescription(),
96115
"None", // structure
97116
channel->inputRange.min, // inputRangeMin
98117
channel->inputRange.max, // inputRangeMax
99-
channel->getUnits()); // units
118+
channel->getUnits(), // units
119+
hasGroupMetadata,
120+
hasYposMetadata,
121+
hasXposMetadata); // metadata flags
100122
}
101123

102124
Array<DisplayBuffer*> toDelete;

0 commit comments

Comments
 (0)