• Welcome to the Internet Infidels Discussion Board.

The Programming Thread

A basic Gnuplot class. Titles and axis labels can be added. An adventurous person looking for a project could expand it into a C++ graphics package.

Gnuplot has to be installed but does not have to be running.

With extents >0 the plot is to the extents of the data, < 1 and plots are to the specified limits, a zoom function.

I found it easier to use C++ strings and use the .c_str() attribute when needed for C functions.

Code:
class GNUPLOT{
    public:
    int n = 1,extents = 1;
    string path = "",plot_file =" ",data_file = "";
    double xlo = 0,xhi = 1,ylo = -1, yhi = 1;
    double *x, *y;
    int plot(void);
};

int GNUPLOT::plot(void){
    int i;
    string fname = path+data_file;
    FILE *p = fopen(fname.c_str(),"w");
    if(!p){cout<<"siog file"<<endl;return 1;}
    for(i=0;i<n;i++)fprintf(p,"%20.15f  \t%20.15f\n",x[i],y[i]);
    fclose(p);

    fname = path+plot_file;
    p = fopen(fname.c_str(),"w");
    if(!p){cout<<"plot file"<<endl;return 1;}
    fprintf(p,"set term windows background rgb 'white'\n");
    fprintf(p,"reset\n");
    if(extents){
        fprintf(p,"set xrange[*:*]\n");
        fprintf(p,"set yrange[*:*]\n");
        }
    else{
        fprintf(p,"set xrange[%f:%f]\n",xlo,xhi);
        fprintf(p,"set yrange[%f:%f]\n",ylo,yhi);
        }
    fname = path + data_file;
    fprintf(p,"set grid lt 1 lw 1 lc rgb 'black'  dashtype solid\n");
    fprintf(p,"plot '%s' using 1:2 with lines ls 4 lt  -1 lw 3\n",fname.c_str());
    fprintf(p,"show grid\n");
    fclose(p);

    fname = path+plot_file;
    system(fname.c_str());
    return 0;
}

void plot_test(void){
    GNUPLOT gp;
    int i, n = 100;
    double t[n],y[n],dt = 1./(n-1);
    for(i=0;i<n;i++){
        t[i] = i*dt;
        y[i] = sin(2*_PI*1*t[i]);
    }
    gp.n = n; gp.extents = 1;
    gp.path = "c:\\gnuplot\\data\\";
    gp.plot_file = "sig.plt";
    gp.data_file = "sig.dat";
    gp.xlo = 0;gp.xhi = .4;gp.ylo = 0;gp.yhi = 1;
    gp.x = t; gp.y = y;
    gp.plot();
}
 
Basic data plotting in Gnuplot, histograms and cumulative distributions. Histograms on real data can be ragged looking. As an integration the cumulative distribution acts to smooth the data into a more recognizable plot.

The Gnuplot script is from Gnuplot documentation.

Compiled with gcc C17 ISO C++

Exponential mean > 1.

Code:
double minf(int n,double *x){
    double xmin = x[0];
    for(int i =0;i<n;i++)if(x[i] < xmin)xmin = x[i];
    return xmin;
}

double maxf(int n,double *x){
    double xmax = x[0];
    for(int i =0;i<n;i++)if(x[i] > xmax)xmax = x[i];
    return xmax;
}


class GNUPLOTHIST{
    public:
    int n,bin_width,box_width,extents = 1;
    string path,file_name;
    double *y,xlo = 0,xhi = 1;
    int plot(void);
};

int GNUPLOTHIST::plot(void){
    int i ;
    string data_file = path + file_name + ".dat";
    string plot_file  = path + file_name + ".plt";
    double *cd = new double[n];
    sort(&y[0],&y[n]);
    for(i=0;i<n;i++)cd[i] = 100*(i+1.)/n;

    FILE *p = fopen(data_file.c_str(),"w");
    if(!p){cout<<"data file error"<<endl;return 1;}
    for(i=0;i<n;i++)fprintf(p,"%10.5f \t%20.15f\n",cd[i],y[i]);
    fclose(p);

    p = fopen(plot_file.c_str(),"w");
    if(!p){cout<<"plot file"<<endl;return 1;}
    //fprintf(p,"unset multiplot\n");
    fprintf(p,"set term windows background rgb 'white'\n");// title "SIGNALS" fontscale 1\n");ntf(p,"clear\n");
    fprintf(p,"clear\n");
    fprintf(p,"reset\n");
    fprintf(p,"set key off\n");
    fprintf(p,"set multiplot layout 2,1 columnsfirst\n");

    if(extents) fprintf(p,"set xrange[%f:%f]\n",y[0],y[n-1]);
        else fprintf(p,"set xrange[%f:%f]\n",xlo,xhi);


    fprintf(p,"set border 3\n");
    fprintf(p,"set grid lt 1 lw 1 lc rgb 'black'  dashtype solid\n");
    fprintf(p,"set boxwidth  %d absolute\n",box_width);
    fprintf(p,"set style fill solid 1.0 noborder\n");
    fprintf(p,"bin_width = %d\n",bin_width);
    fprintf(p,"bin_number(x) = floor(x/bin_width)\n");
    fprintf(p,"rounded(x) = bin_width * ( bin_number(x) + 0.5 )\n");
    fprintf(p,"plot '%s' using (rounded($2)):(2) smooth frequency with boxes\n",data_file.c_str());
    fprintf(p,"show grid\n");

    fprintf(p,"set grid lt 1 lw 1 lc rgb 'black'  dashtype solid\n");
    fprintf(p,"set zeroaxis\n");
    fprintf(p,"set yrange[0:100]\n");
    fprintf(p," plot '%s' using 2:1 with lines ls 4 lt  -1 lw 3\n",data_file.c_str());
    fprintf(p,"show grid\n");
    fprintf(p,"unset multiplot\n");
    fclose(p);
    if(system(plot_file.c_str()) !=0) cout<<"system() error"<<endl;
    delete []cd;
    return 0;

}

struct hist_params{
     int n,bin_width,box_width,extents = 1;
    string path,file_name;
    double *x,*y,xlo = 0,xhi = 1;
};

int hist_plot(struct hist_params p){
    int i ;
    string data_file = p.path + p.file_name + ".dat";
    string plot_file  = p.path + p.file_name + ".plt";
    double *cd = new double[p.n];
    sort(&p.y[0],&p.y[p.n]);
    for(i=0;i<p.n;i++)cd[i] = 100*(i+1.)/p.n;

    FILE *fp = fopen(data_file.c_str(),"w");
    if(!fp){cout<<"data file error"<<endl;return 1;}
    for(i=0;i<p.n;i++)fprintf(fp,"%10.5f \t%20.15f\n",cd[i],p.y[i]);
    fclose(fp);

    fp = fopen(plot_file.c_str(),"w");
    if(!fp){cout<<"plot file"<<endl;return 1;}
    fprintf(fp,"set term windows background rgb 'white'\n");// title "SIGNALS" fontscale 1\n");ntf(p,"clear\n");
    fprintf(fp,"clear\n");
    fprintf(fp,"reset\n");
    fprintf(fp,"set key off\n");
    fprintf(fp,"set multiplot layout 2,1 columnsfirst\n");

    if(p.extents) fprintf(fp,"set xrange[%f:%f]\n",p.y[0],p.y[p.n-1]);
        else fprintf(fp,"set xrange[%f:%f]\n",p.xlo,p.xhi);


    fprintf(fp,"set border 3\n");
    fprintf(fp,"set grid lt 1 lw 1 lc rgb 'black'  dashtype solid\n");
    fprintf(fp,"set boxwidth  %d absolute\n",p.box_width);
    fprintf(fp,"set style fill solid 1.0 noborder\n");
    fprintf(fp,"bin_width = %d\n",p.bin_width);
    fprintf(fp,"bin_number(x) = floor(x/bin_width)\n");
    fprintf(fp,"rounded(x) = bin_width * ( bin_number(x) + 0.5 )\n");
    fprintf(fp,"plot '%s' using (rounded($2)):(2) smooth frequency with boxes\n",data_file.c_str());
    fprintf(fp,"show grid\n");

    fprintf(fp,"set grid lt 1 lw 1 lc rgb 'black'  dashtype solid\n");
    fprintf(fp,"set zeroaxis\n");
    fprintf(fp,"set yrange[0:100]\n");
    fprintf(fp," plot '%s' using 2:1 with lines ls 4 lt  -1 lw 3\n",data_file.c_str());
    fprintf(fp,"show grid\n");
    fprintf(fp,"unset multiplot\n");
    fclose(fp);
    if(system(plot_file.c_str()) !=0) cout<<"system() error"<<endl;
    delete []cd;
    return 0;
}



#include <random>
mt19937 rand_gen(time(NULL));


void hist_test(void){
    GNUPLOTHIST gp;
    struct hist_params p;
    int i, n = 10000;
    double mean = 0,sdev = 20;
    normal_distribution<double> dist(mean,sdev);
    //exponential_distribution<double> dist(1/mean);
    double y[n];
    for(i=0;i<n;i++)y[i] = dist(rand_gen);


    gp.n = n;
    gp.bin_width = 4;
    gp.box_width = 3;
    gp.y = y;
    gp.extents = 1;
    gp.xlo = minf(n,y);
    gp.xhi = maxf(n,y);
    gp.path = "c:\\gnuplot\\data\\";
    gp.file_name = "hist_test";

    p.n = n;
    p.bin_width = 4;
    p.box_width = 3;
    p.y = y;
    p.extents =1;
    p.xlo = 0;//minf(n,y);
    p.xhi = maxf(n,y);
    p.path = "c:\\gnuplot\\data\\";
    p.file_name = "hist_test";

    hist_plot(p);
    //gp.plot();

}
 
Last edited:
You can change bin_width and boxsize and see what it does

Exponential and Normal distribution.

1740875019303.png

1740876943341.png
 
Last edited:


About issues in JavaScript:

You can try this in Chrome and go to "Inspect" then "Console".

JavaScript:
[] + {}; // the string '[object Object]'

{} + []; // 0

{} + {}; // video says '[object Object][object Object]' but I get NaN

[] + []; // empty string

0 == []; // true

0 == "0"; // true

"0" == []; // false

2 + "2"; // '22'

2 - "2"; // 0
 


About issues in JavaScript:

You can try this in Chrome and go to "Inspect" then "Console".

JavaScript:
[] + {}; // the string '[object Object]'

{} + []; // 0

{} + {}; // video says '[object Object][object Object]' but I get NaN

[] + []; // empty string

0 == []; // true

0 == "0"; // true

"0" == []; // false

2 + "2"; // '22'

2 - "2"; // 0

Yes, it is an abomination.
 
Back
Top Bottom