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 #ifdef HAVE_CONFIG_H
00050 #include <config.h>
00051 #endif
00052
00053
00060
00063
00064
00065
00066
00067 #include <math.h>
00068 #include <xsh_drl.h>
00069
00070 #include <xsh_data_rec.h>
00071 #include <xsh_data_localization.h>
00072 #include <xsh_data_pre.h>
00073 #include <xsh_data_order.h>
00074 #include <xsh_dfs.h>
00075 #include <xsh_pfits.h>
00076 #include <xsh_error.h>
00077 #include <xsh_msg.h>
00078 #include <xsh_fit.h>
00079 #include <xsh_ifu_defs.h>
00080 #include <xsh_data_slice_offset.h>
00081 #include <xsh_data_atmos_ext.h>
00082 #include <cpl.h>
00083 #include <xsh_utils.h>
00084 #include <gsl/gsl_integration.h>
00085 #include <xsh_data_star_flux.h>
00086 #include <xsh_data_spectrum.h>
00087
00088 #define USE_SPLINE
00089 #if defined(USE_SPLINE)
00090 #include <gsl/gsl_spline.h>
00091 #endif
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102 #if defined(USE_SPLINE)
00103 static gsl_interp_accel * AcceleratorResp, * AcceleratorAtmos ;
00104 static gsl_spline * SplineResp, * SplineAtmos ;
00105
00106 static void init_interpolate( double * x, double * yf, int nb,
00107 gsl_spline ** spline,
00108 gsl_interp_accel ** accel)
00109 {
00110 int ok ;
00111
00112
00113
00114 *accel = gsl_interp_accel_alloc();
00115 if ( *accel == NULL ) xsh_msg( "Accelerator = NULL" ) ;
00116
00117 *spline = gsl_spline_alloc( gsl_interp_cspline, nb);
00118
00119 if ( *spline == NULL ) xsh_msg( "Spline = NULL" ) ;
00120
00121 ok = gsl_spline_init( *spline, x, yf, nb ) ;
00122
00123 xsh_msg( "gsl_spline_init --> %d", ok ) ;
00124
00125 return ;
00126 }
00127
00128 static double do_interpolation( double x, gsl_spline * spline,
00129 gsl_interp_accel * accel )
00130 {
00131 double y =0;
00132
00133 y = gsl_spline_eval( spline, x, accel );
00134
00135 return y ;
00136 }
00137
00138 static void clear_interpolate( void )
00139 {
00140 gsl_spline_free( SplineResp ) ;
00141 gsl_spline_free( SplineAtmos ) ;
00142 gsl_interp_accel_free( AcceleratorResp ) ;
00143 gsl_interp_accel_free( AcceleratorAtmos ) ;
00144
00145 }
00146 #else
00147
00148 static int get_idx_by_lambda( double lambda, double * a_lambda, int from,
00149 int to, double step )
00150 {
00151 int idx =0;
00152 double * plambda=NULL ;
00153
00154 for( idx = from, plambda = a_lambda+from ; idx<to ; idx++, plambda++ ) {
00155 if ( lambda >= (*plambda - step/2) &&
00156 lambda < (*plambda + step/2) ) {
00157 return idx ;
00158 }
00159 }
00160
00161 return -1 ;
00162 }
00163
00164 #endif
00165
00166 static double myfunc (double x, void * params) {
00167 double alpha = *(double *) params;
00168 double thefunc = exp(alpha*x*x) ;
00169
00170 return thefunc ;
00171 }
00172
00173 static double compute_Lx( double slit_width, double seeing )
00174 {
00175 gsl_integration_workspace * w
00176 = gsl_integration_workspace_alloc (10000);
00177
00178 double result, error;
00179 double alpha = -1.0;
00180
00181 gsl_function F;
00182 double limit ;
00183
00184 double Lx ;
00185
00186 F.function = &myfunc ;
00187 F.params = α
00188 limit = (slit_width/2.)/((seeing*sqrt(2.))/2.35482) ;
00189
00190 gsl_integration_qags (&F, 0, limit, 0, 1e-7, 10000,
00191 w, &result, &error);
00192
00193
00194 Lx = 1- (2/sqrt(M_PI))*result ;
00195
00196 return Lx ;
00197 }
00198
00199 static xsh_spectrum * do_calib_spectrum( xsh_spectrum * spectrum_in,
00200 xsh_star_flux_list * response_list,
00201 xsh_atmos_ext_list * atmos_ext_list,
00202 double airmass_ratio,
00203 double Lx )
00204 {
00205 xsh_spectrum * spectrum =NULL;
00206 double * spectrum_flux = NULL ;
00207 int * spectrum_qual = NULL ;
00208 double spectrum_lambda_min=0, spectrum_lambda_max=0 ;
00209 int spectrum_nlambda=0, spectrum_nslit=0 ;
00210 double lambda=0 ;
00211 double lambda_step=0 ;
00212
00213 double * atmos_lambda = NULL ;
00214 double * atmos_K = NULL ;
00215 double atmos_step=0 ;
00216 int atmos_size=0 ;
00217
00218 double * response_lambda = NULL ;
00219 double * response_flux = NULL ;
00220 double response_step=0 ;
00221 int response_size=0 ;
00222 int ipix=0 ;
00223 #if !defined(USE_SPLINE)
00224 int atmidx = 0, respidx = 0 ;
00225 #endif
00226
00227 check( spectrum = xsh_spectrum_duplicate( spectrum_in ) ) ;
00228
00229 check( spectrum_nlambda = xsh_spectrum_get_size_lambda( spectrum ) ) ;
00230 check( spectrum_nslit = xsh_spectrum_get_size_slit( spectrum ) ) ;
00231 if ( spectrum_nslit > 1 ) {
00232 xsh_msg( "2D Spectrum" ) ;
00233 }
00234 else {
00235 xsh_msg( "1D Spectrum" ) ;
00236 }
00237
00238 check( spectrum_flux = xsh_spectrum_get_flux( spectrum ) ) ;
00239 check( spectrum_qual = xsh_spectrum_get_qual( spectrum ) ) ;
00240 check( spectrum_lambda_min = xsh_spectrum_get_lambda_min( spectrum ) ) ;
00241 check( spectrum_lambda_max = xsh_spectrum_get_lambda_max( spectrum ) ) ;
00242 check( lambda_step = xsh_spectrum_get_lambda_step( spectrum ) ) ;
00243
00244 check( atmos_lambda = xsh_atmos_ext_list_get_lambda( atmos_ext_list ) ) ;
00245 check( atmos_K = xsh_atmos_ext_list_get_K( atmos_ext_list ) ) ;
00246 if (atmos_ext_list != NULL) {
00247 atmos_size = atmos_ext_list->size ;
00248 }
00249 atmos_step = *(atmos_lambda+atmos_size-1) - *atmos_lambda ;
00250 #if defined(USE_SPLINE)
00251 check( init_interpolate( atmos_lambda, atmos_K, atmos_size, &SplineAtmos,
00252 &AcceleratorAtmos ) ) ;
00253 #endif
00254
00255 check( response_lambda = xsh_star_flux_list_get_lambda( response_list ) ) ;
00256 check( response_flux = xsh_star_flux_list_get_flux( response_list ) ) ;
00257 response_size = response_list->size ;
00258 response_step = *(response_lambda+response_size-1) - *response_lambda ;
00259 #if defined(USE_SPLINE)
00260 check( init_interpolate( response_lambda, response_flux, response_size,
00261 &SplineResp,
00262 &AcceleratorResp ) ) ;
00263 #endif
00264
00265 lambda = spectrum_lambda_min ;
00266
00267 for( ipix = 0 ; ipix < spectrum_nlambda ; ipix++, lambda += lambda_step ) {
00268 double kvalue, vresp ;
00269 int islit ;
00270
00271
00272
00273 if ( atmos_ext_list != NULL ) {
00274 #if defined(USE_SPLINE)
00275 double inter_k ;
00276
00277 inter_k = do_interpolation( lambda, SplineAtmos, AcceleratorAtmos ) ;
00278 kvalue = pow( 10., -inter_k*0.4 ) ;
00279 #else
00280
00281 atmidx = get_idx_by_lambda( lambda, atmos_lambda, atmidx, atmos_size,
00282 atmos_step ) ;
00283 kvalue = pow(10., -atmos_K[atmidx]*0.4 ) ;
00284 #endif
00285 }
00286 else kvalue = 1. ;
00287
00288
00289
00290 #if defined(USE_SPLINE)
00291 vresp = do_interpolation( lambda, SplineResp, AcceleratorResp ) ;
00292 #else
00293
00294 respidx = get_idx_by_lambda( lambda, response_lambda, respidx,
00295 response_size, response_step ) ;
00296 vresp = response_flux[respidx] ;
00297 #endif
00298
00299 for( islit = 0 ; islit < spectrum_nslit ; islit++ ) {
00300 int idx=0 ;
00301
00302 if ( spectrum_qual[idx] != QFLAG_GOOD_PIXEL )
00303 continue ;
00304 idx = ipix + islit*spectrum_nlambda ;
00305 spectrum_flux[idx] *= (airmass_ratio*kvalue*vresp)/Lx ;
00306 }
00307 }
00308
00309 clear_interpolate() ;
00310
00311 cleanup:
00312 return spectrum ;
00313 }
00314
00315 cpl_frame * xsh_calibrate_flux( cpl_frame * spectrum_frame,
00316 cpl_frame * respon_frame,
00317 cpl_frame * atmos_ext_frame,
00318 const char * fname,
00319 xsh_instrument * instrument )
00320 {
00321 cpl_frame * result = NULL ;
00322 double s_airm_start, s_airm_end, r_airm_start, r_airm_end ;
00323 double s_airmass = 1., r_airmass = 1., airmass_ratio = 1. ;
00324 double slit_width, seeing_start, seeing_end, seeing ;
00325 cpl_propertylist * s_header = NULL, * r_header = NULL ;
00326 xsh_spectrum * spectrum = NULL;
00327 xsh_star_flux_list * response_list = NULL ;
00328 xsh_atmos_ext_list * atmos_ext_list = NULL ;
00329 double Lx ;
00330
00331 XSH_ASSURE_NOT_NULL( spectrum_frame ) ;
00332 XSH_ASSURE_NOT_NULL( respon_frame ) ;
00333 XSH_ASSURE_NOT_NULL( instrument ) ;
00334
00335
00336 check( spectrum = xsh_spectrum_load( spectrum_frame)) ;
00337 check( s_header = spectrum->flux_header ) ;
00338 s_airm_start = xsh_pfits_get_airm_start( s_header ) ;
00339 s_airm_end = xsh_pfits_get_airm_end( s_header ) ;
00340 if ( cpl_error_get_code() != CPL_ERROR_NONE ) {
00341 cpl_error_reset() ;
00342 s_airmass = 1. ;
00343 }
00344 else s_airmass = (s_airm_start + s_airm_end)/2. ;
00345
00346 check( response_list = xsh_star_flux_list_load( respon_frame ) ) ;
00347 check( r_header = response_list->header ) ;
00348 r_airm_start = xsh_pfits_get_airm_start( r_header ) ;
00349 r_airm_end = xsh_pfits_get_airm_end( r_header ) ;
00350 if ( cpl_error_get_code() != CPL_ERROR_NONE ) {
00351 cpl_error_reset() ;
00352 r_airmass = 1. ;
00353 }
00354 else r_airmass = (r_airm_start + r_airm_end)/2. ;
00355 airmass_ratio = s_airmass/r_airmass ;
00356
00357
00358 if ( xsh_instrument_get_mode( instrument ) == XSH_MODE_IFU ) {
00359 slit_width = WIDTH_SLIT_IFU ;
00360 xsh_msg( "IFU Mode Slit width: %.2lf", slit_width ) ;
00361 }
00362 else {
00363 check( slit_width = xsh_pfits_get_slit_width( s_header, instrument ) ) ;
00364 xsh_msg( "SLIT Mode Slit width: %.2lf", slit_width ) ;
00365 }
00366 check( seeing_start = xsh_pfits_get_seeing_start( s_header ) ) ;
00367 check( seeing_end = xsh_pfits_get_seeing_end( s_header ) ) ;
00368 seeing = (seeing_start + seeing_end)/2. ;
00369 xsh_msg_warning("SEEING=%g",seeing);
00370
00371 Lx = compute_Lx( slit_width, seeing ) ;
00372
00373
00374 if ( atmos_ext_frame != NULL ) {
00375 check( atmos_ext_list = xsh_atmos_ext_list_load( atmos_ext_frame ) ) ;
00376 xsh_msg( "ATMOS EXT Loaded" ) ;
00377 }
00378
00379
00380 check( do_calib_spectrum( spectrum, response_list, atmos_ext_list,
00381 airmass_ratio, Lx ) ) ;
00382
00383
00384 check( result = xsh_phys_spectrum_save( spectrum, fname, instrument )) ;
00385
00386 cleanup:
00387
00388 return result ;
00389 }