From e7fb53f6fc94186d736f61aa952e0914089705f3 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Fri, 14 Aug 2026 00:45:29 +0200 Subject: [PATCH] Add an arrowplot flag to plot, gnuplot commands for plotting signal strenth versus frequency with vertical arrows. An internal flag PLOT_ARROWS is set. With command 'plot' this is the same as the combplot flag. With 'gnuplot' this adds an extra drawing style using vectors. --- examples/hb/amp2n2222/amp2n2222_mod.cir | 6 ++++-- src/frontend/cpitf.c | 1 + src/frontend/outitf.c | 3 +++ src/frontend/plotting/gnuplot.c | 27 +++++++++++++++++++++---- src/frontend/plotting/graf.c | 1 + src/frontend/plotting/plotit.c | 16 ++++++++++++++- src/frontend/plotting/pvec.c | 4 ++++ src/frontend/plotting/pyplot.c | 5 ++++- src/include/ngspice/dvec.h | 2 +- src/spicelib/analysis/dcpss.c | 2 +- 10 files changed, 57 insertions(+), 10 deletions(-) diff --git a/examples/hb/amp2n2222/amp2n2222_mod.cir b/examples/hb/amp2n2222/amp2n2222_mod.cir index 4608fb417..8b1786c25 100644 --- a/examples/hb/amp2n2222/amp2n2222_mod.cir +++ b/examples/hb/amp2n2222/amp2n2222_mod.cir @@ -23,9 +23,11 @@ Q1 out1 Net-_Q1-B_ Net-_Q1-E_ Q2n2222a hb $&freq 8 display set xbrushwidth=3 -plot db(out2) combplot ylimit -200 0 +plot db(out2) arrowplot ylimit -200 0 *pyplot db(out1) db(out2) combplot -*gnuplot gout db(out1) db(out2) combplot +gnuplot gout db(out2) arrowplot ylimit -250 0 +set gnuplot_terminal=png +gnuplot gout db(out2) arrowplot ylimit -250 0 print hbfrequency db(out1) db(out2) *quit .endc diff --git a/src/frontend/cpitf.c b/src/frontend/cpitf.c index eb047f54c..74172ee4e 100644 --- a/src/frontend/cpitf.c +++ b/src/frontend/cpitf.c @@ -121,6 +121,7 @@ ft_cpinit(void) cp_addkword(CT_PLOTKEYWORDS, "ylabel"); cp_addkword(CT_PLOTKEYWORDS, "linplot"); cp_addkword(CT_PLOTKEYWORDS, "combplot"); + cp_addkword(CT_PLOTKEYWORDS, "arrowplot"); cp_addkword(CT_PLOTKEYWORDS, "pointplot"); cp_addkword(CT_RUSEARGS, "time"); diff --git a/src/frontend/outitf.c b/src/frontend/outitf.c index 7b17a7940..09ce27f14 100644 --- a/src/frontend/outitf.c +++ b/src/frontend/outitf.c @@ -980,6 +980,9 @@ OUTattributes(runDesc *plotPtr, IFuid varName, int param, IFvalue *value) } else if (param == PLOT_COMB) { for (d = run->runPlot->pl_dvecs; d; d = d->v_next) d->v_plottype = PLOT_COMB; + } else if (param == PLOT_ARROWS) { + for (d = run->runPlot->pl_dvecs; d; d = d->v_next) + d->v_plottype = PLOT_ARROWS; } else { run->runPlot->pl_scale->v_gridtype = type; } diff --git a/src/frontend/plotting/gnuplot.c b/src/frontend/plotting/gnuplot.c index b7b17f5b5..705842e10 100644 --- a/src/frontend/plotting/gnuplot.c +++ b/src/frontend/plotting/gnuplot.c @@ -483,6 +483,9 @@ void ft_gnuplot(double *xlims, double *ylims, strcpy(plotstyle, "boxes"); } else if (plottype == PLOT_COMB) { strcpy(plotstyle, "impulses"); + } else if (plottype == PLOT_ARROWS) { + fprintf(file, "set style arrow 1 head nofilled size screen 0.03, 15 lw 2\n"); + strcpy(plotstyle, "arrows"); } else if (plottype == PLOT_POINT) { if (markers) { // fprintf(file, "Markers: True\n"); @@ -520,8 +523,16 @@ void ft_gnuplot(double *xlims, double *ylims, if (v->v_name) { i = i + 2; if (i > 2) fprintf(file, ",\\\n"); - fprintf(file, "\'%s\' using %d:%d with %s lw %d title ", - filename_data, i - 1, i, plotstyle, linewidth); + if (eq(plotstyle, "arrows")) + if (ylims) + fprintf(file, "\'%s\' using %d:(%e):(0):(%e+$%d) with vectors arrowstyle 1 title ", + filename_data, i - 1, ylims[0], (-1) * ylims[0], i); + else + fprintf(file, "\'%s\' using %d:(-200):(0):(200+$%d) with vectors arrowstyle 1 title ", + filename_data, i - 1, i); + else + fprintf(file, "\'%s\' using %d:%d with %s lw %d title ", + filename_data, i - 1, i, plotstyle, linewidth); quote_gnuplot_string(file, v->v_name); } } @@ -570,8 +581,16 @@ void ft_gnuplot(double *xlims, double *ylims, if (v->v_name) { i = i + 2; if (i > 2) fprintf(file, ",\\\n"); - fprintf(file, "\'%s\' using %d:%d with %s lw %d title ", - filename_data, i - 1, i, plotstyle, linewidth); + if (eq(plotstyle, "arrows")) + if (ylims) + fprintf(file, "\'%s\' using %d:(%e):(0):(%e+$%d) with vectors arrowstyle 1 title ", + filename_data, i - 1, ylims[0], (-1) * ylims[0], i); + else + fprintf(file, "\'%s\' using %d:(-200):(0):(200+$%d) with vectors arrowstyle 1 title ", + filename_data, i - 1, i); + else + fprintf(file, "\'%s\' using %d:%d with %s lw %d title ", + filename_data, i - 1, i, plotstyle, linewidth); quote_gnuplot_string(file, v->v_name); } } diff --git a/src/frontend/plotting/graf.c b/src/frontend/plotting/graf.c index 6a6ca5f57..723555b98 100644 --- a/src/frontend/plotting/graf.c +++ b/src/frontend/plotting/graf.c @@ -517,6 +517,7 @@ void gr_point(struct dvec *dv, } break; case PLOT_COMB: + case PLOT_ARROWS: DatatoScreen(currentgraph, 0.0, currentgraph->datawindow.ymin, &dummy, &ymin); diff --git a/src/frontend/plotting/plotit.c b/src/frontend/plotting/plotit.c index 40dde6e6c..878ed15d2 100644 --- a/src/frontend/plotting/plotit.c +++ b/src/frontend/plotting/plotit.c @@ -633,11 +633,22 @@ bool plotit(wordlist *wl, const char *hcopy, const char *devname) pfound = TRUE; } } + if (getflag(wl, "arrowplot")) { + if (pfound) { + fprintf(cp_err, + "Warning: too many plot types given. " + "\"arrowplot\" is ignored.\n"); + } + else { + ptype = PLOT_ARROWS; + pfound = TRUE; + } + } if (getflag(wl, "boxesplot")) { if (pfound) { fprintf(cp_err, "Warning: too many plot types given. " - "\"combplot\" is ignored.\n"); + "\"boxesplot\" is ignored.\n"); } else { ptype = PLOT_BOXES; @@ -668,6 +679,9 @@ bool plotit(wordlist *wl, const char *hcopy, const char *devname) else if (eq(buf, "combplot")) { ptype = PLOT_COMB; } + else if (eq(buf, "arrowplot")) { + ptype = PLOT_ARROWS; + } else if (eq(buf, "pointplot")) { ptype = PLOT_POINT; } diff --git a/src/frontend/plotting/pvec.c b/src/frontend/plotting/pvec.c index 2fdbea3b0..f700a9348 100644 --- a/src/frontend/plotting/pvec.c +++ b/src/frontend/plotting/pvec.c @@ -63,6 +63,10 @@ pvec(struct dvec *d) strcat(buf, ", plot = comb"); break; + case PLOT_ARROWS: + strcat(buf, ", plot = arrows"); + break; + case PLOT_BOXES: strcat(buf, ", plot = boxes"); break; diff --git a/src/frontend/plotting/pyplot.c b/src/frontend/plotting/pyplot.c index cc86313ce..61394d852 100644 --- a/src/frontend/plotting/pyplot.c +++ b/src/frontend/plotting/pyplot.c @@ -47,7 +47,7 @@ void ft_pyplot(double *xlims, double *ylims, FILE *file, *file_data; struct dvec *v, *scale = NULL; int i, col, numVecs, err, nper, nrows, row; - bool xlog, ylog, nogrid, markers, boxes, impulses, have_style, have_figsize; + bool xlog, ylog, nogrid, markers, boxes, impulses, arrows, have_style, have_figsize; char pointstyle[BSIZE_SP], terminal[BSIZE_SP], python[BSIZE_SP], style[BSIZE_SP]; char figsize[BSIZE_SP], fmt[16]; char lwarg[32]; /* Enhancement-183: "linewidth=%g, " or "" */ @@ -147,6 +147,7 @@ void ft_pyplot(double *xlims, double *ylims, impulses = (plottype == PLOT_COMB); boxes = (plottype == PLOT_BOXES); + arrows = (plottype == PLOT_ARROWS); if (plottype == PLOT_POINT) markers = TRUE; @@ -248,6 +249,8 @@ void ft_pyplot(double *xlims, double *ylims, fprintf(file, "step(d[:, %d], d[:, %d], where='mid', %s", col, col + 1, lwarg); else if (impulses) fprintf(file, "stem(d[:, %d], d[:, %d], markerfmt=' ', %s", col, col + 1, lwarg); + else if (arrows) + fprintf(file, "stem(d[:, %d], d[:, %d], markerfmt=' ', %s", col, col + 1, lwarg); else if (markers) fprintf(file, "plot(d[:, %d], d[:, %d], marker='.', linestyle='None', ", col, col + 1); diff --git a/src/include/ngspice/dvec.h b/src/include/ngspice/dvec.h index d33b5a8ec..241baf311 100644 --- a/src/include/ngspice/dvec.h +++ b/src/include/ngspice/dvec.h @@ -24,7 +24,7 @@ enum dvec_flags { /* Plot types. */ typedef enum { - PLOT_LIN, PLOT_COMB, PLOT_POINT, PLOT_RETLIN, PLOT_BOXES + PLOT_LIN, PLOT_COMB, PLOT_POINT, PLOT_RETLIN, PLOT_BOXES, PLOT_ARROWS } PLOTTYPE; diff --git a/src/spicelib/analysis/dcpss.c b/src/spicelib/analysis/dcpss.c index 7dc0d0202..8b0bc3165 100644 --- a/src/spicelib/analysis/dcpss.c +++ b/src/spicelib/analysis/dcpss.c @@ -4371,7 +4371,7 @@ shootingexit: numNames, nameList, IF_COMPLEX, &(job->PSSplot_fd)) ; tfree (nameList) ; - SPfrontEnd->OUTattributes (job->PSSplot_fd, NULL, PLOT_COMB, NULL) ; + SPfrontEnd->OUTattributes (job->PSSplot_fd, NULL, PLOT_ARROWS, NULL) ; /* ******************** */ /* Starting DFT on data */