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;
122 static char outfile[100];
123 static char outpaf[100];
124 static const char *PROCATG = OMEGA_CALIB_RDNOISE;
138 cpl_recipe * recipe = cpl_calloc(1,
sizeof(*recipe)) ;
139 cpl_plugin * plugin = &recipe->interface ;
141 cpl_plugin_init(plugin,
143 OMEGA_BINARY_VERSION,
144 CPL_PLUGIN_TYPE_RECIPE,
146 "OMEGA - Calculate the read noise of the detector.",
147 "The read_noise is computed by subtracting two raw bias images, \n"
148 "and dividing the standard deviation by sqrt(2). The descriptor \n"
149 "value read_noise will be set to the computed value. The statistics \n"
150 "of the difference between the raw biases is computed iteratively. Bad \n"
151 "pixels are rejected if they differ more than process_params.REJECTION_THRESHOLD \n"
152 "sigma from the median. The maximum number of iteration is \n"
153 "process_params.MAXIMUM_ITERATIONS.",
157 omega_readnoise_create,
158 omega_readnoise_exec,
159 omega_readnoise_destroy) ;
161 cpl_pluginlist_append(list, plugin) ;
176 static int omega_readnoise_create(cpl_plugin * plugin)
182 if (cpl_error_get_code() != CPL_ERROR_NONE) {
183 cpl_msg_error(cpl_func,
"%s():%d: An error is already set: %s",
184 cpl_func, __LINE__, cpl_error_get_where());
185 return (
int)cpl_error_get_code();
188 if (plugin == NULL) {
189 cpl_msg_error(cpl_func,
"Null plugin");
190 cpl_ensure_code(0, (
int)CPL_ERROR_NULL_INPUT);
194 if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {
195 cpl_msg_error(cpl_func,
"Plugin is not a recipe");
196 cpl_ensure_code(0, (
int)CPL_ERROR_TYPE_MISMATCH);
200 recipe = (cpl_recipe *)plugin;
203 recipe->parameters = cpl_parameterlist_new() ;
205 if (recipe->parameters == NULL) {
206 cpl_msg_error(cpl_func,
"Parameter list allocation failed");
207 cpl_ensure_code(0, (
int)CPL_ERROR_ILLEGAL_OUTPUT);
211 p = cpl_parameter_new_value(
"omega.omega_readnoise.ExtensionNumber",
213 "FITS extension number to load (1 to 32). (-1 = all)",
217 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"ext") ;
218 cpl_parameterlist_append(recipe->parameters, p) ;
220 p = cpl_parameter_new_value(
"omega.omega_readnoise.PAF",
222 "Boolean value to create PAF files. 1(Yes), 0(No)",
226 cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,
"paf") ;
227 cpl_parameterlist_append(recipe->parameters, p) ;
229 p = cpl_parameter_new_range(
"omega.omega_readnoise.NumberIter",
231 "Maximum number of iterations",
235 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"niter") ;
236 cpl_parameterlist_append(recipe->parameters, p) ;
239 p = cpl_parameter_new_range(
"omega.omega_readnoise.RejSigma",
241 "Sigma Clipping Threshold",
245 cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,
"sig-clip") ;
246 cpl_parameterlist_append(recipe->parameters, p) ;
261 static int omega_readnoise_exec(cpl_plugin * plugin)
267 if (cpl_error_get_code() != CPL_ERROR_NONE) {
268 cpl_msg_error(cpl_func,
"%s():%d: An error is already set: %s",
269 cpl_func, __LINE__, cpl_error_get_where());
270 return (
int)cpl_error_get_code();
273 if (plugin == NULL) {
274 cpl_msg_error(cpl_func,
"Null plugin");
275 cpl_ensure_code(0, (
int)CPL_ERROR_NULL_INPUT);
279 if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {
280 cpl_msg_error(cpl_func,
"Plugin is not a recipe");
281 cpl_ensure_code(0, (
int)CPL_ERROR_TYPE_MISMATCH);
285 recipe = (cpl_recipe *)plugin;
288 if (recipe->parameters == NULL) {
289 cpl_msg_error(cpl_func,
"Recipe invoked with NULL parameter list");
290 cpl_ensure_code(0, (
int)CPL_ERROR_NULL_INPUT);
292 if (recipe->frames == NULL) {
293 cpl_msg_error(cpl_func,
"Recipe invoked with NULL frame set");
294 cpl_ensure_code(0, (
int)CPL_ERROR_NULL_INPUT);
298 recipe_status = omega_readnoise(recipe->frames, recipe->parameters);
301 if (cpl_dfs_update_product_header(recipe->frames)) {
302 if (!recipe_status) recipe_status = (int)cpl_error_get_code();
305 return recipe_status;
316 static int omega_readnoise_destroy(cpl_plugin * plugin)
320 if (plugin == NULL) {
321 cpl_msg_error(cpl_func,
"Null plugin");
322 cpl_ensure_code(0, (
int)CPL_ERROR_NULL_INPUT);
326 if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {
327 cpl_msg_error(cpl_func,
"Plugin is not a recipe");
328 cpl_ensure_code(0, (
int)CPL_ERROR_TYPE_MISMATCH);
332 recipe = (cpl_recipe *)plugin;
334 cpl_parameterlist_delete(recipe->parameters);
350 static int omega_readnoise(cpl_frameset *
set,cpl_parameterlist *pars)
357 const char *_id =
"omega_readnoise";
358 const char *chipid = NULL;
360 const cpl_frame *bias1, *bias2;
361 const cpl_image *rawbiasfits1, *rawbiasfits2=NULL;
364 cpl_propertylist *plist;
370 cpl_msg_error (_id,
"Parameters list not found");
374 if (cpl_frameset_is_empty(
set) == 1) {
375 cpl_msg_error (_id,
"Frameset not found");
381 omega_readnoise_init();
386 par = cpl_parameterlist_find(pars,
"omega.omega_readnoise.ExtensionNumber") ;
387 omega_readnoise_config.extnum = cpl_parameter_get_int(par) ;
389 par = cpl_parameterlist_find(pars,
"omega.omega_readnoise.NumberIter") ;
390 omega_readnoise_config.niter = cpl_parameter_get_int(par) ;
392 par = cpl_parameterlist_find(pars,
"omega.omega_readnoise.RejSigma") ;
393 omega_readnoise_config.rej_sig = cpl_parameter_get_double(par) ;
395 par = cpl_parameterlist_find(pars,
"omega.omega_readnoise.PAF") ;
396 omega_readnoise_config.paf = cpl_parameter_get_bool(par) ;
399 if (oc_dfs_set_groups(
set)) {
400 cpl_msg_error(_id,
"Cannot identify RAW and CALIB frames") ;
401 omega_readnoise_tidy();
410 cpl_msg_error(_id,
"Cannot labelise the input frameset");
411 omega_readnoise_tidy();
415 RNOISE_RAW)) == NULL) {
416 cpl_msg_error(_id,
"Cannot find bias frames in input frameset");
417 omega_readnoise_tidy();
420 if (cpl_frameset_get_size(ps.biaslist) < 2) {
421 cpl_msg_error(_id,
"Need exactly 2 (%s) frames to run this recipe",RNOISE_RAW);
422 omega_readnoise_tidy();
427 bias1 = cpl_frameset_get_frame_const(ps.biaslist,0);
428 bias2 = cpl_frameset_get_frame_const(ps.biaslist,1);
430 cpl_msg_info (_id,
"Using %s frames: %s and %s",RNOISE_RAW,cpl_frame_get_filename(bias1),
431 cpl_frame_get_filename(bias2));
435 if(omega_readnoise_config.extnum == 0){
436 cpl_msg_error(cpl_func,
"Unsupported extension request, %d",omega_readnoise_config.extnum);
437 omega_readnoise_tidy();
443 omega_readnoise_config.extnum == 0 && jfn == 32)
446 for (j = jst; j <= jfn; j++) {
447 cpl_msg_info(_id,
"Beginning work on extension %d",j);
448 isfirst = (j == jst);
449 omega_readnoise_config.rnoise = 0.0;
450 omega_readnoise_config.mean_diff = 0.0;
451 omega_readnoise_config.median_diff = 0.0;
452 omega_readnoise_config.RawBias1Min=0.;
453 omega_readnoise_config.RawBias1Max=0.;
454 omega_readnoise_config.RawBias1Mean=0.;
455 omega_readnoise_config.RawBias1Median=0.;
456 omega_readnoise_config.RawBias1Stdev=0.;
457 omega_readnoise_config.RawBias2Min=0.;
458 omega_readnoise_config.RawBias2Max=0.;
459 omega_readnoise_config.RawBias2Mean=0.;
460 omega_readnoise_config.RawBias2Median=0.;
461 omega_readnoise_config.RawBias2Stdev=0.;
466 if (ps.biasfits1 == NULL || ps.biasfits2 == NULL) {
467 cpl_msg_error(_id,
"NULL image input for extension %d",j);
469 freefits(ps.biasfits1);
470 freefits(ps.biasfits2);
476 plist = cpl_propertylist_load(cpl_frame_get_filename(bias1),j);
479 cpl_msg_warning(_id,
"First bias image detector not live");
481 freefits(ps.biasfits1);
482 freefits(ps.biasfits2);
488 plist = cpl_propertylist_load(cpl_frame_get_filename(bias2),j);
491 cpl_msg_warning(_id,
"Second bias image detector not live");
493 freefits(ps.biasfits1);
494 freefits(ps.biasfits2);
504 omega_readnoise_config.RawBias1Min =cpl_image_get_min(rawbiasfits1);
505 omega_readnoise_config.RawBias1Max =cpl_image_get_max(rawbiasfits1);
506 omega_readnoise_config.RawBias1Mean =cpl_image_get_mean(rawbiasfits1);
507 omega_readnoise_config.RawBias1Median=cpl_image_get_median(rawbiasfits1);
508 omega_readnoise_config.RawBias1Stdev =cpl_image_get_stdev(rawbiasfits1);
509 omega_readnoise_config.RawBias2Min =cpl_image_get_min(rawbiasfits2);
510 omega_readnoise_config.RawBias2Max =cpl_image_get_max(rawbiasfits2);
511 omega_readnoise_config.RawBias2Mean =cpl_image_get_mean(rawbiasfits2);
512 omega_readnoise_config.RawBias2Median=cpl_image_get_median(rawbiasfits2);
513 omega_readnoise_config.RawBias2Stdev =cpl_image_get_stdev(rawbiasfits2);
520 freefits(ps.biasfits2);
523 ps.stats =
omega_iter_stat(biasim,omega_readnoise_config.rej_sig,omega_readnoise_config.niter);
526 if(ps.stats != NULL){
527 stdev = cpl_stats_get_stdev(ps.stats);
528 omega_readnoise_config.rnoise = stdev / sqrt(2);
529 omega_readnoise_config.mean_diff = cpl_stats_get_mean(ps.stats);
530 omega_readnoise_config.median_diff = cpl_stats_get_median(ps.stats);
533 cpl_msg_warning(_id,
"Cannot calculate statistics iteratively");
536 plist = cpl_propertylist_load(cpl_frame_get_filename(bias1),j);
539 cpl_msg_info(_id,
"The read noise of %s is: %5.3g", chipid, omega_readnoise_config.rnoise);
540 cpl_msg_info(_id,
"Difference between bias frames is: %5.3g (mean), %5.3g (median)",
541 omega_readnoise_config.mean_diff, omega_readnoise_config.median_diff);
548 ps.table = cpl_table_new(1);
549 cpl_table_new_column(ps.table,
"READNOISE", CPL_TYPE_DOUBLE);
550 cpl_table_new_column(ps.table,
"MEAN_DIFF", CPL_TYPE_DOUBLE);
551 cpl_table_new_column(ps.table,
"MEDIAN_DIFF", CPL_TYPE_DOUBLE);
552 cpl_table_set_double(ps.table,
"READNOISE", 0, omega_readnoise_config.rnoise);
553 cpl_table_set_double(ps.table,
"MEAN_DIFF", 0, omega_readnoise_config.mean_diff);
554 cpl_table_set_double(ps.table,
"MEDIAN_DIFF", 0, omega_readnoise_config.median_diff);
558 cpl_msg_error(_id,
"Cannot save this extension product");
559 omega_readnoise_tidy();
563 freefits(ps.biasfits1);
567 omega_readnoise_tidy();
584 cpl_parameterlist *parlist)
587 const char *fctid =
"omega_readnoise_save";
588 cpl_propertylist *plist;
589 cpl_propertylist *qclist;
597 sprintf(INSTRUME,
"wfi");
600 sprintf(outfile,
"%s_%s.fits",INSTRUME,PROCATG) ;
603 product_frame = cpl_frame_new();
604 cpl_frame_set_filename(product_frame,outfile);
605 cpl_frame_set_tag(product_frame,PROCATG);
606 cpl_frame_set_type(product_frame,CPL_FRAME_TYPE_TABLE);
607 cpl_frame_set_group(product_frame,CPL_FRAME_GROUP_PRODUCT);
608 cpl_frame_set_level(product_frame,CPL_FRAME_LEVEL_FINAL);
610 plist = cpl_propertylist_new();
613 if (cpl_dfs_setup_product_header(plist, product_frame,
set, parlist,
614 RECIPE,PIPEID,DICID,NULL) != CPL_ERROR_NONE) {
616 cpl_msg_warning(fctid,
"Problem in the main header of product DFS-compliance") ;
622 cpl_propertylist_erase_regexp(plist,REM_PRIM_KEYS,0);
625 if (cpl_propertylist_save(plist,outfile,CPL_IO_DEFAULT) != CPL_ERROR_NONE){
626 cpl_msg_error(fctid,
"Cannot save product PHU");
627 cpl_frame_delete(product_frame);
633 cpl_frameset_insert(
set,product_frame);
638 qclist = cpl_propertylist_new();
641 if (cpl_dfs_setup_product_header(plist, product_frame,
set, parlist,
642 RECIPE,PIPEID,DICID,NULL) != CPL_ERROR_NONE) {
644 cpl_msg_warning(fctid,
"Problem in the extension header of product DFS-compliance") ;
648 cpl_propertylist_erase_regexp(plist, REM_EXT_KEYS, 0);
653 cpl_propertylist_update_float(qclist,
"ESO QC READNOISE",
654 omega_readnoise_config.rnoise);
655 cpl_propertylist_update_float(qclist,
"ESO QC READNOISE MEAN DIFF",
656 omega_readnoise_config.mean_diff);
657 cpl_propertylist_update_float(qclist,
"ESO QC READNOISE MEDIAN DIFF",
658 omega_readnoise_config.median_diff);
660 cpl_propertylist_update_float(qclist,
"ESO QC RAW BIAS1 MIN" , omega_readnoise_config.RawBias1Min );
661 cpl_propertylist_update_float(qclist,
"ESO QC RAW BIAS1 MAX" , omega_readnoise_config.RawBias1Max );
662 cpl_propertylist_update_float(qclist,
"ESO QC RAW BIAS1 MEAN" , omega_readnoise_config.RawBias1Mean );
663 cpl_propertylist_update_float(qclist,
"ESO QC RAW BIAS1 MEDIAN", omega_readnoise_config.RawBias1Median);
664 cpl_propertylist_update_float(qclist,
"ESO QC RAW BIAS1 STDEV" , omega_readnoise_config.RawBias1Stdev );
665 cpl_propertylist_update_float(qclist,
"ESO QC RAW BIAS2 MIN" , omega_readnoise_config.RawBias2Min );
666 cpl_propertylist_update_float(qclist,
"ESO QC RAW BIAS2 MAX" , omega_readnoise_config.RawBias2Max );
667 cpl_propertylist_update_float(qclist,
"ESO QC RAW BIAS2 MEAN" , omega_readnoise_config.RawBias2Mean );
668 cpl_propertylist_update_float(qclist,
"ESO QC RAW BIAS2 MEDIAN", omega_readnoise_config.RawBias2Median);
669 cpl_propertylist_update_float(qclist,
"ESO QC RAW BIAS2 STDEV ", omega_readnoise_config.RawBias2Stdev );
671 cpl_propertylist_set_comment(qclist,
"ESO QC RAW BIAS1 MIN" ,
"minimum value of first frame");
672 cpl_propertylist_set_comment(qclist,
"ESO QC RAW BIAS1 MAX" ,
"maximum value of first frame");
673 cpl_propertylist_set_comment(qclist,
"ESO QC RAW BIAS1 MEAN" ,
"mean value of first frame");
674 cpl_propertylist_set_comment(qclist,
"ESO QC RAW BIAS1 MEDIAN",
"median value of first frame");
675 cpl_propertylist_set_comment(qclist,
"ESO QC RAW BIAS1 STDEV" ,
"standard deviation of first frame");
676 cpl_propertylist_set_comment(qclist,
"ESO QC RAW BIAS2 MIN" ,
"minimum value of second frame");
677 cpl_propertylist_set_comment(qclist,
"ESO QC RAW BIAS2 MAX" ,
"maximum value of second frame");
678 cpl_propertylist_set_comment(qclist,
"ESO QC RAW BIAS2 MEAN" ,
"mean value of second frame");
679 cpl_propertylist_set_comment(qclist,
"ESO QC RAW BIAS2 MEDIAN",
"median value of second frame");
680 cpl_propertylist_set_comment(qclist,
"ESO QC RAW BIAS2 STDEV ",
"standard deviation of second frame");
683 cpl_propertylist_append(plist, qclist);
686 cpl_propertylist_set_comment(plist,
"ESO QC READNOISE",
687 "Calculated detector readnoise");
688 cpl_propertylist_set_comment(plist,
"ESO QC READNOISE MEAN DIFF",
689 "Calculated mean of difference");
690 cpl_propertylist_set_comment(plist,
"ESO QC READNOISE MEDIAN DIFF",
691 "Calculated median of difference");
694 if (cpl_table_save(ps.table,NULL,plist,outfile,CPL_IO_EXTEND) != CPL_ERROR_NONE) {
695 cpl_msg_error(fctid,
"Cannot save product. %s", cpl_error_get_message());
702 if(omega_readnoise_config.paf){
704 const char pafcopy[] =
"^(DATE-OBS|ARCFILE|ESO TPL ID|ESO DET WIN1 DIT1|MJD-OBS|EXTNAME|ESO PRO CATG)$";
705 sprintf(outpaf,
"%s_%s_%d.paf",INSTRUME,PROCATG,xtnum) ;
706 cpl_frame *fframe = cpl_frameset_get_first(
set);
707 cpl_propertylist *mlist = cpl_propertylist_load_regexp(cpl_frame_get_filename(fframe),0,pafcopy, 0);
708 cpl_propertylist_copy_property_regexp(qclist, mlist, pafcopy, 0);
709 if(cpl_propertylist_copy_property_regexp(qclist, plist,
710 pafcopy, 0) != CPL_ERROR_NONE){
711 cpl_msg_warning(fctid,
"Some mandatory keywords are missing in PAF file");
714 cpl_dfs_save_paf(INSTRUME, RECIPE, qclist, outpaf);
731 static void omega_readnoise_init(
void) {
747 static void omega_readnoise_tidy(
void) {
748 freespace(ps.labels);
749 freeframeset(ps.biaslist);
750 freefits(ps.biasfits1);
751 freefits(ps.biasfits2);