Skip to content

Commit

Permalink
Files uploaded for 2v3
Browse files Browse the repository at this point in the history
  • Loading branch information
p-j-miller authored Jan 23, 2022
1 parent 32cc5bd commit 6d1000d
Show file tree
Hide file tree
Showing 24 changed files with 2,869 additions and 66 deletions.
2 changes: 1 addition & 1 deletion About.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------
* Copyright (c) 2019 Peter Miller
* Copyright (c) 2019,2022 Peter Miller
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
Expand Down
57 changes: 33 additions & 24 deletions UDataPlotWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,13 @@
// : all filters now report progress as a % (previoulsy min abs error and min rel error did not report progress and they could be quite slow).
// : skip N lines before csv header option added for cases where csv header is not on the 1st row of the file
// : Added column numbers to X column and Y column listboxes to make it easier to select columns when names are not very descriptive (or missing).
// 2v3 3/1/2022 : can optionally use yasort2() for sorting - this has a guarantee on worse case execution time and can use all available processors to speed up sorting
// : yamedian() used which can calculate median in place without needing to copy the array of y values (but will for speed if memory is available)
// : added linear regression y=m*x*log2(x)+c
//
//---------------------------------------------------------------------------
/*----------------------------------------------------------------------------
* Copyright (c) 2019,2020,2021 Peter Miller
* Copyright (c) 2019,2020,2021,2022 Peter Miller
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
Expand Down Expand Up @@ -107,7 +110,7 @@
#include "multiple-lin-reg-fn.h"

extern TForm1 *Form1;
const char * Prog_Name="CSVgraph (Github) 2v2g"; // needs to be global as used in about box as well.
const char * Prog_Name="CSVgraph (Github) 2v3"; // needs to be global as used in about box as well.
#if 1 /* if 1 then use fast_strtof() rather than atof() for floating point conversion. Note in this application this is only slightly faster (1-5%) */
extern "C" float fast_strtof(const char *s,char **endptr); // if endptr != NULL returns 1st character thats not in the number
#define strtod fast_strtof /* set so we use it in place of strtod() */
Expand Down Expand Up @@ -2111,78 +2114,83 @@ void __fastcall TPlotWindow::Button_add_trace1Click(TObject *Sender)
pScientificGraph->fnLinreg(SqrtLin,iGraph,filter_callback);
break;
case 16:
// nlog2(n) regression y=m*x*log2(x)+c
StatusText->Caption=FString;
pScientificGraph->fnLinreg(Nlog2nLin,iGraph,filter_callback);
break;
case 17:
// y=a*x+b*sqrt(x)+c (least squares fit)
StatusText->Caption=FString;
pScientificGraph->fnLinreg_3(iGraph,filter_callback);
break;

case 17:
case 18:
// y=a+b*sqrt(x)+c*x+d*x^1.5
StatusText->Caption=FString;
gen_lin_reg(reg_sqrt,4,true,iGraph);
break;
case 18:
case 19:
// y=(a+bx)/(1+cx) (least squares fit)
StatusText->Caption=FString;
pScientificGraph->fnrat_3(iGraph,filter_callback);
break;
case 19:
case 20:
// N=5=> y=(a0+a1*x+a2*x^2)/(1+b1*x+b2*x^2)
StatusText->Caption=FString;
gen_lin_reg(reg_rat,5,true,iGraph);
break;
case 20: // general purpose polynomial fit (least squares using orthogonal polynomials)
case 21: // general purpose polynomial fit (least squares using orthogonal polynomials)
StatusText->Caption=FString;
if(!pScientificGraph->fnPolyreg(poly_order,iGraph,filter_callback))
{StatusText->Caption="Polynomial fit failed";
ShowMessage("Warning: Polynomial fit failed - adding original trace to graph");
}
break;
case 21:
case 22:
// general purpose polynomial fit in sqrt(x) with user defined order
StatusText->Caption=FString;
gen_lin_reg(reg_sqrt,poly_order+1,true,iGraph);
break;
case 22:
case 23:
// rational fit (poly1/poly2) with user defined order
StatusText->Caption=FString;
gen_lin_reg(reg_rat,poly_order+1,true,iGraph);
break;
case 23:
case 24:
// derivative
StatusText->Caption=FString;
deriv_trace(iGraph);
break;
case 24:
case 25:
// integral
StatusText->Caption=FString;
integral_trace(iGraph);
break;
case 25: // bool TScientificGraph::fnFFT(bool dBV_result,bool hanning,int iGraphNumberF, void (*callback)(unsigned int cnt,unsigned int maxcnt))
case 26: // bool TScientificGraph::fnFFT(bool dBV_result,bool hanning,int iGraphNumberF, void (*callback)(unsigned int cnt,unsigned int maxcnt))
// fft return ||
StatusText->Caption=FString;
if(!pScientificGraph->fnFFT(false,false,iGraph,filter_callback))
{StatusText->Caption="FFT failed";
ShowMessage("Warning: FFT failed - adding original trace to graph");
}
break;
case 26: // bool TScientificGraph::fnFFT(bool dBV_result,bool hanning,int iGraphNumberF, void (*callback)(unsigned int cnt,unsigned int maxcnt))
case 27: // bool TScientificGraph::fnFFT(bool dBV_result,bool hanning,int iGraphNumberF, void (*callback)(unsigned int cnt,unsigned int maxcnt))
// fft return dBV
StatusText->Caption=FString;
if(!pScientificGraph->fnFFT(true,false,iGraph,filter_callback))
{StatusText->Caption="FFT failed";
ShowMessage("Warning: FFT failed - adding original trace to graph");
}
break;
case 27: // bool TScientificGraph::fnFFT(bool dBV_result,bool hanning,int iGraphNumberF, void (*callback)(unsigned int cnt,unsigned int maxcnt))
case 28: // bool TScientificGraph::fnFFT(bool dBV_result,bool hanning,int iGraphNumberF, void (*callback)(unsigned int cnt,unsigned int maxcnt))
// fft with Hanning window, return ||
StatusText->Caption=FString;
if(!pScientificGraph->fnFFT(false,true,iGraph,filter_callback))
{StatusText->Caption="FFT failed";
ShowMessage("Warning: FFT failed - adding original trace to graph");
}
break;
case 28: // bool TScientificGraph::fnFFT(bool dBV_result,bool hanning,int iGraphNumberF, void (*callback)(unsigned int cnt,unsigned int maxcnt))
case 29: // bool TScientificGraph::fnFFT(bool dBV_result,bool hanning,int iGraphNumberF, void (*callback)(unsigned int cnt,unsigned int maxcnt))
// fft with Hanning window return dBV
StatusText->Caption=FString;
if(!pScientificGraph->fnFFT(true,true,iGraph,filter_callback))
Expand All @@ -2194,20 +2202,20 @@ void __fastcall TPlotWindow::Button_add_trace1Click(TObject *Sender)
if(*ys!=',')
{// if this is the final trace then rescale & actually plot, otherwise skip this step to save time
if(iGraph==0 || !zoomed)
{ // if 1st graph or not already zoomed then autoscale, otherwise leave this to the user.
{ // if 1st graph or not already zoomed then autoscale, otherwise leave this to the user.
StatusText->Caption="Autoscaling";
Application->ProcessMessages(); /* allow windows to update (but not go idle) */
pScientificGraph->fnAutoScale();
}
StatusText->Caption="Drawing graph";
Application->ProcessMessages(); /* allow windows to update (but not go idle) */
fnReDraw();
}
Application->ProcessMessages(); /* allow windows to update (but not go idle) */
pScientificGraph->fnAutoScale();
}
StatusText->Caption="Drawing graph";
Application->ProcessMessages(); /* allow windows to update (but not go idle) */
fnReDraw();
}
end_t=clock();

if(*ys==',')
{// multiple items are comma seperated
++ys; // skip ,
{// multiple items are comma seperated
++ys; // skip ,
rewind(fin); // back to start of file
char *text_first_line=NULL;
{int skip_initial_lines=_wtoi(Form1->pPlotWindow->Edit_skip_lines->Text.c_str());
Expand Down Expand Up @@ -3075,3 +3083,4 @@ void __fastcall TPlotWindow::Action1Execute(TObject *Sender)




23 changes: 12 additions & 11 deletions UDataPlotWindow.dfm
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ object PlotWindow: TPlotWindow
OnResize = FormResize
DesignSize = (
1290
982)
1002)
PixelsPerInch = 96
TextHeight = 13
object Panel1: TPanel
Expand Down Expand Up @@ -705,18 +705,19 @@ object PlotWindow: TPlotWindow
'Median Filter'
'Median1 Filter'
'Linear Filter order:'
'Lin.regression (y=mx)'
'Lin. regression (y=mx+c)'
'GMR regression (y=mx+c)'
'Lin.regression: y=mx'
'Lin. regression: y=mx+c'
'GMR regression: y=mx+c'
'min abs err: y=mx+c'
'min rel err: y=mx+c'
'Log (y=m*log(x)+c)'
'Exponential y=c*exp(mx)'
'Power y=c*x^m'
'Recip (y=m/x+c)'
'Log: y=m*log(x)+c'
'Exponential: y=c*exp(mx)'
'Power: y=c*x^m'
'Recip: y=m/x+c'
'y=1/(mx+c)'
'Hyperbolic'
'sqrt y=m*sqrt(x)+c'
'Hyperbolic: y=x/(m+c*x)'
'sqrt: y=m*sqrt(x)+c'
'y=m*x*log2(x)+c'
'y=a*x+b*sqrt(x)+c'
'y=a+bx^0.5+cx+dx^1.5'
'y=(a+bx)/(1+cx)'
Expand Down Expand Up @@ -934,7 +935,7 @@ object PlotWindow: TPlotWindow
Left = 304
Top = 32
Bitmap = {
494C01010A000E00880110001000FFFFFFFFFF10FFFFFFFFFFFFFFFF424D3600
494C01010A000E00A40110001000FFFFFFFFFF10FFFFFFFFFFFFFFFF424D3600
0000000000003600000028000000400000003000000001002000000000000030
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
Expand Down
2 changes: 1 addition & 1 deletion UScalesWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
// Loosely based on an original public domain version by Frank heinrich, mail@frank-heinrich.de
//---------------------------------------------------------------------------
/*----------------------------------------------------------------------------
* Copyright (c) 2019 Peter Miller
* Copyright (c) 2019,2022 Peter Miller
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
Expand Down
60 changes: 46 additions & 14 deletions UScientificGraph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
// 6/2/2021 for 2v0 major change to use float *x_vals,*y_vals rather than SDataPoints in a TLIST.
//
/*----------------------------------------------------------------------------
* Copyright (c) 2019 Peter Miller
* Copyright (c) 2019,2022 Peter Miller
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
Expand Down Expand Up @@ -45,6 +45,8 @@
#include <cmath>
#include "kiss_fftr.h" // for fft
#include "_kiss_fft_guts.h"
#include "yasort2.h" /* needs to be set so we sort float's ie include "#define elem_type_sort2 float" */
#include "yamedian.h" /* needs to be set to work on floats eg #define elem_type_median float */

// #define USE_double_to_str_exp /* define to use double_to_str_exp() for y axis with max 12 chars, if not defined use gcvt() */

Expand Down Expand Up @@ -1227,17 +1229,21 @@ void TScientificGraph::fnMedian_filt(unsigned int median_ahead, int iGraphNumber

}
if(i==0)
{// do exact median by taking a copy of the values, and using quick_select() to find the median
float *arr=(float *)calloc(endi,sizeof(float));
if(arr!=NULL)
{
for(unsigned int k=0; k<endi;++k) // take a copy of all the y values that we want median of, also get min,max,average
{
{
#if 1
f=ya_median(pAGraph->y_vals,endi); // calculate median in place (don't change arr).
#else // do exact median by taking a copy of the values, and using quick_select() to find the median
float *arr=(float *)calloc(endi,sizeof(float));
if(arr!=NULL)
{
for(unsigned int k=0; k<endi;++k) // take a copy of all the y values that we want median of, also get min,max,average
{
arr[k]= pAGraph->y_vals[k];
}
f=quick_select( arr, endi); // initialise with actual median as its quick to calculate
free(arr);
}
}
f=quick_select( arr, endi); // initialise with actual median as its quick to calculate
free(arr);
}
#endif
}
last_endi=endi; // ensure we don't check values we have already processed
if(endi>=maxi)
Expand Down Expand Up @@ -1315,7 +1321,10 @@ void TScientificGraph::fnMedian_filt(unsigned int median_ahead, int iGraphNumber
this_endT=pAGraph->x_vals[i]+median_ahead_t; // time for the end of the look ahead
for(endi=last_endi;endi<maxi && pAGraph->x_vals[endi] < this_endT;++endi); // search forward to find i that matches end of look ahead time
if(i==0)
{// do exact median by taking a copy of the values, and using quick_select() to find the median
{
#if 1
m=ya_median(pAGraph->y_vals,endi); // calculate median in place (don't change arr).
#else // do exact median by taking a copy of the values, and using quick_select() to find the median
float *arr=(float *)calloc(endi,sizeof(float));
if(arr!=NULL)
{
Expand All @@ -1326,6 +1335,7 @@ void TScientificGraph::fnMedian_filt(unsigned int median_ahead, int iGraphNumber
m=quick_select( arr, endi); // initialise with actual median as its quick to calculate
free(arr);
}
#endif
}
last_endi=endi; // ensure we don't check values we have already processed
if(endi>=maxi)
Expand Down Expand Up @@ -1559,7 +1569,7 @@ void TScientificGraph::fnrat_3(int iGraphNumberF, void (*callback)(unsigned int
void TScientificGraph::fnLinreg(enum LinregType type, int iGraphNumberF, void (*callback)(unsigned int cnt,unsigned int maxcnt))
// apply 1st order least squares linear regression (y=mx+c) to graph in place
// can also do GMR for a straight line when type = LinLin_GMR
// enum LinregType {LinLin,LogLin,LinLog,LogLog,RecipLin,LinRecip,RecipRecip,SqrtLin}; defines preprocessing of varibales before linear regression 1st is X 2nd is Y
// enum LinregType {LinLin,LogLin,LinLog,LogLog,RecipLin,LinRecip,RecipRecip,SqrtLin}; defines preprocessing of variables before linear regression 1st is X 2nd is Y
// results checked using csvfun3.csv. R^2 values (and coefficients) also checked against Excel for the fits excel can do.
{// to save copying data this is done inline
SGraph *pAGraph = ((SGraph*) pHistory->Items[iGraphNumberF]);
Expand Down Expand Up @@ -1597,6 +1607,11 @@ void TScientificGraph::fnLinreg(enum LinregType type, int iGraphNumberF, void (*
{if(xi<0 ) continue; // avoid sqrt of a negative number
xi=sqrt(xi);
}
if(type== Nlog2nLin)
{if(xi<=0 ) continue; // avoid ln of a negative number
// M_LOG2E 1.44269504088896340736 is defined in math.h // 1/ln(2) as multiplication below is probably faster than division
xi=xi*log(xi)*M_LOG2E; // xi*log2(xi) = xi*ln(xi)/ln(2)
}
++N;
meanx+= (xi-meanx)/(double) N; /* calculate means as mi+1=mi+(xi+1 - mi)/i+1 , this should give accurate results and avoids the possibility of the "sum" overflowing*/
meany+= (yi-meany)/(double) N;
Expand Down Expand Up @@ -1676,6 +1691,11 @@ void TScientificGraph::fnLinreg(enum LinregType type, int iGraphNumberF, void (*
// sqrt(x): y=m*sqrt(x)+c
rprintf("Best Least squares curve is Y=%g*sqrt(X)%+g which has an R^2 of %g\n",m,c,r2);
break;
case Nlog2nLin:
// n*log2(n): y=m*x*log2(x)+c
rprintf("Best Least squares curve is Y=%g*X*log2(X)%+g which has an R^2 of %g\n",m,c,r2); // log base 2
rprintf("Best Least squares curve is Y=%g*X*log(X)%+g\n",m*M_LOG2E,c); // log base e
break;
}
// now put new y values back, calculated as y=m*x+c
for(i=0;i<iCount;++i)
Expand Down Expand Up @@ -1719,6 +1739,10 @@ void TScientificGraph::fnLinreg(enum LinregType type, int iGraphNumberF, void (*
// sqrt(x): y=m*sqrt(x)+c
pAGraph->y_vals[i]=m*(xi>=0?sqrt(xi):0.0f)+c;
break;
case Nlog2nLin:
// n*log2(n): y=m*x*log2(x)+c
pAGraph->y_vals[i]=m*(xi>0?xi*log(xi)*M_LOG2E:0.0f)+c;
break;
}
e=fabs(yi-pAGraph->y_vals[i]);
if(e>maxe) maxe=e;
Expand Down Expand Up @@ -2741,12 +2765,19 @@ void TScientificGraph::myqsort(int iGraphNumberF, int p, int r)
#undef my_swapc
#undef Z


void TScientificGraph::sortx( int iGraphNumberF) // sort ordered on x values (makes x values increasing)
{
SGraph *pAGraph = ((SGraph*) pHistory->Items[iGraphNumberF]);
unsigned int iCount=pAGraph->nos_vals ;
time_t start_t=clock();
#if 1
/* sort using yasort2() */

float *xa=pAGraph->x_vals;
float *ya=pAGraph->y_vals;
yasort2(xa,ya,iCount);
rprintf(" sort (yasort2()) completed in %g secs\n",(clock()-start_t)/(double)CLOCKS_PER_SEC);
#else /* original sorting code */
#ifdef CHECK_DEPTH
maxdepth=0;
rn=3103515245u; // initialise random number generator to the same value every time to get consistant sorts for the same data
Expand All @@ -2763,6 +2794,7 @@ void TScientificGraph::sortx( int iGraphNumberF) // sort ordered on x values (m
pAGraph->x_vals[0],pAGraph->x_vals[1],pAGraph->x_vals[2],pAGraph->x_vals[3],
pAGraph->x_vals[4],pAGraph->x_vals[5]);
#endif
#endif
#if 1 /* check array actually is sorted correctly */
int errs=0;

Expand Down
3 changes: 2 additions & 1 deletion UScientificGraph.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
#include <Graphics.hpp>
// #define CHECK_DEPTH /* if defined check depth of recursion in myqsort() */

enum LinregType {LinLin,LinLin_GMR,LogLin,LinLog,LogLog,RecipLin,LinRecip,RecipRecip,SqrtLin};
enum LinregType {LinLin,LinLin_GMR,LogLin,LinLog,LogLog,RecipLin,LinRecip,RecipRecip,SqrtLin,Nlog2nLin};

// class for scientific plots

Expand Down Expand Up @@ -149,6 +149,7 @@ class TScientificGraph
bool fnAddDataPoint(float dXValueF, float dYValueF,
int iGraphNumberF = 0); // returns true if added OK else false
float fnAddDataPoint_nextx(int iGraphNumberF); // returns next x value for this graph assuming its the same as the previous graph
float fnAddDataPoint_thisy(int iGraphNumber); // returns next y value of iGraphNumber (locn from current graph number) used to do $T1
bool fnChangeXoffset(double dX); // change all X values by adding dX to the most recently added graph if at least 2 graphs defined
void fnMedian_filt(unsigned int median_ahead, int iGraphNumberF = 0); // apply median filter to graph in place , lookahead defined in samples
void fnMedian_filt_time1(double median_ahead_t, int iGraphNumberF, void (*callback)(unsigned int cnt,unsigned int maxcnt)); // new algorithm apply median filter to graph in place , lookahead defined in time
Expand Down
2 changes: 1 addition & 1 deletion Unit1.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
// Loosely based on an original public domain version by Frank heinrich, mail@frank-heinrich.de
//---------------------------------------------------------------------------
/*----------------------------------------------------------------------------
* Copyright (c) 2019 Peter Miller
* Copyright (c) 2019.2022 Peter Miller
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
Expand Down
2 changes: 1 addition & 1 deletion atof.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
/*----------------------------------------------------------------------------
* MIT License:
*
* Copyright (c) 2020 Peter Miller
* Copyright (c) 2020,2022 Peter Miller
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
Expand Down
Loading

0 comments on commit 6d1000d

Please sign in to comment.