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
00063
00064 #include <cpl.h>
00065 #include <math.h>
00066
00067
00068
00069
00070
00071
00072
00073 #define RECIPE_ID "xsh_wavecal"
00074 #define RECIPE_AUTHOR "L.Guglielmi"
00075 #define RECIPE_CONTACT "amodigli@eso.org"
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085 static int xsh_wavecal_create(cpl_plugin *);
00086 static int xsh_wavecal_exec(cpl_plugin *);
00087 static int xsh_wavecal_destroy(cpl_plugin *);
00088
00089
00090 static void xsh_wavecal(cpl_parameterlist *, cpl_frameset *);
00091
00092
00093
00094
00095 static char xsh_wavecal_description_short[] =
00096 "Compute arclines tilt and instrument resolution";
00097
00098 static char xsh_wavecal_description[] =
00099 "This recipe detects and follow arc lines in a fully illuminated slit\n\
00100 frame.\n\
00101 Input Frames:\n\
00102 Raw frame (Tag = ARC_SLIT_arm)\n\
00103 Arc Line List (Tag = ARC_LINE_LIST_arm)\n\
00104 Master Bias (Tag = MASTER_BIAS_arm)\n\
00105 [OPTIONAL] Master Dark (Tag = MASTER_DARK_arm)\n\
00106 Order Table (Tag = ORDER_TABLE_EDGES_arm)\n\
00107 [poly mode] Wave Solution (Tag = WAVE_TAB_2D_arm)\n\
00108 [poly mode] Theoretical Map (Tag = THEO_TAB_spec_arm, spec=SING/IFU)\n\
00109 [physical model mode] Model cfg tab (Tag = XSH_MOD_CFG_TAB_arm)\n\
00110 [OPTIONAL] Bad Pixel Map (Tag = BADPIXEL_MAP_arm)\n\
00111 [OPTIONAL-To compute spectral resolution] Dispersion Table Frame (Tag = DISP_TAB_arm)\n\
00112 Prepare PRE structures.\n\
00113 Subtract the master Dark (UVB, VIS and NIR) (xsh_subtract_dark)\n\
00114 Substract the master Bias (UVB and VIS)(xsh_substract_bias)\n\
00115 Divide by Flat.\n\
00116 Detect and follow arc lines.\n\
00117 Products:\n\
00118 Wavelength solution, PRO.CATG = WAVE_TAB_ARC_SLIT_arm [if poly mode]\n\
00119 Linetilt list, PRO.CATG = TILT_TAB_SLIT_arm\n\
00120 Residuals table, PRO.CATG = RESID_TAB_GOOD_LINES_arm\n\
00121 Wave Map, PRO.CATG = WAVE_MAP_arm [if model-wavemap-compute=TRUE]\n\
00122 In case of IFU mode cdata previous producs repat for each IFU slices\n\
00123 Arc frame, Bias subtracted in PRE format, PRO.CATG = ARC_BIAS_SUBTRACT_arm\n\
00124 If arm=UVB/VIS and PRO.CATG=ARC_NIR_ON if arm=NIR\n\
00125 Arc frame, Bias subtracted, FLAT-FIELDED, PRO.CATG = WAVECAL_FLATFIELDED_arm";
00126
00127
00128
00129
00130
00131
00140
00141
00142 int cpl_plugin_get_info(cpl_pluginlist *list) {
00143 cpl_recipe *recipe = NULL;
00144 cpl_plugin *plugin = NULL;
00145
00146 recipe = cpl_calloc(1, sizeof(*recipe));
00147 if ( recipe == NULL ){
00148 return -1;
00149 }
00150
00151 plugin = &recipe->interface ;
00152
00153 cpl_plugin_init(plugin,
00154 CPL_PLUGIN_API,
00155 XSH_BINARY_VERSION,
00156 CPL_PLUGIN_TYPE_RECIPE,
00157 RECIPE_ID,
00158 xsh_wavecal_description_short,
00159 xsh_wavecal_description,
00160 RECIPE_AUTHOR,
00161 RECIPE_CONTACT,
00162 xsh_get_license(),
00163 xsh_wavecal_create,
00164 xsh_wavecal_exec,
00165 xsh_wavecal_destroy);
00166
00167 cpl_pluginlist_append(list, plugin);
00168
00169 return (cpl_error_get_code() != CPL_ERROR_NONE);
00170 }
00171
00172
00182
00183
00184 static int xsh_wavecal_create(cpl_plugin *plugin)
00185 {
00186 cpl_recipe *recipe = NULL;
00187
00188
00189
00190
00191 xsh_init();
00192
00193
00194 assure( plugin != NULL, CPL_ERROR_NULL_INPUT, "Null plugin");
00195
00196
00197 assure( cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE,
00198 CPL_ERROR_TYPE_MISMATCH,
00199 "Plugin is not a recipe");
00200
00201 recipe = (cpl_recipe *)plugin;
00202
00203
00204 recipe->parameters = cpl_parameterlist_new();
00205 assure( recipe->parameters != NULL,
00206 CPL_ERROR_ILLEGAL_OUTPUT,
00207 "Memory allocation failed!");
00208
00209
00210 check( xsh_parameters_generic( RECIPE_ID, recipe->parameters ) ) ;
00211 check( xsh_parameters_pre_overscan( RECIPE_ID, recipe->parameters ) ) ;
00212
00213
00214 check(xsh_parameters_wavecal_range_create( RECIPE_ID,
00215 recipe->parameters));
00216
00217 check(xsh_parameters_wavecal_margin_create( RECIPE_ID,
00218 recipe->parameters));
00219
00220 check( xsh_parameters_wavecal_s_n_create( RECIPE_ID,
00221 recipe->parameters));
00222
00223 check( xsh_parameters_clipping_tilt_create( RECIPE_ID,
00224 recipe->parameters ) ) ;
00225
00226 check( xsh_parameters_clipping_specres_create( RECIPE_ID,
00227 recipe->parameters ) ) ;
00228
00229 cleanup:
00230 if ( cpl_error_get_code() != CPL_ERROR_NONE ){
00231 xsh_error_dump(CPL_MSG_ERROR);
00232 return 1;
00233 }
00234 else {
00235 return 0;
00236 }
00237 }
00238
00239
00245
00246
00247 static int xsh_wavecal_exec(cpl_plugin *plugin)
00248 {
00249 cpl_recipe *recipe = NULL;
00250
00251
00252 assure( plugin != NULL, CPL_ERROR_NULL_INPUT, "Null plugin" );
00253
00254
00255 assure( cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE,
00256 CPL_ERROR_TYPE_MISMATCH, "Plugin is not a recipe");
00257
00258 recipe = (cpl_recipe *)plugin;
00259
00260
00261 xsh_wavecal(recipe->parameters, recipe->frames);
00262
00263 cleanup:
00264 if ( cpl_error_get_code() != CPL_ERROR_NONE ) {
00265 xsh_error_dump(CPL_MSG_ERROR);
00266
00267 cpl_error_reset();
00268 return 1;
00269 }
00270 else {
00271 return 0;
00272 }
00273 }
00274
00275
00281
00282 static int xsh_wavecal_destroy(cpl_plugin *plugin)
00283 {
00284 cpl_recipe *recipe = NULL;
00285
00286
00287 assure( plugin != NULL, CPL_ERROR_NULL_INPUT, "Null plugin" );
00288
00289
00290 assure( cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE,
00291 CPL_ERROR_TYPE_MISMATCH, "Plugin is not a recipe");
00292
00293 recipe = (cpl_recipe *)plugin;
00294
00295 xsh_free_parameterlist(&recipe->parameters);
00296
00297 cleanup:
00298 if (cpl_error_get_code() != CPL_ERROR_NONE)
00299 {
00300 return 1;
00301 }
00302 else
00303 {
00304 return 0;
00305 }
00306 }
00307
00308 static void xsh_wavecal_get_parameters( cpl_parameterlist* parameters,
00309 xsh_follow_arclines_param * par )
00310 {
00311 check( par->range = xsh_parameters_wavecal_range_get( RECIPE_ID,
00312 parameters));
00313 check( par->margin = xsh_parameters_wavecal_margin_get( RECIPE_ID,
00314 parameters));
00315 check( par->s_n_min = xsh_parameters_wavecal_s_n_get( RECIPE_ID,
00316 parameters));
00317 check( par->tilt_clipping = xsh_parameters_clipping_tilt_get( RECIPE_ID,
00318 parameters));
00319 check( par->specres_clipping = xsh_parameters_clipping_specres_get( RECIPE_ID,
00320 parameters));
00321 cleanup:
00322 return ;
00323 }
00324
00325
00326
00327
00328
00329
00330
00331
00332 static cpl_error_code
00333 xsh_params_monitor(xsh_follow_arclines_param follow_param)
00334 {
00335 xsh_msg_dbg_low("follow arclines: range=%d margin=%d",
00336 follow_param.range,follow_param.margin);
00337
00338 return cpl_error_get_code();
00339
00340 }
00341
00342
00343
00344
00345 static cpl_error_code
00346 xsh_params_set_defaults(cpl_parameterlist* pars,
00347 xsh_instrument* inst)
00348 {
00349 cpl_parameter* p=NULL;
00350 if (xsh_instrument_get_mode(inst) == XSH_MODE_IFU){
00351 check(p=xsh_parameters_find(pars,RECIPE_ID,"followarclines-min-sn"));
00352 if(xsh_parameter_get_default_flag(p) == 0) {
00353
00354 cpl_parameter_set_double(p,6);
00355
00356 }
00357 }
00358
00359
00360 cleanup:
00361
00362 return cpl_error_get_code();
00363
00364 }
00365
00366
00367
00368
00369
00377
00378
00379 static cpl_error_code
00380 xsh_params_bin_scale(cpl_frameset* raws,
00381 xsh_follow_arclines_param follow_param)
00382 {
00383
00384 cpl_frame* frame=NULL;
00385 const char* name=NULL;
00386 cpl_propertylist* plist=NULL;
00387 int binx=0;
00388 int biny=0;
00389
00390 check(frame=cpl_frameset_get_first(raws));
00391 check(name=cpl_frame_get_filename(frame));
00392 check(plist=cpl_propertylist_load(name,0));
00393 check(binx=xsh_pfits_get_binx(plist));
00394 check(biny=xsh_pfits_get_biny(plist));
00395
00396 if(biny>1) {
00397
00398 follow_param.range=follow_param.range/biny;
00399
00400 }
00401
00402
00403 if(binx>1) {
00404
00405 follow_param.margin=follow_param.margin/binx;
00406
00407 }
00408
00409 cleanup:
00410 xsh_free_propertylist(&plist);
00411 return cpl_error_get_code();
00412
00413 }
00414
00415
00416
00417
00418
00419
00420
00421
00422
00430
00431 static void xsh_wavecal(cpl_parameterlist* parameters,
00432 cpl_frameset* frameset)
00433 {
00434 const char* recipe_tags[1] = {XSH_WAVECAL};
00435 int recipe_tags_size = 1;
00436
00437 const char *prefix = "ARC_";
00438
00439 cpl_frameset* raws = NULL;
00440 cpl_frameset* calib = NULL;
00441 cpl_frameset* on = NULL;
00442 cpl_frameset* off = NULL;
00443 cpl_frameset* on_off = NULL;
00444
00445 cpl_frame * raw_frame = NULL ;
00446 cpl_frame * bpmap = NULL;
00447 cpl_frame * order_tab_edges = NULL ;
00448 cpl_frame * arc_line_list = NULL ;
00449 cpl_frame * model_config_frame = NULL;
00450 cpl_frame * spectralformat_frame = NULL;
00451 cpl_frame * wave_tab_2d = NULL ;
00452 cpl_frame * master_bias = NULL ;
00453 cpl_frame * master_dark = NULL ;
00454 cpl_frame * rmbias = NULL ;
00455 cpl_frame * intFrame = NULL ;
00456 cpl_frame * resFrame = NULL ;
00457 cpl_frame *wavemap_frame = NULL;
00458 cpl_frame *disptab_frame = NULL;
00459 cpl_frame *slitmap_frame = NULL;
00460
00461
00462 cpl_frame * shiftFrame = NULL ;
00463 cpl_frame * tilt_list = NULL ;
00464
00465
00466 cpl_frameset * tilt_set = NULL ;
00467
00468
00469 xsh_instrument* instrument = NULL;
00470 xsh_follow_arclines_param follow_param;
00471 int follow_param_init=false;
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484 char file_prefix[10];
00485
00486 int pre_overscan_corr=0;
00487
00488 const char* rec_prefix ="xsh_wavecal";
00489
00490
00491
00492
00493 xsh_begin( frameset, parameters, &instrument, &raws, &calib,
00494 recipe_tags, recipe_tags_size,
00495 RECIPE_ID, XSH_BINARY_VERSION, xsh_wavecal_description_short );
00496
00497
00498
00499
00500 bpmap = xsh_find_master_bpmap(calib);
00501 check(order_tab_edges = xsh_find_order_tab_edges(calib,instrument));
00502 spectralformat_frame = xsh_find_spectral_format( calib, instrument);
00503 xsh_error_reset();
00504 if((model_config_frame = xsh_find_frame_with_tag(calib,
00505 XSH_MOD_CFG_OPT_2D,
00506 instrument)) == NULL) {
00507
00508 xsh_error_reset();
00509
00510 if ((model_config_frame = xsh_find_frame_with_tag(calib,XSH_MOD_CFG_TAB,
00511 instrument)) == NULL) {
00512 xsh_error_reset();
00513 }
00514
00515 }
00516
00517 xsh_error_reset();
00518 check(arc_line_list = xsh_find_frame_with_tag(calib,
00519 XSH_ARC_LINE_LIST,
00520 instrument));
00521
00522 check(wave_tab_2d = xsh_find_wave_tab_2d( calib, instrument ));
00523
00524 check( wavemap_frame = xsh_find_wavemap( calib, instrument));
00525 if (wavemap_frame){
00526 wavemap_frame = cpl_frame_duplicate( wavemap_frame);
00527 }
00528 check( slitmap_frame = xsh_find_slitmap( calib, instrument));
00529 if ( slitmap_frame){
00530 slitmap_frame = cpl_frame_duplicate( slitmap_frame);
00531 }
00532
00533 if( NULL==(disptab_frame = xsh_find_disp_tab( calib, instrument))) {
00534 xsh_msg_warning("No input DISP_TAB_ARM provided. Spectral Resolution will not be computed");
00535 }
00536
00537
00538
00539 if ( xsh_instrument_get_arm(instrument) != XSH_ARM_NIR){
00540
00541 XSH_ASSURE_NOT_ILLEGAL(cpl_frameset_get_size(raws) == 1);
00542
00543 if((master_bias = xsh_find_frame_with_tag(calib,XSH_MASTER_BIAS,
00544 instrument)) == NULL) {
00545
00546 xsh_msg_warning("Frame %s not provided",XSH_MASTER_BIAS);
00547 xsh_error_reset();
00548 }
00549
00550
00551
00552 if ( (master_dark = xsh_find_master_dark(calib,instrument)) == NULL ) {
00553 xsh_msg_warning("Frame %s not provided",XSH_MASTER_DARK);
00554 xsh_error_reset();
00555 }
00556 else xsh_msg( "Frame %s Found", XSH_MASTER_DARK ) ;
00557 }
00558
00559 else {
00560
00561 check(xsh_dfs_split_nir(raws,&on,&off));
00562 XSH_ASSURE_NOT_ILLEGAL(cpl_frameset_get_size(on) == 1);
00563 XSH_ASSURE_NOT_ILLEGAL(cpl_frameset_get_size(off) == 1);
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));
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));
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));
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));
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,
00723 parameters, RECIPE_ID, instrument));
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 }