uves_plot.c

00001 /*                                                                              *
00002  *   This file is part of the ESO UVES Pipeline                                 *
00003  *   Copyright (C) 2004,2005 European Southern Observatory                      *
00004  *                                                                              *
00005  *   This library is free software; you can redistribute it and/or modify       *
00006  *   it under the terms of the GNU General Public License as published by       *
00007  *   the Free Software Foundation; either version 2 of the License, or          *
00008  *   (at your option) any later version.                                        *
00009  *                                                                              *
00010  *   This program is distributed in the hope that it will be useful,            *
00011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of             *
00012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              *
00013  *   GNU General Public License for more details.                               *
00014  *                                                                              *
00015  *   You should have received a copy of the GNU General Public License          *
00016  *   along with this program; if not, write to the Free Software                *
00017  *   Foundation, 51 Franklin St, Fifth Floor, Boston, MA  02111-1307  USA       *
00018  *                                                                              */
00019 
00020 /*
00021  * $Author: amodigli $
00022  * $Date: 2010/09/24 09:32:07 $
00023  * $Revision: 1.35 $
00024  * $Name: uves-4_9_1 $
00025  * $Log: uves_plot.c,v $
00026  * Revision 1.35  2010/09/24 09:32:07  amodigli
00027  * put back QFITS dependency to fix problem spot by NRI on FIBER mode (with MIDAS calibs) data
00028  *
00029  * Revision 1.33  2009/12/15 14:07:58  amodigli
00030  * changed IRPLIB_PLOTTER to CPL_PLOTTER
00031  *
00032  * Revision 1.32  2007/08/21 13:08:26  jmlarsen
00033  * Removed irplib_access module, largely deprecated by CPL-4
00034  *
00035  * Revision 1.31  2007/06/06 08:17:33  amodigli
00036  * replace tab with 4 spaces
00037  *
00038  * Revision 1.30  2007/05/23 13:03:19  jmlarsen
00039  * Added missing include directive
00040  *
00041  * Revision 1.29  2007/05/22 11:31:35  jmlarsen
00042  * Removed image plotting functionality
00043  *
00044  * Revision 1.28  2007/05/22 08:44:37  jmlarsen
00045  * Don't rely on popen/pclose
00046  *
00047  * Revision 1.27  2007/04/24 09:41:35  jmlarsen
00048  * Removed deprecated irplib_string_concatenate_all
00049  *
00050  * Revision 1.26  2007/01/15 08:48:41  jmlarsen
00051  * Shortened lines
00052  *
00053  * Revision 1.25  2006/11/15 15:02:15  jmlarsen
00054  * Implemented const safe workarounds for CPL functions
00055  *
00056  * Revision 1.23  2006/11/15 14:04:08  jmlarsen
00057  * Removed non-const version of parameterlist_get_first/last/next which is 
00058  * already in CPL, added const-safe wrapper, unwrapper and deallocator functions
00059  *
00060  * Revision 1.22  2006/11/13 14:23:55  jmlarsen
00061  * Removed workarounds for CPL const bugs
00062  *
00063  * Revision 1.21  2006/11/06 15:19:41  jmlarsen
00064  * Removed unused include directives
00065  *
00066  * Revision 1.20  2006/09/20 12:53:57  jmlarsen
00067  * Replaced stringcat functions with uves_sprintf()
00068  *
00069  * Revision 1.19  2006/08/23 15:09:23  jmlarsen
00070  * Added uves_plot_bivectors
00071  *
00072  * Revision 1.18  2006/08/18 07:07:43  jmlarsen
00073  * Switched order of cpl_calloc arguments
00074  *
00075  * Revision 1.17  2006/08/17 13:56:53  jmlarsen
00076  * Reduced max line length
00077  *
00078  * Revision 1.16  2006/06/01 14:43:17  jmlarsen
00079  * Added missing documentation
00080  *
00081  * Revision 1.15  2006/05/12 15:07:35  jmlarsen
00082  * Implemented 3 sigma clipping to have better ranges for plots
00083  *
00084  * Revision 1.14  2006/04/24 09:22:53  jmlarsen
00085  * Renamed shadowing variable
00086  *
00087  * Revision 1.13  2006/02/21 14:26:54  jmlarsen
00088  * Minor changes
00089  *
00090  * Revision 1.12  2005/12/19 16:17:56  jmlarsen
00091  * Replaced bool -> int
00092  *
00093  */
00094 
00095 #ifdef HAVE_CONFIG_H
00096 #  include <config.h>
00097 #endif
00098 
00099 /*----------------------------------------------------------------------------*/
00121 /*----------------------------------------------------------------------------*/
00122 
00123 /* If we can link to setenv but it is not declared, then declare it manually */
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                                 Includes
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>   /* setenv */
00150 
00151 /*-----------------------------------------------------------------------------
00152                             Functions prototypes
00153  -----------------------------------------------------------------------------*/
00154 static char *title_string(const char *title, int npoints);
00155 /*-----------------------------------------------------------------------------
00156                             Defines
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;           /* If caller forgets to call 
00175                            the initializer, plotting
00176                            will be disabled */
00177 static const char *plotter = "";
00178 
00181 /*-----------------------------------------------------------------------------
00182                         Implementation
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     /* Note that 'setenv' is *not* ANSI C. If it does not exist, tell user to
00207      *  define the environment variable him-/herself.
00208      */
00209 
00210     if (plotting_enabled)
00211     {
00212         const char *env = "CPL_PLOTTER";
00213 
00214         /* Check if 'which x' returns non-zero.
00215            x is the first word of plotting command.
00216            Note: this assumes the environment understands
00217            'which' and '> /dev/null'. If not,
00218            plotting will be disabled.
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         /* popen may return non-NULL even when the external command
00236            is not available. This causes the recipe to crash when writing
00237            to an invalid FILE pointer.
00238            Therefore, check (using 'which') that the
00239            command is available.
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             /* Setenv succeeded, remember command */
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         /* Create pre string */
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         /* Threshold each row */
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         /* Create pre string */
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         /* Threshold each column */
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 *)); /* Initialized to NULL */
00505     assure_mem( options );
00506 
00507     if (plotting_enabled)
00508     {
00509         int npoints, i;
00510         cpl_bivector *temp;
00511         char *temps;
00512 
00513         /* Create options strings */
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         /* Swap first/last bivectors */
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         /* Create options string */
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         /* Create pre string */
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                              /* It's a couple of bytes more than enough */
00652         sprintf(pre, pre_format, colx, coly);
00653 
00654 
00655         /* Threshold y-values to median +- 3 sigma before plotting */
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         /* Copy the data we need, then threshold */
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); /* polymorphic */
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     /* Option to choose plotting style
00715      * depending on the number of points 
00716      */
00717     const char *options = (npoints > 100) ?
00718     "w points pointsize 1" :
00719     "w linespoints pointsize 1";
00720     /* If less than, say, 100 points, connect them with lines */
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 

Generated on 8 Mar 2011 for UVES Pipeline Reference Manual by  doxygen 1.6.1