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
5355using 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
0 commit comments