MUSE Pipeline Reference Manual  2.1.1
muse_cube_filter.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) 2014-2015 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 /*----------------------------------------------------------------------------*/
59 /*----------------------------------------------------------------------------*/
60 
63 #define PRINT_USAGE(rc) \
64  fprintf(stderr, "Usage: %s [ -x ] [ -f filter,names ] CUBE FILTER_LIST\n", \
65  argv[0]); \
66  cpl_end(); return (rc);
67 
68 int main(int argc, char **argv)
69 {
70  const char *idstring = "muse_cube_filter";
71  cpl_init(CPL_INIT_DEFAULT);
72  cpl_msg_set_time_on();
74  cpl_msg_set_level(CPL_MSG_DEBUG);
75  cpl_msg_set_component_on();
76  cpl_errorstate state = cpl_errorstate_get();
77 
78  if (argc < 3) {
79  /* two filenames are needed at least */
80  PRINT_USAGE(1);
81  }
82 
83  cpl_array *filters = NULL; /* filter names */
84  char *iname = NULL, /* input name */
85  *list = NULL; /* filter list names */
86  cpl_boolean extended = CPL_FALSE;
87  int i;
88 
89  /* argument processing */
90  for (i = 1; i < argc; i++) {
91  if (strncmp(argv[i], "-f", 3) == 0) {
92  /* skip to next arg to get start value */
93  i++;
94  if (i < argc) {
95  filters = muse_cplarray_new_from_delimited_string(argv[i], ",");
96  } else {
97  PRINT_USAGE(2);
98  }
99  } else if (strncmp(argv[i], "-x", 3) == 0) {
100  extended = CPL_TRUE;
101  } else if (strncmp(argv[i], "-", 1) == 0) { /* unallowed options */
102  PRINT_USAGE(9);
103  } else {
104  if (iname && list) {
105  break; /* we have the required names, skip the rest */
106  }
107  if (!iname) {
108  iname = argv[i]; /* set the name for the input cube */
109  } else {
110  list = argv[i]; /* set the name for the filter list table */
111  }
112  }
113  } /* for i (all arguments) */
114  if (!iname || !list) {
115  PRINT_USAGE(10);
116  }
117  int iext = 0;
118  if (!filters) {
119  cpl_msg_info(idstring, "No filter names given, will use all from \"%s\"",
120  list);
121  /* create the array from the filter list file extension names */
122  filters = cpl_array_new(0, CPL_TYPE_STRING);
123  cpl_errorstate es = cpl_errorstate_get();
124  do {
125  iext++;
126  cpl_propertylist *header = cpl_propertylist_load(list, iext);
127  if (!header) {
128  break;
129  }
130  if (!cpl_propertylist_has(header, "EXTNAME")) {
131  continue;
132  }
133  const char *extname = muse_pfits_get_extname(header);
134  cpl_array_set_size(filters, cpl_array_get_size(filters) + 1);
135  cpl_array_set_string(filters, cpl_array_get_size(filters) - 1, extname);
136  cpl_msg_info(idstring, "Added filter \"%s\"", extname);
137  cpl_propertylist_delete(header);
138  } while (cpl_errorstate_is_equal(es));
139  cpl_errorstate_set(es);
140  } /* if no filters given */
141 #if 0
142  cpl_array_dump(filters, 0, 10000, stdout);
143  fflush(stdout);
144 #endif
145 
146  cpl_msg_info(idstring, "Loading cube \"%s\"", iname);
147  muse_datacube *cube = muse_datacube_load(iname);
148  if (!cube) {
149  cpl_msg_error(idstring, "MUSE cube could not be loaded from \"%s\"!", iname);
150  PRINT_USAGE(11);
151  }
152 
153  /* get data sizes, mainly for display */
154  int nx = cpl_image_get_size_x(cpl_imagelist_get(cube->data, 0)),
155  ny = cpl_image_get_size_y(cpl_imagelist_get(cube->data, 0)),
156  nl = cpl_imagelist_get_size(cube->data);
157  cpl_msg_info(idstring, "Loaded cube \"%s\" (%dx%dx%d)", iname, nx, ny, nl);
158 
160  cpl_array *names = cpl_array_new(0, CPL_TYPE_STRING);
161  int idx, n = cpl_array_get_size(filters);
162  for (i = 0, idx = 0; i < n; i++) {
163  const char *fname = cpl_array_get_string(filters, i);
164  muse_table *ftable = NULL;
165  if (fname && strncmp(fname, "white", 6)) {
166  iext = cpl_fits_find_extension(list, fname);
167  if (iext < 1) {
168  cpl_msg_warning(idstring, "No filter \"%s\" found in table \"%s\"", fname,
169  list);
170  continue;
171  }
172  cpl_msg_info(idstring, "Integrating over filter \"%s\" (from %s)", fname,
173  MUSE_TAG_FILTER_LIST);
174  ftable = muse_table_new();
175  ftable->table = cpl_table_load(list, iext, 1);
176  ftable->header = cpl_propertylist_load(list, 0);
177  cpl_propertylist *hext = cpl_propertylist_load(list, iext);
178  cpl_propertylist_copy_property_regexp(ftable->header, hext,
179  "^EXTNAME$|^Z|^COMMENT", 0);
180  cpl_propertylist_delete(hext);
181  } else {
182  cpl_msg_info(idstring, "Integrating over filter \"%s\" (builtin)", fname);
183  ftable = muse_table_load_filter(NULL, fname);
184  }
185  muse_image *fov = muse_datacube_collapse(cube, ftable);
186  muse_table_delete(ftable);
187  /* we want NANs instead of DQ in the output images */
189  muse_imagelist_set(images, fov, idx++);
190  cpl_array_set_size(names, cpl_array_get_size(names) + 1);
191  cpl_array_set_string(names, cpl_array_get_size(names) - 1, fname);
192  } /* for i (all filters) */
193  cpl_array_delete(filters);
194  muse_datacube_delete(cube);
195 
196 #if 0
197  cpl_array_dump(names, 0, n, stdout);
198  fflush(stdout);
199 #endif
200 
201  /* extended format: append the new images to the original cube file */
202  n = muse_imagelist_get_size(images);
203  if (extended) {
204  cpl_errorstate es = cpl_errorstate_get();
205  cpl_error_code rc = muse_datacube_save_recimages(iname, images, names);
206  if (rc == CPL_ERROR_NONE && cpl_errorstate_is_equal(es)) {
207  cpl_msg_info(idstring, "Appended %d images into cube \"%s\"", n, iname);
208  } else {
209  cpl_msg_error(idstring, "Appending %d images into cube \"%s\" failed: %s",
210  n, iname, cpl_error_get_message());
211  }
212  } else { /* not extended */
213  /* normal case: save new images for each filtered image */
214  char *fn = cpl_sprintf("%s", iname),
215  *basename = strstr(fn, ".fits");
216  basename[0] = '\0'; /* clip off the .fits extension to get the base name */
217  for (i = 0; i < n; i++) {
218  const char *fname = cpl_array_get_string(names, i);
219  muse_image *image = muse_imagelist_get(images, i);
220  char *outname = cpl_sprintf("%s_%s.fits", fn, fname);
221  // XXX treat the FITS header!!
222  muse_image_save(image, outname);
223  cpl_msg_info(idstring, "Saved image for filter \"%s\" into \"%s\"", fname,
224  outname);
225  cpl_free(outname);
226  } /* for i (all images) */
227  cpl_free(fn);
228  } /* else: not extended */
229  cpl_array_delete(names);
230  muse_imagelist_delete(images);
231 
232  if (!cpl_errorstate_is_equal(state)) {
233  cpl_errorstate_dump(state, CPL_FALSE, muse_cplerrorstate_dump_some);
234  }
235  cpl_memory_dump();
236  cpl_end();
237  return 0;
238 }
239 
Structure definition of a MUSE datacube.
Definition: muse_datacube.h:48
Structure definition for a collection of muse_images.
const char * muse_pfits_get_extname(const cpl_propertylist *aHeaders)
find out the extension name
Definition: muse_pfits.c:205
muse_datacube * muse_datacube_load(const char *aFilename)
Load header, DATA and optionally STAT and DQ extensions as well as the reconstructed images of a MUSE...
void muse_datacube_delete(muse_datacube *aCube)
Deallocate memory associated to a muse_datacube object.
void muse_imagelist_delete(muse_imagelist *aList)
Free the memory of the MUSE image list.
muse_table * muse_table_new(void)
Allocate memory for a new muse_table object.
Definition: muse_table.c:63
Structure definition of MUSE three extension FITS file.
Definition: muse_image.h:40
unsigned int muse_imagelist_get_size(muse_imagelist *aList)
Return the number of stored images.
cpl_array * muse_cplarray_new_from_delimited_string(const char *aString, const char *aDelim)
Convert a delimited string into an array of strings.
muse_image * muse_imagelist_get(muse_imagelist *aList, unsigned int aIdx)
Get the muse_image of given list index.
cpl_table * table
The table.
Definition: muse_table.h:49
cpl_error_code muse_datacube_save_recimages(const char *aFilename, muse_imagelist *aImages, cpl_array *aNames)
Save reconstructed images of a cube in extra extensions.
void muse_cplerrorstate_dump_some(unsigned aCurrent, unsigned aFirst, unsigned aLast)
Dump some CPL errors.
muse_table * muse_table_load_filter(muse_processing *aProcessing, const char *aFilterName)
Load a table for a given filter name.
Definition: muse_utils.c:799
cpl_imagelist * data
the cube containing the actual data values
Definition: muse_datacube.h:76
Structure to store a table together with a property list.
Definition: muse_table.h:43
void muse_table_delete(muse_table *aTable)
Deallocate memory associated to a muse_table object.
Definition: muse_table.c:80
cpl_propertylist * header
the header
Definition: muse_table.h:56
cpl_error_code muse_image_save(muse_image *aImage, const char *aFilename)
Save the three image extensions and the FITS headers of a MUSE image to a file.
Definition: muse_image.c:405
muse_imagelist * muse_imagelist_new(void)
Create a new (empty) MUSE image list.
muse_image * muse_datacube_collapse(muse_datacube *aCube, const muse_table *aFilter)
Integrate a FITS NAXIS=3 datacube along the wavelength direction.
void muse_processing_recipeinfo(cpl_plugin *)
Output main pipeline configuration, inputs, and parameters.
cpl_error_code muse_imagelist_set(muse_imagelist *aList, muse_image *aImage, unsigned int aIdx)
Set the muse_image of given list index.
cpl_error_code muse_image_dq_to_nan(muse_image *aImage)
Convert pixels flagged in the DQ extension to NANs in DATA (and STAT, if present).
Definition: muse_image.c:904