29#include <cxmessages.h>
30#include <cxstrutils.h>
34#include <cpl_parameter.h>
40#include "gichebyshev.h"
67typedef struct GiBiasResults GiBiasResults;
75_giraffe_biasresults_clear(GiBiasResults *self)
85 cx_string_delete(self->limits);
90 cpl_matrix_delete(self->coeffs);
95 cpl_image_delete(self->model);
111_giraffe_method_string(cx_string *
string, GiBiasMethod method,
116 case GIBIAS_METHOD_UNIFORM:
117 cx_string_set(
string,
"UNIFORM");
120 case GIBIAS_METHOD_PLANE:
121 cx_string_set(
string,
"PLANE");
124 case GIBIAS_METHOD_CURVE:
125 cx_string_set(
string,
"CURVE");
128 case GIBIAS_METHOD_PROFILE:
129 cx_string_set(
string,
"PROFILE");
132 case GIBIAS_METHOD_MASTER:
133 cx_string_set(
string,
"MASTER");
136 case GIBIAS_METHOD_ZMASTER:
137 cx_string_set(
string,
"ZMASTER");
144 if (option != GIBIAS_OPTION_UNDEFINED) {
146 case GIBIAS_OPTION_PLANE:
147 cx_string_append(
string,
"+PLANE");
150 case GIBIAS_OPTION_CURVE:
151 cx_string_append(
string,
"+CURVE");
165_giraffe_stringify_coefficients(cx_string *
string, cpl_matrix *matrix)
170 cxchar *tmp = cx_line_alloc();
172 cxint nr = cpl_matrix_get_nrow(matrix);
173 cxint nc = cpl_matrix_get_ncol(matrix);
175 cxsize sz = cx_line_max();
177 cxdouble *data = cpl_matrix_get_data(matrix);
180 for (i = 0; i < nr; i++) {
181 for (j = 0; j < nc; j++) {
182 snprintf(tmp, sz,
"%g", data[i * nc + j]);
183 cx_string_append(
string, tmp);
185 if (i != nr - 1 || j < nc - 1) {
186 cx_string_append(
string,
":");
214_giraffe_compare_overscans(
const GiImage* image1,
const GiImage* image2)
217 cxint32 l1ovscx = -1;
218 cxint32 l1ovscy = -1;
219 cxint32 l1prscx = -1;
220 cxint32 l1prscy = -1;
221 cxint32 l2ovscx = -1;
222 cxint32 l2ovscy = -1;
223 cxint32 l2prscx = -1;
224 cxint32 l2prscy = -1;
226 cpl_propertylist *l1, *l2;
229 cx_assert(image1 != NULL && image2 != NULL);
234 if (cpl_propertylist_has(l1, GIALIAS_OVSCX)) {
235 l1ovscx = cpl_propertylist_get_int(l1, GIALIAS_OVSCX);
237 if (cpl_propertylist_has(l1, GIALIAS_OVSCY)) {
238 l1ovscy = cpl_propertylist_get_int(l1, GIALIAS_OVSCY);
240 if (cpl_propertylist_has(l1, GIALIAS_PRSCX)) {
241 l1prscx = cpl_propertylist_get_int(l1, GIALIAS_PRSCX);
243 if (cpl_propertylist_has(l1, GIALIAS_PRSCY)) {
244 l1prscy = cpl_propertylist_get_int(l1, GIALIAS_PRSCY);
247 if (cpl_propertylist_has(l2, GIALIAS_OVSCX)) {
248 l2ovscx = cpl_propertylist_get_int(l2, GIALIAS_OVSCX);
250 if (cpl_propertylist_has(l2, GIALIAS_OVSCY)) {
251 l2ovscy = cpl_propertylist_get_int(l2, GIALIAS_OVSCY);
253 if (cpl_propertylist_has(l2, GIALIAS_PRSCX)) {
254 l2prscx = cpl_propertylist_get_int(l2, GIALIAS_PRSCX);
256 if (cpl_propertylist_has(l2, GIALIAS_PRSCY)) {
257 l2prscy = cpl_propertylist_get_int(l2, GIALIAS_PRSCY);
260 if (l1ovscx != l2ovscx || l1ovscy != l2ovscy) {
264 if (l1prscx != l2prscx || l1prscy != l2prscy) {
286inline static cpl_matrix*
287_giraffe_bias_get_areas(
const cxchar*
string)
290 cxchar** regions = NULL;
292 cpl_matrix* areas = NULL;
295 cx_assert(
string != NULL);
297 regions = cx_strsplit(
string,
",", -1);
299 if (regions == NULL) {
306 const cxsize nvalues = 4;
311 while (regions[i] != NULL) {
316 areas = cpl_matrix_new(nregions, nvalues);
319 while (regions[i] != NULL) {
321 register cxsize j = 0;
323 cxchar** limits = cx_strsplit(regions[i],
":", nvalues);
326 if (limits == NULL) {
328 cpl_matrix_delete(areas);
335 for (j = 0; j < nvalues; ++j) {
343 if (limits[j] == NULL || *limits[j] ==
'\0') {
350 value = strtol(limits[j], &last, 10);
356 if ((errno == ERANGE &&
357 (value == LONG_MAX || value == LONG_MIN)) ||
358 (errno != 0 && value == 0)) {
375 cpl_matrix_set(areas, i, j, value);
384 cpl_matrix_delete(areas);
387 cx_strfreev(regions);
398 cx_strfreev(regions);
455_giraffe_bias_compute_mean(GiBiasResults* results,
const cpl_image* image,
456 const cpl_matrix* areas, cxdouble kappa, cxint numiter,
457 cxdouble maxfraction)
460 const cxchar*
const fctid =
"giraffe_bias_compute_mean";
463 const cxdouble* pdimg = NULL;
466 cxint img_dimx, img_dimy;
470 cxint x0, x1, x2, x3;
475 cxlong naccepted = 0L;
477 cxlong pixcount = 0L;
479 cxdouble currfraction = 2.;
481 cx_string* tmp = NULL;
483 cpl_matrix* matrix_zz1;
484 cpl_matrix* matrix_zz1diff;
491 if (results->limits == NULL) {
492 cpl_msg_info(fctid,
"Unable to store biaslimits return parameter, "
497 if (cpl_image_get_type(image) != CPL_TYPE_DOUBLE) {
498 cpl_msg_info(fctid,
"Only images allowed of type double, "
513 cpl_msg_info(fctid,
"Bias Areas: Missing bias areas, "
519 ba_num_rows = cpl_matrix_get_nrow(areas);
521 for (j = 0; j < ba_num_rows; j++) {
522 x3 = (cxint) cpl_matrix_get(areas, j, 3);
523 x2 = (cxint) cpl_matrix_get(areas, j, 2);
524 x1 = (cxint) cpl_matrix_get(areas, j, 1);
525 x0 = (cxint) cpl_matrix_get(areas, j, 0);
527 ntotal += (cxulong) ((x3 - x2 + 1) * (x1 - x0 + 1));
531 cpl_msg_info(fctid,
"Bias Areas: Inconsistent specification, "
536 matrix_zz1 = cpl_matrix_new(ntotal, 1);
537 matrix_zz1diff = cpl_matrix_new(ntotal, 1);
544 img_dimx = cpl_image_get_size_x(image);
545 img_dimy = cpl_image_get_size_y(image);
547 cx_string_set(results->limits,
"");
549 for (j = 0; j < ba_num_rows; j++) {
551 x3 = (cxint) cpl_matrix_get(areas, j, 3);
552 x2 = (cxint) cpl_matrix_get(areas, j, 2);
553 x1 = (cxint) cpl_matrix_get(areas, j, 1);
554 x0 = (cxint) cpl_matrix_get(areas, j, 0);
556 if ((x0 > img_dimx) || (x1 > img_dimx) ||
557 (x2 > img_dimy) || (x3 > img_dimy)) {
561 tmp = cx_string_new();
563 cx_string_sprintf(tmp,
"%d:%d:%d:%d;", x0, x1, x2, x3);
564 cx_string_append(results->limits, cx_string_get(tmp));
566 cx_string_delete(tmp);
569 pdimg = cpl_image_get_data_double_const(image);
571 for (l = x2; l < x3 + 1; l++) {
572 for (k = x0; k < x1 + 1; k++) {
573 cpl_matrix_set(matrix_zz1, n, 1, pdimg[k + l * img_dimx]);
580 cpl_msg_info(fctid,
"Bias Areas: Validation failed, aborting ...");
582 cpl_matrix_delete(matrix_zz1);
583 cpl_matrix_delete(matrix_zz1diff);
588 cpl_msg_info(fctid,
"Bias Areas: Using %s",
589 cx_string_get(results->limits));
600 cpl_msg_info(fctid,
"Sigma Clipping : Start");
604 while ((naccepted > 0) && (curriter < numiter) &&
605 (currfraction > maxfraction)) {
607 cxdouble ksigma = 0.;
609 results->mean = cpl_matrix_get_mean(matrix_zz1);
612 for (k = 0; k < cpl_matrix_get_nrow(matrix_zz1); k++) {
613 cpl_matrix_set(matrix_zz1diff, k, 0,
614 cpl_matrix_get(matrix_zz1, k, 0) - results->mean);
617 cpl_msg_info(fctid,
"bias[%d]: mean = %5g, sigma = %6.3g, "
618 "ratio = %6.3g, accepted = %ld\n", curriter,
619 results->mean, sigma, currfraction, naccepted);
621 ksigma = sigma * kappa;
624 for (l = 0; l < cpl_matrix_get_nrow(matrix_zz1); l++) {
625 if (fabs(cpl_matrix_get(matrix_zz1diff, l, 0)) > ksigma) {
629 cpl_matrix_set(matrix_zz1, pixcount, 0,
630 cpl_matrix_get(matrix_zz1, l, 0));
634 cpl_matrix_resize(matrix_zz1, 0, 0, 0, pixcount -
635 cpl_matrix_get_nrow(matrix_zz1));
637 cpl_matrix_resize(matrix_zz1diff, 0, 0, 0, pixcount -
638 cpl_matrix_get_nrow(matrix_zz1diff));
640 if (pixcount == naccepted) {
644 naccepted = pixcount;
646 currfraction = (cxdouble) naccepted / (cxdouble) ntotal;
650 cpl_msg_info(fctid,
"Sigma Clipping : End");
657 results->mean = cpl_matrix_get_mean(matrix_zz1);
660 results->sigma = results->rms / sqrt(cpl_matrix_get_nrow(matrix_zz1));
663 cpl_msg_info(fctid,
"Sigma Clipping Results : bias[%d]: mean = %5g, "
664 "sigma = %6.3g, ratio = %6.3g, accepted=%ld\n", curriter,
665 results->mean, results->rms, currfraction, naccepted);
672 if (matrix_zz1 != NULL) {
673 cpl_matrix_delete(matrix_zz1);
676 if (matrix_zz1diff != NULL) {
677 cpl_matrix_delete(matrix_zz1diff);
738_giraffe_bias_compute_plane(GiBiasResults* results,
const cpl_image* image,
739 const cpl_matrix* areas, cxdouble kappa,
740 cxint numiter, cxdouble maxfraction)
743 const cxchar*
const fctid =
"giraffe_bias_compute_plane";
754 cxsize naccepted = 0;
756 cxdouble fraction = 1.;
759 cpl_matrix* xbs = NULL;
760 cpl_matrix* ybs = NULL;
761 cpl_matrix* zbs = NULL;
762 cpl_matrix* coeffs = NULL;
765 cx_assert(results->limits != NULL);
766 cx_assert(results->coeffs == NULL);
768 cx_assert(areas != NULL);
770 cx_assert(cpl_image_get_type(image) == CPL_TYPE_DOUBLE);
777 nareas = cpl_matrix_get_nrow(areas);
779 for (j = 0; j < nareas; j++) {
781 cxint x3 = (cxint) cpl_matrix_get(areas, j, 3);
782 cxint x2 = (cxint) cpl_matrix_get(areas, j, 2);
783 cxint x1 = (cxint) cpl_matrix_get(areas, j, 1);
784 cxint x0 = (cxint) cpl_matrix_get(areas, j, 0);
786 ntotal += (cxsize) ((x3 - x2 + 1) * (x1 - x0 + 1));
792 cpl_msg_info(fctid,
"Bias Areas: Inconsistent specification, "
798 nx = cpl_image_get_size_x(image);
799 ny = cpl_image_get_size_y(image);
801 cpl_msg_info(fctid,
"Bias Areas: specified are %zu points in %dx%d "
802 "image", ntotal, nx, ny);
813 cx_string_set(results->limits,
"");
815 xbs = cpl_matrix_new(ntotal, 1);
816 ybs = cpl_matrix_new(ntotal, 1);
817 zbs = cpl_matrix_new(1, ntotal);
819 for (j = 0; j < nareas; ++j) {
821 const cxdouble* _img = cpl_image_get_data_double_const(image);
825 cx_string* tmp = NULL;
828 cxint x3 = (cxint)cpl_matrix_get(areas, j, 3);
829 cxint x2 = (cxint)cpl_matrix_get(areas, j, 2);
830 cxint x1 = (cxint)cpl_matrix_get(areas, j, 1);
831 cxint x0 = (cxint)cpl_matrix_get(areas, j, 0);
833 if ((x0 > nx) || (x1 > nx) || (x2 > ny) || (x3 > ny)) {
837 tmp = cx_string_new();
839 cx_string_sprintf(tmp,
"%d:%d:%d:%d;", x0, x1, x2, x3);
840 cx_string_append(results->limits, cx_string_get(tmp));
842 cx_string_delete(tmp);
845 for (k = x2; k < x3 + 1; ++k) {
847 register cxint l = 0;
850 for (l = x0; l < x1 + 1; ++l) {
852 cpl_matrix_set(xbs, n, 0, l);
853 cpl_matrix_set(ybs, n, 0, k);
854 cpl_matrix_set(zbs, 0, n, _img[k * nx + l]);
863 cpl_matrix_set_size(xbs, n, 1);
864 cpl_matrix_set_size(ybs, n, 1);
865 cpl_matrix_set_size(zbs, 1, n);
869 cpl_msg_info(fctid,
"Bias Areas: Validation failed, aborting...");
871 cpl_matrix_delete(xbs);
872 cpl_matrix_delete(ybs);
873 cpl_matrix_delete(zbs);
881 cpl_msg_info(fctid,
"Bias Areas: Using %s [%zu pixels]",
882 cx_string_get(results->limits), ntotal);
889 cpl_msg_info(fctid,
"Sigma Clipping : Start");
893 while ((naccepted > 0) && (iteration < numiter) &&
894 (fraction > maxfraction)) {
898 cxdouble ksigma = 0.;
900 cpl_matrix* base = NULL;
901 cpl_matrix* fit = NULL;
904 base = cpl_matrix_new(3, naccepted);
908 cpl_msg_info(fctid,
"Sigma Clipping: Error creating design "
911 cpl_matrix_delete(zbs);
912 cpl_matrix_delete(ybs);
913 cpl_matrix_delete(xbs);
918 for (k = 0; k < naccepted; ++k) {
920 cpl_matrix_set(base, 0, k, 1.);
921 cpl_matrix_set(base, 1, k, cpl_matrix_get(xbs, k, 0));
922 cpl_matrix_set(base, 2, k, cpl_matrix_get(ybs, k, 0));
926 cpl_matrix_delete(coeffs);
931 if (coeffs == NULL) {
933 cpl_msg_info(fctid,
"Sigma Clipping : Error in least square "
934 "solution, aborting...");
936 cpl_matrix_delete(base);
939 cpl_matrix_delete(xbs);
940 cpl_matrix_delete(ybs);
941 cpl_matrix_delete(zbs);
952 fit = cpl_matrix_product_create(coeffs, base);
954 cpl_matrix_delete(base);
957 results->mean = cpl_matrix_get_mean(fit);
961 cpl_msg_info(fctid,
"Sigma Clipping : bias plane[%d]: %g + "
962 "%g * x + %g * y, sigma = %.5g, ratio = %.4g, "
963 "accepted = %zu\n", iteration,
964 cpl_matrix_get(coeffs, 0, 0),
965 cpl_matrix_get(coeffs, 0, 1),
966 cpl_matrix_get(coeffs, 0, 2),
967 sigma, fraction, naccepted);
974 ksigma = sigma * kappa;
978 for (j = 0; j < cpl_matrix_get_ncol(zbs); ++j) {
980 register cxdouble z = cpl_matrix_get(zbs, 0, j);
982 if (fabs(cpl_matrix_get(fit, 0, j) - z) > ksigma) {
986 cpl_matrix_set(xbs, n, 0, cpl_matrix_get(xbs, j, 0));
988 cpl_matrix_set(ybs, n, 0, cpl_matrix_get(ybs, j, 0));
990 cpl_matrix_set(zbs, 0, n, z);
995 cpl_matrix_set_size(xbs, n, 1);
996 cpl_matrix_set_size(ybs, n, 1);
997 cpl_matrix_set_size(zbs, 1, n);
999 cpl_matrix_delete(fit);
1002 if (n == naccepted) {
1008 fraction = (cxdouble)naccepted / (cxdouble)ntotal;
1013 cpl_msg_info(fctid,
"Sigma Clipping : End");
1020 results->coeffs = coeffs;
1021 results->rms = sigma;
1029 results->sigma = sigma / sqrt(cpl_matrix_get_ncol(zbs));
1031 cpl_msg_info(fctid,
"Sigma Clipping Results (%d/%zu, sigma = %g)",
1032 iteration, naccepted, results->rms);
1039 cpl_matrix_delete(xbs);
1042 cpl_matrix_delete(ybs);
1045 cpl_matrix_delete(zbs);
1048 return EXIT_SUCCESS;
1095_giraffe_bias_compute_curve(GiBiasResults* results,
const cpl_image* image,
1096 const cpl_matrix *areas, cxdouble kappa,
1097 cxint numiter, cxdouble maxfraction,
1098 cxdouble xdeg, cxdouble ydeg,
1099 cxdouble xstep, cxdouble ystep)
1102 const cxchar*
const fctid =
"giraffe_bias_compute_curve";
1108 cxint iteration = 0;
1112 cxsize naccepted = 0;
1114 cxdouble fraction = 1.;
1115 cxdouble sigma = 0.;
1117 cpl_matrix* xbs = NULL;
1118 cpl_matrix* ybs = NULL;
1119 cpl_matrix* zbs = NULL;
1121 GiChebyshev2D* fit = NULL;
1124 cx_assert(results != NULL);
1125 cx_assert(results->limits != NULL);
1126 cx_assert(results->coeffs == NULL);
1128 cx_assert(areas != NULL);
1130 cx_assert(image != NULL);
1131 cx_assert(cpl_image_get_type(image) == CPL_TYPE_DOUBLE);
1138 nareas = cpl_matrix_get_nrow(areas);
1140 for (j = 0; j < nareas; ++j) {
1142 cxint x3 = (cxint)cpl_matrix_get(areas, j, 3);
1143 cxint x2 = (cxint)cpl_matrix_get(areas, j, 2);
1144 cxint x1 = (cxint)cpl_matrix_get(areas, j, 1);
1145 cxint x0 = (cxint)cpl_matrix_get(areas, j, 0);
1147 ntotal += (cxulong) (ceil((1. + x3 - x2) / ystep) *
1148 ceil((1. + x1 - x0) / xstep));
1151 nx = cpl_image_get_size_x(image);
1152 ny = cpl_image_get_size_y(image);
1154 cpl_msg_info(fctid,
"Bias Areas: Found %zu points in %dx%d image",
1163 results->sigma = 0.;
1166 cx_string_set(results->limits,
"");
1168 xbs = cpl_matrix_new(ntotal, 1);
1169 ybs = cpl_matrix_new(ntotal, 1);
1170 zbs = cpl_matrix_new(1, ntotal);
1172 for (j = 0; j < nareas; ++j) {
1174 const cxdouble* _img = cpl_image_get_data_double_const(image);
1178 cx_string* tmp = NULL;
1181 cxint x3 = (cxint)cpl_matrix_get(areas, j, 3);
1182 cxint x2 = (cxint)cpl_matrix_get(areas, j, 2);
1183 cxint x1 = (cxint)cpl_matrix_get(areas, j, 1);
1184 cxint x0 = (cxint)cpl_matrix_get(areas, j, 0);
1186 if ((x0 > nx) || (x1 > nx) ||
1187 (x2 > ny) || (x3 > ny)) {
1191 tmp = cx_string_new();
1193 cx_string_sprintf(tmp,
"%d:%d:%d:%d;", x0, x1, x2, x3);
1194 cx_string_append(results->limits, cx_string_get(tmp));
1196 cx_string_delete(tmp);
1199 for (k = x2; k < x3 + 1; k += ystep) {
1201 register cxint l = 0;
1204 for (l = x0; l < x1 + 1; l += xstep) {
1206 cpl_matrix_set(xbs, n, 0, l);
1207 cpl_matrix_set(ybs, n, 0, k);
1208 cpl_matrix_set(zbs, 0, n, _img[k * nx + l]);
1217 cpl_matrix_set_size(xbs, n, 1);
1218 cpl_matrix_set_size(ybs, n, 1);
1219 cpl_matrix_set_size(zbs, 1, n);
1223 cpl_msg_info(fctid,
"Bias Areas: Validation failed, aborting...");
1225 cpl_matrix_delete(xbs);
1226 cpl_matrix_delete(ybs);
1227 cpl_matrix_delete(zbs);
1235 cpl_msg_info(fctid,
"Bias Areas: Using %s [%zu pixels]",
1236 cx_string_get(results->limits), ntotal);
1243 cpl_msg_info(fctid,
"Sigma Clipping : Start");
1247 while ((naccepted > 0) && (iteration < numiter) &&
1248 (fraction > maxfraction)) {
1252 cxdouble ksigma = 0.;
1254 cpl_matrix* base = NULL;
1255 cpl_matrix* coeffs = NULL;
1256 cpl_matrix* _coeffs = NULL;
1257 cpl_matrix* _fit = NULL;
1260 base = giraffe_chebyshev_base2d(0., 0., nx, ny,
1261 xdeg, ydeg, xbs, ybs);
1265 cpl_msg_info(fctid,
"Sigma Clipping: Error creating design "
1268 cpl_matrix_delete(zbs);
1269 cpl_matrix_delete(ybs);
1270 cpl_matrix_delete(xbs);
1277 cpl_matrix_delete(base);
1280 if (_coeffs == NULL) {
1282 cpl_msg_info(fctid,
"Sigma Clipping : Error in least square "
1283 "solution, aborting...");
1285 cpl_matrix_delete(xbs);
1286 cpl_matrix_delete(ybs);
1287 cpl_matrix_delete(zbs);
1298 coeffs = cpl_matrix_wrap(xdeg, ydeg, cpl_matrix_get_data(_coeffs));
1301 giraffe_chebyshev2d_delete(fit);
1305 fit = giraffe_chebyshev2d_new(xdeg - 1, ydeg - 1);
1306 status = giraffe_chebyshev2d_set(fit, 0., nx, 0., ny,
1311 giraffe_chebyshev2d_delete(fit);
1314 cpl_matrix_unwrap(coeffs);
1317 cpl_matrix_delete(_coeffs);
1320 cpl_matrix_delete(xbs);
1321 cpl_matrix_delete(ybs);
1322 cpl_matrix_delete(zbs);
1328 cpl_matrix_unwrap(coeffs);
1331 cpl_matrix_delete(_coeffs);
1334 _fit = cpl_matrix_new(1, cpl_matrix_get_ncol(zbs));
1336 for (j = 0; j < cpl_matrix_get_ncol(_fit); ++j) {
1338 cxdouble x = cpl_matrix_get(xbs, n, 0);
1339 cxdouble y = cpl_matrix_get(ybs, n, 0);
1340 cxdouble z = giraffe_chebyshev2d_eval(fit, x, y);
1342 cpl_matrix_set(_fit, 0, j, z);
1346 results->mean = cpl_matrix_get_mean(_fit);
1350 cpl_msg_info(fctid,
"Sigma Clipping : bias surface[%d]: "
1351 "sigma = %8.5g, ratio = %7.4g, accepted = %zu\n",
1352 iteration, sigma, fraction, naccepted);
1359 ksigma = sigma * kappa;
1363 for (j = 0; j < cpl_matrix_get_ncol(zbs); ++j) {
1365 register cxdouble z = cpl_matrix_get(zbs, 0, j);
1367 if (fabs(cpl_matrix_get(_fit, 0, j) - z) > ksigma) {
1371 cpl_matrix_set(xbs, n, 0, cpl_matrix_get(xbs, j, 0));
1372 cpl_matrix_set(ybs, n, 0, cpl_matrix_get(ybs, j, 0));
1373 cpl_matrix_set(zbs, 0, n, z);
1378 cpl_matrix_set_size(xbs, n, 1);
1379 cpl_matrix_set_size(ybs, n, 1);
1380 cpl_matrix_set_size(zbs, 1, n);
1382 cpl_matrix_delete(_fit);
1386 if (n == naccepted) {
1392 fraction = (cxdouble)naccepted / (cxdouble)ntotal;
1397 cpl_msg_info(fctid,
"Sigma Clipping : End");
1404 results->coeffs = cpl_matrix_duplicate(giraffe_chebyshev2d_coeffs(fit));
1405 results->rms = sigma;
1413 results->sigma = sigma / sqrt(cpl_matrix_get_ncol(zbs));
1415 cpl_msg_info(fctid,
"Sigma Clipping Results (%d/%zu, sigma = %g)",
1416 iteration, naccepted, results->rms);
1423 giraffe_chebyshev2d_delete(fit);
1426 cpl_matrix_delete(xbs);
1429 cpl_matrix_delete(ybs);
1432 cpl_matrix_delete(zbs);
1435 return EXIT_SUCCESS;
1464_giraffe_bias_compute_profile(GiBiasResults* results,
const cpl_image* image,
1465 const cpl_matrix* areas, cxchar axis)
1468 const cxchar*
const fctid =
"_giraffe_bias_compute_profile";
1483 cxdouble sigma = 0.;
1485 cpl_matrix* _areas = NULL;
1487 cpl_image* profile = NULL;
1488 cpl_image* model = NULL;
1491 cx_assert(results != NULL);
1492 cx_assert(results->limits != NULL);
1493 cx_assert(results->model == NULL);
1495 cx_assert(areas != NULL);
1497 cx_assert(image != NULL);
1498 cx_assert(cpl_image_get_type(image) == CPL_TYPE_DOUBLE);
1500 cx_assert((axis ==
'x') || (axis ==
'y'));
1503 nx = cpl_image_get_size_x(image);
1504 ny = cpl_image_get_size_y(image);
1511 _areas = cpl_matrix_duplicate(areas);
1512 cx_assert(_areas != NULL);
1514 nareas = cpl_matrix_get_nrow(_areas);
1518 for (j = 0; j < nareas; ++j) {
1520 cxint y_1 = (cxint)cpl_matrix_get(_areas, j, 3);
1521 cxint y_0 = (cxint)cpl_matrix_get(_areas, j, 2);
1522 cxint x_1 = (cxint)cpl_matrix_get(_areas, j, 1);
1523 cxint x_0 = (cxint)cpl_matrix_get(_areas, j, 0);
1528 cpl_matrix_set(_areas, j, 0, x_0);
1533 cpl_matrix_set(_areas, j, 1, x_1);
1538 cpl_matrix_set(_areas, j, 2, y_0);
1541 if (y_1 != ny - 1) {
1543 cpl_matrix_set(_areas, j, 3, y_1);
1546 if ((x_1 >= x_0) && (y_1 >= y_0)) {
1547 ntotal += (y_1 - y_0 + 1) * (x_1 - x_0 + 1);
1557 for (j = 0; j < nareas; ++j) {
1559 cxint y_1 = (cxint)cpl_matrix_get(_areas, j, 3);
1560 cxint y_0 = (cxint)cpl_matrix_get(_areas, j, 2);
1561 cxint x_1 = (cxint)cpl_matrix_get(_areas, j, 1);
1562 cxint x_0 = (cxint)cpl_matrix_get(_areas, j, 0);
1567 cpl_matrix_set(_areas, j, 0, x_0);
1572 cpl_matrix_set(_areas, j, 1, x_1);
1577 cpl_matrix_set(_areas, j, 2, y_0);
1582 cpl_matrix_set(_areas, j, 3, y_1);
1585 if ((x_1 >= x_0) && (y_1 >= y_0)) {
1586 ntotal += (y_1 - y_0 + 1) * (x_1 - x_0 + 1);
1596 cpl_msg_info(fctid,
"Bias Areas: Found %zu points in %dx%d image",
1605 results->sigma = 0.;
1608 cx_string_set(results->limits,
"");
1610 profile = cpl_image_new(sx, sy, CPL_TYPE_DOUBLE);
1612 for (j = 0; j < nareas; ++j) {
1614 cxint y_1 = (cxint)cpl_matrix_get(_areas, j, 3);
1615 cxint y_0 = (cxint)cpl_matrix_get(_areas, j, 2);
1616 cxint x_1 = (cxint)cpl_matrix_get(_areas, j, 1);
1617 cxint x_0 = (cxint)cpl_matrix_get(_areas, j, 0);
1619 if ((x_1 >= x_0) && (y_1 >= y_0)) {
1621 cx_string* tmp = cx_string_new();
1624 cx_string_sprintf(tmp,
"%d:%d:%d:%d;", x_0, x_1, y_0, y_1);
1625 cx_string_append(results->limits, cx_string_get(tmp));
1627 cx_string_delete(tmp);
1645 cxint sz = x_1 - x_0 + 1;
1647 cxdouble residual = 0.;
1649 const cxdouble* _img = cpl_image_get_data_double_const(image);
1651 cxdouble* _profile = cpl_image_get_data_double(profile);
1654 for (i = y_0; i < y_1 + 1; ++i) {
1656 register cxint k = i * nx;
1657 register cxint l = 0;
1659 cxdouble m = giraffe_array_mean(&_img[k + x_0], sz);
1661 _profile[i * sx + j] = m;
1663 for (l = x_0; l < x_1 + 1; ++l) {
1664 residual += (_img[k + l] - m) * (_img[k + l] - m);
1675 rms += residual / (sz - 1);
1676 sigma += residual / (sz * (sz - 1));
1682 cxint sz = y_1 - y_0 + 1;
1684 cxdouble residual = 0.;
1686 const cxdouble* _img = cpl_image_get_data_double_const(image);
1688 cxdouble* _profile = cpl_image_get_data_double(profile);
1689 cxdouble* buffer = cx_calloc(sz,
sizeof(cxdouble));
1692 for (i = x_0; i < x_1 + 1; ++i) {
1694 register cxint l = 0;
1696 register cxdouble m = 0.;
1699 for (l = y_0; l < y_1 + 1; ++l) {
1700 buffer[l - y_0] = _img[l * nx + i];
1703 m = giraffe_array_mean(buffer, sz);
1704 _profile[i * sx + j] = m;
1706 for (l = 0; l < sz; ++l) {
1707 residual += (buffer[l] - m) * (buffer[l] - m);
1718 rms += residual / (sz - 1);
1719 sigma += residual / (sz * (sz - 1));
1730 cpl_matrix_delete(_areas);
1738 model = cpl_image_collapse_create(profile, 1);
1740 cpl_image_delete(profile);
1743 cpl_image_divide_scalar(model, nvalid);
1744 results->model = model;
1748 results->mean = cpl_image_get_mean(results->model);
1751 results->rms = sqrt(rms / (sy * nvalid));
1752 results->sigma = sqrt(sigma / sy) / nvalid;
1755 return EXIT_SUCCESS;
1785_giraffe_bias_fit_profile(GiBiasResults* results,
const cpl_image* profile,
1791 cxint sy = cpl_image_get_size_y(profile);
1792 cxint nc = order + 1;
1794 cxdouble* _profile = (cxdouble*)cpl_image_get_data_double_const(profile);
1796 cpl_matrix* base = NULL;
1797 cpl_matrix* baseT = NULL;
1798 cpl_matrix* coeff = NULL;
1799 cpl_matrix* fit = NULL;
1800 cpl_matrix* x = cpl_matrix_new(sy, 1);
1801 cpl_matrix* y = cpl_matrix_wrap(sy, 1, _profile);
1802 cpl_matrix* covy = cpl_matrix_new(sy, sy);
1803 cpl_matrix* covc = cpl_matrix_new(nc, nc);
1806 if ((x == NULL) || (y == NULL) || (covy == NULL) || (covc == NULL)) {
1808 cpl_matrix_delete(covc);
1809 cpl_matrix_delete(covy);
1810 cpl_matrix_unwrap(y);
1811 cpl_matrix_delete(x);
1822 for (i = 0; i < sy; ++i)
1824 cpl_matrix_set(x, i, 0, i);
1827 baseT = giraffe_chebyshev_base1d(0., sy, nc, x);
1828 base = cpl_matrix_transpose_create(baseT);
1830 cpl_matrix_delete(baseT);
1833 cpl_matrix_delete(x);
1837 cpl_matrix_unwrap(y);
1841 cpl_matrix_fill_diagonal(covy, results->rms * results->rms, 0);
1851 cpl_matrix_delete(covy);
1854 if (coeff == NULL) {
1856 cpl_matrix_delete(base);
1859 cpl_matrix_unwrap(y);
1867 fit = cpl_matrix_product_create(base, coeff);
1869 cpl_matrix_delete(coeff);
1872 cpl_matrix_delete(base);
1877 cpl_matrix_unwrap(y);
1889 for (i = 0; i < sy; ++i)
1891 cpl_matrix_set(y, i, 0, cpl_matrix_get(fit, i, 0));
1894 cpl_matrix_delete(fit);
1897 cpl_matrix_unwrap(y);
1907 results->mean = cpl_image_get_mean(results->model);
1908 results->sigma = sqrt(cpl_matrix_get(covc, 0, 0));
1911 cpl_image_save(results->model,
"idiot.fits", CPL_BPP_IEEE_FLOAT,
1919 cpl_matrix_delete(covc);
1922 return EXIT_SUCCESS;
1956_giraffe_bias_compute(GiBiasResults* results, cpl_image* img,
1957 const cpl_matrix* biasareas,
1958 const cpl_image* master_bias,
1959 const cpl_image* bad_pixel_map,
1960 GiBiasMethod method, GiBiasOption option,
1961 GiBiasModel model, cxbool remove_bias, cxdouble mbias,
1962 cxdouble xdeg, cxdouble ydeg, cxdouble xstep,
1963 cxdouble ystep, cxdouble sigma, cxint numiter,
1964 cxdouble maxfraction)
1967 const cxchar*
const fctid =
"giraffe_bias_compute";
1975 cxint master_bias_dimx;
1976 cxint master_bias_dimy;
1977 cxint bad_pixel_dimx;
1978 cxint bad_pixel_dimy;
1980 cxint error_code = 0;
1982 cx_string* s = NULL;
1984 const cpl_matrix* coeff = NULL;
1987 cx_assert(results != NULL);
1988 cx_assert(results->limits == NULL);
1989 cx_assert(results->coeffs == NULL);
1990 cx_assert(results->model == NULL);
1992 cx_assert(img != NULL);
1993 cx_assert(cpl_image_get_type(img) == CPL_TYPE_DOUBLE);
1995 cx_assert(biasareas != NULL);
2002 img_dimx = cpl_image_get_size_x(img);
2003 img_dimy = cpl_image_get_size_y(img);
2005 img_centerx = img_dimx / 2;
2006 img_centery = img_dimy / 2;
2008 results->limits = cx_string_new();
2016 cpl_msg_info(fctid,
"Bias correction will be done.");
2019 cpl_msg_warning(fctid,
"No Bias correction will be done!");
2023 if (model == GIBIAS_MODEL_MEAN) {
2029 cpl_msg_info(fctid,
"Using bias model 'MEAN' ...");
2031 if ((option == GIBIAS_OPTION_PLANE) ||
2032 (method == GIBIAS_METHOD_PLANE)) {
2034 cpl_msg_error(fctid,
"Can not use MEAN model with PLANE method.");
2039 error_code = _giraffe_bias_compute_mean(results, img, biasareas,
2040 sigma, numiter, maxfraction);
2044 else if ((method == GIBIAS_METHOD_CURVE) ||
2045 ((method != GIBIAS_METHOD_PROFILE) &&
2046 (option == GIBIAS_OPTION_CURVE))) {
2053 cpl_msg_info(fctid,
"Using bias model 'CURVE' ...");
2055 error_code = _giraffe_bias_compute_curve(results, img, biasareas,
2056 sigma, numiter, maxfraction, xdeg, ydeg, xstep, ystep);
2058 if (error_code != EXIT_SUCCESS) {
2060 cpl_msg_error(fctid,
"Error during calculation of bias curve, "
2066 coeff = results->coeffs;
2075 cpl_msg_info(fctid,
"Using bias model 'PLANE (FITTED)' ...");
2077 error_code = _giraffe_bias_compute_plane(results, img, biasareas,
2078 sigma, numiter, maxfraction);
2080 if (error_code == EXIT_SUCCESS) {
2082 coeff = results->coeffs;
2084 results->mean = cpl_matrix_get(coeff, 0, 0) +
2085 cpl_matrix_get(coeff, 0, 1) * img_centerx +
2086 cpl_matrix_get(coeff, 0, 2) * img_centery;
2091 cpl_msg_error(fctid,
"Error during calculation of bias plane, "
2104 s = cx_string_new();
2105 _giraffe_method_string(s, method, option);
2107 cpl_msg_info(fctid,
"Using bias method '%s'", cx_string_get(s));
2109 cx_string_delete(s);
2114 case GIBIAS_METHOD_UNIFORM:
2121 if (model == GIBIAS_MODEL_MEAN) {
2123 cpl_msg_info(fctid,
"bias value (areas mean) = %f, "
2124 "bias sigma = %f", results->mean, results->sigma);
2129 cpl_msg_info(fctid,
"bias value at (%d, %d) = %f, "
2130 "bias sigma = %f", img_centerx, img_centery,
2131 results->mean, results->sigma);
2135 if (remove_bias == TRUE) {
2137 cpl_image_subtract_scalar(img, results->mean);
2144 case GIBIAS_METHOD_PLANE:
2147 if (coeff == NULL) {
2149 error_code = _giraffe_bias_compute_plane(results, img,
2150 biasareas, sigma, numiter, maxfraction);
2152 if (error_code == EXIT_SUCCESS) {
2154 coeff = results->coeffs;
2156 results->mean = cpl_matrix_get(coeff, 0, 0) +
2157 cpl_matrix_get(coeff, 0, 1) * img_centerx +
2158 cpl_matrix_get(coeff, 0, 2) * img_centery;
2163 cpl_msg_error(fctid,
"Error during calculation of bias "
2164 "plane, aborting...");
2171 cpl_msg_info(fctid,
"bias value at (%d, %d) = %f, bias sigma = %f, "
2172 "bias plane = %g + %g * x + %g * y", img_centerx,
2173 img_centery, results->mean, results->sigma,
2174 cpl_matrix_get(coeff, 0, 0),
2175 cpl_matrix_get(coeff, 0, 1),
2176 cpl_matrix_get(coeff, 0, 2));
2178 if (remove_bias == TRUE) {
2182 cxdouble* _img = cpl_image_get_data_double(img);
2185 cpl_image* bsmodel = cpl_image_new(img_dimx, img_dimy,
2187 cxdouble* _bsmodel = cpl_image_get_data_double(bsmodel);
2191 for (j = 0; j < img_dimy; j++) {
2193 cxsize jj = j * img_dimx;
2195 for (i = 0; i < img_dimx; i++) {
2198 _bsmodel[jj + i] = cpl_matrix_get(coeff, 0, 0)
2199 + cpl_matrix_get(coeff, 0, 1) * i
2200 + cpl_matrix_get(coeff, 0, 2) * j;
2203 _img[jj + i] -= cpl_matrix_get(coeff, 0, 0)
2204 + cpl_matrix_get(coeff, 0, 1) * i
2205 + cpl_matrix_get(coeff, 0, 2) * j;
2212 cpl_image_save(bsmodel,
"idiot.fits", CPL_BPP_IEEE_FLOAT,
2214 cpl_image_delete(bsmodel);
2223 case GIBIAS_METHOD_CURVE:
2226 if (coeff == NULL) {
2229 _giraffe_bias_compute_curve(results, img, biasareas,
2230 sigma, numiter, maxfraction,
2231 xdeg, ydeg, xstep, ystep);
2233 if (error_code != EXIT_SUCCESS) {
2235 cpl_msg_error(fctid,
"Error during calculation of bias "
2236 "surface curve, aborting...");
2241 coeff = results->coeffs;
2245 cpl_msg_info(fctid,
"bias value %f, bias sigma = %f\n",
2246 results->mean, results->sigma);
2249 if (remove_bias == TRUE) {
2251 cpl_image* bsmodel = NULL;
2253 cpl_matrix* x = cpl_matrix_new(img_dimx * img_dimy, 1);
2254 cpl_matrix* y = cpl_matrix_new(img_dimx * img_dimy, 1);
2255 cpl_matrix* fit = NULL;
2258 for (j = 0; j < img_dimy; ++j) {
2260 register cxsize jj = j * img_dimx;
2262 for (i = 0; i < img_dimx; ++i) {
2264 cpl_matrix_set(x, jj + i, 0, i);
2265 cpl_matrix_set(y, jj + i, 0, j);
2271 fit = giraffe_chebyshev_fit2d(0., 0., img_dimx, img_dimy,
2274 cpl_matrix_delete(y);
2277 cpl_matrix_delete(x);
2280 bsmodel = cpl_image_wrap_double(img_dimx, img_dimy,
2281 cpl_matrix_get_data(fit));
2284 cpl_image_save(bsmodel,
"idiot.fits", CPL_BPP_IEEE_FLOAT,
2288 cpl_image_subtract(img, bsmodel);
2290 cpl_image_unwrap(bsmodel);
2293 cpl_matrix_delete(fit);
2302 case GIBIAS_METHOD_PROFILE:
2305 error_code = _giraffe_bias_compute_profile(results, img,
2308 if (error_code != EXIT_SUCCESS) {
2310 cpl_msg_error(fctid,
"Error computing the bias area(s) "
2316 if (option == GIBIAS_OPTION_CURVE) {
2318 error_code = _giraffe_bias_fit_profile(results, results->model,
2320 if (error_code != EXIT_SUCCESS) {
2322 cpl_msg_error(fctid,
"Error fitting the bias profile");
2329 if (remove_bias == TRUE) {
2331 const cxdouble* _bias =
2332 cpl_image_get_data_double(results->model);
2334 cxdouble* _img = cpl_image_get_data_double(img);
2337 cx_assert(_bias != NULL);
2338 cx_assert(_img != NULL);
2340 for (j = 0; j < img_dimy; ++j) {
2342 cxsize jj = j * img_dimx;
2345 for (i = 0; i < img_dimx; ++i) {
2346 _img[jj + i] -= _bias[j];
2357 case GIBIAS_METHOD_MASTER:
2358 case GIBIAS_METHOD_ZMASTER:
2361 cxdouble biasdrift = 0.;
2363 if (master_bias == NULL) {
2365 cpl_msg_error(fctid,
"Master Bias Frame required with MASTER "
2371 master_bias_dimx = cpl_image_get_size_x(master_bias);
2372 master_bias_dimy = cpl_image_get_size_y(master_bias);
2374 if ((master_bias_dimx != img_dimx) ||
2375 (master_bias_dimy != img_dimy)) {
2377 cpl_msg_error(fctid,
"Invalid master bias! Size should "
2378 "be [%d, %d] but is [%d, %d].", img_dimx, img_dimy,
2379 master_bias_dimx, master_bias_dimy);
2384 if (coeff == NULL) {
2386 if (option == GIBIAS_OPTION_CURVE) {
2388 error_code = _giraffe_bias_compute_curve(results, img,
2389 biasareas, sigma, numiter, maxfraction, xdeg,
2390 ydeg, xstep, ystep);
2392 if (error_code != EXIT_SUCCESS) {
2394 cpl_msg_error(fctid,
"Error during calculation of "
2395 "bias surface curve, aborting...");
2400 coeff = results->coeffs;
2409 error_code = _giraffe_bias_compute_plane(results, img,
2410 biasareas, sigma, numiter, maxfraction);
2412 if (error_code == EXIT_SUCCESS) {
2414 coeff = results->coeffs;
2416 results->mean = cpl_matrix_get(coeff, 0, 0) +
2417 cpl_matrix_get(coeff, 0, 1) * img_centerx +
2418 cpl_matrix_get(coeff, 0, 2) * img_centery;
2423 cpl_msg_error(fctid,
"Error during calculation of "
2424 "bias surface plane, aborting...");
2433 if (method == GIBIAS_METHOD_ZMASTER) {
2441 biasdrift = results->mean - mbias;
2443 cpl_msg_info(fctid,
"Using bias drift value %.4g", biasdrift);
2452 if (option == GIBIAS_OPTION_CURVE) {
2456 cpl_msg_info(fctid,
"Computed bias mean = %.4f, bias "
2457 "sigma = %.4e", results->mean, results->sigma);
2462 if (option == GIBIAS_OPTION_PLANE) {
2464 cpl_msg_info(fctid,
"Bias plane = %.4e + "
2465 "%.4e * x + %.4e * y",
2466 cpl_matrix_get(coeff, 0, 0),
2467 cpl_matrix_get(coeff, 0, 1),
2468 cpl_matrix_get(coeff, 0, 2));
2469 cpl_msg_info(fctid,
"Computed bias mean = %.4f, "
2470 "bias sigma = %.4e at (%d, %d)",
2471 results->mean, results->sigma,
2472 img_centerx, img_centery);
2477 cpl_msg_info(fctid,
"Computed bias mean = %.4f, bias "
2479 results->mean, results->sigma);
2490 if (remove_bias == TRUE) {
2507 if (bad_pixel_map == NULL) {
2509 cpl_image_subtract(img, master_bias);
2511 if (biasdrift != 0.) {
2512 cpl_image_subtract_scalar(img, biasdrift);
2518 bad_pixel_dimx = cpl_image_get_size_x(bad_pixel_map);
2519 bad_pixel_dimy = cpl_image_get_size_y(bad_pixel_map);
2521 if ((bad_pixel_dimx != img_dimx) ||
2522 (bad_pixel_dimy != img_dimy)) {
2524 cpl_msg_error(fctid,
"Invalid bad pixel map size "
2525 "should be [%d, %d] but is [%d, %d].",
2527 bad_pixel_dimx, bad_pixel_dimy);
2532 if (option == GIBIAS_OPTION_CURVE) {
2534 const cxint* _bpix =
2535 cpl_image_get_data_int_const(bad_pixel_map);
2537 const cxdouble* _mbias =
2538 cpl_image_get_data_double_const(master_bias);
2540 cxdouble* _img = cpl_image_get_data_double(img);
2543 cpl_matrix_new(img_dimx * img_dimy, 1);
2545 cpl_matrix_new(img_dimx * img_dimy, 1);
2546 cpl_matrix* fit = NULL;
2549 for (j = 0; j < img_dimy; ++j) {
2551 register cxsize jj = j * img_dimx;
2553 for (i = 0; i < img_dimx; ++i) {
2555 cpl_matrix_set(x, jj + i, 0, i);
2556 cpl_matrix_set(y, jj + i, 0, j);
2561 fit = giraffe_chebyshev_fit2d(0., 0.,
2565 cpl_matrix_delete(y);
2568 cpl_matrix_delete(x);
2572 for (j = 0; j < img_dimy; ++j) {
2574 register cxsize jj = j * img_dimx;
2576 for (i = 0; i < img_dimx; ++i) {
2578 if (!(_bpix[jj + i] & GIR_M_PIX_SET)) {
2580 _img[jj + i] -= (_mbias[jj + i] +
2585 _img[jj + i] -= cpl_matrix_get(fit, i, j);
2592 cpl_matrix_delete(fit);
2596 else if (option == GIBIAS_OPTION_PLANE) {
2598 const cxint* _bpix =
2599 cpl_image_get_data_int_const(bad_pixel_map);
2601 const cxdouble* _mbias =
2602 cpl_image_get_data_double_const(master_bias);
2604 cxdouble* _img = cpl_image_get_data_double(img);
2607 for (j = 0; j < img_dimy; j++) {
2609 cxsize jj = j * img_dimx;
2611 for (i = 0; i < img_dimx; i++) {
2613 if (!(_bpix[jj + i] & GIR_M_PIX_SET)) {
2615 _img[jj + i] -= (_mbias[jj + i] +
2622 cpl_matrix_get(coeff, 0, 0) +
2623 cpl_matrix_get(coeff, 0, 1) * j +
2624 cpl_matrix_get(coeff, 0, 2) * i;
2634 const cxint* _bpix =
2635 cpl_image_get_data_int_const(bad_pixel_map);
2637 const cxdouble* _mbias =
2638 cpl_image_get_data_double_const(master_bias);
2640 cxdouble* _img = cpl_image_get_data_double(img);
2643 for (j = 0; j < img_dimy; j++) {
2645 cxsize jj = j * img_dimx;
2647 for (i = 0; i < img_dimx; i++) {
2649 if (!(_bpix[jj + i] & GIR_M_PIX_SET)) {
2651 _img[jj + i] -= (_mbias[jj + i] +
2657 _img[jj + i] -= results->mean;
2678 cpl_msg_error(fctid,
"Invalid method, aborting...");
2687 cpl_msg_info(fctid,
"Resulting biaslimits : %s",
2688 cx_string_get(results->limits));
2716 const cxchar *
const _id =
"giraffe_get_raw_areas";
2726 cxint32 tprescx = 0;
2727 cxint32 tprescy = 0;
2728 cxint32 tovrscx = 0;
2729 cxint32 tovrscy = 0;
2734 cpl_propertylist *properties;
2739 cpl_error_set(_id, CPL_ERROR_NULL_INPUT);
2743 winx = cpl_propertylist_get_int(properties, GIALIAS_WINX);
2744 winy = cpl_propertylist_get_int(properties, GIALIAS_WINY);
2746 if (cpl_propertylist_has(properties, GIALIAS_PRSCX)) {
2747 tprescx = cpl_propertylist_get_int(properties, GIALIAS_PRSCX);
2752 if (cpl_propertylist_has(properties, GIALIAS_PRSCY)) {
2753 tprescy = cpl_propertylist_get_int(properties, GIALIAS_PRSCY);
2758 if (cpl_propertylist_has(properties, GIALIAS_OVSCX)) {
2759 tovrscx = cpl_propertylist_get_int(properties, GIALIAS_OVSCX);
2764 if (cpl_propertylist_has(properties, GIALIAS_OVSCY)) {
2765 tovrscy = cpl_propertylist_get_int(properties, GIALIAS_OVSCY);
2772 m_tmp = cpl_matrix_new(1, 4);
2776 cpl_matrix_set(m_tmp, row, 0, 0.0);
2777 cpl_matrix_set(m_tmp, row, 1, (cxdouble) prescx - 1);
2778 cpl_matrix_set(m_tmp, row, 2, 0.0);
2779 cpl_matrix_set(m_tmp, row, 3, (cxdouble) winy - 1);
2781 cpl_matrix_resize(m_tmp, 0, 1, 0, 0);
2787 cpl_matrix_set(m_tmp, row, 0, (cxdouble) winx - ovrscx);
2788 cpl_matrix_set(m_tmp, row, 1, (cxdouble) winx - 1);
2789 cpl_matrix_set(m_tmp, row, 2, 0.0);
2790 cpl_matrix_set(m_tmp, row, 3, (cxdouble) winy - 1);
2792 cpl_matrix_resize(m_tmp, 0, 1, 0, 0);
2796 if (!(prescy == 0 || prescx == 0 || ovrscx == 0)) {
2798 cpl_matrix_set(m_tmp, row, 0, (cxdouble) prescx);
2799 cpl_matrix_set(m_tmp, row, 1, (cxdouble) winx - ovrscx - 1);
2800 cpl_matrix_set(m_tmp, row, 2, 0.0);
2801 cpl_matrix_set(m_tmp, row, 3, (cxdouble) prescy - 1);
2803 cpl_matrix_resize(m_tmp, 0, 1, 0, 0);
2807 else if (!(prescy == 0 || prescx == 0)) {
2809 cpl_matrix_set(m_tmp, row, 0, (cxdouble) prescx);
2810 cpl_matrix_set(m_tmp, row, 1, (cxdouble) winx - 1);
2811 cpl_matrix_set(m_tmp, row, 2, 0.0);
2812 cpl_matrix_set(m_tmp, row, 3, (cxdouble) prescy - 1);
2814 cpl_matrix_resize(m_tmp, 0, 1, 0, 0);
2818 else if (!(prescy == 0 || ovrscx == 0)) {
2820 cpl_matrix_set(m_tmp, row, 0, 0.0);
2821 cpl_matrix_set(m_tmp, row, 1, (cxdouble) winx - ovrscx - 1);
2822 cpl_matrix_set(m_tmp, row, 2, 0.0);
2823 cpl_matrix_set(m_tmp, row, 3, (cxdouble) prescy - 1);
2825 cpl_matrix_resize(m_tmp, 0, 1, 0, 0);
2829 else if (prescy > 0) {
2831 cpl_matrix_set(m_tmp, row, 0, 0.0);
2832 cpl_matrix_set(m_tmp, row, 1, (cxdouble) winx - 1);
2833 cpl_matrix_set(m_tmp, row, 2, 0.0);
2834 cpl_matrix_set(m_tmp, row, 3, (cxdouble) prescy - 1);
2836 cpl_matrix_resize(m_tmp, 0, 1, 0, 0);
2840 if (!(ovrscy == 0 || prescx == 0 || ovrscx == 0)) {
2842 cpl_matrix_set(m_tmp, row, 0, (cxdouble) prescx);
2843 cpl_matrix_set(m_tmp, row, 1, (cxdouble) winx - ovrscx - 1);
2844 cpl_matrix_set(m_tmp, row, 2, (cxdouble) winy - ovrscy);
2845 cpl_matrix_set(m_tmp, row, 3, (cxdouble) winy - 1);
2847 cpl_matrix_resize(m_tmp, 0, 1, 0, 0);
2851 else if (!(ovrscy == 0 || prescx == 0)) {
2853 cpl_matrix_set(m_tmp, row, 0, (cxdouble) prescx);
2854 cpl_matrix_set(m_tmp, row, 1, (cxdouble) winx - 1);
2855 cpl_matrix_set(m_tmp, row, 2, (cxdouble) winy - ovrscy);
2856 cpl_matrix_set(m_tmp, row, 3, (cxdouble) winy - 1);
2858 cpl_matrix_resize(m_tmp, 0, 1, 0, 0);
2862 else if (!(ovrscy == 0 || ovrscx == 0)) {
2864 cpl_matrix_set(m_tmp, row, 0, 0.0);
2865 cpl_matrix_set(m_tmp, row, 1, (cxdouble) winx - ovrscx - 1);
2866 cpl_matrix_set(m_tmp, row, 2, (cxdouble) winy - ovrscy);
2867 cpl_matrix_set(m_tmp, row, 3, (cxdouble) winy - 1);
2869 cpl_matrix_resize(m_tmp, 0, 1, 0, 0);
2873 else if (ovrscy > 0) {
2875 cpl_matrix_set(m_tmp, row, 0, 0.0);
2876 cpl_matrix_set(m_tmp, row, 1, (cxdouble) winx - 1);
2877 cpl_matrix_set(m_tmp, row, 2, (cxdouble) winy - ovrscy);
2878 cpl_matrix_set(m_tmp, row, 3, (cxdouble) winy - 1);
2880 cpl_matrix_resize(m_tmp, 0, 1, 0, 0);
2884 cpl_matrix_resize(m_tmp, 0, -1, 0, 0);
2888 cpl_matrix_delete(m_tmp);
2918 const cxchar *fctid =
"giraffe_trim_raw_areas";
2921 cxint newlx, newly, newux, newuy;
2935 cpl_msg_error(fctid,
"Image does not contain any properties!");
2939 nx = cpl_image_get_size_x(_image);
2940 ny = cpl_image_get_size_y(_image);
2942 if (cpl_propertylist_has(properties, GIALIAS_NAXIS1)) {
2943 cxint _nx = cpl_propertylist_get_int(properties, GIALIAS_NAXIS1);
2946 cpl_msg_warning(fctid,
"Image size (%d) and image property `%s' "
2947 "(%d) are not consistent! Using image size ...",
2948 nx, GIALIAS_NAXIS1, _nx);
2952 cpl_msg_warning(fctid,
"Image does not contain any property `%s'. "
2953 "Using image size (%d)", GIALIAS_NAXIS1, nx);
2957 if (cpl_propertylist_has(properties, GIALIAS_NAXIS2)) {
2958 cxint _ny = cpl_propertylist_get_int(properties, GIALIAS_NAXIS2);
2961 cpl_msg_warning(fctid,
"Image size (%d) and image property `%s' "
2962 "(%d) are not consistent! Using image size ...",
2963 ny, GIALIAS_NAXIS2, _ny);
2967 cpl_msg_warning(fctid,
"Image does not contain any property `%s'. "
2968 "Using image size (%d)", GIALIAS_NAXIS2, ny);
2971 if (cpl_propertylist_has(properties, GIALIAS_OVSCX)) {
2972 ovscx = cpl_propertylist_get_int(properties, GIALIAS_OVSCX);
2975 if (cpl_propertylist_has(properties, GIALIAS_OVSCY)) {
2976 ovscy = cpl_propertylist_get_int(properties, GIALIAS_OVSCY);
2979 if (cpl_propertylist_has(properties, GIALIAS_PRSCX)) {
2980 prscx = cpl_propertylist_get_int(properties, GIALIAS_PRSCX);
2983 if (cpl_propertylist_has(properties, GIALIAS_PRSCY)) {
2984 prscy = cpl_propertylist_get_int(properties, GIALIAS_PRSCY);
2996 tmp = cpl_image_extract(_image, newlx, newly, newux, newuy);
2999 cpl_image_delete(tmp);
3003 nx = cpl_image_get_size_x(_image);
3004 ny = cpl_image_get_size_y(_image);
3011 cpl_propertylist_set_int(properties, GIALIAS_NAXIS1, nx);
3012 cpl_propertylist_set_int(properties, GIALIAS_NAXIS2, ny);
3014 if (cpl_propertylist_has(properties, GIALIAS_CRPIX1)) {
3015 cxdouble crpix1 = cpl_propertylist_get_double(properties,
3023 crpix1 += (cxdouble)prscx;
3024 cpl_propertylist_set_double(properties, GIALIAS_CRPIX1, crpix1);
3027 if (cpl_propertylist_has(properties, GIALIAS_CRPIX2)) {
3028 cxdouble crpix2 = cpl_propertylist_get_double(properties,
3031 crpix2 -= (cxdouble) prscy;
3032 cpl_propertylist_set_double(properties, GIALIAS_CRPIX2, crpix2);
3035 cpl_propertylist_erase(properties, GIALIAS_OVSCX);
3036 cpl_propertylist_erase(properties, GIALIAS_OVSCY);
3037 cpl_propertylist_erase(properties, GIALIAS_PRSCX);
3038 cpl_propertylist_erase(properties, GIALIAS_PRSCY);
3108 const GiImage* master_bias,
const GiImage* bad_pixels,
3109 const cpl_matrix* biaslimits,
const GiBiasConfig* config)
3112 const cxchar*
const fctid =
"giraffe_bias_remove";
3116 cxdouble bias_value = 0.;
3120 cpl_matrix* areas = NULL;
3127 cpl_propertylist* properties;
3129 GiBiasResults bias_results = {0., 0., 0., NULL, NULL, NULL};
3132 cx_assert(raw != NULL);
3133 cx_assert(config != NULL);
3134 cx_assert(biaslimits == NULL);
3136 if (result == NULL) {
3145 if (strncmp(config->areas,
"None", 4) == 0) {
3147 cpl_msg_info(fctid,
"No bias areas specified, using pre/overscan"
3148 "regions of the raw frame.");
3152 if (areas == NULL) {
3153 if (cpl_error_get_code() == CPL_ERROR_NULL_INPUT) {
3154 cpl_msg_error(fctid,
"Invalid raw image! Image does not "
3155 "contain any properties!");
3158 cpl_msg_error(fctid,
"Invalid raw image! Image does not "
3159 "contain or has invalid pre- and overscan "
3169 areas = _giraffe_bias_get_areas(config->areas);
3171 if (areas == NULL) {
3173 cpl_msg_error(fctid,
"Invalid bias area specification '%s'!",
3179 cpl_msg_info(fctid,
"Using bias area(s) '%s' for bias computation",
3195 if (master_bias != NULL) {
3196 cpl_propertylist *_properties;
3197 cxbool is_same_size = FALSE;
3199 is_same_size = _giraffe_compare_overscans(raw, master_bias);
3206 if (is_same_size==FALSE) {
3207 cpl_msg_info(fctid,
"PRE/OVRSCAN Regions do not match between "
3208 "RAW Image and Masterbias Image.");
3215 if (cpl_propertylist_has(_properties, GIALIAS_BIASVALUE)) {
3216 bias_value = cpl_propertylist_get_double(_properties,
3227 if (bad_pixels != NULL) {
3228 cxbool is_same_size = FALSE;
3230 is_same_size = _giraffe_compare_overscans(raw, bad_pixels);
3237 if (is_same_size == FALSE) {
3238 cpl_msg_info(fctid,
"PRE/OVRSCAN Regions do not match between "
3239 "RAW Image and Bad Pixel Image.");
3254 timage = cpl_image_duplicate(_raw);
3262 error_code = _giraffe_bias_compute(&bias_results, timage,
3263 areas, _master_bias,
3264 _bad_pixels, config->method,
3265 config->option, config->model,
3266 config->remove, bias_value,
3267 config->xdeg, config->ydeg,
3268 config->xstep, config->ystep,
3269 config->sigma, config->iterations,
3272 cpl_matrix_delete(areas);
3282 _giraffe_biasresults_clear(&bias_results);
3284 cpl_msg_error(fctid,
"Bias computation failed with error %d!",
3297 if (config->remove == TRUE) {
3300 cpl_image_delete(timage);
3307 cpl_image_delete(timage);
3321 if (config->remove == TRUE) {
3323 cpl_propertylist_set_int(properties, GIALIAS_BITPIX, -32);
3324 cpl_propertylist_set_double(properties, GIALIAS_BZERO, 0.);
3325 cpl_propertylist_set_double(properties, GIALIAS_BSCALE, 1.);
3327 if (cpl_propertylist_has(properties, GIALIAS_GIRFTYPE)) {
3328 cpl_propertylist_set_string(properties,
3329 GIALIAS_GIRFTYPE,
"BRMIMG");
3332 cpl_propertylist_append_string(properties,
3333 GIALIAS_GIRFTYPE,
"BRMIMG");
3335 cpl_propertylist_set_comment(properties, GIALIAS_GIRFTYPE,
3336 "GIRAFFE bias subtracted frame");
3353 if (cpl_propertylist_has(properties, GIALIAS_CONAD)) {
3354 cxdouble conad = cpl_propertylist_get_double(properties, GIALIAS_CONAD);
3360 cpl_msg_info(fctid,
"Converting bias subtracted frame to "
3361 "electrons; conversion factor is %.2f e-/ADU",
3363 cpl_image_multiply_scalar(_result, conad);
3366 cpl_msg_warning(fctid,
"Invalid conversion factor %.2f "
3367 "e-/ADU! Bias subtracted image will not be "
3368 "converted.", conad);
3372 cpl_msg_info(fctid,
"Conversion factor not found. Bias subtracted "
3373 "image will remain in ADU");
3378 s = cx_string_new();
3380 _giraffe_method_string(s, config->method, config->option);
3381 cpl_propertylist_append_string(properties, GIALIAS_BIASMETHOD, cx_string_get(s));
3383 cx_string_delete(s);
3385 cpl_propertylist_append_double(properties, GIALIAS_BIASVALUE,
3387 cpl_propertylist_append_double(properties, GIALIAS_BIASERROR,
3388 bias_results.sigma);
3389 cpl_propertylist_append_double(properties, GIALIAS_BIASSIGMA,
3392 if (bias_results.coeffs) {
3393 cpl_propertylist_append_double(properties, GIALIAS_BCLIPSIGMA,
3395 cpl_propertylist_append_int(properties, GIALIAS_BCLIPNITER,
3396 config->iterations);
3397 cpl_propertylist_append_double(properties, GIALIAS_BCLIPMFRAC,
3401 if (bias_results.limits) {
3402 cpl_propertylist_append_string(properties, GIALIAS_BIASAREAS,
3403 cx_string_get(bias_results.limits));
3406 if (bias_results.coeffs) {
3407 s = cx_string_new();
3409 _giraffe_stringify_coefficients(s, bias_results.coeffs);
3410 cpl_propertylist_append_string(properties, GIALIAS_BIASPLANE,
3413 cx_string_delete(s);
3421 _giraffe_biasresults_clear(&bias_results);
3445 GiBiasConfig* config = NULL;
3452 config = cx_calloc(1,
sizeof *config);
3459 config->method = GIBIAS_METHOD_UNDEFINED;
3460 config->option = GIBIAS_OPTION_UNDEFINED;
3461 config->model = GIBIAS_MODEL_UNDEFINED;
3467 p = cpl_parameterlist_find(list,
"giraffe.biasremoval.remove");
3468 config->remove = cpl_parameter_get_bool(p);
3470 p = cpl_parameterlist_find(list,
"giraffe.biasremoval.method");
3471 s = cpl_parameter_get_string(p);
3473 if (!strcmp(s,
"UNIFORM")) {
3474 config->method = GIBIAS_METHOD_UNIFORM;
3477 if (!strcmp(s,
"PLANE")) {
3478 config->method = GIBIAS_METHOD_PLANE;
3481 if (!strcmp(s,
"CURVE")) {
3482 config->method = GIBIAS_METHOD_CURVE;
3485 if (!strcmp(s,
"PROFILE")) {
3486 config->method = GIBIAS_METHOD_PROFILE;
3489 if (!strcmp(s,
"MASTER")) {
3490 config->method = GIBIAS_METHOD_MASTER;
3493 if (!strcmp(s,
"ZMASTER")) {
3494 config->method = GIBIAS_METHOD_ZMASTER;
3497 if (!strcmp(s,
"PROFILE+CURVE")) {
3498 config->method = GIBIAS_METHOD_PROFILE;
3499 config->option = GIBIAS_OPTION_CURVE;
3502 if (!strcmp(s,
"MASTER+PLANE")) {
3503 config->method = GIBIAS_METHOD_MASTER;
3504 config->option = GIBIAS_OPTION_PLANE;
3507 if (!strcmp(s,
"ZMASTER+PLANE")) {
3508 config->method = GIBIAS_METHOD_ZMASTER;
3509 config->option = GIBIAS_OPTION_PLANE;
3512 if (!strcmp(s,
"MASTER+CURVE")) {
3513 config->method = GIBIAS_METHOD_MASTER;
3514 config->option = GIBIAS_OPTION_CURVE;
3517 if (!strcmp(s,
"ZMASTER+CURVE")) {
3518 config->method = GIBIAS_METHOD_ZMASTER;
3519 config->option = GIBIAS_OPTION_CURVE;
3522 cx_assert(config->method != GIBIAS_METHOD_UNDEFINED);
3524 p = cpl_parameterlist_find(list,
"giraffe.biasremoval.areas");
3525 s = cpl_parameter_get_string(p);
3526 config->areas = cx_strdup(s);
3528 p = cpl_parameterlist_find(list,
"giraffe.biasremoval.sigma");
3529 config->sigma = cpl_parameter_get_double(p);
3531 p = cpl_parameterlist_find(list,
"giraffe.biasremoval.iterations");
3532 config->iterations = cpl_parameter_get_int(p);
3534 p = cpl_parameterlist_find(list,
"giraffe.biasremoval.fraction");
3535 config->fraction = cpl_parameter_get_double(p);
3537 if (config->method == GIBIAS_METHOD_CURVE ||
3538 config->option == GIBIAS_OPTION_CURVE) {
3539 p = cpl_parameterlist_find(list,
"giraffe.biasremoval.xorder");
3540 config->xdeg = 1 + cpl_parameter_get_int(p);
3542 p = cpl_parameterlist_find(list,
"giraffe.biasremoval.yorder");
3543 config->ydeg = 1 + cpl_parameter_get_int(p);
3546 p = cpl_parameterlist_find(list,
"giraffe.biasremoval.xstep");
3547 config->xstep = cpl_parameter_get_int(p);
3549 p = cpl_parameterlist_find(list,
"giraffe.biasremoval.ystep");
3550 config->ystep = cpl_parameter_get_int(p);
3574 if (config->areas) {
3575 cx_free(config->areas);
3576 config->areas = NULL;
3608 p = cpl_parameter_new_value(
"giraffe.biasremoval.remove",
3610 "Enable bias removal",
3611 "giraffe.biasremoval",
3613 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"remove-bias");
3614 cpl_parameterlist_append(list, p);
3617 p = cpl_parameter_new_enum(
"giraffe.biasremoval.method",
3619 "Bias removal method",
3620 "giraffe.biasremoval",
3621 "PROFILE", 11,
"UNIFORM",
"PLANE",
"CURVE",
3622 "PROFILE",
"MASTER",
"ZMASTER",
"PROFILE+CURVE",
3623 "MASTER+PLANE",
"MASTER+CURVE",
"ZMASTER+PLANE",
3625 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"bsremove-method");
3626 cpl_parameterlist_append(list, p);
3629 p = cpl_parameter_new_value(
"giraffe.biasremoval.areas",
3631 "Bias areas to use "
3632 "(Xl0:Xr0:Yl0:Yr0, ... ,Xln:Xrn:Yln:Yrn)",
3633 "giraffe.biasremoval",
3635 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"bsremove-areas");
3636 cpl_parameterlist_append(list, p);
3639 p = cpl_parameter_new_value(
"giraffe.biasremoval.sigma",
3641 "Sigma Clipping: sigma threshold factor",
3642 "giraffe.biasremoval",
3644 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"bsremove-sigma");
3645 cpl_parameterlist_append(list, p);
3648 p = cpl_parameter_new_value(
"giraffe.biasremoval.iterations",
3650 "Sigma Clipping: maximum number of "
3652 "giraffe.biasremoval",
3654 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"bsremove-niter");
3655 cpl_parameterlist_append(list, p);
3658 p = cpl_parameter_new_value(
"giraffe.biasremoval.fraction",
3660 "Sigma Clipping: minimum fraction of points "
3661 "accepted/total [0.0..1.0]",
3662 "giraffe.biasremoval",
3664 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"bsremove-mfrac");
3665 cpl_parameterlist_append(list, p);
3668 p = cpl_parameter_new_value(
"giraffe.biasremoval.xorder",
3670 "Order of X polynomial fit (CURVE method "
3672 "giraffe.biasremoval",
3674 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"bsremove-xorder");
3675 cpl_parameterlist_append(list, p);
3677 p = cpl_parameter_new_value(
"giraffe.biasremoval.yorder",
3679 "Order of Y polynomial fit (CURVE method "
3681 "giraffe.biasremoval",
3683 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"bsremove-yorder");
3684 cpl_parameterlist_append(list, p);
3687 p = cpl_parameter_new_value(
"giraffe.biasremoval.xstep",
3689 "Sampling step along X (CURVE method only)",
3690 "giraffe.biasremoval",
3692 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"bsremove-xstep");
3693 cpl_parameterlist_append(list, p);
3696 p = cpl_parameter_new_value(
"giraffe.biasremoval.ystep",
3698 "Sampling step along Y (CURVE method only)",
3699 "giraffe.biasremoval",
3701 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"bsremove-ystep");
3702 cpl_parameterlist_append(list, p);
cxint giraffe_trim_raw_areas(GiImage *image)
Remove pre- and overscan ares from an image.
GiBiasConfig * giraffe_bias_config_create(cpl_parameterlist *list)
Creates a setup structure for a bias removal task.
void giraffe_bias_config_add(cpl_parameterlist *list)
Adds parameters for the bias removal.
cxint giraffe_bias_remove(GiImage *result, const GiImage *raw, const GiImage *master_bias, const GiImage *bad_pixels, const cpl_matrix *biaslimits, const GiBiasConfig *config)
Removes the bias from an image.
cpl_matrix * giraffe_get_raw_areas(const GiImage *image)
Create bias areas from an image.
void giraffe_bias_config_destroy(GiBiasConfig *config)
Destroys a bias removal setup structure.
cpl_image * giraffe_image_get(const GiImage *self)
Gets the image data.
cpl_propertylist * giraffe_image_get_properties(const GiImage *self)
Get the properties of an image.
cxint giraffe_image_set(GiImage *self, cpl_image *image)
Sets the image data.
cxint giraffe_image_set_properties(GiImage *self, cpl_propertylist *properties)
Attaches a property list to an image.
cpl_matrix * giraffe_matrix_solve_cholesky(const cpl_matrix *A, const cpl_matrix *b, const cpl_matrix *Cb, cpl_matrix *Cx)
Solve a linear system using the Cholesky decomposition.
cxdouble giraffe_matrix_sigma_fit(const cpl_matrix *matrix, const cpl_matrix *matrix_fit)
Compute sigma of matrix fit.
cpl_matrix * giraffe_matrix_leastsq(const cpl_matrix *mA, const cpl_matrix *mB)
Computes the solution of an equation using a pseudo-inverse.
cxdouble giraffe_matrix_sigma_mean(const cpl_matrix *matrix, cxdouble mean)
Compute sigma of matrix elements, with a given mean value.