You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: UDataPlotWindow.cpp
+99-51
Original file line number
Diff line number
Diff line change
@@ -4,10 +4,9 @@
4
4
// Loosely based on an original public domain version by Frank Heinrich, mail@frank-heinrich.de
5
5
//
6
6
// Originally created using Borland Builder c++ V5
7
-
// This version compiled with Embarcadero® C++Builder 11.3
7
+
// This version compiled with Embarcadero® C++Builder 12.1
8
8
// It should be easy to move to a more recent version of C++Builder, but equally it would not be very hard to revert to earlier versions if necessary.
9
-
// This is compiled for (and this is the only version that has been tested) Windows 32 bits.
10
-
// It runs on Windows 10 64 bits. In theory it should run on windows versions from Vista onwards and 32bit versions of Windows but this is untested.
9
+
//
11
10
//
12
11
// Version Date : changes from previous version
13
12
// 1v0 1/1/2021 : 1st version released on github (was 16v6).
@@ -153,6 +152,19 @@
153
152
// 11n - added tiff and wdp file save
154
153
// 11o - csvgraph/manual path can now be unicode - removed AnsiOf() & UnicodeOf() as not needed anymore. Most _WIN64 #if's also removed as no longer required.
155
154
// >> renamed 4v0 for release
155
+
// 4v1 24/9/2024 1st version using C++ Builder 12.1
156
+
// 1b - for x values allowed >= for "monotonic". Previoulsy required > which caused issues when we run out of resolution in a float (e.g. file csvfunbig.csv)
157
+
// 1c - better "fixup" for equal x values
158
+
// 1d - min abs/rel error fit improved (some calculations were done in double but should have been in float)
159
+
// - GMR line fit could generate a line with the wrong slope! - fixed
160
+
// 1e - let user select if equal x values are optimised or not. Only ask once if multiple traces added in a block.
161
+
// 1f - central moving average & cumulative average filters added
162
+
// 1g - central moving average filter - full (efficient) code in place
163
+
// 1h - start of new median filter code
164
+
// 1i - new median code fully working. Uses time to swap from exact to approximate algorithms.
165
+
// 1j - new median code optimised, and errors of approximate algorithms bounded
166
+
// 1k - cumulate average changed to Kalman filter as that's more useful.
167
+
// 1L - improved Kalman filter implementation
156
168
//
157
169
// TO DO:
158
170
//
@@ -234,9 +246,9 @@
234
246
extern TForm1 *Form1;
235
247
externconstchar * Prog_Name;
236
248
#ifdef _WIN64
237
-
constchar * Prog_Name="CSVgraph (Github) 4v0 (64 bit)"; // needs to be global as used in about box as well.
249
+
constchar * Prog_Name="CSVgraph (Github) 4v1 (64 bit)"; // needs to be global as used in about box as well.
238
250
#else
239
-
constchar * Prog_Name="CSVgraph (Github) 4v0 (32 bit)"; // needs to be global as used in about box as well.
251
+
constchar * Prog_Name="CSVgraph (Github) 4v1 (32 bit)"; // needs to be global as used in about box as well.
240
252
#endif
241
253
#if1/* if 1 then use fast_strtof() rather than atof() for floating point conversion. Note in this application this is only slightly faster (1-5%) */
242
254
extern"C"floatfast_strtof(constchar *s,char **endptr); // if endptr != NULL returns 1st character thats not in the number
doublemedian_ahead_t; // >0 for median filtering to be used
1537
1550
int poly_order=2;
@@ -2195,7 +2208,7 @@ try{
2195
2208
}
2196
2209
2197
2210
// get x value
2198
-
if(allvalidxvals && nos_traces_added>1 && xmonotonic && !compress ) // This optimisation disabled if lines with invalid xvals found (and skipped)
2211
+
if(allvalidxvals && nos_traces_added>1 && xmonotonic && !compress && dupXmessage!=IDNO ) // This optimisation disabled if lines with invalid xvals found (and skipped)
2199
2212
{xval=(float)((double)(pScientificGraph->fnAddDataPoint_nextx(iGraph))-x_offset); // same value as previous graph loaded as this is faster than decoding it again , x_offset will be added later but is already in previous trace so must subtract here
{// try and fix up (starts with two x values being equal, but fixup could make this worse for a while)
2436
-
// eg 1 2 2 2 3 -> 1 2 3 4 5
2437
-
xval=nextafterf(previousxvalue,FLT_MAX); // keep incrementing value we wil use for x-axis
2438
-
// rprintf("Fixup x value: xval was %.9g fixed up to %.9g, previousxvalue=%.9g prev_last_actual_x_value=%.9g\n",last_actual_x_value,xval,previousxvalue,prev_last_actual_x_value);
2439
-
}
2440
-
elseif((float)xval<=(float)previousxvalue)
2441
-
{ // x value is NOT monotonically increasing (could be =, but we leave that case for sorting as well as in general we cannot fix that here)
2447
+
if((float)xval<(float)previousxvalue)
2448
+
{ // x value is NOT monotonically increasing (equal values are OK)
else {// x value is monotonically increasing (or =)
2446
2453
2447
2454
#if1/* this way of compressing only works if x values are monotonically increasing, we only know this correctly on the 2nd trace added onwards when we can trust xmonotonic */
2448
2455
/* There is a general solution for compression in function compress_y() but that requires reading all data into an array and then compressing it (and then freeing extra memory) so peak RAM is lower by doing it here if we can */
@@ -2509,18 +2516,21 @@ try{
2509
2516
ShowMessage(cap_str);
2510
2517
}
2511
2518
#if1/* check x values are monotonic if we think they are */
2519
+
bool found_eq_xvals=false;
2512
2520
if(xmonotonic)
2513
2521
{float *xptr,*yptr;
2514
2522
size_t nos_points;
2515
2523
bool sorted=true;
2516
2524
// size_t fnGetxyarr(float **x_arr,float **y_arr,int iGraphNumberF = 0); // allow access to x and y arrays, returns nos points
if(dupXmessage==0) // IDYES!=0 and IDNO!=0, so we only ask user once for every set of traces added
2571
+
dupXmessage=Application->MessageBox(L"Are duplicate X values expected?\n Duplicates were found, but this may be due to\n csvgraphs 7 significant digit resolution", L"Optimise duplicate X values", MB_YESNO);
2572
+
if(dupXmessage==IDNO)
2573
+
pScientificGraph->fix_dupx(iGraph); // "fix" any duplicate xvalues
2574
+
}
2575
+
#endif
2545
2576
#if1/* general purpose compression - works well but does require all data for the trace is read into ram , then excess is returned so peak ram is high */
2546
2577
if(compress && !(nos_traces_added>1 && xmonotonic) ) // && ! bit traps cases that can be done when reading the trace data in (above)
2547
-
{StatusText->Caption="Compressing...";
2548
-
Application->ProcessMessages(); /* allow windows to update (but not go idle) */
2549
-
pScientificGraph->compress_y(iGraph); // compress by deleting points with equal y values except for 1st and last in a row
2550
-
StatusText->Caption="Compression completed";
2551
-
Application->ProcessMessages(); /* allow windows to update (but not go idle) */
2552
-
}
2578
+
{
2579
+
StatusText->Caption="Compressing...";
2580
+
Application->ProcessMessages(); /* allow windows to update (but not go idle) */
2581
+
pScientificGraph->compress_y(iGraph); // compress by deleting points with equal y values except for 1st and last in a row
2582
+
StatusText->Caption="Compression completed";
2583
+
Application->ProcessMessages(); /* allow windows to update (but not go idle) */
2584
+
2585
+
}
2553
2586
#endif
2554
2587
// now implement filter on data just read in if user requires this
ShowMessage("Warning: Polynomial fit failed - adding original trace to graph");
2740
2788
}
2741
2789
break;
2742
-
case24:
2790
+
case26:
2743
2791
// general purpose polynomial fit in sqrt(x) with user defined order
2744
2792
StatusText->Caption=FString;
2745
2793
gen_lin_reg(reg_sqrt,poly_order+1,true,iGraph);
2746
2794
break;
2747
-
case25:
2795
+
case27:
2748
2796
// rational fit (poly1/poly2) with user defined order
2749
2797
StatusText->Caption=FString;
2750
2798
gen_lin_reg(reg_rat,poly_order+1,true,iGraph);
2751
2799
break;
2752
-
case26:
2800
+
case28:
2753
2801
// derivative
2754
2802
StatusText->Caption=FString;
2755
2803
#if1
@@ -2758,41 +2806,41 @@ try{
2758
2806
deriv_trace(iGraph); // this was used till csvgraph 3v8
2759
2807
#endif
2760
2808
break;
2761
-
case27:
2809
+
case29:
2762
2810
// 2nd derivative
2763
2811
StatusText->Caption=FString;
2764
2812
pScientificGraph->deriv2_filter((unsignedint)poly_order,iGraph); // used fom 3v9 - uses Savitzky Golay filtered derivative of specfied order (1,2,4 are very efficient)
2765
2813
break;
2766
-
case28:
2814
+
case30:
2767
2815
// integral
2768
2816
StatusText->Caption=FString;
2769
2817
integral_trace(iGraph);
2770
2818
break;
2771
-
case29: // bool TScientificGraph::fnFFT(bool dBV_result,bool hanning,int iGraphNumberF, void (*callback)(unsigned int cnt,unsigned int maxcnt))
2819
+
case31: // bool TScientificGraph::fnFFT(bool dBV_result,bool hanning,int iGraphNumberF, void (*callback)(unsigned int cnt,unsigned int maxcnt))
0 commit comments