36 #include "omega_recipe.h"
66 static int omega_readnoise_create(cpl_plugin *) ;
67 static int omega_readnoise_exec(cpl_plugin *) ;
68 static int omega_readnoise_destroy(cpl_plugin *) ;
69 static int omega_readnoise(cpl_frameset *,cpl_parameterlist *) ;
75 static void omega_readnoise_init(
void);
76 static void omega_readnoise_tidy(
void);
92 double RawBias1Median;
98 double RawBias2Median;
101 }omega_readnoise_config;
105 cpl_frameset *biaslist;
106 omega_fits *biasfits1;
107 omega_fits *biasfits2;
117 #define RECIPE "omega_readnoise"
119 static cpl_frame *product_frame = NULL;
121 static char outfile[100];
122 static char outpaf[100];
123 static const char *PROCATG = OMEGA_CALIB_RDNOISE;
137 cpl_recipe * recipe = cpl_calloc(1,
sizeof(*recipe)) ;
138 cpl_plugin * plugin = &recipe->interface ;
140 cpl_plugin_init(plugin,
142 OMEGA_BINARY_VERSION,
143 CPL_PLUGIN_TYPE_RECIPE,
145 "OMEGA - Calculate the read noise of the detector.",
146 "The read_noise is computed by subtracting two raw bias images, \n"
147 "and dividing the standard deviation by sqrt(2). The descriptor \n"
148 "value read_noise will be set to the computed value. The statistics \n"
149 "of the difference between the raw biases is computed iteratively. Bad \n"
150 "pixels are rejected if they differ more than process_params.REJECTION_THRESHOLD \n"
151 "sigma from the median. The maximum number of iteration is \n"
152 "process_params.MAXIMUM_ITERATIONS.",
156 omega_readnoise_create,
157 omega_readnoise_exec,
158 omega_readnoise_destroy) ;
160 cpl_pluginlist_append(list, plugin) ;
175 static int omega_readnoise_create(cpl_plugin * plugin)
181 if (cpl_error_get_code() != CPL_ERROR_NONE) {
182 cpl_msg_error(cpl_func,
"%s():%d: An error is already set: %s",
183 cpl_func, __LINE__, cpl_error_get_where());
184 return (
int)cpl_error_get_code();
187 if (plugin == NULL) {
188 cpl_msg_error(cpl_func,
"Null plugin");
189 cpl_ensure_code(0, (
int)CPL_ERROR_NULL_INPUT);
193 if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {
194 cpl_msg_error(cpl_func,
"Plugin is not a recipe");
195 cpl_ensure_code(0, (
int)CPL_ERROR_TYPE_MISMATCH);
199 recipe = (cpl_recipe *)plugin;
202 recipe->parameters = cpl_parameterlist_new() ;
204 if (recipe->parameters == NULL) {
205 cpl_msg_error(cpl_func,
"Parameter list allocation failed");
206 cpl_ensure_code(0, (
int)CPL_ERROR_ILLEGAL_OUTPUT);
210 p = cpl_parameter_new_value(
"omega.omega_readnoise.ExtensionNumber",
212 "FITS extension number to load (1 to 32). (-1 = all)",
216 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"ext") ;
217 cpl_parameterlist_append(recipe->parameters, p) ;
219 p = cpl_parameter_new_value(
"omega.omega_readnoise.PAF",
221 "Boolean value to create PAF files. 1(Yes), 0(No)",
225 cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,
"paf") ;
226 cpl_parameterlist_append(recipe->parameters, p) ;
228 p = cpl_parameter_new_range(
"omega.omega_readnoise.NumberIter",
230 "Maximum number of iterations",
234 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"niter") ;
235 cpl_parameterlist_append(recipe->parameters, p) ;
238 p = cpl_parameter_new_range(
"omega.omega_readnoise.RejSigma",
240 "Sigma Clipping Threshold",
244 cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,
"sig-clip") ;
245 cpl_parameterlist_append(recipe->parameters, p) ;
260 static int omega_readnoise_exec(cpl_plugin * plugin)
266 if (cpl_error_get_code() != CPL_ERROR_NONE) {
267 cpl_msg_error(cpl_func,
"%s():%d: An error is already set: %s",
268 cpl_func, __LINE__, cpl_error_get_where());
269 return (
int)cpl_error_get_code();
272 if (plugin == NULL) {
273 cpl_msg_error(cpl_func,
"Null plugin");
274 cpl_ensure_code(0, (
int)CPL_ERROR_NULL_INPUT);
278 if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {
279 cpl_msg_error(cpl_func,
"Plugin is not a recipe");
280 cpl_ensure_code(0, (
int)CPL_ERROR_TYPE_MISMATCH);
284 recipe = (cpl_recipe *)plugin;
287 if (recipe->parameters == NULL) {
288 cpl_msg_error(cpl_func,
"Recipe invoked with NULL parameter list");
289 cpl_ensure_code(0, (
int)CPL_ERROR_NULL_INPUT);
291 if (recipe->frames == NULL) {
292 cpl_msg_error(cpl_func,
"Recipe invoked with NULL frame set");
293 cpl_ensure_code(0, (
int)CPL_ERROR_NULL_INPUT);
297 recipe_status = omega_readnoise(recipe->frames, recipe->parameters);
300 if (cpl_dfs_update_product_header(recipe->frames)) {
301 if (!recipe_status) recipe_status = (int)cpl_error_get_code();
304 return recipe_status;
315 static int omega_readnoise_destroy(cpl_plugin * plugin)
319 if (plugin == NULL) {
320 cpl_msg_error(cpl_func,
"Null plugin");
321 cpl_ensure_code(0, (
int)CPL_ERROR_NULL_INPUT);
325 if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {
326 cpl_msg_error(cpl_func,
"Plugin is not a recipe");
327 cpl_ensure_code(0, (
int)CPL_ERROR_TYPE_MISMATCH);
331 recipe = (cpl_recipe *)plugin;
333 cpl_parameterlist_delete(recipe->parameters);
349 static int omega_readnoise(cpl_frameset *set,cpl_parameterlist *pars)
356 const char *_id =
"omega_readnoise";
357 const char *chipid = NULL;
359 const cpl_frame *bias1, *bias2;
360 const cpl_image *rawbiasfits1, *rawbiasfits2=NULL;
363 cpl_propertylist *plist;
369 cpl_msg_error (_id,
"Parameters list not found");
373 if (cpl_frameset_is_empty(set) == 1) {
374 cpl_msg_error (_id,
"Frameset not found");
380 omega_readnoise_init();
385 par = cpl_parameterlist_find(pars,
"omega.omega_readnoise.ExtensionNumber") ;
386 omega_readnoise_config.extnum = cpl_parameter_get_int(par) ;
388 par = cpl_parameterlist_find(pars,
"omega.omega_readnoise.NumberIter") ;
389 omega_readnoise_config.niter = cpl_parameter_get_int(par) ;
391 par = cpl_parameterlist_find(pars,
"omega.omega_readnoise.RejSigma") ;
392 omega_readnoise_config.rej_sig = cpl_parameter_get_double(par) ;
394 par = cpl_parameterlist_find(pars,
"omega.omega_readnoise.PAF") ;
395 omega_readnoise_config.paf = cpl_parameter_get_bool(par) ;
398 if (oc_dfs_set_groups(set)) {
399 cpl_msg_error(_id,
"Cannot identify RAW and CALIB frames") ;
400 omega_readnoise_tidy();
409 cpl_msg_error(_id,
"Cannot labelise the input frameset");
410 omega_readnoise_tidy();
414 RNOISE_RAW)) == NULL) {
415 cpl_msg_error(_id,
"Cannot find bias frames in input frameset");
416 omega_readnoise_tidy();
419 if (cpl_frameset_get_size(ps.biaslist) < 2) {
420 cpl_msg_error(_id,
"Need exactly 2 (%s) frames to run this recipe",RNOISE_RAW);
421 omega_readnoise_tidy();
426 bias1 = cpl_frameset_get_position_const(ps.biaslist,0);
427 bias2 = cpl_frameset_get_position_const(ps.biaslist,1);
429 cpl_msg_info (_id,
"Using %s frames: %s and %s",RNOISE_RAW,cpl_frame_get_filename(bias1),
430 cpl_frame_get_filename(bias2));
434 if(omega_readnoise_config.extnum == 0){
435 cpl_msg_error(cpl_func,
"Unsupported extension request, %d",omega_readnoise_config.extnum);
436 omega_readnoise_tidy();
442 omega_readnoise_config.extnum == 0 && jfn == 32)
445 for (j = jst; j <= jfn; j++) {
446 cpl_msg_info(_id,
"Beginning work on extension %d",j);
447 isfirst = (j == jst);
448 omega_readnoise_config.rnoise = 0.0;
449 omega_readnoise_config.mean_diff = 0.0;
450 omega_readnoise_config.median_diff = 0.0;
451 omega_readnoise_config.RawBias1Min=0.;
452 omega_readnoise_config.RawBias1Max=0.;
453 omega_readnoise_config.RawBias1Mean=0.;
454 omega_readnoise_config.RawBias1Median=0.;
455 omega_readnoise_config.RawBias1Stdev=0.;
456 omega_readnoise_config.RawBias2Min=0.;
457 omega_readnoise_config.RawBias2Max=0.;
458 omega_readnoise_config.RawBias2Mean=0.;
459 omega_readnoise_config.RawBias2Median=0.;
460 omega_readnoise_config.RawBias2Stdev=0.;
465 if (ps.biasfits1 == NULL || ps.biasfits2 == NULL) {
466 cpl_msg_error(_id,
"NULL image input for extension %d",j);
468 freefits(ps.biasfits1);
469 freefits(ps.biasfits2);
475 plist = cpl_propertylist_load(cpl_frame_get_filename(bias1),j);
478 cpl_msg_warning(_id,
"First bias image detector not live");
480 freefits(ps.biasfits1);
481 freefits(ps.biasfits2);
487 plist = cpl_propertylist_load(cpl_frame_get_filename(bias2),j);
490 cpl_msg_warning(_id,
"Second bias image detector not live");
492 freefits(ps.biasfits1);
493 freefits(ps.biasfits2);
503 omega_readnoise_config.RawBias1Min =cpl_image_get_min(rawbiasfits1);
504 omega_readnoise_config.RawBias1Max =cpl_image_get_max(rawbiasfits1);
505 omega_readnoise_config.RawBias1Mean =cpl_image_get_mean(rawbiasfits1);
506 omega_readnoise_config.RawBias1Median=cpl_image_get_median(rawbiasfits1);
507 omega_readnoise_config.RawBias1Stdev =cpl_image_get_stdev(rawbiasfits1);
508 omega_readnoise_config.RawBias2Min =cpl_image_get_min(rawbiasfits2);
509 omega_readnoise_config.RawBias2Max =cpl_image_get_max(rawbiasfits2);
510 omega_readnoise_config.RawBias2Mean =cpl_image_get_mean(rawbiasfits2);
511 omega_readnoise_config.RawBias2Median=cpl_image_get_median(rawbiasfits2);
512 omega_readnoise_config.RawBias2Stdev =cpl_image_get_stdev(rawbiasfits2);
519 freefits(ps.biasfits2);
522 ps.stats =
omega_iter_stat(biasim,omega_readnoise_config.rej_sig,omega_readnoise_config.niter);
525 if(ps.stats != NULL){
526 stdev = cpl_stats_get_stdev(ps.stats);
527 omega_readnoise_config.rnoise = stdev / sqrt(2);
528 omega_readnoise_config.mean_diff = cpl_stats_get_mean(ps.stats);
529 omega_readnoise_config.median_diff = cpl_stats_get_median(ps.stats);
532 cpl_msg_warning(_id,
"Cannot calculate statistics iteratively");
535 plist = cpl_propertylist_load(cpl_frame_get_filename(bias1),j);
538 cpl_msg_info(_id,
"The read noise of %s is: %5.3g", chipid, omega_readnoise_config.rnoise);
539 cpl_msg_info(_id,
"Difference between bias frames is: %5.3g (mean), %5.3g (median)",
540 omega_readnoise_config.mean_diff, omega_readnoise_config.median_diff);
547 ps.table = cpl_table_new(1);
548 cpl_table_new_column(ps.table,
"READNOISE", CPL_TYPE_DOUBLE);
549 cpl_table_new_column(ps.table,
"MEAN_DIFF", CPL_TYPE_DOUBLE);
550 cpl_table_new_column(ps.table,
"MEDIAN_DIFF", CPL_TYPE_DOUBLE);
551 cpl_table_set_double(ps.table,
"READNOISE", 0, omega_readnoise_config.rnoise);
552 cpl_table_set_double(ps.table,
"MEAN_DIFF", 0, omega_readnoise_config.mean_diff);
553 cpl_table_set_double(ps.table,
"MEDIAN_DIFF", 0, omega_readnoise_config.median_diff);
557 cpl_msg_error(_id,
"Cannot save this extension product");
558 omega_readnoise_tidy();
562 freefits(ps.biasfits1);
566 omega_readnoise_tidy();
583 cpl_parameterlist *parlist)
586 const char *fctid =
"omega_readnoise_save";
587 cpl_propertylist *plist;
588 cpl_propertylist *qclist;
596 sprintf(INSTRUME,
"wfi");
599 sprintf(outfile,
"%s_%s.fits",INSTRUME,PROCATG) ;
602 product_frame = cpl_frame_new();
603 cpl_frame_set_filename(product_frame,outfile);
604 cpl_frame_set_tag(product_frame,PROCATG);
605 cpl_frame_set_type(product_frame,CPL_FRAME_TYPE_TABLE);
606 cpl_frame_set_group(product_frame,CPL_FRAME_GROUP_PRODUCT);
607 cpl_frame_set_level(product_frame,CPL_FRAME_LEVEL_FINAL);
609 plist = cpl_propertylist_new();
612 if (cpl_dfs_setup_product_header(plist, product_frame, set, parlist,
613 RECIPE,PIPEID,DICID,NULL) != CPL_ERROR_NONE) {
615 cpl_msg_warning(fctid,
"Problem in the main header of product DFS-compliance") ;
621 cpl_propertylist_erase_regexp(plist,REM_PRIM_KEYS,0);
624 if (cpl_propertylist_save(plist,outfile,CPL_IO_DEFAULT) != CPL_ERROR_NONE){
625 cpl_msg_error(fctid,
"Cannot save product PHU");
626 cpl_frame_delete(product_frame);
632 cpl_frameset_insert(set,product_frame);
637 qclist = cpl_propertylist_new();
640 if (cpl_dfs_setup_product_header(plist, product_frame, set, parlist,
641 RECIPE,PIPEID,DICID,NULL) != CPL_ERROR_NONE) {
643 cpl_msg_warning(fctid,
"Problem in the extension header of product DFS-compliance") ;
647 cpl_propertylist_erase_regexp(plist, REM_EXT_KEYS, 0);
652 cpl_propertylist_update_float(qclist,
"ESO QC READNOISE",
653 omega_readnoise_config.rnoise);
654 cpl_propertylist_update_float(qclist,
"ESO QC READNOISE MEAN DIFF",
655 omega_readnoise_config.mean_diff);
656 cpl_propertylist_update_float(qclist,
"ESO QC READNOISE MEDIAN DIFF",
657 omega_readnoise_config.median_diff);
659 cpl_propertylist_update_float(qclist,
"ESO QC RAW BIAS1 MIN" , omega_readnoise_config.RawBias1Min );
660 cpl_propertylist_update_float(qclist,
"ESO QC RAW BIAS1 MAX" , omega_readnoise_config.RawBias1Max );
661 cpl_propertylist_update_float(qclist,
"ESO QC RAW BIAS1 MEAN" , omega_readnoise_config.RawBias1Mean );
662 cpl_propertylist_update_float(qclist,
"ESO QC RAW BIAS1 MEDIAN", omega_readnoise_config.RawBias1Median);
663 cpl_propertylist_update_float(qclist,
"ESO QC RAW BIAS1 STDEV" , omega_readnoise_config.RawBias1Stdev );
664 cpl_propertylist_update_float(qclist,
"ESO QC RAW BIAS2 MIN" , omega_readnoise_config.RawBias2Min );
665 cpl_propertylist_update_float(qclist,
"ESO QC RAW BIAS2 MAX" , omega_readnoise_config.RawBias2Max );
666 cpl_propertylist_update_float(qclist,
"ESO QC RAW BIAS2 MEAN" , omega_readnoise_config.RawBias2Mean );
667 cpl_propertylist_update_float(qclist,
"ESO QC RAW BIAS2 MEDIAN", omega_readnoise_config.RawBias2Median);
668 cpl_propertylist_update_float(qclist,
"ESO QC RAW BIAS2 STDEV ", omega_readnoise_config.RawBias2Stdev );
670 cpl_propertylist_set_comment(qclist,
"ESO QC RAW BIAS1 MIN" ,
"minimum value of first frame");
671 cpl_propertylist_set_comment(qclist,
"ESO QC RAW BIAS1 MAX" ,
"maximum value of first frame");
672 cpl_propertylist_set_comment(qclist,
"ESO QC RAW BIAS1 MEAN" ,
"mean value of first frame");
673 cpl_propertylist_set_comment(qclist,
"ESO QC RAW BIAS1 MEDIAN",
"median value of first frame");
674 cpl_propertylist_set_comment(qclist,
"ESO QC RAW BIAS1 STDEV" ,
"standard deviation of first frame");
675 cpl_propertylist_set_comment(qclist,
"ESO QC RAW BIAS2 MIN" ,
"minimum value of second frame");
676 cpl_propertylist_set_comment(qclist,
"ESO QC RAW BIAS2 MAX" ,
"maximum value of second frame");
677 cpl_propertylist_set_comment(qclist,
"ESO QC RAW BIAS2 MEAN" ,
"mean value of second frame");
678 cpl_propertylist_set_comment(qclist,
"ESO QC RAW BIAS2 MEDIAN",
"median value of second frame");
679 cpl_propertylist_set_comment(qclist,
"ESO QC RAW BIAS2 STDEV ",
"standard deviation of second frame");
682 cpl_propertylist_append(plist, qclist);
685 cpl_propertylist_set_comment(plist,
"ESO QC READNOISE",
686 "Calculated detector readnoise");
687 cpl_propertylist_set_comment(plist,
"ESO QC READNOISE MEAN DIFF",
688 "Calculated mean of difference");
689 cpl_propertylist_set_comment(plist,
"ESO QC READNOISE MEDIAN DIFF",
690 "Calculated median of difference");
693 if (cpl_table_save(ps.table,NULL,plist,outfile,CPL_IO_EXTEND) != CPL_ERROR_NONE) {
694 cpl_msg_error(fctid,
"Cannot save product. %s", cpl_error_get_message());
700 if(omega_readnoise_config.paf){
702 const char pafcopy[] =
"^(DATE-OBS|ARCFILE|ESO TPL ID|ESO DET WIN1 DIT1|MJD-OBS|EXTNAME|ESO PRO CATG)$";
703 sprintf(outpaf,
"%s_%s_%d.paf",INSTRUME,PROCATG,xtnum) ;
704 cpl_frame *fframe = cpl_frameset_get_position(set, 0);
705 cpl_propertylist *mlist = cpl_propertylist_load_regexp(cpl_frame_get_filename(fframe),0,pafcopy, 0);
706 cpl_propertylist_copy_property_regexp(qclist, mlist, pafcopy, 0);
707 if(cpl_propertylist_copy_property_regexp(qclist, plist,
708 pafcopy, 0) != CPL_ERROR_NONE){
709 cpl_msg_warning(fctid,
"Some mandatory keywords are missing in PAF file");
712 cpl_dfs_save_paf(INSTRUME, RECIPE, qclist, outpaf);
729 static void omega_readnoise_init(
void) {
745 static void omega_readnoise_tidy(
void) {
746 freespace(ps.labels);
747 freeframeset(ps.biaslist);
748 freefits(ps.biasfits1);
749 freefits(ps.biasfits2);
cpl_stats * omega_iter_stat(cpl_image *img, double threshold, int iter)
Compute statistics of an image iteratively.
int omega_pfits_get_detlive(const cpl_propertylist *plist, int *detlive)
Get the value of DET_LIVE.
cpl_image * omega_fits_get_image(omega_fits *p)
int omega_readnoise_save(cpl_frameset *set, cpl_parameterlist *parlist)
Save the omega_readnoise recipe products on disk.
int omega_compare_tags(const cpl_frame *frame1, const cpl_frame *frame2)
int omega_pfits_check_instrume(const cpl_frame *fr)
Check if INSTRUME is WFI or OMEGA.
omega_fits * omega_fits_load(const cpl_frame *inframe, cpl_type type, int extnum)
int omega_fits_get_extnum(omega_fits *p)
const char * omega_get_license(void)
Get the pipeline copyright and license.
void omega_exten_range(int inexten, int *out1, int *out2)
cpl_propertylist * omega_fits_get_ehu(omega_fits *p)
const char * omega_pfits_get_chipid(const cpl_propertylist *plist)
Get CHIP ID from header.
cpl_frameset * omega_frameset_subgroup(cpl_frameset *frameset, cpl_size *labels, cpl_size nlab, const char *tag)
int cpl_plugin_get_info(cpl_pluginlist *list)
Build the list of available plugins, for this module.