32 #include "muse_quadrants.h" 33 #include "muse_instrument.h" 35 #include "muse_artifacts.h" 37 #include "muse_pfits.h" 38 #include "muse_utils.h" 82 cpl_ensure_code(aImage && aImage->
data && aImage->
header, CPL_ERROR_NULL_INPUT);
85 CPL_ERROR_BAD_FILE_FORMAT);
90 for (n = 1; n <= 4; n++) {
92 cpl_ensure_code(w, CPL_ERROR_ILLEGAL_INPUT);
95 int nx = cpl_image_get_size_x(aImage->
data);
97 enum { REJ_NONE, REJ_DCR, REJ_FIT } reject = REJ_NONE;
99 if (!strncmp(aRejection,
"dcr", 3)) {
101 }
else if (!strncmp(aRejection,
"fit", 3)) {
103 }
else if (strncmp(aRejection,
"none", 5)) {
104 return cpl_error_set_message(__func__, CPL_ERROR_ILLEGAL_INPUT,
105 "Unknown rejection type \"%s\"", aRejection);
115 unsigned long dcrbox1 = 128, dcrbox2 = 32, dcrnpass = 3;
116 float dcrthres = 2.5,
118 if (reject == REJ_DCR) {
119 char *rest = strchr(aRejection,
':');
120 if (strlen(aRejection) > 4 && rest++) {
121 dcrbox1 = strtoul(rest, &rest, 10);
122 if (strlen(rest++) > 0) {
123 dcrbox2 = strtoul(rest, &rest, 10);
124 if (strlen(rest++) > 0) {
125 dcrnpass = strtoul(rest, &rest, 10);
126 if (strlen(rest++) > 0) {
127 dcrthres = strtof(rest, NULL);
133 if (dcrbox2 > overx || dcrbox2 > overy ||
134 dcrbox1 > outnx || dcrbox1 > outny ||
135 dcrnpass <= 0 || dcrthres <= 0.) {
136 cpl_msg_warning(__func__,
"Detected illegal DCR parameters for overscan " 137 "statistics (%lux%lu, %lu, %f; overscan: %ux%u, output: " 138 "%ux%u), not rejecting anything!", dcrbox1, dcrbox2,
139 dcrnpass, dcrthres, overx, overy, outnx, outny);
142 cpl_msg_debug(__func__,
"Using DCR cosmic ray rejection for overscan " 143 "statistics (%lux%lu, %lu, %f)", dcrbox1, dcrbox2, dcrnpass,
146 }
else if (reject == REJ_FIT) {
147 char *rest = strchr(aRejection,
':');
148 if (strlen(aRejection) > 4 && rest++) {
149 sigma = strtof(rest, NULL);
153 cpl_msg_warning(__func__,
"Detected illegal fit sigma for overscan " 154 "statistics (%f; overscan: %ux%u, output: %ux%u) not " 155 "rejecting anything!", sigma, overx, overy, outnx, outny);
158 cpl_msg_debug(__func__,
"Using constant fit for overscan statistics (0, " 163 const float *data = cpl_image_get_data_float_const(aImage->
data);
164 const int *dq = cpl_image_get_data_int_const(aImage->
dq);
167 for (n = 1; n <= 4; n++) {
170 int nh1 = w[1] - w[0] + 1,
171 nh2 = w[3] - w[2] + 1,
173 nv1 = w[5] - w[4] + 1,
174 nv2 = w[7] - w[6] + 1,
176 ntot = nhori + nvert,
179 if (reject == REJ_DCR && dcrnpass > 0 && dcrbox1 > 0 && dcrbox2 > 0) {
183 image->
data = cpl_image_extract(aImage->
data, w[0], w[2], w[1], w[3]);
184 image->
dq = cpl_image_extract(aImage->
dq, w[0], w[2], w[1], w[3]);
185 image->
stat = cpl_image_extract(aImage->
stat, w[0], w[2], w[1], w[3]);
188 CPL_MIN((
int)dcrbox2, nh2),
190 cpl_image_copy(aImage->
data, image->
data, w[0], w[2]);
191 cpl_image_copy(aImage->
dq, image->
dq, w[0], w[2]);
192 cpl_image_copy(aImage->
stat, image->
stat, w[0], w[2]);
196 image->
data = cpl_image_extract(aImage->
data, w[4], w[6], w[5], w[7]);
197 image->
dq = cpl_image_extract(aImage->
dq, w[4], w[6], w[5], w[7]);
198 image->
stat = cpl_image_extract(aImage->
stat, w[4], w[6], w[5], w[7]);
201 CPL_MIN((
int)dcrbox1, nv2),
203 cpl_image_copy(aImage->
data, image->
data, w[4], w[6]);
204 cpl_image_copy(aImage->
dq, image->
dq, w[4], w[6]);
205 cpl_image_copy(aImage->
stat, image->
stat, w[4], w[6]);
210 cpl_vector *hori = cpl_vector_new(nhori),
211 *vert = cpl_vector_new(nvert),
212 *tot = cpl_vector_new(ntot);
214 int i, j, ihori = 0, ivert = 0;
215 for (i = w[0] - 1; i < w[1]; i++) {
216 for (j = w[2] - 1; j < w[3]; j++) {
220 cpl_vector_set(tot, ihori + ivert, data[i + j*nx]);
221 cpl_vector_set(hori, ihori++, data[i + j*nx]);
224 for (i = w[4] - 1; i < w[5]; i++) {
225 for (j = w[6] - 1; j < w[7]; j++) {
229 cpl_vector_set(tot, ihori + ivert, data[i + j*nx]);
230 cpl_vector_set(vert, ivert++, data[i + j*nx]);
233 cpl_vector_set_size(hori, ihori);
234 cpl_vector_set_size(vert, ivert);
235 cpl_vector_set_size(tot, ihori + ivert);
239 if (reject == REJ_FIT) {
242 cpl_matrix *pos = cpl_matrix_new(1, ihori + ivert);
243 cpl_vector *val = cpl_vector_duplicate(tot);
246 0, sigma, &mse, NULL);
247 nrej = ihori + ivert - cpl_vector_get_size(val);
249 mean = cpl_polynomial_get_coeff(fit, &pows);
251 cpl_polynomial_delete(fit);
252 cpl_matrix_delete(pos);
253 cpl_vector_delete(val);
256 mean = cpl_vector_get_mean(tot);
257 stdev = cpl_vector_get_stdev(tot);
260 double hmean = cpl_vector_get_mean(hori),
261 vmean = cpl_vector_get_mean(vert),
262 hstdev = cpl_vector_get_stdev(hori),
263 vstdev = cpl_vector_get_stdev(vert);
264 cpl_msg_debug(__func__,
"quadrant %1hhu: %.3f+/-%.3f (h=%.1f+/-%.1f; " 265 "v=%.1f+/-%.1f; nrej=%d) [%s]", n, mean, stdev,
266 hmean, hstdev, vmean, vstdev, nrej, aRejection);
268 double lo = mean - stdev,
270 if (hmean < lo || hmean > hi) {
271 cpl_msg_warning(__func__,
"Horizontal overscan differs from total " 272 "(%.3f outside %.3f+/-%.3f)", hmean, mean, stdev);
274 if (vmean < lo || vmean > hi) {
275 cpl_msg_warning(__func__,
"Vertical overscan differs from total " 276 "(%.3f outside %.3f+/-%.3f)", vmean, mean, stdev);
279 char *keyword = cpl_sprintf(MUSE_HDR_OVSC_MEAN, n);
280 cpl_propertylist_append_float(aImage->
header, keyword, mean);
282 keyword = cpl_sprintf(MUSE_HDR_OVSC_STDEV, n);
283 cpl_propertylist_append_float(aImage->
header, keyword, stdev);
286 cpl_vector_delete(hori);
287 cpl_vector_delete(vert);
288 cpl_vector_delete(tot);
292 return CPL_ERROR_NONE;
312 cpl_ensure(aImage && aImage->
header && aRefImage && aRefImage->
header,
313 CPL_ERROR_NULL_INPUT, CPL_FALSE);
317 for (n = 1; n <= 4; n++) {
319 char *keywordmean = cpl_sprintf(MUSE_HDR_OVSC_MEAN, n),
320 *keywordstdev = cpl_sprintf(MUSE_HDR_OVSC_STDEV, n);
323 float refmean = cpl_propertylist_get_float(aRefImage->
header, keywordmean),
324 refstdev = cpl_propertylist_get_float(aRefImage->
header, keywordstdev),
325 hilimit = refmean + aSigma * refstdev,
326 lolimit = refmean - aSigma * refstdev;
328 float mean = cpl_propertylist_get_float(aImage->
header, keywordmean),
329 stdev = cpl_propertylist_get_float(aImage->
header, keywordstdev);
330 if (mean > hilimit || mean < lolimit) {
331 const char *fn = cpl_propertylist_get_string(aImage->
header, MUSE_HDR_TMP_FN),
332 *reffn = cpl_propertylist_get_string(aRefImage->
header, MUSE_HDR_TMP_FN);
333 cpl_msg_warning(__func__,
"Overscan of quadrant %1u of image [%s] " 334 "(%.3f+/-%.3f) differs from reference image [%s] " 335 "(%.3f+/-%.3f)!", n, fn, mean, stdev, reffn, refmean,
340 cpl_free(keywordmean);
341 cpl_free(keywordstdev);
365 cpl_ensure_code(aImage && aImage->
header && aRefImage && aRefImage->
header,
366 CPL_ERROR_NULL_INPUT);
369 for (n = 1; n <= 4; n++) {
370 char *keywordmean = cpl_sprintf(MUSE_HDR_OVSC_MEAN, n),
371 *keywordstdev = cpl_sprintf(MUSE_HDR_OVSC_STDEV, n);
372 float refmean = cpl_propertylist_get_float(aRefImage->
header, keywordmean),
373 refstdev = cpl_propertylist_get_float(aRefImage->
header, keywordstdev),
374 mean = cpl_propertylist_get_float(aImage->
header, keywordmean),
375 stdev = cpl_propertylist_get_float(aImage->
header, keywordstdev);
377 cpl_msg_debug(__func__,
"ref=%f+/-%f, image=%f+/-%f", refmean, refstdev,
384 cpl_image *data = cpl_image_extract(aImage->
data, w[0], w[2], w[1], w[3]);
385 cpl_image_add_scalar(data, refmean - mean);
387 cpl_image_copy(aImage->
data, data, w[0], w[2]);
388 cpl_image_delete(data);
391 cpl_image *stat = cpl_image_extract(aImage->
stat, w[0], w[2], w[1], w[3]);
395 cpl_msg_debug(__func__,
"variance: %f", (refstdev*refstdev + stdev*stdev) / gain);
397 cpl_image_add_scalar(stat, (refstdev*refstdev + stdev*stdev) / gain);
398 cpl_image_copy(aImage->
stat, stat, w[0], w[2]);
399 cpl_image_delete(stat);
402 cpl_propertylist_update_float(aImage->
header, keywordmean, refmean);
405 cpl_free(keywordmean);
406 cpl_free(keywordstdev);
409 return CPL_ERROR_NONE;
462 unsigned char aOrder,
double aSigma,
463 const double aFRMS,
double aFChiSq)
465 cpl_ensure_code(aImage && aImage->
data && aImage->
dq && aImage->
header,
466 CPL_ERROR_NULL_INPUT);
467 cpl_ensure_code(aFRMS > 1. && aFChiSq > 1., CPL_ERROR_ILLEGAL_INPUT);
470 CPL_ERROR_BAD_FILE_FORMAT);
473 int nx = cpl_image_get_size_x(aImage->
data),
482 cpl_ensure_code(outnx > 0 && outny > 0 && overx > 0 && overy > 0 &&
483 prex > 0 && prey > 0, CPL_ERROR_INCOMPATIBLE_INPUT);
491 for (n = 1; n <= 4; n++) {
493 cpl_ensure_code(w, CPL_ERROR_ILLEGAL_INPUT);
498 if (getenv(
"MUSE_DEBUG_QUADRANTS")) {
499 debug = atoi(getenv(
"MUSE_DEBUG_QUADRANTS"));
502 float *data = cpl_image_get_data_float(aImage->
data);
503 const int *dq = cpl_image_get_data_int_const(aImage->
dq);
504 for (n = 1; n <= 4; n++) {
507 int nvert = (w[5] - w[4] + 1) * (w[7] - w[6] + 1);
508 cpl_matrix *pos = cpl_matrix_new(1, nvert);
509 cpl_vector *val = cpl_vector_new(nvert);
511 for (i = w[4] - 1; i < w[5]; i++) {
512 for (j = w[6] - 1; j < w[7]; j++) {
516 cpl_matrix_set(pos, 0, ivert, j + 1);
517 cpl_vector_set(val, ivert++, data[i + j*nx]);
520 cpl_matrix_set_size(pos, 1, ivert);
521 cpl_vector_set_size(val, ivert);
525 double rms1, rms2, chisq1, chisq2;
527 FLT_MAX, &rms1, &chisq1),
531 cpl_msg_debug(__func__,
"IFU %2hhu Q%1hhu order 0: %f / %f, p(%" 532 CPL_SIZE_FORMAT
")=%f .. p(%"CPL_SIZE_FORMAT
")=%f",
533 ifu, n, rms1, chisq1,
534 w[6], cpl_polynomial_eval_1d(fit, w[6], NULL),
535 w[7], cpl_polynomial_eval_1d(fit, w[7], NULL));
538 unsigned char norder;
539 for (norder = 1; norder <= aOrder; norder++) {
541 norder, FLT_MAX, &rms2,
545 double frms = rms1 / rms2,
546 fchisq = chisq1 / chisq2;
548 cpl_msg_debug(__func__,
"IFU %2hhu Q%1hhu order %hhu: %f / %f, %f / %f," 549 " p(%"CPL_SIZE_FORMAT
")=%f .. p(%"CPL_SIZE_FORMAT
")=%f",
550 ifu, n, norder, rms2, chisq2, frms, fchisq,
551 w[6], cpl_polynomial_eval_1d(fit2, w[6], NULL),
552 w[7], cpl_polynomial_eval_1d(fit2, w[7], NULL));
554 if (norder == aOrder || (frms < aFRMS && fchisq < aFChiSq)) {
558 cpl_polynomial_delete(fit2);
564 unsigned char order = cpl_polynomial_get_degree(fit);
565 cpl_polynomial_delete(fit);
567 aSigma, &rms2, &chisq2);
570 cpl_msg_debug(__func__,
"IFU %2hhu Q%1hhu order %hhu (final, sigma %.3f):" 571 " %f / %f, p(%"CPL_SIZE_FORMAT
")=%f .. p(%"CPL_SIZE_FORMAT
")=%f",
572 ifu, n, order, aSigma, rms2, chisq2,
573 w[6], cpl_polynomial_eval_1d(fit, w[6], NULL),
574 w[7], cpl_polynomial_eval_1d(fit, w[7], NULL));
576 char *fntmp = cpl_strdup(cpl_propertylist_get_string(aImage->
header,
578 *dotfits = strstr(fntmp,
".fits");
582 char *fn = cpl_sprintf(
"%s_vpoly_IFU%02hhu_Q%1hhu.ascii", fntmp, ifu, n);
583 cpl_msg_debug(__func__,
"Saving extra debug data to \"%s\"", fn);
585 FILE *fp = fopen(fn,
"w");
587 fprintf(fp,
"# IFU %2hhu Q%1hhu order %hhu (final, sigma %.3f): %f / %f," 588 " p(%"CPL_SIZE_FORMAT
")=%f .. p(%"CPL_SIZE_FORMAT
")=%f\n",
589 ifu, n, order, aSigma, rms2, chisq2,
590 w[6], cpl_polynomial_eval_1d(fit, w[6], NULL),
591 w[7], cpl_polynomial_eval_1d(fit, w[7], NULL));
593 fprintf(fp,
"# p(y) =");
594 for (i = 0; i <= order; i++) {
595 cpl_size pows[] = { i };
596 fprintf(fp,
" + (%.10e) * y**%d", cpl_polynomial_get_coeff(fit, pows),
599 fprintf(fp,
"\n\n# y\tvalue\n");
601 for (i = 0; i < cpl_vector_get_size(val); i++) {
602 fprintf(fp,
"%4d\t%f\n", (
int)cpl_matrix_get(pos, 0, i),
603 cpl_vector_get(val, i));
608 cpl_matrix_delete(pos);
609 cpl_vector_delete(val);
610 char *kw = cpl_sprintf(MUSE_HDR_OVSC_PNC, n);
611 cpl_propertylist_append_int(aImage->
header, kw, order + 1);
613 for (norder = 0; norder <= order; norder++) {
614 cpl_size pows = norder;
615 kw = cpl_sprintf(MUSE_HDR_OVSC_PY, n, norder);
616 cpl_propertylist_append_double(aImage->
header, kw,
617 cpl_polynomial_get_coeff(fit, &pows));
625 i1 = outx == 1 ? 1 : prex + outnx + overx + 1,
626 i2 = outx == 1 ? prex + outnx + overx : 2 * (prex + outnx + overx),
627 j1 = outy == 1 ? 1 : prey + outny + overy + 1,
628 j2 = outy == 1 ? prey + outny + overy : 2 * (prey + outny + overy);
630 cpl_msg_debug(__func__,
"quad %1hhu fill region [%d:%d,%d:%d]", n,
635 for (j = j1 - 1; j < j2; j++) {
636 double subval = cpl_polynomial_eval_1d(fit, j + 1, NULL);
637 for (i = i1 - 1; i < i2; i++) {
638 data[i + j*nx] -= subval;
643 cpl_polynomial_delete(fit);
645 cpl_polynomial_delete(fit0);
649 return CPL_ERROR_NONE;
687 unsigned char aQuadrant,
688 unsigned int aIgnore)
690 cpl_ensure(aImage && aImage->
data && aImage->
header, CPL_ERROR_NULL_INPUT,
692 cpl_ensure(aQuadrant >= 1 && aQuadrant <= 4, CPL_ERROR_ILLEGAL_INPUT, NULL);
694 cpl_errorstate state = cpl_errorstate_get();
706 cpl_msg_debug(__func__,
"%d/%d, out %d/%d, pre %d/%d, over %d/%d, port %d/%d",
707 binx, biny, outnx, outny, prex, prey, overx, overy, portx, porty);
709 cpl_ensure(cpl_errorstate_is_equal(state) &&
710 outnx > 0 && outny > 0 && overx > 0 && overy > 0 &&
711 prex >= 0 && prey >= 0 && binx > 0 && biny > 0 &&
712 (portx == 1 || portx == kMuseOutputXRight) &&
713 (porty == 1 || porty == kMuseOutputYTop),
714 CPL_ERROR_INCOMPATIBLE_INPUT, NULL);
715 cpl_ensure(aIgnore < (
unsigned int)overx, CPL_ERROR_ILLEGAL_INPUT, NULL);
719 cpl_size *over = cpl_calloc(8,
sizeof(cpl_size));
722 over[1] = prex + outnx;
723 over[4] = prex + outnx + 1 + aIgnore;
724 over[5] = prex + outnx + overx;
726 over[0] = prex + outnx + 2*overx + 1;
727 over[1] = prex + 2*outnx + 2*overx;
728 over[4] = prex + outnx + overx + 1;
729 over[5] = prex + outnx + 2*overx - aIgnore;
732 over[2] = prey + outny + 1 + aIgnore;
733 over[3] = prey + outny + overy;
735 over[7] = prey + outny + overy;
737 over[2] = prey + outny + overy + 1;
738 over[3] = prey + outny + 2*overy - aIgnore;
739 over[6] = prey + outny + overy + 1;
740 over[7] = prey + 2*outny + 2*overy;
743 if (getenv(
"MUSE_DEBUG_QUADRANTS") &&
744 atoi(getenv(
"MUSE_DEBUG_QUADRANTS")) > 0) {
745 cpl_msg_debug(__func__,
"Quadrant %hhu overscan regions: " 746 "[%"CPL_SIZE_FORMAT
":%"CPL_SIZE_FORMAT
747 ",%"CPL_SIZE_FORMAT
":%"CPL_SIZE_FORMAT
"] and " 748 "[%"CPL_SIZE_FORMAT
":%"CPL_SIZE_FORMAT
749 ",%"CPL_SIZE_FORMAT
":%"CPL_SIZE_FORMAT
"]", aQuadrant,
750 over[0], over[1], over[2], over[3],
751 over[4], over[5], over[6], over[7]);
775 cpl_ensure(aImage && aImage->
data && aImage->
header, CPL_ERROR_NULL_INPUT,
777 cpl_boolean debug = CPL_FALSE;
778 if (getenv(
"MUSE_DEBUG_QUADRANTS")) {
779 debug = atoi(getenv(
"MUSE_DEBUG_QUADRANTS")) > 0;
783 int xout = 0, yout = 0;
785 int nx[4], ny[4], portx[4], porty[4];
792 for (n = 1; n <= 4; n++) {
798 if (nx[n-1] < 0 || ny[n-1] < 0 || portx[n-1] < 0 || porty[n-1] < 0) {
799 cpl_msg_error(__func__,
"FITS headers necessary for trimming are missing " 800 "from quadrant %1d: NX=%d, NY=%d at OUT X=%d/OUT Y=%d", n,
801 nx[n-1], ny[n-1], portx[n-1], porty[n-1]);
802 cpl_error_set(__func__, CPL_ERROR_DATA_NOT_FOUND);
806 if ((portx[n-1] != 1 && portx[n-1] != kMuseOutputXRight) ||
807 (porty[n-1] != 1 && porty[n-1] != kMuseOutputYTop)) {
808 cpl_msg_error(__func__,
"FITS headers necessary for trimming are " 809 "unsupported for quadrant %1d: OUT X=%d/OUT Y=%d", n,
810 portx[n-1], porty[n-1]);
811 cpl_error_set(__func__, CPL_ERROR_INCOMPATIBLE_INPUT);
816 if (portx[n-1] == 1) {
820 if (porty[n-1] == 1) {
826 int x_size = cpl_image_get_size_x(aImage->
data),
827 y_size = cpl_image_get_size_y(aImage->
data);
828 if (xout > x_size || yout > y_size) {
829 cpl_msg_error(__func__,
"output size (%dx%d) is larger than input size " 830 "(%dx%d): wrong binning?!", xout, yout, x_size, y_size);
831 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT);
835 cpl_msg_debug(__func__,
"output size %dx%d", xout, yout);
837 cpl_ensure(xout > 0 && yout > 0, CPL_ERROR_ILLEGAL_INPUT, NULL);
840 for (n = 1; n < 4; n++) {
841 if (nx[n] != nx[0] || ny[n] != ny[0]) {
842 cpl_msg_error(__func__,
"Data section of quadrant %d is different from " 844 cpl_error_set(__func__, CPL_ERROR_INCOMPATIBLE_INPUT);
851 trimmed->
data = cpl_image_new(xout, yout, CPL_TYPE_FLOAT);
854 trimmed->
dq = cpl_image_new(xout, yout, CPL_TYPE_INT);
857 trimmed->
stat = cpl_image_new(xout, yout, CPL_TYPE_FLOAT);
861 trimmed->
header = cpl_propertylist_duplicate(aImage->
header);
862 cpl_propertylist_erase_regexp(trimmed->
header,
863 "^NAXIS|^DATASUM$|^DATAMIN$|^DATAMAX$|^DATAMD5$|" 864 "^ESO DET OUT.*PRSC|^ESO DET OUT.*OVSC",
869 for (n = 1; n <= 4; n++) {
875 int x1 = 0, x2 = 0, y1 = 0, y2= 0,
876 xtarget = 0, ytarget = 0;
879 if (portx[n-1] == 1) {
881 cpl_msg_debug(__func__,
"left quadrant (OUT%d)", n);
884 x2 = x_prescan + nx[0];
886 }
else if (portx[n-1] == kMuseOutputXRight) {
888 cpl_msg_debug(__func__,
"right quadrant (OUT%d)", n);
890 x1 = x_size - x_prescan - nx[0] + 1;
891 x2 = x_size - x_prescan;
896 if (porty[n-1] == 1) {
898 cpl_msg_debug(__func__,
"bottom quadrant (OUT%d)", n);
901 y2 = y_prescan + ny[0];
903 }
else if (porty[n-1] == kMuseOutputYTop) {
905 cpl_msg_debug(__func__,
"top quadrant (OUT%d)", n);
907 y1 = y_size - y_prescan - ny[0] + 1;
908 y2 = y_size - y_prescan;
913 cpl_image *image = cpl_image_extract(aImage->
data, x1, y1, x2, y2);
915 cpl_msg_debug(__func__,
"port at %d,%d: %d,%d - %d,%d, extracted: " 916 "%"CPL_SIZE_FORMAT
"x%"CPL_SIZE_FORMAT
" -> %d,%d",
917 portx[n-1], porty[n-1], x1,y1, x2,y2,
918 cpl_image_get_size_x(image), cpl_image_get_size_y(image),
921 cpl_image_copy(trimmed->
data, image, xtarget, ytarget);
922 cpl_image_delete(image);
924 image = cpl_image_extract(aImage->
dq, x1, y1, x2, y2);
925 cpl_image_copy(trimmed->
dq, image, xtarget, ytarget);
926 cpl_image_delete(image);
929 image = cpl_image_extract(aImage->
stat, x1, y1, x2, y2);
930 cpl_image_copy(trimmed->
stat, image, xtarget, ytarget);
931 cpl_image_delete(image);
960 cpl_ensure_code(aX || aY, CPL_ERROR_NULL_INPUT);
964 int xraw = *aX + kMusePreOverscanSize;
965 if (*aX > kMuseOutputXRight/2) {
966 xraw += 2 * kMusePreOverscanSize;
971 int yraw = *aY + kMusePreOverscanSize;
972 if (*aY > kMuseOutputYTop/2) {
973 yraw += 2 * kMusePreOverscanSize;
977 return CPL_ERROR_NONE;
980 return CPL_ERROR_NONE;
1008 cpl_ensure(aHeader, CPL_ERROR_NULL_INPUT, CPL_FALSE);
1010 int portx[4], porty[4], nx[4], ny[4],
1011 prex[4], prey[4], overx[4], overy[4];
1017 for (n = 1; n <= 4; n++) {
1027 cpl_msg_debug(__func__,
"quadrant %1hhu: port=%d,%d, n=%d,%d, pre=%d,%d, over=%d,%d",
1028 n+1, portx[n-1], porty[n-1], nx[n-1], ny[n-1],
1029 prex[n-1], prey[n-1], overx[n-1], overy[n-1]);
1033 cpl_ensure(portx[0] < portx[1], CPL_ERROR_ILLEGAL_INPUT, CPL_FALSE);
1035 if (!cpl_propertylist_has(aHeader,
"INMMODEL")) {
1036 cpl_ensure(portx[0] < portx[2], CPL_ERROR_ILLEGAL_INPUT, CPL_FALSE);
1037 cpl_ensure(portx[0] == portx[3], CPL_ERROR_ILLEGAL_INPUT, CPL_FALSE);
1039 cpl_ensure(porty[0] == porty[1], CPL_ERROR_ILLEGAL_INPUT, CPL_FALSE);
1040 cpl_ensure(porty[0] < porty[2], CPL_ERROR_ILLEGAL_INPUT, CPL_FALSE);
1041 cpl_ensure(porty[0] < porty[3], CPL_ERROR_ILLEGAL_INPUT, CPL_FALSE);
1043 for (n = 1; n < 4; n++) {
1044 cpl_ensure(nx[0] == nx[n] && ny[0] == ny[n], CPL_ERROR_INCOMPATIBLE_INPUT,
1046 cpl_ensure(prex[0] == prex[n] && prey[0] == prey[n],
1047 CPL_ERROR_INCOMPATIBLE_INPUT, CPL_FALSE);
1048 cpl_ensure(overx[0] == overx[n] && overy[0] == overy[n],
1049 CPL_ERROR_INCOMPATIBLE_INPUT, CPL_FALSE);
1076 cpl_ensure(aImage && aImage->
data && aImage->
header, CPL_ERROR_NULL_INPUT,
1078 cpl_ensure(aQuadrant >= 1 && aQuadrant <= 4, CPL_ERROR_ILLEGAL_INPUT, NULL);
1080 cpl_boolean debug = CPL_FALSE;
1081 if (getenv(
"MUSE_DEBUG_QUADRANTS")) {
1082 debug = atoi(getenv(
"MUSE_DEBUG_QUADRANTS")) > 0;
1089 nx[0] = cpl_image_get_size_x(aImage->
data);
1090 ny[0] = cpl_image_get_size_y(aImage->
data);
1092 for (n = 1; n <= 4; n++) {
1097 cpl_size *window = (cpl_size *)cpl_calloc(
sizeof(cpl_size), 4);
1098 switch (aQuadrant) {
1106 window[0] = nx[1] + 1;
1107 window[1] = nx[1] + nx[2];
1112 window[0] = nx[3] + 1;
1113 window[1] = nx[3] + nx[4];
1114 window[2] = ny[2] + 1;
1115 window[3] = ny[2] + ny[4];
1120 window[2] = ny[1] + 1;
1121 window[3] = ny[1] + ny[3];
1127 if ((nx[1] + nx[2]) == nx[0] && (ny[1] + ny[3]) == ny[0]) {
1129 cpl_msg_debug(__func__,
"quadrant %d, trimmed: %"CPL_SIZE_FORMAT
",%" 1130 CPL_SIZE_FORMAT
" -> %"CPL_SIZE_FORMAT
",%"CPL_SIZE_FORMAT
"",
1131 aQuadrant, window[0], window[2], window[1], window[3]);
1138 int overx[5], overy[5],
1140 for (n = 1; n <= 4; n++) {
1147 int addx = 0, addy = 0;
1148 switch (aQuadrant) {
1154 addx = prex[1] + overx[1] + overx[2];
1158 addx = prex[3] + overx[3] + overx[4];
1159 addy = prey[1] + overy[1] + overy[3];
1163 addy = prey[2] + overy[2] + overy[4];
1172 cpl_msg_debug(__func__,
"quadrant %d, not trimmed: %"CPL_SIZE_FORMAT
",%" 1173 CPL_SIZE_FORMAT
" -> %"CPL_SIZE_FORMAT
",%"CPL_SIZE_FORMAT,
1174 aQuadrant, window[0], window[2], window[1], window[3]);
cpl_error_code muse_quadrants_overscan_correct(muse_image *aImage, muse_image *aRefImage)
Adapt bias level to reference image using overscan statistics.
int muse_pfits_get_out_overscan_y(const cpl_propertylist *aHeaders, unsigned char aQuadrant)
find out the vertical size of the overscan region of one quadrant
int muse_pfits_get_out_output_y(const cpl_propertylist *aHeaders, unsigned char aQuadrant)
find out the vertical location of the output port of one quadrant
void muse_image_delete(muse_image *aImage)
Deallocate memory associated to a muse_image object.
cpl_size * muse_quadrants_get_window(const muse_image *aImage, unsigned char aQuadrant)
Determine the data window of a given quadrant on the CCD.
unsigned char muse_utils_get_ifu(const cpl_propertylist *aHeaders)
Find out the IFU/channel from which this header originated.
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
int muse_pfits_get_out_overscan_x(const cpl_propertylist *aHeaders, unsigned char aQuadrant)
find out the horizontal size of the overscan region of one quadrant
int muse_cosmics_dcr(muse_image *aImage, unsigned int aXBox, unsigned int aYBox, unsigned int aPasses, float aThres)
Quickly mark cosmic rays in an image using the DCR algorithm.
int muse_pfits_get_out_output_x(const cpl_propertylist *aHeaders, unsigned char aQuadrant)
find out the horizontal location of the output port of one quadrant
cpl_image * stat
the statistics extension
Structure definition of MUSE three extension FITS file.
cpl_error_code muse_quadrants_overscan_polyfit_vertical(muse_image *aImage, unsigned aIgnore, unsigned char aOrder, double aSigma, const double aFRMS, double aFChiSq)
Correct quadrants by polynomial representation of vertical overscan.
cpl_propertylist * header
the FITS header
cpl_image * dq
the data quality extension
cpl_boolean muse_quadrants_verify(cpl_propertylist *aHeader)
Verify that quadrant locations and sizes meet the expectations.
int muse_pfits_get_biny(const cpl_propertylist *aHeaders)
find out the binning factor in y direction
cpl_boolean muse_quadrants_overscan_check(muse_image *aImage, muse_image *aRefImage, double aSigma)
Compare overscan statistics of all quadrants to those of reference image.
int muse_pfits_get_out_prescan_y(const cpl_propertylist *aHeaders, unsigned char aQuadrant)
find out the vertical size of the prescan region of one quadrant
int muse_pfits_get_out_nx(const cpl_propertylist *aHeaders, unsigned char aQuadrant)
find out the horizontal size of the data section of one quadrant
cpl_polynomial * muse_utils_iterate_fit_polynomial(cpl_matrix *aPos, cpl_vector *aVal, cpl_vector *aErr, cpl_table *aExtra, const unsigned int aOrder, const double aRSigma, double *aMSE, double *aChiSq)
Iterate a polynomial fit.
cpl_error_code muse_quadrants_overscan_stats(muse_image *aImage, const char *aRejection, unsigned int aIgnore)
Compute overscan statistics of all quadrants and save in FITS header.
int muse_pfits_get_binx(const cpl_propertylist *aHeaders)
find out the binning factor in x direction
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.
cpl_error_code muse_quadrants_coords_to_raw(cpl_propertylist *aHeader, int *aX, int *aY)
Convert coordinates of a trimmed image to raw-image coordinates.
int muse_pfits_get_out_prescan_x(const cpl_propertylist *aHeaders, unsigned char aQuadrant)
find out the horizontal size of the prescan region of one quadrant
muse_image * muse_image_new(void)
Allocate memory for a new muse_image object.
int muse_pfits_get_out_ny(const cpl_propertylist *aHeaders, unsigned char aQuadrant)
find out the vertical size of the data section of one quadrant
muse_image * muse_quadrants_trim_image(muse_image *aImage)
Trim the input image of pre- and over-scan regions of all quadrants.
cpl_size * muse_quadrants_overscan_get_window(const muse_image *aImage, unsigned char aQuadrant, unsigned int aIgnore)
Determine the overscan windows of a given quadrant on the CCD.