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