35 #include "muse_processing.h"
36 #include "muse_instrument.h"
39 #include "muse_pfits.h"
41 #include "muse_datacube.h"
42 #include "muse_utils.h"
48 #define DEBUG_EXPOSURES_SORT 0
77 muse_processing_get_rawtags(cpl_recipe *aRecipe)
80 cpl_array *rawtags = cpl_array_new(0, CPL_TYPE_STRING);
84 cpl_msg_error(__func__,
"No recipeconfig found!");
90 cpl_size iframe, nframes = cpl_frameset_get_size(aRecipe->frames);
91 for (iframe = 0; iframe < nframes; iframe++) {
92 cpl_frame *frame = cpl_frameset_get_position(aRecipe->frames, iframe);
93 const char *tag = cpl_frame_get_tag(frame);
95 cpl_size itag, ntags = cpl_array_get_size(rawtags);
96 for (itag = 0; itag < ntags; itag++) {
97 if (!strcmp(cpl_array_get_string(rawtags, itag), tag)) {
102 cpl_errorstate state = cpl_errorstate_get();
103 char **tags = cpl_recipeconfig_get_inputs(recipeconfig, tag);
105 cpl_errorstate_set(state);
109 cpl_array_set_size(rawtags, ntags + 1);
110 cpl_array_set_string(rawtags, ntags, tag);
113 for (i = 0; tags[i]; i++) {
118 if (!cpl_array_get_size(rawtags)) {
119 cpl_msg_error(__func__,
"No valid raw tag(s) found!");
136 processing->
name = aName;
137 processing->
recipe = aRecipe;
138 processing->
inframes = cpl_frameset_duplicate(aRecipe->frames);
140 processing->
outframes = cpl_frameset_new();
141 #pragma omp critical(cpl_parameters)
143 processing->
intags = muse_processing_get_rawtags(aRecipe);
161 cpl_array_delete(aProcessing->
intags);
162 cpl_frameset_delete(aProcessing->
inframes);
164 cpl_frameset_delete(aProcessing->
outframes);
165 cpl_parameterlist_delete(aProcessing->
parameters);
167 for (i = 0; aProcessing->
counter[i].
tag != NULL; i++) {
168 cpl_free((
char *)aProcessing->
counter[i].
tag);
170 cpl_free(aProcessing->
counter);
171 cpl_free(aProcessing);
193 cpl_frame *aFrame, cpl_frame_group aGroup,
197 cpl_msg_error(__func__,
"NULL processing struct!");
201 if (aGroup == CPL_FRAME_GROUP_CALIB) {
202 cpl_msg_debug(__func__,
"using %s %s frame %s",
"calibration",
203 cpl_frame_get_tag(aFrame), cpl_frame_get_filename(aFrame));
204 }
else if (aGroup == CPL_FRAME_GROUP_RAW) {
205 cpl_msg_debug(__func__,
"using %s %s frame %s",
"raw",
206 cpl_frame_get_tag(aFrame), cpl_frame_get_filename(aFrame));
210 const char *fn = cpl_frame_get_filename(aFrame),
211 *tag = cpl_frame_get_tag(aFrame);
212 cpl_size iframe, nframes = cpl_frameset_get_size(aProcessing->
usedframes);
214 (iframe < nframes) && fn && tag;
216 cpl_frame *frame = cpl_frameset_get_position(aProcessing->
usedframes, iframe);
217 const char *fn2 = cpl_frame_get_filename(frame),
218 *tag2 = cpl_frame_get_tag(frame);
219 if (fn2 && !strncmp(fn, fn2, strlen(fn) + 1) &&
220 tag2 && !strncmp(tag, tag2, strlen(tag) + 1)) {
222 cpl_frame_delete(aFrame);
227 cpl_frame_set_group(aFrame, aGroup);
229 cpl_frameset_insert(aProcessing->
usedframes, cpl_frame_duplicate(aFrame));
231 cpl_frameset_insert(aProcessing->
usedframes, aFrame);
251 const char *aTag,
int aIFU)
254 cpl_msg_error(__func__,
"NULL processing struct!");
258 for (i = 0; aProcessing->
counter[i].
tag != NULL; i++) {
259 if (strcmp(aProcessing->
counter[i].
tag, aTag) == 0 &&
266 aProcessing->
counter[i].
tag = cpl_strdup(aTag);
289 cpl_propertylist *aHeader, cpl_frame *aFrame,
290 int aIndex,
const char *aDateObs,
291 cpl_boolean aSequence)
294 cpl_msg_error(__func__,
"NULL processing struct!");
298 cpl_frameset_is_empty(aProcessing->
inframes)) {
299 cpl_msg_warning(__func__,
"No raw input files, no DFS product header added");
304 cpl_propertylist *hkeep = cpl_propertylist_new();
305 cpl_propertylist_copy_property_regexp(hkeep, aHeader,
306 MUSE_HEADERS_KEEP_REGEXP, 0);
309 cpl_propertylist_erase_regexp(aHeader,
"^ESO PRO|^COMMENT", 0);
311 cpl_propertylist_erase_regexp(aHeader, MUSE_HDR_TMP_REGEXP, 0);
315 aIndex, aDateObs, aSequence);
318 if (cpl_propertylist_has(aHeader,
"EQUINOX") &&
319 cpl_propertylist_get_type(aHeader,
"EQUINOX") < CPL_TYPE_FLOAT) {
320 cpl_property *equinox = cpl_propertylist_get_property(aHeader,
"EQUINOX");
321 double equvalue = cpl_property_get_long_long(equinox);
322 const char *equcomment = cpl_property_get_comment(equinox);
323 cpl_property_set_name(equinox,
"EQUIBRK");
324 cpl_propertylist_insert_after_double(aHeader,
"EQUIBRK",
"EQUINOX",
326 cpl_propertylist_set_comment(aHeader,
"EQUINOX", equcomment);
327 cpl_propertylist_erase(aHeader,
"EQUIBRK");
330 char *pkgstring = cpl_sprintf(
"%s/%s", PACKAGE, PACKAGE_VERSION);
331 if (cpl_dfs_setup_product_header(aHeader, aFrame, fset,
333 pkgstring, MUSE_PRO_DID, NULL)
335 cpl_msg_error(__func__,
"Could not add DFS product header: %s",
336 cpl_error_get_message());
339 cpl_frameset_delete(fset);
342 int i, n = cpl_propertylist_get_size(hkeep);
343 for (i = 0; i < n; i++) {
344 const cpl_property *p = cpl_propertylist_get_const(hkeep, i);
345 cpl_propertylist_erase(aHeader, cpl_property_get_name(p));
346 cpl_propertylist_append_property(aHeader, p);
348 cpl_propertylist_delete(hkeep);
351 cpl_propertylist_update_string(aHeader,
"ESO PRO TECH",
"IFU");
353 if (strstr(aProcessing->
name,
"muse_sci") ||
354 !strcmp(aProcessing->
name,
"muse_exp_combine")) {
355 cpl_propertylist_update_bool(aHeader,
"ESO PRO SCIENCE", 1);
385 cpl_propertylist *aHeader,
const char *aTag,
386 cpl_frame_type aType)
388 cpl_ensure(aProcessing, CPL_ERROR_NULL_INPUT, NULL);
390 const char *prefix = cpl_propertylist_has(aHeader,
"MUSE PRIVATE FILE PREFIX")
391 ? cpl_propertylist_get_string(aHeader,
392 "MUSE PRIVATE FILE PREFIX")
395 cpl_frame *frame = cpl_frame_new();
397 cpl_errorstate prestate = cpl_errorstate_get();
404 framecounter = muse_processing_get_framecounter(aProcessing, prefix, aIFU);
406 const char *dateobs = NULL;
413 char filename[FILENAME_MAX];
415 if (framecounter == 0) {
416 snprintf(filename, FILENAME_MAX,
"%s-%02d.fits", prefix, aIFU);
418 snprintf(filename, FILENAME_MAX,
"%s_%04d-%02d.fits", prefix,
422 if (framecounter == 0) {
423 snprintf(filename, FILENAME_MAX,
"%s.fits", prefix);
425 snprintf(filename, FILENAME_MAX,
"%s_%04d.fits", prefix, framecounter);
428 cpl_frame_set_filename(frame, filename);
429 cpl_frame_set_tag(frame, aTag);
430 cpl_frame_set_type(frame, aType);
431 cpl_frame_set_group(frame, CPL_FRAME_GROUP_PRODUCT);
432 cpl_frame_set_level(frame,
435 if (cpl_errorstate_get() != prestate) {
436 cpl_msg_error(__func__,
"Error while initialising the product frame: %s",
437 cpl_error_get_message());
438 cpl_frame_delete(frame);
441 cpl_propertylist_erase_regexp(aHeader,
"MUSE PRIVATE.*", 0);
444 muse_processing_setup_header(aProcessing, aHeader, frame, idx, dateobs,
470 cpl_ensure_code(aProcessing && aImage && aTag, CPL_ERROR_NULL_INPUT);
474 CPL_FRAME_TYPE_IMAGE);
475 cpl_msg_info(__func__,
"Saving image as %s", cpl_frame_get_filename(frame));
477 if (r == CPL_ERROR_NONE) {
478 cpl_frameset_insert(aProcessing->
outframes, frame);
480 cpl_frame_delete(frame);
510 cpl_ensure_code(aProcessing && aCube && aTag, CPL_ERROR_NULL_INPUT);
512 , CPL_ERROR_ILLEGAL_INPUT);
518 aTag, CPL_FRAME_TYPE_IMAGE);
519 cpl_msg_info(__func__,
"Saving %s cube as \"%s\"",
521 cpl_frame_get_filename(frame));
522 cpl_error_code rc = CPL_ERROR_NONE;
525 cpl_frame_get_filename(frame));
528 cpl_frame_get_filename(frame));
533 if (rc == CPL_ERROR_NONE) {
534 cpl_frameset_insert(aProcessing->
outframes, frame);
536 cpl_frame_delete(frame);
565 void *aTable, cpl_propertylist *aHeader,
568 cpl_ensure_code(aProcessing && aTable && aTag, CPL_ERROR_NULL_INPUT);
570 CPL_ERROR_ILLEGAL_INPUT);
573 cpl_propertylist *header;
575 cpl_ensure_code(aHeader, CPL_ERROR_NULL_INPUT);
581 aTag, CPL_FRAME_TYPE_TABLE);
582 cpl_msg_info(__func__,
"Saving %stable as \"%s\"",
584 cpl_frame_get_filename(frame));
585 cpl_error_code rc = CPL_ERROR_NONE;
587 rc = cpl_table_save((cpl_table *)aTable, aHeader, NULL,
588 cpl_frame_get_filename(frame), CPL_IO_CREATE);
591 cpl_frame_get_filename(frame));
593 if (rc == CPL_ERROR_NONE) {
594 cpl_frameset_insert(aProcessing->
outframes, frame);
596 cpl_msg_error(__func__,
"Saving %stable failed: %s",
598 cpl_error_get_message());
599 cpl_frame_delete(frame);
624 cpl_image *aImage, cpl_propertylist *aHeader,
627 cpl_ensure_code(aProcessing && aImage && aHeader && aTag, CPL_ERROR_NULL_INPUT);
631 CPL_FRAME_TYPE_IMAGE);
632 cpl_msg_info(__func__,
"Saving image as %s", cpl_frame_get_filename(frame));
633 int r = cpl_image_save(aImage, cpl_frame_get_filename(frame),
634 CPL_TYPE_UNSPECIFIED, aHeader, CPL_IO_CREATE);
635 if (r == CPL_ERROR_NONE) {
636 cpl_frameset_insert(aProcessing->
outframes, frame);
638 cpl_msg_error(__func__,
"Saving image failed: %s", cpl_error_get_message());
639 cpl_frame_delete(frame);
663 cpl_propertylist *aHeader,
const char *aTag)
665 cpl_ensure_code(aProcessing && aHeader && aTag, CPL_ERROR_NULL_INPUT);
669 CPL_FRAME_TYPE_IMAGE);
670 cpl_msg_info(__func__,
"Saving header as %s", cpl_frame_get_filename(frame));
671 cpl_error_code rc = cpl_propertylist_save(aHeader,
672 cpl_frame_get_filename(frame),
674 if (rc == CPL_ERROR_NONE) {
675 cpl_frameset_insert(aProcessing->
outframes, frame);
677 cpl_msg_error(__func__,
"Saving header failed: %s", cpl_error_get_message());
678 cpl_frame_delete(frame);
704 cpl_ensure_code(aProcessing && aMask && aTag, CPL_ERROR_NULL_INPUT);
708 CPL_FRAME_TYPE_IMAGE);
709 cpl_msg_info(__func__,
"Saving mask as %s", cpl_frame_get_filename(frame));
711 if (r == CPL_ERROR_NONE) {
712 cpl_frameset_insert(aProcessing->
outframes, frame);
714 cpl_frame_delete(frame);
737 cpl_ensure(aProcessing && aTag, CPL_ERROR_NULL_INPUT, CPL_FALSE);
739 cpl_boolean hastag = CPL_FALSE;
741 cpl_size itag, ntags = cpl_array_get_size(aProcessing->
intags);
742 for (itag = 0; itag < ntags; itag++) {
743 const char *tag = cpl_array_get_string(aProcessing->
intags, itag);
744 if (tag && !strncmp(tag, aTag, aNChars)) {
773 cpl_msg_error(__func__,
"NULL processing struct");
774 return CPL_ERROR_NULL_INPUT;
776 cpl_recipeconfig *recipeconfig
779 cpl_msg_error(__func__,
"No recipeconfig found!");
780 return CPL_ERROR_ILLEGAL_INPUT;
783 cpl_size itag, ntags = cpl_array_get_size(aProcessing->
intags);
784 unsigned int errors = 0;
785 for (itag = 0; itag < ntags; itag++) {
786 const char *intag = cpl_array_get_string(aProcessing->
intags, itag);
788 intag, aIFU, CPL_FALSE);
789 int nframes = cpl_frameset_count_tags(frames, intag),
790 nmin = cpl_recipeconfig_get_min_count(recipeconfig, intag, intag),
791 nmax = cpl_recipeconfig_get_max_count(recipeconfig, intag, intag);
792 cpl_frameset_delete(frames);
793 if (nmin >= 0 && nframes < nmin) {
794 cpl_msg_error(__func__,
"Required %d, found %d input frames with tag "
795 "\"%s\" with IFU %hhu", nmin, nframes, intag, aIFU);
798 if (nmax >= 0 && nframes > nmax) {
799 cpl_msg_error(__func__,
"At most %d allowed, found %d input frames with "
800 "tag \"%s\" with IFU %hhu", nmax, nframes, intag, aIFU);
803 char **tags = cpl_recipeconfig_get_inputs(recipeconfig, intag);
805 cpl_msg_error(__func__,
"Input frames with tag \"%s\" cannot be used with"
806 " this recipe", intag);
812 for (i = 0; tags[i]; i++) {
815 nframes = cpl_frameset_count_tags(frames, tags[i]);
816 cpl_frameset_delete(frames);
818 nmin = cpl_recipeconfig_get_min_count(recipeconfig, intag, tags[i]);
819 nmax = cpl_recipeconfig_get_max_count(recipeconfig, intag, tags[i]);
820 if (nmin >= 0 && nframes < nmin) {
821 cpl_msg_error(__func__,
"Required %d, found %d frames with tag \"%s\" "
822 "with IFU %hhu", nmin, nframes, tags[i], aIFU);
825 if (nframes == 0 && nmin <= 0) {
826 cpl_msg_debug(__func__,
"Optional frame with tag \"%s\" not given",
829 if (nmax >= 0 && nframes > nmax) {
830 cpl_msg_error(__func__,
"At most %d allowed, found %d frames with tag "
831 "\"%s\" with IFU %hhu", nmax, nframes, tags[i], aIFU);
840 cpl_msg_error(__func__,
"Found %u error(s)", errors);
841 return CPL_ERROR_DATA_NOT_FOUND;
843 return CPL_ERROR_NONE;
873 cpl_ensure(aProcessing, CPL_ERROR_NULL_INPUT, NULL);
874 cpl_size nframes = cpl_frameset_get_size(aProcessing->
inframes);
875 cpl_ensure(nframes, CPL_ERROR_DATA_NOT_FOUND, NULL);
879 cpl_table *exptable = cpl_table_new(0);
881 cpl_table_new_column(exptable,
"DATE-OBS", CPL_TYPE_STRING);
884 for (i = 0; i <= kMuseNumIFUs; i++) {
885 snprintf(colname, 3,
"%02d", i);
886 cpl_table_new_column(exptable, colname, CPL_TYPE_STRING);
891 for (iframe = 0; iframe < nframes; iframe++) {
892 cpl_frame *frame = cpl_frameset_get_position(aProcessing->
inframes,
894 const char *tag = cpl_frame_get_tag(frame);
896 const char *filename = cpl_frame_get_filename(frame);
899 cpl_propertylist *header = cpl_propertylist_load(filename, 0);
902 cpl_msg_warning(__func__,
"\"%s\" does not contain the DATE-OBS "
903 "keyword, it will be ignored!", filename);
904 cpl_propertylist_delete(header);
909 cpl_msg_debug(__func__,
"\"%s\" seems to contain merged data (no "
910 "EXTNAME=CHANnn)", filename);
912 #if DEBUG_EXPOSURES_SORT
913 cpl_msg_debug(__func__,
"\"%s\": IFU %2d, DATE-OBS=\"%s\"", filename, ifu, date);
918 for (i = 0; i < cpl_table_get_nrow(exptable); i++) {
919 #if DEBUG_EXPOSURES_SORT
920 cpl_msg_debug(__func__,
"i=%d, DATE-OBS=\"%s\"", i,
921 cpl_table_get_string(exptable,
"DATE-OBS", i));
923 if (!strcmp(date, cpl_table_get_string(exptable,
"DATE-OBS", i))) {
930 cpl_table_set_size(exptable, cpl_table_get_nrow(exptable)+1);
931 irow = cpl_table_get_nrow(exptable) - 1;
932 cpl_table_set_string(exptable,
"DATE-OBS", irow, date);
937 snprintf(colname, 3,
"%02d", ifu);
938 if (cpl_table_is_valid(exptable, colname, irow)) {
939 cpl_msg_warning(__func__,
"we already have IFU %d of exposure %d (\"%s\")!"
940 " Ignoring \"%s\"", ifu, irow+1,
941 cpl_table_get_string(exptable, colname, irow),
943 cpl_propertylist_delete(header);
946 cpl_table_set_string(exptable, colname, irow, filename);
952 cpl_propertylist_delete(header);
954 #if DEBUG_EXPOSURES_SORT
956 cpl_msg_debug(__func__,
"wrong tag \"%s\" for \"%s\"", tag,
957 cpl_frame_get_filename(frame));
962 if (cpl_table_get_nrow(exptable) <= 0) {
964 cpl_table_delete(exptable);
965 cpl_error_set(__func__, CPL_ERROR_DATA_NOT_FOUND);
969 for (i = 0; i < cpl_table_get_nrow(exptable); i++) {
971 if (cpl_table_is_valid(exptable,
"00", i)) {
975 for (j = 1; j <= kMuseNumIFUs; j++) {
976 snprintf(colname, 3,
"%02d", j);
977 if (cpl_table_is_valid(exptable, colname, i)) {
981 cpl_msg_debug(__func__,
"Data from exposure %2d is contained in %2d "
982 "IFU%s/%d merged file%s", i+1, nvalid, nvalid == 1 ?
"" :
"s",
983 nmerged, nmerged == 1 ?
"" :
"s");
988 cpl_propertylist *sorting = cpl_propertylist_new();
989 cpl_propertylist_append_bool(sorting,
"DATE-OBS",
991 cpl_table_sort(exptable, sorting);
992 cpl_propertylist_delete(sorting);
1016 aTag, 0, CPL_FALSE);
1017 if (frames == NULL || cpl_frameset_get_size(frames) <= 0) {
1018 cpl_frameset_delete(frames);
1021 cpl_frame *frame = cpl_frameset_get_position(frames, 0);
1024 cpl_msg_warning(__func__,
"loading mask \"%s\" failed!",
1025 cpl_frame_get_filename(frame));
1026 cpl_frameset_delete(frames);
1029 cpl_msg_info(__func__,
"using mask \"%s\" (%"CPL_SIZE_FORMAT
" pixels)",
1030 cpl_frame_get_filename(frame), cpl_mask_count(mask->
mask));
1032 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.
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.
muse_processing_framecounter * counter
const char * muse_pfits_get_dateobs(const cpl_propertylist *aHeaders)
find out the date of observations
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
cpl_boolean muse_processing_check_intags(muse_processing *aProcessing, const char *aTag, int aNChars)
Check that a tag is part of the input tags of a processing structure.
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_frameset * usedframes
muse_processing * muse_processing_new(const char *aName, cpl_recipe *aRecipe)
Create a new processing structure.
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.
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_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_parameterlist * muse_cplparameterlist_duplicate(const cpl_parameterlist *aPList)
Duplicate a CPL parameter list.
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_mask * mask
The mask data.
cpl_parameterlist * parameters