Пример #1
0
def combineRedLaw(ofn, chiar_curve='ism', power=-1.8):
    '''
    A method to combine the Fitzpatrick 2004 and Chiar & Tielens 2006 reddening
    laws as well as to extrapolate Chiar and Tielens 2006 to longer wavelengths.
    
    The result is saved in a file and used by the IvS repository as a valid 
    reddening law. 
    
    @param ofn: The output filename with path
    @type ofn: str
    
    @keyword chiar_curve: The curve type for Chiar & Tielens 2004. Either 'gc' 
                          or 'ism'.
                          
                          (default: 'ism')
    @type chiar_curve: str
    @keyword power: The power for the power law extrapolation. Default is taken
                    from Chiar and Tielens 2006, as a typical value for local
                    ISM between 2 and 5 micron. gc may require different value
                    but not very important.
                    
                    (default: -1.8)
    @type power: float

    '''

    chiar_curve = chiar_curve.lower()

    #-- Extract the two relevant extinction laws.
    xchiar, a_ak_chiar = red.get_law('chiar2006',norm='Ak',wave_units='micron',\
                                     curve=chiar_curve)
    xfitz, a_ak_fitz = red.get_law('fitzpatrick2004',norm='Ak',\
                                   wave_units='micron')

    #-- Define a power law for the extrapolation
    def power_law(x, scale, power):
        return scale * (x)**power

    #-- Determine the scaling factor from specific chiar/tielens law
    scale = a_ak_chiar[-1] / (xchiar[-1]**power)

    #-- Create an x grid for longer wavelengths.
    xlong = np.linspace(xchiar[-1] + 0.1, 1000, 1000)
    a_ak_long = power_law(xlong, scale, power)

    #-- Combine the three sections
    xcom = hstack([xfitz[xfitz < xchiar[0]], xchiar, xlong])
    a_ak_com = hstack([a_ak_fitz[xfitz < xchiar[0]], a_ak_chiar, a_ak_long])

    #-- Write the result to a file
    comments = '#-- wavelength (micron)   A_lambda/A_k\n'
    DataIO.writeCols(filename=ofn, cols=[[comments]])
    DataIO.writeCols(filename=ofn, cols=[xcom, a_ak_com], mode='a')
Пример #2
0
def combineRedLaw(ofn, chiar_curve="ism", power=-1.8):

    """
    A method to combine the Fitzpatrick 2004 and Chiar & Tielens 2006 reddening
    laws as well as to extrapolate Chiar and Tielens 2006 to longer wavelengths.
    
    The result is saved in a file and used by the IvS repository as a valid 
    reddening law. 
    
    @param ofn: The output filename with path
    @type ofn: str
    
    @keyword chiar_curve: The curve type for Chiar & Tielens 2004. Either 'gc' 
                          or 'ism'.
                          
                          (default: 'ism')
    @type chiar_curve: str
    @keyword power: The power for the power law extrapolation. Default is taken
                    from Chiar and Tielens 2006, as a typical value for local
                    ISM between 2 and 5 micron. gc may require different value
                    but not very important.
                    
                    (default: -1.8)
    @type power: float

    """

    chiar_curve = chiar_curve.lower()

    # -- Extract the two relevant extinction laws.
    xchiar, a_ak_chiar = red.get_law("chiar2006", norm="Ak", wave_units="micron", curve=chiar_curve)
    xfitz, a_ak_fitz = red.get_law("fitzpatrick2004", norm="Ak", wave_units="micron")

    # -- Define a power law for the extrapolation
    def power_law(x, scale, power):
        return scale * (x) ** power

    # -- Determine the scaling factor from specific chiar/tielens law
    scale = a_ak_chiar[-1] / (xchiar[-1] ** power)

    # -- Create an x grid for longer wavelengths.
    xlong = np.linspace(xchiar[-1] + 0.1, 1000, 1000)
    a_ak_long = power_law(xlong, scale, power)

    # -- Combine the three sections
    xcom = hstack([xfitz[xfitz < xchiar[0]], xchiar, xlong])
    a_ak_com = hstack([a_ak_fitz[xfitz < xchiar[0]], a_ak_chiar, a_ak_long])

    # -- Write the result to a file
    comments = "#-- wavelength (micron)   A_lambda/A_k\n"
    DataIO.writeCols(filename=ofn, cols=[[comments]])
    DataIO.writeCols(filename=ofn, cols=[xcom, a_ak_com], mode="a")
Пример #3
0
def redden(wave, flux, ak, law='Fitz2004Chiar2006', lawtype='ism'):
    '''
    Redden model fluxes, correcting for interstellar extinction. 
    
    Flux is assumed to be flux, and not magnitudes!
    
    For dereddening, pass -ak instead.
    
    The reddening law can be chosen, but should probably be Fitz2004Chiar2006 as
    it was tailored to infrared reddening of AGB sources in the Solar 
    neighbourhood.
    
    @param wave: The wavelength grid
    @type wave: array
    @param flux: The flux from the models
    @type flux: array
    @param ak: The interstellar reddening magnitude in Johnson K-band
    @type ak: float 
    
    @keyword law: The reddening law
                
                  (default: 'Fitz2004Chiar2006')
    @type law: str
    @keyword lawtype: The type of Chiar & Tielens reddening law (either ism or 
                      gc)
                      
                      (default: 'ism')
    @type lawtype: str
    
    @return: The reddened fluxes
    @rtype: array
     
    '''

    wave,a_ak = red.get_law(name=law,wave=wave,curve=lawtype,\
                            norm='Ak',wave_units='micron')
    return flux / 10**(a_ak * ak / 2.5)
Пример #4
0
def redden(wave, flux, ak, law="Fitz2004Chiar2006", lawtype="ism"):

    """
    Redden model fluxes, correcting for interstellar extinction. 
    
    Flux is assumed to be flux, and not magnitudes!
    
    For dereddening, pass -ak instead.
    
    The reddening law can be chosen, but should probably be Fitz2004Chiar2006 as
    it was tailored to infrared reddening of AGB sources in the Solar 
    neighbourhood.
    
    @param wave: The wavelength grid
    @type wave: array
    @param flux: The flux from the models
    @type flux: array
    @param ak: The interstellar reddening magnitude in Johnson K-band
    @type ak: float 
    
    @keyword law: The reddening law
                
                  (default: 'Fitz2004Chiar2006')
    @type law: str
    @keyword lawtype: The type of Chiar & Tielens reddening law (either ism or 
                      gc)
                      
                      (default: 'ism')
    @type lawtype: str
    
    @return: The reddened fluxes
    @rtype: array
     
    """

    wave, a_ak = red.get_law(name=law, wave=wave, curve=lawtype, norm="Ak", wave_units="micron")
    return flux / 10 ** (a_ak * ak / 2.5)
Пример #5
0
def getCFlux(wav,seds=[],star_grid=[],nans=1,deredden=[],\
             law='Fitz2004Chiar2006',lawtype='ism',map='marshall'):
    
    ''' 
    Retrieve the continuum flux at a given wavelength from either a model
    spectrum or an observation. If both seds and star_grid are given, 
    values from the seds are returned first in the array, then the models.
    
    For now assumes the observation is either an ISO SWS spectrum OR that the 
    continuum point is given in a dictionary that is property of the Sed() 
    object (sed.cflux) with wavelengths as keys. 
    
    star_grid are all models! Works also when seds or star_grid are empty.
    
    Reddening is taken into account when requested in the models and parameters
    are taken from the model objects. However, this is only allowed if only one
    data object is given (otherwise model reddening doesn't make sense)
    
    Dereddening of data is also possible (and extra arguments can be passed to 
    the reddening law), in which case distances have to be given for the seds. 
    If any model reddening is requested and only sed is given, sed dereddening 
    is always turned off.
    
    @param wav: The continuum wavelength point
    @type wav: float
    
    @keyword seds: The SEDs of the data objects. Number of SEDs sets the amount
                   of Star() objects represent data versus number of models.
                 
                   (default: [])
    @type seds: list(Sed())
    @keyword star_grid: The data + model objects
                        
                        (default: [])
    @type star_grid: list(Star())
    @keyword nans: Set undefined line strengths as nans. Errors are set as a 
                   nan if it concerns mode==dint. Otherwise, they are not set.
                   
                   (default: 1)
    @type nans: bool
    @keyword deredden: Deredden the SEDs with distances given here. This option 
                       is turned off automatically if any reddening is requested
                       in the models and only one sed is given to avoid double 
                       correction. Number of distances given must be equal to 
                       number of SEDs given. If not, it is also turned off. 
                       
                       (default: []) 
    @type deredden: list
    @keyword law: The reddening law for DEREDDENING
                
                  (default: 'Fitz2004Chiar2006')
    @type law: str
    @keyword lawtype: The type of Chiar & Tielens reddening law (either ism or 
                      gc) for DEREDDENING
                      
                      (default: 'ism')
    @type lawtype: str
    @keyword map: The galactic 3d extinction model for DEREDDENING. 
    
                      (default: 'marshall')
    @type map: str
    
    @return: The continuum fluxes in W/m2/Hz with length that of star_grid, as 
             well as errors if applicable. If a combo mode is requested, errors 
             are given when available, and listed as None/nan if not available 
             (Plotting2 module knows how to deal with this).
    @rtype: (array[float],array[float])
    
    '''
    
    all_cflux = []
    all_eflux = []
    rlaw = []
    
    dtype = ''
    if seds:
        ddict = dict([('SWS',(2.4,45.0)),('PACS',(55.1,189.))])
        for k,v in ddict.items():
            if v[0] <= wav and wav <= v[1]:
                dtype = k
                break
    
    #-- Only allow model reddening if one sed is given. Multiple: makes no sense
    #   to redden models. None: No galactic coordinates given to redden.
    redden = [s['REDDENING'] for s in star_grid] if len(seds) == 1 else []
    
    #-- Only allow dereddening if enough distances are given, and if model 
    #   reddening for one sed is not requested.
    if len(deredden) != len(seds) or np.any(redden):
        deredden = []
    
    #-- Interpolate the reddening law once.
    if deredden or redden: 
        wave_arr,rlaw = ivs_red.get_law(name=law,wave=wav,curve=lawtype,\
                                        norm='Ak',wave_units='micron')
        
    #-- First all data objects
    for ised,sed in enumerate(seds):
        dtypes = []
        if dtype:
            dtypes = [dt for dt in sed.data.keys() if dtype in dt[0].upper()]
        #-- If no SWS spectrum find, check if the flux is available in sed.flux
        if not dtypes:
            if sed.cflux.has_key(wav): 
                tflux = sed.cflux[wav]
                if deredden:
                    ak = sed.getAk(deredden[ised],map=map,law=law)
                    #-- deredden so increase flux, as opposed to redden
                    tflux = tflux * 10**(rlaw*ak/2.5)
                all_cflux.append(tflux)
                all_eflux.append(sed.eflux[wav])
            else:
                all_cflux.append(nans and float('nan') or None)
                all_eflux.append(nans and float('nan') or None)
            continue
        #-- At least one dtype spectrum found, take the first one.
        dt = dtypes[0]
        abs_err = sed.abs_err[dt[0]]
        dwave = sed.data[dt][0]
        dflux = sed.data[dt][1]
        
        #-- Check if the data object gives the standard deviation
        if len(sed.data[dt]) > 2:
            i = np.argmin(abs(dwave-wav))
            ilow = i if wav>dwave[i] else i-1
            iup = i if wav<dwave[i] else i+1
            errs = sed.data[dt][2]
            deflux = np.sqrt((errs/dflux)[ilow]**2+(errs/dflux)[iup]**2)
        else:
            deflux = 0.0
        
        #-- Interpolate for flux, and set the error taking into account abs flux
        #   calib uncert.
        interp = interp1d(dwave,dflux)
        tflux = interp(wav)
        if deredden:
            ak = sed.getAk(deredden[ised],map=map,law=law)
            #-- deredden so increase flux
            tflux = tflux * 10**(rlaw*ak/2.5)
        all_cflux.append(tflux)
        all_eflux.append(np.sqrt(deflux**2+abs_err**2))
        
    #-- Then all model objects
    all_eflux.extend([nans and float('nan') or None]*len(star_grid))
    for s in star_grid:
        if not s['LAST_MCMAX_MODEL']:
            all_cflux.append(nans and float('nan') or None)
            continue
        cc.path.mout = os.path.join(cc.path.mcmax,s.path_mcmax)
        dpath = os.path.join(cc.path.mcmax,s.path_mcmax,'models',\
                             s['LAST_MCMAX_MODEL'])
        w,f = MCMax.readModelSpectrum(dpath,rt_sed=1)
        interp = interp1d(w,f)
        tflux = interp(wav)
        if s['REDDENING'] and seds:
            #-- Only one SED is supposed to be given.
            ak = seds[0].getAk(s['DISTANCE'],map=s['REDDENING_MAP'],\
                               law=s['REDDENING_LAW'])
            #-- redden so decrease flux
            tflux = tflux / 10**(rlaw*ak/2.5)
        all_cflux.append(tflux)
    
    #-- All fluxes for SED type data or models are given in Jy. Convert to 
    #   W/m2/Hz. Errors are given in relative numbers, so no conversion needed.
    all_cflux = array(all_cflux)*1e-26
    all_eflux = array(all_eflux)
    
    return (all_cflux,all_eflux)
Пример #6
0
def getCFlux(wav,seds=[],star_grid=[],nans=1,deredden=[],\
             law='Fitz2004Chiar2006',lawtype='ism',map='marshall'):
    ''' 
    Retrieve the continuum flux at a given wavelength from either a model
    spectrum or an observation. If both seds and star_grid are given, 
    values from the seds are returned first in the array, then the models.
    
    For now assumes the observation is either an ISO SWS spectrum OR that the 
    continuum point is given in a dictionary that is property of the Sed() 
    object (sed.cflux) with wavelengths as keys. 
    
    star_grid are all models! Works also when seds or star_grid are empty.
    
    Reddening is taken into account when requested in the models and parameters
    are taken from the model objects. However, this is only allowed if only one
    data object is given (otherwise model reddening doesn't make sense)
    
    Dereddening of data is also possible (and extra arguments can be passed to 
    the reddening law), in which case distances have to be given for the seds. 
    If any model reddening is requested and only sed is given, sed dereddening 
    is always turned off.
    
    @param wav: The continuum wavelength point
    @type wav: float
    
    @keyword seds: The SEDs of the data objects. Number of SEDs sets the amount
                   of Star() objects represent data versus number of models.
                 
                   (default: [])
    @type seds: list(Sed())
    @keyword star_grid: The data + model objects
                        
                        (default: [])
    @type star_grid: list(Star())
    @keyword nans: Set undefined line strengths as nans. Errors are set as a 
                   nan if it concerns mode==dint. Otherwise, they are not set.
                   
                   (default: 1)
    @type nans: bool
    @keyword deredden: Deredden the SEDs with distances given here. This option 
                       is turned off automatically if any reddening is requested
                       in the models and only one sed is given to avoid double 
                       correction. Number of distances given must be equal to 
                       number of SEDs given. If not, it is also turned off. 
                       
                       (default: []) 
    @type deredden: list
    @keyword law: The reddening law for DEREDDENING
                
                  (default: 'Fitz2004Chiar2006')
    @type law: str
    @keyword lawtype: The type of Chiar & Tielens reddening law (either ism or 
                      gc) for DEREDDENING
                      
                      (default: 'ism')
    @type lawtype: str
    @keyword map: The galactic 3d extinction model for DEREDDENING. 
    
                      (default: 'marshall')
    @type map: str
    
    @return: The continuum fluxes in W/m2/Hz with length that of star_grid, as 
             well as errors if applicable. If a combo mode is requested, errors 
             are given when available, and listed as None/nan if not available 
             (Plotting2 module knows how to deal with this).
    @rtype: (array[float],array[float])
    
    '''

    all_cflux = []
    all_eflux = []
    rlaw = []

    dtype = ''
    if seds:
        ddict = dict([('SWS', (2.4, 45.0)), ('PACS', (55.1, 189.))])
        for k, v in ddict.items():
            if v[0] <= wav and wav <= v[1]:
                dtype = k
                break

    #-- Only allow model reddening if one sed is given. Multiple: makes no sense
    #   to redden models. None: No galactic coordinates given to redden.
    redden = [s['REDDENING'] for s in star_grid] if len(seds) == 1 else []

    #-- Only allow dereddening if enough distances are given, and if model
    #   reddening for one sed is not requested.
    if len(deredden) != len(seds) or np.any(redden):
        deredden = []

    #-- Interpolate the reddening law once.
    if deredden or redden:
        wave_arr,rlaw = ivs_red.get_law(name=law,wave=wav,curve=lawtype,\
                                        norm='Ak',wave_units='micron')

    #-- First all data objects
    for ised, sed in enumerate(seds):
        dtypes = []
        if dtype:
            dtypes = [dt for dt in sed.data.keys() if dtype in dt[0].upper()]
        #-- If no SWS spectrum find, check if the flux is available in sed.flux
        if not dtypes:
            if sed.cflux.has_key(wav):
                tflux = sed.cflux[wav]
                if deredden:
                    ak = sed.getAk(deredden[ised], map=map, law=law)
                    #-- deredden so increase flux, as opposed to redden
                    tflux = tflux * 10**(rlaw * ak / 2.5)
                all_cflux.append(tflux)
                all_eflux.append(sed.eflux[wav])
            else:
                all_cflux.append(nans and float('nan') or None)
                all_eflux.append(nans and float('nan') or None)
            continue
        #-- At least one dtype spectrum found, take the first one.
        dt = dtypes[0]
        abs_err = sed.abs_err[dt[0]]
        dwave = sed.data[dt][0]
        dflux = sed.data[dt][1]

        #-- Check if the data object gives the standard deviation
        if len(sed.data[dt]) > 2:
            i = np.argmin(abs(dwave - wav))
            ilow = i if wav > dwave[i] else i - 1
            iup = i if wav < dwave[i] else i + 1
            errs = sed.data[dt][2]
            deflux = np.sqrt((errs / dflux)[ilow]**2 + (errs / dflux)[iup]**2)
        else:
            deflux = 0.0

        #-- Interpolate for flux, and set the error taking into account abs flux
        #   calib uncert.
        interp = interp1d(dwave, dflux)
        tflux = interp(wav)
        if deredden:
            ak = sed.getAk(deredden[ised], map=map, law=law)
            #-- deredden so increase flux
            tflux = tflux * 10**(rlaw * ak / 2.5)
        all_cflux.append(tflux)
        all_eflux.append(np.sqrt(deflux**2 + abs_err**2))

    #-- Then all model objects
    all_eflux.extend([nans and float('nan') or None] * len(star_grid))
    for s in star_grid:
        if not s['LAST_MCMAX_MODEL']:
            all_cflux.append(nans and float('nan') or None)
            continue
        cc.path.mout = os.path.join(cc.path.mcmax, s.path_mcmax)
        dpath = os.path.join(cc.path.mcmax,s.path_mcmax,'models',\
                             s['LAST_MCMAX_MODEL'])
        w, f = MCMax.readModelSpectrum(dpath, rt_sed=1)
        interp = interp1d(w, f)
        tflux = interp(wav)
        if s['REDDENING'] and seds:
            #-- Only one SED is supposed to be given.
            ak = seds[0].getAk(s['DISTANCE'],map=s['REDDENING_MAP'],\
                               law=s['REDDENING_LAW'])
            #-- redden so decrease flux
            tflux = tflux / 10**(rlaw * ak / 2.5)
        all_cflux.append(tflux)

    #-- All fluxes for SED type data or models are given in Jy. Convert to
    #   W/m2/Hz. Errors are given in relative numbers, so no conversion needed.
    all_cflux = array(all_cflux) * 1e-26
    all_eflux = array(all_eflux)

    return (all_cflux, all_eflux)