00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
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
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;
00052
00053 int xcol;
00054 int nmax;
00055 int ycol[NYMAX];
00056 int ny;
00057 int zcol;
00058
00059 int lines;
00060 float point_size;
00061 int ntrail;
00062 float* xsave;
00063 float* ysave;
00064 int output;
00065
00066 char xlabel[256];
00067 int xlabel_set;
00068 char ylabel[256];
00069 int ylabel_set;
00070 char header[256];
00071
00072 char color[NYMAX][16];
00073 int icolor[NYMAX];
00074 int ibox;
00075 int iback;
00076 int curr_color;
00077
00078 int limits_from_data;
00079 limits lims;
00080
00081 int crop_data;
00082 int crop_x;
00083 int crop_y;
00084 int wrap_data;
00085 int wrap_x;
00086 int wrap_y;
00087 float yscale;
00088
00089 int xorigin;
00090 int yorigin;
00091 int xsize;
00092 int ysize;
00093
00094 int quiet;
00095 int ignore_inline;
00096 int skip;
00097
00098 int modify;
00099 int pause;
00100
00101 int echo;
00102
00103 } plot_params;
00104
00105 static int init_arr_size, arr_size;
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
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
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')
00230 params->crop_x = 1;
00231 else if (argv[i][2] == 'y')
00232 params->crop_y = 1;
00233 else if (argv[i][2] == 'c') {
00234 if (argv[i][3] == 'x')
00235 params->crop_x = 0;
00236 else if (argv[i][3] == 'y')
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 ¶ms->lims.xmin_from_data,
00315 ¶ms->lims.xmin);
00316
00317 if (i < argc-1)
00318 set_or_flag(argv[++i],
00319 ¶ms->lims.xmax_from_data,
00320 ¶ms->lims.xmax);
00321
00322 if (i < argc-1)
00323 set_or_flag(argv[++i],
00324 ¶ms->lims.ymin_from_data,
00325 ¶ms->lims.ymin);
00326
00327 if (i < argc-1)
00328 set_or_flag(argv[++i],
00329 ¶ms->lims.ymax_from_data,
00330 ¶ms->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(¶ms->lims.xmax,
00337 ¶ms->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(¶ms->lims.ymax,
00344 ¶ms->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;
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;
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')
00444 params->wrap_x = 1;
00445 else if (argv[i][2] == 'y')
00446 params->wrap_y = 1;
00447 else if (argv[i][2] == 'w') {
00448 if (argv[i][3] == 'x')
00449 params->wrap_x = 0;
00450 else if (argv[i][3] == 'y')
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
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];
00591
00592
00593
00594
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
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
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
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
00640
00641 char xlabel[256], ylabel[256];
00642
00643 if (!params->limits_from_data) {
00644
00645 int xcol, ycol[NYMAX], zcol, iy, ny, ntrail;
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
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
00675
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
00689
00690
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
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
00742
00743
00744 dx = 0.05 * (*xmax - *xmin);
00745
00746
00747
00748 dy = log10(dx);
00749 idy = dy + 0.5;
00750 if (dy < -0.5) idy = idy - 1;
00751
00752
00753
00754
00755
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
00766
00767
00768
00769
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
00779 }
00780
00781 void get_limits(float* x, float* y, int n, plot_params* params)
00782 {
00783
00784
00785
00786 int i, j;
00787
00788
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
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
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
00851
00852
00853
00854
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
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
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
00891
00892
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
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919 char input_line[MAX_LINE], *c;
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929 if (fgets(input_line, MAX_LINE, stdin) <= 0) return 0;
00930
00931
00932
00933
00934
00935
00936
00937
00938 while (input_line[0] == '-' && input_line[1] >= 'A') {
00939
00940
00941
00942
00943
00944
00945 if (!params->ignore_inline &&
00946 !params->limits_from_data &&
00947 !params->modify) {
00948
00949
00950
00951 params->modify = 1;
00952 return 0;
00953 }
00954
00955
00956
00957
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
00965
00966 if (params->xwin > 0) win_checkevent(params->xwin);
00967
00968
00969
00970 if (fgets(input_line, MAX_LINE, stdin) <= 0) return 0;
00971 }
00972
00973
00974
00975 for (c = input_line; *c != '\0'; c++)
00976 if (*c == ',') *c = ' ';
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998 if (col_init < 0) {
00999 sort_columns(params, read_list, &nread, index);
01000 col_init = 1;
01001 }
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013 len = strlen(input_line);
01014
01015
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++) {
01026 while (input_line[p] > ' ') p++;
01027 while (input_line[p] <= ' ') p++;
01028 }
01029
01030
01031
01032 start[j] = p;
01033
01034
01035
01036 while (input_line[p] > ' ') p++;
01037 while (input_line[p] <= ' ') p++;
01038
01039 last = read_list[j];
01040 }
01041
01042
01043
01044 for (j = 0; j < nread; j++)
01045 if (sscanf(input_line+start[j], "%f", temp+j) <= 0) return 0;
01046
01047
01048
01049
01050
01051 if (output) {
01052 printf("%s", input_line);
01053 fflush(stdout);
01054 }
01055
01056
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
01073
01074
01075
01076
01077
01078
01079
01080
01081
01082
01083
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
01094
01095
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
01146
01147
01148
01149
01150
01151
01152
01153
01154
01155
01156
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
01178
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
01198
01199
01200
01201 }
01202
01203 #include <sys/time.h>
01204 #include <unistd.h>
01205 #include <stdlib.h>
01206
01207
01208
01209
01210
01211
01212
01213
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
01243
01244 params->xwin = 0;
01245
01246 params->xcol = 1;
01247 params->nmax = NMAX;
01248 params->ycol[0] = 2;
01249 params->ny = 1;
01250 params->zcol = 0;
01251
01252 params->lines = 1;
01253 params->point_size = 0.0;
01254 params->ntrail = 0;
01255 params->xsave = NULL;
01256 params->ysave = NULL;
01257 params->output = 0;
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';
01264
01265 strcpy(params->color[0], "black");
01266 params->icolor[0] = 1;
01267 params->ibox = 1;
01268 params->iback = 0;
01269 params->curr_color = 1;
01270
01271 params->limits_from_data = 1;
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;
01317 int i, j;
01318 int erase = 0, save = 0;
01319 int nread = NBUFFER;
01320
01321
01322
01323 plot_params params;
01324 initialize_params(argc, argv, ¶ms);
01325
01326
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(¶ms);
01348 }
01349
01350 if (params.xsave) nread = 1;
01351
01352 if (params.limits_from_data)
01353 arr_size = params.nmax;
01354
01355 else
01356 arr_size = nread;
01357
01358 init_arr_size = arr_size;
01359
01360
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
01370
01371
01372
01373
01374 create_labels(¶ms);
01375
01376 if (params.skip) {
01377 skip_lines(params.skip, params.output);
01378 params.skip = 0;
01379 }
01380
01381 if (params.echo) echo_parameters(¶ms);
01382
01383 if (params.limits_from_data) {
01384
01385
01386
01387
01388
01389 get_data(¶ms, 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, ¶ms);
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
01412
01413 if (set_up_window(¶ms) <= 0)
01414
01415 fprintf(stderr, "Error opening X-window!\n");
01416
01417 else {
01418
01419
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
01429
01430 if (!params.limits_from_data) n = 1;
01431
01432 while (n > 0) {
01433
01434
01435
01436
01437
01438
01439
01440 if (!params.limits_from_data) {
01441 get_data(¶ms, x, y, z, &n);
01442 if (params.crop_data)
01443 crop_data(¶ms, x, y, n);
01444 else if (params.wrap_data)
01445 wrap_data(¶ms, x, y, n);
01446 }
01447
01448 if (n > 0) {
01449
01450 if (params.lines) {
01451
01452
01453
01454 if (params.ntrail > 0 && erase) {
01455
01456
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
01488
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
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
01529
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
01549
01550 if (params.ntrail > 0 && erase) {
01551
01552
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(¶ms, 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(¶ms, x, y + j*arr_size, n);
01572 }
01573
01574 else {
01575
01576
01577
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(¶ms, x + i,
01590 y + j*arr_size + i, 1);
01591 }
01592 }
01593 }
01594
01595
01596
01597 win_checkevent(params.xwin);
01598
01599 if (params.ntrail > 0) {
01600
01601
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 }
01614
01615 if (params.limits_from_data) {
01616
01617
01618
01619 n = 0;
01620
01621 } else {
01622
01623
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
01634
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
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 }