00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095 #ifdef HAVE_CONFIG_H
00096 # include <config.h>
00097 #endif
00098
00099
00121
00122
00123
00124 #if defined HAVE_SETENV && HAVE_SETENV
00125 #if defined HAVE_DECL_SETENV && !HAVE_DECL_SETENV
00126 int setenv(const char *name, const char *value, int overwrite);
00127 #endif
00128 #endif
00129
00130
00131
00132
00133
00134 #include <uves_plot.h>
00135
00136 #include <uves_dump.h>
00137 #include <uves_utils_wrappers.h>
00138 #include <uves_error.h>
00139 #include <uves_msg.h>
00140
00141 #include <irplib_plot.h>
00142 #include <irplib_utils.h>
00143
00144 #include <cpl.h>
00145
00146 #include <stdarg.h>
00147 #include <stdio.h>
00148 #include <string.h>
00149 #include <stdlib.h>
00150
00151
00152
00153
00154 static char *title_string(const char *title, int npoints);
00155
00156
00157
00158 #define MAXTITLELENGTH 10000
00159 #define RECOVER_FROM_ERROR(EXTERNAL_COMMAND) do { \
00160 if (cpl_error_get_code() != CPL_ERROR_NONE) \
00161 { \
00162 uves_msg_error("Could not send plot to " \
00163 "command '%s': " \
00164 "%s in '%s'", \
00165 EXTERNAL_COMMAND, \
00166 cpl_error_get_message(), \
00167 cpl_error_get_where()); \
00168 cpl_error_reset(); \
00169 goto cleanup; \
00170 } } while (false)
00171
00172
00173 static char title[MAXTITLELENGTH];
00174 static bool plotting_enabled = false;
00175
00176
00177 static const char *plotter = "";
00178
00181
00182
00183
00184
00185
00197
00198 cpl_error_code
00199 uves_plot_initialize(const char *plotter_command)
00200 {
00201 char *test_cmd = NULL;
00202 char *first_word = NULL;
00203
00204 plotting_enabled = (strcmp(plotter_command, "no") != 0);
00205
00206
00207
00208
00209
00210 if (plotting_enabled)
00211 {
00212 const char *env = "CPL_PLOTTER";
00213
00214
00215
00216
00217
00218
00219
00220 first_word = uves_sprintf("%s ", plotter_command);
00221
00222 assure( strtok(first_word, " ") != NULL, CPL_ERROR_ILLEGAL_OUTPUT,
00223 "Error splitting string '%s'", first_word);
00224
00225 test_cmd = uves_sprintf("which %s > /dev/null", first_word);
00226
00227 #if defined HAVE_SETENV && HAVE_SETENV
00228
00229 if (setenv(env, plotter_command, 1) != 0)
00230 {
00231 uves_msg_warning("Could not set environment variable '%s'. "
00232 "Plotting disabled!", env);
00233 plotting_enabled = false;
00234 }
00235
00236
00237
00238
00239
00240
00241 else if (system(test_cmd) != 0)
00242 {
00243 uves_msg_debug("Command '%s' returned non-zero", test_cmd);
00244 uves_msg_warning("Command '%s' failed. Plotting disabled!", test_cmd);
00245 plotting_enabled = false;
00246 }
00247 else
00248 {
00249
00250 uves_msg_debug("setenv %s='%s' succeeded", env, plotter_command);
00251 uves_msg_debug("Command '%s' returned zero", test_cmd);
00252
00253 plotter = plotter_command;
00254 }
00255 #else
00256 uves_msg_warning("setenv() is not available on this platform. You have to manually "
00257 "set the environment variable '%s' to '%s'", env, plotter_command);
00258
00259 plotter = plotter_command;
00260
00261 #endif
00262 }
00263
00264 cleanup:
00265 cpl_free(test_cmd);
00266 cpl_free(first_word);
00267
00268 return cpl_error_get_code();
00269 }
00270
00271
00286
00287 cpl_error_code
00288 uves_plot_image_rows(const cpl_image *image, int first_row, int last_row, int step,
00289 const char *xtitle, const char *ytitle, const char *format, ...)
00290 {
00291 va_list al;
00292
00293 char *pre = NULL;
00294 char *options = NULL;
00295 const char *post = "";
00296 cpl_image *thresholded = NULL;
00297
00298 assure( image != NULL, CPL_ERROR_NULL_INPUT, "Null image");
00299 if (xtitle == NULL) xtitle = "";
00300 if (ytitle == NULL) ytitle = "";
00301 assure( 1 <= first_row && first_row <= last_row &&
00302 last_row <= cpl_image_get_size_y(image),
00303 CPL_ERROR_ILLEGAL_INPUT,
00304 "Illegal rows: %d - %d; rows in image = %d",
00305 first_row, last_row, cpl_image_get_size_y(image));
00306
00307 assure( step >= 1, CPL_ERROR_ILLEGAL_INPUT,
00308 "Illegal step size: %d", step);
00309
00310 if (plotting_enabled)
00311 {
00312 const char *pre_format;
00313 int row;
00314
00315
00316 pre_format = "set grid; set xlabel '%s'; set ylabel '%s';";
00317 pre = cpl_calloc(strlen(pre_format) +
00318 strlen(xtitle) + strlen(ytitle) + 1,
00319 sizeof(char));
00320 sprintf(pre, pre_format, xtitle, ytitle);
00321
00322
00323 va_start(al, format);
00324 vsnprintf(title, MAXTITLELENGTH - 1, format, al);
00325 va_end(al);
00326 title[MAXTITLELENGTH - 1] = '\0';
00327
00328 options = title_string(title, cpl_image_get_size_x(image));
00329
00330
00331 thresholded = cpl_image_duplicate(image);
00332 for (row = first_row; row <= last_row; row++)
00333 {
00334 int nx = cpl_image_get_size_x(thresholded);
00335 double median = cpl_image_get_median_window(thresholded,
00336 1, first_row,
00337 nx, last_row);
00338 double stdev = cpl_image_get_stdev_window(thresholded,
00339 1, first_row,
00340 nx, last_row);
00341
00342 double locut = median - 3*stdev;
00343 double hicut = median + 3*stdev;
00344
00345 int x, pis_rejected;
00346
00347 for (x = 1; x <= nx; x++)
00348 {
00349 double data =
00350 cpl_image_get(thresholded, x, row, &pis_rejected);
00351 if (data < locut) data = locut;
00352 if (data > hicut) data = hicut;
00353 cpl_image_set(thresholded, x, row, data);
00354 }
00355 }
00356
00357 irplib_image_row_plot(pre,
00358 (strcmp(options, "t '%s'") == 0) ? "" : options,
00359 post,
00360 thresholded,
00361 first_row, last_row, step);
00362
00363 RECOVER_FROM_ERROR(plotter);
00364 }
00365
00366 cleanup:
00367 uves_free_image(&thresholded);
00368 cpl_free(pre);
00369 cpl_free(options);
00370
00371 return cpl_error_get_code();
00372 }
00373
00374
00392
00393 cpl_error_code
00394 uves_plot_image_columns(const cpl_image *image, int first_column, int last_column, int step,
00395 const char *xtitle, const char *ytitle, const char *format, ...)
00396 {
00397 va_list al;
00398
00399 char *pre = NULL;
00400 char *options = NULL;
00401 const char *post = "";
00402 cpl_image *thresholded = NULL;
00403
00404 assure( image != NULL, CPL_ERROR_NULL_INPUT, "Null image");
00405 if (xtitle == NULL) xtitle = "";
00406 if (ytitle == NULL) ytitle = "";
00407 assure( 1 <= first_column && first_column <= last_column &&
00408 last_column <= cpl_image_get_size_x(image),
00409 CPL_ERROR_ILLEGAL_INPUT,
00410 "Illegal columns: %d - %d; columns in image = %d",
00411 first_column, last_column, cpl_image_get_size_x(image));
00412
00413 assure( step >= 1, CPL_ERROR_ILLEGAL_INPUT,
00414 "Illegal step size: %d", step);
00415
00416 if (plotting_enabled)
00417 {
00418 const char *pre_format;
00419 int col;
00420
00421
00422 pre_format = "set grid; set xlabel '%s'; set ylabel '%s';";
00423 pre = cpl_calloc(strlen(pre_format) +
00424 strlen(xtitle) + strlen(ytitle) + 1,
00425 sizeof(char));
00426 sprintf(pre, pre_format, xtitle, ytitle);
00427
00428 va_start(al, format);
00429 vsnprintf(title, MAXTITLELENGTH - 1, format, al);
00430 va_end(al);
00431 title[MAXTITLELENGTH - 1] = '\0';
00432
00433 options = title_string(title, cpl_image_get_size_y(image));
00434
00435
00436 thresholded = cpl_image_duplicate(image);
00437 for (col = first_column; col <= last_column; col++)
00438 {
00439 int ny = cpl_image_get_size_x(thresholded);
00440 double median = cpl_image_get_median_window(thresholded,
00441 first_column, 1,
00442 last_column, ny);
00443 double stdev = cpl_image_get_stdev_window(thresholded,
00444 first_column, 1,
00445 last_column, ny);
00446
00447 double locut = median - 3*stdev;
00448 double hicut = median + 3*stdev;
00449
00450 int y, pis_rejected;
00451
00452 for (y = 1; y <= ny; y++)
00453 {
00454 double data = cpl_image_get(thresholded, col, y, &pis_rejected);
00455 if (data < locut) data = locut;
00456 if (data > hicut) data = hicut;
00457 cpl_image_set(thresholded, col, y, data);
00458 }
00459 }
00460
00461
00462 check( irplib_image_col_plot(pre,
00463 (strcmp(options, "t '%s'") == 0) ? "" : options,
00464 post,
00465 image,
00466 first_column, last_column, step),
00467 "Error plotting image");
00468
00469 RECOVER_FROM_ERROR(plotter);
00470 }
00471
00472 cleanup:
00473 uves_free_image(&thresholded);
00474 cpl_free(pre);
00475 cpl_free(options);
00476
00477 return cpl_error_get_code();
00478 }
00479
00480
00494
00495 void
00496 uves_plot_bivectors(cpl_bivector **bivectors, char **titles,
00497 int N, const char *xtitle,
00498 const char *ytitle)
00499 {
00500 char *pre = NULL;
00501 char **options = NULL;
00502 const char *post = "";
00503
00504 options = cpl_calloc(N, sizeof(char *));
00505 assure_mem( options );
00506
00507 if (plotting_enabled)
00508 {
00509 int npoints, i;
00510 cpl_bivector *temp;
00511 char *temps;
00512
00513
00514
00515 npoints = 0;
00516 for (i = 0; i < N; i++)
00517 {
00518 npoints += cpl_bivector_get_size(bivectors[i]);
00519 }
00520 for (i = 0; i < N; i++)
00521 {
00522 options[i] = title_string(titles[i], npoints);
00523 }
00524
00525
00526 {
00527 double datamax = cpl_vector_get_max(cpl_bivector_get_y(bivectors[0]));
00528 double datamin = cpl_vector_get_min(cpl_bivector_get_y(bivectors[0]));
00529
00530 double locut = datamin - 0.2*(datamax-datamin);
00531 double hicut = datamax + 0.2*(datamax-datamin);
00532
00533 for (i = 0; i < N; i++)
00534 {
00535 int j;
00536 for (j = 0; j < cpl_bivector_get_size(bivectors[i]); j++)
00537 {
00538 if (cpl_bivector_get_y_data(bivectors[i])[j] < locut)
00539 {
00540 cpl_bivector_get_y_data(bivectors[i])[j] = locut;
00541 }
00542 if (cpl_bivector_get_y_data(bivectors[i])[j] > hicut)
00543 {
00544 cpl_bivector_get_y_data(bivectors[i])[j] = hicut;
00545 }
00546 }
00547 }
00548 }
00549
00550
00551 temp = bivectors[0];
00552 bivectors[0] = bivectors[N-1];
00553 bivectors[N-1] = temp;
00554
00555 temps = options[0];
00556 options[0] = options[N-1];
00557 options[N-1] = temps;
00558
00559 pre = uves_sprintf(
00560 "set grid; set xlabel '%s'; set ylabel '%s';", xtitle, ytitle);
00561
00562 irplib_bivectors_plot(pre,
00563 (const char **)options,
00564 post,
00565 (const cpl_bivector **)bivectors, N);
00566
00567 RECOVER_FROM_ERROR(plotter);
00568 }
00569
00570 cleanup:
00571 cpl_free(pre);
00572 {
00573 int i;
00574 for (i = 0; i < N; i++)
00575 {
00576 cpl_free(options[i]);
00577 }
00578 }
00579 cpl_free(options);
00580 return;
00581 }
00582
00583
00599
00600 cpl_error_code
00601 uves_plot_table(const cpl_table *table, const char *colx, const char *coly,
00602 const char *format, ...)
00603 {
00604 va_list al;
00605
00606 char *pre = NULL;
00607 char *options = NULL;
00608 const char *post = "";
00609 cpl_table *thresholded = NULL;
00610
00611 assure( table != NULL, CPL_ERROR_NULL_INPUT, "Null table");
00612 assure( colx != NULL, CPL_ERROR_NULL_INPUT, "Null x column");
00613 assure( coly != NULL, CPL_ERROR_NULL_INPUT, "Null y column");
00614 assure( cpl_table_has_column(table, colx), CPL_ERROR_ILLEGAL_INPUT,
00615 "No such column: '%s'", colx);
00616 assure( cpl_table_has_column(table, coly), CPL_ERROR_ILLEGAL_INPUT,
00617 "No such column: '%s'", coly);
00618
00619 assure( cpl_table_get_column_type(table, colx) == CPL_TYPE_INT ||
00620 cpl_table_get_column_type(table, colx) == CPL_TYPE_FLOAT ||
00621 cpl_table_get_column_type(table, colx) == CPL_TYPE_DOUBLE,
00622 CPL_ERROR_TYPE_MISMATCH,
00623 "Column '%s' has type '%s'. Numerical type expected",
00624 colx,
00625 uves_tostring_cpl_type(cpl_table_get_column_type(table, colx)));
00626
00627 assure( cpl_table_get_column_type(table, coly) == CPL_TYPE_INT ||
00628 cpl_table_get_column_type(table, coly) == CPL_TYPE_FLOAT ||
00629 cpl_table_get_column_type(table, coly) == CPL_TYPE_DOUBLE,
00630 CPL_ERROR_TYPE_MISMATCH,
00631 "Column '%s' has type '%s'. Numerical type expected",
00632 coly,
00633 uves_tostring_cpl_type(cpl_table_get_column_type(table, coly)));
00634
00635 if (plotting_enabled)
00636 {
00637 const char *pre_format;
00638
00639
00640 va_start(al, format);
00641 vsnprintf(title, MAXTITLELENGTH - 1, format, al);
00642 va_end(al);
00643 title[MAXTITLELENGTH - 1] = '\0';
00644
00645 options = title_string(title, cpl_table_get_nrow(table));
00646
00647
00648 pre_format = "set grid; set xlabel '%s'; set ylabel '%s';";
00649 pre = cpl_calloc(strlen(pre_format) + strlen(colx) + strlen(coly) + 1,
00650 sizeof(char));
00651
00652 sprintf(pre, pre_format, colx, coly);
00653
00654
00655
00656 {
00657 double median, sigma, locut, hicut;
00658 int i;
00659
00660 median = cpl_table_get_column_median(table, coly);
00661 sigma = cpl_table_get_column_stdev(table, coly);
00662
00663 locut = median - 3*sigma;
00664 hicut = median + 3*sigma;
00665
00666
00667 thresholded = cpl_table_new(cpl_table_get_nrow(table));
00668 cpl_table_duplicate_column(thresholded, coly, table, coly);
00669 cpl_table_duplicate_column(thresholded, colx, table, colx);
00670
00671 for (i = 0; i < cpl_table_get_nrow(thresholded); i++)
00672 {
00673 double data = cpl_table_get(thresholded, coly, i, NULL);
00674
00675 if (data < locut && data > hicut)
00676 {
00677 cpl_table_set_invalid(thresholded, coly, i);
00678 }
00679 }
00680
00681 }
00682
00683 irplib_table_plot(pre,
00684 (strcmp(options, "t '%s'") == 0) ? "" : options,
00685 post,
00686 thresholded, colx, coly);
00687
00688 RECOVER_FROM_ERROR(plotter);
00689 }
00690
00691 cleanup:
00692 uves_free_table(&thresholded);
00693 cpl_free(pre);
00694 cpl_free(options);
00695
00696 return cpl_error_get_code();
00697 }
00698
00699
00700
00710
00711 static char *
00712 title_string(const char *plot_title, int npoints)
00713 {
00714
00715
00716
00717 const char *options = (npoints > 100) ?
00718 "w points pointsize 1" :
00719 "w linespoints pointsize 1";
00720
00721
00722 size_t length = strlen("t '' ") + strlen(plot_title) + strlen(options) + 1;
00723 char *result = cpl_calloc(length, sizeof(char));
00724
00725 snprintf(result, length, "t '%s' %s", plot_title, options);
00726
00727 return result;
00728 }
00729