32 #include "muse_image.h"
34 #include "muse_quadrants.h"
35 #include "muse_pfits.h"
36 #include "muse_utils.h"
93 cpl_image_delete(aImage->
data);
95 cpl_image_delete(aImage->
dq);
97 cpl_image_delete(aImage->
stat);
101 cpl_propertylist_delete(aImage->
header);
122 image->
header = cpl_propertylist_load(aFilename, 0);
124 cpl_error_set_message(aID, cpl_error_get_code(),
"Loading primary FITS "
125 "header of \"%s\" did not succeed", aFilename);
131 char extname[KEYWORD_LENGTH];
133 snprintf(extname, KEYWORD_LENGTH,
"CHAN%02hhu.%s", aIFU, EXTNAME_DATA);
135 snprintf(extname, KEYWORD_LENGTH,
"%s", EXTNAME_DATA);
137 int extension = cpl_fits_find_extension(aFilename, extname);
138 image->
data = cpl_image_load(aFilename, CPL_TYPE_FLOAT, 0, extension);
140 cpl_error_set_message(aID, MUSE_ERROR_READ_DATA,
"Could not load extension "
141 "%s from \"%s\"", extname, aFilename);
146 cpl_propertylist *hdata = cpl_propertylist_load(aFilename, extension);
147 if (cpl_propertylist_has(hdata,
"BUNIT")) {
148 cpl_propertylist_append_string(image->
header,
"BUNIT",
149 cpl_propertylist_get_string(hdata,
"BUNIT"));
150 cpl_propertylist_set_comment(image->
header,
"BUNIT",
151 cpl_propertylist_get_comment(hdata,
"BUNIT"));
153 cpl_msg_warning(aID,
"No BUNIT given in extension %d [%s] of \"%s\"!",
154 extension, extname, aFilename);
159 cpl_propertylist_erase_regexp(hdata,
"^ESO ", 1);
160 cpl_propertylist_append(image->
header, hdata);
162 cpl_propertylist_delete(hdata);
165 snprintf(extname, KEYWORD_LENGTH,
"CHAN%02hhu.%s", aIFU, EXTNAME_DQ);
167 snprintf(extname, KEYWORD_LENGTH,
"%s", EXTNAME_DQ);
169 extension = cpl_fits_find_extension(aFilename, extname);
170 image->
dq = cpl_image_load(aFilename, CPL_TYPE_INT, 0, extension);
172 cpl_error_set_message(aID, MUSE_ERROR_READ_DQ,
"Could not load extension "
173 "%s from \"%s\"", extname, aFilename);
179 snprintf(extname, KEYWORD_LENGTH,
"CHAN%02hhu.%s", aIFU, EXTNAME_STAT);
181 snprintf(extname, KEYWORD_LENGTH,
"%s", EXTNAME_STAT);
183 extension = cpl_fits_find_extension(aFilename, extname);
184 image->
stat = cpl_image_load(aFilename, CPL_TYPE_FLOAT, 0, extension);
186 cpl_error_set_message(aID, MUSE_ERROR_READ_STAT,
"Could not load extension "
187 "%s from \"%s\"", extname, aFilename);
290 cpl_errorstate prestate = cpl_errorstate_get();
293 mImage->
data = cpl_image_load(aFilename, CPL_TYPE_FLOAT, 0, aExtension);
294 char *channel = NULL;
298 cpl_propertylist *header = cpl_propertylist_load(aFilename, aExtension);
300 cpl_msg_error(__func__,
"Image \"%s\" (extension %d) could not be read: %s",
301 aFilename, aExtension, cpl_error_get_message());
308 cpl_propertylist_delete(header);
310 cpl_msg_error(__func__,
"Image \"%s[%s]\" (extension %d) could not be read "
311 "although chip is alive: %s", aFilename, channel, aExtension,
312 cpl_error_get_message());
316 cpl_msg_warning(__func__,
"Image \"%s[%s]\" (extension %d) could not be read,"
317 " but chip is dead: %s", aFilename, channel, aExtension,
318 cpl_error_get_message());
319 cpl_errorstate_set(prestate);
320 cpl_error_set_message(__func__, MUSE_ERROR_CHIP_NOT_LIVE,
"Image \"%s[%s]\" "
321 "(extension %d) is dead", aFilename, channel,
329 mImage->
dq = cpl_image_new(cpl_image_get_size_x(mImage->
data),
330 cpl_image_get_size_y(mImage->
data),
335 mImage->
stat = cpl_image_new(cpl_image_get_size_x(mImage->
data),
336 cpl_image_get_size_y(mImage->
data),
340 mImage->
header = cpl_propertylist_load(aFilename, 0);
341 if (aExtension > 0) {
342 cpl_propertylist *extHeader = cpl_propertylist_load(aFilename, aExtension);
344 cpl_propertylist_copy_property_regexp(mImage->
header, extHeader,
348 cpl_propertylist_delete(extHeader);
350 prestate = cpl_errorstate_get();
352 if (!cpl_errorstate_is_equal(prestate)) {
353 cpl_errorstate_set(prestate);
356 cpl_propertylist_update_string(mImage->
header,
"BUNIT",
"adu");
357 cpl_propertylist_set_comment(mImage->
header,
"BUNIT",
358 "DATA is in analog-to-digital units");
359 cpl_msg_info(__func__,
"loaded \"%s[%s]\" (extension %d)", aFilename,
360 channel ? channel :
"0", aExtension);
398 cpl_ensure_code(aImage && aFilename, CPL_ERROR_NULL_INPUT);
399 cpl_ensure_code(cpl_propertylist_has(aImage->
header,
"BUNIT"),
400 CPL_ERROR_INCOMPATIBLE_INPUT);
404 cpl_propertylist *header = cpl_propertylist_duplicate(aImage->
header);
405 cpl_propertylist_erase(header,
"BUNIT");
409 cpl_error_code error = cpl_propertylist_save(header, aFilename, CPL_IO_CREATE);
410 cpl_propertylist_delete(header);
411 if (error != CPL_ERROR_NONE) {
412 cpl_msg_error(__func__,
"Could not save header: %s",
413 cpl_error_get_message());
419 cpl_propertylist *extheader = cpl_propertylist_new();
422 cpl_propertylist_copy_property_regexp(extheader, aImage->
header,
425 cpl_propertylist_append_string(extheader,
"EXTNAME", EXTNAME_DATA);
426 cpl_propertylist_set_comment(extheader,
"EXTNAME", EXTNAME_DATA_COMMENT);
427 const char *unit = cpl_propertylist_get_string(aImage->
header,
"BUNIT"),
428 *ucomment = cpl_propertylist_get_comment(aImage->
header,
"BUNIT");
429 cpl_propertylist_append_string(extheader,
"BUNIT", unit);
430 cpl_propertylist_set_comment(extheader,
"BUNIT", ucomment);
432 EXTNAME_DATA, EXTNAME_DQ, EXTNAME_STAT);
433 error = cpl_image_save(aImage->
data, aFilename, CPL_TYPE_FLOAT,
434 extheader, CPL_IO_EXTEND);
435 if (error != CPL_ERROR_NONE) {
436 cpl_msg_error(__func__,
"Could not append data image: %s",
437 cpl_error_get_message());
438 cpl_propertylist_delete(extheader);
442 cpl_propertylist_set_string(extheader,
"EXTNAME", EXTNAME_DQ);
443 cpl_propertylist_set_comment(extheader,
"EXTNAME", EXTNAME_DQ_COMMENT);
444 cpl_propertylist_erase(extheader,
"BUNIT");
446 EXTNAME_DATA, EXTNAME_DQ, EXTNAME_STAT);
447 error = cpl_image_save(aImage->
dq, aFilename, CPL_TYPE_INT,
448 extheader, CPL_IO_EXTEND);
449 if (error != CPL_ERROR_NONE) {
450 cpl_msg_error(__func__,
"Could not append dq image: %s",
451 cpl_error_get_message());
452 cpl_propertylist_delete(extheader);
456 cpl_propertylist_set_string(extheader,
"EXTNAME", EXTNAME_STAT);
457 cpl_propertylist_set_comment(extheader,
"EXTNAME", EXTNAME_STAT_COMMENT);
458 char *ustat = cpl_sprintf(
"%s^2", unit);
459 cpl_propertylist_append_string(extheader,
"BUNIT", ustat);
462 EXTNAME_DATA, EXTNAME_DQ, EXTNAME_STAT);
463 error = cpl_image_save(aImage->
stat, aFilename, CPL_TYPE_FLOAT,
464 extheader, CPL_IO_EXTEND);
465 if (error != CPL_ERROR_NONE) {
466 cpl_msg_error(__func__,
"Could not append stat image: %s",
467 cpl_error_get_message());
468 cpl_propertylist_delete(extheader);
471 cpl_propertylist_delete(extheader);
473 return CPL_ERROR_NONE;
496 cpl_ensure(aImage, CPL_ERROR_NULL_INPUT, NULL);
499 image->
data = cpl_image_duplicate(aImage->
data);
500 image->
dq = cpl_image_duplicate(aImage->
dq);
501 image->
stat = cpl_image_duplicate(aImage->
stat);
502 image->
header = cpl_propertylist_duplicate(aImage->
header);
528 muse_image_dq_merge(cpl_image *aDQ1, cpl_image *aDQ2)
530 cpl_ensure(aDQ1, CPL_ERROR_NULL_INPUT, -1);
531 cpl_ensure(aDQ2, CPL_ERROR_NULL_INPUT, -2);
534 int *dq1 = cpl_image_get_data_int(aDQ1);
536 const int *dq2 = cpl_image_get_data_int_const(aDQ2);
538 return cpl_error_get_code();
542 nx = cpl_image_get_size_x(aDQ1),
543 ny = cpl_image_get_size_y(aDQ1);
544 for (i = 0; i < nx; i++) {
546 for (j = 0; j < ny; j++) {
550 dq1[i + j*nx] |= dq2[i + j*nx];
579 cpl_ensure(aImage, CPL_ERROR_NULL_INPUT, -1);
580 cpl_ensure(aSubtract, CPL_ERROR_NULL_INPUT, -2);
582 cpl_error_code rc = cpl_image_subtract(aImage->
data, aSubtract->
data);
583 if (rc != CPL_ERROR_NONE) {
584 cpl_msg_error(__func__,
"failure while subtracting data extension");
588 rc = cpl_image_add(aImage->
stat, aSubtract->
stat);
589 if (rc != CPL_ERROR_NONE) {
590 cpl_msg_error(__func__,
"failure for stat extension");
594 rc = muse_image_dq_merge(aImage->
dq, aSubtract->
dq);
596 cpl_msg_error(__func__,
"failure for dq extension");
625 cpl_ensure(aImage, CPL_ERROR_NULL_INPUT, -1);
626 cpl_ensure(aDivisor, CPL_ERROR_NULL_INPUT, -2);
632 cpl_image *term2 = cpl_image_power_create(aImage->
data, 2);
634 cpl_error_code rc = cpl_image_divide(aImage->
data, aDivisor->
data);
635 if (rc != CPL_ERROR_NONE) {
636 cpl_msg_error(__func__,
"failure while dividing data extension");
637 cpl_image_delete(term2);
641 cpl_image *divsq = cpl_image_power_create(aDivisor->
data, 2);
642 rc = cpl_image_multiply(term2, aDivisor->
stat);
645 if (rc != CPL_ERROR_NONE) {
646 cpl_msg_error(__func__,
"failure while accessing stat extension of divisor");
647 cpl_image_delete(term2);
648 cpl_image_delete(divsq);
651 cpl_image_divide(term2, divsq);
652 rc = cpl_image_add(aImage->
stat, term2);
653 if (rc != CPL_ERROR_NONE) {
654 cpl_msg_error(__func__,
"failure while accessing stat extension of image");
655 cpl_image_delete(term2);
656 cpl_image_delete(divsq);
659 cpl_image_delete(term2);
660 cpl_image_divide(aImage->
stat, divsq);
661 cpl_image_delete(divsq);
663 rc = muse_image_dq_merge(aImage->
dq, aDivisor->
dq);
665 cpl_msg_error(__func__,
"failure for dq extension");
689 cpl_ensure(aImage, CPL_ERROR_NULL_INPUT, -1);
692 cpl_error_code rc = cpl_image_multiply_scalar(aImage->
data, aScale);
693 if (rc != CPL_ERROR_NONE) {
694 cpl_msg_error(__func__,
"failure while scaling data extension");
699 rc = cpl_image_multiply_scalar(aImage->
stat, aScale*aScale);
700 if (rc != CPL_ERROR_NONE) {
701 cpl_msg_error(__func__,
"failure while scaling stat extension");
733 cpl_ensure(aImage, CPL_ERROR_NULL_INPUT, -1);
734 cpl_ensure(aBias, CPL_ERROR_NULL_INPUT, -2);
735 int nx = cpl_image_get_size_x(aImage->
stat),
736 ny = cpl_image_get_size_y(aImage->
stat),
737 nxbias = cpl_image_get_size_x(aBias->
stat),
738 nybias = cpl_image_get_size_y(aBias->
stat);
739 cpl_ensure(nx == nxbias && ny == nybias, CPL_ERROR_INCOMPATIBLE_INPUT, -3);
744 cpl_image_delete(aImage->
stat);
745 aImage->
stat = cpl_image_subtract_create(aImage->
data, aBias->
data);
746 float *pixstat = cpl_image_get_data_float(aImage->
stat);
751 for (n = 1; n <= 4; n++) {
756 for (i = window[0] - 1; i < window[1]; i++) {
758 for (j = window[2] - 1; j < window[3]; j++) {
759 pixstat[i + j*nx] /= gain;
762 if (pixstat[i + j*nx] <= 0.0) {
764 pixstat[i + j*nx] = FLT_MIN;
797 cpl_ensure_code(aImage && aImage->
header, CPL_ERROR_NULL_INPUT);
798 cpl_ensure_code(cpl_propertylist_has(aImage->
header,
"BUNIT") &&
799 !strncmp(cpl_propertylist_get_string(aImage->
header,
"BUNIT"),
801 CPL_ERROR_INCOMPATIBLE_INPUT);
802 int nx = cpl_image_get_size_x(aImage->
data);
803 float *data = cpl_image_get_data_float(aImage->
data),
804 *stat = cpl_image_get_data_float(aImage->
stat);
805 cpl_ensure_code(data && stat, CPL_ERROR_ILLEGAL_INPUT);
808 for (n = 1; n <= 4; n++) {
812 cpl_msg_debug(__func__,
"looping %"CPL_SIZE_FORMAT
"...%"CPL_SIZE_FORMAT
813 " %"CPL_SIZE_FORMAT
"...%"CPL_SIZE_FORMAT
"",
814 w[0], w[1], w[2], w[3]);
818 for (i = w[0] - 1; i < w[1]; i++) {
820 for (j = w[2] - 1; j < w[3]; j++) {
821 data[i + j*nx] *= gain;
822 stat[i + j*nx] *= gain*gain;
827 cpl_propertylist_update_string(aImage->
header,
"BUNIT",
"count");
828 cpl_propertylist_set_comment(aImage->
header,
"BUNIT",
"DATA is in electrons");
829 return CPL_ERROR_NONE;
850 cpl_ensure_code(aImage && aImage->
data && aImage->
dq, CPL_ERROR_NULL_INPUT);
851 int nx = cpl_image_get_size_x(aImage->
data),
852 ny = cpl_image_get_size_y(aImage->
data);
853 const int *dq = cpl_image_get_data_int_const(aImage->
dq);
855 for (i = 0; i < nx; i++) {
856 for (j = 0; j < ny; j++) {
860 cpl_image_reject(aImage->
data, i+1, j+1);
862 cpl_image_reject(aImage->
stat, i+1, j+1);
867 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...