00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
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
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
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
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
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
00218
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
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
00272
00273
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
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
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
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
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
00510
00511
00512
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
00527
00528
00529
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
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
00589
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
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
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
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
00692
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
00832
00833
00834
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
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
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
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
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
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 }