MUSE Pipeline Reference Manual  2.1.1
muse_badpix_from_region.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  * This file is part of the MUSE Instrument Pipeline
5  * Copyright (C) 2007-2014 European Southern Observatory
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  */
21 
22 #include <muse.h>
23 #include <string.h>
24 
25 #include <muse_instrument.h>
26 #include "muse_data_format_z.h"
27 
28 /*----------------------------------------------------------------------------*/
79 /*----------------------------------------------------------------------------*/
80 
83 #define PRINT_USAGE(rc) \
84  fprintf(stderr, "Usage: %s [ -i INTABLE ] [ -r REFIMAGE [ -n extname ] ] " \
85  "[ -t ] REGION DQVAL IFUNUM OUTTABLE\n", argv[0]); \
86  cpl_end(); return (rc);
87 
88 int main(int argc, char **argv)
89 {
90  cpl_init(CPL_INIT_DEFAULT);
92  if (argc <= 4) {
93  PRINT_USAGE(1);
94  }
95 
96  if (getenv("ESOREX_MSG_LEVEL") && !strncmp(getenv("ESOREX_MSG_LEVEL"),
97  "debug", 6)) {
98  cpl_msg_set_level(CPL_MSG_DEBUG);
99  }
100 
101  char *region = NULL, /* input region */
102  *toname = NULL, /* output table */
103  *riname = NULL, /* optional reference image */
104  *tiname = NULL, /* optional input table */
105  *extname = NULL; /* optional extension name */
106  long dqvalue = 0; /* DQ value */
107  unsigned char nifu = 0; /* IFU number */
108  cpl_boolean trimmedcoords = CPL_FALSE;
109 
110  /* argument processing */
111  int i;
112  for (i = 1; i < argc; i++) {
113  if (strncmp(argv[i], "-i", 3) == 0) {
114  /* skip to next arg to input table filename */
115  i++;
116  if (i < argc) {
117  tiname = argv[i];
118  } else {
119  PRINT_USAGE(2);
120  }
121  } else if (strncmp(argv[i], "-r", 3) == 0) {
122  /* skip to next arg to input image filename */
123  i++;
124  if (i < argc) {
125  riname = argv[i];
126  } else {
127  PRINT_USAGE(3);
128  }
129  } else if (strncmp(argv[i], "-n", 3) == 0) {
130  /* skip to next arg to get sigma value */
131  i++;
132  if (i < argc) {
133  extname = argv[i];
134  } else {
135  PRINT_USAGE(5);
136  }
137  } else if (strncmp(argv[i], "-t", 3) == 0) {
138  /* skip to next arg to get sigma value */
139  trimmedcoords = CPL_TRUE;
140  } else if (strncmp(argv[i], "-", 1) == 0) { /* unallowed options */
141  PRINT_USAGE(9);
142  } else {
143  if (region && dqvalue && toname) {
144  break; /* we have the possible names, skip the rest */
145  }
146  if (!region) {
147  region = argv[i]; /* set the name for the input ASCII file */
148  } else if (!dqvalue) {
149  dqvalue = atol(argv[i]);
150  } else if (nifu == 0) {
151  int ifunum = atoi(argv[i]);
152  if (ifunum < 1 || ifunum > kMuseNumIFUs) {
153  PRINT_USAGE(9);
154  }
155  nifu = ifunum;
156  } else {
157  toname = argv[i]; /* set the name for the output table */
158  }
159  }
160  } /* for i (all arguments) */
161 
162  /* parse the region */
163  int x1, x2, y1, y2,
164  n = sscanf(region, "[%d:%d,%d:%d]", &x1, &x2, &y1, &y2);
165  if (n != 4) {
166  PRINT_USAGE(10);
167  }
168 
169  /* part1: ======================================= *
170  * convert the ASCII file into a new table */
171  if (trimmedcoords) {
172  printf("Converting coordinates from trimmed to raw data dimensions\n");
173  }
174  cpl_table *table = muse_cpltable_new(muse_badpix_table_def,
175  (x2-x1+1) * (y2-y1+1));
176  cpl_size irow = 0;
177  for (i = x1; i <= x2; i++) {
178  int j;
179  for (j = y1; j <= y2; j++) {
180  int ix = i,
181  iy = j;
182  if (trimmedcoords) {
183  muse_quadrants_coords_to_raw(NULL, &ix, &iy);
184  }
185  if (ix < 1 || ix > (kMuseOutputXRight + 4*kMusePreOverscanSize) ||
186  iy < 1 || iy > (kMuseOutputYTop + 4*kMusePreOverscanSize)) {
187  fprintf(stderr, "Excluding bad pixel at given %d,%d %s coordinates, as "
188  "it would be outside the MUSE CCD!\n", i, j,
189  trimmedcoords ? "trimmed" : "raw");
190  continue;
191  } /* if outside */
192  cpl_table_set_int(table, MUSE_BADPIX_X, irow, ix);
193  cpl_table_set_int(table, MUSE_BADPIX_Y, irow, iy);
194  cpl_table_set_int(table, MUSE_BADPIX_DQ, irow++, dqvalue);
195  } /* for j (vertical pixels) */
196  } /* for i (horizontal pixels) */
197  cpl_table_set_size(table, irow);
198  printf("%"CPL_SIZE_FORMAT" bad pixel%s created from region %s\n", irow,
199  irow != 1 ? "s" : "", region);
200  if (cpl_msg_get_level() == CPL_MSG_DEBUG) {
201  printf("first 10 entries of the new table, as converted from region:\n");
202  cpl_table_dump(table, 0, 10, stdout);
203  fflush(stdout);
204  }
205 
206  /* part2: ============================================ *
207  * load and handle the input badpix table if it exists */
208  if (tiname) { /* try to open the input table, verify that it really exists */
209  cpl_propertylist *htest = cpl_propertylist_load(tiname, 0);
210  if (htest) {
211  cpl_propertylist_delete(htest);
212  } else {
213  printf("WARNING: could not open input table \"%s\"!\n", tiname);
214  tiname = NULL; /* it doesn't exist, don't keep the name */
215  } /* else */
216  } /* if tiname */
217 
218  /* merge created table with existing one, if there is one */
219  char *chan = cpl_sprintf("CHAN%02hhu", nifu);
220  cpl_table *intable = NULL;
221  int inext = -1;
222  if (tiname) {
223  cpl_errorstate state = cpl_errorstate_get();
224  intable = muse_quality_merge_badpix_from_file(table, tiname, chan, &inext);
225  if (!intable) {
226  cpl_errorstate_set(state);
227  intable = table;
228  } /* if !intable */
229  } /* if tiname */
230  /* copy the input BADPIX_TABLE, maybe replacing the one extension we modified */
231  cpl_error_code rc = muse_quality_copy_badpix_table(tiname, toname, inext,
232  intable);
233  cpl_boolean savedsomething = rc == CPL_ERROR_NONE;
234 
235  /* save or append the extension if not already done above */
236  inext = cpl_fits_find_extension(toname, chan);
237  if (inext <= 0) {
238  cpl_propertylist *pheader = NULL,
239  *header = NULL;
240  if (!riname) {
241  printf("WARNING: no pre-existing data, creating minimal header from "
242  "scratch!\n");
243  pheader = cpl_propertylist_new();
244  cpl_propertylist_append_string(pheader, "TELESCOP", "ESO-VLT-U4");
245  cpl_propertylist_append_string(pheader, "INSTRUME", "MUSE");
246  cpl_propertylist_append_string(pheader, "OBJECT",
247  "Bad pixel table for MUSE (BADPIX_TABLE)");
248  header = cpl_propertylist_new();
249  cpl_propertylist_append_string(header, "EXTNAME", chan);
250  cpl_propertylist_append_string(header, "ESO DET CHIP NAME", chan);
251  } else {
252  printf("Using primary header from \"%s\" as starting point\n", riname);
253  pheader = cpl_propertylist_load_regexp(riname, 0, "TELESCOP|INSTRUME|"
254  "ESO DET ", 0);
255  /* remove exposure-specifc info and the stuff about *
256  * CHIP and OUTi again, that belongs into the extension */
257  cpl_propertylist_erase_regexp(pheader, "ESO DET DEV[0-9] (SHUT |EXP )|"
258  "ESO DET (EXP |[DU]IT|NDIT|DKTM)", 0);
259  cpl_propertylist_erase_regexp(pheader, "ESO DET (CHIP |OUT[1-4])", 0);
260  cpl_propertylist_update_string(pheader, "OBJECT",
261  "Bad pixel table for MUSE (BADPIX_TABLE)");
262  int refext = cpl_fits_find_extension(riname, extname);
263  if (refext >= 0) {
264  printf("Using extension header from \"%s[%s]\" (%d)\n", riname, extname,
265  refext);
266  header = cpl_propertylist_load_regexp(riname, refext,
267  "^EXT|ESO DET (CHIP |OUT[1-4])", 0);
268  } else {
269  printf("WARNING: no pre-existing extension found, creating minimal "
270  "extension header from scratch!\n");
271  header = cpl_propertylist_new();
272  cpl_propertylist_append_string(header, "EXTNAME", chan);
273  cpl_propertylist_append_string(header, "ESO DET CHIP NAME", chan);
274  }
275  }
276  if (savedsomething) {
277  /* just extend the already saved data with the new extension */
278  rc = cpl_table_save(table, NULL, header, toname, CPL_IO_EXTEND);
279  } else {
280  /* save the whole file, overwriting what may be there under that name */
281  cpl_propertylist_update_string(pheader, "PIPEFILE", toname);
282  cpl_propertylist_set_comment(pheader, "PIPEFILE",
283  "pretend to be a pipeline output file");
284  cpl_propertylist_update_string(pheader, "ESO PRO CATG", MUSE_TAG_BADPIX_TABLE);
285  cpl_propertylist_set_comment(pheader, "ESO PRO CATG",
286  "MUSE bad pixel table");
287  rc = cpl_table_save(table, pheader, header, toname, CPL_IO_CREATE);
288  }
289  if (rc != CPL_ERROR_NONE) {
290  fprintf(stderr, "Saving to \"%s\" failed (rc=%d): %s\n", toname, rc,
291  cpl_error_get_message());
292  } else {
293  printf("Saved to \"%s\" (%s)\n", toname,
294  savedsomething ? "new extension" : "new file");
295  }
296  cpl_propertylist_delete(pheader);
297  cpl_propertylist_delete(header);
298  } /* if new table now saved yet */
299  cpl_free(chan);
300  cpl_table_delete(table);
301 
302  if (cpl_msg_get_level() == CPL_MSG_DEBUG) {
303  printf("Output file \"%s\" has primary header and %"CPL_SIZE_FORMAT
304  " extensions\n", toname, cpl_fits_count_extensions(toname));
305  cpl_errorstate_dump(0, CPL_FALSE, NULL);
306  cpl_memory_dump();
307  fflush(NULL);
308  }
309  cpl_end();
310  return 0;
311 }
312 
cpl_error_code muse_quality_copy_badpix_table(const char *aInFile, const char *aOutFile, int aExtension, const cpl_table *aTable)
Copy bad pixel table on disk, replacing the table in one extension.
Definition: muse_quality.c:764
cpl_table * muse_quality_merge_badpix_from_file(const cpl_table *aTable, const char *aInFile, const char *aExtname, int *aExt)
Merge bad pixel table in memory with table from file on disk.
Definition: muse_quality.c:698
cpl_table * muse_cpltable_new(const muse_cpltable_def *aDef, cpl_size aLength)
Create an empty table according to the specified definition.
const muse_cpltable_def muse_badpix_table_def[]
cpl_error_code muse_quadrants_coords_to_raw(cpl_propertylist *aHeader, int *aX, int *aY)
Convert coordinates of a trimmed image to raw-image coordinates.
void muse_processing_recipeinfo(cpl_plugin *)
Output main pipeline configuration, inputs, and parameters.