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
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180 #ifdef HAVE_CONFIG_H
00181 # include <config.h>
00182 #endif
00183
00184
00191
00192
00193
00194
00195
00196 #include <uves_mbias_impl.h>
00197
00198 #include <uves_corrbadpix.h>
00199 #include <uves_parameters.h>
00200 #include <uves.h>
00201 #include <uves_dfs.h>
00202 #include <uves_pfits.h>
00203 #include <uves_qclog.h>
00204 #include <uves_recipe.h>
00205 #include <uves_utils_wrappers.h>
00206 #include <uves_error.h>
00207 #include <uves_msg.h>
00208
00209
00210 #include <cpl.h>
00211 #include <float.h>
00212 #include <ctype.h>
00213
00214
00215
00216
00217
00218 static void uves_mbias_qclog(const cpl_imagelist* raw_imgs,
00219 uves_propertylist **raw_headers,
00220 enum uves_chip chip,
00221 const cpl_image* mbia,
00222
00223
00224 cpl_table* qclog
00225 );
00226
00227 static void
00228 uves_mbias_qc_ron_raw(const cpl_image* rbia,
00229 enum uves_chip chip,
00230 const int x_cent_s,
00231 const int x_cent_e,
00232 const int y_cent_s,
00233 const int y_cent_e,
00234 cpl_table* qclog);
00235
00236 static int
00237 uves_mbias_define_parameters(cpl_parameterlist *parameters);
00238
00239
00240
00241
00242 #define cpl_plugin_get_info uves_mbias_get_info
00243 UVES_RECIPE_DEFINE(
00244 UVES_MBIAS_ID, UVES_MBIAS_DOM,
00245
00246
00247 uves_mbias_define_parameters,
00248 "Jonas M. Larsen", "cpl@eso.org",
00249 "Creates the master bias frame",
00250 "This recipe creates a master bias frame by computing the median of all input\n"
00251 "bias frames. All input frames must have same tag and size and must be either\n"
00252 "BIAS_BLUE or BIAS_RED.\n"
00253 "On blue input the recipe computes one master bias frame; on red input a \n"
00254 "master bias frame for each chip is produced. The average, standard deviation\n"
00255 "and median of the master bias image(s) are written to the FITS header(s)");
00256
00257
00258
00259
00260
00263
00270
00271 int uves_mbias_define_parameters_body(cpl_parameterlist *parameters,
00272 const char *recipe_id)
00273 {
00274
00275
00276
00277
00278 if (uves_define_global_parameters(parameters) != CPL_ERROR_NONE)
00279 {
00280 return -1;
00281 }
00282
00283
00284
00285
00286
00287 if (uves_corr_traps_define_parameters(parameters,recipe_id)
00288 != CPL_ERROR_NONE)
00289 {
00290 return -1;
00291 }
00292
00293 return (cpl_error_get_code() != CPL_ERROR_NONE);
00294 }
00295
00296
00297
00298
00304
00305 static int
00306 uves_mbias_define_parameters(cpl_parameterlist *parameters)
00307 {
00308 return uves_mbias_define_parameters_body(parameters, make_str(UVES_MBIAS_ID));
00309 }
00310
00311
00312
00313
00314
00315
00332
00333 static cpl_image *
00334 uves_mbias_process_chip(const cpl_imagelist *raw_images,
00335 uves_propertylist **raw_headers,
00336 uves_propertylist *mbias_header,
00337 int binx, int biny,
00338 enum uves_chip chip,
00339 bool CLEAN_TRAPS)
00340 {
00341 cpl_image *master_bias = NULL;
00342 double exposure_time = 0;
00343 int badpixels_cleaned;
00344 int i;
00345 int nraw=0;
00346
00347 uves_msg("Calculating master bias...");
00348
00349
00350 check( master_bias = cpl_imagelist_collapse_median_create(raw_images),
00351 "Error computing median");
00352
00353
00354 exposure_time = 0;
00355 nraw=cpl_imagelist_get_size(raw_images);
00356 for (i = 0; i < nraw; i++)
00357 {
00358 check( exposure_time += uves_pfits_get_exptime(raw_headers[i]),
00359 "Error reading exposure time");
00360 }
00361 exposure_time /= nraw;
00362
00363 check( uves_pfits_set_exptime(mbias_header, exposure_time),
00364 "Error setting master bias exposure time");
00365 if(CLEAN_TRAPS) {
00366 check( badpixels_cleaned =
00367 uves_correct_badpix_all(master_bias, mbias_header,
00368 chip, binx, biny, false),
00369 "Error replacing bad pixels");
00370
00371 uves_msg("%d bad pixels replaced", badpixels_cleaned);
00372 }
00373
00374 cleanup:
00375 if (cpl_error_get_code() != CPL_ERROR_NONE)
00376 {
00377 uves_free_image(&master_bias);
00378 }
00379
00380 return master_bias;
00381 }
00382
00383
00390
00391 static void
00392 UVES_CONCAT2X(UVES_MBIAS_ID,exe)(cpl_frameset *frames,
00393 const cpl_parameterlist *parameters,
00394 const char *starttime)
00395 {
00396 uves_mbias_exe_body(frames, parameters, starttime, make_str(UVES_MBIAS_ID));
00397 return;
00398 }
00399
00400
00411
00412 void
00413 uves_mbias_exe_body(cpl_frameset *frames,
00414 const cpl_parameterlist *parameters,
00415 const char *starttime,
00416 const char *recipe_id)
00417 {
00418
00419 cpl_imagelist *raw_images[2] = {NULL, NULL};
00420 uves_propertylist **raw_headers[2] = {NULL, NULL};
00421
00422 cpl_table* qclog[2] = {NULL, NULL};
00423
00424
00425 uves_propertylist *product_header[2] = {NULL, NULL};
00426 cpl_image *master_bias = NULL;
00427 cpl_stats *mbias_stats = NULL;
00428
00429
00430 char *product_filename = NULL;
00431 bool blue;
00432 enum uves_chip chip;
00433 int binx, biny;
00434 const char* PROCESS_CHIP=NULL;
00435 bool CLEAN_TRAPS;
00436
00437
00438
00439 check( uves_load_raw_imagelist(frames,
00440 false,
00441 UVES_BIAS(true), UVES_BIAS(false),
00442 CPL_TYPE_DOUBLE,
00443 raw_images, raw_headers, product_header,
00444 &blue), "Error loading raw frames");
00445
00446
00447 check( binx = uves_pfits_get_binx(raw_headers[0][0]),
00448 "Could not get raw frame x-binning");
00449 check( biny = uves_pfits_get_biny(raw_headers[0][0]),
00450 "Could not get raw frame y-binning");
00451 check( uves_get_parameter(parameters, NULL, "uves", "process_chip", CPL_TYPE_STRING, &PROCESS_CHIP),
00452 "Could not read parameter");
00453 uves_string_toupper((char*)PROCESS_CHIP);
00454
00455 check( uves_get_parameter(parameters, NULL, recipe_id, "clean_traps", CPL_TYPE_BOOL, &CLEAN_TRAPS),
00456 "Could not read parameter");
00457
00458
00459 for (chip = uves_chip_get_first(blue);
00460 chip != UVES_CHIP_INVALID;
00461 chip = uves_chip_get_next(chip))
00462 {
00463 if(strcmp(PROCESS_CHIP,"REDU") == 0) {
00464 chip = uves_chip_get_next(chip);
00465 }
00466 int raw_index = uves_chip_get_index(chip);
00467
00468 uves_msg("Processing %s chip",
00469 uves_chip_tostring_upper(chip));
00470
00471 uves_msg_debug("Binning = %dx%d", binx, biny);
00472
00473
00474 uves_free_image(&master_bias);
00475 check( master_bias = uves_mbias_process_chip(raw_images[raw_index],
00476 raw_headers[raw_index],
00477 product_header[raw_index],
00478 binx, biny,
00479 chip,CLEAN_TRAPS),
00480 "Error processing chip");
00481
00482
00483 cpl_free(product_filename);
00484 check( product_filename = uves_masterbias_filename(chip),
00485 "Error getting filename");
00486
00487
00488 uves_msg("Calculating QC parameters");
00489 uves_qclog_delete(&qclog[0]);
00490 qclog[0] = uves_qclog_init(raw_headers[raw_index][0], chip);
00491 check(uves_mbias_qclog(raw_images[raw_index],
00492 raw_headers[raw_index],
00493 chip,
00494 master_bias,
00495
00496 qclog[0]),"error computing qclog");
00497
00498
00499 uves_msg("Saving product...");
00500
00501 check( uves_frameset_insert(frames,
00502 master_bias,
00503 CPL_FRAME_GROUP_PRODUCT,
00504 CPL_FRAME_TYPE_IMAGE,
00505 CPL_FRAME_LEVEL_INTERMEDIATE,
00506 product_filename,
00507 UVES_MASTER_BIAS(chip),
00508 raw_headers[raw_index][0],
00509 product_header[raw_index],
00510 NULL,
00511 parameters,
00512 recipe_id,
00513 PACKAGE "/" PACKAGE_VERSION,qclog,
00514 starttime, true,
00515 UVES_ALL_STATS),
00516 "Could not add master bias %s to frameset", product_filename);
00517 uves_qclog_delete(&qclog[0]);
00518 uves_msg("Master bias '%s' added to frameset", product_filename);
00519
00520 if(strcmp(PROCESS_CHIP,"REDL") == 0) {
00521 chip = uves_chip_get_next(chip);
00522 }
00523
00524
00525 }
00526
00527 cleanup:
00528
00529 if (raw_images[0] != NULL)
00530 {
00531 int i;
00532 for (i = 0; i < cpl_imagelist_get_size(raw_images[0]); i++)
00533 {
00534 if (raw_headers[0] != NULL) uves_free_propertylist(&raw_headers[0][i]);
00535 if (raw_headers[1] != NULL) uves_free_propertylist(&raw_headers[1][i]);
00536 }
00537 cpl_free(raw_headers[0]); raw_headers[0] = NULL;
00538 cpl_free(raw_headers[1]); raw_headers[1] = NULL;
00539 }
00540 uves_free_imagelist(&raw_images[0]);
00541 uves_free_imagelist(&raw_images[1]);
00542
00543
00544
00545 uves_qclog_delete(&qclog[0]);
00546 uves_free_image(&master_bias);
00547 uves_free_propertylist(&product_header[0]);
00548 uves_free_propertylist(&product_header[1]);
00549 cpl_free(product_filename);
00550 uves_free_stats(&mbias_stats);
00551
00552 return;
00553 }
00554
00555
00556
00557 static int
00558 count_good(const cpl_image *image)
00559 {
00560 return
00561 cpl_image_get_size_x(image) * cpl_image_get_size_y(image) -
00562 cpl_image_count_rejected(image);
00563 }
00564
00571
00572 static void
00573 reject_lo_hi(cpl_image *image, double min, double max)
00574 {
00575 cpl_mask *mask_lo = NULL;
00576 cpl_mask *mask_hi = NULL;
00577
00578 mask_lo = cpl_mask_threshold_image_create(image, -DBL_MAX, min);
00579 mask_hi = cpl_mask_threshold_image_create(image, max, DBL_MAX);
00580 assure_mem( mask_lo );
00581 assure_mem( mask_hi );
00582
00583 cpl_mask_or(mask_lo, mask_hi);
00584
00585 cpl_image_reject_from_mask(image, mask_lo);
00586
00587 cleanup:
00588 uves_free_mask(&mask_lo);
00589 uves_free_mask(&mask_hi);
00590 return;
00591 }
00592
00603 static void uves_mbias_qclog(const cpl_imagelist* raw_imgs,
00604 uves_propertylist **raw_headers,
00605 enum uves_chip chip,
00606 const cpl_image* mbia,
00607
00608
00609 cpl_table* qclog
00610 )
00611 {
00612 int nx_pix= 0;
00613 int ny_pix= 0;
00614
00615 int sample_x= 100;
00616 int sample_y= 100;
00617 int x_cent_s= 0;
00618 int x_cent_e= 0;
00619 int y_cent_s= 0;
00620 int y_cent_e= 0;
00621
00622
00623
00624
00625
00626 double upp_threshold= 0.0;
00627 double low_threshold= 0.0;
00628 double extra=0.1;
00629 double qc_ron_master= 0.0;
00630
00631 double master_median=0.0;
00632 int pn= 0;
00633
00634
00635 double min=0.0;
00636 double max=0.0;
00637 double struct_col=0.0;
00638 double struct_row=0.0;
00639
00640 double time_s=+9999999.0;
00641 double time_e=-9999999.0;
00642 int nraw=0;
00643 double qc_duty_cycle=0.;
00644 double exposure_time=0;
00645 int i=0;
00646 char key_name[80];
00647
00648 const cpl_image* rbia=NULL;
00649 cpl_image* tima=NULL;
00650 cpl_image* avg_col=NULL;
00651 cpl_image* avg_row=NULL;
00652
00653 uves_qclog_add_string(qclog,
00654 "QC TEST1 ID",
00655 "Test-on-Master-Bias",
00656 "Name of QC test",
00657 "%s");
00658
00659 uves_msg("Computing duty cycle...");
00660
00661
00662 exposure_time = 0;
00663 nraw = cpl_imagelist_get_size(raw_imgs);
00664 check_nomsg(uves_qclog_add_int(qclog,
00665 "PRO DATANCOM",
00666 nraw,
00667 "Number of frames combined",
00668 "%d"));
00669
00670
00671 for (i = 0; i < nraw; i++)
00672 {
00673 check( exposure_time = uves_pfits_get_mjdobs(raw_headers[i]),
00674 "Error reading exposure time");
00675 if(exposure_time >= time_e) time_e = exposure_time;
00676 if(exposure_time <= time_s) time_s = exposure_time;
00677 }
00678 if(nraw > 1) {
00679 qc_duty_cycle = (time_e-time_s)/ (nraw-1);
00680 }
00681 else
00682 {
00683 qc_duty_cycle = 0;
00684 }
00685
00686 check_nomsg(uves_qclog_add_double(qclog,
00687 "QC DUTYCYCL",
00688 qc_duty_cycle,
00689 "Time to store a frame",
00690 "%.5e"));
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702 nx_pix = cpl_image_get_size_x(mbia);
00703 ny_pix = cpl_image_get_size_y(mbia);
00704
00705
00706 x_cent_s = (nx_pix - sample_x)/2;
00707 x_cent_e = (nx_pix + sample_x)/2;
00708 y_cent_s = (ny_pix - sample_y)/2;
00709 y_cent_e = (ny_pix + sample_y)/2;
00710
00711
00712 check_nomsg(upp_threshold =
00713 cpl_image_get_median_window(mbia,
00714 x_cent_s,
00715 y_cent_s,
00716 x_cent_e,
00717 y_cent_e)*(1 + extra));
00718 check_nomsg(low_threshold =
00719 cpl_image_get_median_window(mbia,
00720 x_cent_s,
00721 y_cent_s,
00722 x_cent_e,
00723 y_cent_e)*(1 - extra));
00724
00725
00726
00727
00728 check_nomsg(pn = PORT_ID(chip));
00729 uves_msg_debug("Port number = %d", pn);
00730
00731 rbia = cpl_imagelist_get_const(raw_imgs,0);
00732 check_nomsg(uves_mbias_qc_ron_raw(rbia, chip,
00733 x_cent_s,x_cent_e,y_cent_s,y_cent_e,qclog));
00734
00735
00736
00737
00738
00739 check_nomsg(tima=cpl_image_duplicate(mbia));
00740
00741 check_nomsg( reject_lo_hi(tima, low_threshold, upp_threshold) );
00742 if (count_good(tima) >= 2)
00743 {
00744 check_nomsg(master_median = cpl_image_get_median(tima));
00745 check_nomsg(qc_ron_master = cpl_image_get_stdev(tima));
00746 }
00747 else
00748 {
00749 master_median = -1;
00750 qc_ron_master = -1;
00751 uves_msg_warning("Only %d good pixels in image. Setting QC parameters to -1",
00752 count_good(tima));
00753 }
00754 uves_free_image(&tima);
00755
00756 check_nomsg(uves_qclog_add_double(qclog,
00757 "PRO DATAMED",
00758 master_median,
00759 "Median of pixel values",
00760 "%7.3f"));
00761
00762 sprintf(key_name, "QC OUT%d RON MASTER", pn);
00763 check_nomsg(uves_qclog_add_double(qclog,
00764 key_name,
00765 qc_ron_master,
00766 "Read noise frame in ADU",
00767 "%8.4f"));
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782 check_nomsg(tima=cpl_image_duplicate(mbia));
00783 if (chip != UVES_CHIP_BLUE) {
00784
00785
00786
00787 check_nomsg(cpl_image_threshold(tima,
00788 -DBL_MAX,300,
00789 -DBL_MAX,300));
00790 }
00791
00792
00793 check_nomsg(avg_col = cpl_image_collapse_create(tima,1));
00794 check_nomsg(cpl_image_divide_scalar(avg_col,cpl_image_get_size_x(tima)));
00795
00796
00797 min = cpl_image_get_mean(avg_col) - 2;
00798 max = cpl_image_get_mean(avg_col) + 2;
00799
00800
00801
00802
00803 check_nomsg( reject_lo_hi(avg_col, min, max) );
00804 if (count_good(avg_col) >= 2)
00805 {
00806 check_nomsg(struct_col = cpl_image_get_stdev(avg_col));
00807 }
00808 else
00809 {
00810 struct_col = -1;
00811 uves_msg_warning("Only %d good pixels in image. Setting QC parameter to -1",
00812 count_good(avg_col));
00813 }
00814
00815 sprintf(key_name,"%s%d%s","QC OUT",pn," STRUCTY");
00816 check_nomsg(uves_qclog_add_double(qclog,
00817 key_name,
00818 struct_col,
00819 "structure in Y (bias slope)",
00820 "%8.4f"));
00821
00822
00823
00824 check_nomsg(avg_row = cpl_image_collapse_create(tima,0));
00825 check_nomsg(cpl_image_divide_scalar(avg_row,cpl_image_get_size_y(tima)));
00826
00827
00828 min = cpl_image_get_mean(avg_row) - 2;
00829 max = cpl_image_get_mean(avg_row) + 2;
00830
00831
00832
00833
00834 check_nomsg( reject_lo_hi(avg_row, min, max) );
00835 if (count_good(avg_row) >= 2)
00836 {
00837 check_nomsg(struct_row = cpl_image_get_stdev(avg_row));
00838 }
00839 else
00840 {
00841 struct_row = -1;
00842 uves_msg_warning("Only %d good pixels in image. Setting QC parameter to -1",
00843 count_good(avg_row));
00844 }
00845
00846
00847 sprintf(key_name,"%s%d%s","QC OUT",pn," STRUCTX");
00848 check_nomsg(uves_qclog_add_double(qclog,
00849 key_name,
00850 struct_row,
00851 "structure in X (bias slope)",
00852 "%8.4f"));
00853
00854
00855
00856
00857 cleanup:
00858 uves_free_image(&avg_col);
00859 uves_free_image(&avg_row);
00860 uves_free_image(&tima);
00861
00862 return;
00863
00864 }
00878 static void
00879 uves_mbias_qc_ron_raw(const cpl_image* rbia,
00880 enum uves_chip chip,
00881 const int x_cent_s,
00882 const int x_cent_e,
00883 const int y_cent_s,
00884 const int y_cent_e,
00885 cpl_table* qclog)
00886 {
00887
00888 double qc_ron_raw=0.0;
00889 double upp_threshold=0.0;
00890 double low_threshold=0.0;
00891 double extra=0.1;
00892 char key_name[80];
00893 int pn=0;
00894 cpl_image* tima=NULL;
00895
00896
00897
00898
00899
00900 check_nomsg(upp_threshold =
00901 cpl_image_get_median_window(rbia,
00902 x_cent_s,
00903 y_cent_s,
00904 x_cent_e,
00905 y_cent_e)*(1 + extra));
00906
00907 check_nomsg(low_threshold =
00908 cpl_image_get_median_window(rbia,
00909 x_cent_s,
00910 y_cent_s,
00911 x_cent_e,
00912 y_cent_e)*(1 - extra));
00913
00914
00915
00916
00917
00918
00919 check_nomsg(tima=cpl_image_duplicate(rbia));
00920
00921 check_nomsg( reject_lo_hi(tima, low_threshold, upp_threshold) );
00922 if (count_good(tima) >= 2)
00923 {
00924 check_nomsg(qc_ron_raw = cpl_image_get_stdev(tima));
00925 }
00926 else
00927 {
00928 qc_ron_raw = -1;
00929 uves_msg_warning("Only %d good pixels in image. Setting QC parameter to -1",
00930 count_good(tima));
00931 }
00932
00933
00934
00935
00936
00937 check_nomsg(pn = PORT_ID(chip));
00938
00939
00940 sprintf(key_name,"%s%d%s","QC OUT",pn," RON RAW");
00941 check_nomsg(uves_qclog_add_double(qclog,
00942 key_name,
00943 qc_ron_raw,
00944 "Read noise frame in ADU",
00945 "%8.4f"));
00946
00947 cleanup:
00948 uves_free_image(&tima);
00949 return;
00950 }
00951