def prepareModels(self): ''' Prepare models for dust feature continuum division. The equivalent width of the feature is also calculated here. ''' for i, s in enumerate(self.star_grid): model_id = s['LAST_MCMAX_MODEL'] if not model_id: continue dpath = os.path.join(cc.path.mout, 'models', model_id) fn_spec = 'spectrum{:04.1f}.dat'.format(s['RT_INCLINATION']) w, f = MCMax.readModelSpectrum(dpath, s['RT_SPEC'], fn_spec) self.divideContinuum(w, f, dtype=model_id, frindex=i) self.calcEqWidth(dtype=model_id, frindex=i)
def prepareModels(self): ''' Prepare models for dust feature continuum division. The equivalent width of the feature is also calculated here. ''' for i,s in enumerate(self.star_grid): model_id = s['LAST_MCMAX_MODEL'] if not model_id: continue dpath = os.path.join(cc.path.mout,'models',model_id) fn_spec = 'spectrum{:04.1f}.dat'.format(s['RT_INCLINATION']) w,f = MCMax.readModelSpectrum(dpath,s['RT_SPEC'],fn_spec) self.divideContinuum(w,f,dtype=model_id,frindex=i) self.calcEqWidth(dtype=model_id,frindex=i)
def prepareModels(self): ''' Prepare models for dust feature continuum division. The equivalent width of the feature is also calculated here. ''' model_ids = [ s['LAST_MCMAX_MODEL'] for s in self.star_grid if s['LAST_MCMAX_MODEL'] ] if model_ids: rt_sed = self.star_grid[0]['RT_SED'] path_mcmax = self.star_grid[0].path_mcmax for i, model_id in enumerate(model_ids): w, f = MCMax.readModelSpectrum(path_mcmax, model_id, rt_sed) self.divideContinuum(w, f, dtype=model_id, frindex=i) self.calcEqWidth(dtype=model_id, frindex=i)
def prepareModels(self): ''' Prepare models for dust feature continuum division. The equivalent width of the feature is also calculated here. ''' model_ids = [s['LAST_MCMAX_MODEL'] for s in self.star_grid if s['LAST_MCMAX_MODEL']] if model_ids: rt_sed = self.star_grid[0]['RT_SED'] path_mcmax = self.star_grid[0].path_mcmax for i,model_id in enumerate(model_ids): w,f = MCMax.readModelSpectrum(path_mcmax,model_id,rt_sed) self.divideContinuum(w,f,dtype=model_id,frindex=i) self.calcEqWidth(dtype=model_id,frindex=i)
def setModelPhotometry(self): ''' Prepare the model photometry to be compared with the data. Two kinds: The IvS photometry with proper photometric bands, and other photometry to be compared with the interpolated model spectrum. ''' #- Collect model data and set ak if needed mids = [s['LAST_MCMAX_MODEL'] for s in self.star_grid] if not mids: print "No successfully calculated MCMax models found." return self.mwave = [] self.mflux = [] for model_id,s in zip(mids,self.star_grid): dpath = os.path.join(cc.path.mout,'models',model_id) fn_spec = 'spectrum{:04.1f}.dat'.format(s['RT_INCLINATION']) w,f = MCMax.readModelSpectrum(dpath,s['RT_SPEC'],fn_spec) if s['REDDENING']: print 'Reddening models to correct for interstellar extinction.' ak = self.sed.getAk(s['DISTANCE'],s['REDDENING_MAP'],\ s['REDDENING_LAW']) f = Reddening.redden(w,f,ak,law=s['REDDENING_LAW']) self.mwave.append(w) self.mflux.append(f) if self.photbands.size: self.mphot_ivs = [Sed.calcPhotometry(w,f,self.photbands) for w,f in zip(self.mwave,self.mflux)] for fn in self.dphot_other.keys(): self.mphot_other[fn] = [] if self.dphot_other.keys(): for w,f in zip(self.mwave,self.mflux): interp = interp1d(w,f) for fn in self.dphot_other.keys(): finter = interp(self.dphot_other[fn]['wave']) self.mphot_other[fn].append(finter)
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 plotSed(self,star_grid=[],cfg='',iterative=0,no_models=0,\ fn_add_star=0): """ Creating an SED with 0, 1 or more models and data. Includes data preparation on the spot. @keyword star_grid: list of Star() models to plot. If star_grid is [], only data are plotted. (default: []) @type star_grid: list[Star()] @keyword cfg: path to the Plotting2.plotCols config file. If default, the hard-coded default plotting options are used. (default: '') @type cfg: string @keyword iterative: add an extra suffix to the filename for each iteratively calculated model, with this number giving the model muber (index in star_grid), 0 if not used. (default: 0) @type iterative: int @keyword no_models: Only show data. (default: 0) @type no_models: bool @keyword fn_add_star: Add the star name to the requested plot filename. (default: 1) @type fn_add_star: bool """ if self.sed is None: print 'No dsed given in Path.dat. Cannot plot SED. Aborting...' return print '***********************************' print '** Creating SED plot.' cfg_dict = Plotting2.readCfg(cfg) if cfg_dict.has_key('no_models'): no_models = cfg_dict['no_models'] if cfg_dict.has_key('fn_add_star'): fn_add_star = bool(cfg_dict['fn_add_star']) if cfg_dict.has_key('filename'): fn_plt = cfg_dict['filename'] del cfg_dict['filename'] else: fn_plt = '' data_labels = dict([(dt,(n,ls)) for n,dt,ls in zip(DataIO.getInputData(path=cc.path.usr,\ keyword='PLOT_NAMES',\ filename='Sed.dat',\ remove_underscore=1),\ DataIO.getInputData(path=cc.path.usr,\ keyword='DATA_TYPES',\ filename='Sed.dat'),\ DataIO.getInputData(path=cc.path.usr,\ keyword='LINE_TYPES',\ filename='Sed.dat'))]) #- filename settings and copying inputfiles to plot output folder if not fn_plt: fn_plt = os.path.join(self.pplot, 'SED_%s' % self.star_name) if fn_add_star: fn_plt = '_'.join([fn_plt, self.star_name]) if iterative: fn_plt = fn_plt + '_iterative_%i' % iterative if self.inputfilename <> None: ipfn = os.path.split(self.inputfilename)[1] subprocess.call(['cp ' + self.inputfilename + ' ' + \ os.path.join(self.pplot,ipfn)],\ shell=True) plot_title = 'SED %s' % self.star_name_plots #- prepare and collect data, keytags and line types keytags = [] data_x = [] data_y = [] data_err = [] line_types = [] for (dt, fn), tdata in sorted([ dset for dset in self.sed.data.items() if 'PHOT' not in dset[0][0].upper() ]): keytags.append(data_labels[dt][0]) data_x.append(tdata[0]) data_y.append(tdata[1]) #data_err.append(tdata[2]) #-- For now, no error bars for spectra. data_err.append(None) line_types.append(data_labels[dt][1]) for (dt, fn), (w, f, err) in sorted([ dset for dset in self.sed.data.items() if 'PHOT' in dset[0][0].upper() ]): keytags.append(data_labels[dt][0]) data_x.append(w) data_y.append(f) data_err.append(err) line_types.append(data_labels[dt][1]) #- Collect model data as well as keytags and set line types model_ids_mcm = [ s['LAST_MCMAX_MODEL'] for s in star_grid if s['LAST_MCMAX_MODEL'] ] #- Only if the model_ids list is not empty, MCMax models are available #- Otherwise the ray tracing keyword is unnecessary. if no_models: model_ids_mcm = [] if model_ids_mcm: rt_sed = star_grid[0]['RT_SED'] for model_id in model_ids_mcm: dpath = os.path.join(cc.path.mout, 'models', model_id) w, f = MCMax.readModelSpectrum(dpath, rt_sed) data_x.append(w) data_y.append(f) data_err.append(None) keytags.append(model_id.replace('_', '\_')) line_types += [0] * len(star_grid) keytags = [tag.replace('#', '') for tag in keytags] extra_pars = dict() try: extra_pars['ymax'] = 1.3 * max([max(dy) for dy in data_y]) except ValueError: pass try: extra_pars['ymin'] = 0.5 * min([min(dy) for dy in data_y]) except ValueError: pass filename = Plotting2.plotCols(x=data_x,y=data_y,yerr=data_err,\ filename=fn_plt,\ figsize=(20,10),number_subplots=1,\ plot_title=plot_title,fontsize_axis=20,\ keytags=keytags,fontsize_title=24,\ linewidth=3,key_location=(0.0,0.75),\ xlogscale=1,transparent=0,cfg=cfg_dict,\ line_types=line_types,ylogscale=0,\ fontsize_ticklabels=20,fontsize_key=18,\ xmin=2,xmax=200,extension='.pdf',\ **extra_pars) print '** Your SED plots can be found at:' print filename print '***********************************'
def plotVisibilities(self,star_grid=[],cfg='',no_models=0,\ fn_add_star=0): """ Plot visibilities as a function of baseline. Wavelengths plotted are what is requested in the ray tracing Includes data preparation on the spot. Data location is that of correlated flux (for the visibilities), but also requires an sed object to retrieve the MIDI spectrum. If one of them is not available, models are be plotted without data. @keyword star_grid: list of Star() models to plot. If star_grid is [], only data are plotted. (default: []) @type star_grid: list[Star()] @keyword cfg: path to the Plotting2.plotCols config file. If default, the hard-coded default plotting options are used. (default: '') @type cfg: string @keyword no_models: Only show data. (default: 0) @type no_models: bool @keyword fn_add_star: Add the star name to the requested plot filename. (default: 1) @type fn_add_star: bool """ if not cc.path.dcflux: print 'No dcflux given in Path.dat. Aborting...' return if not self.sed or 'MIDI' not in self.sed.data_types: print 'No dsed given in Path.dat or no MIDI spectral data found. Aborting.' return print '***********************************' print '** Creating Visibilities plot.' cfg_dict = Plotting2.readCfg(cfg) if cfg_dict.has_key('no_models'): no_models = cfg_dict['no_models'] if cfg_dict.has_key('fn_add_star'): fn_add_star = bool(cfg_dict['fn_add_star']) if cfg_dict.has_key('filename'): fn_plt = cfg_dict['filename'] del cfg_dict['filename'] else: fn_plt = '' #- filename settings and copying inputfiles to plot output folder if not fn_plt: fn_plt = os.path.join(self.pplot, 'Visibilities') if fn_add_star: fn_plt = '_'.join([fn_plt, self.star_name]) if self.inputfilename <> None: ipfn = os.path.split(self.inputfilename)[1] subprocess.call(['cp ' + self.inputfilename + ' ' + \ os.path.join(self.pplot,ipfn)],\ shell=True) #-- Read the models. Wavelengths are taken from the ray-tracing output models = [] if not no_models: for s in star_grid: model_id = s['LAST_MCMAX_MODEL'] dpath = os.path.join(cc.path.mout, 'models', model_id) model = MCMax.readVisibilities(dpath=dpath,\ fn_vis='basevis01.0.dat') models.append(model) real_models = [model for model in models if model] if not real_models: no_models = 1 else: wavelengths = sorted(real_models[0]['wavelength'].keys()) if no_models: wavelengths = (8., 10., 13.) #-- Grab the MIDI spectrum fn = self.sed.data_filenames[self.sed.data_types.index('MIDI')] midi_flux = self.sed.data[('MIDI', fn)][1] midi_err = self.sed.data[('MIDI', fn)][2] midi_relerr = (midi_err / midi_flux)**2 #-- Select MIDI data. Assumes baseline at the end of the filename. ssd = os.path.join(cc.path.dcflux,self.star_name,\ '_'.join([self.star_name,'MIDI','*.fits'])) files = [os.path.splitext(gi)[0] for gi in glob.glob(ssd)] ggd = dict([(float(gi.split('_')[-1].strip('m')), gi + '.fits') for gi in files]) #-- Collect MIDI data from the fits file and calculate visibilities ddf = dict() for k, v in sorted(ggd.items()): ddf[k] = dict() dfits = pyfits.open(v) #-- Read the wavelength cwave = 1e6 * dfits['OI_WAVELENGTH'].data['EFF_WAVE'][::-1] #-- Read flux + err and select the right range cflux = dfits['OI_VIS'].data['VISAMP'][0][::-1] cflux = cflux[(cwave <= 13.) * (cwave >= 8.)] cflux_err = dfits['OI_VIS'].data['VISAMPERR'][0][::-1] cflux_err = cflux_err[(cwave <= 13.) * (cwave >= 8.)] #-- The visibilities are correlated flux divided by real flux ddf[k]['y'] = cflux / midi_flux #-- Error propagation cflux_relerr = (cflux_err / cflux)**2 yerr = np.sqrt(midi_relerr + cflux_relerr) * cflux / midi_flux ddf[k]['yerr'] = yerr #-- Wavelength grid ddf[k]['x'] = cwave[(cwave <= 13.) * (cwave >= 8.)] dfits.close() #-- prepare and collect plot data, keytags and line types data = [] for w in wavelengths: ddict = dict() data.append(ddict) #-- Set the plot x and y bls = [k for k in sorted(ddf.keys())] ddict['x'] = [[bl for bl in bls]] ddict['y'] = [[ ddf[bl]['y'][np.argmin(abs(ddf[bl]['x'] - w))] for bl in bls ]] ddict['yerr'] = [[ ddf[bl]['yerr'][np.argmin(abs(ddf[bl]['x'] - w))] for bl in bls ]] #-- Set limits and labels ddict['labels'] = [('MIDI %s $\\mu$m' % w, 0.85, 0.9)] if no_models: continue #-- Extract models from the model folders for model in models: ddict['yerr'].append(None) if not model: ddict['x'].append(np.empty(0)) ddict['y'].append(np.empty(0)) continue ddict['x'].append(model['baseline']) ddict['y'].append(model['wavelength'][w]) kwargs = dict() kwargs['keytags'] = ['MIDI'] if not no_models: kwargs['keytags'].extend( [s['LAST_MCMAX_MODEL'].replace('_', '\_') for s in star_grid]) kwargs['xaxis'] = 'Baseline (m)' kwargs['yaxis'] = 'Visibility' kwargs['dimensions'] = (1, len(data) + 1) kwargs['figsize'] = (10, 15) kwargs['fontsize_axis'] = 20 kwargs['fontsize_ticklabels'] = 20 kwargs['fontsize_key'] = 18 kwargs['fontsize_label'] = 14 kwargs['linewidth'] = 3 kwargs['cfg'] = cfg_dict kwargs['extension'] = '.pdf' kwargs['hspace'] = 0.3 kwargs['ws_bot'] = 0.01 kwargs['ws_top'] = 0.99 kwargs['ws_left'] = 0.10 kwargs['ws_right'] = 0.98 filename = Plotting2.plotTiles(data=data, filename=fn_plt, **kwargs) print '** Your Correlated Flux plots can be found at:' print filename print '***********************************'
def plotCorrflux(self, star_grid=[], cfg='', no_models=0, fn_add_star=0): """ Plot correlated fluxes with 0, 1 or more models and data. Includes data preparation on the spot. @keyword star_grid: list of Star() models to plot. If star_grid is [], only data are plotted. (default: []) @type star_grid: list[Star()] @keyword cfg: path to the Plotting2.plotCols config file. If default, the hard-coded default plotting options are used. (default: '') @type cfg: string @keyword no_models: Only show data. (default: 0) @type no_models: bool @keyword fn_add_star: Add the star name to the requested plot filename. (default: 1) @type fn_add_star: bool """ if not cc.path.dcflux: print 'No dcflux given in Path.dat. Cannot plot Correlated Fluxes. Aborting...' return print '***********************************' print '** Creating Correlated Fluxes plot.' cfg_dict = Plotting2.readCfg(cfg) if cfg_dict.has_key('no_models'): no_models = cfg_dict['no_models'] if cfg_dict.has_key('fn_add_star'): fn_add_star = bool(cfg_dict['fn_add_star']) if cfg_dict.has_key('filename'): fn_plt = cfg_dict['filename'] del cfg_dict['filename'] else: fn_plt = '' #- filename settings and copying inputfiles to plot output folder if not fn_plt: fn_plt = os.path.join(self.pplot, 'CorrFlux') if fn_add_star: fn_plt = '_'.join([fn_plt, self.star_name]) if self.inputfilename <> None: ipfn = os.path.split(self.inputfilename)[1] subprocess.call(['cp ' + self.inputfilename + ' ' + \ os.path.join(self.pplot,ipfn)],\ shell=True) #-- Select MIDI data. Assumes baseline at the end of the filename. ssd = os.path.join(cc.path.dcflux,self.star_name,\ '_'.join([self.star_name,'MIDI','*.fits'])) files = [os.path.splitext(gi)[0] for gi in glob.glob(ssd)] ggd = dict([(float(gi.split('_')[-1].strip('m')), gi + '.fits') for gi in files]) #-- Read the models models = [] if not no_models: for s in star_grid: model_id = s['LAST_MCMAX_MODEL'] dpath = os.path.join(cc.path.mout, 'models', model_id) model = MCMax.readVisibilities(dpath=dpath,\ fn_vis='visibility01.0.dat') models.append(model) real_models = [model for model in models if model] if not real_models: no_models = 1 baselines = sorted(ggd.keys()) else: baselines = sorted(real_models[0]['baseline'].keys()) #-- prepare and collect data, keytags and line types data = [] for bl in baselines: ddict = dict() data.append(ddict) #-- Extract data from the fits file if ggd.has_key(bl): dfits = pyfits.open(ggd[bl]) x = 1e6 * dfits['OI_WAVELENGTH'].data['EFF_WAVE'][::-1] ddict['x'] = [x] ddict['y'] = [dfits['OI_VIS'].data['VISAMP'][0]][::-1] ddict['yerr'] = [dfits['OI_VIS'].data['VISAMPERR'][0]][::-1] dfits.close() else: ddict['x'] = [] ddict['y'] = [] ddict['yerr'] = [] if no_models: continue #-- Extract models from the model folders for model in models: ddict['yerr'].append(None) if not model: ddict['x'].append(np.empty(0)) ddict['y'].append(np.empty(0)) continue ddict['x'].append(model['wavelength']) ddict['y'].append(model['flux'] * model['baseline'][bl]) #-- Set some plot limits ddict['xmin'] = 8 ddict['xmax'] = 13 ddict['ymin'] = -0.1 ddict['labels'] = [('MIDI %.1f m' % bl, 0.05, 0.9)] #-- Wavelength limits between 8 and 13 micron, limits of the N band # atmospheric transmission. Outside these ranges, the flux is not # relevant ddict['ymax'] = 1.1 * max([ max(iy[(ix <= 13.) * (ix >= 8.)]) for ix, iy in zip(ddict['x'], ddict['y']) if iy.size ]) kwargs = dict() kwargs['keytags'] = ['MIDI'] if not no_models: kwargs['keytags'].extend( [s['LAST_MCMAX_MODEL'].replace('_', '\_') for s in star_grid]) kwargs['xaxis'] = '$\lambda$ ($\mu$m)' kwargs['yaxis'] = 'Corr.~FLux (Jy)' kwargs['dimensions'] = (1, len(data) + 1) kwargs['figsize'] = (10, 15) kwargs['fontsize_axis'] = 20 kwargs['fontsize_ticklabels'] = 20 kwargs['fontsize_key'] = 18 kwargs['fontsize_label'] = 14 kwargs['linewidth'] = 3 kwargs['cfg'] = cfg_dict kwargs['extension'] = '.pdf' kwargs['hspace'] = 0.3 kwargs['ws_bot'] = 0.01 kwargs['ws_top'] = 0.99 kwargs['ws_left'] = 0.10 kwargs['ws_right'] = 0.98 filename = Plotting2.plotTiles(data=data, filename=fn_plt, **kwargs) print '** Your Correlated Flux plots can be found at:' print filename print '***********************************'
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 plotSed(self,star_grid=[],cfg='',iterative=0,no_models=0,\ fn_add_star=0): """ Creating an SED with 0, 1 or more models and data. Includes data preparation on the spot. @keyword star_grid: list of Star() models to plot. If star_grid is [], only data are plotted. (default: []) @type star_grid: list[Star()] @keyword cfg: path to the Plotting2.plotCols config file. If default, the hard-coded default plotting options are used. (default: '') @type cfg: string @keyword iterative: add an extra suffix to the filename for each iteratively calculated model, with this number giving the model muber (index in star_grid), 0 if not used. (default: 0) @type iterative: int @keyword no_models: Only show data. (default: 0) @type no_models: bool @keyword fn_add_star: Add the star name to the requested plot filename. (default: 1) @type fn_add_star: bool """ if self.sed is None: print 'No dsed given in Path.dat. Cannot plot SED. Aborting...' return print '***********************************' print '** Creating SED plot.' cfg_dict = Plotting2.readCfg(cfg) if cfg_dict.has_key('no_models'): no_models = cfg_dict['no_models'] if cfg_dict.has_key('fn_add_star'): fn_add_star = bool(cfg_dict['fn_add_star']) if cfg_dict.has_key('filename'): fn_plt = cfg_dict['filename'] del cfg_dict['filename'] else: fn_plt = '' data_labels = dict([(dt,(n,ls)) for n,dt,ls in zip(DataIO.getInputData(path=cc.path.usr,\ keyword='PLOT_NAMES',\ filename='Sed.dat',\ remove_underscore=1),\ DataIO.getInputData(path=cc.path.usr,\ keyword='DATA_TYPES',\ filename='Sed.dat'),\ DataIO.getInputData(path=cc.path.usr,\ keyword='LINE_TYPES',\ filename='Sed.dat'))]) #- filename settings and copying inputfiles to plot output folder if not fn_plt: fn_plt = os.path.join(self.pplot,'SED_%s'%self.star_name) if fn_add_star: fn_plt = '_'.join([fn_plt,self.star_name]) if iterative: fn_plt = fn_plt + '_iterative_%i'%iterative if self.inputfilename <> None: ipfn = os.path.split(self.inputfilename)[1] subprocess.call(['cp ' + self.inputfilename + ' ' + \ os.path.join(self.pplot,ipfn)],\ shell=True) plot_title='SED %s'%self.star_name_plots #- prepare and collect data, keytags and line types keytags = [] data_x = [] data_y = [] data_err = [] line_types = [] for (dt,fn),tdata in sorted([dset for dset in self.sed.data.items() if 'PHOT' not in dset[0][0].upper()]): keytags.append(data_labels[dt][0]) data_x.append(tdata[0]) data_y.append(tdata[1]) #data_err.append(tdata[2]) #-- For now, no error bars for spectra. data_err.append(None) line_types.append(data_labels[dt][1]) for (dt,fn),(w,f,err) in sorted([dset for dset in self.sed.data.items() if 'PHOT' in dset[0][0].upper()]): keytags.append(data_labels[dt][0]) data_x.append(w) data_y.append(f) data_err.append(err) line_types.append(data_labels[dt][1]) #- Collect model data as well as keytags and set line types model_ids_mcm = [s['LAST_MCMAX_MODEL'] for s in star_grid if s['LAST_MCMAX_MODEL']] #- Only if the model_ids list is not empty, MCMax models are available #- Otherwise the ray tracing keyword is unnecessary. if no_models: model_ids_mcm = [] if model_ids_mcm: rt_sed = star_grid[0]['RT_SED'] for model_id in model_ids_mcm: dpath = os.path.join(cc.path.mout,'models',model_id) w,f = MCMax.readModelSpectrum(dpath,rt_sed) data_x.append(w) data_y.append(f) data_err.append(None) keytags.append(model_id.replace('_','\_')) line_types += [0]*len(star_grid) keytags = [tag.replace('#','') for tag in keytags] extra_pars = dict() try: extra_pars['ymax'] = 1.3*max([max(dy) for dy in data_y]) except ValueError: pass try: extra_pars['ymin'] = 0.5*min([min(dy) for dy in data_y]) except ValueError: pass filename = Plotting2.plotCols(x=data_x,y=data_y,yerr=data_err,\ filename=fn_plt,\ figsize=(20,10),number_subplots=1,\ plot_title=plot_title,fontsize_axis=20,\ keytags=keytags,fontsize_title=24,\ linewidth=3,key_location=(0.0,0.75),\ xlogscale=1,transparent=0,cfg=cfg_dict,\ line_types=line_types,ylogscale=0,\ fontsize_ticklabels=20,fontsize_key=18,\ xmin=2,xmax=200,extension='.pdf',\ **extra_pars) print '** Your SED plots can be found at:' print filename print '***********************************'
def plotVisibilities(self,star_grid=[],cfg='',no_models=0,\ fn_add_star=0): """ Plot visibilities as a function of baseline. Wavelengths plotted are what is requested in the ray tracing Includes data preparation on the spot. Data location is that of correlated flux (for the visibilities), but also requires an sed object to retrieve the MIDI spectrum. If one of them is not available, models are be plotted without data. @keyword star_grid: list of Star() models to plot. If star_grid is [], only data are plotted. (default: []) @type star_grid: list[Star()] @keyword cfg: path to the Plotting2.plotCols config file. If default, the hard-coded default plotting options are used. (default: '') @type cfg: string @keyword no_models: Only show data. (default: 0) @type no_models: bool @keyword fn_add_star: Add the star name to the requested plot filename. (default: 1) @type fn_add_star: bool """ if not cc.path.dcflux: print 'No dcflux given in Path.dat. Aborting...' return if not self.sed or 'MIDI' not in self.sed.data_types: print 'No dsed given in Path.dat or no MIDI spectral data found. Aborting.' return print '***********************************' print '** Creating Visibilities plot.' cfg_dict = Plotting2.readCfg(cfg) if cfg_dict.has_key('no_models'): no_models = cfg_dict['no_models'] if cfg_dict.has_key('fn_add_star'): fn_add_star = bool(cfg_dict['fn_add_star']) if cfg_dict.has_key('filename'): fn_plt = cfg_dict['filename'] del cfg_dict['filename'] else: fn_plt = '' #- filename settings and copying inputfiles to plot output folder if not fn_plt: fn_plt = os.path.join(self.pplot,'Visibilities') if fn_add_star: fn_plt = '_'.join([fn_plt,self.star_name]) if self.inputfilename <> None: ipfn = os.path.split(self.inputfilename)[1] subprocess.call(['cp ' + self.inputfilename + ' ' + \ os.path.join(self.pplot,ipfn)],\ shell=True) #-- Read the models. Wavelengths are taken from the ray-tracing output models = [] if not no_models: for s in star_grid: model_id = s['LAST_MCMAX_MODEL'] dpath = os.path.join(cc.path.mout,'models',model_id) model = MCMax.readVisibilities(dpath=dpath,\ fn_vis='basevis01.0.dat') models.append(model) real_models = [model for model in models if model] if not real_models: no_models = 1 else: wavelengths = sorted(real_models[0]['wavelength'].keys()) if no_models: wavelengths = (8.,10.,13.) #-- Grab the MIDI spectrum fn = self.sed.data_filenames[self.sed.data_types.index('MIDI')] midi_flux = self.sed.data[('MIDI',fn)][1] midi_err = self.sed.data[('MIDI',fn)][2] midi_relerr = (midi_err/midi_flux)**2 #-- Select MIDI data. Assumes baseline at the end of the filename. ssd = os.path.join(cc.path.dcflux,self.star_name,\ '_'.join([self.star_name,'MIDI','*.fits'])) files = [os.path.splitext(gi)[0] for gi in glob.glob(ssd)] ggd = dict([(float(gi.split('_')[-1].strip('m')),gi+'.fits') for gi in files]) #-- Collect MIDI data from the fits file and calculate visibilities ddf = dict() for k,v in sorted(ggd.items()): ddf[k] = dict() dfits = pyfits.open(v) #-- Read the wavelength cwave = 1e6*dfits['OI_WAVELENGTH'].data['EFF_WAVE'][::-1] #-- Read flux + err and select the right range cflux = dfits['OI_VIS'].data['VISAMP'][0][::-1] cflux = cflux[(cwave<=13.)*(cwave>=8.)] cflux_err = dfits['OI_VIS'].data['VISAMPERR'][0][::-1] cflux_err = cflux_err[(cwave<=13.)*(cwave>=8.)] #-- The visibilities are correlated flux divided by real flux ddf[k]['y'] = cflux/midi_flux #-- Error propagation cflux_relerr = (cflux_err/cflux)**2 yerr = np.sqrt(midi_relerr + cflux_relerr)*cflux/midi_flux ddf[k]['yerr'] = yerr #-- Wavelength grid ddf[k]['x'] = cwave[(cwave<=13.)*(cwave>=8.)] dfits.close() #-- prepare and collect plot data, keytags and line types data = [] for w in wavelengths: ddict = dict() data.append(ddict) #-- Set the plot x and y bls = [k for k in sorted(ddf.keys())] ddict['x'] = [[bl for bl in bls]] ddict['y'] = [[ddf[bl]['y'][np.argmin(abs(ddf[bl]['x']-w))] for bl in bls]] ddict['yerr'] = [[ddf[bl]['yerr'][np.argmin(abs(ddf[bl]['x']-w))] for bl in bls]] #-- Set limits and labels ddict['labels'] = [('MIDI %s $\\mu$m'%w,0.85,0.9)] if no_models: continue #-- Extract models from the model folders for model in models: ddict['yerr'].append(None) if not model: ddict['x'].append(np.empty(0)) ddict['y'].append(np.empty(0)) continue ddict['x'].append(model['baseline']) ddict['y'].append(model['wavelength'][w]) kwargs = dict() kwargs['keytags'] = ['MIDI'] if not no_models: kwargs['keytags'].extend([s['LAST_MCMAX_MODEL'].replace('_','\_') for s in star_grid]) kwargs['xaxis'] = 'Baseline (m)' kwargs['yaxis'] = 'Visibility' kwargs['dimensions'] = (1,len(data)+1) kwargs['figsize'] = (10,15) kwargs['fontsize_axis'] = 20 kwargs['fontsize_ticklabels'] = 20 kwargs['fontsize_key'] = 18 kwargs['fontsize_label'] = 14 kwargs['linewidth'] = 3 kwargs['cfg'] = cfg_dict kwargs['extension'] = '.pdf' kwargs['hspace'] = 0.3 kwargs['ws_bot'] = 0.01 kwargs['ws_top'] = 0.99 kwargs['ws_left'] = 0.10 kwargs['ws_right'] = 0.98 filename = Plotting2.plotTiles(data=data,filename=fn_plt,**kwargs) print '** Your Correlated Flux plots can be found at:' print filename print '***********************************'
def plotCorrflux(self,star_grid=[],cfg='',no_models=0,fn_add_star=0): """ Plot correlated fluxes with 0, 1 or more models and data. Includes data preparation on the spot. @keyword star_grid: list of Star() models to plot. If star_grid is [], only data are plotted. (default: []) @type star_grid: list[Star()] @keyword cfg: path to the Plotting2.plotCols config file. If default, the hard-coded default plotting options are used. (default: '') @type cfg: string @keyword no_models: Only show data. (default: 0) @type no_models: bool @keyword fn_add_star: Add the star name to the requested plot filename. (default: 1) @type fn_add_star: bool """ if not cc.path.dcflux: print 'No dcflux given in Path.dat. Cannot plot Correlated Fluxes. Aborting...' return print '***********************************' print '** Creating Correlated Fluxes plot.' cfg_dict = Plotting2.readCfg(cfg) if cfg_dict.has_key('no_models'): no_models = cfg_dict['no_models'] if cfg_dict.has_key('fn_add_star'): fn_add_star = bool(cfg_dict['fn_add_star']) if cfg_dict.has_key('filename'): fn_plt = cfg_dict['filename'] del cfg_dict['filename'] else: fn_plt = '' #- filename settings and copying inputfiles to plot output folder if not fn_plt: fn_plt = os.path.join(self.pplot,'CorrFlux') if fn_add_star: fn_plt = '_'.join([fn_plt,self.star_name]) if self.inputfilename <> None: ipfn = os.path.split(self.inputfilename)[1] subprocess.call(['cp ' + self.inputfilename + ' ' + \ os.path.join(self.pplot,ipfn)],\ shell=True) #-- Select MIDI data. Assumes baseline at the end of the filename. ssd = os.path.join(cc.path.dcflux,self.star_name,\ '_'.join([self.star_name,'MIDI','*.fits'])) files = [os.path.splitext(gi)[0] for gi in glob.glob(ssd)] ggd = dict([(float(gi.split('_')[-1].strip('m')),gi+'.fits') for gi in files]) #-- Read the models models = [] if not no_models: for s in star_grid: model_id = s['LAST_MCMAX_MODEL'] dpath = os.path.join(cc.path.mout,'models',model_id) model = MCMax.readVisibilities(dpath=dpath,\ fn_vis='visibility01.0.dat') models.append(model) real_models = [model for model in models if model] if not real_models: no_models = 1 baselines = sorted(ggd.keys()) else: baselines = sorted(real_models[0]['baseline'].keys()) #-- prepare and collect data, keytags and line types data = [] for bl in baselines: ddict = dict() data.append(ddict) #-- Extract data from the fits file if ggd.has_key(bl): dfits = pyfits.open(ggd[bl]) x = 1e6*dfits['OI_WAVELENGTH'].data['EFF_WAVE'][::-1] ddict['x'] = [x] ddict['y'] = [dfits['OI_VIS'].data['VISAMP'][0]][::-1] ddict['yerr'] = [dfits['OI_VIS'].data['VISAMPERR'][0]][::-1] dfits.close() else: ddict['x'] = [] ddict['y'] = [] ddict['yerr'] = [] if no_models: continue #-- Extract models from the model folders for model in models: ddict['yerr'].append(None) if not model: ddict['x'].append(np.empty(0)) ddict['y'].append(np.empty(0)) continue ddict['x'].append(model['wavelength']) ddict['y'].append(model['flux']*model['baseline'][bl]) #-- Set some plot limits ddict['xmin'] = 8 ddict['xmax'] = 13 ddict['ymin'] = -0.1 ddict['labels'] = [('MIDI %.1f m'%bl,0.05,0.9)] #-- Wavelength limits between 8 and 13 micron, limits of the N band # atmospheric transmission. Outside these ranges, the flux is not # relevant ddict['ymax'] = 1.1*max([max(iy[(ix<=13.)*(ix>=8.)]) for ix,iy in zip(ddict['x'],ddict['y']) if iy.size]) kwargs = dict() kwargs['keytags'] = ['MIDI'] if not no_models: kwargs['keytags'].extend([s['LAST_MCMAX_MODEL'].replace('_','\_') for s in star_grid]) kwargs['xaxis'] = '$\lambda$ ($\mu$m)' kwargs['yaxis'] = 'Corr.~FLux (Jy)' kwargs['dimensions'] = (1,len(data)+1) kwargs['figsize'] = (10,15) kwargs['fontsize_axis'] = 20 kwargs['fontsize_ticklabels'] = 20 kwargs['fontsize_key'] = 18 kwargs['fontsize_label'] = 14 kwargs['linewidth'] = 3 kwargs['cfg'] = cfg_dict kwargs['extension'] = '.pdf' kwargs['hspace'] = 0.3 kwargs['ws_bot'] = 0.01 kwargs['ws_top'] = 0.99 kwargs['ws_left'] = 0.10 kwargs['ws_right'] = 0.98 filename = Plotting2.plotTiles(data=data,filename=fn_plt,**kwargs) print '** Your Correlated Flux plots can be found at:' print filename print '***********************************'