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