GIRAFFE Pipeline Reference Manual

girebinning.c
1/*
2 * This file is part of the GIRAFFE Pipeline
3 * Copyright (C) 2002-2019 European Southern Observatory
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#ifdef HAVE_CONFIG_H
21# include <config.h>
22#endif
23
24#include <math.h>
25
26#include <cxmacros.h>
27#include <cxtypes.h>
28#include <cxmemory.h>
29#include <cxmessages.h>
30
31#include <cpl_parameter.h>
32#include <cpl_parameterlist.h>
33#include <cpl_image.h>
34#include <cpl_msg.h>
35
36#include "gimacros.h"
37#include "gidebug.h"
38#include "gierror.h"
39#include "gialias.h"
40#include "gimatrix.h"
41#include "gimessages.h"
42#include "gimath.h"
43#include "gimath_lm.h"
44#include "gifiberutils.h"
45#include "giutils.h"
46#include "girebinning.h"
47
48
57#define GIFITS_KEYWORD_MISSING_MSG "FITS KEYWORD [%s] not found!! Aborting..."
58#define GIWAVECAL_GRATING_WAVELENGTH_EPSILON 0.0001
59
60
61enum GiLocDataType {
62 GILOCDATATYPE_UNDEFINED,
63 GILOCDATATYPE_FITTED_DATA,
64 GILOCDATATYPE_FIT_COEFFS
65};
66
67typedef enum GiLocDataType GiLocDataType;
68
69
70struct GiGrat {
71 cx_string *name;
72 cx_string *filter_name;
73 cx_string *setup_name;
74 cx_string *slit_name;
75 cxint order;
76 cxdouble wlen0;
77 cxdouble wlenmin;
78 cxdouble wlenmax;
79 cxdouble band;
80 cxdouble resol;
81 cxdouble space;
82 cxdouble theta;
83 cxdouble fcoll;
84 cxdouble gcam;
85 cxdouble slitdx;
86 cxdouble slitdy;
87 cxdouble slitphi;
88};
89
90typedef struct GiGrat GiGrat;
91
92
93struct GiFiberPosition {
94 cpl_matrix *x_fiber;
95 cpl_matrix *y_fiber;
96};
97
98typedef struct GiFiberPosition GiFiberPosition;
99
100
101struct GiLocPosition {
102 cxint ydeg;
103 cxint wdeg;
104 GiLocDataType type;
105 cpl_image *centroids;
106 cpl_image *widths;
107};
108
109typedef struct GiLocPosition GiLocPosition;
110
111
112struct GiBinnParams {
113 cxint xdeg;
114 cxint ydeg;
115};
116
117typedef struct GiBinnParams GiBinnParams;
118
119
120struct GiSlitGeo {
121 cxint nsubslits;
122 cpl_matrix **subslits;
123};
124
125typedef struct GiSlitGeo GiSlitGeo;
126
127struct GiWcalSolution {
128 cxbool subslitfit;
129 lmrq_model_id opt_mod;
130 cpl_matrix *opt_mod_params;
131 GiSlitGeo *wav_coeffs;
132 GiSlitGeo *wav_limits;
133};
134
135typedef struct GiWcalSolution GiWcalSolution;
136
137
138struct GiRebinInfo {
139 const cxchar* method;
140 const cxchar* scale;
141 const cxchar* range;
142 const cxchar* units;
143
144 cxdouble wmin;
145 cxdouble wcenter;
146 cxdouble wmax;
147 cxdouble wstep;
148
149 cxint offset;
150
151};
152
153typedef struct GiRebinInfo GiRebinInfo;
154
155
156/*
157 * Static vars for spline interpolation...
158 */
159
160static cxdouble ddb, dde;
161
162
163inline static cxint
164_giraffe_resample_update_properties(GiImage* spectra, GiRebinInfo* info)
165{
166
167 cpl_image* image = giraffe_image_get(spectra);
168
169 cpl_propertylist* properties = giraffe_image_get_properties(spectra);
170
171
172 giraffe_error_push();
173
174 cpl_propertylist_update_double(properties, GIALIAS_DATAMIN,
175 cpl_image_get_min(image));
176 cpl_propertylist_update_double(properties, GIALIAS_DATAMAX,
177 cpl_image_get_max(image));
178
179 cpl_propertylist_update_string(properties, GIALIAS_GIRFTYPE,
180 "BINSP");
181
182 cpl_propertylist_update_int(properties, GIALIAS_BINWNX,
183 cpl_image_get_size_y(image));
184 cpl_propertylist_update_int(properties, GIALIAS_BINWNS,
185 cpl_image_get_size_x(image));
186
187 cpl_propertylist_update_string(properties, GIALIAS_BUNIT,
188 "adu");
189
190 cpl_propertylist_update_string(properties, GIALIAS_CTYPE1,
191 "INDEX");
192 cpl_propertylist_update_string(properties, GIALIAS_CUNIT1,
193 "");
194 cpl_propertylist_update_double(properties, GIALIAS_CRPIX1,
195 1.);
196 cpl_propertylist_update_double(properties, GIALIAS_CRVAL1,
197 1.);
198 cpl_propertylist_update_double(properties, GIALIAS_CDELT1,
199 1.);
200
201 cpl_propertylist_update_string(properties, GIALIAS_CTYPE2,
202 "AWAV");
203 cpl_propertylist_update_string(properties, GIALIAS_CUNIT2,
204 info->units);
205 cpl_propertylist_update_double(properties, GIALIAS_CRPIX2,
206 info->offset + 1);
207 cpl_propertylist_update_double(properties, GIALIAS_CRVAL2,
208 info->wmin);
209 cpl_propertylist_update_double(properties, GIALIAS_CDELT2,
210 info->wstep);
211
212 cpl_propertylist_update_double(properties, GIALIAS_BINWLMIN,
213 info->wmin);
214 cpl_propertylist_update_double(properties, GIALIAS_BINWL0,
215 info->wcenter);
216 cpl_propertylist_update_double(properties, GIALIAS_BINWLMAX,
217 info->wmax);
218 cpl_propertylist_update_double(properties, GIALIAS_BINSTEP,
219 info->wstep);
220 cpl_propertylist_update_string(properties, GIALIAS_BINMETHOD,
221 info->method);
222 cpl_propertylist_update_string(properties, GIALIAS_BINSCALE,
223 info->scale);
224 cpl_propertylist_update_string(properties, GIALIAS_BINRANGE,
225 info->range);
226
227 if (cpl_error_get_code() != CPL_ERROR_NONE) {
228 return 1;
229 }
230
231 giraffe_error_pop();
232
233 return 0;
234
235}
236
237
238static GiGrat*
239_giraffe_grating_new(void)
240{
241
242 GiGrat *grating = NULL;
243
244 grating = (GiGrat*) cx_calloc(1, (cxsize)sizeof(GiGrat));
245
246 grating->name = cx_string_create("UNKNOWN");
247 grating->filter_name = cx_string_create("UNKNOWN");
248 grating->setup_name = cx_string_create("UNKNOWN");
249 grating->slit_name = cx_string_create("UNKNOWN");
250
251 return grating;
252
253}
254
255
256static void
257_giraffe_grating_delete(GiGrat *grating)
258{
259
260 if (grating==NULL) { return; }
261
262 if (grating->name!=NULL) {
263 cx_string_delete(grating->name);
264 }
265 if (grating->filter_name!=NULL) {
266 cx_string_delete(grating->filter_name);
267 }
268 if (grating->setup_name!=NULL) {
269 cx_string_delete(grating->setup_name);
270 }
271 if (grating->slit_name!=NULL) {
272 cx_string_delete(grating->slit_name);
273 }
274 cx_free(grating);
275
276}
277
278
279static cxint
280_giraffe_grating_setup(const GiTable *grating_table,
281 const GiImage *grating_ass_img, GiGrat *grating_setup)
282{
283
284 /*************************************************************************
285 Variables
286 *************************************************************************/
287
288 const cxchar *fctid = "_giraffe_grating_setup";
289
290 cxdouble wlen_match = 0.0,
291 wlen = 0.0,
292 tmp_gratgrv = 0.0;
293
294 cxint32 row_match = 0,
295 row_nulls,
296 i = 0;
297
298 const cxchar *c_name_setup = "SETUP";
299 const cxchar *c_name_order = "ORDER";
300 const cxchar *c_name_wl0 = "WLEN0";
301 const cxchar *c_name_wlmin = "WLMIN";
302 const cxchar *c_name_wlmax = "WLMAX";
303 const cxchar *c_name_band = "BAND";
304 const cxchar *c_name_theta = "THETA";
305 const cxchar *c_name_fcoll = "FCOLL";
306 const cxchar *c_name_gcam = "GCAM";
307 const cxchar *c_name_sdx = "SDX";
308 const cxchar *c_name_sdy = "SDY";
309 const cxchar *c_name_sdphi = "SPHI";
310 const cxchar *c_name_rmed = "RMED";
311 const cxchar *c_name_rifa = "RIFA";
312
313 cpl_propertylist *ref_plimg = NULL;
314 cpl_table *ref_gtable = NULL;
315 cx_string *slit_name = NULL;
316
317 GiInstrumentMode instrument_mode;
318
319
320 /*************************************************************************
321 Preprocessing
322 *************************************************************************/
323
324 if (grating_table ==NULL) { return 1; }
325 if (grating_ass_img==NULL) { return 1; }
326 if (grating_setup ==NULL) { return 1; }
327
328 if ((ref_plimg=giraffe_image_get_properties(grating_ass_img))==NULL) {
329 return 128;
330 }
331
332 if ((ref_gtable = giraffe_table_get(grating_table))==NULL) {
333 return 128;
334 }
335
336 slit_name = cx_string_new();
337
338 /*************************************************************************
339 Processing
340 *************************************************************************/
341
342 /*
343 * Retrieve Grating information from associated image...
344 */
345
346 if (!cpl_propertylist_has(ref_plimg, GIALIAS_GRATWLEN)) {
347 cpl_msg_error(fctid, GIFITS_KEYWORD_MISSING_MSG, GIALIAS_GRATWLEN);
348 cx_string_delete(slit_name);
349 return 2;
350 }
351 else {
352 grating_setup->wlen0 = cpl_propertylist_get_double(ref_plimg,
353 GIALIAS_GRATWLEN);
354 }
355
356 if (!cpl_propertylist_has(ref_plimg, GIALIAS_GRATORDER)) {
357 cpl_msg_error(fctid, GIFITS_KEYWORD_MISSING_MSG, GIALIAS_GRATORDER);
358 cx_string_delete(slit_name);
359 return 2;
360 }
361 else {
362 grating_setup->order = cpl_propertylist_get_int(ref_plimg, GIALIAS_GRATORDER);
363 }
364
365 if (!cpl_propertylist_has(ref_plimg, GIALIAS_SLITNAME)) {
366
367 cpl_msg_error(fctid, GIFITS_KEYWORD_MISSING_MSG, GIALIAS_SLITNAME);
368 cx_string_delete(slit_name);
369 return 2;
370 } else {
371 cx_string_set(slit_name,
372 cpl_propertylist_get_string(ref_plimg, GIALIAS_SLITNAME));
373 }
374
375 if (!cpl_propertylist_has(ref_plimg, GIALIAS_GRATGRV)) {
376
377 cpl_msg_error(fctid, GIFITS_KEYWORD_MISSING_MSG, GIALIAS_GRATGRV);
378 cx_string_delete(slit_name);
379 return 2;
380 } else {
381 tmp_gratgrv = cpl_propertylist_get_double(ref_plimg, GIALIAS_GRATGRV );
382 }
383
384 if (!cpl_propertylist_has(ref_plimg, GIALIAS_GRATNAME)) {
385 cpl_msg_error(fctid, GIFITS_KEYWORD_MISSING_MSG, GIALIAS_GRATNAME);
386 cx_string_delete(slit_name);
387 return 2;
388 } else {
389 cx_string_set(grating_setup->name,
390 cpl_propertylist_get_string(ref_plimg, GIALIAS_GRATNAME));
391 }
392
393 if (!cpl_propertylist_has(ref_plimg, GIALIAS_FILTNAME)) {
394 cpl_msg_error(fctid, GIFITS_KEYWORD_MISSING_MSG, GIALIAS_FILTNAME);
395 cx_string_delete(slit_name);
396 return 2;
397 }
398 else {
399 cx_string_set(grating_setup->filter_name,
400 cpl_propertylist_get_string(ref_plimg, GIALIAS_FILTNAME));
401 }
402
403
404 /*
405 * Find wavelength nearest to central wavelength...
406 */
407
408 for (i = 0; i < cpl_table_get_nrow(ref_gtable); i++) {
409
410 cxint _order = cpl_table_get_int(ref_gtable, c_name_order, i, NULL);
411
412 if (_order == grating_setup->order) {
413
414 wlen = cpl_table_get(ref_gtable, c_name_wl0, i, &row_nulls);
415
416 if (fabs(wlen - grating_setup->wlen0) <
417 fabs(wlen_match - grating_setup->wlen0)) {
418 wlen_match = wlen;
419 row_match = i;
420 }
421
422 }
423 }
424
425
426 /*
427 * Have we found a match?...
428 */
429
430 if (fabs(wlen_match - grating_setup->wlen0) >
431 GIWAVECAL_GRATING_WAVELENGTH_EPSILON) {
432
433 cpl_msg_error(fctid, "Grating setup (wavelength %.2f nm, order %d) "
434 "not found in grating table!", grating_setup->wlen0,
435 grating_setup->order);
436 cx_string_delete(slit_name);
437 return 3;
438 }
439 else {
440 cpl_msg_debug(fctid, "Found wlen0 in grating table at position %d",
441 row_match);
442 }
443
444
445 /*
446 * Retrieve values associated to matched wavelength from grating table...
447 */
448
449 cx_string_set(grating_setup->setup_name,
450 (cxchar*) cpl_table_get_string(ref_gtable, c_name_setup,
451 row_match));
452
453 cx_string_set(grating_setup->slit_name, cx_string_get(slit_name));
454
455 grating_setup->wlenmin = cpl_table_get(ref_gtable, c_name_wlmin,
456 row_match, &row_nulls);
457
458 grating_setup->wlenmax = cpl_table_get(ref_gtable, c_name_wlmax,
459 row_match, &row_nulls);
460
461 grating_setup->band = cpl_table_get(ref_gtable, c_name_band,
462 row_match, &row_nulls);
463
464 grating_setup->theta = cpl_table_get(ref_gtable, c_name_theta,
465 row_match, &row_nulls);
466
467 grating_setup->space = 1.0 / fabs(GI_MM_TO_NM * tmp_gratgrv);
468
469
470 instrument_mode = giraffe_get_mode(ref_plimg);
471
472 switch (instrument_mode) {
473 case GIMODE_MEDUSA:
474 grating_setup->resol = cpl_table_get(ref_gtable, c_name_rmed,
475 row_match, &row_nulls);
476 break;
477
478 case GIMODE_IFU:
479 grating_setup->resol = cpl_table_get(ref_gtable, c_name_rifa,
480 row_match, &row_nulls);
481 break;
482
483 case GIMODE_ARGUS:
484 grating_setup->resol = cpl_table_get(ref_gtable, c_name_rifa,
485 row_match, &row_nulls);
486 break;
487
488 default:
489 grating_setup->resol = -1.0;
490 break;
491 }
492
493 grating_setup->fcoll =
494 cpl_table_get(ref_gtable, c_name_fcoll, row_match, &row_nulls);
495
496 grating_setup->gcam =
497 cpl_table_get(ref_gtable, c_name_gcam, row_match, &row_nulls);
498
499 grating_setup->slitdx =
500 cpl_table_get(ref_gtable, c_name_sdx, row_match, &row_nulls);
501
502 grating_setup->slitdy =
503 cpl_table_get(ref_gtable, c_name_sdy, row_match, &row_nulls);
504
505 grating_setup->slitphi =
506 cpl_table_get(ref_gtable, c_name_sdphi, row_match, &row_nulls);
507
508 cx_string_delete(slit_name);
509
510 return 0;
511
512}
513
514
515static GiFiberPosition*
516_giraffe_fiberposition_new(void)
517{
518
519 GiFiberPosition* tmp = NULL;
520
521 tmp = (GiFiberPosition*) cx_calloc(1, sizeof(GiFiberPosition));
522
523 tmp->x_fiber = NULL;
524 tmp->y_fiber = NULL;
525
526 return tmp;
527}
528
529
530static void
531_giraffe_fiberposition_delete(GiFiberPosition *fp)
532{
533
534 if (fp != NULL) {
535
536 if (fp->x_fiber) {
537 cpl_matrix_delete(fp->x_fiber);
538 }
539
540 if (fp->y_fiber) {
541 cpl_matrix_delete(fp->y_fiber);
542 }
543
544 cx_free(fp);
545
546 }
547
548 return;
549
550}
551
552
553static GiSlitGeo*
554_giraffe_slitgeo_new(void)
555{
556
557 GiSlitGeo *sgeometry = NULL;
558
559 sgeometry = cx_malloc(sizeof(GiSlitGeo));
560
561 sgeometry->subslits = NULL;
562 sgeometry->nsubslits = 0;
563
564 return sgeometry;
565
566}
567
568
569static void
570_giraffe_slitgeo_delete(GiSlitGeo *sgeometry)
571{
572
573 if (sgeometry != NULL) {
574
575 if (sgeometry->subslits != NULL) {
576
577 cxint i;
578
579 for (i = 0; i < sgeometry->nsubslits; i++) {
580 cpl_matrix_delete(sgeometry->subslits[i]);
581 }
582
583 cx_free(sgeometry->subslits);
584 }
585
586 cx_free(sgeometry);
587
588 }
589
590 return;
591
592}
593
594
595static cxint
596_giraffe_slitgeo_size(GiSlitGeo *sgeometry)
597{
598
599 if (sgeometry == NULL) {
600 return -1;
601 }
602
603 if (sgeometry->subslits != NULL) {
604 return sgeometry->nsubslits;
605 }
606
607 return -1;
608
609}
610
611
612static void
613_giraffe_slitgeo_resize(GiSlitGeo *sgeometry, cxint size)
614{
615
616 if (sgeometry == NULL) {
617 return;
618 }
619
620 if (size == sgeometry->nsubslits) {
621 return;
622 }
623
624 if (sgeometry->subslits != NULL) {
625
626 cxint i;
627
628 for (i = 0; i < sgeometry->nsubslits; i++) {
629 cpl_matrix_delete(sgeometry->subslits[i]);
630 }
631 }
632
633 cx_free(sgeometry->subslits);
634
635 sgeometry->nsubslits = size;
636 sgeometry->subslits = cx_calloc(sgeometry->nsubslits, sizeof(cpl_matrix*));
637
638 return;
639
640}
641
642
643static void
644_giraffe_slitgeo_create(GiSlitGeo *sgeometry, cxint idx, cxint nrow,
645 cxint ncol)
646{
647
648 if (sgeometry == NULL) {
649 return;
650 }
651
652 if (sgeometry->subslits == NULL) {
653 return;
654 }
655
656 if ((idx < 0) || (idx > sgeometry->nsubslits)) {
657 return;
658 }
659
660 if (sgeometry->subslits[idx] != NULL) {
661 cpl_matrix_delete(sgeometry->subslits[idx]);
662 }
663
664 sgeometry->subslits[idx] = cpl_matrix_new(nrow, ncol);
665
666 return;
667
668}
669
670
671static void
672_giraffe_slitgeo_set(GiSlitGeo *sgeometry, cxint idx, cpl_matrix *nm)
673{
674
675 if (sgeometry == NULL) {
676 return;
677 }
678
679 if (sgeometry->subslits == NULL) {
680 return;
681 }
682
683 if ((idx < 0) || (idx > sgeometry->nsubslits)) {
684 return;
685 }
686
687 if (sgeometry->subslits[idx] != NULL) {
688 cpl_matrix_delete(sgeometry->subslits[idx]);
689 }
690
691 if (nm) {
692 sgeometry->subslits[idx] = cpl_matrix_duplicate(nm);
693 }
694 else {
695 sgeometry->subslits[idx] = NULL;
696 }
697
698}
699
700
701static cpl_matrix*
702_giraffe_slitgeo_get(GiSlitGeo *sgeometry, cxint idx)
703{
704
705 if (sgeometry == NULL) {
706 return NULL;
707 }
708
709 if (sgeometry->subslits == NULL) {
710 return NULL;
711 }
712
713 if ((idx < 0)||(idx > sgeometry->nsubslits)) {
714 return NULL;
715 }
716
717 return (sgeometry->subslits[idx]);
718
719}
720
721
722static cxint
723_giraffe_slitgeo_setup(const GiTable *slitgeo,
724 GiFiberPosition *fiber_slit_position,
725 GiSlitGeo *subslits, cxbool fitsubslit)
726{
727
728 const cxchar *const fctid = "_giraffe_slitgeo_setup";
729
730
731 const cxchar *c_name_xf = "XF";
732 const cxchar *c_name_yf = "YF";
733 const cxchar *c_name_nspec = "FPS";
734 const cxchar *c_name_ssn = "SSN";
735
736
737 cpl_matrix *nspec = NULL;
738 cpl_matrix *nsubslits = NULL;
739
740 cxint nr_slitgeo = 0,
741 max_nsubslits = 0,
742 i = 0,
743 j = 0,
744 row_null = 0,
745 count = 0,
746 column_index = 0,
747 tmp_nspec = 0,
748 tmp_nsubslits = 0;
749
750 cxdouble tmp_xf,
751 tmp_yf;
752
753 cpl_table *ref_slitgeo = NULL;
754
755 /*cpl_error_code ce_code;*/
756
757
758 /*************************************************************************
759 Preprocessing
760 *************************************************************************/
761
762 if (slitgeo ==NULL) { return 1; }
763 if (fiber_slit_position==NULL) { return 1; }
764 if (subslits ==NULL) { return 1; }
765
766 /*************************************************************************
767 Processing
768 *************************************************************************/
769
770 ref_slitgeo = giraffe_table_get(slitgeo);
771 nr_slitgeo = cpl_table_get_nrow(ref_slitgeo);
772
773 fiber_slit_position->x_fiber = cpl_matrix_new(nr_slitgeo, 1);
774 fiber_slit_position->y_fiber = cpl_matrix_new(nr_slitgeo, 1);
775
776 nspec = cpl_matrix_new(nr_slitgeo, 1);
777 nsubslits = cpl_matrix_new(nr_slitgeo, 1);
778
779 /*
780 * Copy relevant data to matrices
781 */
782
783 max_nsubslits = 0;
784
785 for (i = 0; i < nr_slitgeo; i++) {
786
787 tmp_xf = cpl_table_get(ref_slitgeo, c_name_xf, i, &row_null);
788 tmp_yf = cpl_table_get(ref_slitgeo, c_name_yf, i, &row_null);
789
790 tmp_nspec = cpl_table_get_int(ref_slitgeo, c_name_nspec, i,
791 &row_null) - 1;
792
793 tmp_nsubslits = cpl_table_get_int(ref_slitgeo, c_name_ssn, i,
794 &row_null);
795
796 if (tmp_nsubslits>max_nsubslits) {
797 max_nsubslits = tmp_nsubslits;
798 }
799
800 /*ce_code =*/ cpl_matrix_set(fiber_slit_position->x_fiber, i, 0, tmp_xf);
801 /*ce_code =*/ cpl_matrix_set(fiber_slit_position->y_fiber, i, 0, tmp_yf);
802
803 /*ce_code =*/ cpl_matrix_set(nspec, i, 0, (cxdouble)tmp_nspec);
804 /*ce_code =*/ cpl_matrix_set(nsubslits, i, 0, (cxdouble)tmp_nsubslits);
805
806 }
807
808 /*
809 * Create Slit Geometry
810 */
811
812 if (fitsubslit) {
813
814 /* create multiple subslits */
815
816 _giraffe_slitgeo_resize(subslits, max_nsubslits);
817
818 for (i = 1; i <= max_nsubslits; i++) {
819
820 cpl_matrix *ref_matrix = NULL;
821 cxint curr_ssn;
822
823 count = 0;
824 for (j=0; j<nr_slitgeo; j++) {
825 curr_ssn = (cxint) cpl_matrix_get(nsubslits, j, 0);
826 if (i==curr_ssn) {
827 ++count;
828 }
829 }
830
831 _giraffe_slitgeo_create(subslits, i-1, count, 1);
832
833 ref_matrix = _giraffe_slitgeo_get(subslits, i-1);
834
835 column_index = 0;
836 for (j = 0; j < nr_slitgeo; j++) {
837
838 curr_ssn = (cxint) cpl_matrix_get(nsubslits, j, 0);
839
840 if (i == curr_ssn) {
841 /*ce_code =*/ cpl_matrix_set(ref_matrix, column_index, 0,
842 (cxdouble)j);
843 column_index++;
844 }
845
846 }
847 }
848
849 cpl_msg_debug(fctid, "Using multiple slits for Slit Geometry");
850
851 }
852 else {
853
854 const cxchar *idx = giraffe_fiberlist_query_index(ref_slitgeo);
855
856
857 /*
858 * Create one subslit containing all fibers
859 */
860
861 cpl_matrix *ref_matrix = NULL;
862
863 _giraffe_slitgeo_resize(subslits, 1);
864 _giraffe_slitgeo_create(subslits, 0, nr_slitgeo, 1);
865
866 ref_matrix = _giraffe_slitgeo_get(subslits, 0);
867
868 for (j = 0; j < nr_slitgeo; j++) {
869
870 cxint cs = cpl_table_get_int(ref_slitgeo, idx, j, NULL) - 1;
871 /*ce_code =*/ cpl_matrix_set(ref_matrix, j, 0, cs);
872// ce_code = cpl_matrix_set(ref_matrix, j, 0, (cxdouble)j);
873
874 }
875
876 cpl_msg_debug(fctid, "Using single slit for Slit Geometry");
877
878 }
879
880 cpl_matrix_delete(nspec);
881 nspec = NULL;
882
883 cpl_matrix_delete(nsubslits);
884 nsubslits = NULL;
885
886 return 0;
887
888}
889
890
891static GiWcalSolution*
892_giraffe_wcalsolution_new(void)
893{
894
895 GiWcalSolution* tmp = NULL;
896
897 tmp = (GiWcalSolution*) cx_calloc(1, sizeof(GiWcalSolution));
898
899 tmp->subslitfit = FALSE;
900 tmp->opt_mod = LMRQ_UNDEFINED;
901 tmp->opt_mod_params = NULL;
902 tmp->wav_coeffs = NULL;
903 tmp->wav_limits = NULL;
904
905 return tmp;
906}
907
908
909static void
910_giraffe_wcalsolution_delete(GiWcalSolution *ws)
911{
912
913 if (ws != NULL) {
914
915 if (ws->opt_mod_params!=NULL) {
916 cpl_matrix_delete(ws->opt_mod_params);
917 }
918
919 if (ws->wav_coeffs!=NULL) {
920 _giraffe_slitgeo_delete(ws->wav_coeffs);
921 }
922
923 if (ws->wav_limits!=NULL) {
924 _giraffe_slitgeo_delete(ws->wav_limits);
925 }
926
927 cx_free(ws);
928
929 }
930
931 return;
932
933}
934
935
936static GiWcalSolution*
937_giraffe_wcalsolution_create(const GiTable *wavesolution)
938{
939
940 cxchar buffer[68];
941
942 cxint i = 0;
943 cxint poly_x_deg = 0;
944 cxint poly_y_deg = 0;
945 cxint ncoefficients = 0;
946
947 cxdouble* pd_coefficients = NULL;
948
949 cpl_matrix* coefficients = NULL;
950 cpl_matrix* limits = NULL;
951
952 cpl_propertylist* _properties = NULL;
953
954 cpl_table* _table = NULL;
955
956 GiWcalSolution* wavcoeff = NULL;
957
958
959
960 if (wavesolution == NULL) {
961 return NULL;
962 }
963
964 wavcoeff = _giraffe_wcalsolution_new();
965
966 _properties = giraffe_table_get_properties(wavesolution);
967
968
969 /*
970 * Build up optical model from the wavelength solution properties
971 */
972
973 if (cpl_propertylist_has(_properties, GIALIAS_OPT_MOD) == TRUE) {
974
975 const cxchar* optmod = cpl_propertylist_get_string(_properties,
976 GIALIAS_OPT_MOD);
977
978 if (strncmp(optmod, "xoptmod2", 8) == 0) {
979 wavcoeff->opt_mod = LMRQ_XOPTMOD2;
980 }
981 else if (strncmp(optmod, "xoptmod", 7) == 0) {
982 wavcoeff->opt_mod = LMRQ_XOPTMOD;
983 }
984 else {
985 wavcoeff->opt_mod = LMRQ_UNDEFINED;
986 }
987 }
988
989 if (wavcoeff->opt_mod == LMRQ_XOPTMOD2) {
990
991 wavcoeff->opt_mod_params = cpl_matrix_new(7,1);
992
993 if (cpl_propertylist_has(_properties, GIALIAS_OPTMDIR)) {
994 cpl_matrix_set(
995 wavcoeff->opt_mod_params,
996 0,
997 0,
998 cpl_propertylist_get_int(_properties, GIALIAS_OPTMDIR)
999 );
1000 } else {
1001 _giraffe_wcalsolution_delete(wavcoeff);
1002 return NULL;
1003 }
1004
1005 if (cpl_propertylist_has(_properties, GIALIAS_WSOL_OPTMFCOLL)) {
1006 cpl_matrix_set(
1007 wavcoeff->opt_mod_params,
1008 1,
1009 0,
1010 cpl_propertylist_get_double(_properties, GIALIAS_WSOL_OPTMFCOLL)
1011 );
1012 } else {
1013 _giraffe_wcalsolution_delete(wavcoeff);
1014 return NULL;
1015 }
1016
1017 if (cpl_propertylist_has(_properties, GIALIAS_WSOL_OPTMGCAM)) {
1018 cpl_matrix_set(
1019 wavcoeff->opt_mod_params,
1020 2,
1021 0,
1022 cpl_propertylist_get_double(_properties, GIALIAS_WSOL_OPTMGCAM)
1023 );
1024 } else {
1025 _giraffe_wcalsolution_delete(wavcoeff);
1026 return NULL;
1027 }
1028
1029 if (cpl_propertylist_has(_properties, GIALIAS_WSOL_OPTMTHETA)) {
1030 cpl_matrix_set(
1031 wavcoeff->opt_mod_params,
1032 3,
1033 0,
1034 cpl_propertylist_get_double(_properties, GIALIAS_WSOL_OPTMTHETA)
1035 );
1036 } else {
1037 _giraffe_wcalsolution_delete(wavcoeff);
1038 return NULL;
1039 }
1040
1041 if (cpl_propertylist_has(_properties, GIALIAS_WSOL_OPTMSDX)) {
1042 cpl_matrix_set(
1043 wavcoeff->opt_mod_params,
1044 4,
1045 0,
1046 cpl_propertylist_get_double(_properties, GIALIAS_WSOL_OPTMSDX)
1047 );
1048 } else {
1049 _giraffe_wcalsolution_delete(wavcoeff);
1050 return NULL;
1051 }
1052
1053 if (cpl_propertylist_has(_properties, GIALIAS_WSOL_OPTMSDY)) {
1054
1055
1056
1057 cpl_matrix_set(
1058 wavcoeff->opt_mod_params,
1059 5,
1060 0,
1061 cpl_propertylist_get_double(_properties, GIALIAS_WSOL_OPTMSDY)
1062 );
1063
1064 } else {
1065 _giraffe_wcalsolution_delete(wavcoeff);
1066 return NULL;
1067 }
1068
1069 if (cpl_propertylist_has(_properties, GIALIAS_WSOL_OPTMSPHI)) {
1070 cpl_matrix_set(
1071 wavcoeff->opt_mod_params,
1072 6,
1073 0,
1074 cpl_propertylist_get_double(_properties, GIALIAS_WSOL_OPTMSPHI)
1075 );
1076
1077 } else {
1078 _giraffe_wcalsolution_delete(wavcoeff);
1079 return NULL;
1080 }
1081
1082 } else if (wavcoeff->opt_mod==LMRQ_XOPTMOD) {
1083
1084 wavcoeff->opt_mod_params = cpl_matrix_new(4,1);
1085
1086 if (cpl_propertylist_has(_properties, GIALIAS_OPTMDIR)) {
1087 cpl_matrix_set(
1088 wavcoeff->opt_mod_params,
1089 0,
1090 0,
1091 cpl_propertylist_get_int(_properties, GIALIAS_OPTMDIR)
1092 );
1093 } else {
1094 _giraffe_wcalsolution_delete(wavcoeff);
1095 return NULL;
1096 }
1097
1098 if (cpl_propertylist_has(_properties, GIALIAS_WSOL_OPTMFCOLL)) {
1099 cpl_matrix_set(
1100 wavcoeff->opt_mod_params,
1101 1,
1102 0,
1103 cpl_propertylist_get_double(_properties, GIALIAS_WSOL_OPTMFCOLL)
1104 );
1105 } else {
1106 _giraffe_wcalsolution_delete(wavcoeff);
1107 return NULL;
1108 }
1109
1110 if (cpl_propertylist_has(_properties, GIALIAS_WSOL_OPTMGCAM)) {
1111 cpl_matrix_set(
1112 wavcoeff->opt_mod_params,
1113 2,
1114 0,
1115 cpl_propertylist_get_double(_properties, GIALIAS_WSOL_OPTMGCAM)
1116 );
1117 } else {
1118 _giraffe_wcalsolution_delete(wavcoeff);
1119 return NULL;
1120 }
1121
1122 if (cpl_propertylist_has(_properties, GIALIAS_WSOL_OPTMTHETA)) {
1123 cpl_matrix_set(
1124 wavcoeff->opt_mod_params,
1125 3,
1126 0,
1127 cpl_propertylist_get_double(_properties, GIALIAS_WSOL_OPTMTHETA)
1128 );
1129 } else {
1130 _giraffe_wcalsolution_delete(wavcoeff);
1131 return NULL;
1132 }
1133
1134
1135 } else {
1136
1137 _giraffe_wcalsolution_delete(wavcoeff);
1138 return NULL;
1139
1140 }
1141
1142
1143 /*
1144 * Set up the optical model residuals if the given table contains them.
1145 */
1146
1147 _table = giraffe_table_get(wavesolution);
1148
1149 if (_table != NULL) {
1150
1151
1152 if (cpl_propertylist_has(_properties, GIALIAS_SSF)) {
1153
1154 if (cpl_propertylist_get_bool(_properties, GIALIAS_SSF) == 0) {
1155 wavcoeff->subslitfit = FALSE;
1156 }
1157 else {
1158 wavcoeff->subslitfit = TRUE;
1159 }
1160
1161 }
1162 else {
1163
1164 _giraffe_wcalsolution_delete(wavcoeff);
1165 return NULL;
1166
1167 }
1168
1169 wavcoeff->wav_limits = _giraffe_slitgeo_new();
1170 _giraffe_slitgeo_resize(wavcoeff->wav_limits, 1);
1171
1172 limits = cpl_matrix_new(1, 4);
1173 cpl_matrix_fill(limits, -1.);
1174
1175 if (cpl_table_has_column(_table, "XMIN") &&
1176 cpl_table_has_column(_table, "XMAX")) {
1177 cpl_matrix_set(limits, 0, 0,
1178 cpl_table_get_double(_table, "XMIN", 0, NULL));
1179 cpl_matrix_set(limits, 0, 1,
1180 cpl_table_get_double(_table, "XMAX", 0, NULL));
1181 }
1182
1183 if (cpl_table_has_column(_table, "YMIN") &&
1184 cpl_table_has_column(_table, "YMAX")) {
1185 cpl_matrix_set(limits, 0, 2,
1186 cpl_table_get_double(_table, "YMIN", 0, NULL));
1187 cpl_matrix_set(limits, 0, 3,
1188 cpl_table_get_double(_table, "YMAX", 0, NULL));
1189 }
1190
1191 _giraffe_slitgeo_set(wavcoeff->wav_limits, 0, limits);
1192
1193 cpl_matrix_delete(limits);
1194 limits = NULL;
1195
1196 wavcoeff->wav_coeffs = _giraffe_slitgeo_new();
1197 _giraffe_slitgeo_resize(wavcoeff->wav_coeffs, 1);
1198
1199 if (cpl_propertylist_has(_properties, GIALIAS_XRES_PDEG)) {
1200
1201 cxchar *l, *r, *tmpstr;
1202
1203 tmpstr = (cxchar*) cpl_propertylist_get_string(_properties,
1204 GIALIAS_XRES_PDEG);
1205
1206 l = &(tmpstr[0]);
1207 r = &(tmpstr[2]);
1208
1209 poly_x_deg = atoi(l) + 1;
1210 poly_y_deg = atoi(r) + 1;
1211
1212 }
1213 else {
1214
1215 _giraffe_wcalsolution_delete(wavcoeff);
1216 return NULL;
1217
1218 }
1219
1220 ncoefficients = poly_x_deg * poly_y_deg;
1221
1222 coefficients = cpl_matrix_new(poly_x_deg,poly_y_deg);
1223 pd_coefficients = cpl_matrix_get_data(coefficients);
1224
1225 for (i=0; i<ncoefficients; i++) {
1226
1227 snprintf(buffer, sizeof buffer, "XC%-d", i);
1228
1229 pd_coefficients[i] =
1230 cpl_table_get_double(_table, buffer, 0, NULL);
1231
1232 }
1233
1234 _giraffe_slitgeo_set(wavcoeff->wav_coeffs, 0, coefficients);
1235
1236 cpl_matrix_delete(coefficients);
1237 coefficients = NULL;
1238
1239 }
1240
1241 return wavcoeff;
1242
1243}
1244
1245
1246static cpl_image*
1247_giraffe_compute_pixel_abscissa(cpl_matrix* m_wavelengths,
1248 cpl_matrix* m_wloffset,
1249 GiFiberPosition* fiber_slit_position,
1250 cpl_matrix* m_opt_mod_params,
1251 lmrq_model lmrq_opt_mod_x)
1252{
1253
1254 /*************************************************************************
1255 VARIABLES
1256 *************************************************************************/
1257
1258 const cxchar *fctid = "_giraffe_compute_pixel_abscissa";
1259
1260 register cxint n;
1261 register cxint line;
1262 register cxint nwlen; /* number of reference lines */
1263 register cxint ns; /* number of reference spectra */
1264
1265 cxint nr_m_opt_mod_params = 0;
1266
1267 cxdouble xccd = 0.;
1268 cxdouble* pd_xref = NULL;
1269 cxdouble* pd_m_inputs = NULL;
1270 cxdouble* pd_m_yfibre = NULL;
1271 cxdouble* pd_m_xfibre = NULL;
1272 cxdouble* pd_m_wavelengths = NULL;
1273 cxdouble* pd_m_opt_mod_params = NULL;
1274
1275 cpl_image* xref = NULL;
1276
1277 cpl_matrix* m_inputs = NULL;
1278
1279
1280 /************************************************************************
1281 INITIALIZATION
1282 ************************************************************************/
1283
1284 if (m_wavelengths == NULL) {
1285 return NULL;
1286 }
1287
1288 if ((fiber_slit_position == NULL) ||
1289 (fiber_slit_position->x_fiber == NULL) ||
1290 (fiber_slit_position->y_fiber == NULL)) {
1291 return NULL;
1292 }
1293
1294 if (m_opt_mod_params == NULL) {
1295 return NULL;
1296 }
1297
1298
1299 nwlen = cpl_matrix_get_nrow(m_wavelengths);
1300 ns = cpl_matrix_get_nrow(fiber_slit_position->y_fiber);
1301
1302 if ((m_wloffset != NULL) && (cpl_matrix_get_nrow(m_wloffset) != ns)) {
1303 return NULL;
1304 }
1305
1306
1307 /************************************************************************
1308 PREPROCESSING
1309 ************************************************************************/
1310
1311 xref = cpl_image_new(ns, nwlen, CPL_TYPE_DOUBLE);
1312 pd_xref = cpl_image_get_data_double(xref);
1313
1314 m_inputs = cpl_matrix_new(lmrq_opt_mod_x.ninputs, 1);
1315 pd_m_inputs = cpl_matrix_get_data(m_inputs);
1316
1317 pd_m_yfibre = cpl_matrix_get_data(fiber_slit_position->y_fiber);
1318 pd_m_xfibre = cpl_matrix_get_data(fiber_slit_position->x_fiber);
1319 pd_m_wavelengths = cpl_matrix_get_data(m_wavelengths);
1320
1321 pd_m_opt_mod_params = cpl_matrix_get_data(m_opt_mod_params);
1322 nr_m_opt_mod_params = cpl_matrix_get_nrow(m_opt_mod_params);
1323
1324
1325 /************************************************************************
1326 PROCESSING
1327 ************************************************************************/
1328
1329 if (m_wloffset != NULL) {
1330
1331 cxdouble* pd_m_wloffset = cpl_matrix_get_data(m_wloffset);
1332
1333 for (n = 0; n < ns; n++) {
1334
1335 pd_m_inputs[2] = pd_m_yfibre[n];
1336 pd_m_inputs[1] = pd_m_xfibre[n];
1337
1338 for (line = 0; line < nwlen; line++) {
1339
1340 pd_m_inputs[0] = pd_m_wavelengths[line] + pd_m_wloffset[n];
1341
1342 lmrq_opt_mod_x.cfunc(pd_m_inputs, pd_m_opt_mod_params,
1343 NULL, &xccd, NULL, nr_m_opt_mod_params);
1344
1345 pd_xref[line * ns + n] = xccd;
1346
1347 } /* each line */
1348
1349 } /* each spectrum */
1350
1351 }
1352 else {
1353
1354 for (n = 0; n < ns; n++) {
1355
1356 pd_m_inputs[2] = pd_m_yfibre[n];
1357 pd_m_inputs[1] = pd_m_xfibre[n];
1358
1359 for (line = 0; line < nwlen; line++) {
1360
1361 pd_m_inputs[0] = pd_m_wavelengths[line];
1362
1363 lmrq_opt_mod_x.cfunc(pd_m_inputs, pd_m_opt_mod_params,
1364 NULL, &xccd, NULL, nr_m_opt_mod_params);
1365
1366 pd_xref[line * ns + n] = xccd;
1367
1368 } /* each line */
1369
1370 } /* each spectrum */
1371
1372 }
1373
1374 cpl_matrix_delete(m_inputs);
1375
1376 cpl_msg_debug(fctid, "Processing completed: Returning image [x,y] ="
1377 " [%" CPL_SIZE_FORMAT ",%" CPL_SIZE_FORMAT "]",
1378 cpl_image_get_size_x(xref), cpl_image_get_size_y(xref));
1379
1380 return xref;
1381
1382}
1383
1384
1385inline static cpl_matrix *
1386_giraffe_rebin_setup_model(GiImage *extspectra, GiWcalSolution *wcal)
1387{
1388
1389 cxint npixel;
1390
1391 cxdouble pixelsize;
1392
1393 cpl_propertylist *properties = NULL;
1394
1395 cpl_matrix *model = NULL;
1396
1397
1398 if (extspectra == NULL) {
1399 return NULL;
1400 }
1401
1402 if (wcal == NULL) {
1403 return NULL;
1404 }
1405
1406 properties = giraffe_image_get_properties(extspectra);
1407
1408 if (properties == NULL) {
1409 return NULL;
1410 }
1411
1412
1413 /*
1414 * Get the number of pixels extracted along the dispersion axis.
1415 */
1416
1417 if (!cpl_propertylist_has(properties, GIALIAS_EXT_NX)) {
1418 return NULL;
1419 }
1420
1421 npixel = cpl_propertylist_get_int(properties, GIALIAS_EXT_NX);
1422
1423
1424 /*
1425 * Compute pixel size along the dispersion axis in terms of mm.
1426 */
1427
1428 if (!cpl_propertylist_has(properties, GIALIAS_PIXSIZX)) {
1429 return NULL;
1430 }
1431
1432 pixelsize = cpl_propertylist_get_double(properties, GIALIAS_PIXSIZX);
1433 pixelsize /= 1000.;
1434
1435
1436 /*
1437 * Setup the optical model parameters
1438 */
1439
1440 switch (wcal->opt_mod) {
1441 case LMRQ_XOPTMOD:
1442 if (cpl_matrix_get_nrow(wcal->opt_mod_params) != 4) {
1443 return NULL;
1444 }
1445 else {
1446
1447 cxdouble direction = cpl_matrix_get(wcal->opt_mod_params, 0, 0);
1448 cxdouble fcoll = cpl_matrix_get(wcal->opt_mod_params, 1, 0);
1449 cxdouble cfact = cpl_matrix_get(wcal->opt_mod_params, 2, 0);
1450
1451 model = cpl_matrix_new(4, 1);
1452
1453 cpl_matrix_set(model, 0, 0, npixel * direction);
1454 cpl_matrix_set(model, 1, 0, pixelsize);
1455 cpl_matrix_set(model, 2, 0, fcoll);
1456 cpl_matrix_set(model, 3, 0, cfact);
1457 }
1458 break;
1459
1460 case LMRQ_XOPTMOD2:
1461 if (cpl_matrix_get_nrow(wcal->opt_mod_params) != 7) {
1462 return NULL;
1463 }
1464 else {
1465
1466 cxdouble direction = cpl_matrix_get(wcal->opt_mod_params, 0, 0);
1467 cxdouble fcoll = cpl_matrix_get(wcal->opt_mod_params, 1, 0);
1468 cxdouble cfact = cpl_matrix_get(wcal->opt_mod_params, 2, 0);
1469 cxdouble sdx = cpl_matrix_get(wcal->opt_mod_params, 4, 0);
1470 cxdouble sdy = cpl_matrix_get(wcal->opt_mod_params, 5, 0);
1471 cxdouble sphi = cpl_matrix_get(wcal->opt_mod_params, 6, 0);
1472
1473 model = cpl_matrix_new(7, 1);
1474
1475 cpl_matrix_set(model, 0, 0, npixel * direction);
1476 cpl_matrix_set(model, 1, 0, pixelsize);
1477 cpl_matrix_set(model, 2, 0, fcoll);
1478 cpl_matrix_set(model, 3, 0, cfact);
1479 cpl_matrix_set(model, 4, 0, sdx);
1480 cpl_matrix_set(model, 5, 0, sdy);
1481 cpl_matrix_set(model, 6, 0, sphi);
1482 }
1483 break;
1484
1485 default:
1486 return NULL;
1487 break;
1488 }
1489
1490 cx_assert(model != NULL);
1491
1492 return model;
1493
1494}
1495
1496
1497inline static cpl_matrix *
1498_giraffe_rebin_setup_grating(GiImage *extspectra, GiTable *grating,
1499 GiTable *wlsolution)
1500{
1501
1502 cxint status = 0;
1503
1504 cpl_propertylist *properties = NULL;
1505
1506 cpl_matrix *setup = NULL;
1507
1508 GiGrat *grating_data = _giraffe_grating_new();
1509
1510
1511 status = _giraffe_grating_setup(grating, extspectra, grating_data);
1512
1513 if (status != 0) {
1514 _giraffe_grating_delete(grating_data);
1515 return NULL;
1516 }
1517
1518
1519 properties = giraffe_table_get_properties(wlsolution);
1520
1521 if (cpl_propertylist_has(properties, GIALIAS_WSOL_OMFCOLL)) {
1522 grating_data->fcoll = cpl_propertylist_get_double(properties,
1523 GIALIAS_WSOL_OMFCOLL);
1524 }
1525
1526 if (cpl_propertylist_has(properties, GIALIAS_WSOL_OMGCAM)) {
1527 grating_data->gcam = cpl_propertylist_get_double(properties,
1528 GIALIAS_WSOL_OMGCAM);
1529 }
1530
1531 if (cpl_propertylist_has(properties, GIALIAS_WSOL_OMGTHETA)) {
1532 grating_data->theta = cpl_propertylist_get_double(properties,
1533 GIALIAS_WSOL_OMGTHETA);
1534 }
1535
1536 if (cpl_propertylist_has(properties, GIALIAS_WSOL_OMSDX)) {
1537 grating_data->slitdx = cpl_propertylist_get_double(properties,
1538 GIALIAS_WSOL_OMSDX);
1539 }
1540
1541 if (cpl_propertylist_has(properties, GIALIAS_WSOL_OMSDY)) {
1542 grating_data->slitdy = cpl_propertylist_get_double(properties,
1543 GIALIAS_WSOL_OMSDY);
1544 }
1545
1546 if (cpl_propertylist_has(properties, GIALIAS_WSOL_OMSPHI)) {
1547 grating_data->slitphi = cpl_propertylist_get_double(properties,
1548 GIALIAS_WSOL_OMSPHI);
1549 }
1550
1551
1552 setup = cpl_matrix_new(7, 1);
1553
1554 cpl_matrix_set(setup, 0, 0, grating_data->theta);
1555 cpl_matrix_set(setup, 1, 0, grating_data->order);
1556 cpl_matrix_set(setup, 2, 0, grating_data->wlenmin / GI_MM_TO_NM);
1557 cpl_matrix_set(setup, 3, 0, grating_data->wlen0 / GI_MM_TO_NM);
1558 cpl_matrix_set(setup, 4, 0, grating_data->wlenmax / GI_MM_TO_NM);
1559 cpl_matrix_set(setup, 5, 0, grating_data->resol);
1560 cpl_matrix_set(setup, 6, 0, grating_data->space);
1561
1562 _giraffe_grating_delete(grating_data);
1563 grating_data = NULL;
1564
1565 return setup;
1566
1567}
1568
1569
1582inline static cxint
1583_giraffe_spline_calc_circe(cxdouble x, register cxdouble* t, cxint n)
1584{
1585
1586 register cxint lo = 0;
1587 register cxint hi = n - 1;
1588
1589
1590 if (x >= t[0] && x <= t[n - 1]) {
1591
1592 while (hi - lo > 1) {
1593
1594 register cxint mid = (lo + hi) / 2.;
1595
1596 cxdouble tm = 0.;
1597
1598 tm = t[mid];
1599
1600 if (x < tm) {
1601 hi = mid;
1602 }
1603 else {
1604 lo = mid;
1605 }
1606 }
1607
1608 return hi;
1609
1610 }
1611
1612 return -1;
1613
1614}
1615
1635inline static void
1636_giraffe_spline_calc_tridi(register cxdouble* a, register cxdouble* b,
1637 register cxdouble* c, register cxdouble* f,
1638 register cxdouble* x, cxint n)
1639{
1640
1641 register cxint i = 0;
1642
1643 c[0] /= a[0];
1644
1645 for (i = 1; i < n; i++) {
1646 c[i] /= (a[i] - b[i] * c[i - 1]);
1647 }
1648
1649 f[0] /= a[0];
1650
1651 for (i = 1; i < n; i++) {
1652 f[i] = (f[i] - b[i] * f[i - 1]) / (a[i] - b[i] * c[i - 1]);
1653 }
1654
1655 x[n - 1] = f[n - 1];
1656
1657 for (i = n - 2; i >= 0; i--) {
1658 x[i] = f[i] - c[i] * x[i + 1];
1659 }
1660
1661 return;
1662}
1663
1683inline static cxint
1684_giraffe_spline_calc_interpolate(cxdouble z, cxdouble* val,
1685 register cxdouble* x, register cxdouble* y,
1686 register cxdouble* k, cxint n)
1687{
1688
1689 cxint m = 0;
1690
1691 cxdouble h = 0.;
1692 cxdouble t = 0.;
1693 cxdouble d = 0.;
1694 cxdouble a = 0.;
1695 cxdouble b = 0.;
1696 cxdouble dx = 0.;
1697
1698
1699 m = _giraffe_spline_calc_circe(z, x, n);
1700
1701 if (m < 0) {
1702
1703 /* out of bounds */
1704 if (z < x[0]) {
1705 dx = z - x[0];
1706 *val = y[0] + dx * (k[0] + 0.5 * dx * ddb);
1707 } else {
1708 dx = z - x[n - 1];
1709 *val = y[n - 1] + dx * (k[n - 1] + 0.5 * dx * dde);
1710 }
1711
1712 return 1;
1713
1714 }
1715
1716 dx = z - x[m - 1];
1717 h = x[m] - x[m - 1];
1718 d = (y[m] - y[m - 1]) / h;
1719 t = dx / h;
1720 a = (k[m - 1] - d) * (1 - t);
1721 b = (k[m] - d) * t;
1722 *val = t * y[m] + (1 - t) * y[m - 1] + h * t * (1 - t) * (a - b);
1723
1724 return 0;
1725
1726}
1727
1748inline static cxint
1749_giraffe_spline_calc_initalize(cxdouble* x, cxdouble* y, cxdouble* k,
1750 cxint n, cxdouble q2b, cxdouble q2e)
1751{
1752
1753 register cxint i = 0;
1754 register cxint ip = 0;
1755
1756 register cxdouble* a;
1757 register cxdouble* b;
1758 register cxdouble* c;
1759 register cxdouble* f;
1760
1761 cxdouble hio = 0.;
1762 cxdouble hip = 0.;
1763 cxdouble dio = 0.;
1764 cxdouble dip = 0.;
1765
1766
1767
1768 ddb = q2b;
1769 dde = q2e; /* save end second derivatives */
1770
1771 a = (cxdouble*) cx_malloc(4 * n * sizeof(cxdouble));
1772
1773 b = a + n;
1774 c = b + n;
1775 f = c + n;
1776
1777 for (i = 0; i < n; i++) {
1778
1779 hip = ((ip = i + 1) < n ? x[ip] - x[i] : 0.0);
1780 dip = (ip < n ? (y[ip] - y[i]) / hip : 0.0);
1781 b[i] = (ip < n ? hip : hio);
1782 a[i] = 2.0 * (hip + hio);
1783 c[i] = (i > 0 ? hio : hip);
1784 f[i] = 3.0 * (hip * dio + hio * dip);
1785
1786 if (i == 0) {
1787 f[0] = 3.0 * hip * dip - hip * hip * q2b * 0.5;
1788 }
1789 else if (i == n - 1) {
1790 f[n - 1] = 3.0 * hio * dio + hio * hio * q2e * 0.5;
1791 }
1792
1793 dio = dip;
1794 hio = hip;
1795 }
1796
1797 _giraffe_spline_calc_tridi(a, b, c, f, k, n);
1798
1799 cx_free(a);
1800
1801 return 0;
1802
1803}
1804
1823inline static cxint
1824_giraffe_rebin_interpolate_spline(cpl_matrix* x_1, cpl_matrix* y_1,
1825 cpl_matrix* x_2, cpl_matrix* y_2)
1826{
1827
1828 cxint i = 0;
1829 cxint res = 0;
1830 cxint nr_x1 = 0;
1831 cxint nr_x2 = 0;
1832
1833 cxdouble* k = NULL;
1834 cxdouble* pd_x1 = NULL;
1835 cxdouble* pd_y1 = NULL;
1836 cxdouble* pd_x2 = NULL;
1837 cxdouble* pd_y2 = NULL;
1838
1839
1840
1841 if (x_1 == NULL || y_1 == NULL || x_2 == NULL || y_2 == NULL) {
1842 return 1;
1843 }
1844
1845 nr_x1 = cpl_matrix_get_nrow(x_1);
1846 nr_x2 = cpl_matrix_get_nrow(x_2);
1847
1848 pd_x1 = cpl_matrix_get_data(x_1);
1849 pd_y1 = cpl_matrix_get_data(y_1);
1850 pd_y2 = cpl_matrix_get_data(y_2);
1851 pd_x2 = cpl_matrix_get_data(x_2);
1852
1853
1854 /*
1855 * Get storage for spline coefficients and vector y2
1856 */
1857
1858 k = (cxdouble*) cx_malloc(nr_x1 * sizeof(cxdouble));
1859
1860
1861 /*
1862 * Initialise spline calculation...
1863 */
1864
1865 res = _giraffe_spline_calc_initalize(pd_x1, pd_y1, k, nr_x1, 0.0, 0.0);
1866
1867 if (res < 0) {
1868 cx_free(k);
1869 return res;
1870 }
1871
1872 /*
1873 * Calculate spline...
1874 */
1875
1876 for (i = 0; i < nr_x2; i++) {
1877 res = _giraffe_spline_calc_interpolate(pd_x2[i], &(pd_y2[i]), pd_x1,
1878 pd_y1, k, nr_x1);
1879 }
1880
1881 cx_free(k);
1882
1883 return 0;
1884
1885}
1886
1908inline static cxint
1909_giraffe_rebin_interpolate_linear(
1910 cpl_matrix *x_1,
1911 cpl_matrix *y_1,
1912 cpl_matrix *x_2,
1913 cpl_matrix *y_2
1914 )
1915{
1916
1917 /*************************************************************************
1918 Variables
1919 *************************************************************************/
1920
1921 register cxdouble a, b ;
1922 register cxint i, j, j_1, found, n1;
1923
1924 cxint nr_x1 = 0,
1925 nr_x2 = 0;
1926 cxdouble *pd_x1 = NULL,
1927 *pd_x2 = NULL,
1928 *pd_y2 = NULL,
1929 *pd_y1 = NULL;
1930
1931 /*************************************************************************
1932 Preprocessing
1933 *************************************************************************/
1934
1935 if (x_1 == NULL) { return 1; }
1936 if (y_1 == NULL) { return 1; }
1937 if (x_2 == NULL) { return 1; }
1938 if (y_2 == NULL) { return 1; }
1939
1940 nr_x1 = cpl_matrix_get_nrow(x_1);
1941 nr_x2 = cpl_matrix_get_nrow(x_2);
1942 pd_x1 = cpl_matrix_get_data(x_1);
1943 pd_x2 = cpl_matrix_get_data(x_2);
1944 pd_y1 = cpl_matrix_get_data(y_1);
1945 pd_y2 = cpl_matrix_get_data(y_2);
1946
1947 /*************************************************************************
1948 Processing
1949 *************************************************************************/
1950
1951 n1 = nr_x1 - 1;
1952
1953 for (i = 0; i < nr_x2; i++) {
1954 /* Find (x1,y1) on the left of the current point */
1955 found = 0;
1956 for (j = 0; j < n1; j++) {
1957 if ((pd_x2[i] >= pd_x1[j]) && (pd_x2[i] <= pd_x1[j+1])) {
1958 found++ ;
1959 break ;
1960 }
1961 }
1962
1963 if (!found) {
1964 pd_y2[i] = 0.0;
1965 } else {
1966 j_1 = j + 1;
1967 a = (pd_y1[j_1] - pd_y1[j]) / (pd_x1[j_1] - pd_x1[j]);
1968 b = pd_y1[j] - a * pd_x1[j];
1969 pd_y2[i] = (a * pd_x2[i] + b);
1970
1971 }
1972 }
1973
1974 return 0;
1975
1976} /* end giraffe_rebin_interpolate_linear() */
1977
2003inline static cxint
2004_giraffe_rebin_interpolate_linear_error(
2005 cpl_matrix *x_1,
2006 cpl_matrix *y_1,
2007 cpl_matrix *y_1err,
2008 cpl_matrix *x_2,
2009 cpl_matrix *y_2,
2010 cpl_matrix *y_2err
2011 ) {
2012
2013 /*************************************************************************
2014 Variables
2015 *************************************************************************/
2016
2017 register double a, b ,dx;
2018 register int i, j, j_1, found, n1 ;
2019
2020 cxint nr_x1 = 0,
2021 nr_x2 = 0;
2022 cxdouble *pd_x1 = NULL,
2023 *pd_y1 = NULL,
2024 *pd_y1err = NULL,
2025 *pd_x2 = NULL,
2026 *pd_y2 = NULL,
2027 *pd_y2err = NULL;
2028
2029 /*************************************************************************
2030 Preprocessing
2031 *************************************************************************/
2032
2033 if (x_1 == NULL) { return 1; }
2034 if (y_1 == NULL) { return 1; }
2035 if (y_1err == NULL) { return 1; }
2036 if (x_2 == NULL) { return 1; }
2037 if (y_2 == NULL) { return 1; }
2038 if (y_2err == NULL) { return 1; }
2039
2040 nr_x1 = cpl_matrix_get_nrow(x_1);
2041 nr_x2 = cpl_matrix_get_nrow(x_2);
2042 pd_x1 = cpl_matrix_get_data(x_1);
2043 pd_y1 = cpl_matrix_get_data(y_1);
2044 pd_y1err = cpl_matrix_get_data(y_1err);
2045 pd_x2 = cpl_matrix_get_data(x_2);
2046 pd_y2 = cpl_matrix_get_data(y_2);
2047 pd_y2err = cpl_matrix_get_data(y_2err);
2048
2049 /*************************************************************************
2050 Processing
2051 *************************************************************************/
2052
2053 n1 = nr_x1 - 1;
2054
2055 for (i = 0; i < nr_x2; i++) {
2056 /* Find (x1,y1) on the left of the current point */
2057 found = 0;
2058 for (j = 0; j < n1; j++) {
2059 if ((pd_x2[i] >= pd_x1[j]) && (pd_x2[i] <= pd_x1[j+1])) {
2060 found++ ;
2061 break ;
2062 }
2063 }
2064
2065 if (!found) {
2066 pd_y2[i] = 0.0;
2067 pd_y2err[i] = 0.0;
2068 } else {
2069
2070 j_1 = j + 1;
2071 dx = (pd_x1[j_1] - pd_x1[j]);
2072 a = (pd_y1[j_1] - pd_y1[j]) / dx;
2073 b = pd_y1[j] - a * pd_x1[j] ;
2074 pd_y2[i] = (a * pd_x2[i] + b) ;
2075 a = (pd_y1err[j_1] - pd_y1err[j]) / dx;
2076 b = pd_y1err[j] - a * pd_x1[j] ;
2077 pd_y2err[i] = (a * pd_x2[i] + b) ;
2078
2079 }
2080 }
2081
2082 return 0;
2083
2084} /* end giraffe_rebin_interpolate_linear_error() */
2085
2105inline static cxint
2106_giraffe_resample_linear(cpl_image* rbspectra, cpl_image* rberrors,
2107 cpl_image* abscissa, cpl_image* exspectra,
2108 cpl_image* exerrors, cxint opt_direction)
2109{
2110
2111 const cxchar* const fctid = "_giraffe_resample_linear";
2112
2113 register cxlong n = 0;
2114
2115 /*cxint status = 0;*/
2116 cxint nx = 0; /* size of extracted spectra */
2117 cxint ns = 0; /* number of extracted spectra */
2118 cxint nwl = 0; /* size of rebinned spectra */
2119
2120 cxdouble nx1 = 0.;
2121 cxdouble* _mabscissa = NULL;
2122 cxdouble* _mexspectra = NULL;
2123 cxdouble* _mexerrors = NULL;
2124 cxdouble* _mwavelength = NULL;
2125 cxdouble* _mrbspectra = NULL;
2126 cxdouble* _mrberrors = NULL;
2127 cxdouble* _abscissa = NULL;
2128 cxdouble* _exspectra = NULL;
2129 cxdouble* _exerrors = NULL;
2130 cxdouble* _rbspectra = NULL;
2131 cxdouble* _rberrors = NULL;
2132
2133 cpl_matrix* mabscissa = NULL;
2134 cpl_matrix* mwavelength = NULL;
2135 cpl_matrix* mexspectra = NULL;
2136 cpl_matrix* mexerrors = NULL;
2137 cpl_matrix* mrbspectra = NULL;
2138 cpl_matrix* mrberrors = NULL;
2139
2140
2141
2142 if ((abscissa == NULL) || (exspectra == NULL) || (rbspectra == NULL)) {
2143 return 1;
2144 }
2145
2146 if ((exerrors != NULL) && (rberrors == NULL)) {
2147 return 1;
2148 }
2149
2150
2151 nx = cpl_image_get_size_y(exspectra);
2152 ns = cpl_image_get_size_x(exspectra);
2153 nwl = cpl_image_get_size_y(abscissa);
2154
2155 if ((exerrors != NULL) &&
2156 ((nx != cpl_image_get_size_y(exerrors)) ||
2157 (ns != cpl_image_get_size_x(exerrors)))) {
2158 return 1;
2159 }
2160
2161 nx1 = nx - 0.5;
2162
2163 mabscissa = cpl_matrix_new(nx, 1);
2164 mexspectra = cpl_matrix_new(nx, 1);
2165
2166 mwavelength = cpl_matrix_new(nwl, 1);
2167 mrbspectra = cpl_matrix_new(nwl, 1);
2168
2169 _mabscissa = cpl_matrix_get_data(mabscissa);
2170 _mexspectra = cpl_matrix_get_data(mexspectra);
2171 _mwavelength = cpl_matrix_get_data(mwavelength);
2172 _mrbspectra = cpl_matrix_get_data(mrbspectra);
2173
2174 _abscissa = cpl_image_get_data_double(abscissa);
2175 _exspectra = cpl_image_get_data_double(exspectra);
2176 _rbspectra = cpl_image_get_data_double(rbspectra);
2177
2178 if (exerrors != NULL) {
2179 mexerrors = cpl_matrix_new(nx, 1);
2180 mrberrors = cpl_matrix_new(nwl, 1);
2181
2182 _mexerrors = cpl_matrix_get_data(mexerrors);
2183 _mrberrors = cpl_matrix_get_data(mrberrors);
2184
2185 _exerrors = cpl_image_get_data_double(exerrors);
2186 _rberrors = cpl_image_get_data_double(rberrors);
2187 }
2188
2189
2190 /*
2191 * Resample each spectrum to the new grid, taking the direction of the
2192 * optical model into account. If the errors of the spectra are
2193 * available they are also resampled to the new grid.
2194 */
2195
2196 cpl_msg_debug(fctid, "Rebinning %d spectra, using dispersion direction "
2197 "%d and linear interpolation", ns, opt_direction);
2198
2199 for (n = 0; n < ns; n++) {
2200
2201 register cxlong x = 0;
2202
2203
2204 for (x = 0; x < nwl; x++) {
2205 register cxlong j = x * ns + n;
2206 _mwavelength[x] = _abscissa[j];
2207 }
2208
2209 if (exerrors == NULL) {
2210
2211 if (opt_direction < 0) {
2212
2213 for (x = 0; x < nx; x++) {
2214
2215 register cxlong j = x * ns + n;
2216 register cxlong k = nx - x - 1;
2217
2218 _mabscissa[x] = (cxdouble) x;
2219 _mexspectra[k] = _exspectra[j];
2220 }
2221
2222 }
2223 else {
2224
2225 for (x = 0; x < nx; x++) {
2226
2227 register cxlong j = x * ns + n;
2228
2229 _mabscissa[x] = (cxdouble) x;
2230 _mexspectra[x] = _exspectra[j];
2231
2232 }
2233
2234 }
2235
2236
2237 /*
2238 * Linear interpolation of spectra and errors
2239 */
2240
2241 /*status =*/ _giraffe_rebin_interpolate_linear(mabscissa,
2242 mexspectra,
2243 mwavelength,
2244 mrbspectra);
2245
2246 for (x = 0; x < nwl; x++) {
2247
2248 register cxlong j = x * ns + n;
2249
2250 if ((-0.5 > _mwavelength[x]) || (_mwavelength[x] > nx1)) {
2251 _rbspectra[j] = 0.;
2252 }
2253 else {
2254 _rbspectra[j] = _mrbspectra[x];
2255 }
2256
2257 }
2258
2259 }
2260 else {
2261
2262 if (opt_direction < 0) {
2263
2264 for (x = 0; x < nx; x++) {
2265
2266 register cxlong j = x * ns + n;
2267 register cxlong k = nx - x - 1;
2268
2269 _mabscissa[x] = (cxdouble) x;
2270 _mexspectra[k] = _exspectra[j];
2271 _mexerrors[k] = _exerrors[j];
2272 }
2273
2274 }
2275 else {
2276
2277 for (x = 0; x < nx; x++) {
2278
2279 register cxlong j = x * ns + n;
2280
2281 _mabscissa[x] = (cxdouble) x;
2282 _mexspectra[x] = _exspectra[j];
2283 _mexerrors[x] = _exerrors[j];
2284
2285 }
2286
2287 }
2288
2289
2290 /*
2291 * Linear interpolation of spectra and errors
2292 */
2293
2294 /*status =*/
2295 _giraffe_rebin_interpolate_linear_error(mabscissa,
2296 mexspectra,
2297 mexerrors,
2298 mwavelength,
2299 mrbspectra,
2300 mrberrors);
2301
2302 for (x = 0; x < nwl; x++) {
2303
2304 register cxlong j = x * ns + n;
2305
2306 if ((-0.5 > _mwavelength[x]) || (_mwavelength[x] > nx1)) {
2307 _rbspectra[j] = 0.;
2308 _rberrors[j] = 0.;
2309 }
2310 else {
2311 _rbspectra[j] = _mrbspectra[x];
2312 _rberrors[j] = _mrberrors[x];
2313 }
2314
2315 }
2316
2317 }
2318
2319 } /* each spectrum */
2320
2321
2322 cpl_matrix_delete(mrbspectra);
2323 mrbspectra = NULL;
2324
2325 cpl_matrix_delete(mwavelength);
2326 mwavelength = NULL;
2327
2328 cpl_matrix_delete(mexspectra);
2329 mexspectra = NULL;
2330
2331 cpl_matrix_delete(mabscissa);
2332 mabscissa = NULL;
2333
2334 if (exerrors != NULL) {
2335 cpl_matrix_delete(mrberrors);
2336 mrberrors = NULL;
2337
2338 cpl_matrix_delete(mexerrors);
2339 mexerrors = NULL;
2340 }
2341
2342 cpl_msg_debug(fctid, "Rebinned %d spectra", ns);
2343
2344 return 0;
2345
2346}
2347
2348
2368inline static cxint
2369_giraffe_resample_spline(cpl_image* rbspectra, cpl_image* rberrors,
2370 cpl_image* abscissa, cpl_image* exspectra,
2371 cpl_image* exerrors, cxint opt_direction)
2372{
2373
2374 const cxchar* const fctid = "_giraffe_resample_spline";
2375
2376 register cxlong n = 0;
2377
2378 /*cxint status = 0;*/
2379 cxint nx = 0; /* size of extracted spectra */
2380 cxint ns = 0; /* number of extracted spectra */
2381 cxint nwl = 0; /* size of rebinned spectra */
2382
2383 cxdouble nx1 = 0.;
2384 cxdouble* _mabscissa = NULL;
2385 cxdouble* _mexspectra = NULL;
2386 cxdouble* _mexerrors = NULL;
2387 cxdouble* _mwavelength = NULL;
2388 cxdouble* _mrbspectra = NULL;
2389 cxdouble* _mrberrors = NULL;
2390 cxdouble* _abscissa = NULL;
2391 cxdouble* _exspectra = NULL;
2392 cxdouble* _exerrors = NULL;
2393 cxdouble* _rbspectra = NULL;
2394 cxdouble* _rberrors = NULL;
2395
2396 cpl_matrix* mabscissa = NULL;
2397 cpl_matrix* mwavelength = NULL;
2398 cpl_matrix* mexspectra = NULL;
2399 cpl_matrix* mexerrors = NULL;
2400 cpl_matrix* mrbspectra = NULL;
2401 cpl_matrix* mrberrors = NULL;
2402
2403
2404
2405 if ((abscissa == NULL) || (exspectra == NULL) || (rbspectra == NULL)) {
2406 return 1;
2407 }
2408
2409 if ((exerrors != NULL) && (rberrors == NULL)) {
2410 return 1;
2411 }
2412
2413
2414 nx = cpl_image_get_size_y(exspectra);
2415 ns = cpl_image_get_size_x(exspectra);
2416 nwl = cpl_image_get_size_y(abscissa);
2417
2418 if ((exerrors != NULL) &&
2419 ((nx != cpl_image_get_size_y(exerrors)) ||
2420 (ns != cpl_image_get_size_x(exerrors)))) {
2421 return 1;
2422 }
2423
2424 nx1 = nx - 0.5;
2425
2426 mabscissa = cpl_matrix_new(nx, 1);
2427 mexspectra = cpl_matrix_new(nx, 1);
2428
2429 mwavelength = cpl_matrix_new(nwl, 1);
2430 mrbspectra = cpl_matrix_new(nwl, 1);
2431
2432 _mabscissa = cpl_matrix_get_data(mabscissa);
2433 _mexspectra = cpl_matrix_get_data(mexspectra);
2434 _mwavelength = cpl_matrix_get_data(mwavelength);
2435 _mrbspectra = cpl_matrix_get_data(mrbspectra);
2436
2437 _abscissa = cpl_image_get_data_double(abscissa);
2438 _exspectra = cpl_image_get_data_double(exspectra);
2439 _rbspectra = cpl_image_get_data_double(rbspectra);
2440
2441 if (exerrors != NULL) {
2442 mexerrors = cpl_matrix_new(nx, 1);
2443 mrberrors = cpl_matrix_new(nwl, 1);
2444
2445 _mexerrors = cpl_matrix_get_data(mexerrors);
2446 _mrberrors = cpl_matrix_get_data(mrberrors);
2447
2448 _exerrors = cpl_image_get_data_double(exerrors);
2449 _rberrors = cpl_image_get_data_double(rberrors);
2450 }
2451
2452
2453 /*
2454 * Resample each spectrum to the new grid, taking the direction of the
2455 * optical model into account. If the errors of the spectra are
2456 * available they are also resampled to the new grid.
2457 */
2458
2459 cpl_msg_debug(fctid, "Rebinning %d spectra, using dispersion direction "
2460 "%d and linear interpolation", ns, opt_direction);
2461
2462 for (n = 0; n < ns; n++) {
2463
2464 register cxlong x = 0;
2465
2466
2467 for (x = 0; x < nwl; x++) {
2468 register cxlong j = x * ns + n;
2469 _mwavelength[x] = _abscissa[j];
2470 }
2471
2472 if (exerrors == NULL) {
2473
2474 if (opt_direction < 0) {
2475
2476 for (x = 0; x < nx; x++) {
2477
2478 register cxlong j = x * ns + n;
2479 register cxlong k = nx - x - 1;
2480
2481 _mabscissa[x] = (cxdouble) x;
2482 _mexspectra[k] = _exspectra[j];
2483 }
2484
2485 }
2486 else {
2487
2488 for (x = 0; x < nx; x++) {
2489
2490 register cxlong j = x * ns + n;
2491
2492 _mabscissa[x] = (cxdouble) x;
2493 _mexspectra[x] = _exspectra[j];
2494
2495 }
2496
2497 }
2498
2499
2500 /*
2501 * Spline interpolation of spectra and errors
2502 */
2503
2504 /*status =*/ _giraffe_rebin_interpolate_spline(mabscissa,
2505 mexspectra,
2506 mwavelength,
2507 mrbspectra);
2508
2509 for (x = 0; x < nwl; x++) {
2510
2511 register cxlong j = x * ns + n;
2512
2513 if ((-0.5 > _mwavelength[x]) || (_mwavelength[x] > nx1)) {
2514 _rbspectra[j] = 0.;
2515 }
2516 else {
2517 _rbspectra[j] = _mrbspectra[x];
2518 }
2519
2520 }
2521
2522 }
2523 else {
2524
2525 if (opt_direction < 0) {
2526
2527 for (x = 0; x < nx; x++) {
2528
2529 register cxlong j = x * ns + n;
2530 register cxlong k = nx - x - 1;
2531
2532 _mabscissa[x] = (cxdouble) x;
2533 _mexspectra[k] = _exspectra[j];
2534 _mexerrors[k] = _exerrors[j];
2535 }
2536
2537 }
2538 else {
2539
2540 for (x = 0; x < nx; x++) {
2541
2542 register cxlong j = x * ns + n;
2543
2544 _mabscissa[x] = (cxdouble) x;
2545 _mexspectra[x] = _exspectra[j];
2546 _mexerrors[x] = _exerrors[j];
2547
2548 }
2549
2550 }
2551
2552
2553 /*
2554 * Spline interpolation of spectra and linear interpolation of
2555 * errors
2556 */
2557
2558 /*status =*/ _giraffe_rebin_interpolate_spline(mabscissa,
2559 mexspectra,
2560 mwavelength,
2561 mrbspectra);
2562
2563 /*status =*/ _giraffe_rebin_interpolate_linear(mabscissa,
2564 mexerrors,
2565 mwavelength,
2566 mrberrors);
2567
2568 for (x = 0; x < nwl; x++) {
2569
2570 register cxlong j = x * ns + n;
2571
2572 if ((-0.5 > _mwavelength[x]) || (_mwavelength[x] > nx1)) {
2573 _rbspectra[j] = 0.;
2574 _rberrors[j] = 0.;
2575 }
2576 else {
2577 _rbspectra[j] = _mrbspectra[x];
2578 _rberrors[j] = _mrberrors[x];
2579 }
2580
2581 }
2582
2583 }
2584
2585 } /* each spectrum */
2586
2587
2588 cpl_matrix_delete(mrbspectra);
2589 mrbspectra = NULL;
2590
2591 cpl_matrix_delete(mwavelength);
2592 mwavelength = NULL;
2593
2594 cpl_matrix_delete(mexspectra);
2595 mexspectra = NULL;
2596
2597 cpl_matrix_delete(mabscissa);
2598 mabscissa = NULL;
2599
2600 if (exerrors != NULL) {
2601 cpl_matrix_delete(mrberrors);
2602 mrberrors = NULL;
2603
2604 cpl_matrix_delete(mexerrors);
2605 mexerrors = NULL;
2606 }
2607
2608 cpl_msg_debug(fctid, "Rebinned %d spectra", ns);
2609
2610 return 0;
2611
2612}
2613
2614
2688static cxdouble
2689giraffe_rebin_compute_opt_mod3(cxdouble xccd, cxdouble xfibre,
2690 cxdouble yfibre, cxdouble nx,
2691 cxdouble pixsize, cxdouble fcoll,
2692 cxdouble cfact, cxdouble gtheta,
2693 cxdouble gorder, cxdouble gspace,
2694 cxdouble slitdx, cxdouble slitdy,
2695 cxdouble slitphi)
2696{
2697
2698 /*************************************************************************
2699 Variables
2700 *************************************************************************/
2701
2702 cxdouble xf, yf, d, t1, t12, t13, t18, t19, t2, t23, t28,
2703 t3, t31, t32, t36, t37, t39, t4, t40, t5, t62, t8, t9;
2704
2705 /*************************************************************************
2706 Processing
2707 *************************************************************************/
2708
2709 /* should take care of negative NX value */
2710
2711 xf = xfibre * (1.0 + slitphi * yfibre) + slitdx;
2712 yf = yfibre * sqrt(1.0 - slitphi * slitphi) + slitdy;
2713 d = sqrt(xf * xf + yf * yf + fcoll * fcoll);
2714 t1 = cos(gtheta);
2715 t2 = xf*t1;
2716 t3 = xccd*xccd;
2717 t4 = pixsize*pixsize;
2718 t5 = t3*t4;
2719 t8 = sin(gtheta);
2720 t9 = fcoll*t8;
2721 t12 = cfact*cfact;
2722 t13 = fcoll*fcoll;
2723 t18 = nx*nx;
2724 t19 = t18*t4;
2725 t23 = xccd*t4*nx;
2726 t28 = t12*t13;
2727 t31 = yf*yf;
2728 t32 = d*d;
2729 t36 = 4.0*t28;
2730 t37 = t19+4.0*t5-4.0*t23+t36;
2731 t39 = t1*t1;
2732 t40 = t39*t4;
2733 t62 = sqrt((-t31+t32)*t37*(4.0*t40*t3-4.0*xccd*nx*t40 +
2734 8.0*xccd*t1*cfact*t9*pixsize+t19*t39 -
2735 4.0*cfact*fcoll*t8*nx*t1*pixsize+t36 -
2736 4.0*t28*t39));
2737
2738 return((4.0*t2*t5 + 4.0*t9*t5 + 4.0*t12*t13*fcoll*t8+t2*t19+t9*t19 -
2739 4.0*t9*t23 - 4.0*t2*t23 + 4.0*t28*t2+t62)*gspace/t37/gorder/d);
2740
2741} /* end giraffe_rebin_compute_opt_mod3() */
2742
2767static cxdouble
2768giraffe_rebin_compute_log_opt_mod3(cxdouble xccd, cxdouble xfibre,
2769 cxdouble yfibre, cxdouble nx,
2770 cxdouble pixsize, cxdouble fcoll,
2771 cxdouble cfact, cxdouble gtheta,
2772 cxdouble gorder, cxdouble gspace,
2773 cxdouble slitdx, cxdouble slitdy,
2774 cxdouble slitphi)
2775{
2776
2777 return log(giraffe_rebin_compute_opt_mod3(xccd, xfibre, yfibre, nx,
2778 pixsize, fcoll, cfact, gtheta,
2779 gorder, gspace, slitdx, slitdy,
2780 slitphi));
2781
2782} /* end of giraffe_rebin_compute_log_opt_mod3() */
2783
2830static cxint
2831giraffe_rebin_compute_lambda_range(GiFiberPosition *fiber_slit_position,
2832 cpl_matrix *opt_mod_params,
2833 cpl_matrix *grat_params,
2834 cxbool lambda_logarithmic,
2835 cxbool wlen_range_common,
2836 cxdouble *lambda_min, cxdouble *lambda_max)
2837{
2838
2839 /*************************************************************************
2840 Variables
2841 *************************************************************************/
2842
2843 const cxchar *fctid = "giraffe_rebin_compute_lambda_range";
2844
2845 register cxlong n, ns;
2846 register cxdouble dx2, dnx, wl1, wl2;
2847
2848 double (*computeWl) (double, double, double, double, double, double,
2849 double, double, double, double, double, double,
2850 double);
2851
2852 cxdouble *pd_opt_mod_params = NULL,
2853 *pd_xfiber = NULL,
2854 *pd_yfiber = NULL,
2855 *pd_grat_params = NULL;
2856
2857 cxint nr_xfiber;
2858
2859 /*************************************************************************
2860 Preprocessing
2861 *************************************************************************/
2862
2863 if (fiber_slit_position ==NULL) { return 1; }
2864 if (fiber_slit_position->x_fiber==NULL) { return 1; }
2865 if (fiber_slit_position->y_fiber==NULL) { return 1; }
2866 if (opt_mod_params ==NULL) { return 1; }
2867 if (grat_params ==NULL) { return 1; }
2868 if (lambda_min ==NULL) { return 1; }
2869 if (lambda_max ==NULL) { return 1; }
2870
2871 pd_opt_mod_params = cpl_matrix_get_data(opt_mod_params);
2872
2873 pd_xfiber = cpl_matrix_get_data(fiber_slit_position->x_fiber);
2874 nr_xfiber = cpl_matrix_get_nrow(fiber_slit_position->x_fiber);
2875
2876 /*************************************************************************
2877 Processing
2878 *************************************************************************/
2879
2880 if (lambda_logarithmic==TRUE) {
2881 computeWl = giraffe_rebin_compute_log_opt_mod3;
2882 } else {
2883 computeWl = giraffe_rebin_compute_opt_mod3;
2884 }
2885
2886 dnx = abs(pd_opt_mod_params[O_NX]);
2887 dx2 = dnx - 1.0;
2888 ns = nr_xfiber;
2889
2890 if (wlen_range_common==TRUE) {
2891 *lambda_min = 0.0;
2892 *lambda_max = CX_MAXDOUBLE;
2893 } else {
2894 *lambda_min = CX_MAXDOUBLE;
2895 *lambda_max = 0.0;
2896 }
2897
2898 pd_yfiber = cpl_matrix_get_data(fiber_slit_position->y_fiber);
2899 pd_grat_params = cpl_matrix_get_data(grat_params);
2900
2901 for (n = 0; n < ns; n++) {
2902
2903 /* first abcissa of each spectrum */
2904 wl1 =
2905 computeWl(
2906 0.0,
2907 pd_xfiber[n],
2908 pd_yfiber[n],
2909 dnx,
2910 pd_opt_mod_params[O_PXSIZ],
2911 pd_opt_mod_params[O_FCOLL],
2912 pd_opt_mod_params[O_CFACT],
2913 pd_grat_params[G_THETA],
2914 pd_grat_params[G_ORDER],
2915 pd_grat_params[G_SPACE],
2916 pd_opt_mod_params[O_SOFFX],
2917 pd_opt_mod_params[O_SOFFY],
2918 pd_opt_mod_params[O_SPHI]
2919 );
2920
2921 /* last abcissa of each spectrum */
2922 wl2 =
2923 computeWl(
2924 dx2,
2925 pd_xfiber[n],
2926 pd_yfiber[n],
2927 dnx,
2928 pd_opt_mod_params[O_PXSIZ],
2929 pd_opt_mod_params[O_FCOLL],
2930 pd_opt_mod_params[O_CFACT],
2931 pd_grat_params[G_THETA],
2932 pd_grat_params[G_ORDER],
2933 pd_grat_params[G_SPACE],
2934 pd_opt_mod_params[O_SOFFX],
2935 pd_opt_mod_params[O_SOFFY],
2936 pd_opt_mod_params[O_SPHI]
2937 );
2938
2939 if (wlen_range_common==TRUE) {
2940
2941 /* common range = [max(wlen_min), min(wlen_max)] */
2942
2943 if (pd_opt_mod_params[O_NX] < 0) {
2944 *lambda_max = CX_MIN(*lambda_max, wl1);
2945 *lambda_min = CX_MAX(*lambda_min, wl2);
2946 } else {
2947 *lambda_max = CX_MIN(*lambda_max, wl2);
2948 *lambda_min = CX_MAX(*lambda_min, wl1);
2949 }
2950
2951 } else {
2952
2953 /* full range = [min(wlen_min), max(wlen_max)] */
2954
2955 if (pd_opt_mod_params[O_NX] < 0) {
2956 *lambda_max = CX_MAX(*lambda_max, wl1);
2957 *lambda_min = CX_MIN(*lambda_min, wl2);
2958 } else {
2959 *lambda_max = CX_MAX(*lambda_max, wl2);
2960 *lambda_min = CX_MIN(*lambda_min, wl1);
2961 }
2962
2963 }
2964
2965 } /* for each spectrum */
2966
2967 if (wlen_range_common==TRUE) {
2968 /* round to minimum range in integer nanometers */
2969 *lambda_max = floor((*lambda_max) * GI_MM_TO_NM) / GI_MM_TO_NM;
2970 *lambda_min = ceil( (*lambda_min) * GI_MM_TO_NM) / GI_MM_TO_NM;
2971 } else {
2972 /* round to maximum range in integer nanometers */
2973 *lambda_max = ceil( (*lambda_max) * GI_MM_TO_NM) / GI_MM_TO_NM;
2974 *lambda_min = floor((*lambda_min) * GI_MM_TO_NM) / GI_MM_TO_NM;
2975 }
2976
2977 cpl_msg_debug(fctid, "Rebinning lambda range now: [%12.6f,%12.6f]",
2978 *lambda_min, *lambda_max);
2979
2980 return 0;
2981
2982} /* end giraffe_rebin_compute_lambda_range() */
2983
3006static cpl_image*
3007giraffe_rebin_compute_pixel_x_residuals(
3008 GiLocPosition *locPos,
3009 cpl_image *abcissa,
3010 GiSlitGeo *slitGeo,
3011 GiSlitGeo *xresiduals_limits,
3012 GiSlitGeo *xresiduals_coeff
3013 ) {
3014
3015 /*************************************************************************
3016 Variables
3017 *************************************************************************/
3018
3019 const cxchar *fctid = "giraffe_rebin_compute_pixel_x_residuals";
3020
3021 cxdouble xmin, xmax, ymin, ymax, yup, ylo, yccd, ywid;
3022 cxint n, m, x, xx, x0, i, j, k, l, xxp, x0p;
3023
3024 cxint subslit,
3025 nfibers,
3026 /*nmin,*/
3027 /*nmax,*/
3028 /*nlen,*/
3029 nx, /* size of original spectra */
3030 ns, /* number of spectra */
3031 nwl, /* size of rebinned spectra */
3032 nf,
3033 nstart,
3034 ndata,
3035 nr_fit,
3036 nc_fit;
3037
3038 cpl_matrix *xss = NULL,
3039 *yss = NULL,
3040 *fit = NULL,
3041 *curr_xres_limits = NULL,
3042 *curr_xres_coeff = NULL;
3043
3044 cpl_image *x_residuals_img = NULL;
3045
3046 cpl_matrix *curr_subslit = NULL;
3047
3048 cxdouble /* *pd_curr_subslit = NULL,*/
3049 *pd_abcissa = NULL,
3050 *pd_xss = NULL,
3051 *pd_yss = NULL;
3052
3053 cxdouble *pd_locy = NULL,
3054 *pd_locw = NULL,
3055 *buffer = NULL,
3056 *pd_fit = NULL,
3057 *pd_x_residuals_img = NULL;
3058
3059
3060 /*************************************************************************
3061 Preprocessing
3062 *************************************************************************/
3063
3064 if (locPos ==NULL) { return NULL; }
3065 if (locPos->centroids ==NULL) { return NULL; }
3066 if (locPos->widths ==NULL) { return NULL; }
3067 if (abcissa ==NULL) { return NULL; }
3068 if (slitGeo ==NULL) { return NULL; }
3069 if (xresiduals_limits ==NULL) { return NULL; }
3070 if (xresiduals_coeff ==NULL) { return NULL; }
3071
3072 nx = cpl_image_get_size_y(locPos->centroids);
3073 ns = cpl_image_get_size_x(locPos->centroids);
3074 nf = cpl_image_get_size_x(abcissa);
3075 nwl = cpl_image_get_size_y(abcissa);
3076
3077 cpl_msg_debug(
3078 fctid,
3079 "Computing pixel x residuals, using nr spec/nr lines/orig abcissa "
3080 "size: %d/%d/%d",
3081 ns,
3082 nwl,
3083 nx
3084 );
3085
3086 /*************************************************************************
3087 Processing
3088 *************************************************************************/
3089
3090 x_residuals_img = cpl_image_new(nf, nwl, CPL_TYPE_DOUBLE);
3091 pd_x_residuals_img = cpl_image_get_data_double(x_residuals_img);
3092 pd_abcissa = cpl_image_get_data_double(abcissa);
3093
3094 nstart = 0;
3095
3096 for (subslit = 0; subslit<_giraffe_slitgeo_size(slitGeo); subslit++) {
3097
3098 curr_subslit = _giraffe_slitgeo_get(slitGeo, subslit);
3099 /*pd_curr_subslit = cpl_matrix_get_data(curr_subslit);*/
3100
3101 giraffe_matrix_sort(curr_subslit);
3102
3103 curr_xres_limits =
3104 cpl_matrix_duplicate(
3105 _giraffe_slitgeo_get(xresiduals_limits, subslit)
3106 );
3107
3108 curr_xres_coeff =
3109 cpl_matrix_duplicate(
3110 _giraffe_slitgeo_get(xresiduals_coeff, subslit)
3111 );
3112
3113 /* Get spectra/fibers range for current subslit */
3114 nfibers = cpl_matrix_get_nrow(curr_subslit);
3115
3116 /*nmin = (cxint) pd_curr_subslit[0];*/
3117 /*nmax = (cxint) pd_curr_subslit[nfibers - 1];*/
3118 /*nlen = nmax - nmin + 1;*/
3119 ndata = nwl * nfibers;
3120
3121 ymax = 0.0;
3122 ymin = CX_MAXDOUBLE; /* has to be smaller than this one! */
3123
3124 xss = cpl_matrix_new(ndata, 1); /* X abcissas for subslit */
3125 yss = cpl_matrix_new(ndata, 1); /* Y ordinates */
3126
3127 pd_xss = cpl_matrix_get_data(xss);
3128 pd_yss = cpl_matrix_get_data(yss);
3129
3130 pd_locy = cpl_image_get_data_double(locPos->centroids);
3131 pd_locw = cpl_image_get_data_double(locPos->widths);
3132
3133
3134 k = 0;
3135
3136 for (m = 0, n = 0; n < nfibers; n++, m++) {
3137
3138 i = 0; /* running index for valid points */
3139
3140 for (x = 0; x < nwl; x++) {
3141
3142 j = x * nf + (nstart + n);
3143 x0 = (cxint) floor(pd_abcissa[j]);
3144 xx = (cxint) ceil(pd_abcissa[j]);
3145
3146 x0 = CX_MAX(CX_MIN(x0, nx - 1), 0);
3147 xx = CX_MAX(CX_MIN(xx, nx - 1), 0);
3148
3149 l = i * nfibers + m;
3150 xxp = xx * ns + cpl_matrix_get(curr_subslit, n, 0);
3151 x0p = x0 * ns + cpl_matrix_get(curr_subslit, n, 0);
3152
3153 pd_xss[l] = pd_abcissa[j];
3154
3155 /*
3156 * Corresponding Y centroid and width using
3157 * linear interpolation)
3158 */
3159
3160 yccd = pd_locy[x0p];
3161 pd_yss[l] = yccd + ((pd_locy[xxp] - yccd) * (pd_xss[l] - x0));
3162
3163 ywid = pd_locw[x0p];
3164 ywid = ywid + ((pd_locw[xxp] - ywid) * (pd_xss[l] - x0));
3165
3166 /* Get y range for current subslit */
3167 yup = yccd + ywid;
3168 ylo = yccd - ywid;
3169
3170 /* determine minimum and maximum */
3171 if (ymax < yup) {
3172 ymax = yup;
3173 }
3174
3175 if (ymin > ylo) {
3176 ymin = ylo;
3177 }
3178
3179 ++i;
3180 ++k;
3181
3182 }
3183 }
3184
3185 /* resize matrices to number of points found */
3186 cpl_matrix_set_size(xss, k, 1);
3187 cpl_matrix_set_size(yss, k, 1);
3188 pd_xss = cpl_matrix_get_data(xss);
3189 pd_yss = cpl_matrix_get_data(yss);
3190
3191 xmin = cpl_matrix_get(curr_xres_limits, 0, 0);
3192 xmax = cpl_matrix_get(curr_xres_limits, 0, 1);
3193 ymin = cpl_matrix_get(curr_xres_limits, 0, 2);
3194 ymax = cpl_matrix_get(curr_xres_limits, 0, 3);
3195
3196 xmin = xmin < 0. ? 0. : xmin;
3197 xmax = xmax < 0. ? (cxdouble)nx : xmax;
3198
3199 ymin = ymin < 0. ? 0. : ymin;
3200 ymax = ymax < 0. ? 2048. : ymax;
3201
3202 /* do chebyshev fit */
3203 fit =
3204 giraffe_chebyshev_fit2d(
3205 xmin, ymin,
3206 (xmax - xmin),
3207 (ymax - ymin + 1.0),
3208 curr_xres_coeff,
3209 xss,
3210 yss
3211 );
3212
3213 cpl_matrix_delete(yss);
3214 cpl_matrix_delete(xss);
3215 cpl_matrix_delete(curr_xres_coeff);
3216 cpl_matrix_delete(curr_xres_limits);
3217
3218 /* resize fit found to match image dimensions */
3219 buffer = cpl_matrix_get_data(fit);
3220 cpl_matrix_unwrap(fit);
3221 fit = NULL;
3222
3223 fit = cpl_matrix_wrap(nwl, nfibers, buffer);
3224 pd_fit = cpl_matrix_get_data(fit);
3225 nr_fit = cpl_matrix_get_nrow(fit);
3226 nc_fit = cpl_matrix_get_ncol(fit);
3227
3228 /* subslit fit goes into whole fit */
3229 for (x = 0; x < nr_fit; x++) {
3230 for (k = nstart, n = 0; n < nc_fit; n++, k++) {
3231 pd_x_residuals_img[x * nf + k] = pd_fit[x * nc_fit + n];
3232 }
3233 }
3234
3235 cpl_matrix_delete(fit);
3236 fit = NULL;
3237
3238 nstart += nfibers;
3239
3240 } /* for each subslit */
3241
3242 cpl_msg_debug(
3243 fctid,
3244 "Computed pixel x residuals, returning image [%d,%d]",
3245 ns,
3246 nwl
3247 );
3248
3249 return x_residuals_img;
3250
3251} /* end giraffe_rebin_compute_pixel_x_residuals() */
3252
3253
3286static cpl_image*
3287giraffe_rebin_compute_rebin_abcissa(GiFiberPosition* fiber_slit_position,
3288 GiLocPosition* locPos,
3289 GiSlitGeo* slitGeo,
3290 GiSlitGeo* xresiduals_limits,
3291 GiSlitGeo* xresiduals_coeff,
3292 cpl_matrix* grat_params,
3293 cpl_matrix* opt_mod_params,
3294 cpl_matrix* wloffsets,
3295 lmrq_model lmrq_opt_mod_x,
3296 GiRebinParams binPrms)
3297{
3298
3299 /*************************************************************************
3300 Variables
3301 *************************************************************************/
3302
3303 const cxchar* const fctid = "giraffe_rebin_compute_rebin_abcissa";
3304
3305 cpl_matrix* wlengths = NULL;
3306 cpl_matrix* temp_params = NULL;
3307
3308 cpl_image* abcissa = NULL;
3309 cpl_image* x_residuals_img = NULL;
3310
3311 cxdouble* pd_wlengths = NULL;
3312 cxdouble* pd_temp_params = NULL;
3313 cxdouble* pd_opt_mod_params = NULL;
3314 cxdouble* pd_grat_params = NULL;
3315
3316 /*************************************************************************
3317 Preprocessing
3318 *************************************************************************/
3319
3320 if (fiber_slit_position == NULL) {
3321 return NULL;
3322 }
3323
3324 if (locPos == NULL) {
3325 return NULL;
3326 }
3327
3328 if (slitGeo == NULL) {
3329 return NULL;
3330 }
3331
3332 if (grat_params == NULL) {
3333 return NULL;
3334 }
3335
3336 if (opt_mod_params == NULL) {
3337 return NULL;
3338 }
3339
3340 wlengths = cpl_matrix_new(binPrms.size, 1);
3341 pd_wlengths = cpl_matrix_get_data(wlengths);
3342
3343 temp_params = cpl_matrix_new(lmrq_opt_mod_x.nparams, 1);
3344
3345 pd_temp_params = cpl_matrix_get_data(temp_params);
3346 pd_opt_mod_params = cpl_matrix_get_data(opt_mod_params);
3347 pd_grat_params = cpl_matrix_get_data(grat_params);
3348
3349 pd_temp_params[OG_NX] = pd_opt_mod_params[O_NX];
3350 pd_temp_params[OG_PXSIZ] = pd_opt_mod_params[O_PXSIZ];
3351 pd_temp_params[OG_FCOLL] = pd_opt_mod_params[O_FCOLL];
3352 pd_temp_params[OG_CFACT] = pd_opt_mod_params[O_CFACT];
3353 pd_temp_params[OG_THETA] = pd_grat_params[G_THETA];
3354 pd_temp_params[OG_ORDER] = pd_grat_params[G_ORDER];
3355 pd_temp_params[OG_SPACE] = pd_grat_params[G_SPACE];
3356
3357 if (lmrq_opt_mod_x.nparams > OG_SOFFX) {
3358 pd_temp_params[OG_SOFFX] = pd_opt_mod_params[O_SOFFX];
3359 pd_temp_params[OG_SOFFY] = pd_opt_mod_params[O_SOFFY];
3360 pd_temp_params[OG_SPHI] = pd_opt_mod_params[O_SPHI];
3361 }
3362
3363 /*************************************************************************
3364 Processing
3365 *************************************************************************/
3366
3367 /*
3368 * Compute lambda abcissa for rebinning
3369 */
3370
3371 if (binPrms.log==TRUE) {
3372 /* lambda was specified in log(lambda) */
3373 cxint i;
3374 for (i = 0; i < binPrms.size; i++) {
3375 pd_wlengths[i] = exp(binPrms.min + (cxdouble) i * binPrms.step);
3376 }
3377 } else {
3378 cxint i;
3379 for (i = 0; i < binPrms.size; i++) {
3380 pd_wlengths[i] = binPrms.min + (cxdouble) i * binPrms.step;
3381 }
3382 }
3383
3384 abcissa = _giraffe_compute_pixel_abscissa(wlengths, wloffsets,
3385 fiber_slit_position,
3386 temp_params, lmrq_opt_mod_x);
3387
3388
3389 /*
3390 * If X residuals use, specified, calculate them and subtract
3391 * them from the computed abcissa...
3392 */
3393
3394 if ((binPrms.xres==TRUE) && (xresiduals_coeff!=NULL)) {
3395
3396 x_residuals_img =
3397 giraffe_rebin_compute_pixel_x_residuals(
3398 locPos,
3399 abcissa,
3400 slitGeo,
3401 xresiduals_limits,
3402 xresiduals_coeff
3403 );
3404
3405 cpl_image_subtract(abcissa, x_residuals_img);
3406 cpl_image_delete(x_residuals_img);
3407
3408 }
3409
3410 cpl_matrix_delete(wlengths);
3411 cpl_matrix_delete(temp_params);
3412
3413 cpl_msg_debug(fctid, "Processing complete : returning image "
3414 "[%" CPL_SIZE_FORMAT ", %" CPL_SIZE_FORMAT "]",
3415 cpl_image_get_size_x(abcissa), cpl_image_get_size_y(abcissa));
3416
3417 return abcissa;
3418
3419} /* end giraffe_rebin_compute_rebin_abcissa() */
3420
3448inline static cxint
3449_giraffe_resample_spectra(GiRebinning* result,
3450 const GiExtraction* extraction,
3451 const GiLocalization* localization,
3452 GiFiberPosition* fiber_position,
3453 GiSlitGeo* subslits,
3454 GiSlitGeo* xres_limits,
3455 GiSlitGeo* xres_coeff,
3456 GiBinnParams* xres_order,
3457 cpl_matrix* grating_data,
3458 cpl_matrix* optical_model,
3459 cpl_matrix* wlen_offsets,
3460 cxdouble rbstep,
3461 GiRebinMethod method,
3462 GiRebinRange range,
3463 GiRebinScale scale)
3464{
3465
3466 const cxchar* const fctid = "_giraffe_resample_spectra";
3467
3468
3469 cxbool log_scale = FALSE;
3470
3471 cxint i = 0;
3472 cxint status = 0;
3473 cxint om_sign = 0;
3474 cxint rbsize = 0;
3475 cxint nspectra = 0;
3476
3477 cxdouble wlmin = 0.;
3478 cxdouble wlmax = 0.;
3479 cxdouble* _optical_model = NULL;
3480
3481 cpl_matrix* wavelengths = NULL;
3482
3483 cpl_image* _exspectra = NULL;
3484 cpl_image* _exerrors = NULL;
3485 cpl_image* _rbspectra = NULL;
3486 cpl_image* _rberrors = NULL;
3487 cpl_image* abscissa = NULL;
3488
3489 cpl_propertylist* properties = NULL;
3490
3491 GiImage* rbspectra = NULL;
3492 GiImage* rberrors = NULL;
3493
3494 GiLocPosition locPos;
3495
3496 GiRebinParams binPrms;
3497
3498 GiRebinInfo setup;
3499
3500
3501 /*
3502 * default opt model is xoptmod2, python code
3503 * can not handle anything else anyway
3504 */
3505
3506 lmrq_model_id opt_mod_id = LMRQ_XOPTMOD2;
3507
3508
3509 if (result == NULL || extraction == NULL || localization == NULL) {
3510 return 1;
3511 }
3512
3513 if (result->spectra != NULL || result->errors != NULL) {
3514 return 1;
3515 }
3516
3517 if (extraction->spectra == NULL) {
3518 return 1;
3519 }
3520
3521 if (localization->locy == NULL || localization->locw == NULL) {
3522 return 1;
3523 }
3524
3525 if (fiber_position == NULL) {
3526 return 1;
3527 }
3528
3529 if (subslits == NULL) {
3530 return 1;
3531 }
3532
3533 if (grating_data == NULL) {
3534 return 1;
3535 }
3536
3537 if (optical_model == NULL) {
3538 return 1;
3539 }
3540
3541
3542 if (xres_coeff != NULL) {
3543 if (xres_limits == NULL || xres_order == NULL) {
3544 return 1;
3545 }
3546 }
3547
3548
3549 /*
3550 * FIXME: Should we set opt_mod_id to opt_mod_id used by wave
3551 * calibration? Yes!!!
3552 */
3553
3554 _exspectra = giraffe_image_get(extraction->spectra);
3555
3556 if (extraction->error != NULL) {
3557 _exerrors = giraffe_image_get(extraction->error);
3558 }
3559
3560 _optical_model = cpl_matrix_get_data(optical_model);
3561
3562 nspectra = cpl_image_get_size_x(_exspectra);
3563
3564 om_sign = (_optical_model[O_NX] >= 0) ? 1 : -1;
3565
3566 if (scale == GIREBIN_SCALE_LOG) {
3567 log_scale = TRUE;
3568 }
3569
3570
3571 /*
3572 * Find wavelength range
3573 */
3574
3575 if (range == GIREBIN_RANGE_SETUP) {
3576
3577 /*
3578 * Wavelength range taken from observed mode
3579 */
3580
3581 wlmin = cpl_matrix_get(grating_data, 2, 0);
3582 wlmax = cpl_matrix_get(grating_data, 4, 0);
3583
3584 if (log_scale == TRUE) {
3585 wlmin = log(wlmin);
3586 wlmax = log(wlmax);
3587 }
3588
3589 }
3590 else {
3591
3592 /*
3593 * Spectral range based on max/min wavelengths
3594 */
3595
3596 status = giraffe_rebin_compute_lambda_range(fiber_position,
3597 optical_model,
3598 grating_data, log_scale,
3599 TRUE, &wlmin, &wlmax);
3600
3601 }
3602
3603 rbsize = 1 + (cxint) ((wlmax - wlmin) / rbstep);
3604
3605 if (rbsize < 0) {
3606
3607 cpl_msg_debug(fctid, "Invalid dispersion direction [%d], changing "
3608 "optical model orientation", om_sign);
3609
3610 om_sign = -om_sign;
3611 _optical_model[O_NX] = -_optical_model[O_NX];
3612
3613 status = giraffe_rebin_compute_lambda_range(fiber_position,
3614 optical_model,
3615 grating_data, log_scale,
3616 TRUE, &wlmin, &wlmax);
3617
3618 rbsize = 1 + (cxint) ((wlmax - wlmin) / rbstep);
3619
3620 }
3621
3622 if (rbsize < 1) {
3623 cpl_msg_error(fctid, "Invalid size %d of rebinned spectra, "
3624 "aborting...", rbsize);
3625 return 2;
3626 }
3627
3628
3629 /*
3630 * Calculate rebinned X positions...
3631 */
3632
3633 locPos.type = GILOCDATATYPE_FITTED_DATA;
3634 locPos.centroids = giraffe_image_get(localization->locy);
3635 locPos.widths = giraffe_image_get(localization->locw);
3636
3637 binPrms.min = wlmin;
3638 binPrms.step = rbstep;
3639 binPrms.size = rbsize;
3640 binPrms.log = log_scale;
3641
3642 if (xres_coeff == NULL || (xres_order->xdeg == 0 &&
3643 xres_order->ydeg == 0)) {
3644 binPrms.xres = FALSE;
3645 }
3646 else {
3647 binPrms.xres = TRUE;
3648 }
3649
3650 abscissa = giraffe_rebin_compute_rebin_abcissa(fiber_position, &locPos,
3651 subslits, xres_limits,
3652 xres_coeff, grating_data,
3653 optical_model, wlen_offsets,
3654 lmrq_models[opt_mod_id],
3655 binPrms);
3656
3657
3658 /*
3659 * Perform rebinng of spectra and associated errors...
3660 */
3661
3662 wavelengths = cpl_matrix_new(rbsize, 1);
3663
3664 for (i = 0; i < rbsize; i++) {
3665 cpl_matrix_set(wavelengths, i, 0, wlmin + (cxdouble) i * rbstep);
3666 }
3667
3668 rbspectra = giraffe_image_create(CPL_TYPE_DOUBLE, nspectra, rbsize);
3669 _rbspectra = giraffe_image_get(rbspectra);
3670
3671 if (_exerrors != NULL) {
3672 rberrors = giraffe_image_create(CPL_TYPE_DOUBLE, nspectra, rbsize);
3673 _rberrors = giraffe_image_get(rberrors);
3674 }
3675
3676 switch (method) {
3677 case GIREBIN_METHOD_LINEAR:
3678 status = _giraffe_resample_linear(_rbspectra, _rberrors, abscissa,
3679 _exspectra, _exerrors, om_sign);
3680 break;
3681
3682 case GIREBIN_METHOD_SPLINE:
3683 status = _giraffe_resample_spline(_rbspectra, _rberrors, abscissa,
3684 _exspectra, _exerrors, om_sign);
3685 break;
3686
3687 default:
3688
3689 /* We should never get to this point! */
3690
3691 gi_error("Invalid rebinning method!");
3692 break;
3693 }
3694
3695 cpl_image_delete(abscissa);
3696 abscissa = NULL;
3697
3698 if (status != 0) {
3699 cpl_msg_error(fctid, "Error during rebinning, aborting...");
3700
3701 cpl_matrix_delete(wavelengths);
3702 wavelengths = NULL;
3703
3704 giraffe_image_delete(rbspectra);
3705 rbspectra = NULL;
3706
3707 if (rberrors != NULL) {
3708 giraffe_image_delete(rberrors);
3709 rberrors = NULL;
3710 }
3711
3712 return 3;
3713 }
3714
3715
3716
3717 /*
3718 * Add calculated image, keywords etc. to rebinned spectrum frame...
3719 */
3720
3721 switch (scale) {
3722 case GIREBIN_SCALE_LOG:
3723 {
3724 cxsize nw = cpl_matrix_get_nrow(wavelengths);
3725
3726 cxdouble mm2nm = log(GI_MM_TO_NM);
3727
3728 setup.wmin = mm2nm + cpl_matrix_get(wavelengths, 0, 0);
3729 setup.wcenter = mm2nm + cpl_matrix_get(wavelengths, nw / 2, 0);
3730 setup.wmax = mm2nm + cpl_matrix_get(wavelengths, nw - 1, 0);
3731 setup.wstep = rbstep;
3732
3733 setup.units = "log(nm)";
3734 setup.offset = 0;
3735 }
3736 break;
3737
3738 case GIREBIN_SCALE_LINEAR:
3739 {
3740 cxsize nw = cpl_matrix_get_nrow(wavelengths);
3741
3742 setup.wmin = GI_MM_TO_NM * cpl_matrix_get(wavelengths, 0, 0);
3743 setup.wcenter = GI_MM_TO_NM * cpl_matrix_get(wavelengths,
3744 nw / 2, 0);
3745 setup.wmax = GI_MM_TO_NM * cpl_matrix_get(wavelengths,
3746 nw - 1, 0);
3747 setup.wstep = GI_MM_TO_NM * rbstep;
3748
3749 setup.units = "nm";
3750 setup.offset = 0;
3751 }
3752 break;
3753
3754 default:
3755
3756 /* We should never get here */
3757
3758 gi_error("Invalid scaling option!");
3759 break;
3760 }
3761
3762 cpl_matrix_delete(wavelengths);
3763 wavelengths = NULL;
3764
3765
3766 switch (method) {
3767 case GIREBIN_METHOD_LINEAR:
3768 setup.method = "linear";
3769 break;
3770
3771 case GIREBIN_METHOD_SPLINE:
3772 setup.method = "spline";
3773 break;
3774
3775 default:
3776
3777 /* We should never get here */
3778
3779 gi_error("Invalid rebinning method!");
3780 break;
3781 }
3782
3783
3784 switch (scale) {
3785 case GIREBIN_SCALE_LINEAR:
3786 setup.scale = "linear";
3787 break;
3788
3789 case GIREBIN_SCALE_LOG:
3790 setup.scale = "logarithmic";
3791 break;
3792
3793 default:
3794
3795 /* We should never get here */
3796
3797 gi_error("Invalid scaling option!");
3798 break;
3799 }
3800
3801 switch (range) {
3802 case GIREBIN_RANGE_SETUP:
3803 setup.range = "setup";
3804 break;
3805
3806 case GIREBIN_RANGE_COMMON:
3807 setup.range = "common";
3808 break;
3809
3810 default:
3811
3812 /* We should never get here */
3813
3814 gi_error("Invalid range option!");
3815 break;
3816 }
3817
3818
3819 /*
3820 * Finalize resampled spectra
3821 */
3822
3823 giraffe_error_push();
3824
3825 properties = giraffe_image_get_properties(extraction->spectra);
3826 giraffe_image_set_properties(rbspectra, properties);
3827
3828 if (cpl_error_get_code() != CPL_ERROR_NONE) {
3829 giraffe_image_delete(rbspectra);
3830 rbspectra = NULL;
3831
3832 if (rberrors != NULL) {
3833 giraffe_image_delete(rberrors);
3834 rberrors = NULL;
3835 }
3836
3837 return 4;
3838 }
3839
3840 giraffe_error_pop();
3841
3842 status = _giraffe_resample_update_properties(rbspectra, &setup);
3843
3844 if (status != 0) {
3845 giraffe_image_delete(rbspectra);
3846 rbspectra = NULL;
3847
3848 if (rberrors != NULL) {
3849 giraffe_image_delete(rberrors);
3850 rberrors = NULL;
3851 }
3852
3853 return 4;
3854 }
3855
3856
3857 /*
3858 * Finalize resampled spectra errors if they are available
3859 */
3860
3861 if (_rberrors != NULL) {
3862
3863 giraffe_error_push();
3864
3865 properties = giraffe_image_get_properties(extraction->error);
3866 giraffe_image_set_properties(rberrors, properties);
3867
3868 if (cpl_error_get_code() != CPL_ERROR_NONE) {
3869 giraffe_image_delete(rbspectra);
3870 rbspectra = NULL;
3871
3872 if (rberrors != NULL) {
3873 giraffe_image_delete(rberrors);
3874 rberrors = NULL;
3875 }
3876
3877 return 5;
3878 }
3879
3880 giraffe_error_pop();
3881
3882 status = _giraffe_resample_update_properties(rberrors, &setup);
3883
3884 if (status != 0) {
3885 giraffe_image_delete(rbspectra);
3886 rbspectra = NULL;
3887
3888 if (rberrors != NULL) {
3889 giraffe_image_delete(rberrors);
3890 rberrors = NULL;
3891 }
3892
3893 return 5;
3894 }
3895
3896 }
3897
3898 result->spectra = rbspectra;
3899 result->errors = rberrors;
3900
3901 return 0;
3902
3903}
3904
3905
3913GiRange *
3914giraffe_rebin_get_wavelength_range(GiImage *spectra, GiTable *wlsolution,
3915 GiTable *grating, GiTable *slitgeometry,
3916 cxbool common)
3917{
3918
3919 cxint status = 0;
3920
3921 cxdouble min = 0.;
3922 cxdouble max = 0.;
3923
3924 cpl_matrix *optical_model = NULL;
3925 cpl_matrix *grating_data = NULL;
3926
3927 GiFiberPosition *positions = NULL;
3928 GiSlitGeo *subslits = NULL;
3929
3930 GiWcalSolution *wcal = NULL;
3931
3932 GiRange *range = NULL;
3933
3934
3935 if (spectra == NULL) {
3936 return NULL;
3937 }
3938
3939 if (grating == NULL) {
3940 return NULL;
3941 }
3942
3943 if (slitgeometry == NULL) {
3944 return NULL;
3945 }
3946
3947
3948 wcal = _giraffe_wcalsolution_create(wlsolution);
3949
3950 if (wcal == NULL) {
3951 return NULL;
3952 }
3953
3954 optical_model = _giraffe_rebin_setup_model(spectra, wcal);
3955
3956 if (optical_model == NULL) {
3957 _giraffe_wcalsolution_delete(wcal);
3958 return NULL;
3959 }
3960
3961 _giraffe_wcalsolution_delete(wcal);
3962
3963 grating_data = _giraffe_rebin_setup_grating(spectra, grating,
3964 wlsolution);
3965
3966 if (grating_data == NULL) {
3967
3968 cpl_matrix_delete(grating_data);
3969 cpl_matrix_delete(optical_model);
3970
3971 return NULL;
3972
3973 }
3974
3975 positions = _giraffe_fiberposition_new();
3976 subslits = _giraffe_slitgeo_new();
3977
3978 status = _giraffe_slitgeo_setup(slitgeometry, positions, subslits,
3979 FALSE);
3980
3981 if (status != 0) {
3982
3983 _giraffe_slitgeo_delete(subslits);
3984 _giraffe_fiberposition_delete(positions);
3985
3986 cpl_matrix_delete(grating_data);
3987 cpl_matrix_delete(optical_model);
3988
3989 return NULL;
3990
3991 }
3992
3993 status = giraffe_rebin_compute_lambda_range(positions, optical_model,
3994 grating_data,
3995 GIREBIN_SCALE_LINEAR,
3996 common, &min, &max);
3997
3998 /*
3999 * Convert wavelength from millimeters to nanometers.
4000 */
4001
4002 min *= GI_MM_TO_NM;
4003 max *= GI_MM_TO_NM;
4004
4005 _giraffe_slitgeo_delete(subslits);
4006 _giraffe_fiberposition_delete(positions);
4007
4008 cpl_matrix_delete(grating_data);
4009 cpl_matrix_delete(optical_model);
4010
4011 range = giraffe_range_create(min, max);
4012
4013 return range;
4014
4015}
4016
4017
4051cxint
4052giraffe_rebin_spectra(GiRebinning *rebinning,
4053 const GiExtraction *extraction,
4054 const GiTable *fibers,
4055 const GiLocalization *localization,
4056 const GiTable *grating,
4057 const GiTable *slitgeo,
4058 const GiTable *solution,
4059 const GiRebinConfig *config)
4060{
4061
4062 const cxchar* const fctid = "giraffe_rebin_spectra";
4063
4064
4065 cxint status = 0;
4066 cxint ex_sp_extr_pixels = 0;
4067 cxint calc_rebinned_size = 0;
4068 cxint default_rebinned_size = GIREBIN_SIZE_Y_DEFAULT;
4069
4070 cxdouble rbin_multiplier = 0.;
4071 cxdouble ex_sp_pixsize_x = 0.;
4072 cxdouble rbin_stepsize = 0.;
4073
4074 cpl_matrix* grat_params = NULL;
4075 cpl_matrix* opt_mod_params = NULL;
4076 cpl_matrix* wloffsets = NULL;
4077
4078 cpl_table* _fibers = NULL;
4079
4080 cpl_propertylist* _pl_ext_sp = NULL;
4081 cpl_propertylist* _pl_wsol = NULL;
4082
4083 GiImage* ex_sp_frame = NULL;
4084 /*GiImage* ex_sp_err_frame = NULL;*/
4085 /*GiImage* loc_y_frame = NULL;*/
4086 /*GiImage* loc_w_frame = NULL;*/
4087
4088 GiSlitGeo* subslit_fibers = NULL;
4089 GiSlitGeo* wav_coeffs = NULL;
4090 GiSlitGeo* wav_limits = NULL;
4091
4092 GiGrat* grating_data = NULL;
4093
4094 GiFiberPosition* fiber_slit_position = NULL;
4095
4096 GiWcalSolution* wcalib_solution = NULL;
4097
4098 GiBinnParams xres_polynom_deg = {0, 0};
4099
4100
4101
4102 /*
4103 * Preprocessing
4104 */
4105
4106 if (extraction == NULL) {
4107 cpl_msg_error(fctid, "No extracted data, aborting...");
4108 return 1;
4109 }
4110
4111 if (extraction->spectra == NULL) {
4112 cpl_msg_error(fctid, "No extracted spectra, aborting...");
4113 return 1;
4114 }
4115
4116 if (fibers == NULL) {
4117 cpl_msg_error(fctid, "No fiber table, aborting ...");
4118 return 1;
4119 }
4120
4121 if (localization == NULL) {
4122 cpl_msg_error(fctid, "No localization data, aborting...");
4123 return 1;
4124 }
4125
4126 if (localization->locy == NULL) {
4127 cpl_msg_error(fctid, "No localization centroids, aborting...");
4128 return 1;
4129 }
4130
4131 if (localization->locw == NULL) {
4132 cpl_msg_error(fctid, "No localization widths, aborting...");
4133 return 1;
4134 }
4135
4136 if (grating == NULL) {
4137 cpl_msg_error(fctid, "No grating data, aborting...");
4138 return 1;
4139 }
4140
4141 if (rebinning == NULL) {
4142 cpl_msg_error(fctid, "No rebinning results container, aborting...");
4143 return 1;
4144 }
4145
4146 if (config == NULL) {
4147 cpl_msg_error(fctid, "No rebinning configuration data, aborting...");
4148 return 1;
4149 }
4150
4151 if (solution == NULL) {
4152 cpl_msg_error(fctid, "No wavecalibration solution, aborting...");
4153 return 1;
4154 }
4155
4156 ex_sp_frame = extraction->spectra;
4157 /*ex_sp_err_frame = extraction->error;*/
4158 /*loc_y_frame = localization->locy;*/
4159 /*loc_w_frame = localization->locw;*/
4160
4161 _pl_ext_sp = giraffe_image_get_properties(ex_sp_frame);
4162 _pl_wsol = giraffe_table_get_properties(solution);
4163
4164
4165 _fibers = giraffe_table_get(fibers);
4166 cx_assert(_fibers != NULL);
4167
4168
4169
4170 /*
4171 * Initialization
4172 */
4173
4174 /*
4175 * Retrieve necessary values from FITS keywords
4176 */
4177
4178 if (cpl_propertylist_has(_pl_ext_sp, GIALIAS_PIXSIZX) == TRUE) {
4179 ex_sp_pixsize_x = cpl_propertylist_get_double(_pl_ext_sp,
4180 GIALIAS_PIXSIZX);
4181
4182 }
4183 else {
4184 cpl_msg_error(fctid, "%s Keyword missing in Extracted Spectra "
4185 "Frame, aborting ...", GIALIAS_PIXSIZX);
4186 return 2;
4187 }
4188
4189
4190 /*
4191 * Convert pixel size to microns
4192 */
4193
4194 if (ex_sp_pixsize_x > 1.) {
4195 ex_sp_pixsize_x /= 1000.;
4196 }
4197
4198
4199 /*
4200 * Determine rebinning step size multiplier
4201 */
4202
4203 if (cpl_propertylist_has(_pl_ext_sp, GIALIAS_GRATNAME) == TRUE) {
4204
4205 const cxchar* _string = NULL;
4206
4207 _string = cpl_propertylist_get_string(_pl_ext_sp, GIALIAS_GRATNAME);
4208
4209 if (strncmp(_string, "LR", 2) == 0) {
4210 rbin_multiplier = 4.;
4211 }
4212 else if (strncmp(_string, "HR", 2) == 0) {
4213 rbin_multiplier = 1.;
4214 }
4215 else {
4216 rbin_multiplier = 1.;
4217 }
4218
4219 }
4220 else {
4221 cpl_msg_error(fctid, "%s Keyword missing in Extracted Spectra Frame, "
4222 "aborting ...", GIALIAS_GRATNAME);
4223 return 2;
4224 }
4225
4226
4227 /*
4228 * find number of pixel per spectrum
4229 */
4230
4231 if (cpl_propertylist_has(_pl_ext_sp, GIALIAS_EXT_NX) == TRUE) {
4232 ex_sp_extr_pixels = cpl_propertylist_get_int(_pl_ext_sp,
4233 GIALIAS_EXT_NX);
4234
4235 }
4236 else {
4237 cpl_msg_error(fctid, "%s Keyword missing in Extracted Spectra Frame, "
4238 "aborting ...", GIALIAS_EXT_NX);
4239 return 2;
4240 }
4241
4242
4243 /*
4244 * Retrieve Grating information
4245 */
4246
4247 grating_data = _giraffe_grating_new();
4248
4249 status = _giraffe_grating_setup(grating, ex_sp_frame, grating_data);
4250
4251 if (status != 0) {
4252 cpl_msg_error(fctid, "Unable to retrieve grating information, "
4253 "aborting...");
4254 _giraffe_grating_delete(grating_data);
4255 return 3;
4256 }
4257
4258 /*
4259 * Retrieve Slit Geometry Information
4260 */
4261
4262 fiber_slit_position = _giraffe_fiberposition_new();
4263 subslit_fibers = _giraffe_slitgeo_new();
4264
4265 status = _giraffe_slitgeo_setup(slitgeo, fiber_slit_position,
4266 subslit_fibers, FALSE);
4267
4268 if (status != 0) {
4269 cpl_msg_error(fctid, "Unable to retrieve slit geometry information, "
4270 "aborting...");
4271 _giraffe_grating_delete(grating_data);
4272 _giraffe_fiberposition_delete(fiber_slit_position);
4273 _giraffe_slitgeo_delete(subslit_fibers);
4274 return 7;
4275 }
4276
4277
4278 wcalib_solution = _giraffe_wcalsolution_create(solution);
4279
4280 if (wcalib_solution == NULL) {
4281 cpl_msg_error(fctid, "Cannot create wavelength solution, "
4282 "aborting ...");
4283 _giraffe_grating_delete(grating_data);
4284 _giraffe_fiberposition_delete(fiber_slit_position);
4285 _giraffe_slitgeo_delete(subslit_fibers);
4286 return 4;
4287 }
4288
4289 if (cpl_propertylist_has(_pl_wsol, GIALIAS_WSOL_OMFCOLL) == TRUE) {
4290 grating_data->fcoll =
4291 cpl_propertylist_get_double(_pl_wsol, GIALIAS_WSOL_OMFCOLL);
4292 }
4293
4294 if (cpl_propertylist_has(_pl_wsol, GIALIAS_WSOL_OMGCAM) == TRUE) {
4295 grating_data->gcam =
4296 cpl_propertylist_get_double(_pl_wsol, GIALIAS_WSOL_OMGCAM);
4297 }
4298
4299 if (cpl_propertylist_has(_pl_wsol, GIALIAS_WSOL_OMGTHETA) == TRUE) {
4300 grating_data->theta =
4301 cpl_propertylist_get_double(_pl_wsol, GIALIAS_WSOL_OMGTHETA);
4302 }
4303
4304 if (cpl_propertylist_has(_pl_wsol, GIALIAS_WSOL_OMSDX) == TRUE) {
4305 grating_data->slitdx =
4306 cpl_propertylist_get_double(_pl_wsol, GIALIAS_WSOL_OMSDX);
4307 }
4308
4309 if (cpl_propertylist_has(_pl_wsol, GIALIAS_WSOL_OMSDY) == TRUE) {
4310 grating_data->slitdy =
4311 cpl_propertylist_get_double(_pl_wsol, GIALIAS_WSOL_OMSDY);
4312 }
4313
4314 if (cpl_propertylist_has(_pl_wsol, GIALIAS_WSOL_OMSPHI) == TRUE) {
4315 grating_data->slitphi =
4316 cpl_propertylist_get_double(_pl_wsol, GIALIAS_WSOL_OMSPHI);
4317 }
4318
4319
4320 /*
4321 * If wavelength corrections were provided, convert the wavelength
4322 * offsets from nanometers to millimeters and store them as a
4323 * matrix (nfibers x 1).
4324 */
4325
4326 if (cpl_table_has_column(_fibers, "WLRES") != 0) {
4327
4328 cxint fiber = 0;
4329 cxint nfibers = cpl_table_get_nrow(_fibers);
4330
4331
4332 wloffsets = cpl_matrix_new(nfibers, 1);
4333
4334 for (fiber = 0; fiber < nfibers; ++fiber) {
4335
4336 cxdouble wloffset = cpl_table_get_double(_fibers, "WLRES",
4337 fiber, NULL);
4338
4339
4340 wloffset *= -GI_NM_TO_MM;
4341 cpl_matrix_set(wloffsets, fiber, 0, wloffset);
4342
4343 }
4344
4345 cpl_msg_info(fctid, "Applying SIMCAL wavelength corrections ...");
4346
4347 }
4348
4349
4350
4351 /*
4352 * Processing
4353 */
4354
4355
4356 /*
4357 * Determine rebinning stepsize and size in y direction after rebinning
4358 */
4359
4360 if (config->scmethod == GIREBIN_SCALE_LOG) {
4361
4362 cxint rebin_size;
4363
4364 cxdouble wlenmax;
4365 cxdouble wlenmin;
4366
4367 rebin_size = default_rebinned_size;
4368
4369 wlenmin = log(grating_data->wlenmin / GI_MM_TO_NM);
4370 wlenmax = log(grating_data->wlenmax / GI_MM_TO_NM);
4371
4372 if ((config->size != rebin_size) && (config->size != 0)) {
4373 rebin_size = config->size;
4374 }
4375
4376 rbin_stepsize = (wlenmax - wlenmin) / rebin_size;
4377
4378 calc_rebinned_size = 1 + (cxint) ((wlenmax-wlenmin)/ rbin_stepsize);
4379
4380 }
4381 else {
4382
4383 cxint rebin_size;
4384
4385 cxdouble wlenmax;
4386 cxdouble wlenmin;
4387
4388 wlenmin = grating_data->wlenmin / GI_MM_TO_NM;
4389 wlenmax = grating_data->wlenmax / GI_MM_TO_NM;
4390
4391 rbin_stepsize = (config->lstep / GI_MM_TO_NM) * rbin_multiplier;
4392 rebin_size = (wlenmax - wlenmin) / rbin_stepsize;
4393
4394 if ((config->size != rebin_size) && (config->size != 0)) {
4395 rebin_size = config->size;
4396 rbin_stepsize = (wlenmax - wlenmin) / rebin_size;
4397 }
4398
4399 calc_rebinned_size = 1 + (cxint) ((wlenmax-wlenmin) / rbin_stepsize);
4400
4401 }
4402
4403 /*
4404 * Retrieve Wavecalibration Solution Physical Optical Paramters
4405 */
4406
4407 if (wcalib_solution!=NULL) {
4408
4409 if (wcalib_solution->opt_mod==LMRQ_XOPTMOD) {
4410
4411 cxint nrow;
4412 cxdouble opt_direction, fcoll, cfact;
4413
4414 nrow = cpl_matrix_get_nrow(wcalib_solution->opt_mod_params);
4415 if (nrow==4) {
4416 opt_direction =
4417 cpl_matrix_get(wcalib_solution->opt_mod_params, 0, 0);
4418 fcoll =
4419 cpl_matrix_get(wcalib_solution->opt_mod_params, 1, 0);
4420 cfact =
4421 cpl_matrix_get(wcalib_solution->opt_mod_params, 2, 0);
4422
4423 opt_mod_params = cpl_matrix_new(4,1);
4424 cpl_matrix_set(opt_mod_params, 0, 0,
4425 ex_sp_extr_pixels * opt_direction);
4426 cpl_matrix_set(opt_mod_params, 1, 0, ex_sp_pixsize_x);
4427 cpl_matrix_set(opt_mod_params, 2, 0, fcoll);
4428 cpl_matrix_set(opt_mod_params, 3, 0, cfact);
4429 }
4430 else {
4431 cpl_msg_error(fctid, "Invalid number of physical optical "
4432 "parameters, aborting...");
4433
4434 if (wloffsets != NULL) {
4435 cpl_matrix_delete(wloffsets);
4436 }
4437
4438 _giraffe_wcalsolution_delete(wcalib_solution);
4439 _giraffe_grating_delete(grating_data);
4440 _giraffe_fiberposition_delete(fiber_slit_position);
4441 _giraffe_slitgeo_delete(subslit_fibers);
4442 return 6;
4443 }
4444
4445 }
4446 else if (wcalib_solution->opt_mod==LMRQ_XOPTMOD2) {
4447
4448 cxint nrow;
4449 cxdouble opt_direction, fcoll, cfact, /*gtheta,*/ slitdx,
4450 slitdy, slitphi;
4451
4452 nrow = cpl_matrix_get_nrow(wcalib_solution->opt_mod_params);
4453 if (nrow==7) {
4454 opt_direction =
4455 cpl_matrix_get(wcalib_solution->opt_mod_params, 0, 0);
4456 fcoll =
4457 cpl_matrix_get(wcalib_solution->opt_mod_params, 1, 0);
4458 cfact =
4459 cpl_matrix_get(wcalib_solution->opt_mod_params, 2, 0);
4460 /*gtheta =
4461 cpl_matrix_get(wcalib_solution->opt_mod_params, 3, 0);*/
4462 slitdx =
4463 cpl_matrix_get(wcalib_solution->opt_mod_params, 4, 0);
4464 slitdy =
4465 cpl_matrix_get(wcalib_solution->opt_mod_params, 5, 0);
4466 slitphi =
4467 cpl_matrix_get(wcalib_solution->opt_mod_params, 6, 0);
4468
4469 opt_mod_params = cpl_matrix_new(7,1);
4470 cpl_matrix_set(opt_mod_params, 0, 0,
4471 ex_sp_extr_pixels * opt_direction);
4472 cpl_matrix_set(opt_mod_params, 1, 0, ex_sp_pixsize_x);
4473 cpl_matrix_set(opt_mod_params, 2, 0, fcoll);
4474 cpl_matrix_set(opt_mod_params, 3, 0, cfact);
4475 cpl_matrix_set(opt_mod_params, 4, 0, slitdx);
4476 cpl_matrix_set(opt_mod_params, 5, 0, slitdy);
4477 cpl_matrix_set(opt_mod_params, 6, 0, slitphi);
4478
4479 }
4480 else {
4481 cpl_msg_error(fctid, "Invalid number of physical optical "
4482 "parameters, aborting...");
4483
4484 if (wloffsets != NULL) {
4485 cpl_matrix_delete(wloffsets);
4486 }
4487
4488 _giraffe_wcalsolution_delete(wcalib_solution);
4489 _giraffe_grating_delete(grating_data);
4490 _giraffe_fiberposition_delete(fiber_slit_position);
4491 _giraffe_slitgeo_delete(subslit_fibers);
4492 return 6;
4493 }
4494
4495 }
4496 else {
4497 cpl_msg_error(fctid, "Invalid optical model, aborting...");
4498
4499 if (wloffsets != NULL) {
4500 cpl_matrix_delete(wloffsets);
4501 }
4502
4503 _giraffe_wcalsolution_delete(wcalib_solution);
4504 _giraffe_grating_delete(grating_data);
4505 _giraffe_fiberposition_delete(fiber_slit_position);
4506 _giraffe_slitgeo_delete(subslit_fibers);
4507 return 5;
4508 }
4509
4510
4511 if (wcalib_solution->wav_coeffs != NULL) {
4512
4513 GiSlitGeo* coeffs = wcalib_solution->wav_coeffs;
4514
4515 xres_polynom_deg.xdeg =
4516 cpl_matrix_get_nrow(_giraffe_slitgeo_get(coeffs, 0));
4517 xres_polynom_deg.ydeg =
4518 cpl_matrix_get_ncol(_giraffe_slitgeo_get(coeffs, 0));
4519 }
4520
4521 }
4522 else {
4523 cpl_msg_error(fctid, "No Wavelength Calibration solution found, "
4524 "aborting...");
4525
4526 if (wloffsets != NULL) {
4527 cpl_matrix_delete(wloffsets);
4528 }
4529
4530 _giraffe_wcalsolution_delete(wcalib_solution);
4531 _giraffe_grating_delete(grating_data);
4532 _giraffe_fiberposition_delete(fiber_slit_position);
4533 _giraffe_slitgeo_delete(subslit_fibers);
4534 return 4;
4535 }
4536
4537 if (config->xresiduals==FALSE) {
4538 xres_polynom_deg.xdeg = 0;
4539 xres_polynom_deg.ydeg = 0;
4540 }
4541
4542 if (wcalib_solution->wav_coeffs!=NULL) {
4543 wav_coeffs = wcalib_solution->wav_coeffs;
4544 }
4545
4546 if (wcalib_solution->wav_limits!=NULL) {
4547 wav_limits = wcalib_solution->wav_limits;
4548 }
4549
4550
4551 /*
4552 * Setup Rebinning grating parameters
4553 */
4554
4555 grat_params = cpl_matrix_new(7,1);
4556
4557 cpl_matrix_set(grat_params, 0, 0, grating_data->theta);
4558 cpl_matrix_set(grat_params, 1, 0, grating_data->order);
4559 cpl_matrix_set(grat_params, 2, 0, grating_data->wlenmin / GI_MM_TO_NM);
4560 cpl_matrix_set(grat_params, 3, 0, grating_data->wlen0 / GI_MM_TO_NM);
4561 cpl_matrix_set(grat_params, 4, 0, grating_data->wlenmax / GI_MM_TO_NM);
4562 cpl_matrix_set(grat_params, 5, 0, grating_data->resol);
4563 cpl_matrix_set(grat_params, 6, 0, grating_data->space );
4564
4565
4566 /*
4567 * Give user some feedback...
4568 */
4569
4570 cpl_msg_info(fctid, "Performing Rebinning of spectra, stepsize=%.4f "
4571 "[nm], resulting image size=%d, using x residuals : %s",
4572 rbin_stepsize * GI_MM_TO_NM, calc_rebinned_size,
4573 config->xresiduals ? "Yes" : "No");
4574
4575
4576 switch (config->rmethod) {
4577 case GIREBIN_METHOD_LINEAR:
4578 cpl_msg_info(fctid, "Rebinning method : linear");
4579 break;
4580
4581 case GIREBIN_METHOD_SPLINE:
4582 cpl_msg_info(fctid, "Rebinning method : spline");
4583 break;
4584
4585 default:
4586 cpl_msg_info(fctid, "Rebinning method : undefined");
4587 break;
4588 }
4589
4590 switch (config->scmethod) {
4591 case GIREBIN_SCALE_LOG:
4592 cpl_msg_info(fctid, "Scaling method : logarithmic, "
4593 "log(wavelength [nm]): min,max,range = %.3f, %.3f, %.3f",
4594 log(grating_data->wlenmin),
4595 log(grating_data->wlenmax),
4596 log(grating_data->wlenmax) -
4597 log(grating_data->wlenmin));
4598 break;
4599
4600 case GIREBIN_SCALE_LINEAR:
4601 cpl_msg_info(fctid, "Scaling method : linear, wavelength [nm]: "
4602 "min,max,range = %.3f, %.3f, %.3f",
4603 grating_data->wlenmin,
4604 grating_data->wlenmax,
4605 grating_data->wlenmax - grating_data->wlenmin);
4606 break;
4607
4608 default:
4609 cpl_msg_info(fctid, "Scaling method : undefined");
4610 break;
4611 }
4612
4613 switch (config->range) {
4614 case GIREBIN_RANGE_SETUP:
4615 cpl_msg_info(fctid, "Wavelength range : Setup");
4616 break;
4617
4618 case GIREBIN_RANGE_COMMON:
4619 cpl_msg_info(fctid, "Wavelength range : Common");
4620 break;
4621
4622 default:
4623 cpl_msg_info(fctid, "Wavelength range : undefined");
4624 break;
4625 }
4626
4627
4628 /*
4629 * Resample the spectra to the wavelength grid
4630 */
4631
4632 status = _giraffe_resample_spectra(rebinning, extraction,
4633 localization, fiber_slit_position,
4634 subslit_fibers, wav_limits,
4635 wav_coeffs, &xres_polynom_deg,
4636 grat_params, opt_mod_params,
4637 wloffsets, rbin_stepsize,
4638 config->rmethod, config->range,
4639 config->scmethod);
4640
4641 if (status != 0) {
4642
4643 if (wloffsets != NULL) {
4644 cpl_matrix_delete(wloffsets);
4645 }
4646
4647 cpl_matrix_delete(opt_mod_params);
4648 cpl_matrix_delete(grat_params);
4649
4650 _giraffe_wcalsolution_delete(wcalib_solution);
4651 _giraffe_grating_delete(grating_data);
4652 _giraffe_fiberposition_delete(fiber_slit_position);
4653 _giraffe_slitgeo_delete(subslit_fibers);
4654
4655 return 8;
4656
4657 }
4658
4659
4660 /*
4661 * Cleanup...
4662 */
4663
4664 if (wloffsets != NULL) {
4665 cpl_matrix_delete(wloffsets);
4666 }
4667
4668 cpl_matrix_delete(opt_mod_params);
4669 cpl_matrix_delete(grat_params);
4670
4671 _giraffe_wcalsolution_delete(wcalib_solution);
4672 _giraffe_grating_delete(grating_data);
4673 _giraffe_fiberposition_delete(fiber_slit_position);
4674 _giraffe_slitgeo_delete(subslit_fibers);
4675
4676 return 0;
4677
4678} /* end giraffe_rebin_spectra() */
4679
4680
4693GiRebinning*
4695{
4696
4697 GiRebinning *rebinn = cx_malloc(sizeof(GiRebinning));
4698
4699 rebinn->spectra = NULL;
4700 rebinn->errors = NULL;
4701
4702 return rebinn;
4703
4704}
4705
4722GiRebinning*
4723giraffe_rebinning_create(GiImage *spectra, GiImage *errors)
4724{
4725
4726 GiRebinning *rebin = giraffe_rebinning_new();
4727
4728 if (spectra) {
4729 rebin->spectra = spectra;
4730 }
4731
4732 if (errors) {
4733 rebin->errors = errors;
4734 }
4735
4736 return rebin;
4737
4738}
4739
4740
4759void
4760giraffe_rebinning_delete(GiRebinning *rebinning)
4761{
4762
4763 if (rebinning) {
4764 cx_free(rebinning);
4765 }
4766
4767 return;
4768
4769}
4770
4771
4787void
4788giraffe_rebinning_destroy(GiRebinning *rebinning)
4789{
4790
4791 if (rebinning) {
4792
4793 if (rebinning->spectra) {
4794 giraffe_image_delete(rebinning->spectra);
4795 rebinning->spectra = NULL;
4796 }
4797
4798 if (rebinning->errors) {
4799 giraffe_image_delete(rebinning->errors);
4800 rebinning->errors = NULL;
4801 }
4802
4803 cx_free(rebinning);
4804 }
4805
4806 return;
4807
4808}
4809
4810
4825GiRebinConfig *
4826giraffe_rebin_config_create(cpl_parameterlist *list)
4827{
4828
4829 const cxchar *fctid = "giraffe_rebin_config_create";
4830
4831 const cxchar *s;
4832
4833 cpl_parameter *p;
4834
4835 GiRebinConfig *config = NULL;
4836
4837
4838 if (!list) {
4839 return NULL;
4840 }
4841
4842 config = cx_calloc(1, sizeof *config);
4843
4844
4845 config->rmethod = GIREBIN_METHOD_UNDEFINED;
4846 config->xresiduals = FALSE;
4847 config->lstep = 0.0;
4848 config->scmethod = GIREBIN_SCALE_UNDEFINED;
4849 config->size = 0;
4850 config->range = GIREBIN_RANGE_UNDEFINED;
4851
4852
4853 p = cpl_parameterlist_find(list, "giraffe.rebinning.method");
4854 s = cpl_parameter_get_string(p);
4855 if (strcmp(s, "linear")==0) {
4856 config->rmethod = GIREBIN_METHOD_LINEAR;
4857 } else if (strcmp(s, "spline")==0) {
4858 config->rmethod = GIREBIN_METHOD_SPLINE;
4859 }
4860
4861 p = cpl_parameterlist_find(list, "giraffe.rebinning.xresiduals");
4862 config->xresiduals = cpl_parameter_get_bool(p);
4863
4864 p = cpl_parameterlist_find(list, "giraffe.rebinning.lstep");
4865 config->lstep = cpl_parameter_get_double(p);
4866
4867 p = cpl_parameterlist_find(list, "giraffe.rebinning.scalemethod");
4868 s = cpl_parameter_get_string(p);
4869 if (strcmp(s, "log")==0) {
4870 config->scmethod = GIREBIN_SCALE_LOG;
4871 } else if (strcmp(s, "linear")==0) {
4872 config->scmethod = GIREBIN_SCALE_LINEAR;
4873 }
4874
4875 p = cpl_parameterlist_find(list, "giraffe.rebinning.size");
4876 config->size = cpl_parameter_get_int(p);
4877
4878 p = cpl_parameterlist_find(list, "giraffe.rebinning.range");
4879 s = cpl_parameter_get_string(p);
4880 if (strcmp(s, "setup")==0) {
4881 config->range = GIREBIN_RANGE_SETUP;
4882 } else if (strcmp(s, "common")==0) {
4883 config->range = GIREBIN_RANGE_COMMON;
4884 }
4885
4886 /* Validate */
4887
4888 if (config->rmethod==GIREBIN_METHOD_UNDEFINED) {
4889 cpl_msg_info(fctid, "Invalid Rebinning method, aborting");
4890 cx_free(config);
4891 return NULL;
4892 }
4893
4894 if (config->scmethod==GIREBIN_SCALE_UNDEFINED) {
4895 cpl_msg_info(fctid, "Invalid Rebinning scaling method, aborting");
4896 cx_free(config);
4897 return NULL;
4898 }
4899
4900 if (config->range==GIREBIN_RANGE_UNDEFINED) {
4901 cpl_msg_info(fctid, "Invalid Rebinning range, aborting");
4902 cx_free(config);
4903 return NULL;
4904 }
4905
4906 return config;
4907
4908}
4909
4910
4925void
4926giraffe_rebin_config_destroy(GiRebinConfig *config)
4927{
4928
4929 if (config) {
4930 cx_free(config);
4931 }
4932
4933 return;
4934
4935}
4936
4949void
4950giraffe_rebin_config_add(cpl_parameterlist *list)
4951{
4952
4953 cpl_parameter *p;
4954
4955 if (!list) {
4956 return;
4957 }
4958
4959 p = cpl_parameter_new_enum("giraffe.rebinning.method",
4960 CPL_TYPE_STRING,
4961 "Method to use : `linear' or `spline'",
4962 "giraffe.rebinning.method",
4963 "linear", 2, "linear", "spline");
4964 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "rbin-method");
4965 cpl_parameterlist_append(list, p);
4966
4967 p = cpl_parameter_new_value("giraffe.rebinning.xresiduals",
4968 CPL_TYPE_BOOL,
4969 "Use x residuals during rebinning? `true'/"
4970 "`false'",
4971 "giraffe.rebinning.xresiduals",
4972 TRUE);
4973 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "rbin-xresid");
4974 cpl_parameterlist_append(list, p);
4975
4976 p = cpl_parameter_new_value("giraffe.rebinning.lstep",
4977 CPL_TYPE_DOUBLE,
4978 "Lambda step size, only used if "
4979 "scaling method is 'linear'",
4980 "giraffe.rebinning.lstep",
4981 0.005);
4982 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "rbin-lstep");
4983 cpl_parameterlist_append(list, p);
4984
4985 p = cpl_parameter_new_enum("giraffe.rebinning.scalemethod",
4986 CPL_TYPE_STRING,
4987 "Scaling method: `log' or `linear'",
4988 "giraffe.rebinning.scalemethod",
4989 "linear", 2, "linear", "log");
4990 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "rbin-scmethod");
4991 cpl_parameterlist_append(list, p);
4992
4993 p = cpl_parameter_new_value("giraffe.rebinning.size",
4994 CPL_TYPE_INT,
4995 "Size of output rebinned spectra, 0 means "
4996 "calculate size based on wavelength range "
4997 "and lambda stepsize",
4998 "giraffe.rebinning.size",
4999 0);
5000 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "rbin-size");
5001 cpl_parameterlist_append(list, p);
5002
5003 p = cpl_parameter_new_enum("giraffe.rebinning.range",
5004 CPL_TYPE_STRING,
5005 "Rebinning range: `setup' or `common'",
5006 "giraffe.rebinning.scalemethod",
5007 "setup", 2, "setup", "common");
5008 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "rbin-range");
5009 cpl_parameterlist_append(list, p);
5010
5011 return;
5012
5013}
const cxchar * giraffe_fiberlist_query_index(const cpl_table *fibers)
Query a fiber list for the name of the fiber reference index column.
cpl_image * giraffe_image_get(const GiImage *self)
Gets the image data.
Definition: giimage.c:218
cpl_propertylist * giraffe_image_get_properties(const GiImage *self)
Get the properties of an image.
Definition: giimage.c:282
void giraffe_image_delete(GiImage *self)
Destroys an image.
Definition: giimage.c:181
GiImage * giraffe_image_create(cpl_type type, cxint nx, cxint ny)
Creates an image container of a given type.
Definition: giimage.c:95
cxint giraffe_image_set_properties(GiImage *self, cpl_propertylist *properties)
Attaches a property list to an image.
Definition: giimage.c:312
cxint giraffe_matrix_sort(cpl_matrix *mA)
Sort in place the matrix elements in ascending order.
Definition: gimatrix.c:380
void gi_error(const cxchar *format,...)
Log an error message.
Definition: gimessages.c:59
GiRange * giraffe_range_create(cxdouble min, cxdouble max)
Creates a new range from the given minimum and maximum values.
Definition: girange.c:83
GiRange * giraffe_rebin_get_wavelength_range(GiImage *spectra, GiTable *wlsolution, GiTable *grating, GiTable *slitgeometry, cxbool common)
Compute the wavelenght range of spectra.
Definition: girebinning.c:3914
GiRebinning * giraffe_rebinning_create(GiImage *spectra, GiImage *errors)
Fills a rebinning results container.
Definition: girebinning.c:4723
void giraffe_rebin_config_destroy(GiRebinConfig *config)
Destroys a spectrum extraction setup structure.
Definition: girebinning.c:4926
cxint giraffe_rebin_spectra(GiRebinning *rebinning, const GiExtraction *extraction, const GiTable *fibers, const GiLocalization *localization, const GiTable *grating, const GiTable *slitgeo, const GiTable *solution, const GiRebinConfig *config)
Rebin an Extracted Spectra Frame and associated Errors Frame.
Definition: girebinning.c:4052
void giraffe_rebinning_delete(GiRebinning *rebinning)
Destroys a rebinning results container.
Definition: girebinning.c:4760
GiRebinConfig * giraffe_rebin_config_create(cpl_parameterlist *list)
Creates a setup structure for the rebinning.
Definition: girebinning.c:4826
GiRebinning * giraffe_rebinning_new(void)
Create an empty rebinning results container.
Definition: girebinning.c:4694
void giraffe_rebinning_destroy(GiRebinning *rebinning)
Destroys a rebinning results container and its contents.
Definition: girebinning.c:4788
void giraffe_rebin_config_add(cpl_parameterlist *list)
Adds parameters for the rebinning.
Definition: girebinning.c:4950
cpl_table * giraffe_table_get(const GiTable *self)
Get the table data from a Giraffe table.
Definition: gitable.c:433
cpl_propertylist * giraffe_table_get_properties(const GiTable *self)
Gets the table properties.
Definition: gitable.c:489
GiInstrumentMode giraffe_get_mode(cpl_propertylist *properties)
Determines the instrument mode from a property list.
Definition: giutils.c:444
struct definition to handle model functions
Definition: gimath_lm.h:138
fitted_func cfunc
Definition: gimath_lm.h:140
cxint ninputs
Definition: gimath_lm.h:142
cxint nparams
Definition: gimath_lm.h:141

This file is part of the GIRAFFE Pipeline Reference Manual 2.19.4.
Documentation copyright © 2002-2006 European Southern Observatory.
Generated on Fri Feb 6 2026 13:47:23 by doxygen 1.9.6 written by Dimitri van Heesch, © 1997-2004