CR2RE Pipeline Reference Manual 1.6.2
cr2res_pol.c
1/*
2 * This file is part of the CR2RES Pipeline
3 * Copyright (C) 2002,2003 European Southern Observatory
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02111-1307 USA
18 */
19
20#ifdef HAVE_CONFIG_H
21#include <config.h>
22#endif
23
24/*-----------------------------------------------------------------------------
25 Includes
26 -----------------------------------------------------------------------------*/
27
28#include <string.h>
29#include <math.h>
30#include <cpl.h>
31
32#include "cr2res_pol.h"
33#include "cr2res_dfs.h"
34#include "cr2res_calib.h"
35#include "cr2res_trace.h"
36#include "cr2res_pfits.h"
37
38/*-----------------------------------------------------------------------------
39 Defines
40 -----------------------------------------------------------------------------*/
41
42int cr2res_pol_resample(cpl_vector ** intens,
43 cpl_vector ** wl,
44 cpl_vector ** errors,
45 int n,
46 cpl_vector ** xmin,
47 cpl_vector ** xmax);
48
49#define CR2RES_POL_MODE_1U "1u"
50#define CR2RES_POL_MODE_1D "1d"
51#define CR2RES_POL_MODE_2U "2u"
52#define CR2RES_POL_MODE_2D "2d"
53#define CR2RES_POL_MODE_3U "3u"
54#define CR2RES_POL_MODE_3D "3d"
55#define CR2RES_POL_MODE_4U "4u"
56#define CR2RES_POL_MODE_4D "4d"
57#define CR2RES_POL_MODE_ERROR "??"
58
59#define CR2RES_POL_MODE(n) \
60 (((n) == 0) ? CR2RES_POL_MODE_1U : \
61 (((n) == 1) ? CR2RES_POL_MODE_1D : \
62 (((n) == 2) ? CR2RES_POL_MODE_2U : \
63 (((n) == 3) ? CR2RES_POL_MODE_2D : \
64 (((n) == 4) ? CR2RES_POL_MODE_3U : \
65 (((n) == 5) ? CR2RES_POL_MODE_3D : \
66 (((n) == 6) ? CR2RES_POL_MODE_4U : \
67 (((n) == 7) ? CR2RES_POL_MODE_4D : \
68 CR2RES_POL_MODE_ERROR \
69 ))))))))
70
71/*-----------------------------------------------------------------------------
72 Functions prototypes
73 -----------------------------------------------------------------------------*/
74
75/*----------------------------------------------------------------------------*/
79/*----------------------------------------------------------------------------*/
80
83/* TODO demod functions : rebin all 8 vectors to the same wl */
84/* --> wl[0] as reference */
85/*----------------------------------------------------------------------------*/
105/*----------------------------------------------------------------------------*/
107 cpl_vector ** intens,
108 cpl_vector ** wl,
109 cpl_vector ** errors,
110 int n)
111{
112 cpl_bivector * result;
113 cpl_vector * outspec;
114 cpl_vector * outerr;
115 cpl_size size;
116 cpl_vector * xmin, * xmax;
117
118 cpl_vector ** intens_local;
119 cpl_vector ** errors_local;
120 cpl_vector ** wl_local;
121 cpl_size i, j;
122
123 /* Check entries */
124 if (intens == NULL || wl == NULL || errors == NULL) return NULL;
125 if (n != 8) {
126 cpl_msg_error(__func__,
127 "Demodulation fail: Got %i spectra, but expected 8!", n);
128 return NULL;
129 }
130
131 if (intens[0]== NULL) {
132 cpl_msg_error(__func__,
133 "Demodulation fail: Spectrum %s is missing", CR2RES_POL_MODE(0));
134 return NULL;
135 }
136 size = cpl_vector_get_size(intens[0]);
137 for (i = 0; i < n; i++) {
138 if (intens[i] == NULL) {
139 cpl_msg_error(__func__,
140 "Demodulation fail: Spectrum %s is missing", CR2RES_POL_MODE(i));
141 return NULL;
142 }
143 if (wl[i] == NULL) {
144 cpl_msg_error(__func__,
145 "Demodulation fail: Wavelength %s is missing", CR2RES_POL_MODE(i));
146 return NULL;
147 }
148 if (errors[i] == NULL) {
149 cpl_msg_error(__func__,
150 "Demodulation fail: Errors %s are missing", CR2RES_POL_MODE(i));
151 return NULL;
152 }
153 if (cpl_vector_get_size(intens[i]) != size) {
154 cpl_msg_error(__func__, "Spectra have different sizes");
155 return NULL;
156 }
157 if (cpl_vector_get_size(wl[i]) != size) {
158 cpl_msg_error(__func__, "Wavelengths have different sizes");
159 return NULL;
160 }
161 if (cpl_vector_get_size(errors[i]) != size) {
162 cpl_msg_error(__func__, "Errors have different sizes");
163 return NULL;
164 }
165 }
166
167 // Resample to common wavelength grid
168 // This modifies intens and errors, so we should copy them first
169 intens_local = cpl_malloc(n * sizeof(cpl_vector*));
170 errors_local = cpl_malloc(n * sizeof(cpl_vector*));
171 wl_local = cpl_malloc(n * sizeof(cpl_vector*));
172 for (i = 0; i < n; i++){
173 intens_local[i] = cpl_vector_duplicate(intens[i]);
174 errors_local[i] = cpl_vector_duplicate(errors[i]);
175 wl_local[i] = cpl_vector_duplicate(wl[i]);
176 }
177 xmin = cpl_vector_new(n);
178 xmax = cpl_vector_new(n);
179 if (cr2res_pol_resample(intens_local, wl_local,
180 errors_local, n, &xmin, &xmax) == -1){
181 cpl_msg_error(__func__,
182 "Could not resample polarimetry spectra to the same wavelength scale");
183 for (i = 0; i < n; i++)
184 {
185 cpl_vector_delete(intens_local[i]);
186 cpl_vector_delete(errors_local[i]);
187 cpl_vector_delete(wl_local[i]);
188 }
189 cpl_free(intens_local);
190 cpl_free(errors_local);
191 cpl_free(wl_local);
192 cpl_vector_delete(xmin);
193 cpl_vector_delete(xmax);
194 return NULL;
195 }
196
197 result = cpl_bivector_new(size);
198 outspec = cpl_bivector_get_x(result);
199 outerr = cpl_bivector_get_y(result);
200
201 // Initialize to 0
202 for (i = 0; i < size; i++)
203 {
204 cpl_vector_set(outspec, i, 0.);
205 cpl_vector_set(outerr, i, 0.);
206 }
207
208 for (i = cpl_vector_get_max(xmin);
209 i < cpl_vector_get_min(xmax) + 1; i++){
210 double r, s, e;
211 // Calculate R
212 r = cpl_vector_get(intens_local[0], i); // 1u
213 r /= cpl_vector_get(intens_local[2], i); // 2u
214 r *= cpl_vector_get(intens_local[3], i); // 2d
215 r /= cpl_vector_get(intens_local[1], i); // 1d
216 r *= cpl_vector_get(intens_local[5], i); // 3d
217 r /= cpl_vector_get(intens_local[7], i); // 4d
218 r *= cpl_vector_get(intens_local[6], i); // 4u
219 r /= cpl_vector_get(intens_local[4], i); // 3u
220 r = pow(r, 0.25); // 0.25 = 2/n
221
222 // Calculate Spectrum
223 s = (r - 1) / (r + 1);
224
225 // Calculate Error
226 // sum((err / spec)**2)
227 e = 0;
228 for (j = 0; j < n; j++) {
229 double tmp;
230 tmp = cpl_vector_get(errors_local[j], i) /
231 cpl_vector_get(intens_local[j], i);
232 e += tmp * tmp;
233 }
234
235 // 0.5 * R / (R+1)**2 * sqrt(err)
236 e = sqrt(e);
237 e *= 0.5 * r / ((r + 1) * (r + 1));
238
239 cpl_vector_set(outspec, i, s);
240 cpl_vector_set(outerr, i, e);
241 }
242
243 // We need to remove pointless values outside the wavelength overlap
244 for (j = 0; j < cpl_vector_get_max(xmin); j++)
245 {
246 cpl_vector_set(outspec, j, NAN);
247 cpl_vector_set(outerr, j, NAN);
248 }
249 for (j = cpl_vector_get_min(xmax) + 1; j < size; j++)
250 {
251 cpl_vector_set(outspec, j, NAN);
252 cpl_vector_set(outerr, j, NAN);
253 }
254
255 for (i = 0; i < n; i++){
256 cpl_vector_delete(intens_local[i]);
257 cpl_vector_delete(errors_local[i]);
258 cpl_vector_delete(wl_local[i]);
259 }
260 cpl_free(intens_local);
261 cpl_free(errors_local);
262 cpl_free(wl_local);
263 cpl_vector_delete(xmin);
264 cpl_vector_delete(xmax);
265
266 if (cpl_error_get_code() != CPL_ERROR_NONE) {
267 cpl_msg_error(__func__, "Error message: %s", cpl_error_get_message());
268 cpl_bivector_delete(result);
269 cpl_error_reset();
270 return NULL;
271 }
272
273 return result;
274}
275
276/*----------------------------------------------------------------------------*/
288/*----------------------------------------------------------------------------*/
289int cr2res_pol_resample(cpl_vector ** intens,
290 cpl_vector ** wl,
291 cpl_vector ** errors,
292 int n,
293 cpl_vector ** xmin,
294 cpl_vector ** xmax)
295{
296 // TODO: Use some other grid as baseline?
297 double wmin, wmax;
298 cpl_vector * master_wl;
299 cpl_size i, j, m;
300
301 // Construct master_wl
302 // so that we only include points from within ALL wavelength ranges
303 master_wl = cpl_vector_duplicate(wl[0]);
304 wmin = -INFINITY;
305 wmax = INFINITY;
306 for (i = 0; i < n; i++)
307 {
308 if (cpl_vector_get(wl[i], 0) > wmin){
309 wmin = cpl_vector_get(wl[i], 0);
310 }
311 if (cpl_vector_get(wl[i], cpl_vector_get_size(wl[i]) - 1) < wmax){
312 wmax = cpl_vector_get(wl[i], cpl_vector_get_size(wl[i]) - 1);
313 }
314 }
315
316 for (i = 0; i < n; i++){
317 cpl_vector_set(*xmin, i, 0);
318 cpl_vector_set(*xmax, i, cpl_vector_get_size(wl[i]) - 1);
319
320 for (j = 0; j < cpl_vector_get_size(wl[i]); j++){
321 if (cpl_vector_get(wl[i], j) >= wmin){
322 cpl_vector_set(*xmin, i, j);
323 break;
324 }
325 }
326
327 for (j = cpl_vector_get_size(wl[i]) - 1; j >= 0; j--){
328 if (cpl_vector_get(wl[i], j) <= wmax){
329 cpl_vector_set(*xmax, i, j);
330 break;
331 }
332 }
333 }
334
335 // We need to limit master_wl to the valid range, since bivector interpolate
336 // does not extrapolate at all, but gives an error (?)
337 m = cpl_vector_get_size(wl[0]);
338 for (i = 0; i < m; i++)
339 {
340 if (cpl_vector_get(master_wl, i) < wmin){
341 cpl_vector_set(master_wl, i, wmin);
342 } else if (cpl_vector_get(master_wl, i) > wmax){
343 cpl_vector_set(master_wl, i, wmax);
344 }
345 }
346
347 // Do we need to copy the arrays before interpolation
348 // or does it work in place?
349 for (i = 0; i < n; i++) {
350 cpl_bivector *tmp;
351 cpl_bivector *target;
352 tmp = cpl_bivector_wrap_vectors(wl[i], intens[i]);
353 target = cpl_bivector_wrap_vectors(master_wl, intens[i]);
354 cpl_bivector_interpolate_linear(target, tmp);
355 cpl_bivector_unwrap_vectors(tmp);
356 cpl_bivector_unwrap_vectors(target);
357
358 tmp = cpl_bivector_wrap_vectors(wl[i], errors[i]);
359 target = cpl_bivector_wrap_vectors(master_wl, errors[i]);
360 cpl_bivector_interpolate_linear(target, tmp);
361 cpl_bivector_unwrap_vectors(tmp);
362 cpl_bivector_unwrap_vectors(target);
363
364 // We copy the wavelength here, even though it is currently noy used in
365 // the rest of the code
366 cpl_vector_copy(wl[i], master_wl);
367
368 for (j = 0; j < cpl_vector_get(*xmin, i); j++) {
369 cpl_vector_set(intens[i], j, 1);
370 cpl_vector_set(errors[i], j, 1);
371 }
372 for (j = cpl_vector_get(*xmax, i) + 1; j < cpl_vector_get_size(intens[i]);
373 j++) {
374 cpl_vector_set(intens[i], j, 1);
375 cpl_vector_set(errors[i], j, 1);
376 }
377 }
378
379 cpl_vector_delete(master_wl);
380
381 return 0;
382}
383
409/*----------------------------------------------------------------------------*/
411 cpl_vector ** intens,
412 cpl_vector ** wl,
413 cpl_vector ** errors,
414 int n)
415{
416 cpl_vector ** swapintens;
417 cpl_vector ** swapwl;
418 cpl_vector ** swaperrors;
419 cpl_vector * tmpintens;
420 cpl_vector * tmpwl;
421 cpl_vector * tmperrors;
422 cpl_bivector * out ;
423 cpl_size size;
424 int i;
425
426 /* Check entries */
427 if (intens == NULL || wl == NULL || errors == NULL) return NULL;
428 if (n != 8) {
429 cpl_msg_error(__func__,
430 "Demodulation fail: Got %i spectra, but expected 8!", n);
431 return NULL;
432 }
433
434 if (intens[0]== NULL) {
435 cpl_msg_error(__func__,
436 "Demodulation fail: Spectrum %s is missing", CR2RES_POL_MODE(0));
437 return NULL;
438 }
439 size = cpl_vector_get_size(intens[0]);
440 for (i = 0; i < n; i++) {
441 if (intens[i] == NULL) {
442 cpl_msg_error(__func__,
443 "Demodulation fail: Spectrum %s is missing", CR2RES_POL_MODE(i));
444 return NULL;
445 }
446 if (wl[i] == NULL) {
447 cpl_msg_error(__func__,
448 "Demodulation fail: Wavelength %s is missing", CR2RES_POL_MODE(i));
449 return NULL;
450 }
451 if (errors[i] == NULL) {
452 cpl_msg_error(__func__,
453 "Demodulation fail: Errors %s are missing", CR2RES_POL_MODE(i));
454 return NULL;
455 }
456 if (cpl_vector_get_size(intens[i]) != size) {
457 cpl_msg_error(__func__, "Spectra have different sizes");
458 return NULL;
459 }
460 if (cpl_vector_get_size(wl[i]) != size) {
461 cpl_msg_error(__func__, "Wavelengths have different sizes");
462 return NULL;
463 }
464 if (cpl_vector_get_size(errors[i]) != size) {
465 cpl_msg_error(__func__, "Errors have different sizes");
466 return NULL;
467 }
468 }
469
470 // copy list to leave original unchanged
471 swapintens = cpl_malloc(n * sizeof(cpl_vector *));
472 swapwl = cpl_malloc(n * sizeof(cpl_vector *));
473 swaperrors = cpl_malloc(n * sizeof(cpl_vector *));
474 for (i=0 ; i<n ; i++) {
475 swapintens[i]=intens[i];
476 swapwl[i]=wl[i];
477 swaperrors[i]=errors[i];
478 }
479
480 // swap index 2 and 3, i.e. 2u and 2d
481 tmpintens = swapintens[2];
482 tmpwl = swapwl[2];
483 tmperrors = swaperrors[2];
484 swapintens[2] = swapintens[3];
485 swapwl[2] = swapwl[3];
486 swaperrors[2] = swaperrors[3];
487 swapintens[3] = tmpintens;
488 swapwl[3] = tmpwl;
489 swaperrors[3] = tmperrors;
490
491 // swap index 7 and 6, i.e. 4d and 4u
492 tmpintens = swapintens[7];
493 tmpwl = swapwl[7];
494 tmperrors = swaperrors[7];
495 swapintens[7] = swapintens[6];
496 swapwl[7] = swapwl[6];
497 swaperrors[7] = swaperrors[6];
498 swapintens[6] = tmpintens;
499 swapwl[6] = tmpwl;
500 swaperrors[6] = tmperrors;
501
502 out = cr2res_pol_demod_stokes(swapintens, swapwl, swaperrors, n);
503
504 cpl_free(swapintens);
505 cpl_free(swapwl);
506 cpl_free(swaperrors);
507
508 return out ;
509}
510
511/*----------------------------------------------------------------------------*/
527/*----------------------------------------------------------------------------*/
529 cpl_vector ** intens,
530 cpl_vector ** wl,
531 cpl_vector ** errors,
532 int n)
533{
534 cpl_bivector * result;
535 cpl_vector * outspec;
536 cpl_vector * outerr;
537 double * pouterr ;
538 cpl_vector * tmp;
539 int ncorrections ;
540 cpl_size size, i;
541 cpl_vector * xmin, * xmax;
542
543 cpl_vector ** intens_local;
544 cpl_vector ** errors_local;
545 cpl_vector ** wl_local;
546
547 /* Check entries */
548 if (intens == NULL || wl == NULL || errors == NULL) return NULL;
549 if (n != 8) {
550 cpl_msg_error(__func__,
551 "Demodulation fail: Got %i spectra, but expected 8!", n);
552 return NULL;
553 }
554
555 if (intens[0]== NULL) {
556 cpl_msg_error(__func__,
557 "Demodulation fail: Spectrum %s is missing", CR2RES_POL_MODE(0));
558 return NULL;
559 }
560 size = cpl_vector_get_size(intens[0]);
561 for (i = 0; i < n; i++) {
562 if (intens[i] == NULL) {
563 cpl_msg_error(__func__,
564 "Demodulation fail: Spectrum %s is missing", CR2RES_POL_MODE(i));
565 return NULL;
566 }
567 if (wl[i] == NULL) {
568 cpl_msg_error(__func__,
569 "Demodulation fail: Wavelength %s is missing", CR2RES_POL_MODE(i));
570 return NULL;
571 }
572 if (errors[i] == NULL) {
573 cpl_msg_error(__func__,
574 "Demodulation fail: Errors %s are missing", CR2RES_POL_MODE(i));
575 return NULL;
576 }
577 if (cpl_vector_get_size(intens[i]) != size) {
578 cpl_msg_error(__func__, "Spectra have different sizes");
579 return NULL;
580 }
581 if (cpl_vector_get_size(wl[i]) != size) {
582 cpl_msg_error(__func__, "Wavelengths have different sizes");
583 return NULL;
584 }
585 if (cpl_vector_get_size(errors[i]) != size) {
586 cpl_msg_error(__func__, "Errors have different sizes");
587 return NULL;
588 }
589 }
590
591 // Resample to common wavelength grid
592 // This modifies intens and errors, so we should copy them first
593 intens_local = cpl_malloc(n * sizeof(cpl_vector*));
594 errors_local = cpl_malloc(n * sizeof(cpl_vector*));
595 wl_local = cpl_malloc(n * sizeof(cpl_vector*));
596 for (i = 0; i < n; i++){
597 intens_local[i] = cpl_vector_duplicate(intens[i]);
598 errors_local[i] = cpl_vector_duplicate(errors[i]);
599 wl_local[i] = cpl_vector_duplicate(wl[i]);
600 }
601 xmin = cpl_vector_new(n);
602 xmax = cpl_vector_new(n);
603
604 if (cr2res_pol_resample(intens_local, wl_local,
605 errors_local, n, &xmin, &xmax) == -1){
606 cpl_msg_error(__func__,
607 "Could not resample polarimetry spectra to the same wavelength scale");
608 for (i = 0; i < n; i++)
609 {
610 cpl_vector_delete(intens_local[i]);
611 cpl_vector_delete(errors_local[i]);
612 cpl_vector_delete(wl_local[i]);
613 }
614 cpl_free(intens_local);
615 cpl_free(errors_local);
616 cpl_free(wl_local);
617 cpl_vector_delete(xmin);
618 cpl_vector_delete(xmax);
619 return NULL;
620 }
621
622 result = cpl_bivector_new(size);
623 outspec = cpl_bivector_get_x(result);
624 outerr = cpl_bivector_get_y(result);
625
626 // Initialize to 0
627 for (i = 0; i < size; i++) {
628 cpl_vector_set(outspec, i, 0.);
629 cpl_vector_set(outerr, i, 0.);
630 }
631
632 /* Allocate */
633 for (i=0 ; i<n ; i++) {
634 if (i==0) {
635 cpl_vector_copy(outspec, intens[i]);
636 cpl_vector_copy(outerr, errors[i]);
637 cpl_vector_power(outerr, 2.0);
638 } else {
639 cpl_vector_add(outspec, intens[i]);
640 tmp = cpl_vector_duplicate(errors[i]);
641 cpl_vector_power(tmp, 2.0);
642 cpl_vector_add(outerr, tmp);
643 cpl_vector_delete(tmp);
644 }
645 }
646
647 /* Clean Errors */
648 ncorrections = 0 ;
649 pouterr = cpl_vector_get_data(outerr) ;
650 for (i=0 ; i<size ; i++) {
651 if (isnan(pouterr[i]) || pouterr[i] < 0.0) {
652 ncorrections++ ;
653 pouterr[i] = 0.0 ;
654 }
655 }
656 if (ncorrections > 20)
657 cpl_msg_warning(__func__,
658 "The Errors vector contained %d negative values",
659 ncorrections) ;
660
661 cpl_vector_power(outerr, 0.5);
662
663 for (i = 0; i < n; i++){
664 cpl_vector_delete(intens_local[i]);
665 cpl_vector_delete(errors_local[i]);
666 cpl_vector_delete(wl_local[i]);
667 }
668 cpl_free(intens_local);
669 cpl_free(errors_local);
670 cpl_free(wl_local);
671 cpl_vector_delete(xmin);
672 cpl_vector_delete(xmax);
673
674 if (cpl_error_get_code() != CPL_ERROR_NONE) {
675 cpl_msg_error(__func__, "Error message: %s", cpl_error_get_message());
676 cpl_bivector_delete(result);
677 cpl_error_reset();
678 return NULL;
679 }
680
681 return result;
682}
683
684/*----------------------------------------------------------------------------*/
695/*----------------------------------------------------------------------------*/
697 int * orders,
698 cpl_vector ** wl,
699 cpl_bivector ** stokes,
700 cpl_bivector ** null,
701 cpl_bivector ** intens,
702 int norders)
703{
704 cpl_table * out ;
705 char * col_name ;
706 const double * px ;
707 const double * py ;
708 int all_null, i, nrows ;
709
710 /* Check entries */
711 if (orders==NULL || wl==NULL || stokes==NULL || null==NULL || intens==NULL)
712 return NULL ;
713
714 /* Check if all bivectors are not null */
715 all_null = 1 ;
716 for (i=0 ; i<norders ; i++)
717 if (wl[i]!=NULL && stokes[i]!=NULL && null[i]!=NULL && intens[i]!=NULL){
718 nrows = cpl_vector_get_size(wl[i]) ;
719 if (cpl_bivector_get_size(stokes[i]) != nrows ||
720 cpl_bivector_get_size(null[i]) != nrows ||
721 cpl_bivector_get_size(intens[i]) != nrows) {
722 cpl_msg_error(__func__, "Invalid Input Sizes") ;
723 return NULL ;
724 }
725 all_null = 0 ;
726 }
727 if (all_null == 1) return NULL ;
728
729 /* Create the table */
730 out = cpl_table_new(nrows);
731 for (i=0 ; i<norders ; i++) {
732 if (wl[i]!=NULL && stokes[i]!=NULL && null[i]!=NULL && intens[i]!=NULL){
733 /* Create POL_WAVELENGTH column */
734 col_name = cr2res_dfs_POL_WAVELENGTH_colname(orders[i]) ;
735 cpl_table_new_column(out, col_name, CPL_TYPE_DOUBLE);
736 cpl_free(col_name) ;
737
738 /* Create POL_STOKES column */
739 col_name = cr2res_dfs_POL_STOKES_colname(orders[i]) ;
740 cpl_table_new_column(out, col_name, CPL_TYPE_DOUBLE);
741 cpl_free(col_name) ;
742
743 /* Create POL_STOKES_ERROR column */
744 col_name = cr2res_dfs_POL_STOKES_ERROR_colname(orders[i]) ;
745 cpl_table_new_column(out, col_name, CPL_TYPE_DOUBLE);
746 cpl_free(col_name) ;
747
748 /* Create POL_NULL column */
749 col_name = cr2res_dfs_POL_NULL_colname(orders[i]) ;
750 cpl_table_new_column(out, col_name, CPL_TYPE_DOUBLE);
751 cpl_free(col_name) ;
752
753 /* Create POL_NULL_ERROR column */
754 col_name = cr2res_dfs_POL_NULL_ERROR_colname(orders[i]) ;
755 cpl_table_new_column(out, col_name, CPL_TYPE_DOUBLE);
756 cpl_free(col_name) ;
757
758 /* Create POL_INTENS column */
759 col_name = cr2res_dfs_POL_INTENS_colname(orders[i]) ;
760 cpl_table_new_column(out, col_name, CPL_TYPE_DOUBLE);
761 cpl_free(col_name) ;
762
763 /* Create POL_INTENS_ERROR column */
764 col_name = cr2res_dfs_POL_INTENS_ERROR_colname(orders[i]) ;
765 cpl_table_new_column(out, col_name, CPL_TYPE_DOUBLE);
766 cpl_free(col_name) ;
767 }
768 }
769 /* Fill the table */
770 for (i=0 ; i<norders ; i++) {
771 if (wl[i]!=NULL && stokes[i]!=NULL && null[i]!=NULL && intens[i]!=NULL){
772 /* Fill POL_WAVELENGTH column */
773 px = cpl_vector_get_data_const(wl[i]) ;
774 col_name = cr2res_dfs_POL_WAVELENGTH_colname(orders[i]) ;
775 cpl_table_copy_data_double(out, col_name, px) ;
776 cpl_free(col_name) ;
777
778 /* Fill POL_STOKES column */
779 px = cpl_bivector_get_x_data_const(stokes[i]) ;
780 col_name = cr2res_dfs_POL_STOKES_colname(orders[i]) ;
781 cpl_table_copy_data_double(out, col_name, px) ;
782 cpl_free(col_name) ;
783 /* Fill POL_STOKES_ERROR column */
784 py = cpl_bivector_get_y_data_const(stokes[i]) ;
785 col_name = cr2res_dfs_POL_STOKES_ERROR_colname(orders[i]) ;
786 cpl_table_copy_data_double(out, col_name, py) ;
787 cpl_free(col_name) ;
788
789 /* Fill POL_NULL column */
790 px = cpl_bivector_get_x_data_const(null[i]) ;
791 col_name = cr2res_dfs_POL_NULL_colname(orders[i]) ;
792 cpl_table_copy_data_double(out, col_name, px) ;
793 cpl_free(col_name) ;
794 /* Fill POL_NULL_ERROR column */
795 py = cpl_bivector_get_y_data_const(null[i]) ;
796 col_name = cr2res_dfs_POL_NULL_ERROR_colname(orders[i]) ;
797 cpl_table_copy_data_double(out, col_name, py) ;
798 cpl_free(col_name) ;
799
800 /* Fill POL_INTENS column */
801 px = cpl_bivector_get_x_data_const(intens[i]) ;
802 col_name = cr2res_dfs_POL_INTENS_colname(orders[i]) ;
803 cpl_table_copy_data_double(out, col_name, px) ;
804 cpl_free(col_name) ;
805 /* Fill POL_INTENS_ERROR column */
806 py = cpl_bivector_get_y_data_const(intens[i]) ;
807 col_name = cr2res_dfs_POL_INTENS_ERROR_colname(orders[i]) ;
808 cpl_table_copy_data_double(out, col_name, py) ;
809 cpl_free(col_name) ;
810 }
811 }
812 return out ;
813}
814
815/*----------------------------------------------------------------------------*/
832/*----------------------------------------------------------------------------*/
834 const cpl_frame * frame1,
835 const cpl_frame * frame2,
836 const cpl_frame * frame3,
837 const cpl_frame * frame4)
838{
839 int * idx_order ;
840 const char * poltype_first ;
841 const char * fname ;
842 cpl_propertylist * pri_head ;
843 const cpl_frame * frames_holder[4] ;
844 int nframes, i ;
845
846 /* Check Inputs */
847 if (frame1 == NULL || frame2 == NULL || frame3 == NULL || frame4 == NULL)
848 return NULL;
849
850 /* Initialise */
851 nframes = 4 ;
852 frames_holder[0] = frame1 ;
853 frames_holder[1] = frame2 ;
854 frames_holder[2] = frame3 ;
855 frames_holder[3] = frame4 ;
856
857 /* Read POL.TYPE */
858 fname = cpl_frame_get_filename(frames_holder[0]);
859 pri_head = cpl_propertylist_load(fname, 0);
860 poltype_first = cr2res_pfits_get_poltype(pri_head);
861 if (cpl_error_get_code()) {
862 cpl_propertylist_delete(pri_head);
863 cpl_msg_error(__func__, "Missing POL.TYPE in header") ;
864 return NULL ;
865 }
866
867 /* Make sure the others are the same */
868 for (i=1 ; i<nframes ; i++) {
869 const char *poltype_curr;
870 cpl_propertylist *tmp_head;
871 fname = cpl_frame_get_filename(frames_holder[i]);
872 tmp_head = cpl_propertylist_load(fname, 0);
873 poltype_curr = cr2res_pfits_get_poltype(tmp_head);
874 if (cpl_error_get_code()) {
875 cpl_propertylist_delete(tmp_head);
876 cpl_propertylist_delete(pri_head);
877 cpl_msg_error(__func__, "Missing POL.TYPE in header") ;
878 return NULL ;
879 }
880 if (strcmp(poltype_first, poltype_curr)) {
881 cpl_msg_error(__func__, "Different POL.TYPE! %s != %s",
882 poltype_first, poltype_curr) ;
883 return NULL ;
884 }
885 cpl_propertylist_delete(tmp_head);
886 }
887
888 idx_order = cpl_malloc(nframes * sizeof(int)) ;
889
890 if (!strcmp(poltype_first, "V")){
891 cpl_msg_info(__func__, "Set up file order for circular pol.");
892 idx_order[0] = 0 ;
893 idx_order[1] = 1 ;
894 idx_order[2] = 2 ;
895 idx_order[3] = 3 ;
896 } else {
897 cpl_msg_info(__func__, "Set up file order for linear pol.");
898 idx_order[0] = 0 ;
899 idx_order[1] = 3 ;
900 idx_order[2] = 2 ;
901 idx_order[3] = 1 ;
902 }
903 cpl_propertylist_delete(pri_head);
904 return idx_order ;
905}
906
907/*----------------------------------------------------------------------------*/
914/*----------------------------------------------------------------------------*/
916 const cpl_table ** pol_spec_list,
917 int pol_spec_nb)
918{
919 int i, j, k;
920 int n_cols, n_rows;
921 cpl_table * merged_table;
922 double sum, avg;
923 cpl_array * column_names_array;
924
925 /* Check Inputs */
926 if (pol_spec_list == NULL || pol_spec_nb <= 0) return NULL;
927 for (i = 0; i < pol_spec_nb; i++)
928 if (pol_spec_list[i] == NULL) return NULL;
929
930 n_cols = cpl_table_get_ncol(pol_spec_list[0]);
931 n_rows = cpl_table_get_nrow(pol_spec_list[0]);
932 merged_table = cpl_table_new(n_rows);
933
934 column_names_array = cpl_table_get_column_names(pol_spec_list[0]);
935
936 for (i = 0; i < n_cols; i++) {
937 const char *col_name = cpl_array_get_string(column_names_array, i);
938 cpl_table_new_column(merged_table, col_name, CPL_TYPE_DOUBLE);
939
940 /* Loop through the rows */
941 for (j = 0; j < n_rows; j++) {
942 sum = 0.0;
943 for (k = 0; k < pol_spec_nb; k++) {
944 sum += cpl_table_get_double(pol_spec_list[k], col_name, j, NULL);
945 }
946 avg = sum / pol_spec_nb;
947 cpl_table_set_double(merged_table, col_name, j, avg);
948 }
949 }
950
951 /* Clean up */
952 cpl_array_delete(column_names_array);
953
954 return merged_table;
955}
956
957/*----------------------------------------------------------------------------*/
968/*----------------------------------------------------------------------------*/
969
971 const cpl_table *tw_in,
972 cr2res_decker decker_position,
973 int up_or_down)
974{
975
976 cpl_table * tw_out = NULL;
977 cpl_polynomial * wl_poly;
978 cpl_polynomial * corr_poly;
979 double wl, y_corr, newSF;
980 cpl_array * tmp_arr;
981 cpl_size pow0=0;
982 cpl_size pow1=1;
983 char * band;
984 int nb_traces, i;
985 cpl_vector * newSFs;
986
987
988 wl_poly = cr2res_get_trace_wave_poly(tw_in, CR2RES_COL_WAVELENGTH, 5, 1);
989 wl = cpl_polynomial_eval_1d(wl_poly, 1024, NULL);
990 cpl_polynomial_delete(wl_poly);
991
992 /* Correction polynomial gets filled with hardcoded values. */
993 /* These were derived as linear difference from the order mid-line */
994 /* for the upper/lower beams and A/B nodding position, in each band.*/
995 corr_poly = cpl_polynomial_new(1);
996 if (wl < 1125) {
997 band=cpl_sprintf("Y");
998 /*
999 'YuA': array([ 0.03988915, -22.78903764]),
1000 'YuB': array([ 0.04808708, 13.12469913]),
1001 'YdA': array([-0.04965059, -6.51155269]),
1002 'YdB': array([-0.04019722, 28.22704312]),
1003 */
1004 if (decker_position == CR2RES_DECKER_2_4){ // nodd A
1005 if (up_or_down == 1){ // UP
1006 cpl_polynomial_set_coeff(corr_poly, &pow0, -22.78903764);
1007 cpl_polynomial_set_coeff(corr_poly, &pow1, 0.03988915);
1008 } else { // DOWN
1009 cpl_polynomial_set_coeff(corr_poly, &pow0, -6.51155269);
1010 cpl_polynomial_set_coeff(corr_poly, &pow1, -0.04965059);
1011 }
1012 } else if (decker_position == CR2RES_DECKER_1_3){ // nodd B
1013 if (up_or_down == 1){ // UP
1014 cpl_polynomial_set_coeff(corr_poly, &pow0, 13.12469913);
1015 cpl_polynomial_set_coeff(corr_poly, &pow1, 0.04808708);
1016 } else { // DOWN
1017 cpl_polynomial_set_coeff(corr_poly, &pow0, 28.22704312);
1018 cpl_polynomial_set_coeff(corr_poly, &pow1, -0.04019722);
1019 }
1020 }
1021 }
1022 else if (wl < 1360) {
1023 band=cpl_sprintf("J");
1024 /*
1025 'JuA': array([ 0.03903698, -26.55176271]),
1026 'JuB': array([ 0.04496791, 10.27999294]),
1027 'JdA': array([ -0.047482 , -10.87508078]),
1028 'JdB': array([-0.04101687, 25.44306868]),
1029 */
1030 if (decker_position == CR2RES_DECKER_2_4){ // nodd A
1031 if (up_or_down == 1){ // UP
1032 cpl_polynomial_set_coeff(corr_poly, &pow0, -26.55176271);
1033 cpl_polynomial_set_coeff(corr_poly, &pow1, 0.03903698);
1034 } else { // DOWN
1035 cpl_polynomial_set_coeff(corr_poly, &pow0, -10.87508078);
1036 cpl_polynomial_set_coeff(corr_poly, &pow1, -0.047482);
1037 }
1038 } else if (decker_position == CR2RES_DECKER_1_3){ // nodd B
1039 if (up_or_down == 1){ // UP
1040 cpl_polynomial_set_coeff(corr_poly, &pow0, 10.27999294);
1041 cpl_polynomial_set_coeff(corr_poly, &pow1, 0.04496791);
1042 } else { // DOWN
1043 cpl_polynomial_set_coeff(corr_poly, &pow0, 25.44306868);
1044 cpl_polynomial_set_coeff(corr_poly, &pow1, -0.04101687);
1045 }
1046 }
1047
1048 }
1049 else if (wl < 1850) {
1050 band=cpl_sprintf("H");
1051 /*
1052 'HuA': array([ 1.59902724e-02, -2.17975984e+01]),
1053 'HuB': array([ 0.0199041 , 17.44054878]),
1054 'HdA': array([ -0.02831508, -23.23946728]),
1055 'HdB': array([-0.02552662, 18.31347609]),
1056 */
1057 if (decker_position == CR2RES_DECKER_2_4){ // nodd A
1058 if (up_or_down == 1){ // UP
1059 cpl_polynomial_set_coeff(corr_poly, &pow0, -2.17975984e+01);
1060 cpl_polynomial_set_coeff(corr_poly, &pow1, 1.59902724e-02);
1061 } else { // DOWN
1062 cpl_polynomial_set_coeff(corr_poly, &pow0, -23.23946728);
1063 cpl_polynomial_set_coeff(corr_poly, &pow1, -0.02831508);
1064 }
1065 } else if (decker_position == CR2RES_DECKER_1_3){ // nodd B
1066 if (up_or_down == 1){ // UP
1067 cpl_polynomial_set_coeff(corr_poly, &pow0, 17.44054878);
1068 cpl_polynomial_set_coeff(corr_poly, &pow1, 0.0199041);
1069 } else { // DOWN
1070 cpl_polynomial_set_coeff(corr_poly, &pow0, 18.31347609);
1071 cpl_polynomial_set_coeff(corr_poly, &pow1, -0.02552662);
1072 }
1073 }
1074 }
1075 else if (wl < 2600) {
1076 band=cpl_sprintf("K");
1077 /*
1078 'KuA': array([ 2.24337404e-02, -2.30870052e+01]),
1079 'KuB': array([ 0.02467974, 16.43404529]),
1080 'KdA': array([ -0.02667301, -13.55392217]),
1081 'KdB': array([-2.42857387e-02, 2.58313952e+01])
1082 */
1083 if (decker_position == CR2RES_DECKER_2_4){ // nodd A
1084 if (up_or_down == 1){ // UP
1085 cpl_polynomial_set_coeff(corr_poly, &pow0, -2.30870052e+01);
1086 cpl_polynomial_set_coeff(corr_poly, &pow1, 2.24337404e-02);
1087 } else { // DOWN
1088 cpl_polynomial_set_coeff(corr_poly, &pow0, -13.55392217);
1089 cpl_polynomial_set_coeff(corr_poly, &pow1, -0.02667301);
1090 }
1091 } else if (decker_position == CR2RES_DECKER_1_3){ // nodd B
1092 if (up_or_down == 1){ // UP
1093 cpl_polynomial_set_coeff(corr_poly, &pow0, 16.43404529);
1094 cpl_polynomial_set_coeff(corr_poly, &pow1, 0.02467974);
1095 } else { // DOWN
1096 cpl_polynomial_set_coeff(corr_poly, &pow0, 2.58313952e+01);
1097 cpl_polynomial_set_coeff(corr_poly, &pow1, -2.42857387e-02);
1098 }
1099 }
1100 }
1101 else {
1102 cpl_msg_error(__func__, "No proper WL found to identify band.");
1103 cpl_polynomial_delete(corr_poly);
1104 return NULL;
1105 }
1106 cpl_msg_info(__func__, "Found wl=%g nm, therefore applying beam "
1107 "correction for %s-band.", wl, band);
1108
1109
1110 /* Loop through all traces in input TW */
1111 nb_traces = cpl_table_get_nrow(tw_in) ;
1112 newSFs = cpl_vector_new(nb_traces);
1113 for (i = 0; i < nb_traces; i++)
1114 {
1115 int trace_id;
1116 cpl_table_get(tw_in, CR2RES_COL_ORDER, i, NULL) ;
1117 trace_id = cpl_table_get(tw_in, CR2RES_COL_TRACENB, i, NULL);
1118 if (trace_id != 1){
1119 cpl_msg_error(__func__, "More than one input-trace per order"
1120 "is not supported.");
1121 cpl_table_delete(tw_out);
1122 cpl_free(band);
1123 cpl_polynomial_delete(corr_poly);
1124 return NULL;
1125 }
1126
1127 /* Evaluate at middle of detector to get average positions */
1128 y_corr = cpl_polynomial_eval_1d(corr_poly, wl, NULL);
1129 cpl_vector_set(newSFs, i, 0.5 + (y_corr) / CR2RES_APPROX_SLIT_HEIGHT);
1130 }
1131 newSF = cpl_vector_get_median(newSFs);
1132 cpl_vector_delete(newSFs);
1133 cpl_msg_info(__func__, "Median new slit-fraction: %g", newSF);
1134
1135 tmp_arr = cpl_array_new(3,CPL_TYPE_DOUBLE);
1136 cpl_array_set(tmp_arr, 0, newSF-0.15);
1137 cpl_array_set(tmp_arr, 1, newSF);
1138 cpl_array_set(tmp_arr, 2, newSF+0.15);
1139 tw_out = cr2res_trace_new_slit_fraction(tw_in, tmp_arr);
1140 //tw_out = cpl_table_duplicate(tw_in);
1141 cpl_array_delete(tmp_arr);
1142
1143 for (i=0 ; i<nb_traces ; i++) {
1144 double slope_corr, halfSF;
1145 int o;
1146 o = cpl_table_get(tw_in, CR2RES_COL_ORDER, i, NULL) ;
1147 //trace_id = cpl_table_get(tw_in, CR2RES_COL_TRACENB, i, NULL);
1148
1149 /* Calculate new slit-fraction, important for WL-correction */
1150 /* wl is at middle of detector from above */
1151 y_corr = cpl_polynomial_eval_1d(corr_poly, wl, NULL);
1152 tmp_arr = cpl_array_new(3,CPL_TYPE_DOUBLE);
1153 newSF = 0.5 + (y_corr / CR2RES_APPROX_SLIT_HEIGHT);
1154 halfSF = CR2RES_POLARIMETRY_DEFAULT_HEIGHT /
1155 CR2RES_APPROX_SLIT_HEIGHT / 2;
1156 cpl_array_set(tmp_arr, 0, newSF-halfSF);
1157 cpl_array_set(tmp_arr, 1, newSF);
1158 cpl_array_set(tmp_arr, 2, newSF+halfSF);
1159 cpl_table_set_array(tw_out, CR2RES_COL_SLIT_FRACTION, i, tmp_arr);
1160 cpl_array_delete(tmp_arr);
1161
1162 /* Evaluate WL at detector edges, because corr-poly is P(WL)*/
1163 wl_poly = cr2res_get_trace_wave_poly(tw_in, CR2RES_COL_WAVELENGTH, o,1);
1164 wl = cpl_polynomial_eval_1d(wl_poly, 1, NULL);
1165 y_corr = cpl_polynomial_eval_1d(corr_poly, wl, NULL);
1166 wl = cpl_polynomial_eval_1d(wl_poly, CR2RES_DETECTOR_SIZE, NULL);
1167 slope_corr = (cpl_polynomial_eval_1d(corr_poly, wl, NULL)
1168 - y_corr) / CR2RES_DETECTOR_SIZE; // SLOPE!
1169
1170 cpl_msg_debug(__func__,
1171 "newSF, halfSF, slope_corr, y_corr: "
1172 "%g, %g, %g, %g ",
1173 newSF, halfSF, slope_corr, y_corr);
1174
1175 /* Add the correction to the existing trace polys */
1176 tmp_arr = cpl_array_duplicate (
1177 cpl_table_get_array(tw_in, CR2RES_COL_ALL,i));
1178 cpl_array_set(tmp_arr, 0, cpl_array_get(tmp_arr, 0, NULL) + y_corr);
1179 cpl_array_set(tmp_arr, 1, cpl_array_get(tmp_arr, 1, NULL) + slope_corr);
1180 cpl_table_set_array(tw_out, CR2RES_COL_ALL, i, tmp_arr);
1181
1182 /* Edge polynomials are just shifted up/down by height/2 */
1183 cpl_array_set(tmp_arr, 0, cpl_array_get(tmp_arr, 0, NULL) +
1184 CR2RES_POLARIMETRY_DEFAULT_HEIGHT / 2);
1185 cpl_table_set_array(tw_out, CR2RES_COL_UPPER, i, tmp_arr);
1186 cpl_array_set(tmp_arr, 0, cpl_array_get(tmp_arr, 0, NULL) -
1187 CR2RES_POLARIMETRY_DEFAULT_HEIGHT);
1188 cpl_table_set_array(tw_out, CR2RES_COL_LOWER, i, tmp_arr);
1189 cpl_array_delete(tmp_arr);
1190
1191 cpl_polynomial_delete(wl_poly);
1192 }
1193
1194
1195 cpl_free(band);
1196 cpl_polynomial_delete(corr_poly);
1197 return tw_out;
1198}
1199
1200//
1201
char * cr2res_dfs_POL_NULL_colname(int order_idx)
Get the POL_NULL column name for a given order.
Definition: cr2res_dfs.c:258
char * cr2res_dfs_POL_STOKES_ERROR_colname(int order_idx)
Get the POL_STOKES_ERROR column name for a given order.
Definition: cr2res_dfs.c:241
char * cr2res_dfs_POL_INTENS_ERROR_colname(int order_idx)
Get the POL_INTENS_ERROR column name for a given order.
Definition: cr2res_dfs.c:306
char * cr2res_dfs_POL_NULL_ERROR_colname(int order_idx)
Get the POL_NULL_ERROR column name for a given order.
Definition: cr2res_dfs.c:274
char * cr2res_dfs_POL_STOKES_colname(int order_idx)
Get the POL_STOKES column name for a given order.
Definition: cr2res_dfs.c:225
char * cr2res_dfs_POL_INTENS_colname(int order_idx)
Get the POL_INTENS column name for a given order.
Definition: cr2res_dfs.c:290
char * cr2res_dfs_POL_WAVELENGTH_colname(int order_idx)
Get the POL_WAVELENGTH column name for a given order.
Definition: cr2res_dfs.c:209
const char * cr2res_pfits_get_poltype(const cpl_propertylist *plist)
find out the POL TYPE value
Definition: cr2res_pfits.c:241
cpl_bivector * cr2res_pol_demod_intens(cpl_vector **intens, cpl_vector **wl, cpl_vector **errors, int n)
Combine extracted spectra into Intensity spectrum.
Definition: cr2res_pol.c:528
cpl_table * cr2res_pol_POL_SPEC_create(int *orders, cpl_vector **wl, cpl_bivector **stokes, cpl_bivector **null, cpl_bivector **intens, int norders)
Create the POL_SPEC table to be saved.
Definition: cr2res_pol.c:696
cpl_table * cr2res_pol_spec_pol_merge(const cpl_table **pol_spec_list, int pol_spec_nb)
Merge several POL_SPEC tables together, by averaging.
Definition: cr2res_pol.c:915
int * cr2res_pol_sort_frames(const cpl_frame *frame1, const cpl_frame *frame2, const cpl_frame *frame3, const cpl_frame *frame4)
Compute the positions of the passed frames.
Definition: cr2res_pol.c:833
cpl_table * cr2res_pol_get_beam_trace(const cpl_table *tw_in, cr2res_decker decker_position, int up_or_down)
Compute the traces for the polarimetric beams.
Definition: cr2res_pol.c:970
cpl_bivector * cr2res_pol_demod_stokes(cpl_vector **intens, cpl_vector **wl, cpl_vector **errors, int n)
Demodulate extracted spectra into Stokes parameter.
Definition: cr2res_pol.c:106
int cr2res_pol_resample(cpl_vector **intens, cpl_vector **wl, cpl_vector **errors, int n, cpl_vector **xmin, cpl_vector **xmax)
Resample all spectra to the same wavelength grid.
Definition: cr2res_pol.c:289
cpl_bivector * cr2res_pol_demod_null(cpl_vector **intens, cpl_vector **wl, cpl_vector **errors, int n)
Demodulate extracted spectra into Null spectrum.
Definition: cr2res_pol.c:410
cpl_table * cr2res_trace_new_slit_fraction(const cpl_table *traces, const cpl_array *new_slit_fraction)
Recompute the traces at a newly specified slit fraction.
cpl_polynomial * cr2res_get_trace_wave_poly(const cpl_table *trace_wave, const char *poly_column, int order_idx, int trace_nb)
Get a polynomial from a TRACE_WAVE table.
Definition: cr2res_trace.c:685