CR2RE Pipeline Reference Manual 1.6.2
cr2res_wave-test.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 <stdlib.h>
29#include <string.h>
30#include <math.h>
31#include <cpl.h>
32#include <hdrl.h>
33#include <cr2res_dfs.h>
34#include <cr2res_wave.h>
35#include <cr2res_wave.c>
36#include <cr2res_etalon.h>
37
38#define CR2RES_DETECTOR_SIZE 2048
39
40/*-----------------------------------------------------------------------------
41 Functions prototypes
42 -----------------------------------------------------------------------------*/
43
44static void test_cr2res_wave_1d(void);
45//static void test_cr2res_wave_2d(void);
46//static void test_cr2res_wave_line_fitting_2d_other(void);
47//static void test_cr2res_wave_etalon(void);
48//static void test_cr2res_wave_etalon_other(void);
49static void test_cr2res_wave_polys_1d_to_2d(void);
50static void test_cr2res_wave_poly_2d_to_1d(void);
51static void test_cr2res_wave_estimate_compute(void);
52static void test_cr2res_wave_clean_spectrum(void);
53static void test_cr2res_wave_etalon_2d(void);
54
55/*----------------------------------------------------------------------------*/
60/*----------------------------------------------------------------------------*/
63// make a test line list catalog with just 2 lines
64static cpl_table * make_test_catalog()
65{
66 cpl_table * catalog = cpl_table_new(2);
67 cpl_table_new_column(catalog, CR2RES_COL_WAVELENGTH, CPL_TYPE_DOUBLE);
68 cpl_table_new_column(catalog, CR2RES_COL_EMISSION, CPL_TYPE_DOUBLE);
69 //cpl_table_new_column(catalog, CR2RES_COL_WIDTH, CPL_TYPE_DOUBLE);
70
71 // from lines_thar.txt catalog
72 // 2.551218908614062912e+03 9.935860000000000127e+02
73 // 2.603302966671994909e+03 2.992800000000000082e+01
74
75 cpl_table_set_double(catalog, CR2RES_COL_WAVELENGTH, 0, 2.551218908614062912e+03);
76 cpl_table_set_double(catalog, CR2RES_COL_EMISSION, 0, 9.935860000000000127e+02);
77
78 cpl_table_set_double(catalog, CR2RES_COL_WAVELENGTH, 1, 2.603302966671994909e+03);
79 cpl_table_set_double(catalog, CR2RES_COL_EMISSION, 1, 2.992800000000000082e+01);
80
81 return catalog;
82}
83
84static const char * save_catalog(cpl_table * catalog){
85 const char * filename = "TEST_linelist.fits";
86 cpl_propertylist * header = cpl_propertylist_new();
87 cpl_propertylist_append_string(header, CR2RES_HEADER_DRS_TYPE, CR2RES_DRSTYPE_CATALOG);
88
89 cpl_table_save(catalog, header, NULL, filename, CPL_IO_CREATE);
90 cpl_propertylist_delete(header);
91 return filename;
92}
93#ifdef CR2RES_UNUSED_TESTS
94static const char * save_linelist(cpl_bivector * linelist){
95 const char * filename = "TEST_linelist.fits";
96 cpl_propertylist * header = cpl_propertylist_new();
97 cpl_propertylist_append_string(header, CR2RES_HEADER_DRS_TYPE, CR2RES_DRSTYPE_CATALOG);
98
99 cpl_table * table = cpl_table_new(cpl_bivector_get_size(linelist));
100 cpl_table_new_column(table, CR2RES_COL_WAVELENGTH, CPL_TYPE_DOUBLE);
101 cpl_table_new_column(table, CR2RES_COL_EMISSION, CPL_TYPE_DOUBLE);
102
103 for (cpl_size i = 0; i < cpl_bivector_get_size(linelist); i++)
104 {
105 cpl_table_set_double(table, CR2RES_COL_WAVELENGTH, i, cpl_vector_get(cpl_bivector_get_x(linelist), i));
106 cpl_table_set_double(table, CR2RES_COL_EMISSION, i, cpl_vector_get(cpl_bivector_get_y(linelist), i));
107 }
108
109 cpl_table_save(table, header, NULL, filename, CPL_IO_CREATE);
110
111 cpl_propertylist_delete(header);
112 cpl_table_delete(table);
113 return filename;
114}
115#endif
116
117// make a test spectrum based on a line list catalog
118static cpl_bivector * make_test_spectrum(cpl_table * catalog, double wmin, double wmax, int size, cpl_bivector ** spectrum_err)
119{
120 double mu, line_em, sig;
121 int i, j;
122 cpl_bivector * spectrum = cpl_bivector_new(size);
123 *spectrum_err = cpl_bivector_new(size);
124 cpl_vector * wave1 = cpl_bivector_get_x(spectrum);
125 cpl_vector * wave2 = cpl_bivector_get_x(*spectrum_err);
126
127 cpl_vector * spec = cpl_bivector_get_y(spectrum);
128 cpl_vector * unc = cpl_bivector_get_y(*spectrum_err);
129
130 for (i = 0; i < size; i++){
131 double wl;
132 double tmp;
133 wl = wmin + i * (wmax - wmin) / (double)size;
134 tmp = 0;
135 for (j = 0; j < 2; j++){
136 mu = cpl_table_get_double(catalog, CR2RES_COL_WAVELENGTH, j, NULL);
137 line_em = cpl_table_get_double(catalog, CR2RES_COL_EMISSION, j, NULL);
138 sig = 2;
139 tmp += line_em * exp(- 1 * pow(wl - mu, 2) / (2 * pow(sig, 2)));
140 }
141
142 cpl_vector_set(spec, i, tmp);
143 cpl_vector_set(unc, i, 0.01);
144 cpl_vector_set(wave1, i, wl);
145 cpl_vector_set(wave2, i, wl);
146 }
147
148 return spectrum;
149}
150
151#ifdef CR2RES_UNUSED_TESTS
152static cpl_bivector * make_test_etalon_spectrum(int size, double freq, cpl_bivector ** spectrum_err)
153{
154 cpl_bivector * spectrum = cpl_bivector_new(size);
155 *spectrum_err = cpl_bivector_new(size);
156
157 cpl_vector * wave1 = cpl_bivector_get_x(spectrum);
158 cpl_vector * wave2 = cpl_bivector_get_x(*spectrum_err);
159
160 cpl_vector * spec = cpl_bivector_get_y(spectrum);
161 cpl_vector * unc = cpl_bivector_get_y(*spectrum_err);
162
163
164 for (int i = 0; i < size; i++){
165 cpl_vector_set(spec, i, fabs(sin(i * freq)));
166 cpl_vector_set(unc, i, 1);
167 cpl_vector_set(wave1, i, i);
168 cpl_vector_set(wave2, i, i);
169
170 }
171 return spectrum;
172
173}
174#endif
175
176// make a simple linear polynomial from wmin to wmax
177static cpl_polynomial * make_test_polynomial(double wmin, double wmax, int size)
178{
179 cpl_polynomial * poly = cpl_polynomial_new(1);
180 cpl_size power = 0;
181
182 power = 0;
183 cpl_polynomial_set_coeff(poly, &power, wmin);
184 power = 1;
185 cpl_polynomial_set_coeff(poly, &power,(wmax - wmin)/size);
186
187 return poly;
188}
189
190/*----------------------------------------------------------------------------*/
194/*----------------------------------------------------------------------------*/
195static void test_cr2res_wave_1d()
196{
197 double wmin=2500, wmax=2650;
198 int size = 200;
199 cpl_table * catalog = make_test_catalog();
200 cpl_table * diagnostics;
201 cpl_bivector * spectrum_err;
202 cpl_bivector * spectrum = make_test_spectrum(catalog, wmin, wmax, size, &spectrum_err);
203 cpl_polynomial * initial_guess = make_test_polynomial(wmin, wmax, size);
204 int degree = 1;
205 int order = 0;
206 int trace = 0;
207 int log_flag = 0; // False
208 int display = 0; // False
209 int propagate_flag = 0; // False
210 const char * catalog_name = save_catalog(catalog);
211 cr2res_wavecal_type wavecal_type = CR2RES_LINE1D;
212 cpl_array * wave_error_init = cpl_array_new(2, CPL_TYPE_DOUBLE);
213 cpl_array_set_double(wave_error_init, 0, 3.1);
214 cpl_array_set_double(wave_error_init, 1, 3.5);
215
216 cpl_array * wavelength_error;
217 cpl_polynomial * wavelength;
218 cpl_size power;
219
220 // bad inputs
221 wavelength = cr2res_wave_1d(NULL, spectrum_err, initial_guess,
222 wave_error_init, order, trace, wavecal_type, catalog_name,
223 degree, 0, log_flag, propagate_flag, display, -1.0, -1.0, NULL,
224 NULL, NULL, NULL, NULL, &wavelength_error, &diagnostics);
225 cpl_test_null(wavelength);
226
227 wavelength = cr2res_wave_1d(spectrum, NULL, initial_guess,
228 wave_error_init, order, trace, wavecal_type, catalog_name, degree, 0,
229 log_flag, propagate_flag, display, -1.0, -1.0, NULL, NULL, NULL, NULL,
230 NULL, &wavelength_error, &diagnostics);
231 cpl_test_null(wavelength);
232
233 wavelength = cr2res_wave_1d(spectrum, spectrum_err, NULL,
234 wave_error_init, order, trace, wavecal_type, catalog_name, degree,
235 0, log_flag, propagate_flag, display, -1.0, -1.0, NULL, NULL,
236 NULL, NULL, NULL, &wavelength_error, &diagnostics);
237 cpl_test_null(wavelength);
238
239 wavelength = cr2res_wave_1d(spectrum, spectrum_err, initial_guess,
240 wave_error_init, order, trace, wavecal_type, NULL, degree, 0,
241 log_flag, propagate_flag, display, -1.0, -1.0, NULL, NULL, NULL, NULL,
242 NULL, &wavelength_error, &diagnostics);
243 cpl_test_null(wavelength);
244
245 wavelength = cr2res_wave_1d(spectrum, spectrum_err, initial_guess,
246 wave_error_init, order, trace, wavecal_type, catalog_name,
247 degree, 0, log_flag, propagate_flag, display, -1.0, -1.0, NULL, NULL,
248 NULL, NULL, NULL, NULL, &diagnostics);
249 cpl_test_null(wavelength);
250
251 wavelength = cr2res_wave_1d(spectrum, spectrum_err, initial_guess,
252 wave_error_init, order, trace, wavecal_type, catalog_name,
253 degree, 0, log_flag, propagate_flag, display, -1.0, -1.0,NULL, NULL,
254 NULL, NULL, NULL, &wavelength_error, NULL);
255 cpl_test_null(wavelength);
256
257 // // to many polynomial degrees
258 wavelength = cr2res_wave_1d(spectrum, spectrum_err, initial_guess,
259 wave_error_init, order, trace, wavecal_type, catalog_name, 5, 0,
260 log_flag, propagate_flag, display, -1.0, -1.0, NULL, NULL, NULL, NULL,
261 NULL, &wavelength_error, &diagnostics);
262
263 cpl_test_null(wavelength);
264 cpl_test_null(wavelength_error);
265 cpl_test_null(diagnostics);
266
267
268 // regular run
269 cpl_test(wavelength = cr2res_wave_1d(spectrum, spectrum_err, initial_guess,
270 wave_error_init, order, trace, wavecal_type, catalog_name,
271 degree, 0, log_flag, propagate_flag, display, -1.0, -1.0, NULL,
272 NULL, NULL, NULL, NULL, &wavelength_error, &diagnostics));
273
274 cpl_test_nonnull(wavelength);
275 cpl_test_nonnull(wavelength_error);
276 cpl_test_nonnull(diagnostics);
277
278 // these values obviously need to be changed if the number of degrees is changed
279 power = 0;
280 cpl_test_abs(cpl_polynomial_get_coeff(wavelength, &power), wmin, 0.2);
281 power = 1;
282 cpl_test_abs(cpl_polynomial_get_coeff(wavelength, &power), (wmax-wmin)/(double)size, 0.01);
283
284 // Fitting two points with a first order polynomial -> perfect fit
285 cpl_test_abs(cpl_array_get_double(wavelength_error, 0, NULL), 0, DBL_EPSILON);
286 cpl_test_abs(cpl_array_get_double(wavelength_error, 1, NULL), 0, DBL_EPSILON);
287
288
289 cpl_table_delete(diagnostics);
290 cpl_array_delete(wavelength_error);
291 cpl_polynomial_delete(wavelength);
292 cpl_table_delete(catalog);
293 cpl_bivector_delete(spectrum);
294 cpl_bivector_delete(spectrum_err);
295 cpl_polynomial_delete(initial_guess);
296 cpl_array_delete(wave_error_init);
297}
298
299#ifdef CR2RES_UNUSED_TESTS
300/*----------------------------------------------------------------------------*/
304/*----------------------------------------------------------------------------*/
305static void test_cr2res_wave_2d()
306{
307 int i, norders = 5;
308 double wmin=2500, wmax=2650;
309 int size = 200;
310 // Make test data
311 cpl_table * catalog = make_test_catalog();
312 cpl_bivector * spectrum_err;
313 cpl_bivector * spectrum = make_test_spectrum(catalog, wmin, wmax, size, &spectrum_err);
314 cpl_polynomial * initial_guess = make_test_polynomial(wmin, wmax, size);
315 int * orders = cpl_malloc(norders * sizeof(int));
316 int * traces = cpl_malloc(norders * sizeof(int));
317 int display = FALSE; // False
318 const char * catalog_name = save_catalog(catalog);
319 cpl_array * wave_error_init = cpl_array_new(2, CPL_TYPE_DOUBLE);
320 cpl_array_set_double(wave_error_init, 0, 3.1);
321 cpl_array_set_double(wave_error_init, 1, 3.5);
322
323 cpl_array * wavelength_error;
324 cpl_table * diagnostics;
325 cpl_polynomial * wavelength;
326
327 cpl_size degree_x = 1; // polynomial degree in wavelength direction
328 cpl_size degree_y = 2; // polynomial degree in order direction
329
330 // Make lists that contain the same spectrum several times
331 cpl_bivector ** spec = cpl_malloc(norders * sizeof(cpl_bivector*));
332 cpl_bivector ** spec_err = cpl_malloc(norders * sizeof(cpl_bivector*));
333 cpl_polynomial ** guess = cpl_malloc(norders * sizeof(cpl_polynomial*));
334 cpl_array ** init_error = cpl_malloc(norders * sizeof(cpl_array*));
335
336 for (i = 0; i < norders; i++){
337 orders[i] = i;
338 traces[i] = 1;
339
340 spec[i] = spectrum;
341 spec_err[i] = spectrum_err;
342 guess[i] = initial_guess;
343 init_error[i] = wave_error_init;
344 }
345
346 // Run function
347 cpl_test(wavelength = cr2res_wave_2d(spec, spec_err, guess, init_error,
348 orders, traces, norders, catalog_name, degree_x, degree_y,
349 0.0, 0, 0, display, &wavelength_error, &diagnostics));
350
351 // Check output
352 cpl_polynomial_dump(wavelength, stdout);
353 // #----- 2 dimensional polynomial -----
354 // 1.dim.power 2.dim.power coefficient
355 // 0 0 2500
356 // 1 0 0.75
357 // 0 1 -1.04049e-12
358 // 0 2 2.48754e-13
359 // 1 2 1.07764e-16
360 // 1 1 -4.31057e-16
361 // #------------------------------------
362
363 // first two are the linear component in x direction
364 cpl_size idx[2] = {0, 0};
365 cpl_test_abs(wmin, cpl_polynomial_get_coeff(wavelength, idx), 1e-3);
366 idx[0] = 1;
367 cpl_test_abs((wmax-wmin)/(double)size, cpl_polynomial_get_coeff(wavelength, idx), 1e-5);
368 // all others should be 0 (or close to it), as there is no y dependance
369 idx[0] = 0;
370 idx[1] = 1;
371 cpl_test_abs(0, cpl_polynomial_get_coeff(wavelength, idx), 1e-10);
372 idx[0] = 0;
373 idx[1] = 2;
374 cpl_test_abs(0, cpl_polynomial_get_coeff(wavelength, idx), 1e-10);
375 idx[0] = 1;
376 idx[1] = 2;
377 cpl_test_abs(0, cpl_polynomial_get_coeff(wavelength, idx), 1e-10);
378 idx[0] = 1;
379 idx[1] = 1;
380 cpl_test_abs(0, cpl_polynomial_get_coeff(wavelength, idx), 1e-10);
381
382 // Free Memory
383 cpl_free(orders);
384 cpl_free(traces);
385 cpl_array_delete(wavelength_error);
386 cpl_polynomial_delete(wavelength);
387 cpl_table_delete(diagnostics);
388 cpl_table_delete(catalog);
389 cpl_bivector_delete(spectrum);
390 cpl_bivector_delete(spectrum_err);
391 cpl_polynomial_delete(initial_guess);
392 cpl_array_delete(wave_error_init);
393
394 cpl_free(spec);
395 cpl_free(spec_err);
396 cpl_free(guess);
397 cpl_free(init_error);
398}
399#endif
400
401#ifdef CR2RES_UNUSED_TESTS
402static void test_cr2res_wave_etalon(void){
403
404 cpl_bivector * spectrum;
405 cpl_bivector * spectrum_err;
406 cpl_array * error;
407 cpl_polynomial * initial;
408 cpl_polynomial * result;
409 cpl_size power;
410
411 double wmin = 500;
412 double wmax = 600;
413 int size = 2000;
414 int degree = 1;
415
416 spectrum = make_test_etalon_spectrum(size, 0.1, &spectrum_err);
417
418 // Remove one peak
419 for(int i = 100; i < 150; i++)
420 {
421 cpl_vector_set(cpl_bivector_get_y(spectrum), i, 0);
422 }
423
424 // Add a peak
425 for(int i = 1462; i < 1493 ; i++)
426 {
427 cpl_vector_set(cpl_bivector_get_y(spectrum), i, 1);
428 }
429
430 initial = make_test_polynomial(wmin, wmax, size);
431
432 error = cpl_array_new(2, CPL_TYPE_DOUBLE);
433 cpl_array_set_double(error, 0, 3.1);
434 cpl_array_set_double(error, 1, 3.5);
435
436 cpl_test(result = cr2res_wave_etalon(spectrum, spectrum_err, initial, degree, &error));
437
438 // these values obviously need to be changed if the number of degrees is changed
439 power = 0;
440 cpl_test_abs(cpl_polynomial_get_coeff(result, &power), wmin, 0.2);
441 power = 1;
442 cpl_test_abs(cpl_polynomial_get_coeff(result, &power), (wmax-wmin)/(double)size, 0.01);
443
444
445 cpl_bivector_delete(spectrum);
446 cpl_bivector_delete(spectrum_err);
447 cpl_array_delete(error);
448 cpl_polynomial_delete(initial);
449 cpl_polynomial_delete(result);
450}
451#endif
452
453#ifdef CR2RES_UNUSED_TESTS
454static void test_cr2res_wave_etalon_other(void){
455
456 cpl_bivector * spectrum;
457 cpl_bivector * spectrum_err;
458 cpl_array * error;
459 cpl_polynomial * initial;
460 cpl_polynomial * result;
461 cpl_size power;
462
463 double wmin = 500;
464 double wmax = 600;
465 int size = 2000;
466 int degree = 1;
467
468 spectrum = make_test_etalon_spectrum(size, 0.1, &spectrum_err);
469 initial = make_test_polynomial(wmin, wmax, size);
470
471 error = cpl_array_new(2, CPL_TYPE_DOUBLE);
472 cpl_array_set_double(error, 0, 3.1);
473 cpl_array_set_double(error, 1, 3.5);
474
475 result = cr2res_wave_etalon(spectrum, spectrum_err, initial, degree, &error);
476
477 // these values obviously need to be changed if the number of degrees is changed
478 power = 0;
479 cpl_test_abs(cpl_polynomial_get_coeff(result, &power), wmin, 0.2);
480 power = 1;
481 cpl_test_abs(cpl_polynomial_get_coeff(result, &power), (wmax-wmin)/(double)size, 0.01);
482
483
484 cpl_bivector_delete(spectrum);
485 cpl_bivector_delete(spectrum_err);
486 cpl_array_delete(error);
487 cpl_polynomial_delete(initial);
488 cpl_polynomial_delete(result);
489}
490#endif
491
492static void test_cr2res_wave_polys_1d_to_2d(void)
493{
494 int npolys = 10;
495 cpl_polynomial ** poly_1ds = cpl_malloc(npolys * sizeof(cpl_polynomial*));
496 int * orders = cpl_malloc(npolys * sizeof(int));
497 cpl_size degree = 2;
498 cpl_size coef_pos;
499 cpl_size * power = cpl_malloc(2 * sizeof(cpl_size));
500 cpl_polynomial * res;
501
502
503 for (cpl_size i = 0; i < npolys; i++)
504 {
505 orders[i] = i;
506 poly_1ds[i] = cpl_polynomial_new(1);
507 coef_pos = 0;
508 cpl_polynomial_set_coeff(poly_1ds[i], &coef_pos, i * 10);
509 coef_pos = 1;
510 cpl_polynomial_set_coeff(poly_1ds[i], &coef_pos, 1);
511 }
512
513 cpl_test(res = cr2res_wave_polys_1d_to_2d(poly_1ds, orders, npolys, degree));
514
515 // Check results
516 cpl_test_eq(2, cpl_polynomial_get_dimension(res));
517 cpl_test_eq(3, cpl_polynomial_get_degree(res));
518
519 power[0] = 0;
520 power[1] = 0;
521 cpl_test_abs(0, cpl_polynomial_get_coeff(res, power), FLT_EPSILON);
522
523 power[0] = 1;
524 power[1] = 0;
525 cpl_test_abs(1, cpl_polynomial_get_coeff(res, power), FLT_EPSILON);
526
527 power[0] = 0;
528 power[1] = 1;
529 cpl_test_abs(10, cpl_polynomial_get_coeff(res, power), FLT_EPSILON);
530
531 power[0] = 1;
532 power[1] = 1;
533 cpl_test_abs(0, cpl_polynomial_get_coeff(res, power), FLT_EPSILON);
534
535 power[0] = 0;
536 power[1] = 2;
537 cpl_test_abs(0, cpl_polynomial_get_coeff(res, power), FLT_EPSILON);
538
539 power[0] = 1;
540 power[1] = 2;
541 cpl_test_abs(0, cpl_polynomial_get_coeff(res, power), FLT_EPSILON);
542
543
544 cpl_polynomial_delete(res);
545 for (size_t i = 0; i < (size_t) npolys; i++)
546 {
547 cpl_polynomial_delete(poly_1ds[i]);
548 }
549 cpl_free(poly_1ds);
550 cpl_free(orders);
551 cpl_free(power);
552}
553
554static void test_cr2res_wave_poly_2d_to_1d()
555{
556 cpl_polynomial * poly_2d = cpl_polynomial_new(2);
557 int order = 1;
558 cpl_size * power = cpl_malloc(2 * sizeof(cpl_size));
559 cpl_size pow_1d;
560 cpl_polynomial * res;
561
562 power[0] = 0;
563 power[1] = 0;
564 cpl_polynomial_set_coeff(poly_2d, power, 10);
565
566 power[0] = 0;
567 power[1] = 1;
568 cpl_polynomial_set_coeff(poly_2d, power, 1);
569
570 power[0] = 1;
571 power[1] = 0;
572 cpl_polynomial_set_coeff(poly_2d, power, 1);
573
574 cpl_test(res = cr2res_wave_poly_2d_to_1d(poly_2d, order));
575
576 cpl_test_eq(1, cpl_polynomial_get_dimension(res));
577 pow_1d = 0;
578 cpl_test_abs(11, cpl_polynomial_get_coeff(res, &pow_1d), DBL_EPSILON);
579 pow_1d = 1;
580 cpl_test_abs(1, cpl_polynomial_get_coeff(res, &pow_1d), DBL_EPSILON);
581
582 cpl_polynomial_delete(poly_2d);
583 cpl_polynomial_delete(res);
584 cpl_free(power);
585}
586
587/*----------------------------------------------------------------------------*/
591/*----------------------------------------------------------------------------*/
592static void test_cr2res_wave_estimate_compute(void)
593{
594 //define input
595 // these values return "simple" results
596 double wmin = 2000;
597 double wmax = 4047;
598 cpl_polynomial *res;
599
600 //run test
601 cpl_test_null(cr2res_wave_estimate_compute(-1, 1));
602 cpl_test_null(cr2res_wave_estimate_compute(5, -1));
603 cpl_test_null(cr2res_wave_estimate_compute(5, 1));
604
605 cpl_test(res = cr2res_wave_estimate_compute(wmin, wmax));
606 //test output
607 cpl_size power = 0;
608 cpl_test_abs(1999.0, cpl_polynomial_get_coeff(res, &power), DBL_EPSILON);
609 power = 1;
610 cpl_test_abs(1.0, cpl_polynomial_get_coeff(res, &power), DBL_EPSILON);
611
612 //deallocate memory
613 cpl_polynomial_delete(res);
614
615 // Test invalid wavelength ranges
616 wmin = 5000;
617 wmax = 4047;
618 cpl_test_null(cr2res_wave_estimate_compute(wmin, wmax));
619
620 wmin = -10;
621 wmax = 0.11;
622 cpl_test_null(cr2res_wave_estimate_compute(wmin, wmax));
623}
624
625static void test_cr2res_wave_clean_spectrum(void)
626{
627 int ncols = 100;
628 cpl_size pow = 0;
629 cpl_vector * spec_intens = cpl_vector_new(ncols);
630 cpl_polynomial * wl_poly = cpl_polynomial_new(1);
631 cpl_bivector * catalog = cpl_bivector_new(5);
632 double wl_error = 5.;
633
634 cpl_vector * res = NULL;
635
636 // Flat Spectrum (doesn't actually matter as long as its not NaN)
637 for (int i = 0; i < ncols; i++){
638 cpl_vector_set(spec_intens, i, 1);
639 }
640
641 // Add two lines to the catalog
642 cpl_vector_set(cpl_bivector_get_x(catalog), 0, 20);
643 cpl_vector_set(cpl_bivector_get_y(catalog), 0, 1);
644 cpl_vector_set(cpl_bivector_get_x(catalog), 1, 23);
645 cpl_vector_set(cpl_bivector_get_y(catalog), 1, 1);
646 cpl_vector_set(cpl_bivector_get_x(catalog), 2, 23.2);
647 cpl_vector_set(cpl_bivector_get_y(catalog), 2, 1);
648 cpl_vector_set(cpl_bivector_get_x(catalog), 3, 23.3);
649 cpl_vector_set(cpl_bivector_get_y(catalog), 3, 1);
650 cpl_vector_set(cpl_bivector_get_x(catalog), 4, 50);
651 cpl_vector_set(cpl_bivector_get_y(catalog), 4, 1);
652
653 // Just linear spectrum
654 pow = 1;
655 cpl_polynomial_set_coeff(wl_poly, &pow, 1);
656
657 cpl_test(res = cr2res_wave_clean_spectrum(spec_intens, wl_poly, catalog, wl_error));
658
659 for (int i = 0; i < 15 ; i++){
660 cpl_test(isnan(cpl_vector_get(res, i)));
661 }
662 for (int i = 15; i < 29 ; i++){
663 cpl_test_abs(1, cpl_vector_get(res, i), DBL_EPSILON);
664 }
665 for (int i = 29; i < 45 ; i++){
666 cpl_test(isnan(cpl_vector_get(res, i)));
667 }
668 for (int i = 45; i < 56 ; i++){
669 cpl_test_abs(1, cpl_vector_get(res, i), DBL_EPSILON);
670 }
671 for (int i = 56; i < ncols ; i++){
672 cpl_test(isnan(cpl_vector_get(res, i)));
673 }
674
675 // FILE * f = fopen("TEST_spec_clean.txt", "w");
676 // cpl_vector_dump(res, f);
677 // fclose(f);
678
679 cpl_vector_delete(spec_intens);
680 cpl_polynomial_delete(wl_poly);
681 cpl_bivector_delete(catalog);
682 cpl_vector_delete(res);
683
684}
685
686/*----------------------------------------------------------------------------*/
701/*----------------------------------------------------------------------------*/
702static void test_cr2res_wave_etalon_2d(){
703 cpl_bivector ** spectra = NULL;
704 cpl_bivector ** spectra_err = NULL;
705 cpl_polynomial ** wavesol_init = NULL;
706 cpl_array ** wavesol_init_err = NULL;
707 int * orders = NULL;
708 int * traces_nb = NULL;
709 cpl_table * line_diagnostics = NULL;
710 cpl_array * wavelength_error = NULL;
711 int ninputs = 2;
712 cpl_size degree_x = 2;
713 cpl_size degree_y = 2;
714 cpl_polynomial * result = NULL;
715 cpl_size degree;
716 double wave, freq;
717
718 cpl_matrix * px;
719 cpl_vector * py;
720 px = cpl_matrix_new(1, CR2RES_DETECTOR_SIZE);
721 py = cpl_vector_new(CR2RES_DETECTOR_SIZE);
722
723 spectra = cpl_malloc(ninputs * sizeof(cpl_bivector*));
724 spectra_err = cpl_malloc(ninputs * sizeof(cpl_bivector*));
725 wavesol_init = cpl_malloc(ninputs* sizeof(cpl_polynomial*));
726 wavesol_init_err = cpl_malloc(ninputs * sizeof(cpl_array*));
727 orders = cpl_malloc(ninputs * sizeof(int));
728 traces_nb = cpl_malloc(ninputs * sizeof(int));
729 for (cpl_size i = 0; i < ninputs; i++)
730 {
731 orders[i] = i + 1;
732 traces_nb[1] = 1;
733 spectra[i] = cpl_bivector_new(CR2RES_DETECTOR_SIZE);
734 spectra_err[i] = cpl_bivector_new(CR2RES_DETECTOR_SIZE);
735 wavesol_init[i] = cpl_polynomial_new(1);
736 wavesol_init_err[i] = cpl_array_new(2, CPL_TYPE_DOUBLE);
737
738 for (cpl_size j = 0; j < CR2RES_DETECTOR_SIZE; j++)
739 {
740 cpl_vector_set(cpl_bivector_get_y(spectra[i]), j,
741 1 + sin(j * 100 * CPL_MATH_PI / CR2RES_DETECTOR_SIZE));
742
743 // Fit the wavelength guess
744 freq = 60 - i * 5 - j * 0.001;
745 wave = SPEED_OF_LIGHT / freq;
746 cpl_matrix_set(px, 0, j, j);
747 cpl_vector_set(py, j, wave);
748 }
749
750 degree = 3;
751 cpl_polynomial_fit(wavesol_init[i], px, NULL, py, NULL, CPL_FALSE, NULL, &degree);
752 }
753
754 cpl_matrix_delete(px);
755 cpl_vector_delete(py);
756
757 result = cr2res_etalon_wave_2d(spectra, spectra_err, wavesol_init, wavesol_init_err,
758 orders, traces_nb, ninputs, degree_x, degree_y, 0, 0,
759 &wavelength_error, &line_diagnostics);
760
761 cpl_test_nonnull(result);
762 if (result != NULL){
763 cpl_size degree2d[2];
764
765 double c00, c01, c10, c11;
766 degree2d[0] = 0;
767 degree2d[1] = 0;
768 c00 = cpl_polynomial_get_coeff(result, degree2d);
769 degree2d[0] = 0;
770 degree2d[1] = 1;
771 c01 = cpl_polynomial_get_coeff(result, degree2d);
772 degree2d[0] = 1;
773 degree2d[1] = 0;
774 c10 = cpl_polynomial_get_coeff(result, degree2d);
775 degree2d[0] = 1;
776 degree2d[1] = 1;
777 c11 = cpl_polynomial_get_coeff(result, degree2d);
778
779 cpl_test_abs(c00 + c01, SPEED_OF_LIGHT / 60, 2);
780 cpl_test_abs(c10, 0.1, 0.05);
781 cpl_test_abs(c11, -0.01, 0.03);
782 }
783
784 for (cpl_size i = 0; i < ninputs; i++)
785 {
786 cpl_bivector_delete(spectra[i]);
787 cpl_bivector_delete(spectra_err[i]);
788 cpl_polynomial_delete(wavesol_init[i]);
789 cpl_array_delete(wavesol_init_err[i]);
790 }
791 cpl_free(spectra);
792 cpl_free(spectra_err);
793 cpl_free(wavesol_init);
794 cpl_free(wavesol_init_err);
795 cpl_free(orders);
796 cpl_free(traces_nb);
797
798 if (wavelength_error != NULL) cpl_array_delete(wavelength_error);
799 if (line_diagnostics != NULL) cpl_table_delete(line_diagnostics);
800 if (result != NULL) cpl_polynomial_delete(result);
801
802}
803
804/*----------------------------------------------------------------------------*/
808/*----------------------------------------------------------------------------*/
809int main(void)
810{
811 cpl_test_init(PACKAGE_BUGREPORT, CPL_MSG_DEBUG);
812
813 test_cr2res_wave_1d();
814 //test_cr2res_wave_2d();
815 // test_cr2res_wave_etalon();
816 test_cr2res_wave_polys_1d_to_2d();
817 test_cr2res_wave_poly_2d_to_1d();
818 test_cr2res_wave_estimate_compute();
819 test_cr2res_wave_clean_spectrum();
820 test_cr2res_wave_etalon_2d();
821 return cpl_test_end(0);
822}
823
cpl_polynomial * cr2res_etalon_wave_2d(cpl_bivector **spectra, cpl_bivector **spectra_err, cpl_polynomial **wavesol_init, cpl_array **wavesol_init_err, int *orders, int *traces_nb, int ninputs, cpl_size degree_x, cpl_size degree_y, int zp_order, int display, cpl_array **wavelength_error, cpl_table **line_diagnostics)
Create the 2d wavecal fit using etalon peaks.
int main(void)
Run the Unit tests.
cpl_polynomial * cr2res_wave_polys_1d_to_2d(cpl_polynomial **poly_1ds, int *orders, int npolys, cpl_size xdegree)
Create a 2D Wavelength Polynomial out of a several 1D ones.
Definition: cr2res_wave.c:1685
cpl_polynomial * cr2res_wave_poly_2d_to_1d(cpl_polynomial *poly_2d, int order)
Create a 1D Wavelength Polynomial out of a 2D one.
Definition: cr2res_wave.c:1776
cpl_polynomial * cr2res_wave_2d(cpl_bivector **spectra, cpl_bivector **spectra_err, cpl_polynomial **wavesol_init, cpl_array **wavesol_init_err, int *orders, int *traces_nb, int ninputs, const char *catalog, cpl_size degree, cpl_size degree_y, double threshold, int n_iterations, int zp_order, int display, cpl_array **wavelength_error, cpl_table **lines_diagnostics)
Compute the 2D wavelength polynomial based on a line spectrum and a reference catalog by finding line...
Definition: cr2res_wave.c:889
cpl_polynomial * cr2res_wave_1d(cpl_bivector *spectrum, cpl_bivector *spectrum_err, cpl_polynomial *wavesol_init, const cpl_array *wave_error_init, int order, int trace_nb, cr2res_wavecal_type wavecal_type, const char *catalog, int degree, int clean_spectrum, int log_flag, int keep_higher_degrees_flag, int display, double display_wmin, double display_wmax, double *best_xcorr, double *lines_resol_fwhm, double *lines_pos, double *lines_resol, double *lines_intens, cpl_array **wavelength_error, cpl_table **lines_diagnostics)
1D Wavelength Calibration
Definition: cr2res_wave.c:689
cpl_polynomial * cr2res_wave_estimate_compute(double wmin, double wmax)
Compute the polynomial from boundaries.
Definition: cr2res_wave.c:1481
cpl_polynomial * cr2res_wave_etalon(cpl_bivector *spectrum, const cpl_bivector *spectrum_err, cpl_polynomial *wavesol_init, int degree, cpl_array **wavelength_error)
Find solution from etalon.
Definition: cr2res_wave.c:1405