diff --git a/ChangeLog b/ChangeLog index a5e279fd9..6c701aaad 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2008-03-22 Paolo Nenzi + * src/frontend/{commands.c, com_gnuplot.c, com_gnuplot.h}, + * src/frontend/plotting/{gnuplot.c, gnuplot.h,plotit.c}: added + initial support for gnuplot plotting of simulation outputs. + Gnuplot interface code has been sent by Stefano Pedretti. + 2008-01-19 Dietmar Warning * configure.in: w/o optimization better debug * src/main.c: fix conflict for own shutdown function diff --git a/src/frontend/Makefile.am b/src/frontend/Makefile.am index 0a417607d..48261dfd6 100644 --- a/src/frontend/Makefile.am +++ b/src/frontend/Makefile.am @@ -31,6 +31,8 @@ libfte_a_SOURCES = \ com_echo.h \ com_ghelp.c \ com_ghelp.h \ + com_gnuplot.h \ + com_gnuplot.c \ com_hardcopy.c \ com_hardcopy.h \ com_help.c \ diff --git a/src/frontend/com_gnuplot.c b/src/frontend/com_gnuplot.c new file mode 100644 index 000000000..392513ae0 --- /dev/null +++ b/src/frontend/com_gnuplot.c @@ -0,0 +1,41 @@ +#include + +#include +#include +#include + +#include "plotting/plotit.h" + +#include "com_gnuplot.h" + + +/* gnuplot file plotargs */ +void +com_gnuplot(wordlist *wl) +{ + char *fname; + bool tempf = FALSE; + + if (wl) { + fname = wl->wl_word; + wl = wl->wl_next; + } + if (!wl) { + return; + } + if (cieq(fname, "temp") || cieq(fname, "tmp")) { + fname = smktemp("gp"); /* Is this the correct name ? */ + tempf = TRUE; + } + + (void) plotit(wl, fname, "gnuplot"); + +#if 0 + /* Leave temp file sitting around so gnuplot can grab it from + background. */ + if (tempf) + (void) unlink(fname); +#endif + + return; +} diff --git a/src/frontend/com_gnuplot.h b/src/frontend/com_gnuplot.h new file mode 100644 index 000000000..255d5717f --- /dev/null +++ b/src/frontend/com_gnuplot.h @@ -0,0 +1,6 @@ +#ifndef _COM_GNUPLOT_H +#define _COM_GNUPLOT_H + +void com_gnuplot(wordlist *wl); + +#endif diff --git a/src/frontend/commands.c b/src/frontend/commands.c index 5f0f9edd1..94069f20c 100644 --- a/src/frontend/commands.c +++ b/src/frontend/commands.c @@ -48,6 +48,7 @@ #include "com_plot.h" #include "com_setscale.h" #include "com_xgraph.h" +#include "com_gnuplot.h" #include "com_state.h" #include "com_chdir.h" #include "com_echo.h" @@ -149,6 +150,10 @@ struct comm spcp_coms[] = { { 1, 041000, 041000, 041000 }, E_DEFHMASK, 1, LOTS, (void (*)()) NULL, "file plotargs : Send plot to Xgraph-11." } , + { "gnuplot", com_gnuplot, FALSE, FALSE, TRUE, + { 1, 041000, 041000, 041000 }, E_DEFHMASK, 1, LOTS, + (void (*)()) NULL, + "file plotargs : Send plot to gnuplot." } , { "hardcopy", com_hardcopy, FALSE, FALSE, TRUE, { 1, 041000, 041000, 041000 }, E_DEFHMASK, 0, LOTS, (void (*)()) NULL, @@ -540,6 +545,10 @@ struct comm nutcp_coms[] = { { 1, 041000, 041000, 041000 }, E_DEFHMASK, 1, LOTS, (void (*)()) NULL, "file plotargs : Send plot to Xgraph-11." } , + { "gnuplot", com_gnuplot, FALSE, FALSE, TRUE, + { 1, 041000, 041000, 041000 }, E_DEFHMASK, 1, LOTS, + (void (*)()) NULL, + "file plotargs : Send plot to gnuplot." } , { "hardcopy", com_hardcopy, FALSE, FALSE, TRUE, { 1, 041000, 041000, 041000 }, E_DEFHMASK, 0, LOTS, (void (*)()) NULL, diff --git a/src/frontend/plotting/Makefile.am b/src/frontend/plotting/Makefile.am index ec152081e..90aef1c6a 100644 --- a/src/frontend/plotting/Makefile.am +++ b/src/frontend/plotting/Makefile.am @@ -7,6 +7,8 @@ libplotting_a_SOURCES = \ agraf.h \ clip.c \ clip.h \ + gnuplot.c \ + gnuplot.h \ graf.c \ graf.h \ graphdb.c \ diff --git a/src/frontend/plotting/gnuplot.c b/src/frontend/plotting/gnuplot.c new file mode 100644 index 000000000..6a33707ec --- /dev/null +++ b/src/frontend/plotting/gnuplot.c @@ -0,0 +1,203 @@ +/********** + * From xgraph.c: + * Copyright 1992 Regents of the University of California. All rights reserved. + * Author: 1992 David A. Gates, U. C. Berkeley CAD Group + * + * Author: 2008 Stefano Pedretti +**********/ + +/* + * gnuplot plots. + */ + +#include "ngspice.h" +#include "cpdefs.h" +#include "ftedefs.h" +#include "dvec.h" +#include "fteparse.h" +#include "gnuplot.h" + +#include + +#define GP_MAXVECTORS 64 + +void +ft_gnuplot(double *xlims, double *ylims, char *filename, char *title, char *xlabel, char *ylabel, GRIDTYPE gridtype, PLOTTYPE plottype, struct dvec *vecs) +{ + + FILE *file, *file_data; + struct dvec *v, *scale; + double xval, yval; + int i, numVecs, linewidth; + bool xlog, ylog, nogrid, markers; + char buf[BSIZE_SP], pointstyle[BSIZE_SP], *text; + + char filename_data[15]; + sprintf(filename_data, "%s.data", filename); + + + /* Sanity checking. */ + for ( v = vecs, numVecs = 0; v; v = v->v_link2 ) { + numVecs++; + } + if (numVecs == 0) { + return; + } else if (numVecs > GP_MAXVECTORS) { + fprintf( cp_err, "Error: too many vectors for gnuplot.\n" ); + return; + } + if (!cp_getvar("xbrushwidth", VT_NUM, &linewidth)) + linewidth = 1; + if (linewidth < 1) linewidth = 1; + + if (!cp_getvar("pointstyle", VT_STRING, pointstyle)) { + markers = FALSE; + } else { + if (cieq(pointstyle,"markers")) { + markers = TRUE; + } else { + markers = FALSE; + } + } + + + /* Make sure the gridtype is supported. */ + switch (gridtype) { + case GRID_LIN: + nogrid = xlog = ylog = FALSE; + break; + case GRID_XLOG: + xlog = TRUE; + nogrid = ylog = FALSE; + break; + case GRID_YLOG: + ylog = TRUE; + nogrid = xlog = FALSE; + break; + case GRID_LOGLOG: + xlog = ylog = TRUE; + nogrid = FALSE; + break; + case GRID_NONE: + nogrid = TRUE; + xlog = ylog = FALSE; + break; + default: + fprintf( cp_err, "Error: grid type unsupported by gnuplot.\n" ); + return; + } + + /* Open the output gnuplot file. */ + if (!(file = fopen(filename, "w"))) { + perror(filename); + return; + } + + /* Set up the file header. */ + if (title) { + text = cp_unquote(title); + fprintf( file, "set title \"%s\"\n", text ); + tfree(text); + } + if (xlabel) { + text = cp_unquote(xlabel); + fprintf( file, "set xlabel \"%s\"\n", text ); + tfree(text); + } + if (ylabel) { + text = cp_unquote(ylabel); + fprintf( file, "set ylabel \"%s\"\n", text ); + tfree(text); + } + if (nogrid) { + fprintf( file, "set grid\n" ); + } + if (xlog) { + fprintf( file, "set logscale x\n" ); + if (xlims) { + fprintf( file, "set xrange [% e: % e]\n", log10(xlims[0]),log10(xlims[1]) ); + } + } else { + fprintf( file, "unset logscale x \n" ); + if (xlims) { + fprintf( file, "set xrange [% e: % e]\n", xlims[0],xlims[1] ); + } + } + if (ylog) { + fprintf( file, "set logscale y \n" ); + if (ylims) { + fprintf( file, "set yrange [% e: % e]\n", log10(ylims[0]),log10(ylims[1]) ); + } + } else { + fprintf( file, "unset logscale y \n" ); + if (ylims) { + fprintf( file, "set yrange [% e: % e]\n", ylims[0],ylims[1] ); + } + } + + fprintf( file, "#set xtics 1\n" ); + fprintf( file, "#set x2tics 1\n" ); + fprintf( file, "#set ytics 1\n" ); + fprintf( file, "#set y2tics 1\n" ); + +/* TODO + fprintf( file, "LineWidth: %d\n", linewidth ); + if (plottype == PLOT_COMB) { + fprintf( file, "BarGraph: True\n" ); + fprintf( file, "NoLines: True\n" ); + } else if (plottype == PLOT_POINT) { + if (markers) { + fprintf( file, "Markers: True\n" ); + } else { + fprintf( file, "LargePixels: True\n" ); + } + fprintf( file, "NoLines: True\n" ); + } +*/ + + /* Open the output gnuplot data file. */ + + if (!(file_data = fopen(filename_data, "w"))) { + perror(filename); + return; + } + + fprintf( file, "plot ", v->v_name ); + i = 0; + + /* Write out the data and setup arrays */ + for ( v = vecs; v; v = v->v_link2 ) { + scale = v->v_scale; + if (v->v_name) { + i= i+2; + fprintf( file, "\'%s\' using %d:%d with lines t \"%s\" ,", filename_data , i , i+1 , v->v_name ); + } + } + fprintf( file, "\n"); + fprintf (file, "set terminal postscript eps\nset out %s.eps\nreplot\nset term pop", filename); + + 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]); + + fprintf( file_data, "% e % e ", xval, yval ); + } + fprintf( file_data, "\n"); + } + + + (void) fclose( file ); + (void) fclose( file_data ); + + (void) sprintf( buf, "gnuplot %s &", filename ); + (void) system( buf ); + + + return; +} diff --git a/src/frontend/plotting/gnuplot.h b/src/frontend/plotting/gnuplot.h new file mode 100644 index 000000000..afc84c17c --- /dev/null +++ b/src/frontend/plotting/gnuplot.h @@ -0,0 +1,16 @@ +/************* + * Header file for gnuplot.c + * 2008 Stefano Pedretti + ************/ + +#ifndef GNUPLOT_H_INCLUDED +#define GNUPLOT_H_INCLUDED + +void ft_gnuplot(double *xlims, double *ylims, char *filename, char *title, + char *xlabel, char *ylabel, GRIDTYPE gridtype, PLOTTYPE plottype, + struct dvec *vecs); + + + + +#endif diff --git a/src/frontend/plotting/plotit.c b/src/frontend/plotting/plotit.c index a10445557..8557a009f 100644 --- a/src/frontend/plotting/plotit.c +++ b/src/frontend/plotting/plotit.c @@ -14,6 +14,7 @@ #include "plotit.h" #include "agraf.h" #include "xgraph.h" +#include "gnuplot.h" #include "graf.h" static wordlist *wl_root; @@ -960,6 +961,20 @@ plotit(wordlist *wl, char *hcopy, char *devname) rtn = TRUE; goto quit; } + + + if (devname && eq(devname, "gnuplot")) { + /* Interface to XGraph-11 Plot Program */ + ft_gnuplot(xlims, ylims, hcopy, + title ? title : vecs->v_plot->pl_title, + xlabel ? xlabel : ft_typabbrev(vecs->v_scale->v_type), + ylabel ? ylabel : ft_typabbrev(j), + gtype, ptype, vecs); + rtn = TRUE; + goto quit; + } + + for (d = vecs, i = 0; d; d = d->v_link2) i++;