GIRAFFE Pipeline Reference Manual

gifov.c

00001 /* $Id$
00002  *
00003  * This file is part of the GIRAFFE Pipeline
00004  * Copyright (C) 2002-2006 European Southern Observatory
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00019  */
00020 
00021 /*
00022  * $Author$
00023  * $Date$
00024  * $Revision$
00025  * $Name$
00026  */
00027 
00028 #ifdef HAVE_CONFIG_H
00029 #  include <config.h>
00030 #endif
00031 
00032 #include <math.h>
00033 
00034 #include <cxslist.h>
00035 #include <cxstrutils.h>
00036 
00037 #include <cpl_array.h>
00038 #include <cpl_propertylist.h>
00039 
00040 #include "gialias.h"
00041 #include "gimacros.h"
00042 #include "gierror.h"
00043 #include "gimessages.h"
00044 #include "gigrating.h"
00045 #include "gifov.h"
00046 #include "gifiberutils.h"
00047 #include "gisutils.h"
00048 #include "giutils.h"
00049 
00050 
00060 inline static cxint
00061 _giraffe_compare_int(cxcptr first, cxcptr second)
00062 {
00063 
00064     cxint *_first = (cxint *)first;
00065     cxint *_second = (cxint *)second;
00066 
00067     return *_first - *_second;
00068 
00069 }
00070 
00071 
00072 inline static GiCube*
00073 _giraffe_fov_create_cube(const GiImage* spectra,
00074                          const cpl_table* fibers,
00075                          const GiRange* limits)
00076 {
00077 
00078     cxint first = 0;
00079     cxint last = 0;
00080     cxint nx = 0;
00081     cxint ny = 0;
00082     cxint nz = 0;
00083 
00084     cxdouble wmin = 0.;
00085     cxdouble wmax = 0.;
00086     cxdouble wstep = 0.;
00087     cxdouble fstart = 1.;
00088     cxdouble fend = 1.;
00089 
00090     cpl_propertylist* properties = giraffe_image_get_properties(spectra);
00091 
00092     cpl_image* _spectra = giraffe_image_get(spectra);
00093 
00094     GiCube* cube = NULL;
00095 
00096 
00097     if ((properties == NULL) || (_spectra == NULL)) {
00098         return NULL;
00099     }
00100 
00101 
00102     /*
00103      * Get the spectral range of the input spectra.
00104      */
00105 
00106     if (cpl_propertylist_has(properties, GIALIAS_BINWLMIN) == FALSE) {
00107         return NULL;
00108     }
00109     else {
00110         wmin = cpl_propertylist_get_double(properties, GIALIAS_BINWLMIN);
00111     }
00112 
00113     if (cpl_propertylist_has(properties, GIALIAS_BINWLMAX) == FALSE) {
00114         return NULL;
00115     }
00116     else {
00117         wmax = cpl_propertylist_get_double(properties, GIALIAS_BINWLMAX);
00118     }
00119 
00120     if (cpl_propertylist_has(properties, GIALIAS_BINSTEP) == FALSE) {
00121         return NULL;
00122     }
00123     else {
00124         wstep = cpl_propertylist_get_double(properties, GIALIAS_BINSTEP);
00125     }
00126 
00127 
00128     /*
00129      * Determine the pixel limits corresponding to the spectral range.
00130      */
00131 
00132     first = 0;
00133     last = cpl_image_get_size_y(_spectra) - 1;
00134 
00135     if (limits != NULL) {
00136 
00137         if (giraffe_range_get_min(limits) > wmin) {
00138 
00139             cxdouble pixel = (giraffe_range_get_min(limits) - wmin) / wstep;
00140 
00141 
00142             first  = ceil(pixel);
00143             fstart = pixel - first;
00144 
00145         }
00146 
00147         if (giraffe_range_get_max(limits) < wmax) {
00148 
00149             cxdouble pixel = last - (wmax - giraffe_range_get_max(limits)) / wstep;
00150 
00151 
00152             last = floor(pixel);
00153             fend = pixel - last;
00154 
00155         }
00156 
00157     }
00158 
00159 
00160     /*
00161      * Determine the layout of the cube from the list of fibers.
00162      */
00163 
00164     giraffe_error_push();
00165 
00166     nx = (cxint) cpl_table_get_column_max(fibers, "X");
00167     ny = (cxint) cpl_table_get_column_max(fibers, "Y");
00168 
00169     if (cpl_error_get_code() == CPL_ERROR_DATA_NOT_FOUND) {
00170         return NULL;
00171     }
00172 
00173     giraffe_error_pop();
00174 
00175 
00176     nz = last - first + 1;
00177 
00178     if (nz <= 0) {
00179         return NULL;
00180     }
00181 
00182 
00183     /*
00184      * Create the data cube and fill it with the flux values.
00185      */
00186 
00187     cube = giraffe_cube_create(nx, ny, nz, NULL);
00188 
00189     giraffe_cube_set_xaxis(cube, 1., 1.);
00190     giraffe_cube_set_yaxis(cube, 1., 1.);
00191     giraffe_cube_set_zaxis(cube, wmin, wstep);
00192 
00193     if (cube != NULL) {
00194 
00195         register cxint i = 0;
00196         register cxint nf = cpl_table_get_nrow(fibers);
00197 
00198         cxint ns = cpl_image_get_size_x(_spectra);
00199 
00200         cxdouble* spixels = cpl_image_get_data_double(_spectra);
00201         cxdouble* cpixels = giraffe_cube_get_data(cube);
00202 
00203 
00204         cx_assert(spixels != NULL);
00205         cx_assert(cpixels != NULL);
00206         cx_assert(nf <= ns);
00207 
00208         for (i = 0; i < nf; ++i) {
00209 
00210             register cxint j = 0;
00211 
00212             cxint idx = cpl_table_get_int(fibers, "INDEX", i, NULL) - 1;
00213             cxint x = cpl_table_get_int(fibers, "X", i, NULL) - 1;
00214             cxint y = cpl_table_get_int(fibers, "Y", i, NULL) - 1;
00215 
00216 
00217             /*
00218              * Fill image pixels skipping special fibers (CalSim or Sky)
00219              * which have x = 0 and y = 0.
00220              */
00221 
00222             if ((x >= 0) && (y >= 0)) {
00223 
00224                 for (j = 0; j < nz; ++j) {
00225                     cpixels[(ny * j + y) * nx + x] =
00226                         spixels[(first + j) * ns + idx];
00227                 }
00228 
00229             }
00230 
00231         }
00232 
00233     }
00234 
00235     return cube;
00236 
00237 }
00238 
00239 
00240 /*
00241  * Arrange the input images into an output image using a tabular layout.
00242  */
00243 
00244 inline static cpl_image*
00245 _giraffe_fov_arrange_images(const cx_slist* subimages,
00246                             cxsize nrows, cxsize ncolumns, cxint offset)
00247 {
00248 
00249     cxint x = 0;
00250     cxint y = 0;
00251     cxint nx = 0;
00252     cxint ny = 0;
00253     cxint sx = 0;
00254     cxint sy = 0;
00255     cxint xshift = offset;
00256     cxint yshift = offset;
00257 
00258     cxsize nslit = 0;
00259     cxsize column = 0;
00260 
00261     cx_slist_iterator pos;
00262 
00263     cpl_image* image = NULL;
00264 
00265 
00266     cx_assert(subimages != NULL);
00267     cx_assert(nrows > 0);
00268     cx_assert(ncolumns > 0);
00269 
00270 
00271     /*
00272      * Compute the size of the combined output image from the largest
00273      * image in the list. The properties of the mosaic image are taken
00274      * from the first (non-empty) image in the list.
00275      */
00276 
00277     pos = cx_slist_begin(subimages);
00278 
00279     while (pos != cx_slist_end(subimages)) {
00280 
00281         const cpl_image* simage = cx_slist_get(subimages, pos);
00282 
00283         if (simage != NULL) {
00284 
00285             cxint _nx = cpl_image_get_size_x(simage);
00286             cxint _ny = cpl_image_get_size_y(simage);
00287 
00288             sx = CX_MAX(nx, _nx);
00289             sy = CX_MAX(ny, _ny);
00290 
00291         }
00292 
00293         pos = cx_slist_next(subimages, pos);
00294 
00295     }
00296 
00297 
00298     /*
00299      * Adjust the number of rows to what is actually needed.
00300      */
00301 
00302     nslit = cx_slist_size(subimages);
00303     nrows  = CX_MAX(nslit / ncolumns, nrows);
00304 
00305     if (nslit % ncolumns != 0) {
00306         ++nrows;
00307     }
00308 
00309 
00310     /*
00311      * Compute the size of the final "mosaic" image
00312      */
00313 
00314     nx = sx * ncolumns;
00315     ny = sy * nrows;
00316 
00317 
00318     if (offset < 0) {
00319         xshift = nx / -offset + 1;
00320         yshift = ny / -offset + 1;
00321     }
00322 
00323     nx += ncolumns * xshift - (xshift % 2);
00324     ny += nrows * yshift - (yshift % 2);
00325 
00326 
00327     /*
00328      * Arrange subimages into a single image.
00329      */
00330 
00331     image = cpl_image_new(nx, ny, CPL_TYPE_DOUBLE);
00332 
00333     y = yshift / 2;
00334     x = xshift / 2;
00335 
00336     pos = cx_slist_begin(subimages);
00337 
00338     while (pos != cx_slist_end(subimages)) {
00339 
00340         const cpl_image* simage = cx_slist_get(subimages, pos);
00341 
00342         if (simage != NULL) {
00343 
00344             cpl_error_code status = cpl_image_copy(image, simage,
00345                                                    x + 1, y + 1);
00346 
00347             if (status != CPL_ERROR_NONE) {
00348                 cpl_image_delete(image);
00349                 return NULL;
00350             }
00351 
00352         }
00353 
00354         ++column;
00355 
00356         if (column < ncolumns) {
00357             x += sx + xshift;
00358         }
00359         else {
00360             column = 0;
00361 
00362             x = xshift / 2;
00363             y += sy + yshift;
00364         }
00365 
00366         pos = cx_slist_next(subimages, pos);
00367 
00368     }
00369 
00370     return image;
00371 
00372 }
00373 
00374 
00375 inline static cpl_image*
00376 _giraffe_fov_integrate_cube(const GiCube* cube, const GiRange* limits)
00377 {
00378 
00379     cxsize depth = 0;
00380 
00381     cxdouble wmin = 0.;
00382     cxdouble wmax = 0.;
00383     cxdouble wstep = 0.;
00384     cxdouble start = 0.;
00385     cxdouble end = 0.;
00386 
00387     cpl_image* image = NULL;
00388 
00389 
00390     cx_assert(cube != NULL);
00391 
00392     depth = giraffe_cube_get_depth(cube);
00393     giraffe_cube_get_zaxis(cube, &wmin, &wstep);
00394 
00395     wmax = wmin + depth * wstep;
00396     end = depth;
00397 
00398     if (giraffe_range_get_min(limits) > wmin) {
00399         start = (giraffe_range_get_min(limits) - wmin) / wstep;
00400     }
00401 
00402     if (giraffe_range_get_max(limits) < wmax) {
00403         end = (giraffe_range_get_max(limits) - wmin) / wstep;
00404     }
00405 
00406     image = giraffe_cube_integrate(cube, start, end);
00407 
00408     return image;
00409 
00410 }
00411 
00412 
00434 cxint
00435 giraffe_fov_build(GiFieldOfView* result, GiRebinning* rebinning,
00436                   GiTable* fibers, GiTable* wsolution,
00437                   GiTable* grating, GiTable* slitgeometry,
00438                   GiFieldOfViewConfig* config)
00439 {
00440 
00441     const cxchar* const fctid = "giraffe_fov_build";
00442 
00443     cxbool log_scale = FALSE;
00444 
00445     cx_slist* simages = NULL;
00446     cx_slist* eimages = NULL;
00447     cx_slist* scubes = NULL;
00448     cx_slist* ecubes = NULL;
00449 
00450     cpl_propertylist* properties = NULL;
00451 
00452     cpl_array* ssn = NULL;
00453 
00454     cpl_image* fov = NULL;
00455 
00456     cpl_table* _fibers = NULL;
00457 
00458     GiInstrumentMode mode;
00459 
00460     GiRange* limits = NULL;
00461 
00462 
00463     if (result == NULL) {
00464         cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
00465         return -1;
00466     }
00467     else {
00468 
00469         /*
00470          * Make sure that the field of view object is empty
00471          */
00472 
00473         giraffe_fov_clear(result);
00474 
00475     }
00476 
00477     if (rebinning == NULL) {
00478         cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
00479         return -1;
00480     }
00481 
00482     if (rebinning->spectra == NULL || rebinning->errors == NULL) {
00483         cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
00484         return -1;
00485     }
00486 
00487     if (fibers == NULL) {
00488         cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
00489         return -1;
00490     }
00491 
00492     _fibers = giraffe_table_get(fibers);
00493 
00494     if (_fibers == NULL) {
00495         cpl_error_set(fctid, CPL_ERROR_DATA_NOT_FOUND);
00496         return -1;
00497     }
00498 
00499     if (!cpl_table_has_column(_fibers, "X") ||
00500         !cpl_table_has_column(_fibers, "Y")) {
00501         cpl_error_set(fctid, CPL_ERROR_DATA_NOT_FOUND);
00502         return -2;
00503     }
00504 
00505     if (config == NULL) {
00506         cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
00507         return -1;
00508     }
00509 
00510 
00511     /*
00512      * Determine the instrument mode. Spectra taken in IFU mode must
00513      * be processed on a per subslit basis, while ARGUS data can
00514      * be processed ignoring the subslit information (simple
00515      * reconstruction based on X and Y positions of fibers only)
00516      */
00517 
00518     properties = giraffe_image_get_properties(rebinning->spectra);
00519 
00520     if (properties == NULL) {
00521         cpl_error_set(fctid, CPL_ERROR_DATA_NOT_FOUND);
00522         return -1;
00523     }
00524 
00525     mode = giraffe_get_mode(properties);
00526 
00527 
00528     /*
00529      * By default the cube and the fov-image will be reconstructed from
00530      * the input spectra common wavelength range. If a wavelength range
00531      * was specified by parameter settings these will be used, clamped
00532      * to the input spectra common wavelength range.
00533      */
00534 
00535     limits = giraffe_rebin_get_wavelength_range(rebinning->spectra, wsolution,
00536                                                 grating, slitgeometry, TRUE);
00537 
00538     if (limits == NULL) {
00539         cpl_msg_error(fctid, "Computation of spectra common wavelength "
00540                       "range failed!");
00541         return 1;
00542     }
00543 
00544     if (config->minimum > 0.) {
00545         if (config->minimum < giraffe_range_get_min(limits)) {
00546             cpl_msg_warning(fctid, "Ignoring invalid wavelength range "
00547                             "minimum %.3f nm", config->minimum);
00548         }
00549         else {
00550             giraffe_range_set_min(limits, config->minimum);
00551         }
00552     }
00553 
00554     if (config->maximum > 0.) {
00555         if (config->maximum > giraffe_range_get_max(limits)) {
00556             cpl_msg_warning(fctid, "Ignoring invalid wavelength range "
00557                             "maximum %.3f nm", config->maximum);
00558         }
00559         else {
00560             giraffe_range_set_max(limits, config->maximum);
00561         }
00562     }
00563 
00564     cpl_msg_info(fctid, "Building image for wavelength range [%.3f nm, "
00565                  "%.3f nm].", giraffe_range_get_min(limits),
00566                  giraffe_range_get_max(limits));
00567 
00568 
00569     /*
00570      * Convert limits if the spectrum wavelength scale is logarithmic
00571      */
00572 
00573     if (cpl_propertylist_has(properties, GIALIAS_BINSCALE)) {
00574 
00575         const cxchar* s = cpl_propertylist_get_string(properties,
00576                                                       GIALIAS_BINSCALE);
00577 
00578         if (cx_strncasecmp(s, "log", 3) == 0) {
00579             giraffe_range_set_min(limits, log(giraffe_range_get_min(limits)));
00580             giraffe_range_set_max(limits, log(giraffe_range_get_max(limits)));
00581 
00582             log_scale = TRUE;
00583         }
00584     }
00585     else {
00586         cpl_msg_warning(fctid, "Could not determine spectrum wavelength "
00587                         "scaling method. Missing property `%s'. Assuming "
00588                         "scaling method `linear'!", GIALIAS_BINSCALE);
00589     }
00590 
00591 
00592     /*
00593      * Create the containers to store the data cubes and the
00594      * reconstructed images.
00595      */
00596 
00597     simages = cx_slist_new();
00598     eimages = cx_slist_new();
00599     scubes  = cx_slist_new();
00600     ecubes  = cx_slist_new();
00601 
00602 
00603     switch (mode) {
00604         case GIMODE_IFU:
00605         {
00606 
00607             cxint i = 0;
00608 
00609             cpl_array* _ssn = NULL;
00610 
00611             cpl_image* smosaic = NULL;
00612             cpl_image* emosaic = NULL;
00613 
00614             GiImage* variance = NULL;
00615 
00616 
00617             /*
00618              * Determine the number and the list of used subslits.
00619              */
00620 
00621             ssn = giraffe_fiberlist_get_subslits(_fibers);
00622 
00623             if (ssn == NULL) {
00624                 cx_slist_destroy(simages, (cx_free_func)cpl_image_delete);
00625                 simages = NULL;
00626 
00627                 cx_slist_destroy(eimages, (cx_free_func)cpl_image_delete);
00628                 eimages = NULL;
00629 
00630                 cx_slist_destroy(scubes, (cx_free_func)giraffe_cube_delete);
00631                 scubes = NULL;
00632 
00633                 cx_slist_destroy(ecubes, (cx_free_func)giraffe_cube_delete);
00634                 ecubes = NULL;
00635 
00636                 giraffe_range_delete(limits);
00637                 limits = NULL;
00638 
00639                 cpl_msg_error(fctid, "Sub-slit data missing in fiber table!");
00640 
00641                 return 1;
00642             }
00643 
00644 
00645             /*
00646              * Compute the variances from the error map.
00647              */
00648 
00649             variance = giraffe_image_duplicate(rebinning->errors);
00650 
00651             if (variance == NULL) {
00652                 cpl_array_delete(ssn);
00653                 ssn = NULL;
00654 
00655                 cx_slist_destroy(simages, (cx_free_func)cpl_image_delete);
00656                 simages = NULL;
00657 
00658                 cx_slist_destroy(eimages, (cx_free_func)cpl_image_delete);
00659                 eimages = NULL;
00660 
00661                 cx_slist_destroy(scubes, (cx_free_func)giraffe_cube_delete);
00662                 scubes = NULL;
00663 
00664                 cx_slist_destroy(ecubes, (cx_free_func)giraffe_cube_delete);
00665                 ecubes = NULL;
00666 
00667                 giraffe_range_delete(limits);
00668                 limits = NULL;
00669 
00670                 cpl_msg_error(fctid, "Failed to create variance map!");
00671 
00672                 return 1;
00673             }
00674 
00675             cpl_image_power(giraffe_image_get(variance), 2.);
00676 
00677 
00678             /*
00679              * Build the data cubes and images for each sub-slit
00680              */
00681 
00682             _ssn = cpl_array_duplicate(ssn);
00683 
00684             for (i = 0; i < cpl_array_get_size(_ssn); ++i) {
00685 
00686                 cxbool failed = FALSE;
00687 
00688                 cxint nss = cpl_array_get_int(_ssn, i, NULL);
00689 
00690                 cpl_table* ssf = NULL;
00691 
00692                 cpl_table_unselect_all(_fibers);
00693                 cpl_table_or_selected_int(_fibers, "SSN", CPL_EQUAL_TO, nss);
00694 
00695                 /*
00696                  * Remove fibers without position information, i.e.
00697                  * simultaneous calibration fibers and sky fibers.
00698                  */
00699 
00700                 cpl_table_and_selected_int(_fibers, "X", CPL_GREATER_THAN, 0);
00701                 cpl_table_and_selected_int(_fibers, "Y", CPL_GREATER_THAN, 0);
00702 
00703                 ssf = cpl_table_extract_selected(_fibers);
00704 
00705                 if ((ssf != NULL) && (cpl_table_get_nrow(ssf) > 0)) {
00706 
00707                     cpl_matrix* transform = NULL;
00708 
00709                     cpl_propertylist* wcs = NULL;
00710 
00711                     cpl_image* _simage = NULL;
00712                     cpl_image* _eimage = NULL;
00713 
00714                     GiCube* _scube = NULL;
00715                     GiCube* _ecube = NULL;
00716 
00717 
00718                     _scube = _giraffe_fov_create_cube(rebinning->spectra,
00719                                                       ssf, NULL);
00720 
00721                     /*
00722                      * Build a world coordinate system for the cube
00723                      */
00724 
00725                     if (_scube != NULL) {
00726 
00727                         cxdouble xorigin = giraffe_cube_get_width(_scube) / 2.;
00728                         cxdouble yorigin = giraffe_cube_get_height(_scube) / 2.;
00729 
00730                         cxdouble xvalue =
00731                                 cpl_propertylist_get_double(properties,
00732                                                             GIALIAS_RADEG);
00733                         cxdouble yvalue =
00734                                 cpl_propertylist_get_double(properties,
00735                                                             GIALIAS_DECDEG);
00736                         cxdouble orientation =
00737                                 cpl_table_get_double(ssf, "ORIENT", 0, NULL);
00738 
00739                         cxdouble zvalue   = 0.;
00740                         cxdouble zstep    = 0.;
00741                         cxdouble angle    = GI_IFU_POSANG_OFFSET - orientation;
00742                         cxdouble pixscale = GI_IFU_PIXSCALE / 3600.;
00743 
00744 
00745                         transform = cpl_matrix_new(3, 3);
00746 
00747                         wcs = cpl_propertylist_new();
00748 
00749                         cpl_propertylist_update_double(wcs, "XORIGIN", xorigin);
00750                         cpl_propertylist_update_double(wcs, "YORIGIN", yorigin);
00751                         cpl_propertylist_update_double(wcs, "ZORIGIN", 1.);
00752 
00753                         giraffe_cube_get_zaxis(_scube, &zvalue, &zstep);
00754 
00755                         cpl_propertylist_update_double(wcs, "XPOINT", xvalue);
00756                         cpl_propertylist_update_double(wcs, "YPOINT", yvalue);
00757                         cpl_propertylist_update_double(wcs, "ZPOINT", zvalue);
00758 
00759                         cpl_propertylist_update_string(wcs, "XTYPE",
00760                                                        "RA---TAN");
00761                         cpl_propertylist_update_string(wcs, "YTYPE",
00762                                                        "DEC--TAN");
00763 
00764                         if (log_scale == TRUE) {
00765                             cpl_propertylist_update_string(wcs,
00766                                                            "ZTYPE", "AWAV-LOG");
00767                         }
00768                         else {
00769                             cpl_propertylist_update_string(wcs,
00770                                                            "ZTYPE", "AWAV");
00771                         }
00772 
00773                         cpl_propertylist_update_string(wcs, "XUNIT", "deg");
00774                         cpl_propertylist_update_string(wcs, "YUNIT", "deg");
00775                         cpl_propertylist_update_string(wcs, "ZUNIT", "nm");
00776 
00777 
00778                         /*
00779                          * Right ascension is counted eastward from the
00780                          * equinox, hence the negative sign on the upper
00781                          * left element of the scale matrix.
00782                          */
00783 
00784                         angle *= CX_PI / 180.;
00785 
00786                         cpl_matrix_set(transform, 0, 0, -pixscale *  cos(angle));
00787                         cpl_matrix_set(transform, 0, 1,  pixscale * -sin(angle));
00788                         cpl_matrix_set(transform, 1, 0, -pixscale *  sin(angle));
00789                         cpl_matrix_set(transform, 1, 1,  pixscale *  cos(angle));
00790                         cpl_matrix_set(transform, 2, 2, zstep);
00791 
00792                     }
00793 
00794                     if (_scube != NULL) {
00795                         _simage = _giraffe_fov_integrate_cube(_scube, limits);
00796                     }
00797 
00798                     if ((_scube == NULL) || (_simage == NULL)) {
00799 
00800                         cpl_image_delete(_simage);
00801                         _simage = NULL;
00802 
00803                         giraffe_cube_delete(_scube);
00804                         _scube = NULL;
00805 
00806                         failed = TRUE;
00807 
00808                         cpl_msg_error(fctid, "Cannot create data cube for "
00809                                       "sub-slit %d", nss);
00810                     }
00811                     else {
00812                         giraffe_cube_set_wcs(_scube, wcs, transform);
00813 
00814                         cx_slist_push_back(scubes, _scube);
00815                         cx_slist_push_back(simages, _simage);
00816                     }
00817 
00818                     if (!failed) {
00819 
00820                         _ecube = _giraffe_fov_create_cube(variance,
00821                                                           ssf, NULL);
00822 
00823                         if (_ecube != NULL) {
00824                             _eimage = _giraffe_fov_integrate_cube(_ecube,
00825                                                                   limits);
00826                         }
00827 
00828                         if ((_ecube == NULL) || (_eimage == NULL)) {
00829 
00830                             cpl_image_delete(_eimage);
00831                             _eimage = NULL;
00832 
00833                             giraffe_cube_delete(_ecube);
00834                             _ecube = NULL;
00835 
00836                             failed = TRUE;
00837 
00838                             cpl_msg_error(fctid, "Cannot create error "
00839                                           "cube for sub-slit %d", nss);
00840                         }
00841                         else {
00842                             giraffe_cube_sqrt(_ecube);
00843                             cpl_image_power(_eimage, 0.5);
00844 
00845                             giraffe_cube_set_wcs(_ecube, wcs, transform);
00846 
00847                             cx_slist_push_back(ecubes, _ecube);
00848                             cx_slist_push_back(eimages, _eimage);
00849                         }
00850 
00851                     }
00852 
00853                     cpl_propertylist_delete(wcs);
00854                     wcs = NULL;
00855 
00856                     cpl_matrix_delete(transform);
00857                     transform = NULL;
00858 
00859                     if (failed) {
00860 
00861                         cpl_table_delete(ssf);
00862                         ssf = NULL;
00863 
00864                         giraffe_image_delete(variance);
00865                         variance = NULL;
00866 
00867                         cpl_array_delete(_ssn);
00868                         _ssn = NULL;
00869 
00870                         cpl_array_delete(ssn);
00871                         ssn = NULL;
00872 
00873                         cx_slist_destroy(simages,
00874                                          (cx_free_func)cpl_image_delete);
00875                         simages = NULL;
00876 
00877                         cx_slist_destroy(eimages,
00878                                          (cx_free_func)cpl_image_delete);
00879                         eimages = NULL;
00880 
00881                         cx_slist_destroy(scubes,
00882                                          (cx_free_func)giraffe_cube_delete);
00883                         scubes = NULL;
00884 
00885                         cx_slist_destroy(ecubes,
00886                                          (cx_free_func)giraffe_cube_delete);
00887                         ecubes = NULL;
00888 
00889                         giraffe_range_delete(limits);
00890                         limits = NULL;
00891 
00892                         return 1;
00893 
00894                     }
00895 
00896                 }
00897                 else {
00898 
00899                     if (ssf != NULL) {
00900                         cpl_msg_debug(fctid, "Unused IFU button detected. "
00901                                         "Skipping sub-slit %d", nss);
00902 
00903                         cpl_array_erase_window(ssn, i, 1);
00904 
00905                         cx_slist_push_back(simages, NULL);
00906                         cx_slist_push_back(eimages, NULL);
00907                     }
00908                 }
00909 
00910                 cpl_table_delete(ssf);
00911                 ssf = NULL;
00912 
00913             }
00914 
00915             cpl_array_delete(_ssn);
00916             _ssn = NULL;
00917 
00918             giraffe_image_delete(variance);
00919             variance = NULL;
00920 
00921 
00922             /*
00923              * Put the images of the reconstructed field of view in an
00924              * image using a tabular layout. This mosaic is stored as
00925              * the first image in the image containers, to be consistent
00926              * with the Argus mode, where only this image is provided.
00927              */
00928 
00929             smosaic = _giraffe_fov_arrange_images(simages, 5, 3, -4);
00930             emosaic = _giraffe_fov_arrange_images(eimages, 5, 3, -4);
00931 
00932             if ((smosaic == NULL) || (emosaic == NULL)) {
00933 
00934                 cpl_image_delete(smosaic);
00935                 smosaic = NULL;
00936 
00937                 cpl_image_delete(emosaic);
00938                 emosaic = NULL;
00939 
00940                 cx_slist_destroy(simages, (cx_free_func)cpl_image_delete);
00941                 simages = NULL;
00942 
00943                 cx_slist_destroy(eimages, (cx_free_func)cpl_image_delete);
00944                 eimages = NULL;
00945 
00946                 cx_slist_destroy(scubes, (cx_free_func)giraffe_cube_delete);
00947                 scubes = NULL;
00948 
00949                 cx_slist_destroy(ecubes, (cx_free_func)giraffe_cube_delete);
00950                 ecubes = NULL;
00951 
00952                 cpl_array_delete(ssn);
00953                 ssn = NULL;
00954 
00955                 giraffe_range_delete(limits);
00956                 limits = NULL;
00957 
00958                 return 1;
00959 
00960             }
00961 
00962             cx_slist_push_front(simages, smosaic);
00963             cx_slist_push_front(eimages, emosaic);
00964             break;
00965 
00966         }
00967 
00968         case GIMODE_ARGUS:
00969         {
00970             cxbool failed = FALSE;
00971 
00972             cpl_image* simage = NULL;
00973             cpl_image* eimage = NULL;
00974 
00975             cpl_matrix* transform = NULL;
00976 
00977             cpl_propertylist* wcs = NULL;
00978 
00979             GiImage* variance = NULL;
00980 
00981             GiCube* scube = NULL;
00982             GiCube* ecube = NULL;
00983 
00984 
00985             /*
00986              * Compute the variances from the error map.
00987              */
00988 
00989             variance = giraffe_image_duplicate(rebinning->errors);
00990 
00991             if (variance == NULL) {
00992 
00993                 cx_slist_destroy(simages, (cx_free_func)cpl_image_delete);
00994                 simages = NULL;
00995 
00996                 cx_slist_destroy(eimages, (cx_free_func)cpl_image_delete);
00997                 eimages = NULL;
00998 
00999                 cx_slist_destroy(scubes, (cx_free_func)giraffe_cube_delete);
01000                 scubes = NULL;
01001 
01002                 cx_slist_destroy(ecubes, (cx_free_func)giraffe_cube_delete);
01003                 ecubes = NULL;
01004 
01005                 giraffe_range_delete(limits);
01006                 limits = NULL;
01007 
01008                 cpl_msg_error(fctid, "Failed to create variance map!");
01009                 return 1;
01010 
01011             }
01012 
01013             cpl_image_power(giraffe_image_get(variance), 2.);
01014 
01015 
01016             /*
01017              * Build the data cubes and field of view images
01018              */
01019 
01020             scube = _giraffe_fov_create_cube(rebinning->spectra,
01021                                              _fibers, NULL);
01022 
01023             /*
01024              * Build a world coordinate system for the cube.
01025              */
01026              
01027             /*
01028              * Argus has a +90 degrees offset with respect to the adaptor,
01029              * thus: PA_arg = PA_ada + 90.
01030              * 
01031              * The Argus long axis is aligned with the North-South
01032              * direction, and North up for PA_arg = 0. Since in the
01033              * image the Argus long axis is the x-axis an extra 90.
01034              * degrees offset has to be applied to the WCS axes. And
01035              * finally, since the coordinate system is transformed
01036              * relative to the image, and PA_arg is counted positive
01037              * counter clockwise (from North through East), the agular
01038              * offsets must be counted negative.
01039              */
01040 
01041             if (scube != NULL) {
01042 
01043                 cxdouble xorigin = giraffe_cube_get_width(scube) / 2.;
01044                 cxdouble yorigin = giraffe_cube_get_height(scube) / 2.;
01045 
01046                 cxdouble xvalue = cpl_propertylist_get_double(properties,
01047                                                               GIALIAS_RADEG);
01048                 cxdouble yvalue = cpl_propertylist_get_double(properties,
01049                                                               GIALIAS_DECDEG);
01050                 cxdouble zvalue   = 0.;
01051                 cxdouble zstep    = 0.;
01052                 cxdouble angle    = -90. -
01053                         (cpl_propertylist_get_double(properties,
01054                                                      GIALIAS_POSANG) +
01055                                 GI_ARGUS_POSANG_OFFSET);
01056 
01057                 cxdouble pixscale = GI_ARGUS_PIXSCALE_LOW;
01058 
01059                 const cxchar* scale =
01060                         cpl_propertylist_get_string(properties,
01061                                                     GIALIAS_ARGUS_SCALE);
01062 
01063 
01064                 if ((scale != NULL) && (strcmp(scale, "POS_1_67") == 0)) {
01065                     pixscale = GI_ARGUS_PIXSCALE_HIGH;
01066                 }
01067 
01068                 /* Get pixel scale in degrees */
01069 
01070                 pixscale /= 3600.;
01071 
01072 
01073                 transform = cpl_matrix_new(3, 3);
01074 
01075                 wcs = cpl_propertylist_new();
01076 
01077                 cpl_propertylist_update_double(wcs, "XORIGIN", xorigin);
01078                 cpl_propertylist_update_double(wcs, "YORIGIN", yorigin);
01079                 cpl_propertylist_update_double(wcs, "ZORIGIN", 1.);
01080 
01081                 giraffe_cube_get_zaxis(scube, &zvalue, &zstep);
01082 
01083                 cpl_propertylist_update_double(wcs, "XPOINT", xvalue);
01084                 cpl_propertylist_update_double(wcs, "YPOINT", yvalue);
01085                 cpl_propertylist_update_double(wcs, "ZPOINT", zvalue);
01086 
01087                 cpl_propertylist_update_string(wcs, "XTYPE", "RA---TAN");
01088                 cpl_propertylist_update_string(wcs, "YTYPE", "DEC--TAN");
01089 
01090                 if (log_scale == TRUE) {
01091                     cpl_propertylist_update_string(wcs,
01092                                                    "ZTYPE", "AWAV-LOG");
01093                 }
01094                 else {
01095                     cpl_propertylist_update_string(wcs,
01096                                                    "ZTYPE", "AWAV");
01097                 }
01098 
01099                 cpl_propertylist_update_string(wcs, "XUNIT", "deg");
01100                 cpl_propertylist_update_string(wcs, "YUNIT", "deg");
01101                 cpl_propertylist_update_string(wcs, "ZUNIT", "nm");
01102 
01103 
01104                 /*
01105                  * Right ascension is counted eastward from the equinox,
01106                  * hence the negative sign on the upper left element of the
01107                  * scale matrix.
01108                  */
01109 
01110                 angle *= CX_PI / 180.;
01111 
01112                 cpl_matrix_set(transform, 0, 0, -pixscale *  cos(angle));
01113                 cpl_matrix_set(transform, 0, 1,  pixscale * -sin(angle));
01114                 cpl_matrix_set(transform, 1, 0, -pixscale *  sin(angle));
01115                 cpl_matrix_set(transform, 1, 1,  pixscale *  cos(angle));
01116                 cpl_matrix_set(transform, 2, 2, zstep);
01117 
01118             }
01119 
01120 
01121             if (scube != NULL) {
01122                 simage = _giraffe_fov_integrate_cube(scube, limits);
01123             }
01124 
01125             if ((scube == NULL) || (simage == NULL)) {
01126 
01127                 cpl_image_delete(simage);
01128                 simage = NULL;
01129 
01130                 giraffe_cube_delete(scube);
01131                 scube = NULL;
01132 
01133                 failed = TRUE;
01134 
01135                 cpl_msg_error(fctid, "Cannot create data cube!");
01136 
01137             }
01138             else {
01139 
01140                 giraffe_cube_set_wcs(scube, wcs, transform);
01141 
01142                 cx_slist_push_back(scubes, scube);
01143                 cx_slist_push_back(simages, simage);
01144 
01145             }
01146 
01147 
01148             if (!failed) {
01149 
01150                 ecube = _giraffe_fov_create_cube(variance, _fibers, NULL);
01151                 eimage = _giraffe_fov_integrate_cube(ecube, limits);
01152 
01153                 if ((ecube == NULL) || (eimage == NULL)) {
01154 
01155                     cpl_image_delete(eimage);
01156                     eimage = NULL;
01157 
01158                     giraffe_cube_delete(ecube);
01159                     ecube = NULL;
01160 
01161                     failed = TRUE;
01162 
01163                     cpl_msg_error(fctid, "Cannot create error cube!");
01164 
01165                 }
01166                 else {
01167 
01168                     giraffe_cube_sqrt(ecube);
01169                     cpl_image_power(eimage, 0.5);
01170 
01171                     giraffe_cube_set_wcs(ecube, wcs, transform);
01172 
01173                     cx_slist_push_back(ecubes, ecube);
01174                     cx_slist_push_back(eimages, eimage);
01175 
01176                 }
01177 
01178             }
01179 
01180             cpl_propertylist_delete(wcs);
01181             wcs = NULL;
01182 
01183             cpl_matrix_delete(transform);
01184             transform = NULL;
01185 
01186             giraffe_image_delete(variance);
01187             variance = NULL;
01188 
01189             if (failed) {
01190 
01191                 cx_slist_destroy(simages, (cx_free_func)cpl_image_delete);
01192                 simages = NULL;
01193 
01194                 cx_slist_destroy(eimages, (cx_free_func)cpl_image_delete);
01195                 eimages = NULL;
01196 
01197                 cx_slist_destroy(scubes, (cx_free_func)giraffe_cube_delete);
01198                 scubes = NULL;
01199 
01200                 cx_slist_destroy(ecubes, (cx_free_func)giraffe_cube_delete);
01201                 ecubes = NULL;
01202 
01203                 giraffe_range_delete(limits);
01204                 limits = NULL;
01205 
01206                 return 1;
01207 
01208             }
01209 
01210             break;
01211         }
01212 
01213         default:
01214             return 1;
01215             break;
01216     }
01217 
01218 
01219     /*
01220      * Fill the results container.
01221      */
01222 
01223     result->mode = mode;
01224     result->ssn  = ssn;
01225     ssn = NULL;
01226 
01227     properties = giraffe_image_get_properties(rebinning->spectra);
01228     fov = cx_slist_pop_front(simages);
01229 
01230     result->fov.spectra = giraffe_image_new(CPL_TYPE_DOUBLE);
01231     giraffe_image_set(result->fov.spectra, fov);
01232     giraffe_image_set_properties(result->fov.spectra, properties);
01233 
01234     properties = giraffe_image_get_properties(result->fov.spectra);
01235 
01236     /* Clear left over WCS keywords  */
01237 
01238     giraffe_propertylist_update_wcs(properties, 0, NULL, NULL, NULL,
01239                                     NULL, NULL);
01240 
01241     cpl_propertylist_update_double(properties, GIALIAS_FOV_BANDMIN,
01242                                    giraffe_range_get_min(limits));
01243     cpl_propertylist_set_comment(properties, GIALIAS_FOV_BANDMIN,
01244                                  "Minimum wavelength of FOV band");
01245 
01246     cpl_propertylist_update_double(properties, GIALIAS_FOV_BANDMAX,
01247                                    giraffe_range_get_max(limits));
01248     cpl_propertylist_set_comment(properties, GIALIAS_FOV_BANDMAX,
01249                                  "Maximum wavelength of FOV band");
01250 
01251     cpl_image_delete(fov);
01252     fov = NULL;
01253 
01254 
01255     properties = giraffe_image_get_properties(rebinning->errors);
01256     fov = cx_slist_pop_front(eimages);
01257 
01258     result->fov.errors = giraffe_image_new(CPL_TYPE_DOUBLE);
01259     giraffe_image_set(result->fov.errors, fov);
01260     giraffe_image_set_properties(result->fov.errors, properties);
01261 
01262     properties = giraffe_image_get_properties(result->fov.errors);
01263 
01264     /* Clear left over WCS keywords  */
01265 
01266     giraffe_propertylist_update_wcs(properties, 0, NULL, NULL, NULL,
01267                                     NULL, NULL);
01268     cpl_propertylist_update_double(properties, GIALIAS_FOV_BANDMIN,
01269                                    giraffe_range_get_min(limits));
01270     cpl_propertylist_set_comment(properties, GIALIAS_FOV_BANDMIN,
01271                                  "Minimum wavelength of FOV band");
01272 
01273     cpl_propertylist_update_double(properties, GIALIAS_FOV_BANDMAX,
01274                                    giraffe_range_get_max(limits));
01275     cpl_propertylist_set_comment(properties, GIALIAS_FOV_BANDMAX,
01276                                  "Maximum wavelength of FOV band");
01277 
01278     cpl_image_delete(fov);
01279     fov = NULL;
01280 
01281     if (!cx_slist_empty(simages)) {
01282 
01283         cx_slist_iterator pos = cx_slist_begin(simages);
01284 
01285         result->images.spectra = cx_slist_new();
01286 
01287         while (pos != cx_slist_end(simages)) {
01288 
01289             GiImage* image = giraffe_image_new(CPL_TYPE_DOUBLE);
01290 
01291             giraffe_image_set(image, cx_slist_get(simages, pos));
01292             cx_slist_push_back(result->images.spectra, image);
01293 
01294             pos = cx_slist_next(simages, pos);
01295         }
01296 
01297     }
01298 
01299     if (!cx_slist_empty(eimages)) {
01300 
01301         cx_slist_iterator pos = cx_slist_begin(eimages);
01302 
01303         result->images.errors = cx_slist_new();
01304 
01305         while (pos != cx_slist_end(eimages)) {
01306 
01307             GiImage* image = giraffe_image_new(CPL_TYPE_DOUBLE);
01308 
01309             giraffe_image_set(image, cx_slist_get(eimages, pos));
01310             cx_slist_push_back(result->images.errors, image);
01311 
01312             pos = cx_slist_next(eimages, pos);
01313         }
01314 
01315     }
01316 
01317     if (config->cube == TRUE) {
01318 
01319         if (!cx_slist_empty(scubes)) {
01320             result->cubes.spectra = scubes;
01321             scubes = NULL;
01322         }
01323 
01324         if (!cx_slist_empty(ecubes)) {
01325             result->cubes.errors = ecubes;
01326             ecubes = NULL;
01327         }
01328 
01329     }
01330 
01331 
01332     /*
01333      * Cleanup
01334      */
01335 
01336     giraffe_range_delete(limits);
01337     limits = NULL;
01338 
01339     cx_slist_destroy(simages, (cx_free_func)cpl_image_delete);
01340     simages = NULL;
01341 
01342     cx_slist_destroy(eimages, (cx_free_func)cpl_image_delete);
01343     eimages = NULL;
01344 
01345     if (scubes != NULL) {
01346         cx_slist_destroy(scubes, (cx_free_func)giraffe_cube_delete);
01347         scubes = NULL;
01348     }
01349 
01350     if (ecubes != NULL) {
01351         cx_slist_destroy(ecubes, (cx_free_func)giraffe_cube_delete);
01352         ecubes = NULL;
01353     }
01354 
01355     return 0;
01356 
01357 }
01358 
01359 
01373 GiFieldOfView*
01374 giraffe_fov_new(void)
01375 {
01376     GiFieldOfView* self = cx_malloc(sizeof *self);
01377 
01378     self->mode = GIMODE_NONE;
01379     self->ssn  = NULL;
01380 
01381     self->fov.spectra = NULL;
01382     self->fov.errors  = NULL;
01383 
01384     self->images.spectra = NULL;
01385     self->images.errors  = NULL;
01386 
01387     self->cubes.spectra = NULL;
01388     self->cubes.errors  = NULL;
01389 
01390     return self;
01391 
01392 }
01393 
01394 
01407 void
01408 giraffe_fov_clear(GiFieldOfView* self)
01409 {
01410 
01411     if (self != NULL) {
01412 
01413         if (self->cubes.errors != NULL) {
01414             cx_slist_destroy(self->cubes.errors,
01415                              (cx_free_func)giraffe_cube_delete);
01416             self->cubes.errors = NULL;
01417         }
01418 
01419         if (self->cubes.spectra != NULL) {
01420             cx_slist_destroy(self->cubes.spectra,
01421                              (cx_free_func)giraffe_cube_delete);
01422             self->cubes.spectra = NULL;
01423         }
01424 
01425         if (self->images.errors != NULL) {
01426             cx_slist_destroy(self->images.errors,
01427                              (cx_free_func)giraffe_image_delete);
01428             self->images.errors = NULL;
01429         }
01430 
01431         if (self->images.spectra != NULL) {
01432             cx_slist_destroy(self->images.spectra,
01433                              (cx_free_func)giraffe_image_delete);
01434             self->images.spectra = NULL;
01435         }
01436 
01437         if (self->fov.errors != NULL) {
01438             giraffe_image_delete(self->fov.errors);
01439             self->fov.errors = NULL;
01440         }
01441 
01442         if (self->fov.spectra != NULL) {
01443             giraffe_image_delete(self->fov.spectra);
01444             self->fov.spectra = NULL;
01445         }
01446 
01447         if (self->ssn != NULL) {
01448             cpl_array_delete(self->ssn);
01449             self->ssn = NULL;
01450         }
01451 
01452         self->mode = GIMODE_NONE;
01453 
01454     }
01455 
01456     return;
01457 
01458 }
01459 
01460 
01474 void
01475 giraffe_fov_delete(GiFieldOfView* self)
01476 {
01477 
01478     if (self != NULL) {
01479         giraffe_fov_clear(self);
01480         cx_free(self);
01481     }
01482 
01483     return;
01484 
01485 }
01486 
01487 
01510 cxint
01511 giraffe_fov_save_cubes(const GiFieldOfView* self,
01512                        cpl_propertylist* properties,
01513                        const cxchar* filename, cxptr data)
01514 {
01515 
01516 
01517     cxint component = 0;
01518 
01519     cx_slist* cubes = NULL;
01520 
01521 
01522     if ((self == NULL) || (properties == NULL) || (filename == NULL)) {
01523         return -1;
01524     }
01525 
01526 
01527     /*
01528      * Get the cube component that should be saved. Spectra or errors.
01529      */
01530 
01531     if (data != NULL) {
01532         component = *((cxuint*)data);
01533     }
01534 
01535     if (component == 0) {
01536         cubes = self->cubes.spectra;
01537     }
01538     else {
01539         cubes = self->cubes.errors;
01540     }
01541 
01542     if (cubes == NULL) {
01543         return -2;
01544     }
01545 
01546 
01547     if (!cx_slist_empty(cubes)) {
01548 
01549         if (self->mode == GIMODE_ARGUS) {
01550 
01551             cxint status = 0;
01552             cxint iomode = CPL_IO_CREATE;
01553 
01554             GiCube* cube = cx_slist_front(cubes);
01555 
01556             status = giraffe_cube_save(cube, properties, filename, &iomode);
01557 
01558             if (status != 0) {
01559                 return 1;
01560             }
01561 
01562         }
01563         else {
01564 
01565             cxint nss = 0;
01566             cxint status = 0;
01567             cxint iomode = CPL_IO_CREATE;
01568 
01569             cx_slist_const_iterator pos = cx_slist_begin(cubes);
01570 
01571             cx_string* name = NULL;
01572 
01573             cpl_propertylist* xproperties = NULL;
01574 
01575 
01576             status = giraffe_cube_save(NULL, properties, filename, &iomode);
01577 
01578             if (status != 0) {
01579                 return 1;
01580             }
01581 
01582 
01583             name = cx_string_new();
01584             xproperties = cpl_propertylist_new();
01585 
01586             iomode = CPL_IO_EXTEND;
01587 
01588             while (pos != cx_slist_end(cubes)) {
01589 
01590                 cxint ssn = cpl_array_get_int(self->ssn, nss, NULL);
01591 
01592                 GiCube* cube = cx_slist_get(cubes, pos);
01593 
01594 
01595                 cx_string_sprintf(name, "SSN%-d", ssn);
01596                 cpl_propertylist_update_string(xproperties, "EXTNAME",
01597                                                cx_string_get(name));
01598 
01599                 status = giraffe_cube_save(cube, xproperties, filename,
01600                                            &iomode);
01601 
01602                 if (status != 0) {
01603 
01604                     cpl_propertylist_delete(xproperties);
01605                     xproperties = NULL;
01606 
01607                     cx_string_delete(name);
01608                     name = NULL;
01609 
01610                     return 1;
01611 
01612                 }
01613 
01614                 pos = cx_slist_next(cubes, pos);
01615                 ++nss;
01616 
01617             }
01618 
01619             cpl_propertylist_delete(xproperties);
01620             xproperties = NULL;
01621 
01622             cx_string_delete(name);
01623             name = NULL;
01624 
01625         }
01626 
01627     }
01628 
01629     return 0;
01630 
01631 }
01632 
01633 
01653 cxint
01654 giraffe_fov_save_cubes_eso3d(const GiFieldOfView* self,
01655                              cpl_propertylist* properties,
01656                              const cxchar* filename, cxptr data)
01657 {
01658 
01659     const cxchar* data_name     = "SPECTRA";
01660     const cxchar* error_name    = "ERRORS";
01661     const cxchar* link_names[2] = {"SCIDATA", "ERRDATA"};
01662 
01663     cx_slist* scubes = NULL;
01664     cx_slist* ecubes = NULL;
01665 
01666 
01667     /* Currently not used. Set to avoid compiler warnings */
01668 
01669     data = NULL;
01670 
01671 
01672     if ((self == NULL) || (properties == NULL) || (filename == NULL)) {
01673         return -1;
01674     }
01675 
01676     if (self->cubes.spectra == NULL) {
01677         return -2;
01678     }
01679 
01680     if ((cpl_propertylist_has(properties, GIALIAS_EQUINOX) == FALSE) ||
01681         (cpl_propertylist_get_type(properties, GIALIAS_EQUINOX)
01682                 != CPL_TYPE_DOUBLE)) {
01683         return -2;
01684     }
01685 
01686 
01687     /*
01688      * Get the cube components. If errors are present their number must
01689      * match the number of spectrum cubes!
01690      */
01691 
01692     scubes = self->cubes.spectra;
01693 
01694     if (cx_slist_empty(scubes)) {
01695         return -3;
01696     }
01697 
01698     if (self->cubes.errors != NULL) {
01699 
01700         ecubes = self->cubes.errors;
01701 
01702         if (cx_slist_size(scubes) != cx_slist_size(ecubes)) {
01703             return -4;
01704         }
01705 
01706     }
01707 
01708 
01709     if (self->mode == GIMODE_ARGUS) {
01710 
01711         cxint status = 0;
01712         cxint iomode = CPL_IO_CREATE;
01713 
01714         cxdouble equinox = cpl_propertylist_get_double(properties,
01715                                                        GIALIAS_EQUINOX);
01716 
01717         cpl_propertylist* xproperties = NULL;
01718 
01719         GiCube* scube = cx_slist_front(scubes);
01720 
01721 
01722         status = giraffe_cube_save(NULL, properties, filename, &iomode);
01723 
01724         if (status != 0) {
01725             return 1;
01726         }
01727 
01728 
01729         iomode = CPL_IO_EXTEND;
01730 
01731         xproperties = cpl_propertylist_new();
01732 
01733         cpl_propertylist_update_string(xproperties, GIALIAS_EXTNAME, data_name);
01734         cpl_propertylist_set_comment(xproperties, GIALIAS_EXTNAME,
01735                                      "FITS Extension name");
01736 
01737         cpl_propertylist_update_string(xproperties, "HDUCLASS", "ESO");
01738         cpl_propertylist_set_comment(xproperties, "HDUCLASS",
01739                                      "Conforms to ESO data cube conventions");
01740 
01741         cpl_propertylist_update_string(xproperties, "HDUDOC", "DICD");
01742         cpl_propertylist_set_comment(xproperties, "HDUDOC",
01743                                      "Data format specification document");
01744 
01745         cpl_propertylist_update_string(xproperties, "HDUVERS",
01746                                        "DICD version 6");
01747         cpl_propertylist_set_comment(xproperties, "HDUVERS",
01748                                      "Specific version of the data format "
01749                                      "document");
01750 
01751         cpl_propertylist_update_string(xproperties, "HDUCLAS1", "IMAGE");
01752         cpl_propertylist_set_comment(xproperties, "HDUCLAS1",
01753                                      "Image data format");
01754 
01755         cpl_propertylist_update_string(xproperties, "HDUCLAS2", "DATA");
01756         cpl_propertylist_set_comment(xproperties, "HDUCLAS2",
01757                                      "Science data extension");
01758         cpl_propertylist_update_string(xproperties, link_names[1], error_name);
01759         cpl_propertylist_set_comment(xproperties, link_names[1],
01760                                      "Linked error data extension");
01761 
01762         cpl_propertylist_update_double(xproperties, GIALIAS_EQUINOX,
01763                                        equinox);
01764 
01765         status = giraffe_cube_save(scube, xproperties, filename,
01766                                    &iomode);
01767 
01768         if (status != 0) {
01769 
01770             cpl_propertylist_delete(xproperties);
01771             xproperties = NULL;
01772 
01773             return 1;
01774 
01775         }
01776 
01777         cpl_propertylist_erase(xproperties, link_names[1]);
01778         cpl_propertylist_erase(xproperties, "BUNIT");
01779         cpl_propertylist_erase(xproperties, "DATAMIN");
01780         cpl_propertylist_erase(xproperties, "DATAMAX");
01781 
01782 
01783         if (ecubes != NULL) {
01784 
01785             GiCube* ecube = cx_slist_front(ecubes);
01786 
01787 
01788             cpl_propertylist_update_string(xproperties, "EXTNAME", error_name);
01789 
01790             cpl_propertylist_update_string(xproperties, "HDUCLAS2", "ERROR");
01791             cpl_propertylist_set_comment(xproperties, "HDUCLAS2",
01792                                          "Error data extension");
01793 
01794             cpl_propertylist_update_string(xproperties, "HDUCLAS3", "RMSE");
01795             cpl_propertylist_set_comment(xproperties, "HDUCLAS3",
01796                                          "Type of error: root mean squared");
01797 
01798             cpl_propertylist_update_string(xproperties, link_names[0],
01799                                            data_name);
01800             cpl_propertylist_set_comment(xproperties, link_names[0],
01801                                          "Linked science data extension");
01802 
01803             status = giraffe_cube_save(ecube, xproperties, filename,
01804                                        &iomode);
01805 
01806             if (status != 0) {
01807 
01808                 cpl_propertylist_delete(xproperties);
01809                 xproperties = NULL;
01810 
01811                 return 1;
01812 
01813             }
01814 
01815         }
01816 
01817         cpl_propertylist_delete(xproperties);
01818         xproperties = NULL;
01819 
01820     }
01821     else {
01822 
01823         cxint nss = 0;
01824         cxint status = 0;
01825         cxint iomode = CPL_IO_CREATE;
01826 
01827         cxdouble equinox = cpl_propertylist_get_double(properties,
01828                                                        GIALIAS_EQUINOX);
01829 
01830         cx_slist_const_iterator spos = cx_slist_begin(scubes);
01831         cx_slist_const_iterator epos = cx_slist_begin(ecubes);
01832 
01833         cx_string* name = NULL;
01834 
01835         cpl_propertylist* xproperties = NULL;
01836 
01837 
01838         status = giraffe_cube_save(NULL, properties, filename, &iomode);
01839 
01840         if (status != 0) {
01841             return 1;
01842         }
01843 
01844 
01845         name = cx_string_new();
01846         xproperties = cpl_propertylist_new();
01847 
01848         iomode = CPL_IO_EXTEND;
01849 
01850         while (spos != cx_slist_end(scubes)) {
01851 
01852             cxint ssn = cpl_array_get_int(self->ssn, nss, NULL);
01853 
01854             GiCube* scube = cx_slist_get(scubes, spos);
01855 
01856 
01857             cx_string_sprintf(name, "SSN%-d.%s", ssn, data_name);
01858 
01859             cpl_propertylist_update_string(xproperties, GIALIAS_EXTNAME,
01860                                            cx_string_get(name));
01861             cpl_propertylist_set_comment(xproperties, GIALIAS_EXTNAME,
01862                                          "FITS Extension name");
01863 
01864             cpl_propertylist_update_string(xproperties, "HDUCLASS", "ESO");
01865             cpl_propertylist_set_comment(xproperties, "HDUCLASS",
01866                                          "Conforms to ESO data cube "
01867                                          "conventions");
01868 
01869             cpl_propertylist_update_string(xproperties, "HDUDOC", "DICD");
01870             cpl_propertylist_set_comment(xproperties, "HDUDOC",
01871                                          "Data format specification document");
01872 
01873             cpl_propertylist_update_string(xproperties, "HDUVERS",
01874                                            "DICD version 6");
01875             cpl_propertylist_set_comment(xproperties, "HDUVERS",
01876                                          "Specific version of the data format "
01877                                          "document");
01878 
01879             cpl_propertylist_update_string(xproperties, "HDUCLAS1", "IMAGE");
01880             cpl_propertylist_set_comment(xproperties, "HDUCLAS1",
01881                                          "Image data format");
01882 
01883             cpl_propertylist_update_string(xproperties, "HDUCLAS2", "DATA");
01884             cpl_propertylist_set_comment(xproperties, "HDUCLAS2",
01885                                          "Science data extension");
01886 
01887             cx_string_sprintf(name, "SSN%-d.%s", ssn, error_name);
01888 
01889             cpl_propertylist_update_string(xproperties, link_names[1],
01890                                            cx_string_get(name));
01891             cpl_propertylist_set_comment(xproperties, link_names[1],
01892                                          "Linked error data extension");
01893 
01894             cpl_propertylist_update_double(xproperties, GIALIAS_EQUINOX,
01895                                            equinox);
01896 
01897             status = giraffe_cube_save(scube, xproperties, filename,
01898                                        &iomode);
01899 
01900             if (status != 0) {
01901 
01902                 cpl_propertylist_delete(xproperties);
01903                 xproperties = NULL;
01904 
01905                 cx_string_delete(name);
01906                 name = NULL;
01907 
01908                 return 1;
01909 
01910             }
01911 
01912             cpl_propertylist_erase(xproperties, link_names[1]);
01913             cpl_propertylist_erase(xproperties, "BUNIT");
01914             cpl_propertylist_erase(xproperties, "DATAMIN");
01915             cpl_propertylist_erase(xproperties, "DATAMAX");
01916 
01917 
01918             if (ecubes != NULL) {
01919 
01920                 GiCube* ecube = cx_slist_get(ecubes, epos);
01921 
01922 
01923                 cx_string_sprintf(name, "SSN%-d.%s", ssn, error_name);
01924 
01925                 cpl_propertylist_update_string(xproperties, "EXTNAME",
01926                                                cx_string_get(name));
01927 
01928                 cpl_propertylist_update_string(xproperties, "HDUCLAS2", "ERROR");
01929                 cpl_propertylist_set_comment(xproperties, "HDUCLAS2",
01930                                              "Error data extension");
01931 
01932                 cpl_propertylist_update_string(xproperties, "HDUCLAS3", "RMSE");
01933                 cpl_propertylist_set_comment(xproperties, "HDUCLAS3",
01934                                              "Type of error: root mean squared");
01935 
01936                 cx_string_sprintf(name, "SSN%-d.%s", ssn, data_name);
01937 
01938                 cpl_propertylist_update_string(xproperties, link_names[0],
01939                                                cx_string_get(name));
01940                 cpl_propertylist_set_comment(xproperties, link_names[0],
01941                                              "Linked science data extension");
01942 
01943                 status = giraffe_cube_save(ecube, xproperties, filename,
01944                                            &iomode);
01945 
01946 
01947                 if (status != 0) {
01948 
01949                     cpl_propertylist_delete(xproperties);
01950                     xproperties = NULL;
01951 
01952                     cx_string_delete(name);
01953                     name = NULL;
01954 
01955                     return 1;
01956 
01957                 }
01958 
01959                 epos = cx_slist_next(ecubes, epos);
01960 
01961             }
01962 
01963             spos = cx_slist_next(scubes, spos);
01964             ++nss;
01965 
01966         }
01967 
01968         cpl_propertylist_delete(xproperties);
01969         xproperties = NULL;
01970 
01971         cx_string_delete(name);
01972         name = NULL;
01973 
01974     }
01975 
01976     return 0;
01977 
01978 }
01979 
01980 
01992 GiFieldOfViewConfig*
01993 giraffe_fov_config_create(cpl_parameterlist* list)
01994 {
01995 
01996     const cxchar* s = NULL;
01997 
01998     cpl_parameter* p;
01999 
02000     GiFieldOfViewConfig* config = NULL;
02001 
02002 
02003     if (list == NULL) {
02004         return NULL;
02005     }
02006 
02007     config = cx_calloc(1, sizeof *config);
02008 
02009 
02010     p = cpl_parameterlist_find(list, "giraffe.fov.range.minimum");
02011     config->minimum = cpl_parameter_get_double(p);
02012 
02013     p = cpl_parameterlist_find(list, "giraffe.fov.range.maximum");
02014     config->maximum = cpl_parameter_get_double(p);
02015 
02016     p = cpl_parameterlist_find(list, "giraffe.fov.cube");
02017     config->cube = cpl_parameter_get_bool(p);
02018 
02019     p = cpl_parameterlist_find(list, "giraffe.fov.cube.format");
02020     s = cpl_parameter_get_string(p);
02021 
02022     if (strcmp(s, "single") == 0) {
02023         config->format = GIFOV_FORMAT_SINGLE;
02024     }
02025     else if (strcmp(s, "eso3d") == 0) {
02026         config->format = GIFOV_FORMAT_ESO3D;
02027     }
02028 
02029     return config;
02030 
02031 }
02032 
02033 
02047 void
02048 giraffe_fov_config_destroy(GiFieldOfViewConfig* config)
02049 {
02050 
02051     if (config != NULL) {
02052         cx_free(config);
02053     }
02054 
02055     return;
02056 
02057 }
02058 
02059 
02069 void
02070 giraffe_fov_config_add(cpl_parameterlist* list)
02071 {
02072 
02073     cpl_parameter* p;
02074 
02075 
02076     if (list == NULL) {
02077         return;
02078     }
02079 
02080     p = cpl_parameter_new_value("giraffe.fov.range.minimum",
02081                                 CPL_TYPE_DOUBLE,
02082                                 "Minimum wavelength for image reconstruction",
02083                                 "giraffe.fov.range",
02084                                 0.);
02085     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "recon-min");
02086     cpl_parameterlist_append(list, p);
02087 
02088 
02089     p = cpl_parameter_new_value("giraffe.fov.range.maximum",
02090                                 CPL_TYPE_DOUBLE,
02091                                 "Maximum wavelength for image reconstruction",
02092                                 "giraffe.fov.range",
02093                                 0.);
02094     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "recon-max");
02095     cpl_parameterlist_append(list, p);
02096 
02097 
02098     p = cpl_parameter_new_value("giraffe.fov.cube",
02099                                 CPL_TYPE_BOOL,
02100                                 "Turns data cube creation on and off",
02101                                 "giraffe.fov.cube",
02102                                 TRUE);
02103     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "recon-cube");
02104     cpl_parameterlist_append(list, p);
02105 
02106     p = cpl_parameter_new_enum("giraffe.fov.cube.format",
02107                                 CPL_TYPE_STRING,
02108                                 "Selects the file format for cubes",
02109                                 "giraffe.fov.cube",
02110                                 "single", 2, "single", "eso3d");
02111     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "recon-format");
02112     cpl_parameterlist_append(list, p);
02113 
02114     return;
02115 
02116 }

This file is part of the GIRAFFE Pipeline Reference Manual 2.11.1.
Documentation copyright © 2002-2006 European Southern Observatory.
Generated on Fri May 24 12:29:02 2013 by doxygen 1.4.7 written by Dimitri van Heesch, © 1997-2004