00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifdef HAVE_CONFIG_H
00023 #include <config.h>
00024 #endif
00025
00026
00027
00028
00029 #include <stdio.h>
00030 #include <float.h>
00031 #include <math.h>
00032 #include <string.h>
00033 #include <cpl.h>
00034
00035 #include "muse_processing.h"
00036 #include "muse_instrument.h"
00037
00038 #include "muse_dfs.h"
00039 #include "muse_pfits.h"
00040 #include "muse_lsf.h"
00041 #include "muse_datacube.h"
00042 #include "muse_utils.h"
00043 #include "muse_idp.h"
00044
00045
00046
00047
00048
00049 #define DEBUG_EXPOSURES_SORT 0
00050
00051
00058
00059
00062
00063
00064
00065
00066
00076
00077 static cpl_array *
00078 muse_processing_get_rawtags(cpl_recipe *aRecipe)
00079 {
00080
00081 cpl_array *rawtags = cpl_array_new(0, CPL_TYPE_STRING);
00082
00083 cpl_recipeconfig *recipeconfig = muse_processing_get_recipeconfig(aRecipe);
00084 if (!recipeconfig) {
00085 cpl_msg_error(__func__, "No recipeconfig found!");
00086 return rawtags;
00087 }
00088
00089
00090
00091 cpl_size iframe, nframes = cpl_frameset_get_size(aRecipe->frames);
00092 for (iframe = 0; iframe < nframes; iframe++) {
00093 cpl_frame *frame = cpl_frameset_get_position(aRecipe->frames, iframe);
00094 const char *tag = cpl_frame_get_tag(frame);
00095
00096 cpl_size itag, ntags = cpl_array_get_size(rawtags);
00097 for (itag = 0; itag < ntags; itag++) {
00098 if (!strcmp(cpl_array_get_string(rawtags, itag), tag)) {
00099 tag = NULL;
00100 break;
00101 }
00102 }
00103 cpl_errorstate state = cpl_errorstate_get();
00104 char **tags = cpl_recipeconfig_get_inputs(recipeconfig, tag);
00105 if (!tags) {
00106 cpl_errorstate_set(state);
00107 continue;
00108 }
00109
00110 cpl_array_set_size(rawtags, ntags + 1);
00111 cpl_array_set_string(rawtags, ntags, tag);
00112
00113 int i;
00114 for (i = 0; tags[i]; i++) {
00115 cpl_free(tags[i]);
00116 }
00117 cpl_free(tags);
00118 }
00119 if (!cpl_array_get_size(rawtags)) {
00120 cpl_msg_error(__func__, "No valid raw tag(s) found!");
00121 }
00122 return rawtags;
00123 }
00124
00125
00132
00133 muse_processing *
00134 muse_processing_new(const char *aName, cpl_recipe *aRecipe)
00135 {
00136 muse_processing *processing = cpl_malloc(sizeof(muse_processing));
00137 processing->name = aName;
00138 processing->recipe = aRecipe;
00139 processing->inframes = cpl_frameset_duplicate(aRecipe->frames);
00140 processing->usedframes = cpl_frameset_new();
00141 processing->outframes = cpl_frameset_new();
00142 #pragma omp critical(cpl_parameters)
00143 processing->parameters = muse_cplparameterlist_duplicate(aRecipe->parameters);
00144 processing->intags = muse_processing_get_rawtags(aRecipe);
00145 processing->counter = cpl_malloc(sizeof(muse_processing_framecounter));
00146 processing->counter[0].tag = NULL;
00147 return processing;
00148 }
00149
00150
00155
00156 void
00157 muse_processing_delete(muse_processing *aProcessing)
00158 {
00159 if (!aProcessing) {
00160 return;
00161 }
00162 cpl_array_delete(aProcessing->intags);
00163 cpl_frameset_delete(aProcessing->inframes);
00164 cpl_frameset_delete(aProcessing->usedframes);
00165 cpl_frameset_delete(aProcessing->outframes);
00166 cpl_parameterlist_delete(aProcessing->parameters);
00167 int i;
00168 for (i = 0; aProcessing->counter[i].tag != NULL; i++) {
00169 cpl_free((char *)aProcessing->counter[i].tag);
00170 }
00171 cpl_free(aProcessing->counter);
00172 cpl_free(aProcessing);
00173 }
00174
00175
00191
00192 void
00193 muse_processing_append_used(muse_processing *aProcessing,
00194 cpl_frame *aFrame, cpl_frame_group aGroup,
00195 int aDuplicate)
00196 {
00197 if (!aProcessing) {
00198 cpl_msg_error(__func__, "NULL processing struct!");
00199 return;
00200 }
00201 #if 0
00202 if (aGroup == CPL_FRAME_GROUP_CALIB) {
00203 cpl_msg_debug(__func__, "using %s %s frame %s", "calibration",
00204 cpl_frame_get_tag(aFrame), cpl_frame_get_filename(aFrame));
00205 } else if (aGroup == CPL_FRAME_GROUP_RAW) {
00206 cpl_msg_debug(__func__, "using %s %s frame %s", "raw",
00207 cpl_frame_get_tag(aFrame), cpl_frame_get_filename(aFrame));
00208 }
00209 #endif
00210
00211
00212 cpl_boolean doreturn = CPL_FALSE;
00213 #pragma omp critical(muse_processing_used_frames)
00214 {
00215 const char *fn = cpl_frame_get_filename(aFrame),
00216 *tag = cpl_frame_get_tag(aFrame);
00217 cpl_size iframe, nframes = cpl_frameset_get_size(aProcessing->usedframes);
00218 for (iframe = 0;
00219 (iframe < nframes) && fn && tag;
00220 iframe++) {
00221 cpl_frame *frame = cpl_frameset_get_position(aProcessing->usedframes, iframe);
00222 const char *fn2 = cpl_frame_get_filename(frame),
00223 *tag2 = cpl_frame_get_tag(frame);
00224 if (fn2 && !strncmp(fn, fn2, strlen(fn) + 1) &&
00225 tag2 && !strncmp(tag, tag2, strlen(tag) + 1)) {
00226 if (!aDuplicate) {
00227 cpl_frame_delete(aFrame);
00228 }
00229 doreturn = CPL_TRUE;
00230 break;
00231 }
00232 }
00233 }
00234
00235 if (doreturn) {
00236 return;
00237 }
00238
00239 cpl_frame_set_group(aFrame, aGroup);
00240
00241
00242 #pragma omp critical(muse_processing_used_frames)
00243 {
00244 if (aDuplicate) {
00245 cpl_frameset_insert(aProcessing->usedframes, cpl_frame_duplicate(aFrame));
00246 } else {
00247 cpl_frameset_insert(aProcessing->usedframes, aFrame);
00248 }
00249 }
00250 }
00251
00252
00265
00266 static int
00267 muse_processing_get_framecounter(muse_processing *aProcessing,
00268 const char *aTag, int aIFU)
00269 {
00270 if (!aProcessing) {
00271 cpl_msg_error(__func__, "NULL processing struct!");
00272 return 0;
00273 }
00274 int i;
00275 for (i = 0; aProcessing->counter[i].tag != NULL; i++) {
00276 if (strcmp(aProcessing->counter[i].tag, aTag) == 0 &&
00277 aProcessing->counter[i].ifu == aIFU) {
00278 return ++aProcessing->counter[i].counter;
00279 }
00280 }
00281 aProcessing->counter = cpl_realloc(aProcessing->counter,
00282 (i+2)*sizeof(muse_processing_framecounter));
00283 aProcessing->counter[i].tag = cpl_strdup(aTag);
00284 aProcessing->counter[i].ifu = aIFU;
00285 aProcessing->counter[i].counter = 1;
00286 aProcessing->counter[i+1].tag = NULL;
00287 return 1;
00288 }
00289
00290
00303
00304 static void
00305 muse_processing_setup_header(muse_processing *aProcessing,
00306 cpl_propertylist *aHeader, cpl_frame *aFrame,
00307 int aIndex, const char *aDateObs,
00308 cpl_boolean aSequence)
00309 {
00310 if (!aProcessing) {
00311 cpl_msg_error(__func__, "NULL processing struct!");
00312 return;
00313 }
00314 if (!aProcessing->inframes ||
00315 cpl_frameset_is_empty(aProcessing->inframes)) {
00316 cpl_msg_warning(__func__, "No raw input files, no DFS product header added");
00317 return;
00318 }
00319
00320
00321 cpl_propertylist *hkeep = cpl_propertylist_new();
00322 cpl_propertylist_copy_property_regexp(hkeep, aHeader,
00323 MUSE_HEADERS_KEEP_REGEXP, 0);
00324
00325
00326 cpl_propertylist_erase_regexp(aHeader, "^ESO PRO|^COMMENT", 0);
00327
00328 cpl_propertylist_erase_regexp(aHeader, MUSE_HDR_TMP_REGEXP, 0);
00329
00330
00331 cpl_frameset *fset = muse_frameset_sort_raw_other(aProcessing->usedframes,
00332 aIndex, aDateObs, aSequence);
00333
00334 #if CPL_VERSION_CODE < CPL_VERSION(7, 0, 0)
00335
00336 if (cpl_propertylist_has(aHeader, "EQUINOX") &&
00337 cpl_propertylist_get_type(aHeader, "EQUINOX") < CPL_TYPE_FLOAT) {
00338 cpl_property *equinox = cpl_propertylist_get_property(aHeader, "EQUINOX");
00339 double equvalue = cpl_property_get_long_long(equinox);
00340 const char *equcomment = cpl_property_get_comment(equinox);
00341 cpl_property_set_name(equinox, "EQUIBRK");
00342 cpl_propertylist_insert_after_double(aHeader, "EQUIBRK", "EQUINOX",
00343 equvalue);
00344 cpl_propertylist_set_comment(aHeader, "EQUINOX", equcomment);
00345 cpl_propertylist_erase(aHeader, "EQUIBRK");
00346 }
00347 #endif
00348
00349 char *pkgstring = cpl_sprintf("%s/%s", PACKAGE, PACKAGE_VERSION);
00350
00351 #pragma omp critical(muse_processing_dfs_setup_header)
00352 if (cpl_dfs_setup_product_header(aHeader, aFrame, fset,
00353 aProcessing->parameters, aProcessing->name,
00354 pkgstring, MUSE_PRO_DID, NULL)
00355 != CPL_ERROR_NONE) {
00356 cpl_msg_error(__func__, "Could not add DFS product header: %s",
00357 cpl_error_get_message());
00358 }
00359 cpl_free(pkgstring);
00360 cpl_frameset_delete(fset);
00361
00362
00363 int i, n = cpl_propertylist_get_size(hkeep);
00364 for (i = 0; i < n; i++) {
00365 const cpl_property *p = cpl_propertylist_get_const(hkeep, i);
00366 cpl_propertylist_erase(aHeader, cpl_property_get_name(p));
00367 cpl_propertylist_append_property(aHeader, p);
00368 }
00369 cpl_propertylist_delete(hkeep);
00370
00371
00372 cpl_propertylist_update_string(aHeader, "ESO PRO TECH", "IFU");
00373
00374 if (strstr(aProcessing->name, "muse_sci") ||
00375 !strcmp(aProcessing->name, "muse_exp_combine")) {
00376 cpl_propertylist_update_bool(aHeader, "ESO PRO SCIENCE", 1);
00377 }
00378 }
00379
00380
00403
00404 cpl_frame *
00405 muse_processing_new_frame(muse_processing *aProcessing, int aIFU,
00406 cpl_propertylist *aHeader, const char *aTag,
00407 cpl_frame_type aType)
00408 {
00409 cpl_ensure(aProcessing, CPL_ERROR_NULL_INPUT, NULL);
00410 muse_processing_prepare_header(aProcessing->recipe, aTag, aHeader);
00411 const char *prefix = cpl_propertylist_has(aHeader, "MUSE PRIVATE FILE PREFIX")
00412 ? cpl_propertylist_get_string(aHeader,
00413 "MUSE PRIVATE FILE PREFIX")
00414 : aTag;
00415
00416 cpl_frame *frame = cpl_frame_new();
00417
00418 cpl_errorstate prestate = cpl_errorstate_get();
00419
00420
00421
00422 int fmode = muse_processing_get_frame_mode(aProcessing->recipe, aTag),
00423 framecounter = 0;
00424 if (fmode != MUSE_FRAME_MODE_MASTER) {
00425 framecounter = muse_processing_get_framecounter(aProcessing, prefix, aIFU);
00426 }
00427 const char *dateobs = NULL;
00428 if (fmode == MUSE_FRAME_MODE_DATEOBS) {
00429 dateobs = muse_pfits_get_dateobs(aHeader);
00430 }
00431 cpl_boolean sequence = fmode == MUSE_FRAME_MODE_SEQUENCE;
00432
00433
00434 char filename[FILENAME_MAX];
00435 if (aIFU >= 0) {
00436 if (framecounter == 0) {
00437 snprintf(filename, FILENAME_MAX, "%s-%02d.fits", prefix, aIFU);
00438 } else {
00439 snprintf(filename, FILENAME_MAX, "%s_%04d-%02d.fits", prefix,
00440 framecounter, aIFU);
00441 }
00442 } else {
00443 if (framecounter == 0) {
00444 snprintf(filename, FILENAME_MAX, "%s.fits", prefix);
00445 } else {
00446 snprintf(filename, FILENAME_MAX, "%s_%04d.fits", prefix, framecounter);
00447 }
00448 }
00449 cpl_frame_set_filename(frame, filename);
00450 cpl_frame_set_tag(frame, aTag);
00451 cpl_frame_set_type(frame, aType);
00452 cpl_frame_set_group(frame, CPL_FRAME_GROUP_PRODUCT);
00453 cpl_frame_set_level(frame,
00454 muse_processing_get_frame_level(aProcessing->recipe,
00455 aTag));
00456 if (!cpl_errorstate_is_equal(prestate)) {
00457 cpl_msg_error(__func__, "Error while initialising the product frame: %s",
00458 cpl_error_get_message());
00459 cpl_frame_delete(frame);
00460 return NULL;
00461 }
00462 cpl_propertylist_erase_regexp(aHeader, "MUSE PRIVATE.*", 0);
00463
00464 int idx = dateobs || fmode == MUSE_FRAME_MODE_SUBSET ? -1 : framecounter - 1;
00465 muse_processing_setup_header(aProcessing, aHeader, frame, idx, dateobs,
00466 sequence);
00467 return frame;
00468 }
00469
00470
00486
00487 int
00488 muse_processing_save_image(muse_processing *aProcessing, int aIFU,
00489 muse_image *aImage, const char *aTag)
00490 {
00491 cpl_ensure_code(aProcessing && aImage && aTag, CPL_ERROR_NULL_INPUT);
00492
00493 cpl_frame *frame = muse_processing_new_frame(aProcessing, aIFU,
00494 aImage->header, aTag,
00495 CPL_FRAME_TYPE_IMAGE);
00496 cpl_msg_info(__func__, "Saving image as %s", cpl_frame_get_filename(frame));
00497 int r = muse_image_save(aImage, cpl_frame_get_filename(frame));
00498 if (r == CPL_ERROR_NONE) {
00499 #pragma omp critical(muse_processing_output_frames)
00500 cpl_frameset_insert(aProcessing->outframes, frame);
00501 } else {
00502 cpl_frame_delete(frame);
00503 }
00504 return r;
00505 }
00506
00507
00527
00528 cpl_error_code
00529 muse_processing_save_cube(muse_processing *aProcessing, int aIFU,
00530 void *aCube, const char *aTag, muse_cube_type aType)
00531 {
00532 cpl_ensure_code(aProcessing && aCube && aTag, CPL_ERROR_NULL_INPUT);
00533 cpl_ensure_code((aType == MUSE_CUBE_TYPE_EURO3D) ||
00534 (aType == MUSE_CUBE_TYPE_FITS) ||
00535 (aType == MUSE_CUBE_TYPE_SDP) ||
00536 (aType == MUSE_CUBE_TYPE_LSF), CPL_ERROR_ILLEGAL_INPUT);
00537
00538
00539
00540 cpl_frame *frame = muse_processing_new_frame(aProcessing, aIFU,
00541 ((muse_datacube *)aCube)->header,
00542 aTag, CPL_FRAME_TYPE_IMAGE);
00543
00544
00545
00546
00547 if (aType == MUSE_CUBE_TYPE_SDP) {
00548 cpl_errorstate status = cpl_errorstate_get();
00549 muse_idp_properties *properties =
00550 muse_idp_properties_collect(aProcessing, (muse_datacube *)aCube, aTag);
00551 if (properties) {
00552 muse_idp_properties_update(((muse_datacube *)aCube)->header, properties);
00553 }
00554 muse_idp_properties_delete(properties);
00555 if (!cpl_errorstate_is_equal(status)) {
00556 cpl_frame_delete(frame);
00557 return cpl_error_get_code();
00558 }
00559 }
00560
00561 cpl_msg_info(__func__, "Saving %s cube as \"%s\"",
00562 aType == MUSE_CUBE_TYPE_EURO3D ? "Euro3D" : "FITS",
00563 cpl_frame_get_filename(frame));
00564 cpl_error_code rc = CPL_ERROR_NONE;
00565 if (aType == MUSE_CUBE_TYPE_EURO3D) {
00566 rc = muse_euro3dcube_save((muse_euro3dcube *)aCube,
00567 cpl_frame_get_filename(frame));
00568 } else if ((aType == MUSE_CUBE_TYPE_FITS) || (aType == MUSE_CUBE_TYPE_SDP)) {
00569 rc = muse_datacube_save((muse_datacube *)aCube,
00570 cpl_frame_get_filename(frame));
00571 } else {
00572 rc = muse_lsf_cube_save((muse_lsf_cube *)aCube,
00573 cpl_frame_get_filename(frame));
00574 }
00575 if (rc == CPL_ERROR_NONE) {
00576 #pragma omp critical(muse_processing_output_frames)
00577 cpl_frameset_insert(aProcessing->outframes, frame);
00578 } else {
00579 cpl_frame_delete(frame);
00580 }
00581 return rc;
00582 }
00583
00584
00605
00606 cpl_error_code
00607 muse_processing_save_table(muse_processing *aProcessing, int aIFU,
00608 void *aTable, cpl_propertylist *aHeader,
00609 const char *aTag, muse_table_type aType)
00610 {
00611 cpl_ensure_code(aProcessing && aTable && aTag, CPL_ERROR_NULL_INPUT);
00612 cpl_ensure_code(aType == MUSE_TABLE_TYPE_CPL || aType == MUSE_TABLE_TYPE_PIXTABLE,
00613 CPL_ERROR_ILLEGAL_INPUT);
00614
00615
00616 cpl_propertylist *header;
00617 if (aType == MUSE_TABLE_TYPE_CPL) {
00618 cpl_ensure_code(aHeader, CPL_ERROR_NULL_INPUT);
00619 header = aHeader;
00620 } else {
00621 header = ((muse_pixtable *)aTable)->header;
00622 }
00623 cpl_frame *frame = muse_processing_new_frame(aProcessing, aIFU, header,
00624 aTag, CPL_FRAME_TYPE_TABLE);
00625 cpl_msg_info(__func__, "Saving %stable as \"%s\"",
00626 aType == MUSE_TABLE_TYPE_PIXTABLE ? "pixel " : "",
00627 cpl_frame_get_filename(frame));
00628 cpl_error_code rc = CPL_ERROR_NONE;
00629 if (aType == MUSE_TABLE_TYPE_CPL) {
00630 cpl_size nrow = cpl_table_get_nrow((cpl_table *)aTable);
00631 rc = cpl_table_save((cpl_table *)aTable, aHeader, NULL,
00632 cpl_frame_get_filename(frame), CPL_IO_CREATE);
00633 if (nrow < 1) {
00634 cpl_msg_warning(__func__, "Table saved as \"%s\" has no rows!", aTag);
00635 }
00636 } else {
00637 rc = muse_pixtable_save((muse_pixtable *)aTable,
00638 cpl_frame_get_filename(frame));
00639 }
00640 if (rc == CPL_ERROR_NONE) {
00641 #pragma omp critical(muse_processing_output_frames)
00642 cpl_frameset_insert(aProcessing->outframes, frame);
00643 } else {
00644 cpl_msg_error(__func__, "Saving %stable failed: %s",
00645 aType == MUSE_TABLE_TYPE_PIXTABLE ? "pixel " : "",
00646 cpl_error_get_message());
00647 cpl_frame_delete(frame);
00648 }
00649 return rc;
00650 }
00651
00652
00669
00670 int
00671 muse_processing_save_cimage(muse_processing *aProcessing, int aIFU,
00672 cpl_image *aImage, cpl_propertylist *aHeader,
00673 const char *aTag)
00674 {
00675 cpl_ensure_code(aProcessing && aImage && aHeader && aTag, CPL_ERROR_NULL_INPUT);
00676
00677 cpl_frame *frame = muse_processing_new_frame(aProcessing, aIFU,
00678 aHeader, aTag,
00679 CPL_FRAME_TYPE_IMAGE);
00680 cpl_msg_info(__func__, "Saving image as %s", cpl_frame_get_filename(frame));
00681 int r = cpl_image_save(aImage, cpl_frame_get_filename(frame),
00682 CPL_TYPE_UNSPECIFIED, aHeader, CPL_IO_CREATE);
00683 if (r == CPL_ERROR_NONE) {
00684 #pragma omp critical(muse_processing_output_frames)
00685 cpl_frameset_insert(aProcessing->outframes, frame);
00686 } else {
00687 cpl_msg_error(__func__, "Saving image failed: %s", cpl_error_get_message());
00688 cpl_frame_delete(frame);
00689 }
00690 return r;
00691 }
00692
00693
00709
00710 cpl_error_code
00711 muse_processing_save_header(muse_processing *aProcessing, int aIFU,
00712 cpl_propertylist *aHeader, const char *aTag)
00713 {
00714 cpl_ensure_code(aProcessing && aHeader && aTag, CPL_ERROR_NULL_INPUT);
00715
00716 cpl_frame *frame = muse_processing_new_frame(aProcessing, aIFU,
00717 aHeader, aTag,
00718 CPL_FRAME_TYPE_IMAGE);
00719 cpl_msg_info(__func__, "Saving header as %s", cpl_frame_get_filename(frame));
00720 cpl_error_code rc = cpl_propertylist_save(aHeader,
00721 cpl_frame_get_filename(frame),
00722 CPL_IO_CREATE);
00723 if (rc == CPL_ERROR_NONE) {
00724 #pragma omp critical(muse_processing_output_frames)
00725 cpl_frameset_insert(aProcessing->outframes, frame);
00726 } else {
00727 cpl_msg_error(__func__, "Saving header failed: %s", cpl_error_get_message());
00728 cpl_frame_delete(frame);
00729 }
00730 return rc;
00731 }
00732
00733
00749
00750 int
00751 muse_processing_save_mask(muse_processing *aProcessing, int aIFU,
00752 muse_mask *aMask, const char *aTag)
00753 {
00754 cpl_ensure_code(aProcessing && aMask && aTag, CPL_ERROR_NULL_INPUT);
00755
00756 cpl_frame *frame = muse_processing_new_frame(aProcessing, aIFU,
00757 aMask->header, aTag,
00758 CPL_FRAME_TYPE_IMAGE);
00759 cpl_msg_info(__func__, "Saving mask as %s", cpl_frame_get_filename(frame));
00760 int r = muse_mask_save(aMask, cpl_frame_get_filename(frame));
00761 if (r == CPL_ERROR_NONE) {
00762 #pragma omp critical(muse_processing_output_frames)
00763 cpl_frameset_insert(aProcessing->outframes, frame);
00764 } else {
00765 cpl_frame_delete(frame);
00766 }
00767 return r;
00768 }
00769
00770
00783
00784 cpl_boolean
00785 muse_processing_check_intags(muse_processing *aProcessing, const char *aTag,
00786 int aNChars)
00787 {
00788 cpl_ensure(aProcessing && aTag, CPL_ERROR_NULL_INPUT, CPL_FALSE);
00789
00790 cpl_boolean hastag = CPL_FALSE;
00791
00792 cpl_size itag, ntags = cpl_array_get_size(aProcessing->intags);
00793 for (itag = 0; itag < ntags; itag++) {
00794 const char *tag = cpl_array_get_string(aProcessing->intags, itag);
00795 if (tag && !strncmp(tag, aTag, aNChars)) {
00796 hastag = CPL_TRUE;
00797 break;
00798 }
00799 }
00800 return hastag;
00801 }
00802
00803
00820
00821 cpl_error_code
00822 muse_processing_check_input(muse_processing *aProcessing, unsigned char aIFU)
00823 {
00824 if (!aProcessing) {
00825 cpl_msg_error(__func__, "NULL processing struct");
00826 return CPL_ERROR_NULL_INPUT;
00827 }
00828 cpl_recipeconfig *recipeconfig
00829 = muse_processing_get_recipeconfig(aProcessing->recipe);
00830 if (!recipeconfig) {
00831 cpl_msg_error(__func__, "No recipeconfig found!");
00832 return CPL_ERROR_ILLEGAL_INPUT;
00833 }
00834
00835 cpl_boolean output = CPL_TRUE;
00836 cpl_size itag, ntags = cpl_array_get_size(aProcessing->intags);
00837 unsigned int errors = 0;
00838 for (itag = 0; itag < ntags; itag++) {
00839 const char *intag = cpl_array_get_string(aProcessing->intags, itag);
00840 cpl_frameset *frames = muse_frameset_find(aProcessing->inframes,
00841 intag, aIFU, CPL_FALSE);
00842 int nframes = cpl_frameset_count_tags(frames, intag),
00843 nmin = cpl_recipeconfig_get_min_count(recipeconfig, intag, intag),
00844 nmax = cpl_recipeconfig_get_max_count(recipeconfig, intag, intag);
00845 cpl_frameset_delete(frames);
00846 if (nmin >= 0 && nframes < nmin) {
00847 cpl_msg_error(__func__, "Required %d, found %d input frames with tag "
00848 "\"%s\" with IFU %hhu", nmin, nframes, intag, aIFU);
00849 errors++;
00850 }
00851 if (nmax >= 0 && nframes > nmax) {
00852 cpl_msg_error(__func__, "At most %d allowed, found %d input frames with "
00853 "tag \"%s\" with IFU %hhu", nmax, nframes, intag, aIFU);
00854 errors++;
00855 }
00856 char **tags = cpl_recipeconfig_get_inputs(recipeconfig, intag);
00857 if (!tags) {
00858 cpl_msg_error(__func__, "Input frames with tag \"%s\" cannot be used with"
00859 " this recipe", intag);
00860 errors++;
00861 continue;
00862 }
00863
00864 int i;
00865 for (i = 0; tags[i]; i++) {
00866 frames = muse_frameset_find(aProcessing->inframes, tags[i], aIFU,
00867 CPL_FALSE);
00868 nframes = cpl_frameset_count_tags(frames, tags[i]);
00869 cpl_frameset_delete(frames);
00870
00871 nmin = cpl_recipeconfig_get_min_count(recipeconfig, intag, tags[i]);
00872 nmax = cpl_recipeconfig_get_max_count(recipeconfig, intag, tags[i]);
00873 if (nmin >= 0 && nframes < nmin) {
00874 if (output) {
00875 cpl_msg_error(__func__, "Required %d, found %d frames with tag \"%s\" "
00876 "with IFU %hhu", nmin, nframes, tags[i], aIFU);
00877 }
00878 errors++;
00879 }
00880 if (nframes == 0 && nmin <= 0) {
00881 if (output) {
00882 cpl_msg_debug(__func__, "Optional frame with tag \"%s\" not given",
00883 tags[i]);
00884 }
00885 }
00886 if (nmax >= 0 && nframes > nmax) {
00887 if (output) {
00888 cpl_msg_error(__func__, "At most %d allowed, found %d frames with tag "
00889 "\"%s\" with IFU %hhu", nmax, nframes, tags[i], aIFU);
00890 }
00891 errors++;
00892 }
00893 cpl_free(tags[i]);
00894 }
00895 cpl_free(tags);
00896 output = CPL_FALSE;
00897 }
00898
00899 if (errors) {
00900 cpl_msg_error(__func__, "Found %u error(s)", errors);
00901 return CPL_ERROR_DATA_NOT_FOUND;
00902 }
00903 return CPL_ERROR_NONE;
00904 }
00905
00906
00934
00935 cpl_table *
00936 muse_processing_sort_exposures(muse_processing *aProcessing)
00937 {
00938 cpl_ensure(aProcessing, CPL_ERROR_NULL_INPUT, NULL);
00939 cpl_size nframes = cpl_frameset_get_size(aProcessing->inframes);
00940 cpl_ensure(nframes, CPL_ERROR_DATA_NOT_FOUND, NULL);
00941
00942
00943
00944 cpl_table *exptable = cpl_table_new(0);
00945
00946 cpl_table_new_column(exptable, "DATE-OBS", CPL_TYPE_STRING);
00947 char colname[3];
00948 int i;
00949 for (i = 0; i <= kMuseNumIFUs; i++) {
00950 snprintf(colname, 3, "%02d", i);
00951 cpl_table_new_column(exptable, colname, CPL_TYPE_STRING);
00952 }
00953
00954
00955 cpl_size iframe;
00956 for (iframe = 0; iframe < nframes; iframe++) {
00957 cpl_frame *frame = cpl_frameset_get_position(aProcessing->inframes,
00958 iframe);
00959 const char *tag = cpl_frame_get_tag(frame);
00960 if (muse_processing_check_intags(aProcessing, tag, strlen(tag))) {
00961 const char *filename = cpl_frame_get_filename(frame);
00962
00963
00964 cpl_propertylist *header = cpl_propertylist_load(filename, 0);
00965 if (!header) {
00966 cpl_msg_warning(__func__, "\"%s\" could not be loaded, it will be "
00967 "ignored!", filename);
00968 continue;
00969 }
00970 const char *date = muse_pfits_get_dateobs(header);
00971 if (!date) {
00972 cpl_msg_warning(__func__, "\"%s\" does not contain the DATE-OBS "
00973 "keyword, it will be ignored!", filename);
00974 cpl_propertylist_delete(header);
00975 continue;
00976 }
00977 int ifu = muse_utils_get_ifu(header);
00978 if (!ifu) {
00979 cpl_msg_debug(__func__, "\"%s\" seems to contain merged data (no "
00980 "EXTNAME=CHANnn)", filename);
00981 }
00982 #if DEBUG_EXPOSURES_SORT
00983 cpl_msg_debug(__func__, "\"%s\": IFU %2d, DATE-OBS=\"%s\"", filename, ifu, date);
00984 #endif
00985
00986
00987 int irow = -1;
00988 for (i = 0; i < cpl_table_get_nrow(exptable); i++) {
00989 #if DEBUG_EXPOSURES_SORT
00990 cpl_msg_debug(__func__, "i=%d, DATE-OBS=\"%s\"", i,
00991 cpl_table_get_string(exptable, "DATE-OBS", i));
00992 #endif
00993 if (!strcmp(date, cpl_table_get_string(exptable, "DATE-OBS", i))) {
00994 irow = i;
00995 }
00996 }
00997
00998
00999 if (irow < 0) {
01000 cpl_table_set_size(exptable, cpl_table_get_nrow(exptable)+1);
01001 irow = cpl_table_get_nrow(exptable) - 1;
01002 cpl_table_set_string(exptable, "DATE-OBS", irow, date);
01003 }
01004
01005
01006
01007 snprintf(colname, 3, "%02d", ifu);
01008 if (cpl_table_is_valid(exptable, colname, irow)) {
01009 cpl_msg_warning(__func__, "we already have IFU %d of exposure %d (\"%s\")!"
01010 " Ignoring \"%s\"", ifu, irow+1,
01011 cpl_table_get_string(exptable, colname, irow),
01012 filename);
01013 cpl_propertylist_delete(header);
01014 continue;
01015 }
01016 cpl_table_set_string(exptable, colname, irow, filename);
01017
01018
01019
01020 muse_processing_append_used(aProcessing, frame, CPL_FRAME_GROUP_RAW, 1);
01021
01022 cpl_propertylist_delete(header);
01023 }
01024 #if DEBUG_EXPOSURES_SORT
01025 else {
01026 cpl_msg_debug(__func__, "wrong tag \"%s\" for \"%s\"", tag,
01027 cpl_frame_get_filename(frame));
01028 }
01029 #endif
01030 }
01031
01032 if (cpl_table_get_nrow(exptable) <= 0) {
01033
01034 cpl_table_delete(exptable);
01035 cpl_error_set(__func__, CPL_ERROR_DATA_NOT_FOUND);
01036 return NULL;
01037 }
01038
01039 for (i = 0; i < cpl_table_get_nrow(exptable); i++) {
01040 int nmerged = 0;
01041 if (cpl_table_is_valid(exptable, "00", i)) {
01042 nmerged++;
01043 }
01044 int j, nvalid = 0;
01045 for (j = 1; j <= kMuseNumIFUs; j++) {
01046 snprintf(colname, 3, "%02d", j);
01047 if (cpl_table_is_valid(exptable, colname, i)) {
01048 nvalid++;
01049 }
01050 }
01051 cpl_msg_debug(__func__, "Data from exposure %2d is contained in %2d "
01052 "IFU%s/%d merged file%s", i+1, nvalid, nvalid == 1 ? "" : "s",
01053 nmerged, nmerged == 1 ? "" : "s");
01054 }
01055
01056
01057
01058 cpl_propertylist *sorting = cpl_propertylist_new();
01059 cpl_propertylist_append_bool(sorting, "DATE-OBS",
01060 CPL_FALSE);
01061 cpl_table_sort(exptable, sorting);
01062 cpl_propertylist_delete(sorting);
01063
01064 return exptable;
01065 }
01066
01067
01081
01082 muse_mask *
01083 muse_processing_mask_load(muse_processing *aProcessing, const char *aTag)
01084 {
01085 cpl_frameset *frames = muse_frameset_find(aProcessing->inframes,
01086 aTag, 0, CPL_FALSE);
01087 if (frames == NULL || cpl_frameset_get_size(frames) <= 0) {
01088 cpl_frameset_delete(frames);
01089 return NULL;
01090 }
01091 cpl_frame *frame = cpl_frameset_get_position(frames, 0);
01092 muse_mask *mask = muse_mask_load(cpl_frame_get_filename(frame));
01093 if (!mask) {
01094 cpl_msg_warning(__func__, "loading mask \"%s\" failed!",
01095 cpl_frame_get_filename(frame));
01096 cpl_frameset_delete(frames);
01097 return NULL;
01098 }
01099 cpl_msg_info(__func__, "using mask \"%s\" (%"CPL_SIZE_FORMAT" pixels)",
01100 cpl_frame_get_filename(frame), cpl_mask_count(mask->mask));
01101 muse_processing_append_used(aProcessing, frame, CPL_FRAME_GROUP_CALIB, 1);
01102 cpl_frameset_delete(frames);
01103 return mask;
01104 }
01105