MOONS Pipeline Reference Manual 0.13.2
moo_map.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 <cpl.h>
29#include "moo_detector.h"
30#include "moo_pfits.h"
31#include "moo_fits.h"
32#include "moo_qc.h"
33#include "moo_map.h"
34#include "moo_fibres_table.h"
35#include "moo_line_table.h"
36/*----------------------------------------------------------------------------*/
50/*----------------------------------------------------------------------------*/
51
54/*-----------------------------------------------------------------------------
55 Function codes
56 -----------------------------------------------------------------------------*/
57
58/*----------------------------------------------------------------------------*/
66/*----------------------------------------------------------------------------*/
67moo_map *
69{
70 moo_map *res = cpl_calloc(1, sizeof(moo_map));
71 return res;
72}
73
74/*----------------------------------------------------------------------------*/
81/*----------------------------------------------------------------------------*/
82
83cpl_table *
85{
86 cpl_table *result = NULL;
87 cpl_ensure(self != NULL, CPL_ERROR_NULL_INPUT, NULL);
88
89 if (self->line_table != NULL) {
90 result = self->line_table;
91 }
92 else {
93 if (self->filename != NULL) {
94 cpl_size qnum =
95 cpl_fits_find_extension(self->filename, MOO_LINE_TABLE_EXTNAME);
96 if (qnum > 0) {
97 self->line_table = cpl_table_load(self->filename, qnum, 0);
98 }
99 }
100 result = self->line_table;
101 }
102 return result;
103}
104/*----------------------------------------------------------------------------*/
105
106moo_map *
107moo_map_load(const cpl_frame *mapframe)
108{
109 cpl_ensure(mapframe != NULL, CPL_ERROR_NULL_INPUT, NULL);
110 const char *filename = cpl_frame_get_filename(mapframe);
111 cpl_ensure(filename != NULL, CPL_ERROR_NULL_INPUT, NULL);
112
113 cpl_errorstate prev_state = cpl_errorstate_get();
114 moo_map *res = moo_map_new();
115 res->filename = cpl_strdup(filename);
116 cpl_size qnum = cpl_fits_find_extension(filename, MOO_FIBRES_TABLE_EXTNAME);
117 if (qnum > 0) {
118 res->fibre_table = cpl_table_load(filename, qnum, 0);
119 }
120 cpl_errorstate_set(prev_state);
121
122 res->primary_header = cpl_propertylist_load(filename, 0);
123
124 for (int i = 0; i < 2; i++) {
125 for (int j = 0; j < 3; j++) {
126 const char *extname = moo_detector_get_extname(j, i + 1);
127
128 cpl_propertylist *header = NULL;
129 header = moo_fits_load_extension_header(filename, NULL, extname);
130 res->data_header[i * 3 + j] = header;
131
132 if (header != NULL) {
133 int naxis = moo_pfits_get_naxis(header);
134 if (naxis == 2) {
135 res->data[i * 3 + j] =
136 moo_fits_load_extension_image(filename, NULL, extname,
137 CPL_TYPE_FLOAT);
138 }
139 }
140 }
141 }
142 if (!cpl_errorstate_is_equal(prev_state)) {
143 cpl_errorstate_set(prev_state);
144 cpl_msg_error("moo_map", "Error in loading WAVE MAP %s", filename);
145 moo_map_delete(res);
146 res = NULL;
147 }
148
149 return res;
150}
151/*----------------------------------------------------------------------------*/
162/*----------------------------------------------------------------------------*/
163cpl_error_code
164moo_map_set_data(moo_map *self,
166 int ntas,
167 cpl_image *data,
168 cpl_propertylist *header)
169{
170 cpl_ensure_code(ntas >= 1 && ntas <= 2, CPL_ERROR_ILLEGAL_INPUT);
171 cpl_ensure_code(self != NULL, CPL_ERROR_NULL_INPUT);
172 cpl_ensure_code(header != NULL, CPL_ERROR_NULL_INPUT);
173
174 if (data != NULL) {
175 int nx = cpl_image_get_size_x(data);
176 int ny = cpl_image_get_size_y(data);
177 self->data[(ntas - 1) * 3 + type] = data;
178 cpl_array *wmintab = cpl_array_new(ny, CPL_TYPE_DOUBLE);
179 cpl_array *wmaxtab = cpl_array_new(ny, CPL_TYPE_DOUBLE);
180 for (int j = 1; j <= ny; j++) {
181 cpl_image *data_copy = cpl_image_extract(data, 1, j, nx, j);
182 cpl_image_reject_value(data_copy, CPL_VALUE_NAN);
183 int nbrej = cpl_image_count_rejected(data_copy);
184 if (nbrej < nx) {
185 double lmax = cpl_image_get_max(data_copy);
186 double lmin = cpl_image_get_min(data_copy);
187 cpl_array_set(wmintab, j - 1, lmin);
188 cpl_array_set(wmaxtab, j - 1, lmax);
189 }
190 cpl_image_delete(data_copy);
191 }
192 double wmin = cpl_array_get_median(wmintab);
193 double wmax = cpl_array_get_median(wmaxtab);
194 moo_qc_set_wave_min(header, wmin);
195 moo_qc_set_wave_max(header, wmax);
196 cpl_array_delete(wmaxtab);
197 cpl_array_delete(wmintab);
198 }
199 self->data_header[(ntas - 1) * 3 + type] = header;
200 return CPL_ERROR_NONE;
201}
202
203cpl_error_code
204moo_map_set_fibre_table(moo_map *self, cpl_table *fibre_table)
205{
206 cpl_ensure_code(self != NULL, CPL_ERROR_NULL_INPUT);
207 cpl_ensure_code(fibre_table != NULL, CPL_ERROR_NULL_INPUT);
208
209 self->fibre_table = fibre_table;
210
211 return CPL_ERROR_NONE;
212}
213
214cpl_error_code
215moo_map_set_line_table(moo_map *self, cpl_table *line_table)
216{
217 cpl_ensure_code(self != NULL, CPL_ERROR_NULL_INPUT);
218 cpl_ensure_code(line_table != NULL, CPL_ERROR_NULL_INPUT);
219
220 self->line_table = line_table;
221
222 return CPL_ERROR_NONE;
223}
224/*----------------------------------------------------------------------------*/
233/*----------------------------------------------------------------------------*/
234
235void
236moo_map_delete(moo_map *self)
237{
238 if (self != NULL) {
239 int i;
240 if (self->filename != NULL) {
241 cpl_free(self->filename);
242 }
243 if (self->primary_header != NULL) {
244 cpl_propertylist_delete(self->primary_header);
245 }
246 for (i = 0; i < 6; i++) {
247 if (self->data[i] != NULL) {
248 cpl_image_delete(self->data[i]);
249 }
250 if (self->data_header[i] != NULL) {
251 cpl_propertylist_delete(self->data_header[i]);
252 }
253 }
254 if (self->fibre_table != NULL) {
255 cpl_table_delete(self->fibre_table);
256 }
257 if (self->line_table != NULL) {
258 cpl_table_delete(self->line_table);
259 }
260 cpl_free(self);
261 }
262}
263/*----------------------------------------------------------------------------*/
273/*----------------------------------------------------------------------------*/
274void
275moo_map_save(moo_map *self, const char *filename)
276{
277 if (self != NULL) {
278 cpl_propertylist_save(self->primary_header, filename, CPL_IO_CREATE);
279
280 for (int i = 0; i < 2; i++) {
281 for (int j = 0; j < 3; j++) {
282 const char *extname = moo_detector_get_extname(j, i + 1);
283 moo_fits_write_extension_image(self->data[i * 3 + j], filename,
284 NULL, extname, CPL_TYPE_FLOAT,
285 self->data_header[i * 3 + j]);
286 }
287 }
288
289 if (self->fibre_table != NULL) {
290 cpl_propertylist *h = cpl_propertylist_new();
291 cpl_propertylist_append_string(h, MOO_PFITS_EXTNAME,
292 MOO_FIBRES_TABLE_EXTNAME);
293
294 cpl_table_save(self->fibre_table, h, h, filename, CPL_IO_EXTEND);
295 cpl_propertylist_delete(h);
296 }
297 if (self->line_table != NULL) {
298 cpl_propertylist *h = cpl_propertylist_new();
299 cpl_propertylist_append_string(h, MOO_PFITS_EXTNAME,
300 MOO_LINE_TABLE_EXTNAME);
301
302 cpl_table_save(self->line_table, h, h, filename, CPL_IO_EXTEND);
303 cpl_propertylist_delete(h);
304 }
305 }
306}
307
308/*----------------------------------------------------------------------------*/
318/*----------------------------------------------------------------------------*/
319cpl_error_code
320moo_map_check(moo_map *self, moo_spectral_format *sformat)
321{
322 cpl_error_code status = CPL_ERROR_NONE;
323 const char *monotonous_colnames[] = { MOO_FIBRES_TABLE_MONOTONOUS_RI,
324 MOO_FIBRES_TABLE_MONOTONOUS_YJ,
325 MOO_FIBRES_TABLE_MONOTONOUS_H };
326 if (self != NULL) {
327 cpl_table *fibre_table = self->fibre_table;
328 cpl_propertylist *primary_header = self->primary_header;
329
330 cpl_ensure_code(sformat != NULL, CPL_ERROR_NULL_INPUT);
331 cpl_msg_info(__func__, "Check WAVEMAP");
332 int gres = 1;
333 cpl_msg_indent_more();
334 for (int ntas = 1; ntas <= 2; ntas++) {
335 cpl_table_select_all(fibre_table);
336 int size =
337 cpl_table_and_selected_int(fibre_table, MOO_FIBRES_TABLE_HEALTH,
338 CPL_EQUAL_TO, 1);
339 size = cpl_table_and_selected_int(fibre_table,
340 MOO_FIBRES_TABLE_SPECTRO,
341 CPL_EQUAL_TO, ntas);
342 cpl_array *sel = cpl_table_where_selected(fibre_table);
343 for (int type = 0; type < 3; type++) {
344 cpl_image *orig_data = self->data[(ntas - 1) * 3 + type];
345 cpl_propertylist *header =
346 self->data_header[(ntas - 1) * 3 + type];
347 const char *monotonous_colname = monotonous_colnames[type];
348 if (orig_data != NULL) {
349 cpl_image *data = cpl_image_cast(orig_data, CPL_TYPE_FLOAT);
350 int nx = cpl_image_get_size_x(data);
351 const float *tdata = cpl_image_get_data_const(data);
352 moo_spectral_format_info *info =
353 moo_spectral_format_get(sformat, type, ntas);
354 int res = 1;
355 const char *band = moo_detector_get_name(type);
356
357 for (int j = 0; j < size; j++) {
358 int index = cpl_array_get_cplsize(sel, j, NULL);
359 int indexext =
360 cpl_table_get_int(fibre_table,
361 MOO_FIBRES_TABLE_INDEXEXT, index,
362
363 NULL);
364 const char *fibname =
365 cpl_table_get_string(fibre_table,
366 MOO_FIBRES_TABLE_FIBRE, index);
367 int first = 0;
368 while (first < nx &&
369 isnan(tdata[first + (indexext - 1) * nx])) {
370 first++;
371 }
372 int fres = 1;
373 if (first < (nx - 2)) {
374 double w1 = tdata[first + (indexext - 1) * nx];
375 double w2 = tdata[first + 1 + (indexext - 1) * nx];
376 double b1 = w1 - w2;
377
378 for (int i = first + 1; i < nx - 1; i++) {
379 w1 = tdata[i + (indexext - 1) * nx];
380 w2 = tdata[i + 1 + (indexext - 1) * nx];
381 double b2 = w1 - w2;
382
383 if (b1 * b2 < 0) {
384 cpl_msg_warning(
385 __func__,
386 "Not monotonous solution "
387 "for fibre %s band %s spectro %d",
388 fibname, band, ntas);
389 fres = 0;
390 res = 0;
391 break;
392 }
393 }
394 }
395 cpl_table_set_int(fibre_table, monotonous_colname,
396 index, fres);
397 }
399 if (res == 0) {
400 gres = res;
401 }
403 cpl_image_delete(data);
404 }
405 }
406 cpl_array_delete(sel);
407 }
408 moo_qc_set_wavecal_monotonous_solution(primary_header, gres);
409 cpl_msg_indent_less();
410 }
411 return status;
412}
413
414/*----------------------------------------------------------------------------*/
426/*----------------------------------------------------------------------------*/
427cpl_error_code
428moo_map_dump(const moo_map *self, FILE *stream)
429{
430 cpl_ensure_code(self != NULL, CPL_ERROR_NULL_INPUT);
431 cpl_ensure_code(stream != NULL, CPL_ERROR_NULL_INPUT);
432
433 fprintf(stream, "---MOO_MAP\n");
434
435 int i;
436 for (i = 0; i < 6; i++) {
437 if (self->data[i] != NULL) {
438 fprintf(stream, "data[%d] %p\n", i, self->data[i]);
439 if (self->data[i] != NULL) {
440 cpl_image_dump_structure(self->data[i], stream);
441 }
442 }
443 }
444 if (self->fibre_table) {
445 fprintf(stream, "fibre table %p\n", self->fibre_table);
446 }
447
448 return CPL_ERROR_NONE;
449}
450
451void
452moo_map_update_linetable(moo_map *self, moo_rbn *rbn)
453{
454 cpl_table *line_table = self->line_table;
455 int nrow = cpl_table_get_nrow(line_table);
456 cpl_table *fibre_table = rbn->fibre_table;
457
458 for (int i = 0; i < nrow; i++) {
459 const int spectro =
460 cpl_table_get_int(line_table, MOO_LINE_TABLE_SPECTRO, i, NULL);
461 int indexext =
462 cpl_table_get_int(line_table, MOO_LINE_TABLE_INDEXEXT, i, NULL);
463 if (indexext >= 0) {
464 cpl_table_select_all(fibre_table);
465 cpl_table_and_selected_int(fibre_table, MOO_FIBRES_TABLE_SPECTRO,
466 CPL_EQUAL_TO, spectro);
467 cpl_table_and_selected_int(fibre_table, MOO_FIBRES_TABLE_INDEXEXT,
468 CPL_EQUAL_TO, indexext);
469 cpl_array *sel = cpl_table_where_selected(fibre_table);
470 int idx = cpl_array_get_cplsize(sel, 0, NULL);
471 int indexrbn =
472 cpl_table_get_int(fibre_table, MOO_FIBRES_TABLE_INDEXRBN, idx,
473 NULL);
474 cpl_table_set_int(line_table, MOO_LINE_TABLE_INDEXRBN, i, indexrbn);
475 cpl_array_delete(sel);
476 }
477 }
478}
const char * moo_detector_get_name(moo_detector_type type)
Get the extension name of a detector.
Definition: moo_detector.c:183
const char * moo_detector_get_extname(moo_detector_type type, int ntas)
Get the extension name of a detector.
Definition: moo_detector.c:137
enum _moo_detector_type_ moo_detector_type
The type code type.
Definition: moo_detector.h:64
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_image * moo_fits_load_extension_image(const char *filename, const char *name, const char *detectorname, cpl_type type)
Load an image from FITS file.
Definition: moo_fits.c:311
cpl_error_code moo_map_check(moo_map *self, moo_spectral_format *sformat)
Save a moo_map to a FITS file.
Definition: moo_map.c:320
cpl_error_code moo_map_dump(const moo_map *self, FILE *stream)
Dump structural information of MAP.
Definition: moo_map.c:428
void moo_map_save(moo_map *self, const char *filename)
Save a moo_map to a FITS file.
Definition: moo_map.c:275
moo_map * moo_map_new(void)
Create a new moo_map.
Definition: moo_map.c:68
cpl_table * moo_map_get_line_table(moo_map *self)
Get the LINE TABLE extension of a map.
Definition: moo_map.c:84
cpl_error_code moo_map_set_data(moo_map *self, moo_detector_type type, int ntas, cpl_image *data, cpl_propertylist *header)
set map data for relevant extension
Definition: moo_map.c:164
void moo_map_delete(moo_map *self)
Delete a moo_map.
Definition: moo_map.c:236
void moo_spectral_format_info_delete(moo_spectral_format_info *self)
Delete a moo_spectral_format_info.
moo_spectral_format_info * moo_spectral_format_get(moo_spectral_format *self, moo_detector_type type, int ntas)
Get the spectral format information for a given ARM.
int moo_pfits_get_naxis(const cpl_propertylist *plist)
find out the NAXIS value
Definition: moo_pfits.c:980
cpl_error_code moo_qc_set_wavecal_monotonous_solution(cpl_propertylist *plist, int val)
Set the QC.WAVECAL.MONOTONOUS.SOLUTION value.
Definition: moo_qc.c:2000
cpl_error_code moo_qc_set_wave_min(cpl_propertylist *plist, double val)
Set the QC.WAVE.MIN value.
Definition: moo_qc.c:1416
cpl_error_code moo_qc_set_wave_max(cpl_propertylist *plist, double val)
Set the QC.WAVE.MAX value.
Definition: moo_qc.c:1445