Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rhs2116 Stimulus Sequence Dialog - Plot pulses in red to highlight them #346

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
<PackageLicenseFile>LICENSE</PackageLicenseFile>
<UseArtifactsOutput>true</UseArtifactsOutput>
<PackageIcon>icon.png</PackageIcon>
<VersionPrefix>0.4.0</VersionPrefix>
<VersionPrefix>0.4.1</VersionPrefix>
<VersionSuffix></VersionSuffix>
<LangVersion>10.0</LangVersion>
<Features>strict</Features>
Expand Down
117 changes: 93 additions & 24 deletions OpenEphys.Onix1.Design/Rhs2116StimulusSequenceDialog.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Windows.Forms;
using ZedGraph;
using System.IO;
using System.Collections.Generic;

namespace OpenEphys.Onix1.Design
{
Expand Down Expand Up @@ -258,22 +259,24 @@ private void DrawStimulusWaveform()

if (ChannelDialog.SelectedContacts[i] || plotAllContacts)
{
PointPairList pointPairs = CreateStimulusWaveform(stimuli[i], channelOffset, peakToPeak);
List<PointPairList> pulses = CreatePulses(stimuli[i], channelOffset, peakToPeak);

Color color;
if (stimuli[i].IsValid())
{
color = Color.CornflowerBlue;
}
else
foreach (var pulse in pulses)
{
color = Color.Red;
var pulseCurve = zedGraphWaveform.GraphPane.AddCurve("", pulse, Color.Red, SymbolType.None);

pulseCurve.Label.IsVisible = false;
pulseCurve.Line.Width = 4;
}

var curve = zedGraphWaveform.GraphPane.AddCurve("", pointPairs, color, SymbolType.None);
PointPairList pointPairs = CreateStimulusWaveform(stimuli[i], channelOffset, peakToPeak);

Color color = stimuli[i].IsValid() ? Color.CornflowerBlue : Color.DarkRed;

var waveformCurve = zedGraphWaveform.GraphPane.AddCurve("", pointPairs, color, SymbolType.None);

curve.Label.IsVisible = false;
curve.Line.Width = 3;
waveformCurve.Label.IsVisible = false;
waveformCurve.Line.Width = 2;

maxLength = pointPairs.Last().X > maxLength ? pointPairs.Last().X : maxLength;
}
Expand All @@ -296,7 +299,7 @@ private void DrawStimulusWaveform()

SetZoomOutBoundaries(zedGraphWaveform);

ZoomInBoundaryX = (ZoomOutBoundaryRight - ZoomOutBoundaryLeft) * 0.05;
ZoomInBoundaryX = (ZoomOutBoundaryRight - ZoomOutBoundaryLeft) * 0.01;

dataGridViewStimulusTable.Refresh();

Expand Down Expand Up @@ -375,30 +378,96 @@ private PointPairList CreateStimulusWaveform(Rhs2116Stimulus stimulus, double yO

for (int i = 0; i < stimulus.NumberOfStimuli; i++)
{
double amplitude = (stimulus.AnodicFirst ? stimulus.AnodicAmplitudeSteps : -stimulus.CathodicAmplitudeSteps) * Sequence.CurrentStepSizeuA / peakToPeak + yOffset;
double width = (stimulus.AnodicFirst ? stimulus.AnodicWidthSamples : stimulus.CathodicWidthSamples) * SamplePeriodMilliSeconds;
double amplitude = CalculateFirstPulseAmplitude(stimulus.AnodicFirst, stimulus.AnodicAmplitudeSteps, stimulus.CathodicAmplitudeSteps, peakToPeak, yOffset);
double width = CalculateFirstPulseWidth(stimulus.AnodicFirst, stimulus.AnodicWidthSamples, stimulus.CathodicWidthSamples);

points.Add(points[points.Count - 1].X, amplitude);
points.Add(points[points.Count - 1].X + width, amplitude);
points.Add(points[points.Count - 1].X, yOffset);
points.AddRange(CreatePulse(points[points.Count - 1].X, amplitude, width, yOffset));

points.Add(points[points.Count - 1].X + stimulus.DwellSamples * SamplePeriodMilliSeconds, yOffset);
points.Add(points.Last().X + stimulus.DwellSamples * SamplePeriodMilliSeconds, yOffset);

amplitude = (stimulus.AnodicFirst ? -stimulus.CathodicAmplitudeSteps : stimulus.AnodicAmplitudeSteps) * Sequence.CurrentStepSizeuA / peakToPeak + yOffset;
width = (stimulus.AnodicFirst ? stimulus.CathodicWidthSamples : stimulus.AnodicWidthSamples) * SamplePeriodMilliSeconds;
amplitude = CalculateSecondPulseAmplitude(stimulus.AnodicFirst, stimulus.AnodicAmplitudeSteps, stimulus.CathodicAmplitudeSteps, peakToPeak, yOffset);
width = CalculateSecondPulseWidth(stimulus.AnodicFirst, stimulus.AnodicWidthSamples, stimulus.CathodicWidthSamples);

points.Add(points[points.Count - 1].X, amplitude);
points.Add(points[points.Count - 1].X + width, amplitude);
points.Add(points[points.Count - 1].X, yOffset);
points.AddRange(CreatePulse(points[points.Count - 1].X, amplitude, width, yOffset));

points.Add(points[points.Count - 1].X + stimulus.InterStimulusIntervalSamples * SamplePeriodMilliSeconds, yOffset);
points.Add(points.Last().X + stimulus.InterStimulusIntervalSamples * SamplePeriodMilliSeconds, yOffset);
}

points.Add(Sequence.SequenceLengthSamples * SamplePeriodMilliSeconds, yOffset);

return points;
}

/// <summary>
/// Only create the pulses, so that they can be plotted as an overlay on top of the full waveform to highlight individual pulses
/// </summary>
/// <param name="stimulus"></param>
/// <param name="yOffset"></param>
/// <param name="peakToPeak"></param>
/// <returns></returns>
private List<PointPairList> CreatePulses(Rhs2116Stimulus stimulus, double yOffset, double peakToPeak)
{
yOffset /= peakToPeak;

var pulses = new List<PointPairList>();

for (int i = 0; i < stimulus.NumberOfStimuli; i++)
{
PointPairList pulse = new();

if (i == 0)
pulse.Add(stimulus.DelaySamples * SamplePeriodMilliSeconds, yOffset);
else
pulse.Add(pulses.Last().Last().X + stimulus.InterStimulusIntervalSamples * SamplePeriodMilliSeconds, yOffset);

double amplitude = CalculateFirstPulseAmplitude(stimulus.AnodicFirst, stimulus.AnodicAmplitudeSteps, stimulus.CathodicAmplitudeSteps, peakToPeak, yOffset);
double width = CalculateFirstPulseWidth(stimulus.AnodicFirst, stimulus.AnodicWidthSamples, stimulus.CathodicWidthSamples);

pulse.AddRange(CreatePulse(pulse[pulse.Count - 1].X, amplitude, width, yOffset));

pulse.Add(pulse[pulse.Count - 1].X + stimulus.DwellSamples * SamplePeriodMilliSeconds, yOffset);

amplitude = CalculateSecondPulseAmplitude(stimulus.AnodicFirst, stimulus.AnodicAmplitudeSteps, stimulus.CathodicAmplitudeSteps, peakToPeak, yOffset);
width = CalculateSecondPulseWidth(stimulus.AnodicFirst, stimulus.AnodicWidthSamples, stimulus.CathodicWidthSamples);

pulse.AddRange(CreatePulse(pulse[pulse.Count - 1].X, amplitude, width, yOffset));

pulses.Add(pulse);
}

return pulses;
}

private double CalculateSecondPulseWidth(bool anodicFirst, uint anodicWidthSamples, uint cathodicWidthSamples)
{
return (anodicFirst ? cathodicWidthSamples : anodicWidthSamples) * SamplePeriodMilliSeconds;
}

private double CalculateSecondPulseAmplitude(bool anodicFirst, byte anodicAmplitudeSteps, byte cathodicAmplitudeSteps, double peakToPeak, double yOffset)
{
return (anodicFirst ? -cathodicAmplitudeSteps : anodicAmplitudeSteps) * Sequence.CurrentStepSizeuA / peakToPeak + yOffset;
}

private List<PointPair> CreatePulse(double x, double amplitude, double width, double yOffset)
{
return new List<PointPair>()
{
{ new PointPair(x, amplitude) },
{ new PointPair(x + width, amplitude) },
{ new PointPair(x + width, yOffset) },
};
}

private double CalculateFirstPulseWidth(bool anodicFirst, uint anodicWidthSamples, uint cathodicWidthSamples)
{
return (anodicFirst ? anodicWidthSamples : cathodicWidthSamples) * SamplePeriodMilliSeconds;
}

private double CalculateFirstPulseAmplitude(bool anodicFirst, byte anodicAmplitudeSteps, byte cathodicAmplitudeSteps, double peakToPeak, double yOffset)
{
return (anodicFirst ? anodicAmplitudeSteps : -cathodicAmplitudeSteps) * Sequence.CurrentStepSizeuA / peakToPeak + yOffset;
}

private void InitializeZedGraphWaveform()
{
zedGraphWaveform.IsZoomOnMouseCenter = true;
Expand Down