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 #ifdef HAVE_CONFIG_H
00027 #include <config.h>
00028 #endif
00029
00030
00038
00041
00042
00043
00044
00045
00046
00047
00048
00049 #include <xsh_error.h>
00050
00051 #include <xsh_utils.h>
00052 #include <xsh_model_utils.h>
00053 #include <xsh_msg.h>
00054
00055 #include <xsh_dfs.h>
00056 #include <xsh_pfits.h>
00057
00058 #include <xsh_drl.h>
00059 #include <xsh_drl_check.h>
00060 #include <xsh_data_instrument.h>
00061 #include <xsh_model_kernel.h>
00062 #include <xsh_model_arm_constants.h>
00063
00064
00065 #include <cpl.h>
00066 #include <math.h>
00067
00068
00069
00070
00071
00072
00073
00074 #define RECIPE_ID "xsh_wavecal"
00075 #define RECIPE_AUTHOR "L.Guglielmi"
00076 #define RECIPE_CONTACT "amodigli@eso.org"
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086 static int xsh_wavecal_create(cpl_plugin *);
00087 static int xsh_wavecal_exec(cpl_plugin *);
00088 static int xsh_wavecal_destroy(cpl_plugin *);
00089
00090
00091 static void xsh_wavecal(cpl_parameterlist *, cpl_frameset *);
00092
00093
00094
00095
00096 static char xsh_wavecal_description_short[] =
00097 "Compute arclines tilt and instrument resolution";
00098
00099 static char xsh_wavecal_description[] =
00100 "This recipe detects and follow arc lines in a fully illuminated slit\n\
00101 frame.\n\
00102 Input Frames:\n\
00103 Raw frame (Tag = ARC_SLIT_arm)\n\
00104 Arc Line List (Tag = ARC_LINE_LIST_arm)\n\
00105 Master Bias (Tag = MASTER_BIAS_arm)\n\
00106 [OPTIONAL] Master Dark (Tag = MASTER_DARK_arm)\n\
00107 Order Table (Tag = ORDER_TABLE_EDGES_arm)\n\
00108 [poly mode] Wave Solution (Tag = WAVE_TAB_2D_arm)\n\
00109 [poly mode] Theoretical Map (Tag = THEO_TAB_spec_arm, spec=SING/IFU)\n\
00110 [physical model mode] Model cfg tab (Tag = XSH_MOD_CFG_TAB_arm)\n\
00111 - [OPTIONAL] A non-linear badpixel map (Tag = BP_MAP_NL_arm)\n\
00112 - [OPTIONAL] A reference badpixel map (Tag = BP_MAP_RP_arm)\n\
00113 [OPTIONAL-To compute spectral resolution] Dispersion Table Frame (Tag = DISP_TAB_arm)\n\
00114 Prepare PRE structures.\n\
00115 Subtract the master Dark (UVB, VIS and NIR) (xsh_subtract_dark)\n\
00116 Substract the master Bias (UVB and VIS)(amodigli@pc014007$ vi xsh_wavecal_fail.sofxsh_substract_bias)\n\
00117 Divide by Flat.\n\
00118 Detect and follow arc lines.\n\
00119 Products:\n\
00120 Wavelength solution, PRO.CATG = WAVE_TAB_ARC_SLIT_arm [if poly mode]\n\
00121 Linetilt list, PRO.CATG = TILT_TAB_SLIT_arm\n\
00122 Residuals table, PRO.CATG = RESID_TAB_GOOD_LINES_arm\n\
00123 Wave Map, PRO.CATG = WAVE_MAP_arm [if model-wavemap-compute=TRUE]\n\
00124 In case of IFU mode cdata previous producs repat for each IFU slices\n\
00125 Arc frame, Bias subtracted in PRE format, PRO.CATG = ARC_BIAS_SUBTRACT_arm\n\
00126 If arm=UVB/VIS and PRO.CATG=ARC_NIR_ON if arm=NIR\n\
00127 Arc frame, Bias subtracted, FLAT-FIELDED, PRO.CATG = WAVECAL_FLATFIELDED_arm";
00128
00129
00130
00131
00132
00133
00142
00143
00144 int cpl_plugin_get_info(cpl_pluginlist *list) {
00145 cpl_recipe *recipe = NULL;
00146 cpl_plugin *plugin = NULL;
00147
00148 recipe = cpl_calloc(1, sizeof(*recipe));
00149 if ( recipe == NULL ){
00150 return -1;
00151 }
00152
00153 plugin = &recipe->interface ;
00154
00155 cpl_plugin_init(plugin,
00156 CPL_PLUGIN_API,
00157 XSH_BINARY_VERSION,
00158 CPL_PLUGIN_TYPE_RECIPE,
00159 RECIPE_ID,
00160 xsh_wavecal_description_short,
00161 xsh_wavecal_description,
00162 RECIPE_AUTHOR,
00163 RECIPE_CONTACT,
00164 xsh_get_license(),
00165 xsh_wavecal_create,
00166 xsh_wavecal_exec,
00167 xsh_wavecal_destroy);
00168
00169 cpl_pluginlist_append(list, plugin);
00170
00171 return (cpl_error_get_code() != CPL_ERROR_NONE);
00172 }
00173
00174
00184
00185
00186 static int xsh_wavecal_create(cpl_plugin *plugin)
00187 {
00188 cpl_recipe *recipe = NULL;
00189
00190
00191
00192
00193 xsh_init();
00194
00195
00196 assure( plugin != NULL, CPL_ERROR_NULL_INPUT, "Null plugin");
00197
00198
00199 assure( cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE,
00200 CPL_ERROR_TYPE_MISMATCH,
00201 "Plugin is not a recipe");
00202
00203 recipe = (cpl_recipe *)plugin;
00204
00205
00206 recipe->parameters = cpl_parameterlist_new();
00207 assure( recipe->parameters != NULL,
00208 CPL_ERROR_ILLEGAL_OUTPUT,
00209 "Memory allocation failed!");
00210
00211
00212 check( xsh_parameters_generic( RECIPE_ID, recipe->parameters ) ) ;
00213 check( xsh_parameters_pre_overscan( RECIPE_ID, recipe->parameters ) ) ;
00214
00215
00216 check(xsh_parameters_wavecal_range_create( RECIPE_ID,
00217 recipe->parameters));
00218
00219 check(xsh_parameters_wavecal_margin_create( RECIPE_ID,
00220 recipe->parameters));
00221
00222 check( xsh_parameters_wavecal_s_n_create( RECIPE_ID,
00223 recipe->parameters));
00224
00225 check( xsh_parameters_clipping_tilt_create( RECIPE_ID,
00226 recipe->parameters ) ) ;
00227
00228 check( xsh_parameters_clipping_specres_create( RECIPE_ID,
00229 recipe->parameters ) ) ;
00230
00231 cleanup:
00232 if ( cpl_error_get_code() != CPL_ERROR_NONE ){
00233 xsh_error_dump(CPL_MSG_ERROR);
00234 return 1;
00235 }
00236 else {
00237 return 0;
00238 }
00239 }
00240
00241
00247
00248
00249 static int xsh_wavecal_exec(cpl_plugin *plugin)
00250 {
00251 cpl_recipe *recipe = NULL;
00252
00253
00254 assure( plugin != NULL, CPL_ERROR_NULL_INPUT, "Null plugin" );
00255
00256
00257 assure( cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE,
00258 CPL_ERROR_TYPE_MISMATCH, "Plugin is not a recipe");
00259
00260 recipe = (cpl_recipe *)plugin;
00261
00262
00263 xsh_wavecal(recipe->parameters, recipe->frames);
00264
00265 cleanup:
00266 if ( cpl_error_get_code() != CPL_ERROR_NONE ) {
00267 xsh_error_dump(CPL_MSG_ERROR);
00268
00269 cpl_error_reset();
00270 return 1;
00271 }
00272 else {
00273 return 0;
00274 }
00275 }
00276
00277
00283
00284 static int xsh_wavecal_destroy(cpl_plugin *plugin)
00285 {
00286 cpl_recipe *recipe = NULL;
00287
00288
00289 assure( plugin != NULL, CPL_ERROR_NULL_INPUT, "Null plugin" );
00290
00291
00292 assure( cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE,
00293 CPL_ERROR_TYPE_MISMATCH, "Plugin is not a recipe");
00294
00295 recipe = (cpl_recipe *)plugin;
00296
00297 xsh_free_parameterlist(&recipe->parameters);
00298
00299 cleanup:
00300 if (cpl_error_get_code() != CPL_ERROR_NONE)
00301 {
00302 return 1;
00303 }
00304 else
00305 {
00306 return 0;
00307 }
00308 }
00309
00310 static void xsh_wavecal_get_parameters( cpl_parameterlist* parameters,
00311 xsh_follow_arclines_param * par )
00312 {
00313 check( par->range = xsh_parameters_wavecal_range_get( RECIPE_ID,
00314 parameters));
00315 check( par->margin = xsh_parameters_wavecal_margin_get( RECIPE_ID,
00316 parameters));
00317 check( par->s_n_min = xsh_parameters_wavecal_s_n_get( RECIPE_ID,
00318 parameters));
00319 check( par->tilt_clipping = xsh_parameters_clipping_tilt_get( RECIPE_ID,
00320 parameters));
00321 check( par->specres_clipping = xsh_parameters_clipping_specres_get( RECIPE_ID,
00322 parameters));
00323 cleanup:
00324 return ;
00325 }
00326
00327
00328
00329
00330
00331
00332
00333
00334 static cpl_error_code
00335 xsh_params_monitor(xsh_follow_arclines_param follow_param)
00336 {
00337 xsh_msg_dbg_low("follow arclines: range=%d margin=%d",
00338 follow_param.range,follow_param.margin);
00339
00340 return cpl_error_get_code();
00341
00342 }
00343
00344
00345
00346
00347 static cpl_error_code
00348 xsh_params_set_defaults(cpl_parameterlist* pars,
00349 xsh_instrument* inst)
00350 {
00351 cpl_parameter* p=NULL;
00352 check(p=xsh_parameters_find(pars,RECIPE_ID,"followarclines-min-sn"));
00353 if(cpl_parameter_get_double(p) <= 0) {
00354 if (xsh_instrument_get_mode(inst) == XSH_MODE_IFU){
00355 cpl_parameter_set_double(p,6);
00356 } else {
00357 cpl_parameter_set_double(p,15);
00358 }
00359 }
00360
00361
00362 cleanup:
00363
00364 return cpl_error_get_code();
00365
00366 }
00367
00368
00369
00370
00371
00379
00380
00381 static cpl_error_code
00382 xsh_params_bin_scale(cpl_frameset* raws,
00383 xsh_follow_arclines_param follow_param)
00384 {
00385
00386 cpl_frame* frame=NULL;
00387 const char* name=NULL;
00388 cpl_propertylist* plist=NULL;
00389 int binx=0;
00390 int biny=0;
00391
00392 check(frame=cpl_frameset_get_first(raws));
00393 check(name=cpl_frame_get_filename(frame));
00394 check(plist=cpl_propertylist_load(name,0));
00395 check(binx=xsh_pfits_get_binx(plist));
00396 check(biny=xsh_pfits_get_biny(plist));
00397
00398 if(biny>1) {
00399
00400 follow_param.range=follow_param.range/biny;
00401
00402 }
00403
00404
00405 if(binx>1) {
00406
00407 follow_param.margin=follow_param.margin/binx;
00408
00409 }
00410
00411 cleanup:
00412 xsh_free_propertylist(&plist);
00413 return cpl_error_get_code();
00414
00415 }
00416
00417
00425
00426 static void xsh_wavecal(cpl_parameterlist* parameters,
00427 cpl_frameset* frameset)
00428 {
00429 const char* recipe_tags[1] = {XSH_WAVECAL};
00430 int recipe_tags_size = 1;
00431
00432 const char *prefix = "ARC_";
00433
00434 cpl_frameset* raws = NULL;
00435 cpl_frameset* calib = NULL;
00436 cpl_frameset* on = NULL;
00437 cpl_frameset* off = NULL;
00438 cpl_frameset* on_off = NULL;
00439
00440 cpl_frame * raw_frame = NULL ;
00441 cpl_frame * bpmap = NULL;
00442 cpl_frame * order_tab_edges = NULL ;
00443 cpl_frame * arc_line_list = NULL ;
00444 cpl_frame * model_config_frame = NULL;
00445 cpl_frame * spectralformat_frame = NULL;
00446 cpl_frame * wave_tab_2d = NULL ;
00447 cpl_frame * master_bias = NULL ;
00448 cpl_frame * master_dark = NULL ;
00449 cpl_frame * rmbias = NULL ;
00450 cpl_frame * intFrame = NULL ;
00451 cpl_frame * resFrame = NULL ;
00452 cpl_frame *wavemap_frame = NULL;
00453 cpl_frame *disptab_frame = NULL;
00454 cpl_frame *slitmap_frame = NULL;
00455
00456
00457 cpl_frame * shiftFrame = NULL ;
00458 cpl_frame * tilt_list = NULL ;
00459
00460
00461 cpl_frameset * tilt_set = NULL ;
00462
00463
00464 xsh_instrument* instrument = NULL;
00465 xsh_follow_arclines_param follow_param;
00466 int follow_param_init=false;
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479 char file_prefix[10];
00480
00481 int pre_overscan_corr=0;
00482
00483 const char* rec_prefix ="xsh_wavecal";
00484
00485
00486
00487
00488 xsh_begin( frameset, parameters, &instrument, &raws, &calib,
00489 recipe_tags, recipe_tags_size,
00490 RECIPE_ID, XSH_BINARY_VERSION, xsh_wavecal_description_short );
00491
00492
00493 xsh_recipe_params_check(parameters,instrument,RECIPE_ID);
00494
00495
00496
00497 check(bpmap = xsh_check_load_master_bpmap(calib,instrument,RECIPE_ID));
00498 check(order_tab_edges = xsh_find_order_tab_edges(calib,instrument));
00499 spectralformat_frame = xsh_find_spectral_format( calib, instrument);
00500 xsh_error_reset();
00501 if((model_config_frame = xsh_find_frame_with_tag(calib,
00502 XSH_MOD_CFG_OPT_2D,
00503 instrument)) == NULL) {
00504
00505 xsh_error_reset();
00506
00507 if ((model_config_frame = xsh_find_frame_with_tag(calib,XSH_MOD_CFG_TAB,
00508 instrument)) == NULL) {
00509 xsh_error_reset();
00510 }
00511
00512 }
00513
00514 xsh_error_reset();
00515 check(arc_line_list = xsh_find_frame_with_tag(calib,
00516 XSH_ARC_LINE_LIST,
00517 instrument));
00518
00519 check(wave_tab_2d = xsh_find_wave_tab_2d( calib, instrument ));
00520
00521 check( wavemap_frame = xsh_find_wavemap( calib, instrument));
00522 if (wavemap_frame){
00523 wavemap_frame = cpl_frame_duplicate( wavemap_frame);
00524 }
00525 check( slitmap_frame = xsh_find_slitmap( calib, instrument));
00526 if ( slitmap_frame){
00527 slitmap_frame = cpl_frame_duplicate( slitmap_frame);
00528 }
00529
00530 if( NULL==(disptab_frame = xsh_find_disp_tab( calib, instrument))) {
00531 xsh_msg_warning("No input DISP_TAB_ARM provided. Spectral Resolution will not be computed");
00532 }
00533
00534
00535
00536 if ( xsh_instrument_get_arm(instrument) != XSH_ARM_NIR){
00537
00538 XSH_ASSURE_NOT_ILLEGAL_MSG(cpl_frameset_get_size(raws) == 1,
00539 "UVB,VIS arm provide one slit,arc lamp frame");
00540
00541 if((master_bias = xsh_find_frame_with_tag(calib,XSH_MASTER_BIAS,
00542 instrument)) == NULL) {
00543
00544 xsh_msg_warning("Frame %s not provided",XSH_MASTER_BIAS);
00545 xsh_error_reset();
00546 }
00547
00548
00549
00550 if ( (master_dark = xsh_find_master_dark(calib,instrument)) == NULL ) {
00551 xsh_msg_warning("Frame %s not provided",XSH_MASTER_DARK);
00552 xsh_error_reset();
00553 }
00554 else xsh_msg( "Frame %s Found", XSH_MASTER_DARK ) ;
00555 }
00556
00557 else {
00558
00559 check(xsh_dfs_split_nir(raws,&on,&off));
00560 XSH_ASSURE_NOT_ILLEGAL_MSG(cpl_frameset_get_size(on) == 1,
00561 "NIR arm provide one slit,arc lamp on frame");
00562 XSH_ASSURE_NOT_ILLEGAL_MSG(cpl_frameset_get_size(off) == 1,
00563 "NIR arm provide one slit,arc lamp off frame");
00564 }
00565 check( xsh_instrument_update_from_spectralformat( instrument,
00566 spectralformat_frame));
00567
00568
00569
00570
00571
00572 check(xsh_params_set_defaults(parameters,instrument));
00573 check(xsh_wavecal_get_parameters( parameters, &follow_param ));
00574 follow_param_init=true;
00575 xsh_msg_dbg_low( "Parameters: Y range = %d, X Margin = %d", follow_param.range,
00576 follow_param.margin ) ;
00577 xsh_msg_dbg_low( "Clipping Tilt Parameters: sigma = %.2lf, Niter = %d, Frac = %.2lf",
00578 follow_param.tilt_clipping->sigma,
00579 follow_param.tilt_clipping->niter,
00580 follow_param.tilt_clipping->frac ) ;
00581
00582
00583 if ( xsh_instrument_get_arm(instrument) != XSH_ARM_NIR){
00584 check(xsh_params_monitor(follow_param));
00585 check(xsh_params_bin_scale(raws,follow_param));
00586 }
00587 check(xsh_params_monitor(follow_param));
00588
00589
00590
00591
00592
00593
00594
00595 if ( xsh_instrument_get_arm(instrument) != XSH_ARM_NIR){
00596 check(xsh_prepare( raws, bpmap, master_bias, XSH_WAVECAL, instrument,pre_overscan_corr));
00597 check(raw_frame = cpl_frameset_get_first(raws));
00598
00599
00600 if(master_bias != NULL) {
00601 xsh_msg( "Subtract bias" );
00602 sprintf(file_prefix,"ARC_%s_",xsh_instrument_mode_tostring(instrument));
00603 check(rmbias = xsh_subtract_bias( raw_frame, master_bias, instrument,file_prefix,pre_overscan_corr,0));
00604 } else {
00605 rmbias=cpl_frame_duplicate(raw_frame);
00606 }
00607
00608
00609
00610 check( intFrame = xsh_check_subtract_dark( rmbias, master_dark,
00611 instrument, prefix));
00612 }
00613 else{
00614
00615 check(xsh_prepare(on, bpmap, NULL, "ON", instrument,pre_overscan_corr));
00616 check(xsh_prepare(off,bpmap, NULL, "OFF", instrument,pre_overscan_corr));
00617
00618 xsh_msg( "Subtract ON-OFF" ) ;
00619 check( on_off = xsh_subtract_nir_on_off(on, off, instrument));
00620 XSH_ASSURE_NOT_ILLEGAL(cpl_frameset_get_size(on_off) == 1);
00621 check( intFrame = cpl_frame_duplicate( cpl_frameset_get_first( on_off)));
00622 }
00623
00624
00625
00626
00627 if ( model_config_frame != NULL && wavemap_frame == NULL){
00628 char wave_map_tag[80];
00629 char slit_map_tag[80];
00630 int found_temp=true;
00631
00632 xsh_free_frame( &slitmap_frame);
00633 sprintf(wave_map_tag,"%s_%s_%s",rec_prefix,XSH_WAVE_MAP_MODEL,
00634 xsh_instrument_arm_tostring( instrument ));
00635 sprintf(slit_map_tag,"%s_%s_%s",rec_prefix,XSH_SLIT_MAP_MODEL,
00636 xsh_instrument_arm_tostring( instrument ));
00637
00638
00639 check(xsh_model_temperature_update_frame(&model_config_frame,intFrame,
00640 instrument,&found_temp));
00641
00642 check( xsh_create_model_map( model_config_frame, instrument,
00643 wave_map_tag,slit_map_tag,
00644 &wavemap_frame, &slitmap_frame,1));
00645 }
00646
00647
00648
00649
00650
00651
00652
00653
00654 if ( xsh_instrument_get_mode( instrument) == XSH_MODE_SLIT) {
00655 xsh_msg( "Call xsh_follow_arclines, SLIT mode" );
00656 check( xsh_follow_arclines_slit( intFrame, arc_line_list,
00657 wave_tab_2d, order_tab_edges,
00658 spectralformat_frame, model_config_frame,
00659 wavemap_frame, slitmap_frame,
00660 disptab_frame,
00661 &follow_param, instrument,
00662 &tilt_list,
00663 &shiftFrame));
00664
00665
00666
00667
00668 xsh_msg("Saving products, SLIT mode");
00669
00670 XSH_ASSURE_NOT_NULL( tilt_list);
00671 xsh_msg_dbg_low( "Tilt List Product from '%s'",
00672 cpl_frame_get_filename(tilt_list));
00673 check( xsh_add_product_table( tilt_list, frameset, parameters, RECIPE_ID,
00674 instrument,NULL));
00675 }
00676 else {
00677 int i ;
00678
00679 xsh_msg( "Call xsh_follow_arclines, IFU mode" ) ;
00680 check( tilt_set = cpl_frameset_new() ) ;
00681 check( xsh_follow_arclines_ifu( intFrame, arc_line_list,
00682 wave_tab_2d, order_tab_edges,
00683 spectralformat_frame, model_config_frame,
00684 wavemap_frame, slitmap_frame, disptab_frame,
00685 &follow_param, instrument,
00686 tilt_set, &shiftFrame));
00687
00688
00689
00690 xsh_msg("Saving products, IFU mode");
00691
00692 for( i = 0 ; i<3 ; i++ ) {
00693
00694 cpl_frame *tilt_frame = NULL;
00695
00696 check( tilt_frame = cpl_frameset_get_frame( tilt_set, i));
00697 xsh_msg_dbg_low( "Product from '%s'",
00698 cpl_frame_get_filename( tilt_frame));
00699 check( xsh_add_product_table( tilt_frame, frameset, parameters,
00700 RECIPE_ID, instrument,NULL));
00701 }
00702 }
00703
00704
00705
00706
00707 if ( xsh_instrument_get_arm(instrument) != XSH_ARM_NIR){
00708 xsh_msg_dbg_low( "Product from '%s'",
00709 cpl_frame_get_filename( rmbias));
00710
00711 check(xsh_add_product_pre(rmbias,frameset,parameters,
00712 RECIPE_ID,instrument));
00713 } else {
00714 xsh_msg_dbg_low( "Product from '%s'",
00715 cpl_frame_get_filename( intFrame));
00716 check(xsh_add_product_pre(intFrame,frameset,parameters,
00717 RECIPE_ID,instrument));
00718 }
00719
00720 xsh_msg_dbg_low( "Product from '%s'",
00721 cpl_frame_get_filename( shiftFrame));
00722 check( xsh_add_product_table( shiftFrame, frameset,parameters, RECIPE_ID,
00723 instrument,NULL));
00724
00725 cleanup:
00726 xsh_end( RECIPE_ID, frameset, parameters);
00727 xsh_instrument_free( &instrument);
00728 xsh_free_frameset( &raws);
00729 xsh_free_frameset( &calib);
00730 xsh_free_frame( &wavemap_frame);
00731 xsh_free_frame( &slitmap_frame);
00732 xsh_free_frame( &rmbias);
00733 xsh_free_frame( &intFrame);
00734 xsh_free_frameset( &on);
00735 xsh_free_frameset( &off);
00736 xsh_free_frameset( &on_off);
00737 xsh_free_frame( &resFrame);
00738 xsh_free_frame( &shiftFrame);
00739 if(follow_param_init) {
00740 XSH_FREE( follow_param.tilt_clipping);
00741 XSH_FREE( follow_param.specres_clipping);
00742 }
00743 xsh_free_frame( &tilt_list);
00744 xsh_free_frameset( &tilt_set);
00745
00746 return;
00747 }