36 #include "omega_recipe.h"
66 static int omega_darkcurrent_create(cpl_plugin *) ;
67 static int omega_darkcurrent_exec(cpl_plugin *) ;
68 static int omega_darkcurrent_destroy(cpl_plugin *) ;
69 static int omega_darkcurrent(cpl_frameset *
set,cpl_parameterlist *pars) ;
76 cpl_propertylist *qclist, cpl_type_bpp bitpix,
77 const char *outfile, cpl_frame *product_frame);
78 static void omega_darkcurrent_init(
void);
79 static void omega_darkcurrent_tidy(
void);
96 }omega_darkcurrent_config;
101 const cpl_frame *mbframe;
102 cpl_frameset *darklist;
103 omega_fits *firstdark;
104 cpl_propertylist *eh;
113 #define RECIPE "omega_darkcurrent"
130 cpl_recipe * recipe = cpl_calloc(1,
sizeof(*recipe)) ;
131 cpl_plugin * plugin = &recipe->interface ;
133 cpl_plugin_init(plugin,
135 OMEGA_BINARY_VERSION,
136 CPL_PLUGIN_TYPE_RECIPE,
138 "OMEGA - Measure the dark current and the particle event rate.(Calfile 531).",
139 "The raw dark frames are trimmed, overscan-corrected and"
140 "debiased. The dark current is calculated by median averaging"
141 "three reduced dark frames and iteratively rejecting outliers"
142 "from the result, and computing the mean of the remaining pixels.",
146 omega_darkcurrent_create,
147 omega_darkcurrent_exec,
148 omega_darkcurrent_destroy) ;
150 cpl_pluginlist_append(list, plugin) ;
166 static int omega_darkcurrent_create(cpl_plugin * plugin)
173 if (cpl_error_get_code() != CPL_ERROR_NONE) {
174 cpl_msg_error(cpl_func,
"%s():%d: An error is already set: %s",
175 cpl_func, __LINE__, cpl_error_get_where());
176 return (
int)cpl_error_get_code();
179 if (plugin == NULL) {
180 cpl_msg_error(cpl_func,
"Null plugin");
181 cpl_ensure_code(0, (
int)CPL_ERROR_NULL_INPUT);
185 if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {
186 cpl_msg_error(cpl_func,
"Plugin is not a recipe");
187 cpl_ensure_code(0, (
int)CPL_ERROR_TYPE_MISMATCH);
191 recipe = (cpl_recipe *)plugin;
194 recipe->parameters = cpl_parameterlist_new() ;
195 if (recipe->parameters == NULL) {
196 cpl_msg_error(cpl_func,
"Parameter list allocation failed");
197 cpl_ensure_code(0, (
int)CPL_ERROR_ILLEGAL_OUTPUT);
201 p = cpl_parameter_new_value(
"omega.omega_darkcurrent.ExtensionNumber",
203 "FITS extension number to load (1 to 32). (-1 = all)",
207 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"ext") ;
208 cpl_parameterlist_append(recipe->parameters, p) ;
211 p = cpl_parameter_new_range(
"omega.omega_darkcurrent.OverscanMethod",
213 "Overscan Correction Method",
216 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"oc-meth") ;
217 cpl_parameterlist_append(recipe->parameters, p) ;
219 p = cpl_parameter_new_value(
"omega.omega_darkcurrent.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_value(
"omega.omega_darkcurrent.RejThre",
230 "The threshold rejecting outlying pixels",
234 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"rej-thre") ;
235 cpl_parameterlist_append(recipe->parameters, p) ;
237 p = cpl_parameter_new_value(
"omega.omega_darkcurrent.DetThre",
239 "The detection threshold for cosmic ray event ",
243 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"det-thre") ;
244 cpl_parameterlist_append(recipe->parameters, p) ;
247 p = cpl_parameter_new_value(
"omega.omega_darkcurrent.MaxIter",
249 "The maximum number of iterations",
253 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"niter") ;
254 cpl_parameterlist_append(recipe->parameters, p) ;
256 p = cpl_parameter_new_value(
"omega.omega_darkcurrent.MaxCurrent",
258 "The maximum dark current in ADU/pixel/hour",
262 cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,
"maxcur") ;
263 cpl_parameterlist_append(recipe->parameters, p) ;
266 p = cpl_parameter_new_value(
"omega.omega_darkcurrent.MaxDiffCurrent",
268 "The maximum difference of dark current between previous ??",
272 cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,
"maxdifcur") ;
273 cpl_parameterlist_append(recipe->parameters, p) ;
276 path = cpl_sprintf(
"%s", OMEGA_BIN_PATH);
277 p = cpl_parameter_new_value(
"omega.omega_darkcurrent.BinPath",
279 "Path to any external executable program.",
283 cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,
"bin-path");
284 cpl_parameterlist_append(recipe->parameters, p);
287 path = cpl_sprintf(
"%s/omega.cosmic.sex", OMEGA_CONFIG_PATH);
288 p = cpl_parameter_new_value(
"omega.omega_darkcurrent.SexCosmic",
290 "Path to Sextractor cosmic detection mode config file.",
294 cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,
"sex-cosmic");
295 cpl_parameterlist_append(recipe->parameters, p);
298 path = cpl_sprintf(
"%s/omega.conv", OMEGA_CONFIG_PATH);
299 p = cpl_parameter_new_value(
"omega.omega_darkcurrent.SexConv",
301 "Path to Sextractor convolution mask file.",
305 cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,
"sex-conv");
306 cpl_parameterlist_append(recipe->parameters, p);
309 path = cpl_sprintf(
"%s/omega.param", OMEGA_CONFIG_PATH);
310 p = cpl_parameter_new_value(
"omega.omega_darkcurrent.SexParam",
312 "Path to Sextractor parameters file.",
316 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI,
"sex-param");
317 cpl_parameterlist_append(recipe->parameters, p);
320 path = cpl_sprintf(
"%s/omega.nnw", OMEGA_CONFIG_PATH);
321 p = cpl_parameter_new_value(
"omega.omega_darkcurrent.SexNnw",
323 "Path to Sextractor neural network config file.",
327 cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,
"sex-nnw");
328 cpl_parameterlist_append(recipe->parameters, p);
343 static int omega_darkcurrent_exec(cpl_plugin * plugin)
350 if (cpl_error_get_code() != CPL_ERROR_NONE) {
351 cpl_msg_error(cpl_func,
"%s():%d: An error is already set: %s",
352 cpl_func, __LINE__, cpl_error_get_where());
353 return (
int)cpl_error_get_code();
356 if (plugin == NULL) {
357 cpl_msg_error(cpl_func,
"Null plugin");
358 cpl_ensure_code(0, (
int)CPL_ERROR_NULL_INPUT);
362 if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {
363 cpl_msg_error(cpl_func,
"Plugin is not a recipe");
364 cpl_ensure_code(0, (
int)CPL_ERROR_TYPE_MISMATCH);
368 recipe = (cpl_recipe *)plugin;
371 if (recipe->parameters == NULL) {
372 cpl_msg_error(cpl_func,
"Recipe invoked with NULL parameter list");
373 cpl_ensure_code(0, (
int)CPL_ERROR_NULL_INPUT);
375 if (recipe->frames == NULL) {
376 cpl_msg_error(cpl_func,
"Recipe invoked with NULL frame set");
377 cpl_ensure_code(0, (
int)CPL_ERROR_NULL_INPUT);
381 recipe_status = omega_darkcurrent(recipe->frames, recipe->parameters);
384 if (cpl_dfs_update_product_header(recipe->frames)) {
385 if (!recipe_status) recipe_status = (int)cpl_error_get_code();
389 return recipe_status;
399 static int omega_darkcurrent_destroy(cpl_plugin * plugin)
403 if (plugin == NULL) {
404 cpl_msg_error(cpl_func,
"Null plugin");
405 cpl_ensure_code(0, (
int)CPL_ERROR_NULL_INPUT);
409 if (cpl_plugin_get_type(plugin) != CPL_PLUGIN_TYPE_RECIPE) {
410 cpl_msg_error(cpl_func,
"Plugin is not a recipe");
411 cpl_ensure_code(0, (
int)CPL_ERROR_TYPE_MISMATCH);
415 recipe = (cpl_recipe *)plugin;
417 cpl_parameterlist_delete(recipe->parameters);
431 static int omega_darkcurrent(cpl_frameset *
set, cpl_parameterlist *pars)
440 char *outmdark = NULL;
441 const char *_id =
"omega_darkcurrent";
443 cpl_parameter *par = NULL;
444 cpl_frame *firstframe = NULL;
445 cpl_frame *prframe_mdark = NULL;
446 cpl_propertylist *qclist = NULL;
447 cpl_propertylist *alist = NULL;
454 cpl_msg_error (_id,
"Parameters list not found");
458 if (cpl_frameset_is_empty(
set) == 1) {
459 cpl_msg_error (_id,
"Frameset not found");
464 par = cpl_parameterlist_find(pars,
"omega.omega_darkcurrent.ExtensionNumber") ;
465 omega_darkcurrent_config.extnum = cpl_parameter_get_int(par) ;
467 par = cpl_parameterlist_find(pars,
"omega.omega_darkcurrent.OverscanMethod") ;
468 omega_darkcurrent_config.oc = cpl_parameter_get_int(par) ;
470 par = cpl_parameterlist_find(pars,
"omega.omega_darkcurrent.PAF");
471 omega_darkcurrent_config.paf = cpl_parameter_get_bool(par);
476 if (oc_dfs_set_groups(
set)) {
477 cpl_msg_error(_id,
"Cannot identify RAW and CALIB frames") ;
482 omega_darkcurrent_init();
487 cpl_msg_error(_id,
"Cannot labelise the input frameset");
488 omega_darkcurrent_tidy();
492 DARK_RAW)) == NULL) {
493 cpl_msg_error(_id,
"Cannot find bias frames in input frameset");
494 omega_darkcurrent_tidy();
498 ndark = cpl_frameset_count_tags (
set, DARK_RAW);
500 cpl_msg_error (_id,
"Need at least 3 (%s) frames to run this recipe", DARK_RAW);
501 omega_darkcurrent_tidy();
505 cpl_msg_info (_id,
"There are %d %s frames in frame set",ndark, DARK_RAW);
508 firstframe = cpl_frameset_get_first(ps.darklist);
513 ps.mbframe = cpl_frameset_find_const(
set, OMEGA_CALIB_BIAS);
514 if (ps.mbframe == NULL) {
515 cpl_msg_info(_id,
"A Master Bias is not present in frame set. Using default value %f", bias);
518 cpl_msg_info(_id,
"Using %s %s",OMEGA_CALIB_BIAS, cpl_frame_get_filename(ps.mbframe));
523 if(omega_darkcurrent_config.extnum == 0){
524 cpl_msg_error(cpl_func,
"Unsupported extension request, %d",omega_darkcurrent_config.extnum);
525 omega_darkcurrent_tidy();
530 for (j = jst; j <= jfn; j++) {
532 isfirst = (j == jst);
533 cpl_msg_info(_id,
"Beginning work on extension %d",j);
534 omega_darkcurrent_config.dark_current = 0.0;
535 omega_darkcurrent_config.rate = 0;
539 if(omega_darkcurrent_config.oc==0){
540 if(ps.mbframe != NULL){
542 if(oscan1 != omega_darkcurrent_config.oc) {
543 cpl_msg_warning (_id,
"Overscan correction mode for Master Bias (oc = %d) differs from "
544 "the one used here (oc = %d)", oscan1, omega_darkcurrent_config.oc);
555 cpl_msg_warning(_id,
"Image detector is not live");
557 freefits(ps.firstdark);
561 else if(status == -1){
562 cpl_msg_error(_id,
"Cannot combine images");
564 omega_darkcurrent_tidy();
572 qclist = cpl_propertylist_new();
573 cpl_propertylist_append_double(qclist,
"ESO QC DARK CURRENT",
574 omega_darkcurrent_config.dark_current) ;
575 cpl_propertylist_set_comment(qclist,
"ESO QC DARK CURRENT",
577 cpl_propertylist_append_double(qclist,
"ESO QC PARTICLE RATE",
578 omega_darkcurrent_config.rate) ;
579 cpl_propertylist_set_comment(qclist,
"ESO QC PARTICLE RATE",
580 "Value of particle rate" ) ;
583 outmdark = cpl_sprintf(
"%s_%s.fits", INSTRUME,DARK_PROCATG);
587 alist = cpl_propertylist_new();
588 cpl_propertylist_append_string(alist,
"EXTNAME",
589 cpl_propertylist_get_string(ps.eh,
"EXTNAME"));
590 cpl_propertylist_set_comment(alist,
"EXTNAME",
"Extension name");
592 cpl_propertylist_copy_property_regexp(alist, ps.eh, WCS_KEYS, 0);
594 if(
omega_save_image(ps.mdark,
set,pars,alist,qclist,CPL_BPP_IEEE_FLOAT,outmdark,
595 RECIPE,prframe_mdark,NULL,isfirst) == -1){
596 cpl_msg_error(_id,
"Cannot save product %s", DARK_PROCATG);
600 omega_darkcurrent_tidy();
607 freefits(ps.firstdark);
615 omega_darkcurrent_tidy();
640 double dethres = 3.0;
641 double exptime = 0.0;
644 double detector_size_x=1.;
645 double detector_size_y=1.;
646 double detector_size=1.;
648 const char *cmd = NULL;
649 const char *cosmiccat =
"OMEGA_cosmicrays.fits";
650 const char *cosmic_conf = NULL;
651 const char *_id =
"";
652 const char *path = NULL;
653 const char *sex_conv = NULL;
654 const char *sex_nnw = NULL;
655 const char *sex_par = NULL;
656 const char *temp1739 =
"OMEGA_temp001739.fits";
658 const cpl_frame *darkfr = NULL;
659 cpl_image *mbias = NULL, *trim_raw = NULL;
660 cpl_imagelist *ilist = NULL;
661 cpl_stats *stats = NULL;
662 cpl_parameter *par = NULL;
663 cpl_propertylist *mplist = NULL, *xplist = NULL;
666 par = cpl_parameterlist_find(pars,
"omega.omega_darkcurrent.MaxIter") ;
667 maxiter = cpl_parameter_get_int(par) ;
669 par = cpl_parameterlist_find(pars,
"omega.omega_darkcurrent.RejThre") ;
670 rejt = cpl_parameter_get_double(par) ;
672 par = cpl_parameterlist_find(pars,
"omega.omega_darkcurrent.DetThre") ;
673 dethres = cpl_parameter_get_double(par) ;
675 par = cpl_parameterlist_find(pars,
"omega.omega_darkcurrent.BinPath");
676 path = cpl_parameter_get_string(par) ;
678 par = cpl_parameterlist_find(pars,
"omega.omega_darkcurrent.SexCosmic" );
679 cosmic_conf = cpl_parameter_get_string(par) ;
681 par = cpl_parameterlist_find(pars,
"omega.omega_darkcurrent.SexConv" );
682 sex_conv = cpl_parameter_get_string(par) ;
684 par = cpl_parameterlist_find(pars,
"omega.omega_darkcurrent.SexParam" );
685 sex_par = cpl_parameter_get_string(par) ;
687 par = cpl_parameterlist_find(pars,
"omega.omega_darkcurrent.SexNnw" );
688 sex_nnw = cpl_parameter_get_string(par) ;
690 ndark = cpl_frameset_get_size(ps.darklist);
691 darkfr = cpl_frameset_get_first_const(ps.darklist);
700 if(ps.mbframe != NULL){
701 mbias = cpl_image_load(cpl_frame_get_filename(ps.mbframe), CPL_TYPE_FLOAT,0,xn);
703 cpl_msg_warning(_id,
"Cannot load image %s", OMEGA_CALIB_BIAS);
707 ilist = cpl_imagelist_new();
708 cpl_msg_info (_id,
"Doing trim and overscan correction on images");
713 for (i=0; i< ndark; i++)
717 if(trim_raw == NULL){
718 cpl_msg_error(_id,
"Cannot trim image");
723 if(omega_darkcurrent_config.oc==0){
725 cpl_msg_info(cpl_func,
"Subtracting bias frame");
726 cpl_image_subtract(trim_raw, mbias);
729 cpl_image_subtract_scalar(trim_raw, bias);
732 cpl_imagelist_set(ilist, trim_raw, i);
733 darkfr = cpl_frameset_get_next_const(ps.darklist);
741 cpl_msg_error(_id,
"Error in image list <%s>",cpl_error_get_message());
746 cpl_msg_info (_id,
"Computing the median of all images...");
747 ps.mdark = cpl_imagelist_collapse_median_create(ilist);
749 if (ps.mdark == NULL) {
750 cpl_msg_error (_id,
"Cannot take median of list <%s>",cpl_error_get_message());
755 cpl_msg_info(_id,
"Estimating the RMS using %d maximum iterations",maxiter);
756 cpl_msg_info(_id,
"Rejection threshold is %g (sigma)",rejt);
762 cpl_msg_warning(_id,
"Cannot calculate statistics iteratively");
765 darkfr = cpl_frameset_get_first(ps.darklist);
766 mplist = cpl_propertylist_load_regexp(cpl_frame_get_filename(darkfr), 0,
"EXPTIME", 0);
767 xplist = cpl_propertylist_load_regexp(cpl_frame_get_filename(darkfr), xn,
"EXPTIME", 0);
773 omega_darkcurrent_config.dark_current = cpl_stats_get_mean(stats) / exptime*3600.0;
781 for(i=0; i < ndark; i++){
783 cpl_image_save(cpl_imagelist_get(ilist, i),temp1739,BITPIX,NULL,CPL_IO_DEFAULT);
789 cmd = cpl_sprintf(
"%s/sex %s -c %s -PARAMETERS_NAME %s -FILTER_NAME %s -STARNNW_NAME %s "
791 "-CHECKIMAGE_NAME chkimage.fits "
792 "-CATALOG_TYPE FITS_1.0 "
803 if (system(cmd) != 0) {
804 cpl_free((
char *)cmd);
806 cpl_msg_error(
"",
"%s Failed to run Sextractor", _id);
810 cpl_free((
char *)cmd);
812 mplist = cpl_propertylist_load_regexp(cosmiccat, 1,
"NAXIS2", 0);
814 cpl_msg_error(_id,
"Cannot load header for %s",cosmiccat);
819 count = cpl_propertylist_get_int(mplist,
"NAXIS2");
827 detector_size_x=cpl_image_get_size_x(cpl_imagelist_get(ilist,0));
828 detector_size_y=cpl_image_get_size_y(cpl_imagelist_get(ilist,0));
829 detector_size=detector_size_x * detector_size_y * 0.0015 * 0.0015;
832 rate = rate/exptime*3600.0;
834 rate = rate/detector_size;
836 omega_darkcurrent_config.rate = rate;
873 cpl_propertylist *qclist, cpl_type_bpp bitpix,
874 const char *outfile, cpl_frame *product_frame)
878 const char *fctid =
"omega_darkcurrent_save";
879 cpl_propertylist *plist = NULL;
885 plist = cpl_propertylist_new();
888 if (cpl_dfs_setup_product_header(plist, product_frame,
set, parlist,
889 RECIPE,PIPEID,DICID,NULL) != CPL_ERROR_NONE) {
891 cpl_msg_warning(fctid,
"Problem in the main header of product DFS-compliance") ;
897 cpl_propertylist_erase_regexp(plist,REM_PRIM_KEYS,0);
900 if (cpl_propertylist_save(plist,outfile,CPL_IO_DEFAULT) != CPL_ERROR_NONE){
901 cpl_msg_error(fctid,
"Cannot save product PHU");
907 cpl_frameset_insert(
set,product_frame);
911 plist = cpl_propertylist_duplicate(ps.eh);
915 cpl_propertylist_append_int(plist,
"ESO DRS OVERSCAN METHOD", omega_darkcurrent_config.oc);
916 cpl_propertylist_set_comment(plist,
"ESO DRS OVERSCAN METHOD",
"overscan correction method");
919 if (cpl_dfs_setup_product_header(plist, product_frame,
set, parlist,
920 RECIPE,PIPEID,DICID,NULL) != CPL_ERROR_NONE) {
922 cpl_msg_warning(fctid,
"Problem in the extension header of product DFS-compliance") ;
926 cpl_propertylist_erase_regexp(plist, REM_EXT_KEYS, 0);
930 cpl_propertylist_append(plist, qclist);
933 if (cpl_image_save(image,outfile,bitpix,plist,
934 CPL_IO_EXTEND) != CPL_ERROR_NONE) {
935 cpl_msg_error(fctid,
"Cannot save product. %s", cpl_error_get_message());
942 if(omega_darkcurrent_config.paf){
945 char *outpaf = cpl_sprintf(
"%s_%d.paf",prefix,xtnum);
946 const char pafcopy[] =
"^(DATE-OBS|ARCFILE|ESO TPL ID|ESO DET WIN1 DIT1|MJD-OBS|EXTNAME|ESO PRO CATG)$";
947 cpl_frame *fframe = cpl_frameset_get_first(
set);
948 cpl_propertylist *mlist = cpl_propertylist_load_regexp(cpl_frame_get_filename(fframe),0,pafcopy, 0);
949 cpl_propertylist_copy_property_regexp(qclist, mlist, pafcopy, 0);
950 if (cpl_propertylist_copy_property_regexp(qclist, plist,
951 pafcopy, 0) != CPL_ERROR_NONE){
953 cpl_msg_warning(fctid,
"Some mandatory keywords are missing in PAF file");
956 cpl_dfs_save_paf(INSTRUME, RECIPE, qclist, outpaf);
967 static void omega_darkcurrent_init(
void) {
977 static void omega_darkcurrent_tidy(
void) {
978 freespace(ps.labels);
979 freeframeset(ps.darklist);
981 freefits(ps.firstdark);