KMOS Pipeline Reference Manual 4.5.10
kmos_level_correct.c
1/*
2 * This file is part of the KMOS 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., 59 Temple Place, Suite 330, 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 <string.h>
29#include <math.h>
30
31#include <cpl.h>
32
33#include "kmo_utils.h"
34#include "kmos_pfits.h"
35#include "kmo_dfs.h"
36#include "kmo_error.h"
37#include "kmo_constants.h"
38#include "kmo_debug.h"
39#include "kmos_oscan.h"
40
41/*-----------------------------------------------------------------------------
42 * Functions prototypes
43 *----------------------------------------------------------------------------*/
44
45static char * kmos_get_root_name(const char * filename) ;
46static int kmos_level_correct_create(cpl_plugin *);
47static int kmos_level_correct_exec(cpl_plugin *);
48static int kmos_level_correct_destroy(cpl_plugin *);
49static int kmos_level_correct(cpl_parameterlist *, cpl_frameset *);
50
51/*-----------------------------------------------------------------------------
52 * Static variables
53 *----------------------------------------------------------------------------*/
54
55static char kmos_level_correct_description[] =
56"This recipe applies the level correction to the input frames.\n"
57"\n"
58"---------------------------------------------------------------------------\n"
59"Input files:\n"
60" DO CATG Type Explanation Required #Frames\n"
61" ------- ----- ----------- -------- -------\n"
62" SCIENCE RAW Science frames Y 1-n \n"
63" LCAL F2D Wavelength calib. frame N 0,1 \n"
64" BADPIXEL_DARK B2D Bad pixels frame N 0,1 \n"
65"\n"
66"Output files:\n"
67" DO CATG Type Explanation\n"
68" ------- ----- -----------\n"
69" LEVEL_CORRECTED F2D Level corrected frame\n"
70"---------------------------------------------------------------------------"
71"\n";
72
73/*----------------------------------------------------------------------------*/
77/*----------------------------------------------------------------------------*/
78
81/*-----------------------------------------------------------------------------
82 * Functions code
83 *----------------------------------------------------------------------------*/
84
85/*----------------------------------------------------------------------------*/
94/*----------------------------------------------------------------------------*/
95int cpl_plugin_get_info(cpl_pluginlist *list)
96{
97 cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe);
98 cpl_plugin *plugin = &recipe->interface;
99
100 cpl_plugin_init(plugin,
101 CPL_PLUGIN_API,
102 KMOS_BINARY_VERSION,
103 CPL_PLUGIN_TYPE_RECIPE,
104 "kmos_level_correct",
105 "Create level corrected frames",
106 kmos_level_correct_description,
107 "Yves Jung",
108 "https://support.eso.org/",
109 kmos_get_license(),
110 kmos_level_correct_create,
111 kmos_level_correct_exec,
112 kmos_level_correct_destroy);
113
114 cpl_pluginlist_append(list, plugin);
115
116 return 0;
117}
118
119/*----------------------------------------------------------------------------*/
127/*----------------------------------------------------------------------------*/
128static int kmos_level_correct_create(cpl_plugin *plugin)
129{
130 cpl_recipe *recipe;
131 cpl_parameter *p;
132
133 /* Check that the plugin is part of a valid recipe */
134 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
135 recipe = (cpl_recipe *)plugin;
136 else
137 return -1;
138
139 /* Create the parameters list in the cpl_recipe object */
140 recipe->parameters = cpl_parameterlist_new();
141
142 /* Fill the parameters list */
143
144 /* --lcmethod (level correction method) */
145 p = cpl_parameter_new_value("kmos.kmos_level_correct.lcmethod",
146 CPL_TYPE_STRING,
147 "Method to use for the level correction "
148 "[\"OSCAN\" (overscan), "
149 "\"SLICES_MEAN\" (intra slices with average), "
150 "\"SLICES_MEDIAN\" (intra slices with median)]",
151 "kmos.kmos_level_correct", "OSCAN");
152 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "lcmethod");
153 cpl_parameter_disable(p, CPL_PARAMETER_MODE_ENV);
154 cpl_parameterlist_append(recipe->parameters, p);
155
156 return 0;
157}
158
159/*----------------------------------------------------------------------------*/
165/*----------------------------------------------------------------------------*/
166static int kmos_level_correct_exec(cpl_plugin *plugin)
167{
168 cpl_recipe *recipe;
169
170 /* Get the recipe out of the plugin */
171 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
172 recipe = (cpl_recipe *)plugin;
173 else return -1;
174
175 return kmos_level_correct(recipe->parameters, recipe->frames);
176}
177
178/*----------------------------------------------------------------------------*/
184/*----------------------------------------------------------------------------*/
185static int kmos_level_correct_destroy(cpl_plugin *plugin)
186{
187 cpl_recipe *recipe;
188
189 /* Get the recipe out of the plugin */
190 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
191 recipe = (cpl_recipe *)plugin;
192 else return -1 ;
193
194 cpl_parameterlist_delete(recipe->parameters);
195 return 0 ;
196}
197
198/*----------------------------------------------------------------------------*/
208/*----------------------------------------------------------------------------*/
209static int kmos_level_correct(
210 cpl_parameterlist * parlist,
211 cpl_frameset * frameset)
212{
213 const cpl_parameter * par ;
214 const char * lcmethod ;
215 int i ;
216 const cpl_frame * rawframe ;
217 cpl_frame * bpm_frame ;
218 cpl_frame * lcal_frame ;
219 const char * in_fn ;
220 char * out_fn ;
221 char * bpm_out_fn ;
222 char * level_out_fn ;
223 cpl_image * img_in ;
224 cpl_image * bpm_im ;
225 cpl_image * lcal_im ;
226 cpl_image * ima_corr ;
227 cpl_image * level_out ;
228 cpl_mask * bpm_out ;
229 cpl_propertylist * mh_plist ;
230 cpl_propertylist * plist ;
231 double rotangle_found, rotangle ;
232
233 /* Initialise */
234 bpm_frame = lcal_frame = NULL ;
235
236 /* Check initial Entries */
237 if (kmos_check_and_set_groups(frameset) != CPL_ERROR_NONE) {
238 return cpl_error_get_code();
239 }
240
241 /* Get Parameters */
242 par = cpl_parameterlist_find_const(parlist,
243 "kmos.kmos_level_correct.lcmethod");
244 lcmethod = cpl_parameter_get_string(par) ;
245
246 if (strcmp(lcmethod, "OSCAN") && strcmp(lcmethod, "SLICES_MEAN") &&
247 strcmp(lcmethod, "SLICES_MEDIAN")) {
248 cpl_msg_error(__func__,
249 "lcmethod must be 'OSCAN', 'SLICES_MEAN' or 'SLICES_MEDIAN'") ;
250 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
251 return -1 ;
252 }
253
254 /* Get frames */
255 bpm_frame = kmo_dfs_get_frame(frameset, BADPIXEL_DARK) ;
256 lcal_frame = kmo_dfs_get_frame(frameset, LCAL) ;
257
258 /* Loop on the raw frames */
259 rawframe = kmo_dfs_get_frame(frameset, SCIENCE);
260 while (rawframe != NULL) {
261 /* Output filename */
262 in_fn = cpl_frame_get_filename(rawframe) ;
263 out_fn = cpl_sprintf("%s_LC.fits",
264 kmos_get_root_name(kmos_get_base_name(in_fn))) ;
265 bpm_out_fn = cpl_sprintf("%s_BPM.fits",
266 kmos_get_root_name(kmos_get_base_name(in_fn))) ;
267 level_out_fn = cpl_sprintf("%s_LEVEL.fits",
268 kmos_get_root_name(kmos_get_base_name(in_fn))) ;
269
270 /* Create primary header products */
271 mh_plist = cpl_propertylist_load(in_fn, 0) ;
272
273 /* BPM_OUT */
274 cpl_propertylist_update_string(mh_plist, CPL_DFS_PRO_CATG,
275 "BPM_OUT") ;
276 cpl_dfs_save_propertylist(frameset, NULL, parlist, frameset,
277 rawframe, cpl_func, mh_plist, NULL, VERSION, bpm_out_fn);
278 /* LEVEL_OUT */
279 cpl_propertylist_update_string(mh_plist, CPL_DFS_PRO_CATG,
280 "LEVEL_OUT") ;
281 cpl_dfs_save_propertylist(frameset, NULL, parlist, frameset,
282 rawframe, cpl_func, mh_plist, NULL, VERSION, level_out_fn);
283 /* LEVEL_CORRECTED */
284 cpl_propertylist_update_string(mh_plist, CPL_DFS_PRO_CATG,
285 "LEVEL_CORRECTED") ;
286 cpl_dfs_save_propertylist(frameset, NULL, parlist, frameset,
287 rawframe, cpl_func, mh_plist, NULL, VERSION, out_fn);
288
289 /* Loop on detectors */
290 for (i = 1; i <= KMOS_NR_DETECTORS ; i++) {
291 cpl_msg_info(cpl_func, "Processing det %d of file %s", i, in_fn) ;
292
293 /* Load the input image */
294 img_in = cpl_image_load(in_fn, CPL_TYPE_FLOAT, 0, i) ;
295
296 /* Load the extension header */
297 plist = cpl_propertylist_load(in_fn, i) ;
298
299 /* Load the BPM / LCAL if passed */
300 bpm_im = NULL ;
301 if (bpm_frame != NULL) {
302 bpm_im = cpl_image_load(cpl_frame_get_filename(bpm_frame),
303 CPL_TYPE_INT, 0, i) ;
304 }
305 lcal_im = NULL ;
306 if (lcal_frame != NULL) {
307 rotangle = kmo_dfs_get_property_double(mh_plist, ROTANGLE);
308 lcal_im = kmo_dfs_load_cal_image_frame(lcal_frame, i, 0,
309 rotangle, FALSE, NULL, &rotangle_found, -1, 0, 0) ;
310 }
311
312 /* Apply correction */
313 ima_corr = NULL ;
314 level_out = NULL ;
315 bpm_out = NULL ;
316 if (!strcmp(lcmethod, "OSCAN")) {
317 cpl_msg_info(__func__, "Apply Overscan correction") ;
318 ima_corr = kmos_oscan_correct(img_in) ;
319 } else if (!strcmp(lcmethod, "SLICES_MEAN")) {
320 cpl_msg_info(__func__, "Apply Intra Slices correction (mean)") ;
321 ima_corr = kmos_intraslices_correct(img_in, bpm_im,
322 lcal_im, 1, &bpm_out, &level_out);
323 } else if (!strcmp(lcmethod, "SLICES_MEDIAN")) {
324 cpl_msg_info(__func__,"Apply Intra Slices correction (median)");
325 ima_corr = kmos_intraslices_correct(img_in, bpm_im,
326 lcal_im, 2, &bpm_out, &level_out);
327 }
328 cpl_image_delete(img_in) ;
329 if (lcal_im != NULL) cpl_image_delete(lcal_im) ;
330 if (bpm_im != NULL) cpl_image_delete(bpm_im) ;
331
332 /* Save LEVEL_OUT */
333 if (level_out == NULL) {
334 cpl_propertylist_save(plist, level_out_fn, CPL_IO_EXTEND);
335 } else {
336 cpl_image_save(level_out, level_out_fn, CPL_TYPE_DOUBLE, plist,
337 CPL_IO_EXTEND);
338 cpl_image_delete(level_out) ;
339 }
340
341 /* Save BPM_OUT */
342 if (bpm_out == NULL) {
343 cpl_propertylist_save(plist, bpm_out_fn, CPL_IO_EXTEND);
344 } else {
345 cpl_mask_save(bpm_out, bpm_out_fn, plist, CPL_IO_EXTEND);
346 cpl_mask_delete(bpm_out) ;
347 }
348
349 /* Save LEVEL_CORRECTED */
350 if (ima_corr == NULL) {
351 cpl_propertylist_save(plist, out_fn, CPL_IO_EXTEND);
352 } else {
353 cpl_image_save(ima_corr, out_fn, CPL_TYPE_FLOAT, plist,
354 CPL_IO_EXTEND);
355 cpl_image_delete(ima_corr) ;
356 }
357 cpl_propertylist_delete(plist) ;
358 }
359 cpl_propertylist_delete(mh_plist) ;
360 cpl_free(out_fn) ;
361 cpl_free(bpm_out_fn) ;
362 cpl_free(level_out_fn) ;
363
364 /* Get next RAW frame */
365 rawframe = kmo_dfs_get_frame(frameset, NULL);
366 }
367
368 /* Free and Return */
369 return CPL_ERROR_NONE;
370}
371
374/*----------------------------------------------------------------------------*/
380/*----------------------------------------------------------------------------*/
381static char * kmos_get_root_name(const char * filename)
382{
383 static char path[4096+1];
384 char * lastdot ;
385 if (filename == NULL) return NULL;
386
387 if (strlen(filename)>4096) return NULL ;
388 memset(path, 0, 4096);
389 strcpy(path, filename);
390 lastdot = strrchr(path, '.');
391 if (lastdot == NULL) return path ;
392 if ((!strcmp(lastdot, ".fits")) || (!strcmp(lastdot, ".FITS")) ||
393 (!strcmp(lastdot, ".dat")) || (!strcmp(lastdot, ".DAT")) ||
394 (!strcmp(lastdot, ".paf")) || (!strcmp(lastdot, ".PAF")) ||
395 (!strcmp(lastdot, ".txt")) || (!strcmp(lastdot, ".TXT")) ||
396 (!strcmp(lastdot, ".ascii")) || (!strcmp(lastdot, ".ASCII")))
397 {
398 lastdot[0] = (char)0;
399 }
400 return path ;
401}
402
int cpl_plugin_get_info(cpl_pluginlist *list)
Build the list of available plugins, for this module.