Skip to content

Commit c7a7469

Browse files
committed
Merge branch 'development' into test-pr
2 parents 0d2ff1d + 6d0e282 commit c7a7469

23 files changed

+467
-50
lines changed

.github/workflows/tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ jobs:
9696
- name: Install test-suite
9797
shell: powershell
9898
run: |
99-
git clone --branch juce8 https://github.com/open-ephys/open-ephys-python-tools.git C:\open-ephys-python-tools
99+
git clone --branch main https://github.com/open-ephys/open-ephys-python-tools.git C:\open-ephys-python-tools
100100
cd C:\open-ephys-python-tools
101101
pip install -e .
102102
pip install psutil

Plugins/LfpViewer/DisplayBuffer.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,10 @@ void DisplayBuffer::addChannel (
6666
int group,
6767
float ypos,
6868
String description,
69-
String structure)
69+
String structure,
70+
float inputRangeMin,
71+
float inputRangeMax,
72+
String units)
7073
{
7174
ChannelMetadata metadata = ChannelMetadata();
7275
metadata.name = name;
@@ -77,6 +80,9 @@ void DisplayBuffer::addChannel (
7780
metadata.type = type;
7881
metadata.isRecorded = isRecorded;
7982
metadata.description = description;
83+
metadata.inputRangeMin = inputRangeMin;
84+
metadata.inputRangeMax = inputRangeMax;
85+
metadata.units = units;
8086

8187
channelMetadata.add (metadata);
8288
channelMap[channelNum] = numChannels;

Plugins/LfpViewer/DisplayBuffer.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,10 @@ 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,
69+
String units = "");
6770

6871
/** Initializes the event channel at the start of each buffer */
6972
void initializeEventChannel (int nSamples);
@@ -91,6 +94,9 @@ class TESTABLE DisplayBuffer : public AudioBuffer<float>
9194
ContinuousChannel::Type type;
9295
bool isRecorded = false;
9396
String description = "";
97+
float inputRangeMin = -5000.0f;
98+
float inputRangeMax = +5000.0f;
99+
String units = "";
94100
};
95101

96102
Array<ChannelMetadata> channelMetadata;

Plugins/LfpViewer/LfpChannelDisplay.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,16 @@ void LfpChannelDisplay::setType (ContinuousChannel::Type type_)
7979
typeStr = options->getTypeName (type);
8080
}
8181

82+
void LfpChannelDisplay::setUnits (const String& newUnits)
83+
{
84+
units = newUnits;
85+
}
86+
87+
const String& LfpChannelDisplay::getUnits() const
88+
{
89+
return units;
90+
}
91+
8292
void LfpChannelDisplay::setEnabledState (bool state)
8393
{
8494
/*if (state)

Plugins/LfpViewer/LfpChannelDisplay.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,12 @@ class LfpChannelDisplay : public Component
113113
/** Return the assigned channel name */
114114
String getName();
115115

116+
/** Set the units string used for display */
117+
void setUnits (const String& newUnits);
118+
119+
/** Return the units string for this channel */
120+
const String& getUnits() const;
121+
116122
/** Returns the assigned channel number for this display, relative
117123
to the subset of channels being drawn to the canvas */
118124
int getDrawableChannelNumber();
@@ -193,6 +199,8 @@ class LfpChannelDisplay : public Component
193199
float depth;
194200
bool isRecorded;
195201

202+
String units;
203+
196204
FontOptions channelFont;
197205

198206
Colour lineColour;

Plugins/LfpViewer/LfpChannelDisplayInfo.cpp

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,8 +239,31 @@ void LfpChannelDisplayInfo::paint (Graphics& g)
239239

240240
if (getChannelTypeStringVisibility())
241241
{
242+
constexpr int textHeight = 14;
243+
constexpr int textStartX = 5;
244+
const int textY = center + 10;
245+
242246
g.setFont (FontOptions (13.0f));
243-
g.drawText (typeStr, 5, center + 10, 50, 14, Justification::centred, false);
247+
g.setColour (lineColour);
248+
const auto currentFont = g.getCurrentFont();
249+
250+
const int typeWidth = currentFont.getStringWidth (typeStr);
251+
const int typeBoundsWidth = typeWidth + 2;
252+
g.drawText (typeStr, textStartX, textY, typeBoundsWidth, textHeight, Justification::centredLeft, false);
253+
254+
const String& unitsText = getUnits();
255+
if (unitsText.isNotEmpty())
256+
{
257+
const int unitsX = textStartX + typeWidth + 5;
258+
const int unitsWidth = getWidth() - unitsX - 4;
259+
260+
if (unitsWidth > 0)
261+
{
262+
g.setColour (Colours::grey.withAlpha (0.8f));
263+
g.setFont (FontOptions (12.0f));
264+
g.drawFittedText (unitsText, unitsX, textY, unitsWidth, textHeight, Justification::centredLeft, 1, 0.8f);
265+
}
266+
}
244267
}
245268

246269
if (isSingleChannel)

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/LfpDisplayCanvas.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
#include "ShowHideOptionsButton.h"
3131

3232
#include <math.h>
33+
#include <algorithm>
34+
#include <cmath>
3335

3436
#define MS_FROM_START Time::highResolutionTicksToSeconds (Time::getHighResolutionTicks() - start) * 1000
3537

@@ -750,6 +752,27 @@ String LfpDisplaySplitter::getStreamKey()
750752
return stream->getKey();
751753
}
752754

755+
void LfpDisplaySplitter::refreshLeftMargin()
756+
{
757+
int newMargin = minimumLeftMargin;
758+
759+
if (displayBuffer != nullptr)
760+
{
761+
const auto labelFont = Font (FontOptions (14.0f));
762+
constexpr int padding = 20;
763+
764+
for (int i = 0; i < displayBuffer->channelMetadata.size(); ++i)
765+
{
766+
const auto& metadata = displayBuffer->channelMetadata.getReference (i);
767+
const float textWidth = labelFont.getStringWidthFloat (metadata.name);
768+
const int requiredWidth = static_cast<int> (std::ceil (textWidth)) + padding;
769+
newMargin = std::max (newMargin, requiredWidth);
770+
}
771+
}
772+
773+
leftmargin = newMargin;
774+
}
775+
753776
void LfpDisplaySplitter::resized()
754777
{
755778
const int timescaleHeight = 30;
@@ -928,6 +951,7 @@ void LfpDisplaySplitter::updateSettings()
928951
sampleRate = 44100.0f;
929952

930953
options->setEnabled (true);
954+
leftmargin = minimumLeftMargin;
931955
}
932956
else
933957
{
@@ -942,6 +966,8 @@ void LfpDisplaySplitter::updateSettings()
942966

943967
options->setEnabled (true);
944968
channelOverlapFactor = options->selectedOverlapValue.getFloatValue();
969+
970+
refreshLeftMargin();
945971
}
946972

947973
if (eventDisplayBuffer == nullptr) // not yet initialized
@@ -968,12 +994,14 @@ void LfpDisplaySplitter::updateSettings()
968994
lfpDisplay->channels[i]->setDepth (displayBuffer->channelMetadata[i].ypos);
969995
lfpDisplay->channels[i]->setRecorded (displayBuffer->channelMetadata[i].isRecorded);
970996
lfpDisplay->channels[i]->updateType (displayBuffer->channelMetadata[i].type);
997+
lfpDisplay->channels[i]->setUnits (displayBuffer->channelMetadata[i].units);
971998

972999
lfpDisplay->channelInfo[i]->setName (displayBuffer->channelMetadata[i].name);
9731000
lfpDisplay->channelInfo[i]->setGroup (displayBuffer->channelMetadata[i].group);
9741001
lfpDisplay->channelInfo[i]->setDepth (displayBuffer->channelMetadata[i].ypos);
9751002
lfpDisplay->channelInfo[i]->setRecorded (displayBuffer->channelMetadata[i].isRecorded);
9761003
lfpDisplay->channelInfo[i]->updateType (displayBuffer->channelMetadata[i].type);
1004+
lfpDisplay->channelInfo[i]->setUnits (displayBuffer->channelMetadata[i].units);
9771005

9781006
lfpDisplay->updateRange (i);
9791007

Plugins/LfpViewer/LfpDisplayCanvas.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -308,8 +308,11 @@ class LfpDisplaySplitter : public Component,
308308
*/
309309
bool fullredraw;
310310

311-
/** Left margin for lfp plots (so the ch number text doesnt overlap) */
312-
static const int leftmargin = 60; //
311+
/** Minimum left margin for LFP plots (so the channel label has space) */
312+
static constexpr int minimumLeftMargin = 60;
313+
314+
/** Left margin for LFP plots, adjusted to fit the widest channel label */
315+
int leftmargin = minimumLeftMargin;
313316

314317
Array<bool> isChannelEnabled;
315318

@@ -359,6 +362,8 @@ class LfpDisplaySplitter : public Component,
359362
String getStreamKey();
360363

361364
private:
365+
void refreshLeftMargin();
366+
362367
bool isSelected;
363368
bool isUpdating;
364369

0 commit comments

Comments
 (0)