2011-12-11 19:05:00 +01:00
|
|
|
#include "ngspice/ngspice.h"
|
2011-12-27 12:33:01 +01:00
|
|
|
#include "ngspice/config.h"
|
2011-12-11 19:05:00 +01:00
|
|
|
#include "ngspice/bool.h"
|
|
|
|
|
#include "ngspice/wordlist.h"
|
|
|
|
|
#include "ngspice/graph.h"
|
|
|
|
|
#include "ngspice/cpdefs.h"
|
|
|
|
|
#include "ngspice/pnode.h"
|
|
|
|
|
#include "ngspice/sim.h"
|
|
|
|
|
#include "ngspice/fteext.h"
|
2000-05-13 19:28:16 +02:00
|
|
|
|
2000-06-27 18:09:02 +02:00
|
|
|
#include <circuits.h>
|
|
|
|
|
|
2000-06-16 21:04:15 +02:00
|
|
|
#include "plotit.h"
|
|
|
|
|
#include "agraf.h"
|
|
|
|
|
#include "xgraph.h"
|
2008-03-22 14:10:46 +01:00
|
|
|
#include "gnuplot.h"
|
2000-06-16 21:04:15 +02:00
|
|
|
#include "graf.h"
|
2000-04-27 22:03:57 +02:00
|
|
|
|
|
|
|
|
static bool sameflag;
|
|
|
|
|
|
2008-08-27 15:39:05 +02:00
|
|
|
#ifdef TCL_MODULE
|
2011-12-11 19:05:00 +01:00
|
|
|
#include "ngspice/tclspice.h"
|
2008-08-27 15:39:05 +02:00
|
|
|
#endif
|
2000-04-27 22:03:57 +02:00
|
|
|
|
2012-07-23 19:17:25 +02:00
|
|
|
|
2000-06-16 21:04:15 +02:00
|
|
|
/* This routine gets parameters from the command line, which are of
|
|
|
|
|
* the form "name number ..." It returns a pointer to the parameter
|
|
|
|
|
* values. */
|
2012-07-23 19:17:25 +02:00
|
|
|
|
2000-06-16 21:04:15 +02:00
|
|
|
static double *
|
|
|
|
|
getlims(wordlist *wl, char *name, int number)
|
|
|
|
|
{
|
2011-07-24 22:30:44 +02:00
|
|
|
double *d;
|
2000-06-16 21:04:15 +02:00
|
|
|
wordlist *beg, *wk;
|
|
|
|
|
int n;
|
2000-04-27 22:03:57 +02:00
|
|
|
|
2011-07-17 18:44:07 +02:00
|
|
|
if(number < 1)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
2012-07-28 19:55:09 +02:00
|
|
|
beg = wl_find(name, wl->wl_next);
|
2011-07-24 22:30:44 +02:00
|
|
|
|
|
|
|
|
if(!beg)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
2012-07-29 12:40:00 +02:00
|
|
|
wk = beg->wl_next;
|
2011-07-24 22:30:44 +02:00
|
|
|
|
|
|
|
|
d = TMALLOC(double, number);
|
|
|
|
|
|
|
|
|
|
for (n = 0; n < number; n++) {
|
|
|
|
|
|
|
|
|
|
char *ss;
|
|
|
|
|
double *td;
|
|
|
|
|
|
|
|
|
|
if (!wk) {
|
|
|
|
|
fprintf(cp_err,
|
|
|
|
|
"Syntax error: not enough parameters for \"%s\".\n", name);
|
|
|
|
|
txfree(d);
|
|
|
|
|
return NULL;
|
2000-06-16 21:04:15 +02:00
|
|
|
}
|
2011-07-24 22:30:44 +02:00
|
|
|
|
|
|
|
|
ss = wk->wl_word;
|
|
|
|
|
td = ft_numparse(&ss, FALSE);
|
|
|
|
|
|
|
|
|
|
if (!td) {
|
|
|
|
|
fprintf(cp_err,
|
|
|
|
|
"Syntax error: bad parameters for \"%s\".\n", name);
|
|
|
|
|
txfree(d);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
d[n] = *td;
|
|
|
|
|
|
2012-07-29 12:40:00 +02:00
|
|
|
wk = wk->wl_next;
|
2011-07-24 22:30:44 +02:00
|
|
|
}
|
|
|
|
|
|
2012-07-29 12:40:00 +02:00
|
|
|
wl_delete_slice(beg, wk);
|
2011-07-24 22:30:44 +02:00
|
|
|
|
|
|
|
|
return d;
|
2000-06-16 21:04:15 +02:00
|
|
|
}
|
2000-04-27 22:03:57 +02:00
|
|
|
|
|
|
|
|
|
2000-06-16 21:04:15 +02:00
|
|
|
/* Extend a data vector to length by replicating the last element, or
|
|
|
|
|
* truncate it if it is too long. */
|
2012-07-23 19:17:25 +02:00
|
|
|
|
2000-06-16 21:04:15 +02:00
|
|
|
static void
|
|
|
|
|
xtend(struct dvec *v, int length)
|
2000-04-27 22:03:57 +02:00
|
|
|
{
|
2000-06-16 21:04:15 +02:00
|
|
|
int i;
|
2010-10-24 14:45:05 +02:00
|
|
|
ngcomplex_t c, *oc;
|
2000-06-16 21:04:15 +02:00
|
|
|
double d, *od;
|
|
|
|
|
|
|
|
|
|
if (v->v_length == length)
|
|
|
|
|
return;
|
2012-07-23 19:17:25 +02:00
|
|
|
|
2000-06-16 21:04:15 +02:00
|
|
|
if (v->v_length > length) {
|
|
|
|
|
v->v_length = length;
|
|
|
|
|
return;
|
|
|
|
|
}
|
2012-07-23 19:17:25 +02:00
|
|
|
|
2000-06-16 21:04:15 +02:00
|
|
|
if (isreal(v)) {
|
|
|
|
|
od = v->v_realdata;
|
2010-10-28 21:32:34 +02:00
|
|
|
v->v_realdata = TMALLOC(double, length);
|
2000-06-16 21:04:15 +02:00
|
|
|
for (i = 0; i < v->v_length; i++)
|
|
|
|
|
v->v_realdata[i] = od[i];
|
|
|
|
|
d = od[--i];
|
|
|
|
|
while (i < length)
|
|
|
|
|
v->v_realdata[i++] = d;
|
|
|
|
|
tfree(od);
|
|
|
|
|
} else {
|
|
|
|
|
oc = v->v_compdata;
|
2010-10-28 21:32:34 +02:00
|
|
|
v->v_compdata = TMALLOC(ngcomplex_t, length);
|
2000-06-16 21:04:15 +02:00
|
|
|
for (i = 0; i < v->v_length; i++) {
|
2012-02-07 20:53:12 +01:00
|
|
|
realpart(v->v_compdata[i]) = realpart(oc[i]);
|
|
|
|
|
imagpart(v->v_compdata[i]) = imagpart(oc[i]);
|
2000-06-16 21:04:15 +02:00
|
|
|
}
|
2012-02-07 20:53:12 +01:00
|
|
|
realpart(c) = realpart(oc[--i]);
|
|
|
|
|
imagpart(c) = imagpart(oc[i]);
|
2000-06-16 21:04:15 +02:00
|
|
|
while (i < length) {
|
2012-02-07 20:53:12 +01:00
|
|
|
realpart(v->v_compdata[i]) = realpart(c);
|
|
|
|
|
imagpart(v->v_compdata[i++]) = imagpart(c);
|
2012-07-23 19:17:25 +02:00
|
|
|
tfree(oc);
|
2000-06-16 21:04:15 +02:00
|
|
|
}
|
|
|
|
|
}
|
2012-07-23 19:17:25 +02:00
|
|
|
|
2000-06-16 21:04:15 +02:00
|
|
|
v->v_length = length;
|
2000-04-27 22:03:57 +02:00
|
|
|
}
|
|
|
|
|
|
2000-06-16 21:04:15 +02:00
|
|
|
|
|
|
|
|
/* Collapse every *xcomp elements into one, and use only the elements
|
|
|
|
|
* between xind[0] and xind[1].
|
2000-04-27 22:03:57 +02:00
|
|
|
*/
|
|
|
|
|
|
2000-06-16 21:04:15 +02:00
|
|
|
static void
|
|
|
|
|
compress(struct dvec *d, double *xcomp, double *xind)
|
2000-04-27 22:03:57 +02:00
|
|
|
{
|
2000-06-16 21:04:15 +02:00
|
|
|
int cfac, ihi, ilo, newlen, i;
|
2000-04-27 22:03:57 +02:00
|
|
|
|
2000-06-16 21:04:15 +02:00
|
|
|
if (xind) {
|
|
|
|
|
ilo = (int) xind[0];
|
|
|
|
|
ihi = (int) xind[1];
|
2010-11-06 19:08:27 +01:00
|
|
|
if ((ihi >= ilo) && (ilo > 0) && (ilo < d->v_length) &&
|
2012-07-23 19:17:25 +02:00
|
|
|
(ihi > 1) && (ihi <= d->v_length)) {
|
2000-06-16 21:04:15 +02:00
|
|
|
newlen = ihi - ilo;
|
|
|
|
|
if (isreal(d)) {
|
2010-11-06 19:08:27 +01:00
|
|
|
double *dd = TMALLOC(double, newlen);
|
|
|
|
|
bcopy(d->v_realdata + ilo, dd, (size_t) newlen * sizeof(double));
|
2000-06-16 21:04:15 +02:00
|
|
|
tfree(d->v_realdata);
|
|
|
|
|
d->v_realdata = dd;
|
|
|
|
|
} else {
|
2010-11-06 19:08:27 +01:00
|
|
|
ngcomplex_t *cc = TMALLOC(ngcomplex_t, newlen);
|
|
|
|
|
bcopy(d->v_compdata + ilo, cc, (size_t) newlen * sizeof(ngcomplex_t));
|
2000-06-16 21:04:15 +02:00
|
|
|
tfree(d->v_compdata);
|
|
|
|
|
d->v_compdata = cc;
|
|
|
|
|
}
|
|
|
|
|
d->v_length = newlen;
|
|
|
|
|
}
|
2000-04-27 22:03:57 +02:00
|
|
|
}
|
|
|
|
|
|
2000-06-16 21:04:15 +02:00
|
|
|
if (xcomp) {
|
|
|
|
|
cfac = (int) *xcomp;
|
|
|
|
|
if ((cfac > 1) && (cfac < d->v_length)) {
|
|
|
|
|
for (i = 0; i * cfac < d->v_length; i++)
|
|
|
|
|
if (isreal(d))
|
2012-08-04 16:03:52 +02:00
|
|
|
d->v_realdata[i] = d->v_realdata[i * cfac];
|
2000-06-16 21:04:15 +02:00
|
|
|
else
|
2012-08-04 16:03:52 +02:00
|
|
|
d->v_compdata[i] = d->v_compdata[i * cfac];
|
2000-06-16 21:04:15 +02:00
|
|
|
d->v_length = i;
|
|
|
|
|
}
|
|
|
|
|
}
|
2000-04-27 22:03:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2000-06-16 21:04:15 +02:00
|
|
|
/* Check for and remove a one-word keyword. */
|
2012-07-23 19:17:25 +02:00
|
|
|
|
2000-06-16 21:04:15 +02:00
|
|
|
static bool
|
|
|
|
|
getflag(wordlist *wl, char *name)
|
2000-04-27 22:03:57 +02:00
|
|
|
{
|
2012-07-28 19:55:09 +02:00
|
|
|
wl = wl_find(name, wl->wl_next);
|
2012-07-28 12:29:19 +02:00
|
|
|
|
|
|
|
|
if (!wl)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
2012-07-29 12:40:00 +02:00
|
|
|
wl_delete_slice(wl, wl->wl_next);
|
2012-07-23 19:17:25 +02:00
|
|
|
|
2012-07-28 12:29:19 +02:00
|
|
|
return TRUE;
|
2000-06-16 21:04:15 +02:00
|
|
|
}
|
2000-04-27 22:03:57 +02:00
|
|
|
|
|
|
|
|
|
2000-06-16 21:04:15 +02:00
|
|
|
/* Return a parameter of the form "xlabel foo" */
|
2012-07-23 19:17:25 +02:00
|
|
|
|
2000-06-16 21:04:15 +02:00
|
|
|
static char *
|
|
|
|
|
getword(wordlist *wl, char *name)
|
|
|
|
|
{
|
|
|
|
|
wordlist *beg;
|
|
|
|
|
char *s;
|
2000-04-27 22:03:57 +02:00
|
|
|
|
2012-07-28 19:55:09 +02:00
|
|
|
beg = wl_find(name, wl->wl_next);
|
2012-07-28 12:29:19 +02:00
|
|
|
|
|
|
|
|
if (!beg)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
2012-07-28 19:55:09 +02:00
|
|
|
if (!beg->wl_next) {
|
2012-07-28 12:29:19 +02:00
|
|
|
fprintf(cp_err,
|
|
|
|
|
"Syntax error: looking for plot keyword at \"%s\".\n", name);
|
|
|
|
|
return NULL;
|
2000-04-27 22:03:57 +02:00
|
|
|
}
|
2012-07-23 19:17:25 +02:00
|
|
|
|
2012-07-28 12:29:19 +02:00
|
|
|
s = copy(beg->wl_next->wl_word);
|
|
|
|
|
|
2012-07-29 12:40:00 +02:00
|
|
|
wl_delete_slice(beg, beg->wl_next->wl_next);
|
2012-07-28 12:29:19 +02:00
|
|
|
|
|
|
|
|
return s;
|
2000-04-27 22:03:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* The common routine for all plotting commands. This does hardcopy
|
2000-06-16 21:04:15 +02:00
|
|
|
* and graphics plotting. */
|
2012-07-23 19:17:25 +02:00
|
|
|
|
2000-06-16 21:04:15 +02:00
|
|
|
bool
|
2000-04-27 22:03:57 +02:00
|
|
|
plotit(wordlist *wl, char *hcopy, char *devname)
|
|
|
|
|
{
|
|
|
|
|
/* All these things are static so that "samep" will work. */
|
|
|
|
|
static double *xcompress = NULL, *xindices = NULL;
|
2009-04-05 10:02:03 +02:00
|
|
|
static double *xlim = NULL, *ylim = NULL, *xynull;
|
2000-04-27 22:03:57 +02:00
|
|
|
static double *xdelta = NULL, *ydelta = NULL;
|
|
|
|
|
static char *xlabel = NULL, *ylabel = NULL, *title = NULL;
|
|
|
|
|
static bool nointerp = FALSE;
|
|
|
|
|
static GRIDTYPE gtype = GRID_LIN;
|
|
|
|
|
static PLOTTYPE ptype = PLOT_LIN;
|
|
|
|
|
|
|
|
|
|
bool gfound = FALSE, pfound = FALSE, oneval = FALSE;
|
|
|
|
|
double *dd, ylims[2], xlims[2];
|
|
|
|
|
struct pnode *n, *names;
|
|
|
|
|
struct dvec *dv, *d = NULL, *vecs = NULL, *lv, *lastvs = NULL;
|
|
|
|
|
char *xn;
|
|
|
|
|
int i, j, xt;
|
2012-08-04 16:04:00 +02:00
|
|
|
double tt;
|
2012-07-28 19:55:09 +02:00
|
|
|
wordlist *wwl;
|
2000-04-27 22:03:57 +02:00
|
|
|
char cline[BSIZE_SP], buf[BSIZE_SP], *pname;
|
2009-03-08 13:10:15 +01:00
|
|
|
char *nxlabel = NULL, *nylabel = NULL, *ntitle = NULL;
|
2000-04-27 22:03:57 +02:00
|
|
|
|
|
|
|
|
double tstep, tstart, tstop, ttime;
|
2012-07-23 19:17:25 +02:00
|
|
|
|
2003-07-23 21:36:39 +02:00
|
|
|
/* return value, error by default */
|
|
|
|
|
bool rtn = FALSE;
|
2000-04-27 22:03:57 +02:00
|
|
|
|
|
|
|
|
if (!wl)
|
2012-07-28 19:55:09 +02:00
|
|
|
return rtn;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* we need a preceding element here,
|
|
|
|
|
* and we will destructively modify the wordlist in stupid ways,
|
|
|
|
|
* thus lets make our own copy which fits our purpose
|
|
|
|
|
*/
|
|
|
|
|
wl = wl_cons(NULL, wl_copy(wl));
|
2000-04-27 22:03:57 +02:00
|
|
|
|
2012-07-23 19:17:25 +02:00
|
|
|
/* First get the command line, without the limits.
|
2009-03-08 13:10:15 +01:00
|
|
|
Wii be used for zoomed windows */
|
2000-04-27 22:03:57 +02:00
|
|
|
wwl = wl_copy(wl);
|
2012-08-04 16:03:08 +02:00
|
|
|
xynull = getlims(wwl, "xl", 2);
|
|
|
|
|
tfree(xynull);
|
2009-04-05 10:02:03 +02:00
|
|
|
xynull = getlims(wwl, "xlimit", 2);
|
2012-08-04 16:03:08 +02:00
|
|
|
tfree(xynull);
|
2009-04-05 10:02:03 +02:00
|
|
|
xynull = getlims(wwl, "yl", 2);
|
2012-08-04 16:03:08 +02:00
|
|
|
tfree(xynull);
|
2009-04-05 10:02:03 +02:00
|
|
|
xynull = getlims(wwl, "ylimit", 2);
|
2012-08-04 16:03:08 +02:00
|
|
|
tfree(xynull);
|
2009-03-08 13:10:15 +01:00
|
|
|
/* remove tile, xlabel, ylabel */
|
|
|
|
|
nxlabel = getword(wwl, "xlabel");
|
|
|
|
|
nylabel = getword(wwl, "ylabel");
|
|
|
|
|
ntitle = getword(wwl, "title");
|
2012-07-28 19:55:09 +02:00
|
|
|
pname = wl_flatten(wwl->wl_next);
|
2003-07-23 21:36:39 +02:00
|
|
|
(void) sprintf(cline, "plot %s", pname);
|
|
|
|
|
tfree(pname);
|
2000-04-27 22:03:57 +02:00
|
|
|
wl_free(wwl);
|
2012-07-23 19:17:25 +02:00
|
|
|
|
2009-03-08 13:10:15 +01:00
|
|
|
/* add title, xlabel or ylabel, if available, with quotes '' */
|
|
|
|
|
if (nxlabel) {
|
2012-07-23 19:17:25 +02:00
|
|
|
sprintf(cline, "%s xlabel '%s'", cline, nxlabel);
|
|
|
|
|
tfree (nxlabel);
|
2009-03-08 13:10:15 +01:00
|
|
|
}
|
|
|
|
|
if (nylabel) {
|
2012-07-23 19:17:25 +02:00
|
|
|
sprintf(cline, "%s ylabel '%s'", cline, nylabel);
|
|
|
|
|
tfree (nylabel);
|
2009-03-08 13:10:15 +01:00
|
|
|
}
|
|
|
|
|
if (ntitle) {
|
2012-07-23 19:17:25 +02:00
|
|
|
sprintf(cline, "%s title '%s'", cline, ntitle);
|
|
|
|
|
tfree (ntitle);
|
2009-03-08 13:10:15 +01:00
|
|
|
}
|
2000-04-27 22:03:57 +02:00
|
|
|
|
|
|
|
|
/* Now extract all the parameters. */
|
|
|
|
|
|
|
|
|
|
sameflag = getflag(wl, "samep");
|
|
|
|
|
|
|
|
|
|
if (!sameflag || !xlim) {
|
|
|
|
|
xlim = getlims(wl, "xl", 2);
|
|
|
|
|
if (!xlim)
|
|
|
|
|
xlim = getlims(wl, "xlimit", 2);
|
|
|
|
|
} else {
|
|
|
|
|
(void) getlims(wl, "xl", 2);
|
|
|
|
|
(void) getlims(wl, "xlimit", 2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!sameflag || !ylim) {
|
|
|
|
|
ylim = getlims(wl, "yl", 2);
|
|
|
|
|
if (!ylim)
|
|
|
|
|
ylim = getlims(wl, "ylimit", 2);
|
|
|
|
|
} else {
|
|
|
|
|
(void) getlims(wl, "yl", 2);
|
|
|
|
|
(void) getlims(wl, "ylimit", 2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!sameflag || !xcompress) {
|
|
|
|
|
xcompress = getlims(wl, "xcompress", 1);
|
|
|
|
|
if (!xcompress)
|
|
|
|
|
xcompress = getlims(wl, "xcomp", 1);
|
|
|
|
|
} else {
|
|
|
|
|
(void) getlims(wl, "xcompress", 1);
|
|
|
|
|
(void) getlims(wl, "xcomp", 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!sameflag || !xindices) {
|
|
|
|
|
xindices = getlims(wl, "xindices", 2);
|
|
|
|
|
if (!xindices)
|
|
|
|
|
xindices = getlims(wl, "xind", 2);
|
|
|
|
|
} else {
|
|
|
|
|
(void) getlims(wl, "xindices", 2);
|
|
|
|
|
(void) getlims(wl, "xind", 2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!sameflag || !xdelta) {
|
|
|
|
|
xdelta = getlims(wl, "xdelta", 1);
|
|
|
|
|
if (!xdelta)
|
|
|
|
|
xdelta = getlims(wl, "xdel", 1);
|
|
|
|
|
} else {
|
|
|
|
|
(void) getlims(wl, "xdelta", 1);
|
|
|
|
|
(void) getlims(wl, "xdel", 1);
|
|
|
|
|
}
|
2012-07-23 19:17:25 +02:00
|
|
|
|
2000-04-27 22:03:57 +02:00
|
|
|
if (!sameflag || !ydelta) {
|
|
|
|
|
ydelta = getlims(wl, "ydelta", 1);
|
|
|
|
|
if (!ydelta)
|
|
|
|
|
ydelta = getlims(wl, "ydel", 1);
|
|
|
|
|
} else {
|
|
|
|
|
(void) getlims(wl, "ydelta", 1);
|
|
|
|
|
(void) getlims(wl, "ydel", 1);
|
|
|
|
|
}
|
2012-07-23 19:17:25 +02:00
|
|
|
|
2000-04-27 22:03:57 +02:00
|
|
|
/* Get the grid type and the point type. Note we can't do if-else
|
|
|
|
|
* here because we want to catch all the grid types.
|
|
|
|
|
*/
|
|
|
|
|
if (getflag(wl, "lingrid")) {
|
|
|
|
|
if (gfound)
|
2012-08-03 20:42:37 +02:00
|
|
|
fprintf(cp_err, "Warning: too many grid types given\n");
|
2000-04-27 22:03:57 +02:00
|
|
|
else {
|
|
|
|
|
gtype = GRID_LIN;
|
|
|
|
|
gfound = TRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (getflag(wl, "loglog")) {
|
|
|
|
|
if (gfound)
|
2012-08-03 20:42:37 +02:00
|
|
|
fprintf(cp_err, "Warning: too many grid types given\n");
|
2000-04-27 22:03:57 +02:00
|
|
|
else {
|
|
|
|
|
gtype = GRID_LOGLOG;
|
|
|
|
|
gfound = TRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (getflag(wl, "nogrid")) {
|
|
|
|
|
if (gfound)
|
2012-08-03 20:42:37 +02:00
|
|
|
fprintf(cp_err, "Warning: too many grid types given\n");
|
2000-04-27 22:03:57 +02:00
|
|
|
else {
|
|
|
|
|
gtype = GRID_NONE;
|
|
|
|
|
gfound = TRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (getflag(wl, "linear")) {
|
|
|
|
|
if (gfound)
|
2012-08-03 20:42:37 +02:00
|
|
|
fprintf(cp_err, "Warning: too many grid types given\n");
|
2000-04-27 22:03:57 +02:00
|
|
|
else {
|
|
|
|
|
gtype = GRID_LIN;
|
|
|
|
|
gfound = TRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (getflag(wl, "xlog")) {
|
|
|
|
|
if (gfound)
|
2012-08-03 20:42:37 +02:00
|
|
|
fprintf(cp_err, "Warning: too many grid types given\n");
|
2000-04-27 22:03:57 +02:00
|
|
|
else {
|
|
|
|
|
gtype = GRID_XLOG;
|
|
|
|
|
gfound = TRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (getflag(wl, "ylog")) {
|
|
|
|
|
if (gfound)
|
2012-08-03 20:42:37 +02:00
|
|
|
fprintf(cp_err, "Warning: too many grid types given\n");
|
2000-04-27 22:03:57 +02:00
|
|
|
else {
|
|
|
|
|
gtype = GRID_YLOG;
|
|
|
|
|
gfound = TRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (getflag(wl, "polar")) {
|
|
|
|
|
if (gfound)
|
2012-08-03 20:42:37 +02:00
|
|
|
fprintf(cp_err, "Warning: too many grid types given\n");
|
2000-04-27 22:03:57 +02:00
|
|
|
else {
|
|
|
|
|
gtype = GRID_POLAR;
|
|
|
|
|
gfound = TRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (getflag(wl, "smith")) {
|
|
|
|
|
if (gfound)
|
2012-08-03 20:42:37 +02:00
|
|
|
fprintf(cp_err, "Warning: too many grid types given\n");
|
2000-04-27 22:03:57 +02:00
|
|
|
else {
|
|
|
|
|
gtype = GRID_SMITH;
|
|
|
|
|
gfound = TRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (getflag(wl, "smithgrid")) {
|
|
|
|
|
if (gfound)
|
2012-08-03 20:42:37 +02:00
|
|
|
fprintf(cp_err, "Warning: too many grid types given\n");
|
2000-04-27 22:03:57 +02:00
|
|
|
else {
|
|
|
|
|
gtype = GRID_SMITHGRID;
|
|
|
|
|
gfound = TRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!sameflag && !gfound) {
|
2010-07-17 22:48:20 +02:00
|
|
|
if (cp_getvar("gridstyle", CP_STRING, buf)) {
|
2000-04-27 22:03:57 +02:00
|
|
|
if (eq(buf, "lingrid"))
|
|
|
|
|
gtype = GRID_LIN;
|
|
|
|
|
else if (eq(buf, "loglog"))
|
|
|
|
|
gtype = GRID_LOGLOG;
|
|
|
|
|
else if (eq(buf, "xlog"))
|
|
|
|
|
gtype = GRID_XLOG;
|
|
|
|
|
else if (eq(buf, "ylog"))
|
|
|
|
|
gtype = GRID_YLOG;
|
|
|
|
|
else if (eq(buf, "smith"))
|
|
|
|
|
gtype = GRID_SMITH;
|
|
|
|
|
else if (eq(buf, "smithgrid"))
|
|
|
|
|
gtype = GRID_SMITHGRID;
|
|
|
|
|
else if (eq(buf, "polar"))
|
|
|
|
|
gtype = GRID_POLAR;
|
|
|
|
|
else if (eq(buf, "nogrid"))
|
|
|
|
|
gtype = GRID_NONE;
|
|
|
|
|
else {
|
2012-08-03 20:42:37 +02:00
|
|
|
fprintf(cp_err, "Warning: strange grid type %s\n", buf);
|
2000-04-27 22:03:57 +02:00
|
|
|
gtype = GRID_LIN;
|
|
|
|
|
}
|
|
|
|
|
gfound = TRUE;
|
|
|
|
|
} else
|
|
|
|
|
gtype = GRID_LIN;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Now get the point type. */
|
|
|
|
|
|
|
|
|
|
if (getflag(wl, "linplot")) {
|
|
|
|
|
if (pfound)
|
2012-08-03 20:42:37 +02:00
|
|
|
fprintf(cp_err, "Warning: too many plot types given\n");
|
2000-04-27 22:03:57 +02:00
|
|
|
else {
|
|
|
|
|
ptype = PLOT_LIN;
|
|
|
|
|
pfound = TRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (getflag(wl, "combplot")) {
|
|
|
|
|
if (pfound)
|
2012-08-03 20:42:37 +02:00
|
|
|
fprintf(cp_err, "Warning: too many plot types given\n");
|
2000-04-27 22:03:57 +02:00
|
|
|
else {
|
|
|
|
|
ptype = PLOT_COMB;
|
|
|
|
|
pfound = TRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (getflag(wl, "pointplot")) {
|
|
|
|
|
if (pfound)
|
2012-08-03 20:42:37 +02:00
|
|
|
fprintf(cp_err, "Warning: too many plot types given\n");
|
2000-04-27 22:03:57 +02:00
|
|
|
else {
|
|
|
|
|
ptype = PLOT_POINT;
|
|
|
|
|
pfound = TRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!sameflag && !pfound) {
|
2010-07-17 22:48:20 +02:00
|
|
|
if (cp_getvar("plotstyle", CP_STRING, buf)) {
|
2000-04-27 22:03:57 +02:00
|
|
|
if (eq(buf, "linplot"))
|
|
|
|
|
ptype = PLOT_LIN;
|
|
|
|
|
else if (eq(buf, "combplot"))
|
|
|
|
|
ptype = PLOT_COMB;
|
|
|
|
|
else if (eq(buf, "pointplot"))
|
|
|
|
|
ptype = PLOT_POINT;
|
|
|
|
|
else {
|
2012-08-03 20:42:37 +02:00
|
|
|
fprintf(cp_err, "Warning: strange plot type %s\n", buf);
|
2000-04-27 22:03:57 +02:00
|
|
|
ptype = PLOT_LIN;
|
|
|
|
|
}
|
|
|
|
|
pfound = TRUE;
|
|
|
|
|
} else
|
|
|
|
|
ptype = PLOT_LIN;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!sameflag || !xlabel)
|
|
|
|
|
xlabel = getword(wl, "xlabel");
|
|
|
|
|
else
|
|
|
|
|
(void) getword(wl, "xlabel");
|
2012-07-23 19:17:25 +02:00
|
|
|
|
2000-04-27 22:03:57 +02:00
|
|
|
if (!sameflag || !ylabel)
|
|
|
|
|
ylabel = getword(wl, "ylabel");
|
|
|
|
|
else
|
|
|
|
|
(void) getword(wl, "ylabel");
|
2012-07-23 19:17:25 +02:00
|
|
|
|
2000-04-27 22:03:57 +02:00
|
|
|
if (!sameflag || !title)
|
|
|
|
|
title = getword(wl, "title");
|
|
|
|
|
else
|
|
|
|
|
(void) getword(wl, "title");
|
|
|
|
|
|
|
|
|
|
if (!sameflag)
|
|
|
|
|
nointerp = getflag(wl, "nointerp");
|
|
|
|
|
else if (getflag(wl, "nointerp"))
|
|
|
|
|
nointerp = TRUE;
|
|
|
|
|
|
2012-07-28 19:55:09 +02:00
|
|
|
if (!wl->wl_next) {
|
2000-04-27 22:03:57 +02:00
|
|
|
fprintf(cp_err, "Error: no vectors given\n");
|
2003-07-23 21:36:39 +02:00
|
|
|
goto quit1;
|
2000-04-27 22:03:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Now parse the vectors. We have a list of the form
|
|
|
|
|
* "a b vs c d e vs f g h". Since it's a bit of a hassle for
|
|
|
|
|
* us to parse the vector boundaries here, we do this -- call
|
|
|
|
|
* ft_getpnames() without the check flag, and then look for 0-length
|
|
|
|
|
* vectors with the name "vs"... This is a sort of a gross hack,
|
|
|
|
|
* since we have to check for 0-length vectors ourselves after
|
|
|
|
|
* evaulating the pnodes...
|
|
|
|
|
*/
|
|
|
|
|
|
2012-07-28 19:55:09 +02:00
|
|
|
names = ft_getpnames(wl->wl_next, FALSE);
|
2000-04-27 22:03:57 +02:00
|
|
|
if (names == NULL)
|
2003-07-23 21:36:39 +02:00
|
|
|
goto quit1;
|
2000-04-27 22:03:57 +02:00
|
|
|
|
|
|
|
|
/* Now evaluate the names. */
|
2012-08-04 16:04:32 +02:00
|
|
|
for (n = names, lv = NULL; n; n = n->pn_next)
|
2000-04-27 22:03:57 +02:00
|
|
|
if (n->pn_value && (n->pn_value->v_length == 0) &&
|
2012-08-04 16:04:32 +02:00
|
|
|
eq(n->pn_value->v_name, "vs"))
|
|
|
|
|
{
|
2000-04-27 22:03:57 +02:00
|
|
|
if (!lv) {
|
|
|
|
|
fprintf(cp_err, "Error: misplaced vs arg\n");
|
2003-07-23 21:36:39 +02:00
|
|
|
goto quit;
|
2012-08-04 16:04:21 +02:00
|
|
|
}
|
2010-11-19 19:54:40 +01:00
|
|
|
if ((n = n->pn_next) == NULL) {
|
2012-08-03 20:42:37 +02:00
|
|
|
fprintf(cp_err, "Error: missing vs arg\n");
|
2003-07-23 21:36:39 +02:00
|
|
|
goto quit;
|
2000-04-27 22:03:57 +02:00
|
|
|
}
|
|
|
|
|
dv = ft_evaluate(n);
|
|
|
|
|
if (!dv)
|
2003-07-23 21:36:39 +02:00
|
|
|
goto quit;
|
2012-07-23 19:17:25 +02:00
|
|
|
|
2000-04-27 22:03:57 +02:00
|
|
|
if (lastvs)
|
|
|
|
|
lv = lastvs->v_link2;
|
|
|
|
|
else
|
|
|
|
|
lv = vecs;
|
2012-07-23 19:17:25 +02:00
|
|
|
|
2000-04-27 22:03:57 +02:00
|
|
|
while (lv) {
|
|
|
|
|
lv->v_scale = dv;
|
|
|
|
|
lastvs = lv;
|
|
|
|
|
lv = lv->v_link2;
|
|
|
|
|
}
|
2012-08-04 16:05:05 +02:00
|
|
|
|
|
|
|
|
} else {
|
2012-07-23 19:17:25 +02:00
|
|
|
|
2000-04-27 22:03:57 +02:00
|
|
|
dv = ft_evaluate(n);
|
2012-07-23 19:17:25 +02:00
|
|
|
|
2000-04-27 22:03:57 +02:00
|
|
|
if (!dv)
|
2003-07-23 21:36:39 +02:00
|
|
|
goto quit;
|
2012-07-23 19:17:25 +02:00
|
|
|
|
2000-04-27 22:03:57 +02:00
|
|
|
if (!d)
|
|
|
|
|
vecs = dv;
|
|
|
|
|
else
|
|
|
|
|
d->v_link2 = dv;
|
2012-07-23 19:17:25 +02:00
|
|
|
|
2000-04-27 22:03:57 +02:00
|
|
|
for (d = dv; d->v_link2; d = d->v_link2)
|
|
|
|
|
;
|
2012-07-23 19:17:25 +02:00
|
|
|
|
2000-04-27 22:03:57 +02:00
|
|
|
lv = dv;
|
2012-08-04 16:05:05 +02:00
|
|
|
}
|
2012-07-23 19:17:25 +02:00
|
|
|
|
|
|
|
|
/* free_pnode(names); pn:really should be commented out ? */
|
2000-04-27 22:03:57 +02:00
|
|
|
d->v_link2 = NULL;
|
|
|
|
|
|
|
|
|
|
/* Now check for 0-length vectors. */
|
|
|
|
|
for (d = vecs; d; d = d->v_link2)
|
|
|
|
|
if (!d->v_length) {
|
2007-10-08 17:36:56 +02:00
|
|
|
fprintf(cp_err, "Error(plotit.c--plotit): %s: no such vector\n",
|
2000-04-27 22:03:57 +02:00
|
|
|
d->v_name);
|
2003-07-23 21:36:39 +02:00
|
|
|
goto quit;
|
2000-04-27 22:03:57 +02:00
|
|
|
}
|
2012-07-23 19:17:25 +02:00
|
|
|
|
2000-04-27 22:03:57 +02:00
|
|
|
/* If there are higher dimensional vectors, transform them into a
|
|
|
|
|
* family of vectors.
|
|
|
|
|
*/
|
2012-08-04 16:04:32 +02:00
|
|
|
for (d = vecs, lv = NULL; d; d = d->v_link2)
|
2000-04-27 22:03:57 +02:00
|
|
|
if (d->v_numdims > 1) {
|
2012-07-23 19:17:25 +02:00
|
|
|
if (lv)
|
|
|
|
|
lv->v_link2 = vec_mkfamily(d);
|
|
|
|
|
else
|
|
|
|
|
vecs = lv = vec_mkfamily(d);
|
2000-04-27 22:03:57 +02:00
|
|
|
while (lv->v_link2)
|
|
|
|
|
lv = lv->v_link2;
|
|
|
|
|
lv->v_link2 = d->v_link2;
|
|
|
|
|
d = lv;
|
|
|
|
|
} else {
|
|
|
|
|
lv = d;
|
2012-07-23 19:17:25 +02:00
|
|
|
}
|
2000-04-27 22:03:57 +02:00
|
|
|
|
|
|
|
|
/* Now fill in the scales for vectors who aren't already fixed up. */
|
|
|
|
|
for (d = vecs; d; d = d->v_link2)
|
|
|
|
|
if (!d->v_scale) {
|
|
|
|
|
if (d->v_plot->pl_scale)
|
|
|
|
|
d->v_scale = d->v_plot->pl_scale;
|
|
|
|
|
else
|
|
|
|
|
d->v_scale = d;
|
|
|
|
|
}
|
|
|
|
|
|
2012-07-23 19:17:25 +02:00
|
|
|
/* The following line displays the unit at the time of
|
|
|
|
|
temp-sweep and res-sweep. This may not be a so good solution. by H.T */
|
2012-08-04 16:03:52 +02:00
|
|
|
if (strcmp(vecs->v_scale->v_name, "temp-sweep") == 0)
|
|
|
|
|
vecs->v_scale->v_type = SV_TEMP;
|
|
|
|
|
if (strcmp(vecs->v_scale->v_name, "res-sweep") == 0)
|
|
|
|
|
vecs->v_scale->v_type = SV_RES;
|
2000-04-27 22:03:57 +02:00
|
|
|
|
|
|
|
|
/* See if the log flag is set anywhere... */
|
|
|
|
|
if (!gfound) {
|
|
|
|
|
for (d = vecs; d; d = d->v_link2)
|
|
|
|
|
if (d->v_scale && (d->v_scale->v_gridtype == GRID_XLOG))
|
|
|
|
|
gtype = GRID_XLOG;
|
|
|
|
|
for (d = vecs; d; d = d->v_link2)
|
|
|
|
|
if (d->v_gridtype == GRID_YLOG) {
|
2012-08-04 16:03:52 +02:00
|
|
|
if ((gtype == GRID_XLOG) || (gtype == GRID_LOGLOG))
|
2000-04-27 22:03:57 +02:00
|
|
|
gtype = GRID_LOGLOG;
|
|
|
|
|
else
|
|
|
|
|
gtype = GRID_YLOG;
|
|
|
|
|
}
|
|
|
|
|
for (d = vecs; d; d = d->v_link2)
|
|
|
|
|
if (d->v_gridtype == GRID_SMITH || d->v_gridtype == GRID_SMITHGRID
|
2012-07-23 19:17:25 +02:00
|
|
|
|| d->v_gridtype == GRID_POLAR)
|
|
|
|
|
{
|
2000-04-27 22:03:57 +02:00
|
|
|
gtype = d->v_gridtype;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* See if there are any default plot types... Here, like above, we
|
|
|
|
|
* don't do entirely the best thing when there is a mixed set of
|
|
|
|
|
* default plot types...
|
|
|
|
|
*/
|
|
|
|
|
if (!sameflag && !pfound) {
|
|
|
|
|
ptype = PLOT_LIN;
|
|
|
|
|
for (d = vecs; d; d = d->v_link2)
|
|
|
|
|
if (d->v_plottype != PLOT_LIN) {
|
|
|
|
|
ptype = d->v_plottype;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Check and see if this is pole zero stuff. */
|
|
|
|
|
if ((vecs->v_type == SV_POLE) || (vecs->v_type == SV_ZERO))
|
|
|
|
|
oneval = TRUE;
|
2012-07-23 19:17:25 +02:00
|
|
|
|
2000-04-27 22:03:57 +02:00
|
|
|
for (d = vecs; d; d = d->v_link2)
|
|
|
|
|
if (((d->v_type == SV_POLE) || (d->v_type == SV_ZERO)) !=
|
2012-07-23 19:17:25 +02:00
|
|
|
oneval ? 1 : 0) {
|
2000-04-27 22:03:57 +02:00
|
|
|
fprintf(cp_err,
|
2012-07-23 19:17:25 +02:00
|
|
|
"Error: plot must be either all pole-zero or contain no poles or zeros\n");
|
2003-07-23 21:36:39 +02:00
|
|
|
goto quit;
|
2000-04-27 22:03:57 +02:00
|
|
|
}
|
2012-07-23 19:17:25 +02:00
|
|
|
|
2000-04-27 22:03:57 +02:00
|
|
|
if ((gtype == GRID_POLAR) || (gtype == GRID_SMITH
|
2012-07-23 19:17:25 +02:00
|
|
|
|| gtype == GRID_SMITHGRID))
|
2000-04-27 22:03:57 +02:00
|
|
|
{
|
|
|
|
|
oneval = TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* If we are plotting scalars, make sure there is enough
|
|
|
|
|
* data to fit on the screen.
|
|
|
|
|
*/
|
|
|
|
|
for (d = vecs; d; d = d->v_link2)
|
|
|
|
|
if (d->v_length == 1)
|
|
|
|
|
xtend(d, d->v_scale->v_length);
|
|
|
|
|
|
|
|
|
|
/* Now patch up each vector with the compression and thestrchr
|
|
|
|
|
* selection.
|
|
|
|
|
*/
|
2012-08-04 16:04:32 +02:00
|
|
|
if (xcompress || xindices)
|
2000-04-27 22:03:57 +02:00
|
|
|
for (d = vecs; d; d = d->v_link2) {
|
|
|
|
|
compress(d, xcompress, xindices);
|
|
|
|
|
d->v_scale = vec_copy(d->v_scale);
|
|
|
|
|
compress(d->v_scale, xcompress, xindices);
|
|
|
|
|
}
|
2012-07-23 19:17:25 +02:00
|
|
|
|
2000-04-27 22:03:57 +02:00
|
|
|
/* Transform for smith plots */
|
|
|
|
|
if (gtype == GRID_SMITH) {
|
2012-07-23 19:17:25 +02:00
|
|
|
double re, im, rex, imx;
|
|
|
|
|
double r;
|
|
|
|
|
struct dvec **prevvp, *n;
|
|
|
|
|
int j;
|
|
|
|
|
|
|
|
|
|
prevvp = &vecs;
|
|
|
|
|
|
|
|
|
|
for (d = vecs; d; d = d->v_link2) {
|
|
|
|
|
if (d->v_flags & VF_PERMANENT) {
|
|
|
|
|
n = vec_copy(d);
|
|
|
|
|
n->v_flags &= ~VF_PERMANENT;
|
|
|
|
|
n->v_link2 = d->v_link2;
|
|
|
|
|
d = n;
|
|
|
|
|
*prevvp = d;
|
|
|
|
|
}
|
|
|
|
|
prevvp = &d->v_link2;
|
|
|
|
|
|
|
|
|
|
if (isreal(d)) {
|
|
|
|
|
fprintf(cp_err,
|
|
|
|
|
"Warning: plotting real data \"%s\" on a smith grid\n",
|
|
|
|
|
d->v_name);
|
|
|
|
|
|
|
|
|
|
for (j = 0; j < d->v_length; j++) {
|
|
|
|
|
r = d->v_realdata[j];
|
|
|
|
|
d->v_realdata[j] = (r - 1) / (r + 1);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
for (j = 0; j < d->v_length; j++) {
|
|
|
|
|
/* (re - 1, im) / (re + 1, im) */
|
|
|
|
|
|
|
|
|
|
re = realpart(d->v_compdata[j]);
|
|
|
|
|
im = imagpart(d->v_compdata[j]);
|
|
|
|
|
|
|
|
|
|
rex = re + 1;
|
|
|
|
|
imx = im;
|
|
|
|
|
re = re - 1;
|
|
|
|
|
|
|
|
|
|
/* (re, im) / (rex, imx) */
|
|
|
|
|
/* x = 1 - (imx / rex) * (imx / rex);
|
|
|
|
|
* r = re / rex + im / rex * imx / rex;
|
|
|
|
|
* i = im / rex - re / rex * imx / rex;
|
|
|
|
|
*
|
|
|
|
|
*
|
|
|
|
|
* realpart(d->v_compdata[j]) = r / x;
|
|
|
|
|
* imagpart(d->v_compdata[j]) = i / x;
|
|
|
|
|
*/
|
|
|
|
|
realpart(d->v_compdata[j]) = (rex*re+imx*imx) / (rex*rex+imx*imx);
|
|
|
|
|
imagpart(d->v_compdata[j]) = (2*imx) / (rex*rex+imx*imx);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2000-04-27 22:03:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Figure out the proper x- and y-axis limits. */
|
|
|
|
|
if (ylim) {
|
2012-07-23 19:17:25 +02:00
|
|
|
ylims[0] = ylim[0];
|
|
|
|
|
ylims[1] = ylim[1];
|
2000-04-27 22:03:57 +02:00
|
|
|
} else if (oneval) {
|
|
|
|
|
ylims[0] = HUGE;
|
|
|
|
|
ylims[1] = - ylims[0];
|
|
|
|
|
for (d = vecs; d; d = d->v_link2) {
|
2012-07-23 19:17:25 +02:00
|
|
|
/* dd = ft_minmax(d, TRUE); */
|
|
|
|
|
/* With this we seek the maximum and minimum of imaginary part
|
|
|
|
|
* that will go to Y axis
|
|
|
|
|
*/
|
|
|
|
|
dd = ft_minmax(d, FALSE);
|
2012-08-04 16:03:01 +02:00
|
|
|
if (ylims[0] > dd[0])
|
2000-04-27 22:03:57 +02:00
|
|
|
ylims[0] = dd[0];
|
2012-08-04 16:03:01 +02:00
|
|
|
if (ylims[1] < dd[1])
|
2000-04-27 22:03:57 +02:00
|
|
|
ylims[1] = dd[1];
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
ylims[0] = HUGE;
|
|
|
|
|
ylims[1] = - ylims[0];
|
|
|
|
|
for (d = vecs; d; d = d->v_link2) {
|
|
|
|
|
dd = ft_minmax(d, TRUE);
|
2012-08-04 16:03:01 +02:00
|
|
|
if (ylims[0] > dd[0])
|
2000-04-27 22:03:57 +02:00
|
|
|
ylims[0] = dd[0];
|
2012-08-04 16:03:01 +02:00
|
|
|
if (ylims[1] < dd[1])
|
2000-04-27 22:03:57 +02:00
|
|
|
ylims[1] = dd[1];
|
|
|
|
|
}
|
|
|
|
|
|
2012-07-23 19:17:25 +02:00
|
|
|
/* XXX */
|
|
|
|
|
for (d = vecs; d; d = d->v_link2) {
|
|
|
|
|
if (d->v_flags & VF_MINGIVEN)
|
|
|
|
|
if (ylims[0] < d->v_minsignal)
|
|
|
|
|
ylims[0] = d->v_minsignal;
|
|
|
|
|
if (d->v_flags & VF_MAXGIVEN)
|
|
|
|
|
if (ylims[1] > d->v_maxsignal)
|
|
|
|
|
ylims[1] = d->v_maxsignal;
|
|
|
|
|
}
|
2000-04-27 22:03:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (xlim) {
|
2012-07-23 19:17:25 +02:00
|
|
|
xlims[0] = xlim[0];
|
|
|
|
|
xlims[1] = xlim[1];
|
2000-04-27 22:03:57 +02:00
|
|
|
} else if (oneval) {
|
|
|
|
|
xlims[0] = HUGE;
|
|
|
|
|
xlims[1] = - xlims[0];
|
|
|
|
|
for (d = vecs; d; d = d->v_link2) {
|
2012-07-23 19:17:25 +02:00
|
|
|
/* dd = ft_minmax(d, FALSE); */
|
|
|
|
|
/* With this we seek the maximum and minimum of imaginary part
|
|
|
|
|
* that will go to Y axis
|
|
|
|
|
*/
|
|
|
|
|
dd = ft_minmax(d, TRUE);
|
2000-04-27 22:03:57 +02:00
|
|
|
|
2012-08-04 16:03:01 +02:00
|
|
|
if (xlims[0] > dd[0])
|
2000-04-27 22:03:57 +02:00
|
|
|
xlims[0] = dd[0];
|
2012-08-04 16:03:01 +02:00
|
|
|
if (xlims[1] < dd[1])
|
2000-04-27 22:03:57 +02:00
|
|
|
xlims[1] = dd[1];
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
xlims[0] = HUGE;
|
|
|
|
|
xlims[1] = - xlims[0];
|
|
|
|
|
for (d = vecs; d; d = d->v_link2) {
|
|
|
|
|
dd = ft_minmax(d->v_scale, TRUE);
|
2012-08-04 16:03:01 +02:00
|
|
|
if (xlims[0] > dd[0])
|
2000-04-27 22:03:57 +02:00
|
|
|
xlims[0] = dd[0];
|
2012-08-04 16:03:01 +02:00
|
|
|
if (xlims[1] < dd[1])
|
2000-04-27 22:03:57 +02:00
|
|
|
xlims[1] = dd[1];
|
|
|
|
|
}
|
|
|
|
|
for (d = vecs; d; d = d->v_link2) {
|
|
|
|
|
if (d->v_scale->v_flags & VF_MINGIVEN)
|
|
|
|
|
if (xlims[0] < d->v_scale->v_minsignal)
|
|
|
|
|
xlims[0] = d->v_scale->v_minsignal;
|
|
|
|
|
if (d->v_scale->v_flags & VF_MAXGIVEN)
|
|
|
|
|
if (xlims[1] > d->v_scale->v_maxsignal)
|
|
|
|
|
xlims[1] = d->v_scale->v_maxsignal;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Do some coercion of the limits to make them reasonable. */
|
|
|
|
|
if ((xlims[0] == 0) && (xlims[1] == 0)) {
|
|
|
|
|
xlims[0] = -1.0;
|
|
|
|
|
xlims[1] = 1.0;
|
|
|
|
|
}
|
|
|
|
|
if ((ylims[0] == 0) && (ylims[1] == 0)) {
|
|
|
|
|
ylims[0] = -1.0;
|
|
|
|
|
ylims[1] = 1.0;
|
|
|
|
|
}
|
|
|
|
|
if (xlims[0] > xlims[1]) {
|
|
|
|
|
tt = xlims[1];
|
|
|
|
|
xlims[1] = xlims[0];
|
|
|
|
|
xlims[0] = tt;
|
|
|
|
|
}
|
|
|
|
|
if (ylims[0] > ylims[1]) {
|
|
|
|
|
tt = ylims[1];
|
|
|
|
|
ylims[1] = ylims[0];
|
|
|
|
|
ylims[0] = tt;
|
|
|
|
|
}
|
|
|
|
|
if (xlims[0] == xlims[1]) {
|
|
|
|
|
xlims[0] *= (xlims[0] > 0) ? 0.9 : 1.1;
|
|
|
|
|
xlims[1] *= (xlims[1] > 0) ? 1.1 : 0.9;
|
|
|
|
|
}
|
|
|
|
|
if (ylims[0] == ylims[1]) {
|
2012-07-23 19:17:25 +02:00
|
|
|
/* || fabs(ylims[0])/(ylims[1]-ylims[0]) > 1.0e9
|
|
|
|
|
|| fabs(ylims[1])/(ylims[1]-ylims[0]) > 1.0e9) */
|
2000-04-27 22:03:57 +02:00
|
|
|
ylims[0] *= (ylims[0] > 0) ? 0.9 : 1.1;
|
|
|
|
|
ylims[1] *= (ylims[1] > 0) ? 1.1 : 0.9;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((xlims[0] <= 0.0) && ((gtype == GRID_XLOG) ||
|
2012-07-23 19:17:25 +02:00
|
|
|
(gtype == GRID_LOGLOG))) {
|
2012-08-03 20:42:37 +02:00
|
|
|
fprintf(cp_err, "Error: X values must be > 0 for log scale\n");
|
2003-07-23 21:36:39 +02:00
|
|
|
goto quit;
|
2000-04-27 22:03:57 +02:00
|
|
|
}
|
|
|
|
|
if ((ylims[0] <= 0.0) && ((gtype == GRID_YLOG) ||
|
2012-07-23 19:17:25 +02:00
|
|
|
(gtype == GRID_LOGLOG))) {
|
2012-08-03 20:42:37 +02:00
|
|
|
fprintf(cp_err, "Error: Y values must be > 0 for log scale\n");
|
2003-07-23 21:36:39 +02:00
|
|
|
goto quit;
|
2000-04-27 22:03:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Fix the plot limits for smith and polar grids. */
|
|
|
|
|
if ((!xlim || !ylim) && (gtype == GRID_POLAR)) {
|
2012-08-04 16:04:00 +02:00
|
|
|
double mx, my, rad;
|
2000-04-27 22:03:57 +02:00
|
|
|
/* (0,0) must be in the center of the screen. */
|
2012-08-04 16:03:52 +02:00
|
|
|
mx = (fabs(xlims[0]) > fabs(xlims[1])) ? fabs(xlims[0]) : fabs(xlims[1]);
|
|
|
|
|
my = (fabs(ylims[0]) > fabs(ylims[1])) ? fabs(ylims[0]) : fabs(ylims[1]);
|
2012-07-23 19:17:25 +02:00
|
|
|
/* rad = (mx > my) ? mx : my; */
|
|
|
|
|
/* AM.Roldán
|
|
|
|
|
* Change this reason that this was discussed, as in the case of 1 + i want to plot point
|
|
|
|
|
* is outside the drawing area so I'll stay as the maximum size of the hypotenuse of
|
|
|
|
|
* the complex value
|
|
|
|
|
*/
|
2009-01-18 17:37:05 +01:00
|
|
|
rad = sqrt(mx * mx + my * my);
|
2000-04-27 22:03:57 +02:00
|
|
|
xlims[0] = - rad;
|
|
|
|
|
xlims[1] = rad;
|
|
|
|
|
ylims[0] = - rad;
|
|
|
|
|
ylims[1] = rad;
|
|
|
|
|
} else if ((!xlim || !ylim) && (gtype == GRID_SMITH
|
2012-07-23 19:17:25 +02:00
|
|
|
|| gtype == GRID_SMITHGRID))
|
2000-04-27 22:03:57 +02:00
|
|
|
{
|
|
|
|
|
xlims[0] = -1.0;
|
|
|
|
|
xlims[1] = 1.0;
|
|
|
|
|
ylims[0] = -1.0;
|
|
|
|
|
ylims[1] = 1.0;
|
|
|
|
|
}
|
|
|
|
|
|
2012-08-04 19:09:13 +02:00
|
|
|
if(xlim)
|
|
|
|
|
tfree(xlim);
|
|
|
|
|
if(ylim)
|
|
|
|
|
tfree(ylim);
|
|
|
|
|
|
2000-04-27 22:03:57 +02:00
|
|
|
/* We don't want to try to deal with smith plots for asciiplot. */
|
|
|
|
|
if (devname && eq(devname, "lpr")) {
|
|
|
|
|
/* check if we should (can) linearize */
|
2012-08-04 16:02:49 +02:00
|
|
|
if (ft_curckt && ft_curckt->ci_ckt &&
|
|
|
|
|
(strcmp(ft_curckt->ci_name, plot_cur->pl_title) == 0) &&
|
|
|
|
|
if_tranparams(ft_curckt, &tstart, &tstop, &tstep) &&
|
|
|
|
|
((tstop - tstart) * tstep > 0.0) &&
|
|
|
|
|
((tstop - tstart) >= tstep) &&
|
|
|
|
|
plot_cur && plot_cur->pl_dvecs &&
|
|
|
|
|
plot_cur->pl_scale &&
|
|
|
|
|
isreal(plot_cur->pl_scale) &&
|
|
|
|
|
ciprefix("tran", plot_cur->pl_typename))
|
|
|
|
|
{
|
2012-08-04 16:04:00 +02:00
|
|
|
int newlen = (int)((tstop - tstart) / tstep + 1.5);
|
2012-07-23 19:17:25 +02:00
|
|
|
|
2012-08-04 16:04:00 +02:00
|
|
|
double *newscale = TMALLOC(double, newlen);
|
|
|
|
|
|
|
|
|
|
struct dvec *newv_scale = alloc(struct dvec);
|
|
|
|
|
struct dvec *v;
|
2012-07-23 19:17:25 +02:00
|
|
|
|
|
|
|
|
newv_scale->v_flags = vecs->v_scale->v_flags;
|
|
|
|
|
newv_scale->v_type = vecs->v_scale->v_type;
|
|
|
|
|
newv_scale->v_gridtype = vecs->v_scale->v_gridtype;
|
|
|
|
|
newv_scale->v_length = newlen;
|
|
|
|
|
newv_scale->v_name = copy(vecs->v_scale->v_name);
|
|
|
|
|
newv_scale->v_realdata = newscale;
|
|
|
|
|
|
|
|
|
|
for (i = 0, ttime = tstart; i < newlen; i++, ttime += tstep)
|
|
|
|
|
newscale[i] = ttime;
|
|
|
|
|
|
|
|
|
|
for (v = vecs; v; v= v->v_link2) {
|
2012-08-04 16:04:00 +02:00
|
|
|
double *newdata = TMALLOC(double, newlen);
|
2012-07-23 19:17:25 +02:00
|
|
|
|
|
|
|
|
if (!ft_interpolate(v->v_realdata, newdata,
|
|
|
|
|
v->v_scale->v_realdata, v->v_scale->v_length,
|
|
|
|
|
newscale, newlen, 1)) {
|
2012-08-03 20:42:37 +02:00
|
|
|
fprintf(cp_err, "Error: can't interpolate %s\n", v->v_name);
|
2012-07-23 19:17:25 +02:00
|
|
|
goto quit;
|
|
|
|
|
}
|
2000-04-27 22:03:57 +02:00
|
|
|
|
2012-07-23 19:17:25 +02:00
|
|
|
tfree(v->v_realdata);
|
|
|
|
|
v->v_realdata = newdata;
|
2000-04-27 22:03:57 +02:00
|
|
|
|
2012-07-23 19:17:25 +02:00
|
|
|
/* Why go to all this trouble if agraf ignores it? */
|
|
|
|
|
nointerp = TRUE;
|
|
|
|
|
}
|
2000-04-27 22:03:57 +02:00
|
|
|
|
2012-07-23 19:17:25 +02:00
|
|
|
vecs->v_scale = newv_scale;
|
2000-04-27 22:03:57 +02:00
|
|
|
|
|
|
|
|
}
|
2012-08-04 16:03:52 +02:00
|
|
|
ft_agraf(xlims, ylims,
|
|
|
|
|
vecs->v_scale, vecs->v_plot, vecs,
|
|
|
|
|
xdelta ? *xdelta : 0.0,
|
|
|
|
|
ydelta ? *ydelta : 0.0,
|
2012-07-23 19:17:25 +02:00
|
|
|
((gtype == GRID_XLOG) || (gtype == GRID_LOGLOG)),
|
|
|
|
|
((gtype == GRID_YLOG) || (gtype == GRID_LOGLOG)),
|
|
|
|
|
nointerp);
|
2003-07-23 21:36:39 +02:00
|
|
|
rtn = TRUE;
|
2012-07-23 19:17:25 +02:00
|
|
|
goto quit;
|
2000-04-27 22:03:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* See if there is one type we can give for the y scale... */
|
|
|
|
|
for (j = vecs->v_type, d = vecs->v_link2; d; d = d->v_link2)
|
|
|
|
|
if (d->v_type != j) {
|
|
|
|
|
j = SV_NOTYPE;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2008-08-21 12:34:29 +02:00
|
|
|
#ifndef X_DISPLAY_MISSING
|
2000-04-27 22:03:57 +02:00
|
|
|
if (devname && eq(devname, "xgraph")) {
|
2012-07-23 19:17:25 +02:00
|
|
|
/* Interface to XGraph-11 Plot Program */
|
|
|
|
|
ft_xgraph(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;
|
2000-04-27 22:03:57 +02:00
|
|
|
}
|
2008-08-21 12:34:29 +02:00
|
|
|
#endif
|
2008-03-22 14:10:46 +01:00
|
|
|
|
2012-07-23 19:17:25 +02:00
|
|
|
if (devname && eq(devname, "gnuplot")) {
|
|
|
|
|
/* Interface to Gnuplot 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;
|
2010-02-27 22:11:30 +01:00
|
|
|
}
|
|
|
|
|
|
2012-07-23 19:17:25 +02:00
|
|
|
if (devname && eq(devname, "writesimple")) {
|
|
|
|
|
/* Interface to simple write output */
|
|
|
|
|
ft_writesimple(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;
|
2008-03-22 14:10:46 +01:00
|
|
|
}
|
|
|
|
|
|
2008-08-27 15:39:05 +02:00
|
|
|
#ifdef TCL_MODULE
|
|
|
|
|
if (devname && eq(devname, "blt")) {
|
2012-07-23 19:17:25 +02:00
|
|
|
/* Just send the pairs to Tcl/Tk */
|
2012-08-04 16:04:32 +02:00
|
|
|
for (d = vecs; d; d = d->v_link2)
|
2012-07-23 19:17:25 +02:00
|
|
|
blt_plot(d, oneval ? NULL : d->v_scale, (d == vecs) ? 1 : 0);
|
|
|
|
|
rtn = TRUE;
|
|
|
|
|
goto quit;
|
2008-08-27 15:39:05 +02:00
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2000-04-27 22:03:57 +02:00
|
|
|
for (d = vecs, i = 0; d; d = d->v_link2)
|
|
|
|
|
i++;
|
|
|
|
|
|
|
|
|
|
/* Figure out the X name and the X type. This is sort of bad... */
|
|
|
|
|
xn = vecs->v_scale->v_name;
|
|
|
|
|
xt = vecs->v_scale->v_type;
|
|
|
|
|
|
|
|
|
|
pname = plot_cur->pl_typename;
|
|
|
|
|
|
2011-04-28 17:59:36 +02:00
|
|
|
if (!gr_init(xlims, ylims, (oneval ? NULL : xn),
|
2012-08-04 16:03:52 +02:00
|
|
|
title ? title : vecs->v_plot->pl_title,
|
|
|
|
|
hcopy, i,
|
|
|
|
|
xdelta ? *xdelta : 0.0,
|
|
|
|
|
ydelta ? *ydelta : 0.0,
|
|
|
|
|
gtype, ptype, xlabel, ylabel, xt, j, pname, cline))
|
2003-07-23 21:36:39 +02:00
|
|
|
goto quit;
|
2000-04-27 22:03:57 +02:00
|
|
|
|
|
|
|
|
/* Now plot all the graphs. */
|
|
|
|
|
for (d = vecs; d; d = d->v_link2)
|
2011-04-28 17:59:36 +02:00
|
|
|
ft_graf(d, oneval ? NULL : d->v_scale, FALSE);
|
2000-04-27 22:03:57 +02:00
|
|
|
|
|
|
|
|
gr_clean();
|
|
|
|
|
|
2003-07-23 21:36:39 +02:00
|
|
|
rtn = TRUE;
|
|
|
|
|
quit:
|
|
|
|
|
free_pnode(names);
|
|
|
|
|
quit1:
|
2012-07-28 19:55:09 +02:00
|
|
|
wl_free(wl);
|
2003-07-23 21:36:39 +02:00
|
|
|
return rtn;
|
2000-04-27 22:03:57 +02:00
|
|
|
}
|