Skip to content

Commit f9e1196

Browse files
committed
Added PPD scaling per decade, and Markers checkbox
1 parent 1f858ea commit f9e1196

File tree

4 files changed

+67
-16
lines changed

4 files changed

+67
-16
lines changed

source/NSD.UI/MainWindow.axaml

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@
7878
<Label Grid.Row="4" VerticalAlignment="Stretch" VerticalContentAlignment="Center" Margin="0,3,0,3">Input scaling</Label>
7979
<TextBox Grid.Row="4" Grid.Column="1" Margin="0,3,0,3" Watermark="Input scaling..." Text="{Binding InputScaling}" IsEnabled="{Binding Enabled}" MinWidth="120" HorizontalAlignment="Left"></TextBox>
8080

81-
<Label Grid.Row="5" Grid.Column="0" VerticalAlignment="Stretch" VerticalContentAlignment="Center" Margin="0,3,0,3">NSD algorithm</Label>
81+
<Label Grid.Row="5" Grid.Column="0" VerticalAlignment="Stretch" VerticalContentAlignment="Center" Margin="0,3,0,3">NSD mode</Label>
8282
<StackPanel Orientation="Horizontal" Grid.Row="5" Grid.Column="1" Margin="0,3,0,3">
8383
<ComboBox SelectedIndex="0" SelectedItem="{Binding SelectedNsdAlgorithm, Mode=OneWayToSource}" IsEnabled="{Binding Enabled}" HorizontalAlignment="Stretch" VerticalAlignment="Center" MinWidth="120">
8484
<ComboBoxItem>Logarithmic</ComboBoxItem>
@@ -87,12 +87,26 @@
8787
</ComboBox>
8888

8989
<StackPanel x:Name="spLogarithmic" Orientation="Horizontal" Margin="6,0,0,0" IsVisible="{Binding AlgorithmLog}">
90-
<Label VerticalAlignment="Stretch" VerticalContentAlignment="Center" Margin="6,0,0,0">Points per decade</Label>
91-
<TextBox Text="{Binding LogNsdPointsDecade}" IsEnabled="{Binding Enabled}" MinWidth="30" Width="50" HorizontalAlignment="Left"></TextBox>
92-
<Label VerticalAlignment="Stretch" VerticalContentAlignment="Center">Minimum averages</Label>
93-
<TextBox Text="{Binding LogNsdMinAverages}" IsEnabled="{Binding Enabled}" MinWidth="30" Width="50" HorizontalAlignment="Left"></TextBox>
94-
<Label VerticalAlignment="Stretch" VerticalContentAlignment="Center">Minimum spectrum length</Label>
95-
<TextBox Text="{Binding LogNsdMinLength}" IsEnabled="{Binding Enabled}" MinWidth="30" Width="50" HorizontalAlignment="Left"></TextBox>
90+
<Label VerticalAlignment="Stretch" VerticalContentAlignment="Center" Margin="6,0,0,0">Points per decade (PPD)</Label>
91+
<TextBox Text="{Binding LogNsdPointsDecade}" IsEnabled="{Binding Enabled}" MinWidth="30" Width="40" HorizontalAlignment="Left"></TextBox>
92+
<Label VerticalAlignment="Stretch" VerticalContentAlignment="Center" Margin="6,0,0,0">PPD scaling per decade</Label>
93+
<TextBox Text="{Binding LogNsdPointsDecadeScaling}" IsEnabled="{Binding Enabled}" MinWidth="30" Width="40" HorizontalAlignment="Left"></TextBox>
94+
<Label IsVisible="false" VerticalAlignment="Stretch" VerticalContentAlignment="Center">Min. averages</Label>
95+
<TextBox IsVisible="false" Text="{Binding LogNsdMinAverages}" IsEnabled="{Binding Enabled}" MinWidth="30" Width="40" HorizontalAlignment="Left"></TextBox>
96+
<Label VerticalAlignment="Stretch" VerticalContentAlignment="Center">Min. spectral length</Label>
97+
<TextBox IsVisible="false" Text="{Binding LogNsdMinLength}" IsEnabled="{Binding Enabled}" MinWidth="30" Width="40" HorizontalAlignment="Left"></TextBox>
98+
<ComboBox SelectedIndex="6" SelectedItem="{Binding SelectedLogNsdMinLength, Mode=OneWayToSource}" IsEnabled="{Binding Enabled}" HorizontalAlignment="Stretch">
99+
<ComboBoxItem>2</ComboBoxItem>
100+
<ComboBoxItem>4</ComboBoxItem>
101+
<ComboBoxItem>8</ComboBoxItem>
102+
<ComboBoxItem>16</ComboBoxItem>
103+
<ComboBoxItem>32</ComboBoxItem>
104+
<ComboBoxItem>64</ComboBoxItem>
105+
<ComboBoxItem>128</ComboBoxItem>
106+
<ComboBoxItem>256</ComboBoxItem>
107+
<ComboBoxItem>512</ComboBoxItem>
108+
<ComboBoxItem>1024</ComboBoxItem>
109+
</ComboBox>
96110
</StackPanel>
97111
<StackPanel x:Name="spLinear" Orientation="Horizontal" Margin="6,0,0,0" IsVisible="{Binding AlgorithmLin}">
98112
<Label VerticalAlignment="Stretch" VerticalContentAlignment="Center">FFT length</Label>
@@ -163,6 +177,7 @@
163177
<Label VerticalAlignment="Center">Y Max</Label>
164178
<NumericUpDown Value="{Binding YMax}" AllowSpin="false" ShowButtonSpinner="false" Width="100" IsEnabled="{Binding Enabled}" Padding="0"></NumericUpDown>
165179
<CheckBox Grid.Row="9" Grid.Column="0" Grid.ColumnSpan="2" Margin="6,0,0,0" Content="Savitzky-Golay filter" IsChecked="{Binding SgFilterChecked}" IsEnabled="{Binding Enabled}"></CheckBox>
180+
<CheckBox Grid.Row="9" Grid.Column="0" Grid.ColumnSpan="2" Margin="6,0,0,0" Content="Markers" IsChecked="{Binding MarkersChecked}" IsEnabled="{Binding Enabled}"></CheckBox>
166181
</StackPanel>
167182
<Button Grid.Row="9" Grid.ColumnSpan="3" Margin="0,6,0,6" Content="Set axis" HorizontalAlignment="Stretch" Click="btnSetAxis_Click" IsEnabled="{Binding Enabled}"></Button>
168183

source/NSD.UI/MainWindow.axaml.cs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -186,16 +186,19 @@ await Task.Run(() =>
186186
case "Logarithmic":
187187
{
188188
var pointsPerDecade = int.Parse(viewModel.LogNsdPointsDecade);
189+
var pointsPerDecadeScaling = double.Parse(viewModel.LogNsdPointsDecadeScaling);
189190
var minAverages = int.Parse(viewModel.LogNsdMinAverages);
190-
var minLength = int.Parse(viewModel.LogNsdMinLength);
191+
//var minLength = int.Parse(viewModel.LogNsdMinLength);
192+
var minLength = int.Parse((string)viewModel.SelectedLogNsdMinLength.Content);
191193
var nsd = await Task.Factory.StartNew(() => NSD.Log(
192194
input: records.ToArray(),
193195
sampleRateHz: 1.0 / acquisitionTimeSeconds,
194196
freqMin: viewModel.XMin,
195197
freqMax: viewModel.XMax,
196198
pointsPerDecade,
197199
minAverages,
198-
minLength));
200+
minLength,
201+
pointsPerDecadeScaling));
199202
spectrum = nsd;
200203
break;
201204
}
@@ -336,6 +339,12 @@ public void UpdateNSDChart(Memory<double> x, Memory<double> y)
336339
double[] logYs = y.ToArray().Select(pt => Math.Log10(pt * 1E9)).ToArray();
337340
var scatter = WpfPlot1.Plot.Add.ScatterLine(logXs, logYs);
338341
//var scatter = WpfPlot1.Plot.Add.Scatter(logXs, logYs);
342+
if (viewModel.MarkersChecked)
343+
{
344+
scatter.MarkerStyle.Shape = ScottPlot.MarkerShape.FilledCircle;
345+
scatter.MarkerStyle.Size = 3;
346+
scatter.MarkerStyle.IsVisible = true;
347+
}
339348
CommonChartConfig();
340349
}
341350

source/NSD.UI/MainWindowViewModel.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,13 @@ public partial class MainWindowViewModel : ObservableObject
2222
[ObservableProperty] int selectedInputFileIndex = -1;
2323
[ObservableProperty] string outputFileName = "output.nsd";
2424
[ObservableProperty] bool sgFilterChecked = false;
25+
[ObservableProperty] bool markersChecked = false;
2526
[ObservableProperty] IBrush statusBackground = Brushes.WhiteSmoke;
2627
[ObservableProperty] string inputScaling = "1.0";
27-
[ObservableProperty] string logNsdPointsDecade = "20";
28+
[ObservableProperty] string logNsdPointsDecade = "5";
29+
[ObservableProperty] string logNsdPointsDecadeScaling = "2.0";
2830
[ObservableProperty] string logNsdMinAverages = "1";
29-
[ObservableProperty] string logNsdMinLength = "256";
31+
[ObservableProperty] string logNsdMinLength = "128";
3032

3133
public ComboBoxItem? SelectedAcquisitionTimebaseItem { get; set; }
3234
public ComboBoxItem? SelectedDataRateUnitItem { get; set; }
@@ -60,6 +62,7 @@ public ComboBoxItem? SelectedNsdAlgorithm
6062
public ComboBoxItem? SelectedLinearLengthItem { get; set; }
6163
public ComboBoxItem? SelectedLinearStackingLengthItem { get; set; }
6264
public ComboBoxItem? SelectedLinearStackingMinLengthItem { get; set; }
65+
public ComboBoxItem? SelectedLogNsdMinLength { get; set; }
6366
[ObservableProperty] bool algorithmLog = true; // Controls visibility of sub-stack panel
6467
[ObservableProperty] bool algorithmLin = false; // Controls visibility of sub-stack panel
6568
[ObservableProperty] bool algorithmLinStack = false; // Controls visibility of sub-stack panel

source/NSD/NSD.cs

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -84,12 +84,12 @@ public static Spectrum StackedLinear(Memory<double> input, double sampleRate, in
8484
}
8585

8686
private record WelchGoertzelJob(double Frequency, int SpectrumLength, int CalculatedAverages);
87-
public static Spectrum Log(Memory<double> input, double sampleRateHz, double freqMin, double freqMax, int pointsPerDecade, int minimumAverages, int minimumLength)
87+
public static Spectrum Log(Memory<double> input, double sampleRateHz, double freqMin, double freqMax, int pointsPerDecade, int minimumAverages, int minimumFourierLength, double pointsPerDecadeScaling)
8888
{
8989
if (freqMax <= freqMin)
9090
throw new ArgumentException("freqMax must be greater than freqMin");
91-
if (pointsPerDecade <= 0 || minimumAverages <= 0 || minimumLength <= 0)
92-
throw new ArgumentException("pointsPerDecade, minimumAverages, and minimumLength must be positive");
91+
if (pointsPerDecade <= 0 || minimumAverages <= 0 || minimumFourierLength <= 0)
92+
throw new ArgumentException("pointsPerDecade, minimumAverages, and minimumFourierLength must be positive");
9393
if (sampleRateHz <= 0)
9494
throw new ArgumentException("sampleRateHz must be positive");
9595

@@ -104,11 +104,35 @@ public static Spectrum Log(Memory<double> input, double sampleRateHz, double fre
104104
double decades = Math.Log10(decadeMax / decadeMin);
105105
int desiredNumberOfPoints = (int)(decades * pointsPerDecade) + 1; // + 1 to get points on the decade grid lines
106106

107+
int decadeMinExponent = (int)Math.Log10(decadeMin);
108+
int decadeMaxExponent = (int)Math.Log10(decadeMax);
109+
List<double> meh = [];
110+
int pointsPerDecadeScaled = pointsPerDecade;
111+
for (int decadeExponent = decadeMinExponent; decadeExponent < decadeMaxExponent; decadeExponent++)
112+
{
113+
double currentDecadeMin = Math.Pow(10, decadeExponent);
114+
double currentDecadeMax = Math.Pow(10, decadeExponent + 1);
115+
double multiple = Math.Log(currentDecadeMax) - Math.Log(currentDecadeMin);
116+
var decadeFrequencies = Enumerable.Range(0, pointsPerDecadeScaled - 1).Select(i => currentDecadeMin * Math.Exp(i * multiple / (pointsPerDecadeScaled - 1))).ToArray();
117+
meh.AddRange(decadeFrequencies);
118+
pointsPerDecadeScaled = (int)(pointsPerDecadeScaled * pointsPerDecadeScaling);
119+
}
120+
107121
double g = Math.Log(decadeMax) - Math.Log(decadeMin);
108-
double[] frequencies = Enumerable.Range(0, desiredNumberOfPoints).Select(j => decadeMin * Math.Exp(j * g / (desiredNumberOfPoints - 1))).ToArray();
122+
//double[] frequencies = Enumerable.Range(0, desiredNumberOfPoints).Select(j => decadeMin * Math.Exp(j * g / (desiredNumberOfPoints - 1))).ToArray();
123+
double[] frequencies = meh.ToArray();
109124
double[] spectrumResolution = frequencies.Select(freq => freq / firstUsableBinForWindow).ToArray();
110125
// spectrumResolution contains the 'desired resolutions' for each frequency bin, respecting the rule that we want the first usuable bin for the given window.
111126

127+
// Maybe we also want to scale the spectrum resolution by integer log values?
128+
List<int> scalingValues = new List<int>();
129+
for(int i = 0; i < desiredNumberOfPoints; i++)
130+
{
131+
var scale = (int)Math.Exp(i * (g/4.0) / (desiredNumberOfPoints - 1));
132+
scalingValues.Add(scale);
133+
//spectrumResolution[i] /= scale;
134+
}
135+
112136
int[] spectrumLengths = spectrumResolution.Select(resolution => (int)Math.Round(sampleRateHz / resolution)).ToArray();
113137

114138
// Create a job list of valid points to calculate
@@ -128,7 +152,7 @@ public static Spectrum Log(Memory<double> input, double sampleRateHz, double fre
128152
bool continueLoop = true;
129153
while (continueLoop)
130154
{
131-
if (spectrumLength < minimumLength && averages > minimumAverages)
155+
if (spectrumLength < minimumFourierLength && averages > minimumAverages)
132156
{
133157
var success = TryCalculateAverages(input.Length, spectrumLength * 2, optimumOverlap, out var newAverages);
134158
if (!success)

0 commit comments

Comments
 (0)