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);
123 image->
header = cpl_propertylist_load(aFilename, 0);
125 cpl_error_set_message(aID, cpl_error_get_code(),
"Loading primary FITS "
126 "header of \"%s\" did not succeed", aFilename);
132 char extname[KEYWORD_LENGTH];
134 snprintf(extname, KEYWORD_LENGTH,
"CHAN%02hhu.%s", aIFU, EXTNAME_DATA);
136 snprintf(extname, KEYWORD_LENGTH,
"%s", EXTNAME_DATA);
138 int extension = cpl_fits_find_extension(aFilename, extname);
139 image->
data = cpl_image_load(aFilename, CPL_TYPE_FLOAT, 0, extension);
141 cpl_error_set_message(aID, MUSE_ERROR_READ_DATA,
"Could not load extension "
142 "%s from \"%s\"", extname, aFilename);
147 cpl_propertylist *hdata = cpl_propertylist_load(aFilename, extension);
148 if (cpl_propertylist_has(hdata,
"BUNIT")) {
149 cpl_propertylist_append_string(image->
header,
"BUNIT",
150 cpl_propertylist_get_string(hdata,
"BUNIT"));
151 cpl_propertylist_set_comment(image->
header,
"BUNIT",
152 cpl_propertylist_get_comment(hdata,
"BUNIT"));
154 cpl_msg_warning(aID,
"No BUNIT given in extension %d [%s] of \"%s\"!",
155 extension, extname, aFilename);
160 cpl_propertylist_erase_regexp(hdata,
"^ESO ", 1);
161 cpl_propertylist_append(image->
header, hdata);
163 cpl_propertylist_delete(hdata);
166 snprintf(extname, KEYWORD_LENGTH,
"CHAN%02hhu.%s", aIFU, EXTNAME_DQ);
168 snprintf(extname, KEYWORD_LENGTH,
"%s", EXTNAME_DQ);
170 extension = cpl_fits_find_extension(aFilename, extname);
171 image->
dq = cpl_image_load(aFilename, CPL_TYPE_INT, 0, extension);
173 cpl_error_set_message(aID, MUSE_ERROR_READ_DQ,
"Could not load extension "
174 "%s from \"%s\"", extname, aFilename);
180 snprintf(extname, KEYWORD_LENGTH,
"CHAN%02hhu.%s", aIFU, EXTNAME_STAT);
182 snprintf(extname, KEYWORD_LENGTH,
"%s", EXTNAME_STAT);
184 extension = cpl_fits_find_extension(aFilename, extname);
185 image->
stat = cpl_image_load(aFilename, CPL_TYPE_FLOAT, 0, extension);
187 cpl_error_set_message(aID, MUSE_ERROR_READ_STAT,
"Could not load extension "
188 "%s from \"%s\"", extname, aFilename);
291 cpl_errorstate prestate = cpl_errorstate_get();
294 mImage->
data = cpl_image_load(aFilename, CPL_TYPE_FLOAT, 0, aExtension);
295 char *channel = NULL;
299 cpl_propertylist *header = cpl_propertylist_load(aFilename, aExtension);
301 cpl_msg_error(__func__,
"Image \"%s\" (extension %d) could not be read: %s",
302 aFilename, aExtension, cpl_error_get_message());
309 cpl_propertylist_delete(header);
311 cpl_msg_error(__func__,
"Image \"%s[%s]\" (extension %d) could not be read "
312 "although chip is alive: %s", aFilename, channel, aExtension,
313 cpl_error_get_message());
317 cpl_msg_warning(__func__,
"Image \"%s[%s]\" (extension %d) could not be read,"
318 " but chip is dead: %s", aFilename, channel, aExtension,
319 cpl_error_get_message());
320 cpl_errorstate_set(prestate);
321 cpl_error_set_message(__func__, MUSE_ERROR_CHIP_NOT_LIVE,
"Image \"%s[%s]\" "
322 "(extension %d) is dead", aFilename, channel,
330 mImage->
dq = cpl_image_new(cpl_image_get_size_x(mImage->
data),
331 cpl_image_get_size_y(mImage->
data),
336 mImage->
stat = cpl_image_new(cpl_image_get_size_x(mImage->
data),
337 cpl_image_get_size_y(mImage->
data),
341 mImage->
header = cpl_propertylist_load(aFilename, 0);
342 if (aExtension > 0) {
343 cpl_propertylist *extHeader = cpl_propertylist_load(aFilename, aExtension);
345 cpl_propertylist_copy_property_regexp(mImage->
header, extHeader,
349 cpl_propertylist_delete(extHeader);
351 prestate = cpl_errorstate_get();
353 if (!cpl_errorstate_is_equal(prestate)) {
354 cpl_errorstate_set(prestate);
357 cpl_propertylist_update_string(mImage->
header,
"BUNIT",
"adu");
358 cpl_propertylist_set_comment(mImage->
header,
"BUNIT",
359 "DATA is in analog-to-digital units");
360 cpl_msg_info(__func__,
"loaded \"%s[%s]\" (extension %d)", aFilename,
361 channel ? channel :
"0", aExtension);
401 cpl_ensure_code(aImage && aImage->
data && aFilename, CPL_ERROR_NULL_INPUT);
402 cpl_ensure_code(cpl_propertylist_has(aImage->
header,
"BUNIT"),
403 CPL_ERROR_INCOMPATIBLE_INPUT);
407 cpl_propertylist *header = cpl_propertylist_duplicate(aImage->
header);
408 cpl_propertylist_erase(header,
"BUNIT");
412 cpl_error_code error = cpl_propertylist_save(header, aFilename, CPL_IO_CREATE);
413 cpl_propertylist_delete(header);
414 if (error != CPL_ERROR_NONE) {
415 cpl_msg_error(__func__,
"Could not save header: %s",
416 cpl_error_get_message());
422 cpl_propertylist *extheader = cpl_propertylist_new();
425 cpl_propertylist_copy_property_regexp(extheader, aImage->
header,
428 cpl_propertylist_append_string(extheader,
"EXTNAME", EXTNAME_DATA);
429 cpl_propertylist_set_comment(extheader,
"EXTNAME", EXTNAME_DATA_COMMENT);
430 const char *unit = cpl_propertylist_get_string(aImage->
header,
"BUNIT"),
431 *ucomment = cpl_propertylist_get_comment(aImage->
header,
"BUNIT");
432 cpl_propertylist_append_string(extheader,
"BUNIT", unit);
433 cpl_propertylist_set_comment(extheader,
"BUNIT", ucomment);
435 aImage->
dq ? EXTNAME_DQ : NULL,
436 aImage->
stat ? EXTNAME_STAT : NULL);
437 error = cpl_image_save(aImage->
data, aFilename, CPL_TYPE_FLOAT,
438 extheader, CPL_IO_EXTEND);
439 if (error != CPL_ERROR_NONE) {
440 cpl_msg_error(__func__,
"Could not append data image: %s",
441 cpl_error_get_message());
442 cpl_propertylist_delete(extheader);
447 cpl_propertylist_set_string(extheader,
"EXTNAME", EXTNAME_DQ);
448 cpl_propertylist_set_comment(extheader,
"EXTNAME", EXTNAME_DQ_COMMENT);
449 cpl_propertylist_erase(extheader,
"BUNIT");
451 aImage->
stat ? EXTNAME_STAT : NULL);
452 error = cpl_image_save(aImage->
dq, aFilename, CPL_TYPE_INT,
453 extheader, CPL_IO_EXTEND);
454 if (error != CPL_ERROR_NONE) {
455 cpl_msg_error(__func__,
"Could not append dq image: %s",
456 cpl_error_get_message());
457 cpl_propertylist_delete(extheader);
463 cpl_propertylist_set_string(extheader,
"EXTNAME", EXTNAME_STAT);
464 cpl_propertylist_set_comment(extheader,
"EXTNAME", EXTNAME_STAT_COMMENT);
465 char *ustat = cpl_sprintf(
"(%s)**2", unit);
466 cpl_propertylist_append_string(extheader,
"BUNIT", ustat);
469 aImage->
dq ? EXTNAME_DQ : NULL, EXTNAME_STAT);
470 error = cpl_image_save(aImage->
stat, aFilename, CPL_TYPE_FLOAT,
471 extheader, CPL_IO_EXTEND);
472 if (error != CPL_ERROR_NONE) {
473 cpl_msg_error(__func__,
"Could not append stat image: %s",
474 cpl_error_get_message());
475 cpl_propertylist_delete(extheader);
479 cpl_propertylist_delete(extheader);
481 return CPL_ERROR_NONE;
504 cpl_ensure(aImage, CPL_ERROR_NULL_INPUT, NULL);
507 image->
data = cpl_image_duplicate(aImage->
data);
508 image->
dq = cpl_image_duplicate(aImage->
dq);
509 image->
stat = cpl_image_duplicate(aImage->
stat);
510 image->
header = cpl_propertylist_duplicate(aImage->
header);
536 muse_image_dq_merge(cpl_image *aDQ1, cpl_image *aDQ2)
538 cpl_ensure(aDQ1, CPL_ERROR_NULL_INPUT, -1);
539 cpl_ensure(aDQ2, CPL_ERROR_NULL_INPUT, -2);
542 int *dq1 = cpl_image_get_data_int(aDQ1);
544 const int *dq2 = cpl_image_get_data_int_const(aDQ2);
546 return cpl_error_get_code();
550 nx = cpl_image_get_size_x(aDQ1),
551 ny = cpl_image_get_size_y(aDQ1);
552 for (i = 0; i < nx; i++) {
554 for (j = 0; j < ny; j++) {
558 dq1[i + j*nx] |= dq2[i + j*nx];
587 cpl_ensure(aImage, CPL_ERROR_NULL_INPUT, -1);
588 cpl_ensure(aSubtract, CPL_ERROR_NULL_INPUT, -2);
590 cpl_error_code rc = cpl_image_subtract(aImage->
data, aSubtract->
data);
591 if (rc != CPL_ERROR_NONE) {
592 cpl_msg_error(__func__,
"failure while subtracting data extension");
596 rc = cpl_image_add(aImage->
stat, aSubtract->
stat);
597 if (rc != CPL_ERROR_NONE) {
598 cpl_msg_error(__func__,
"failure for stat extension");
602 rc = muse_image_dq_merge(aImage->
dq, aSubtract->
dq);
604 cpl_msg_error(__func__,
"failure for dq extension");
633 cpl_ensure(aImage, CPL_ERROR_NULL_INPUT, -1);
634 cpl_ensure(aDivisor, CPL_ERROR_NULL_INPUT, -2);
640 cpl_image *term2 = cpl_image_power_create(aImage->
data, 2);
642 cpl_error_code rc = cpl_image_divide(aImage->
data, aDivisor->
data);
643 if (rc != CPL_ERROR_NONE) {
644 cpl_msg_error(__func__,
"failure while dividing data extension");
645 cpl_image_delete(term2);
649 cpl_image *divsq = cpl_image_power_create(aDivisor->
data, 2);
650 rc = cpl_image_multiply(term2, aDivisor->
stat);
653 if (rc != CPL_ERROR_NONE) {
654 cpl_msg_error(__func__,
"failure while accessing stat extension of divisor");
655 cpl_image_delete(term2);
656 cpl_image_delete(divsq);
659 cpl_image_divide(term2, divsq);
660 rc = cpl_image_add(aImage->
stat, term2);
661 if (rc != CPL_ERROR_NONE) {
662 cpl_msg_error(__func__,
"failure while accessing stat extension of image");
663 cpl_image_delete(term2);
664 cpl_image_delete(divsq);
667 cpl_image_delete(term2);
668 cpl_image_divide(aImage->
stat, divsq);
669 cpl_image_delete(divsq);
671 rc = muse_image_dq_merge(aImage->
dq, aDivisor->
dq);
673 cpl_msg_error(__func__,
"failure for dq extension");
697 cpl_ensure(aImage, CPL_ERROR_NULL_INPUT, -1);
700 cpl_error_code rc = cpl_image_multiply_scalar(aImage->
data, aScale);
701 if (rc != CPL_ERROR_NONE) {
702 cpl_msg_error(__func__,
"failure while scaling data extension");
707 rc = cpl_image_multiply_scalar(aImage->
stat, aScale*aScale);
708 if (rc != CPL_ERROR_NONE) {
709 cpl_msg_error(__func__,
"failure while scaling stat extension");
741 cpl_ensure(aImage, CPL_ERROR_NULL_INPUT, -1);
742 cpl_ensure(aBias, CPL_ERROR_NULL_INPUT, -2);
743 int nx = cpl_image_get_size_x(aImage->
stat),
744 ny = cpl_image_get_size_y(aImage->
stat),
745 nxbias = cpl_image_get_size_x(aBias->
stat),
746 nybias = cpl_image_get_size_y(aBias->
stat);
747 cpl_ensure(nx == nxbias && ny == nybias, CPL_ERROR_INCOMPATIBLE_INPUT, -3);
752 cpl_image_delete(aImage->
stat);
753 aImage->
stat = cpl_image_subtract_create(aImage->
data, aBias->
data);
754 float *pixstat = cpl_image_get_data_float(aImage->
stat);
759 for (n = 1; n <= 4; n++) {
764 for (i = window[0] - 1; i < window[1]; i++) {
766 for (j = window[2] - 1; j < window[3]; j++) {
767 pixstat[i + j*nx] /= gain;
770 if (pixstat[i + j*nx] <= 0.0) {
772 pixstat[i + j*nx] = FLT_MIN;
805 cpl_ensure_code(aImage && aImage->
header, CPL_ERROR_NULL_INPUT);
806 cpl_ensure_code(cpl_propertylist_has(aImage->
header,
"BUNIT") &&
807 !strncmp(cpl_propertylist_get_string(aImage->
header,
"BUNIT"),
809 CPL_ERROR_INCOMPATIBLE_INPUT);
810 int nx = cpl_image_get_size_x(aImage->
data);
811 float *data = cpl_image_get_data_float(aImage->
data),
812 *stat = cpl_image_get_data_float(aImage->
stat);
813 cpl_ensure_code(data && stat, CPL_ERROR_ILLEGAL_INPUT);
816 for (n = 1; n <= 4; n++) {
820 cpl_msg_debug(__func__,
"looping %"CPL_SIZE_FORMAT
"...%"CPL_SIZE_FORMAT
821 " %"CPL_SIZE_FORMAT
"...%"CPL_SIZE_FORMAT
"",
822 w[0], w[1], w[2], w[3]);
826 for (i = w[0] - 1; i < w[1]; i++) {
828 for (j = w[2] - 1; j < w[3]; j++) {
829 data[i + j*nx] *= gain;
830 stat[i + j*nx] *= gain*gain;
835 cpl_propertylist_update_string(aImage->
header,
"BUNIT",
"count");
836 cpl_propertylist_set_comment(aImage->
header,
"BUNIT",
"DATA is in electrons");
837 return CPL_ERROR_NONE;
858 cpl_ensure_code(aImage && aImage->
data && aImage->
dq, CPL_ERROR_NULL_INPUT);
859 int nx = cpl_image_get_size_x(aImage->
data),
860 ny = cpl_image_get_size_y(aImage->
data);
861 const int *dq = cpl_image_get_data_int_const(aImage->
dq);
863 for (i = 0; i < nx; i++) {
864 for (j = 0; j < ny; j++) {
868 cpl_image_reject(aImage->
data, i+1, j+1);
870 cpl_image_reject(aImage->
stat, i+1, j+1);
875 return CPL_ERROR_NONE;
899 cpl_ensure_code(aImage && aImage->
data && aImage->
dq, CPL_ERROR_NULL_INPUT);
902 int *pdq = cpl_image_get_data_int(aImage->
dq);
903 float *pdata = cpl_image_get_data_float(aImage->
data),
907 pstat = cpl_image_get_data_float(aImage->
stat);
909 int i, nx = cpl_image_get_size_x(aImage->
data),
910 ny = cpl_image_get_size_y(aImage->
data);
911 for (i = 0; i < nx; i++) {
913 for (j = 0; j < ny; j++) {
914 if (pdq[i + j*nx] == EURO3D_GOODPIXEL) {
918 pdata[i + j*nx] = NAN;
920 pstat[i + j*nx] = NAN;
926 cpl_image_delete(aImage->
dq);
929 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.
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
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).