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
00029
00030 #ifdef HAVE_CONFIG_H
00031 #include <config.h>
00032 #endif
00033
00034 #include <stdio.h>
00035 #include <cpl.h>
00036 #include <math.h>
00037
00038 #include "vircam_utils.h"
00039 #include "vircam_pfits.h"
00040 #include "vircam_dfs.h"
00041 #include "vircam_mods.h"
00042 #include "vircam_stats.h"
00043 #include "vircam_fits.h"
00044 #include "vircam_mask.h"
00045 #include "vircam_channel.h"
00046 #include "vircam_dfs.h"
00047 #include "vircam_paf.h"
00048 #include "vircam_wcsutils.h"
00049
00050
00051
00052 #define MEANDARK 1
00053 #define DIFFIMG 2
00054 #define STATS_TAB 4
00055
00056
00057
00058 static int vircam_dark_combine_create(cpl_plugin *) ;
00059 static int vircam_dark_combine_exec(cpl_plugin *) ;
00060 static int vircam_dark_combine_destroy(cpl_plugin *) ;
00061 static int vircam_dark_combine(cpl_parameterlist *, cpl_frameset *) ;
00062 static int vircam_dark_combine_save(cpl_frameset *framelist,
00063 cpl_parameterlist *parlist);
00064 static void vircam_dark_combine_dummy_products(void);
00065 static void vircam_dark_combine_hotpix(void);
00066 static void vircam_dark_combine_normal(int jext, float exptime);
00067 static int vircam_dark_combine_lastbit(int jext, cpl_frameset *framelist,
00068 cpl_parameterlist *parlist);
00069 static void vircam_dark_combine_init(void);
00070 static void vircam_dark_combine_tidy(int level);
00071
00072
00073
00074 static struct {
00075
00076
00077
00078 int combtype;
00079 int scaletype;
00080 int xrej;
00081 float thresh;
00082 int ncells;
00083 int extenum;
00084
00085
00086
00087 float particle_rate;
00088 float darkmed;
00089 float darkrms;
00090 float darkdiff_med;
00091 float darkdiff_rms;
00092 float striperms;
00093 int nhot;
00094 float hotfrac;
00095 float ron12;
00096
00097 } vircam_dark_combine_config;
00098
00099
00100 static struct {
00101 cpl_size *labels;
00102 cpl_frameset *darklist;
00103 vir_fits **darks;
00104 int ndarks;
00105 vir_fits **good;
00106 int ngood;
00107 cpl_frame *master_dark;
00108 vir_mask *master_mask;
00109 cpl_frame *chantab;
00110 cpl_image *outimage;
00111 cpl_propertylist *drs;
00112 unsigned char *rejmask;
00113 unsigned char *rejplus;
00114 vir_fits *mdimage;
00115 cpl_image *diffimg;
00116 cpl_table *diffimstats;
00117 cpl_propertylist *phupaf;
00118 } ps;
00119
00120 static cpl_frame *product_frame_mean_dark = NULL;
00121 static cpl_frame *product_frame_diffimg = NULL;
00122 static cpl_frame *product_frame_diffimg_stats = NULL;
00123 static int isfirst;
00124 static int we_expect;
00125 static int we_get;
00126
00127 static char vircam_dark_combine_description[] =
00128 "vircam_dark_combine -- VIRCAM dark combine recipe.\n\n"
00129 "Combine a list of dark frames into a mean dark frame. Optionally compare \n"
00130 "the output frame to a master dark frame\n\n"
00131 "The program accepts the following files in the SOF:\n\n"
00132 " Tag Description\n"
00133 " -----------------------------------------------------------------------\n"
00134 " %-21s A list of raw dark images\n"
00135 " %-21s Optional reference dark frame\n"
00136 " %-21s Optional master bad pixel map or\n"
00137 " %-21s Optional master confidence map\n"
00138 " %-21s Optional channel table or\n"
00139 " %-21s Optional initial channel table\n"
00140 "If no master dark frame is made available, then no comparison will be done\n"
00141 "This means there will be no output difference image. If a master dark is\n"
00142 "available, but no channel table is, then a difference image will be formed\n"
00143 "but no stats will be written."
00144 "\n";
00145
00274
00275
00276
00277
00285
00286
00287 int cpl_plugin_get_info(cpl_pluginlist *list) {
00288 cpl_recipe *recipe = cpl_calloc(1,sizeof(*recipe));
00289 cpl_plugin *plugin = &recipe->interface;
00290 char alldesc[SZ_ALLDESC];
00291 (void)snprintf(alldesc,SZ_ALLDESC,vircam_dark_combine_description,
00292 VIRCAM_DARK_RAW,VIRCAM_REF_DARK,VIRCAM_CAL_BPM,
00293 VIRCAM_CAL_CONF,VIRCAM_CAL_CHANTAB,VIRCAM_CAL_CHANTAB_INIT);
00294
00295 cpl_plugin_init(plugin,
00296 CPL_PLUGIN_API,
00297 VIRCAM_BINARY_VERSION,
00298 CPL_PLUGIN_TYPE_RECIPE,
00299 "vircam_dark_combine",
00300 "VIRCAM dark combination recipe",
00301 alldesc,
00302 "Jim Lewis",
00303 "jrl@ast.cam.ac.uk",
00304 vircam_get_license(),
00305 vircam_dark_combine_create,
00306 vircam_dark_combine_exec,
00307 vircam_dark_combine_destroy);
00308
00309 cpl_pluginlist_append(list,plugin);
00310
00311 return(0);
00312 }
00313
00314
00323
00324
00325 static int vircam_dark_combine_create(cpl_plugin *plugin) {
00326 cpl_recipe *recipe;
00327 cpl_parameter *p;
00328
00329
00330
00331 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
00332 recipe = (cpl_recipe *)plugin;
00333 else
00334 return(-1);
00335
00336
00337
00338 recipe->parameters = cpl_parameterlist_new();
00339
00340
00341
00342 p = cpl_parameter_new_range("vircam.vircam_dark_combine.combtype",
00343 CPL_TYPE_INT,
00344 "1 == Median,\n 2 == Mean",
00345 "vircam.vircam_dark_combine",
00346 1,1,2);
00347 cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"combtype");
00348 cpl_parameterlist_append(recipe->parameters,p);
00349
00350
00351
00352 p = cpl_parameter_new_range("vircam.vircam_dark_combine.scaletype",
00353 CPL_TYPE_INT,
00354 "0 == none,\n 1 == additive offset,\n 2 == multiplicative offset,\n 3 == exposure time scaling + additive offset",
00355 "vircam.vircam_dark_combine",
00356 1,0,3);
00357 cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"scaletype");
00358 cpl_parameterlist_append(recipe->parameters,p);
00359
00360
00361
00362 p = cpl_parameter_new_value("vircam.vircam_dark_combine.xrej",
00363 CPL_TYPE_BOOL,
00364 "True if using extra rejection cycle",
00365 "vircam.vircam_dark_combine",
00366 TRUE);
00367 cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"xrej");
00368 cpl_parameterlist_append(recipe->parameters,p);
00369
00370
00371
00372 p = cpl_parameter_new_value("vircam.vircam_dark_combine.thresh",
00373 CPL_TYPE_DOUBLE,
00374 "Rejection threshold in sigma above background",
00375 "vircam.vircam_dark_combine",5.0);
00376 cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"thresh");
00377 cpl_parameterlist_append(recipe->parameters,p);
00378
00379
00380
00381 p = cpl_parameter_new_enum("vircam.vircam_dark_combine.ncells",
00382 CPL_TYPE_INT,
00383 "Number of cells for data channel stats",
00384 "vircam.vircam_dark_combine",8,7,1,2,4,8,
00385 16,32,64);
00386 cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"ncells");
00387 cpl_parameterlist_append(recipe->parameters,p);
00388
00389
00390
00391 p = cpl_parameter_new_range("vircam.vircam_dark_combine.extenum",
00392 CPL_TYPE_INT,
00393 "Extension number to be done, 0 == all",
00394 "vircam.vircam_dark_combine",
00395 1,0,16);
00396 cpl_parameter_set_alias(p,CPL_PARAMETER_MODE_CLI,"ext");
00397 cpl_parameterlist_append(recipe->parameters,p);
00398
00399
00400
00401 return(0);
00402 }
00403
00404
00405
00411
00412
00413 static int vircam_dark_combine_exec(cpl_plugin *plugin) {
00414 cpl_recipe *recipe;
00415
00416
00417
00418 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
00419 recipe = (cpl_recipe *)plugin;
00420 else
00421 return(-1);
00422
00423 return(vircam_dark_combine(recipe->parameters,recipe->frames));
00424 }
00425
00426
00432
00433
00434 static int vircam_dark_combine_destroy(cpl_plugin *plugin) {
00435 cpl_recipe *recipe ;
00436
00437
00438
00439 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
00440 recipe = (cpl_recipe *)plugin;
00441 else
00442 return(-1);
00443
00444 cpl_parameterlist_delete(recipe->parameters);
00445 return(0);
00446 }
00447
00448
00455
00456
00457 static int vircam_dark_combine(cpl_parameterlist *parlist,
00458 cpl_frameset *framelist) {
00459 const char *fctid="vircam_dark_combine";
00460 const char *fname;
00461 int j,jst,jfn,retval,status,live,nx,ny;
00462 cpl_size nlab;
00463 long i;
00464 float exptime;
00465 vir_fits *ff;
00466 cpl_parameter *p;
00467 cpl_propertylist *plist;
00468
00469
00470
00471 if (framelist == NULL || cpl_frameset_get_size(framelist) <= 0) {
00472 cpl_msg_error(fctid,"Input framelist NULL or has no input data");
00473 return(-1);
00474 }
00475
00476
00477
00478 if (vircam_frameset_fexists(framelist) != VIR_OK) {
00479 cpl_msg_error(fctid,"Input frameset is missing files. Check SOF");
00480 return(-1);
00481 }
00482
00483
00484
00485 vircam_dark_combine_init();
00486 we_expect |= MEANDARK;
00487
00488
00489
00490 p = cpl_parameterlist_find(parlist,"vircam.vircam_dark_combine.combtype");
00491 vircam_dark_combine_config.combtype = cpl_parameter_get_int(p);
00492 p = cpl_parameterlist_find(parlist,"vircam.vircam_dark_combine.scaletype");
00493 vircam_dark_combine_config.scaletype = cpl_parameter_get_int(p);
00494 p = cpl_parameterlist_find(parlist,"vircam.vircam_dark_combine.xrej");
00495 vircam_dark_combine_config.xrej = cpl_parameter_get_bool(p);
00496 p = cpl_parameterlist_find(parlist,"vircam.vircam_dark_combine.thresh");
00497 vircam_dark_combine_config.thresh = (float)cpl_parameter_get_double(p);
00498 p = cpl_parameterlist_find(parlist,"vircam.vircam_dark_combine.ncells");
00499 vircam_dark_combine_config.ncells = cpl_parameter_get_int(p);
00500 p = cpl_parameterlist_find(parlist,"vircam.vircam_dark_combine.extenum");
00501 vircam_dark_combine_config.extenum = cpl_parameter_get_int(p);
00502
00503
00504
00505 if (vircam_dfs_set_groups(framelist) != VIR_OK) {
00506 cpl_msg_error(fctid,"Cannot identify RAW and CALIB frames");
00507 vircam_dark_combine_tidy(2);
00508 return(-1);
00509 }
00510
00511
00512
00513 if ((ps.labels = cpl_frameset_labelise(framelist,vircam_compare_tags,
00514 &nlab)) == NULL) {
00515 cpl_msg_error(fctid,"Cannot labelise the input frames");
00516 vircam_dark_combine_tidy(2);
00517 return(-1);
00518 }
00519
00520
00521
00522 if ((ps.darklist = vircam_frameset_subgroup(framelist,ps.labels,nlab,
00523 VIRCAM_DARK_RAW)) == NULL) {
00524 cpl_msg_error(fctid,"Cannot find dark frames in input frameset");
00525 vircam_dark_combine_tidy(2);
00526 return(-1);
00527 }
00528 ps.ndarks = cpl_frameset_get_size(ps.darklist);
00529
00530
00531
00532 fname = cpl_frame_get_filename(cpl_frameset_get_first(ps.darklist));
00533 plist = cpl_propertylist_load(fname,0);
00534 if (vircam_pfits_get_exptime(plist,&exptime) != VIR_OK) {
00535 cpl_msg_warning(fctid,"Unable to get exposure time for %s",fname);
00536 exptime = 1.0;
00537 }
00538 cpl_propertylist_delete(plist);
00539
00540
00541
00542 if ((ps.master_dark = vircam_frameset_subgroup_1(framelist,ps.labels,nlab,
00543 VIRCAM_REF_DARK)) == NULL)
00544 cpl_msg_info(fctid,"No master dark found -- no difference image will be formed");
00545 else
00546 we_expect |= DIFFIMG;
00547
00548
00549
00550
00551 ps.master_mask = vircam_mask_define(framelist,ps.labels,nlab);
00552
00553
00554
00555 if ((ps.chantab = vircam_frameset_subgroup_1(framelist,ps.labels,nlab,
00556 VIRCAM_CAL_CHANTAB)) == NULL) {
00557 if ((ps.chantab = vircam_frameset_subgroup_1(framelist,ps.labels,nlab,
00558 VIRCAM_CAL_CHANTAB_INIT)) == NULL)
00559 cpl_msg_info(fctid,"No channel table found -- no difference image stats will be done");
00560 } else if (we_expect & DIFFIMG)
00561 we_expect |= STATS_TAB;
00562
00563
00564
00565
00566
00567 vircam_exten_range(vircam_dark_combine_config.extenum,
00568 (const cpl_frame *)cpl_frameset_get_frame(ps.darklist,0),
00569 &jst,&jfn);
00570 if (jst == -1 || jfn == -1) {
00571 cpl_msg_error(fctid,"Unable to continue");
00572 vircam_dark_combine_tidy(2);
00573 return(-1);
00574 }
00575
00576
00577
00578 ps.good = cpl_malloc(ps.ndarks*sizeof(vir_fits *));
00579
00580
00581
00582 for (j = jst; j <= jfn; j++) {
00583 status = VIR_OK;
00584 we_get = 0;
00585 isfirst = (j == jst);
00586
00587
00588
00589
00590 ps.darks = vircam_fits_load_list(ps.darklist,CPL_TYPE_FLOAT,j);
00591 if (ps.darks == NULL) {
00592 cpl_msg_info(fctid,
00593 "Extension %" CPL_SIZE_FORMAT " darks wouldn't load",
00594 (cpl_size)j);
00595 retval = vircam_dark_combine_lastbit(j,framelist,parlist);
00596 if (retval != 0)
00597 return(-1);
00598 continue;
00599 }
00600
00601
00602
00603 ps.ngood = 0;
00604 for (i = 0; i < ps.ndarks; i++) {
00605 ff = ps.darks[i];
00606 vircam_pfits_get_detlive(vircam_fits_get_ehu(ff),&live);
00607 if (! live) {
00608 cpl_msg_info(fctid,"Detector flagged dead %s",
00609 vircam_fits_get_fullname(ff));
00610 vircam_fits_set_error(ff,VIR_FATAL);
00611 } else {
00612 ps.good[ps.ngood] = ff;
00613 ps.ngood += 1;
00614 }
00615 }
00616
00617
00618
00619
00620 if (ps.ngood == 0) {
00621 cpl_msg_info(fctid,"All images flagged bad for this extension");
00622 retval = vircam_dark_combine_lastbit(j,framelist,parlist);
00623 if (retval != 0)
00624 return(-1);
00625 continue;
00626 }
00627
00628
00629
00630 nx = (int)cpl_image_get_size_x(vircam_fits_get_image(ps.good[0]));
00631 ny = (int)cpl_image_get_size_y(vircam_fits_get_image(ps.good[0]));
00632 retval = vircam_mask_load(ps.master_mask,j,nx,ny);
00633 if (retval == VIR_FATAL) {
00634 cpl_msg_info(fctid,
00635 "Unable to load mask image %s[%" CPL_SIZE_FORMAT "]",
00636 vircam_mask_get_filename(ps.master_mask),(cpl_size)j);
00637 cpl_msg_info(fctid,"Forcing all pixels to be good from now on");
00638 vircam_mask_force(ps.master_mask,nx,ny);
00639 }
00640
00641
00642
00643
00644 cpl_msg_info(fctid,"Doing combination for extension %" CPL_SIZE_FORMAT,
00645 (cpl_size)j);
00646 (void)vircam_imcombine(ps.good,ps.ngood,
00647 vircam_dark_combine_config.combtype,
00648 vircam_dark_combine_config.scaletype,
00649 vircam_dark_combine_config.xrej,
00650 vircam_dark_combine_config.thresh,
00651 &(ps.outimage),&(ps.rejmask),
00652 &(ps.rejplus),&(ps.drs),&status);
00653 if (status == VIR_OK) {
00654 we_get |= MEANDARK;
00655 vircam_dark_combine_hotpix();
00656 vircam_dark_combine_normal(j,exptime);
00657 }
00658
00659
00660
00661 retval = vircam_dark_combine_lastbit(j,framelist,parlist);
00662 if (retval != 0)
00663 return(-1);
00664 }
00665 vircam_dark_combine_tidy(2);
00666 return(0);
00667 }
00668
00669
00670
00677
00678
00679 static int vircam_dark_combine_save(cpl_frameset *framelist,
00680 cpl_parameterlist *parlist) {
00681 cpl_propertylist *plist,*elist,*p,*pafprop;
00682 int status;
00683 const char *fctid = "vircam_dark_combine_save";
00684 const char *outfile = "darkcomb.fits";
00685 const char *outdiff = "darkdiff.fits";
00686 const char *outdimst = "darkdifftab.fits";
00687 const char *outfilepaf = "darkcomb";
00688 const char *outdiffpaf = "darkdiff";
00689 const char *recipeid = "vircam_dark_combine";
00690
00691
00692
00693 if (isfirst) {
00694
00695
00696
00697 product_frame_mean_dark = cpl_frame_new();
00698 cpl_frame_set_filename(product_frame_mean_dark,outfile);
00699 cpl_frame_set_tag(product_frame_mean_dark,VIRCAM_PRO_DARK);
00700 cpl_frame_set_type(product_frame_mean_dark,CPL_FRAME_TYPE_IMAGE);
00701 cpl_frame_set_group(product_frame_mean_dark,CPL_FRAME_GROUP_PRODUCT);
00702 cpl_frame_set_level(product_frame_mean_dark,CPL_FRAME_LEVEL_FINAL);
00703
00704
00705
00706 plist = vircam_fits_get_phu(ps.darks[0]);
00707 ps.phupaf = vircam_paf_phu_items(plist);
00708 if (ps.master_dark != NULL) {
00709 cpl_propertylist_update_string(ps.phupaf,"REF_DARK",
00710 cpl_frame_get_filename(ps.master_dark));
00711 cpl_propertylist_set_comment(ps.phupaf,"REF_DARK",
00712 "Reference dark used");
00713 }
00714 vircam_dfs_set_product_primary_header(plist,product_frame_mean_dark,
00715 framelist,parlist,
00716 (char *)recipeid,"PRO-1.15",
00717 NULL,0);
00718
00719
00720
00721 if (cpl_image_save(NULL,outfile,CPL_TYPE_UCHAR,plist,
00722 CPL_IO_DEFAULT) != CPL_ERROR_NONE) {
00723 cpl_msg_error(fctid,"Cannot save product PHU");
00724 cpl_frame_delete(product_frame_mean_dark);
00725 return(-1);
00726 }
00727 cpl_frameset_insert(framelist,product_frame_mean_dark);
00728
00729
00730
00731 if (we_expect & DIFFIMG) {
00732 product_frame_diffimg = cpl_frame_new();
00733 cpl_frame_set_filename(product_frame_diffimg,outdiff);
00734 cpl_frame_set_tag(product_frame_diffimg,VIRCAM_PRO_DIFFIMG_DARK);
00735 cpl_frame_set_type(product_frame_diffimg,CPL_FRAME_TYPE_IMAGE);
00736 cpl_frame_set_group(product_frame_diffimg,CPL_FRAME_GROUP_PRODUCT);
00737 cpl_frame_set_level(product_frame_diffimg,CPL_FRAME_LEVEL_FINAL);
00738
00739
00740
00741 plist = vircam_fits_get_phu(ps.darks[0]);
00742 vircam_dfs_set_product_primary_header(plist,product_frame_diffimg,
00743 framelist,parlist,
00744 (char *)recipeid,
00745 "PRO-1.15",NULL,0);
00746
00747
00748
00749 if (cpl_image_save(NULL,outdiff,CPL_TYPE_UCHAR,plist,
00750 CPL_IO_DEFAULT) != CPL_ERROR_NONE) {
00751 cpl_msg_error(fctid,"Cannot save product PHU");
00752 cpl_frame_delete(product_frame_diffimg);
00753 return(-1);
00754 }
00755 cpl_frameset_insert(framelist,product_frame_diffimg);
00756 }
00757
00758
00759
00760
00761 if (we_expect & STATS_TAB) {
00762 product_frame_diffimg_stats = cpl_frame_new();
00763 cpl_frame_set_filename(product_frame_diffimg_stats,outdimst);
00764 cpl_frame_set_tag(product_frame_diffimg_stats,
00765 VIRCAM_PRO_DIFFIMG_DARK_STATS);
00766 cpl_frame_set_type(product_frame_diffimg_stats,
00767 CPL_FRAME_TYPE_TABLE);
00768 cpl_frame_set_group(product_frame_diffimg_stats,
00769 CPL_FRAME_GROUP_PRODUCT);
00770 cpl_frame_set_level(product_frame_diffimg_stats,
00771 CPL_FRAME_LEVEL_FINAL);
00772
00773
00774
00775 plist = vircam_fits_get_phu(ps.darks[0]);
00776 vircam_dfs_set_product_primary_header(plist,
00777 product_frame_diffimg_stats,
00778 framelist,parlist,
00779 (char *)recipeid,
00780 "PRO-1.15",NULL,0);
00781
00782
00783
00784 elist = vircam_fits_get_ehu(ps.darks[0]);
00785 p = cpl_propertylist_duplicate(elist);
00786 vircam_merge_propertylists(p,ps.drs);
00787 if (! (we_get & STATS_TAB))
00788 vircam_dummy_property(p);
00789 vircam_dfs_set_product_exten_header(p,product_frame_diffimg_stats,
00790 framelist,parlist,
00791 (char *)recipeid,
00792 "PRO-1.15",NULL);
00793 status = VIR_OK;
00794 vircam_removewcs(p,&status);
00795
00796
00797
00798 if (cpl_table_save(ps.diffimstats,plist,p,outdimst,
00799 CPL_IO_DEFAULT) != CPL_ERROR_NONE) {
00800 cpl_msg_error(fctid,"Cannot save product table extension");
00801 cpl_frame_delete(product_frame_diffimg_stats);
00802 cpl_propertylist_delete(p);
00803 return(-1);
00804 }
00805 cpl_propertylist_delete(p);
00806 cpl_frameset_insert(framelist,product_frame_diffimg_stats);
00807 }
00808 }
00809
00810
00811
00812 plist = vircam_fits_get_ehu(ps.darks[0]);
00813 cpl_propertylist_update_int(plist,"ESO PRO DATANCOM",ps.ngood);
00814
00815
00816
00817 vircam_merge_propertylists(plist,ps.drs);
00818 p = cpl_propertylist_duplicate(plist);
00819 if (! (we_get & MEANDARK))
00820 vircam_dummy_property(p);
00821 vircam_dfs_set_product_exten_header(p,product_frame_mean_dark,
00822 framelist,parlist,
00823 (char *)recipeid,"PRO-1.15",NULL);
00824
00825
00826
00827 cpl_propertylist_update_float(p,"ESO QC DARKMED",
00828 vircam_dark_combine_config.darkmed);
00829 cpl_propertylist_set_comment(p,"ESO QC DARKMED",
00830 "Median of mean dark frame");
00831 cpl_propertylist_update_float(p,"ESO QC DARKRMS",
00832 vircam_dark_combine_config.darkrms);
00833 cpl_propertylist_set_comment(p,"ESO QC DARKRMS",
00834 "RMS of mean dark frame");
00835 cpl_propertylist_update_float(p,"ESO QC PARTICLE_RATE",
00836 vircam_dark_combine_config.particle_rate);
00837 cpl_propertylist_set_comment(p,"ESO QC PARTICLE_RATE",
00838 "[N/(detector*sec)] Particle rate");
00839 cpl_propertylist_update_float(p,"ESO QC STRIPERMS",
00840 vircam_dark_combine_config.striperms);
00841 cpl_propertylist_set_comment(p,"ESO QC STRIPERMS","RMS of stripe pattern");
00842 cpl_propertylist_update_int(p,"ESO QC NHOTPIX",
00843 vircam_dark_combine_config.nhot);
00844 cpl_propertylist_set_comment(p,"ESO QC NHOTPIX","Number of hot pixels");
00845 cpl_propertylist_update_float(p,"ESO QC HOTFRAC",
00846 vircam_dark_combine_config.hotfrac);
00847 cpl_propertylist_set_comment(p,"ESO QC HOTFRAC","Hot pixel fraction");
00848 cpl_propertylist_update_float(p,"ESO QC RON12",
00849 vircam_dark_combine_config.ron12);
00850 cpl_propertylist_set_comment(p,"ESO QC RON12",
00851 "[ADU] Estimate of readnoise + stripe RMS");
00852 if (cpl_image_save(ps.outimage,outfile,CPL_TYPE_FLOAT,p,
00853 CPL_IO_EXTEND) != CPL_ERROR_NONE) {
00854 cpl_msg_error(fctid,"Cannot save product image extension");
00855 cpl_propertylist_delete(p);
00856 return(-1);
00857 }
00858
00859
00860
00861 pafprop = vircam_paf_req_items(p);
00862 vircam_merge_propertylists(pafprop,ps.phupaf);
00863 vircam_paf_append(pafprop,p,"ESO DET NDIT");
00864 vircam_paf_append(pafprop,p,"ESO PRO CATG");
00865 vircam_paf_append(pafprop,p,"ESO PRO DATANCOM");
00866 if (vircam_paf_print((char *)outfilepaf,"VIRCAM/vircam_dark_combine",
00867 "QC file",pafprop) != VIR_OK)
00868 cpl_msg_warning(fctid,"Unable to save PAF for mean dark");
00869 cpl_propertylist_delete(pafprop);
00870 cpl_propertylist_delete(p);
00871
00872
00873
00874 if (we_expect & DIFFIMG) {
00875 p = cpl_propertylist_duplicate(plist);
00876 if (! (we_get & DIFFIMG))
00877 vircam_dummy_property(p);;
00878 cpl_propertylist_update_float(p,"ESO QC DARKDIFF_MED",
00879 vircam_dark_combine_config.darkdiff_med);
00880 cpl_propertylist_set_comment(p,"ESO QC DARKDIFF_MED",
00881 "Median of dark difference image");
00882 cpl_propertylist_update_float(p,"ESO QC DARKDIFF_RMS",
00883 vircam_dark_combine_config.darkdiff_rms);
00884 cpl_propertylist_set_comment(p,"ESO QC DARKDIFF_RMS",
00885 "RMS of dark difference image");
00886 vircam_dfs_set_product_exten_header(p,product_frame_diffimg,
00887 framelist,parlist,
00888 (char *)recipeid,
00889 "PRO-1.15",NULL);
00890 if (cpl_image_save(ps.diffimg,outdiff,CPL_TYPE_FLOAT,p,
00891 CPL_IO_EXTEND) != CPL_ERROR_NONE) {
00892 cpl_msg_error(fctid,"Cannot save product image extension");
00893 cpl_propertylist_delete(p);
00894 return(-1);
00895 }
00896
00897
00898
00899 pafprop = vircam_paf_req_items(p);
00900 vircam_paf_append(pafprop,p,"ESO PRO CATG");
00901 vircam_merge_propertylists(pafprop,ps.phupaf);
00902 if (vircam_paf_print((char *)outdiffpaf,"VIRCAM/vircam_dark_combine",
00903 "QC file",pafprop) != VIR_OK)
00904 cpl_msg_warning(fctid,"Unable to save PAF for difference image");
00905 cpl_propertylist_delete(pafprop);
00906 cpl_propertylist_delete(p);
00907 }
00908
00909
00910
00911 if (! isfirst && (we_expect & STATS_TAB)) {
00912 p = cpl_propertylist_duplicate(plist);
00913 if (! (we_get & STATS_TAB))
00914 vircam_dummy_property(p);
00915 vircam_dfs_set_product_exten_header(p,product_frame_diffimg_stats,
00916 framelist,parlist,
00917 (char *)recipeid,
00918 "PRO-1.15",NULL);
00919 status = VIR_OK;
00920 vircam_removewcs(p,&status);
00921 if (cpl_table_save(ps.diffimstats,NULL,p,outdimst,CPL_IO_EXTEND)
00922 != CPL_ERROR_NONE) {
00923 cpl_msg_error(fctid,"Cannot save product table extension");
00924 cpl_propertylist_delete(p);
00925 return(-1);
00926 }
00927 cpl_propertylist_delete(p);
00928 }
00929
00930 return(0);
00931 }
00932
00933
00937
00938
00939 static void vircam_dark_combine_dummy_products(void) {
00940
00941
00942
00943 if (we_get == we_expect)
00944 return;
00945
00946
00947
00948
00949 if (! (we_get & MEANDARK)) {
00950 ps.outimage = vircam_dummy_image(ps.darks[0]);
00951
00952
00953
00954 vircam_dark_combine_config.particle_rate = 0.0;
00955 vircam_dark_combine_config.darkmed = 0.0;
00956 vircam_dark_combine_config.darkrms = 0.0;
00957 vircam_dark_combine_config.nhot = 0;
00958 vircam_dark_combine_config.hotfrac = 0.0;
00959 vircam_dark_combine_config.striperms = 0.0;
00960 vircam_dark_combine_config.ron12 = 0.0;
00961 }
00962
00963
00964
00965 if ((we_expect & DIFFIMG) && ! (we_get & DIFFIMG)) {
00966 vircam_dark_combine_config.darkdiff_med = 0.0;
00967 vircam_dark_combine_config.darkdiff_rms = 0.0;
00968 ps.diffimg = vircam_dummy_image(ps.darks[0]);
00969 }
00970
00971
00972
00973 if ((we_expect & STATS_TAB) && ! (we_get & STATS_TAB))
00974 ps.diffimstats = vircam_create_diffimg_stats(0);
00975
00976 return;
00977 }
00978
00979
00983
00984
00985 static void vircam_dark_combine_hotpix(void) {
00986 int i,nx,ny,status,nh,nhot,j;
00987 long npts;
00988 cpl_image *im;
00989 unsigned char *bpm;
00990 float med,mad,lowcut,highcut,*data;
00991 vir_fits *f;
00992
00993
00994
00995 im = vircam_fits_get_image(ps.good[0]);
00996 nx = (int)cpl_image_get_size_x(im);
00997 ny = (int)cpl_image_get_size_y(im);
00998 npts = (long)(nx*ny);
00999 bpm = cpl_calloc(npts,sizeof(*bpm));
01000
01001
01002
01003
01004 for (i = 0; i < ps.ngood; i++) {
01005 f = vircam_fits_duplicate(ps.good[i]);
01006 im = vircam_fits_get_image(f);
01007 cpl_image_subtract(im,ps.outimage);
01008 status = VIR_OK;
01009 vircam_destripe(f,NULL,&status);
01010 if (i == 0) {
01011 vircam_dark_combine_config.striperms =
01012 cpl_propertylist_get_float(vircam_fits_get_ehu(f),
01013 "ESO DRS STRIPERMS");
01014 }
01015
01016
01017
01018
01019
01020
01021
01022 data = cpl_image_get_data_float(im);
01023 vircam_medmad(data,NULL,npts,&med,&mad);
01024 lowcut = med - 1.48*mad*vircam_dark_combine_config.thresh;
01025 highcut = med + 1.48*mad*vircam_dark_combine_config.thresh;
01026 for (j = 0; j < npts; j++)
01027 if (data[j] > highcut || data[j] < lowcut)
01028 bpm[j] += 1;
01029
01030
01031
01032 vircam_fits_delete(f);
01033 }
01034
01035
01036
01037
01038 nh = (ps.ngood + 1)/2;
01039 nhot = 0;
01040 for (j = 0; j < npts; j++)
01041 if (bpm[j] >= nh)
01042 nhot++;
01043
01044
01045
01046 im = cpl_image_subtract_create(vircam_fits_get_image(ps.good[0]),
01047 vircam_fits_get_image(ps.good[1]));
01048 data = cpl_image_get_data_float(im);
01049 vircam_medmad(data,bpm,npts,&med,&mad);
01050 mad *= 1.48/CPL_MATH_SQRT2;
01051 vircam_dark_combine_config.ron12 = mad;
01052 cpl_image_delete(im);
01053
01054
01055
01056 cpl_free(bpm);
01057
01058
01059
01060 vircam_dark_combine_config.nhot = nhot;
01061 vircam_dark_combine_config.hotfrac = (float)nhot/(float)npts;
01062 }
01063
01064
01065
01071
01072
01073 static void vircam_dark_combine_normal(int jext, float exptime) {
01074 int nx,ny,ndiff,ncells;
01075 long npi,i;
01076 unsigned char *bpm;
01077 float med,sig,*idata,grms,gdiff;
01078 const char *fctid="vircam_dark_combine_normal";
01079 cpl_table *ctable;
01080 cpl_propertylist *p;
01081
01082
01083
01084 nx = (int)cpl_image_get_size_x(ps.outimage);
01085 ny = (int)cpl_image_get_size_y(ps.outimage);
01086 npi = nx*ny;
01087 vircam_dark_combine_config.particle_rate = 0;
01088 bpm = vircam_mask_get_data(ps.master_mask);
01089
01090
01091
01092
01093 ndiff = 0;
01094 for (i = 0; i < npi; i++)
01095 if ((ps.rejplus)[i] > 0 && bpm[i] == 0)
01096 ndiff += (ps.rejplus)[i];
01097 vircam_dark_combine_config.particle_rate =
01098 (float)ndiff/(exptime*(float)(ps.ndarks));
01099
01100
01101
01102 idata = cpl_image_get_data(ps.outimage);
01103 vircam_medmad(idata,bpm,npi,&med,&sig);
01104 sig *= 1.48;
01105 vircam_dark_combine_config.darkmed = med;
01106 vircam_dark_combine_config.darkrms = sig;
01107
01108
01109
01110 if (ps.master_dark != NULL) {
01111 ps.mdimage = vircam_fits_load(ps.master_dark,CPL_TYPE_FLOAT,jext);
01112 if (ps.mdimage == NULL)
01113 cpl_msg_info(fctid,
01114 "Master dark extension %" CPL_SIZE_FORMAT " won't load",
01115 (cpl_size)jext);
01116 else if (vircam_is_dummy(vircam_fits_get_ehu(ps.mdimage))) {
01117 cpl_msg_info(fctid,
01118 "Master dark extension %" CPL_SIZE_FORMAT " is a dummy!",
01119 (cpl_size)jext);
01120 freefits(ps.mdimage);
01121 }
01122 } else
01123 ps.mdimage = NULL;
01124
01125
01126
01127 if (ps.chantab != NULL) {
01128 ctable = cpl_table_load(cpl_frame_get_filename(ps.chantab),jext,0);
01129 if (ctable == NULL) {
01130 cpl_error_reset();
01131 cpl_msg_info(fctid,
01132 "Channel table extension %" CPL_SIZE_FORMAT " won't load",
01133 (cpl_size)jext);
01134 } else if (vircam_chantab_verify(ctable) != VIR_OK) {
01135 cpl_msg_info(fctid,
01136 "Channel table extension %" CPL_SIZE_FORMAT " has errors",
01137 (cpl_size)jext);
01138 freetable(ctable);
01139 } else {
01140 p = cpl_propertylist_load(cpl_frame_get_filename(ps.chantab),
01141 (cpl_size)jext);
01142 if (vircam_is_dummy(p)) {
01143 cpl_msg_info(fctid,
01144 "Channel table extensions %" CPL_SIZE_FORMAT " is a dummy",
01145 (cpl_size)jext);
01146 freetable(ctable);
01147 }
01148 freepropertylist(p);
01149 }
01150 } else
01151 ctable = NULL;
01152
01153
01154
01155
01156
01157
01158
01159 vircam_dark_combine_config.darkdiff_med = 0.0;
01160 vircam_dark_combine_config.darkdiff_rms = 0.0;
01161 ncells = vircam_dark_combine_config.ncells;
01162 vircam_difference_image(vircam_fits_get_image(ps.mdimage),
01163 ps.outimage,bpm,ctable,ncells,1,
01164 &gdiff,&grms,&(ps.diffimg),
01165 &(ps.diffimstats));
01166 vircam_mask_clear(ps.master_mask);
01167 vircam_dark_combine_config.darkdiff_med = gdiff;
01168 vircam_dark_combine_config.darkdiff_rms = grms;
01169 freetable(ctable);
01170 if (ps.diffimg != NULL)
01171 we_get |= DIFFIMG;
01172 if (ps.diffimstats != NULL)
01173 we_get |= STATS_TAB;
01174 return;
01175 }
01176
01177
01185
01186
01187 static int vircam_dark_combine_lastbit(int jext, cpl_frameset *framelist,
01188 cpl_parameterlist *parlist) {
01189 int retval;
01190 const char *fctid="vircam_dark_combine_lastbit";
01191
01192
01193
01194 vircam_dark_combine_dummy_products();
01195
01196
01197
01198 cpl_msg_info(fctid,"Saving products for extension %" CPL_SIZE_FORMAT,
01199 (cpl_size)jext);
01200 retval = vircam_dark_combine_save(framelist,parlist);
01201 if (retval != 0) {
01202 vircam_dark_combine_tidy(2);
01203 return(-1);
01204 }
01205
01206
01207
01208 vircam_dark_combine_tidy(1);
01209 return(0);
01210 }
01211
01212
01216
01217
01218 static void vircam_dark_combine_init(void) {
01219 ps.labels = NULL;
01220 ps.darklist = NULL;
01221 ps.darks = NULL;
01222 ps.ndarks = 0;
01223 ps.good = NULL;
01224 ps.ngood = 0;
01225 ps.master_dark = NULL;
01226 ps.master_mask = NULL;
01227 ps.chantab = NULL;
01228 ps.outimage = NULL;
01229 ps.drs = NULL;
01230 ps.rejmask = NULL;
01231 ps.rejplus = NULL;
01232 ps.mdimage = NULL;
01233 ps.diffimg = NULL;
01234 ps.diffimstats = NULL;
01235 ps.phupaf = NULL;
01236 we_expect = 0;
01237 we_get = 0;
01238 }
01239
01240
01244
01245
01246 static void vircam_dark_combine_tidy(int level) {
01247
01248 freeimage(ps.outimage);
01249 freefitslist(ps.darks,ps.ndarks);
01250 freepropertylist(ps.drs);
01251 freefits(ps.mdimage);
01252 freeimage(ps.diffimg);
01253 freetable(ps.diffimstats);
01254 freespace(ps.rejmask);
01255 freespace(ps.rejplus);
01256 if (level == 1)
01257 return;
01258 freespace(ps.labels);
01259 freeframeset(ps.darklist);
01260 freespace(ps.good);
01261 freeframe(ps.master_dark);
01262 freemask(ps.master_mask);
01263 freeframe(ps.chantab);
01264 freepropertylist(ps.phupaf);
01265 }
01266
01269
01270
01271
01272
01273
01274
01275
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331
01332
01333
01334
01335
01336
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361
01362
01363
01364
01365
01366
01367
01368
01369
01370
01371
01372
01373
01374
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387
01388
01389
01390
01391
01392
01393
01394
01395
01396
01397
01398
01399
01400
01401
01402
01403
01404
01405
01406
01407
01408
01409
01410
01411
01412
01413
01414
01415
01416
01417
01418
01419
01420
01421
01422
01423
01424
01425
01426
01427
01428
01429
01430
01431
01432
01433
01434
01435
01436
01437
01438
01439
01440
01441
01442
01443
01444
01445
01446
01447
01448
01449
01450
01451
01452
01453
01454
01455
01456
01457
01458
01459
01460
01461
01462
01463
01464
01465
01466
01467
01468
01469
01470
01471
01472
01473
01474
01475
01476
01477
01478
01479
01480
01481
01482
01483
01484
01485
01486
01487
01488
01489
01490
01491
01492
01493
01494