34 #include <cxmessages.h>
37 #include <cpl_recipe.h>
38 #include <cpl_plugininfo.h>
39 #include <cpl_parameterlist.h>
40 #include <cpl_frameset.h>
41 #include <cpl_propertylist.h>
42 #include <cpl_vector.h>
54 #include "gistacking.h"
59 #define GIMASTERBIAS_BIAS_EXTENSION_IMG 0
60 #define GIMASTERBIAS_BIAS_EXTENSION_PL 0
61 #define GIMASTERBIAS_BAD_PIXEL_EXTENSION 0
64 struct GiMasterbiasConfig {
66 cxbool removeoverscan;
67 cxbool correctbadpixels;
77 typedef struct GiMasterbiasConfig GiMasterbiasConfig;
79 static cxint gimasterbias(cpl_parameterlist*, cpl_frameset*);
80 static cxint giqcmasterbias(cpl_frameset*);
87 static cxdouble max_bpx_fraction = 0.15;
96 gimasterbias_create(cpl_plugin* plugin)
99 cpl_recipe* recipe = (cpl_recipe*)plugin;
104 giraffe_error_init();
113 recipe->parameters = cpl_parameterlist_new();
114 cx_assert(recipe->parameters != NULL);
126 p = cpl_parameter_new_value(
"giraffe.masterbias.overscan.remove",
128 "Remove pre- and over-scan regions from "
129 "the created master bias image.",
130 "giraffe.masterbias.overscan",
132 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"mbias-oscremove");
133 cpl_parameterlist_append(recipe->parameters, p);
135 p = cpl_parameter_new_value(
"giraffe.masterbias.badpixel.clean",
137 "Correct master bias image for bad pixels",
138 "giraffe.masterbias.badpixel",
140 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"mbias-bpxclean");
141 cpl_parameterlist_append(recipe->parameters, p);
143 p = cpl_parameter_new_value(
"giraffe.masterbias.bpm.create",
145 "Create bad pixel map using a simple "
146 "thresholding algorithm. (temporary!)",
147 "giraffe.masterbias.bpm",
149 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"bpm-create");
150 cpl_parameterlist_append(recipe->parameters, p);
152 p = cpl_parameter_new_value(
"giraffe.masterbias.bpm.factor",
154 "Readout noise multiplier defining the "
155 "valid range of pixel values for searching "
157 "giraffe.masterbias.bpm",
159 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"bpm-factor");
160 cpl_parameterlist_append(recipe->parameters, p);
162 p = cpl_parameter_new_value(
"giraffe.masterbias.bpm.fraction",
164 "Maximum fraction of pixels which may be "
165 "flagged as 'bad. If more pixels are "
166 "found to be 'bad a warning is issued.",
167 "giraffe.masterbias.bpm",
169 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"bpm-frac");
170 cpl_parameterlist_append(recipe->parameters, p);
181 gimasterbias_exec(cpl_plugin* plugin)
184 cpl_recipe* recipe = (cpl_recipe*)plugin;
189 if (recipe->parameters == NULL || recipe->frames == NULL) {
193 status = gimasterbias(recipe->parameters, recipe->frames);
199 status = giqcmasterbias(recipe->frames);
211 gimasterbias_destroy(cpl_plugin* plugin)
214 cpl_recipe* recipe = (cpl_recipe*)plugin;
223 cpl_parameterlist_delete(recipe->parameters);
225 giraffe_error_clear();
236 gimasterbias_remove_badpixels(GiImage* img, GiImage* img_badpixels)
239 const cxchar*
const fctid =
"gimasterbias_remove_badpixels";
246 register cxint nr_pairs;
256 cxint search_horizon = 100;
260 cxint sx[] = { 0, 1, 1, 1 };
261 cxint sy[] = { 1,-1, 0, 1 };
264 cxlong nr_bad_pixels = 0L;
270 cxdouble* pd_img = NULL;
272 cxdouble estimate[4];
277 cpl_msg_error(fctid,
"NULL Image as input, aborting..." );
281 if (!img_badpixels) {
282 cpl_msg_error(fctid,
"NULL Bad Pixel Image as input, aborting..." );
288 npix_bp = ncol_bp * nrow_bp;
293 for (n=0; n<npix_bp; n++) {
298 if (((cxdouble)nr_bad_pixels / (cxdouble)npix_bp) >= max_bpx_fraction) {
299 cpl_msg_error(fctid,
"Too many bad pixels, aborting..." );
307 for (badx=0; badx<ncol_bp; badx++) {
308 for (bady=0; bady<nrow_bp; bady++) {
309 if (pi_bp[badx + bady * ncol_bp]==1) {
311 for (j=0; j<4; j++) {
312 estimate[nr_pairs] = 0.0;
315 for (k=0; k<2; k++) {
323 if (cx<0 || cx>=ncol_bp || cy<0 || cy>=nrow_bp)
326 }
while (pi_bp[cx+cy*ncol_bp] && (d<search_horizon));
328 if (cx>=0 && cx<ncol_bp && cy>=0 && cy<nrow_bp &&
331 save = pd_img[cx+cy*ncol_bp];
332 estimate[nr_pairs] += save / d;
333 sumd += 1.0 / (cxdouble) d;
335 estimate[nr_pairs] /= sumd;
343 estimate[nr_pairs] = save;
347 cpl_vector* _estimate =
348 cpl_vector_wrap(nr_pairs,
351 pd_img[badx+bady*ncol_bp] =
352 cpl_vector_get_median(_estimate);
354 cpl_vector_unwrap(_estimate);
357 }
else if (nr_pairs==2) {
358 pd_img[badx+bady*ncol_bp] =
359 (estimate[0]+estimate[1]) * 0.5;
360 }
else if (nr_pairs==1) {
361 pd_img[badx+bady*ncol_bp] =
366 "Can't correct badpixel [%d,%d]",
391 gimasterbias(cpl_parameterlist* config, cpl_frameset* set)
394 const cxchar*
const fctid =
"gimasterbias";
397 cxint raw_bias_count = 0;
398 cxint bad_pixel_count = 0;
404 cpl_propertylist* properties = NULL;
406 cpl_frame* curr_frame = NULL;
407 cpl_frame* bad_pixel_frame = NULL;
408 cpl_frame* product_frame = NULL;
410 cpl_parameter* p = NULL;
412 GiImage** raw_bias_list = NULL;
413 GiImage* bad_pixels = NULL;
414 GiImage* master_bias = NULL;
416 GiMasterbiasConfig mbias_config;
418 GiStackingConfig* stack_config = NULL;
420 GiRecipeInfo info = {(cxchar*)fctid, 1, NULL};
422 GiGroupInfo groups[] = {
423 {GIFRAME_BIAS, CPL_FRAME_GROUP_RAW},
424 {GIFRAME_BADPIXEL_MAP, CPL_FRAME_GROUP_CALIB},
425 {NULL, CPL_FRAME_GROUP_NONE}
433 p = cpl_parameterlist_find(config,
"giraffe.masterbias.overscan.remove");
434 mbias_config.removeoverscan = cpl_parameter_get_bool(p);
436 p = cpl_parameterlist_find(config,
"giraffe.masterbias.badpixel.clean");
437 mbias_config.correctbadpixels = cpl_parameter_get_bool(p);
439 p = cpl_parameterlist_find(config,
"giraffe.masterbias.bpm.create");
440 mbias_config.bpm.create = cpl_parameter_get_bool(p);
442 p = cpl_parameterlist_find(config,
"giraffe.masterbias.bpm.factor");
443 mbias_config.bpm.factor = cpl_parameter_get_double(p);
445 p = cpl_parameterlist_find(config,
"giraffe.masterbias.bpm.fraction");
446 mbias_config.bpm.fraction = cpl_parameter_get_double(p);
449 e_code = giraffe_frameset_set_groups(set, groups);
452 cpl_msg_error(fctid,
"Setting frame group information failed!");
464 raw_bias_count = cpl_frameset_count_tags(set, GIFRAME_BIAS);
466 if (raw_bias_count < stack_config->min_nr_frames) {
467 cpl_msg_error(fctid,
"Not enough raw bias Images [%d, need %d], "
468 "aborting...", raw_bias_count,
469 stack_config->min_nr_frames);
477 bad_pixel_count = cpl_frameset_count_tags(set, GIFRAME_BADPIXEL_MAP);
479 if (mbias_config.correctbadpixels == TRUE) {
480 if (bad_pixel_count != 1) {
481 cpl_msg_error(fctid,
"Invalid number of bad pixel Images "
482 "[%d instead of 1], aborting...", bad_pixel_count);
491 cpl_msg_info(fctid,
"Creating master bias from %d bias frames ...",
497 raw_bias_list = (GiImage**)cx_calloc(raw_bias_count + 1,
sizeof(GiImage*));
499 raw_bias_list[raw_bias_count] = NULL;
501 curr_frame = cpl_frameset_find(set, GIFRAME_BIAS);
503 for (i = 0; i < raw_bias_count; ++i) {
508 cpl_frame_get_filename(curr_frame),
509 GIMASTERBIAS_BIAS_EXTENSION_IMG);
513 cpl_msg_error(fctid,
"Could not load raw Bias Image [%s], "
514 "aborting...", cpl_frame_get_filename(curr_frame));
516 for (j = 0; j <= i; ++j) {
517 if (raw_bias_list[j] != NULL) {
519 raw_bias_list[j] = NULL;
523 cx_free(raw_bias_list);
532 curr_frame = cpl_frameset_find(set, NULL);
536 if (mbias_config.correctbadpixels == TRUE) {
540 bad_pixel_frame = cpl_frameset_find(set, GIFRAME_BADPIXEL_MAP);
542 cpl_msg_info(fctid,
"Bad Pixel Frame is : %s.",
543 cpl_frame_get_filename(bad_pixel_frame));
548 cpl_frame_get_filename(bad_pixel_frame),
549 GIMASTERBIAS_BAD_PIXEL_EXTENSION);
552 cpl_msg_error(fctid,
"Could not load Bad Pixel Image [%s], "
554 cpl_frame_get_filename(bad_pixel_frame));
556 for (j = 0; j < raw_bias_count; j++) {
557 if (raw_bias_list[j] != NULL) {
562 cx_free(raw_bias_list);
578 if (master_bias == NULL) {
579 cpl_msg_error(fctid,
"Stacking of raw bias frames failed! "
580 "No master bias was created, aborting...");
582 for (j = 0; j < raw_bias_count; j++) {
583 if (raw_bias_list[j] != NULL) {
588 cx_free(raw_bias_list);
590 if (bad_pixels != NULL) {
612 if (mbias_config.correctbadpixels == TRUE) {
614 cpl_msg_info(fctid,
"Cleaning bad pixels on created "
615 "master bias image.");
617 if (gimasterbias_remove_badpixels(master_bias, bad_pixels) != 0) {
619 cpl_msg_error(fctid,
"Bad pixel cleaning failed, aborting...");
621 for (j = 0; j < raw_bias_count; j++) {
622 if (raw_bias_list[j] != NULL) {
627 cx_free(raw_bias_list);
629 if (bad_pixels != NULL) {
633 if (master_bias != NULL) {
646 if (mbias_config.removeoverscan == TRUE) {
648 cpl_msg_info(fctid,
"Removing overscan areas from "
649 "master bias image");
653 cpl_msg_error(fctid,
"Removing overscan areas from master "
654 "bias failed, aborting...");
656 for (j = 0; j < raw_bias_count; j++) {
657 if (raw_bias_list[j] != NULL) {
662 cx_free(raw_bias_list);
664 if (bad_pixels != NULL) {
668 if (master_bias != NULL) {
683 cpl_msg_info(fctid,
"Writing master bias image ...");
686 cx_assert(properties != NULL);
688 cpl_propertylist_update_double(properties, GIALIAS_CRPIX1, 1.);
690 cpl_propertylist_update_double(properties, GIALIAS_EXPTTOT, 0.0);
691 cpl_propertylist_update_int(properties, GIALIAS_DATANCOM, raw_bias_count);
692 cpl_propertylist_update_double(properties, GIALIAS_BZERO, 0.0);
694 cpl_propertylist_update_double(properties, GIALIAS_BIASVALUE,
696 cpl_propertylist_update_double(properties, GIALIAS_BIASSIGMA,
699 cpl_propertylist_erase(properties, GIALIAS_EXPTIME);
700 cpl_propertylist_erase(properties, GIALIAS_TPLEXPNO);
707 for (j = 0; j < raw_bias_count; j++) {
708 if (raw_bias_list[j] != NULL) {
713 cx_free(raw_bias_list);
714 raw_bias_list = NULL;
716 if (bad_pixels != NULL) {
726 CPL_FRAME_LEVEL_FINAL,
729 if (product_frame == NULL) {
731 cpl_msg_error(fctid,
"Cannot create local file! Aborting ...");
733 if (master_bias != NULL) {
741 cpl_frameset_insert(set, product_frame);
749 if ((mbias_config.bpm.create == TRUE) && (master_bias != NULL)
750 && (bad_pixel_count == 0)) {
754 const cxdouble* pd_mbias =
755 cpl_image_get_data_double_const(_master_bias);
761 cxint ncol = cpl_image_get_size_x(_master_bias);
762 cxint nrow = cpl_image_get_size_y(_master_bias);
763 cxint* pi_bpm = NULL;
765 cxlong npix = ncol * nrow;
767 cxlong nbpx_max = (cxlong)(mbias_config.bpm.fraction * npix + 0.5);
769 cxdouble median = 0.;
770 cxdouble median_max = CX_MINDOUBLE;
771 cxdouble median_min = CX_MAXDOUBLE;
779 cpl_msg_info(fctid,
"Creating bad pixel map from master bias "
803 if ((cpl_propertylist_has(properties, GIALIAS_PRSCX) == TRUE) ||
804 (cpl_propertylist_has(properties, GIALIAS_OVSCX) == TRUE)) {
808 if (cpl_propertylist_has(properties, GIALIAS_PRSCX) == TRUE) {
810 cxint xsz = cpl_propertylist_get_int(properties,
816 for (i = 0; i < nrow; ++i) {
818 register cxint stride = i * ncol;
820 cxdouble scx_mean = giraffe_array_mean(pd_mbias + stride,
823 for (j = 0; j < xsz; ++j) {
824 sdev += (pd_mbias[stride + j] - scx_mean) *
825 (pd_mbias[stride + j] - scx_mean);
830 ron = sqrt(sdev / (cxdouble)(nrow * xsz - 1));
835 if (cpl_propertylist_has(properties, GIALIAS_OVSCX) == TRUE) {
837 cxint xsz = cpl_propertylist_get_int(properties,
843 for (i = 0; i < nrow; ++i) {
845 register cxint stride = (i + 1) * ncol - xsz;
847 cxdouble scx_mean = giraffe_array_mean(pd_mbias + stride,
850 for (j = 0; j < xsz; ++j) {
851 sdev += (pd_mbias[stride + j] - scx_mean) *
852 (pd_mbias[stride + j] - scx_mean);
857 ron += sqrt(sdev / (cxdouble)(nrow * xsz - 1));
862 ron /= (cxdouble)nvalues;
867 if (cpl_propertylist_has(properties, GIALIAS_RON)) {
872 ron = cpl_propertylist_get_double(properties, GIALIAS_RON);
874 giraffe_error_push();
878 if (cpl_error_get_code() != CPL_ERROR_NONE) {
903 cpl_msg_info(fctid,
"Using local median +/- %.4f [ADU] as "
904 "valid pixel value range", ron);
907 for (i = 0; i < nrow; ++i) {
909 register cxint stride = i * ncol;
910 register cxint* bpx_row = pi_bpm + stride;
912 register const cxdouble* bias_row = pd_mbias + stride;
914 register cxdouble sdev = 0.;
916 median = giraffe_array_median(bias_row, ncol);
918 for (j = 0; j < ncol; ++j) {
919 sdev += (bias_row[j] - median) * (bias_row[j] - median);
921 sdev = sqrt(sdev / (cxdouble)(ncol - 1));
923 if (median < median_min) {
928 if (median > median_max) {
933 tlow = median - mbias_config.bpm.factor * ron;
934 thigh = median + mbias_config.bpm.factor * ron;
936 for (j = 0; j < ncol; ++j) {
938 if ((bias_row[j] < tlow) || (bias_row[j] > thigh)) {
951 if (nbpx > nbpx_max) {
952 cpl_msg_warning(fctid,
"Number of bad pixels found (%ld) exceeds "
953 "maximum number of bad pixels expected (%ld)!", nbpx,
959 cpl_propertylist_update_double(properties, GIALIAS_BZERO, 0.);
961 cpl_propertylist_update_double(properties,
962 GIALIAS_BPM_FRACTION, mbias_config.bpm.fraction);
963 cpl_propertylist_set_comment(properties, GIALIAS_BPM_FRACTION,
964 "Maximum fraction of bad pixels allowed.");
966 cpl_propertylist_update_int(properties,
967 GIALIAS_BPM_NPIX, nbpx);
968 cpl_propertylist_set_comment(properties, GIALIAS_BPM_NPIX,
969 "Number of pixels flagged as bad.");
971 cpl_propertylist_update_double(properties,
972 GIALIAS_BPM_MEDIAN_MIN, median_min);
973 cpl_propertylist_set_comment(properties, GIALIAS_BPM_MEDIAN_MIN,
974 "Minimum median pixel value used for bad pixel detection.");
976 cpl_propertylist_update_double(properties,
977 GIALIAS_BPM_MEDIAN_MAX, median_max);
978 cpl_propertylist_set_comment(properties, GIALIAS_BPM_MEDIAN_MAX,
979 "Maximum median pixel value used for bad pixel detection.");
981 cpl_propertylist_update_double(properties,
982 GIALIAS_BPM_FACTOR, mbias_config.bpm.factor);
983 cpl_propertylist_set_comment(properties, GIALIAS_BPM_FACTOR,
984 "Noise multiplier defining thresholds for bad pixel "
987 cpl_propertylist_update_double(properties,
988 GIALIAS_BPM_NOISE, ron);
989 cpl_propertylist_set_comment(properties, GIALIAS_BPM_NOISE,
990 "Bias noise value [ADU] used for bad pixel detection.");
995 GIFRAME_BADPIXEL_MAP,
996 CPL_FRAME_LEVEL_FINAL,
999 if (product_frame == NULL) {
1001 cpl_msg_error(fctid,
"Cannot create local file! Aborting ...");
1003 if (master_bias != NULL) {
1007 if (bpixel != NULL) {
1015 cpl_frameset_insert(set, product_frame);
1022 if (bpixel != NULL) {
1028 if (master_bias != NULL) {
1042 giqcmasterbias(cpl_frameset* set)
1045 const cxchar*
const fctid =
"giqcmasterbias";
1048 const cxint wstart = 50;
1049 const cxint wsize = 100;
1060 const cxdouble low = 100.;
1061 const cxdouble high = 300.;
1062 const cxdouble sthreshold = 2.;
1065 cxdouble median = 0.;
1066 cxdouble smean = 0.;
1068 cxdouble* _mbdata = NULL;
1069 cxdouble* _tdata = NULL;
1070 cxdouble sigma[nsigma];
1072 cpl_propertylist* properties = NULL;
1073 cpl_propertylist* qclog = NULL;
1075 cpl_vector* _sigma = NULL;
1077 cpl_image* _mbias = NULL;
1078 cpl_image* _smbias = NULL;
1079 cpl_image* _test = NULL;
1081 cpl_frame* rframe = NULL;
1082 cpl_frame* pframe = NULL;
1086 GiImage* mbias = NULL;
1087 GiImage* bias = NULL;
1092 cpl_msg_info(fctid,
"Computing QC1 parameters ...");
1094 qc = giraffe_qclog_open(0);
1097 cpl_msg_error(fctid,
"Cannot create QC1 log!");
1101 qclog = giraffe_paf_get_properties(qc);
1102 cx_assert(qclog != NULL);
1110 CPL_FRAME_GROUP_PRODUCT);
1112 if (pframe == NULL) {
1113 cpl_msg_error(fctid,
"Missing product frame (%s)",
1114 GIFRAME_BIAS_MASTER);
1116 giraffe_paf_delete(qc);
1122 cpl_msg_info(fctid,
"Processing product frame '%s' (%s)",
1123 cpl_frame_get_filename(pframe), cpl_frame_get_tag(pframe));
1129 cpl_msg_error(fctid,
"Could not load master bias '%s'! Aborting ...",
1130 cpl_frame_get_filename(pframe));
1135 giraffe_paf_delete(qc);
1146 rframe = cpl_frameset_find(set, GIFRAME_BIAS);
1148 if (rframe == NULL) {
1149 cpl_msg_error(fctid,
"Missing raw frame (%s)", GIFRAME_BIAS);
1154 giraffe_paf_delete(qc);
1164 cpl_msg_error(fctid,
"Could not load bias '%s'!",
1165 cpl_frame_get_filename(rframe));
1173 giraffe_paf_delete(qc);
1181 cx_assert(properties != NULL);
1186 cpl_propertylist_update_string(qclog,
"PRO.CATG",
1187 cpl_frame_get_tag(pframe));
1188 cpl_propertylist_set_comment(qclog,
"PRO.CATG",
1189 "Pipeline product category");
1192 cx_assert(properties != NULL);
1195 properties, GIALIAS_DATAMEAN);
1197 properties, GIALIAS_DATASIG);
1199 properties, GIALIAS_DATAMEDI);
1201 properties, GIALIAS_DATANCOM);
1209 _mbdata = cpl_image_get_data(_mbias);
1211 nx = cpl_image_get_size_x(_mbias);
1212 ny = cpl_image_get_size_y(_mbias);
1216 for (i = 0; i < nx * ny; i++) {
1218 if (_mbdata[i] >= low && _mbdata[i] < high) {
1224 _test = cpl_image_new(nvalid, 1, CPL_TYPE_DOUBLE);
1225 _tdata = cpl_image_get_data(_test);
1229 for (i = 0; i < nx * ny; i++) {
1231 if (_mbdata[i] >= low && _mbdata[i] < high) {
1232 _tdata[j++] = _mbdata[i];
1237 cpl_propertylist_update_double(properties, GIALIAS_QCMBIASMED,
1238 cpl_image_get_median(_test));
1239 cpl_propertylist_set_comment(properties, GIALIAS_QCMBIASMED,
1240 "Median master bias level (ADU)");
1242 cpl_propertylist_update_double(properties, GIALIAS_QCMBIASAVG,
1243 cpl_image_get_mean(_test));
1244 cpl_propertylist_set_comment(properties, GIALIAS_QCMBIASAVG,
1245 "Mean master bias level (ADU)");
1247 cpl_propertylist_update_double(properties, GIALIAS_QCMBIASRMS,
1248 cpl_image_get_stdev(_test));
1249 cpl_propertylist_set_comment(properties, GIALIAS_QCMBIASRMS,
1250 "RMS of master bias level (ADU)");
1252 cpl_image_delete(_test);
1256 properties, GIALIAS_QCMBIASMED);
1258 properties, GIALIAS_QCMBIASAVG);
1260 properties, GIALIAS_QCMBIASRMS);
1268 if (cpl_frameset_count_tags(set, GIFRAME_BIAS) > 1) {
1270 cpl_frame* _frame = NULL;
1272 cpl_image* diff = NULL;
1278 memset(sigma, 0, nsigma *
sizeof(cxdouble));
1280 _frame = cpl_frameset_find(set, GIFRAME_BIAS);
1281 _frame = cpl_frameset_find(set, NULL);
1287 cpl_msg_error(fctid,
"Could not load bias '%s'! Aborting ...",
1288 cpl_frame_get_filename(_frame));
1299 giraffe_paf_delete(qc);
1308 cpl_msg_error(fctid,
"Cannot compute bias difference image! "
1320 giraffe_paf_delete(qc);
1337 w.x1 = w.x0 + wsize;
1338 w.y1 = w.y0 + wsize;
1340 giraffe_error_push();
1342 sigma[i++] = cpl_image_get_stdev_window(diff, w.x0, w.y0, w.x1, w.y1);
1344 if (cpl_error_get_code() != CPL_ERROR_NONE) {
1348 giraffe_error_pop();
1353 w.x0 = cpl_image_get_size_x(diff) - wstart - wsize;
1354 w.x1 = w.x0 + wsize;
1356 giraffe_error_push();
1358 sigma[i++] = cpl_image_get_stdev_window(diff, w.x0, w.y0, w.x1, w.y1);
1360 if (cpl_error_get_code() != CPL_ERROR_NONE) {
1364 giraffe_error_pop();
1369 w.y0 = cpl_image_get_size_y(diff) - wstart - wsize;
1370 w.y1 = w.y0 + wsize;
1372 giraffe_error_push();
1374 sigma[i++] = cpl_image_get_stdev_window(diff, w.x0, w.y0, w.x1, w.y1);
1376 if (cpl_error_get_code() != CPL_ERROR_NONE) {
1380 giraffe_error_pop();
1386 w.x1 = w.x0 + wsize;
1388 giraffe_error_push();
1390 sigma[i++] = cpl_image_get_stdev_window(diff, w.x0, w.y0, w.x1, w.y1);
1392 if (cpl_error_get_code() != CPL_ERROR_NONE) {
1396 giraffe_error_pop();
1406 giraffe_error_push();
1408 sigma[i++] = cpl_image_get_stdev_window(diff, w.x0, w.y0, w.x1, w.y1);
1410 if (cpl_error_get_code() != CPL_ERROR_NONE) {
1414 giraffe_error_pop();
1417 for (i = 0; i < nsigma; i++) {
1418 sigma[i] /= sqrt(2.);
1422 cpl_msg_error(fctid,
"Could not compute image statistics in any "
1423 "window! Aborting ...");
1425 cpl_image_delete(diff);
1434 giraffe_paf_delete(qc);
1441 _sigma = cpl_vector_wrap(nsigma, sigma);
1443 median = cpl_vector_get_median(_sigma);
1445 cpl_vector_unwrap(_sigma);
1448 cpl_image_delete(diff);
1452 cpl_propertylist_update_double(properties, GIALIAS_QCRON, median);
1453 cpl_propertylist_set_comment(properties, GIALIAS_QCRON,
1454 "Readout noise (raw)");
1470 memset(sigma, 0, nsigma *
sizeof(cxdouble));
1477 w.x1 = w.x0 + wsize;
1478 w.y1 = w.y0 + wsize;
1480 _smbias = cpl_image_extract(_mbias, w.x0, w.y0, w.x1, w.y1);
1481 _mbdata = cpl_image_get_data(_smbias);
1485 for (i = 0; i < wsize * wsize; i++) {
1487 if (_mbdata[i] >= low && _mbdata[i] < high) {
1493 _test = cpl_image_new(nvalid, 1, CPL_TYPE_DOUBLE);
1494 _tdata = cpl_image_get_data(_test);
1498 for (i = 0; i < wsize * wsize; i++) {
1500 if (_mbdata[i] >= low && _mbdata[i] < high) {
1501 _tdata[j++] = _mbdata[i];
1506 giraffe_error_push();
1508 sigma[k++] = cpl_image_get_stdev(_test);
1510 if (cpl_error_get_code() != CPL_ERROR_NONE) {
1514 giraffe_error_pop();
1516 cpl_image_delete(_smbias);
1519 cpl_image_delete(_test);
1524 w.x0 = cpl_image_get_size_x(_mbias) - wstart - wsize;
1525 w.x1 = w.x0 + wsize;
1527 _smbias = cpl_image_extract(_mbias, w.x0, w.y0, w.x1, w.y1);
1528 _mbdata = cpl_image_get_data(_smbias);
1532 for (i = 0; i < wsize * wsize; i++) {
1534 if (_mbdata[i] >= low && _mbdata[i] < high) {
1540 _test = cpl_image_new(nvalid, 1, CPL_TYPE_DOUBLE);
1541 _tdata = cpl_image_get_data(_test);
1545 for (i = 0; i < wsize * wsize; i++) {
1547 if (_mbdata[i] >= low && _mbdata[i] < high) {
1548 _tdata[j++] = _mbdata[i];
1553 giraffe_error_push();
1555 sigma[k++] = cpl_image_get_stdev(_test);
1557 if (cpl_error_get_code() != CPL_ERROR_NONE) {
1561 giraffe_error_pop();
1563 cpl_image_delete(_smbias);
1566 cpl_image_delete(_test);
1571 w.y0 = cpl_image_get_size_y(_mbias) - wstart - wsize;
1572 w.y1 = w.y0 + wsize;
1574 _smbias = cpl_image_extract(_mbias, w.x0, w.y0, w.x1, w.y1);
1575 _mbdata = cpl_image_get_data(_smbias);
1579 for (i = 0; i < wsize * wsize; i++) {
1581 if (_mbdata[i] >= low && _mbdata[i] < high) {
1587 _test = cpl_image_new(nvalid, 1, CPL_TYPE_DOUBLE);
1588 _tdata = cpl_image_get_data(_test);
1592 for (i = 0; i < wsize * wsize; i++) {
1594 if (_mbdata[i] >= low && _mbdata[i] < high) {
1595 _tdata[j++] = _mbdata[i];
1600 giraffe_error_push();
1602 sigma[k++] = cpl_image_get_stdev(_test);
1604 if (cpl_error_get_code() != CPL_ERROR_NONE) {
1608 giraffe_error_pop();
1610 cpl_image_delete(_smbias);
1613 cpl_image_delete(_test);
1619 w.x1 = w.x0 + wsize;
1621 _smbias = cpl_image_extract(_mbias, w.x0, w.y0, w.x1, w.y1);
1622 _mbdata = cpl_image_get_data(_smbias);
1626 for (i = 0; i < wsize * wsize; i++) {
1628 if (_mbdata[i] >= low && _mbdata[i] < high) {
1634 _test = cpl_image_new(nvalid, 1, CPL_TYPE_DOUBLE);
1635 _tdata = cpl_image_get_data(_test);
1639 for (i = 0; i < wsize * wsize; i++) {
1641 if (_mbdata[i] >= low && _mbdata[i] < high) {
1642 _tdata[j++] = _mbdata[i];
1647 giraffe_error_push();
1649 sigma[k++] = cpl_image_get_stdev(_test);
1651 if (cpl_error_get_code() != CPL_ERROR_NONE) {
1655 giraffe_error_pop();
1657 cpl_image_delete(_smbias);
1660 cpl_image_delete(_test);
1670 _smbias = cpl_image_extract(_mbias, w.x0, w.y0, w.x1, w.y1);
1671 _mbdata = cpl_image_get_data(_smbias);
1675 for (i = 0; i < wsize * wsize; i++) {
1677 if (_mbdata[i] >= low && _mbdata[i] < high) {
1683 _test = cpl_image_new(nvalid, 1, CPL_TYPE_DOUBLE);
1684 _tdata = cpl_image_get_data(_test);
1688 for (i = 0; i < wsize * wsize; i++) {
1690 if (_mbdata[i] >= low && _mbdata[i] < high) {
1691 _tdata[j++] = _mbdata[i];
1696 giraffe_error_push();
1698 sigma[k++] = cpl_image_get_stdev(_test);
1700 if (cpl_error_get_code() != CPL_ERROR_NONE) {
1704 giraffe_error_pop();
1706 cpl_image_delete(_smbias);
1709 cpl_image_delete(_test);
1713 cpl_msg_error(fctid,
"Could not compute image statistics in any "
1714 "window! Aborting ...");
1719 giraffe_paf_delete(qc);
1725 _sigma = cpl_vector_wrap(nsigma, sigma);
1727 median = cpl_vector_get_median(_sigma);
1729 cpl_vector_unwrap(_sigma);
1732 cpl_propertylist_update_double(properties, GIALIAS_QCMRON, median);
1733 cpl_propertylist_set_comment(properties, GIALIAS_QCMRON,
"Readout noise "
1744 _test = cpl_image_collapse_create(_mbias, 0);
1745 cpl_image_divide_scalar(_test, cpl_image_get_size_y(_mbias));
1747 mean = cpl_image_get_mean(_test);
1757 _tdata = cpl_image_get_data(_test);
1759 for (i = 0; i < cpl_image_get_size_x(_test); i++) {
1761 if ((_tdata[i] > mean - sthreshold) &&
1762 (_tdata[i] < mean + sthreshold)) {
1769 smean = sum / nvalid;
1779 for (i = 0; i < cpl_image_get_size_x(_test); i++) {
1781 if ((_tdata[i] > mean - sthreshold) &&
1782 (_tdata[i] < mean + sthreshold)) {
1783 sum += pow(_tdata[i] - smean, 2.);
1789 sum = sqrt(sum / (nvalid - 1));
1791 cpl_propertylist_update_double(properties, GIALIAS_QCSTRUCTX, sum);
1792 cpl_propertylist_set_comment(properties, GIALIAS_QCSTRUCTX,
1793 "Structure along the x axis");
1798 cpl_image_delete(_test);
1802 _test = cpl_image_collapse_create(_mbias, 1);
1803 cpl_image_divide_scalar(_test, cpl_image_get_size_x(_mbias));
1805 mean = cpl_image_get_mean(_test);
1815 _tdata = cpl_image_get_data(_test);
1817 for (i = 0; i < cpl_image_get_size_y(_test); i++) {
1819 if ((_tdata[i] > mean - sthreshold) &&
1820 (_tdata[i] < mean + sthreshold)) {
1827 smean = sum / nvalid;
1837 _tdata = cpl_image_get_data(_test);
1839 for (i = 0; i < cpl_image_get_size_y(_test); i++) {
1841 if ((_tdata[i] > mean - sthreshold) &&
1842 (_tdata[i] < mean + sthreshold)) {
1843 sum += pow(_tdata[i] - smean, 2.);
1849 sum = sqrt(sum / (nvalid - 1));
1851 cpl_propertylist_update_double(properties, GIALIAS_QCSTRUCTY, sum);
1852 cpl_propertylist_set_comment(properties, GIALIAS_QCSTRUCTY,
1853 "Structure along the y axis");
1858 cpl_image_delete(_test);
1871 giraffe_qclog_close(qc);
1885 cpl_plugin_get_info(cpl_pluginlist* list)
1888 cpl_recipe* recipe = cx_calloc(1,
sizeof *recipe);
1889 cpl_plugin* plugin = &recipe->interface;
1892 cpl_plugin_init(plugin,
1894 GIRAFFE_BINARY_VERSION,
1895 CPL_PLUGIN_TYPE_RECIPE,
1897 "Creates a master bias image from a set of raw biases.",
1898 "For detailed information please refer to the "
1899 "GIRAFFE pipeline user manual.\nIt is available at "
1900 "http://www.eso.org/pipelines.",
1904 gimasterbias_create,
1906 gimasterbias_destroy);
1908 cpl_pluginlist_append(list, plugin);
cxint giraffe_image_add_info(GiImage *image, const GiRecipeInfo *info, const cpl_frameset *set)
Add additional frame information to an image.
cpl_frame * giraffe_get_frame(const cpl_frameset *set, const cxchar *tag, cpl_frame_group group)
Get a frame from a frame set.
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_trim_raw_areas(GiImage *image)
Remove pre- and overscan ares from an image.
cxint giraffe_image_load(GiImage *self, const cxchar *filename, cxint position)
Gets image data and properties from a file.
cxint giraffe_image_save(GiImage *self, const cxchar *filename)
Write a Giraffe image to a file.
void giraffe_stacking_config_destroy(GiStackingConfig *config)
Destroys a setup structure for the stacking of images.
void giraffe_image_delete(GiImage *self)
Destroys an image.
cxdouble giraffe_propertylist_get_conad(const cpl_propertylist *properties)
Retrieve the ADU to electrons conversion factor from the given properties.
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.
GiImage * giraffe_image_new(cpl_type type)
Creates an empty image container.
GiStackingConfig * giraffe_stacking_config_create(cpl_parameterlist *list)
Creates a setup structure for the stacking of images.
GiImage * giraffe_image_create(cpl_type type, cxint nx, cxint ny)
Creates an image container of a given type.
const cxchar * giraffe_get_license(void)
Get the pipeline copyright and license.
void giraffe_stacking_config_add(cpl_parameterlist *list)
Adds parameters for the stacking of images.
cpl_image * giraffe_image_get(const GiImage *self)
Gets the image data.
cxint giraffe_image_set_properties(GiImage *self, cpl_propertylist *properties)
Attaches a property list to 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_propertylist * giraffe_image_get_properties(const GiImage *self)
Get the properties of an image.