GIRAFFE Pipeline Reference Manual

giwlsolution.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 <stdlib.h>
33 #include <math.h>
34 
35 #include <cxmap.h>
36 #include <cxstring.h>
37 #include <cxstrutils.h>
38 
39 #include <cpl_error.h>
40 #include <cpl_propertylist.h>
41 
42 #include "gialias.h"
43 #include "gierror.h"
44 #include "giimage.h"
45 #include "gitable.h"
46 #include "gichebyshev.h"
47 #include "giwlsolution.h"
48 
49 
58 struct GiWlSolution {
59 
60  GiModel *model;
61 
62  cxbool subslits;
63  GiWlResiduals *residuals;
64 
65 };
66 
67 
68 inline static GiWlSolution *
69 _giraffe_wlsolution_new(const cxchar *name)
70 {
71 
72  GiWlSolution *self = cx_calloc(1, sizeof *self);
73 
74 
75  if (self) {
76 
77  self->model = giraffe_model_new(name);
78 
79  if (self->model == NULL) {
80  giraffe_wlsolution_delete(self);
81  return NULL;
82  }
83 
84  if (giraffe_model_get_type(self->model) != GI_MODEL_XOPT) {
85  giraffe_wlsolution_delete(self);
86  return NULL;
87  }
88 
89  self->subslits = FALSE;
90  self->residuals = NULL;
91 
92  }
93 
94  return self;
95 
96 }
97 
98 
99 GiWlSolution *
100 giraffe_wlsolution_new(const cxchar *name, cxint orientation, cxint npixels,
101  cxdouble pixelsize, GiGrating *grating)
102 {
103 
104  GiWlSolution *self = NULL;
105 
106 
107  if (name == NULL) {
108  return self;
109  }
110 
111  if (grating == NULL) {
112  return self;
113  }
114 
115 
116  self = _giraffe_wlsolution_new(name);
117 
118  if (self) {
119 
120  orientation = orientation < 0 ? -npixels : npixels;
121  pixelsize /= 1000.;
122 
123  giraffe_error_push();
124 
125  giraffe_model_set_parameter(self->model, "Orientation",
126  orientation);
127  giraffe_model_set_parameter(self->model, "Order",
128  grating->order);
129  giraffe_model_set_parameter(self->model, "PixelSize",
130  pixelsize);
131  giraffe_model_set_parameter(self->model, "FocalLength",
132  grating->fcoll);
133  giraffe_model_set_parameter(self->model, "Magnification",
134  grating->gcam);
135  giraffe_model_set_parameter(self->model, "Angle",
136  grating->theta);
137  giraffe_model_set_parameter(self->model, "Spacing",
138  grating->space);
139 
140  if (strcmp(name, "xoptmod2") == 0) {
141 
142  giraffe_model_set_parameter(self->model, "Sdx", grating->sdx);
143  giraffe_model_set_parameter(self->model, "Sdy", grating->sdy);
144  giraffe_model_set_parameter(self->model, "Sphi", grating->sphi);
145 
146  }
147 
148  if (cpl_error_get_code() != CPL_ERROR_NONE) {
149  giraffe_wlsolution_delete(self);
150  return NULL;
151  }
152 
153  giraffe_error_pop();
154 
155  }
156 
157  return self;
158 
159 }
160 
161 
175 GiWlSolution *
176 giraffe_wlsolution_clone(const GiWlSolution *other)
177 {
178 
179  GiWlSolution *self = NULL;
180 
181 
182  if (other != NULL) {
183 
184  self = cx_calloc(1, sizeof(GiWlSolution));
185 
186  self->model = giraffe_model_clone(other->model);
187 
188  self->subslits = other->subslits;
189  self->residuals = giraffe_wlresiduals_clone(other->residuals);
190 
191  }
192 
193  return self;
194 
195 }
196 
197 
213 GiWlSolution *
214 giraffe_wlsolution_create(GiTable *solution, GiImage *spectra,
215  GiGrating *grating)
216 {
217 
218  const cxchar *name = NULL;
219 
220  cxint npixels = 0;
221  cxint orientation = 0;
222 
223  cxdouble pixelsize = 0.;
224  cxdouble fcoll = 0.;
225  cxdouble gcam = 0.;
226  cxdouble theta = 0.;
227  cxdouble sdx = 0.;
228  cxdouble sdy = 0.;
229  cxdouble sphi = 0.;
230 
231 
232  cpl_propertylist *properties = NULL;
233 
234  GiWlSolution *self = NULL;
235 
236 
237 
238  if (solution == NULL) {
239  return NULL;
240  }
241 
242  if (giraffe_table_get_properties(solution) == NULL) {
243  return NULL;
244  }
245 
246  if (giraffe_table_get(solution) == NULL) {
247  return NULL;
248  }
249 
250 
251  if (spectra == NULL) {
252  return NULL;
253  }
254 
255  if (giraffe_image_get_properties(spectra) == NULL) {
256  return NULL;
257  }
258 
259  if (giraffe_image_get(spectra) == NULL) {
260  return NULL;
261  }
262 
263 
264  if (grating == NULL) {
265  return NULL;
266  }
267 
268 
269  /*
270  * Setup the optical model from the wavelength solution table properties,
271  * the grating setup and the reference spectrum.
272  */
273 
274  /*
275  * Reference image: number of pixels and pixel size
276  */
277 
278  properties = giraffe_image_get_properties(spectra);
279 
280  if (!cpl_propertylist_has(properties, GIALIAS_PIXSIZX)) {
281  return NULL;
282  }
283  else {
284 
285  /*
286  * Get pixel size and convert it from microns to mm.
287  */
288 
289  pixelsize = cpl_propertylist_get_double(properties, GIALIAS_PIXSIZX);
290  pixelsize /= 1000.;
291 
292  }
293 
294  npixels = cpl_image_get_size_y(giraffe_image_get(spectra));
295 
296 
297  /*
298  * Wavelength solution properties: orientation, collimator focal
299  * length, camera magnification, grating angle and slit offsets.
300  */
301 
302  properties = giraffe_table_get_properties(solution);
303 
304 
305  if (!cpl_propertylist_has(properties, GIALIAS_WSOL_OMNAME)) {
306  return NULL;
307  }
308  else {
309  name = cpl_propertylist_get_string(properties, GIALIAS_WSOL_OMNAME);
310  }
311 
312 
313  self = _giraffe_wlsolution_new(name);
314 
315  if (self) {
316 
317  if (!cpl_propertylist_has(properties, GIALIAS_WSOL_SUBSLITS)) {
318  giraffe_wlsolution_delete(self);
319  return NULL;
320  }
321  else {
322 
323  self->subslits = cpl_propertylist_get_bool(properties,
324  GIALIAS_WSOL_SUBSLITS);
325 
326  }
327 
328  if (!cpl_propertylist_has(properties, GIALIAS_WSOL_OMDIR)) {
329  giraffe_wlsolution_delete(self);
330  return NULL;
331  }
332  else {
333  orientation = cpl_propertylist_get_int(properties,
334  GIALIAS_WSOL_OMDIR);
335  orientation = orientation < 0 ? -fabs(npixels) : fabs(npixels);
336  }
337 
338 
339  if (!cpl_propertylist_has(properties, GIALIAS_WSOL_OMFCOLL)) {
340  giraffe_wlsolution_delete(self);
341  return NULL;
342  }
343  else {
344  fcoll = cpl_propertylist_get_double(properties,
345  GIALIAS_WSOL_OMFCOLL);
346  }
347 
348 
349  if (!cpl_propertylist_has(properties, GIALIAS_WSOL_OMGCAM)) {
350  giraffe_wlsolution_delete(self);
351  return NULL;
352  }
353  else {
354  gcam = cpl_propertylist_get_double(properties,
355  GIALIAS_WSOL_OMGCAM);
356  }
357 
358 
359  if (!cpl_propertylist_has(properties, GIALIAS_WSOL_OMGTHETA)) {
360  giraffe_wlsolution_delete(self);
361  return NULL;
362  }
363  else {
364  theta = cpl_propertylist_get_double(properties,
365  GIALIAS_WSOL_OMGTHETA);
366  }
367 
368 
369  if (strcmp(name, "xoptmod2") == 0) {
370 
371  if (!cpl_propertylist_has(properties, GIALIAS_WSOL_OMSDX)) {
372  giraffe_wlsolution_delete(self);
373  return NULL;
374  }
375  else {
376  sdx = cpl_propertylist_get_double(properties,
377  GIALIAS_WSOL_OMSDX);
378  }
379 
380 
381  if (!cpl_propertylist_has(properties, GIALIAS_WSOL_OMSDY)) {
382  giraffe_wlsolution_delete(self);
383  return NULL;
384  }
385  else {
386  sdy = cpl_propertylist_get_double(properties,
387  GIALIAS_WSOL_OMSDY);
388  }
389 
390 
391  if (!cpl_propertylist_has(properties, GIALIAS_WSOL_OMSPHI)) {
392  giraffe_wlsolution_delete(self);
393  return NULL;
394  }
395  else {
396  sphi = cpl_propertylist_get_double(properties,
397  GIALIAS_WSOL_OMSPHI);
398  }
399 
400  }
401 
402 
403  /*
404  * Initialize the optical model parameters
405  */
406 
407  giraffe_error_push();
408 
409  giraffe_model_set_parameter(self->model, "Orientation", orientation);
410  giraffe_model_set_parameter(self->model, "Order", grating->order);
411  giraffe_model_set_parameter(self->model, "PixelSize", pixelsize);
412  giraffe_model_set_parameter(self->model, "FocalLength", fcoll);
413  giraffe_model_set_parameter(self->model, "Magnification", gcam);
414  giraffe_model_set_parameter(self->model, "Angle", theta);
415  giraffe_model_set_parameter(self->model, "Spacing", grating->space);
416 
417  if (strcmp(name, "xoptmod2") == 0) {
418  giraffe_model_set_parameter(self->model, "Sdx", sdx);
419  giraffe_model_set_parameter(self->model, "Sdy", sdy);
420  giraffe_model_set_parameter(self->model, "Sphi", sphi);
421  }
422 
423  if (cpl_error_get_code() != CPL_ERROR_NONE) {
424  giraffe_wlsolution_delete(self);
425  return NULL;
426  }
427 
428  giraffe_error_pop();
429 
430 
431  /*
432  * Get the wavelength residuals fit coefficients from the wavelength
433  * solution table.
434  */
435 
436  self->residuals = giraffe_wlresiduals_create(solution);
437 
438  if (self->residuals == NULL) {
439  self->subslits = FALSE;
440  }
441 
442  }
443 
444  return self;
445 
446 }
447 
448 
449 void
450 giraffe_wlsolution_delete(GiWlSolution *self)
451 {
452 
453  if (self != NULL) {
454 
455  if (self->model != NULL) {
456  giraffe_model_delete(self->model);
457  }
458 
459  if (self->residuals != NULL) {
460  giraffe_wlresiduals_delete(self->residuals);
461  }
462 
463  cx_free(self);
464 
465  }
466 
467  return;
468 
469 }
470 
471 
472 const cxchar *
473 giraffe_wlsolution_name(const GiWlSolution *self)
474 {
475 
476  GiModel *model = NULL;
477 
478 
479  cx_assert(self != NULL);
480 
481  model = self->model;
482  cx_assert(model != NULL);
483 
484  return giraffe_model_get_name(model);
485 
486 }
487 
488 
489 GiModel *
490 giraffe_wlsolution_model(const GiWlSolution *self)
491 {
492 
493  cx_assert(self != NULL);
494 
495  return self->model;
496 
497 }
498 
499 
500 cxint
501 giraffe_wlsolution_set_subslits(GiWlSolution *self, cxbool flag)
502 {
503 
504  cx_assert(self != NULL);
505 
506  if (self->residuals != NULL) {
507  return 1;
508  }
509 
510  self->subslits = flag;
511 
512  return 0;
513 
514 }
515 
516 
517 cxbool
518 giraffe_wlsolution_get_subslits(const GiWlSolution *self)
519 {
520 
521  cx_assert(self != NULL);
522 
523  return self->subslits;
524 
525 }
526 
527 
528 cxint
529 giraffe_wlsolution_set_residuals(GiWlSolution *self,
530  const GiWlResiduals *residuals)
531 {
532 
533  cxbool subslits = FALSE;
534 
535 
536  cx_assert(self != NULL);
537 
538  if (residuals == NULL) {
539  return 1;
540  }
541 
542 
543  /* FIXME: This is a very weak check whether the residuals to accept
544  * are valid for the current subslits flag setting. A better
545  * mechanism needs to be put here, but this needs to be supported
546  * by the GiWlResidual class.
547  */
548 
549  subslits = giraffe_wlresiduals_get(residuals, 0) == NULL;
550 
551  if (self->subslits != subslits) {
552  return 2;
553  }
554 
555  giraffe_wlsolution_reset_residuals(self);
556 
557  self->residuals = (GiWlResiduals *)residuals;
558 
559  return 0;
560 
561 }
562 
563 
564 GiWlResiduals *
565 giraffe_wlsolution_get_residuals(const GiWlSolution *self)
566 {
567 
568  cx_assert(self != NULL);
569 
570  return self->residuals;
571 
572 }
573 
574 
575 void
576 giraffe_wlsolution_reset_residuals(GiWlSolution *self)
577 {
578 
579  cx_assert(self != NULL);
580 
581  if (self->residuals != NULL) {
582  giraffe_wlresiduals_delete(self->residuals);
583  self->residuals = NULL;
584  }
585 
586  return;
587 
588 }
589 
590 
591 cxdouble
592 giraffe_wlsolution_compute_pixel(const GiWlSolution *self, cxdouble lambda,
593  cxdouble x, cxdouble y, cxint *status)
594 {
595 
596  cxint code = 0;
597  cxint _status = 0;
598 
599  cxdouble result = 0.;
600 
601 
602  cx_assert(self != NULL);
603 
604  giraffe_error_push();
605 
606  giraffe_model_set_argument(self->model, "xf", x);
607  giraffe_model_set_argument(self->model, "yf", y);
608  giraffe_model_set_argument(self->model, "lambda", lambda);
609 
610  if (cpl_error_get_code() != CPL_ERROR_NONE) {
611 
612  if (status != NULL) {
613  *status = -128;
614  }
615 
616  return result;
617  }
618 
619  giraffe_error_pop();
620 
621  code = giraffe_model_evaluate(self->model, &result, &_status);
622 
623  if (code != 0) {
624 
625  if (status != NULL) {
626  *status = -128;
627  }
628 
629  return result;
630 
631  }
632 
633  if (status != NULL) {
634  *status = _status;
635  }
636 
637  return result;
638 
639 }
640 
641 
642 cxdouble
643 giraffe_wlsolution_compute_residual(const GiWlSolution *self, cxdouble x,
644  cxdouble y)
645 {
646 
647  cxint i;
648 
649  cxdouble r = 0.;
650 
651  const GiWlResiduals *residuals = NULL;
652 
653 
654  cx_assert(self != NULL);
655 
656  residuals = giraffe_wlsolution_get_residuals(self);
657 
658  if (residuals == NULL) {
659  return r;
660  }
661 
662 
663  /*
664  * Find first residual fit with matching ranges. This is used
665  * for the residual computation assuming that the intervals
666  * for which the fits are valid do not overlap.
667  */
668 
669  for (i = 0; (cxsize)i < giraffe_wlresiduals_get_size(residuals); i++) {
670 
671  const GiChebyshev2D *fit = giraffe_wlresiduals_get(residuals, i);
672 
673  if (fit != NULL) {
674 
675  cxdouble ax;
676  cxdouble bx;
677  cxdouble ay;
678  cxdouble by;
679 
680  giraffe_chebyshev2d_get_range(fit, &ax, &bx, &ay, &by);
681 
682  if (ax <= x && x <= bx && ay <= y && y <= by) {
683  r = giraffe_chebyshev2d_eval(fit, x, y);
684  break;
685  }
686 
687  }
688 
689  }
690 
691  return r;
692 
693 }
694 
695 
696 GiTable *
697 giraffe_wlsolution_create_table(const GiWlSolution *solution)
698 {
699 
700 
701  cxint sign = 1;
702 
703  cxdouble value = 0.;
704 
705  cpl_propertylist *properties = NULL;
706 
707  GiTable *result = NULL;
708 
709  const GiModel *model = NULL;
710 
711  const GiWlResiduals *residuals = NULL;
712 
713 
714  if (solution == NULL) {
715  return NULL;
716  }
717 
718 
719  result = giraffe_table_new();
720  cx_assert(result != NULL);
721 
722  properties = cpl_propertylist_new();
723  cx_assert(properties != NULL);
724 
725 
726  /*
727  * Build up wavelength solution properties
728  */
729 
730  cpl_propertylist_update_string(properties, GIALIAS_GIRFTYPE,
731  "WLSOLUTION");
732  cpl_propertylist_set_comment(properties, GIALIAS_GIRFTYPE,
733  "Giraffe frame type.");
734 
735  cpl_propertylist_update_string(properties, GIALIAS_WSOL_OMNAME,
736  giraffe_wlsolution_name(solution));
737  cpl_propertylist_set_comment(properties, GIALIAS_WSOL_OMNAME,
738  "Optical model name");
739 
740  model = giraffe_wlsolution_model(solution);
741 
742  sign = giraffe_model_get_parameter(model,"Orientation") < 0 ? -1 : 1;
743  cpl_propertylist_update_int(properties, GIALIAS_WSOL_OMDIR, sign);
744  cpl_propertylist_set_comment(properties, GIALIAS_WSOL_OMDIR,
745  "Optical model orientation");
746 
747  value = giraffe_model_get_parameter(model, "FocalLength");
748  cpl_propertylist_update_double(properties, GIALIAS_WSOL_OMFCOLL, value);
749  cpl_propertylist_set_comment(properties, GIALIAS_WSOL_OMFCOLL,
750  "Optical model focal length");
751 
752  value = giraffe_model_get_parameter(model, "Magnification");
753  cpl_propertylist_update_double(properties, GIALIAS_WSOL_OMGCAM, value);
754  cpl_propertylist_set_comment(properties, GIALIAS_WSOL_OMGCAM,
755  "Optical model camera factor");
756 
757  value = giraffe_model_get_parameter(model, "Angle");
758  cpl_propertylist_update_double(properties, GIALIAS_WSOL_OMGTHETA,
759  value);
760  cpl_propertylist_set_comment(properties, GIALIAS_WSOL_OMGTHETA,
761  "Optical model grating angle");
762 
763  if (strcmp(giraffe_wlsolution_name(solution), "xoptmod2") == 0) {
764 
765  value = giraffe_model_get_parameter(model, "Sdx");
766  cpl_propertylist_update_double(properties, GIALIAS_WSOL_OMSDX,
767  value);
768  cpl_propertylist_set_comment(properties, GIALIAS_WSOL_OMSDX,
769  "Optical model slit x-offset");
770 
771  value = giraffe_model_get_parameter(model, "Sdy");
772  cpl_propertylist_update_double(properties, GIALIAS_WSOL_OMSDY,
773  value);
774  cpl_propertylist_set_comment(properties, GIALIAS_WSOL_OMSDY,
775  "Optical model slit y-offset");
776 
777  value = giraffe_model_get_parameter(model, "Sphi");
778  cpl_propertylist_update_double(properties, GIALIAS_WSOL_OMSPHI,
779  value);
780  cpl_propertylist_set_comment(properties, GIALIAS_WSOL_OMSPHI,
781  "Optical model slit rotation");
782 
783  }
784 
785 
786  /*
787  * Add optical model residuals fit coefficients, if they are present
788  * in the wavelength solution.
789  */
790 
791  residuals = giraffe_wlsolution_get_residuals(solution);
792 
793  if (residuals != NULL) {
794 
795  cpl_table *coeffs = giraffe_wlresiduals_table(residuals);
796 
797  if (coeffs != NULL) {
798  giraffe_table_set(result, coeffs);
799  }
800 
801  }
802 
803  giraffe_table_set_properties(result, properties);
804 
805  cpl_propertylist_delete(properties);
806  properties = NULL;
807 
808  return result;
809 
810 }

This file is part of the GIRAFFE Pipeline Reference Manual 2.12.
Documentation copyright © 2002-2006 European Southern Observatory.
Generated on Mon Mar 24 2014 11:43:53 by doxygen 1.8.2 written by Dimitri van Heesch, © 1997-2004