0
votes

I don't manage to plot my data with gnuplot when I store it as a binary. Plotting from an ASCII file works without problems. Here's my attempt: First, save the data

// omitted
double *t = alloc_mat(row + 1, col + 1);
    for(x = 0; x < row + 1; x++)
        for(y = 0; y < col + 1; y++)
            if(!y && !x)
                t[0] = col + 1;
            else if(!x && y != 0)
                t[x * (col + 1) + y] = y - 1;
            else if(!y && x != 0)
                t[x * (col + 1) + y] = x - 1;
            else
                t[x * (col + 1) + y] = data[(x - 1) * col + y - 1];

writebin_double(fname, t, row + 1, col + 1);
free(t);

The code creates a structure like

N+1, y0,  y1,  y2,  y3,  ...  yN
x0,  z00, z01, z02, z03, ..., z0N
x1,  y10, ...

according to http://gnuplot.sourceforge.net/docs_4.2/node330.html#binary_matrix

The function writebin_double is simply

void writebin_double(char *fname, double *data, int row, int col)
{
    // omitted
    FILE *outfile = fopen(fname, "w");
    // omitted
    fwrite(data, sizeof(double), row * col, outfile);
    fclose(outfile);
}

When trying to plot the data as

set xr [0:599] # an example
set yr [0:799]
splot 'plttmp.dat' binary matrix format='%double' using 1:2:3 w l palette t ''

it fails with "Read grid of zero width" which I don't understand in this case, as the grid is specified in the for loop. I also tried the binary general setting, but it didn't help and I got the same message.

Thanks for ideas!

PS: gnuplot 4.6.4 on Ubuntu 14.04, 64 bit

1
Have you tried using floats instead of double? Possibly the format option isn't supported for this kind binary matrices, see also the binary.c source which is mentioned on the page you linked. - Christoph
Yes, floats doesn't work, it's either float or double. In my case, it should read double. I really don't get what I'm doing wrong, since it's just the fact that the data is hold as binary produces this problem. I can provoke an output by splot '%s' binary format='%double' w pm3d but it gives me just a couple of weird lines. - Clemens
No, I mean try to use a float array in you C-code instead of a double one and don't use the format specifier at all. - Christoph
OK, tried it. The error then reads File doesn't factorize into full matrix. The plot command I changed to splot '%s' binary matrix using 1:2:3 - Clemens
Try setting t[0] = col; instead of setting it to col +1. The example in the documentation might be misleading. There the columns are number from 0 to N, so you have N+1 columns. In your case you have col columns. - Christoph

1 Answers

1
votes

Solution to the problem: gnuplot takes only single precision floating point numbers in the binary format, as Christoph pointed out.

However, the plotting of binary data in this format only works on Ubuntu, not on Windows. My systems: Windows 7 64 bit, gnuplot 4.6.5 || Ubuntu 14.04 64 bit, gnuplot 4.6.4

Here's the minimum working example:

#include "stdio.h"
#include "stdlib.h"

typedef unsigned int uint;

void wdata_ascii(const char *fname, const double *data, const uint row, const uint col)
{
    FILE *wfile = fopen(fname, "w");
    uint x, y;
    for(x = 0; x < row + 1; x++)
        for(y = 0; y < col + 1; y++)
        {
            if(!y && !x)
                fprintf(wfile, "%u", col);
            else if(!x && y != 0)
                fprintf(wfile, "%u", y - 1);
            else if(!y && x != 0)
                fprintf(wfile, "%u", x - 1);
            else
                fprintf(wfile, "%g", data[(x - 1) * col + y - 1]);

            if(y == col)
                fprintf(wfile, "\n");
            else
                fprintf(wfile, " ");
        }
    fclose(wfile);
}

void wdata_bin(const char *fname, const double *data, const uint row, const uint col)
{
    uint x, y;
    float *tsp = (float *)malloc((row + 1) * (col + 1) * sizeof(float));

    for(x = 0; x < row + 1; x++)
        for(y = 0; y < col + 1; y++)
            if(!y && !x)
                tsp[0] = col;
            else if(!x && y != 0)
                tsp[x * (col + 1) + y] = y - 1;
            else if(!y && x != 0)
                tsp[x * (col + 1) + y] = x - 1;
            else
                tsp[x * (col + 1) + y] = (float)data[(x - 1) * col + y - 1];

    FILE *outfile = fopen(fname, "w");
    fwrite(tsp, sizeof(float), (row + 1) * (col + 1), outfile);
    fclose(outfile);
    free(tsp);
}

void plotdata(const double *data, const uint row, const uint col)
{
    char *tmpdat = "pltdat",
         *cmdtmp = "pltcmd";

    fprintf(stdout,
            "\nthis will create or overwrite the files '%s' and '%s'. press enter to continue.\n",
            tmpdat, cmdtmp);
    getchar();

//  wdata_bin(tmpdat, data, row, col);
    wdata_ascii(tmpdat, data, row, col);

    FILE *gnufile = fopen(cmdtmp, "w");

    fprintf(gnufile,
            "set term png size 1024, 768\n" \
            "set yl 'y'\n" \
            "set xl 'x'\n" \
            "set out 'test.png'\n" \
            "#splot '%s' binary matrix using 2:1:3 w pm3d palette t ''\n"
            "splot '%s' nonuniform matrix u 2:1:3 w pm3d palette t ''\n",
            tmpdat, tmpdat);

    fclose(gnufile);
    system("gnuplot pltcmd");
    remove(tmpdat);
    remove(cmdtmp);
}

int main(void)
{
    uint x, y,
         row = 100, col = 200;
    double *dat = (double *)malloc(row * col * sizeof(double));

    for(x = 0; x < row; x++)
        for(y = 0; y < col; y++)
            dat[x * col + y] = (double)(x << 1) * y / 100.;

    plotdata(dat, row, col);
    free(dat);
    return 0;
}

I've removed any kind of validity checks, but it might also help people looking for a direct plotting of data within a C program via gnuplot. To check the described problem, switch between wdata_ascii and wdata_bin and also toogle between the splot lines (just change the # tag).