Menu

#864 Gnuplot not working with multiple graphs

v1.0 (example)
open
nobody
None
5
2026-08-27
2026-08-27
No

When a plot is made through the "gnuplot" command, it is not displayed correctly. The same plot using the normal "plot" command seems to work well.

A minimal example to reproduce the bug is the following code:

.control
compose t start = -3 stop = 3 step =.1
let x = sin(3*t)

gnuplot testplot x+3 vs t-.2 
gnuplot testplot2 x+3 vs t-.2  0.2*x vs t+.2 

.endc

The issue is that when using the "gnuplot" command, there are issues in the way that the plot.data file is being written, it can have too many newlines in it. For a single line, everything is ok, testplot displays correctly. However testplot2 in the attached screenshot does not display correctly as a plot with two lines.

testplot2 should contain 2 lines, so 4 lists of numbers are required (vertical and horizontal coordinates for 2 lines). As can be seen on the screenshot, the testplot2.data file contains too many newline (return) characters, so gnuplot interprets data belonging to the second line to belong to the first line.

first lines of testplot2.data

-3.200000e+00 2.587882e+00 -2.800000e+00 -8.242370e-02 
-3.100000e+00 2.337031e+00 
-2.700000e+00 -1.325938e-01 
-3.000000e+00 2.145401e+00 
-2.600000e+00 -1.709198e-01 
-2.900000e+00 2.030110e+00 
1 Attachments

Discussion

  • Roeland Dilz

    Roeland Dilz - 2026-08-27

    I'm using ngpsice version 47

     
  • Roeland Dilz

    Roeland Dilz - 2026-08-27

    I have found the bug in src/frontend/plotting/gnuplot.c, line598 and onwards

    There is a for-loop to save the data, which looks like this:

            for (i = 0; i < scale->v_length; i++) {
                for (v = vecs; v; v = v->v_link2) {
                    scale = v->v_scale;
    
                    xval = isreal(scale) ?
                           scale->v_realdata[i] : realpart(scale->v_compdata[i]);
    
                    yval = isreal(v) ?
                           v->v_realdata[i] : realpart(v->v_compdata[i]);
    
                    if (i > 0 && (mono || (scale->v_plot && scale->v_plot->pl_scale == scale))) {
                        if (dir * (xval - prev_xval) < 0) {
                            /* direction reversal, start a new graph */
                            fprintf(file_data, "\n");
                            dir = 0;
                        } else if (!dir && xval > prev_xval) {
                            dir = 1;
                        } else if (!dir && xval < prev_xval) {
                            dir = -1;
                        }
                    }
    
                    fprintf(file_data, "%e %e ", xval, yval);
    
                    prev_xval = xval;  \\<<THIS IS THE PROBLEM
                }
                fprintf(file_data, "\n");
            }
        }
    

    The issue is with the prev_xval = xval. When two plots are employed with different x-coordinates, the prev_xval corresponds to the second line, while it is compared with an xval of the first line. So even with monotonic plots, the direction-reversal will be triggered and an extra \n will be inserted.

    I cannot judge wether the direction reversal code works well. But changing this code to:

            for (i = 0; i < scale->v_length; i++) {
                for (v = vecs; v; v = v->v_link2) {
                    scale = v->v_scale;
    
                    xval = isreal(scale) ?
                           scale->v_realdata[i] : realpart(scale->v_compdata[i]);
    
                    yval = isreal(v) ?
                           v->v_realdata[i] : realpart(v->v_compdata[i]);
                    if (i > 0 && (mono || (scale->v_plot && scale->v_plot->pl_scale == scale))) {
                        prev_xval = isreal(scale) ?
                           scale->v_realdata[i] : realpart(scale->v_compdata[i-1]);
    
                        if (dir * (xval - prev_xval) < 0) {
                            /* direction reversal, start a new graph */
                            fprintf(file_data, "\n");
                            dir = 0;
                        } else if (!dir && xval > prev_xval) {
                            dir = 1;
                        } else if (!dir && xval < prev_xval) {
                            dir = -1;
                        }
                    }
    
                    fprintf(file_data, "%e %e ", xval, yval);
    
                }
                fprintf(file_data, "\n");
            }
    

    Now, the prev_xval corresponds to the correct plot. And at least for my case, it seems to work.

     

    Last edit: Roeland Dilz 2026-08-27

Log in to post a comment.