def spec2filter(filter, obs_spec, model_spec=None, badpxl_tolerance = 0.5): ''' Converts a spectrum on AB magnitude given a filter bandpass. If there are bad pixels on filter interval on a fraction inferior to the badpxl_tolerance, it will interpolate the missing values or, in case of a model_spec != None, it will use the values from model_spec. Parameters ---------- filter : dict Filter transmission curve. Dictionary containing the following entries: {'wl': array_like Wavelength (in Angstroms!). 'transm': array_like Filter transmission response. } obs_spec : dict Observed Spectra. Dictionary containing the following entries: {'wl': array_like, 'flux': array_like, 'error': array_like, optional, 'flag': array_like, optional, 'model_spec': array_like, optional } model_spec : dict, optional Model Spectra which could be used when there are missing (due to err or flagged). Dictionary containing the following entries: { 'wl': array_like Wavelength (in the same units as filter response curve) 'flux': array_like Flux on a given wl } badpxl_tolerance : float, default: 0.5 Bad pixel fraction tolerance on the spectral interval of the filter. Returns ------- m_ab : float AB magnitude on given filter e_ab : float AB magnitude error on given filter See Also -------- Notes ----- ''' log = logging.getLogger('bgpe.photometry.photoconv') #Cut the spectrum on the filterset range. This improves the velocity of the rest of the accounts. obs_cut = obs_spec[np.bitwise_and(obs_spec['wl'] >= np.min(filter['wl']), obs_spec['wl'] <= np.max(filter['wl']))] if model_spec != None: model_cut = model_spec[:,np.bitwise_and(model_spec['wl'] >= np.min(filter['wl']), model_spec['wl'] <= np.max(filter['wl']))] if len(model_cut) == 0: log.warning('No enough MODEL datapoints eval synthetic photometry on this filter. Model will NOT be considered.') model_spec = None elif np.any(model_cut['wl'] != obs_cut['wl']): log.warning('Model is not sampled the same way as the observed spectrum. Interpolating...') aux = np.copy(model_cut) model_cut = obs_cut[:len(model_spec)] model_cut['flux'] = np.interp(obs_cut['wl'],aux['wl'],aux['flux'], left=0.0, right=0.0) #Check if the filterset is sampled correctly # - Tip: Resample the filter to your data when reading the filter to avoid unnessessary interpolations. if(np.any(obs_cut['wl'] != filter['wl'])): log.warning('Filter is not sampled the same way as the observed spectrum. Interpolating...') wl_ = obs_cut['wl'] transm_ = np.interp(obs_cut['wl'],filter['wl'],filter['transm']) else: wl_ = filter['wl'] transm_ = filter['transm'] #Check for bad pixels. Good pixels should be signaled with flag(lambda) = 0 or 1. # The recipe is: # - If there is LESS bad_pixels than badpxl_tolerance: # And there is a model_spec: use model_spec # And there is NOT a model_spec: interpolate values # - If there is MORE bad_pixels than badpxl_tolerance: # Return a magnitude np.inf and an error of np.inf. n = len(obs_cut) if('flag' in obs_cut.dtype.names and 'error' in obs_cut.dtype.names): # First check if there is error AND flag. good = np.bitwise_and(obs_cut['flag'] <= 1, obs_cut['error'] > 0) bad = np.invert(good) n_bad = np.sum(bad) elif('error' in obs_cut.dtype.names): # Check if there is ONLY error. good = (obs_cut['error'] > 0) bad = np.invert(good) n_bad = np.sum(bad) elif('flag' in obs_cut.dtype.names): # Check if there is ONLY flag. good = (obs_cut['flag'] <= 1) bad = np.invert(good) n_bad = np.sum(bad) else: # If there is only spectra, all the pixels are good! =) good = (obs_cut['wl'] > 0) bad = np.invert(good) n_bad = np.sum(bad) log.debug( 'N_points: %d, N_bad: %d' % (n, n_bad) ) if(n_bad > 0 or n == 0): #If we have problems we have to deal with them... ;) if (n == 0): log.debug('# of pixels = 0. m = inf and m_err = inf') m_ab = np.inf e_ab = np.inf return m_ab, e_ab p_bad = np.float(n_bad)/np.float(len(obs_cut)) if(p_bad > badpxl_tolerance): #If we have # of bad pixels greater than 50%, then make filter flux and error equal to inf. log.debug('# of bad pixels > badpxl_tolerance. m = inf and m_err = inf') m_ab = np.inf e_ab = np.inf return m_ab, e_ab else: #If we have # of bad pixels less than 50%, we simply neglect this point on the error acoounts, #and make flux = synthetic flux, if available, if not, interpolate values. if model_spec != None: obs_cut['flux'][bad] = model_cut['flux'][bad] else: raise 'interpo' #TODO: interpolation! else: # If our observed obs_spec is ALL ok. =) log.debug('No bad pixel! =)') m_ab = -2.5 * np.log10( np.trapz(obs_cut['flux'] * transm_ * wl_, wl_) / np.trapz(transm_ / wl_, wl_) ) - 2.41 if('error' in obs_cut.dtype.names): e_ab = 1.0857362047581294 * np.sqrt( np.sum(transm_[good]**2 * obs_cut['error'][good]**2 * wl_[good] ** 2 )) / np.sum(obs_cut['flux'][good] * transm_[good] * wl_[good]) else: e_ab = 0.0 return m_ab, e_ab
def spec2filterset(filterset, obs_spec, model_spec = None, badpxl_tolerance = 0.5): ''' Run spec2filter over a filterset Parameters ---------- filterset : object Filter transmission curves (see: bgpe.io.readfilterset). obs_spec : dict Observed Spectra. Dictionary containing the following entries: { 'wl': array_like Wavelength. (in Angstroms!) 'flux': array_like Flux on a given wl. 'error': array_like, optional Flux error. If err < 0, the point will be considered as a problem. 'flag': array_like, optional Bad pixel flag. Pixels are considered bad if flag > 1. 'model_spec': array_like, optional Model Spectra which could be used when there are missing (due to err or flagged). } model_spec : dict, optional Model Spectra which could be used when there are missing (due to err or flagged). Dictionary containing the following entries: { 'wl': array_like Wavelength (in the same units as filter response curve) 'flux': array_like Flux on a given wl } badpxl_tolerance : float, default: 0.5 Bad pixel fraction tolerance on the spectral interval of the filter. Returns ------- mags : array_like Filterset magnitudes Dictionary containing the following entries: { 'm_ab': array_like AB magnitude on given filter. 'e_ab' : array_like AB magnitude error on given filter. } See Also -------- spec2filter, bgpe.io.readfilterset Notes ----- ''' log = logging.getLogger('bgpe.photometry.photoconv') filter_ids = np.unique(filterset['ID_filter']) mags = np.zeros(len(filter_ids), dtype = np.dtype([('m_ab', '<f8'), ('e_ab', '<f8')])) for i_filter in range(len(filter_ids)): filter = filterset[filterset['ID_filter'] == filter_ids[i_filter]] mags[i_filter]['m_ab'], mags[i_filter]['e_ab'] = spec2filter(filter, obs_spec, model_spec, badpxl_tolerance = badpxl_tolerance) log.debug('Magnitude to filter %s: %3.2f, error: %3.2f' % (filter_ids[i_filter], mags[i_filter]['m_ab'], mags[i_filter]['e_ab']) ) return mags
syn02_file = '%s/sample.F%s.%s.f.Starlight.SYN02.tab.BS.bz2' % (tables_dir, args.d[0], args.sa[0]) syn03_file = '%s/sample.F%s.%s.f.Starlight.SYN03.tab.BS.bz2' % (tables_dir, args.d[0], args.sa[0]) syn04_file = '%s/sample.F%s.%s.f.Starlight.SYN04.tab.BS.bz2' % (tables_dir, args.d[0], args.sa[0]) db_file = args.o[0] filter_file = args.f[0] filterid = os.path.basename(filter_file).split('.')[0] z_from = np.float(args.z_ini[0]) z_to = np.float(args.z_fin[0]) z_step = np.float(args.dz[0]) # 1 - Read files # 1.1 - Filter db_f = read_filterhdf5(filter_file) # 1.2 - Emission lines log.debug('Reading elines...') t_start = time.time() tb = atpy.Table(el_file, type='starlight_el') log.debug('Took %3.2f seconds.' % (time.time() - t_start)) # 1.3 - SYN0[1-4] log.debug('Reading SYN files...') t_start = time.time() tsyn01 = atpy.Table(syn01_file, type='starlight_syn01', include_names = ('id', 'A_V', 'v0', 'vd', 'SN_w', 'SN_n')) tsyn02 = atpy.Table(syn02_file, type='starlight_syn02', include_names = ('id', 'at_flux', 'at_mass', 'aZ_flux', 'aZ_mass', 'am_flux', 'am_mass')) tsyn03 = atpy.Table(syn03_file, type='starlight_syn03', include_names = ('id', 'M2L_r')) tsyn04 = atpy.Table(syn04_file, type='starlight_syn04', include_names = ('id', 'Mcor_fib', 'Mcor_gal', 'DL_Mpc', 'Mini_fib', 'z')) log.debug('Took %3.2f seconds.' % (time.time() - t_start))