#include <../../nrnconf.h> /* /local/src/master/nrn/src/oc/axis.c,v 1.2 1999/01/04 13:04:55 hines Exp */ /* axis.c,v * Revision 1.2 1999/01/04 13:04:55 hines * fabs now from include math.h * * Revision 1.1.1.1 1994/10/12 17:22:06 hines * NEURON 3.0 distribution * * Revision 2.63 1993/11/04 15:55:48 hines * port to solaris2 (no more warnings) * * Revision 2.19 1993/02/02 10:34:03 hines * static functions declared before used * * Revision 1.9 92/10/29 09:19:17 hines * some errors in freeing objects fixed and replace usage of getarg for * non numbers. * * Revision 1.8 92/10/14 10:07:55 hines * move oc specific stuff out of axis.c and into code2.c * new argument function hoc_pgetarg checks for double pointer on stack * and returns it. * hoc_val_pointer(string) returns a pointer to the variable resulting * from parsing the string. * * Revision 1.7 92/10/09 12:13:51 hines * remove old style point process syntax * make hoc_run_expr(sym) much more general * added hoc_run_stmt(sym) as well * create them with hoc_parse_expr(char*, Symlist**) and * hoc_parse_stmt(char*, Symlist**) * * Revision 1.6 92/07/31 08:54:52 hines * following merged from hoc to oc * Stewart Jasloves contribution to axis labels. This can be invoked by * setting #define Jaslove 1. It is 0 by default. The 3rd and 6th arguments * of axis() may have a precision which specifies the number of digits * after the decimal point for axis labels. eg. 5.3 denotes 5 tic marks with * 3 digits after the decimal point for each tic label * * * Revision 1.5 92/04/15 11:22:16 hines * double hoc_run_expr(sym) returns value of expresssion in sym made by * hoc_parse_exper() * * Revision 1.4 92/04/09 12:39:52 hines * ready to add idplot usage with newgraph(), addgraph(), initgraph(), xgraph() * flushgraph(). * A facilitating function exists called * Symbol* hoc_parse_expr(char* str, Symlist** psymlist) which * return a procedure symbol which can be used as * hoc_execute(sym->u.u_proc->defn.in); * val = hoc_xpop(); * * Revision 1.3 92/03/19 08:57:01 hines * axis labels close to origin set to 0 so label not strange looking. * * Revision 1.2 91/10/18 14:39:40 hines * symbol tables now are type Symlist containing pointers to first and last * symbols. New symbols get added onto the end. * * Revision 1.1 91/10/11 11:11:28 hines * Initial revision * * Revision 4.17 91/03/18 10:38:43 hines * some builtin functions take address of varname. eg. regraph(&name) * regraph saves list of addresses for fast plotting * * Revision 4.11 91/01/23 17:54:20 hines * use emalloc * * Revision 3.99 90/09/18 13:14:31 hines * plotx() and ploty() functions added so that we can hang absolute * location stuff around a scaled point. * * Revision 3.96 90/09/04 08:30:55 hines * try to get dos and unix together again in one RCS directory * * Revision 3.93 90/08/09 09:19:21 hines * axis.c placement of labels slightly lowered to look good with FIG * * Revision 3.83 90/07/25 10:39:56 hines * almost lint free on sparc 1+ under sunos 4.1 * * Revision 3.82 90/07/25 08:51:10 hines * sun uses color in graph * * Revision 3.53 90/03/22 16:22:18 jamie * correct error with checkin * * Revision 3.47 90/03/22 15:22:18 jamie * Jamie's Additions stopwatch and settext. * * Revision 3.46 90/01/24 06:35:48 mlh * emalloc() and ecalloc() are macros which return null if out of space * and then call execerror. This ensures that pointers are set to null. * If more cleanup necessary then use hoc_Emalloc() followed by hoc_malchk() * * Revision 3.29 89/10/19 06:54:44 mlh * printing directed through plprint(string) instead * of detailed routing at each place * * Revision 3.7 89/07/13 08:20:25 mlh * stack functions involve specific types instead of Datum * * Revision 3.4 89/07/12 10:25:54 mlh * Lint free * * Revision 3.3 89/07/10 15:44:02 mlh * Lint pass1 is silent. Inst structure changed to union. * * Revision 2.0 89/07/07 16:01:42 mlh * ready to add cable stuff * */ /* version 7.1.1 12/8/88 change graph to not interact with plot. Adding graphmode(mode). */ /* version 7.1.2 12/20/88 ordinate labels not positioned correctly on laser writer because leading spaces not printed */ /* version 7.1.3 12/29/88 sometimes doesn't return to last point after flushing because call to axis from setup can destroy xsav and ysav */ /* version 7.2.1 2-jan-89 make sure graph(t) and graphmode dont try to do anything when graph list is empty. Replace onerr with static badgraph which is one when graph is empty. */ #include #include #include "hoc.h" # define CLIP 1e9 # define XS 500. # define YS 400. # define XO 100. # define YO 100. # define Ret(a) hoc_ret(); hoc_pushx(a); extern double *getarg(); extern int ifarg(); extern int color; /* This makes it easier to save and restore the 8 plot scale parameters*/ #define NPARAM 10 static double param[NPARAM] = { XO, YO, XS, YS, -1e9,-1e9,1e9,1e9,0.0,0.0 }; #define xorg param[0] #define yorg param[1] #define xscale param[2] #define yscale param[3] #define xlow param[4] #define ylow param[5] #define xhigh param[6] #define yhigh param[7] #define xsav param[8] #define ysav param[9] static double XSIZE=XS, YSIZE=YS, XORG=XO, YORG=YO; static double xstart=0., xstop=1., ystart=0., ystop=1.; static double xinc=1., yinc=1.; static double lastmode=1; static double clip=CLIP; static int grphing=0; /* flag true if multiple graphs */ static int SaveForRegraph=0; static int regraph_index; static int max_regraph_index = 1000; static int regraph_narg[1000]; static int regraph_mode[1000]; static int regraph_color[1000]; static double regraph_x[1000]; static double *regraph_y[1000]; extern double* hoc_pgetarg(); static int PLOT(); static free_graph(); static plotstream(); static plotflush(); static do_setup(); hoc_regraph() { if (regraph_index < max_regraph_index) { regraph_y[regraph_index] = hoc_pgetarg(1); regraph_index++; } Ret(1.) } static open_regraph(){ SaveForRegraph=1; regraph_index = 0; } static close_regraph() { SaveForRegraph=0; } static do_regraph() { int i; for (i=0; i= xlow && y <=yhigh && y >= ylow) { plt(mode, x, y); } else if (mode > 0) { lastmode = 1; ok = 0; } return ok; } hoc_plotx() { double val; val = xorg + *getarg(1)*xscale; Ret(val); } hoc_ploty() { double val; val = yorg + *getarg(1)*yscale; Ret(val); } # define WIDTH 10. # define HEIGHT 10. axis() { #if DOS extern int newstyle; extern unsigned text_style, text_orient, text_size; #endif int width, height; double x, y; double i, j, offset; char s[200]; double x0, y0; #define Jaslove 0 #if Jaslove /* tick mark values are printed with the precision indicated in the call to axis() from hoc. For example, if x ticks is 10.2 then the number of ticks (xinc) is 10, and the precision (xprec) is 2 decimal places. The first Sprintf() below builds the precision for the second Sprintf(), so in the above example values would essentially be output as printf("%.2f",x), in which x is the real value of the tick mark. */ char ss[6]; static double xprec=.1, yprec=.1; #endif /*Jaslove*/ if (ifarg(6)) { xstart = *getarg(1); xstop = *getarg(2); xinc = *getarg(3); ystart = *getarg(4); ystop = *getarg(5); yinc = *getarg(6); #if Jaslove xprec = xinc - floor(xinc); yprec = yinc - floor(yinc); #endif xinc = floor(xinc); yinc = floor(yinc); } else if (ifarg(4)) { XORG = *getarg(1); XSIZE = *getarg(2); YORG = *getarg(3); YSIZE = *getarg(4); } else if (ifarg(1)) { clip = *getarg(1); } xscale = XSIZE/(xstop - xstart); yscale = YSIZE/(ystop - ystart); xorg = XORG - xstart*xscale; yorg = YORG - ystart*yscale; xlow = xstop - clip*(xstop - xstart); xlow = xorg + xscale*xlow; xhigh = xstart + clip*(xstop - xstart); xhigh = xorg + xscale*xhigh; ylow = ystop - clip*(ystop - ystart); ylow = yorg + yscale*ylow; yhigh = ystart + clip*(ystop - ystart); yhigh = yorg + yscale*yhigh; if (xorg < XORG || xorg > XORG+XSIZE) x0 = XORG; else x0 = xorg; if (yorg < YORG || yorg > YORG+YSIZE) y0 = YORG; else y0 = yorg; if (!ifarg(1)) { plt(1,XORG,y0); for (x = xstart; x <= xstop+1e-10; x=x+(xstop-xstart)/xinc){ i = xorg + xscale*x; plt(2,i,y0); plt(2,i,y0+10.); plt(1,i,y0); } plt(1,x0,YORG); for (y = ystart; y <= ystop+1e-10; y = y+(ystop-ystart)/yinc){ j = yorg + yscale*y; plt(2,x0,j); plt(2,x0+10.,j); plt(1,x0,j); } #if DOS if (newstyle) { settextstyle(text_style,text_orient,text_size); newstyle = 0; } width = textwidth("O")*1.5; height = textheight("O"); #else width = WIDTH; height = HEIGHT; #endif #if Jaslove Sprintf(ss, "%%%.1ff", xprec); #endif for (x = xstart; x <= xstop+1e-10; x=x + (xstop-xstart)/xinc){ i = xorg + xscale*x; #if Jaslove Sprintf(s, ss, x); #else if (fabs(x) < 1e-10) { x = 0.; } Sprintf(s, "%g", x); #endif offset = width*(int)strlen(s)/2; if( i == x0 && y0 != YORG ) offset = -width/2; #if DOS plt(1,i-offset,y0-height); plt(-2,0.,0.); #else plt(1,i-offset,y0-1.5*height); plt(-2,0.,0.); #endif plprint(s); } #if Jaslove Sprintf(ss, "%%%.1ff", yprec); #endif for (y = ystart; y <= ystop+1e-10; y = y+(ystop-ystart)/yinc){ #if Jaslove Sprintf(s, ss, y); #else if (fabs(y) < 1e-10) { y = 0.; } Sprintf(s, "%g", y); #endif offset = width*(int)strlen(s) + width; j = yorg + yscale*y; if ( j == y0 && x0 != XORG ) #if DOS plt(1, x0-offset, j+height); #else plt(1, x0-offset, j+2.); #endif else #if DOS plt(1,x0-offset,j+height/2); #else plt(1,x0-offset,j-6.); #endif plt(-2,0.,0.); plprint(s); } plt(-1,0.,0.); } Ret(1.); } /* prior to version 7.1.1 graph connects with the plot functions in such a way that multiple line graphs can be generated by using the plot function in the same way that one creates a single plot. graph() starts a new list of expressions and setup statements graph("expr", "setup") adds this spec to the list graph(1) executes the setup statements graph(-1) flushes remaining part of graph version 7.1.1 graph(t) accumulates a point with this abscissa for all expr in list. graphmode(1) executes setup statements graphmode(-1) flushes remaining part of graph, next graphs with start new lines graphmode(2...) flushes, but next graphs don't start new lines */ extern double hoc_run_expr(); extern Symbol* hoc_parse_expr(), *hoc_parse_stmt(); extern hoc_run_stmt(); /* local info for graph */ static int initialized; /* true if the setup statements have been executed*/ static Symlist *graph_sym_list; /*list of expressions and setup statements*/ #define MAXCNT 50 static int pcnt; /* points per plot already stored */ static int badgraph=1; /* graph data structure is no good or empty */ static double *lx; /* points to array which holds abscissa values */ typedef struct Grph { /* holds info for graphing */ struct Grph *g_next; /*next one in the queue*/ Symbol *g_sexp; /* symbol for the expression */ Symbol *g_setup; /* symbol for the setup statement */ int g_color; double g_param[NPARAM]; /* holds plot scale factors, etc. */ double g_val[MAXCNT]; /* y value buffer to plot */ } Grph; static Grph *glist_head, *glist_tail; /* access for the queue */ hoc_Graph() { Grph *g; if (ifarg(2)) { if (badgraph) { free_graph(); } badgraph = 1; /* if this is not reset at end then we had an execerror*/ initialized = pcnt = 0; if (glist_head == (Grph *)0) { lx = (double *)emalloc(sizeof(double)*MAXCNT); } g = (Grph *)emalloc(sizeof(Grph)); g->g_next = (Grph *)0; g->g_sexp = g->g_setup = (Symbol *)0; if (glist_tail != (Grph *)0) { glist_tail->g_next = g; }else{ glist_head = g; } glist_tail = g; g->g_sexp = hoc_parse_expr(gargstr(1), &graph_sym_list); g->g_setup = hoc_parse_stmt(gargstr(2), &graph_sym_list); badgraph = 0; /* successful */ grphing = 1; }else if (ifarg(1) && !badgraph) { plotstream(2,2,*getarg(1)); }else{ free_graph(); badgraph = 1; } Ret(0.); } int hoc_Graphmode() { int mode; if (!badgraph) { mode = *getarg(1); if (mode == 1) { do_setup(); } if (mode == -1) { plotflush(1); } if (mode > 1 && pcnt > 0) { plotflush(2); } } Ret(0.); } static free_graph() { Grph *g, *gnext; /* free all graph space and reinitialize */ hoc_free_list(&graph_sym_list); for (g = glist_head; g != (Grph *)0; g = gnext) { gnext = g->g_next; free((char *)g); } if (lx) { free((char *)lx); lx = (double *)0; } glist_head = glist_tail = (Grph *)0; grphing = initialized = pcnt = 0; } static plotstream(narg, mode, x) int narg, mode; double x; { Grph *g; if (narg == 1 || narg == 3) { plotflush(1); IGNORE(PLOT(narg, mode, xsav, ysav)); } if (pcnt >= MAXCNT) { plotflush(2); } if (narg == 2 || narg == 3) { lx[pcnt] = x; for (g = glist_head; g != (Grph *)0; g = g->g_next) { g->g_val[pcnt] = hoc_run_expr(g->g_sexp); } pcnt++; } } static plotflush(contin) int contin; { /* contin = 1 then flush after this will start with new points contin = 2 then it will start with last points of this flush */ int savcolor; int i, savmode; double parsav[NPARAM]; Grph *g; savmode = lastmode; if (!initialized) { do_setup(); } for (i=0; ig_next) { for (i=0; ig_param[i]; } if (color != g->g_color) { IGNORE(set_color(g->g_color)); } IGNORE(PLOT(1,1,0.,0.)); for (i=0; ig_val[i])); } if (contin == 2) { g->g_val[0] = g->g_val[pcnt-1]; } } for (i=0; i 0) { lx[0] = lx[pcnt-1]; pcnt = 1; IGNORE(PLOT(3,1,xsav,ysav)); /* last point of explicit plot */ } lastmode = savmode; if (contin == 1) { pcnt = 0; } } static do_setup() { Grph *g; double parsav[NPARAM]; int i; int savcolor; for (i=0; ig_next) { hoc_run_stmt(g->g_setup); for (i=0; ig_param[i] = param[i]; } g->g_color = color; } for (i=0; i