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