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