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_level(CPL_MSG_DEBUG);
70 cpl_msg_set_time_on();
71 cpl_msg_set_component_on();
72 cpl_errorstate state = cpl_errorstate_get();
83 for (i = 1; i < argc; i++) {
84 if (strncmp(argv[i],
"-xxx", 5) == 0) {
92 }
else if (strncmp(argv[i],
"-", 1) == 0) {
104 FILE *fp = fopen(oname,
"r");
106 cpl_msg_error(idstring,
"Output cube \"%s\" is already present!", oname);
107 cpl_msg_error(idstring,
"Please specify another output name or rename the "
108 "existing file with this name.");
113 int ncubes = argc - i;
114 cpl_msg_info(idstring,
"Will write combination of %d cubes to \"%s\".",
118 cpl_table *table = cpl_table_new(ncubes);
119 cpl_table_new_column(table,
"FILENAME", CPL_TYPE_STRING);
120 cpl_table_new_column(table,
"LMIN", CPL_TYPE_DOUBLE);
121 cpl_table_new_column(table,
"LMAX", CPL_TYPE_DOUBLE);
122 cpl_table_new_column(table,
"P1", CPL_TYPE_INT);
123 cpl_table_new_column(table,
"P2", CPL_TYPE_INT);
126 char *ctype1ref = NULL, *ctype2ref = NULL,
127 *cunit1ref = NULL, *cunit2ref = NULL;
128 double crpix1ref = NAN, crpix2ref = NAN, crval1ref = NAN, crval2ref = NAN,
129 cd11ref = NAN, cd12ref = NAN, cd21ref = NAN, cd22ref = NAN;
130 char *ctype3ref = NULL;
131 double crpix3ref = NAN,
135 for (ic = 0; ic < ncubes; ic++) {
137 char *iname = argv[argidx];
139 int iext = cpl_fits_find_extension(iname,
"DATA");
141 cpl_msg_warning(idstring,
"Could not open cube \"%s\"", iname);
146 cpl_propertylist *header = cpl_propertylist_load(iname, 0);
147 double lmin = -FLT_MAX,
150 cpl_errorstate es = cpl_errorstate_get();
154 char *hname = cpl_sprintf(
"ESO PRO REC1 PARAM%d NAME", ipar);
155 const char *name = cpl_propertylist_get_string(header, hname);
157 cpl_boolean islmin = name && !strncmp(name,
"lambdamin", 10),
158 islmax = name && !strncmp(name,
"lambdamax", 10);
159 if (islmin || islmax) {
160 char *hval = cpl_sprintf(
"ESO PRO REC1 PARAM%d VALUE", ipar);
162 lmin = atof(cpl_propertylist_get_string(header, hval));
163 cpl_msg_debug(idstring,
"lmin = %f", lmin);
165 lmax = atof(cpl_propertylist_get_string(header, hval));
166 cpl_msg_debug(idstring,
"lmax = %f", lmax);
170 }
while (cpl_errorstate_is_equal(es));
171 cpl_errorstate_set(es);
172 cpl_propertylist_delete(header);
175 header = cpl_propertylist_load(iname, iext);
176 double crpix3 = cpl_propertylist_get_double(header,
"CRPIX3"),
177 crval3 = cpl_propertylist_get_double(header,
"CRVAL3"),
178 cd33 = cpl_propertylist_get_double(header,
"CD3_3");
179 int naxis3 = cpl_propertylist_get_int(header,
"NAXIS3");
181 const char *cunit3 = cpl_propertylist_get_string(header,
"CUNIT3"),
182 *lunit = cpl_table_get_column_unit(table,
"LMIN");
184 cpl_table_set_column_unit(table,
"LMIN", cunit3);
185 cpl_table_set_column_unit(table,
"LMAX", cunit3);
186 }
else if (strncmp(lunit, cunit3, strlen(lunit) + 1)) {
187 cpl_msg_warning(idstring,
"Cube %d does not contain wavelengths in "
188 "%s (%s), skipping it", ic + 1, lunit, cunit3);
189 cpl_propertylist_delete(header);
192 const char *ctype3 = cpl_propertylist_get_string(header,
"CTYPE3");
194 ctype3ref = cpl_strdup(ctype3);
198 }
else if (strncmp(ctype3ref, ctype3, strlen(ctype3ref)) ||
199 fabs(crpix3 - crpix3ref) > DBL_EPSILON ||
200 fabs(crval3 - crval3ref) > DBL_EPSILON ||
201 fabs(cd33 - cd33ref) > DBL_EPSILON) {
202 cpl_msg_warning(idstring,
"Cube %d does not match in spectral WCS, "
203 "skipping it", ic + 1);
204 cpl_propertylist_delete(header);
207 double lpx1 = (1. - crpix3) * cd33 + crval3,
208 lpx2 = (naxis3 - crpix3) * cd33 + crval3;
209 cpl_msg_debug(idstring,
"Cube %d, axis 3 WCS: %f %f %f (%s, %d pixels, "
210 "%f..%f %s)", ic + 1, crpix3, crval3, cd33, ctype3, naxis3,
221 const char *ctype1 = cpl_propertylist_get_string(header,
"CTYPE1"),
222 *ctype2 = cpl_propertylist_get_string(header,
"CTYPE2"),
223 *cunit1 = cpl_propertylist_get_string(header,
"CUNIT1"),
224 *cunit2 = cpl_propertylist_get_string(header,
"CUNIT2");
225 double crpix1 = cpl_propertylist_get_double(header,
"CRPIX1"),
226 crpix2 = cpl_propertylist_get_double(header,
"CRVAL2"),
227 crval1 = cpl_propertylist_get_double(header,
"CRVAL1"),
228 crval2 = cpl_propertylist_get_double(header,
"CRVAL2"),
229 cd11 = cpl_propertylist_get_double(header,
"CD1_1"),
230 cd12 = cpl_propertylist_get_double(header,
"CD1_2"),
231 cd21 = cpl_propertylist_get_double(header,
"CD2_1"),
232 cd22 = cpl_propertylist_get_double(header,
"CD2_2");
234 ctype1ref = cpl_strdup(ctype1);
235 ctype2ref = cpl_strdup(ctype2);
236 cunit1ref = cpl_strdup(cunit1);
237 cunit2ref = cpl_strdup(cunit2);
246 }
else if (strncmp(ctype1ref, ctype1, strlen(ctype1ref)) ||
247 strncmp(ctype2ref, ctype2, strlen(ctype2ref)) ||
248 strncmp(cunit1ref, cunit1, strlen(cunit1ref)) ||
249 strncmp(cunit2ref, cunit2, strlen(cunit2ref)) ||
250 fabs(crpix1 - crpix1ref) > DBL_EPSILON ||
251 fabs(crval1 - crval1ref) > DBL_EPSILON ||
252 fabs(crpix2 - crpix2ref) > DBL_EPSILON ||
253 fabs(crval2 - crval2ref) > DBL_EPSILON ||
254 fabs(cd11 - cd11ref) > DBL_EPSILON ||
255 fabs(cd12 - cd12ref) > DBL_EPSILON ||
256 fabs(cd21 - cd21ref) > DBL_EPSILON ||
257 fabs(cd22 - cd22ref) > DBL_EPSILON) {
258 cpl_msg_warning(idstring,
"Cube %d does not match in spatial WCS, "
259 "skipping it", ic + 1);
260 cpl_propertylist_delete(header);
263 cpl_propertylist_delete(header);
266 int l1 = lround((lmin - crval3) / cd33 + crpix3),
267 l2 = lround((lmax - crval3) / cd33 + crpix3);
268 cpl_msg_debug(idstring,
"Cube %d: %d..%d (%f..%f Angstrom)", ic + 1,
272 }
else if (l1 >= naxis3) {
273 cpl_msg_warning(idstring,
"Something is wrong with cube %d: l1 = %d!",
282 }
else if (l2 <= 1) {
283 cpl_msg_warning(idstring,
"Something is wrong with cube %d: l2 = %d!",
289 cpl_msg_debug(idstring,
"Cube %d: ---> %d..%d", ic + 1, l1, l2);
292 cpl_table_set_string(table,
"FILENAME", ic, iname);
293 cpl_table_set(table,
"LMIN", ic, lmin);
294 cpl_table_set(table,
"LMAX", ic, lmax);
295 cpl_table_set(table,
"P1", ic, l1);
296 cpl_table_set(table,
"P2", ic, l2);
305 cpl_table_select_all(table);
306 cpl_table_and_selected_invalid(table,
"FILENAME");
307 cpl_table_erase_selected(table);
308 ncubes = cpl_table_get_nrow(table);
310 cpl_msg_error(idstring,
"Only %d cube%s with valid info %s found!", ncubes,
311 ncubes ?
"" :
"s", ncubes ?
"was" :
"were");
317 cpl_propertylist *order = cpl_propertylist_new();
318 cpl_propertylist_append_bool(order,
"P1", CPL_FALSE);
319 cpl_table_sort(table, order);
320 cpl_propertylist_delete(order);
322 printf(
"Stored and sorted %d cubes:\n", ncubes);
323 cpl_table_dump(table, 0, ncubes, stdout);
332 int nover = 0, ngaps = 0;
333 for (ic = 1; ic < cpl_table_get_nrow(table); ic++) {
334 int p2a = cpl_table_get_int(table,
"P2", ic - 1, NULL),
335 p1b = cpl_table_get_int(table,
"P1", ic, NULL);
336 double lmaxa = cpl_table_get_double(table,
"LMAX", ic - 1, NULL);
337 int pdiff = p1b - p2a;
343 lmaxa += cd33ref * (pdiff - 1);
348 lmaxa += cd33ref * (pdiff - 1);
351 cpl_table_set_int(table,
"P2", ic - 1, p2a);
352 cpl_table_set_double(table,
"LMAX", ic - 1, lmaxa);
355 printf(
"Cleaned up %d overlaps and %d gaps.\n", nover, ngaps);
356 cpl_table_dump(table, 0, ncubes, stdout);
362 const char *fn = cpl_table_get_string(table,
"FILENAME", 0);
363 cpl_msg_info(idstring,
"Loading cube from \"%s\"", fn);
364 cube->
header = cpl_propertylist_load(fn, 0);
366 int iext = cpl_fits_find_extension(fn,
"DATA");
369 cpl_propertylist *wcs = cpl_propertylist_load(fn, iext);
370 cpl_propertylist_erase_regexp(wcs, MUSE_WCS_KEYS, 1);
371 cpl_propertylist_append(cube->
header, wcs);
372 cpl_propertylist_delete(wcs);
374 cube->
data = cpl_imagelist_load(fn, CPL_TYPE_FLOAT, iext);
375 iext = cpl_fits_find_extension(fn,
"STAT");
376 cube->
stat = cpl_imagelist_load(fn, CPL_TYPE_FLOAT, iext);
379 int nplanes = cpl_imagelist_get_size(cube->
data),
380 l1 = cpl_table_get_int(table,
"P1", 0, NULL),
381 l2 = cpl_table_get_int(table,
"P2", 0, NULL);
382 cpl_array *aflags = cpl_array_new(nplanes, CPL_TYPE_DOUBLE);
383 cpl_array_fill_window_double(aflags, 0, nplanes, -1.);
384 cpl_array_fill_window_double(aflags, l1 - 1, l2 - l1 + 1, 1.);
386 cpl_array_dump(aflags, 0, 5, stdout);
387 cpl_array_dump(aflags, l1 - 4, 10, stdout);
388 cpl_array_dump(aflags, l2 - 4, 10, stdout);
389 cpl_array_dump(aflags, nplanes - 5, 6, stdout);
392 cpl_vector *vflags = cpl_vector_wrap(nplanes, cpl_array_unwrap(aflags));
393 cpl_imagelist_erase(cube->
data, vflags);
394 cpl_imagelist_erase(cube->
stat, vflags);
395 cpl_vector_delete(vflags);
396 cpl_msg_debug(idstring,
"%d of %d planes left in first cube",
397 (
int)cpl_imagelist_get_size(cube->
data), nplanes);
398 nplanes = cpl_imagelist_get_size(cube->
data);
400 cpl_propertylist_update_double(cube->
header,
"CRPIX3", 1.);
401 cpl_propertylist_update_double(cube->
header,
"CRVAL3",
402 cpl_table_get(table,
"LMIN", 0, NULL));
406 for (ic = 1; ic < cpl_table_get_nrow(table); ic++) {
407 fn = cpl_table_get_string(table,
"FILENAME", ic);
408 cpl_msg_info(idstring,
"Loading cube from \"%s\"", fn);
409 iext = cpl_fits_find_extension(fn,
"DATA");
410 cpl_imagelist *cubedata = cpl_imagelist_load(fn, CPL_TYPE_FLOAT, iext);
411 iext = cpl_fits_find_extension(fn,
"STAT");
412 cpl_imagelist *cubestat = cpl_imagelist_load(fn, CPL_TYPE_FLOAT, iext);
415 l1 = cpl_table_get_int(table,
"P1", ic, NULL);
416 l2 = cpl_table_get_int(table,
"P2", ic, NULL);
418 for (l = l1 - 1; l < l2; l++, nplanes = cpl_imagelist_get_size(cube->
data)) {
419 cpl_error_code rc1, rc2;
420 rc1 = cpl_imagelist_set(cube->
data,
421 cpl_image_duplicate(cpl_imagelist_get(cubedata, l)),
423 rc2 = cpl_imagelist_set(cube->
stat,
424 cpl_image_duplicate(cpl_imagelist_get(cubestat, l)),
426 if (rc1 != rc2 || rc1 != CPL_ERROR_NONE || rc2 != CPL_ERROR_NONE) {
427 cpl_msg_warning(idstring,
"Could not append plane %d of cube %d to output cube",
431 cpl_imagelist_delete(cubedata);
432 cpl_imagelist_delete(cubestat);
433 cpl_msg_debug(idstring,
"output cube now has %d/%d planes after copying %d "
434 "planes from cube %d", nplanes,
435 (
int)cpl_imagelist_get_size(cube->
data), l2 - l1 + 1, ic + 1);
437 cpl_table_delete(table);
440 cpl_propertylist_erase_regexp(cube->
header,
"ESO PRO REC1 ", 0);
444 if (rc == CPL_ERROR_NONE) {
445 cpl_msg_info(idstring,
"Saved cube to \"%s\".", oname);
447 cpl_msg_error(idstring,
"Error while saving cube to \"%s\": %s (%d)", oname,
448 cpl_error_get_message(), rc);
452 if (!cpl_errorstate_is_equal(state)) {
Structure definition of a MUSE datacube.
void muse_datacube_delete(muse_datacube *aCube)
Deallocate memory associated to a muse_datacube object.
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. ...
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
cpl_propertylist * header
the FITS header
cpl_imagelist * stat
the cube containing the data variance