60 #define PRINT_USAGE(rc) \ 61 fprintf(stderr, "Usage: %s CUBE_OUT CUBE_IN_1 CUBE_IN_2 [ CUBE_IN_3 ... ]\n",\ 63 cpl_end(); return (rc); 65 int main(
int argc,
char **argv)
67 const char *idstring =
"muse_cube_combine";
68 cpl_init(CPL_INIT_DEFAULT);
69 cpl_msg_set_time_on();
71 cpl_msg_set_level(CPL_MSG_DEBUG);
72 cpl_msg_set_component_on();
73 cpl_errorstate state = cpl_errorstate_get();
84 for (i = 1; i < argc; i++) {
85 if (strncmp(argv[i],
"-xxx", 5) == 0) {
93 }
else if (strncmp(argv[i],
"-", 1) == 0) {
105 FILE *fp = fopen(oname,
"r");
107 cpl_msg_error(idstring,
"Output cube \"%s\" is already present!", oname);
108 cpl_msg_error(idstring,
"Please specify another output name or rename the " 109 "existing file with this name.");
114 int ncubes = argc - i;
115 cpl_msg_info(idstring,
"Will write combination of %d cubes to \"%s\".",
119 cpl_table *table = cpl_table_new(ncubes);
120 cpl_table_new_column(table,
"FILENAME", CPL_TYPE_STRING);
121 cpl_table_new_column(table,
"LMIN", CPL_TYPE_DOUBLE);
122 cpl_table_new_column(table,
"LMAX", CPL_TYPE_DOUBLE);
123 cpl_table_new_column(table,
"P1", CPL_TYPE_INT);
124 cpl_table_new_column(table,
"P2", CPL_TYPE_INT);
130 double lminout = 99999.,
132 char *ctype1ref = NULL, *ctype2ref = NULL,
133 *cunit1ref = NULL, *cunit2ref = NULL;
134 double crpix1ref = NAN, crpix2ref = NAN, crval1ref = NAN, crval2ref = NAN,
135 cd11ref = NAN, cd12ref = NAN, cd21ref = NAN, cd22ref = NAN;
136 char *ctype3ref = NULL;
137 cpl_boolean loglambda = CPL_FALSE;
138 double crpix3ref = NAN,
142 for (ic = 0; ic < ncubes; ic++) {
144 char *iname = argv[argidx];
146 int iext = cpl_fits_find_extension(iname,
"DATA");
148 cpl_msg_warning(idstring,
"Could not open cube \"%s\"", iname);
153 cpl_propertylist *header = cpl_propertylist_load(iname, 0);
154 double lmin = -FLT_MAX,
157 cpl_errorstate es = cpl_errorstate_get();
161 char *hname = cpl_sprintf(
"ESO PRO REC%d ID", irec);
163 const char *name = cpl_propertylist_get_string(header, hname);
168 cpl_msg_debug(idstring,
"REC = %d, ID = %s", irec, name);
169 }
while (cpl_errorstate_is_equal(es));
170 cpl_errorstate_set(es);
171 cpl_msg_info(idstring,
"Using recipe parameters ESO PRO REC%d to determine " 172 "wavelength ranges", --irec);
181 char *hname = cpl_sprintf(
"ESO PRO REC%d PARAM%d NAME", irec, ipar);
182 const char *name = cpl_propertylist_get_string(header, hname);
184 cpl_boolean islmin = name && !strncmp(name,
"lambdamin", 10),
185 islmax = name && !strncmp(name,
"lambdamax", 10);
186 if (islmin || islmax) {
187 char *hval = cpl_sprintf(
"ESO PRO REC%d PARAM%d VALUE", irec, ipar);
192 lmin = atof(cpl_propertylist_get_string(header, hval));
193 cpl_msg_debug(idstring,
"lmin = %f", lmin);
194 if (lmin < lminout) {
201 lmax = atof(cpl_propertylist_get_string(header, hval));
202 cpl_msg_debug(idstring,
"lmax = %f", lmax);
203 if (lmax > lmaxout) {
209 }
while (cpl_errorstate_is_equal(es));
210 cpl_errorstate_set(es);
211 cpl_propertylist_delete(header);
214 header = cpl_propertylist_load(iname, iext);
218 int naxis3 = cpl_propertylist_get_int(header,
"NAXIS3");
221 *lunit = cpl_table_get_column_unit(table,
"LMIN");
223 cpl_table_set_column_unit(table,
"LMIN", cunit3);
224 cpl_table_set_column_unit(table,
"LMAX", cunit3);
225 }
else if (strncmp(lunit, cunit3, strlen(lunit) + 1)) {
226 cpl_msg_warning(idstring,
"Cube %d does not contain wavelengths in " 227 "%s (%s), skipping it", ic + 1, lunit, cunit3);
228 cpl_propertylist_delete(header);
233 ctype3ref = cpl_strdup(ctype3);
237 loglambda = ctype3ref && (!strncmp(ctype3ref,
"AWAV-LOG", 9) ||
238 !strncmp(ctype3ref,
"WAVE-LOG", 9));
239 }
else if (strncmp(ctype3ref, ctype3, strlen(ctype3ref)) ||
240 fabs(crpix3 - crpix3ref) > DBL_EPSILON ||
241 fabs(crval3 - crval3ref) > DBL_EPSILON ||
242 fabs(cd33 - cd33ref) > DBL_EPSILON) {
243 cpl_msg_warning(idstring,
"Cube %d does not match in spectral WCS, " 244 "skipping it", ic + 1);
245 cpl_propertylist_delete(header);
248 double lpx1 = (1. - crpix3) * cd33 + crval3,
249 lpx2 = (naxis3 - crpix3) * cd33 + crval3;
251 lpx1 = crval3 * exp((1 - crpix3) * cd33 / crval3);
252 lpx2 = crval3 * exp((naxis3 - crpix3) * cd33 / crval3);
254 cpl_msg_debug(idstring,
"Cube %d, axis 3 WCS: %f %f %f (%s, %d pixels, " 255 "%f..%f %s)", ic + 1, crpix3, crval3, cd33, ctype3, naxis3,
279 ctype1ref = cpl_strdup(ctype1);
280 ctype2ref = cpl_strdup(ctype2);
281 cunit1ref = cpl_strdup(cunit1);
282 cunit2ref = cpl_strdup(cunit2);
291 }
else if (strncmp(ctype1ref, ctype1, strlen(ctype1ref)) ||
292 strncmp(ctype2ref, ctype2, strlen(ctype2ref)) ||
293 strncmp(cunit1ref, cunit1, strlen(cunit1ref)) ||
294 strncmp(cunit2ref, cunit2, strlen(cunit2ref)) ||
295 fabs(crpix1 - crpix1ref) > DBL_EPSILON ||
296 fabs(crval1 - crval1ref) > DBL_EPSILON ||
297 fabs(crpix2 - crpix2ref) > DBL_EPSILON ||
298 fabs(crval2 - crval2ref) > DBL_EPSILON ||
299 fabs(cd11 - cd11ref) > DBL_EPSILON ||
300 fabs(cd12 - cd12ref) > DBL_EPSILON ||
301 fabs(cd21 - cd21ref) > DBL_EPSILON ||
302 fabs(cd22 - cd22ref) > DBL_EPSILON) {
303 cpl_msg_warning(idstring,
"Cube %d does not match in spatial WCS, " 304 "skipping it", ic + 1);
305 cpl_propertylist_delete(header);
308 cpl_propertylist_delete(header);
311 int l1 = lround((lmin - crval3) / cd33 + crpix3),
312 l2 = lround((lmax - crval3) / cd33 + crpix3);
314 l1 = lround(crval3 / cd33 * log(lmin / crval3)) + crpix3;
315 l2 = lround(crval3 / cd33 * log(lmax / crval3)) + crpix3;
317 cpl_msg_debug(idstring,
"Cube %d: %d..%d (%f..%f Angstrom)", ic + 1,
321 }
else if (l1 >= naxis3) {
322 cpl_msg_warning(idstring,
"Something is wrong with cube %d: l1 = %d!",
331 }
else if (l2 <= 1) {
332 cpl_msg_warning(idstring,
"Something is wrong with cube %d: l2 = %d!",
338 cpl_msg_debug(idstring,
"Cube %d: ---> %d..%d", ic + 1, l1, l2);
341 cpl_table_set_string(table,
"FILENAME", ic, iname);
342 cpl_table_set(table,
"LMIN", ic, lmin);
343 cpl_table_set(table,
"LMAX", ic, lmax);
344 cpl_table_set(table,
"P1", ic, l1);
345 cpl_table_set(table,
"P2", ic, l2);
354 cpl_table_select_all(table);
355 cpl_table_and_selected_invalid(table,
"FILENAME");
356 cpl_table_erase_selected(table);
357 ncubes = cpl_table_get_nrow(table);
359 cpl_msg_error(idstring,
"Only %d cube%s with valid info %s found!", ncubes,
360 ncubes ?
"" :
"s", ncubes ?
"was" :
"were");
366 cpl_propertylist *order = cpl_propertylist_new();
367 cpl_propertylist_append_bool(order,
"P1", CPL_FALSE);
368 cpl_table_sort(table, order);
369 cpl_propertylist_delete(order);
371 printf(
"Stored and sorted %d cubes:\n", ncubes);
372 cpl_table_dump(table, 0, ncubes, stdout);
381 int nover = 0, ngaps = 0;
382 for (ic = 1; ic < cpl_table_get_nrow(table); ic++) {
383 int p2a = cpl_table_get_int(table,
"P2", ic - 1, NULL),
384 p1b = cpl_table_get_int(table,
"P1", ic, NULL);
385 double lmaxa = cpl_table_get_double(table,
"LMAX", ic - 1, NULL);
386 int pdiff = p1b - p2a;
392 lmaxa += cd33ref * (pdiff - 1);
397 lmaxa += cd33ref * (pdiff - 1);
400 cpl_table_set_int(table,
"P2", ic - 1, p2a);
401 cpl_table_set_double(table,
"LMAX", ic - 1, lmaxa);
404 printf(
"Cleaned up %d overlaps and %d gaps.\n", nover, ngaps);
405 cpl_table_dump(table, 0, ncubes, stdout);
411 const char *fn = cpl_table_get_string(table,
"FILENAME", 0);
412 cpl_msg_info(idstring,
"Loading cube from \"%s\"", fn);
413 cube->
header = cpl_propertylist_load(fn, 0);
415 int iext = cpl_fits_find_extension(fn,
"DATA");
418 cpl_propertylist *wcs = cpl_propertylist_load(fn, iext);
420 cpl_propertylist_append(cube->
header, wcs);
421 cpl_propertylist_delete(wcs);
423 cube->
data = cpl_imagelist_load(fn, CPL_TYPE_FLOAT, iext);
424 iext = cpl_fits_find_extension(fn,
"STAT");
425 cube->
stat = cpl_imagelist_load(fn, CPL_TYPE_FLOAT, iext);
428 int nplanes = cpl_imagelist_get_size(cube->
data),
429 l1 = cpl_table_get_int(table,
"P1", 0, NULL),
430 l2 = cpl_table_get_int(table,
"P2", 0, NULL);
431 cpl_array *aflags = cpl_array_new(nplanes, CPL_TYPE_DOUBLE);
432 cpl_array_fill_window_double(aflags, 0, nplanes, -1.);
433 cpl_array_fill_window_double(aflags, l1 - 1, l2 - l1 + 1, 1.);
435 cpl_array_dump(aflags, 0, 5, stdout);
436 cpl_array_dump(aflags, l1 - 4, 10, stdout);
437 cpl_array_dump(aflags, l2 - 4, 10, stdout);
438 cpl_array_dump(aflags, nplanes - 5, 6, stdout);
441 cpl_vector *vflags = cpl_vector_wrap(nplanes, cpl_array_unwrap(aflags));
442 cpl_imagelist_erase(cube->
data, vflags);
443 cpl_imagelist_erase(cube->
stat, vflags);
444 cpl_vector_delete(vflags);
445 cpl_msg_debug(idstring,
"%d of %d planes left in first cube",
446 (
int)cpl_imagelist_get_size(cube->
data), nplanes);
447 nplanes = cpl_imagelist_get_size(cube->
data);
450 cpl_propertylist_update_double(cube->
header,
"CRPIX3", crpix3ref - (l1 - 1));
454 for (ic = 1; ic < cpl_table_get_nrow(table); ic++) {
455 fn = cpl_table_get_string(table,
"FILENAME", ic);
456 cpl_msg_info(idstring,
"Loading cube from \"%s\"", fn);
457 iext = cpl_fits_find_extension(fn,
"DATA");
458 cpl_imagelist *cubedata = cpl_imagelist_load(fn, CPL_TYPE_FLOAT, iext);
459 iext = cpl_fits_find_extension(fn,
"STAT");
460 cpl_imagelist *cubestat = cpl_imagelist_load(fn, CPL_TYPE_FLOAT, iext);
463 l1 = cpl_table_get_int(table,
"P1", ic, NULL);
464 l2 = cpl_table_get_int(table,
"P2", ic, NULL);
466 for (l = l1 - 1; l < l2; l++, nplanes = cpl_imagelist_get_size(cube->
data)) {
467 cpl_error_code rc1, rc2;
468 rc1 = cpl_imagelist_set(cube->
data,
469 cpl_image_duplicate(cpl_imagelist_get(cubedata, l)),
471 rc2 = cpl_imagelist_set(cube->
stat,
472 cpl_image_duplicate(cpl_imagelist_get(cubestat, l)),
474 if (rc1 != rc2 || rc1 != CPL_ERROR_NONE || rc2 != CPL_ERROR_NONE) {
475 cpl_msg_warning(idstring,
"Could not append plane %d of cube %d to output cube",
479 cpl_imagelist_delete(cubedata);
480 cpl_imagelist_delete(cubestat);
481 cpl_msg_debug(idstring,
"output cube now has %d/%d planes after copying %d " 482 "planes from cube %d", nplanes,
483 (
int)cpl_imagelist_get_size(cube->
data), l2 - l1 + 1, ic + 1);
485 cpl_table_delete(table);
488 cpl_msg_info(idstring,
"Resetting recipe parameters ESO PRO REC%d to determine " 489 "wavelength ranges", irecout);
490 char *hname = cpl_sprintf(
"ESO PRO REC%d PARAM%d VALUE", irecout, iparout1),
491 *hvalue = cpl_sprintf(
"%g", lminout),
492 *hcomment = cpl_sprintf(
"set with %s!", idstring);
493 cpl_propertylist_update_string(cube->
header, hname, hvalue);
494 cpl_propertylist_set_comment(cube->
header, hname, hcomment);
497 hname = cpl_sprintf(
"ESO PRO REC%d PARAM%d VALUE", irecout, iparout2),
498 hvalue = cpl_sprintf(
"%g", lmaxout),
499 cpl_propertylist_update_string(cube->
header, hname, hvalue);
500 cpl_propertylist_set_comment(cube->
header, hname, hcomment);
508 if (rc == CPL_ERROR_NONE) {
509 cpl_msg_info(idstring,
"Saved cube to \"%s\".", oname);
511 cpl_msg_error(idstring,
"Error while saving cube to \"%s\": %s (%d)", oname,
512 cpl_error_get_message(), rc);
516 if (!cpl_errorstate_is_equal(state)) {
Structure definition of a MUSE datacube.
double muse_pfits_get_cd(const cpl_propertylist *aHeaders, unsigned int aAxisI, unsigned int aAxisJ)
find out the WCS coordinate at the reference point
double muse_pfits_get_crval(const cpl_propertylist *aHeaders, unsigned int aAxis)
find out the WCS coordinate at the reference point
void muse_datacube_delete(muse_datacube *aCube)
Deallocate memory associated to a muse_datacube object.
const char * muse_pfits_get_cunit(const cpl_propertylist *aHeaders, unsigned int aAxis)
find out the WCS axis unit string
cpl_error_code muse_datacube_save(muse_datacube *aCube, const char *aFilename)
Save the three cube extensions and the FITS headers of a MUSE datacube to a file. ...
double muse_pfits_get_crpix(const cpl_propertylist *aHeaders, unsigned int aAxis)
find out the WCS reference point
#define MUSE_WCS_KEYS
regular expression for WCS properties
void muse_cplerrorstate_dump_some(unsigned aCurrent, unsigned aFirst, unsigned aLast)
Dump some CPL errors.
cpl_imagelist * data
the cube containing the actual data values
const char * muse_pfits_get_ctype(const cpl_propertylist *aHeaders, unsigned int aAxis)
find out the WCS axis type string
cpl_propertylist * header
the FITS header
void muse_processing_recipeinfo(cpl_plugin *)
Output main pipeline configuration, inputs, and parameters.
cpl_imagelist * stat
the cube containing the data variance