32 #include "muse_image.h" 34 #include "muse_quadrants.h" 35 #include "muse_quality.h" 36 #include "muse_pfits.h" 37 #include "muse_utils.h" 94 cpl_image_delete(aImage->
data);
96 cpl_image_delete(aImage->
dq);
98 cpl_image_delete(aImage->
stat);
102 cpl_propertylist_delete(aImage->
header);
124 image->
header = cpl_propertylist_load(aFilename, 0);
126 cpl_error_set_message(aID, cpl_error_get_code(),
"Loading primary FITS " 127 "header of \"%s\" did not succeed", aFilename);
133 char extname[KEYWORD_LENGTH];
136 snprintf(extname, KEYWORD_LENGTH,
"CHAN%02hhu", aIFU);
137 cpl_propertylist_update_string(image->
header,
"EXTNAME", extname);
139 snprintf(extname, KEYWORD_LENGTH,
"CHAN%02hhu.%s", aIFU, EXTNAME_DATA);
141 snprintf(extname, KEYWORD_LENGTH,
"%s", EXTNAME_DATA);
143 int extension = cpl_fits_find_extension(aFilename, extname);
144 image->
data = cpl_image_load(aFilename, CPL_TYPE_FLOAT, 0, extension);
146 cpl_error_set_message(aID, MUSE_ERROR_READ_DATA,
"Could not load extension " 147 "%s from \"%s\"", extname, aFilename);
152 cpl_propertylist *hdata = cpl_propertylist_load(aFilename, extension);
153 if (cpl_propertylist_has(hdata,
"BUNIT")) {
154 cpl_propertylist_append_string(image->
header,
"BUNIT",
156 cpl_propertylist_set_comment(image->
header,
"BUNIT",
157 cpl_propertylist_get_comment(hdata,
"BUNIT"));
159 cpl_msg_warning(aID,
"No BUNIT given in extension %d [%s] of \"%s\"!",
160 extension, extname, aFilename);
165 cpl_propertylist_erase_regexp(hdata,
"^ESO ", 1);
166 cpl_propertylist_append(image->
header, hdata);
168 cpl_propertylist_delete(hdata);
171 snprintf(extname, KEYWORD_LENGTH,
"CHAN%02hhu.%s", aIFU, EXTNAME_DQ);
173 snprintf(extname, KEYWORD_LENGTH,
"%s", EXTNAME_DQ);
175 extension = cpl_fits_find_extension(aFilename, extname);
176 image->
dq = cpl_image_load(aFilename, CPL_TYPE_INT, 0, extension);
178 cpl_error_set_message(aID, MUSE_ERROR_READ_DQ,
"Could not load extension " 179 "%s from \"%s\"", extname, aFilename);
185 snprintf(extname, KEYWORD_LENGTH,
"CHAN%02hhu.%s", aIFU, EXTNAME_STAT);
187 snprintf(extname, KEYWORD_LENGTH,
"%s", EXTNAME_STAT);
189 extension = cpl_fits_find_extension(aFilename, extname);
190 image->
stat = cpl_image_load(aFilename, CPL_TYPE_FLOAT, 0, extension);
192 cpl_error_set_message(aID, MUSE_ERROR_READ_STAT,
"Could not load extension " 193 "%s from \"%s\"", extname, aFilename);
296 cpl_errorstate prestate = cpl_errorstate_get();
299 mImage->
data = cpl_image_load(aFilename, CPL_TYPE_FLOAT, 0, aExtension);
300 char *channel = NULL;
304 cpl_propertylist *header = cpl_propertylist_load(aFilename, aExtension);
306 cpl_msg_error(__func__,
"Image \"%s\" (extension %d) could not be read: %s",
307 aFilename, aExtension, cpl_error_get_message());
314 cpl_propertylist_delete(header);
316 cpl_msg_error(__func__,
"Image \"%s[%s]\" (extension %d) could not be read " 317 "although chip is alive: %s", aFilename, channel, aExtension,
318 cpl_error_get_message());
322 cpl_msg_warning(__func__,
"Image \"%s[%s]\" (extension %d) could not be read," 323 " but chip is dead: %s", aFilename, channel, aExtension,
324 cpl_error_get_message());
325 cpl_errorstate_set(prestate);
326 cpl_error_set_message(__func__, MUSE_ERROR_CHIP_NOT_LIVE,
"Image \"%s[%s]\" " 327 "(extension %d) is dead", aFilename, channel,
335 mImage->
dq = cpl_image_new(cpl_image_get_size_x(mImage->
data),
336 cpl_image_get_size_y(mImage->
data),
341 mImage->
stat = cpl_image_new(cpl_image_get_size_x(mImage->
data),
342 cpl_image_get_size_y(mImage->
data),
346 mImage->
header = cpl_propertylist_load(aFilename, 0);
347 if (aExtension > 0) {
348 cpl_propertylist *extHeader = cpl_propertylist_load(aFilename, aExtension);
350 cpl_propertylist_copy_property_regexp(mImage->
header, extHeader,
354 cpl_propertylist_delete(extHeader);
356 prestate = cpl_errorstate_get();
358 if (!cpl_errorstate_is_equal(prestate)) {
359 cpl_errorstate_set(prestate);
362 cpl_propertylist_update_string(mImage->
header,
"BUNIT",
"adu");
363 cpl_propertylist_set_comment(mImage->
header,
"BUNIT",
364 "DATA is in analog-to-digital units");
365 cpl_msg_info(__func__,
"loaded \"%s[%s]\" (extension %d)", aFilename,
366 channel ? channel :
"0", aExtension);
407 cpl_ensure_code(aImage && aImage->
data && aFilename, CPL_ERROR_NULL_INPUT);
408 cpl_ensure_code(cpl_propertylist_has(aImage->
header,
"BUNIT"),
409 CPL_ERROR_INCOMPATIBLE_INPUT);
413 cpl_propertylist *header = cpl_propertylist_duplicate(aImage->
header);
414 cpl_propertylist_erase(header,
"BUNIT");
420 cpl_error_code error = cpl_propertylist_save(header, aFilename, CPL_IO_CREATE);
421 cpl_propertylist_delete(header);
422 if (error != CPL_ERROR_NONE) {
423 cpl_msg_error(__func__,
"Could not save header: %s",
424 cpl_error_get_message());
430 cpl_propertylist *extheader = cpl_propertylist_new();
433 cpl_propertylist_copy_property_regexp(extheader, aImage->
header,
436 cpl_propertylist_append_string(extheader,
"EXTNAME", EXTNAME_DATA);
437 cpl_propertylist_set_comment(extheader,
"EXTNAME", EXTNAME_DATA_COMMENT);
439 *ucomment = cpl_propertylist_get_comment(aImage->
header,
"BUNIT");
440 cpl_propertylist_append_string(extheader,
"BUNIT", unit);
441 cpl_propertylist_set_comment(extheader,
"BUNIT", ucomment);
443 aImage->
dq ? EXTNAME_DQ : NULL,
444 aImage->
stat ? EXTNAME_STAT : NULL);
445 error = cpl_image_save(aImage->
data, aFilename, CPL_TYPE_FLOAT,
446 extheader, CPL_IO_EXTEND);
447 if (error != CPL_ERROR_NONE) {
448 cpl_msg_error(__func__,
"Could not append data image: %s",
449 cpl_error_get_message());
450 cpl_propertylist_delete(extheader);
455 cpl_propertylist_set_string(extheader,
"EXTNAME", EXTNAME_DQ);
456 cpl_propertylist_set_comment(extheader,
"EXTNAME", EXTNAME_DQ_COMMENT);
457 cpl_propertylist_erase(extheader,
"BUNIT");
459 aImage->
stat ? EXTNAME_STAT : NULL);
460 error = cpl_image_save(aImage->
dq, aFilename, CPL_TYPE_INT,
461 extheader, CPL_IO_EXTEND);
462 if (error != CPL_ERROR_NONE) {
463 cpl_msg_error(__func__,
"Could not append dq image: %s",
464 cpl_error_get_message());
465 cpl_propertylist_delete(extheader);
471 cpl_propertylist_set_string(extheader,
"EXTNAME", EXTNAME_STAT);
472 cpl_propertylist_set_comment(extheader,
"EXTNAME", EXTNAME_STAT_COMMENT);
473 char *ustat = cpl_sprintf(
"(%s)**2", unit);
474 cpl_propertylist_append_string(extheader,
"BUNIT", ustat);
477 aImage->
dq ? EXTNAME_DQ : NULL, EXTNAME_STAT);
478 error = cpl_image_save(aImage->
stat, aFilename, CPL_TYPE_FLOAT,
479 extheader, CPL_IO_EXTEND);
480 if (error != CPL_ERROR_NONE) {
481 cpl_msg_error(__func__,
"Could not append stat image: %s",
482 cpl_error_get_message());
483 cpl_propertylist_delete(extheader);
487 cpl_propertylist_delete(extheader);
489 return CPL_ERROR_NONE;
512 cpl_ensure(aImage, CPL_ERROR_NULL_INPUT, NULL);
515 image->
data = cpl_image_duplicate(aImage->
data);
516 image->
dq = cpl_image_duplicate(aImage->
dq);
517 image->
stat = cpl_image_duplicate(aImage->
stat);
518 image->
header = cpl_propertylist_duplicate(aImage->
header);
544 muse_image_dq_merge(cpl_image *aDQ1, cpl_image *aDQ2)
546 cpl_ensure(aDQ1, CPL_ERROR_NULL_INPUT, -1);
547 cpl_ensure(aDQ2, CPL_ERROR_NULL_INPUT, -2);
550 int *dq1 = cpl_image_get_data_int(aDQ1);
552 const int *dq2 = cpl_image_get_data_int_const(aDQ2);
554 return cpl_error_get_code();
558 nx = cpl_image_get_size_x(aDQ1),
559 ny = cpl_image_get_size_y(aDQ1);
560 for (i = 0; i < nx; i++) {
562 for (j = 0; j < ny; j++) {
566 dq1[i + j*nx] |= dq2[i + j*nx];
595 cpl_ensure(aImage, CPL_ERROR_NULL_INPUT, -1);
596 cpl_ensure(aSubtract, CPL_ERROR_NULL_INPUT, -2);
598 cpl_error_code rc = cpl_image_subtract(aImage->
data, aSubtract->
data);
599 if (rc != CPL_ERROR_NONE) {
600 cpl_msg_error(__func__,
"failure while subtracting data extension");
604 rc = cpl_image_add(aImage->
stat, aSubtract->
stat);
605 if (rc != CPL_ERROR_NONE) {
606 cpl_msg_error(__func__,
"failure for stat extension");
610 rc = muse_image_dq_merge(aImage->
dq, aSubtract->
dq);
612 cpl_msg_error(__func__,
"failure for dq extension");
641 cpl_ensure(aImage, CPL_ERROR_NULL_INPUT, -1);
642 cpl_ensure(aDivisor, CPL_ERROR_NULL_INPUT, -2);
648 cpl_image *term2 = cpl_image_power_create(aImage->
data, 2);
650 cpl_error_code rc = cpl_image_divide(aImage->
data, aDivisor->
data);
651 if (rc != CPL_ERROR_NONE) {
652 cpl_msg_error(__func__,
"failure while dividing data extension");
653 cpl_image_delete(term2);
657 cpl_image *divsq = cpl_image_power_create(aDivisor->
data, 2);
658 rc = cpl_image_multiply(term2, aDivisor->
stat);
661 if (rc != CPL_ERROR_NONE) {
662 cpl_msg_error(__func__,
"failure while accessing stat extension of divisor");
663 cpl_image_delete(term2);
664 cpl_image_delete(divsq);
667 cpl_image_divide(term2, divsq);
668 rc = cpl_image_add(aImage->
stat, term2);
669 if (rc != CPL_ERROR_NONE) {
670 cpl_msg_error(__func__,
"failure while accessing stat extension of image");
671 cpl_image_delete(term2);
672 cpl_image_delete(divsq);
675 cpl_image_delete(term2);
676 cpl_image_divide(aImage->
stat, divsq);
677 cpl_image_delete(divsq);
679 rc = muse_image_dq_merge(aImage->
dq, aDivisor->
dq);
681 cpl_msg_error(__func__,
"failure for dq extension");
705 cpl_ensure(aImage, CPL_ERROR_NULL_INPUT, -1);
708 cpl_error_code rc = cpl_image_multiply_scalar(aImage->
data, aScale);
709 if (rc != CPL_ERROR_NONE) {
710 cpl_msg_error(__func__,
"failure while scaling data extension");
715 rc = cpl_image_multiply_scalar(aImage->
stat, aScale*aScale);
716 if (rc != CPL_ERROR_NONE) {
717 cpl_msg_error(__func__,
"failure while scaling stat extension");
749 cpl_ensure(aImage, CPL_ERROR_NULL_INPUT, -1);
750 cpl_ensure(aBias, CPL_ERROR_NULL_INPUT, -2);
751 int nx = cpl_image_get_size_x(aImage->
stat),
752 ny = cpl_image_get_size_y(aImage->
stat),
753 nxbias = cpl_image_get_size_x(aBias->
stat),
754 nybias = cpl_image_get_size_y(aBias->
stat);
755 cpl_ensure(nx == nxbias && ny == nybias, CPL_ERROR_INCOMPATIBLE_INPUT, -3);
760 cpl_image_delete(aImage->
stat);
761 aImage->
stat = cpl_image_subtract_create(aImage->
data, aBias->
data);
762 float *pixstat = cpl_image_get_data_float(aImage->
stat);
767 for (n = 1; n <= 4; n++) {
772 for (i = window[0] - 1; i < window[1]; i++) {
774 for (j = window[2] - 1; j < window[3]; j++) {
775 pixstat[i + j*nx] /= gain;
778 if (pixstat[i + j*nx] <= 0.0) {
780 pixstat[i + j*nx] = FLT_MIN;
813 cpl_ensure_code(aImage && aImage->
header, CPL_ERROR_NULL_INPUT);
814 cpl_ensure_code(cpl_propertylist_has(aImage->
header,
"BUNIT") &&
816 CPL_ERROR_INCOMPATIBLE_INPUT);
817 int nx = cpl_image_get_size_x(aImage->
data);
818 float *data = cpl_image_get_data_float(aImage->
data),
819 *stat = cpl_image_get_data_float(aImage->
stat);
820 cpl_ensure_code(data && stat, CPL_ERROR_ILLEGAL_INPUT);
823 for (n = 1; n <= 4; n++) {
827 cpl_msg_debug(__func__,
"looping %"CPL_SIZE_FORMAT
"...%"CPL_SIZE_FORMAT
828 " %"CPL_SIZE_FORMAT
"...%"CPL_SIZE_FORMAT
"",
829 w[0], w[1], w[2], w[3]);
833 for (i = w[0] - 1; i < w[1]; i++) {
835 for (j = w[2] - 1; j < w[3]; j++) {
836 data[i + j*nx] *= gain;
837 stat[i + j*nx] *= gain*gain;
842 cpl_propertylist_update_string(aImage->
header,
"BUNIT",
"count");
843 cpl_propertylist_set_comment(aImage->
header,
"BUNIT",
"DATA is in electrons");
844 return CPL_ERROR_NONE;
865 cpl_ensure_code(aImage && aImage->
data && aImage->
dq, CPL_ERROR_NULL_INPUT);
866 int nx = cpl_image_get_size_x(aImage->
data),
867 ny = cpl_image_get_size_y(aImage->
data);
868 const int *dq = cpl_image_get_data_int_const(aImage->
dq);
870 for (i = 0; i < nx; i++) {
871 for (j = 0; j < ny; j++) {
875 cpl_image_reject(aImage->
data, i+1, j+1);
877 cpl_image_reject(aImage->
stat, i+1, j+1);
882 return CPL_ERROR_NONE;
906 cpl_ensure_code(aImage && aImage->
data && aImage->
dq, CPL_ERROR_NULL_INPUT);
909 int *pdq = cpl_image_get_data_int(aImage->
dq);
910 float *pdata = cpl_image_get_data_float(aImage->
data),
914 pstat = cpl_image_get_data_float(aImage->
stat);
916 int i, nx = cpl_image_get_size_x(aImage->
data),
917 ny = cpl_image_get_size_y(aImage->
data);
918 for (i = 0; i < nx; i++) {
920 for (j = 0; j < ny; j++) {
921 if (pdq[i + j*nx] == EURO3D_GOODPIXEL) {
925 pdata[i + j*nx] = NAN;
927 pstat[i + j*nx] = NAN;
933 cpl_image_delete(aImage->
dq);
936 return CPL_ERROR_NONE;
void muse_image_delete(muse_image *aImage)
Deallocate memory associated to a muse_image object.
cpl_boolean muse_pfits_get_chip_live(const cpl_propertylist *aHeaders)
find out if the CCD was active (live)
int muse_image_divide(muse_image *aImage, muse_image *aDivisor)
Divide a muse_image by another with correct treatment of bad pixels and variance. ...
const char * muse_pfits_get_extname(const cpl_propertylist *aHeaders)
find out the extension name
cpl_size * muse_quadrants_get_window(const muse_image *aImage, unsigned char aQuadrant)
Determine the data window of a given quadrant on the CCD.
int muse_image_scale(muse_image *aImage, double aScale)
Scale a muse_image with correct treatment of variance.
double muse_pfits_get_gain(const cpl_propertylist *aHeaders, unsigned char aQuadrant)
find the detector gain (in units of count/adu)
cpl_image * data
the data extension
muse_image * muse_image_load_from_raw(const char *aFilename, int aExtension)
Load raw image into the data extension of a MUSE image.
static muse_image * muse_image_load_internal(const char *aFilename, unsigned char aIFU, const char *aID)
Load the three extensions and the FITS headers of a MUSE image.
muse_image * muse_image_duplicate(const muse_image *aImage)
Duplicate the three image extensions and the FITS headers of a MUSE image.
cpl_image * stat
the statistics extension
int muse_image_subtract(muse_image *aImage, muse_image *aSubtract)
Subtract a muse_image from another with correct treatment of bad pixels and variance.
const char * muse_pfits_get_bunit(const cpl_propertylist *aHeaders)
find out the unit string
Structure definition of MUSE three extension FITS file.
cpl_propertylist * header
the FITS header
cpl_error_code muse_utils_set_hduclass(cpl_propertylist *aHeader, const char *aClass2, const char *aExtData, const char *aExtDQ, const char *aExtStat)
Set HDU headers for the ESO FITS data format.
int muse_image_variance_create(muse_image *aImage, muse_image *aBias)
Create the photon noise-based variance in the stat extension.
cpl_image * dq
the data quality extension
#define MUSE_WCS_KEYS
regular expression for WCS properties
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.
muse_image * muse_image_load(const char *aFilename)
Load the three extensions and the FITS headers of a MUSE image from a file.
cpl_error_code muse_image_reject_from_dq(muse_image *aImage)
Reject pixels of a muse_image depending on its DQ data.
muse_image * muse_image_new(void)
Allocate memory for a new muse_image object.
cpl_error_code muse_image_adu_to_count(muse_image *aImage)
Convert the data units from raw adu to count (= electron) units.
muse_image * muse_image_load_from_extensions(const char *aFilename, unsigned char aIFU)
Load the three extensions and the FITS headers of a MUSE image from extensions of a merged file...
cpl_error_code muse_image_dq_to_nan(muse_image *aImage)
Convert pixels flagged in the DQ extension to NANs in DATA (and STAT, if present).