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')
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")
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)
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)
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)
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)