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 int *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 nlab,j,jst,jfn,retval,status,live,nx,ny;
00462 long i;
00463 float exptime;
00464 vir_fits *ff;
00465 cpl_parameter *p;
00466 cpl_propertylist *plist;
00467
00468
00469
00470 if (framelist == NULL || cpl_frameset_get_size(framelist) <= 0) {
00471 cpl_msg_error(fctid,"Input framelist NULL or has no input data");
00472 return(-1);
00473 }
00474
00475
00476
00477 if (vircam_frameset_fexists(framelist) != VIR_OK) {
00478 cpl_msg_error(fctid,"Input frameset is missing files. Check SOF");
00479 return(-1);
00480 }
00481
00482
00483
00484 vircam_dark_combine_init();
00485 we_expect |= MEANDARK;
00486
00487
00488
00489 p = cpl_parameterlist_find(parlist,"vircam.vircam_dark_combine.combtype");
00490 vircam_dark_combine_config.combtype = cpl_parameter_get_int(p);
00491 p = cpl_parameterlist_find(parlist,"vircam.vircam_dark_combine.scaletype");
00492 vircam_dark_combine_config.scaletype = cpl_parameter_get_int(p);
00493 p = cpl_parameterlist_find(parlist,"vircam.vircam_dark_combine.xrej");
00494 vircam_dark_combine_config.xrej = cpl_parameter_get_bool(p);
00495 p = cpl_parameterlist_find(parlist,"vircam.vircam_dark_combine.thresh");
00496 vircam_dark_combine_config.thresh = (float)cpl_parameter_get_double(p);
00497 p = cpl_parameterlist_find(parlist,"vircam.vircam_dark_combine.ncells");
00498 vircam_dark_combine_config.ncells = cpl_parameter_get_int(p);
00499 p = cpl_parameterlist_find(parlist,"vircam.vircam_dark_combine.extenum");
00500 vircam_dark_combine_config.extenum = cpl_parameter_get_int(p);
00501
00502
00503
00504 if (vircam_dfs_set_groups(framelist) != VIR_OK) {
00505 cpl_msg_error(fctid,"Cannot identify RAW and CALIB frames");
00506 vircam_dark_combine_tidy(2);
00507 return(-1);
00508 }
00509
00510
00511
00512 if ((ps.labels = cpl_frameset_labelise(framelist,vircam_compare_tags,
00513 &nlab)) == NULL) {
00514 cpl_msg_error(fctid,"Cannot labelise the input frames");
00515 vircam_dark_combine_tidy(2);
00516 return(-1);
00517 }
00518
00519
00520
00521 if ((ps.darklist = vircam_frameset_subgroup(framelist,ps.labels,nlab,
00522 VIRCAM_DARK_RAW)) == NULL) {
00523 cpl_msg_error(fctid,"Cannot find dark frames in input frameset");
00524 vircam_dark_combine_tidy(2);
00525 return(-1);
00526 }
00527 ps.ndarks = cpl_frameset_get_size(ps.darklist);
00528
00529
00530
00531 fname = cpl_frame_get_filename(cpl_frameset_get_first(ps.darklist));
00532 plist = cpl_propertylist_load(fname,0);
00533 if (vircam_pfits_get_exptime(plist,&exptime) != VIR_OK) {
00534 cpl_msg_warning(fctid,"Unable to get exposure time for %s",fname);
00535 exptime = 1.0;
00536 }
00537 cpl_propertylist_delete(plist);
00538
00539
00540
00541 if ((ps.master_dark = vircam_frameset_subgroup_1(framelist,ps.labels,nlab,
00542 VIRCAM_REF_DARK)) == NULL)
00543 cpl_msg_info(fctid,"No master dark found -- no difference image will be formed");
00544 else
00545 we_expect |= DIFFIMG;
00546
00547
00548
00549
00550 ps.master_mask = vircam_mask_define(framelist,ps.labels,nlab);
00551
00552
00553
00554 if ((ps.chantab = vircam_frameset_subgroup_1(framelist,ps.labels,nlab,
00555 VIRCAM_CAL_CHANTAB)) == NULL) {
00556 if ((ps.chantab = vircam_frameset_subgroup_1(framelist,ps.labels,nlab,
00557 VIRCAM_CAL_CHANTAB_INIT)) == NULL)
00558 cpl_msg_info(fctid,"No channel table found -- no difference image stats will be done");
00559 } else if (we_expect & DIFFIMG)
00560 we_expect |= STATS_TAB;
00561
00562
00563
00564
00565
00566 vircam_exten_range(vircam_dark_combine_config.extenum,
00567 (const cpl_frame *)cpl_frameset_get_frame(ps.darklist,0),
00568 &jst,&jfn);
00569 if (jst == -1 || jfn == -1) {
00570 cpl_msg_error(fctid,"Unable to continue");
00571 vircam_dark_combine_tidy(2);
00572 return(-1);
00573 }
00574
00575
00576
00577 ps.good = cpl_malloc(ps.ndarks*sizeof(vir_fits *));
00578
00579
00580
00581 for (j = jst; j <= jfn; j++) {
00582 status = VIR_OK;
00583 we_get = 0;
00584 isfirst = (j == jst);
00585
00586
00587
00588
00589 ps.darks = vircam_fits_load_list(ps.darklist,CPL_TYPE_FLOAT,j);
00590 if (ps.darks == NULL) {
00591 cpl_msg_info(fctid,"Extension %d darks wouldn't load",j);
00592 retval = vircam_dark_combine_lastbit(j,framelist,parlist);
00593 if (retval != 0)
00594 return(-1);
00595 continue;
00596 }
00597
00598
00599
00600 ps.ngood = 0;
00601 for (i = 0; i < ps.ndarks; i++) {
00602 ff = ps.darks[i];
00603 vircam_pfits_get_detlive(vircam_fits_get_ehu(ff),&live);
00604 if (! live) {
00605 cpl_msg_info(fctid,"Detector flagged dead %s",
00606 vircam_fits_get_fullname(ff));
00607 vircam_fits_set_error(ff,VIR_FATAL);
00608 } else {
00609 ps.good[ps.ngood] = ff;
00610 ps.ngood += 1;
00611 }
00612 }
00613
00614
00615
00616
00617 if (ps.ngood == 0) {
00618 cpl_msg_info(fctid,"All images flagged bad for this extension");
00619 retval = vircam_dark_combine_lastbit(j,framelist,parlist);
00620 if (retval != 0)
00621 return(-1);
00622 continue;
00623 }
00624
00625
00626
00627 nx = cpl_image_get_size_x(vircam_fits_get_image(ps.good[0]));
00628 ny = cpl_image_get_size_y(vircam_fits_get_image(ps.good[0]));
00629 retval = vircam_mask_load(ps.master_mask,j,nx,ny);
00630 if (retval == VIR_FATAL) {
00631 cpl_msg_info(fctid,"Unable to load mask image %s[%d]",
00632 vircam_mask_get_filename(ps.master_mask),j);
00633 cpl_msg_info(fctid,"Forcing all pixels to be good from now on");
00634 vircam_mask_force(ps.master_mask,nx,ny);
00635 }
00636
00637
00638
00639
00640 cpl_msg_info(fctid,"Doing combination for extension %d",j);
00641 (void)vircam_imcombine(ps.good,ps.ngood,
00642 vircam_dark_combine_config.combtype,
00643 vircam_dark_combine_config.scaletype,
00644 vircam_dark_combine_config.xrej,
00645 vircam_dark_combine_config.thresh,
00646 &(ps.outimage),&(ps.rejmask),
00647 &(ps.rejplus),&(ps.drs),&status);
00648 if (status == VIR_OK) {
00649 we_get |= MEANDARK;
00650 vircam_dark_combine_hotpix();
00651 vircam_dark_combine_normal(j,exptime);
00652 }
00653
00654
00655
00656 retval = vircam_dark_combine_lastbit(j,framelist,parlist);
00657 if (retval != 0)
00658 return(-1);
00659 }
00660 vircam_dark_combine_tidy(2);
00661 return(0);
00662 }
00663
00664
00665
00672
00673
00674 static int vircam_dark_combine_save(cpl_frameset *framelist,
00675 cpl_parameterlist *parlist) {
00676 cpl_propertylist *plist,*elist,*p,*pafprop;
00677 int status;
00678 const char *fctid = "vircam_dark_combine_save";
00679 const char *outfile = "darkcomb.fits";
00680 const char *outdiff = "darkdiff.fits";
00681 const char *outdimst = "darkdifftab.fits";
00682 const char *outfilepaf = "darkcomb";
00683 const char *outdiffpaf = "darkdiff";
00684 const char *recipeid = "vircam_dark_combine";
00685
00686
00687
00688 if (isfirst) {
00689
00690
00691
00692 product_frame_mean_dark = cpl_frame_new();
00693 cpl_frame_set_filename(product_frame_mean_dark,outfile);
00694 cpl_frame_set_tag(product_frame_mean_dark,VIRCAM_PRO_DARK);
00695 cpl_frame_set_type(product_frame_mean_dark,CPL_FRAME_TYPE_IMAGE);
00696 cpl_frame_set_group(product_frame_mean_dark,CPL_FRAME_GROUP_PRODUCT);
00697 cpl_frame_set_level(product_frame_mean_dark,CPL_FRAME_LEVEL_FINAL);
00698
00699
00700
00701 plist = vircam_fits_get_phu(ps.darks[0]);
00702 ps.phupaf = vircam_paf_phu_items(plist);
00703 if (ps.master_dark != NULL) {
00704 cpl_propertylist_update_string(ps.phupaf,"REF_DARK",
00705 cpl_frame_get_filename(ps.master_dark));
00706 cpl_propertylist_set_comment(ps.phupaf,"REF_DARK",
00707 "Reference dark used");
00708 }
00709 vircam_dfs_set_product_primary_header(plist,product_frame_mean_dark,
00710 framelist,parlist,
00711 (char *)recipeid,"PRO-1.15",
00712 NULL,0);
00713
00714
00715
00716 if (cpl_image_save(NULL,outfile,CPL_BPP_8_UNSIGNED,plist,
00717 CPL_IO_DEFAULT) != CPL_ERROR_NONE) {
00718 cpl_msg_error(fctid,"Cannot save product PHU");
00719 cpl_frame_delete(product_frame_mean_dark);
00720 return(-1);
00721 }
00722 cpl_frameset_insert(framelist,product_frame_mean_dark);
00723
00724
00725
00726 if (we_expect & DIFFIMG) {
00727 product_frame_diffimg = cpl_frame_new();
00728 cpl_frame_set_filename(product_frame_diffimg,outdiff);
00729 cpl_frame_set_tag(product_frame_diffimg,VIRCAM_PRO_DIFFIMG_DARK);
00730 cpl_frame_set_type(product_frame_diffimg,CPL_FRAME_TYPE_IMAGE);
00731 cpl_frame_set_group(product_frame_diffimg,CPL_FRAME_GROUP_PRODUCT);
00732 cpl_frame_set_level(product_frame_diffimg,CPL_FRAME_LEVEL_FINAL);
00733
00734
00735
00736 plist = vircam_fits_get_phu(ps.darks[0]);
00737 vircam_dfs_set_product_primary_header(plist,product_frame_diffimg,
00738 framelist,parlist,
00739 (char *)recipeid,
00740 "PRO-1.15",NULL,0);
00741
00742
00743
00744 if (cpl_image_save(NULL,outdiff,CPL_BPP_8_UNSIGNED,plist,
00745 CPL_IO_DEFAULT) != CPL_ERROR_NONE) {
00746 cpl_msg_error(fctid,"Cannot save product PHU");
00747 cpl_frame_delete(product_frame_diffimg);
00748 return(-1);
00749 }
00750 cpl_frameset_insert(framelist,product_frame_diffimg);
00751 }
00752
00753
00754
00755
00756 if (we_expect & STATS_TAB) {
00757 product_frame_diffimg_stats = cpl_frame_new();
00758 cpl_frame_set_filename(product_frame_diffimg_stats,outdimst);
00759 cpl_frame_set_tag(product_frame_diffimg_stats,
00760 VIRCAM_PRO_DIFFIMG_DARK_STATS);
00761 cpl_frame_set_type(product_frame_diffimg_stats,
00762 CPL_FRAME_TYPE_TABLE);
00763 cpl_frame_set_group(product_frame_diffimg_stats,
00764 CPL_FRAME_GROUP_PRODUCT);
00765 cpl_frame_set_level(product_frame_diffimg_stats,
00766 CPL_FRAME_LEVEL_FINAL);
00767
00768
00769
00770 plist = vircam_fits_get_phu(ps.darks[0]);
00771 vircam_dfs_set_product_primary_header(plist,
00772 product_frame_diffimg_stats,
00773 framelist,parlist,
00774 (char *)recipeid,
00775 "PRO-1.15",NULL,0);
00776
00777
00778
00779 elist = vircam_fits_get_ehu(ps.darks[0]);
00780 p = cpl_propertylist_duplicate(elist);
00781 vircam_merge_propertylists(p,ps.drs);
00782 if (! (we_get & STATS_TAB))
00783 vircam_dummy_property(p);
00784 vircam_dfs_set_product_exten_header(p,product_frame_diffimg_stats,
00785 framelist,parlist,
00786 (char *)recipeid,
00787 "PRO-1.15",NULL);
00788 status = VIR_OK;
00789 vircam_removewcs(p,&status);
00790
00791
00792
00793 if (cpl_table_save(ps.diffimstats,plist,p,outdimst,
00794 CPL_IO_DEFAULT) != CPL_ERROR_NONE) {
00795 cpl_msg_error(fctid,"Cannot save product table extension");
00796 cpl_frame_delete(product_frame_diffimg_stats);
00797 cpl_propertylist_delete(p);
00798 return(-1);
00799 }
00800 cpl_propertylist_delete(p);
00801 cpl_frameset_insert(framelist,product_frame_diffimg_stats);
00802 }
00803 }
00804
00805
00806
00807 plist = vircam_fits_get_ehu(ps.darks[0]);
00808 cpl_propertylist_update_int(plist,"ESO PRO DATANCOM",ps.ngood);
00809
00810
00811
00812 vircam_merge_propertylists(plist,ps.drs);
00813 p = cpl_propertylist_duplicate(plist);
00814 if (! (we_get & MEANDARK))
00815 vircam_dummy_property(p);
00816 vircam_dfs_set_product_exten_header(p,product_frame_mean_dark,
00817 framelist,parlist,
00818 (char *)recipeid,"PRO-1.15",NULL);
00819
00820
00821
00822 cpl_propertylist_update_float(p,"ESO QC DARKMED",
00823 vircam_dark_combine_config.darkmed);
00824 cpl_propertylist_set_comment(p,"ESO QC DARKMED",
00825 "Median of mean dark frame");
00826 cpl_propertylist_update_float(p,"ESO QC DARKRMS",
00827 vircam_dark_combine_config.darkrms);
00828 cpl_propertylist_set_comment(p,"ESO QC DARKRMS",
00829 "RMS of mean dark frame");
00830 cpl_propertylist_update_float(p,"ESO QC PARTICLE_RATE",
00831 vircam_dark_combine_config.particle_rate);
00832 cpl_propertylist_set_comment(p,"ESO QC PARTICLE_RATE",
00833 "[N/(detector*sec)] Particle rate");
00834 cpl_propertylist_update_float(p,"ESO QC STRIPERMS",
00835 vircam_dark_combine_config.striperms);
00836 cpl_propertylist_set_comment(p,"ESO QC STRIPERMS","RMS of stripe pattern");
00837 cpl_propertylist_update_int(p,"ESO QC NHOTPIX",
00838 vircam_dark_combine_config.nhot);
00839 cpl_propertylist_set_comment(p,"ESO QC NHOTPIX","Number of hot pixels");
00840 cpl_propertylist_update_float(p,"ESO QC HOTFRAC",
00841 vircam_dark_combine_config.hotfrac);
00842 cpl_propertylist_set_comment(p,"ESO QC HOTFRAC","Hot pixel fraction");
00843 cpl_propertylist_update_float(p,"ESO QC RON12",
00844 vircam_dark_combine_config.ron12);
00845 cpl_propertylist_set_comment(p,"ESO QC RON12",
00846 "[ADU] Estimate of readnoise + stripe RMS");
00847 if (cpl_image_save(ps.outimage,outfile,CPL_BPP_IEEE_FLOAT,p,
00848 CPL_IO_EXTEND) != CPL_ERROR_NONE) {
00849 cpl_msg_error(fctid,"Cannot save product image extension");
00850 cpl_propertylist_delete(p);
00851 return(-1);
00852 }
00853
00854
00855
00856 pafprop = vircam_paf_req_items(p);
00857 vircam_merge_propertylists(pafprop,ps.phupaf);
00858 vircam_paf_append(pafprop,p,"ESO DET NDIT");
00859 vircam_paf_append(pafprop,p,"ESO PRO CATG");
00860 vircam_paf_append(pafprop,p,"ESO PRO DATANCOM");
00861 if (vircam_paf_print((char *)outfilepaf,"VIRCAM/vircam_dark_combine",
00862 "QC file",pafprop) != VIR_OK)
00863 cpl_msg_warning(fctid,"Unable to save PAF for mean dark");
00864 cpl_propertylist_delete(pafprop);
00865 cpl_propertylist_delete(p);
00866
00867
00868
00869 if (we_expect & DIFFIMG) {
00870 p = cpl_propertylist_duplicate(plist);
00871 if (! (we_get & DIFFIMG))
00872 vircam_dummy_property(p);;
00873 cpl_propertylist_update_float(p,"ESO QC DARKDIFF_MED",
00874 vircam_dark_combine_config.darkdiff_med);
00875 cpl_propertylist_set_comment(p,"ESO QC DARKDIFF_MED",
00876 "Median of dark difference image");
00877 cpl_propertylist_update_float(p,"ESO QC DARKDIFF_RMS",
00878 vircam_dark_combine_config.darkdiff_rms);
00879 cpl_propertylist_set_comment(p,"ESO QC DARKDIFF_RMS",
00880 "RMS of dark difference image");
00881 vircam_dfs_set_product_exten_header(p,product_frame_diffimg,
00882 framelist,parlist,
00883 (char *)recipeid,
00884 "PRO-1.15",NULL);
00885 if (cpl_image_save(ps.diffimg,outdiff,CPL_BPP_IEEE_FLOAT,p,
00886 CPL_IO_EXTEND) != CPL_ERROR_NONE) {
00887 cpl_msg_error(fctid,"Cannot save product image extension");
00888 cpl_propertylist_delete(p);
00889 return(-1);
00890 }
00891
00892
00893
00894 pafprop = vircam_paf_req_items(p);
00895 vircam_paf_append(pafprop,p,"ESO PRO CATG");
00896 vircam_merge_propertylists(pafprop,ps.phupaf);
00897 if (vircam_paf_print((char *)outdiffpaf,"VIRCAM/vircam_dark_combine",
00898 "QC file",pafprop) != VIR_OK)
00899 cpl_msg_warning(fctid,"Unable to save PAF for difference image");
00900 cpl_propertylist_delete(pafprop);
00901 cpl_propertylist_delete(p);
00902 }
00903
00904
00905
00906 if (! isfirst && (we_expect & STATS_TAB)) {
00907 p = cpl_propertylist_duplicate(plist);
00908 if (! (we_get & STATS_TAB))
00909 vircam_dummy_property(p);
00910 vircam_dfs_set_product_exten_header(p,product_frame_diffimg_stats,
00911 framelist,parlist,
00912 (char *)recipeid,
00913 "PRO-1.15",NULL);
00914 status = VIR_OK;
00915 vircam_removewcs(p,&status);
00916 if (cpl_table_save(ps.diffimstats,NULL,p,outdimst,CPL_IO_EXTEND)
00917 != CPL_ERROR_NONE) {
00918 cpl_msg_error(fctid,"Cannot save product table extension");
00919 cpl_propertylist_delete(p);
00920 return(-1);
00921 }
00922 cpl_propertylist_delete(p);
00923 }
00924
00925 return(0);
00926 }
00927
00928
00932
00933
00934 static void vircam_dark_combine_dummy_products(void) {
00935
00936
00937
00938 if (we_get == we_expect)
00939 return;
00940
00941
00942
00943
00944 if (! (we_get & MEANDARK)) {
00945 ps.outimage = vircam_dummy_image(ps.darks[0]);
00946
00947
00948
00949 vircam_dark_combine_config.particle_rate = 0.0;
00950 vircam_dark_combine_config.darkmed = 0.0;
00951 vircam_dark_combine_config.darkrms = 0.0;
00952 vircam_dark_combine_config.nhot = 0;
00953 vircam_dark_combine_config.hotfrac = 0.0;
00954 vircam_dark_combine_config.striperms = 0.0;
00955 vircam_dark_combine_config.ron12 = 0.0;
00956 }
00957
00958
00959
00960 if ((we_expect & DIFFIMG) && ! (we_get & DIFFIMG)) {
00961 vircam_dark_combine_config.darkdiff_med = 0.0;
00962 vircam_dark_combine_config.darkdiff_rms = 0.0;
00963 ps.diffimg = vircam_dummy_image(ps.darks[0]);
00964 }
00965
00966
00967
00968 if ((we_expect & STATS_TAB) && ! (we_get & STATS_TAB))
00969 ps.diffimstats = vircam_create_diffimg_stats(0);
00970
00971 return;
00972 }
00973
00974
00978
00979
00980 static void vircam_dark_combine_hotpix(void) {
00981 int i,nx,ny,status,nh,nhot,j;
00982 long npts;
00983 cpl_image *im;
00984 unsigned char *bpm;
00985 float med,mad,lowcut,highcut,*data;
00986 vir_fits *f;
00987
00988
00989
00990 im = vircam_fits_get_image(ps.good[0]);
00991 nx = cpl_image_get_size_x(im);
00992 ny = cpl_image_get_size_y(im);
00993 npts = (long)(nx*ny);
00994 bpm = cpl_calloc(npts,sizeof(*bpm));
00995
00996
00997
00998
00999 for (i = 0; i < ps.ngood; i++) {
01000 f = vircam_fits_duplicate(ps.good[i]);
01001 im = vircam_fits_get_image(f);
01002 cpl_image_subtract(im,ps.outimage);
01003 status = VIR_OK;
01004 vircam_destripe(f,NULL,&status);
01005 if (i == 0) {
01006 vircam_dark_combine_config.striperms =
01007 cpl_propertylist_get_float(vircam_fits_get_ehu(f),
01008 "ESO DRS STRIPERMS");
01009 }
01010
01011
01012
01013
01014
01015
01016
01017 data = cpl_image_get_data_float(im);
01018 vircam_medmad(data,NULL,npts,&med,&mad);
01019 lowcut = med - 1.48*mad*vircam_dark_combine_config.thresh;
01020 highcut = med + 1.48*mad*vircam_dark_combine_config.thresh;
01021 for (j = 0; j < npts; j++)
01022 if (data[j] > highcut || data[j] < lowcut)
01023 bpm[j] += 1;
01024
01025
01026
01027 vircam_fits_delete(f);
01028 }
01029
01030
01031
01032
01033 nh = (ps.ngood + 1)/2;
01034 nhot = 0;
01035 for (j = 0; j < npts; j++)
01036 if (bpm[j] >= nh)
01037 nhot++;
01038
01039
01040
01041 im = cpl_image_subtract_create(vircam_fits_get_image(ps.good[0]),
01042 vircam_fits_get_image(ps.good[1]));
01043 data = cpl_image_get_data_float(im);
01044 vircam_medmad(data,bpm,npts,&med,&mad);
01045 mad *= 1.48/M_SQRT2;
01046 vircam_dark_combine_config.ron12 = mad;
01047 cpl_image_delete(im);
01048
01049
01050
01051 cpl_free(bpm);
01052
01053
01054
01055 vircam_dark_combine_config.nhot = nhot;
01056 vircam_dark_combine_config.hotfrac = (float)nhot/(float)npts;
01057 }
01058
01059
01060
01066
01067
01068 static void vircam_dark_combine_normal(int jext, float exptime) {
01069 int nx,ny,ndiff,ncells;
01070 long npi,i;
01071 unsigned char *bpm;
01072 float med,sig,*idata,grms,gdiff;
01073 const char *fctid="vircam_dark_combine_normal";
01074 cpl_table *ctable;
01075 cpl_propertylist *p;
01076
01077
01078
01079 nx = cpl_image_get_size_x(ps.outimage);
01080 ny = cpl_image_get_size_y(ps.outimage);
01081 npi = nx*ny;
01082 vircam_dark_combine_config.particle_rate = 0;
01083 bpm = vircam_mask_get_data(ps.master_mask);
01084
01085
01086
01087
01088 ndiff = 0;
01089 for (i = 0; i < npi; i++)
01090 if ((ps.rejplus)[i] > 0 && bpm[i] == 0)
01091 ndiff += (ps.rejplus)[i];
01092 vircam_dark_combine_config.particle_rate =
01093 (float)ndiff/(exptime*(float)(ps.ndarks));
01094
01095
01096
01097 idata = cpl_image_get_data(ps.outimage);
01098 vircam_medmad(idata,bpm,npi,&med,&sig);
01099 sig *= 1.48;
01100 vircam_dark_combine_config.darkmed = med;
01101 vircam_dark_combine_config.darkrms = sig;
01102
01103
01104
01105 if (ps.master_dark != NULL) {
01106 ps.mdimage = vircam_fits_load(ps.master_dark,CPL_TYPE_FLOAT,jext);
01107 if (ps.mdimage == NULL)
01108 cpl_msg_info(fctid,"Master dark extension %d won't load",jext);
01109 else if (vircam_is_dummy(vircam_fits_get_ehu(ps.mdimage))) {
01110 cpl_msg_info(fctid,"Master dark extension %d is a dummy!",jext);
01111 freefits(ps.mdimage);
01112 }
01113 } else
01114 ps.mdimage = NULL;
01115
01116
01117
01118 if (ps.chantab != NULL) {
01119 ctable = cpl_table_load(cpl_frame_get_filename(ps.chantab),jext,0);
01120 if (ctable == NULL) {
01121 cpl_error_reset();
01122 cpl_msg_info(fctid,"Channel table extension %d won't load",jext);
01123 } else if (vircam_chantab_verify(ctable) != VIR_OK) {
01124 cpl_msg_info(fctid,"Channel table extension %d has errors",jext);
01125 freetable(ctable);
01126 } else {
01127 p = cpl_propertylist_load(cpl_frame_get_filename(ps.chantab),jext);
01128 if (vircam_is_dummy(p)) {
01129 cpl_msg_info(fctid,"Channel table extensions %d is a dummy",
01130 jext);
01131 freetable(ctable);
01132 }
01133 freepropertylist(p);
01134 }
01135 } else
01136 ctable = NULL;
01137
01138
01139
01140
01141
01142
01143
01144 vircam_dark_combine_config.darkdiff_med = 0.0;
01145 vircam_dark_combine_config.darkdiff_rms = 0.0;
01146 ncells = vircam_dark_combine_config.ncells;
01147 vircam_difference_image(vircam_fits_get_image(ps.mdimage),
01148 ps.outimage,bpm,ctable,ncells,1,
01149 &gdiff,&grms,&(ps.diffimg),
01150 &(ps.diffimstats));
01151 vircam_mask_clear(ps.master_mask);
01152 vircam_dark_combine_config.darkdiff_med = gdiff;
01153 vircam_dark_combine_config.darkdiff_rms = grms;
01154 freetable(ctable);
01155 if (ps.diffimg != NULL)
01156 we_get |= DIFFIMG;
01157 if (ps.diffimstats != NULL)
01158 we_get |= STATS_TAB;
01159 return;
01160 }
01161
01162
01170
01171
01172 static int vircam_dark_combine_lastbit(int jext, cpl_frameset *framelist,
01173 cpl_parameterlist *parlist) {
01174 int retval;
01175 const char *fctid="vircam_dark_combine_lastbit";
01176
01177
01178
01179 vircam_dark_combine_dummy_products();
01180
01181
01182
01183 cpl_msg_info(fctid,"Saving products for extension %d",jext);
01184 retval = vircam_dark_combine_save(framelist,parlist);
01185 if (retval != 0) {
01186 vircam_dark_combine_tidy(2);
01187 return(-1);
01188 }
01189
01190
01191
01192 vircam_dark_combine_tidy(1);
01193 return(0);
01194 }
01195
01196
01200
01201
01202 static void vircam_dark_combine_init(void) {
01203 ps.labels = NULL;
01204 ps.darklist = NULL;
01205 ps.darks = NULL;
01206 ps.ndarks = 0;
01207 ps.good = NULL;
01208 ps.ngood = 0;
01209 ps.master_dark = NULL;
01210 ps.master_mask = NULL;
01211 ps.chantab = NULL;
01212 ps.outimage = NULL;
01213 ps.drs = NULL;
01214 ps.rejmask = NULL;
01215 ps.rejplus = NULL;
01216 ps.mdimage = NULL;
01217 ps.diffimg = NULL;
01218 ps.diffimstats = NULL;
01219 ps.phupaf = NULL;
01220 we_expect = 0;
01221 we_get = 0;
01222 }
01223
01224
01228
01229
01230 static void vircam_dark_combine_tidy(int level) {
01231
01232 freeimage(ps.outimage);
01233 freefitslist(ps.darks,ps.ndarks);
01234 freepropertylist(ps.drs);
01235 freefits(ps.mdimage);
01236 freeimage(ps.diffimg);
01237 freetable(ps.diffimstats);
01238 freespace(ps.rejmask);
01239 freespace(ps.rejplus);
01240 if (level == 1)
01241 return;
01242 freespace(ps.labels);
01243 freeframeset(ps.darklist);
01244 freespace(ps.good);
01245 freeframe(ps.master_dark);
01246 freemask(ps.master_mask);
01247 freeframe(ps.chantab);
01248 freepropertylist(ps.phupaf);
01249 }
01250
01253
01254
01255
01256
01257
01258
01259
01260
01261
01262
01263
01264
01265
01266
01267
01268
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