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 <cpl.h>
00030 #include <string.h>
00031
00032 #include "muse_quadrants.h"
00033 #include "muse_instrument.h"
00034
00035 #include "muse_artifacts.h"
00036 #include "muse_dfs.h"
00037 #include "muse_pfits.h"
00038 #include "muse_utils.h"
00039
00040
00047
00048
00051
00077
00078 cpl_error_code
00079 muse_quadrants_overscan_stats(muse_image *aImage, const char *aRejection,
00080 unsigned int aIgnore)
00081 {
00082 cpl_ensure_code(aImage && aImage->data && aImage->header, CPL_ERROR_NULL_INPUT);
00083
00084 cpl_ensure_code(muse_quadrants_verify(aImage->header),
00085 CPL_ERROR_BAD_FILE_FORMAT);
00086
00087
00088
00089 unsigned char n;
00090 for (n = 1; n <= 4; n++) {
00091 cpl_size *w = muse_quadrants_overscan_get_window(aImage, n, aIgnore);
00092 cpl_ensure_code(w, CPL_ERROR_ILLEGAL_INPUT);
00093 cpl_free(w);
00094 }
00095 int nx = cpl_image_get_size_x(aImage->data);
00096
00097 enum { REJ_NONE, REJ_DCR, REJ_FIT } reject = REJ_NONE;
00098 if (aRejection) {
00099 if (!strncmp(aRejection, "dcr", 3)) {
00100 reject = REJ_DCR;
00101 } else if (!strncmp(aRejection, "fit", 3)) {
00102 reject = REJ_FIT;
00103 } else if (strncmp(aRejection, "none", 5)) {
00104 return cpl_error_set_message(__func__, CPL_ERROR_ILLEGAL_INPUT,
00105 "Unknown rejection type \"%s\"", aRejection);
00106 }
00107 }
00108
00109 unsigned int binx = muse_pfits_get_binx(aImage->header),
00110 biny = muse_pfits_get_biny(aImage->header),
00111 outnx = muse_pfits_get_out_nx(aImage->header, 1) / binx,
00112 outny = muse_pfits_get_out_ny(aImage->header, 1) / biny,
00113 overx = muse_pfits_get_out_overscan_x(aImage->header, 1) / binx,
00114 overy = muse_pfits_get_out_overscan_y(aImage->header, 1) / biny;
00115 unsigned long dcrbox1 = 128, dcrbox2 = 32, dcrnpass = 3;
00116 float dcrthres = 2.5,
00117 sigma = 5.0;
00118 if (reject == REJ_DCR) {
00119 char *rest = strchr(aRejection, ':');
00120 if (strlen(aRejection) > 4 && rest++) {
00121 dcrbox1 = strtoul(rest, &rest, 10);
00122 if (strlen(rest++) > 0) {
00123 dcrbox2 = strtoul(rest, &rest, 10);
00124 if (strlen(rest++) > 0) {
00125 dcrnpass = strtoul(rest, &rest, 10);
00126 if (strlen(rest++) > 0) {
00127 dcrthres = strtof(rest, NULL);
00128 }
00129 }
00130 }
00131 }
00132
00133 if (dcrbox2 > overx || dcrbox2 > overy ||
00134 dcrbox1 > outnx || dcrbox1 > outny ||
00135 dcrnpass <= 0 || dcrthres <= 0.) {
00136 cpl_msg_warning(__func__, "Detected illegal DCR parameters for overscan "
00137 "statistics (%lux%lu, %lu, %f; overscan: %ux%u, output: "
00138 "%ux%u), not rejecting anything!", dcrbox1, dcrbox2,
00139 dcrnpass, dcrthres, overx, overy, outnx, outny);
00140 reject = REJ_NONE;
00141 } else {
00142 cpl_msg_debug(__func__, "Using DCR cosmic ray rejection for overscan "
00143 "statistics (%lux%lu, %lu, %f)", dcrbox1, dcrbox2, dcrnpass,
00144 dcrthres);
00145 }
00146 } else if (reject == REJ_FIT) {
00147 char *rest = strchr(aRejection, ':');
00148 if (strlen(aRejection) > 4 && rest++) {
00149 sigma = strtof(rest, NULL);
00150 }
00151
00152 if (sigma <= 0.) {
00153 cpl_msg_warning(__func__, "Detected illegal fit sigma for overscan "
00154 "statistics (%f; overscan: %ux%u, output: %ux%u) not "
00155 "rejecting anything!", sigma, overx, overy, outnx, outny);
00156 reject = REJ_NONE;
00157 } else {
00158 cpl_msg_debug(__func__, "Using constant fit for overscan statistics (0, "
00159 "%f)", sigma);
00160 }
00161 }
00162
00163 const float *data = cpl_image_get_data_float_const(aImage->data);
00164 const int *dq = cpl_image_get_data_int_const(aImage->dq);
00165
00166
00167 for (n = 1; n <= 4; n++) {
00168
00169 cpl_size *w = muse_quadrants_overscan_get_window(aImage, n, aIgnore);
00170 int nh1 = w[1] - w[0] + 1,
00171 nh2 = w[3] - w[2] + 1,
00172 nhori = nh1 * nh2,
00173 nv1 = w[5] - w[4] + 1,
00174 nv2 = w[7] - w[6] + 1,
00175 nvert = nv1 * nv2,
00176 ntot = nhori + nvert,
00177 nhcr = 0, nvcr = 0;
00178
00179 if (reject == REJ_DCR && dcrnpass > 0 && dcrbox1 > 0 && dcrbox2 > 0) {
00180
00181
00182 muse_image *image = muse_image_new();
00183 image->data = cpl_image_extract(aImage->data, w[0], w[2], w[1], w[3]);
00184 image->dq = cpl_image_extract(aImage->dq, w[0], w[2], w[1], w[3]);
00185 image->stat = cpl_image_extract(aImage->stat, w[0], w[2], w[1], w[3]);
00186
00187 nhcr = muse_cosmics_dcr(image, CPL_MIN((int)dcrbox1, nh1),
00188 CPL_MIN((int)dcrbox2, nh2),
00189 dcrnpass, dcrthres);
00190 cpl_image_copy(aImage->data, image->data, w[0], w[2]);
00191 cpl_image_copy(aImage->dq, image->dq, w[0], w[2]);
00192 cpl_image_copy(aImage->stat, image->stat, w[0], w[2]);
00193 muse_image_delete(image);
00194
00195 image = muse_image_new();
00196 image->data = cpl_image_extract(aImage->data, w[4], w[6], w[5], w[7]);
00197 image->dq = cpl_image_extract(aImage->dq, w[4], w[6], w[5], w[7]);
00198 image->stat = cpl_image_extract(aImage->stat, w[4], w[6], w[5], w[7]);
00199
00200 nvcr = muse_cosmics_dcr(image, CPL_MIN((int)dcrbox2, nv1),
00201 CPL_MIN((int)dcrbox1, nv2),
00202 dcrnpass, dcrthres);
00203 cpl_image_copy(aImage->data, image->data, w[4], w[6]);
00204 cpl_image_copy(aImage->dq, image->dq, w[4], w[6]);
00205 cpl_image_copy(aImage->stat, image->stat, w[4], w[6]);
00206 muse_image_delete(image);
00207 }
00208
00209
00210 cpl_vector *hori = cpl_vector_new(nhori),
00211 *vert = cpl_vector_new(nvert),
00212 *tot = cpl_vector_new(ntot);
00213
00214 int i, j, ihori = 0, ivert = 0;
00215 for (i = w[0] - 1; i < w[1]; i++) {
00216 for (j = w[2] - 1; j < w[3]; j++) {
00217 if (dq[i + j*nx]) {
00218 continue;
00219 }
00220 cpl_vector_set(tot, ihori + ivert, data[i + j*nx]);
00221 cpl_vector_set(hori, ihori++, data[i + j*nx]);
00222 }
00223 }
00224 for (i = w[4] - 1; i < w[5]; i++) {
00225 for (j = w[6] - 1; j < w[7]; j++) {
00226 if (dq[i + j*nx]) {
00227 continue;
00228 }
00229 cpl_vector_set(tot, ihori + ivert, data[i + j*nx]);
00230 cpl_vector_set(vert, ivert++, data[i + j*nx]);
00231 }
00232 }
00233 cpl_vector_set_size(hori, ihori);
00234 cpl_vector_set_size(vert, ivert);
00235 cpl_vector_set_size(tot, ihori + ivert);
00236
00237 int nrej = 0;
00238 double mean, stdev;
00239 if (reject == REJ_FIT) {
00240
00241
00242 cpl_matrix *pos = cpl_matrix_new(1, ihori + ivert);
00243 cpl_vector *val = cpl_vector_duplicate(tot);
00244 double mse;
00245 cpl_polynomial *fit = muse_utils_iterate_fit_polynomial(pos, val, NULL, NULL,
00246 0, sigma, &mse, NULL);
00247 nrej = ihori + ivert - cpl_vector_get_size(val);
00248 cpl_size pows = 0;
00249 mean = cpl_polynomial_get_coeff(fit, &pows);
00250 stdev = sqrt(mse);
00251 cpl_polynomial_delete(fit);
00252 cpl_matrix_delete(pos);
00253 cpl_vector_delete(val);
00254 } else {
00255 nrej = nhcr + nvcr;
00256 mean = cpl_vector_get_mean(tot);
00257 stdev = cpl_vector_get_stdev(tot);
00258 }
00259
00260 double hmean = cpl_vector_get_mean(hori),
00261 vmean = cpl_vector_get_mean(vert),
00262 hstdev = cpl_vector_get_stdev(hori),
00263 vstdev = cpl_vector_get_stdev(vert);
00264 cpl_msg_debug(__func__, "quadrant %1hhu: %.3f+/-%.3f (h=%.1f+/-%.1f; "
00265 "v=%.1f+/-%.1f; nrej=%d) [%s]", n, mean, stdev,
00266 hmean, hstdev, vmean, vstdev, nrej, aRejection);
00267
00268 double lo = mean - stdev,
00269 hi = mean + stdev;
00270 if (hmean < lo || hmean > hi) {
00271 cpl_msg_warning(__func__, "Horizontal overscan differs from total "
00272 "(%.3f outside %.3f+/-%.3f)", hmean, mean, stdev);
00273 }
00274 if (vmean < lo || vmean > hi) {
00275 cpl_msg_warning(__func__, "Vertical overscan differs from total "
00276 "(%.3f outside %.3f+/-%.3f)", vmean, mean, stdev);
00277 }
00278
00279 char *keyword = cpl_sprintf(MUSE_HDR_OVSC_MEAN, n);
00280 cpl_propertylist_append_float(aImage->header, keyword, mean);
00281 cpl_free(keyword);
00282 keyword = cpl_sprintf(MUSE_HDR_OVSC_STDEV, n);
00283 cpl_propertylist_append_float(aImage->header, keyword, stdev);
00284 cpl_free(keyword);
00285
00286 cpl_vector_delete(hori);
00287 cpl_vector_delete(vert);
00288 cpl_vector_delete(tot);
00289 cpl_free(w);
00290 }
00291
00292 return CPL_ERROR_NONE;
00293 }
00294
00295
00307
00308 cpl_boolean
00309 muse_quadrants_overscan_check(muse_image *aImage, muse_image *aRefImage,
00310 double aSigma)
00311 {
00312 cpl_ensure(aImage && aImage->header && aRefImage && aRefImage->header,
00313 CPL_ERROR_NULL_INPUT, CPL_FALSE);
00314
00315 int rc = CPL_TRUE;
00316 unsigned char n;
00317 for (n = 1; n <= 4; n++) {
00318
00319 char *keywordmean = cpl_sprintf(MUSE_HDR_OVSC_MEAN, n),
00320 *keywordstdev = cpl_sprintf(MUSE_HDR_OVSC_STDEV, n);
00321
00322
00323 float refmean = cpl_propertylist_get_float(aRefImage->header, keywordmean),
00324 refstdev = cpl_propertylist_get_float(aRefImage->header, keywordstdev),
00325 hilimit = refmean + aSigma * refstdev,
00326 lolimit = refmean - aSigma * refstdev;
00327
00328 float mean = cpl_propertylist_get_float(aImage->header, keywordmean),
00329 stdev = cpl_propertylist_get_float(aImage->header, keywordstdev);
00330 if (mean > hilimit || mean < lolimit) {
00331 const char *fn = cpl_propertylist_get_string(aImage->header, MUSE_HDR_TMP_FN),
00332 *reffn = cpl_propertylist_get_string(aRefImage->header, MUSE_HDR_TMP_FN);
00333 cpl_msg_warning(__func__, "Overscan of quadrant %1u of image [%s] "
00334 "(%.3f+/-%.3f) differs from reference image [%s] "
00335 "(%.3f+/-%.3f)!", n, fn, mean, stdev, reffn, refmean,
00336 refstdev);
00337 rc = CPL_FALSE;
00338 }
00339
00340 cpl_free(keywordmean);
00341 cpl_free(keywordstdev);
00342 }
00343
00344 return rc;
00345 }
00346
00347
00361
00362 cpl_error_code
00363 muse_quadrants_overscan_correct(muse_image *aImage, muse_image *aRefImage)
00364 {
00365 cpl_ensure_code(aImage && aImage->header && aRefImage && aRefImage->header,
00366 CPL_ERROR_NULL_INPUT);
00367
00368 unsigned char n;
00369 for (n = 1; n <= 4; n++) {
00370 char *keywordmean = cpl_sprintf(MUSE_HDR_OVSC_MEAN, n),
00371 *keywordstdev = cpl_sprintf(MUSE_HDR_OVSC_STDEV, n);
00372 float refmean = cpl_propertylist_get_float(aRefImage->header, keywordmean),
00373 refstdev = cpl_propertylist_get_float(aRefImage->header, keywordstdev),
00374 mean = cpl_propertylist_get_float(aImage->header, keywordmean),
00375 stdev = cpl_propertylist_get_float(aImage->header, keywordstdev);
00376 #if 0
00377 cpl_msg_debug(__func__, "ref=%f+/-%f, image=%f+/-%f", refmean, refstdev,
00378 mean, stdev);
00379 #endif
00380 cpl_size *w = muse_quadrants_get_window(aImage, n);
00381
00382
00383
00384 cpl_image *data = cpl_image_extract(aImage->data, w[0], w[2], w[1], w[3]);
00385 cpl_image_add_scalar(data, refmean - mean);
00386
00387 cpl_image_copy(aImage->data, data, w[0], w[2]);
00388 cpl_image_delete(data);
00389
00390
00391 cpl_image *stat = cpl_image_extract(aImage->stat, w[0], w[2], w[1], w[3]);
00392
00393 double gain = muse_pfits_get_gain(aImage->header, n);
00394 #if 0
00395 cpl_msg_debug(__func__, "variance: %f", (refstdev*refstdev + stdev*stdev) / gain);
00396 #endif
00397 cpl_image_add_scalar(stat, (refstdev*refstdev + stdev*stdev) / gain);
00398 cpl_image_copy(aImage->stat, stat, w[0], w[2]);
00399 cpl_image_delete(stat);
00400
00401
00402 cpl_propertylist_update_float(aImage->header, keywordmean, refmean);
00403
00404 cpl_free(w);
00405 cpl_free(keywordmean);
00406 cpl_free(keywordstdev);
00407 }
00408
00409 return CPL_ERROR_NONE;
00410 }
00411
00412
00459
00460 cpl_error_code
00461 muse_quadrants_overscan_polyfit_vertical(muse_image *aImage, unsigned aIgnore,
00462 unsigned char aOrder, double aSigma,
00463 const double aFRMS, double aFChiSq)
00464 {
00465 cpl_ensure_code(aImage && aImage->data && aImage->dq && aImage->header,
00466 CPL_ERROR_NULL_INPUT);
00467 cpl_ensure_code(aFRMS > 1. && aFChiSq > 1., CPL_ERROR_ILLEGAL_INPUT);
00468
00469 cpl_ensure_code(muse_quadrants_verify(aImage->header),
00470 CPL_ERROR_BAD_FILE_FORMAT);
00471
00472
00473 int nx = cpl_image_get_size_x(aImage->data),
00474 binx = muse_pfits_get_binx(aImage->header),
00475 biny = muse_pfits_get_biny(aImage->header),
00476 outnx = muse_pfits_get_out_nx(aImage->header, 1) / binx,
00477 outny = muse_pfits_get_out_ny(aImage->header, 1) / biny,
00478 prex = muse_pfits_get_out_prescan_x(aImage->header, 1) / binx,
00479 prey = muse_pfits_get_out_prescan_y(aImage->header, 1) / biny,
00480 overx = muse_pfits_get_out_overscan_x(aImage->header, 1) / binx,
00481 overy = muse_pfits_get_out_overscan_y(aImage->header, 1) / biny;
00482 cpl_ensure_code(outnx > 0 && outny > 0 && overx > 0 && overy > 0 &&
00483 prex > 0 && prey > 0, CPL_ERROR_INCOMPATIBLE_INPUT);
00484 unsigned char ifu = muse_utils_get_ifu(aImage->header);
00485
00486
00487
00488
00489
00490 unsigned char n;
00491 for (n = 1; n <= 4; n++) {
00492 cpl_size *w = muse_quadrants_overscan_get_window(aImage, n, aIgnore);
00493 cpl_ensure_code(w, CPL_ERROR_ILLEGAL_INPUT);
00494 cpl_free(w);
00495 }
00496
00497 int debug = 0;
00498 if (getenv("MUSE_DEBUG_QUADRANTS")) {
00499 debug = atoi(getenv("MUSE_DEBUG_QUADRANTS"));
00500 }
00501
00502 float *data = cpl_image_get_data_float(aImage->data);
00503 const int *dq = cpl_image_get_data_int_const(aImage->dq);
00504 for (n = 1; n <= 4; n++) {
00505 cpl_size *w = muse_quadrants_overscan_get_window(aImage, n, aIgnore);
00506
00507 int nvert = (w[5] - w[4] + 1) * (w[7] - w[6] + 1);
00508 cpl_matrix *pos = cpl_matrix_new(1, nvert);
00509 cpl_vector *val = cpl_vector_new(nvert);
00510 int i, j, ivert = 0;
00511 for (i = w[4] - 1; i < w[5]; i++) {
00512 for (j = w[6] - 1; j < w[7]; j++) {
00513 if (dq[i + j*nx]) {
00514 continue;
00515 }
00516 cpl_matrix_set(pos, 0, ivert, j + 1);
00517 cpl_vector_set(val, ivert++, data[i + j*nx]);
00518 }
00519 }
00520 cpl_matrix_set_size(pos, 1, ivert);
00521 cpl_vector_set_size(val, ivert);
00522
00523
00524
00525 double rms1, rms2, chisq1, chisq2;
00526 cpl_polynomial *fit0 = muse_utils_iterate_fit_polynomial(pos, val, NULL, NULL, 0,
00527 FLT_MAX, &rms1, &chisq1),
00528 *fit = fit0;
00529 rms1 = sqrt(rms1);
00530 if (debug) {
00531 cpl_msg_debug(__func__, "IFU %2hhu Q%1hhu order 0: %f / %f, p(%"
00532 CPL_SIZE_FORMAT")=%f .. p(%"CPL_SIZE_FORMAT")=%f",
00533 ifu, n, rms1, chisq1,
00534 w[6], cpl_polynomial_eval_1d(fit, w[6], NULL),
00535 w[7], cpl_polynomial_eval_1d(fit, w[7], NULL));
00536 }
00537
00538 unsigned char norder;
00539 for (norder = 1; norder <= aOrder; norder++) {
00540 cpl_polynomial *fit2 = muse_utils_iterate_fit_polynomial(pos, val, NULL, NULL,
00541 norder, FLT_MAX, &rms2,
00542 &chisq2);
00543 rms2 = sqrt(rms2);
00544
00545 double frms = rms1 / rms2,
00546 fchisq = chisq1 / chisq2;
00547 if (debug) {
00548 cpl_msg_debug(__func__, "IFU %2hhu Q%1hhu order %hhu: %f / %f, %f / %f,"
00549 " p(%"CPL_SIZE_FORMAT")=%f .. p(%"CPL_SIZE_FORMAT")=%f",
00550 ifu, n, norder, rms2, chisq2, frms, fchisq,
00551 w[6], cpl_polynomial_eval_1d(fit2, w[6], NULL),
00552 w[7], cpl_polynomial_eval_1d(fit2, w[7], NULL));
00553 }
00554 if (norder == aOrder || (frms < aFRMS && fchisq < aFChiSq)) {
00555 fit = fit2;
00556 break;
00557 }
00558 cpl_polynomial_delete(fit2);
00559 rms1 = rms2;
00560 chisq1 = chisq2;
00561 }
00562
00563
00564 unsigned char order = cpl_polynomial_get_degree(fit);
00565 cpl_polynomial_delete(fit);
00566 fit = muse_utils_iterate_fit_polynomial(pos, val, NULL, NULL, order,
00567 aSigma, &rms2, &chisq2);
00568 rms2 = sqrt(rms2);
00569 if (debug) {
00570 cpl_msg_debug(__func__, "IFU %2hhu Q%1hhu order %hhu (final, sigma %.3f):"
00571 " %f / %f, p(%"CPL_SIZE_FORMAT")=%f .. p(%"CPL_SIZE_FORMAT")=%f",
00572 ifu, n, order, aSigma, rms2, chisq2,
00573 w[6], cpl_polynomial_eval_1d(fit, w[6], NULL),
00574 w[7], cpl_polynomial_eval_1d(fit, w[7], NULL));
00575 if (debug > 1) {
00576 char *fntmp = cpl_strdup(cpl_propertylist_get_string(aImage->header,
00577 MUSE_HDR_TMP_FN)),
00578 *dotfits = strstr(fntmp, ".fits");
00579 if (dotfits) {
00580 *dotfits = '\0';
00581 }
00582 char *fn = cpl_sprintf("%s_vpoly_IFU%02hhu_Q%1hhu.ascii", fntmp, ifu, n);
00583 cpl_msg_debug(__func__, "Saving extra debug data to \"%s\"", fn);
00584 cpl_free(fntmp);
00585 FILE *fp = fopen(fn, "w");
00586 cpl_free(fn);
00587 fprintf(fp, "# IFU %2hhu Q%1hhu order %hhu (final, sigma %.3f): %f / %f,"
00588 " p(%"CPL_SIZE_FORMAT")=%f .. p(%"CPL_SIZE_FORMAT")=%f\n",
00589 ifu, n, order, aSigma, rms2, chisq2,
00590 w[6], cpl_polynomial_eval_1d(fit, w[6], NULL),
00591 w[7], cpl_polynomial_eval_1d(fit, w[7], NULL));
00592
00593 fprintf(fp, "# p(y) =");
00594 for (i = 0; i <= order; i++) {
00595 cpl_size pows[] = { i };
00596 fprintf(fp, " + (%.10e) * y**%d", cpl_polynomial_get_coeff(fit, pows),
00597 i);
00598 }
00599 fprintf(fp, "\n\n# y\tvalue\n");
00600
00601 for (i = 0; i < cpl_vector_get_size(val); i++) {
00602 fprintf(fp, "%4d\t%f\n", (int)cpl_matrix_get(pos, 0, i),
00603 cpl_vector_get(val, i));
00604 }
00605 fclose(fp);
00606 }
00607 }
00608 cpl_matrix_delete(pos);
00609 cpl_vector_delete(val);
00610 char *kw = cpl_sprintf(MUSE_HDR_OVSC_PNC, n);
00611 cpl_propertylist_append_int(aImage->header, kw, order + 1);
00612 cpl_free(kw);
00613 for (norder = 0; norder <= order; norder++) {
00614 cpl_size pows = norder;
00615 kw = cpl_sprintf(MUSE_HDR_OVSC_PY, n, norder);
00616 cpl_propertylist_append_double(aImage->header, kw,
00617 cpl_polynomial_get_coeff(fit, &pows));
00618 cpl_free(kw);
00619 }
00620
00621
00622
00623 int outx = muse_pfits_get_out_output_x(aImage->header, n),
00624 outy = muse_pfits_get_out_output_y(aImage->header, n),
00625 i1 = outx == 1 ? 1 : prex + outnx + overx + 1,
00626 i2 = outx == 1 ? prex + outnx + overx : 2 * (prex + outnx + overx),
00627 j1 = outy == 1 ? 1 : prey + outny + overy + 1,
00628 j2 = outy == 1 ? prey + outny + overy : 2 * (prey + outny + overy);
00629 if (debug > 1) {
00630 cpl_msg_debug(__func__, "quad %1hhu fill region [%d:%d,%d:%d]", n,
00631 i1, i2, j1, j2);
00632 }
00633
00634
00635 for (j = j1 - 1; j < j2; j++) {
00636 double subval = cpl_polynomial_eval_1d(fit, j + 1, NULL);
00637 for (i = i1 - 1; i < i2; i++) {
00638 data[i + j*nx] -= subval;
00639 }
00640 }
00641
00642 if (fit != fit0) {
00643 cpl_polynomial_delete(fit);
00644 }
00645 cpl_polynomial_delete(fit0);
00646 cpl_free(w);
00647 }
00648
00649 return CPL_ERROR_NONE;
00650 }
00651
00652
00684
00685 cpl_size *
00686 muse_quadrants_overscan_get_window(const muse_image *aImage,
00687 unsigned char aQuadrant,
00688 unsigned int aIgnore)
00689 {
00690 cpl_ensure(aImage && aImage->data && aImage->header, CPL_ERROR_NULL_INPUT,
00691 NULL);
00692 cpl_ensure(aQuadrant >= 1 && aQuadrant <= 4, CPL_ERROR_ILLEGAL_INPUT, NULL);
00693
00694 cpl_errorstate state = cpl_errorstate_get();
00695 int binx = muse_pfits_get_binx(aImage->header),
00696 biny = muse_pfits_get_biny(aImage->header),
00697 outnx = muse_pfits_get_out_nx(aImage->header, aQuadrant) / binx,
00698 outny = muse_pfits_get_out_ny(aImage->header, aQuadrant) / biny,
00699 prex = muse_pfits_get_out_prescan_x(aImage->header, aQuadrant) / binx,
00700 prey = muse_pfits_get_out_prescan_y(aImage->header, aQuadrant) / biny,
00701 overx = muse_pfits_get_out_overscan_x(aImage->header, aQuadrant) / binx,
00702 overy = muse_pfits_get_out_overscan_y(aImage->header, aQuadrant) / biny,
00703 portx = muse_pfits_get_out_output_x(aImage->header, aQuadrant),
00704 porty = muse_pfits_get_out_output_y(aImage->header, aQuadrant);
00705 #if 0
00706 cpl_msg_debug(__func__, "%d/%d, out %d/%d, pre %d/%d, over %d/%d, port %d/%d",
00707 binx, biny, outnx, outny, prex, prey, overx, overy, portx, porty);
00708 #endif
00709 cpl_ensure(cpl_errorstate_is_equal(state) &&
00710 outnx > 0 && outny > 0 && overx > 0 && overy > 0 &&
00711 prex >= 0 && prey >= 0 && binx > 0 && biny > 0 &&
00712 (portx == 1 || portx == kMuseOutputXRight) &&
00713 (porty == 1 || porty == kMuseOutputYTop),
00714 CPL_ERROR_INCOMPATIBLE_INPUT, NULL);
00715 cpl_ensure(aIgnore < (unsigned int)overx, CPL_ERROR_ILLEGAL_INPUT, NULL);
00716
00717
00718
00719 cpl_size *over = cpl_calloc(8, sizeof(cpl_size));
00720 if (portx == 1) {
00721 over[0] = prex + 1;
00722 over[1] = prex + outnx;
00723 over[4] = prex + outnx + 1 + aIgnore;
00724 over[5] = prex + outnx + overx;
00725 } else {
00726 over[0] = prex + outnx + 2*overx + 1;
00727 over[1] = prex + 2*outnx + 2*overx;
00728 over[4] = prex + outnx + overx + 1;
00729 over[5] = prex + outnx + 2*overx - aIgnore;
00730 }
00731 if (porty == 1) {
00732 over[2] = prey + outny + 1 + aIgnore;
00733 over[3] = prey + outny + overy;
00734 over[6] = prey + 1;
00735 over[7] = prey + outny + overy;
00736 } else {
00737 over[2] = prey + outny + overy + 1;
00738 over[3] = prey + outny + 2*overy - aIgnore;
00739 over[6] = prey + outny + overy + 1;
00740 over[7] = prey + 2*outny + 2*overy;
00741 }
00742
00743 if (getenv("MUSE_DEBUG_QUADRANTS") &&
00744 atoi(getenv("MUSE_DEBUG_QUADRANTS")) > 0) {
00745 cpl_msg_debug(__func__, "Quadrant %hhu overscan regions: "
00746 "[%"CPL_SIZE_FORMAT":%"CPL_SIZE_FORMAT
00747 ",%"CPL_SIZE_FORMAT":%"CPL_SIZE_FORMAT"] and "
00748 "[%"CPL_SIZE_FORMAT":%"CPL_SIZE_FORMAT
00749 ",%"CPL_SIZE_FORMAT":%"CPL_SIZE_FORMAT"]", aQuadrant,
00750 over[0], over[1], over[2], over[3],
00751 over[4], over[5], over[6], over[7]);
00752 }
00753 return over;
00754 }
00755
00756
00771
00772 muse_image *
00773 muse_quadrants_trim_image(muse_image *aImage)
00774 {
00775 cpl_ensure(aImage && aImage->data && aImage->header, CPL_ERROR_NULL_INPUT,
00776 NULL);
00777 cpl_boolean debug = CPL_FALSE;
00778 if (getenv("MUSE_DEBUG_QUADRANTS")) {
00779 debug = atoi(getenv("MUSE_DEBUG_QUADRANTS")) > 0;
00780 }
00781
00782
00783 int xout = 0, yout = 0;
00784
00785 int nx[4], ny[4], portx[4], porty[4];
00786
00787 int binx = muse_pfits_get_binx(aImage->header),
00788 biny = muse_pfits_get_biny(aImage->header);
00789
00790
00791 unsigned char n;
00792 for (n = 1; n <= 4; n++) {
00793 nx[n-1] = muse_pfits_get_out_nx(aImage->header, n) / binx;
00794 ny[n-1] = muse_pfits_get_out_ny(aImage->header, n) / biny;
00795 portx[n-1] = muse_pfits_get_out_output_x(aImage->header, n);
00796 porty[n-1] = muse_pfits_get_out_output_y(aImage->header, n);
00797
00798 if (nx[n-1] < 0 || ny[n-1] < 0 || portx[n-1] < 0 || porty[n-1] < 0) {
00799 cpl_msg_error(__func__, "FITS headers necessary for trimming are missing "
00800 "from quadrant %1d: NX=%d, NY=%d at OUT X=%d/OUT Y=%d", n,
00801 nx[n-1], ny[n-1], portx[n-1], porty[n-1]);
00802 cpl_error_set(__func__, CPL_ERROR_DATA_NOT_FOUND);
00803 return NULL;
00804 }
00805
00806 if ((portx[n-1] != 1 && portx[n-1] != kMuseOutputXRight) ||
00807 (porty[n-1] != 1 && porty[n-1] != kMuseOutputYTop)) {
00808 cpl_msg_error(__func__, "FITS headers necessary for trimming are "
00809 "unsupported for quadrant %1d: OUT X=%d/OUT Y=%d", n,
00810 portx[n-1], porty[n-1]);
00811 cpl_error_set(__func__, CPL_ERROR_INCOMPATIBLE_INPUT);
00812 return NULL;
00813 }
00814
00815
00816 if (portx[n-1] == 1) {
00817 yout += ny[n-1];
00818 }
00819
00820 if (porty[n-1] == 1) {
00821 xout += nx[n-1];
00822 }
00823 }
00824
00825
00826 int x_size = cpl_image_get_size_x(aImage->data),
00827 y_size = cpl_image_get_size_y(aImage->data);
00828 if (xout > x_size || yout > y_size) {
00829 cpl_msg_error(__func__, "output size (%dx%d) is larger than input size "
00830 "(%dx%d): wrong binning?!", xout, yout, x_size, y_size);
00831 cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT);
00832 return NULL;
00833 }
00834 if (debug) {
00835 cpl_msg_debug(__func__, "output size %dx%d", xout, yout);
00836 }
00837 cpl_ensure(xout > 0 && yout > 0, CPL_ERROR_ILLEGAL_INPUT, NULL);
00838
00839
00840 for (n = 1; n < 4; n++) {
00841 if (nx[n] != nx[0] || ny[n] != ny[0]) {
00842 cpl_msg_error(__func__, "Data region of quadrant %d is different from "
00843 "quadrant 1!", n+1);
00844 cpl_error_set(__func__, CPL_ERROR_INCOMPATIBLE_INPUT);
00845 return NULL;
00846 }
00847 }
00848
00849
00850 muse_image *trimmed = muse_image_new();
00851 trimmed->data = cpl_image_new(xout, yout, CPL_TYPE_FLOAT);
00852
00853 if (aImage->dq) {
00854 trimmed->dq = cpl_image_new(xout, yout, CPL_TYPE_INT);
00855 }
00856 if (aImage->stat) {
00857 trimmed->stat = cpl_image_new(xout, yout, CPL_TYPE_FLOAT);
00858 }
00859
00860
00861 trimmed->header = cpl_propertylist_duplicate(aImage->header);
00862 cpl_propertylist_erase_regexp(trimmed->header,
00863 "^NAXIS|^DATASUM$|^DATAMIN$|^DATAMAX$|^DATAMD5$|"
00864 "^ESO DET OUT.*PRSC|^ESO DET OUT.*OVSC",
00865 0);
00866
00867
00868
00869 for (n = 1; n <= 4; n++) {
00870
00871 int x_prescan = muse_pfits_get_out_prescan_x(aImage->header, n) / binx,
00872 y_prescan = muse_pfits_get_out_prescan_y(aImage->header, n) / biny;
00873
00874
00875 int x1 = 0, x2 = 0, y1 = 0, y2= 0,
00876 xtarget = 0, ytarget = 0;
00877
00878
00879 if (portx[n-1] == 1) {
00880 #if 0
00881 cpl_msg_debug(__func__, "left quadrant (OUT%d)", n);
00882 #endif
00883 x1 = x_prescan + 1;
00884 x2 = x_prescan + nx[0];
00885 xtarget = 1;
00886 } else if (portx[n-1] == kMuseOutputXRight) {
00887 #if 0
00888 cpl_msg_debug(__func__, "right quadrant (OUT%d)", n);
00889 #endif
00890 x1 = x_size - x_prescan - nx[0] + 1;
00891 x2 = x_size - x_prescan;
00892 xtarget = nx[0] + 1;
00893 }
00894
00895
00896 if (porty[n-1] == 1) {
00897 #if 0
00898 cpl_msg_debug(__func__, "bottom quadrant (OUT%d)", n);
00899 #endif
00900 y1 = y_prescan + 1;
00901 y2 = y_prescan + ny[0];
00902 ytarget = 1;
00903 } else if (porty[n-1] == kMuseOutputYTop) {
00904 #if 0
00905 cpl_msg_debug(__func__, "top quadrant (OUT%d)", n);
00906 #endif
00907 y1 = y_size - y_prescan - ny[0] + 1;
00908 y2 = y_size - y_prescan;
00909 ytarget = ny[0] + 1;
00910 }
00911
00912
00913 cpl_image *image = cpl_image_extract(aImage->data, x1, y1, x2, y2);
00914 if (debug) {
00915 cpl_msg_debug(__func__, "port at %d,%d: %d,%d - %d,%d, extracted: "
00916 "%"CPL_SIZE_FORMAT"x%"CPL_SIZE_FORMAT" -> %d,%d",
00917 portx[n-1], porty[n-1], x1,y1, x2,y2,
00918 cpl_image_get_size_x(image), cpl_image_get_size_y(image),
00919 xtarget, ytarget);
00920 }
00921 cpl_image_copy(trimmed->data, image, xtarget, ytarget);
00922 cpl_image_delete(image);
00923 if (aImage->dq) {
00924 image = cpl_image_extract(aImage->dq, x1, y1, x2, y2);
00925 cpl_image_copy(trimmed->dq, image, xtarget, ytarget);
00926 cpl_image_delete(image);
00927 }
00928 if (aImage->stat) {
00929 image = cpl_image_extract(aImage->stat, x1, y1, x2, y2);
00930 cpl_image_copy(trimmed->stat, image, xtarget, ytarget);
00931 cpl_image_delete(image);
00932 }
00933 }
00934
00935 #if 0
00936 muse_image_save(aImage, "input.fits");
00937 muse_image_save(trimmed, "trimmed.fits");
00938 #endif
00939
00940 return trimmed;
00941 }
00942
00943
00956
00957 cpl_error_code
00958 muse_quadrants_coords_to_raw(cpl_propertylist *aHeader, int *aX, int *aY)
00959 {
00960 cpl_ensure_code(aX || aY, CPL_ERROR_NULL_INPUT);
00961 if (!aHeader) {
00962
00963 if (aX) {
00964 int xraw = *aX + kMusePreOverscanSize;
00965 if (*aX > kMuseOutputXRight/2) {
00966 xraw += 2 * kMusePreOverscanSize;
00967 }
00968 *aX = xraw;
00969 }
00970 if (aY) {
00971 int yraw = *aY + kMusePreOverscanSize;
00972 if (*aY > kMuseOutputYTop/2) {
00973 yraw += 2 * kMusePreOverscanSize;
00974 }
00975 *aY = yraw;
00976 }
00977 return CPL_ERROR_NONE;
00978 }
00979
00980 return CPL_ERROR_NONE;
00981 }
00982
00983
01004
01005 cpl_boolean
01006 muse_quadrants_verify(cpl_propertylist *aHeader)
01007 {
01008 cpl_ensure(aHeader, CPL_ERROR_NULL_INPUT, CPL_FALSE);
01009
01010 int portx[4], porty[4], nx[4], ny[4],
01011 prex[4], prey[4], overx[4], overy[4];
01012
01013
01014 int binx = muse_pfits_get_binx(aHeader),
01015 biny = muse_pfits_get_biny(aHeader);
01016 unsigned char n;
01017 for (n = 1; n <= 4; n++) {
01018 portx[n-1] = muse_pfits_get_out_output_x(aHeader, n);
01019 porty[n-1] = muse_pfits_get_out_output_y(aHeader, n);
01020 nx[n-1] = muse_pfits_get_out_nx(aHeader, n) / binx;
01021 ny[n-1] = muse_pfits_get_out_ny(aHeader, n) / biny;
01022 prex[n-1] = muse_pfits_get_out_prescan_x(aHeader, n) / binx;
01023 prey[n-1] = muse_pfits_get_out_prescan_y(aHeader, n) / biny;
01024 overx[n-1] = muse_pfits_get_out_overscan_x(aHeader, n) / binx;
01025 overy[n-1] = muse_pfits_get_out_overscan_y(aHeader, n) / biny;
01026 #if 0
01027 cpl_msg_debug(__func__, "quadrant %1hhu: port=%d,%d, n=%d,%d, pre=%d,%d, over=%d,%d",
01028 n+1, portx[n-1], porty[n-1], nx[n-1], ny[n-1],
01029 prex[n-1], prey[n-1], overx[n-1], overy[n-1]);
01030 #endif
01031 }
01032
01033 cpl_ensure(portx[0] < portx[1], CPL_ERROR_ILLEGAL_INPUT, CPL_FALSE);
01034
01035 if (!cpl_propertylist_has(aHeader, "INMMODEL")) {
01036 cpl_ensure(portx[0] < portx[2], CPL_ERROR_ILLEGAL_INPUT, CPL_FALSE);
01037 cpl_ensure(portx[0] == portx[3], CPL_ERROR_ILLEGAL_INPUT, CPL_FALSE);
01038 }
01039 cpl_ensure(porty[0] == porty[1], CPL_ERROR_ILLEGAL_INPUT, CPL_FALSE);
01040 cpl_ensure(porty[0] < porty[2], CPL_ERROR_ILLEGAL_INPUT, CPL_FALSE);
01041 cpl_ensure(porty[0] < porty[3], CPL_ERROR_ILLEGAL_INPUT, CPL_FALSE);
01042
01043 for (n = 1; n < 4; n++) {
01044 cpl_ensure(nx[0] == nx[n] && ny[0] == ny[n], CPL_ERROR_INCOMPATIBLE_INPUT,
01045 0);
01046 cpl_ensure(prex[0] == prex[n] && prey[0] == prey[n],
01047 CPL_ERROR_INCOMPATIBLE_INPUT, CPL_FALSE);
01048 cpl_ensure(overx[0] == overx[n] && overy[0] == overy[n],
01049 CPL_ERROR_INCOMPATIBLE_INPUT, CPL_FALSE);
01050 }
01051
01052 return CPL_TRUE;
01053 }
01054
01055
01072
01073 cpl_size *
01074 muse_quadrants_get_window(const muse_image *aImage, unsigned char aQuadrant)
01075 {
01076 cpl_ensure(aImage && aImage->data && aImage->header, CPL_ERROR_NULL_INPUT,
01077 NULL);
01078 cpl_ensure(aQuadrant >= 1 && aQuadrant <= 4, CPL_ERROR_ILLEGAL_INPUT, NULL);
01079
01080 cpl_boolean debug = CPL_FALSE;
01081 if (getenv("MUSE_DEBUG_QUADRANTS")) {
01082 debug = atoi(getenv("MUSE_DEBUG_QUADRANTS")) > 0;
01083 }
01084
01085
01086 int binx = muse_pfits_get_binx(aImage->header),
01087 biny = muse_pfits_get_biny(aImage->header),
01088 nx[5], ny[5];
01089 nx[0] = cpl_image_get_size_x(aImage->data);
01090 ny[0] = cpl_image_get_size_y(aImage->data);
01091 unsigned char n;
01092 for (n = 1; n <= 4; n++) {
01093 nx[n] = muse_pfits_get_out_nx(aImage->header, n) / binx;
01094 ny[n] = muse_pfits_get_out_ny(aImage->header, n) / biny;
01095 }
01096
01097 cpl_size *window = (cpl_size *)cpl_calloc(sizeof(cpl_size), 4);
01098 switch (aQuadrant) {
01099 case 1:
01100 window[0] = 1;
01101 window[1] = nx[1];
01102 window[2] = 1;
01103 window[3] = ny[1];
01104 break;
01105 case 2:
01106 window[0] = nx[1] + 1;
01107 window[1] = nx[1] + nx[2];
01108 window[2] = 1;
01109 window[3] = ny[2];
01110 break;
01111 case 3:
01112 window[0] = nx[3] + 1;
01113 window[1] = nx[3] + nx[4];
01114 window[2] = ny[2] + 1;
01115 window[3] = ny[2] + ny[4];
01116 break;
01117 case 4:
01118 window[0] = 1;
01119 window[1] = nx[3];
01120 window[2] = ny[1] + 1;
01121 window[3] = ny[1] + ny[3];
01122 break;
01123 }
01124
01125
01126
01127 if ((nx[1] + nx[2]) == nx[0] && (ny[1] + ny[3]) == ny[0]) {
01128 if (debug) {
01129 cpl_msg_debug(__func__, "quadrant %d, trimmed: %"CPL_SIZE_FORMAT",%"
01130 CPL_SIZE_FORMAT " -> %"CPL_SIZE_FORMAT",%"CPL_SIZE_FORMAT"",
01131 aQuadrant, window[0], window[2], window[1], window[3]);
01132 }
01133 return window;
01134 }
01135
01136
01137
01138 int overx[5], overy[5],
01139 prex[5], prey[5];
01140 for (n = 1; n <= 4; n++) {
01141 prex[n] = muse_pfits_get_out_prescan_x(aImage->header, n) / binx;
01142 prey[n] = muse_pfits_get_out_prescan_y(aImage->header, n) / biny;
01143 overx[n] = muse_pfits_get_out_overscan_x(aImage->header, n) / binx;
01144 overy[n] = muse_pfits_get_out_overscan_y(aImage->header, n) / biny;
01145 }
01146
01147 int addx = 0, addy = 0;
01148 switch (aQuadrant) {
01149 case 1:
01150 addx = prex[1];
01151 addy = prey[1];
01152 break;
01153 case 2:
01154 addx = prex[1] + overx[1] + overx[2];
01155 addy = prey[2];
01156 break;
01157 case 3:
01158 addx = prex[3] + overx[3] + overx[4];
01159 addy = prey[1] + overy[1] + overy[3];
01160 break;
01161 case 4:
01162 addx = prex[3];
01163 addy = prey[2] + overy[2] + overy[4];
01164 break;
01165 }
01166 window[0] += addx;
01167 window[1] += addx;
01168 window[2] += addy;
01169 window[3] += addy;
01170
01171 if (debug) {
01172 cpl_msg_debug(__func__, "quadrant %d, not trimmed: %"CPL_SIZE_FORMAT",%"
01173 CPL_SIZE_FORMAT " -> %"CPL_SIZE_FORMAT",%"CPL_SIZE_FORMAT,
01174 aQuadrant, window[0], window[2], window[1], window[3]);
01175 }
01176
01177 return window;
01178 }
01179