/* NIGHTFALL Light Curve Synthesis Program */ /* Copyright (C) 1998 Rainer Wichmann */ /* */ /* This program is free software; you can redistribute it */ /* and/or modify */ /* it under the terms of the GNU General Public License as */ /* published by */ /* the Free Software Foundation; either version 2 of the License, or */ /* (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* + this is a library of functions that somehow emulate the + PGPLOT calls in 'nightfall'. Some of the emulated + functions are just dirty hacks. Display of images + is not possible with GNUPLOT + + the different plotting 'philosophy' of GNUPLOT and PGPLOT + adds considerable complications + + based on demo code in the gnuplot faq + for calling gnuplot from C using named pipes + pipes are opened in /tmp directory + + animated mode requires three separate data pipes to run + + for details about the arguments of these subroutines, see + the PGPLOT manual */ /* ========================================================== * * 'set no...' is deprecated syntax, new syntax is 'unset ...' * * ========================================================== */ #include #include #ifdef HAVE_SYS_TIMERS_H #include #endif #include #include #include #include #include "Light.h" #ifdef HAVE_UNISTD_H #include #include #endif #include #ifdef _WITH_GNUPLOT static struct timespec sleep_req = { 0, 20000000 }; static struct timespec sleep_rem; static int gnuSubpageflag = OFF; /* flag for multiplot */ static int gnuPageX = 0; /* # of pages in x (multiplot) */ static int gnuPageY = 0; /* # of pages in y (multiplot) */ static int gnuPageXn = 0; /* actual page in x (multiplot) */ static int gnuPageYn = 0; /* actual page in y (multiplot) */ static float gnuLw = 1.; /* linewidth */ static float gnuPs = 1.; /* pointsize */ static int gnuLt = 1; /* linetype */ static float gnuOrig_x, gnuOrig_y; /* origin location */ static float gnuSizex, gnuSizey; /* page size */ static float gnuMOrig_x, gnuMOrig_y; /* origin location / bookkeping */ static float gnuMSizex, gnuMSizey; /* page size / bookkeping */ static char gnuCommands[1024]; /* command pipe */ static char gnuData1[1024]; /* data pipe1 */ static char gnuData2[1024]; /* data pipe2 */ static char gnuData3[1024]; /* data pipe3 */ static char gnuData4[1024]; /* data pipe4 */ static FILE *gnustr, *gnudat1, *gnudat2; /* pipe filehandles */ static FILE *gnudat3, *gnudat4; /* pipe filehandles */ static pid_t childPid; /* PID of forked process */ static pid_t processGroup; /* PID of forked process */ static char sig_msg[64]; /* signal name */ /****************************************************************** @package nightfall @author Rainer Wichmann (rwichman@lsw.uni-heidelberg.de) @version 1.0 @short Return signal name @param (void) @return (void) @heading Signal Handling *******************************************************************/ char * nf_signame(int signum) { switch (signum) { #ifdef SIGHUP case SIGHUP: return "Hangup"; #endif #ifdef SIGINT case SIGINT: return "Interrupt"; #endif #ifdef SIGQUIT case SIGQUIT: return "Quit"; #endif #ifdef SIGILL case SIGILL: return "Illegal instruction"; #endif #ifdef SIGTRAP case SIGTRAP: return "Trace/breakpoint trap"; #endif #ifdef SIGABRT case SIGABRT: return "IOT trap/Abort"; #endif #ifdef SIGBUS case SIGBUS: return "Bus error"; #endif #ifdef SIGFPE case SIGFPE: return "Floating point exception"; #endif #ifdef SIGKILL case SIGKILL: return "Killed"; #endif #ifdef SIGUSR1 case SIGUSR1: return "User defined signal 1"; #endif #ifdef SIGSEGV case SIGSEGV: return "Segmentation fault"; #endif #ifdef SIGUSR2 case SIGUSR2: return "User defined signal 2"; #endif #ifdef SIGPIPE case SIGPIPE: return "Broken pipe"; #endif #ifdef SIGALRM case SIGALRM: return "Alarm clock"; #endif #ifdef SIGTERM case SIGTERM: return "Terminated"; #endif #ifdef SIGSTKFLT case SIGSTKFLT: return "Stack fault"; #endif #ifdef SIGCHLD case SIGCHLD: return "Child exited"; #endif #ifdef SIGCONT case SIGCONT: return "Continued"; #endif #ifdef SIGSTOP case SIGSTOP: return "Stopped (signal)"; #endif #ifdef SIGTSTP case SIGTSTP: return "Stopped"; #endif #ifdef SIGTTIN case SIGTTIN: return "Stopped (tty input)"; #endif #ifdef SIGTTOU case SIGTTOU: return "Stopped (tty output)"; #endif #ifdef SIGURG case SIGURG: return "Urgent condition"; #endif #ifdef SIGXCPU case SIGXCPU: return "CPU time limit exceeded"; #endif #ifdef SIGXFSZ case SIGXFSZ: return "File size limit exceeded"; #endif #ifdef SIGVTALRM case SIGVTALRM: return "Virtual time alarm"; #endif #ifdef SIGPROF case SIGPROF: return "Profile signal"; #endif #ifdef SIGWINCH case SIGWINCH: return "Window size changed"; #endif #ifdef SIGIO case SIGIO: return "Possible I/O"; #endif #ifdef SIGPWR case SIGPWR: return "Power failure"; #endif #ifdef SIGUNUSED case SIGUNUSED: return "Unused signal"; #endif } sprintf (sig_msg, "unknown signal (%8d)", signum); return sig_msg; } /****************************************************************** @package nightfall @author Rainer Wichmann (rwichman@lsw.uni-heidelberg.de) @version 1.0 @short Handle signals, cleanup FIFO's on abnormal termination @param (void) @return (void) @heading Signal Handling *******************************************************************/ void gnu_sighandler (int signal) { if (Flags.plotOpened == ON) { Flags.plotOpened = OFF; cpgend(); } #ifdef HAVE_GNOME if (Flags.interactive == ON) doQuit(); #endif /* is it safe to use fprintf() in a signal handler ? fprintf(stderr,"** SIGHANDLE **: caught signal: %s ...\n", nf_signame(signal)); fprintf(stderr," ... cleanup and exit to system \n"); */ fputs("** SIGHANDLE **: caught signal: ", stderr); fputs(nf_signame(signal), stderr); fputs("\n", stderr); NF_MPI_Abort(); exit(EXIT_FAILURE); } /****************************************************************** @package nightfall @author Rainer Wichmann (rwichman@lsw.uni-heidelberg.de) @version 1.0 @short Additional function required at plot start @param (void) @return (void) @heading PGPLOT emulation *******************************************************************/ void gnu_end() { fprintf(gnustr, "unset multiplot\n"); fflush(gnustr); return; } /****************************************************************** @package nightfall @author Rainer Wichmann (rwichman@lsw.uni-heidelberg.de) @version 1.0 @short Additional function required at temorary plot end @param (void) @return (void) @heading PGPLOT emulation *******************************************************************/ void gnu_start() { fprintf(gnustr, "set multiplot\n"); fflush(gnustr); return; } /****************************************************************** @package nightfall @author Rainer Wichmann (rwichman@lsw.uni-heidelberg.de) @version 1.0 @short Image display @param (see PGPLOT manual) @return (void) @heading PGPLOT emulation *******************************************************************/ void cpgimag(const float *a, int idim, int jdim, int i1, int i2, int j1, int j2, float a1, float a2, const float *tr) { /* there is no such resource in GNUPLOT */ return; } /****************************************************************** @package nightfall @author Rainer Wichmann (rwichman@lsw.uni-heidelberg.de) @version 1.0 @short Contour plotting @param (see PGPLOT manual) @return (void) @heading PGPLOT emulation *******************************************************************/ void cpgcont(const float *a, int xdim, int ydim, int x1, int x2, int y1, int y2, const float *c, int nc, const float *tr) { register unsigned int i, j; /* loop variables */ register unsigned int l; /* loop variables */ float xfactor = 60.0; /* scale factor x */ float yfactor = 60.0; /* scale factor y */ float xstart = -1.0; /* start x */ float ystart = -1.0; /* start y */ if (xdim == _CHI_SCANS_) { xfactor = 1.0/tr[1]; yfactor = 1.0/tr[5]; xstart = tr[0] + 0.5*tr[1]; ystart = tr[3] + 0.5*tr[5]; } fprintf(gnustr,"unset surface\n"); fprintf(gnustr,"set contour\n"); fprintf(gnustr,"set view 0., 0., 1.5\n"); /* put commands in command pipe and data in data pipe */ fprintf(gnustr,"set cntrparam cubicspline\n"); fprintf(gnustr,"set cntrparam levels discrete %f, %f, %f, %f, %f\n", *(c), *(c + 1), *(c + 2), *(c + 3), *(c + 4)); fprintf(gnustr,"clear\n"); fprintf(gnustr,"splot '%s' index 0 notitle w lines \n", gnuData4); fflush(gnustr); /* this fopen must occur AFTER gnuplot has already */ /* tried to open the pipe for reading */ gnudat4 = fopen(gnuData4, "w"); if(!gnudat4) perror (_("could not open pipe")); l = (xdim/10)*10; for (i=0; i < ydim; ++i) { /* some dynamic loop unrolling */ j= 0; while (j < l) { fprintf(gnudat4,"%7.4f %7.4f %7.4f\n", j/xfactor + xstart, i/yfactor + ystart, MAX(-99., *(a + xdim*i + j)) ); fprintf(gnudat4,"%7.4f %7.4f %7.4f\n", (1+j)/xfactor + xstart, i/yfactor + ystart, MAX(-99., *(a + xdim*i + j + 1)) ); fprintf(gnudat4,"%7.4f %7.4f %7.4f\n", (2+j)/xfactor + xstart, i/yfactor + ystart, MAX(-99., *(a + xdim*i + j + 2)) ); fprintf(gnudat4,"%7.4f %7.4f %7.4f\n", (3+j)/xfactor + xstart, i/yfactor + ystart, MAX(-99., *(a + xdim*i + j + 3)) ); fprintf(gnudat4,"%7.4f %7.4f %7.4f\n", (4+j)/xfactor + xstart, i/yfactor + ystart, MAX(-99., *(a + xdim*i + j + 4)) ); fprintf(gnudat4,"%7.4f %7.4f %7.4f\n", (5+j)/xfactor + xstart, i/yfactor + ystart, MAX(-99., *(a + xdim*i + j + 5)) ); fprintf(gnudat4,"%7.4f %7.4f %7.4f\n", (6+j)/xfactor + xstart, i/yfactor + ystart, MAX(-99., *(a + xdim*i + j + 6)) ); fprintf(gnudat4,"%7.4f %7.4f %7.4f\n", (7+j)/xfactor + xstart, i/yfactor + ystart, MAX(-99., *(a + xdim*i + j + 7)) ); fprintf(gnudat4,"%7.4f %7.4f %7.4f\n", (8+j)/xfactor + xstart, i/yfactor + ystart, MAX(-99., *(a + xdim*i + j + 8)) ); fprintf(gnudat4,"%7.4f %7.4f %7.4f\n", (9+j)/xfactor + xstart, i/yfactor + ystart, MAX(-99., *(a + xdim*i + j + 9)) ); /********************************************* fprintf(stderr,"%7.4f %7.4f %7.4f\n", j/xfactor + xstart, i/yfactor + ystart, *(a + xdim*i + j)); fprintf(stderr,"%7.4f %7.4f %7.4f\n", (1+j)/xfactor + xstart, i/yfactor + ystart, *(a + xdim*i + j + 1)); fprintf(stderr,"%7.4f %7.4f %7.4f\n", (2+j)/xfactor + xstart, i/yfactor + ystart, *(a + xdim*i + j + 2)); fprintf(stderr,"%7.4f %7.4f %7.4f\n", (3+j)/xfactor + xstart, i/yfactor + ystart, *(a + xdim*i + j + 3)); fprintf(stderr,"%7.4f %7.4f %7.4f\n", (4+j)/xfactor + xstart, i/yfactor + ystart, *(a + xdim*i + j + 4)); fprintf(stderr,"%7.4f %7.4f %7.4f\n", (5+j)/xfactor + xstart, i/yfactor + ystart, *(a + xdim*i + j + 5)); fprintf(stderr,"%7.4f %7.4f %7.4f\n", (6+j)/xfactor + xstart, i/yfactor + ystart, *(a + xdim*i + j + 6)); fprintf(stderr,"%7.4f %7.4f %7.4f\n", (7+j)/xfactor + xstart, i/yfactor + ystart, *(a + xdim*i + j + 7)); fprintf(stderr,"%7.4f %7.4f %7.4f\n", (8+j)/xfactor + xstart, i/yfactor + ystart, *(a + xdim*i + j + 8)); fprintf(stderr,"%7.4f %7.4f %7.4f\n", (9+j)/xfactor + xstart, i/yfactor + ystart, *(a + xdim*i + j + 9)); ********************************************/ j = j + 10; } if (j < xdim) { switch (xdim -j) { case 9: fprintf(gnudat4,"%7.4f %7.4f %7.4f\n", j/xfactor + xstart, i/yfactor + ystart, MAX(-99., *(a + xdim*i + j))); ++j; case 8: fprintf(gnudat4,"%7.4f %7.4f %7.4f\n", j/xfactor + xstart, i/yfactor + ystart, MAX(-99., *(a + xdim*i + j))); ++j; case 7: fprintf(gnudat4,"%7.4f %7.4f %7.4f\n", j/xfactor + xstart, i/yfactor + ystart, MAX(-99., *(a + xdim*i + j))); ++j; case 6: fprintf(gnudat4,"%7.4f %7.4f %7.4f\n", j/xfactor + xstart, i/yfactor + ystart, MAX(-99., *(a + xdim*i + j))); ++j; case 5: fprintf(gnudat4,"%7.4f %7.4f %7.4f\n", j/xfactor + xstart, i/yfactor + ystart, MAX(-99., *(a + xdim*i + j))); ++j; case 4: fprintf(gnudat4,"%7.4f %7.4f %7.4f\n", j/xfactor + xstart, i/yfactor + ystart, MAX(-99., *(a + xdim*i + j))); ++j; case 3: fprintf(gnudat4,"%7.4f %7.4f %7.4f\n", j/xfactor + xstart, i/yfactor + ystart, MAX(-99., *(a + xdim*i + j))); ++j; case 2: fprintf(gnudat4,"%7.4f %7.4f %7.4f\n", j/xfactor + xstart, i/yfactor + ystart, MAX(-99., *(a + xdim*i + j))); ++j; case 1: fprintf(gnudat4,"%7.4f %7.4f %7.4f\n", j/xfactor + xstart, i/yfactor + ystart, MAX(-99., *(a + xdim*i + j))); ++j; default: break; } } fprintf(gnudat4," \n"); } fclose(gnudat4); /* to avoid 'broken pipe' errors */ nanosleep (&sleep_req, &sleep_rem); return; } /****************************************************************** @package nightfall @author Rainer Wichmann (rwichman@lsw.uni-heidelberg.de) @version 1.0 @short Image display - wedge @param (see PGPLOT manual) @return (void) @heading PGPLOT emulation *******************************************************************/ void cpgwedg(const char *side, float disp, float width, float fg, float bg, const char *label) { /* there is no such resource in GNUPLOT */ return; } /****************************************************************** @package nightfall @author Rainer Wichmann (rwichman@lsw.uni-heidelberg.de) @version 1.0 @short Set line size @param (see PGPLOT manual) @return (void) @heading PGPLOT emulation *******************************************************************/ void cpgsls(int fnt) { /* not required */ return; } /****************************************************************** @package nightfall @author Rainer Wichmann (rwichman@lsw.uni-heidelberg.de) @version 1.0 @short Set character size @param (see PGPLOT manual) @return (void) @heading PGPLOT emulation *******************************************************************/ void cpgscf(int fnt) { /* not required */ return; } /****************************************************************** @package nightfall @author Rainer Wichmann (rwichman@lsw.uni-heidelberg.de) @version 1.0 @short Viewport size default @param (see PGPLOT manual) @return (void) @heading PGPLOT emulation *******************************************************************/ void cpgvstd() { cpgsvp(0.1, 0.9, 0.1, 0.9); return; } /****************************************************************** @package nightfall @author Rainer Wichmann (rwichman@lsw.uni-heidelberg.de) @version 1.0 @short Text label @param (see PGPLOT manual) @return (void) @heading PGPLOT emulation *******************************************************************/ void cpgtext(float xpos, float ypos, const char *label) { fprintf(gnustr,"set label '%s' at first %f, %f \n", label, xpos, ypos ); fflush(gnustr); return; } /****************************************************************** @package nightfall @author Rainer Wichmann (rwichman@lsw.uni-heidelberg.de) @version 1.0 @short Set title and axis labels @param (see PGPLOT manual) @return (void) @heading PGPLOT emulation *******************************************************************/ void cpglab(const char *xlbl, const char *ylbl, const char *toplbl) { fprintf(gnustr,"set title '%s' \n", toplbl); fprintf(gnustr,"set xlabel '%s' \n", xlbl); fprintf(gnustr,"set ylabel '%s' \n", ylbl); fflush(gnustr); return; } /****************************************************************** @package nightfall @author Rainer Wichmann (rwichman@lsw.uni-heidelberg.de) @version 1.0 @short Draw a line @param (see PGPLOT manual) @return (void) @heading PGPLOT emulation *******************************************************************/ void cpgline(int n, const float *xpts, const float *ypts) { int i; /* loop variable */ /* put commands in command pipe and data in data pipe */ fprintf(gnustr,"plot '%s' notitle w lines \n", gnuData1); fflush(gnustr); /* this fopen must occur AFTER gnuplot has already */ /* tried to open the pipe for reading */ gnudat1 = fopen(gnuData1, "w"); if(!gnudat1) perror (_("could not open pipe")); for(i = 0; i < n; ++i) { fprintf(gnudat1,"%8.5g %8.5g\n", xpts[i], ypts[i]); } fclose(gnudat1); return; } /****************************************************************** @package nightfall @author Rainer Wichmann (rwichman@lsw.uni-heidelberg.de) @version 1.0 @short Plot points @param (see PGPLOT manual) @return (void) @heading PGPLOT emulation *******************************************************************/ void cpgpt(int n, const float *xpts, const float *ypts, int npt) { int i; /* loop variable */ /* put commands in command pipe and data in data pipe */ fprintf(gnustr,"plot '%s' notitle w points ps %f \n", gnuData3, gnuPs); fflush(gnustr); /* this fopen must occur AFTER gnuplot has already */ /* tried to open the pipe for reading */ gnudat3 = fopen(gnuData3, "w"); if(!gnudat3) perror (_("could not open pipe")); for(i = 0; i < n; ++i) fprintf(gnudat3,"%8.5g %8.5g\n", xpts[i], ypts[i]); fclose(gnudat3); return; } /****************************************************************** @package nightfall @author Rainer Wichmann (rwichman@lsw.uni-heidelberg.de) @version 1.0 @short Plot points (two datasets) @tip not in PGPLOT @param (see PGPLOT manual) @return (void) @heading PGPLOT emulation *******************************************************************/ void cpgpt2(int n, int n2, const float *x1pts, const float *y1pts, const float *x2pts, const float *y2pts) { int i; /* loop variable */ /* put commands in command pipe and data in data pipe */ fprintf(gnustr, "plot '%s' notitle w points pt 0, '%s' notitle w points pt 0\n", gnuData1, gnuData2); fflush(gnustr); /* this fopen must occur AFTER gnuplot has already */ /* tried to open the pipe for reading */ gnudat1 = fopen(gnuData1, "w"); if(!gnudat1) perror (_("could not open pipe")); for(i = 0; i < n; ++i) { fprintf(gnudat1,"%8.5g %8.5g\n", x1pts[i], y1pts[i]); } fclose(gnudat1); gnudat2 = fopen(gnuData2, "w"); if(!gnudat2) perror (_("could not open pipe")); for(i = 0; i < n2; ++i) { fprintf(gnudat2,"%8.5g %8.5g\n", x2pts[i], y2pts[i]); } fclose(gnudat2); return; } /****************************************************************** @package nightfall @author Rainer Wichmann (rwichman@lsw.uni-heidelberg.de) @version 1.0 @short Draw lines (two datasets) @tip not in PGPLOT @param (see PGPLOT manual) @return (void) @heading PGPLOT emulation *******************************************************************/ void cpgline2(int n, int n2, const float *x1pts, const float *y1pts, const float *x2pts, const float *y2pts) { int i; /* loop variable */ /* put commands in command pipe and data in data pipe */ fprintf(gnustr, "plot '%s' index 0:1 notitle w lines lt 2\n", gnuData2); fflush(gnustr); /* this fopen must occur AFTER gnuplot has already */ /* tried to open the pipe for reading */ gnudat2 = fopen(gnuData2, "w"); if(!gnudat2) perror (_("could not open pipe")); for(i = 0; i < n; ++i) { fprintf(gnudat2,"%8.5g %8.5g\n", x1pts[i], y1pts[i]); } fprintf(gnudat2," \n"); fprintf(gnudat2," \n"); for(i = 0; i < n2; ++i) { fprintf(gnudat2,"%8.5g %8.5g\n", x2pts[i], y2pts[i]); } fclose(gnudat2); return; } /****************************************************************** @package nightfall @author Rainer Wichmann (rwichman@lsw.uni-heidelberg.de) @version 1.0 @short Draw points + line (three datasets) @tip not in PGPLOT @param (see PGPLOT manual) @return (void) @heading PGPLOT emulation *******************************************************************/ void cpgline2pt(int n, int n2, int n3, const float *x1pts, const float *y1pts, const float *x2pts, const float *y2pts, const float *x3pts, const float *y3pts) { int i; /* loop variable */ /* put commands in command pipe and data in data pipe */ /* ------------- POINTS FIRST, LINES SECOND --------------- */ fprintf(gnustr, "plot '%s' notitle w points ps %f, '%s' index 0:1 notitle w lines lt 2\n", gnuData1, gnuPs, gnuData2); fflush(gnustr); /* this fopen must occur AFTER gnuplot has already */ /* tried to open the pipe for reading */ gnudat1 = fopen(gnuData1, "w"); for(i = 0; i < n3; ++i) { fprintf(gnudat1,"%8.5g %8.5g\n", x3pts[i], y3pts[i]); } fclose(gnudat1); gnudat2 = fopen(gnuData2, "w"); if(!gnudat2) perror (_("could not open pipe")); for(i = 0; i < n; ++i) { fprintf(gnudat2,"%8.5g %8.5g\n", x1pts[i], y1pts[i]); } fprintf(gnudat2," \n"); fprintf(gnudat2," \n"); for(i = 0; i < n2; ++i) { fprintf(gnudat2,"%8.5g %8.5g\n", x2pts[i], y2pts[i]); } fclose(gnudat2); return; } /****************************************************************** @package nightfall @author Rainer Wichmann (rwichman@lsw.uni-heidelberg.de) @version 1.0 @short Draw points + line (two datasets) @tip not in PGPLOT @param (see PGPLOT manual) @return (void) @heading PGPLOT emulation *******************************************************************/ void cpglinept(int n, int n2, const float *x1pts, const float *y1pts, const float *x2pts, const float *y2pts) { int i; /* loop variable */ /* put commands in command pipe and data in data pipe */ fprintf(gnustr, "plot '%s' notitle w lines, '%s' notitle w points ps %f\n", gnuData1, gnuData2, gnuPs); fflush(gnustr); /* this fopen must occur AFTER gnuplot has already */ /* tried to open the pipe for reading */ gnudat1 = fopen(gnuData1, "w"); if(!gnudat1) perror (_("could not open pipe")); for(i = 0; i < n; ++i) { fprintf(gnudat1,"%f %f\n", x1pts[i], y1pts[i]); } fclose(gnudat1); gnudat2 = fopen(gnuData2, "w"); if(!gnudat2) perror (_("could not open pipe")); for(i = 0; i < n2; ++i) { fprintf(gnudat2,"%f %f\n", x2pts[i], y2pts[i]); } fclose(gnudat2); return; } /****************************************************************** @package nightfall @author Rainer Wichmann (rwichman@lsw.uni-heidelberg.de) @version 1.0 @short Set box type @tip only BCST, BCMST, ABCNST supported @param (see PGPLOT manual) @return (void) @heading PGPLOT emulation *******************************************************************/ void cpgbox(const char *xopt, float xtick, int nxsub, const char *yopt, float ytick, int nysub) { /* set tickmarks */ if (xtick != 0.0) fprintf(gnustr, "set xtics %10.2f \n", xtick); if (strcmp("BCMST", yopt) != 0) if (ytick != 0.0) fprintf(gnustr, "set ytics %10.2f \n", ytick); /* required: support for BCST, BCMST, ABCNST */ if (strcmp("BCST", xopt) == 0) { fprintf(gnustr, "set xtics (\"\" 0)\n"); } if (strcmp("BCST", yopt) == 0) { fprintf(gnustr, "set ytics (\"\" 0)\n"); } if (strcmp("BCNST", xopt) == 0) { fprintf(gnustr, "set xtics \n"); if (xtick != 0.0) fprintf(gnustr, "set xtics %10.5g \n", xtick); } if (strcmp("BCNST", yopt) == 0) { fprintf(gnustr, "set ytics \n"); if (ytick != 0.0) fprintf(gnustr, "set ytics %10.5g \n", ytick); } if (strcmp("BCMST", xopt) == 0) { fprintf(gnustr, "set xtics (\"\" 0)\n"); fprintf(gnustr, "set x2tics \n"); if (xtick != 0.0) fprintf(gnustr, "set x2tics %10.5g \n", xtick); } if (strcmp("BCMST", yopt) == 0) { fprintf(gnustr, "set ytics (\"\" 0)\n"); /* for some reason, range is not properly set for y2tics */ /* fprintf(gnustr, "set y2tics \n"); */ /* fprintf(gnustr, "set y2range [*:*]\n"); */ if (ytick != 0.0) /* fprintf(gnustr, "set y2tics %10.5g \n", ytick); */ fprintf(gnustr, "set ytics %10.5g \n", ytick); } if (strcmp("ABCNST", xopt) == 0) { fprintf(gnustr, "set xtics \n"); fprintf(gnustr, "set xzeroaxis \n"); } if (strcmp("ABCNST", yopt) == 0) { fprintf(gnustr, "set ytics \n"); fprintf(gnustr, "set yzeroaxis \n"); } fflush(gnustr); return; } /****************************************************************** @package nightfall @author Rainer Wichmann (rwichman@lsw.uni-heidelberg.de) @version 1.0 @short Query plot window location @tip no support for units @param (see PGPLOT manual) @return (void) @heading PGPLOT emulation *******************************************************************/ void cpgqvp(int units, float *x1, float *x2, float *y1, float *y2) { /* no support for units */ if (units != 0) { WARNING(_("PGPLOT emulation: cpgqvp has no support for units")); } else { *x1 = gnuMOrig_x; *x2 = gnuMOrig_x + gnuMSizex; *y1 = gnuMOrig_y; *y2 = gnuMOrig_y + gnuMSizey; } } /****************************************************************** @package nightfall @author Rainer Wichmann (rwichman@lsw.uni-heidelberg.de) @version 1.0 @short Text annotation @tip hardcoded locations of annotations @param (see PGPLOT manual) @return (void) @heading PGPLOT emulation *******************************************************************/ void cpgmtxt(const char *side, float disp, float coord, float fjust, const char *text) { float x = 0., y = 0.; /* the text locations */ if (strcmp("T", side) == 0) { y = 0.85; x = 0.5; } else if (strcmp("B", side) == 0) { y = 0.05; x = 0.8; } else { WARNING(_("PGPLOT emulation: cpgmtxt 'side' argument not valid")); } fprintf(gnustr, "set label \"%s\" at screen %5.2f, %5.2f center\n", text, x, y); fflush(gnustr); } /****************************************************************** @package nightfall @author Rainer Wichmann (rwichman@lsw.uni-heidelberg.de) @version 1.0 @short Set plot window with aspect ratio 1.0 @tip works in GNUPLOT only with no title @param (see PGPLOT manual) @return (void) @heading PGPLOT emulation *******************************************************************/ void cpgwnad(float xleft, float xright, float ybot, float ytop) { float xsize; /* size in x */ float ysize; /* size in y */ float max; /* max of both */ /* set plot ranges */ fprintf(gnustr, "set xrange [%10.5g:%10.5g] \n", xleft, xright ); fprintf(gnustr, "set yrange [%10.5g:%10.5g] \n", ybot, ytop ); /* calculate sizes and their maximum */ xsize = (xright - xleft)/gnuSizex; ysize = (ytop - ybot)/gnuSizey; max = MAX(xsize,ysize); /* adjust aspect */ ysize = 1.375 * (ytop - ybot)/max; xsize = (xright - xleft)/max; /* adjust aspect of subpages */ if (gnuSubpageflag == ON) { ysize = ysize/gnuPageY; xsize = xsize/gnuPageX; } /* store for bookkeeping */ gnuMSizey = ysize; gnuMSizex = xsize; /* set size */ fprintf(gnustr, "set size %5.2f, %5.2f\n", xsize, ysize ); fflush(gnustr); fflush(gnustr); return; } /****************************************************************** @package nightfall @author Rainer Wichmann (rwichman@lsw.uni-heidelberg.de) @version 1.0 @short Set plot window @param (see PGPLOT manual) @return (void) @heading PGPLOT emulation *******************************************************************/ void cpgswin(float xleft, float xright, float ybot, float ytop) { fprintf(gnustr, "set xrange [%10.5g:%10.5g] \n", xleft, xright ); fprintf(gnustr, "set yrange [%10.5g:%10.5g] \n", ybot, ytop ); fprintf(gnustr, "unset autoscale\n"); fflush(gnustr); return; } /****************************************************************** @package nightfall @author Rainer Wichmann (rwichman@lsw.uni-heidelberg.de) @version 1.0 @short Set color @tip Color is linetype in GNUPLOT @param (see PGPLOT manual) @return (void) @heading PGPLOT emulation *******************************************************************/ void cpgsci(int lw) { /* color = linetype in gnuplot */ gnuLt = lw; return; } /****************************************************************** @package nightfall @author Rainer Wichmann (rwichman@lsw.uni-heidelberg.de) @version 1.0 @short Set linewidth @param (see PGPLOT manual) @return (void) @heading PGPLOT emulation *******************************************************************/ void cpgslw(float lw) { gnuLw = lw; return; } /****************************************************************** @package nightfall @author Rainer Wichmann (rwichman@lsw.uni-heidelberg.de) @version 1.0 @short Set point size @param (see PGPLOT manual) @return (void) @heading PGPLOT emulation *******************************************************************/ void cpgsch(float lw) { gnuPs = lw; fprintf(gnustr, "set pointsize %5.2f \n", lw); fflush(gnustr); return; } /****************************************************************** @package nightfall @author Rainer Wichmann (rwichman@lsw.uni-heidelberg.de) @version 1.0 @short Set viewport @param (see PGPLOT manual) @return (void) @heading PGPLOT emulation *******************************************************************/ void cpgsvp(float xleft, float xright, float ybot, float ytop) { float xsize, ysize; /* size of viewport */ float xoff, yoff; /* offset to origin */ /* compute sizes and offset */ xoff = xleft; yoff = ybot; xsize = xright - xleft; ysize = ytop - ybot; /* store for bookkeeping */ gnuSizex = xsize; gnuSizey = ysize; /* compute size and offset to origin for subpage */ if (gnuSubpageflag == ON) { xoff = gnuOrig_x + xoff/gnuPageX; yoff = gnuOrig_y + yoff/gnuPageY; ysize = ysize/gnuPageY; xsize = xsize/gnuPageX; } /* store for bookkeeping */ gnuMSizey = ysize; gnuMSizex = xsize; gnuMOrig_y = yoff; gnuMOrig_x = xoff; /* set viewport and initialize */ fprintf(gnustr, "set title ""\n"); fprintf(gnustr, "set xlabel\n"); fprintf(gnustr, "set ylabel\n"); fprintf(gnustr, "set xrange [*:*]\n"); fprintf(gnustr, "set yrange [*:*]\n"); fprintf(gnustr, "set autoscale\n"); fprintf(gnustr, "unset xzeroaxis \n"); fprintf(gnustr, "unset yzeroaxis \n"); fprintf(gnustr, "unset y2tics \n"); fprintf(gnustr, "unset x2tics \n"); fprintf(gnustr, "unset label\n"); fprintf(gnustr, "set mxtics 5\n"); fprintf(gnustr, "set mytics 5\n"); fprintf(gnustr, "set origin %5.2f, %5.2f\n", xoff, yoff ); fprintf(gnustr, "set size %5.2f, %5.2f\n", xsize, ysize ); fflush(gnustr); return; } /****************************************************************** @package nightfall @author Rainer Wichmann (rwichman@lsw.uni-heidelberg.de) @version 1.0 @short Set viewport @param (see PGPLOT manual) @return (void) @heading PGPLOT emulation *******************************************************************/ void cpgenv(float xmin, float xmax, float ymin, float ymax, int just, int axis) { cpgsvp(xmin, xmax, ymin, ymax); return; } /****************************************************************** @package nightfall @author Rainer Wichmann (rwichman@lsw.uni-heidelberg.de) @version 1.0 @short Set subpage @param (see PGPLOT manual) @return (void) @heading PGPLOT emulation *******************************************************************/ void cpgsubp(int a, int b) { /* store number of subpages */ gnuPageX = a; gnuPageY = b; /* initialize current subpage */ gnuPageXn = 0; gnuPageYn = -1; fprintf(gnustr, "unset multiplot\n"); fprintf(gnustr, "set multiplot\n"); fprintf(gnustr, "set origin 0.0, 0.0\n"); fflush(gnustr); /* initialize origin of current subpage */ gnuMOrig_y = 0.; gnuMOrig_x = 0.; gnuSubpageflag = ON; return; } /****************************************************************** @package nightfall @author Rainer Wichmann (rwichman@lsw.uni-heidelberg.de) @version 1.0 @short Goto next page @param (see PGPLOT manual) @return (void) @heading PGPLOT emulation *******************************************************************/ void cpgpage() { float orig_x, orig_y; /* origin of next page */ orig_y = 0.0; orig_x = 0.0; if (gnuSubpageflag == ON) { /* ------------ multiplot ------------------------------ */ /* page n times offset */ if (gnuPageYn < gnuPageY) ++gnuPageYn; if (gnuPageYn == gnuPageY) { gnuPageYn = 0; ++gnuPageXn; if (gnuPageXn == gnuPageX) { gnuSubpageflag = OFF; gnuPageXn = 0; gnuPageYn = 0; fprintf(gnustr, "unset multiplot\n"); fprintf(gnustr, "set multiplot\n"); fflush(gnustr); } } gnuOrig_x = orig_x + gnuPageXn * (1.0 / gnuPageX); gnuOrig_y = orig_y + gnuPageYn * (1.0 / gnuPageY); gnuMOrig_y = gnuOrig_y; gnuMOrig_x = gnuOrig_x; fprintf(gnustr, "set origin %5.2f ,%5.2f\n", gnuOrig_x, gnuOrig_y); fflush(gnustr); } else { /* ------------ single page ---------------------------- */ gnuMOrig_y = 0.; gnuMOrig_x = 0.; fprintf(gnustr, "unset multiplot\n"); fprintf(gnustr, "set multiplot\n"); fprintf(gnustr, "set origin 0.0 ,0.0\n"); fflush(gnustr); } } /****************************************************************** @package nightfall @author Rainer Wichmann (rwichman@lsw.uni-heidelberg.de) @version 1.0 @short Open plot device @param (see PGPLOT manual) @return (int) The error code @heading PGPLOT emulation *******************************************************************/ int cpgopen(char *s) { char gnu_geometry[256]; /* Window geometry */ int result; /* Error code */ char tmpdir[1024]; /* tmp directory */ struct sigaction act, oldact; /* signal handling */ /* xwindow already open */ if (strcmp("/XSERVE", s) == 0 && Flags.plotOpened == ON) { fprintf(gnustr, "set terminal x11\n"); fflush(gnustr); /* seems to be reqired unfortunately */ nanosleep (&sleep_req, &sleep_rem); fprintf(gnustr, "set terminal x11\n"); fprintf(gnustr, "unset mouse\n"); /* requires 3.8c+ */ fflush(gnustr); return (1); } else if (Flags.plotOpened == ON) { fprintf(gnustr, "set terminal postscript color\n"); fprintf(gnustr, "set output \"%s\" \n", Out_Plot_File); fflush(gnustr); return (1); } /* get tmp directory */ if (getenv("TEMPDIR") != NULL) strncpy(tmpdir, getenv("TEMPDIR"), 960); if (getenv("TMPDIR") != NULL) strncpy(tmpdir, getenv("TMPDIR"), 960); else strcpy(tmpdir, "/tmp"); strcpy(gnuCommands, tmpdir); strcpy(gnuData1, tmpdir); strcpy(gnuData2, tmpdir); strcpy(gnuData3, tmpdir); strcpy(gnuData4, tmpdir); /* create command pipe */ sprintf(gnuCommands + strlen(gnuCommands), "/gnuplot.input.%ld", (long) getpid() ); result = mkfifo(gnuCommands, 0666); if(result) perror (_("could not create command pipe")); /* create first data pipe */ sprintf(gnuData1 + strlen(gnuData1), "/gnuplot.data1.%ld", (long) getpid() ); result = mkfifo(gnuData1, 0666); if(result) perror (_("could not create data1 pipe")); /* create second data pipe */ sprintf(gnuData2 + strlen(gnuData2), "/gnuplot.data2.%ld", (long) getpid() ); result = mkfifo(gnuData2, 0666); if(result) perror (_("could not create data2 pipe")); /* create third data pipe */ sprintf(gnuData3 + strlen(gnuData3), "/gnuplot.data3.%ld", (long) getpid() ); result = mkfifo(gnuData3, 0666); if(result) perror (_("could not create data3 pipe")); /* create forth data pipe */ sprintf(gnuData4 + strlen(gnuData4), "/gnuplot.data4.%ld", (long) getpid() ); result = mkfifo(gnuData4, 0666); if(result) perror (_("could not create data4 pipe")); /* fork a process for GNUPLOT */ childPid = fork(); /* FIXME: does this affect the MPI environment ? */ if ( childPid == -1 ) { perror (_("unable to fork")); _exit (EXIT_FAILURE); return 0; } if ( childPid == 0 ){ /* ------------ child process ----------------------------- */ processGroup = getpid(); setpgid(0, processGroup); if (getenv("GNUPLOT_GEOMETRY") == NULL) strncpy(gnu_geometry, GNU_GEOMETRY, 255); else strncpy(gnu_geometry, getenv("GNUPLOT_GEOMETRY"), 255); gnu_geometry[255] = '\0'; /* start GNUPLOT and exit */ if (strcmp("/XSERVE", s) == 0) { /* fprintf(stderr, "gnuplot -persist -geometry %s %s\n", gnu_geometry, gnuCommands); */ execlp("gnuplot", "gnuplot", "-persist", "-geometry", gnu_geometry, gnuCommands, NULL); } else { /* fprintf(stderr, "gnuplot -geometry %s %s\n", gnu_geometry, gnuCommands); */ execlp("gnuplot", "gnuplot", "-geometry", gnu_geometry, gnuCommands, NULL); } /* execlp only returns if an error has occured */ perror (_("could not execute gnuplot")); _exit(EXIT_FAILURE); return 0; } else { /* ------------- parent process --------------------------- */ if (Flags.interactive == ON) setpgid ( childPid, processGroup); /* open command pipe for write and return */ gnustr = fopen(gnuCommands, "w"); if(!gnustr) perror (_("could not open command pipe")); /* set up a signal handler so we can clean up if killed */ act.sa_handler = &gnu_sighandler; /* signal action */ sigemptyset( &act.sa_mask ); /* set an empty mask */ act.sa_flags = 0; /* init sa_flags */ #ifdef SIGHUP sigaction(SIGHUP, &act, &oldact); #endif #ifdef SIGINT sigaction(SIGINT, &act, &oldact); #endif #ifdef SIGQUIT sigaction(SIGQUIT, &act, &oldact); #endif #ifdef SIGILL sigaction(SIGILL, &act, &oldact); #endif #ifdef SIGABRT sigaction(SIGABRT, &act, &oldact); #endif #ifdef SIGSEGV sigaction(SIGSEGV, &act, &oldact); #endif #ifdef SIGPIPE sigaction(SIGPIPE, &act, &oldact); #endif #ifdef SIGTRAP sigaction(SIGTRAP, &act, &oldact); #endif #ifdef SIGIOT sigaction(SIGIOT, &act, &oldact); #endif #ifdef SIGTERM sigaction(SIGTERM, &act, &oldact); #endif #ifdef SIGBUS sigaction(SIGBUS, &act, &oldact); #endif #ifdef SIGIO sigaction(SIGIO, &act, &oldact); #endif #ifdef SIGPOLL sigaction(SIGPOLL, &act, &oldact); #endif #ifdef SIGXCPU sigaction(SIGXCPU, &act, &oldact); #endif #ifdef SIGPWR sigaction(SIGPWR, &act, &oldact); #endif if (strcmp("/XSERVE", s) == 0 || strcmp("/XNOP", s) == 0 ) { fprintf(gnustr, "set terminal x11\n"); fprintf(gnustr, "unset mouse\n"); /* requires 3.8c+ */ fflush(gnustr); } else { fprintf(gnustr, "set terminal postscript color\n"); fprintf(gnustr, "set output \"%s\" \n", Out_Plot_File); fflush(gnustr); } fprintf(gnustr, "set origin 0.0, 0.0\n"); fflush(gnustr); gnuSubpageflag = OFF; if (strcmp("/XSERVE", s) == 0) Flags.plotOpened = ON; return(1); } } /****************************************************************** @package nightfall @author Rainer Wichmann (rwichman@lsw.uni-heidelberg.de) @version 1.0 @short Close plot device @param (see PGPLOT manual) @return (void) @heading PGPLOT emulation *******************************************************************/ void cpgend() { /* static char command[80], line[133], *linep, *token; FILE *fp; int try; */ fprintf(gnustr, "unset multiplot\n"); fflush(gnustr); fprintf(gnustr, "unset multiplot\n"); fflush(gnustr); fprintf(gnustr, "set output \n "); fflush(gnustr); /* ------- return if plot window is open ---------------- */ if (Flags.plotOpened == ON) { fprintf(gnustr, "set terminal x11\n "); fflush(gnustr); return; } /* ------- else ---------------- */ /* required for proper closedown of pipes */ nanosleep (&sleep_req, &sleep_rem); remove(gnuData1); remove(gnuData2); remove(gnuData3); remove(gnuData4); fclose(gnustr); if (Flags.interactive == ON) kill ( -childPid, SIGKILL); else kill ( childPid, SIGKILL); remove(gnuCommands); return; } #endif