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 "gimessages.h"
00042 #include "gigrating.h"
00043 #include "gifov.h"
00044 #include "gifiberutils.h"
00045 #include "gisutils.h"
00046 #include "giutils.h"
00047 
00048 
00058 inline static cxint
00059 _giraffe_compare_int(cxcptr first, cxcptr second)
00060 {
00061 
00062     cxint *_first = (cxint *)first;
00063     cxint *_second = (cxint *)second;
00064 
00065     return *_first - *_second;
00066 
00067 }
00068 
00069 
00070 inline static GiCube*
00071 _giraffe_fov_create_cube(const GiImage* spectra,
00072                          const cpl_table* fibers,
00073                          const GiRange* limits)
00074 {
00075 
00076     cxint first = 0;
00077     cxint last = 0;
00078     cxint nx = 0;
00079     cxint ny = 0;
00080     cxint nz = 0;
00081 
00082     cxdouble wmin = 0.;
00083     cxdouble wmax = 0.;
00084     cxdouble wstep = 0.;
00085     cxdouble fstart = 1.;
00086     cxdouble fend = 1.;
00087 
00088     cpl_propertylist* properties = giraffe_image_get_properties(spectra);
00089 
00090     cpl_image* _spectra = giraffe_image_get(spectra);
00091 
00092     GiCube* cube = NULL;
00093 
00094 
00095     if ((properties == NULL) || (_spectra == NULL)) {
00096         return NULL;
00097     }
00098 
00099 
00100     /*
00101      * Get the spectral range of the input spectra.
00102      */
00103 
00104     if (cpl_propertylist_has(properties, GIALIAS_BINWLMIN) == FALSE) {
00105         return NULL;
00106     }
00107     else {
00108         wmin = cpl_propertylist_get_double(properties, GIALIAS_BINWLMIN);
00109     }
00110 
00111     if (cpl_propertylist_has(properties, GIALIAS_BINWLMAX) == FALSE) {
00112         return NULL;
00113     }
00114     else {
00115         wmax = cpl_propertylist_get_double(properties, GIALIAS_BINWLMAX);
00116     }
00117 
00118     if (cpl_propertylist_has(properties, GIALIAS_BINSTEP) == FALSE) {
00119         return NULL;
00120     }
00121     else {
00122         wstep = cpl_propertylist_get_double(properties, GIALIAS_BINSTEP);
00123     }
00124 
00125 
00126     /*
00127      * Determine the pixel limits corresponding to the spectral range.
00128      */
00129 
00130     first = 0;
00131     last = cpl_image_get_size_y(_spectra) - 1;
00132 
00133     if (limits != NULL) {
00134 
00135         if (giraffe_range_get_min(limits) > wmin) {
00136 
00137             cxdouble pixel = (giraffe_range_get_min(limits) - wmin) / wstep;
00138 
00139 
00140             first  = ceil(pixel);
00141             fstart = pixel - first;
00142 
00143         }
00144 
00145         if (giraffe_range_get_max(limits) < wmax) {
00146 
00147             cxdouble pixel = last - (wmax - giraffe_range_get_max(limits)) / wstep;
00148 
00149 
00150             last = floor(pixel);
00151             fend = pixel - last;
00152 
00153         }
00154 
00155     }
00156 
00157 
00158     /*
00159      * Determine the layout of the cube from the list of fibers.
00160      */
00161 
00162     nx = (cxint) cpl_table_get_column_max(fibers, "X");
00163     ny = (cxint) cpl_table_get_column_max(fibers, "Y");
00164     nz = last - first + 1;
00165 
00166 
00167     /*
00168      * Create the data cube and fill it with the flux values.
00169      */
00170 
00171     cube = giraffe_cube_create(nx, ny, nz, NULL);
00172 
00173     giraffe_cube_set_xaxis(cube, 1., 1.);
00174     giraffe_cube_set_yaxis(cube, 1., 1.);
00175     giraffe_cube_set_zaxis(cube, wmin, wstep);
00176 
00177     if (cube != NULL) {
00178 
00179         register cxint i = 0;
00180         register cxint nf = cpl_table_get_nrow(fibers);
00181 
00182         cxint ns = cpl_image_get_size_x(_spectra);
00183 
00184         cxdouble* spixels = cpl_image_get_data_double(_spectra);
00185         cxdouble* cpixels = giraffe_cube_get_data(cube);
00186 
00187 
00188         cx_assert(spixels != NULL);
00189         cx_assert(cpixels != NULL);
00190         cx_assert(nf <= ns);
00191 
00192         for (i = 0; i < nf; ++i) {
00193 
00194             register cxint j = 0;
00195 
00196             cxint idx = cpl_table_get_int(fibers, "INDEX", i, NULL) - 1;
00197             cxint x = cpl_table_get_int(fibers, "X", i, NULL) - 1;
00198             cxint y = cpl_table_get_int(fibers, "Y", i, NULL) - 1;
00199 
00200 
00201             /*
00202              * Fill image pixels skipping special fibers (CalSim or Sky)
00203              * which have x = 0 and y = 0.
00204              */
00205 
00206             if ((x >= 0) && (y >= 0)) {
00207 
00208                 for (j = 0; j < nz; ++j) {
00209                     cpixels[(ny * j + y) * nx + x] =
00210                         spixels[(first + j) * ns + idx];
00211                 }
00212 
00213             }
00214 
00215         }
00216 
00217     }
00218 
00219     return cube;
00220 
00221 }
00222 
00223 
00224 /*
00225  * Arrange the input images into an output image using a tabular layout.
00226  */
00227 
00228 inline static cpl_image*
00229 _giraffe_fov_arrange_images(const cx_slist* subimages,
00230                             cxsize nrows, cxsize ncolumns, cxint offset)
00231 {
00232 
00233     cxint x = 0;
00234     cxint y = 0;
00235     cxint nx = 0;
00236     cxint ny = 0;
00237     cxint sx = 0;
00238     cxint sy = 0;
00239     cxint xshift = offset;
00240     cxint yshift = offset;
00241 
00242     cxsize nslit = 0;
00243     cxsize column = 0;
00244 
00245     cx_slist_iterator pos;
00246 
00247     cpl_image* image = NULL;
00248 
00249 
00250     cx_assert(subimages != NULL);
00251     cx_assert(nrows > 0);
00252     cx_assert(ncolumns > 0);
00253 
00254 
00255     /*
00256      * Compute the size of the combined output image from the largest
00257      * image in the list. The properties of the mosaic image are taken
00258      * from the first (non-empty) image in the list.
00259      */
00260 
00261     pos = cx_slist_begin(subimages);
00262 
00263     while (pos != cx_slist_end(subimages)) {
00264 
00265         const cpl_image* simage = cx_slist_get(subimages, pos);
00266 
00267         if (simage != NULL) {
00268 
00269             cxint _nx = cpl_image_get_size_x(simage);
00270             cxint _ny = cpl_image_get_size_y(simage);
00271 
00272             sx = CX_MAX(nx, _nx);
00273             sy = CX_MAX(ny, _ny);
00274 
00275         }
00276 
00277         pos = cx_slist_next(subimages, pos);
00278 
00279     }
00280 
00281 
00282     /*
00283      * Adjust the number of rows to what is actually needed.
00284      */
00285 
00286     nslit = cx_slist_size(subimages);
00287     nrows  = CX_MAX(nslit / ncolumns, nrows);
00288 
00289     if (nslit % ncolumns != 0) {
00290         ++nrows;
00291     }
00292 
00293 
00294     /*
00295      * Compute the size of the final "mosaic" image
00296      */
00297 
00298     nx = sx * ncolumns;
00299     ny = sy * nrows;
00300 
00301 
00302     if (offset < 0) {
00303         xshift = nx / -offset + 1;
00304         yshift = ny / -offset + 1;
00305     }
00306 
00307     nx += ncolumns * xshift - (xshift % 2);
00308     ny += nrows * yshift - (yshift % 2);
00309 
00310 
00311     /*
00312      * Arrange subimages into a single image.
00313      */
00314 
00315     image = cpl_image_new(nx, ny, CPL_TYPE_DOUBLE);
00316 
00317     y = yshift / 2;
00318     x = xshift / 2;
00319 
00320     pos = cx_slist_begin(subimages);
00321 
00322     while (pos != cx_slist_end(subimages)) {
00323 
00324         const cpl_image* simage = cx_slist_get(subimages, pos);
00325 
00326         if (simage != NULL) {
00327 
00328             cpl_error_code status = cpl_image_copy(image, simage,
00329                                                    x + 1, y + 1);
00330 
00331             if (status != CPL_ERROR_NONE) {
00332                 cpl_image_delete(image);
00333                 return NULL;
00334             }
00335 
00336         }
00337 
00338         ++column;
00339 
00340         if (column < ncolumns) {
00341             x += sx + xshift;
00342         }
00343         else {
00344             column = 0;
00345 
00346             x = xshift / 2;
00347             y += sy + yshift;
00348         }
00349 
00350         pos = cx_slist_next(subimages, pos);
00351 
00352     }
00353 
00354     return image;
00355 
00356 }
00357 
00358 
00359 inline static cpl_image*
00360 _giraffe_fov_integrate_cube(const GiCube* cube, const GiRange* limits)
00361 {
00362 
00363     cxsize depth = 0;
00364 
00365     cxdouble wmin = 0.;
00366     cxdouble wmax = 0.;
00367     cxdouble wstep = 0.;
00368     cxdouble start = 0.;
00369     cxdouble end = 0.;
00370 
00371     cpl_image* image = NULL;
00372 
00373 
00374     cx_assert(cube != NULL);
00375 
00376     depth = giraffe_cube_get_depth(cube);
00377     giraffe_cube_get_zaxis(cube, &wmin, &wstep);
00378 
00379     wmax = wmin + depth * wstep;
00380     end = depth;
00381 
00382     if (giraffe_range_get_min(limits) > wmin) {
00383         start = (giraffe_range_get_min(limits) - wmin) / wstep;
00384     }
00385 
00386     if (giraffe_range_get_max(limits) < wmax) {
00387         end = (giraffe_range_get_max(limits) - wmin) / wstep;
00388     }
00389 
00390     image = giraffe_cube_integrate(cube, start, end);
00391 
00392     return image;
00393 
00394 }
00395 
00396 
00418 cxint
00419 giraffe_fov_build(GiFieldOfView* result, GiRebinning* rebinning,
00420                   GiTable* fibers, GiTable* wsolution,
00421                   GiTable* grating, GiTable* slitgeometry,
00422                   GiFieldOfViewConfig* config)
00423 {
00424 
00425     const cxchar* const fctid = "giraffe_fov_build";
00426 
00427     cx_slist* simages = NULL;
00428     cx_slist* eimages = NULL;
00429     cx_slist* scubes = NULL;
00430     cx_slist* ecubes = NULL;
00431 
00432     cpl_propertylist* properties = NULL;
00433 
00434     cpl_array* ssn = NULL;
00435 
00436     cpl_image* fov = NULL;
00437 
00438     cpl_table* _fibers = NULL;
00439 
00440     GiInstrumentMode mode;
00441 
00442     GiRange* limits = NULL;
00443 
00444 
00445     if (result == NULL) {
00446         cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
00447         return -1;
00448     }
00449     else {
00450 
00451         /*
00452          * Make sure that the field of view object is empty
00453          */
00454 
00455         giraffe_fov_clear(result);
00456 
00457     }
00458 
00459     if (rebinning == NULL) {
00460         cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
00461         return -1;
00462     }
00463 
00464     if (rebinning->spectra == NULL || rebinning->errors == NULL) {
00465         cpl_error_set(fctid, CPL_ERROR_ILLEGAL_INPUT);
00466         return -1;
00467     }
00468 
00469     if (fibers == NULL) {
00470         cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
00471         return -1;
00472     }
00473 
00474     _fibers = giraffe_table_get(fibers);
00475 
00476     if (_fibers == NULL) {
00477         cpl_error_set(fctid, CPL_ERROR_DATA_NOT_FOUND);
00478         return -1;
00479     }
00480 
00481     if (!cpl_table_has_column(_fibers, "X") ||
00482         !cpl_table_has_column(_fibers, "Y")) {
00483         cpl_error_set(fctid, CPL_ERROR_DATA_NOT_FOUND);
00484         return -2;
00485     }
00486 
00487     if (config == NULL) {
00488         cpl_error_set(fctid, CPL_ERROR_NULL_INPUT);
00489         return -1;
00490     }
00491 
00492 
00493     /*
00494      * Determine the instrument mode. Spectra taken in IFU mode must
00495      * be processed on a per subslit basis, while ARGUS data can
00496      * be processed ignoring the subslit information (simple
00497      * reconstruction based on X and Y positions of fibers only)
00498      */
00499 
00500     properties = giraffe_image_get_properties(rebinning->spectra);
00501 
00502     if (properties == NULL) {
00503         cpl_error_set(fctid, CPL_ERROR_DATA_NOT_FOUND);
00504         return -1;
00505     }
00506 
00507     mode = giraffe_get_mode(properties);
00508 
00509 
00510     /*
00511      * By default the cube and the fov-image will be reconstructed from
00512      * the input spectra common wavelength range. If a wavelength range
00513      * was specified by parameter settings these will be used, clamped
00514      * to the input spectra common wavelength range.
00515      */
00516 
00517     limits = giraffe_rebin_get_wavelength_range(rebinning->spectra, wsolution,
00518                                                 grating, slitgeometry, TRUE);
00519 
00520     if (limits == NULL) {
00521         cpl_msg_error(fctid, "Computation of spectra common wavelength "
00522                       "range failed!");
00523         return 1;
00524     }
00525 
00526     if (config->minimum > 0.) {
00527         if (config->minimum < giraffe_range_get_min(limits)) {
00528             cpl_msg_warning(fctid, "Ignoring invalid wavelength range "
00529                             "minimum %.3f nm", config->minimum);
00530         }
00531         else {
00532             giraffe_range_set_min(limits, config->minimum);
00533         }
00534     }
00535 
00536     if (config->maximum > 0.) {
00537         if (config->maximum > giraffe_range_get_max(limits)) {
00538             cpl_msg_warning(fctid, "Ignoring invalid wavelength range "
00539                             "maximum %.3f nm", config->maximum);
00540         }
00541         else {
00542             giraffe_range_set_max(limits, config->maximum);
00543         }
00544     }
00545 
00546     cpl_msg_info(fctid, "Building image for wavelength range [%.3f nm, "
00547                  "%.3f nm].", giraffe_range_get_min(limits),
00548                  giraffe_range_get_max(limits));
00549 
00550 
00551     /*
00552      * Convert limits if the spectrum wavelength scale is logarithmic
00553      */
00554 
00555     if (cpl_propertylist_has(properties, GIALIAS_BINSCALE)) {
00556 
00557         const cxchar* s = cpl_propertylist_get_string(properties,
00558                                                       GIALIAS_BINSCALE);
00559 
00560         if (cx_strncasecmp(s, "log", 3) == 0) {
00561             giraffe_range_set_min(limits, log(giraffe_range_get_min(limits)));
00562             giraffe_range_set_max(limits, log(giraffe_range_get_max(limits)));
00563         }
00564     }
00565     else {
00566         cpl_msg_warning(fctid, "Could not determine spectrum wavelength "
00567                         "scaling method. Missing property `%s'. Assuming "
00568                         "scaling method `linear'!", GIALIAS_BINSCALE);
00569     }
00570 
00571 
00572     /*
00573      * Create the containers to store the data cubes and the
00574      * reconstructed images.
00575      */
00576 
00577     simages = cx_slist_new();
00578     eimages = cx_slist_new();
00579     scubes  = cx_slist_new();
00580     ecubes  = cx_slist_new();
00581 
00582 
00583     switch (mode) {
00584         case GIMODE_IFU:
00585         {
00586 
00587             cxint i = 0;
00588 
00589             cpl_image* smosaic = NULL;
00590             cpl_image* emosaic = NULL;
00591 
00592             GiImage* variance = NULL;
00593 
00594 
00595             /*
00596              * Determine the number and the list of used subslits.
00597              */
00598 
00599             ssn = giraffe_fiberlist_get_subslits(_fibers);
00600 
00601             if (ssn == NULL) {
00602                 cx_slist_destroy(simages, (cx_free_func)cpl_image_delete);
00603                 simages = NULL;
00604 
00605                 cx_slist_destroy(eimages, (cx_free_func)cpl_image_delete);
00606                 eimages = NULL;
00607 
00608                 cx_slist_destroy(scubes, (cx_free_func)giraffe_cube_delete);
00609                 scubes = NULL;
00610 
00611                 cx_slist_destroy(ecubes, (cx_free_func)giraffe_cube_delete);
00612                 ecubes = NULL;
00613 
00614                 giraffe_range_delete(limits);
00615                 limits = NULL;
00616 
00617                 cpl_msg_error(fctid, "Sub-slit data missing in fiber table!");
00618 
00619                 return 1;
00620             }
00621 
00622 
00623             /*
00624              * Compute the variances from the error map.
00625              */
00626 
00627             variance = giraffe_image_duplicate(rebinning->errors);
00628 
00629             if (variance == NULL) {
00630                 cpl_array_delete(ssn);
00631                 ssn = NULL;
00632 
00633                 cx_slist_destroy(simages, (cx_free_func)cpl_image_delete);
00634                 simages = NULL;
00635 
00636                 cx_slist_destroy(eimages, (cx_free_func)cpl_image_delete);
00637                 eimages = NULL;
00638 
00639                 cx_slist_destroy(scubes, (cx_free_func)giraffe_cube_delete);
00640                 scubes = NULL;
00641 
00642                 cx_slist_destroy(ecubes, (cx_free_func)giraffe_cube_delete);
00643                 ecubes = NULL;
00644 
00645                 giraffe_range_delete(limits);
00646                 limits = NULL;
00647 
00648                 cpl_msg_error(fctid, "Failed to create variance map!");
00649 
00650                 return 1;
00651             }
00652 
00653             cpl_image_power(giraffe_image_get(variance), 2.);
00654 
00655 
00656             /*
00657              * Build the data cubes and images for each sub-slit
00658              */
00659 
00660             for (i = 0; i < cpl_array_get_size(ssn); ++i) {
00661 
00662                 cxbool failed = FALSE;
00663 
00664                 cxint nss = cpl_array_get_int(ssn, i, NULL);
00665 
00666                 cpl_table* ssf = NULL;
00667 
00668                 cpl_table_unselect_all(_fibers);
00669                 cpl_table_or_selected_int(_fibers, "SSN", CPL_EQUAL_TO, nss);
00670 
00671                 ssf = cpl_table_extract_selected(_fibers);
00672 
00673                 if (ssf != NULL) {
00674 
00675                     cpl_image* _simage = NULL;
00676                     cpl_image* _eimage = NULL;
00677 
00678                     GiCube* _scube = NULL;
00679                     GiCube* _ecube = NULL;
00680 
00681 
00682                     _scube = _giraffe_fov_create_cube(rebinning->spectra,
00683                                                       ssf, NULL);
00684 
00685                     if (_scube != NULL) {
00686                         _simage = _giraffe_fov_integrate_cube(_scube, limits);
00687                     }
00688 
00689                     if ((_scube == NULL) || (_simage == NULL)) {
00690 
00691                         cpl_image_delete(_simage);
00692                         _simage = NULL;
00693 
00694                         giraffe_cube_delete(_scube);
00695                         _scube = NULL;
00696 
00697                         failed = TRUE;
00698 
00699                         cpl_msg_error(fctid, "Cannot create data cube for "
00700                                       "sub-slit %d", nss);
00701                     }
00702                     else {
00703                         cx_slist_push_back(scubes, _scube);
00704                         cx_slist_push_back(simages, _simage);
00705                     }
00706 
00707                     if (!failed) {
00708 
00709                         _ecube = _giraffe_fov_create_cube(variance,
00710                                                           ssf, NULL);
00711 
00712                         if (_ecube != NULL) {
00713                             _eimage = _giraffe_fov_integrate_cube(_ecube,
00714                                                                   limits);
00715                         }
00716 
00717                         if ((_ecube == NULL) || (_eimage == NULL)) {
00718 
00719                             cpl_image_delete(_eimage);
00720                             _eimage = NULL;
00721 
00722                             giraffe_cube_delete(_ecube);
00723                             _ecube = NULL;
00724 
00725                             failed = TRUE;
00726 
00727                             cpl_msg_error(fctid, "Cannot create error "
00728                                           "cube for sub-slit %d", nss);
00729                         }
00730                         else {
00731                             giraffe_cube_sqrt(_ecube);
00732                             cpl_image_power(_eimage, 0.5);
00733 
00734                             cx_slist_push_back(ecubes, _ecube);
00735                             cx_slist_push_back(eimages, _eimage);
00736                         }
00737 
00738                     }
00739 
00740                     cpl_table_delete(ssf);
00741                     ssf = NULL;
00742 
00743                     if (failed) {
00744 
00745                         giraffe_image_delete(variance);
00746                         variance = NULL;
00747 
00748                         cpl_array_delete(ssn);
00749                         ssn = NULL;
00750 
00751                         cx_slist_destroy(simages,
00752                                          (cx_free_func)cpl_image_delete);
00753                         simages = NULL;
00754 
00755                         cx_slist_destroy(eimages,
00756                                          (cx_free_func)cpl_image_delete);
00757                         eimages = NULL;
00758 
00759                         cx_slist_destroy(scubes,
00760                                          (cx_free_func)giraffe_cube_delete);
00761                         scubes = NULL;
00762 
00763                         cx_slist_destroy(ecubes,
00764                                          (cx_free_func)giraffe_cube_delete);
00765                         ecubes = NULL;
00766 
00767                         giraffe_range_delete(limits);
00768                         limits = NULL;
00769 
00770                         return 1;
00771 
00772                     }
00773 
00774                 }
00775 
00776             }
00777 
00778             giraffe_image_delete(variance);
00779             variance = NULL;
00780 
00781 
00782             /*
00783              * Put the images of the reconstructed field of view in an
00784              * image using a tabular layout. This mosaic is stored as
00785              * the first image in the image containers, to be consistent
00786              * with the Argus mode, where only this image is provided.
00787              */
00788 
00789             smosaic = _giraffe_fov_arrange_images(simages, 5, 3, -4);
00790             emosaic = _giraffe_fov_arrange_images(eimages, 5, 3, -4);
00791 
00792             if ((smosaic == NULL) || (emosaic == NULL)) {
00793 
00794                 cpl_image_delete(smosaic);
00795                 smosaic = NULL;
00796 
00797                 cpl_image_delete(emosaic);
00798                 emosaic = NULL;
00799 
00800                 cx_slist_destroy(simages, (cx_free_func)cpl_image_delete);
00801                 simages = NULL;
00802 
00803                 cx_slist_destroy(eimages, (cx_free_func)cpl_image_delete);
00804                 eimages = NULL;
00805 
00806                 cx_slist_destroy(scubes, (cx_free_func)giraffe_cube_delete);
00807                 scubes = NULL;
00808 
00809                 cx_slist_destroy(ecubes, (cx_free_func)giraffe_cube_delete);
00810                 ecubes = NULL;
00811 
00812                 cpl_array_delete(ssn);
00813                 ssn = NULL;
00814 
00815                 giraffe_range_delete(limits);
00816                 limits = NULL;
00817 
00818                 return 1;
00819 
00820             }
00821 
00822             cx_slist_push_front(simages, smosaic);
00823             cx_slist_push_front(eimages, emosaic);
00824             break;
00825 
00826         }
00827 
00828         case GIMODE_ARGUS:
00829         {
00830             cxbool failed = FALSE;
00831 
00832             cpl_image* simage = NULL;
00833             cpl_image* eimage = NULL;
00834 
00835             GiImage* variance = NULL;
00836 
00837             GiCube* scube = NULL;
00838             GiCube* ecube = NULL;
00839 
00840 
00841             /*
00842              * Compute the variances from the error map.
00843              */
00844 
00845             variance = giraffe_image_duplicate(rebinning->errors);
00846 
00847             if (variance == NULL) {
00848 
00849                 cx_slist_destroy(simages, (cx_free_func)cpl_image_delete);
00850                 simages = NULL;
00851 
00852                 cx_slist_destroy(eimages, (cx_free_func)cpl_image_delete);
00853                 eimages = NULL;
00854 
00855                 cx_slist_destroy(scubes, (cx_free_func)giraffe_cube_delete);
00856                 scubes = NULL;
00857 
00858                 cx_slist_destroy(ecubes, (cx_free_func)giraffe_cube_delete);
00859                 ecubes = NULL;
00860 
00861                 giraffe_range_delete(limits);
00862                 limits = NULL;
00863 
00864                 cpl_msg_error(fctid, "Failed to create variance map!");
00865                 return 1;
00866 
00867             }
00868 
00869             cpl_image_power(giraffe_image_get(variance), 2.);
00870 
00871 
00872             /*
00873              * Build the data cubes and field of view images
00874              */
00875 
00876             scube = _giraffe_fov_create_cube(rebinning->spectra,
00877                                              _fibers, NULL);
00878 
00879             if (scube != NULL) {
00880                 simage = _giraffe_fov_integrate_cube(scube, limits);
00881             }
00882 
00883             if ((scube == NULL) || (simage == NULL)) {
00884 
00885                 cpl_image_delete(simage);
00886                 simage = NULL;
00887 
00888                 giraffe_cube_delete(scube);
00889                 scube = NULL;
00890 
00891                 failed = TRUE;
00892 
00893                 cpl_msg_error(fctid, "Cannot create data cube!");
00894                 return 1;
00895 
00896             }
00897             else {
00898 
00899                 cx_slist_push_back(scubes, scube);
00900                 cx_slist_push_back(simages, simage);
00901 
00902             }
00903 
00904 
00905             if (!failed) {
00906 
00907                 ecube = _giraffe_fov_create_cube(variance, _fibers, NULL);
00908                 eimage = _giraffe_fov_integrate_cube(ecube, limits);
00909 
00910                 if ((ecube == NULL) || (eimage == NULL)) {
00911 
00912                     cpl_image_delete(eimage);
00913                     eimage = NULL;
00914 
00915                     giraffe_cube_delete(ecube);
00916                     ecube = NULL;
00917 
00918                     failed = TRUE;
00919 
00920                     cpl_msg_error(fctid, "Cannot create error cube!");
00921                     return 1;
00922 
00923                 }
00924                 else {
00925 
00926                     giraffe_cube_sqrt(ecube);
00927                     cpl_image_power(eimage, 0.5);
00928 
00929                     cx_slist_push_back(ecubes, ecube);
00930                     cx_slist_push_back(eimages, eimage);
00931 
00932                 }
00933 
00934             }
00935 
00936             if (failed) {
00937 
00938                 giraffe_image_delete(variance);
00939                 variance = NULL;
00940 
00941                 cx_slist_destroy(simages, (cx_free_func)cpl_image_delete);
00942                 simages = NULL;
00943 
00944                 cx_slist_destroy(eimages, (cx_free_func)cpl_image_delete);
00945                 eimages = NULL;
00946 
00947                 cx_slist_destroy(scubes, (cx_free_func)giraffe_cube_delete);
00948                 scubes = NULL;
00949 
00950                 cx_slist_destroy(ecubes, (cx_free_func)giraffe_cube_delete);
00951                 ecubes = NULL;
00952 
00953                 giraffe_range_delete(limits);
00954                 limits = NULL;
00955 
00956                 return 1;
00957 
00958             }
00959 
00960             giraffe_image_delete(variance);
00961             variance = NULL;
00962             break;
00963         }
00964 
00965         default:
00966             return 1;
00967             break;
00968     }
00969 
00970 
00971     /*
00972      * Fill the results container.
00973      */
00974 
00975     result->mode = mode;
00976     result->ssn  = ssn;
00977     ssn = NULL;
00978 
00979     properties = giraffe_image_get_properties(rebinning->spectra);
00980     fov = cx_slist_pop_front(simages);
00981 
00982     result->fov.spectra = giraffe_image_new(CPL_TYPE_DOUBLE);
00983     giraffe_image_set(result->fov.spectra, fov);
00984     giraffe_image_set_properties(result->fov.spectra, properties);
00985 
00986     properties = giraffe_image_get_properties(result->fov.spectra);
00987 
00988     cpl_propertylist_update_double(properties, GIALIAS_FOV_BANDMIN,
00989                                    giraffe_range_get_min(limits));
00990     cpl_propertylist_set_comment(properties, GIALIAS_FOV_BANDMIN,
00991                                  "Minimum wavelength of FOV band");
00992 
00993     cpl_propertylist_update_double(properties, GIALIAS_FOV_BANDMAX,
00994                                    giraffe_range_get_max(limits));
00995     cpl_propertylist_set_comment(properties, GIALIAS_FOV_BANDMAX,
00996                                  "Maximum wavelength of FOV band");
00997 
00998     cpl_image_delete(fov);
00999     fov = NULL;
01000 
01001 
01002     properties = giraffe_image_get_properties(rebinning->errors);
01003     fov = cx_slist_pop_front(eimages);
01004 
01005     result->fov.errors = giraffe_image_new(CPL_TYPE_DOUBLE);
01006     giraffe_image_set(result->fov.errors, fov);
01007     giraffe_image_set_properties(result->fov.errors, properties);
01008 
01009     properties = giraffe_image_get_properties(result->fov.errors);
01010 
01011     cpl_propertylist_update_double(properties, GIALIAS_FOV_BANDMIN,
01012                                    giraffe_range_get_min(limits));
01013     cpl_propertylist_set_comment(properties, GIALIAS_FOV_BANDMIN,
01014                                  "Minimum wavelength of FOV band");
01015 
01016     cpl_propertylist_update_double(properties, GIALIAS_FOV_BANDMAX,
01017                                    giraffe_range_get_max(limits));
01018     cpl_propertylist_set_comment(properties, GIALIAS_FOV_BANDMAX,
01019                                  "Maximum wavelength of FOV band");
01020 
01021     cpl_image_delete(fov);
01022     fov = NULL;
01023 
01024     if (!cx_slist_empty(simages)) {
01025 
01026         cx_slist_iterator pos = cx_slist_begin(simages);
01027 
01028         result->images.spectra = cx_slist_new();
01029 
01030         while (pos != cx_slist_end(simages)) {
01031 
01032             GiImage* image = giraffe_image_new(CPL_TYPE_DOUBLE);
01033 
01034             giraffe_image_set(image, cx_slist_get(simages, pos));
01035             cx_slist_push_back(result->images.spectra, image);
01036 
01037             pos = cx_slist_next(simages, pos);
01038         }
01039 
01040     }
01041 
01042     if (!cx_slist_empty(eimages)) {
01043 
01044         cx_slist_iterator pos = cx_slist_begin(eimages);
01045 
01046         result->images.errors = cx_slist_new();
01047 
01048         while (pos != cx_slist_end(eimages)) {
01049 
01050             GiImage* image = giraffe_image_new(CPL_TYPE_DOUBLE);
01051 
01052             giraffe_image_set(image, cx_slist_get(eimages, pos));
01053             cx_slist_push_back(result->images.errors, image);
01054 
01055             pos = cx_slist_next(eimages, pos);
01056         }
01057 
01058     }
01059 
01060     if (config->cube == TRUE) {
01061 
01062         if (!cx_slist_empty(scubes)) {
01063             result->cubes.spectra = scubes;
01064             scubes = NULL;
01065         }
01066 
01067         if (!cx_slist_empty(ecubes)) {
01068             result->cubes.errors = ecubes;
01069             ecubes = NULL;
01070         }
01071 
01072     }
01073 
01074 
01075     /*
01076      * Cleanup
01077      */
01078 
01079     giraffe_range_delete(limits);
01080     limits = NULL;
01081 
01082     cx_slist_destroy(simages, (cx_free_func)cpl_image_delete);
01083     simages = NULL;
01084 
01085     cx_slist_destroy(eimages, (cx_free_func)cpl_image_delete);
01086     eimages = NULL;
01087 
01088     if (scubes != NULL) {
01089         cx_slist_destroy(scubes, (cx_free_func)giraffe_cube_delete);
01090         scubes = NULL;
01091     }
01092 
01093     if (ecubes != NULL) {
01094         cx_slist_destroy(ecubes, (cx_free_func)giraffe_cube_delete);
01095         ecubes = NULL;
01096     }
01097 
01098     return 0;
01099 
01100 }
01101 
01102 
01116 GiFieldOfView*
01117 giraffe_fov_new(void)
01118 {
01119     GiFieldOfView* self = cx_malloc(sizeof *self);
01120 
01121     self->mode = GIMODE_NONE;
01122     self->ssn  = NULL;
01123 
01124     self->fov.spectra = NULL;
01125     self->fov.errors  = NULL;
01126 
01127     self->images.spectra = NULL;
01128     self->images.errors  = NULL;
01129 
01130     self->cubes.spectra = NULL;
01131     self->cubes.errors  = NULL;
01132 
01133     return self;
01134 
01135 }
01136 
01137 
01150 void
01151 giraffe_fov_clear(GiFieldOfView* self)
01152 {
01153 
01154     if (self != NULL) {
01155 
01156         if (self->cubes.errors != NULL) {
01157             cx_slist_destroy(self->cubes.errors,
01158                              (cx_free_func)giraffe_cube_delete);
01159             self->cubes.errors = NULL;
01160         }
01161 
01162         if (self->cubes.spectra != NULL) {
01163             cx_slist_destroy(self->cubes.spectra,
01164                              (cx_free_func)giraffe_cube_delete);
01165             self->cubes.spectra = NULL;
01166         }
01167 
01168         if (self->images.errors != NULL) {
01169             cx_slist_destroy(self->images.errors,
01170                              (cx_free_func)giraffe_image_delete);
01171             self->images.errors = NULL;
01172         }
01173 
01174         if (self->images.spectra != NULL) {
01175             cx_slist_destroy(self->images.spectra,
01176                              (cx_free_func)giraffe_image_delete);
01177             self->images.spectra = NULL;
01178         }
01179 
01180         if (self->fov.errors != NULL) {
01181             giraffe_image_delete(self->fov.errors);
01182             self->fov.errors = NULL;
01183         }
01184 
01185         if (self->fov.spectra != NULL) {
01186             giraffe_image_delete(self->fov.spectra);
01187             self->fov.spectra = NULL;
01188         }
01189 
01190         if (self->ssn != NULL) {
01191             cpl_array_delete(self->ssn);
01192             self->ssn = NULL;
01193         }
01194 
01195         self->mode = GIMODE_NONE;
01196 
01197     }
01198 
01199     return;
01200 
01201 }
01202 
01203 
01217 void
01218 giraffe_fov_delete(GiFieldOfView* self)
01219 {
01220 
01221     if (self != NULL) {
01222         giraffe_fov_clear(self);
01223         cx_free(self);
01224     }
01225 
01226     return;
01227 
01228 }
01229 
01230 
01253 cxint
01254 giraffe_fov_save_cubes(const GiFieldOfView* self,
01255                        cpl_propertylist* properties,
01256                        const cxchar* filename, cxptr data)
01257 {
01258 
01259 
01260     cxint component = 0;
01261 
01262     cx_slist* cubes = NULL;
01263 
01264 
01265     if ((self == NULL) || (properties == NULL) || (filename == NULL)) {
01266         return -1;
01267     }
01268 
01269 
01270     /*
01271      * Get the cube component that should be saved. Spectra or errors.
01272      */
01273 
01274     if (data != NULL) {
01275         component = *((cxuint*)data);
01276     }
01277 
01278     if (component == 0) {
01279         cubes = self->cubes.spectra;
01280     }
01281     else {
01282         cubes = self->cubes.errors;
01283     }
01284 
01285     if (cubes == NULL) {
01286         return -2;
01287     }
01288 
01289 
01290     if (!cx_slist_empty(cubes)) {
01291 
01292         if (self->mode == GIMODE_ARGUS) {
01293 
01294             cxint status = 0;
01295             cxint iomode = CPL_IO_CREATE;
01296 
01297             GiCube* cube = cx_slist_front(cubes);
01298 
01299             status = giraffe_cube_save(cube, properties, filename, &iomode);
01300 
01301             if (status != 0) {
01302                 return 1;
01303             }
01304 
01305         }
01306         else {
01307 
01308             cxint nss = 0;
01309             cxint status = 0;
01310             cxint iomode = CPL_IO_CREATE;
01311 
01312             cx_slist_const_iterator pos = cx_slist_begin(cubes);
01313 
01314             cx_string* name = NULL;
01315 
01316             cpl_propertylist* xproperties = NULL;
01317 
01318 
01319             status = giraffe_cube_save(NULL, properties, filename, &iomode);
01320 
01321             if (status != 0) {
01322                 return 1;
01323             }
01324 
01325 
01326             name = cx_string_new();
01327             xproperties = cpl_propertylist_new();
01328 
01329             iomode = CPL_IO_EXTEND;
01330 
01331             while (pos != cx_slist_end(cubes)) {
01332 
01333                 cxint ssn = cpl_array_get_int(self->ssn, nss, NULL);
01334 
01335                 GiCube* cube = cx_slist_get(cubes, pos);
01336 
01337 
01338                 cx_string_sprintf(name, "SSN%-d", ssn);
01339                 cpl_propertylist_update_string(xproperties, "EXTNAME",
01340                                                cx_string_get(name));
01341 
01342                 status = giraffe_cube_save(cube, xproperties, filename,
01343                                            &iomode);
01344 
01345                 if (status != 0) {
01346 
01347                     cpl_propertylist_delete(xproperties);
01348                     xproperties = NULL;
01349 
01350                     cx_string_delete(name);
01351                     name = NULL;
01352 
01353                     return 1;
01354 
01355                 }
01356 
01357                 pos = cx_slist_next(cubes, pos);
01358                 ++nss;
01359 
01360             }
01361 
01362             cpl_propertylist_delete(xproperties);
01363             xproperties = NULL;
01364 
01365             cx_string_delete(name);
01366             name = NULL;
01367 
01368         }
01369 
01370     }
01371 
01372     return 0;
01373 
01374 }
01375 
01376 
01388 GiFieldOfViewConfig*
01389 giraffe_fov_config_create(cpl_parameterlist* list)
01390 {
01391 
01392     cpl_parameter* p;
01393 
01394     GiFieldOfViewConfig* config = NULL;
01395 
01396 
01397     if (list == NULL) {
01398         return NULL;
01399     }
01400 
01401     config = cx_calloc(1, sizeof *config);
01402 
01403 
01404     p = cpl_parameterlist_find(list, "giraffe.fov.range.minimum");
01405     config->minimum = cpl_parameter_get_double(p);
01406 
01407     p = cpl_parameterlist_find(list, "giraffe.fov.range.maximum");
01408     config->maximum = cpl_parameter_get_double(p);
01409 
01410     p = cpl_parameterlist_find(list, "giraffe.fov.cube");
01411     config->cube = cpl_parameter_get_bool(p);
01412 
01413     return config;
01414 
01415 }
01416 
01417 
01431 void
01432 giraffe_fov_config_destroy(GiFieldOfViewConfig* config)
01433 {
01434 
01435     if (config != NULL) {
01436         cx_free(config);
01437     }
01438 
01439     return;
01440 
01441 }
01442 
01443 
01453 void
01454 giraffe_fov_config_add(cpl_parameterlist* list)
01455 {
01456 
01457     cpl_parameter* p;
01458 
01459 
01460     if (list == NULL) {
01461         return;
01462     }
01463 
01464     p = cpl_parameter_new_value("giraffe.fov.range.minimum",
01465                                 CPL_TYPE_DOUBLE,
01466                                 "Minimum wavelength for image reconstruction",
01467                                 "giraffe.fov.range",
01468                                 0.);
01469     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "recon-min");
01470     cpl_parameterlist_append(list, p);
01471 
01472 
01473     p = cpl_parameter_new_value("giraffe.fov.range.maximum",
01474                                 CPL_TYPE_DOUBLE,
01475                                 "Maximum wavelength for image reconstruction",
01476                                 "giraffe.fov.range",
01477                                 0.);
01478     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "recon-max");
01479     cpl_parameterlist_append(list, p);
01480 
01481 
01482     p = cpl_parameter_new_value("giraffe.fov.cube",
01483                                 CPL_TYPE_BOOL,
01484                                 "Turns data cube creation on and off",
01485                                 "giraffe.fov.cube",
01486                                 TRUE);
01487     cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "recon-cube");
01488     cpl_parameterlist_append(list, p);
01489 
01490     return;
01491 
01492 }

This file is part of the GIRAFFE Pipeline Reference Manual 2.8.
Documentation copyright © 2002-2006 European Southern Observatory.
Generated on Tue Jun 2 07:15:33 2009 by doxygen 1.5.1 written by Dimitri van Heesch, © 1997-2004