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 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031
00032
00033
00034
00035 #include <string.h>
00036 #include <math.h>
00037
00038
00039 #include <cpl.h>
00040
00041 #include <xsh_dfs.h>
00042 #include <xsh_data_pre.h>
00043 #include <xsh_parameters.h>
00044 #include <xsh_drl.h>
00045 #include <xsh_msg.h>
00046 #include <xsh_pfits.h>
00047 #include <xsh_pfits_qc.h>
00048 #include <xsh_error.h>
00049 #include <xsh_utils_image.h>
00050
00051
00052
00053
00054
00055
00056 #define RECIPE_ID "xsh_util_efficiency2d"
00057 #define RECIPE_AUTHOR "A.Modigliani"
00058 #define RECIPE_CONTACT "Andrea.Modigliani@eso.org"
00059 #define PRO_IMA "PRO_IMA_UVB"
00060 #define KEY_VALUE_HPRO_DID "PRO-1.15"
00061
00062 #define SPEED_LIGHT 2.99792458*1.E8
00063 #define TEL_AREA 51.2e4
00064
00065
00066
00067
00068 static int xsh_util_efficiency2d_create(cpl_plugin *) ;
00069 static int xsh_util_efficiency2d_exec(cpl_plugin *) ;
00070 static int xsh_util_efficiency2d_destroy(cpl_plugin *) ;
00071 static int xsh_util_efficiency2d(cpl_parameterlist *, cpl_frameset *) ;
00072
00073
00074
00075
00076
00077 static char
00078 xsh_util_efficiency2d_description_short[] = "Compute efficiency";
00079 static char xsh_util_efficiency2d_description[] =
00080 "This recipe compute efficiency.\n"
00081 "The input files should be tagged as: \n"
00082 "input observed spectrum: RAW_IMA_SLIT_arm,\n"
00083 "input reference spectrum: FLUX_STD_TABLE_arm,\n"
00084 "input atmospheric extintion table: EXTCOEFF_TABLE_arm)\n"
00085 "The output is a table with efficiency as function of wavelength\n"
00086 "Information on relevant parameters can be found with\n"
00087 "esorex --params xsh_util_efficiency2d\n"
00088 "esorex --help xsh_util_efficiency2d\n"
00089 "\n";
00090
00091
00092
00093
00094
00099
00100
00102
00110
00111 int cpl_plugin_get_info(cpl_pluginlist * list)
00112 {
00113 cpl_recipe * recipe = cpl_calloc(1, sizeof *recipe ) ;
00114 cpl_plugin * plugin = &recipe->interface ;
00115
00116 cpl_plugin_init(plugin,
00117 CPL_PLUGIN_API,
00118 XSH_BINARY_VERSION,
00119 CPL_PLUGIN_TYPE_RECIPE,
00120 RECIPE_ID,
00121 xsh_util_efficiency2d_description_short,
00122 xsh_util_efficiency2d_description,
00123 RECIPE_AUTHOR,
00124 RECIPE_CONTACT,
00125 xsh_get_license(),
00126 xsh_util_efficiency2d_create,
00127 xsh_util_efficiency2d_exec,
00128 xsh_util_efficiency2d_destroy) ;
00129
00130 cpl_pluginlist_append(list, plugin) ;
00131
00132 return 0;
00133 }
00134
00135
00144
00145 static int xsh_util_efficiency2d_create(cpl_plugin * plugin)
00146 {
00147 cpl_recipe * recipe ;
00148 cpl_parameter * p ;
00149
00150
00151 xsh_init();
00152
00153
00154 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
00155 recipe = (cpl_recipe *)plugin ;
00156 else return -1 ;
00157 cpl_error_reset();
00158
00159
00160
00161 recipe->parameters = cpl_parameterlist_new() ;
00162
00163
00164
00165 check( xsh_parameters_generic(RECIPE_ID,
00166 recipe->parameters ) ) ;
00167
00168
00169 p = cpl_parameter_new_value("xsh.xsh_util_efficiency2d.sky1_lly",
00170 CPL_TYPE_INT,
00171 "Sky1 lly",
00172 "xsh.xsh_util_efficiency2d",2);
00173 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "sky1_lly") ;
00174 cpl_parameterlist_append(recipe->parameters, p) ;
00175
00176
00177
00178
00179 p = cpl_parameter_new_value("xsh.xsh_util_efficiency2d.sky1_ury",
00180 CPL_TYPE_INT,
00181 "Sky1 ury",
00182 "xsh.xsh_util_efficiency2d",20);
00183 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "sky1_ury") ;
00184 cpl_parameterlist_append(recipe->parameters, p) ;
00185
00186
00187
00188
00189
00190 p = cpl_parameter_new_value("xsh.xsh_util_efficiency2d.sky2_lly",
00191 CPL_TYPE_INT,
00192 "Sky2 lly",
00193 "xsh.xsh_util_efficiency2d",75);
00194 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "sky2_lly") ;
00195 cpl_parameterlist_append(recipe->parameters, p) ;
00196
00197
00198
00199
00200 p = cpl_parameter_new_value("xsh.xsh_util_efficiency2d.sky2_ury",
00201 CPL_TYPE_INT,
00202 "Sky ury",
00203 "xsh.xsh_util_efficiency2d",100);
00204 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "sky2_ury") ;
00205 cpl_parameterlist_append(recipe->parameters, p) ;
00206
00207
00208
00209
00210
00211
00212 p = cpl_parameter_new_value("xsh.xsh_util_efficiency2d.obj_lly",
00213 CPL_TYPE_INT,
00214 "Sky2 lly",
00215 "xsh.xsh_util_efficiency2d",22);
00216 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "obj_lly") ;
00217 cpl_parameterlist_append(recipe->parameters, p) ;
00218
00219
00220
00221
00222 p = cpl_parameter_new_value("xsh.xsh_util_efficiency2d.obj_ury",
00223 CPL_TYPE_INT,
00224 "Sky ury",
00225 "xsh.xsh_util_efficiency2d",70);
00226 cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, "obj_ury") ;
00227 cpl_parameterlist_append(recipe->parameters, p) ;
00228
00229
00230
00231
00232 cleanup:
00233
00234
00235 return 0;
00236 }
00237
00238
00244
00245 static int xsh_util_efficiency2d_exec(cpl_plugin * plugin)
00246 {
00247 cpl_recipe * recipe ;
00248 int code=0;
00249 cpl_errorstate initial_errorstate = cpl_errorstate_get();
00250
00251
00252 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
00253 recipe = (cpl_recipe *)plugin ;
00254 else return -1 ;
00255 cpl_error_reset();
00256
00257 code = xsh_util_efficiency2d(recipe->parameters, recipe->frames) ;
00258
00259
00260 if (!cpl_errorstate_is_equal(initial_errorstate)) {
00261
00262
00263 cpl_errorstate_dump(initial_errorstate, CPL_FALSE, NULL);
00264 }
00265
00266 return code ;
00267 }
00268
00269
00275
00276 static int xsh_util_efficiency2d_destroy(cpl_plugin * plugin)
00277 {
00278 cpl_recipe * recipe ;
00279
00280
00281 if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
00282 recipe = (cpl_recipe *)plugin ;
00283 else return -1 ;
00284
00285 cpl_parameterlist_delete(recipe->parameters) ;
00286 return 0 ;
00287 }
00288
00289 static double
00290 xsh_table_get_interpolated(cpl_table* tbl,
00291 double wav,
00292 const char* colx,
00293 const char* coly)
00294 {
00295
00296 double y=0;
00297 double w1=0;
00298 double w2=0;
00299 double pos_y1=0;
00300 double pos_y2=0;
00301 float* pe=NULL;
00302 float* pw=NULL;
00303 int nrow=0;
00304 int i=0;
00305
00306
00307 w1=cpl_table_get_column_min(tbl,colx);
00308 w2=cpl_table_get_column_max(tbl,colx);
00309 pos_y1=cpl_table_get_column_min(tbl,coly);
00310 pos_y2=cpl_table_get_column_max(tbl,coly);
00311
00312
00313 pw=cpl_table_get_data_float(tbl,colx);
00314 pe=cpl_table_get_data_float(tbl,coly);
00315 nrow=cpl_table_get_nrow(tbl);
00316
00317
00318 for(i=0;i<nrow-1;i++) {
00319 if(pw[i]<wav) {
00320 w1=pw[i];
00321 w2=pw[i+1];
00322 pos_y1=pe[i];
00323 pos_y2=pe[i+1];
00324 }
00325 }
00326
00327 y=pos_y1+(pos_y2-pos_y1)/(w2-w1)*(wav-w1);
00328
00329
00330 return y;
00331
00332 }
00333
00334
00335
00342
00343 static int
00344 xsh_util_efficiency2d( cpl_parameterlist * parlist,
00345 cpl_frameset * frames)
00346 {
00347 const char* recipe_tags[1] = {XSH_RAW_IMA_SLIT};
00348 int recipe_tags_size = 1;
00349
00350 xsh_instrument* instrument=NULL;
00351 cpl_parameter * param= NULL ;
00352 cpl_frame* frm_sci=NULL;
00353 cpl_frame* frm_ref=NULL;
00354 cpl_frame* frm_atmext=NULL;
00355
00356 cpl_frameset* raws=NULL;
00357 cpl_frameset* calib=NULL;
00358
00359 cpl_image* ima_sci=NULL;
00360 cpl_table* tbl_ref=NULL;
00361 cpl_table* tbl_ext=NULL;
00362 cpl_table* tbl_atmext=NULL;
00363
00364 const char* name=NULL;
00365 double ref_wmin=0;
00366 double ref_wmax=0;
00367 double ext_wmin=0;
00368 double ext_wmax=0;
00369
00370 cpl_propertylist* plist=NULL;
00371 double crval1=0;
00372 double cdelt1=0;
00373 int naxis1=0;
00374 int nrow=0;
00375 double* pext=NULL;
00376 double* pcor=NULL;
00377 double* pref=NULL;
00378 double* peph=NULL;
00379 double aimprim=1.446;
00380
00381
00382 double exptime=600;
00383 cpl_vector* rec_profile=NULL;
00384 int i=0;
00385 double airmass=0;
00386 double airmass_start=0;
00387 double airmass_end=0;
00388
00389 double nm2AA=10.;
00390 int next=0;
00391 int nord=0;
00392 cpl_image* ima_ord=0;
00393 cpl_image* ima_obj=0;
00394 cpl_image* ima_sky1=0;
00395 cpl_image* ima_sky2=0;
00396 cpl_image* ima_sky=0;
00397 int sx=0;
00398 int obj_lly=37;
00399 int obj_ury=85;
00400
00401 int sky1_lly=20;
00402 int sky1_ury=35;
00403
00404
00405 int sky2_lly=90;
00406 int sky2_ury=105;
00407 cpl_table* obj_tab=NULL;
00408
00409 double * pobj=NULL;
00410 double * pw=NULL;
00411 double * pf=NULL;
00412 int * po=NULL;
00413 int k=0;
00414 int j=0;
00415 double wav=0;
00416 double gain=0;
00417 cpl_table* tbl_sel=NULL;
00418 int biny=1;
00419
00420 xsh_msg("Welcome to XSHOOTER Pipeline release %d.%d.%d",
00421 XSH_MAJOR_VERSION,XSH_MINOR_VERSION,XSH_MICRO_VERSION);
00422
00423
00424 check( xsh_begin( frames, parlist, &instrument, &raws, &calib,
00425 recipe_tags, recipe_tags_size,
00426 RECIPE_ID, XSH_BINARY_VERSION,
00427 xsh_util_efficiency2d_description_short ) ) ;
00428
00429
00430
00431 check(param=cpl_parameterlist_find(parlist,"xsh.xsh_util_efficiency2d.sky1_lly"));
00432 check(sky1_lly=cpl_parameter_get_int(param));
00433
00434 check(param=cpl_parameterlist_find(parlist,"xsh.xsh_util_efficiency2d.sky1_ury"));
00435 check(sky1_ury=cpl_parameter_get_int(param));
00436
00437
00438 check(param=cpl_parameterlist_find(parlist,"xsh.xsh_util_efficiency2d.sky2_lly"));
00439 check(sky2_lly=cpl_parameter_get_int(param));
00440
00441 check(param=cpl_parameterlist_find(parlist,"xsh.xsh_util_efficiency2d.sky2_ury"));
00442 check(sky2_ury=cpl_parameter_get_int(param));
00443
00444
00445
00446
00447 check(param=cpl_parameterlist_find(parlist,"xsh.xsh_util_efficiency2d.obj_lly"));
00448 check(obj_lly=cpl_parameter_get_int(param));
00449
00450 check(param=cpl_parameterlist_find(parlist,"xsh.xsh_util_efficiency2d.obj_ury"));
00451 check(obj_ury=cpl_parameter_get_int(param));
00452 xsh_msg("Obj extraction window: %d %d",obj_lly,obj_ury);
00453 xsh_msg("Sky1 extraction window: %d %d",sky1_lly,sky1_ury);
00454 xsh_msg("Sky2 extraction window: %d %d",sky2_lly,sky2_ury);
00455
00456
00457
00458
00459 check(frm_sci=xsh_find_frame_with_tag(raws,XSH_RAW_IMA_SLIT, instrument));
00460 check(frm_ref=xsh_find_frame_with_tag(calib,XSH_FLUX_STD_TAB,instrument));
00461 check(frm_atmext=xsh_find_frame_with_tag(calib,XSH_EXTCOEFF_TAB,instrument));
00462 check(next = cpl_frame_get_nextensions(frm_sci));
00463
00464 xsh_msg("next=%d",next);
00465 nord=(next+1)/3;
00466 name=cpl_frame_get_filename(frm_sci);
00467
00468 check(plist=cpl_propertylist_load(name,0));
00469 check(naxis1=xsh_pfits_get_naxis1(plist));
00470 check(airmass_start=xsh_pfits_get_airm_start(plist));
00471 check(airmass_end=xsh_pfits_get_airm_end(plist));
00472 if( xsh_instrument_get_arm(instrument) == XSH_ARM_NIR){
00473 gain=2.12;
00474 biny=1;
00475 check(exptime=xsh_pfits_get_dit(plist));
00476 } else {
00477 check(gain=xsh_pfits_get_conad(plist));
00478 check(biny=xsh_pfits_get_biny(plist));
00479 check(exptime=xsh_pfits_get_win1_dit1(plist));
00480 }
00481
00482 xsh_free_propertylist(&plist);
00483 airmass=0.5*(airmass_start+airmass_end);
00484
00485 xsh_msg("gain=%g airm=%g exptime=%g",gain,airmass,exptime);
00486
00487 xsh_msg("name=%s",name);
00488 nrow=naxis1*nord;
00489 obj_tab=cpl_table_new(nrow);
00490 cpl_table_new_column(obj_tab,"ORD",CPL_TYPE_INT);
00491 cpl_table_new_column(obj_tab,"WAVELENGTH",CPL_TYPE_DOUBLE);
00492 cpl_table_new_column(obj_tab,"FLUX",CPL_TYPE_DOUBLE);
00493
00494 check(po=cpl_table_get_data_int(obj_tab,"ORD"));
00495 check(pw=cpl_table_get_data_double(obj_tab,"WAVELENGTH"));
00496 check(pf=cpl_table_get_data_double(obj_tab,"FLUX"));
00497
00498 check(cpl_table_fill_column_window_int(obj_tab,"ORD",0,nrow,-1));
00499 check(cpl_table_fill_column_window_double(obj_tab,"WAVELENGTH",0,nrow,-1));
00500 check(cpl_table_fill_column_window_double(obj_tab,"FLUX",0,nrow,-1));
00501
00502
00503
00504
00505
00506
00507
00508
00509 xsh_msg("extract object");
00510 k=0;
00511 for(i=0;i<next;i+=3) {
00512 xsh_msg("processing extension %d",i);
00513 check(ima_ord=cpl_image_load(name,CPL_TYPE_DOUBLE,0,i));
00514 check(plist=cpl_propertylist_load(name,i));
00515 check(sx=cpl_image_get_size_x(ima_ord));
00516 check(ima_obj=cpl_image_collapse_window_create(ima_ord,1,obj_lly,
00517 sx,obj_ury,0));
00518 check(ima_sky1=cpl_image_collapse_window_create(ima_ord,1,sky1_lly,
00519 sx,sky1_ury,0));
00520 check(ima_sky2=cpl_image_collapse_window_create(ima_ord,1,sky2_lly,
00521 sx,sky2_ury,0));
00522 check(cpl_image_divide_scalar(ima_sky1,sky1_ury-sky1_lly+1));
00523 check(cpl_image_divide_scalar(ima_sky2,sky2_ury-sky2_lly+1));
00524
00525
00526 check(ima_sky=cpl_image_duplicate(ima_sky1));
00527 check(cpl_image_add(ima_sky,ima_sky2));
00528 check(cpl_image_divide_scalar(ima_sky,2));
00529 check(cpl_image_multiply_scalar(ima_sky,obj_ury-obj_lly+1));
00530 check(cpl_image_subtract(ima_obj,ima_sky));
00531
00532 check(pobj=cpl_image_get_data_double(ima_obj));
00533 check(crval1=xsh_pfits_get_crval1(plist));
00534 check(cdelt1=xsh_pfits_get_cdelt1(plist));
00535
00536
00537
00538 for(j=0;j<naxis1;j++) {
00539
00540 wav=crval1+cdelt1*j;
00541 pw[k+j]=wav;
00542 po[k+j]=i/3;
00543 if( ( xsh_instrument_get_arm(instrument) == XSH_ARM_NIR) &&
00544 ( (po[k+j]==3) ||(po[k+j]==8) ) ) {
00545 pf[k+j]=0;
00546 } else {
00547 pf[k+j]=pobj[j];
00548 }
00549 }
00550
00551 k+=naxis1;
00552 xsh_free_image(&ima_ord);
00553 xsh_free_image(&ima_obj);
00554 xsh_free_image(&ima_sky);
00555 xsh_free_image(&ima_sky);
00556 xsh_free_image(&ima_sky1);
00557 xsh_free_image(&ima_sky2);
00558 xsh_free_propertylist(&plist);
00559
00560
00561
00562 }
00563 xsh_msg("Extracted spectrum sampling bin=%g [nm]",cdelt1);
00564 check(name=cpl_frame_get_filename(frm_ref));
00565 check(tbl_ref=cpl_table_load(name,1,0));
00566
00567
00568
00569
00570
00571
00572
00573
00574 cpl_table_multiply_scalar(obj_tab,"WAVELENGTH",nm2AA);
00575
00576
00577 check(ref_wmin=cpl_table_get_column_min(tbl_ref,"WAVELENGTH"));
00578 check(ref_wmax=cpl_table_get_column_max(tbl_ref,"WAVELENGTH"));
00579 xsh_msg("Ref spectrum wmin=%g [A] wmax=%g [A]",ref_wmin,ref_wmax);
00580
00581 check(name=cpl_frame_get_filename(frm_atmext));
00582 check(tbl_atmext=cpl_table_load(name,1,0));
00583
00584
00585 check(ext_wmin=cpl_table_get_column_min(tbl_atmext,"LAMBDA"));
00586 check(ext_wmax=cpl_table_get_column_max(tbl_atmext,"LAMBDA"));
00587 xsh_msg("extinction wmin=%g [A] wmax=%g [A]",ext_wmin,ext_wmax);
00588
00589
00590 check(cpl_table_new_column(obj_tab,"REF",CPL_TYPE_DOUBLE));
00591 check(cpl_table_fill_column_window_double(obj_tab,"REF",0,nrow,-1));
00592
00593 check(cpl_table_new_column(obj_tab,"EXT",CPL_TYPE_DOUBLE));
00594 check(cpl_table_fill_column_window_double(obj_tab,"EXT",0,nrow,-1));
00595
00596 check(cpl_table_new_column(obj_tab,"COR",CPL_TYPE_DOUBLE));
00597 check(cpl_table_fill_column_window_double(obj_tab,"COR",0,nrow,-1));
00598
00599 check(cpl_table_new_column(obj_tab,"EPHOT",CPL_TYPE_DOUBLE));
00600 check(cpl_table_fill_column_window_double(obj_tab,"EPHOT",0,nrow,-1));
00601
00602
00603 check(pref=cpl_table_get_data_double(obj_tab,"REF"));
00604 check(pext=cpl_table_get_data_double(obj_tab,"EXT"));
00605 check(pcor=cpl_table_get_data_double(obj_tab,"COR"));
00606 check(peph=cpl_table_get_data_double(obj_tab,"EPHOT"));
00607
00608 check(pw=cpl_table_get_data_double(obj_tab,"WAVELENGTH"));
00609 check(pf=cpl_table_get_data_double(obj_tab,"FLUX"));
00610 xsh_msg("Resample atmosphere and std star");
00611 for(i=0;i<nrow;i++) {
00612
00613
00614 check(pext[i]=xsh_table_get_interpolated(tbl_atmext,pw[i],
00615 "LAMBDA","LA_SILLA"));
00616
00617 check(pref[i]=xsh_table_get_interpolated(tbl_ref,pw[i],
00618 "WAVELENGTH","FLUX"));
00619
00620 pcor[i]=pow(10,(0.4*pext[i]*aimprim));
00621 if(airmass != 0) pcor[i]/=pow(10,(0.4*pext[i]*airmass));
00622 peph[i]=1.e7*1.986e-19/(pw[i]*1e-4);
00623
00624
00625 }
00626 xsh_msg("apply corrections");
00627 check(cpl_table_duplicate_column(obj_tab,"SRC_COR",obj_tab,"FLUX"));
00628 check(cpl_table_multiply_columns(obj_tab,"SRC_COR","COR"));
00629
00630
00631 cpl_table_divide_scalar(obj_tab,"SRC_COR",nm2AA);
00632 cpl_table_divide_scalar(obj_tab,"SRC_COR",cdelt1);
00633 cpl_table_divide_scalar(obj_tab,"SRC_COR",biny);
00634
00635 check(cpl_table_duplicate_column(obj_tab,"EFF",obj_tab,"SRC_COR"));
00636
00637 check(cpl_table_multiply_scalar(obj_tab,"EFF",gain));
00638 check(cpl_table_multiply_columns(obj_tab,"EFF","EPHOT"));
00639 check(cpl_table_divide_scalar(obj_tab,"EFF",exptime));
00640 check(cpl_table_divide_scalar(obj_tab,"EFF",TEL_AREA));
00641 check(cpl_table_divide_columns(obj_tab,"EFF","REF"));
00642
00643
00644 cpl_table_and_selected_double(obj_tab,"EFF",CPL_GREATER_THAN,1.e-5);
00645 cpl_table_and_selected_double(obj_tab,"EFF",CPL_LESS_THAN,1.);
00646 tbl_sel=cpl_table_extract_selected(obj_tab);
00647
00648
00649 check( cpl_table_save(tbl_sel, NULL, NULL,"eff.fits", CPL_IO_DEFAULT));
00650
00651
00652 xsh_free_table(&obj_tab);
00653
00654 cleanup:
00655 xsh_free_table(&tbl_sel);
00656 xsh_free_image(&ima_sci);
00657 xsh_free_table(&obj_tab);
00658 xsh_free_table(&tbl_ref);
00659 xsh_free_table(&tbl_ext);
00660 xsh_free_table(&tbl_atmext);
00661 xsh_free_vector(&rec_profile);
00662
00663 xsh_free_image(&ima_ord);
00664 xsh_free_image(&ima_obj);
00665 xsh_free_image(&ima_sky);
00666 xsh_free_image(&ima_sky);
00667 xsh_free_image(&ima_sky1);
00668 xsh_free_image(&ima_sky2);
00669 xsh_free_propertylist(&plist);
00670 xsh_free_frameset(&raws);
00671 xsh_free_frameset(&calib);
00672 xsh_instrument_free( &instrument);
00673
00674 if (cpl_error_get_code()) {
00675 return -1 ;
00676 } else {
00677 return 0 ;
00678 }
00679
00680 }