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

This file is part of the GIRAFFE Pipeline Reference Manual 2.8.8.
Documentation copyright © 2002-2006 European Southern Observatory.
Generated on Fri Mar 4 10:50:27 2011 by doxygen 1.6.3 written by Dimitri van Heesch, © 1997-2004