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             if (scube != NULL) {
01028 
01029                 cxdouble xorigin = giraffe_cube_get_width(scube) / 2.;
01030                 cxdouble yorigin = giraffe_cube_get_height(scube) / 2.;
01031 
01032                 cxdouble xvalue = cpl_propertylist_get_double(properties,
01033                                                               GIALIAS_RADEG);
01034                 cxdouble yvalue = cpl_propertylist_get_double(properties,
01035                                                               GIALIAS_DECDEG);
01036                 cxdouble zvalue   = 0.;
01037                 cxdouble zstep    = 0.;
01038                 cxdouble angle    =
01039                         cpl_propertylist_get_double(properties,
01040                                                     GIALIAS_POSANG) +
01041                         GI_ARGUS_POSANG_OFFSET;
01042 
01043                 cxdouble pixscale = GI_ARGUS_PIXSCALE_LOW;
01044 
01045                 const cxchar* scale =
01046                         cpl_propertylist_get_string(properties,
01047                                                     GIALIAS_ARGUS_SCALE);
01048 
01049 
01050                 if ((scale != NULL) && (strcmp(scale, "POS_1_67") == 0)) {
01051                     pixscale = GI_ARGUS_PIXSCALE_HIGH;
01052                 }
01053 
01054                 /* Get pixel scale in degrees */
01055 
01056                 pixscale /= 3600.;
01057 
01058 
01059                 transform = cpl_matrix_new(3, 3);
01060 
01061                 wcs = cpl_propertylist_new();
01062 
01063                 cpl_propertylist_update_double(wcs, "XORIGIN", xorigin);
01064                 cpl_propertylist_update_double(wcs, "YORIGIN", yorigin);
01065                 cpl_propertylist_update_double(wcs, "ZORIGIN", 1.);
01066 
01067                 giraffe_cube_get_zaxis(scube, &zvalue, &zstep);
01068 
01069                 cpl_propertylist_update_double(wcs, "XPOINT", xvalue);
01070                 cpl_propertylist_update_double(wcs, "YPOINT", yvalue);
01071                 cpl_propertylist_update_double(wcs, "ZPOINT", zvalue);
01072 
01073                 cpl_propertylist_update_string(wcs, "XTYPE", "RA---TAN");
01074                 cpl_propertylist_update_string(wcs, "YTYPE", "DEC--TAN");
01075 
01076                 if (log_scale == TRUE) {
01077                     cpl_propertylist_update_string(wcs,
01078                                                    "ZTYPE", "AWAV-LOG");
01079                 }
01080                 else {
01081                     cpl_propertylist_update_string(wcs,
01082                                                    "ZTYPE", "AWAV");
01083                 }
01084 
01085                 cpl_propertylist_update_string(wcs, "XUNIT", "deg");
01086                 cpl_propertylist_update_string(wcs, "YUNIT", "deg");
01087                 cpl_propertylist_update_string(wcs, "ZUNIT", "nm");
01088 
01089 
01090                 /*
01091                  * Right ascension is counted eastward from the equinox,
01092                  * hence the negative sign on the upper left element of the
01093                  * scale matrix.
01094                  */
01095 
01096                 angle *= CX_PI / 180.;
01097 
01098                 cpl_matrix_set(transform, 0, 0, -pixscale *  cos(angle));
01099                 cpl_matrix_set(transform, 0, 1,  pixscale * -sin(angle));
01100                 cpl_matrix_set(transform, 1, 0, -pixscale *  sin(angle));
01101                 cpl_matrix_set(transform, 1, 1,  pixscale *  cos(angle));
01102                 cpl_matrix_set(transform, 2, 2, zstep);
01103 
01104             }
01105 
01106 
01107             if (scube != NULL) {
01108                 simage = _giraffe_fov_integrate_cube(scube, limits);
01109             }
01110 
01111             if ((scube == NULL) || (simage == NULL)) {
01112 
01113                 cpl_image_delete(simage);
01114                 simage = NULL;
01115 
01116                 giraffe_cube_delete(scube);
01117                 scube = NULL;
01118 
01119                 failed = TRUE;
01120 
01121                 cpl_msg_error(fctid, "Cannot create data cube!");
01122 
01123             }
01124             else {
01125 
01126                 giraffe_cube_set_wcs(scube, wcs, transform);
01127 
01128                 cx_slist_push_back(scubes, scube);
01129                 cx_slist_push_back(simages, simage);
01130 
01131             }
01132 
01133 
01134             if (!failed) {
01135 
01136                 ecube = _giraffe_fov_create_cube(variance, _fibers, NULL);
01137                 eimage = _giraffe_fov_integrate_cube(ecube, limits);
01138 
01139                 if ((ecube == NULL) || (eimage == NULL)) {
01140 
01141                     cpl_image_delete(eimage);
01142                     eimage = NULL;
01143 
01144                     giraffe_cube_delete(ecube);
01145                     ecube = NULL;
01146 
01147                     failed = TRUE;
01148 
01149                     cpl_msg_error(fctid, "Cannot create error cube!");
01150 
01151                 }
01152                 else {
01153 
01154                     giraffe_cube_sqrt(ecube);
01155                     cpl_image_power(eimage, 0.5);
01156 
01157                     giraffe_cube_set_wcs(ecube, wcs, transform);
01158 
01159                     cx_slist_push_back(ecubes, ecube);
01160                     cx_slist_push_back(eimages, eimage);
01161 
01162                 }
01163 
01164             }
01165 
01166             cpl_propertylist_delete(wcs);
01167             wcs = NULL;
01168 
01169             cpl_matrix_delete(transform);
01170             transform = NULL;
01171 
01172             giraffe_image_delete(variance);
01173             variance = NULL;
01174 
01175             if (failed) {
01176 
01177                 cx_slist_destroy(simages, (cx_free_func)cpl_image_delete);
01178                 simages = NULL;
01179 
01180                 cx_slist_destroy(eimages, (cx_free_func)cpl_image_delete);
01181                 eimages = NULL;
01182 
01183                 cx_slist_destroy(scubes, (cx_free_func)giraffe_cube_delete);
01184                 scubes = NULL;
01185 
01186                 cx_slist_destroy(ecubes, (cx_free_func)giraffe_cube_delete);
01187                 ecubes = NULL;
01188 
01189                 giraffe_range_delete(limits);
01190                 limits = NULL;
01191 
01192                 return 1;
01193 
01194             }
01195 
01196             break;
01197         }
01198 
01199         default:
01200             return 1;
01201             break;
01202     }
01203 
01204 
01205     /*
01206      * Fill the results container.
01207      */
01208 
01209     result->mode = mode;
01210     result->ssn  = ssn;
01211     ssn = NULL;
01212 
01213     properties = giraffe_image_get_properties(rebinning->spectra);
01214     fov = cx_slist_pop_front(simages);
01215 
01216     result->fov.spectra = giraffe_image_new(CPL_TYPE_DOUBLE);
01217     giraffe_image_set(result->fov.spectra, fov);
01218     giraffe_image_set_properties(result->fov.spectra, properties);
01219 
01220     properties = giraffe_image_get_properties(result->fov.spectra);
01221 
01222     cpl_propertylist_update_double(properties, GIALIAS_FOV_BANDMIN,
01223                                    giraffe_range_get_min(limits));
01224     cpl_propertylist_set_comment(properties, GIALIAS_FOV_BANDMIN,
01225                                  "Minimum wavelength of FOV band");
01226 
01227     cpl_propertylist_update_double(properties, GIALIAS_FOV_BANDMAX,
01228                                    giraffe_range_get_max(limits));
01229     cpl_propertylist_set_comment(properties, GIALIAS_FOV_BANDMAX,
01230                                  "Maximum wavelength of FOV band");
01231 
01232     cpl_image_delete(fov);
01233     fov = NULL;
01234 
01235 
01236     properties = giraffe_image_get_properties(rebinning->errors);
01237     fov = cx_slist_pop_front(eimages);
01238 
01239     result->fov.errors = giraffe_image_new(CPL_TYPE_DOUBLE);
01240     giraffe_image_set(result->fov.errors, fov);
01241     giraffe_image_set_properties(result->fov.errors, properties);
01242 
01243     properties = giraffe_image_get_properties(result->fov.errors);
01244 
01245     cpl_propertylist_update_double(properties, GIALIAS_FOV_BANDMIN,
01246                                    giraffe_range_get_min(limits));
01247     cpl_propertylist_set_comment(properties, GIALIAS_FOV_BANDMIN,
01248                                  "Minimum wavelength of FOV band");
01249 
01250     cpl_propertylist_update_double(properties, GIALIAS_FOV_BANDMAX,
01251                                    giraffe_range_get_max(limits));
01252     cpl_propertylist_set_comment(properties, GIALIAS_FOV_BANDMAX,
01253                                  "Maximum wavelength of FOV band");
01254 
01255     cpl_image_delete(fov);
01256     fov = NULL;
01257 
01258     if (!cx_slist_empty(simages)) {
01259 
01260         cx_slist_iterator pos = cx_slist_begin(simages);
01261 
01262         result->images.spectra = cx_slist_new();
01263 
01264         while (pos != cx_slist_end(simages)) {
01265 
01266             GiImage* image = giraffe_image_new(CPL_TYPE_DOUBLE);
01267 
01268             giraffe_image_set(image, cx_slist_get(simages, pos));
01269             cx_slist_push_back(result->images.spectra, image);
01270 
01271             pos = cx_slist_next(simages, pos);
01272         }
01273 
01274     }
01275 
01276     if (!cx_slist_empty(eimages)) {
01277 
01278         cx_slist_iterator pos = cx_slist_begin(eimages);
01279 
01280         result->images.errors = cx_slist_new();
01281 
01282         while (pos != cx_slist_end(eimages)) {
01283 
01284             GiImage* image = giraffe_image_new(CPL_TYPE_DOUBLE);
01285 
01286             giraffe_image_set(image, cx_slist_get(eimages, pos));
01287             cx_slist_push_back(result->images.errors, image);
01288 
01289             pos = cx_slist_next(eimages, pos);
01290         }
01291 
01292     }
01293 
01294     if (config->cube == TRUE) {
01295 
01296         if (!cx_slist_empty(scubes)) {
01297             result->cubes.spectra = scubes;
01298             scubes = NULL;
01299         }
01300 
01301         if (!cx_slist_empty(ecubes)) {
01302             result->cubes.errors = ecubes;
01303             ecubes = NULL;
01304         }
01305 
01306     }
01307 
01308 
01309     /*
01310      * Cleanup
01311      */
01312 
01313     giraffe_range_delete(limits);
01314     limits = NULL;
01315 
01316     cx_slist_destroy(simages, (cx_free_func)cpl_image_delete);
01317     simages = NULL;
01318 
01319     cx_slist_destroy(eimages, (cx_free_func)cpl_image_delete);
01320     eimages = NULL;
01321 
01322     if (scubes != NULL) {
01323         cx_slist_destroy(scubes, (cx_free_func)giraffe_cube_delete);
01324         scubes = NULL;
01325     }
01326 
01327     if (ecubes != NULL) {
01328         cx_slist_destroy(ecubes, (cx_free_func)giraffe_cube_delete);
01329         ecubes = NULL;
01330     }
01331 
01332     return 0;
01333 
01334 }
01335 
01336 
01350 GiFieldOfView*
01351 giraffe_fov_new(void)
01352 {
01353     GiFieldOfView* self = cx_malloc(sizeof *self);
01354 
01355     self->mode = GIMODE_NONE;
01356     self->ssn  = NULL;
01357 
01358     self->fov.spectra = NULL;
01359     self->fov.errors  = NULL;
01360 
01361     self->images.spectra = NULL;
01362     self->images.errors  = NULL;
01363 
01364     self->cubes.spectra = NULL;
01365     self->cubes.errors  = NULL;
01366 
01367     return self;
01368 
01369 }
01370 
01371 
01384 void
01385 giraffe_fov_clear(GiFieldOfView* self)
01386 {
01387 
01388     if (self != NULL) {
01389 
01390         if (self->cubes.errors != NULL) {
01391             cx_slist_destroy(self->cubes.errors,
01392                              (cx_free_func)giraffe_cube_delete);
01393             self->cubes.errors = NULL;
01394         }
01395 
01396         if (self->cubes.spectra != NULL) {
01397             cx_slist_destroy(self->cubes.spectra,
01398                              (cx_free_func)giraffe_cube_delete);
01399             self->cubes.spectra = NULL;
01400         }
01401 
01402         if (self->images.errors != NULL) {
01403             cx_slist_destroy(self->images.errors,
01404                              (cx_free_func)giraffe_image_delete);
01405             self->images.errors = NULL;
01406         }
01407 
01408         if (self->images.spectra != NULL) {
01409             cx_slist_destroy(self->images.spectra,
01410                              (cx_free_func)giraffe_image_delete);
01411             self->images.spectra = NULL;
01412         }
01413 
01414         if (self->fov.errors != NULL) {
01415             giraffe_image_delete(self->fov.errors);
01416             self->fov.errors = NULL;
01417         }
01418 
01419         if (self->fov.spectra != NULL) {
01420             giraffe_image_delete(self->fov.spectra);
01421             self->fov.spectra = NULL;
01422         }
01423 
01424         if (self->ssn != NULL) {
01425             cpl_array_delete(self->ssn);
01426             self->ssn = NULL;
01427         }
01428 
01429         self->mode = GIMODE_NONE;
01430 
01431     }
01432 
01433     return;
01434 
01435 }
01436 
01437 
01451 void
01452 giraffe_fov_delete(GiFieldOfView* self)
01453 {
01454 
01455     if (self != NULL) {
01456         giraffe_fov_clear(self);
01457         cx_free(self);
01458     }
01459 
01460     return;
01461 
01462 }
01463 
01464 
01487 cxint
01488 giraffe_fov_save_cubes(const GiFieldOfView* self,
01489                        cpl_propertylist* properties,
01490                        const cxchar* filename, cxptr data)
01491 {
01492 
01493 
01494     cxint component = 0;
01495 
01496     cx_slist* cubes = NULL;
01497 
01498 
01499     if ((self == NULL) || (properties == NULL) || (filename == NULL)) {
01500         return -1;
01501     }
01502 
01503 
01504     /*
01505      * Get the cube component that should be saved. Spectra or errors.
01506      */
01507 
01508     if (data != NULL) {
01509         component = *((cxuint*)data);
01510     }
01511 
01512     if (component == 0) {
01513         cubes = self->cubes.spectra;
01514     }
01515     else {
01516         cubes = self->cubes.errors;
01517     }
01518 
01519     if (cubes == NULL) {
01520         return -2;
01521     }
01522 
01523 
01524     if (!cx_slist_empty(cubes)) {
01525 
01526         if (self->mode == GIMODE_ARGUS) {
01527 
01528             cxint status = 0;
01529             cxint iomode = CPL_IO_CREATE;
01530 
01531             GiCube* cube = cx_slist_front(cubes);
01532 
01533             status = giraffe_cube_save(cube, properties, filename, &iomode);
01534 
01535             if (status != 0) {
01536                 return 1;
01537             }
01538 
01539         }
01540         else {
01541 
01542             cxint nss = 0;
01543             cxint status = 0;
01544             cxint iomode = CPL_IO_CREATE;
01545 
01546             cx_slist_const_iterator pos = cx_slist_begin(cubes);
01547 
01548             cx_string* name = NULL;
01549 
01550             cpl_propertylist* xproperties = NULL;
01551 
01552 
01553             status = giraffe_cube_save(NULL, properties, filename, &iomode);
01554 
01555             if (status != 0) {
01556                 return 1;
01557             }
01558 
01559 
01560             name = cx_string_new();
01561             xproperties = cpl_propertylist_new();
01562 
01563             iomode = CPL_IO_EXTEND;
01564 
01565             while (pos != cx_slist_end(cubes)) {
01566 
01567                 cxint ssn = cpl_array_get_int(self->ssn, nss, NULL);
01568 
01569                 GiCube* cube = cx_slist_get(cubes, pos);
01570 
01571 
01572                 cx_string_sprintf(name, "SSN%-d", ssn);
01573                 cpl_propertylist_update_string(xproperties, "EXTNAME",
01574                                                cx_string_get(name));
01575 
01576                 status = giraffe_cube_save(cube, xproperties, filename,
01577                                            &iomode);
01578 
01579                 if (status != 0) {
01580 
01581                     cpl_propertylist_delete(xproperties);
01582                     xproperties = NULL;
01583 
01584                     cx_string_delete(name);
01585                     name = NULL;
01586 
01587                     return 1;
01588 
01589                 }
01590 
01591                 pos = cx_slist_next(cubes, pos);
01592                 ++nss;
01593 
01594             }
01595 
01596             cpl_propertylist_delete(xproperties);
01597             xproperties = NULL;
01598 
01599             cx_string_delete(name);
01600             name = NULL;
01601 
01602         }
01603 
01604     }
01605 
01606     return 0;
01607 
01608 }
01609 
01610 
01630 cxint
01631 giraffe_fov_save_cubes_eso3d(const GiFieldOfView* self,
01632                              cpl_propertylist* properties,
01633                              const cxchar* filename, cxptr data)
01634 {
01635 
01636     const cxchar* data_name     = "SPECTRA";
01637     const cxchar* error_name    = "ERRORS";
01638     const cxchar* link_names[2] = {"SCIDATA", "ERRDATA"};
01639 
01640     cx_slist* scubes = NULL;
01641     cx_slist* ecubes = NULL;
01642 
01643 
01644     /* Currently not used. Set to avoid compiler warnings */
01645 
01646     data = NULL;
01647 
01648 
01649     if ((self == NULL) || (properties == NULL) || (filename == NULL)) {
01650         return -1;
01651     }
01652 
01653     if (self->cubes.spectra == NULL) {
01654         return -2;
01655     }
01656 
01657     if ((cpl_propertylist_has(properties, GIALIAS_EQUINOX) == FALSE) ||
01658         (cpl_propertylist_get_type(properties, GIALIAS_EQUINOX)
01659                 != CPL_TYPE_DOUBLE)) {
01660         return -2;
01661     }
01662 
01663 
01664     /*
01665      * Get the cube components. If errors are present their number must
01666      * match the number of spectrum cubes!
01667      */
01668 
01669     scubes = self->cubes.spectra;
01670 
01671     if (cx_slist_empty(scubes)) {
01672         return -3;
01673     }
01674 
01675     if (self->cubes.errors != NULL) {
01676 
01677         ecubes = self->cubes.errors;
01678 
01679         if (cx_slist_size(scubes) != cx_slist_size(ecubes)) {
01680             return -4;
01681         }
01682 
01683     }
01684 
01685 
01686     if (self->mode == GIMODE_ARGUS) {
01687 
01688         cxint status = 0;
01689         cxint iomode = CPL_IO_CREATE;
01690 
01691         cxdouble equinox = cpl_propertylist_get_double(properties,
01692                                                        GIALIAS_EQUINOX);
01693 
01694         cpl_propertylist* xproperties = NULL;
01695 
01696         GiCube* scube = cx_slist_front(scubes);
01697 
01698 
01699         status = giraffe_cube_save(NULL, properties, filename, &iomode);
01700 
01701         if (status != 0) {
01702             return 1;
01703         }
01704 
01705 
01706         iomode = CPL_IO_EXTEND;
01707 
01708         xproperties = cpl_propertylist_new();
01709 
01710         cpl_propertylist_update_string(xproperties, GIALIAS_EXTNAME, data_name);
01711         cpl_propertylist_set_comment(xproperties, GIALIAS_EXTNAME,
01712                                      "FITS Extension name");
01713 
01714         cpl_propertylist_update_string(xproperties, "HDUCLASS", "ESO");
01715         cpl_propertylist_set_comment(xproperties, "HDUCLASS",
01716                                      "Conforms to ESO data cube conventions");
01717 
01718         cpl_propertylist_update_string(xproperties, "HDUDOC", "DICD");
01719         cpl_propertylist_set_comment(xproperties, "HDUDOC",
01720                                      "Data format specification document");
01721 
01722         cpl_propertylist_update_string(xproperties, "HDUVERS",
01723                                        "DICD version 6");
01724         cpl_propertylist_set_comment(xproperties, "HDUVERS",
01725                                      "Specific version of the data format "
01726                                      "document");
01727 
01728         cpl_propertylist_update_string(xproperties, "HDUCLAS1", "IMAGE");
01729         cpl_propertylist_set_comment(xproperties, "HDUCLAS1",
01730                                      "Image data format");
01731 
01732         cpl_propertylist_update_string(xproperties, "HDUCLAS2", "DATA");
01733         cpl_propertylist_set_comment(xproperties, "HDUCLAS2",
01734                                      "Science data extension");
01735         cpl_propertylist_update_string(xproperties, link_names[1], error_name);
01736         cpl_propertylist_set_comment(xproperties, link_names[1],
01737                                      "Linked error data extension");
01738 
01739         cpl_propertylist_update_double(xproperties, GIALIAS_EQUINOX,
01740                                        equinox);
01741 
01742         status = giraffe_cube_save(scube, xproperties, filename,
01743                                    &iomode);
01744 
01745         if (status != 0) {
01746 
01747             cpl_propertylist_delete(xproperties);
01748             xproperties = NULL;
01749 
01750             return 1;
01751 
01752         }
01753 
01754         cpl_propertylist_erase(xproperties, link_names[1]);
01755         cpl_propertylist_erase(xproperties, "BUNIT");
01756         cpl_propertylist_erase(xproperties, "DATAMIN");
01757         cpl_propertylist_erase(xproperties, "DATAMAX");
01758 
01759 
01760         if (ecubes != NULL) {
01761 
01762             GiCube* ecube = cx_slist_front(ecubes);
01763 
01764 
01765             cpl_propertylist_update_string(xproperties, "EXTNAME", error_name);
01766 
01767             cpl_propertylist_update_string(xproperties, "HDUCLAS2", "ERROR");
01768             cpl_propertylist_set_comment(xproperties, "HDUCLAS2",
01769                                          "Error data extension");
01770 
01771             cpl_propertylist_update_string(xproperties, "HDUCLAS3", "RMSE");
01772             cpl_propertylist_set_comment(xproperties, "HDUCLAS3",
01773                                          "Type of error: root mean squared");
01774 
01775             cpl_propertylist_update_string(xproperties, link_names[0],
01776                                            data_name);
01777             cpl_propertylist_set_comment(xproperties, link_names[0],
01778                                          "Linked science data extension");
01779 
01780             status = giraffe_cube_save(ecube, xproperties, filename,
01781                                        &iomode);
01782 
01783             if (status != 0) {
01784 
01785                 cpl_propertylist_delete(xproperties);
01786                 xproperties = NULL;
01787 
01788                 return 1;
01789 
01790             }
01791 
01792         }
01793 
01794         cpl_propertylist_delete(xproperties);
01795         xproperties = NULL;
01796 
01797     }
01798     else {
01799 
01800         cxint nss = 0;
01801         cxint status = 0;
01802         cxint iomode = CPL_IO_CREATE;
01803 
01804         cxdouble equinox = cpl_propertylist_get_double(properties,
01805                                                        GIALIAS_EQUINOX);
01806 
01807         cx_slist_const_iterator spos = cx_slist_begin(scubes);
01808         cx_slist_const_iterator epos = cx_slist_begin(ecubes);
01809 
01810         cx_string* name = NULL;
01811 
01812         cpl_propertylist* xproperties = NULL;
01813 
01814 
01815         status = giraffe_cube_save(NULL, properties, filename, &iomode);
01816 
01817         if (status != 0) {
01818             return 1;
01819         }
01820 
01821 
01822         name = cx_string_new();
01823         xproperties = cpl_propertylist_new();
01824 
01825         iomode = CPL_IO_EXTEND;
01826 
01827         while (spos != cx_slist_end(scubes)) {
01828 
01829             cxint ssn = cpl_array_get_int(self->ssn, nss, NULL);
01830 
01831             GiCube* scube = cx_slist_get(scubes, spos);
01832 
01833 
01834             cx_string_sprintf(name, "SSN%-d.%s", ssn, data_name);
01835 
01836             cpl_propertylist_update_string(xproperties, GIALIAS_EXTNAME,
01837                                            cx_string_get(name));
01838             cpl_propertylist_set_comment(xproperties, GIALIAS_EXTNAME,
01839                                          "FITS Extension name");
01840 
01841             cpl_propertylist_update_string(xproperties, "HDUCLASS", "ESO");
01842             cpl_propertylist_set_comment(xproperties, "HDUCLASS",
01843                                          "Conforms to ESO data cube "
01844                                          "conventions");
01845 
01846             cpl_propertylist_update_string(xproperties, "HDUDOC", "DICD");
01847             cpl_propertylist_set_comment(xproperties, "HDUDOC",
01848                                          "Data format specification document");
01849 
01850             cpl_propertylist_update_string(xproperties, "HDUVERS",
01851                                            "DICD version 6");
01852             cpl_propertylist_set_comment(xproperties, "HDUVERS",
01853                                          "Specific version of the data format "
01854                                          "document");
01855 
01856             cpl_propertylist_update_string(xproperties, "HDUCLAS1", "IMAGE");
01857             cpl_propertylist_set_comment(xproperties, "HDUCLAS1",
01858                                          "Image data format");
01859 
01860             cpl_propertylist_update_string(xproperties, "HDUCLAS2", "DATA");
01861             cpl_propertylist_set_comment(xproperties, "HDUCLAS2",
01862                                          "Science data extension");
01863 
01864             cx_string_sprintf(name, "SSN%-d.%s", ssn, error_name);
01865 
01866             cpl_propertylist_update_string(xproperties, link_names[1],
01867                                            cx_string_get(name));
01868             cpl_propertylist_set_comment(xproperties, link_names[1],
01869                                          "Linked error data extension");
01870 
01871             cpl_propertylist_update_double(xproperties, GIALIAS_EQUINOX,
01872                                            equinox);
01873 
01874             status = giraffe_cube_save(scube, xproperties, filename,
01875                                        &iomode);
01876 
01877             if (status != 0) {
01878 
01879                 cpl_propertylist_delete(xproperties);
01880                 xproperties = NULL;
01881 
01882                 cx_string_delete(name);
01883                 name = NULL;
01884 
01885                 return 1;
01886 
01887             }
01888 
01889             cpl_propertylist_erase(xproperties, link_names[1]);
01890             cpl_propertylist_erase(xproperties, "BUNIT");
01891             cpl_propertylist_erase(xproperties, "DATAMIN");
01892             cpl_propertylist_erase(xproperties, "DATAMAX");
01893 
01894 
01895             if (ecubes != NULL) {
01896 
01897                 GiCube* ecube = cx_slist_get(ecubes, epos);
01898 
01899 
01900                 cx_string_sprintf(name, "SSN%-d.%s", ssn, error_name);
01901 
01902                 cpl_propertylist_update_string(xproperties, "EXTNAME",
01903                                                cx_string_get(name));
01904 
01905                 cpl_propertylist_update_string(xproperties, "HDUCLAS2", "ERROR");
01906                 cpl_propertylist_set_comment(xproperties, "HDUCLAS2",
01907                                              "Error data extension");
01908 
01909                 cpl_propertylist_update_string(xproperties, "HDUCLAS3", "RMSE");
01910                 cpl_propertylist_set_comment(xproperties, "HDUCLAS3",
01911                                              "Type of error: root mean squared");
01912 
01913                 cx_string_sprintf(name, "SSN%-d.%s", ssn, data_name);
01914 
01915                 cpl_propertylist_update_string(xproperties, link_names[0],
01916                                                cx_string_get(name));
01917                 cpl_propertylist_set_comment(xproperties, link_names[0],
01918                                              "Linked science data extension");
01919 
01920                 status = giraffe_cube_save(ecube, xproperties, filename,
01921                                            &iomode);
01922 
01923 
01924                 if (status != 0) {
01925 
01926                     cpl_propertylist_delete(xproperties);
01927                     xproperties = NULL;
01928 
01929                     cx_string_delete(name);
01930                     name = NULL;
01931 
01932                     return 1;
01933 
01934                 }
01935 
01936                 epos = cx_slist_next(ecubes, epos);
01937 
01938             }
01939 
01940             spos = cx_slist_next(scubes, spos);
01941             ++nss;
01942 
01943         }
01944 
01945         cpl_propertylist_delete(xproperties);
01946         xproperties = NULL;
01947 
01948         cx_string_delete(name);
01949         name = NULL;
01950 
01951     }
01952 
01953     return 0;
01954 
01955 }
01956 
01957 
01969 GiFieldOfViewConfig*
01970 giraffe_fov_config_create(cpl_parameterlist* list)
01971 {
01972 
01973     const cxchar* s = NULL;
01974 
01975     cpl_parameter* p;
01976 
01977     GiFieldOfViewConfig* config = NULL;
01978 
01979 
01980     if (list == NULL) {
01981         return NULL;
01982     }
01983 
01984     config = cx_calloc(1, sizeof *config);
01985 
01986 
01987     p = cpl_parameterlist_find(list, "giraffe.fov.range.minimum");
01988     config->minimum = cpl_parameter_get_double(p);
01989 
01990     p = cpl_parameterlist_find(list, "giraffe.fov.range.maximum");
01991     config->maximum = cpl_parameter_get_double(p);
01992 
01993     p = cpl_parameterlist_find(list, "giraffe.fov.cube");
01994     config->cube = cpl_parameter_get_bool(p);
01995 
01996     p = cpl_parameterlist_find(list, "giraffe.fov.cube.format");
01997     s = cpl_parameter_get_string(p);
01998 
01999     if (strcmp(s, "single") == 0) {
02000         config->format = GIFOV_FORMAT_SINGLE;
02001     }
02002     else if (strcmp(s, "eso3d") == 0) {
02003         config->format = GIFOV_FORMAT_ESO3D;
02004     }
02005 
02006     return config;
02007 
02008 }
02009 
02010 
02024 void
02025 giraffe_fov_config_destroy(GiFieldOfViewConfig* config)
02026 {
02027 
02028     if (config != NULL) {
02029         cx_free(config);
02030     }
02031 
02032     return;
02033 
02034 }
02035 
02036 
02046 void
02047 giraffe_fov_config_add(cpl_parameterlist* list)
02048 {
02049 
02050     cpl_parameter* p;
02051 
02052 
02053     if (list == NULL) {
02054         return;
02055     }
02056 
02057     p = cpl_parameter_new_value("giraffe.fov.range.minimum",
02058                                 CPL_TYPE_DOUBLE,
02059                                 "Minimum wavelength for image reconstruction",
02060                                 "giraffe.fov.range",
02061                                 0.);
02062     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "recon-min");
02063     cpl_parameterlist_append(list, p);
02064 
02065 
02066     p = cpl_parameter_new_value("giraffe.fov.range.maximum",
02067                                 CPL_TYPE_DOUBLE,
02068                                 "Maximum wavelength for image reconstruction",
02069                                 "giraffe.fov.range",
02070                                 0.);
02071     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "recon-max");
02072     cpl_parameterlist_append(list, p);
02073 
02074 
02075     p = cpl_parameter_new_value("giraffe.fov.cube",
02076                                 CPL_TYPE_BOOL,
02077                                 "Turns data cube creation on and off",
02078                                 "giraffe.fov.cube",
02079                                 TRUE);
02080     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "recon-cube");
02081     cpl_parameterlist_append(list, p);
02082 
02083     p = cpl_parameter_new_enum("giraffe.fov.cube.format",
02084                                 CPL_TYPE_STRING,
02085                                 "Selects the file format for cubes",
02086                                 "giraffe.fov.cube",
02087                                 "single", 2, "single", "eso3d");
02088     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "recon-format");
02089     cpl_parameterlist_append(list, p);
02090 
02091     return;
02092 
02093 }

This file is part of the GIRAFFE Pipeline Reference Manual 2.10.
Documentation copyright © 2002-2006 European Southern Observatory.
Generated on Thu Mar 7 14:11:02 2013 by doxygen 1.4.7 written by Dimitri van Heesch, © 1997-2004