MOONS Pipeline Reference Manual 0.13.2
moo_sub_sky_stare.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
31#include "moo_sub_sky_stare.h"
32#include "moo_fibres_table.h"
33#include "moo_f2f.h"
34#include "moo_fits.h"
35#include "moo_pfits.h"
36#include "moo_badpix.h"
37#include "moo_utils.h"
38#include "moo_skycorr.h"
39/*----------------------------------------------------------------------------*/
44/*----------------------------------------------------------------------------*/
45
48/*-----------------------------------------------------------------------------
49 Function codes
50 -----------------------------------------------------------------------------*/
51/* create all sky image */
52static hdrl_image *
53_moo_create_median_sky(cpl_array *sky_indexes, int *indexrbn, hdrl_image *rbn)
54{
55 hdrl_image *median_sky = NULL;
56
57 cpl_ensure(rbn != NULL, CPL_ERROR_NULL_INPUT, NULL);
58 cpl_ensure(sky_indexes != NULL, CPL_ERROR_NULL_INPUT, NULL);
59
60 int nx = hdrl_image_get_size_x(rbn);
61 int nb_sky = (int)cpl_array_get_size(sky_indexes);
62
63 if (nb_sky > 0) {
64 hdrl_image *allsky_img = hdrl_image_new(nx, nb_sky);
65 if (allsky_img == NULL) {
66 return NULL;
67 }
68
69 for (int i = 1; i <= nb_sky; i++) {
70 int idx = cpl_array_get_cplsize(sky_indexes, i - 1, NULL);
71 int rbn_idx = indexrbn[idx];
72
73 for (int j = 1; j <= nx; j++) {
74 int rej;
75 hdrl_value rbn_img_val =
76 hdrl_image_get_pixel(rbn, j, rbn_idx, &rej);
77
78 if (rej) {
79 hdrl_image_reject(allsky_img, j, i);
80 }
81 else {
82 hdrl_image_set_pixel(allsky_img, j, i, rbn_img_val);
83 }
84 }
85 }
86
87 median_sky = moo_image_collapse_median_create(allsky_img);
88 hdrl_image_delete(allsky_img);
89 }
90 else {
91 median_sky = hdrl_image_new(nx, 1);
92 }
93 return median_sky;
94}
95
96/*----------------------------------------------------------------------------*/
120/*----------------------------------------------------------------------------*/
121cpl_array *
122moo_select_sky(const char *targname,
123 int indextarg,
124 int obj_index,
125 double obj_targalpha,
126 double obj_targdelta,
127 cpl_table *target_table,
128 const char *index_colname,
129 cpl_table *sky_stare_table,
131 int maxdistslit,
132 double mintrans,
133 int min_sky,
134 double radius,
135 double step_r,
136 int target_table_idx,
137 moo_f2f *f2f,
138 cpl_array *allsky_indexes)
139{
140 cpl_array *sky_indexes = NULL;
141
142 cpl_ensure(maxdistslit >= 0, CPL_ERROR_ILLEGAL_INPUT, NULL);
143 int *indexes = cpl_table_get_data_int(target_table, index_colname);
144 double *targalpha =
145 cpl_table_get_data_double(target_table, MOO_FIBRES_TABLE_TARGALPHA);
146 double *targdelta =
147 cpl_table_get_data_double(target_table, MOO_FIBRES_TABLE_TARGDELTA);
148 sky_indexes = cpl_array_duplicate(allsky_indexes);
149 int nb_sky = cpl_array_get_size(sky_indexes);
150 int nstart = cpl_table_get_nrow(sky_stare_table);
151 cpl_table_set_size(sky_stare_table, nstart + nb_sky);
152 int nstop = cpl_table_get_nrow(sky_stare_table);
153
154 for (int i = nstart; i < nstop; i++) {
155 cpl_table_set_string(sky_stare_table, MOO_SKY_STARE_TARGNAME, i,
156 targname);
157 cpl_table_set_int(sky_stare_table, MOO_SKY_STARE_INDEXTARG, i,
158 indextarg);
159 cpl_table_set_int(sky_stare_table, MOO_SKY_STARE_INDEXRBN, i,
160 obj_index);
161 }
162 cpl_table_unselect_all(sky_stare_table);
163 cpl_array *obj_sel = NULL;
164 // filter in slit
165 if (maxdistslit >= 0) {
166 cpl_table_select_all(target_table);
167 cpl_table_and_selected_int(target_table, index_colname, CPL_EQUAL_TO,
168 obj_index);
169
170 obj_sel = cpl_table_where_selected(target_table);
171 int tobj_idx = cpl_array_get_cplsize(obj_sel, 0, NULL);
172 cpl_array_delete(obj_sel);
173 obj_sel = NULL;
174 int obj_spectro =
175 cpl_table_get_int(target_table, MOO_FIBRES_TABLE_SPECTRO, tobj_idx,
176 NULL);
177
178 for (int i = 1; i <= nb_sky; i++) {
179 int idx = cpl_array_get_cplsize(sky_indexes, i - 1, NULL);
180 int idx_t = nstart + i - 1;
181 int sky_index = indexes[idx];
182 cpl_table_select_all(target_table);
183 cpl_table_and_selected_int(target_table, index_colname,
184 CPL_EQUAL_TO, sky_index);
185 obj_sel = cpl_table_where_selected(target_table);
186 int tsky_idx = cpl_array_get_cplsize(obj_sel, 0, NULL);
187 cpl_array_delete(obj_sel);
188 obj_sel = NULL;
189 const int sky_spectro =
190 cpl_table_get_int(target_table, MOO_FIBRES_TABLE_SPECTRO,
191 tsky_idx, NULL);
192
193 cpl_table_set_int(sky_stare_table, MOO_SKY_STARE_SKYINDEXRBN, idx_t,
194 sky_index);
195 if (obj_spectro == sky_spectro) {
196 int dslit = (int)fabs((double)sky_index - (double)obj_index);
197 cpl_table_set_int(sky_stare_table, MOO_SKY_STARE_SKYDSLIT,
198 idx_t, dslit);
199 if (dslit == 0) {
200 double sky_alpha = targalpha[idx];
201 double sky_delta = targdelta[idx];
202 double d = moo_sky_distance(obj_targalpha, obj_targdelta,
203 sky_alpha, sky_delta);
204 if (d < 1E-9) {
205 cpl_table_select_row(sky_stare_table, idx_t);
206 cpl_array_set_invalid(sky_indexes, i - 1);
207 }
208 }
209 else if (dslit > maxdistslit) {
210 cpl_table_select_row(sky_stare_table, idx_t);
211 cpl_array_set_invalid(sky_indexes, i - 1);
212 }
213 }
214 else {
215 cpl_array_set_invalid(sky_indexes, i - 1);
216 cpl_table_select_row(sky_stare_table, idx_t);
217 }
218 }
219 }
220 int nb_valid_distslit = nb_sky - cpl_array_count_invalid(sky_indexes);
221
222 if (nb_valid_distslit < min_sky) {
223 cpl_array_delete(sky_indexes);
224 sky_indexes = NULL;
225 cpl_error_set_message(
226 "sub_sky_stare", CPL_ERROR_EOL,
227 "for indextarg %d after using filter with maxdistslit=%d : "
228 "not enough sky fibre (%d) for object indexrbn: %d",
229 indextarg, maxdistslit, nb_valid_distslit, obj_index);
230 return sky_indexes;
231 }
232 // filter in slit
233 if (f2f != NULL && mintrans > 0) {
234 cpl_array *f2f_sel = NULL;
235 const char *f2f_trans_colname = moo_f2f_get_trans_colname(f2f, type);
236
237 for (int i = 0; i < nb_sky; i++) {
238 int rej;
239 int idx_t = nstart + i;
240 int idx = cpl_array_get_cplsize(sky_indexes, i, &rej);
241 int sky_index = indexes[idx];
242
243 cpl_table_select_all(f2f->table);
244 cpl_table_and_selected_int(f2f->table, index_colname, CPL_EQUAL_TO,
245 sky_index);
246 f2f_sel = cpl_table_where_selected(f2f->table);
247 int f2f_sky_idx = cpl_array_get_cplsize(f2f_sel, 0, NULL);
248 cpl_array_delete(f2f_sel);
249 f2f_sel = NULL;
250 float sky_trans =
251 cpl_table_get(f2f->table, f2f_trans_colname, f2f_sky_idx, NULL);
252
253 cpl_table_set_double(sky_stare_table, MOO_SKY_STARE_SKYTRANS, idx_t,
254 sky_trans);
255 if (rej == 0) {
256 if (sky_trans < mintrans) {
257 cpl_table_select_row(sky_stare_table, idx_t);
258 cpl_array_set_invalid(sky_indexes, i);
259 }
260 }
261 }
262 }
263
264 int nb_valid_trans = nb_sky - cpl_array_count_invalid(sky_indexes);
265 if (nb_valid_trans < min_sky) {
266 cpl_array_delete(sky_indexes);
267 sky_indexes = NULL;
268 cpl_error_set_message(
269 "sub_sky_stare", CPL_ERROR_EOL,
270 "for indextarg %d after using filter with mintrans=%f : "
271 "not enough sky fibre (%d) for object indexrbn: %d",
272 indextarg, mintrans, nb_valid_trans, obj_index);
273 return sky_indexes;
274 }
275
276 // filter in sky
277 for (int i = 0; i < nb_sky; i++) {
278 int rej;
279 int idx = cpl_array_get_cplsize(sky_indexes, i, &rej);
280 int idx_t = nstart + i;
281
282 if (rej == 0) {
283 double sky_alpha = targalpha[idx];
284 double sky_delta = targdelta[idx];
285 double d = moo_sky_distance(obj_targalpha, obj_targdelta, sky_alpha,
286 sky_delta);
287 // rad to ARCMIN
288 d = d * CPL_MATH_DEG_RAD * 60;
289 cpl_table_set_double(sky_stare_table, MOO_SKY_STARE_RADIUS, idx_t,
290 radius);
291 cpl_table_set_double(sky_stare_table, MOO_SKY_STARE_SKYDIST, idx_t,
292 d);
293 if (d > radius) {
294 cpl_table_select_row(sky_stare_table, idx_t);
295 cpl_array_set_invalid(sky_indexes, i);
296 }
297 }
298 }
299
300 int nb_valid = nb_sky - cpl_array_count_invalid(sky_indexes);
301
302 if (nb_valid >= min_sky) {
303 cpl_table_erase_selected(sky_stare_table);
304 return sky_indexes;
305 }
306 else if (step_r > 0) {
307 cpl_array_delete(sky_indexes);
308 cpl_table_set_size(sky_stare_table, nstart);
309 sky_indexes =
310 moo_select_sky(targname, indextarg, obj_index, obj_targalpha,
311 obj_targdelta, target_table, index_colname,
312 sky_stare_table, type, maxdistslit, mintrans,
313 min_sky, radius + step_r, step_r, target_table_idx,
314 f2f, allsky_indexes);
315 }
316 else {
317 cpl_array_delete(sky_indexes);
318 sky_indexes = NULL;
319 cpl_error_set_message(
320 "sub_sky_stare", CPL_ERROR_EOL,
321 "for indextarg %d "
322 "filtering distslit: %d valid sky fibre, "
323 "filtering mintrans: %d valid sky fibre, "
324 "after using sky ditance filter with radius=%f : "
325 "not enough sky fibre (%d) for object indexrbn: %d",
326 indextarg, nb_valid_distslit, nb_valid_trans, radius, nb_valid,
327 obj_index);
328 return sky_indexes;
329 }
330 return sky_indexes;
331}
332
333static moo_sci_single *
334_moo_sub_sky_stare_single(moo_rbn_single *obja_rbn_single,
335 cpl_table *obja_fibre_table,
336 double ea,
337 moo_target_table *target_table,
338 moo_rbn_single *objb_rbn_single,
339 cpl_table *objb_fibre_table,
340 double eb,
341 moo_f2f *f2f,
342 const cpl_frame *solflux_frame,
343 const cpl_frame *airglow_group_frame,
344 const cpl_frame *airglow_var_frame,
345 moo_sub_sky_stare_params *params,
346 cpl_array *obja_sky_indexes,
347 cpl_array *objb_sky_indexes,
348 cpl_array *targ_obj_indexes,
349 cpl_propertylist *pheader,
350 const char *filename,
351 int ispaired)
352{
353 moo_sci_single *sci_single = NULL;
354 cpl_array *valid_targets_indexes = NULL;
355 cpl_table *sky_stare_table = NULL;
356 cpl_errorstate prestate = cpl_errorstate_get();
357
358 cpl_ensure(obja_rbn_single != NULL, CPL_ERROR_NULL_INPUT, NULL);
359 cpl_ensure(objb_rbn_single != NULL, CPL_ERROR_NULL_INPUT, NULL);
360 cpl_ensure(target_table != NULL, CPL_ERROR_NULL_INPUT, NULL);
361 cpl_ensure(params != NULL, CPL_ERROR_NULL_INPUT, NULL);
362 cpl_ensure(obja_sky_indexes != NULL, CPL_ERROR_NULL_INPUT, NULL);
363 cpl_ensure(objb_sky_indexes != NULL, CPL_ERROR_NULL_INPUT, NULL);
364 cpl_ensure(targ_obj_indexes != NULL, CPL_ERROR_NULL_INPUT, NULL);
365
366 int nb_target = (int)cpl_array_get_size(targ_obj_indexes);
367
368 if (nb_target == 0) {
369 cpl_msg_warning("sub_sky_stare", "No targets in stare mode");
370 cpl_table_set_size(target_table->table, 0);
371 return NULL;
372 }
373
374 sci_single = moo_sci_single_new(obja_rbn_single->type);
375 double crpix1 = moo_pfits_get_crpix1(obja_rbn_single->header);
376 double crval1 = moo_pfits_get_crval1(obja_rbn_single->header);
377 double cd1_1 = moo_pfits_get_cd1_1(obja_rbn_single->header);
378
379 moo_pfits_append_hduclass_data(sci_single->header, sci_single->type, -1);
380 cpl_propertylist_copy_property(sci_single->header, obja_rbn_single->header,
381 MOO_PFITS_CRPIX1);
382 cpl_propertylist_copy_property(sci_single->header, obja_rbn_single->header,
383 MOO_PFITS_CRVAL1);
384 cpl_propertylist_copy_property(sci_single->header, obja_rbn_single->header,
385 MOO_PFITS_CD1_1);
386 cpl_propertylist_copy_property(sci_single->header, obja_rbn_single->header,
387 MOO_PFITS_CD1_2);
388 cpl_propertylist_copy_property(sci_single->header, obja_rbn_single->header,
389 MOO_PFITS_CUNIT1);
390 cpl_propertylist_copy_property(sci_single->header, obja_rbn_single->header,
391 MOO_PFITS_CTYPE1);
392 cpl_propertylist_copy_property(sci_single->header, obja_rbn_single->header,
393 MOO_PFITS_BUNIT);
394 cpl_propertylist_copy_property(sci_single->header, obja_rbn_single->header,
395 MOO_PFITS_CRPIX2);
396 cpl_propertylist_copy_property(sci_single->header, obja_rbn_single->header,
397 MOO_PFITS_CRVAL2);
398 cpl_propertylist_copy_property(sci_single->header, obja_rbn_single->header,
399 MOO_PFITS_CD2_1);
400 cpl_propertylist_copy_property(sci_single->header, obja_rbn_single->header,
401 MOO_PFITS_CD2_2);
402 cpl_propertylist_copy_property(sci_single->header, obja_rbn_single->header,
403 MOO_PFITS_CTYPE2);
404 cpl_propertylist_copy_property(sci_single->header, obja_rbn_single->header,
405 MOO_PFITS_WAVELMIN);
406 cpl_propertylist_copy_property(sci_single->header, obja_rbn_single->header,
407 MOO_PFITS_WAVELMAX);
408 cpl_propertylist_copy_property(sci_single->header, obja_rbn_single->header,
409 MOO_PFITS_SPECBIN);
410 int nx = hdrl_image_get_size_x(obja_rbn_single->image);
411
412 sci_single->image = hdrl_image_new(nx, nb_target);
413 sci_single->sky = cpl_image_new(nx, nb_target, CPL_TYPE_DOUBLE);
414 sci_single->qual = cpl_image_new(nx, nb_target, CPL_TYPE_INT);
415 sci_single->filename = filename;
416
417 cpl_image *sci_img = hdrl_image_get_image(sci_single->image);
418 /* create the mask if empty */
419 cpl_image_get_bpm(sci_img);
420
421 cpl_image *sci_err_img = hdrl_image_get_error(sci_single->image);
422 cpl_image *sci_qual_img = sci_single->qual;
423
424 int *indexrbnt =
425 cpl_table_get_data_int(target_table->table, MOO_TARGET_TABLE_INDEXRBN);
426 int *pindexrbnt = cpl_table_get_data_int(target_table->table,
427 MOO_TARGET_TABLE_PAIREDINDEXRBN);
428 int *indexestarg =
429 cpl_table_get_data_int(target_table->table, MOO_TARGET_TABLE_INDEXTARG);
430 const char **fibret =
431 cpl_table_get_data_string_const(target_table->table,
432 MOO_TARGET_TABLE_FIBRE);
433 const char **targnames =
434 cpl_table_get_data_string_const(target_table->table,
435 MOO_TARGET_TABLE_TARGNAME);
436 double *targalphat = cpl_table_get_data_double(target_table->table,
437 MOO_TARGET_TABLE_TARGALPHA);
438 double *targdeltat = cpl_table_get_data_double(target_table->table,
439 MOO_TARGET_TABLE_TARGDELTA);
440 /* add objects -sky */
441 const char **obstypet =
442 cpl_table_get_data_string_const(target_table->table,
443 MOO_TARGET_TABLE_OBSTYPE);
444
445 cpl_table_unselect_all(target_table->table);
446 for (int i = 0; i < nb_target; i++) {
447 int obj_idx = cpl_array_get_cplsize(targ_obj_indexes, i, NULL);
448 cpl_table_set_int(target_table->table, MOO_TARGET_TABLE_INDEXTARG,
449 obj_idx, i + 1);
450 cpl_table_set_string(target_table->table, MOO_TARGET_TABLE_SUBSKYMODE,
451 obj_idx, MOO_TARGET_TABLE_SUBSKY_STARE);
452 const char *obstype = obstypet[obj_idx];
453 int is_stare = moo_is_obstype_stare(obstype);
454
455 cpl_table_set_int(target_table->table, MOO_TARGET_TABLE_NBSKY, obj_idx,
456 0);
457 cpl_table_set_int(target_table->table, MOO_TARGET_TABLE_MAX_DIST_SLIT,
458 obj_idx, 0);
459 cpl_table_set_double(target_table->table, MOO_TARGET_TABLE_MEDSNRRI_SCI,
460 obj_idx, 0);
461
462 cpl_table_set_double(target_table->table, MOO_TARGET_TABLE_MEDSNRYJ_SCI,
463 obj_idx, 0);
464 cpl_table_set_double(target_table->table, MOO_TARGET_TABLE_MEDSNRH_SCI,
465 obj_idx, 0);
466 if (is_stare == 1) {
467 cpl_table_select_row(target_table->table, obj_idx);
468 }
469 }
470
471 valid_targets_indexes = cpl_table_where_selected(target_table->table);
472 int nb_valid_targets = cpl_array_get_size(valid_targets_indexes);
473 if (strcmp(params->method, MOO_SUB_SKY_STARE_METHOD_NONE) != 0) {
474 sky_stare_table = cpl_table_new(0);
475 cpl_table_new_column(sky_stare_table, MOO_SKY_STARE_INDEXTARG,
476 CPL_TYPE_INT);
477 cpl_table_new_column(sky_stare_table, MOO_SKY_STARE_TARGNAME,
478 CPL_TYPE_STRING);
479 cpl_table_new_column(sky_stare_table, MOO_SKY_STARE_INDEXRBN,
480 CPL_TYPE_INT);
481 cpl_table_new_column(sky_stare_table, MOO_SKY_STARE_SKYINDEXRBN,
482 CPL_TYPE_INT);
483 cpl_table_new_column(sky_stare_table, MOO_SKY_STARE_SKYDSLIT,
484 CPL_TYPE_INT);
485 cpl_table_new_column(sky_stare_table, MOO_SKY_STARE_SKYTRANS,
486 CPL_TYPE_DOUBLE);
487 cpl_table_new_column(sky_stare_table, MOO_SKY_STARE_RADIUS,
488 CPL_TYPE_DOUBLE);
489 cpl_table_new_column(sky_stare_table, MOO_SKY_STARE_SKYDIST,
490 CPL_TYPE_DOUBLE);
491 int *nbsky =
492 cpl_table_get_data_int(target_table->table, MOO_TARGET_TABLE_NBSKY);
493 int *maxdslit = cpl_table_get_data_int(target_table->table,
494 MOO_TARGET_TABLE_MAX_DIST_SLIT);
495 float *maxdsky =
496 cpl_table_get_data_float(target_table->table,
497 MOO_TARGET_TABLE_MAX_DIST_SKY);
498
499 for (int i = 0; i < nb_valid_targets; i++) {
500 int idx = cpl_array_get_cplsize(valid_targets_indexes, i, NULL);
501 int indextarg = indexestarg[idx];
502 int indexrbn = indexrbnt[idx];
503
504 const char *targname = targnames[idx];
505 const char *obstype = obstypet[idx];
506 double obj_targalpha = targalphat[idx];
507 double obj_targdelta = targdeltat[idx];
508 cpl_array *sky_indexes = NULL;
509 cpl_table *obj_table = NULL;
510 cpl_table *allsky_table = target_table->table;
511 cpl_array *allsky_indexes = NULL;
512 const char *allsky_table_indexcol = MOO_FIBRES_TABLE_INDEXRBN;
513
514 if (strcmp(MOO_OBSTYPE_OBSNODSTARE, obstype) == 0 ||
515 strcmp(MOO_OBSTYPE_OBSPSTARE, obstype) == 0 ||
516 strcmp(MOO_OBSTYPE_SKYRESPSTARE, obstype) == 0 ||
517 (strcmp(MOO_OBSTYPE_OBSSWITCHSTARE, obstype) == 0 &&
518 ispaired)) {
519 obj_table = objb_fibre_table;
520 allsky_table = obja_fibre_table;
521 allsky_indexes = obja_sky_indexes;
522 }
523 else {
524 obj_table = obja_fibre_table;
525 allsky_table = objb_fibre_table;
526 allsky_indexes = objb_sky_indexes;
527 }
528
529 cpl_table_select_all(obj_table);
530 cpl_table_and_selected_int(obj_table, MOO_FIBRES_TABLE_INDEXRBN,
531 CPL_EQUAL_TO, indexrbn);
532 cpl_array *sel = cpl_table_where_selected(obj_table);
533 int ft_idx = cpl_array_get_cplsize(sel, 0, NULL);
534 cpl_array_delete(sel);
535 const char *fibre =
536 cpl_table_get_string(obj_table, MOO_FIBRES_TABLE_FIBRE, ft_idx);
537 cpl_table_set_string(target_table->table, MOO_TARGET_TABLE_FIBRE,
538 idx, fibre);
539 moo_target_table_set_snr(target_table, idx, obj_table, ft_idx);
540 moo_try_check(sky_indexes = moo_select_sky(
541 targname, indextarg, indexrbn, obj_targalpha,
542 obj_targdelta, allsky_table,
543 allsky_table_indexcol, sky_stare_table,
544 obja_rbn_single->type, params->maxdistslit,
545 params->min_trans, params->min_sky,
546 params->radius_sky, params->step_r, idx, f2f,
547 allsky_indexes),
548 " ");
549
550 int nb_sky = cpl_table_and_selected_int(sky_stare_table,
551 MOO_SKY_STARE_INDEXTARG,
552 CPL_EQUAL_TO, indextarg);
553
554 int max_dslit = 0;
555 float max_dsky = 0.0;
556 if (nb_sky > 0) {
557 cpl_table *subtable =
558 cpl_table_extract_selected(sky_stare_table);
559 max_dslit =
560 cpl_table_get_column_max(subtable, MOO_SKY_STARE_SKYDSLIT);
561 max_dsky =
562 cpl_table_get_column_max(subtable, MOO_SKY_STARE_SKYDIST);
563 int all = cpl_array_get_size(allsky_indexes);
564 cpl_msg_debug(
565 __func__,
566 "---do %s %d %d %.3f %.3f %s => all:%d, sel:%d, %d",
567 targname, indextarg, indexrbn, obj_targalpha, obj_targdelta,
568 obstype, all, nb_sky, max_dslit);
569 cpl_table_delete(subtable);
570 }
571 nbsky[idx] = nb_sky;
572 maxdslit[idx] = max_dslit;
573 maxdsky[idx] = max_dsky;
574 cpl_array_delete(sky_indexes);
575 }
576 }
577/* The following addresses an issue with the gcc9 compiler series prior to
578 * gcc 9.3. These compiler versions require that the variable '__func__'
579 * appears in the data sharing clause if default(none) is used. However
580 * adding it to the data sharing clause breaks older compiler versions
581 * where these variables are pre-determined as shared.
582 * This was fixed in gcc 9.3 and OpenMP 5.1.
583 */
584#ifdef _OPENMP
585#if (__GNUC__ == 9) && (__GNUC_MINOR__ < 3)
586#pragma omp parallel shared(nb_target, indexrbnt, pindexrbnt, fibret, \
587 indexestarg, target_table, obstypet, ispaired, \
588 nb_valid_targets, valid_targets_indexes, \
589 sky_stare_table, obja_rbn_single, \
590 objb_rbn_single, params, sci_single, \
591 sci_qual_img, crpix1, crval1, cd1_1, sci_img, \
592 sci_err_img, nx, airglow_var_frame, pheader, \
593 solflux_frame, airglow_group_frame, ea, eb)
594#else
595#pragma omp parallel default(none) \
596 shared(nb_target, indexrbnt, pindexrbnt, fibret, indexestarg, \
597 target_table, obstypet, ispaired, nb_valid_targets, \
598 valid_targets_indexes, sky_stare_table, obja_rbn_single, \
599 objb_rbn_single, params, sci_single, sci_qual_img, crpix1, \
600 crval1, cd1_1, sci_img, sci_err_img, nx, airglow_var_frame, \
601 pheader, solflux_frame, airglow_group_frame, ea, eb)
602#endif
603 {
604#pragma omp for
605#endif
606
607 for (int i = 0; i < nb_valid_targets; i++) {
608 hdrl_image *median_sky = NULL;
609 int idx = cpl_array_get_cplsize(valid_targets_indexes, i, NULL);
610 int rbn_idx = indexrbnt[idx];
611 int targ_idx = indexestarg[idx];
612 const char *obstype = obstypet[idx];
613 const char *fibre = fibret[idx];
614 moo_rbn_single *obj_rbn_single = NULL;
615 moo_rbn_single *sky_rbn_single = NULL;
616 double sky_rescale = 1.0;
617 const char *method = params->method;
618
619 if (strcmp(MOO_OBSTYPE_OBSNODSTARE, obstype) == 0 ||
620 strcmp(MOO_OBSTYPE_OBSPSTARE, obstype) == 0 ||
621 strcmp(MOO_OBSTYPE_SKYRESPSTARE, obstype) == 0 ||
622 (strcmp(MOO_OBSTYPE_OBSSWITCHSTARE, obstype) == 0 &&
623 ispaired)) {
624 cpl_msg_debug(__func__, "---do B-A");
625 obj_rbn_single = objb_rbn_single;
626 sky_rbn_single = obja_rbn_single;
627 }
628 else {
629 cpl_msg_debug(__func__, "---do A-B");
630 obj_rbn_single = obja_rbn_single;
631 sky_rbn_single = objb_rbn_single;
632 sky_rescale = ea / eb;
633 }
634 cpl_image *obj_rbn_img =
635 hdrl_image_get_image(obj_rbn_single->image);
636 cpl_image *obj_rbn_err_img =
637 hdrl_image_get_error(obj_rbn_single->image);
638 cpl_image *obj_rbn_qual_img = obj_rbn_single->qual;
639 if (strcmp(method, MOO_SUB_SKY_STARE_METHOD_NONE) == 0) {
640 double *rbn_img_data = cpl_image_get_data_double(obj_rbn_img);
641 for (int j = 1; j <= nx; j++) {
642 int rej;
643 double rbn_img_val =
644 rbn_img_data[j - 1 + (rbn_idx - 1) * nx];
645 double sci_flux = rbn_img_val;
646 cpl_image_set(sci_img, j, targ_idx, sci_flux);
647 double rbn_err_val =
648 cpl_image_get(obj_rbn_err_img, j, rbn_idx, &rej);
649 double err = rbn_err_val;
650 cpl_image_set(sci_err_img, j, targ_idx, err);
651 double rbn_qual_val =
652 cpl_image_get(obj_rbn_qual_img, j, rbn_idx, &rej);
653
654 cpl_image_set(sci_qual_img, j, targ_idx, rbn_qual_val);
655 }
656 }
657 else {
658 cpl_array *sky_indexes = NULL;
659 cpl_table *private_table = cpl_table_duplicate(sky_stare_table);
660 cpl_table_select_all(private_table);
661 int *sky_indexrbn =
662 cpl_table_get_data_int(private_table,
663 MOO_SKY_STARE_SKYINDEXRBN);
664 int nb_sky = cpl_table_and_selected_int(private_table,
665 MOO_SKY_STARE_INDEXRBN,
666 CPL_EQUAL_TO, rbn_idx);
667 int max_dslit = 0;
668 if (nb_sky > 0) {
669 cpl_table *subtable =
670 cpl_table_extract_selected(private_table);
671 max_dslit =
672 cpl_table_get_column_max(subtable,
673 MOO_SKY_STARE_SKYDSLIT);
674 cpl_table_delete(subtable);
675 }
676 cpl_msg_debug(__func__,
677 "---do indextarg %d indexrbn %d nb_sky %d "
678 "max_dist_slit %d %d",
679 targ_idx, rbn_idx, nb_sky, max_dslit,
680 cpl_error_get_code());
681
682 sky_indexes = cpl_table_where_selected(private_table);
683
684 median_sky = _moo_create_median_sky(sky_indexes, sky_indexrbn,
685 sky_rbn_single->image);
686
687 hdrl_value srescale = { .data = sky_rescale, .error = 0 };
688 hdrl_image_mul_scalar(median_sky, srescale);
689 if (nb_sky == 0) {
690 cpl_msg_info(
691 "sub_sky_stare",
692 "no SKY fibre for fibre indexrbn %d with name %s "
693 ": median sky is 0",
694 rbn_idx, fibre);
695 }
696 cpl_table_delete(private_table);
697 cpl_array_delete(sky_indexes);
698
699 if (median_sky != NULL) {
700 if (strcmp(method, MOO_SUB_SKY_STARE_METHOD_SIMPLE) == 0) {
701 double *rbn_img_data =
702 cpl_image_get_data_double(obj_rbn_img);
703 for (int j = 1; j <= nx; j++) {
704 int rej;
705 hdrl_value sky_val =
706 hdrl_image_get_pixel(median_sky, j, 1, &rej);
707 cpl_image_set(sci_single->sky, j, targ_idx,
708 sky_val.data);
709 double rbn_img_val =
710 rbn_img_data[j - 1 + (rbn_idx - 1) * nx];
711 double sci_flux = rbn_img_val - sky_val.data;
712 cpl_image_set(sci_img, j, targ_idx, sci_flux);
713 double rbn_err_val =
714 cpl_image_get(obj_rbn_err_img, j, rbn_idx,
715 &rej);
716 double err = sqrt(rbn_err_val * rbn_err_val +
717 sky_val.error * sky_val.error);
718 cpl_image_set(sci_err_img, j, targ_idx, err);
719 double rbn_qual_val =
720 cpl_image_get(obj_rbn_qual_img, j, rbn_idx,
721 &rej);
722
723 cpl_image_set(sci_qual_img, j, targ_idx,
724 rbn_qual_val);
725 }
726 }
727 else {
728 moo_skycorr(obj_rbn_single->image, median_sky, targ_idx,
729 rbn_idx, crpix1, crval1, cd1_1, pheader,
730 solflux_frame, airglow_group_frame,
731 airglow_var_frame, params->sk,
732 sci_single->image, sci_single->sky);
733 }
734 hdrl_image_delete(median_sky);
735 }
736 }
737 }
738#ifdef _OPENMP
739 }
740#endif
741
742moo_try_cleanup:
743#if MOO_DEBUG_SKY
744 if (sky_stare_table != NULL) {
745 char *sky_stare_table_name =
746 cpl_sprintf("SKY_TABLE_%s_%s", obja_rbn_single->extname, filename);
747 cpl_table_save(sky_stare_table, NULL, NULL, sky_stare_table_name,
748 CPL_IO_CREATE);
749 cpl_free(sky_stare_table_name);
750 }
751#endif
752 cpl_array_delete(valid_targets_indexes);
753 cpl_table_delete(sky_stare_table);
754 if (!cpl_errorstate_is_equal(prestate)) {
755 cpl_error_set_message(__func__, CPL_ERROR_ILLEGAL_OUTPUT,
756 "Error in sky subtraction %s",
757 obja_rbn_single->extname);
758 moo_sci_single_delete(sci_single);
759 sci_single = NULL;
760 }
761 return sci_single;
762}
763
764static cpl_propertylist *
765_moo_create_primary_header(cpl_propertylist *rbn_primary_header)
766{
767 cpl_propertylist *primary_header = NULL;
768
769 primary_header = cpl_propertylist_new();
770 cpl_propertylist_copy_property(primary_header, rbn_primary_header,
771 MOO_PFITS_EXPTIME);
772 cpl_propertylist_copy_property(primary_header, rbn_primary_header,
773 MOO_PFITS_MJDOBS);
774 cpl_propertylist_copy_property_regexp(primary_header, rbn_primary_header,
775 "TM*", 0);
776 cpl_propertylist_copy_property_regexp(primary_header, rbn_primary_header,
777 "ESO QC IS*", 0);
778 cpl_propertylist_copy_property(primary_header, rbn_primary_header,
779 MOO_PFITS_FLUXCAL);
780
781 return primary_header;
782}
783/*----------------------------------------------------------------------------*/
808/*----------------------------------------------------------------------------*/
809moo_sci *
810moo_sub_sky_stare(moo_rbn *obja_rbn,
811 moo_target_table *target_table,
812 moo_rbn *objb_rbn,
813 moo_f2f *f2f,
814 const cpl_frame *solflux_frame,
815 const cpl_frame *airglow_group_frame,
816 const cpl_frame *airglow_var_frame,
817 moo_sub_sky_stare_params *params,
818 const char *filename,
819 int ispaired)
820{
821 moo_sci *sci = NULL;
822
823 cpl_ensure(obja_rbn != NULL, CPL_ERROR_NULL_INPUT, NULL);
824 cpl_ensure(objb_rbn != NULL, CPL_ERROR_NULL_INPUT, NULL);
825 cpl_ensure(target_table != NULL, CPL_ERROR_NULL_INPUT, NULL);
826 cpl_ensure(params != NULL, CPL_ERROR_NULL_INPUT, NULL);
827
828 cpl_array *objb_sky_indexes = NULL;
829 cpl_array *obja_sky_indexes = NULL;
830 cpl_array *targ_obj_indexes = NULL;
831 moo_target_table *sci_target_table = NULL;
832
833 cpl_errorstate prestate = cpl_errorstate_get();
834
835 unsigned int badpix_level =
837
838 moo_fits_create(filename);
839 sci = moo_sci_new();
840 sci->filename = filename;
841 sci->primary_header = _moo_create_primary_header(obja_rbn->primary_header);
842 cpl_msg_info(
843 __func__,
844 "Substract sky stare with method %s "
845 "using maxdistslit %d, mintrans %f, and radius (%f+%f) and min sky %d",
846 params->method, params->maxdistslit, params->min_trans,
847 params->radius_sky, params->step_r, params->min_sky);
848
849 if (f2f != NULL) {
851 }
852 double exptimeA[3];
853 double exptimeB[3];
854 exptimeA[0] = moo_pfits_get_exptime(obja_rbn->primary_header);
855 exptimeB[0] = moo_pfits_get_exptime(objb_rbn->primary_header);
856 for (int i = 1; i < 3; i++) {
857 moo_rbn_single *obja_rbn_single = moo_rbn_get_single(obja_rbn, i);
858 moo_rbn_single *objb_rbn_single = moo_rbn_get_single(objb_rbn, i);
859 exptimeA[i] = 0;
860 exptimeB[i] = 0;
861 if (obja_rbn_single != NULL) {
862 cpl_propertylist *header =
863 moo_rbn_single_get_header(obja_rbn_single);
864
865 double dit = moo_pfits_get_dit(header);
866 int ndit = moo_pfits_get_ndit(header);
867
868 exptimeA[i] = ndit * dit;
869 }
870 if (objb_rbn_single != NULL) {
871 cpl_propertylist *header =
872 moo_rbn_single_get_header(objb_rbn_single);
873
874 double dit = moo_pfits_get_dit(header);
875 int ndit = moo_pfits_get_ndit(header);
876
877 exptimeB[i] = ndit * dit;
878 }
879 }
880 sci_target_table = moo_target_table_duplicate(target_table);
881 moo_target_table_set_exptimes(sci_target_table, exptimeA, exptimeB);
882
883 sci->target_table = sci_target_table;
884
885 targ_obj_indexes =
886 moo_target_table_select_obj_index(sci_target_table, ispaired);
887 objb_sky_indexes =
888 moo_target_table_select_sky_index(sci_target_table, objb_rbn);
889 obja_sky_indexes =
890 moo_target_table_select_sky_index(sci_target_table, obja_rbn);
891
892 cpl_msg_indent_more();
893 cpl_table *obja_fibre_table = moo_rbn_get_fibre_table(obja_rbn);
894 cpl_table *objb_fibre_table = moo_rbn_get_fibre_table(objb_rbn);
895 if (ispaired) {
896 moo_target_table_xswitch_paired(sci_target_table);
897 }
898
899 for (int i = 0; i < 3; i++) {
900 moo_sci_single *sci_single = NULL;
901 moo_rbn_single *obja_rbn_single =
902 moo_rbn_load_single(obja_rbn, i, badpix_level);
903 moo_rbn_single *objb_rbn_single = NULL;
904
905 if (obja_rbn_single != NULL) {
906 cpl_msg_info(__func__, "Substract sky stare extension %s",
907 obja_rbn_single->extname);
908 objb_rbn_single = moo_rbn_load_single(objb_rbn, i, badpix_level);
909 double ea = exptimeA[i];
910 double eb = exptimeB[i];
911 moo_try_check(sci_single = _moo_sub_sky_stare_single(
912 obja_rbn_single, obja_fibre_table, ea,
913 sci_target_table, objb_rbn_single,
914 objb_fibre_table, eb, f2f, solflux_frame,
915 airglow_group_frame, airglow_var_frame, params,
916 obja_sky_indexes, objb_sky_indexes,
917 targ_obj_indexes, obja_rbn->primary_header,
918 filename, ispaired),
919 " ");
920 }
921 moo_sci_add_single(sci, i, sci_single);
922 }
923 cpl_msg_indent_less();
924 int nrow = cpl_table_get_nrow(sci_target_table->table);
925
926 for (int i = 0; i < nrow; i++) {
927 if (!cpl_table_is_selected(sci_target_table->table, i)) {
928 cpl_table_set_invalid(sci_target_table->table,
929 MOO_TARGET_TABLE_INDEXTARG, i);
930 }
931 }
932 if (nrow > 0) {
933 cpl_table_erase_invalid(sci_target_table->table);
934 }
935 moo_sci_add_target_table(sci, sci_target_table);
936
937moo_try_cleanup:
938 cpl_array_delete(obja_sky_indexes);
939 cpl_array_delete(objb_sky_indexes);
940 cpl_array_delete(targ_obj_indexes);
941
942 if (!cpl_errorstate_is_equal(prestate)) {
943 // cpl_errorstate_dump(prestate, CPL_FALSE, cpl_errorstate_dump_one);
944 // Recover from the error(s) (Reset to prestate))
945 // cpl_errorstate_set(prestate);
946 cpl_error_set_message(__func__, CPL_ERROR_ILLEGAL_OUTPUT,
947 "Error in sky subtraction");
948 moo_sci_delete(sci);
949 sci = NULL;
950 }
951 return sci;
952}
#define MOO_BADPIX_OUTSIDE_DATA_RANGE
Definition: moo_badpix.h:62
#define MOO_BADPIX_CALIB_DEFECT
Definition: moo_badpix.h:48
enum _moo_detector_type_ moo_detector_type
The type code type.
Definition: moo_detector.h:64
const char * moo_f2f_get_trans_colname(moo_f2f *self, moo_detector_type type)
Get transmission column name from table.
Definition: moo_f2f.c:260
cpl_error_code moo_f2f_order_by_indexrbn(moo_f2f *self)
Order F2F by INDEXRBN (ASC)
Definition: moo_f2f.c:169
cpl_error_code moo_fits_create(const char *filename)
Create a new fits file with empty propertylist.
Definition: moo_fits.c:533
cpl_propertylist * moo_rbn_single_get_header(moo_rbn_single *self)
Get header of rbn single.
moo_rbn_single * moo_rbn_load_single(moo_rbn *self, moo_detector_type type, unsigned int level)
Load the type part in RBN and return it.
Definition: moo_rbn.c:360
moo_rbn_single * moo_rbn_get_single(moo_rbn *self, moo_detector_type type)
Get a RBN single from RBN.
Definition: moo_rbn.c:325
cpl_table * moo_rbn_get_fibre_table(moo_rbn *self)
Get the FIBRE TABLE in RBN.
Definition: moo_rbn.c:397
moo_sci_single * moo_sci_single_new(moo_detector_type type)
Create a new moo_sci_single.
void moo_sci_single_delete(moo_sci_single *self)
Delete a moo_sci_single.
cpl_error_code moo_sci_add_target_table(moo_sci *self, moo_target_table *table)
Add target table to SCI file and update moo_sci structure.
Definition: moo_sci.c:132
void moo_sci_delete(moo_sci *self)
Delete a moo_sci.
Definition: moo_sci.c:84
moo_sci * moo_sci_new(void)
Create a new moo_sci.
Definition: moo_sci.c:66
cpl_error_code moo_sci_add_single(moo_sci *self, moo_detector_type type, moo_sci_single *single)
Add SCI_SINGLE extension to SCI file and update moo_sci structure.
Definition: moo_sci.c:216
cpl_array * moo_target_table_select_sky_index(moo_target_table *self, moo_rbn *sky_rbn)
get the index of the sky in the target table sort by indexspec
moo_target_table * moo_target_table_duplicate(moo_target_table *self)
Duplicate an existing target_table.
int moo_target_table_xswitch_paired(moo_target_table *self)
get the index of the object in the target table sort by indexrbn
cpl_array * moo_target_table_select_obj_index(moo_target_table *self, int ispaired)
get the index of the object in the target table sort by indexrbn
cpl_array * moo_select_sky(const char *targname, int indextarg, int obj_index, double obj_targalpha, double obj_targdelta, cpl_table *target_table, const char *index_colname, cpl_table *sky_stare_table, moo_detector_type type, int maxdistslit, double mintrans, int min_sky, double radius, double step_r, int target_table_idx, moo_f2f *f2f, cpl_array *allsky_indexes)
This function selects sky fibres around a target object.
moo_sci * moo_sub_sky_stare(moo_rbn *obja_rbn, moo_target_table *target_table, moo_rbn *objb_rbn, moo_f2f *f2f, const cpl_frame *solflux_frame, const cpl_frame *airglow_group_frame, const cpl_frame *airglow_var_frame, moo_sub_sky_stare_params *params, const char *filename, int ispaired)
This function subtracts the sky in wavelength calibrated and extracted science frames obtain in Stare...
int moo_pfits_get_ndit(const cpl_propertylist *plist)
find out the ESO DET NDIT value
Definition: moo_pfits.c:382
double moo_pfits_get_cd1_1(const cpl_propertylist *plist)
find out the CD1_1 value
Definition: moo_pfits.c:1256
double moo_pfits_get_dit(const cpl_propertylist *plist)
find out the DIT value
Definition: moo_pfits.c:362
cpl_error_code moo_pfits_append_hduclass_data(cpl_propertylist *plist, moo_detector_type type, int ntas)
Set the HDUCLASS DATA Keyword.
Definition: moo_pfits.c:1504
double moo_pfits_get_crval1(const cpl_propertylist *plist)
find out the CRVAL1 value
Definition: moo_pfits.c:1176
double moo_pfits_get_crpix1(const cpl_propertylist *plist)
find out the CRPIX1 value
Definition: moo_pfits.c:1196
double moo_pfits_get_exptime(const cpl_propertylist *plist)
find out the EXPTIME value
Definition: moo_pfits.c:1039
cpl_error_code moo_skycorr(hdrl_image *rbn, hdrl_image *sky, int indextarg, int indexrbn, double crpix1, double crval1, double cd1_1, cpl_propertylist *header, const cpl_frame *solflux_frame, const cpl_frame *airglow_group_frame, const cpl_frame *airglow_var_frame, moo_skycorr_params *params, hdrl_image *sci, cpl_image *sci_sky)
call the skycorr subtract sky function
Definition: moo_skycorr.c:939
double moo_sky_distance(double alpha1, double delta1, double alpha2, double delta2)
Compute sky distance (in rad)
Definition: moo_utils.c:1417
hdrl_image * moo_image_collapse_median_create(hdrl_image *image)
Collapse row of an image using a median and compute associate error.
Definition: moo_utils.c:1386
the different type of detectors