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 #ifdef HAVE_CONFIG_H
00166 # include <config.h>
00167 #endif
00168
00169
00176
00177
00178
00179
00180
00181 #include <uves_mbias_impl.h>
00182
00183 #include <uves_corrbadpix.h>
00184 #include <uves_parameters.h>
00185 #include <uves.h>
00186 #include <uves_dfs.h>
00187 #include <uves_pfits.h>
00188 #include <uves_qclog.h>
00189 #include <uves_recipe.h>
00190 #include <uves_utils_wrappers.h>
00191 #include <uves_error.h>
00192 #include <uves_msg.h>
00193
00194
00195 #include <cpl.h>
00196 #include <float.h>
00197
00198
00199
00200
00201
00202 static void uves_mbias_qclog(const cpl_imagelist* raw_imgs,
00203 uves_propertylist **raw_headers,
00204 enum uves_chip chip,
00205 const cpl_image* mbia,
00206
00207
00208 cpl_table* qclog
00209 );
00210
00211 static void
00212 uves_mbias_qc_ron_raw(const cpl_image* rbia,
00213 enum uves_chip chip,
00214 const int x_cent_s,
00215 const int x_cent_e,
00216 const int y_cent_s,
00217 const int y_cent_e,
00218 cpl_table* qclog);
00219
00220
00221
00222
00223 #define cpl_plugin_get_info uves_mbias_get_info
00224 UVES_RECIPE_DEFINE(
00225 UVES_MBIAS_ID, UVES_MBIAS_DOM,
00226
00227
00228 uves_define_global_parameters,
00229 "Jonas M. Larsen", "cpl@eso.org",
00230 "Creates the master bias frame",
00231 "This recipe creates a master bias frame by computing the median of all input\n"
00232 "bias frames. All input frames must have same tag and size and must be either\n"
00233 "BIAS_BLUE or BIAS_RED.\n"
00234 "On blue input the recipe computes one master bias frame; on red input a \n"
00235 "master bias frame for each chip is produced. The average, standard deviation\n"
00236 "and median of the master bias image(s) are written to the FITS header(s)");
00237
00238
00239
00240
00241
00244
00261
00262 static cpl_image *
00263 uves_mbias_process_chip(const cpl_imagelist *raw_images,
00264 uves_propertylist **raw_headers,
00265 uves_propertylist *mbias_header,
00266 int binx, int biny, enum uves_chip chip)
00267 {
00268 cpl_image *master_bias = NULL;
00269 double exposure_time = 0;
00270 int badpixels_cleaned;
00271 int i;
00272 int nraw=0;
00273 uves_msg("Calculating master bias...");
00274
00275
00276 check( master_bias = cpl_imagelist_collapse_median_create(raw_images),
00277 "Error computing median");
00278
00279
00280 exposure_time = 0;
00281 nraw=cpl_imagelist_get_size(raw_images);
00282 for (i = 0; i < nraw; i++)
00283 {
00284 check( exposure_time += uves_pfits_get_exptime(raw_headers[i]),
00285 "Error reading exposure time");
00286 }
00287 exposure_time /= nraw;
00288
00289 check( uves_pfits_set_exptime(mbias_header, exposure_time),
00290 "Error setting master bias exposure time");
00291
00292 check( badpixels_cleaned =
00293 uves_correct_badpix_all(master_bias, mbias_header, chip, binx, biny, false),
00294 "Error replacing bad pixels");
00295
00296 uves_msg("%d bad pixels replaced", badpixels_cleaned);
00297
00298 cleanup:
00299 if (cpl_error_get_code() != CPL_ERROR_NONE)
00300 {
00301 uves_free_image(&master_bias);
00302 }
00303
00304 return master_bias;
00305 }
00306
00307
00314
00315 static void
00316 IRPLIB_CONCAT2X(UVES_MBIAS_ID,exe)(cpl_frameset *frames,
00317 const cpl_parameterlist *parameters,
00318 const char *starttime)
00319 {
00320 uves_mbias_exe_body(frames, parameters, starttime, make_str(UVES_MBIAS_ID));
00321 return;
00322 }
00323
00324
00335
00336 void
00337 uves_mbias_exe_body(cpl_frameset *frames,
00338 const cpl_parameterlist *parameters,
00339 const char *starttime,
00340 const char *recipe_id)
00341 {
00342
00343 cpl_imagelist *raw_images[2] = {NULL, NULL};
00344 uves_propertylist **raw_headers[2] = {NULL, NULL};
00345
00346 cpl_table* qclog[2] = {NULL, NULL};
00347
00348
00349 uves_propertylist *product_header[2] = {NULL, NULL};
00350 cpl_image *master_bias = NULL;
00351 cpl_stats *mbias_stats = NULL;
00352
00353
00354 char *product_filename = NULL;
00355 bool blue;
00356 enum uves_chip chip;
00357 int binx, biny;
00358 const char* PROCESS_CHIP=NULL;
00359
00360
00361
00362 check( uves_load_raw_imagelist(frames,
00363 false,
00364 UVES_BIAS(true), UVES_BIAS(false),
00365 CPL_TYPE_DOUBLE,
00366 raw_images, raw_headers, product_header,
00367 &blue), "Error loading raw frames");
00368
00369
00370 check( binx = uves_pfits_get_binx(raw_headers[0][0]),
00371 "Could not get raw frame x-binning");
00372 check( biny = uves_pfits_get_biny(raw_headers[0][0]),
00373 "Could not get raw frame y-binning");
00374 check( uves_get_parameter(parameters, NULL, "uves", "process_chip", CPL_TYPE_STRING, &PROCESS_CHIP),
00375 "Could not read parameter");
00376
00377
00378 for (chip = uves_chip_get_first(blue);
00379 chip != UVES_CHIP_INVALID;
00380 chip = uves_chip_get_next(chip))
00381 {
00382 if(strcmp(PROCESS_CHIP,"redu") == 0) {
00383 chip = uves_chip_get_next(chip);
00384 }
00385 int raw_index = uves_chip_get_index(chip);
00386
00387 uves_msg("Processing %s chip",
00388 uves_chip_tostring_upper(chip));
00389
00390 uves_msg_debug("Binning = %dx%d", binx, biny);
00391
00392
00393 uves_free_image(&master_bias);
00394 check( master_bias = uves_mbias_process_chip(raw_images[raw_index],
00395 raw_headers[raw_index],
00396 product_header[raw_index],
00397 binx, biny,
00398 chip),
00399 "Error processing chip");
00400
00401
00402 cpl_free(product_filename);
00403 check( product_filename = uves_masterbias_filename(chip),
00404 "Error getting filename");
00405
00406
00407 uves_msg("Calculating QC parameters");
00408 uves_qclog_delete(&qclog[0]);
00409 qclog[0] = uves_qclog_init(raw_headers[raw_index][0], chip);
00410 check(uves_mbias_qclog(raw_images[raw_index],
00411 raw_headers[raw_index],
00412 chip,
00413 master_bias,
00414
00415 qclog[0]),"error computing qclog");
00416
00417
00418 uves_msg("Saving product...");
00419
00420 check( uves_frameset_insert(frames,
00421 master_bias,
00422 CPL_FRAME_GROUP_PRODUCT,
00423 CPL_FRAME_TYPE_IMAGE,
00424 CPL_FRAME_LEVEL_INTERMEDIATE,
00425 product_filename,
00426 UVES_MASTER_BIAS(chip),
00427 raw_headers[raw_index][0],
00428 product_header[raw_index],
00429 NULL,
00430 parameters,
00431 recipe_id,
00432 PACKAGE "/" PACKAGE_VERSION,qclog,
00433 starttime, true,
00434 UVES_ALL_STATS),
00435 "Could not add master bias %s to frameset", product_filename);
00436 uves_qclog_delete(&qclog[0]);
00437 uves_msg("Master bias '%s' added to frameset", product_filename);
00438
00439 if(strcmp(PROCESS_CHIP,"redl") == 0) {
00440 chip = uves_chip_get_next(chip);
00441 }
00442
00443
00444 }
00445
00446 cleanup:
00447
00448 if (raw_images[0] != NULL)
00449 {
00450 int i;
00451 for (i = 0; i < cpl_imagelist_get_size(raw_images[0]); i++)
00452 {
00453 if (raw_headers[0] != NULL) uves_free_propertylist(&raw_headers[0][i]);
00454 if (raw_headers[1] != NULL) uves_free_propertylist(&raw_headers[1][i]);
00455 }
00456 cpl_free(raw_headers[0]); raw_headers[0] = NULL;
00457 cpl_free(raw_headers[1]); raw_headers[1] = NULL;
00458 }
00459 uves_free_imagelist(&raw_images[0]);
00460 uves_free_imagelist(&raw_images[1]);
00461
00462
00463
00464 uves_qclog_delete(&qclog[0]);
00465 uves_free_image(&master_bias);
00466 uves_free_propertylist(&product_header[0]);
00467 uves_free_propertylist(&product_header[1]);
00468 cpl_free(product_filename);
00469 uves_free_stats(&mbias_stats);
00470
00471 return;
00472 }
00473
00474
00475
00476 static int
00477 count_good(const cpl_image *image)
00478 {
00479 return
00480 cpl_image_get_size_x(image) * cpl_image_get_size_y(image) -
00481 cpl_image_count_rejected(image);
00482 }
00483
00490
00491 static void
00492 reject_lo_hi(cpl_image *image, double min, double max)
00493 {
00494 cpl_mask *mask_lo = NULL;
00495 cpl_mask *mask_hi = NULL;
00496
00497 mask_lo = cpl_mask_threshold_image_create(image, -DBL_MAX, min);
00498 mask_hi = cpl_mask_threshold_image_create(image, max, DBL_MAX);
00499 assure_mem( mask_lo );
00500 assure_mem( mask_hi );
00501
00502 cpl_mask_or(mask_lo, mask_hi);
00503
00504 cpl_image_reject_from_mask(image, mask_lo);
00505
00506 cleanup:
00507 uves_free_mask(&mask_lo);
00508 uves_free_mask(&mask_hi);
00509 return;
00510 }
00511
00522 static void uves_mbias_qclog(const cpl_imagelist* raw_imgs,
00523 uves_propertylist **raw_headers,
00524 enum uves_chip chip,
00525 const cpl_image* mbia,
00526
00527
00528 cpl_table* qclog
00529 )
00530 {
00531 int nx_pix= 0;
00532 int ny_pix= 0;
00533
00534 int sample_x= 100;
00535 int sample_y= 100;
00536 int x_cent_s= 0;
00537 int x_cent_e= 0;
00538 int y_cent_s= 0;
00539 int y_cent_e= 0;
00540
00541
00542
00543
00544
00545 double upp_threshold= 0.0;
00546 double low_threshold= 0.0;
00547 double extra=0.1;
00548 double qc_ron_master= 0.0;
00549
00550 double master_median=0.0;
00551 int pn= 0;
00552
00553
00554 double min=0.0;
00555 double max=0.0;
00556 double struct_col=0.0;
00557 double struct_row=0.0;
00558
00559 double time_s=+9999999.0;
00560 double time_e=-9999999.0;
00561 int nraw=0;
00562 double qc_duty_cycle=0.;
00563 double exposure_time=0;
00564 int i=0;
00565 char key_name[80];
00566
00567 const cpl_image* rbia=NULL;
00568 cpl_image* tima=NULL;
00569 cpl_image* avg_col=NULL;
00570 cpl_image* avg_row=NULL;
00571
00572 uves_qclog_add_string(qclog,
00573 "QC TEST1 ID",
00574 "Test-on-Master-Bias",
00575 "Name of QC test",
00576 "%s");
00577
00578 uves_msg("Computing duty cycle...");
00579
00580
00581 exposure_time = 0;
00582 nraw = cpl_imagelist_get_size(raw_imgs);
00583 check_nomsg(uves_qclog_add_int(qclog,
00584 "PRO DATANCOM",
00585 nraw,
00586 "Number of frames combined",
00587 "%d"));
00588
00589
00590 for (i = 0; i < nraw; i++)
00591 {
00592 check( exposure_time = uves_pfits_get_mjdobs(raw_headers[i]),
00593 "Error reading exposure time");
00594 if(exposure_time >= time_e) time_e = exposure_time;
00595 if(exposure_time <= time_s) time_s = exposure_time;
00596 }
00597 if(nraw > 1) {
00598 qc_duty_cycle = (time_e-time_s)/ (nraw-1);
00599 }
00600 else
00601 {
00602 qc_duty_cycle = 0;
00603 }
00604
00605 check_nomsg(uves_qclog_add_double(qclog,
00606 "QC DUTYCYCL",
00607 qc_duty_cycle,
00608 "Time to store a frame",
00609 "%.5e"));
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621 nx_pix = cpl_image_get_size_x(mbia);
00622 ny_pix = cpl_image_get_size_y(mbia);
00623
00624
00625 x_cent_s = (nx_pix - sample_x)/2;
00626 x_cent_e = (nx_pix + sample_x)/2;
00627 y_cent_s = (ny_pix - sample_y)/2;
00628 y_cent_e = (ny_pix + sample_y)/2;
00629
00630
00631 check_nomsg(upp_threshold =
00632 cpl_image_get_median_window(mbia,
00633 x_cent_s,
00634 y_cent_s,
00635 x_cent_e,
00636 y_cent_e)*(1 + extra));
00637 check_nomsg(low_threshold =
00638 cpl_image_get_median_window(mbia,
00639 x_cent_s,
00640 y_cent_s,
00641 x_cent_e,
00642 y_cent_e)*(1 - extra));
00643
00644
00645
00646
00647 check_nomsg(pn = PORT_ID(chip));
00648 uves_msg_debug("Port number = %d", pn);
00649
00650 rbia = cpl_imagelist_get_const(raw_imgs,0);
00651 check_nomsg(uves_mbias_qc_ron_raw(rbia, chip,
00652 x_cent_s,x_cent_e,y_cent_s,y_cent_e,qclog));
00653
00654
00655
00656
00657
00658 check_nomsg(tima=cpl_image_duplicate(mbia));
00659
00660 check_nomsg( reject_lo_hi(tima, low_threshold, upp_threshold) );
00661 if (count_good(tima) >= 2)
00662 {
00663 check_nomsg(master_median = cpl_image_get_median(tima));
00664 check_nomsg(qc_ron_master = cpl_image_get_stdev(tima));
00665 }
00666 else
00667 {
00668 master_median = -1;
00669 qc_ron_master = -1;
00670 uves_msg_warning("Only %d good pixels in image. Setting QC parameters to -1",
00671 count_good(tima));
00672 }
00673 uves_free_image(&tima);
00674
00675 check_nomsg(uves_qclog_add_double(qclog,
00676 "PRO DATAMED",
00677 master_median,
00678 "Median of pixel values",
00679 "%7.3f"));
00680
00681 sprintf(key_name, "QC OUT%d RON MASTER", pn);
00682 check_nomsg(uves_qclog_add_double(qclog,
00683 key_name,
00684 qc_ron_master,
00685 "Read noise frame in ADU",
00686 "%8.4f"));
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701 check_nomsg(tima=cpl_image_duplicate(mbia));
00702 if (chip != UVES_CHIP_BLUE) {
00703
00704
00705
00706 check_nomsg(cpl_image_threshold(tima,
00707 -DBL_MAX,300,
00708 -DBL_MAX,300));
00709 }
00710
00711
00712 check_nomsg(avg_col = cpl_image_collapse_create(tima,1));
00713 check_nomsg(cpl_image_divide_scalar(avg_col,cpl_image_get_size_x(tima)));
00714
00715
00716 min = cpl_image_get_mean(avg_col) - 2;
00717 max = cpl_image_get_mean(avg_col) + 2;
00718
00719
00720
00721
00722 check_nomsg( reject_lo_hi(avg_col, min, max) );
00723 if (count_good(avg_col) >= 2)
00724 {
00725 check_nomsg(struct_col = cpl_image_get_stdev(avg_col));
00726 }
00727 else
00728 {
00729 struct_col = -1;
00730 uves_msg_warning("Only %d good pixels in image. Setting QC parameter to -1",
00731 count_good(avg_col));
00732 }
00733
00734 sprintf(key_name,"%s%d%s","QC OUT",pn," STRUCTY");
00735 check_nomsg(uves_qclog_add_double(qclog,
00736 key_name,
00737 struct_col,
00738 "structure in Y (bias slope)",
00739 "%8.4f"));
00740
00741
00742
00743 check_nomsg(avg_row = cpl_image_collapse_create(tima,0));
00744 check_nomsg(cpl_image_divide_scalar(avg_row,cpl_image_get_size_y(tima)));
00745
00746
00747 min = cpl_image_get_mean(avg_row) - 2;
00748 max = cpl_image_get_mean(avg_row) + 2;
00749
00750
00751
00752
00753 check_nomsg( reject_lo_hi(avg_row, min, max) );
00754 if (count_good(avg_row) >= 2)
00755 {
00756 check_nomsg(struct_row = cpl_image_get_stdev(avg_row));
00757 }
00758 else
00759 {
00760 struct_row = -1;
00761 uves_msg_warning("Only %d good pixels in image. Setting QC parameter to -1",
00762 count_good(avg_row));
00763 }
00764
00765
00766 sprintf(key_name,"%s%d%s","QC OUT",pn," STRUCTX");
00767 check_nomsg(uves_qclog_add_double(qclog,
00768 key_name,
00769 struct_row,
00770 "structure in X (bias slope)",
00771 "%8.4f"));
00772
00773
00774
00775
00776 cleanup:
00777 uves_free_image(&avg_col);
00778 uves_free_image(&avg_row);
00779 uves_free_image(&tima);
00780
00781 return;
00782
00783 }
00797 static void
00798 uves_mbias_qc_ron_raw(const cpl_image* rbia,
00799 enum uves_chip chip,
00800 const int x_cent_s,
00801 const int x_cent_e,
00802 const int y_cent_s,
00803 const int y_cent_e,
00804 cpl_table* qclog)
00805 {
00806
00807 double qc_ron_raw=0.0;
00808 double upp_threshold=0.0;
00809 double low_threshold=0.0;
00810 double extra=0.1;
00811 char key_name[80];
00812 int pn=0;
00813 cpl_image* tima=NULL;
00814
00815
00816
00817
00818
00819 check_nomsg(upp_threshold =
00820 cpl_image_get_median_window(rbia,
00821 x_cent_s,
00822 y_cent_s,
00823 x_cent_e,
00824 y_cent_e)*(1 + extra));
00825
00826 check_nomsg(low_threshold =
00827 cpl_image_get_median_window(rbia,
00828 x_cent_s,
00829 y_cent_s,
00830 x_cent_e,
00831 y_cent_e)*(1 - extra));
00832
00833
00834
00835
00836
00837
00838 check_nomsg(tima=cpl_image_duplicate(rbia));
00839
00840 check_nomsg( reject_lo_hi(tima, low_threshold, upp_threshold) );
00841 if (count_good(tima) >= 2)
00842 {
00843 check_nomsg(qc_ron_raw = cpl_image_get_stdev(tima));
00844 }
00845 else
00846 {
00847 qc_ron_raw = -1;
00848 uves_msg_warning("Only %d good pixels in image. Setting QC parameter to -1",
00849 count_good(tima));
00850 }
00851
00852
00853
00854
00855
00856 check_nomsg(pn = PORT_ID(chip));
00857
00858
00859 sprintf(key_name,"%s%d%s","QC OUT",pn," RON RAW");
00860 check_nomsg(uves_qclog_add_double(qclog,
00861 key_name,
00862 qc_ron_raw,
00863 "Read noise frame in ADU",
00864 "%8.4f"));
00865
00866 cleanup:
00867 uves_free_image(&tima);
00868 return;
00869 }
00870