Ejemplo n.º 1
0
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
Ejemplo n.º 2
0
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
Ejemplo n.º 3
0
    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))