From fe28feae4efeb76c5532dfab094ed12b31923f08 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Sat, 18 Jul 2020 23:11:34 +0200 Subject: [PATCH] Cut out part of each vector of the current tran plot, from times cut-tstart to cut-tstop and copy these into a new tran plot. A new scale vector 'time' will be generated as well. Vectors that are shorter than the new scale vector will not be copied. --- src/frontend/commands.c | 8 +++ src/frontend/linear.c | 126 ++++++++++++++++++++++++++++++++++- src/frontend/linear.h | 1 + src/frontend/vectors.c | 63 ++++++++++++++++++ src/include/ngspice/fteext.h | 1 + 5 files changed, 198 insertions(+), 1 deletion(-) diff --git a/src/frontend/commands.c b/src/frontend/commands.c index 1beeedd3a..1bae97fd2 100644 --- a/src/frontend/commands.c +++ b/src/frontend/commands.c @@ -597,6 +597,10 @@ struct comm spcp_coms[] = { { 040000, 040000, 040000, 040000 }, E_DEFHMASK, 0, LOTS, NULL, " [ vec ... ] : Convert plot into one with linear scale." } , + { "cutout", com_cutout, FALSE, FALSE, + { 040000, 040000, 040000, 040000 }, E_DEFHMASK, 0, LOTS, + NULL, + " [ vec ... ] : Cut out portion of a vector." }, { "devhelp", com_devhelp, FALSE, FALSE, { 040000, 0400000, 040000, 040000 }, E_DEFHMASK, 0, 5 , NULL, @@ -1005,6 +1009,10 @@ struct comm nutcp_coms[] = { { 040000, 040000, 040000, 040000 }, E_DEFHMASK, 0, LOTS, NULL, " [ vec ... ] : Convert plot into one with linear scale." } , + { "cutout", com_cutout, FALSE, FALSE, + { 040000, 040000, 040000, 040000 }, E_DEFHMASK, 0, LOTS, + NULL, + " [ vec ... ] : Cut out portion of a vector." }, { "devhelp", NULL, FALSE, FALSE, { 040, 040, 040, 040 }, E_DEFHMASK, 0, 5 , NULL, diff --git a/src/frontend/linear.c b/src/frontend/linear.c index 63c622b41..98c44385f 100644 --- a/src/frontend/linear.c +++ b/src/frontend/linear.c @@ -20,7 +20,6 @@ Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group * Interpolation may be restricted to only a region of the input vector, * thus creating a cutout of the original vector. */ - void com_linearize(wordlist *wl) { @@ -129,3 +128,128 @@ com_linearize(wordlist *wl) } } } + + +/* Cut out part of tran vectors from cut-tstart to cut-tstop and copy these + into a new plot. A new scale vector 'time' will be there as well. Vectors + that are shorter than the new scale vector will not be copied. */ +void +com_cutout(wordlist* wl) +{ + double tstart, tstop; + struct plot* new, * old; + struct dvec* newtime, * v, *nv; + struct dvec* oldtime; + struct dvec* sta, *sto; + int len, i, istart, istop; + + if (!plot_cur || !plot_cur->pl_dvecs || !plot_cur->pl_scale) { + fprintf(cp_err, "Error: no vectors available\n"); + return; + } + if (!isreal(plot_cur->pl_scale)) { + fprintf(cp_err, "Error: non-real time scale for %s\n", + plot_cur->pl_typename); + return; + } + if (!ciprefix("tran", plot_cur->pl_typename)) { + fprintf(cp_err, "Error: plot must be a transient analysis\n"); + return; + } + + int length = plot_cur->pl_scale->v_length; + if (length < 1) { + fprintf(cp_err, "Error: no data in vector\n"); + return; + } + /* if this plot contains special vectors cut-tstart or cut-tstop, use these */ + sta = vec_fromplot("cut-tstart", plot_cur); + if (sta) { + tstart = sta->v_realdata[0]; + for (istart = 0; istart < length - 1; istart++) { + if (plot_cur->pl_scale->v_realdata[istart] > tstart) { +// istart--; + break; + } + } + } + else { + tstart = plot_cur->pl_scale->v_realdata[0]; + istart = 0; + } + sto = vec_fromplot("cut-tstop", plot_cur); + /* return if neither start nor stop are given */ + if (!sta && !sto) + return; + if (sto) { + tstop = sto->v_realdata[0]; + for (istop = 0; istop < length - 1; istop++) { + if (plot_cur->pl_scale->v_realdata[istop] > tstop) + break; + } + } + else { + tstop = plot_cur->pl_scale->v_realdata[length - 1]; + istop = length - 1; + } + + + /* finally check if tstart, tstop, istart and istop are reasonable */ + if (((tstop - tstart) <= 0.0) || ((istop - istart) <= 0)) { + fprintf(cp_err, + "Error: bad parameters -- start = %G, stop = %G\n", + tstart, tstop); + return; + } + + /* create a new plot */ + old = plot_cur; + oldtime = old->pl_scale; + new = plot_alloc("transient"); + new->pl_name = tprintf("%s (cut out)", old->pl_name); + new->pl_title = copy(old->pl_title); + new->pl_date = copy(old->pl_date); + new->pl_next = plot_list; + plot_new(new); + plot_setcur(new->pl_typename); + plot_list = new; + + /* copy a new scale vector (time) */ + len = istop - istart; + newtime = dvec_alloc(copy(oldtime->v_name), + oldtime->v_type, + oldtime->v_flags | VF_PERMANENT, + len, NULL); + + newtime->v_plot = new; + for (i = 0; i < len; i++) + newtime->v_realdata[i] = oldtime->v_realdata[istart + i]; + new->pl_scale = new->pl_dvecs = newtime; + + /* copy the vectors from tstart to tstop */ + if (wl) { + while (wl) { + v = vec_fromplot(wl->wl_word, old); + if (!v) { + fprintf(cp_err, "Error: no such vector %s\n", + wl->wl_word); + wl = wl->wl_next; + continue; + } + nv = copycut(v, newtime, istart, istop); + vec_new(nv); + wl = wl->wl_next; + } + } + else { + for (v = old->pl_dvecs; v; v = v->v_next) { + if (v == old->pl_scale) + continue; + /* Don't copy vectors that are too short */ + if (v->v_length < istop) + continue; + nv = copycut(v, newtime, istart, istop); + vec_new(nv); + } + } +} diff --git a/src/frontend/linear.h b/src/frontend/linear.h index 970dc87ac..d1f731721 100644 --- a/src/frontend/linear.h +++ b/src/frontend/linear.h @@ -7,6 +7,7 @@ #define ngspice_LINEAR_H void com_linearize(wordlist *wl); +void com_cutout(wordlist *wl); #endif diff --git a/src/frontend/vectors.c b/src/frontend/vectors.c index 47460b47d..18d3b2161 100644 --- a/src/frontend/vectors.c +++ b/src/frontend/vectors.c @@ -1347,3 +1347,66 @@ static bool plot_prefix(const char *pre, const char *str) else return (TRUE); } + +struct dvec* +copycut(struct dvec* v, struct dvec* newscalevec, int istart, int istop) +{ + struct dvec* nv; + int i; + int len = istop - istart; + + if (!v) { + return (struct dvec*)NULL; + } + + /* Make a copy with the VF_PERMANENT bit cleared in v_flags */ + nv = dvec_alloc(copy(v->v_name), + v->v_type, + v->v_flags,// & ~VF_PERMANENT, + len, NULL); + + /* Copy the data to the new vector */ + if (isreal(v)) { + for (i = 0; i < len; i++) { + nv->v_realdata[i] = v->v_realdata[istart + i]; + } + } + else { + for (i = 0; i < len; i++) { + nv->v_compdata[i] = v->v_compdata[istart + i]; + } + } + + nv->v_minsignal = v->v_minsignal; + nv->v_maxsignal = v->v_maxsignal; + nv->v_gridtype = v->v_gridtype; + nv->v_plottype = v->v_plottype; + + /* Modified to copy the rlength of origin to destination vecor + * instead of always putting it to 0. + * As when it comes to make a print does not leave M1 @ @ M1 = 0.0, + * to do so in the event that rlength = 0 not print anything on screen + * nv-> v_rlength = 0; + * Default -> v_rlength = 0 and only if you come from a print or M1 @ + * @ M1 [all] rlength = 1, after control is one of + * if (v-> v_rlength == 0) com_print (wordlist * wl) + */ + nv->v_rlength = v->v_rlength; + + nv->v_outindex = 0; /*XXX???*/ + nv->v_linestyle = 0; /*XXX???*/ + nv->v_color = 0; /*XXX???*/ + nv->v_defcolor = v->v_defcolor; + nv->v_numdims = v->v_numdims; + + /* Copy defined dimensions */ + (void)memcpy(nv->v_dims, v->v_dims, + (size_t)v->v_numdims * sizeof * v->v_dims); + + nv->v_plot = newscalevec->v_plot; + nv->v_next = NULL; + nv->v_link2 = NULL; + nv->v_scale = newscalevec; + + return nv; +} /* end of function copycut */ diff --git a/src/include/ngspice/fteext.h b/src/include/ngspice/fteext.h index 70cea638c..660be5754 100644 --- a/src/include/ngspice/fteext.h +++ b/src/include/ngspice/fteext.h @@ -366,6 +366,7 @@ extern struct plot *get_plot(const char *name); extern void plot_new(struct plot *pl); extern char *vec_basename(struct dvec *v); extern void vec_transpose(struct dvec *v); +extern struct dvec* copycut(struct dvec* ov, struct dvec* newscalevec, int istart, int istop); /* main.c */ extern bool ft_intrpt;