00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031
00032
00033
00034
00035
00036 #include "omega_recipe.h"
00037
00038
00059
00062
00063
00064
00065
00066 static int omega_readnoise_create(cpl_plugin *) ;
00067 static int omega_readnoise_exec(cpl_plugin *) ;
00068 static int omega_readnoise_destroy(cpl_plugin *) ;
00069 static int omega_readnoise(cpl_frameset *,cpl_parameterlist *) ;
00070
00071
00072
00073
00074 int omega_readnoise_save(cpl_frameset *set, cpl_parameterlist *parlist);
00075 static void omega_readnoise_init(void);
00076 static void omega_readnoise_tidy(void);
00077
00078 static struct {
00079
00080 float rej_sig;
00081 int niter;
00082 int extnum;
00083 int paf;
00084
00085
00086 double rnoise;
00087 double mean_diff;
00088 double median_diff;
00089
00090 }omega_readnoise_config;
00091
00092 static struct {
00093 cpl_size *labels;
00094 cpl_frameset *biaslist;
00095 omega_fits *biasfits1;
00096 omega_fits *biasfits2;
00097 cpl_stats *stats;
00098
00099
00100 cpl_table *table;
00101 } ps;
00102
00103
00104
00105
00106 #define RECIPE "omega_readnoise"
00107
00108 static cpl_frame *product_frame = NULL;
00109 static int isfirst;
00110 static int dummy;
00111 static char outfile[100];
00112 static char outpaf[100];
00113 static const char *PROCATG = OMEGA_CALIB_RDNOISE;
00114
00115
00116
00124
00125 int cpl_plugin_get_info(cpl_pluginlist * list)
00126 {
00127 cpl_recipe * recipe = cpl_calloc(1, sizeof(*recipe)) ;
00128 cpl_plugin * plugin = &recipe->interface ;
00129
00130 cpl_plugin_init(plugin,
00131 CPL_PLUGIN_API,
00132 OMEGA_BINARY_VERSION,
00133 CPL_PLUGIN_TYPE_RECIPE,
00134 "omega_readnoise",
00135 "OMEGA - Calculate the read noise of the detector.",
00136 "The read_noise is computed by subtracting two raw bias images, \n"
00137 "and dividing the standard deviation by sqrt(2). The descriptor \n"
00138 "value read_noise will be set to the computed value. The statistics \n"
00139 "of the difference between the raw biases is computed iteratively. Bad \n"
00140 "pixels are rejected if they differ more than process_params.REJECTION_THRESHOLD \n"
00141 "sigma from the median. The maximum number of iteration is \n"
00142 "process_params.MAXIMUM_ITERATIONS.",
00143 "Sandra Castro",
00144 "scastro@eso.org",
00145 omega_get_license(),
00146 omega_readnoise_create,
00147 omega_readnoise_exec,
00148 omega_readnoise_destroy) ;
00149
00150 cpl_pluginlist_append(list, plugin) ;
00151
00152 return 0;
00153 }
00154
00155
00164
00165 static int omega_readnoise_create(cpl_plugin * plugin)
00166 {
00167 cpl_recipe * recipe;
00168 cpl_parameter * p ;
00169
00170
00171 if (cpl_error_get_code() != CPL_ERROR_NONE) {
00172 cpl_msg_error(cpl_func, "%s():%d: An error is already set: %s",
00173 cpl_func, __LINE__, cpl_error_get_where());
00174 return (int)cpl_error_get_code();
00175 }
00176
00177 if (plugin == NULL) {
00178 cpl_msg_error(cpl_func, "Null plugin");
00179 cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
00180 }
00181
00182
00183 if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {
00184 cpl_msg_error(cpl_func, "Plugin is not a recipe");
00185 cpl_ensure_code(0, (int)CPL_ERROR_TYPE_MISMATCH);
00186 }
00187
00188
00189 recipe = (cpl_recipe *)plugin;
00190
00191
00192 recipe->parameters = cpl_parameterlist_new() ;
00193
00194 if (recipe->parameters == NULL) {
00195 cpl_msg_error(cpl_func, "Parameter list allocation failed");
00196 cpl_ensure_code(0, (int)CPL_ERROR_ILLEGAL_OUTPUT);
00197 }
00198
00199
00200 p = cpl_parameter_new_value("omega.omega_readnoise.ExtensionNumber",
00201 CPL_TYPE_INT,
00202 "FITS extension number to load (1 to 32). (-1 = all)",
00203 "omega_readnoise",
00204 -1) ;
00205
00206 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,"ext") ;
00207 cpl_parameterlist_append(recipe->parameters, p) ;
00208
00209 p = cpl_parameter_new_value("omega.omega_readnoise.PAF",
00210 CPL_TYPE_BOOL,
00211 "Boolean value to create PAF files. 1(Yes), 0(No)",
00212 "omega_readnoise",
00213 0) ;
00214
00215 cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI, "paf") ;
00216 cpl_parameterlist_append(recipe->parameters, p) ;
00217
00218 p = cpl_parameter_new_range("omega.omega_readnoise.NumberIter",
00219 CPL_TYPE_INT,
00220 "Maximum number of iterations",
00221 "omega_readnoise",
00222 5, 2, 10) ;
00223
00224 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,"niter") ;
00225 cpl_parameterlist_append(recipe->parameters, p) ;
00226
00227
00228 p = cpl_parameter_new_range("omega.omega_readnoise.RejSigma",
00229 CPL_TYPE_DOUBLE,
00230 "Sigma Clipping Threshold",
00231 "omega_readnoise",
00232 5.0, 1.0, 10.0) ;
00233
00234 cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI, "sig-clip") ;
00235 cpl_parameterlist_append(recipe->parameters, p) ;
00236
00237
00238
00239 return 0;
00240 }
00241
00242
00243
00249
00250 static int omega_readnoise_exec(cpl_plugin * plugin)
00251 {
00252 cpl_recipe * recipe;
00253 int recipe_status;
00254
00255
00256 if (cpl_error_get_code() != CPL_ERROR_NONE) {
00257 cpl_msg_error(cpl_func, "%s():%d: An error is already set: %s",
00258 cpl_func, __LINE__, cpl_error_get_where());
00259 return (int)cpl_error_get_code();
00260 }
00261
00262 if (plugin == NULL) {
00263 cpl_msg_error(cpl_func, "Null plugin");
00264 cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
00265 }
00266
00267
00268 if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {
00269 cpl_msg_error(cpl_func, "Plugin is not a recipe");
00270 cpl_ensure_code(0, (int)CPL_ERROR_TYPE_MISMATCH);
00271 }
00272
00273
00274 recipe = (cpl_recipe *)plugin;
00275
00276
00277 if (recipe->parameters == NULL) {
00278 cpl_msg_error(cpl_func, "Recipe invoked with NULL parameter list");
00279 cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
00280 }
00281 if (recipe->frames == NULL) {
00282 cpl_msg_error(cpl_func, "Recipe invoked with NULL frame set");
00283 cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
00284 }
00285
00286
00287 recipe_status = omega_readnoise(recipe->frames, recipe->parameters);
00288
00289
00290 if (cpl_dfs_update_product_header(recipe->frames)) {
00291 if (!recipe_status) recipe_status = (int)cpl_error_get_code();
00292 }
00293
00294 return recipe_status;
00295
00296 }
00297
00298
00304
00305 static int omega_readnoise_destroy(cpl_plugin * plugin)
00306 {
00307 cpl_recipe *recipe;
00308
00309 if (plugin == NULL) {
00310 cpl_msg_error(cpl_func, "Null plugin");
00311 cpl_ensure_code(0, (int)CPL_ERROR_NULL_INPUT);
00312 }
00313
00314
00315 if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {
00316 cpl_msg_error(cpl_func, "Plugin is not a recipe");
00317 cpl_ensure_code(0, (int)CPL_ERROR_TYPE_MISMATCH);
00318 }
00319
00320
00321 recipe = (cpl_recipe *)plugin;
00322
00323 cpl_parameterlist_delete(recipe->parameters);
00324
00325 return 0 ;
00326 }
00327
00328
00329
00337
00338
00339 static int omega_readnoise(cpl_frameset *set,cpl_parameterlist *pars)
00340 {
00341
00342 int j,jst,jfn,live;
00343 cpl_size nlab;
00344 float stdev = 0.0;
00345
00346 const char *_id = "omega_readnoise";
00347 const char *chipid = NULL;
00348
00349 const cpl_frame *bias1, *bias2;
00350 cpl_image *biasim;
00351 cpl_parameter *par;
00352 cpl_propertylist *plist;
00353
00354
00355
00356 if (pars == NULL) {
00357 cpl_msg_error (_id, "Parameters list not found");
00358 return -1;
00359 }
00360
00361 if (cpl_frameset_is_empty(set) == 1) {
00362 cpl_msg_error (_id, "Frameset not found");
00363 return -1;
00364 }
00365
00366
00367
00368 omega_readnoise_init();
00369
00370
00371
00372
00373 par = cpl_parameterlist_find(pars, "omega.omega_readnoise.ExtensionNumber") ;
00374 omega_readnoise_config.extnum = cpl_parameter_get_int(par) ;
00375
00376 par = cpl_parameterlist_find(pars, "omega.omega_readnoise.NumberIter") ;
00377 omega_readnoise_config.niter = cpl_parameter_get_int(par) ;
00378
00379 par = cpl_parameterlist_find(pars, "omega.omega_readnoise.RejSigma") ;
00380 omega_readnoise_config.rej_sig = cpl_parameter_get_double(par) ;
00381
00382 par = cpl_parameterlist_find(pars, "omega.omega_readnoise.PAF") ;
00383 omega_readnoise_config.paf = cpl_parameter_get_bool(par) ;
00384
00385
00386 if (oc_dfs_set_groups(set)) {
00387 cpl_msg_error(_id, "Cannot identify RAW and CALIB frames") ;
00388 omega_readnoise_tidy();
00389 return -1 ;
00390 }
00391
00392
00393
00394
00395 if ((ps.labels = cpl_frameset_labelise(set,omega_compare_tags,
00396 &nlab)) == NULL) {
00397 cpl_msg_error(_id,"Cannot labelise the input frameset");
00398 omega_readnoise_tidy();
00399 return -1;
00400 }
00401 if ((ps.biaslist = omega_frameset_subgroup(set,ps.labels,nlab,
00402 RNOISE_RAW)) == NULL) {
00403 cpl_msg_error(_id,"Cannot find bias frames in input frameset");
00404 omega_readnoise_tidy();
00405 return -1;
00406 }
00407 if (cpl_frameset_get_size(ps.biaslist) < 2) {
00408 cpl_msg_error(_id,"Need exactly 2 (%s) frames to run this recipe",RNOISE_RAW);
00409 omega_readnoise_tidy();
00410 return -1;
00411 }
00412
00413
00414 bias1 = cpl_frameset_get_frame_const(ps.biaslist,0);
00415 bias2 = cpl_frameset_get_frame_const(ps.biaslist,1);
00416
00417 cpl_msg_info (_id,"Using %s frames: %s and %s",RNOISE_RAW,cpl_frame_get_filename(bias1),
00418 cpl_frame_get_filename(bias2));
00419
00420
00421 omega_exten_range(omega_readnoise_config.extnum,&jst,&jfn);
00422 if(omega_readnoise_config.extnum == 0){
00423 cpl_msg_error(cpl_func,"Unsupported extension request, %d",omega_readnoise_config.extnum);
00424 omega_readnoise_tidy();
00425 return -1;
00426 }
00427
00428
00429 if(omega_pfits_check_instrume(cpl_frameset_get_first_const(set)) == 1 &&
00430 omega_readnoise_config.extnum == 0 && jfn == 32)
00431 jfn = 8;
00432
00433 for (j = jst; j <= jfn; j++) {
00434 cpl_msg_info(_id,"Beginning work on extension %d",j);
00435 isfirst = (j == jst);
00436 omega_readnoise_config.rnoise = 0.0;
00437 omega_readnoise_config.mean_diff = 0.0;
00438 omega_readnoise_config.median_diff = 0.0;
00439
00440 ps.biasfits1 = omega_fits_load(bias1,CPL_TYPE_FLOAT,j);
00441 ps.biasfits2 = omega_fits_load(bias2,CPL_TYPE_FLOAT,j);
00442
00443 if (ps.biasfits1 == NULL || ps.biasfits2 == NULL) {
00444 cpl_msg_error(_id,"NULL image input for extension %d",j);
00445
00446 freefits(ps.biasfits1);
00447 freefits(ps.biasfits2);
00448 continue;
00449 }
00450
00451
00452
00453 plist = cpl_propertylist_load(cpl_frame_get_filename(bias1),j);
00454 omega_pfits_get_detlive(plist,&live);
00455 if (! live) {
00456 cpl_msg_warning(_id,"First bias image detector not live");
00457
00458 freefits(ps.biasfits1);
00459 freefits(ps.biasfits2);
00460 freeplist(plist);
00461 continue;
00462 }
00463 freeplist(plist);
00464
00465 plist = cpl_propertylist_load(cpl_frame_get_filename(bias2),j);
00466 omega_pfits_get_detlive(plist,&live);
00467 if (! live) {
00468 cpl_msg_warning(_id,"Second bias image detector not live");
00469
00470 freefits(ps.biasfits1);
00471 freefits(ps.biasfits2);
00472 freeplist(plist);
00473 continue;
00474 }
00475 freeplist(plist);
00476
00477
00478
00479 biasim = cpl_image_subtract_create(omega_fits_get_image(ps.biasfits1),
00480 omega_fits_get_image(ps.biasfits2));
00481
00482 freefits(ps.biasfits2);
00483
00484
00485 ps.stats = omega_iter_stat(biasim,omega_readnoise_config.rej_sig,omega_readnoise_config.niter);
00486
00487
00488 if(ps.stats != NULL){
00489 stdev = cpl_stats_get_stdev(ps.stats);
00490 omega_readnoise_config.rnoise = stdev / sqrt(2);
00491 omega_readnoise_config.mean_diff = cpl_stats_get_mean(ps.stats);
00492 omega_readnoise_config.median_diff = cpl_stats_get_median(ps.stats);
00493 }
00494 else{
00495 cpl_msg_warning(_id,"Cannot calculate statistics iteratively");
00496 }
00497
00498 plist = cpl_propertylist_load(cpl_frame_get_filename(bias1),j);
00499 chipid = omega_pfits_get_chipid(plist);
00500
00501 cpl_msg_info(_id,"The read noise of %s is: %5.3g", chipid, omega_readnoise_config.rnoise);
00502 cpl_msg_info(_id,"Difference between bias frames is: %5.3g (mean), %5.3g (median)",
00503 omega_readnoise_config.mean_diff, omega_readnoise_config.median_diff);
00504
00505 freeimage(biasim);
00506 freestats(ps.stats);
00507 freeplist(plist);
00508
00509
00510 ps.table = cpl_table_new(1);
00511 cpl_table_new_column(ps.table, "READNOISE", CPL_TYPE_DOUBLE);
00512 cpl_table_new_column(ps.table, "MEAN_DIFF", CPL_TYPE_DOUBLE);
00513 cpl_table_new_column(ps.table, "MEDIAN_DIFF", CPL_TYPE_DOUBLE);
00514 cpl_table_set_double(ps.table, "READNOISE", 0, omega_readnoise_config.rnoise);
00515 cpl_table_set_double(ps.table, "MEAN_DIFF", 0, omega_readnoise_config.mean_diff);
00516 cpl_table_set_double(ps.table, "MEDIAN_DIFF", 0, omega_readnoise_config.median_diff);
00517
00518
00519 if(omega_readnoise_save(set, pars) == -1){
00520 cpl_msg_error(_id,"Cannot save this extension product");
00521 omega_readnoise_tidy();
00522 return -1;
00523 }
00524
00525 freefits(ps.biasfits1);
00526 freetable(ps.table);
00527 }
00528
00529 omega_readnoise_tidy();
00530
00531 return 0;
00532
00533 }
00534
00535
00544
00545 int omega_readnoise_save(cpl_frameset *set,
00546 cpl_parameterlist *parlist)
00547 {
00548
00549 const char *fctid = "omega_readnoise_save";
00550 cpl_propertylist *plist;
00551 cpl_propertylist *qclist;
00552
00553
00554
00555 if (isfirst) {
00556
00557
00558 if(omega_pfits_check_instrume(cpl_frameset_get_first_const(set)) == 1)
00559 sprintf(INSTRUME,"wfi");
00560
00561
00562 sprintf(outfile, "%s_%s.fits",INSTRUME,PROCATG) ;
00563
00564
00565 product_frame = cpl_frame_new();
00566 cpl_frame_set_filename(product_frame,outfile);
00567 cpl_frame_set_tag(product_frame,PROCATG);
00568 cpl_frame_set_type(product_frame,CPL_FRAME_TYPE_TABLE);
00569 cpl_frame_set_group(product_frame,CPL_FRAME_GROUP_PRODUCT);
00570 cpl_frame_set_level(product_frame,CPL_FRAME_LEVEL_FINAL);
00571
00572 plist = cpl_propertylist_new();
00573
00574
00575 if (cpl_dfs_setup_product_header(plist, product_frame, set, parlist,
00576 RECIPE,PIPEID,DICID,NULL) != CPL_ERROR_NONE) {
00577
00578 cpl_msg_warning(fctid, "Problem in the main header of product DFS-compliance") ;
00579 }
00580
00581
00582
00583
00584 cpl_propertylist_erase_regexp(plist,REM_PRIM_KEYS,0);
00585
00586
00587 if (cpl_propertylist_save(plist,outfile,CPL_IO_DEFAULT) != CPL_ERROR_NONE){
00588 cpl_msg_error(fctid,"Cannot save product PHU");
00589 cpl_frame_delete(product_frame);
00590 freeplist(plist);
00591 return -1;
00592 }
00593
00594 freeplist(plist);
00595 cpl_frameset_insert(set,product_frame);
00596 }
00597
00598
00599 plist = cpl_propertylist_duplicate(omega_fits_get_ehu(ps.biasfits1));
00600 qclist = cpl_propertylist_new();
00601
00602
00603 if (cpl_dfs_setup_product_header(plist, product_frame, set, parlist,
00604 RECIPE,PIPEID,DICID,NULL) != CPL_ERROR_NONE) {
00605
00606 cpl_msg_warning(fctid, "Problem in the extension header of product DFS-compliance") ;
00607 }
00608
00609
00610 cpl_propertylist_erase_regexp(plist, REM_EXT_KEYS, 0);
00611
00612
00613
00614
00615 cpl_propertylist_update_float(qclist,"ESO QC READNOISE",
00616 omega_readnoise_config.rnoise);
00617 cpl_propertylist_update_float(qclist,"ESO QC READNOISE MEAN DIFF",
00618 omega_readnoise_config.mean_diff);
00619 cpl_propertylist_update_float(qclist,"ESO QC READNOISE MEDIAN DIFF",
00620 omega_readnoise_config.median_diff);
00621
00622
00623 cpl_propertylist_append(plist, qclist);
00624
00625
00626 cpl_propertylist_set_comment(plist,"ESO QC READNOISE",
00627 "Calculated detector readnoise");
00628 cpl_propertylist_set_comment(plist,"ESO QC READNOISE MEAN DIFF",
00629 "Calculated mean of difference");
00630 cpl_propertylist_set_comment(plist,"ESO QC READNOISE MEDIAN DIFF",
00631 "Calculated median of difference");
00632
00633
00634 if (cpl_table_save(ps.table,NULL,plist,outfile,CPL_IO_EXTEND) != CPL_ERROR_NONE) {
00635 cpl_msg_error(fctid,"Cannot save product. %s", cpl_error_get_message());
00636 freeplist(plist);
00637 freeplist(qclist);
00638 return -1;
00639 }
00640
00641
00642 if(omega_readnoise_config.paf){
00643 int xtnum = omega_fits_get_extnum(ps.biasfits1);
00644 const char pafcopy[] = "^(DATE-OBS|ARCFILE|ESO TPL ID|ESO DET WIN1 DIT1|MJD-OBS|EXTNAME|ESO PRO CATG)$";
00645 sprintf(outpaf, "%s_%s_%d.paf",INSTRUME,PROCATG,xtnum) ;
00646 cpl_frame *fframe = cpl_frameset_get_first(set);
00647 cpl_propertylist *mlist = cpl_propertylist_load_regexp(cpl_frame_get_filename(fframe),0,pafcopy, 0);
00648 cpl_propertylist_copy_property_regexp(qclist, mlist, pafcopy, 0);
00649 if(cpl_propertylist_copy_property_regexp(qclist, plist,
00650 pafcopy, 0) != CPL_ERROR_NONE){
00651 cpl_msg_warning(fctid,"Some mandatory keywords are missing in PAF file");
00652 }
00653
00654 cpl_dfs_save_paf(INSTRUME, RECIPE, qclist, outpaf);
00655 freeplist(mlist);
00656 }
00657
00658 freeplist(plist);
00659 freeplist(qclist);
00660
00661 return 0;
00662 }
00663
00664
00665
00669
00670
00671 static void omega_readnoise_init(void) {
00672 ps.labels = NULL;
00673 ps.biaslist = NULL;
00674 ps.biasfits1 = NULL;
00675 ps.biasfits2 = NULL;
00676 ps.stats = NULL;
00677 ps.table = NULL;
00678 return;
00679 }
00680
00681
00685
00686
00687 static void omega_readnoise_tidy(void) {
00688 freespace(ps.labels);
00689 freeframeset(ps.biaslist);
00690 freefits(ps.biasfits1);
00691 freefits(ps.biasfits2);
00692 freetable(ps.table);
00693 freestats(ps.stats);
00694 return;
00695 }