MOONS Pipeline Reference Manual 0.13.1
moo_compute_p2p.c
1/*
2 * This file is part of the MOONS Pipeline
3 * Copyright (C) 2002-2016 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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20#ifdef HAVE_CONFIG_H
21#include <config.h>
22#endif
23
24/*-----------------------------------------------------------------------------
25 Includes
26 -----------------------------------------------------------------------------*/
27#include <math.h>
28#include <string.h>
29#include <cpl.h>
30#include <hdrl.h>
31#include "moo_utils.h"
32#include "moo_fits.h"
33#include "moo_params.h"
34#include "moo_single.h"
35#include "moo_psf_single.h"
36#include "moo_badpix.h"
37#include "moo_compute_p2p.h"
38#include "moo_qc.h"
39#include "moo_fibres_table.h"
40#ifdef _OPENMP
41#include <omp.h>
42#endif
43/*----------------------------------------------------------------------------*/
48/*----------------------------------------------------------------------------*/
51/*-----------------------------------------------------------------------------
52 Function codes
53 -----------------------------------------------------------------------------*/
54
55static cpl_error_code
56_moo_compute_p2p_qc(moo_single *single, int level)
57{
58 cpl_error_code status = CPL_ERROR_NONE;
59
60 cpl_ensure_code(single != NULL, CPL_ERROR_NULL_INPUT);
61 hdrl_image *himage = moo_single_get_image(single);
62
63 cpl_mask *mask = hdrl_image_get_mask(single->image);
64 moo_badpix_to_mask(single->qual, mask, level);
65
66 cpl_image *data = hdrl_image_get_image(himage);
67 cpl_ensure_code(data != NULL, CPL_ERROR_NULL_INPUT);
68
69 double min = cpl_image_get_min(data);
70 double max = cpl_image_get_max(data);
71 double rms = cpl_image_get_stdev(data);
72 double mad;
73 double median = cpl_image_get_mad(data, &mad);
74 double mean = cpl_image_get_mean(data);
75
76 cpl_propertylist *header = moo_single_get_header(single);
77 cpl_ensure_code(header != NULL, CPL_ERROR_NULL_INPUT);
78
79 moo_ensure_status(moo_qc_set_p2p_min(header, min), status);
80 moo_ensure_status(moo_qc_set_p2p_max(header, max), status);
81 moo_ensure_status(moo_qc_set_p2p_avg(header, mean), status);
82 moo_ensure_status(moo_qc_set_p2p_med(header, median), status);
83 moo_ensure_status(moo_qc_set_p2p_mad(header, mad), status);
84 moo_ensure_status(moo_qc_set_p2p_rms(header, rms), status);
85moo_try_cleanup:
86 return status;
87}
88
89static void
90_moo_reproject_model_fibre(cpl_image *image,
91 int numfib,
92 cpl_image *centroids,
93 cpl_image *model,
94 double crpix2,
95 double cd2_2,
96 cpl_image *result,
97 cpl_image *contrib)
98{
99 int nx = cpl_image_get_size_x(image);
100 int ny = cpl_image_get_size_y(model);
101
102 double *data = cpl_image_get_data(result);
103 int *contrib_data = cpl_image_get_data(contrib);
104
105 for (int x = 1; x <= nx; x++) {
106 int rej;
107 double centroid = cpl_image_get(centroids, x, numfib, &rej);
108 if (!isnan(centroid)) {
109 double y_lo = centroid + (1 - crpix2) * cd2_2;
110 double y_up = centroid + (ny - crpix2) * cd2_2;
111 int y_start = (int)ceil(y_lo);
112 int y_stop = (int)floor(y_up);
113 int model_idx = 1;
114 for (int y = y_start; y <= y_stop; y++) {
115 double y_model = centroid + (model_idx - crpix2) * cd2_2;
116 while (y_model < y) {
117 model_idx++;
118 y_model = centroid + (model_idx - crpix2) * cd2_2;
119 }
120 double y_model1 = centroid + (model_idx - 1 - crpix2) * cd2_2;
121 ;
122 double flux_model1 =
123 cpl_image_get(model, x, model_idx - 1, &rej);
124 double y_model2 = y_model;
125 double flux_model2 = cpl_image_get(model, x, model_idx, &rej);
126 double y_flux = flux_model1 + (flux_model2 - flux_model1) /
127 (y_model2 - y_model1) *
128 (y - y_model1);
129 data[(y - 1) * nx + x - 1] += y_flux;
130 contrib_data[(y - 1) * nx + x - 1]++;
131 }
132 }
133 }
134}
135
136static cpl_image *
137_moo_reproject_model(moo_single *det,
138 moo_loc_single *loc,
139 moo_psf_single *psf_single,
140 const int *health)
141{
142 cpl_ensure(det != NULL, CPL_ERROR_NULL_INPUT, NULL);
143 cpl_ensure(loc != NULL, CPL_ERROR_NULL_INPUT, NULL);
144 cpl_ensure(psf_single != NULL, CPL_ERROR_NULL_INPUT, NULL);
145 cpl_ensure(health != NULL, CPL_ERROR_NULL_INPUT, NULL);
146
147 cpl_errorstate prestate = cpl_errorstate_get();
148
149 cpl_image *res = NULL;
150 cpl_image *fcentroids = moo_loc_single_get_f_centroids(loc);
151 hdrl_image *himage = moo_single_get_image(det);
152 cpl_image *image = hdrl_image_get_image(himage);
153
154 int nx = hdrl_image_get_size_x(himage);
155 int ny = hdrl_image_get_size_y(himage);
156 int nb_fibres = cpl_image_get_size_y(fcentroids);
157
158 cpl_imagelist *cube = moo_psf_single_get_cube(psf_single);
159 double crpix2, cd2_2;
160 moo_psf_single_get_cube_ref(psf_single, &crpix2, &cd2_2);
161 res = cpl_image_new(nx, ny, CPL_TYPE_DOUBLE);
162 cpl_image *contrib = cpl_image_new(nx, ny, CPL_TYPE_INT);
163 cpl_msg_debug(__func__, "start %d", cpl_error_get_code());
164
165 /*REGDEBUG */
166 // nb_fibres = 1;
167
168/* The following addresses an issue with the gcc9 compiler series prior to
169 * gcc 9.3. These compiler versions require that the variable '__func__'
170 * appears in the data sharing clause if default(none) is used. However
171 * adding it to the data sharing clause breaks older compiler versions where
172 * these variables are pre-determined as shared.
173 * This was fixed in gcc 9.3 and OpenMP 5.1.
174 */
175#ifdef _OPENMP
176#if (__GNUC__ == 9) && (__GNUC_MINOR__ < 3)
177#pragma omp parallel shared(nb_fibres, health, cube, image, fcentroids, \
178 crpix2, cd2_2, res, contrib)
179#else
180#pragma omp parallel default(none) \
181 shared(nb_fibres, health, cube, image, fcentroids, crpix2, cd2_2, res, \
182 contrib)
183#endif
184 {
185#pragma omp for
186#endif
187 for (int i = 1; i <= nb_fibres; i++) {
188 int h = health[i - 1];
189 cpl_msg_debug(__func__, "reproject fibre %d", i);
190
191 if (h != 0) {
192 cpl_image *model = cpl_imagelist_get(cube, i - 1);
193 _moo_reproject_model_fibre(image, i, fcentroids, model, crpix2,
194 cd2_2, res, contrib);
195 }
196 }
197#ifdef _OPENMP
198 }
199#endif
200 double *data = cpl_image_get_data(res);
201
202 int *contrib_data = cpl_image_get_data(contrib);
203 for (int i = 0; i < nx * ny; i++) {
204 if (contrib_data[i] != 0) {
205 data[i] /= contrib_data[i];
206 }
207 }
208 cpl_image_delete(contrib);
209
210 // dump error from the state
211 if (!cpl_errorstate_is_equal(prestate)) {
212 cpl_msg_error(__func__, "Error in modelize flat");
213 cpl_errorstate_dump(prestate, CPL_FALSE, cpl_errorstate_dump_one);
214 // Recover from the error(s) (Reset to prestate))
215 cpl_errorstate_set(prestate);
216 }
217 return res;
218}
219
220/*----------------------------------------------------------------------------*/
230/*----------------------------------------------------------------------------*/
231cpl_error_code
232moo_reproject_model(moo_det *flat1,
233 moo_loc *loc1,
234 moo_psf *model_flat1,
235 const char *filename)
236{
237 cpl_ensure_code(flat1 != NULL, CPL_ERROR_NULL_INPUT);
238 cpl_ensure_code(loc1 != NULL, CPL_ERROR_NULL_INPUT);
239 cpl_ensure_code(model_flat1 != NULL, CPL_ERROR_NULL_INPUT);
240
241 cpl_msg_info(__func__, "Reproject model");
242
243 cpl_table *fibres_table = moo_loc_get_fibre_table(loc1);
244 cpl_ensure_code(fibres_table != NULL, CPL_ERROR_ILLEGAL_INPUT);
245
246 unsigned int badpix_level = MOO_BADPIX_OUTSIDE_DATA_RANGE |
248
249 moo_fits_create(filename);
250
251 cpl_msg_indent_more();
252
253 for (int i = 1; i <= 2; i++) {
254 cpl_table_unselect_all(fibres_table);
255 int fibname = i;
256 cpl_table_or_selected_int(fibres_table, MOO_FIBRES_TABLE_SPECTRO,
257 CPL_EQUAL_TO, fibname);
258 cpl_table *selected = cpl_table_extract_selected(fibres_table);
259 const int *health =
260 cpl_table_get_data_int_const(selected, MOO_FIBRES_TABLE_HEALTH);
261
262 for (int j = 0; j < 3; j++) {
263 moo_single *flat_single1 =
264 moo_det_load_single(flat1, j, i, badpix_level);
265
266 moo_loc_single *loc_single1 = moo_loc_get_single(loc1, j, i);
267
268 moo_psf_single *psf_single1 = moo_psf_get_single(model_flat1, j, i);
269
270 if (flat_single1 != NULL && loc_single1 != NULL && psf_single1) {
271 cpl_image *model =
272 _moo_reproject_model(flat_single1, loc_single1, psf_single1,
273 health);
274 moo_fits_write_extension_image(model, filename, "MODEL_",
275 flat_single1->extname,
276 CPL_TYPE_FLOAT, NULL);
277 cpl_image_delete(model);
278 }
279 }
280 cpl_table_delete(selected);
281 }
282 cpl_msg_indent_less();
283 return CPL_ERROR_NONE;
284}
285
286static moo_single *
287_moo_compute_p2p_single(moo_single *flat1,
288 moo_loc_single *loc1,
289 moo_psf_single *model_flat1,
290 moo_single *flat2,
291 moo_loc_single *loc2,
292 moo_psf_single *model_flat2,
293 const int *health)
294{
295 moo_single *result = NULL;
296 cpl_mask *mask_loc1 = NULL;
297 cpl_mask *mask_loc2 = NULL;
298
299 cpl_msg_indent_more();
300 cpl_msg_info("moo_compute_p2p", "Reproject model");
301 cpl_ensure(flat1 != NULL, CPL_ERROR_NULL_INPUT, NULL);
302 cpl_ensure(loc1 != NULL, CPL_ERROR_NULL_INPUT, NULL);
303 cpl_ensure(model_flat1 != NULL, CPL_ERROR_NULL_INPUT, NULL);
304 cpl_ensure(flat2 != NULL, CPL_ERROR_NULL_INPUT, NULL);
305 cpl_ensure(loc2 != NULL, CPL_ERROR_NULL_INPUT, NULL);
306 cpl_ensure(model_flat2 != NULL, CPL_ERROR_NULL_INPUT, NULL);
307 cpl_ensure(health != NULL, CPL_ERROR_NULL_INPUT, NULL);
308
309 cpl_errorstate prestate = cpl_errorstate_get();
310
311 cpl_image *model1 = NULL;
312 cpl_image *model2 = NULL;
313 cpl_image *model_sum = NULL;
314 hdrl_image *model = NULL;
315 cpl_mask *orig = NULL;
316
317 moo_try_check(model1 =
318 _moo_reproject_model(flat1, loc1, model_flat1, health),
319 " Reproject model1 failed");
320 moo_try_check(model2 =
321 _moo_reproject_model(flat2, loc2, model_flat2, health),
322 "reproject model2 failed");
323
324 moo_try_check(model_sum = cpl_image_add_create(model1, model2), " ");
325
326#if MOO_DEBUG_P2P_MODEL
327 moo_fits_write_extension_image(model1, "model.fits", "MODEL1_",
328 flat1->extname, CPL_TYPE_FLOAT, NULL);
329 moo_fits_write_extension_image(model2, "model.fits", "MODEL2_",
330 flat1->extname, CPL_TYPE_FLOAT, NULL);
331#endif
332 result = moo_single_add_create(flat1, flat2);
333
334 model = hdrl_image_create(model_sum, NULL);
335
336 cpl_mask *mask = hdrl_image_get_mask(result->image);
337
338 int size_y = hdrl_image_get_size_y(result->image);
339 mask_loc1 = moo_loc_single_get_ODR(loc1, size_y);
340 mask_loc2 = moo_loc_single_get_ODR(loc2, size_y);
341 cpl_mask_and(mask_loc1, mask_loc2);
342 moo_mask_to_badpix(result->qual, mask_loc1, MOO_BADPIX_OUTSIDE_DATA_RANGE);
343
344 cpl_mask_or(mask, mask_loc1);
345
346 orig = cpl_mask_duplicate(mask);
347 hdrl_image_div_image(result->image, model);
348
349 cpl_mask_not(orig);
350 cpl_mask_and(orig, mask);
351 cpl_msg_info("", "new bad pix %" CPL_SIZE_FORMAT, cpl_mask_count(orig));
352 moo_mask_to_badpix(result->qual, orig, MOO_BADPIX_CALIB_DEFECT);
353
354moo_try_cleanup:
355 cpl_msg_indent_less();
356 cpl_mask_delete(mask_loc1);
357 cpl_mask_delete(mask_loc2);
358 cpl_image_delete(model1);
359 cpl_image_delete(model2);
360 cpl_mask_delete(orig);
361 hdrl_image_delete(model);
362 cpl_image_delete(model_sum);
363
364 if (!cpl_errorstate_is_equal(prestate)) {
365 cpl_msg_error(__func__, "Error in model flat");
366 cpl_errorstate_dump(prestate, CPL_FALSE, cpl_errorstate_dump_one);
367 // Recover from the error(s) (Reset to prestate))
368 cpl_errorstate_set(prestate);
369 }
370 return result;
371}
372/*----------------------------------------------------------------------------*/
396/*----------------------------------------------------------------------------*/
397moo_det *
398moo_compute_p2p(moo_det *flat1,
399 moo_loc *loc1,
400 moo_psf *model_flat1,
401 moo_det *flat2,
402 moo_loc *loc2,
403 moo_psf *model_flat2)
404{
405 moo_det *result = NULL;
406
407 cpl_errorstate prestate = cpl_errorstate_get();
408
409 cpl_table *selected = NULL;
410
411 cpl_ensure(flat1 != NULL, CPL_ERROR_NULL_INPUT, NULL);
412 cpl_ensure(loc1 != NULL, CPL_ERROR_NULL_INPUT, NULL);
413 cpl_ensure(model_flat1 != NULL, CPL_ERROR_NULL_INPUT, NULL);
414 cpl_ensure(flat2 != NULL, CPL_ERROR_NULL_INPUT, NULL);
415 cpl_ensure(loc2 != NULL, CPL_ERROR_NULL_INPUT, NULL);
416 cpl_ensure(model_flat2 != NULL, CPL_ERROR_NULL_INPUT, NULL);
417
418 cpl_msg_info(__func__, "Compute pixel-to-pixel variation map");
419
420 cpl_table *fibres_table = moo_loc_get_fibre_table(loc1);
421 cpl_ensure(fibres_table != NULL, CPL_ERROR_ILLEGAL_INPUT, NULL);
422
423 unsigned int badpix_level = MOO_BADPIX_OUTSIDE_DATA_RANGE |
425
426#if MOO_DEBUG_P2P_MODEL
427 moo_fits_create("model.fits");
428#endif
429 cpl_msg_indent_more();
430
431 result = moo_det_new();
432
433 result->primary_header = cpl_propertylist_new();
434
435 for (int i = 1; i <= 2; i++) {
436 cpl_table_unselect_all(fibres_table);
437 int fibname = i;
438 cpl_table_or_selected_int(fibres_table, MOO_FIBRES_TABLE_SPECTRO,
439 CPL_EQUAL_TO, fibname);
440 moo_try_check(selected = cpl_table_extract_selected(fibres_table), " ");
441 const int *health =
442 cpl_table_get_data_int_const(selected, MOO_FIBRES_TABLE_HEALTH);
443 for (int j = 0; j < 3; j++) {
444 moo_single *single = NULL;
445 moo_single *det_single1 =
446 moo_det_load_single(flat1, j, i, badpix_level);
447 moo_loc_single *loc_single1 = moo_loc_get_single(loc1, j, i);
448 moo_psf_single *psf_single1 = moo_psf_get_single(model_flat1, j, i);
449
450 moo_single *det_single2 =
451 moo_det_load_single(flat2, j, i, badpix_level);
452 moo_loc_single *loc_single2 = moo_loc_get_single(loc2, j, i);
453 moo_psf_single *psf_single2 = moo_psf_get_single(model_flat2, j, i);
454
455 if (det_single1 != NULL && loc_single1 != NULL && psf_single1 &&
456 det_single2 != NULL && loc_single2 != NULL && psf_single2) {
457 cpl_msg_info(__func__, "Compute p2p for extension %s",
459
460 moo_try_check(single = _moo_compute_p2p_single(
461 det_single1, loc_single1, psf_single1,
462 det_single2, loc_single2, psf_single2,
463 health),
464 " ");
465 moo_try_check(_moo_compute_p2p_qc(single, badpix_level), " ");
466 moo_try_check(moo_det_set_single(result, j, i, single), " ");
467 }
468#if MOO_DEBUG_P2P_MODEL
469 else {
470 moo_fits_write_extension_image(NULL, "model.fits", "MODEL1_",
472 CPL_TYPE_FLOAT, NULL);
473 moo_fits_write_extension_image(NULL, "model.fits", "MODEL2_",
475 CPL_TYPE_FLOAT, NULL);
476 }
477#endif
478 }
479 cpl_table_delete(selected);
480 selected = NULL;
481 }
482 cpl_msg_indent_less();
483
484moo_try_cleanup:
485 if (!cpl_errorstate_is_equal(prestate)) {
486 cpl_msg_error(__func__, "Error in compute_p2p");
487 moo_det_delete(result);
488 cpl_table_delete(selected);
489 result = NULL;
490 cpl_errorstate_dump(prestate, CPL_FALSE, cpl_errorstate_dump_one);
491 // Recover from the error(s) (Reset to prestate))
492 cpl_errorstate_set(prestate);
493 }
494 return result;
495}
cpl_error_code moo_mask_to_badpix(cpl_image *badpix, cpl_mask *mask, unsigned int level)
Add the mask of the badpix level to the badpix map.
Definition: moo_badpix.c:105
#define MOO_BADPIX_LOW_QE
Definition: moo_badpix.h:45
#define MOO_BADPIX_OUTSIDE_DATA_RANGE
Definition: moo_badpix.h:62
#define MOO_BADPIX_CALIB_DEFECT
Definition: moo_badpix.h:48
cpl_error_code moo_badpix_to_mask(cpl_image *badpix, cpl_mask *mask, unsigned int level)
Apply the badpix map on the given mask.
Definition: moo_badpix.c:58
moo_single * moo_det_load_single(moo_det *self, moo_detector_type type, int num, int level)
Load the type part in DET and return it.
Definition: moo_det.c:197
moo_det * moo_det_new(void)
Create a new moo_det.
Definition: moo_det.c:71
void moo_det_delete(moo_det *self)
Delete a moo_det.
Definition: moo_det.c:472
const char * moo_detector_get_extname(moo_detector_type type, int ntas)
Get the extension name of a detector.
Definition: moo_detector.c:137
cpl_error_code moo_fits_write_extension_image(cpl_image *image, const char *filename, const char *name, const char *detectorname, cpl_type type, cpl_propertylist *header)
Write an image as extension in FITS file.
Definition: moo_fits.c:123
cpl_error_code moo_fits_create(const char *filename)
Create a new fits file with empty propertylist.
Definition: moo_fits.c:533
cpl_image * moo_loc_single_get_f_centroids(moo_loc_single *self)
Get image of fit centroids.
cpl_mask * moo_loc_single_get_ODR(moo_loc_single *self, int size_y)
Get outside data range mask far a DET single.
moo_loc_single * moo_loc_get_single(moo_loc *self, moo_detector_type type, int ntas)
Get the type part in LOC and return it.
Definition: moo_loc.c:155
cpl_table * moo_loc_get_fibre_table(moo_loc *self)
Get the FIBRE TABLE in LOC.
Definition: moo_loc.c:306
cpl_error_code moo_psf_single_get_cube_ref(moo_psf_single *self, double *crpix2, double *cd2_2)
Set cube parameters.
cpl_imagelist * moo_psf_single_get_cube(moo_psf_single *self)
Get cube.
moo_psf_single * moo_psf_get_single(moo_psf *self, moo_detector_type type, int ntas)
Get a PSF single from PSF.
Definition: moo_psf.c:151
hdrl_image * moo_single_get_image(moo_single *self)
Get the IMAGE part (DATA,ERR) of single DET.
Definition: moo_single.c:330
moo_det * moo_compute_p2p(moo_det *flat1, moo_loc *loc1, moo_psf *model_flat1, moo_det *flat2, moo_loc *loc2, moo_psf *model_flat2)
To compute pixel-to-pixel variation map.
cpl_error_code moo_reproject_model(moo_det *flat1, moo_loc *loc1, moo_psf *model_flat1, const char *filename)
Reporject a model on detector.
cpl_error_code moo_qc_set_p2p_max(cpl_propertylist *plist, double val)
Set the QC.P2P.MAX value.
Definition: moo_qc.c:1186
cpl_error_code moo_qc_set_p2p_med(cpl_propertylist *plist, double val)
Set the QC.P2P.MED value.
Definition: moo_qc.c:1244
cpl_error_code moo_qc_set_p2p_min(cpl_propertylist *plist, double val)
Set the QC.P2P.MIN value.
Definition: moo_qc.c:1157
cpl_error_code moo_qc_set_p2p_mad(cpl_propertylist *plist, double val)
Set the QC.P2P.MAD value.
Definition: moo_qc.c:1273
cpl_error_code moo_qc_set_p2p_avg(cpl_propertylist *plist, double val)
Set the QC.P2P.AVG value.
Definition: moo_qc.c:1215
cpl_error_code moo_qc_set_p2p_rms(cpl_propertylist *plist, double val)
Set the QC.P2P.RMS value.
Definition: moo_qc.c:1301