26 #include <cxmessages.h>
29 #include <cpl_recipe.h>
30 #include <cpl_plugininfo.h>
31 #include <cpl_parameterlist.h>
32 #include <cpl_frameset.h>
33 #include <cpl_propertylist.h>
34 #include <cpl_vector.h>
46 #include "gistacking.h"
51 #define GIMASTERBIAS_BIAS_EXTENSION_IMG 0
52 #define GIMASTERBIAS_BIAS_EXTENSION_PL 0
53 #define GIMASTERBIAS_BAD_PIXEL_EXTENSION 0
56 struct GiMasterbiasConfig {
58 cxbool removeoverscan;
59 cxbool correctbadpixels;
69 typedef struct GiMasterbiasConfig GiMasterbiasConfig;
71 static cxint gimasterbias(cpl_parameterlist*, cpl_frameset*);
72 static cxint giqcmasterbias(cpl_frameset*);
79 static cxdouble max_bpx_fraction = 0.15;
88 gimasterbias_create(cpl_plugin* plugin)
91 cpl_recipe* recipe = (cpl_recipe*)plugin;
105 recipe->parameters = cpl_parameterlist_new();
106 cx_assert(recipe->parameters != NULL);
118 p = cpl_parameter_new_value(
"giraffe.masterbias.overscan.remove",
120 "Remove pre- and over-scan regions from "
121 "the created master bias image.",
122 "giraffe.masterbias.overscan",
124 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"mbias-oscremove");
125 cpl_parameterlist_append(recipe->parameters, p);
127 p = cpl_parameter_new_value(
"giraffe.masterbias.badpixel.clean",
129 "Correct master bias image for bad pixels",
130 "giraffe.masterbias.badpixel",
132 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"mbias-bpxclean");
133 cpl_parameterlist_append(recipe->parameters, p);
135 p = cpl_parameter_new_value(
"giraffe.masterbias.bpm.create",
137 "Create bad pixel map using a simple "
138 "thresholding algorithm. (temporary!)",
139 "giraffe.masterbias.bpm",
141 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"bpm-create");
142 cpl_parameterlist_append(recipe->parameters, p);
144 p = cpl_parameter_new_value(
"giraffe.masterbias.bpm.factor",
146 "Readout noise multiplier defining the "
147 "valid range of pixel values for searching "
149 "giraffe.masterbias.bpm",
151 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"bpm-factor");
152 cpl_parameterlist_append(recipe->parameters, p);
154 p = cpl_parameter_new_value(
"giraffe.masterbias.bpm.fraction",
156 "Maximum fraction of pixels which may be "
157 "flagged as 'bad. If more pixels are "
158 "found to be 'bad a warning is issued.",
159 "giraffe.masterbias.bpm",
161 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"bpm-frac");
162 cpl_parameterlist_append(recipe->parameters, p);
173 gimasterbias_exec(cpl_plugin* plugin)
176 cpl_recipe* recipe = (cpl_recipe*)plugin;
181 if (recipe->parameters == NULL || recipe->frames == NULL) {
185 status = gimasterbias(recipe->parameters, recipe->frames);
191 status = giqcmasterbias(recipe->frames);
203 gimasterbias_destroy(cpl_plugin* plugin)
206 cpl_recipe* recipe = (cpl_recipe*)plugin;
215 cpl_parameterlist_delete(recipe->parameters);
217 giraffe_error_clear();
228 gimasterbias_remove_badpixels(GiImage* img, GiImage* img_badpixels)
231 const cxchar*
const fctid =
"gimasterbias_remove_badpixels";
238 register cxint nr_pairs;
248 cxint search_horizon = 100;
252 cxint sx[] = { 0, 1, 1, 1 };
253 cxint sy[] = { 1,-1, 0, 1 };
256 cxlong nr_bad_pixels = 0L;
262 cxdouble* pd_img = NULL;
264 cxdouble estimate[4];
269 cpl_msg_error(fctid,
"NULL Image as input, aborting..." );
273 if (!img_badpixels) {
274 cpl_msg_error(fctid,
"NULL Bad Pixel Image as input, aborting..." );
280 npix_bp = ncol_bp * nrow_bp;
285 for (n=0; n<npix_bp; n++) {
290 if (((cxdouble)nr_bad_pixels / (cxdouble)npix_bp) >= max_bpx_fraction) {
291 cpl_msg_error(fctid,
"Too many bad pixels, aborting..." );
299 for (badx=0; badx<ncol_bp; badx++) {
300 for (bady=0; bady<nrow_bp; bady++) {
301 if (pi_bp[badx + bady * ncol_bp]==1) {
303 for (j=0; j<4; j++) {
304 estimate[nr_pairs] = 0.0;
307 for (k=0; k<2; k++) {
315 if (cx<0 || cx>=ncol_bp || cy<0 || cy>=nrow_bp)
318 }
while (pi_bp[cx+cy*ncol_bp] && (d<search_horizon));
320 if (cx>=0 && cx<ncol_bp && cy>=0 && cy<nrow_bp &&
323 save = pd_img[cx+cy*ncol_bp];
324 estimate[nr_pairs] += save / d;
325 sumd += 1.0 / (cxdouble) d;
327 estimate[nr_pairs] /= sumd;
335 estimate[nr_pairs] = save;
339 cpl_vector* _estimate =
340 cpl_vector_wrap(nr_pairs,
343 pd_img[badx+bady*ncol_bp] =
344 cpl_vector_get_median(_estimate);
346 cpl_vector_unwrap(_estimate);
349 }
else if (nr_pairs==2) {
350 pd_img[badx+bady*ncol_bp] =
351 (estimate[0]+estimate[1]) * 0.5;
352 }
else if (nr_pairs==1) {
353 pd_img[badx+bady*ncol_bp] =
358 "Can't correct badpixel [%d,%d]",
383 gimasterbias(cpl_parameterlist* config, cpl_frameset* set)
386 const cxchar*
const fctid =
"gimasterbias";
389 cxint raw_bias_count = 0;
390 cxint bad_pixel_count = 0;
396 cpl_propertylist* properties = NULL;
398 cpl_frame* curr_frame = NULL;
399 cpl_frame* bad_pixel_frame = NULL;
400 cpl_frame* product_frame = NULL;
402 cpl_parameter* p = NULL;
404 GiImage** raw_bias_list = NULL;
405 GiImage* bad_pixels = NULL;
406 GiImage* master_bias = NULL;
408 GiMasterbiasConfig mbias_config;
410 GiStackingConfig* stack_config = NULL;
412 GiRecipeInfo info = {(cxchar*)fctid, 1, NULL, config};
414 GiGroupInfo groups[] = {
415 {GIFRAME_BIAS, CPL_FRAME_GROUP_RAW},
416 {GIFRAME_BADPIXEL_MAP, CPL_FRAME_GROUP_CALIB},
417 {NULL, CPL_FRAME_GROUP_NONE}
425 p = cpl_parameterlist_find(config,
"giraffe.masterbias.overscan.remove");
426 mbias_config.removeoverscan = cpl_parameter_get_bool(p);
428 p = cpl_parameterlist_find(config,
"giraffe.masterbias.badpixel.clean");
429 mbias_config.correctbadpixels = cpl_parameter_get_bool(p);
431 p = cpl_parameterlist_find(config,
"giraffe.masterbias.bpm.create");
432 mbias_config.bpm.create = cpl_parameter_get_bool(p);
434 p = cpl_parameterlist_find(config,
"giraffe.masterbias.bpm.factor");
435 mbias_config.bpm.factor = cpl_parameter_get_double(p);
437 p = cpl_parameterlist_find(config,
"giraffe.masterbias.bpm.fraction");
438 mbias_config.bpm.fraction = cpl_parameter_get_double(p);
441 e_code = giraffe_frameset_set_groups(set, groups);
444 cpl_msg_error(fctid,
"Setting frame group information failed!");
456 raw_bias_count = cpl_frameset_count_tags(set, GIFRAME_BIAS);
458 if (raw_bias_count < stack_config->min_nr_frames) {
459 cpl_msg_error(fctid,
"Not enough raw bias Images [%d, need %d], "
460 "aborting...", raw_bias_count,
461 stack_config->min_nr_frames);
469 bad_pixel_count = cpl_frameset_count_tags(set, GIFRAME_BADPIXEL_MAP);
471 if (mbias_config.correctbadpixels == TRUE) {
472 if (bad_pixel_count != 1) {
473 cpl_msg_error(fctid,
"Invalid number of bad pixel Images "
474 "[%d instead of 1], aborting...", bad_pixel_count);
483 cpl_msg_info(fctid,
"Creating master bias from %d bias frames ...",
489 raw_bias_list = (GiImage**)cx_calloc(raw_bias_count + 1,
sizeof(GiImage*));
491 raw_bias_list[raw_bias_count] = NULL;
493 curr_frame = cpl_frameset_find(set, GIFRAME_BIAS);
495 for (i = 0; i < raw_bias_count; ++i) {
500 cpl_frame_get_filename(curr_frame),
501 GIMASTERBIAS_BIAS_EXTENSION_IMG);
505 cpl_msg_error(fctid,
"Could not load raw Bias Image [%s], "
506 "aborting...", cpl_frame_get_filename(curr_frame));
508 for (j = 0; j <= i; ++j) {
509 if (raw_bias_list[j] != NULL) {
511 raw_bias_list[j] = NULL;
515 cx_free(raw_bias_list);
524 curr_frame = cpl_frameset_find(set, NULL);
528 if (mbias_config.correctbadpixels == TRUE) {
532 bad_pixel_frame = cpl_frameset_find(set, GIFRAME_BADPIXEL_MAP);
534 cpl_msg_info(fctid,
"Bad Pixel Frame is : %s.",
535 cpl_frame_get_filename(bad_pixel_frame));
540 cpl_frame_get_filename(bad_pixel_frame),
541 GIMASTERBIAS_BAD_PIXEL_EXTENSION);
544 cpl_msg_error(fctid,
"Could not load Bad Pixel Image [%s], "
546 cpl_frame_get_filename(bad_pixel_frame));
548 for (j = 0; j < raw_bias_count; j++) {
549 if (raw_bias_list[j] != NULL) {
554 cx_free(raw_bias_list);
570 if (master_bias == NULL) {
571 cpl_msg_error(fctid,
"Stacking of raw bias frames failed! "
572 "No master bias was created, aborting...");
574 for (j = 0; j < raw_bias_count; j++) {
575 if (raw_bias_list[j] != NULL) {
580 cx_free(raw_bias_list);
582 if (bad_pixels != NULL) {
604 if (mbias_config.correctbadpixels == TRUE) {
606 cpl_msg_info(fctid,
"Cleaning bad pixels on created "
607 "master bias image.");
609 if (gimasterbias_remove_badpixels(master_bias, bad_pixels) != 0) {
611 cpl_msg_error(fctid,
"Bad pixel cleaning failed, aborting...");
613 for (j = 0; j < raw_bias_count; j++) {
614 if (raw_bias_list[j] != NULL) {
619 cx_free(raw_bias_list);
621 if (bad_pixels != NULL) {
625 if (master_bias != NULL) {
638 if (mbias_config.removeoverscan == TRUE) {
640 cpl_msg_info(fctid,
"Removing overscan areas from "
641 "master bias image");
645 cpl_msg_error(fctid,
"Removing overscan areas from master "
646 "bias failed, aborting...");
648 for (j = 0; j < raw_bias_count; j++) {
649 if (raw_bias_list[j] != NULL) {
654 cx_free(raw_bias_list);
656 if (bad_pixels != NULL) {
660 if (master_bias != NULL) {
675 cpl_msg_info(fctid,
"Writing master bias image ...");
678 cx_assert(properties != NULL);
680 cpl_propertylist_update_double(properties, GIALIAS_CRPIX1, 1.);
682 cpl_propertylist_update_double(properties, GIALIAS_EXPTTOT, 0.0);
683 cpl_propertylist_update_int(properties, GIALIAS_DATANCOM, raw_bias_count);
684 cpl_propertylist_update_double(properties, GIALIAS_BZERO, 0.0);
686 cpl_propertylist_update_double(properties, GIALIAS_BIASVALUE,
688 cpl_propertylist_update_double(properties, GIALIAS_BIASSIGMA,
691 cpl_propertylist_erase(properties, GIALIAS_EXPTIME);
692 cpl_propertylist_erase(properties, GIALIAS_TPLEXPNO);
699 for (j = 0; j < raw_bias_count; j++) {
700 if (raw_bias_list[j] != NULL) {
705 cx_free(raw_bias_list);
706 raw_bias_list = NULL;
708 if (bad_pixels != NULL) {
718 CPL_FRAME_LEVEL_FINAL,
721 if (product_frame == NULL) {
723 cpl_msg_error(fctid,
"Cannot create local file! Aborting ...");
725 if (master_bias != NULL) {
733 cpl_frameset_insert(set, product_frame);
741 if ((mbias_config.bpm.create == TRUE) && (master_bias != NULL)
742 && (bad_pixel_count == 0)) {
746 const cxdouble* pd_mbias =
747 cpl_image_get_data_double_const(_master_bias);
753 cxint ncol = cpl_image_get_size_x(_master_bias);
754 cxint nrow = cpl_image_get_size_y(_master_bias);
755 cxint* pi_bpm = NULL;
757 cxlong npix = ncol * nrow;
759 cxlong nbpx_max = (cxlong)(mbias_config.bpm.fraction * npix + 0.5);
761 cxdouble median = 0.;
762 cxdouble median_max = CX_MINDOUBLE;
763 cxdouble median_min = CX_MAXDOUBLE;
771 cpl_msg_info(fctid,
"Creating bad pixel map from master bias "
795 if ((cpl_propertylist_has(properties, GIALIAS_PRSCX) == TRUE) ||
796 (cpl_propertylist_has(properties, GIALIAS_OVSCX) == TRUE)) {
800 if (cpl_propertylist_has(properties, GIALIAS_PRSCX) == TRUE) {
802 cxint xsz = cpl_propertylist_get_int(properties,
808 for (i = 0; i < nrow; ++i) {
810 register cxint stride = i * ncol;
812 cxdouble scx_mean = giraffe_array_mean(pd_mbias + stride,
815 for (j = 0; j < xsz; ++j) {
816 sdev += (pd_mbias[stride + j] - scx_mean) *
817 (pd_mbias[stride + j] - scx_mean);
822 ron = sqrt(sdev / (cxdouble)(nrow * xsz - 1));
827 if (cpl_propertylist_has(properties, GIALIAS_OVSCX) == TRUE) {
829 cxint xsz = cpl_propertylist_get_int(properties,
835 for (i = 0; i < nrow; ++i) {
837 register cxint stride = (i + 1) * ncol - xsz;
839 cxdouble scx_mean = giraffe_array_mean(pd_mbias + stride,
842 for (j = 0; j < xsz; ++j) {
843 sdev += (pd_mbias[stride + j] - scx_mean) *
844 (pd_mbias[stride + j] - scx_mean);
849 ron += sqrt(sdev / (cxdouble)(nrow * xsz - 1));
854 ron /= (cxdouble)nvalues;
859 if (cpl_propertylist_has(properties, GIALIAS_RON)) {
864 ron = cpl_propertylist_get_double(properties, GIALIAS_RON);
866 giraffe_error_push();
870 if (cpl_error_get_code() != CPL_ERROR_NONE) {
895 cpl_msg_info(fctid,
"Using local median +/- %.4f [ADU] as "
896 "valid pixel value range", ron);
899 for (i = 0; i < nrow; ++i) {
901 register cxint stride = i * ncol;
902 register cxint* bpx_row = pi_bpm + stride;
904 register const cxdouble* bias_row = pd_mbias + stride;
906 register cxdouble sdev = 0.;
908 median = giraffe_array_median(bias_row, ncol);
910 for (j = 0; j < ncol; ++j) {
911 sdev += (bias_row[j] - median) * (bias_row[j] - median);
913 sdev = sqrt(sdev / (cxdouble)(ncol - 1));
915 if (median < median_min) {
920 if (median > median_max) {
925 tlow = median - mbias_config.bpm.factor * ron;
926 thigh = median + mbias_config.bpm.factor * ron;
928 for (j = 0; j < ncol; ++j) {
930 if ((bias_row[j] < tlow) || (bias_row[j] > thigh)) {
943 if (nbpx > nbpx_max) {
944 cpl_msg_warning(fctid,
"Number of bad pixels found (%ld) exceeds "
945 "maximum number of bad pixels expected (%ld)!", nbpx,
951 cpl_propertylist_update_double(properties, GIALIAS_BZERO, 0.);
953 cpl_propertylist_update_double(properties,
954 GIALIAS_BPM_FRACTION, mbias_config.bpm.fraction);
955 cpl_propertylist_set_comment(properties, GIALIAS_BPM_FRACTION,
956 "Maximum fraction of bad pixels allowed.");
958 cpl_propertylist_update_int(properties,
959 GIALIAS_BPM_NPIX, nbpx);
960 cpl_propertylist_set_comment(properties, GIALIAS_BPM_NPIX,
961 "Number of pixels flagged as bad.");
963 cpl_propertylist_update_double(properties,
964 GIALIAS_BPM_MEDIAN_MIN, median_min);
965 cpl_propertylist_set_comment(properties, GIALIAS_BPM_MEDIAN_MIN,
966 "Minimum median pixel value used for bad pixel detection.");
968 cpl_propertylist_update_double(properties,
969 GIALIAS_BPM_MEDIAN_MAX, median_max);
970 cpl_propertylist_set_comment(properties, GIALIAS_BPM_MEDIAN_MAX,
971 "Maximum median pixel value used for bad pixel detection.");
973 cpl_propertylist_update_double(properties,
974 GIALIAS_BPM_FACTOR, mbias_config.bpm.factor);
975 cpl_propertylist_set_comment(properties, GIALIAS_BPM_FACTOR,
976 "Noise multiplier defining thresholds for bad pixel "
979 cpl_propertylist_update_double(properties,
980 GIALIAS_BPM_NOISE, ron);
981 cpl_propertylist_set_comment(properties, GIALIAS_BPM_NOISE,
982 "Bias noise value [ADU] used for bad pixel detection.");
987 GIFRAME_BADPIXEL_MAP,
988 CPL_FRAME_LEVEL_FINAL,
991 if (product_frame == NULL) {
993 cpl_msg_error(fctid,
"Cannot create local file! Aborting ...");
995 if (master_bias != NULL) {
999 if (bpixel != NULL) {
1007 cpl_frameset_insert(set, product_frame);
1014 if (bpixel != NULL) {
1020 if (master_bias != NULL) {
1034 giqcmasterbias(cpl_frameset* set)
1037 const cxchar*
const fctid =
"giqcmasterbias";
1040 const cxint wstart = 50;
1041 const cxint wsize = 100;
1052 const cxdouble low = 100.;
1053 const cxdouble high = 300.;
1054 const cxdouble sthreshold = 2.;
1057 cxdouble median = 0.;
1058 cxdouble smean = 0.;
1060 cxdouble* _mbdata = NULL;
1061 cxdouble* _tdata = NULL;
1062 cxdouble sigma[nsigma];
1064 cpl_propertylist* properties = NULL;
1065 cpl_propertylist* qclog = NULL;
1067 cpl_vector* _sigma = NULL;
1069 cpl_image* _mbias = NULL;
1070 cpl_image* _smbias = NULL;
1071 cpl_image* _test = NULL;
1073 cpl_frame* rframe = NULL;
1074 cpl_frame* pframe = NULL;
1078 GiImage* mbias = NULL;
1079 GiImage* bias = NULL;
1084 cpl_msg_info(fctid,
"Computing QC1 parameters ...");
1086 qc = giraffe_qclog_open(0);
1089 cpl_msg_error(fctid,
"Cannot create QC1 log!");
1093 qclog = giraffe_paf_get_properties(qc);
1094 cx_assert(qclog != NULL);
1102 CPL_FRAME_GROUP_PRODUCT);
1104 if (pframe == NULL) {
1105 cpl_msg_error(fctid,
"Missing product frame (%s)",
1106 GIFRAME_BIAS_MASTER);
1108 giraffe_paf_delete(qc);
1114 cpl_msg_info(fctid,
"Processing product frame '%s' (%s)",
1115 cpl_frame_get_filename(pframe), cpl_frame_get_tag(pframe));
1121 cpl_msg_error(fctid,
"Could not load master bias '%s'! Aborting ...",
1122 cpl_frame_get_filename(pframe));
1127 giraffe_paf_delete(qc);
1138 rframe = cpl_frameset_find(set, GIFRAME_BIAS);
1140 if (rframe == NULL) {
1141 cpl_msg_error(fctid,
"Missing raw frame (%s)", GIFRAME_BIAS);
1146 giraffe_paf_delete(qc);
1156 cpl_msg_error(fctid,
"Could not load bias '%s'!",
1157 cpl_frame_get_filename(rframe));
1165 giraffe_paf_delete(qc);
1173 cx_assert(properties != NULL);
1178 cpl_propertylist_update_string(qclog,
"PRO.CATG",
1179 cpl_frame_get_tag(pframe));
1180 cpl_propertylist_set_comment(qclog,
"PRO.CATG",
1181 "Pipeline product category");
1184 cx_assert(properties != NULL);
1187 properties, GIALIAS_DATAMEAN);
1189 properties, GIALIAS_DATASIG);
1191 properties, GIALIAS_DATAMEDI);
1193 properties, GIALIAS_DATANCOM);
1201 _mbdata = cpl_image_get_data(_mbias);
1203 nx = cpl_image_get_size_x(_mbias);
1204 ny = cpl_image_get_size_y(_mbias);
1208 for (i = 0; i < nx * ny; i++) {
1210 if (_mbdata[i] >= low && _mbdata[i] < high) {
1216 _test = cpl_image_new(nvalid, 1, CPL_TYPE_DOUBLE);
1217 _tdata = cpl_image_get_data(_test);
1221 for (i = 0; i < nx * ny; i++) {
1223 if (_mbdata[i] >= low && _mbdata[i] < high) {
1224 _tdata[j++] = _mbdata[i];
1229 cpl_propertylist_update_double(properties, GIALIAS_QCMBIASMED,
1230 cpl_image_get_median(_test));
1231 cpl_propertylist_set_comment(properties, GIALIAS_QCMBIASMED,
1232 "Median master bias level (ADU)");
1234 cpl_propertylist_update_double(properties, GIALIAS_QCMBIASAVG,
1235 cpl_image_get_mean(_test));
1236 cpl_propertylist_set_comment(properties, GIALIAS_QCMBIASAVG,
1237 "Mean master bias level (ADU)");
1239 cpl_propertylist_update_double(properties, GIALIAS_QCMBIASRMS,
1240 cpl_image_get_stdev(_test));
1241 cpl_propertylist_set_comment(properties, GIALIAS_QCMBIASRMS,
1242 "RMS of master bias level (ADU)");
1244 cpl_image_delete(_test);
1248 properties, GIALIAS_QCMBIASMED);
1250 properties, GIALIAS_QCMBIASAVG);
1252 properties, GIALIAS_QCMBIASRMS);
1260 if (cpl_frameset_count_tags(set, GIFRAME_BIAS) > 1) {
1262 cpl_frame* _frame = NULL;
1264 cpl_image* diff = NULL;
1270 memset(sigma, 0, nsigma *
sizeof(cxdouble));
1272 _frame = cpl_frameset_find(set, GIFRAME_BIAS);
1273 _frame = cpl_frameset_find(set, NULL);
1279 cpl_msg_error(fctid,
"Could not load bias '%s'! Aborting ...",
1280 cpl_frame_get_filename(_frame));
1291 giraffe_paf_delete(qc);
1300 cpl_msg_error(fctid,
"Cannot compute bias difference image! "
1312 giraffe_paf_delete(qc);
1329 w.x1 = w.x0 + wsize;
1330 w.y1 = w.y0 + wsize;
1332 giraffe_error_push();
1334 sigma[i++] = cpl_image_get_stdev_window(diff, w.x0, w.y0, w.x1, w.y1);
1336 if (cpl_error_get_code() != CPL_ERROR_NONE) {
1340 giraffe_error_pop();
1345 w.x0 = cpl_image_get_size_x(diff) - wstart - wsize;
1346 w.x1 = w.x0 + wsize;
1348 giraffe_error_push();
1350 sigma[i++] = cpl_image_get_stdev_window(diff, w.x0, w.y0, w.x1, w.y1);
1352 if (cpl_error_get_code() != CPL_ERROR_NONE) {
1356 giraffe_error_pop();
1361 w.y0 = cpl_image_get_size_y(diff) - wstart - wsize;
1362 w.y1 = w.y0 + wsize;
1364 giraffe_error_push();
1366 sigma[i++] = cpl_image_get_stdev_window(diff, w.x0, w.y0, w.x1, w.y1);
1368 if (cpl_error_get_code() != CPL_ERROR_NONE) {
1372 giraffe_error_pop();
1378 w.x1 = w.x0 + wsize;
1380 giraffe_error_push();
1382 sigma[i++] = cpl_image_get_stdev_window(diff, w.x0, w.y0, w.x1, w.y1);
1384 if (cpl_error_get_code() != CPL_ERROR_NONE) {
1388 giraffe_error_pop();
1398 giraffe_error_push();
1400 sigma[i++] = cpl_image_get_stdev_window(diff, w.x0, w.y0, w.x1, w.y1);
1402 if (cpl_error_get_code() != CPL_ERROR_NONE) {
1406 giraffe_error_pop();
1409 for (i = 0; i < nsigma; i++) {
1410 sigma[i] /= sqrt(2.);
1414 cpl_msg_error(fctid,
"Could not compute image statistics in any "
1415 "window! Aborting ...");
1417 cpl_image_delete(diff);
1426 giraffe_paf_delete(qc);
1433 _sigma = cpl_vector_wrap(nsigma, sigma);
1435 median = cpl_vector_get_median(_sigma);
1437 cpl_vector_unwrap(_sigma);
1440 cpl_image_delete(diff);
1444 cpl_propertylist_update_double(properties, GIALIAS_QCRON, median);
1445 cpl_propertylist_set_comment(properties, GIALIAS_QCRON,
1446 "Readout noise (raw)");
1462 memset(sigma, 0, nsigma *
sizeof(cxdouble));
1469 w.x1 = w.x0 + wsize;
1470 w.y1 = w.y0 + wsize;
1472 _smbias = cpl_image_extract(_mbias, w.x0, w.y0, w.x1, w.y1);
1473 _mbdata = cpl_image_get_data(_smbias);
1477 for (i = 0; i < wsize * wsize; i++) {
1479 if (_mbdata[i] >= low && _mbdata[i] < high) {
1485 _test = cpl_image_new(nvalid, 1, CPL_TYPE_DOUBLE);
1486 _tdata = cpl_image_get_data(_test);
1490 for (i = 0; i < wsize * wsize; i++) {
1492 if (_mbdata[i] >= low && _mbdata[i] < high) {
1493 _tdata[j++] = _mbdata[i];
1498 giraffe_error_push();
1500 sigma[k++] = cpl_image_get_stdev(_test);
1502 if (cpl_error_get_code() != CPL_ERROR_NONE) {
1506 giraffe_error_pop();
1508 cpl_image_delete(_smbias);
1511 cpl_image_delete(_test);
1516 w.x0 = cpl_image_get_size_x(_mbias) - wstart - wsize;
1517 w.x1 = w.x0 + wsize;
1519 _smbias = cpl_image_extract(_mbias, w.x0, w.y0, w.x1, w.y1);
1520 _mbdata = cpl_image_get_data(_smbias);
1524 for (i = 0; i < wsize * wsize; i++) {
1526 if (_mbdata[i] >= low && _mbdata[i] < high) {
1532 _test = cpl_image_new(nvalid, 1, CPL_TYPE_DOUBLE);
1533 _tdata = cpl_image_get_data(_test);
1537 for (i = 0; i < wsize * wsize; i++) {
1539 if (_mbdata[i] >= low && _mbdata[i] < high) {
1540 _tdata[j++] = _mbdata[i];
1545 giraffe_error_push();
1547 sigma[k++] = cpl_image_get_stdev(_test);
1549 if (cpl_error_get_code() != CPL_ERROR_NONE) {
1553 giraffe_error_pop();
1555 cpl_image_delete(_smbias);
1558 cpl_image_delete(_test);
1563 w.y0 = cpl_image_get_size_y(_mbias) - wstart - wsize;
1564 w.y1 = w.y0 + wsize;
1566 _smbias = cpl_image_extract(_mbias, w.x0, w.y0, w.x1, w.y1);
1567 _mbdata = cpl_image_get_data(_smbias);
1571 for (i = 0; i < wsize * wsize; i++) {
1573 if (_mbdata[i] >= low && _mbdata[i] < high) {
1579 _test = cpl_image_new(nvalid, 1, CPL_TYPE_DOUBLE);
1580 _tdata = cpl_image_get_data(_test);
1584 for (i = 0; i < wsize * wsize; i++) {
1586 if (_mbdata[i] >= low && _mbdata[i] < high) {
1587 _tdata[j++] = _mbdata[i];
1592 giraffe_error_push();
1594 sigma[k++] = cpl_image_get_stdev(_test);
1596 if (cpl_error_get_code() != CPL_ERROR_NONE) {
1600 giraffe_error_pop();
1602 cpl_image_delete(_smbias);
1605 cpl_image_delete(_test);
1611 w.x1 = w.x0 + wsize;
1613 _smbias = cpl_image_extract(_mbias, w.x0, w.y0, w.x1, w.y1);
1614 _mbdata = cpl_image_get_data(_smbias);
1618 for (i = 0; i < wsize * wsize; i++) {
1620 if (_mbdata[i] >= low && _mbdata[i] < high) {
1626 _test = cpl_image_new(nvalid, 1, CPL_TYPE_DOUBLE);
1627 _tdata = cpl_image_get_data(_test);
1631 for (i = 0; i < wsize * wsize; i++) {
1633 if (_mbdata[i] >= low && _mbdata[i] < high) {
1634 _tdata[j++] = _mbdata[i];
1639 giraffe_error_push();
1641 sigma[k++] = cpl_image_get_stdev(_test);
1643 if (cpl_error_get_code() != CPL_ERROR_NONE) {
1647 giraffe_error_pop();
1649 cpl_image_delete(_smbias);
1652 cpl_image_delete(_test);
1662 _smbias = cpl_image_extract(_mbias, w.x0, w.y0, w.x1, w.y1);
1663 _mbdata = cpl_image_get_data(_smbias);
1667 for (i = 0; i < wsize * wsize; i++) {
1669 if (_mbdata[i] >= low && _mbdata[i] < high) {
1675 _test = cpl_image_new(nvalid, 1, CPL_TYPE_DOUBLE);
1676 _tdata = cpl_image_get_data(_test);
1680 for (i = 0; i < wsize * wsize; i++) {
1682 if (_mbdata[i] >= low && _mbdata[i] < high) {
1683 _tdata[j++] = _mbdata[i];
1688 giraffe_error_push();
1690 sigma[k++] = cpl_image_get_stdev(_test);
1692 if (cpl_error_get_code() != CPL_ERROR_NONE) {
1696 giraffe_error_pop();
1698 cpl_image_delete(_smbias);
1701 cpl_image_delete(_test);
1705 cpl_msg_error(fctid,
"Could not compute image statistics in any "
1706 "window! Aborting ...");
1711 giraffe_paf_delete(qc);
1717 _sigma = cpl_vector_wrap(nsigma, sigma);
1719 median = cpl_vector_get_median(_sigma);
1721 cpl_vector_unwrap(_sigma);
1724 cpl_propertylist_update_double(properties, GIALIAS_QCMRON, median);
1725 cpl_propertylist_set_comment(properties, GIALIAS_QCMRON,
"Readout noise "
1736 _test = cpl_image_collapse_create(_mbias, 0);
1737 cpl_image_divide_scalar(_test, cpl_image_get_size_y(_mbias));
1739 mean = cpl_image_get_mean(_test);
1749 _tdata = cpl_image_get_data(_test);
1751 for (i = 0; i < cpl_image_get_size_x(_test); i++) {
1753 if ((_tdata[i] > mean - sthreshold) &&
1754 (_tdata[i] < mean + sthreshold)) {
1761 smean = sum / nvalid;
1771 for (i = 0; i < cpl_image_get_size_x(_test); i++) {
1773 if ((_tdata[i] > mean - sthreshold) &&
1774 (_tdata[i] < mean + sthreshold)) {
1775 sum += pow(_tdata[i] - smean, 2.);
1781 sum = sqrt(sum / (nvalid - 1));
1783 cpl_propertylist_update_double(properties, GIALIAS_QCSTRUCTX, sum);
1784 cpl_propertylist_set_comment(properties, GIALIAS_QCSTRUCTX,
1785 "Structure along the x axis");
1790 cpl_image_delete(_test);
1794 _test = cpl_image_collapse_create(_mbias, 1);
1795 cpl_image_divide_scalar(_test, cpl_image_get_size_x(_mbias));
1797 mean = cpl_image_get_mean(_test);
1807 _tdata = cpl_image_get_data(_test);
1809 for (i = 0; i < cpl_image_get_size_y(_test); i++) {
1811 if ((_tdata[i] > mean - sthreshold) &&
1812 (_tdata[i] < mean + sthreshold)) {
1819 smean = sum / nvalid;
1829 _tdata = cpl_image_get_data(_test);
1831 for (i = 0; i < cpl_image_get_size_y(_test); i++) {
1833 if ((_tdata[i] > mean - sthreshold) &&
1834 (_tdata[i] < mean + sthreshold)) {
1835 sum += pow(_tdata[i] - smean, 2.);
1841 sum = sqrt(sum / (nvalid - 1));
1843 cpl_propertylist_update_double(properties, GIALIAS_QCSTRUCTY, sum);
1844 cpl_propertylist_set_comment(properties, GIALIAS_QCSTRUCTY,
1845 "Structure along the y axis");
1850 cpl_image_delete(_test);
1863 giraffe_qclog_close(qc);
1877 cpl_plugin_get_info(cpl_pluginlist* list)
1880 cpl_recipe* recipe = cx_calloc(1,
sizeof *recipe);
1881 cpl_plugin* plugin = &recipe->interface;
1884 cpl_plugin_init(plugin,
1886 GIRAFFE_BINARY_VERSION,
1887 CPL_PLUGIN_TYPE_RECIPE,
1889 "Creates a master bias image from a set of raw biases.",
1890 "For detailed information please refer to the "
1891 "GIRAFFE pipeline user manual.\nIt is available at "
1892 "http://www.eso.org/pipelines.",
1896 gimasterbias_create,
1898 gimasterbias_destroy);
1900 cpl_pluginlist_append(list, plugin);
cxint giraffe_trim_raw_areas(GiImage *image)
Remove pre- and overscan ares from an image.
cpl_frame * giraffe_frame_create_image(GiImage *image, const cxchar *tag, cpl_frame_level level, cxbool save, cxbool update)
Create an image product frame.
cpl_frame * giraffe_get_frame(const cpl_frameset *set, const cxchar *tag, cpl_frame_group group)
Get a frame from a frame set.
void giraffe_image_delete(GiImage *self)
Destroys an image.
cpl_propertylist * giraffe_image_get_properties(const GiImage *self)
Get the properties of an image.
cxint giraffe_image_add_info(GiImage *image, const GiRecipeInfo *info, const cpl_frameset *set)
Add additional frame information to an image.
cxint giraffe_image_save(GiImage *self, const cxchar *filename)
Write a Giraffe image to a file.
cpl_image * giraffe_image_get(const GiImage *self)
Gets the image data.
GiImage * giraffe_image_create(cpl_type type, cxint nx, cxint ny)
Creates an image container of a given type.
GiImage * giraffe_image_new(cpl_type type)
Creates an empty image container.
cxint giraffe_image_set_properties(GiImage *self, cpl_propertylist *properties)
Attaches a property list to an image.
cxint giraffe_image_load(GiImage *self, const cxchar *filename, cxint position)
Gets image data and properties from a file.
void giraffe_stacking_config_add(cpl_parameterlist *list)
Adds parameters for the stacking of images.
void giraffe_stacking_config_destroy(GiStackingConfig *config)
Destroys a setup structure for the stacking of images.
GiStackingConfig * giraffe_stacking_config_create(cpl_parameterlist *list)
Creates a setup structure for the stacking of images.
GiImage * giraffe_stacking_stack_images(GiImage **img_array, const GiStackingConfig *config)
Stack a list of images using one of four different kinds of stacking and return the resulting image.
cxint giraffe_propertylist_copy(cpl_propertylist *self, const cxchar *name, const cpl_propertylist *other, const cxchar *othername)
Copy a property from one list to another.
cxdouble giraffe_propertylist_get_conad(const cpl_propertylist *properties)
Retrieve the ADU to electrons conversion factor from the given properties.
const cxchar * giraffe_get_license(void)
Get the pipeline copyright and license.