Main Page   Class Hierarchy   Data Structures   File List   Data Fields   Globals  

plot_data.c

Go to the documentation of this file.
00001 /*
00002  *  plot_data:  create a simple plot of the input data stream.
00003  *              Type plot_data --help to see current options.
00004  *
00005  *              This version plots multiple columns and allows
00006  *              inline commands to be embedded in the data.
00007  *
00008  *  Author:     Copyright (c) Steve McMillan, Drexel University, 1994-2000.
00009  */
00010 
00011 
00012 /* Wish list:
00013 
00014    1. Tolerance of errors in data
00015    2. log plots
00016    3. dialogs, etc.
00017 
00018 */
00019 
00020 
00021 #include <stdio.h>
00022 #include <string.h>
00023 #include <math.h>
00024 #include <stdlib.h>
00025 
00026 #define NMAX     50000
00027 #define NYMAX    10
00028 #define NBUFFER  100
00029 #define INFINITY 1.e15  /* Close enough! */
00030 
00031 #define USAGE    "\n\
00032 Usage:  plot_data  [-c xcol ycol1 ycol2 ...]  [-c[c][xy]]  [-C color1...] \n\
00033                    [-e]  [-h header]  [-i]  [-l xmin xmax ymin ymax] \n\
00034                    [-L scale]  [-N nmax]  [-o]  [-O xo yo]  [-p[p]] \n\
00035                    [-P point_size]  [-q]  [-s xs ys]  [-S skip]  [-t ntrail] \n\
00036                    [-w[w][xy]]  [-W]  [-x x-label]  [-X]  [-y y-label] \n\
00037                    [-z zcol] [[-]-help] \n"
00038 
00039 typedef unsigned long Window;
00040 
00041 typedef struct {float xmin;
00042                 float xmax;
00043                 float ymin;
00044                 float ymax;
00045                 int xmin_from_data;
00046                 int xmax_from_data;
00047                 int ymin_from_data;
00048                 int ymax_from_data;
00049             } limits;
00050 
00051 typedef struct {Window xwin;            /* X window ID                */
00052 
00053                 int xcol;               /* X-column to graph          */
00054                 int nmax;               /* Length of storage arrays   */
00055                 int ycol[NYMAX];        /* Y-column(s) to graph.      */
00056                 int ny;                 /* Number of y columns        */
00057                 int zcol;               /* Colors from this column    */
00058 
00059                 int lines;              /* Plot lines                 */
00060                 float point_size;       /* Point size (0 ==> 1 pixel) */
00061                 int ntrail;             /* >0 ==> trail length        */
00062                 float* xsave;           /* For saving trail data      */
00063                 float* ysave;
00064                 int output;             /* Don't pass data to stdout  */
00065 
00066                 char xlabel[256];       /* X-axis label               */
00067                 int  xlabel_set;
00068                 char ylabel[256];       /* Y-axis label               */
00069                 int  ylabel_set;
00070                 char header[256];       /* Overall label              */
00071 
00072                 char color[NYMAX][16];  /* Point color(s) (by name)   */
00073                 int icolor[NYMAX];      /* X indices of colors        */
00074                 int ibox;               /* Color index of box         */
00075                 int iback;              /* Color index of background  */
00076                 int curr_color;         /* Current color index        */
00077 
00078                 int limits_from_data;   /* Get limits from input data */
00079                 limits lims;            /* X and Y plotting limits    */
00080 
00081                 int crop_data;          /* Crop x or y to plot limits */
00082                 int crop_x;             /* Crop x to plot limits      */
00083                 int crop_y;             /* Crop y to plot limits      */
00084                 int wrap_data;          /* Wrap x or y to plot limits */
00085                 int wrap_x;             /* Wrap x to plot limits      */
00086                 int wrap_y;             /* Wrap y to plot limits      */
00087                 float yscale;           /* "Aspect ratio"             */
00088 
00089                 int xorigin;            /* Top left of plot window    */
00090                 int yorigin;            /* Top left of plot window    */
00091                 int xsize;              /* Size of plot window        */
00092                 int ysize;              /* Size of plot window        */
00093 
00094                 int quiet;              /* Suppress most output       */
00095                 int ignore_inline;      /* Ignore inline commands     */
00096                 int skip;               /* Skip leading lines         */
00097 
00098                 int modify;             /* Internal flag              */
00099                 int pause;              /* Internal flag              */
00100 
00101                 int echo;
00102 
00103             } plot_params;
00104 
00105 static int init_arr_size, arr_size;     /* Ugly but simple! */
00106 static int in_line = 0;
00107 
00108 void err_exit(char* s)
00109 {
00110     fprintf(stderr, "Error: %s\n", s);
00111     if (!in_line) exit(1);
00112 }
00113 
00114 static int counter = 0;
00115 static char last_err[1024];
00116 
00117 void print_help(char* s)
00118 {
00119     if (!s) counter = 0;
00120     if (counter == 1 && strcmp(s, last_err)) counter = 0;
00121 
00122     /* Print error message only if s is not the same as last time around. */
00123 
00124     if (counter == 0) {
00125 
00126         if (s) fprintf(stderr, "Unknown option %s\n\n", s);
00127         fprintf(stderr, USAGE);
00128 
00129         fprintf(stderr, "\nOptions:\n");
00130         fprintf(stderr,
00131 "\t-c xcol ycol1...  plot data in xcol horizontally, ycol vertically [1 2]\n");
00132         fprintf(stderr,
00133                 "\t-c[c][xy]\tcrop [x or y] data to plot limits\n");
00134         fprintf(stderr,
00135                 "\t-C color1...\tspecify line/point colors [all black]\n");
00136         fprintf(stderr,
00137                 "\t-e\t\techo current settings\n");
00138         fprintf(stderr,
00139                 "\t-h header\tspecify overall label for plot [none]\n");
00140         fprintf(stderr,
00141                 "\t-i\t\tignore inline commands [don't ignore]\n");
00142         fprintf(stderr,
00143                 "\t-l xmin xmax ymin ymax\tspecify limits for plot [get from data]\n");
00144         fprintf(stderr,
00145                 "\t-ll\t\tforce plot lines only [plot lines]\n");
00146         fprintf(stderr,
00147                 "\t-L scale\tspecify limits to be +/- scale for both axes\n");
00148         fprintf(stderr,
00149                 "\t-N nmax\t\tspecify maximum number of points to store [%d]\n",
00150                 NMAX);
00151         fprintf(stderr,
00152                 "\t-o\t\techo stdin to stdout [do not echo]\n");
00153         fprintf(stderr,
00154                 "\t-O xo yo\tspecify top left corner of plotting box [150, 50]\n");
00155         fprintf(stderr,
00156                 "\t-p\t\ttoggle plot points only [plot lines]\n");
00157         fprintf(stderr,
00158                 "\t-pp\t\tforce plot points only [plot lines]\n");
00159         fprintf(stderr,
00160                 "\t-P size\t\tspecify point size, in x-axis units [0 ==> pixel]\n");
00161         fprintf(stderr,
00162                 "\t-q\t\tsuppress most output [don't suppress]\n");
00163         fprintf(stderr,
00164                 "\t-Q\t\tquit\n");
00165         fprintf(stderr,
00166                 "\t-s xs ys\tspecify box size [500, 500]\n");
00167         fprintf(stderr,
00168                 "\t-S skip\t\tskip leading lines [0]\n");
00169         fprintf(stderr,
00170                 "\t-t ntrail\tspecify number of trailing points [infinite]\n");
00171         fprintf(stderr,
00172                 "\t-w[w][xy]\twrap [x or y] data to plot limits\n");
00173         fprintf(stderr,
00174                 "\t-W\t\twait for keyboard input [inline only]\n");
00175         fprintf(stderr,
00176                 "\t-x xlabel\tspecify label for x-axis [\"column 'xcol'\"]\n");
00177         fprintf(stderr,
00178                 "\t-X\t\tclear the display and redraw axes [inline only]\n");
00179         fprintf(stderr,
00180                 "\t-y ylabel\tspecify label for y-axis [\"column 'ycol1...'\"]\n");
00181         fprintf(stderr,
00182                 "\t-z zcol\t\tspecify column for color data [none]\n");
00183         fprintf(stderr,
00184                 "\t[-]-help\t\tprint this help message\n");
00185     }
00186 
00187     counter++;
00188     if (s) strcpy(last_err, s);
00189     
00190 }
00191 
00192 void swap (float* x, float* y)
00193 {
00194     float z;
00195 
00196     z = *x;
00197     *x = *y;
00198     *y = z;
00199 }
00200 
00201 void set_or_flag(char* arg, int* flag, float* limit)
00202 {
00203     if (!strcmp(arg, "."))
00204         *flag = 1;
00205     else {
00206         *flag = 0;
00207         *limit = atof(arg);
00208     }
00209 }
00210 
00211 void parse_command_line(int argc, char** argv, plot_params* params)
00212 {
00213     int i, j;
00214     double temp;
00215 
00216     /* Parse the argument list. */
00217 
00218     for (i = 1; i < argc; i++)
00219 
00220         if (argv[i][0] == '-') {
00221 
00222             switch (argv[i][1]) {
00223 
00224                 case '-':       if (!strcmp(argv[i], "--help")) {
00225                                     print_help(NULL);
00226                                     exit(0);
00227                                 }
00228 
00229                 case 'c':       if (argv[i][2] == 'x')                 /*  cx */
00230                                     params->crop_x = 1;
00231                                 else if (argv[i][2] == 'y')            /*  cy */
00232                                     params->crop_y = 1;
00233                                 else if (argv[i][2] == 'c') {
00234                                     if (argv[i][3] == 'x')             /* ccx */
00235                                         params->crop_x = 0;
00236                                     else if (argv[i][3] == 'y')        /* ccy */
00237                                         params->crop_y = 0;
00238                                     else {
00239                                         params->crop_x = params->crop_y = 1;
00240                                     }
00241                                 } else if (i < argc-1) {
00242                                     params->xcol = atoi(argv[++i]);
00243                                     if (params->xcol <= 0) {
00244                                         fprintf(stderr, USAGE);
00245                                         if (!in_line) exit(1);
00246                                     }
00247                                     params->ny = 0;
00248                                     while (i < argc-1
00249                                            && sscanf(argv[i+1], "%d", &j) > 0) {
00250                                         if (j == params->xcol) {
00251                                             fprintf(stderr, USAGE);
00252                                             if (!in_line) exit(1);
00253                                         } else if (j > 0) {
00254                                             params->ycol[(params->ny)++] = j;
00255                                             if (params->ny > 10) err_exit(
00256                                            "Maximum of 10 y-columns allowed.");
00257                                             if (params->ny > 1)
00258                                             strcpy(params->color[params->ny-1],
00259                                                   params->color[params->ny-2]);
00260                                             params->icolor[params->ny-1] = -1;
00261                                         }
00262                                         i++;
00263                                     }
00264                                 } else
00265                                     fprintf(stderr,
00266                                             "-c: No parameters specified.\n");
00267 
00268                                 params->crop_data = (params->crop_x
00269                                                       || params->crop_y);
00270                                 if (params->crop_data) params->wrap_data = 0;
00271 
00272                                 break;
00273 
00274                 case 'C':       if (i < argc-1) {
00275                                     for (j = 0; j < params->ny; j++) {
00276                                         if (i < argc-1 && argv[i+1][0] != '-')
00277                                             strcpy(params->color[j], argv[++i]);
00278                                         else if (j > 0)
00279                                             strcpy(params->color[j],
00280                                                    params->color[j-1]);
00281                                         params->icolor[j] = -1;
00282                                     }
00283                                 } else
00284                                     fprintf(stderr,
00285                                             "-C: No parameter specified.\n");
00286 
00287                                 break;
00288 
00289                 case 'e':       if (argv[i][2] <= ' ') params->echo = 1;
00290                                 break;
00291 
00292                 case 'h':       if (!strcmp(argv[i], "-help")) {
00293                                     print_help(NULL);
00294                                     exit(0);
00295                                 }
00296                                 if (i < argc-1) {
00297                                     strcpy(params->header, argv[++i]);
00298                                 } else
00299                                     fprintf(stderr,
00300                                             "-h: No parameter specified.\n");
00301 
00302                                 break;
00303 
00304                 case 'i':       params->ignore_inline =
00305                                         1 - params->ignore_inline;
00306                                 break;
00307 
00308                 case 'l':       if (argv[i][2] == 'l')
00309                                     params->lines = 1;
00310                                 else {
00311                                     if (i < argc-1) {
00312 
00313                                         set_or_flag(argv[++i],
00314                                                    &params->lims.xmin_from_data,
00315                                                    &params->lims.xmin);
00316 
00317                                         if (i < argc-1)
00318                                             set_or_flag(argv[++i],
00319                                                    &params->lims.xmax_from_data,
00320                                                    &params->lims.xmax);
00321 
00322                                         if (i < argc-1)
00323                                             set_or_flag(argv[++i],
00324                                                    &params->lims.ymin_from_data,
00325                                                    &params->lims.ymin);
00326 
00327                                         if (i < argc-1)
00328                                             set_or_flag(argv[++i],
00329                                                    &params->lims.ymax_from_data,
00330                                                    &params->lims.ymax);
00331 
00332                                         if (!params->lims.xmin_from_data
00333                                             && !params->lims.xmax_from_data
00334                                             && params->lims.xmax
00335                                                 <= params->lims.xmin)
00336                                             swap(&params->lims.xmax,
00337                                                  &params->lims.xmin);
00338 
00339                                         if (!params->lims.ymin_from_data
00340                                             && !params->lims.ymax_from_data
00341                                             && params->lims.ymax
00342                                                 <= params->lims.ymin)
00343                                             swap(&params->lims.ymax,
00344                                                  &params->lims.ymin);
00345 
00346                                         params->limits_from_data = 
00347                                             params->lims.xmin_from_data
00348                                             || params->lims.xmax_from_data
00349                                             || params->lims.ymin_from_data
00350                                             || params->lims.ymax_from_data;
00351 
00352                                         if (!params->limits_from_data)
00353                                             if (params->lims.xmax
00354                                                 <= params->lims.xmin
00355                                                 || params->lims.ymax
00356                                                 <= params->lims.ymin)
00357                                                 err_exit("Illegal limits");
00358 
00359                                         params->yscale = -1.0;
00360                                     }
00361                                 }
00362 
00363                                 break;
00364 
00365                 case 'L':       if (i < argc-1) {
00366                                     temp = atof(argv[++i]);
00367                                     if (temp <= 0) temp = 1.0;     /* "-L" OK */
00368                                 } else
00369                                      temp = 1.0;
00370 
00371                                 params->lims.xmin = -temp;
00372                                 params->lims.xmax = temp;
00373                                 params->lims.ymin = -temp;
00374                                 params->lims.ymax = temp;
00375 
00376                                 params->limits_from_data = 0;
00377                                 params->lims.xmin_from_data = 0;
00378                                 params->lims.xmax_from_data = 0;
00379                                 params->lims.ymin_from_data = 0;
00380                                 params->lims.ymax_from_data = 0;
00381 
00382                                 params->yscale = -1.0;
00383                                 break;
00384 
00385                 case 'N':       if (i < argc-1)
00386                                     params->nmax = atoi(argv[++i]);
00387                                 else
00388                                     fprintf(stderr,
00389                                             "-N: No parameter specified.\n");
00390 
00391                                 break;
00392 
00393                 case 'o':       params->output = 1 - params->output;
00394                                 break;
00395 
00396                 case 'O':       if (i < argc-1)
00397                                     params->xorigin = atoi(argv[++i]);
00398                                 if (i < argc-1)
00399                                     params->yorigin = atoi(argv[++i]);
00400                                 break;
00401 
00402                 case 'p':       if (argv[i][2] == 'p')
00403                                     params->lines = 0;
00404                                 else
00405                                     params->lines = 1 - params->lines;
00406 
00407                                 break;
00408 
00409                 case 'P':       if (i < argc-1)
00410                                     params->point_size = atof(argv[++i]);
00411                                 if (params->point_size < 0.0)
00412                                     params->point_size = 0.0;
00413                                 break;
00414 
00415                 case 'q':       params->quiet = 1 - params->quiet;
00416                                 break;
00417 
00418                 case 'Q':       exit(0);
00419 
00420                 case 's':       if (i < argc-1)
00421                                     params->xsize = atoi(argv[++i]);
00422                                 if (i+1 < argc && argv[i+1][0] != '-')
00423                                     params->ysize = atoi(argv[++i]);
00424                                 else
00425                                     params->ysize = params->xsize;
00426                                 break;
00427 
00428                 case 'S':       if (i < argc-1)
00429                                     params->skip = atoi(argv[++i]);
00430                                 break;
00431 
00432                 case 't':       if (i < argc-1) {
00433                                     j = atoi(argv[++i]);
00434                                     if (j < 0) j = 0;              /* "-t" OK */
00435                                 } else
00436                                      j = 0;
00437                                 params->ntrail = j;
00438                                 break;
00439 
00440                 case 'W':       params->pause = 1;
00441                                 break;
00442 
00443                 case 'w':       if (argv[i][2] == 'x')                 /*  wx */
00444                                     params->wrap_x = 1;
00445                                 else if (argv[i][2] == 'y')            /*  wy */
00446                                     params->wrap_y = 1;
00447                                 else if (argv[i][2] == 'w') {
00448                                     if (argv[i][3] == 'x')             /* wwx */
00449                                         params->wrap_x = 0;
00450                                     else if (argv[i][3] == 'y')        /* wwy */
00451                                         params->wrap_y = 0;
00452                                 }
00453 
00454                                 params->wrap_data = (params->wrap_x
00455                                                       || params->wrap_y);
00456 
00457                                 break;
00458 
00459                 case 'x':       if (i < argc-1) {
00460                                     strcpy(params->xlabel, argv[++i]);
00461                                     params->xlabel_set = 1;
00462                                     params->yscale = -1.0;
00463                                 } else
00464                                     fprintf(stderr,
00465                                             "-x: No parameter specified.\n");
00466 
00467                                 break;
00468 
00469                 case 'X':       params->yscale = -1.0;
00470                                 break;
00471 
00472                 case 'y':       if (i < argc-1) {
00473                                     strcpy(params->ylabel, argv[++i]);
00474                                     params->ylabel_set = 1;
00475                                     params->yscale = -1.0;
00476                                 } else
00477                                     fprintf(stderr,
00478                                             "-y: No parameter specified.\n");
00479 
00480                                 break;
00481 
00482                 case 'z':       if (i < argc-1)
00483                                     params->zcol = atoi(argv[++i]);
00484                                 break;
00485 
00486                 case 'H':
00487                 default:        if (!params->quiet) print_help(argv[i]);
00488                                 if (strcmp(argv[0], "INLINE")) exit(1);
00489 
00490             }
00491 
00492         }
00493 }
00494 
00495 void echo_parameters(plot_params* params)
00496 {
00497     int i;
00498 
00499     if (!params->echo) return;
00500 
00501     fprintf(stderr, "\nCurrent parameter settings:\n");
00502     fprintf(stderr, "    xcol = %d, ycol =", params->xcol);
00503     if (params->ny > 0)
00504         for (i = 0; i < params->ny; i++)
00505             fprintf(stderr, " %d (%s)", params->ycol[i], params->color[i]);
00506     else
00507         fprintf(stderr, " (not set)");
00508     fprintf(stderr, ", zcol = %d\n", params->zcol);
00509 
00510     fprintf(stderr, "    xmin = %f, xmax = %f, ymin = %f, ymax = %f\n",
00511            params->lims.xmin, params->lims.xmax,
00512            params->lims.ymin, params->lims.ymax);
00513     fprintf(stderr, "    crop_x = %d, crop_y = %d\n",
00514             params->crop_x, params->crop_y);
00515     fprintf(stderr, "    wrap_x = %d, wrap_y = %d\n",
00516             params->wrap_x, params->wrap_y);
00517 
00518     fprintf(stderr, "    x-label = \"%s\", y-label = \"%s\", header = \"%s\"\n",
00519            params->xlabel, params->ylabel,
00520            (params->header ? params->header : "(none)"));
00521 
00522     fprintf(stderr, "    lines = %d, ntrail = %d, point_size = %f\n",
00523            params->lines, params->ntrail, params->point_size);
00524 
00525     fprintf(stderr, "    quiet = %d, ignore_inline = %d, output = %d\n",
00526            params->quiet, params->ignore_inline, params->output);
00527 
00528     fprintf(stderr, "\n");
00529     params->echo = 0;
00530 }
00531 
00532 void create_labels(plot_params* params)
00533 {
00534     int j;
00535 
00536     if (!params->xlabel_set) sprintf(params->xlabel, "column %d", params->xcol);
00537     if (!params->ylabel_set) {
00538         sprintf(params->ylabel, "column");
00539         if (params->ny > 1) strcat(params->ylabel, "s");
00540         for (j = 0; j < params->ny; j++) {
00541             char temp[4];
00542             sprintf(temp, " %d", params->ycol[j]);
00543             strcat(params->ylabel, temp);
00544         }
00545     }
00546 }
00547 
00548 void allocate_save(plot_params* params)
00549 {
00550     if ((params->xsave = (float*)malloc(params->ntrail*sizeof(float)))
00551         == NULL)
00552         err_exit("Can't allocate x-storage space.");
00553     if ((params->ysave = (float*)malloc(NYMAX*params->ntrail*sizeof(float)))
00554         == NULL)
00555         err_exit("Can't allocate y-storage space.");
00556 }
00557 
00558 void skip_lines(int skip, int output)
00559 {
00560     /* Place pointer after the skip-th newline. */
00561 
00562     int i;
00563 
00564     while (skip-- > 0) {
00565         while ((i = getchar()) != '\n' && i != EOF)
00566             if (output) putchar(i);
00567         if (output) putchar('\n');
00568     }
00569 }
00570 
00571 void split_inline_command(char* temp, int* argc, char** argv)
00572 {
00573     *argc = 0;
00574     argv[(*argc)++] = "INLINE";
00575 
00576     while (*temp != '\0') {
00577         while (*temp == ' ') temp++;
00578         argv[(*argc)++] = temp;
00579         while (*temp != ' ' && *temp != '\0') temp++;
00580         if (*temp != '\0') {
00581             *temp = '\0';
00582             temp++;
00583         }
00584     }    
00585 }
00586 
00587 void parse_inline_command(char* temp, plot_params* params)
00588 {
00589     int argc;
00590     char* argv[256];    /* Seems like a conservative limit! */
00591 
00592     /* Parse an inline command.  Assume syntax identical to the
00593        UNIX command-line switches (use parse_command_line to do
00594        the work).
00595      */
00596 
00597     split_inline_command(temp, &argc, argv);
00598     parse_command_line(argc, argv, params);
00599 }
00600 
00601 void set_window_parameters(plot_params* params)
00602 {
00603     /* Draw a box, with tick marks. */
00604 
00605     lux_setup_region(params->xwin, 1.5, 1.5, 7.5, 7.5);
00606     lux_setup_axis(params->xwin,
00607                    params->lims.xmin, params->lims.xmax,
00608                    params->lims.ymin, params->lims.ymax);
00609     lux_draw_axis(params->xwin);
00610 
00611     /* Add some (optional) labels. */
00612 
00613     if (params->xlabel)
00614         lux_draw_string(params->xwin,
00615                         0.5*(params->lims.xmin + params->lims.xmax),
00616                         params->lims.ymin - 0.075*(params->lims.ymax
00617                                                    - params->lims.ymin),
00618                         -1., params->xlabel, 0);
00619     if (params->ylabel)
00620         lux_draw_vstring(params->xwin,
00621                          params->lims.xmin - 0.077*(params->lims.xmax
00622                                                     - params->lims.xmin),
00623                          0.5*(params->lims.ymin + params->lims.ymax),
00624                          0., params->ylabel, 0);
00625 
00626     /* Add an optional header. */
00627 
00628     if (params->header)
00629         lux_draw_string(params->xwin,
00630                         0.5*(params->lims.xmin + params->lims.xmax),
00631                         params->lims.ymax + 0.05*(params->lims.ymax
00632                                                   - params->lims.ymin),
00633                         0., params->header, 0);
00634 }
00635 
00636 void process_inline_command(char *input_line,
00637                             plot_params* params, int* reinit)
00638 {
00639     /* Decode an embedded command line. */
00640 
00641     char xlabel[256], ylabel[256];
00642 
00643     if (!params->limits_from_data) {
00644 
00645         int xcol, ycol[NYMAX], zcol, iy, ny, ntrail;    /* Local copies */
00646 
00647         xcol = params->xcol;
00648         ny = params->ny;
00649         for (iy = 0; iy < params->ny; iy++) ycol[iy] = params->ycol[iy];
00650         zcol = params->zcol;
00651         ntrail = params->ntrail;
00652 
00653         strcpy(xlabel, params->xlabel);
00654         strcpy(ylabel, params->ylabel);
00655 
00656 /*      if (!params->quiet) */
00657             fprintf(stderr, "Read inline command \"%s\"\n", input_line);
00658 
00659         parse_inline_command(input_line, params);
00660 
00661         if (params->ntrail != ntrail) {
00662             if (ntrail == 0) {
00663                 arr_size = 1;
00664                 allocate_save(params);
00665             }
00666                 
00667             if (params->ntrail == 0) {
00668                 arr_size = init_arr_size;
00669                 free(params->xsave);
00670                 free(params->ysave);
00671             }
00672         }
00673 
00674         /* Force recomputation of read_list and index (saved as static
00675            variables for efficiency) if xcol, ycol, or zcol are modified. */
00676 
00677         if (params->xcol != xcol || params->ny != ny || params->zcol != zcol)
00678             *reinit = -1;
00679         else
00680             for (iy = 0; iy < params->ny; iy++)
00681                 if (params->ycol[iy] != ycol[iy]) *reinit = -1;
00682 
00683         if (*reinit == -1) create_labels(params);
00684 
00685         if (strcmp(xlabel, params->xlabel) || strcmp(xlabel, params->xlabel))
00686             params->yscale = -1;
00687 
00688         /* (Setting yscale < 0 forces the box to be redrawn.) */
00689 
00690         /* Check to see if any color was changed. */
00691 
00692         for (iy = 0; iy < params->ny; iy++)
00693             if (params->icolor[iy] < 0)
00694                 params->icolor[iy] = lux_lookup_color(params->xwin,
00695                                                       params->color[iy]);
00696 
00697         /* Check to see if limits were changed. */
00698 
00699         if (params->yscale < 0) {
00700 
00701             lux_reset_window(params->xwin);
00702 
00703             params->curr_color = params->ibox;
00704             lux_set_color(params->xwin, params->curr_color);
00705             set_window_parameters(params);
00706 
00707             params->yscale = (params->lims.ymax - params->lims.ymin)
00708                 / (params->lims.xmax - params->lims.xmin);
00709         }
00710 
00711         if (params->pause) {
00712 
00713             fprintf(stderr,
00714                     "Press any key in display window to continue\n");
00715             while(!win_getkey(params->xwin));
00716 
00717             params->pause = 0;
00718         }
00719 
00720         if (params->skip) {
00721             skip_lines(params->skip, params->output);
00722             params->skip = 0;
00723         }
00724 
00725         if (params->echo) echo_parameters(params);
00726 
00727     } else
00728 
00729         if (!params->quiet)
00730             fprintf(stderr, "Read and skipped inline command \"%s\"\n",
00731                     input_line);
00732 }
00733 
00734 void force_limits(float* xmin, int set_xmin, float* xmax, int set_xmax)
00735 {
00736     double dx, dy, z;
00737     int idy, i;
00738 
00739     if (*xmax <= *xmin) return;
00740 
00741     /* Simple criterion: take the next "tick-mark" up or down, in units
00742        of the power of 10 closest to one-twentieth the given interval. */
00743 
00744     dx = 0.05 * (*xmax - *xmin);
00745 
00746     /* Find the power of 10 closest to dx. */
00747 
00748     dy = log10(dx);
00749     idy = dy + 0.5;
00750     if (dy < -0.5) idy = idy - 1;
00751 
00752     /* Don't trust floating-point work with floats...
00753 
00754     dy = pow(10., (float)idy);
00755     fprintf(stderr, "idy = %d, dy = %f\n", idy, dy);
00756 
00757     */
00758 
00759     dy = 1.0;
00760     if (idy > 0)
00761         for (i = 0; i < idy; i++) dy *= 10.0;
00762     else if (idy < 0)
00763         for (i = 0; i < -idy; i++) dy /= 10.0;
00764 
00765     /* fprintf(stderr, "idy = %d, dy = %f\n", idy, dy); */
00766 
00767     /* Start at zero, go up above xmax, then down below xmin. */
00768 
00769     /* fprintf(stderr, "*xmin, *xmax = %f %f\n", *xmin, *xmax); */
00770 
00771     for (z = 0.0; z < *xmax + 0.1*dx; z += dy);
00772     for (; z > *xmin - 0.1*dx; z -= dy);
00773     if (set_xmin) *xmin = z;
00774 
00775     for (; z < *xmax + 0.1*dx; z += dy);
00776     if (set_xmax) *xmax = z;
00777 
00778     /* fprintf(stderr, "*xmin, *xmax = %f %f\n", *xmin, *xmax); */
00779 }
00780 
00781 void get_limits(float* x, float* y, int n, plot_params* params)
00782 {
00783     /* Note: y is actually a 2D array, with ny rows, each of length n,
00784      * stored in a rectangular grid of total length arr_size. */
00785 
00786     int i, j;
00787 
00788     /* Determine the lower and upper limits on the data. */
00789 
00790     if (params->lims.xmin_from_data) params->lims.xmin = INFINITY;
00791     if (params->lims.xmax_from_data) params->lims.xmax = -INFINITY;
00792     if (params->lims.ymin_from_data) params->lims.ymin = INFINITY;
00793     if (params->lims.ymax_from_data) params->lims.ymax = -INFINITY;
00794 
00795     for (i = 0; i < n; i++) {
00796         if (params->lims.xmin_from_data
00797              && x[i] < params->lims.xmin) params->lims.xmin = x[i];
00798         if (params->lims.xmax_from_data
00799              && x[i] > params->lims.xmax) params->lims.xmax = x[i];
00800         for (j = 0; j < params->ny; j++) {
00801             float yy = *(y+j*arr_size+i);
00802             if (params->lims.ymin_from_data
00803                  && yy < params->lims.ymin) params->lims.ymin = yy;
00804             if (params->lims.ymax_from_data
00805                  && yy > params->lims.ymax) params->lims.ymax = yy;
00806         }
00807     }
00808 
00809     /* Force the limits to something sensible. */
00810 
00811     force_limits(&(params->lims.xmin), params->lims.xmin_from_data,
00812                  &(params->lims.xmax), params->lims.xmax_from_data);
00813     force_limits(&(params->lims.ymin), params->lims.ymin_from_data,
00814                  &(params->lims.ymax), params->lims.ymax_from_data);
00815 
00816     if (!params->quiet) {
00817         fprintf(stderr, "Selected x limits %f to %f,  ",
00818                 params->lims.xmin, params->lims.xmax);
00819         fprintf(stderr, "y limits %f to %f\n",
00820                 params->lims.ymin, params->lims.ymax);
00821     }
00822 }
00823 
00824 Window set_up_window(plot_params* params)
00825 {
00826     /* Open an X-window. */
00827     
00828     params->xwin = lux_openwin(params->xorigin, params->yorigin,
00829                                params->xsize, params->ysize);
00830 
00831     if (params->xwin > 0) set_window_parameters(params);
00832 
00833     return params->xwin;
00834 }
00835 
00836 void swapi(int* i, int* j)
00837 {
00838     int k;
00839 
00840     k = *i;
00841     *i = *j;
00842     *j = k;
00843 }
00844 
00845 void sort_columns(plot_params* params,
00846                   int* read_list, int* nread, int* index)
00847 {
00848     int i, j, index1[NYMAX+2];
00849 
00850     /* List all columns and establish connections with actual data.
00851      *
00852      *          index1 = 0       ==>  xcol
00853      *          index1 = 1 -- ny ==>  ycol
00854      *          index1 = ny+1    ==>  zcol
00855      */
00856 
00857     *nread = 1;
00858     index1[0] = 0;
00859     read_list[0] = params->xcol;
00860     
00861     for (j = 0; j < params->ny; j++) {
00862         index1[(*nread)] = j+1;
00863         read_list[(*nread)++] = params->ycol[j];
00864     }
00865 
00866     if (params->zcol > 0) {
00867         index1[(*nread)] = params->ny + 1;
00868         read_list[(*nread)++] = params->zcol;
00869     }
00870 
00871     /* Sort the columns, retaining connections. */
00872 
00873     for (i = 0; i < *nread; i++)
00874         for (j = i + 1; j < *nread; j++)
00875             if (read_list[j] < read_list[i]) {
00876                 swapi(read_list+i, read_list+j);
00877                 swapi(index1+i, index1+j);
00878             }
00879 
00880     /* Finally, invert index1 to obtain index. */
00881 
00882     for (i = 0; i < *nread; i++) index[index1[i]] = i;
00883 }
00884 
00885 #define MAX_LINE 1024
00886 
00887 int readxyz(plot_params* params, float* x, float* y, float* z,
00888             int output)
00889 {
00890     /* Read x, y (array), and possibly z, from stdin.  Return 1 if
00891        successful, 0 otherwise.  Also allow special processing of
00892        control lines embedded in the data. */
00893 
00894     static int read_list[NYMAX+2], index[NYMAX+2], nread, col_init = -1;
00895     int start[NYMAX+2];
00896 
00897     float temp[NYMAX+2];
00898     int i, j, last, p, len;
00899 
00900     /* If an EOF is encountered, return 0, which terminates the read.
00901      *
00902      * If a line cannot be interpreted as numeric data, attempt to read
00903      * an inline command from it, act on the command, if possible, then
00904      * return 0 to force all data up to this point to be plotted and all
00905      * buffers to be flushed.  Graphics changes will take effect after
00906      * the NEXT read.
00907      *
00908      * The "modify" variable controls when changes can be made.
00909      * It is 0 if the buffers contain current data, 1 otherwise.
00910      * Only allow changes if modify = 1.
00911      *
00912      * Otherwise, return 1 to continue the read on the next line.
00913      */
00914 
00915     /* Problems with reading and interpreting data from stdin...
00916      * Read in an entire line and handle it as a string.
00917      */
00918 
00919     char input_line[MAX_LINE], *c;
00920 
00921     /* Rules:   fgets > 0 is the first character read.
00922      *          fgets = 0 ==> error
00923      *          fgets < 0 ==> EOF (= -1, usually)
00924      *
00925      * Return for fgets <= 0.  Otherwise, input_line is a null-terminated
00926      * string read containing the input line (including the '\n'). 
00927      */
00928 
00929     if (fgets(input_line, MAX_LINE, stdin) <= 0) return 0;
00930 
00931     /* We have read a valid line from stdin.  Check for embedded
00932      * commands, then read the data.
00933      *
00934      * Embedded commands always start with "-", just like command-line
00935      * arguments.
00936      */
00937 
00938     while (input_line[0] == '-' && input_line[1] >= 'A') {
00939 
00940         /* Line appears to contain an embedded inline command.  Read and
00941          * decode it if and only if ignore_inline = 0, limits_from_data = 0,
00942          * and modify = 1.
00943          */ 
00944 
00945         if (!params->ignore_inline &&
00946             !params->limits_from_data &&
00947             !params->modify) {
00948 
00949             /* Force buffers to be flushed before rereading line */
00950 
00951             params->modify = 1;
00952             return 0;
00953         }
00954 
00955         /* fprintf(stderr, "line length = %d\n", strlen(input_line)); */
00956 
00957         /* Need to strip any trailing newline... */
00958 
00959         i = strlen(input_line);
00960         if (i > 0 && input_line[i-1] == '\n') input_line[i-1] = '\0';
00961 
00962         process_inline_command(input_line, params, &col_init);
00963 
00964         /* Check for expose/resize events and refresh the display. */
00965 
00966         if (params->xwin > 0) win_checkevent(params->xwin);
00967 
00968         /* Read the next line. */
00969 
00970         if (fgets(input_line, MAX_LINE, stdin) <= 0) return 0;
00971     }
00972 
00973     /* Deal with unwanted punctuation. */
00974 
00975     for (c = input_line; *c != '\0'; c++)
00976         if (*c == ',') *c = ' ';
00977 
00978     /* Line apparently contains data.  Read it. */
00979 
00980     /* Maintain two static arrays to help in reading data:
00981      * 
00982      *  (1) read_list, an ordered list of columns to read (length nread),
00983      *  (2) index, to assign each column to the correct variable.
00984      *
00985      * Most of the complication here is because we may want to read
00986      * several columns, and that xcol, ycol and zcol are not in any
00987      * particular order.
00988      *
00989      * Columns to be read are read_list[0] < read_list[1] < ...
00990      *
00991      * Temp column index[0]        ==> xcol
00992      *                  [1 -- ny]  ==> ycol
00993      *                  [ny+1]     ==> zcol
00994      */
00995 
00996     /* (Re)sort xcol, ycol (and possibly zcol), if necessary. */
00997 
00998     if (col_init < 0) {
00999         sort_columns(params, read_list, &nread, index);
01000         col_init = 1;
01001     }
01002 
01003     /* Note that we use FORTRAN numbering in specifying columns (in xcol,
01004      * ycol, etc.): the first column is 1, NOT 0!  We will continue this
01005      * convention here as we read in the temp array.
01006      */
01007 
01008     /* Read the data.   Start by locating the starting points of the
01009      * nread columns we want (avoids extra scanfs, note).  Note that
01010      * we don't check for end-of-line after every character.
01011      */
01012 
01013     len = strlen(input_line);
01014 
01015     /* Move to the start of the first column. */
01016 
01017     p = 0;
01018     while (input_line[p] <= ' ') p++;
01019 
01020     last = 0;
01021     for (j = 0; j < nread; j++) {
01022 
01023         if (p > len) return 0;
01024 
01025         for (i = last+1; i < read_list[j]; i++) {    /* skip unwanted data */
01026             while (input_line[p] > ' ') p++;
01027             while (input_line[p] <= ' ') p++;
01028         }
01029 
01030         /* Store this p for future use. */
01031 
01032         start[j] = p;
01033 
01034         /* Move to the start of the next column. */
01035 
01036         while (input_line[p] > ' ') p++;
01037         while (input_line[p] <= ' ') p++;
01038 
01039         last = read_list[j];
01040     }
01041 
01042     /* Now actually read the data. */
01043 
01044     for (j = 0; j < nread; j++)
01045         if (sscanf(input_line+start[j], "%f", temp+j) <= 0) return 0;
01046 
01047     /* Optionally print out the line only if we were successful in
01048      * reading it.
01049      */
01050 
01051     if (output) {
01052         printf("%s", input_line);
01053         fflush(stdout);
01054     }
01055 
01056     /* Redistribute the data. */
01057 
01058     *x = temp[index[0]];
01059 
01060     for (j = 0; j < params->ny; j++) *(y+j*arr_size) = temp[index[j+1]];
01061 
01062     if (params->zcol > 0) *z = temp[index[params->ny+2]];
01063 
01064     params->modify = 0;
01065 
01066     return 1;
01067 }
01068 
01069 void get_data(plot_params* params,
01070               float* x, float* y, float* z, int* n)
01071 {
01072     /* Read the input data. Note that the remainder of each input
01073      * line is discarded once the desired columns are read in.
01074      * The current read is terminated on encountering EOF or an
01075      * unreadable line (readxyz returns 0).
01076      */
01077 
01078     /* To avoid wasting too much space, we probably should buffer the
01079      * input and use malloc to increase the array sizes in the case
01080      * arr_size = NMAX (limits_from_data = 1)...
01081      *
01082      * Note also: y is actually a 2D array, with ny rows, each of length,
01083      * n, stored in a rectangular grid of total declared length arr_size.
01084      */
01085 
01086     params->modify = 1;
01087     *n = 0;
01088 
01089     while (*n < arr_size && readxyz(params, x + *n, y + *n, z + *n,
01090                                     params->output)) {
01091 
01092 #if 0
01093         /* This version would just echo the columns being plotted.
01094            Probably better to echo everything, do plot_data can be
01095            used in a pipeline. */
01096 
01097         if (params->output) {
01098             int j;
01099             printf("%f", *(x+*n));
01100             for (j = 0; j < params->ny; j++) printf(" %f", *(y+j*arr_size+*n));
01101             if (params->zcol > 0) printf(" %f", *(z+*n));
01102             printf("\n");
01103         }
01104 #endif
01105 
01106         (*n)++;
01107     }
01108 }
01109 
01110 void crop(float*x, float xmin, float xmax)
01111 {
01112     if (*x < xmin) *x = xmin;
01113     if (*x > xmax) *x = xmax;
01114 }
01115 
01116 void crop_data(plot_params* params, float* x, float* y, int n)
01117 {
01118     int i;
01119     for (i = 0; i < n; i++) {
01120         if (params->crop_x) crop(x+i, params->lims.xmin, params->lims.xmax);
01121         if (params->crop_y) crop(y+i, params->lims.ymin, params->lims.ymax);
01122     }
01123 }
01124 
01125 void wrap(float*x, float xmin, float xmax)
01126 {
01127     float dx = xmax - xmin;
01128     if (dx <= 0) return;
01129 
01130     while (*x < xmin) *x += dx;
01131     while (*x > xmax) *x -= dx;
01132 }
01133 
01134 void wrap_data(plot_params* params, float* x, float* y, int n)
01135 {
01136     int i;
01137     for (i = 0; i < n; i++) {
01138         if (params->wrap_x) wrap(x+i, params->lims.xmin, params->lims.xmax);
01139         if (params->wrap_y) wrap(y+i, params->lims.ymin, params->lims.ymax);
01140     }
01141 }
01142 
01143 int decode_color(Window xwin, float z)
01144 {
01145     /* Completely arbitrary color scheme:
01146 
01147                 0 = white
01148                 1 = black
01149                 2 = red
01150                 3 = green
01151                 4 = blue
01152                 5 = yellow
01153                 6 = orange
01154                 7 = purple
01155                 8 = cyan
01156                 9 = grey
01157     */
01158 
01159     if (z < 0) z = -z;
01160     while (z > 9.5) z -= 10;
01161 
01162     if (z < 0.5)      return lux_lookup_color(xwin, "white");
01163     else if (z < 1.5) return lux_lookup_color(xwin, "black");
01164     else if (z < 2.5) return lux_lookup_color(xwin, "red");
01165     else if (z < 3.5) return lux_lookup_color(xwin, "green");
01166     else if (z < 4.5) return lux_lookup_color(xwin, "blue");
01167     else if (z < 5.5) return lux_lookup_color(xwin, "yellow");
01168     else if (z < 6.5) return lux_lookup_color(xwin, "orange");
01169     else if (z < 7.5) return lux_lookup_color(xwin, "purple");
01170     else if (z < 8.5) return lux_lookup_color(xwin, "cyan");
01171     else if (z < 9.5) return lux_lookup_color(xwin, "grey");
01172     else              return lux_lookup_color(xwin, "black");
01173 }
01174 
01175 void plot_points(plot_params* params, float* x, float* y, int n)
01176 {
01177     /* Plot one or more points in the desired style.
01178      * Note: point_size here is point size in x units.
01179      */
01180 
01181     if (params->point_size <= 0.0)
01182 
01183             lux_draw_pointsf(params->xwin, x, y, n, 0);
01184 
01185     else {
01186 
01187         int i;
01188         for (i = 0; i < n; i++)
01189                 lux_draw_arcf(params->xwin,
01190                               x[i] - params->point_size/2,
01191                               y[i] - params->point_size/2, 
01192                               params->point_size,
01193                               params->point_size * params->yscale,
01194                               0.0, 360.0);
01195     }
01196 
01197 /*  lux_flush(win); */          /* Appears unnecessary, so long as the
01198                                    program generating the data forces
01199                                    output and flushes the data properly. */
01200 
01201 }
01202 
01203 #include <sys/time.h>
01204 #include <unistd.h>
01205 #include <stdlib.h>
01206 
01207 /* In general, UNIX systems are very vague about what value is assigned
01208    to RAND_MAX.  For the old rand() function, it was 32767.  However, this
01209    been superseded by random(), which should have RAND_MAX = 2147483647.
01210    Unfortunately, even in systems with the new random(), the old value of
01211    RAND_MAX is often still defined (e.g. DEC UNIX, Solaris 2,...).  For
01212    our purposes here, it doesn't much matter, but it *is* important that
01213    a properly normalized final result be obtained. */
01214 
01215 float myrandom()
01216 {
01217     int i = random() % RAND_MAX;
01218     return ((float)i) / RAND_MAX;
01219 }
01220 
01221 #define XOR_MIN         75
01222 #define XOR_RANGE       100
01223 #define YOR_MIN         75
01224 #define YOR_RANGE       100
01225 
01226 void randomize_origin(plot_params* params)
01227 {
01228     struct timeval tv;
01229 
01230     gettimeofday(&tv, NULL);
01231     srandom((unsigned int)(tv.tv_usec * tv.tv_usec));
01232 
01233     if (params->xorigin == -1)
01234         params->xorigin = XOR_MIN + (int)(XOR_RANGE*myrandom());
01235 
01236     if (params->yorigin == -1)
01237         params->yorigin = YOR_MIN + (int)(YOR_RANGE*myrandom());
01238 }
01239 
01240 void initialize_params(int argc, char** argv, plot_params* params)
01241 {
01242    /* Set default plotting parameters: */
01243 
01244     params->xwin = 0;
01245 
01246     params->xcol = 1;
01247     params->nmax = NMAX;
01248     params->ycol[0] = 2;
01249     params->ny = 1;                     /* Only 1 y column            */
01250     params->zcol = 0;                   /* No z-coloring              */
01251 
01252     params->lines = 1;                  /* Plot lines                 */
01253     params->point_size = 0.0;           /* Point size (0 ==> 1 pixel) */
01254     params->ntrail = 0;                 /* No trails                  */
01255     params->xsave = NULL;
01256     params->ysave = NULL;
01257     params->output = 0;                 /* Don't pass data to stdout  */
01258 
01259     params->xlabel[0] = '\0';
01260     params->xlabel_set = 0;
01261     params->ylabel[0] = '\0';
01262     params->ylabel_set = 0;
01263     params->header[0] = '\0';           /* No overall label           */
01264 
01265     strcpy(params->color[0], "black");
01266     params->icolor[0] = 1;
01267     params->ibox = 1;
01268     params->iback = 0;                  /* Always 0 since I can't change it! */
01269     params->curr_color = 1;
01270 
01271     params->limits_from_data = 1;       /* Get limits from input data */
01272 
01273     params->lims.xmin_from_data = 1;
01274     params->lims.xmax_from_data = 1;
01275     params->lims.ymin_from_data = 1;
01276     params->lims.ymax_from_data = 1;
01277 
01278     params->lims.xmin = 0;
01279     params->lims.xmax = 1;
01280     params->lims.ymin = 0;
01281     params->lims.ymax = 1;
01282 
01283     params->crop_data = 0;
01284     params->crop_x = 0;
01285     params->crop_y = 0;
01286 
01287     params->wrap_data = 0;
01288     params->wrap_x = 0;
01289     params->wrap_y = 0;
01290 
01291     params->yscale = 0.0;
01292 
01293     params->xorigin = -1;
01294     params->yorigin = -1;
01295     params->xsize = 400;
01296     params->ysize = 400;
01297 
01298     params->skip = 0;
01299     params->ignore_inline = 0;
01300     params->quiet = 0;
01301     params->modify = 1;
01302     params->pause = 0;
01303 
01304     params->echo = 0;
01305 
01306     parse_command_line(argc, argv, params);
01307     
01308     if (params->xorigin == -1 || params->yorigin == -1)
01309         randomize_origin(params);
01310 }
01311 
01312 main(int argc, char* argv[])
01313 {
01314     int n, nt = 0;
01315     float *x, *y, *z;
01316     float tempx[2], tempy[NYMAX][2], tempz;   /* Used in connecting segments */
01317     int i, j;
01318     int erase = 0, save = 0;
01319     int nread = NBUFFER;
01320 
01321     /* Initialize all parameters. */
01322 
01323     plot_params params;
01324     initialize_params(argc, argv, &params);
01325 
01326     /* Echo some input data. */
01327 
01328     if (!params.quiet) {
01329         fprintf(stderr, "xcol = %d\n", params.xcol);
01330         fprintf(stderr, "ycol =");
01331         for (j = 0; j < params.ny; j++) fprintf(stderr, " %d (%s) ",
01332                                                params.ycol[j], params.color[j]);
01333         fprintf(stderr, "\n");
01334         fprintf(stderr, "%s, ", (params.lines ? "line mode" : "point mode"));
01335         if (params.ntrail)
01336             fprintf(stderr, "ntrail = %d\n", params.ntrail);
01337         else
01338             fprintf(stderr, "no trails\n");
01339         if (params.limits_from_data)
01340           fprintf(stderr, "Getting (some) plot limits from input data...\n");
01341     }
01342 
01343     if (params.ntrail > 0) {
01344         if (params.limits_from_data)
01345             err_exit("Inconsistent parameters limits_from_data and ntrail.");
01346 
01347         allocate_save(&params);
01348     }
01349 
01350     if (params.xsave) nread = 1;        /* Plot data point by point */
01351 
01352     if (params.limits_from_data)
01353         arr_size = params.nmax;         /* Probably should reduce this    */
01354                                         /* and expand buffer as needed... */
01355     else
01356         arr_size = nread;
01357 
01358     init_arr_size = arr_size;
01359 
01360     /* Establish sufficient storage for all data arrays. */
01361 
01362     if ((x = (float*)malloc(arr_size*sizeof(float))) == NULL)
01363         err_exit("Can't allocate x-storage space.");
01364     if ((y = (float*)malloc(NYMAX*arr_size*sizeof(float))) == NULL)
01365         err_exit("Can't allocate y-storage space.");
01366     if ((z = (float*)malloc(arr_size*sizeof(float))) == NULL)
01367         err_exit("Can't allocate z-storage space.");
01368 
01369     /* NOTE that we will have to use ugly explicit pointer notation
01370        below because y and ysave are not declared as 2-D arrays... */
01371 
01372     /* Establish default labels if none specified. */
01373 
01374     create_labels(&params);
01375 
01376     if (params.skip) {
01377         skip_lines(params.skip, params.output);
01378         params.skip = 0;
01379     }
01380 
01381     if (params.echo) echo_parameters(&params);
01382 
01383     if (params.limits_from_data) {
01384 
01385         /* Obtain limits from data in advance of plotting anything.
01386          * Note that, in this case, inline control statements are ignored.
01387          */
01388 
01389         get_data(&params, x, y, z, &n);
01390         if (n <= 0) exit(1);
01391 
01392         if (!params.quiet)
01393             fprintf(stderr, "Read %d points from standard input\n", n);
01394 
01395         get_limits(x, y, n, &params);
01396 
01397         if (params.lims.xmin >= params.lims.xmax
01398             || params.lims.ymin >= params.lims.ymax) {
01399             fprintf(stderr, "Inconsistent limits: %f %f %f %f\n",
01400                     params.lims.xmin,params.lims.xmax,
01401                     params.lims.ymin, params.lims.ymax);
01402             exit(1);
01403         }
01404     }
01405 
01406     in_line = 1;
01407 
01408     params.yscale = (params.lims.ymax - params.lims.ymin)
01409                         / (params.lims.xmax - params.lims.xmin);
01410 
01411     /* Plot the data. */
01412 
01413     if (set_up_window(&params) <= 0)
01414 
01415         fprintf(stderr, "Error opening X-window!\n");
01416 
01417     else {
01418 
01419         /* Establish colors, now that X is properly initialized. */
01420 
01421         params.ibox = lux_lookup_color(params.xwin, "black");
01422         params.iback = lux_lookup_color(params.xwin, "white");
01423         for (j = 0; j < params.ny; j++)
01424             params.icolor[j] = lux_lookup_color(params.xwin, params.color[j]);
01425 
01426         lux_set_color(params.xwin, params.curr_color);
01427 
01428         /* Two-in-one loop:  Read and plot, or just plot, the data. */
01429 
01430         if (!params.limits_from_data) n = 1;    /* Just to initialize... */
01431 
01432         while (n > 0) {
01433 
01434             /* Read the next block of data, if we don't already have it.
01435              * Note that normally the data are buffered for efficiency.
01436              * In the case of "trailing" points, we read the data point
01437              * by point.
01438              */
01439 
01440             if (!params.limits_from_data) {
01441                 get_data(&params, x, y, z, &n);
01442                 if (params.crop_data)
01443                     crop_data(&params, x, y, n);
01444                 else if (params.wrap_data)
01445                     wrap_data(&params, x, y, n);
01446             }
01447 
01448             if (n > 0) {
01449 
01450                 if (params.lines) {
01451 
01452                     /* ----------  Drawing lines  ---------- */
01453 
01454                     if (params.ntrail > 0 && erase) {
01455 
01456                         /* Erase a previous line segment. */
01457 
01458                         params.curr_color = params.iback;
01459                         lux_set_color(params.xwin, params.curr_color);
01460 
01461                         if (save == params.ntrail - 1) {
01462 
01463                             float erasex[2], erasey[2];
01464 
01465                             erasex[0] = *(params.xsave+save);
01466                             erasex[1] = *(params.xsave);
01467                             for (j = 0; j < params.ny; j++) {
01468                                 erasey[0] = *(params.ysave
01469                                               + j*params.ntrail+save);
01470                                 erasey[1] = *(params.ysave
01471                                               + j*params.ntrail);
01472                                 lux_draw_linesf(params.xwin,
01473                                                 erasex, erasey, 2, 0);
01474                             }
01475 
01476                         } else
01477 
01478                             for (j = 0; j < params.ny; j++)
01479                                 lux_draw_linesf(params.xwin, params.xsave+save,
01480                                                 params.ysave
01481                                                   + j*params.ntrail+save,
01482                                                 2, 0);
01483                     }
01484 
01485                     if (nt == 2) {
01486 
01487                         /* Connect to the ends of the previous lines, setting
01488                            color from the z-array if necessary. */
01489 
01490                         if (params.zcol > 0) {
01491                             params.curr_color = decode_color(params.xwin,
01492                                                              tempz);
01493                             lux_set_color(params.xwin, params.curr_color);
01494                         }
01495 
01496                         tempx[1] = x[0];
01497                         for (j = 0; j < params.ny; j++) {
01498 
01499                             if (params.zcol <= 0
01500                                 && params.icolor[j] != params.curr_color) {
01501                                 params.curr_color = params.icolor[j];
01502                                 lux_set_color(params.xwin, params.curr_color);
01503                             }
01504 
01505                             tempy[j][1] = *(y+j*arr_size);
01506                             lux_draw_linesf(params.xwin,
01507                                             tempx, &tempy[j][0], nt, 0);
01508                         }
01509                     }
01510 
01511                     /* Plot the new line segments. */
01512 
01513                     if (params.zcol <= 0)
01514 
01515                         for (j = 0; j < params.ny; j++) {
01516 
01517                             if (params.icolor[j] != params.curr_color) {
01518                                 params.curr_color = params.icolor[j];
01519                                 lux_set_color(params.xwin, params.curr_color);
01520                             }
01521 
01522                             lux_draw_linesf(params.xwin, x, y+j*arr_size,
01523                                             n, 0);
01524                         }
01525 
01526                     else {
01527 
01528                         /* Plot point by point, selecting color
01529                            from the z array. */
01530 
01531                         for (i = 1; i < n; i++) {
01532                             int ic;
01533 
01534                             if ((ic  = decode_color(params.xwin, z[i-1]))
01535                                   != params.curr_color) {
01536                                 params.curr_color = ic;
01537                                 lux_set_color(params.xwin, params.curr_color);
01538                             }
01539 
01540                             for (j = 0; j < params.ny; j++)
01541                                 lux_draw_linesf(params.xwin,
01542                                                 x+i-1, y+j*arr_size+i-1, 2, 0);
01543                         }
01544                     }
01545 
01546                 } else {
01547 
01548                     /* ----------  Drawing points only  ---------- */
01549 
01550                     if (params.ntrail > 0 && erase) {
01551 
01552                         /* Erase a previous point. */
01553 
01554                         params.curr_color = params.iback;
01555                         lux_set_color(params.xwin, params.curr_color);
01556 
01557                         for (j = 0; j < params.ny; j++)
01558                             plot_points(&params, params.xsave+save,
01559                                         params.ysave+j*params.ntrail+save, 1);
01560                     }
01561 
01562                     if (params.zcol <= 0)
01563 
01564                         for (j = 0; j < params.ny; j++) {
01565 
01566                             if (params.icolor[j] != params.curr_color) {
01567                                 params.curr_color = params.icolor[j];
01568                                 lux_set_color(params.xwin, params.curr_color);
01569                             }
01570 
01571                             plot_points(&params, x, y + j*arr_size, n);
01572                         }
01573 
01574                     else {
01575 
01576                         /* Plot point by point, selecting color
01577                            from the z array. */
01578 
01579                         for (i = 0; i < n; i++) {
01580                             int ic;
01581 
01582                             if ((ic  = decode_color(params.xwin, z[i]))
01583                                   != params.curr_color) {
01584                                 params.curr_color = ic;
01585                                 lux_set_color(params.xwin, params.curr_color);
01586                             }
01587 
01588                             for (j = 0; j < params.ny; j++)
01589                                 plot_points(&params, x + i,
01590                                             y + j*arr_size + i, 1);
01591                         }
01592                     }
01593                 }
01594 
01595                 /* Check for expose/resize events and refresh the display. */
01596 
01597                 win_checkevent(params.xwin);
01598 
01599                 if (params.ntrail > 0) {
01600                         
01601                     /* Save past data in a circular buffer. */
01602 
01603                     *(params.xsave+save) = x[0];
01604                     for (j = 0; j < params.ny; j++)
01605                         *(params.ysave+j*params.ntrail+save) = *(y+j*arr_size);
01606 
01607                     if (++save >= params.ntrail) {
01608                         erase = 1;
01609                         save = 0;
01610                     }
01611                 }
01612 
01613             }   /* End of "if (n > 0)..." */
01614 
01615             if (params.limits_from_data) {
01616 
01617                 /* Time to quit. */
01618 
01619                 n = 0;          /* This will force exit from the while loop */
01620 
01621             } else {
01622 
01623                 /* Save last point for connection to next segment. */
01624 
01625                 nt = 2;
01626                 tempx[0] = x[n-1];
01627                 for (j = 0; j < params.ny; j++)
01628                     tempy[j][0] = *(y+j*arr_size+n-1);
01629                 tempz = z[n-1];
01630             }
01631         }
01632 
01633         /* Clean up only at end (quite expensive!).
01634            Redraw the box in case it was partly erased. */
01635 
01636         if (params.curr_color != params.ibox)
01637             lux_set_color(params.xwin, params.ibox);
01638 
01639         lux_draw_axis(params.xwin);
01640 
01641         if (params.curr_color != params.ibox)
01642             lux_set_color(params.xwin, params.curr_color);
01643 
01644         if (params.output) fclose(stdout);
01645 
01646         /* Enter idle mode before quitting. */
01647 
01648         fprintf(stderr,
01649                 "Press any key in display window to quit current plot\n");
01650         while(!win_getkey(params.xwin));
01651 
01652     }
01653 }

Generated at Sun Feb 24 09:57:11 2002 for STARLAB by doxygen1.2.6 written by Dimitri van Heesch, © 1997-2001