GIRAFFE Pipeline Reference Manual

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

This file is part of the GIRAFFE Pipeline Reference Manual 2.14.
Documentation copyright © 2002-2006 European Southern Observatory.
Generated on Wed Mar 11 2015 13:19:42 by doxygen 1.8.9.1 written by Dimitri van Heesch, © 1997-2004