36 #include "muse_processing.h"
37 #include "muse_instrument.h"
40 #include "muse_pfits.h"
41 #include "muse_resampling.h"
42 #include "muse_utils.h"
48 #define DEBUG_EXPOSURES_SORT 0
77 muse_processing_get_rawtag(cpl_recipe *aRecipe)
80 if (recipeconfig == NULL) {
81 cpl_msg_error(__func__,
"No recipeconfig found!");
82 return MUSE_TAG_EMPTY;
84 const char *rawTag = NULL;
85 cpl_size iframe, nframes = cpl_frameset_get_size(aRecipe->frames);
86 for (iframe = 0; iframe < nframes; iframe++) {
87 cpl_frame *frame = cpl_frameset_get_position(aRecipe->frames, iframe);
88 rawTag = cpl_frame_get_tag(frame);
89 cpl_errorstate state = cpl_errorstate_get();
90 char**calibTags = cpl_recipeconfig_get_inputs(recipeconfig, rawTag);
91 if (calibTags != NULL) {
93 for (i = 0; calibTags[i] != NULL; i++) {
94 cpl_free(calibTags[i]);
99 cpl_errorstate_set(state);
102 if (iframe >= nframes) {
103 cpl_msg_error(__func__,
"No valid raw tag found!");
104 return MUSE_TAG_EMPTY;
123 processing->
inputFrames = cpl_frameset_duplicate(aRecipe->frames);
124 processing->
recipe = aRecipe;
128 processing->
inputTag = muse_processing_get_rawtag(aRecipe);
129 processing->
framecounter = cpl_malloc(
sizeof(muse_framecounter_s));
150 for (i = 0; aProcessing->
framecounter[i].tag != NULL; i++) {
154 cpl_free(aProcessing);
176 cpl_frame *aFrame, cpl_frame_group aGroup,
180 cpl_msg_error(__func__,
"NULL processing struct!");
184 if (aGroup == CPL_FRAME_GROUP_CALIB) {
185 cpl_msg_debug(__func__,
"using %s %s frame %s",
"calibration",
186 cpl_frame_get_tag(aFrame), cpl_frame_get_filename(aFrame));
187 }
else if (aGroup == CPL_FRAME_GROUP_RAW) {
188 cpl_msg_debug(__func__,
"using %s %s frame %s",
"raw",
189 cpl_frame_get_tag(aFrame), cpl_frame_get_filename(aFrame));
193 const char *fn = cpl_frame_get_filename(aFrame),
194 *tag = cpl_frame_get_tag(aFrame);
195 cpl_size iframe, nframes = cpl_frameset_get_size(aProcessing->
usedFrames);
197 (iframe < nframes) && fn && tag;
199 cpl_frame *frame = cpl_frameset_get_position(aProcessing->
usedFrames, iframe);
200 const char *fn2 = cpl_frame_get_filename(frame),
201 *tag2 = cpl_frame_get_tag(frame);
202 if (fn2 && !strncmp(fn, fn2, strlen(fn) + 1) &&
203 tag2 && !strncmp(tag, tag2, strlen(tag) + 1)) {
205 cpl_frame_delete(aFrame);
210 cpl_frame_set_group(aFrame, aGroup);
212 cpl_frameset_insert(aProcessing->
usedFrames, cpl_frame_duplicate(aFrame));
214 cpl_frameset_insert(aProcessing->
usedFrames, aFrame);
234 const char *aTag,
int aIFU)
237 cpl_msg_error(__func__,
"NULL processing struct!");
241 for (i = 0; aProcessing->
framecounter[i].tag != NULL; i++) {
242 if (strcmp(aProcessing->
framecounter[i].tag, aTag) == 0 &&
248 (i+2)*
sizeof(muse_framecounter_s));
272 cpl_propertylist *aHeader, cpl_frame *aFrame,
273 int aIndex,
const char *aDateObs,
274 cpl_boolean aSequence)
277 cpl_msg_error(__func__,
"NULL processing struct!");
282 cpl_msg_warning(__func__,
"No raw input files, no DFS product header added");
287 cpl_propertylist *hkeep = cpl_propertylist_new();
288 cpl_propertylist_copy_property_regexp(hkeep, aHeader,
289 MUSE_HEADERS_KEEP_REGEXP, 0);
292 cpl_propertylist_erase_regexp(aHeader,
"^ESO PRO|^COMMENT", 0);
294 cpl_propertylist_erase_regexp(aHeader, MUSE_HDR_TMP_REGEXP, 0);
298 aIndex, aDateObs, aSequence);
301 if (cpl_propertylist_has(aHeader,
"EQUINOX") &&
302 cpl_propertylist_get_type(aHeader,
"EQUINOX") < CPL_TYPE_FLOAT) {
303 cpl_property *equinox = cpl_propertylist_get_property(aHeader,
"EQUINOX");
304 double equvalue = cpl_property_get_long_long(equinox);
305 const char *equcomment = cpl_property_get_comment(equinox);
306 cpl_property_set_name(equinox,
"EQUIBRK");
307 cpl_propertylist_insert_after_double(aHeader,
"EQUIBRK",
"EQUINOX",
309 cpl_propertylist_set_comment(aHeader,
"EQUINOX", equcomment);
310 cpl_propertylist_erase(aHeader,
"EQUIBRK");
313 char *pkgstring = cpl_sprintf(
"%s/%s", PACKAGE, PACKAGE_VERSION);
314 if (cpl_dfs_setup_product_header(aHeader, aFrame, fset,
317 pkgstring, MUSE_PRO_DID, NULL)
319 cpl_msg_error(__func__,
"Could not add DFS product header: %s",
320 cpl_error_get_message());
323 cpl_frameset_delete(fset);
326 int i, n = cpl_propertylist_get_size(hkeep);
327 for (i = 0; i < n; i++) {
328 const cpl_property *p = cpl_propertylist_get_const(hkeep, i);
329 cpl_propertylist_erase(aHeader, cpl_property_get_name(p));
330 cpl_propertylist_append_property(aHeader, p);
332 cpl_propertylist_delete(hkeep);
335 cpl_propertylist_update_string(aHeader,
"ESO PRO TECH",
"IFU");
338 cpl_propertylist_update_bool(aHeader,
"ESO PRO SCIENCE", 1);
368 cpl_propertylist *aHeader,
const char *aTag,
369 cpl_frame_type aType)
371 cpl_ensure(aProcessing, CPL_ERROR_NULL_INPUT, NULL);
373 const char *prefix = cpl_propertylist_has(aHeader,
"MUSE PRIVATE FILE PREFIX")
374 ? cpl_propertylist_get_string(aHeader,
375 "MUSE PRIVATE FILE PREFIX")
378 cpl_frame *frame = cpl_frame_new();
380 cpl_errorstate prestate = cpl_errorstate_get();
387 framecounter = muse_processing_get_framecounter(aProcessing, prefix, aIFU);
389 const char *dateobs = NULL;
396 char filename[FILENAME_MAX];
398 if (framecounter == 0) {
399 snprintf(filename, FILENAME_MAX,
"%s-%02d.fits", prefix, aIFU);
401 snprintf(filename, FILENAME_MAX,
"%s_%04d-%02d.fits", prefix,
405 if (framecounter == 0) {
406 snprintf(filename, FILENAME_MAX,
"%s.fits", prefix);
408 snprintf(filename, FILENAME_MAX,
"%s_%04d.fits", prefix, framecounter);
411 cpl_frame_set_filename(frame, filename);
412 cpl_frame_set_tag(frame, aTag);
413 cpl_frame_set_type(frame, aType);
414 cpl_frame_set_group(frame, CPL_FRAME_GROUP_PRODUCT);
415 cpl_frame_set_level(frame,
418 if (cpl_errorstate_get() != prestate) {
419 cpl_msg_error(__func__,
"Error while initialising the product frame: %s",
420 cpl_error_get_message());
421 cpl_frame_delete(frame);
424 cpl_propertylist_erase_regexp(aHeader,
"MUSE PRIVATE.*", 0);
427 muse_processing_setup_header(aProcessing, aHeader, frame, idx, dateobs,
453 cpl_ensure_code(aProcessing && aImage && aTag, CPL_ERROR_NULL_INPUT);
457 CPL_FRAME_TYPE_IMAGE);
458 cpl_msg_info(__func__,
"Saving image as %s", cpl_frame_get_filename(frame));
460 if (r == CPL_ERROR_NONE) {
463 cpl_frame_delete(frame);
492 cpl_ensure_code(aProcessing && aCube && aTag, CPL_ERROR_NULL_INPUT);
494 CPL_ERROR_ILLEGAL_INPUT);
500 aTag, CPL_FRAME_TYPE_IMAGE);
501 cpl_msg_info(__func__,
"Saving %s cube as \"%s\"",
503 cpl_frame_get_filename(frame));
504 cpl_error_code rc = CPL_ERROR_NONE;
507 cpl_frame_get_filename(frame));
510 cpl_frame_get_filename(frame));
512 if (rc == CPL_ERROR_NONE) {
515 cpl_frame_delete(frame);
544 void *aTable, cpl_propertylist *aHeader,
547 cpl_ensure_code(aProcessing && aTable && aTag, CPL_ERROR_NULL_INPUT);
549 CPL_ERROR_ILLEGAL_INPUT);
552 cpl_propertylist *header;
554 cpl_ensure_code(aHeader, CPL_ERROR_NULL_INPUT);
560 aTag, CPL_FRAME_TYPE_TABLE);
561 cpl_msg_info(__func__,
"Saving %stable as \"%s\"",
563 cpl_frame_get_filename(frame));
564 cpl_error_code rc = CPL_ERROR_NONE;
566 rc = cpl_table_save((cpl_table *)aTable, aHeader, NULL,
567 cpl_frame_get_filename(frame), CPL_IO_CREATE);
570 cpl_frame_get_filename(frame));
572 if (rc == CPL_ERROR_NONE) {
575 cpl_msg_error(__func__,
"Saving %stable failed: %s",
577 cpl_error_get_message());
578 cpl_frame_delete(frame);
603 cpl_image *aImage, cpl_propertylist *aHeader,
606 cpl_ensure_code(aProcessing && aImage && aHeader && aTag, CPL_ERROR_NULL_INPUT);
610 CPL_FRAME_TYPE_IMAGE);
611 cpl_msg_info(__func__,
"Saving image as %s", cpl_frame_get_filename(frame));
612 int r = cpl_image_save(aImage, cpl_frame_get_filename(frame),
613 CPL_TYPE_UNSPECIFIED, aHeader, CPL_IO_CREATE);
614 if (r == CPL_ERROR_NONE) {
617 cpl_msg_error(__func__,
"Saving image failed: %s", cpl_error_get_message());
618 cpl_frame_delete(frame);
642 cpl_propertylist *aHeader,
const char *aTag)
644 cpl_ensure_code(aProcessing && aHeader && aTag, CPL_ERROR_NULL_INPUT);
648 CPL_FRAME_TYPE_IMAGE);
649 cpl_msg_info(__func__,
"Saving header as %s", cpl_frame_get_filename(frame));
650 cpl_error_code rc = cpl_propertylist_save(aHeader,
651 cpl_frame_get_filename(frame),
653 if (rc == CPL_ERROR_NONE) {
656 cpl_msg_error(__func__,
"Saving header failed: %s", cpl_error_get_message());
657 cpl_frame_delete(frame);
683 cpl_ensure_code(aProcessing && aMask && aTag, CPL_ERROR_NULL_INPUT);
687 CPL_FRAME_TYPE_IMAGE);
688 cpl_msg_info(__func__,
"Saving mask as %s", cpl_frame_get_filename(frame));
690 if (r == CPL_ERROR_NONE) {
693 cpl_frame_delete(frame);
719 cpl_msg_error(__func__,
"NULL processing struct");
720 return CPL_ERROR_NULL_INPUT;
722 cpl_recipeconfig *recipeconfig
725 cpl_msg_error(__func__,
"No recipeconfig found!");
726 return CPL_ERROR_ILLEGAL_INPUT;
733 int nFrames = cpl_frameset_count_tags(frames, aProcessing->
inputTag);
734 cpl_frameset_delete(frames);
735 int minFrames = cpl_recipeconfig_get_min_count(recipeconfig,
738 int maxFrames = cpl_recipeconfig_get_max_count(recipeconfig,
741 if (minFrames >= 0 && nFrames < minFrames) {
742 cpl_msg_error(__func__,
"Required %i, found %i input frames "
743 "with tag \"%s\" with IFU %hhu",
744 minFrames, nFrames, aProcessing->
inputTag, aIFU);
747 if (maxFrames >= 0 && nFrames > maxFrames) {
748 cpl_msg_error(__func__,
"Maximal %i, found %i input frames "
749 "with tag \"%s\" with IFU %hhu",
750 maxFrames, nFrames, aProcessing->
inputTag, aIFU);
753 char **tags = cpl_recipeconfig_get_inputs(recipeconfig,
756 cpl_msg_error(__func__,
"Input frames %s cannot be used with this recipe",
761 for (i = 0; tags != NULL && tags[i] != NULL; i++) {
764 nFrames = cpl_frameset_count_tags(frames, tags[i]);
765 cpl_frameset_delete(frames);
767 minFrames = cpl_recipeconfig_get_min_count(recipeconfig,
770 maxFrames = cpl_recipeconfig_get_max_count(recipeconfig,
773 if (minFrames >= 0 && nFrames < minFrames) {
774 cpl_msg_error(__func__,
"Required %i, found %i frames "
775 "with tag \"%s\" with IFU %hhu",
776 minFrames, nFrames, tags[i], aIFU);
779 if (nFrames == 0 && minFrames <= 0) {
780 cpl_msg_debug(__func__,
"Optional frame with tag %s not given", tags[i]);
782 if (maxFrames >= 0 && nFrames > maxFrames) {
783 cpl_msg_error(__func__,
"Maximal %i, found %i frames "
784 "with tag \"%s\" with IFU %hhu",
785 maxFrames, nFrames, tags[i], aIFU);
793 cpl_msg_error(__func__,
"Found %i error(s)", errors);
794 return CPL_ERROR_DATA_NOT_FOUND;
796 return CPL_ERROR_NONE;
826 cpl_ensure(aProcessing, CPL_ERROR_NULL_INPUT, NULL);
827 cpl_size nframes = cpl_frameset_get_size(aProcessing->
inputFrames);
828 cpl_ensure(nframes, CPL_ERROR_DATA_NOT_FOUND, NULL);
832 cpl_table *exptable = cpl_table_new(0);
834 cpl_table_new_column(exptable,
"DATE-OBS", CPL_TYPE_STRING);
837 for (i = 0; i <= kMuseNumIFUs; i++) {
838 snprintf(colname, 3,
"%02d", i);
839 cpl_table_new_column(exptable, colname, CPL_TYPE_STRING);
844 for (iframe = 0; iframe < nframes; iframe++) {
845 cpl_frame *frame = cpl_frameset_get_position(aProcessing->
inputFrames,
847 if (!strcmp(cpl_frame_get_tag(frame), aProcessing->
inputTag)) {
848 const char *filename = cpl_frame_get_filename(frame);
851 cpl_propertylist *header = cpl_propertylist_load(filename, 0);
854 cpl_msg_warning(__func__,
"\"%s\" does not contain the DATE-OBS "
855 "keyword, it will be ignored!", filename);
856 cpl_propertylist_delete(header);
861 cpl_msg_debug(__func__,
"\"%s\" seems to contain merged data (no "
862 "EXTNAME=CHANnn)", filename);
864 #if DEBUG_EXPOSURES_SORT
865 cpl_msg_debug(__func__,
"\"%s\": IFU %2d, DATE-OBS=\"%s\"", filename, ifu, date);
870 for (i = 0; i < cpl_table_get_nrow(exptable); i++) {
871 #if DEBUG_EXPOSURES_SORT
872 cpl_msg_debug(__func__,
"i=%d, DATE-OBS=\"%s\"", i,
873 cpl_table_get_string(exptable,
"DATE-OBS", i));
875 if (!strcmp(date, cpl_table_get_string(exptable,
"DATE-OBS", i))) {
882 cpl_table_set_size(exptable, cpl_table_get_nrow(exptable)+1);
883 irow = cpl_table_get_nrow(exptable) - 1;
884 cpl_table_set_string(exptable,
"DATE-OBS", irow, date);
889 snprintf(colname, 3,
"%02d", ifu);
890 if (cpl_table_is_valid(exptable, colname, irow)) {
891 cpl_msg_warning(__func__,
"we already have IFU %d of exposure %d (\"%s\")!"
892 " Ignoring \"%s\"", ifu, irow+1,
893 cpl_table_get_string(exptable, colname, irow),
895 cpl_propertylist_delete(header);
898 cpl_table_set_string(exptable, colname, irow, filename);
904 cpl_propertylist_delete(header);
906 #if DEBUG_EXPOSURES_SORT
908 cpl_msg_debug(__func__,
"wrong tag \"%s\" for \"%s\"",
909 cpl_frame_get_tag(frame), cpl_frame_get_filename(frame));
914 if (cpl_table_get_nrow(exptable) <= 0) {
916 cpl_table_delete(exptable);
917 cpl_error_set(__func__, CPL_ERROR_DATA_NOT_FOUND);
921 for (i = 0; i < cpl_table_get_nrow(exptable); i++) {
923 if (cpl_table_is_valid(exptable,
"00", i)) {
927 for (j = 1; j <= kMuseNumIFUs; j++) {
928 snprintf(colname, 3,
"%02d", j);
929 if (cpl_table_is_valid(exptable, colname, i)) {
933 cpl_msg_debug(__func__,
"Data from exposure %2d is contained in %2d "
934 "IFU%s/%d merged file%s", i+1, nvalid, nvalid == 1 ?
"" :
"s",
935 nmerged, nmerged == 1 ?
"" :
"s");
940 cpl_propertylist *sorting = cpl_propertylist_new();
941 cpl_propertylist_append_bool(sorting,
"DATE-OBS",
943 cpl_table_sort(exptable, sorting);
944 cpl_propertylist_delete(sorting);
968 if (frames == NULL || cpl_frameset_get_size(frames) <= 0) {
969 cpl_frameset_delete(frames);
972 cpl_frame *frame = cpl_frameset_get_position(frames, 0);
974 cpl_msg_info(__func__,
"using sky mask \"%s\" (%"CPL_SIZE_FORMAT
" pixels)",
975 cpl_frame_get_filename(frame), cpl_mask_count(skymask->
mask));
977 cpl_frameset_delete(frames);
int muse_processing_save_cimage(muse_processing *aProcessing, int aIFU, cpl_image *aImage, cpl_propertylist *aHeader, const char *aTag)
Save a computed FITS image to disk.
Structure definition of a MUSE datacube.
int muse_processing_get_frame_mode(const cpl_recipe *, const char *)
Get the mode for a product frame with a certain tag.
void muse_processing_delete(muse_processing *aProcessing)
Free the muse_processing structure.
muse_framecounter_s * framecounter
int muse_processing_save_mask(muse_processing *aProcessing, int aIFU, muse_mask *aMask, const char *aTag)
Save a computed MUSE mask to disk.
cpl_error_code muse_euro3dcube_save(muse_euro3dcube *aEuro3D, const char *aFilename)
Save a Euro3D cube object to a file.
unsigned char muse_utils_get_ifu(const cpl_propertylist *aHeaders)
Find out the IFU/channel from which this header originated.
const char * muse_pfits_get_dateobs(const cpl_propertylist *aHeaders)
find out the exposure time
Structure definition of MUSE three extension FITS file.
muse_mask * muse_processing_mask_load(muse_processing *aProcessing, const char *aTag)
Load a mask file and its FITS header.
cpl_propertylist * header
the FITS header
muse_mask * muse_mask_load(const char *aFilename)
Load a mask file and its FITS header.
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. ...
cpl_error_code muse_processing_prepare_header(const cpl_recipe *, const char *, cpl_propertylist *)
Prepare and check a FITS header for a certain frame tag.
cpl_error_code muse_processing_save_header(muse_processing *aProcessing, int aIFU, cpl_propertylist *aHeader, const char *aTag)
Save a FITS header to disk.
Structure definition of MUSE pixel table.
muse_processing * muse_processing_new(const char *aRecipeName, cpl_recipe *aRecipe)
Create a new processing structure.
cpl_frame * muse_processing_new_frame(muse_processing *aProcessing, int aIFU, cpl_propertylist *aHeader, const char *aTag, cpl_frame_type aType)
Create a new frame for a result file.
cpl_error_code muse_mask_save(muse_mask *aMask, const char *aFilename)
Save the data and the FITS headers of a MUSE mask to a file.
cpl_error_code muse_processing_save_cube(muse_processing *aProcessing, int aIFU, void *aCube, const char *aTag, muse_cube_type aType)
Save a MUSE datacube to disk.
cpl_frame_level muse_processing_get_frame_level(const cpl_recipe *, const char *)
Get the level for a product frame with a certain tag.
cpl_frameset * muse_frameset_sort_raw_other(const cpl_frameset *aFrames, int aIndex, const char *aDateObs, cpl_boolean aSequence)
Create a new frameset containing all relevant raw frames first then all other frames.
cpl_frameset * outputFrames
cpl_recipeconfig * muse_processing_get_recipeconfig(cpl_recipe *)
Get the recipe (frame) configuration.
Structure definition of a Euro3D datacube.
void muse_processing_append_used(muse_processing *aProcessing, cpl_frame *aFrame, cpl_frame_group aGroup, int aDuplicate)
Add a frame to the set of used frames.
cpl_error_code muse_pixtable_save(muse_pixtable *aPixtable, const char *aFilename)
Save a MUSE pixel table to a file on disk.
int muse_processing_save_image(muse_processing *aProcessing, int aIFU, muse_image *aImage, const char *aTag)
Save a computed MUSE image to disk.
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.
Handling of "mask" files.
cpl_error_code muse_processing_save_table(muse_processing *aProcessing, int aIFU, void *aTable, cpl_propertylist *aHeader, const char *aTag, muse_table_type aType)
Save a computed table to disk.
cpl_error_code muse_processing_check_input(muse_processing *aProcessing, unsigned char aIFU)
Check the input files for completeness.
cpl_propertylist * header
the FITS header
cpl_frameset * muse_frameset_find(const cpl_frameset *aFrames, const char *aTag, unsigned char aIFU, cpl_boolean aInvert)
return frameset containing data from an IFU/channel with a certain tag
cpl_table * muse_processing_sort_exposures(muse_processing *aProcessing)
Sort input frames (containing lists of pixel table filenames) into different exposures.
cpl_frameset * inputFrames
cpl_mask * mask
The mask data.
cpl_frameset * usedFrames
cpl_parameterlist * parameters