MUSE Pipeline Reference Manual  0.18.1
muse_quick_image.c
1 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:set sw=2 sts=2 et cin: */
3 /*
4  *
5  * This file is part of the MUSE Instrument Pipeline
6  * Copyright (C) 2005-2011 European Southern Observatory
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21  */
22 
23 /*----------------------------------------------------------------------------*
24  * Includes *
25  *----------------------------------------------------------------------------*/
26 #include <muclipm_make_image.h>
27 #include <muse.h>
28 #include "muse_quick_image_z.h"
29 
30 /*---------------------------------------------------------------------------*
31  * Functions code *
32  *---------------------------------------------------------------------------*/
33 
34 /*---------------------------------------------------------------------------*/
45 /*---------------------------------------------------------------------------*/
46 int
47 muse_quick_image_compute(muse_processing *aProcessing,
49 {
50  /* local variables */
51  cpl_image *raw_img, *bias, *flat, *mask;
52  cpl_propertylist *mask_hdr;
53  cpl_image *computed_img;
54  cpl_propertylist *output_header = NULL;
55  int nifu, n1, n2;
56  long xstart[MUCLIPM_NB_SLICES*MUCLIPM_NB_SUBSLICERS],
57  xend[MUCLIPM_NB_SLICES*MUCLIPM_NB_SUBSLICERS];
58 
59  /* check the nifu parameter */
60  if (aParams->nifu < 0 || aParams->nifu > kMuseNumIFUs) {
61  cpl_msg_error(__func__, "Illegal IFU number %d", aParams->nifu);
62  return -1;
63  }
64 
65  /* create the ouput image */
66  computed_img = cpl_image_new(MUCLIPM_NB_SUBSLICERS * MUCLIPM_NB_SPEC_PER_SLICE,
67  MUCLIPM_NB_SLICES * MUCLIPM_NB_IFU,
68  CPL_TYPE_FLOAT);
69 
70  n1 = aParams->nifu ? aParams->nifu : 1,
71  n2 = aParams->nifu ? aParams->nifu : kMuseNumIFUs;
72  for (nifu = n1; nifu <= n2; nifu++) {
73  int extension;
74  cpl_frameset *input_frames;
75  cpl_frame *frame;
76  cpl_image *ifu_img;
77 
78  cpl_msg_info(__func__, "Processing IFU %d", nifu);
79 
80  /* duplicate the frameset so that we can delete files */
81  input_frames = cpl_frameset_duplicate(aProcessing->inputFrames);
82 
83  frame = cpl_frameset_find(input_frames, MUSE_TAG_MASK_IMAGE);
84  extension = muse_utils_get_extension_for_ifu(cpl_frame_get_filename(frame),
85  nifu);
86  mask = cpl_image_load(cpl_frame_get_filename(frame), CPL_TYPE_INT, 0,
87  extension);
88  if (!mask) {
89  if (extension < 0) { /* append to CPL error message */
90  cpl_error_set_message(__func__, cpl_error_get_code(), "extension for "
91  "IFU %d not found", nifu);
92  }
93  cpl_msg_error(__func__, "Could not load frame %s (%s): %s",
94  cpl_frame_get_filename(frame), MUSE_TAG_MASK_IMAGE,
95  cpl_error_get_message());
96  cpl_frameset_delete(input_frames);
97  continue; /* try the next IFU */
98  }
99  /* if reading of the image succeeded, there is no reason why loading *
100  * the header should fail, so no need to test for success */
101  mask_hdr = cpl_propertylist_load(cpl_frame_get_filename(frame), extension);
102  muse_processing_append_used(aProcessing, frame, CPL_FRAME_GROUP_CALIB, 1);
103  cpl_frameset_erase(input_frames, MUSE_TAG_MASK_IMAGE);
104 
105  /* read slice limitder */
106  long i;
107  for (i = 0; i < MUCLIPM_NB_SLICES*MUCLIPM_NB_SUBSLICERS; i++) {
108  char *p1 = cpl_sprintf("ESO DET SLICE%ld XSTART", i + 1),
109  *p2 = cpl_sprintf("ESO DET SLICE%ld XEND", i + 1);
110  xstart[i] = cpl_propertylist_get_int(mask_hdr, p1);
111  xend[i] = cpl_propertylist_get_int(mask_hdr, p2);
112  cpl_free(p1);
113  cpl_free(p2);
114 #if 0 /* DEBUG */
115  cpl_msg_debug(__func__, "Slice %ld: limits [%ld,%ld]", i + 1,
116  xstart[i], xend[i]);
117 #endif
118  if (xstart[i] >= xend[i]) {
119  cpl_msg_error(__func__, "IFU %d: inconsistant slice limits in X "
120  "[%ld,%ld] for slice %ld", nifu,
121  xstart[i], xend[i], i + 1);
122  return -1;
123  } /* if */
124  } /* for i (all slices) */
125  for (i = 1; i < MUCLIPM_NB_SLICES*MUCLIPM_NB_SUBSLICERS; i++) {
126  if (xstart[i] <= xend[i-1]) {
127  cpl_msg_error(__func__, "IFU %d: inconsistant interslice for slices "
128  "%ld and %ld (%ld,%ld)", nifu,
129  i - 1, i, xend[i-1], xstart[i]);
130  return -1;
131  } /* if */
132  } /* for i (all but the first slice) */
133 
134  cpl_errorstate prestate = cpl_errorstate_get();
135  frame = cpl_frameset_find(input_frames, MUSE_TAG_BIAS);
136  extension = muse_utils_get_extension_for_ifu(cpl_frame_get_filename(frame),
137  nifu);
138  bias = cpl_image_load(cpl_frame_get_filename(frame),
139  CPL_TYPE_FLOAT, 0, extension);
140  if (!bias) {
141  cpl_msg_debug(__func__, "Proceeding without %s that could not be loaded: "
142  "%s", MUSE_TAG_BIAS, cpl_error_get_message());
143  cpl_errorstate_set(prestate); /* clean up non-critical error */
144  } else {
145  muse_processing_append_used(aProcessing, frame, CPL_FRAME_GROUP_CALIB, 1);
146  }
147  muse_processing_append_used(aProcessing, frame, CPL_FRAME_GROUP_CALIB, 1);
148  cpl_frameset_erase(input_frames, MUSE_TAG_BIAS);
149 
150  prestate = cpl_errorstate_get();
151  frame = cpl_frameset_find(input_frames, MUSE_TAG_FLAT);
152  extension = muse_utils_get_extension_for_ifu(cpl_frame_get_filename(frame),
153  nifu);
154  flat = cpl_image_load(cpl_frame_get_filename(frame), CPL_TYPE_FLOAT, 0,
155  extension);
156  if (!flat) {
157  cpl_msg_debug(__func__, "Proceeding without %s that could not be loaded: "
158  "%s", MUSE_TAG_FLAT, cpl_error_get_message());
159  cpl_errorstate_set(prestate); /* clean up non-critical error */
160  } else {
161  muse_processing_append_used(aProcessing, frame, CPL_FRAME_GROUP_CALIB, 1);
162  }
163  cpl_frameset_erase(input_frames, MUSE_TAG_FLAT);
164 
165  /* the remaining frame should be the raw data */
166  frame = cpl_frameset_get_position(input_frames, 0);
167  extension = muse_utils_get_extension_for_ifu(cpl_frame_get_filename(frame),
168  nifu);
169  raw_img = cpl_image_load(cpl_frame_get_filename(frame), CPL_TYPE_FLOAT, 0,
170  extension);
171  if (!raw_img) {
172  if (extension < 0) { /* append to CPL error message */
173  cpl_error_set_message(__func__, cpl_error_get_code(), "extension for "
174  "IFU %d not found", nifu);
175  }
176  cpl_msg_error(__func__, "Could not load data frame %s: %s",
177  cpl_frame_get_filename(frame), cpl_error_get_message());
178  cpl_frameset_delete(input_frames);
179  cpl_image_delete(mask);
180  cpl_propertylist_delete(mask_hdr);
181  cpl_image_delete(bias);
182  cpl_image_delete(flat);
183  continue; /* try the next IFU */
184  }
185  muse_processing_append_used(aProcessing, frame, CPL_FRAME_GROUP_RAW, 1);
186  /* read output header from input file */
187  if (!output_header) {
188  output_header = cpl_propertylist_load(cpl_frame_get_filename(frame), 0);
189  }
190  cpl_frameset_delete(input_frames);
191 
192  /* compute reconstructed image for this one IFU */
193  ifu_img = cpl_image_new(MUCLIPM_NB_SUBSLICERS * MUCLIPM_NB_SPEC_PER_SLICE,
194  MUCLIPM_NB_SLICES, CPL_TYPE_FLOAT);
195  if (muclipm_make_image(raw_img, bias, flat, mask, xstart, xend, &ifu_img)
196  != CPL_ERROR_NONE) {
197  cpl_msg_info(__func__, "Error while computing reconstructed image: %s",
198  cpl_error_get_message());
199  cpl_image_delete(computed_img);
200  cpl_propertylist_delete(output_header);
201  cpl_image_delete(mask);
202  cpl_propertylist_delete(mask_hdr);
203  cpl_image_delete(bias);
204  cpl_image_delete(flat);
205  return -1; /* this should really be fatal */
206  }
207 
208  /* copy reconstructed image of this IFU into the output image */
209  cpl_image_copy(computed_img, ifu_img, 1, (24 - nifu) * MUCLIPM_NB_SLICES + 1);
210 
211  /* free memory associated to images, these are NULL tolerant... */
212  cpl_image_delete(bias);
213  cpl_image_delete(flat);
214  cpl_image_delete(mask);
215  cpl_propertylist_delete(mask_hdr);
216  cpl_image_delete(raw_img);
217  cpl_image_delete(ifu_img);
218  } /* for nifu */
219 
220  cpl_image_flip(computed_img, 0);
221  muse_processing_save_cimage(aProcessing, aParams->nifu, computed_img,
222  output_header, MUSE_TAG_QUICK_IMAGE);
223  cpl_image_delete(computed_img);
224  cpl_propertylist_delete(output_header);
225 
226  return 0;
227 } /* muse_quick_image_compute() */
Structure to hold the parameters of the muse_quick_image recipe.
int muse_processing_save_cimage(muse_processing *aProcessing, int aIFU, cpl_image *aImage, cpl_propertylist *aHeader, const char *aTag)
Save a computed FITS image to disk.
int muse_utils_get_extension_for_ifu(const char *aFilename, unsigned char aIFU)
Return extension number that corresponds to this IFU/channel number.
Definition: muse_utils.c:115
void muse_processing_append_used(muse_processing *aProcessing, cpl_frame *aFrame, cpl_frame_group aGroup, int aDuplicate)
Add a frame to the set of used frames.
cpl_error_code muclipm_make_image(const cpl_image *raw_img, const cpl_image *offset, const cpl_image *flat, const cpl_image *mask, const long *slice_xstart, const long *slice_xend, cpl_image **out_img)
Collapses spectra over the spectral direction.
cpl_frameset * inputFrames
int nifu
IFU to handle. If set to 0, all IFUs are processed serially. If set to -1, all IFUs are processed in ...