Skip to content

Commit 38dfd75

Browse files
committed
Add input range handling and auto-scaling for AUX channels
1 parent 759700a commit 38dfd75

File tree

8 files changed

+189
-21
lines changed

8 files changed

+189
-21
lines changed

Plugins/LfpViewer/DisplayBuffer.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,9 @@ void DisplayBuffer::addChannel (
6666
int group,
6767
float ypos,
6868
String description,
69-
String structure)
69+
String structure,
70+
float inputRangeMin,
71+
float inputRangeMax)
7072
{
7173
ChannelMetadata metadata = ChannelMetadata();
7274
metadata.name = name;
@@ -77,6 +79,8 @@ void DisplayBuffer::addChannel (
7779
metadata.type = type;
7880
metadata.isRecorded = isRecorded;
7981
metadata.description = description;
82+
metadata.inputRangeMin = inputRangeMin;
83+
metadata.inputRangeMax = inputRangeMax;
8084

8185
channelMetadata.add (metadata);
8286
channelMap[channelNum] = numChannels;

Plugins/LfpViewer/DisplayBuffer.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,9 @@ class TESTABLE DisplayBuffer : public AudioBuffer<float>
6363
int group = 0,
6464
float ypos = 0,
6565
String description = "",
66-
String structure = "None");
66+
String structure = "None",
67+
float inputRangeMin = -5000.0f,
68+
float inputRangeMax = +5000.0f);
6769

6870
/** Initializes the event channel at the start of each buffer */
6971
void initializeEventChannel (int nSamples);
@@ -91,6 +93,8 @@ class TESTABLE DisplayBuffer : public AudioBuffer<float>
9193
ContinuousChannel::Type type;
9294
bool isRecorded = false;
9395
String description = "";
96+
float inputRangeMin = -5000.0f;
97+
float inputRangeMax = +5000.0f;
9498
};
9599

96100
Array<ChannelMetadata> channelMetadata;

Plugins/LfpViewer/LfpDisplay.cpp

Lines changed: 80 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -162,8 +162,32 @@ ChannelColourScheme* LfpDisplay::getColourSchemePtr()
162162

163163
void LfpDisplay::updateRange (int i)
164164
{
165-
channels[i]->setRange (range[channels[i]->getType()]);
166-
channelInfo[i]->setRange (range[channels[i]->getType()]);
165+
// Check if this is an AUX channel with auto-scaling enabled
166+
if (channels[i]->getType() == ContinuousChannel::Type::AUX && options->isAuxAutoScaleEnabled())
167+
{
168+
// Apply individual auto-scaling based on this channel's InputRange
169+
float rangeMin = canvasSplit->displayBuffer->channelMetadata[i].inputRangeMin;
170+
float rangeMax = canvasSplit->displayBuffer->channelMetadata[i].inputRangeMax;
171+
float autoRange = rangeMax - rangeMin;
172+
173+
if (autoRange > 0.0f)
174+
{
175+
channels[i]->setRange (autoRange);
176+
channelInfo[i]->setRange (autoRange);
177+
}
178+
else
179+
{
180+
// Fall back to the default range for this type
181+
channels[i]->setRange (range[channels[i]->getType()]);
182+
channelInfo[i]->setRange (range[channels[i]->getType()]);
183+
}
184+
}
185+
else
186+
{
187+
// Use the standard range for the channel type
188+
channels[i]->setRange (range[channels[i]->getType()]);
189+
channelInfo[i]->setRange (range[channels[i]->getType()]);
190+
}
167191
}
168192

169193
void LfpDisplay::setNumChannels (int newChannelCount)
@@ -602,7 +626,10 @@ void LfpDisplay::setRange (float r, ContinuousChannel::Type type)
602626
for (int i = 0; i < numChans; i++)
603627
{
604628
if (channels[i]->getType() == type)
629+
{
605630
channels[i]->setRange (range[type]);
631+
channelInfo[i]->setRange (range[type]);
632+
}
606633
}
607634

608635
if (displayIsPaused)
@@ -615,6 +642,46 @@ void LfpDisplay::setRange (float r, ContinuousChannel::Type type)
615642
}
616643
}
617644

645+
void LfpDisplay::setAutoRangeForAuxChannels()
646+
{
647+
if (canvasSplit->displayBuffer == nullptr || channels.size() == 0)
648+
return;
649+
650+
// Apply individual ranges to each AUX channel based on their InputRange
651+
for (int i = 0; i < numChans; i++)
652+
{
653+
if (channels[i]->getType() == ContinuousChannel::Type::AUX)
654+
{
655+
// Get the InputRange from the channel metadata
656+
if (i < canvasSplit->displayBuffer->channelMetadata.size())
657+
{
658+
float rangeMin = canvasSplit->displayBuffer->channelMetadata[i].inputRangeMin;
659+
float rangeMax = canvasSplit->displayBuffer->channelMetadata[i].inputRangeMax;
660+
float autoRange = rangeMax - rangeMin;
661+
662+
if (autoRange > 0.0f)
663+
{
664+
channels[i]->setRange (autoRange);
665+
channelInfo[i]->setRange (autoRange);
666+
}
667+
else
668+
{
669+
// Fall back to the default range for this type
670+
channels[i]->setRange (range[ContinuousChannel::Type::AUX]);
671+
channelInfo[i]->setRange (range[ContinuousChannel::Type::AUX]);
672+
}
673+
}
674+
}
675+
}
676+
677+
if (displayIsPaused)
678+
{
679+
timeOffsetChanged = true;
680+
canRefresh = true;
681+
refresh();
682+
}
683+
}
684+
618685
int LfpDisplay::getRange()
619686
{
620687
return getRange (options->getSelectedType());
@@ -834,20 +901,25 @@ void LfpDisplay::mouseWheelMove (const MouseEvent& e, const MouseWheelDetails& w
834901
{
835902
if (e.mods.isAltDown()) // ALT + scroll wheel -> change channel range (was SHIFT but that clamps wheel.deltaY to 0 on OSX for some reason..)
836903
{
904+
auto chanType = options->getSelectedType();
905+
906+
if (chanType == ContinuousChannel::AUX && options->isAuxAutoScaleEnabled())
907+
return;
908+
837909
int h = getRange();
838910

839-
int step = options->getRangeStep (options->getSelectedType());
911+
int step = options->getRangeStep (chanType);
840912

841913
// std::cout << wheel.deltaY << std::endl;
842914

843915
if (wheel.deltaY > 0)
844916
{
845-
setRange (h + step, options->getSelectedType());
917+
setRange (h + step, chanType);
846918
}
847919
else
848920
{
849921
if (h > step + 1)
850-
setRange (h - step, options->getSelectedType());
922+
setRange (h - step, chanType);
851923
}
852924

853925
options->setRangeSelection (h); // update combobox
@@ -1174,6 +1246,7 @@ void LfpDisplay::mouseDown (const MouseEvent& event)
11741246
int dist = 0;
11751247
int mindist = 10000;
11761248
int closest = 5;
1249+
float chanRange = getRange();
11771250

11781251
for (int n = 0; n < drawableChannels.size(); n++) // select closest instead of relying on eventComponent
11791252
{
@@ -1188,6 +1261,7 @@ void LfpDisplay::mouseDown (const MouseEvent& event)
11881261
{
11891262
mindist = dist - 1;
11901263
closest = n;
1264+
chanRange = drawableChannels[n].channel->getRange();
11911265
}
11921266
}
11931267

@@ -1213,7 +1287,7 @@ void LfpDisplay::mouseDown (const MouseEvent& event)
12131287
{
12141288
drawableChannels[0].channelInfo->updateXY (
12151289
float (x) / getWidth() * canvasSplit->timebase,
1216-
(-(float (y) - viewport->getViewPositionY()) / viewport->getViewHeight() * float (getRange())) + float (getRange() / 2));
1290+
(-(float (y) - viewport->getViewPositionY()) / viewport->getViewHeight() * float (chanRange)) + float (chanRange / 2));
12171291
}
12181292
}
12191293

Plugins/LfpViewer/LfpDisplay.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,9 @@ class LfpDisplay : public Component,
9292
/** Sets the display range for a particular channel type*/
9393
void setRange (float range, ContinuousChannel::Type type);
9494

95+
/** Applies auto-scaling to AUX channels based on their individual InputRange values */
96+
void setAutoRangeForAuxChannels();
97+
9598
/** Returns the display range for the current channel type*/
9699
int getRange();
97100

Plugins/LfpViewer/LfpDisplayNode.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,14 +85,17 @@ void LfpDisplayNode::updateSettings()
8585
displayBufferMap[streamId]->sampleRate = channel->getSampleRate();
8686
displayBufferMap[streamId]->name = name;
8787
}
88-
//
88+
8989
displayBufferMap[streamId]->addChannel (channel->getName(), // name
9090
ch, // index
9191
channel->getChannelType(), // type
9292
channel->isRecorded,
93-
0, // group
93+
channel->group.number, // group
9494
channel->position.y, // ypos
95-
channel->getDescription());
95+
channel->getDescription(),
96+
"None", // structure
97+
channel->inputRange.min, // inputRangeMin
98+
channel->inputRange.max); // inputRangeMax
9699
}
97100

98101
Array<DisplayBuffer*> toDelete;

Plugins/LfpViewer/LfpDisplayOptions.cpp

Lines changed: 63 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ LfpDisplayOptions::LfpDisplayOptions (LfpDisplayCanvas* canvas_, LfpDisplaySplit
154154
typeButtons.add (tbut);
155155

156156
//Ranges for AUX/accelerometer data
157+
voltageRanges[ContinuousChannel::Type::AUX].add ("Auto");
157158
voltageRanges[ContinuousChannel::Type::AUX].add ("25");
158159
voltageRanges[ContinuousChannel::Type::AUX].add ("50");
159160
voltageRanges[ContinuousChannel::Type::AUX].add ("100");
@@ -163,7 +164,7 @@ LfpDisplayOptions::LfpDisplayOptions (LfpDisplayCanvas* canvas_, LfpDisplaySplit
163164
voltageRanges[ContinuousChannel::Type::AUX].add ("750");
164165
voltageRanges[ContinuousChannel::Type::AUX].add ("1000");
165166
voltageRanges[ContinuousChannel::Type::AUX].add ("2000");
166-
selectedVoltageRange[ContinuousChannel::Type::AUX] = 9;
167+
selectedVoltageRange[ContinuousChannel::Type::AUX] = 1; // Default to Auto
167168
rangeGain[ContinuousChannel::Type::AUX] = 0.001f; //mV
168169
rangeSteps[ContinuousChannel::Type::AUX] = 10;
169170
rangeUnits.add ("mV");
@@ -549,11 +550,23 @@ LfpDisplayOptions::LfpDisplayOptions (LfpDisplayCanvas* canvas_, LfpDisplaySplit
549550
* rangeGain[ContinuousChannel::Type::ELECTRODE],
550551
ContinuousChannel::Type::ELECTRODE);
551552
lfpDisplay->setRange (voltageRanges[ContinuousChannel::Type::ADC][selectedVoltageRange[ContinuousChannel::Type::ADC] - 1].getFloatValue()
552-
* rangeGain[ContinuousChannel::Type::AUX],
553+
* rangeGain[ContinuousChannel::Type::ADC],
553554
ContinuousChannel::Type::ADC);
554-
lfpDisplay->setRange (voltageRanges[ContinuousChannel::Type::AUX][selectedVoltageRange[ContinuousChannel::Type::AUX] - 1].getFloatValue()
555-
* rangeGain[ContinuousChannel::Type::AUX],
556-
ContinuousChannel::Type::AUX);
555+
556+
// Handle Auto scaling for AUX channels during initialization
557+
String auxRangeValue = voltageRanges[ContinuousChannel::Type::AUX][selectedVoltageRange[ContinuousChannel::Type::AUX] - 1];
558+
if (auxRangeValue.equalsIgnoreCase("Auto"))
559+
{
560+
// Set a default range value for the type (used as fallback)
561+
lfpDisplay->setRange(2000.0f * rangeGain[ContinuousChannel::Type::AUX], ContinuousChannel::Type::AUX);
562+
// Apply individual auto-scaling to each AUX channel based on their InputRange
563+
lfpDisplay->setAutoRangeForAuxChannels();
564+
}
565+
else
566+
{
567+
lfpDisplay->setRange (auxRangeValue.getFloatValue() * rangeGain[ContinuousChannel::Type::AUX],
568+
ContinuousChannel::Type::AUX);
569+
}
557570
}
558571

559572
void LfpDisplayOptions::timerCallback()
@@ -1198,17 +1211,39 @@ void LfpDisplayOptions::comboBoxChanged (ComboBox* cb)
11981211
{
11991212
if (cb->getSelectedId())
12001213
{
1201-
lfpDisplay->setRange (voltageRanges[selectedChannelType][cb->getSelectedId() - 1].getFloatValue() * rangeGain[selectedChannelType], selectedChannelType);
1214+
String selectedText = voltageRanges[selectedChannelType][cb->getSelectedId() - 1];
1215+
1216+
// Check if "Auto" is selected for AUX channels
1217+
if (selectedChannelType == ContinuousChannel::Type::AUX && selectedText.equalsIgnoreCase("Auto"))
1218+
{
1219+
// Set a default range value for the type (used as fallback)
1220+
lfpDisplay->setRange(2000.0f * rangeGain[selectedChannelType], selectedChannelType);
1221+
// Apply individual auto-scaling to each AUX channel based on their InputRange
1222+
lfpDisplay->setAutoRangeForAuxChannels();
1223+
}
1224+
else
1225+
{
1226+
lfpDisplay->setRange (selectedText.getFloatValue() * rangeGain[selectedChannelType], selectedChannelType);
1227+
}
12021228
}
12031229
else
12041230
{
12051231
float vRange = cb->getText().getFloatValue();
12061232
if (vRange)
12071233
{
1208-
if (vRange < voltageRanges[selectedChannelType][0].getFloatValue())
1234+
// Check if we should skip the first item (Auto) when validating range
1235+
int firstRangeIndex = 0;
1236+
if (selectedChannelType == ContinuousChannel::Type::AUX &&
1237+
voltageRanges[selectedChannelType][0].equalsIgnoreCase("Auto"))
12091238
{
1210-
cb->setSelectedId (1, dontSendNotification);
1211-
vRange = voltageRanges[selectedChannelType][0].getFloatValue();
1239+
firstRangeIndex = 1;
1240+
}
1241+
1242+
if (firstRangeIndex < voltageRanges[selectedChannelType].size() &&
1243+
vRange < voltageRanges[selectedChannelType][firstRangeIndex].getFloatValue())
1244+
{
1245+
cb->setSelectedId (firstRangeIndex + 1, dontSendNotification);
1246+
vRange = voltageRanges[selectedChannelType][firstRangeIndex].getFloatValue();
12121247
}
12131248
else if (vRange > voltageRanges[selectedChannelType][voltageRanges[selectedChannelType].size() - 1].getFloatValue())
12141249
{
@@ -1396,6 +1431,11 @@ ContinuousChannel::Type LfpDisplayOptions::getSelectedType()
13961431
return selectedChannelType;
13971432
}
13981433

1434+
bool LfpDisplayOptions::isAuxAutoScaleEnabled()
1435+
{
1436+
return selectedVoltageRangeValues[ContinuousChannel::Type::AUX].equalsIgnoreCase("Auto");
1437+
}
1438+
13991439
void LfpDisplayOptions::setSelectedType (ContinuousChannel::Type type, bool toggleButton)
14001440
{
14011441
if (selectedChannelType == type)
@@ -1547,7 +1587,20 @@ void LfpDisplayOptions::loadParameters (XmlElement* xml)
15471587
selectedVoltageRange[2] = voltageRanges[2].indexOf (ranges[2]) + 1;
15481588
rangeSelection->setText (ranges[selectedChannelType]);
15491589
lfpDisplay->setRange (ranges[0].getFloatValue() * rangeGain[0], ContinuousChannel::Type::ELECTRODE);
1550-
lfpDisplay->setRange (ranges[1].getFloatValue() * rangeGain[1], ContinuousChannel::Type::AUX);
1590+
1591+
// Handle Auto scaling for AUX channels
1592+
if (ranges[1].equalsIgnoreCase("Auto"))
1593+
{
1594+
// Set a default range value for the type (used as fallback)
1595+
lfpDisplay->setRange(2000.0f * rangeGain[ContinuousChannel::Type::AUX], ContinuousChannel::Type::AUX);
1596+
// Apply individual auto-scaling to each AUX channel based on their InputRange
1597+
lfpDisplay->setAutoRangeForAuxChannels();
1598+
}
1599+
else
1600+
{
1601+
lfpDisplay->setRange (ranges[1].getFloatValue() * rangeGain[1], ContinuousChannel::Type::AUX);
1602+
}
1603+
15511604
lfpDisplay->setRange (ranges[2].getFloatValue() * rangeGain[2], ContinuousChannel::Type::ADC);
15521605

15531606
// LOGD(" Set range in ", MS_FROM_START, " milliseconds");

Plugins/LfpViewer/LfpDisplayOptions.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,9 @@ class LfpDisplayOptions : public Component,
103103
/** Returns the selected channel type for the range editor */
104104
ContinuousChannel::Type getSelectedType();
105105

106+
/** Returns true if AUX channels are set to auto-scale */
107+
bool isAuxAutoScaleEnabled();
108+
106109
/** Returns the name for a given channel type (DATA, AUX, ADC) */
107110
String getTypeName (ContinuousChannel::Type type);
108111

Source/Processors/FileReader/FileReader.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,30 @@ void FileReader::updateSettings()
542542
};
543543

544544
continuousChannels.add (new ContinuousChannel (channelSettings));
545+
auto name = channelInfo[i].name;
546+
547+
if (channelInfo[i].type == ContinuousChannel::Type::AUX)
548+
{
549+
if (name.equalsIgnoreCase("Eul-Y"))
550+
continuousChannels.getLast()->inputRange = { -360.0f, 360.0f };
551+
else if (name.equalsIgnoreCase("Eul-R"))
552+
continuousChannels.getLast()->inputRange = { -90.0f, 90.0f };
553+
else if (name.equalsIgnoreCase("Eul-P"))
554+
continuousChannels.getLast()->inputRange = { -180.0f, 180.0f };
555+
else if (name.startsWithIgnoreCase("Quat"))
556+
continuousChannels.getLast()->inputRange = { -1.0f, 1.0f };
557+
else if (name.startsWithIgnoreCase("Acc"))
558+
continuousChannels.getLast()->inputRange = { -100.0f, 100.0f };
559+
else if (name.startsWithIgnoreCase("Grav"))
560+
continuousChannels.getLast()->inputRange = { -10.0f, 10.0f };
561+
else if (name.equalsIgnoreCase("Temp"))
562+
continuousChannels.getLast()->inputRange = { -100.0f, 100.0f };
563+
else if (name.startsWithIgnoreCase("Cal"))
564+
continuousChannels.getLast()->inputRange = { -3.0f, 3.0f };
565+
else
566+
continuousChannels.getLast()->inputRange = { -5000.0f, 5000.0f };
567+
}
568+
545569
continuousChannels.getLast()->addProcessor (this);
546570
}
547571

0 commit comments

Comments
 (0)