示例#1
0
def mergeOpacity(species,lowres='nom_res',highres='high_res'):
    
    '''
    Merge high-res opacities into a grid of low-res opacities.
    
    The wavelength range of the inserted high res opacities is taken from the 
    given high res grid. 
        
    @param species: The dust species for which this is done. This is also the 
                    name of the folder in ~/MCMax/DustOpacities/ that contains
                    the data files.
    @type species: string
    @keyword lowres: The subfolder in ~/MCMax/DustOpacities/species containing
                     the low resolution datafiles.
                   
                     (default: low_res)
    @type lowres: string
    @keyword highres: The subfolder in ~/MCMax/DustOpacities/species containing
                      the high resolution datafiles.
                      
                      (default: high_res)
    @type highres: string
    
    '''
    
    path = os.path.join(cc.path.mopac,species)
    lowres_files = [f 
                    for f in glob(os.path.join(path,lowres,'*')) 
                    if f[-5:] == '.opac']
    highres_files = [f 
                     for f in glob(os.path.join(path,highres,'*')) 
                     if f[-5:] == '.opac']
    files = set([os.path.split(f)[1] for f in lowres_files] + \
                [os.path.split(f)[1] for f in highres_files])
    
    for f in files:
        hdfile = os.path.join(path,highres,f)
        ldfile = os.path.join(path,lowres,f)
        if os.path.isfile(ldfile) and os.path.isfile(hdfile):
            hd = DataIO.readCols(hdfile)
            ld = DataIO.readCols(ldfile)
            hdw = hd[0]
            ldw = ld[0]
            wmin = hdw[0]
            wmax = hdw[-1]
            ld_low = [list(col[ldw<wmin]) for col in ld]
            ld_high = [list(col[ldw>wmax]) for col in ld]
            hd = [list(col) for col in hd]
            merged = [ld_low[i] + hd[i] + ld_high[i] 
                      for i in range(len(hd))]
            DataIO.writeCols(filename=os.path.join(path,f),cols=merged)
示例#2
0
def mergeOpacity(species,lowres='nom_res',highres='high_res'):
    
    '''
    Merge high-res opacities into a grid of low-res opacities.
    
    The wavelength range of the inserted high res opacities is taken from the 
    given high res grid. 
        
    @param species: The dust species for which this is done. This is also the 
                    name of the folder in ~/MCMax/DustOpacities/ that contains
                    the data files.
    @type species: string
    @keyword lowres: The subfolder in ~/MCMax/DustOpacities/species containing
                     the low resolution datafiles.
                   
                     (default: low_res)
    @type lowres: string
    @keyword highres: The subfolder in ~/MCMax/DustOpacities/species containing
                      the high resolution datafiles.
                      
                      (default: high_res)
    @type highres: string
    
    '''
    
    path = os.path.join(cc.path.mopac,species)
    lowres_files = [f 
                    for f in glob(os.path.join(path,lowres,'*')) 
                    if f[-5:] == '.opac']
    highres_files = [f 
                     for f in glob(os.path.join(path,highres,'*')) 
                     if f[-5:] == '.opac']
    files = set([os.path.split(f)[1] for f in lowres_files] + \
                [os.path.split(f)[1] for f in highres_files])
    
    for f in files:
        hdfile = os.path.join(path,highres,f)
        ldfile = os.path.join(path,lowres,f)
        if os.path.isfile(ldfile) and os.path.isfile(hdfile):
            hd = DataIO.readCols(hdfile)
            ld = DataIO.readCols(ldfile)
            hdw = hd[0]
            ldw = ld[0]
            wmin = hdw[0]
            wmax = hdw[-1]
            ld_low = [list(col[ldw<wmin]) for col in ld]
            ld_high = [list(col[ldw>wmax]) for col in ld]
            hd = [list(col) for col in hd]
            merged = [ld_low[i] + hd[i] + ld_high[i] 
                      for i in range(len(hd))]
            DataIO.writeCols(filename=os.path.join(path,f),cols=merged)
示例#3
0
def readModelSpectrum(dpath, rt_spec=1, fn_spec='spectrum45.0.dat'):
    '''
    Read the model output spectrum.
     
    If no ray-tracing is requested or no ray-tracing output is found, the 
    average of the MC spectra is taken.
     
    @param dpath: folder that contains the MCMax outputfiles
    @type dpath: string
    
    @keyword rt_spec: If a ray-traced spectrum is requested
     
                      (default: 1)
    @type rt_spec: bool
    @keyword fn_spec: The filename of the ray-traced spectrum. Typically this 
                      is the default name, but can be different depending on 
                      the ray-tracing angle (inclination) that is used. 
                      Not used if MCSpec are used.
                      
                      (default: spectrum45.0.dat)
    @type fn_spec: str
    
    @return: The wavelength and flux grids (micron,Jy)
    @rtype: (array,array)
     
    '''

    rt_spec = int(rt_spec)
    try:
        if rt_spec:
            dfile = os.path.join(dpath, fn_spec)
            this_data = DataIO.readCols(dfile)
            #- if the lists are not empty
            if list(this_data[0]) and list(this_data[1]):
                w = this_data[0]
                f = this_data[1]
            else:
                raise IOError
        else:
            raise IOError
    except IOError:
        print 'No spectrum was found or ray-tracing is off for ' + \
              'this model. Taking average of theta-grid MCSpectra.'
        dfiles = glob(os.path.join(dpath, 'MCSpec*.dat'))
        w = DataIO.readCols(filename=dfiles[0])[0]
        mcy_list = [DataIO.readCols(f)[1] for f in dfiles]
        f = sum(mcy_list) / len(mcy_list)
    return (w, f)
示例#4
0
    def plotExtinction(self, star_grid=[], models=[], plot_default=1, cfg=''):
        """ 
        Plotting wavelength dependent extinction efficiencies wrt grain size.
        
        This always depends on a star_grid or one created from a list of MCMax 
        model ids.
        
        Plotted are the total efficiencies, including relative weights between 
        the included dust species. This is the input for GASTRoNOoM!
        
        @keyword star_grid: List of Star() instances. If default, model ids 
                            have to be given.
                                  
                            (default: [])
        @type star_grid: list[Star()]
        @keyword models: The model ids, only required if star_grid is []
        
                         (default: [])
        @type models: list[string]
        @keyword cfg: path to the Plotting2.plotCols config file. If default, 
                      the hard-coded default plotting options are used.
                          
                      (default: '')
        @type cfg: string
        
        """

        print '***********************************'
        print '** Plotting Q_ext/a.'
        if not star_grid and not models:
            print 'Input is undefined. Aborting.'
            return
        elif not star_grid and models:
            star_grid = self.makeMCMaxStars(models=models)
        x = []
        y = []
        keys = []
        for star in star_grid:
            try:
                inputfile = os.path.join(cc.path.gdata,
                                         star['TEMDUST_FILENAME'])
                opacities = DataIO.readCols(filename=inputfile)
                x.append(opacities[0])
                y.append(opacities[1])
                keys.append('$Q_\mathrm{ext}/a$ for MCMax %s'\
                            %star['LAST_MCMAX_MODEL'].replace('_','\_'))
            except IOError:
                pass
        filename = os.path.join(self.pplot,'gastronoom_opacities_%s'\
                                %star['LAST_MCMAX_MODEL'])
        title = 'GASTRoNOoM Extinction Efficiencies in %s'\
                 %(self.star_name_plots)
        filename = Plotting2.plotCols(x=x,y=y,cfg=cfg,filename=filename,\
                                      xaxis='$\lambda$ ($\mu$m)',keytags=keys,\
                                      yaxis='$Q_{ext}/a$ (cm$^{-1}$)',\
                                      plot_title=title,key_location=(0.7,0.6),\
                                      xlogscale=1,ylogscale=1,fontsize_key=20)
        print '** The extinction efficiency plot can be found at:'
        print filename
        print '***********************************'
示例#5
0
 def getSphinxConvolution(self,star,fn):
     
     '''
     Read the sphinx convolution and return if it has already been done. 
     
     Returns None if the convolution is not available. 
     
     @param star: The Star() object
     @type star: Star()
     @param fn: The filename of the dataset (band) for which the convolution
                is to be returned.
     @type fn: str
     
     @return: The sphinx convolution result. (wavelength, flux)
     @rtype: array
     
     '''
     
     this_id = star['LAST_PACS_MODEL']
     if not this_id:
         return ([],[])
     fn = os.path.split(fn)[1]
     sphinx_file = os.path.join(cc.path.gout,'stars',self.star_name,\
                               'PACS_results',this_id,'%s_%s'%('sphinx',fn))
     return DataIO.readCols(sphinx_file)
示例#6
0
    def readData(self):
        '''
        Read in data, taking special care of NaNs. 
        
        Four colums are taken as input! wave - contsub - original - continuum
        
        Two columns still works, but may result in errors in other places in 
        the code. 
        
        Data are always read in Jy versus micron, for both SPIRE and PACS.
        
        '''

        self.data_wave_list = []
        self.data_flux_list = []
        self.data_original_list = []
        self.data_continuum_list = []
        for filename in self.data_filenames:
            data = DataIO.readCols(filename=filename, nans=1)
            self.data_wave_list.append(data[0])
            self.data_flux_list.append(data[1])
            if len(data) == 2:
                continue
            self.data_original_list.append(data[2])
            self.data_continuum_list.append(data[3])
示例#7
0
    def readDustInfo(self):

        """
        Read all column densities, min/max temperatures and min/max radii for 
        the species involved in the MCMax model.
        
        Note that the self.coldens dictionary does not give real column 
        densities! This dict merely gives column densities in a prescribed 
        shell with given min and max radius, in order to compare with the H2 
        col density. 
        
        """

        dens = self.star.getDustDensity()
        temp = self.star.getDustTemperature()
        compf = os.path.join(
            cc.path.mcmax, self.star.path_mcmax, "models", self.star["LAST_MCMAX_MODEL"], "composition.dat"
        )
        comp = DataIO.readCols(compf)
        self.rad = comp.pop(0) * self.au
        self.r_outer = self.rad[-1]

        for species in self.star.getDustList():
            # - Save the actual density profile for this dust species, as well
            # - as calculating the full column density of a dust species.
            self.dustfractions[species] = comp.pop(0)
            self.compd[species] = self.dustfractions[species] * dens
            self.fullcoldens[species] = trapz(x=self.rad, y=self.compd[species])
            # - Determine the column density from 90% of the dust species formed
            # - onward, based on the mass fractions!
            # - Not before, because the comparison with H2 must be made,
            # - and this will skew the result if not solely looking at where the
            # - dust has (almost) all been formed.
            # - We also save min amd max radii, for use with the H2 calculation
            a_species = self.star["A_%s" % species]
            maxdens = max(self.compd[species])
            mindens = maxdens * 10 ** (-10)
            radsel = self.rad[(self.dustfractions[species] > 0.9 * a_species) * (self.compd[species] > mindens)]
            denssel = self.compd[species][
                (self.dustfractions[species] > 0.9 * a_species) * (self.compd[species] > mindens)
            ]
            self.coldens[species] = trapz(x=radsel, y=denssel)
            if radsel.size:
                self.r_min_cd[species] = radsel[0]
                self.r_max_cd[species] = radsel[-1]
            else:
                print "Threshold dust mass fraction not reached for %s." % species
                self.r_min_cd[species] = 0
                self.r_max_cd[species] = 0
            # - Determine the actual destruction radius and temperature.
            # - Taken where the density reaches 1% of the maximum density
            # - (not mass fraction).
            self.r_des[species] = self.rad[self.compd[species] > (maxdens * 0.01)][0]
            self.t_des[species] = temp[self.compd[species] > (maxdens * 0.01)][0]

            # - e-10 as limit for minimum is ok, because if shell is 100000 R*
            # - the mass conservation dictates ~ (10^5)^2 = 10^10 (r^2 law)
            # - decrease in density. Shells this big dont occur anyway.
            self.r_max[species] = self.rad[self.compd[species] > mindens][-1]
            self.t_min[species] = temp[self.compd[species] > mindens][-1]
示例#8
0
def updateDustMCMaxDatabase(filename):

    '''
    Update dust filenames in MCMax database with the new OPAC_PATH system. 
    
    @param filename: The file and path to the MCMax database. 
    @type filename: str
    
    '''
    
    i = 0
    new_filename = '%s_new'%(filename)
    
    db_old = Database(filename)
    db_new = Database(new_filename)
    
    path = os.path.join(cc.path.usr,'Dust_updatefile.dat')
    dustfiles = DataIO.readCols(path)
    pfn_old = list(dustfiles[0])
    pfn_new = list(dustfiles[1])
    
    for k,v in db_old.items():
        dd = v['dust_species']
        dd_new = dict()
        for pfn,cont in dd.items():
            try:
                new_key = pfn_new[pfn_old.index(pfn)]
                dd_new[new_key] = cont
            except ValueError:
                dd_new[pfn] = cont
        v['dust_species'] = dd_new
        db_new[k] = v
    db_new.sync()
示例#9
0
 def plotExtinction(self,star_grid=[],models=[],plot_default=1,cfg=''):
     
     """ 
     Plotting wavelength dependent extinction efficiencies wrt grain size.
     
     This always depends on a star_grid or one created from a list of MCMax 
     model ids.
     
     Plotted are the total efficiencies, including relative weights between 
     the included dust species. This is the input for GASTRoNOoM!
     
     @keyword star_grid: List of Star() instances. If default, model ids 
                         have to be given.
                               
                         (default: [])
     @type star_grid: list[Star()]
     @keyword models: The model ids, only required if star_grid is []
     
                      (default: [])
     @type models: list[string]
     @keyword cfg: path to the Plotting2.plotCols config file. If default, 
                   the hard-coded default plotting options are used.
                       
                   (default: '')
     @type cfg: string
     
     """
     
     print '***********************************'
     print '** Plotting Q_ext/a.'
     if not star_grid and not models:
         print 'Input is undefined. Aborting.'
         return      
     elif not star_grid and models:
         star_grid = self.makeMCMaxStars(models=models)
     x = []
     y = []
     keys = []
     for star in star_grid:        
         try:
             inputfile = os.path.join(cc.path.gdata,star['TEMDUST_FILENAME'])
             opacities = DataIO.readCols(filename=inputfile)
             x.append(opacities[0])
             y.append(opacities[1])
             keys.append('$Q_\mathrm{ext}/a$ for MCMax %s'\
                         %star['LAST_MCMAX_MODEL'].replace('_','\_'))
         except IOError: 
             pass
     filename = os.path.join(self.pplot,'gastronoom_opacities_%s'\
                             %star['LAST_MCMAX_MODEL'])
     title = 'GASTRoNOoM Extinction Efficiencies in %s'\
              %(self.star_name_plots)
     filename = Plotting2.plotCols(x=x,y=y,cfg=cfg,filename=filename,\
                                   xaxis='$\lambda$ ($\mu$m)',keytags=keys,\
                                   yaxis='$Q_{ext}/a$ (cm$^{-1}$)',\
                                   plot_title=title,key_location=(0.7,0.6),\
                                   xlogscale=1,ylogscale=1,fontsize_key=20)
     print '** The extinction efficiency plot can be found at:'
     print filename
     print '***********************************'  
示例#10
0
def updateDustMCMaxDatabase(filename):

    """
    Update dust filenames in MCMax database with the new OPAC_PATH system. 
    
    @param filename: The file and path to the MCMax database. 
    @type filename: str
    
    """

    i = 0
    new_filename = "%s_new" % (filename)

    db_old = Database(filename)
    db_new = Database(new_filename)

    path = os.path.join(cc.path.usr, "Dust_updatefile.dat")
    dustfiles = DataIO.readCols(path)
    pfn_old = list(dustfiles[0])
    pfn_new = list(dustfiles[1])

    for k, v in db_old.items():
        dd = v["dust_species"]
        dd_new = dict()
        for pfn, cont in dd.items():
            try:
                new_key = pfn_new[pfn_old.index(pfn)]
                dd_new[new_key] = cont
            except ValueError:
                dd_new[pfn] = cont
        v["dust_species"] = dd_new
        db_new[k] = v
    db_new.sync()
示例#11
0
 def getSphinxConvolution(self,star,fn):
     
     '''
     Read the sphinx convolution and return if it has already been done. 
     
     Returns None if the convolution is not available. 
     
     @param star: The Star() object
     @type star: Star()
     @param fn: The filename of the dataset (band) for which the convolution
                is to be returned.
     @type fn: str
     
     @return: The sphinx convolution result. (wavelength, flux)
     @rtype: array
     
     '''
     
     this_id = star['LAST_PACS_MODEL']
     if not this_id:
         return ([],[])
     fn = os.path.split(fn)[1]
     sphinx_file = os.path.join(cc.path.gout,'stars',self.star_name,\
                               'PACS_results',this_id,'%s_%s'%('sphinx',fn))
     return DataIO.readCols(sphinx_file)
示例#12
0
 def readData(self):
     
     '''
     Read the raw SED data. 
     
     '''
     
     for dt,fn in zip(self.data_types,self.data_filenames):
         data = DataIO.readCols(fn,nans=0)
         #-- Currently, error bars only available for these types of data.
         if 'Photometric' in dt or 'MIDI' in dt or 'Sacha' in dt: 
             #-- Sort MIDI data
             if 'MIDI' in dt: 
                 cdat = [dd[(data[0]<=13.)*(data[0]>=8.)] for dd in data]
                 i = argsort(cdat[0])
                 self.data[(dt,fn)] = (cdat[0][i],cdat[1][i],cdat[2][i])
             else:
                 self.data[(dt,fn)] = (data[0],data[1],data[2])
             if  dt == 'Photometric_IvS':
                 self.photbands = data[3]
                 self.photwave = data[0]
         else:
             #-- Still sorting for PACS. Obsolete when separate bands for 
             #   PACS are available. 
             i = argsort(data[0])
             self.data[(dt,fn)] = (data[0][i],data[1][i])
示例#13
0
    def readData(self):
        '''
        Read the raw SED data. 
        
        '''

        for dt, fn in zip(self.data_types, self.data_filenames):
            data = DataIO.readCols(fn, nans=0)
            #-- Currently, error bars only available for these types of data.
            if 'Photometric' in dt or 'MIDI' in dt or 'Sacha' in dt:
                #-- Sort MIDI data
                if 'MIDI' in dt:
                    cdat = [
                        dd[(data[0] <= 13.) * (data[0] >= 8.)] for dd in data
                    ]
                    i = argsort(cdat[0])
                    self.data[(dt, fn)] = (cdat[0][i], cdat[1][i], cdat[2][i])
                else:
                    self.data[(dt, fn)] = (data[0], data[1], data[2])
                if dt == 'Photometric_IvS':
                    self.photbands = data[3]
                    self.photwave = data[0]
            else:
                #-- Still sorting for PACS. Obsolete when separate bands for
                #   PACS are available.
                i = argsort(data[0])
                self.data[(dt, fn)] = (data[0][i], data[1][i])
示例#14
0
 def readData(self):
     
     '''
     Read in data, taking special care of NaNs. 
     
     Four colums are taken as input! wave - contsub - original - continuum
     
     Two columns still works, but may result in errors in other places in 
     the code. 
     
     Data are always read in Jy versus micron, for both SPIRE and PACS.
     
     '''
     
     self.data_wave_list = [] 
     self.data_flux_list = []
     self.data_original_list = [] 
     self.data_continuum_list = [] 
     for filename in self.data_filenames:
         data = DataIO.readCols(filename=filename,nans=1)
         self.data_wave_list.append(data[0])
         self.data_flux_list.append(data[1])
         if len(data) == 2: 
             continue
         self.data_original_list.append(data[2])
         self.data_continuum_list.append(data[3])
示例#15
0
def readModelSpectrum(dpath,rt_sed=1,fn_spec='spectrum45.0.dat'):
     
    '''
    Read the model output spectrum.
     
    If no ray-tracing is requested or no ray-tracing output is found, the 
    average of the MC spectra is taken.
     
    @param dpath: folder that contains the MCMax outputfiles
    @type dpath: string
    
    @keyword rt_sed: If a ray-traced spectrum is requested
     
                     (default: 1)
    @type rt_sed: bool
    @keyword fn_spec: The filename of the ray-traced spectrum. Typically this 
                      is the default name, but can be different depending on 
                      the ray-tracing angle that is used. 
                      Not used if MCSpec are used.
                      
                      (default: spectrum45.0.dat)
    @type fn_spec: str
    
    @return: The wavelength and flux grids (micron,Jy)
    @rtype: (array,array)
     
    '''
     
    rt_sed = int(rt_sed)
    try:    
        if rt_sed:  
            dfile = os.path.join(dpath,fn_spec)
            this_data = DataIO.readCols(dfile)
            #- if the lists are not empty
            if list(this_data[0]) and list(this_data[1]):    
                w = this_data[0]
                f = this_data[1]
            else: raise IOError
        else: raise IOError                                
    except IOError:
        print 'No spectrum was found or ray-tracing is off for ' + \
              'this model. Taking average of theta-grid MCSpectra.'
        dfiles = glob(os.path.join(dpath,'MCSpec*.dat'))
        w = DataIO.readCols(filename=dfiles[0])[0]
        mcy_list = [DataIO.readCols(f)[1] for f in dfiles]
        f = sum(mcy_list)/len(mcy_list)
    return (w,f)
示例#16
0
    def parseImpact(self):
        ''' 
        Parse sphinx file 1, which includes all the impact parameter info. 
        
        The output is stored in dict self.sph1.
        
        '''

        self.sph1 = dict()
        self.contents['sph1'] = self.sph1
        data = DataIO.readCols(self.filename.replace('*', '1'), start_row=1)
        self.sph1['impact'] = data[0]
        self.sph1['norm_intens'] = data[1]
        self.sph1['weighted_intens'] = data[2]
        self.sph1['sum_intens_p'] = data[3]
        self.sph1['sum_intens'] = data[4]
示例#17
0
def coolingDbRetrieval(path_gastronoom, r_outer=None):

    """    
    Reconstruct a cooling database based on the mline database and the
    GASTRoNOoM inputfiles.
    
    Only works if the water MOLECULE convenience keywords, the MOLECULE R_OUTER
    and/or the MOLECULE ENHANCE_ABUNDANCE_FACTOR keywords were not adapted!
    
    @param path_gastronoom: The path_gastronoom to the output folder
    @type path_gastronoom: string
    
    @keyword r_outer: The outer radius used for the cooling model, regardless
                      of the outer_r_mode parameter.
                      
                      (default: None)
    @type r_outer: float
    
    """

    # -- Convenience path
    cc.path.gout = os.path.join(cc.path.gastronoom, path_gastronoom)

    coolkeys_path = os.path.join(cc.path.aux, "Input_Keywords_Cooling.dat")
    coolkeys = DataIO.readCols(coolkeys_path, make_float=0, make_array=0)[0]
    extra_keys = [
        "ENHANCE_ABUNDANCE_FACTOR",
        "MOLECULE_TABLE",
        "ISOTOPE_TABLE",
        "ABUNDANCE_FILENAME",
        "NUMBER_INPUT_ABUNDANCE_VALUES",
        "KEYWORD_TABLE",
    ]
    coolkeys = [k for k in coolkeys if k not in extra_keys]
    cool_db_path = os.path.join(cc.path.gout, "GASTRoNOoM_cooling_models.db")
    ml_db_path = os.path.join(cc.path.gout, "GASTRoNOoM_mline_models.db")
    subprocess.call(["mv %s %s_backupCoolDbRetrieval" % (cool_db_path, cool_db_path)], shell=True)
    cool_db = Database(db_path=cool_db_path)
    ml_db = Database(db_path=ml_db_path)
    for ml_id in ml_db.keys():
        file_path = os.path.join(cc.path.gout, "models", "gastronoom_%s.inp" % ml_id)
        input_dict = DataIO.readDict(file_path)
        input_dict = dict([(k, v) for k, v in input_dict.items() if k in coolkeys])
        cool_db[ml_id] = input_dict
        if r_outer <> None:
            cool_db[ml_id]["R_OUTER"] = r_outer
    cool_db.sync()
示例#18
0
    def parseImpact(self):

        """ 
        Parse sphinx file 1, which includes all the impact parameter info. 
        
        The output is stored in dict self.sph1.
        
        """

        self.sph1 = dict()
        self.contents["sph1"] = self.sph1
        data = DataIO.readCols(self.filename.replace("*", "1"), start_row=1)
        self.sph1["impact"] = data[0]
        self.sph1["norm_intens"] = data[1]
        self.sph1["weighted_intens"] = data[2]
        self.sph1["sum_intens_p"] = data[3]
        self.sph1["sum_intens"] = data[4]
示例#19
0
def coolingDbRetrieval(path_gastronoom,r_outer=None):
    
    '''    
    Reconstruct a cooling database based on the mline database and the
    GASTRoNOoM inputfiles.
    
    Only works if the water MOLECULE convenience keywords, the MOLECULE R_OUTER
    and/or the MOLECULE ENHANCE_ABUNDANCE_FACTOR keywords were not adapted!
    
    @param path_gastronoom: The path_gastronoom to the output folder
    @type path_gastronoom: string
    
    @keyword r_outer: The outer radius used for the cooling model, regardless
                      of the outer_r_mode parameter.
                      
                      (default: None)
    @type r_outer: float
    
    '''
    
    #-- Convenience path
    cc.path.gout = os.path.join(cc.path.gastronoom,path_gastronoom)
                                
    coolkeys_path = os.path.join(cc.path.aux,'Input_Keywords_Cooling.dat')
    coolkeys = DataIO.readCols(coolkeys_path,make_float=0,make_array=0)[0]
    extra_keys = ['ENHANCE_ABUNDANCE_FACTOR','MOLECULE_TABLE','ISOTOPE_TABLE',\
                  'ABUNDANCE_FILENAME','NUMBER_INPUT_ABUNDANCE_VALUES',\
                  'KEYWORD_TABLE']
    coolkeys = [k for k in coolkeys if k not in extra_keys]
    cool_db_path = os.path.join(cc.path.gout,'GASTRoNOoM_cooling_models.db')
    ml_db_path = os.path.join(cc.path.gout,'GASTRoNOoM_mline_models.db')
    subprocess.call(['mv %s %s_backupCoolDbRetrieval'\
                     %(cool_db_path,cool_db_path)],shell=True)
    cool_db = Database(db_path=cool_db_path)
    ml_db = Database(db_path=ml_db_path)
    for ml_id in ml_db.keys():
        file_path = os.path.join(cc.path.gout,'models',\
                                 'gastronoom_%s.inp'%ml_id)
        input_dict = DataIO.readDict(file_path)
        input_dict = dict([(k,v) for k,v in input_dict.items() 
                                 if k in coolkeys])
        cool_db[ml_id] = input_dict
        if r_outer <> None:
            cool_db[ml_id]['R_OUTER'] = r_outer
    cool_db.sync()
示例#20
0
def readVisibilities(dpath,fn_vis='visibility01.0.dat'):
    
    '''
    Read the model output visibilities, either as function of wavelength or
    baseline. 
     
    @param dpath: folder that contains the MCMax outputfiles
    @type dpath: string
    
    @keyword fn_spec: The filename of the ray-traced visibilities. Typically 
                      this is the default name, but can be different depending 
                      on the inclination (or baseline) that is used. 
                      
                      (default: visibility01.0.dat)
    @type fn_spec: str
    
    @return: A dictionary containing either wavelength or baseline, the flux, 
             and the visibilities for either given baselines or wavelengths
    @rtype: dict
     
    '''
    
    #-- Read file and 
    dfile = os.path.join(dpath,fn_vis)
    if not os.path.isfile(dfile):
        return dict()
    cols, comments = DataIO.readCols(dfile,return_comments=1)
    comments = [comment for comment in comments if comment]
    
    if 'visibility' in fn_vis: 
        xtype = 'wavelength'
        seltype = 'baseline'
    elif 'basevis' in fn_vis: 
        xtype = 'baseline'
        seltype = 'wavelength'
    model = dict()
    model[xtype] = cols[0]
    model['flux'] = cols[1]
    model[seltype] = dict()
    for i,comment in enumerate(comments[2:]):
        val = float(comment.partition(seltype)[2].partition(',')[0])
        model[seltype][val] = cols[2+i]
    return model
示例#21
0
    def readTxt(self):
        ''' 
        Read the txt file. 
        
        Assumes Tmb flux values in K, with respect to velocity. 
                
        '''

        data = DataIO.readCols(filename=self.fn, start_row=0, nans=1)
        if self.fn[-6:] == '.ISPEC':
            del data[0]
            data[0] = data[0] / 1000.
        self['contents']['velocity'] = data[0]
        self['contents']['flux'] = data[1]
        if self['contents']['velocity'][0] > self['contents']['velocity'][-1]:
            self['contents']['velocity'] = self['contents']['velocity'][::-1]
            self['contents']['flux'] = self['contents']['flux'][::-1]
        self['contents']['date_obs'] = 'N.A.'
        self['contents']['vlsr'] = None
示例#22
0
 def readTxt(self):
     
     ''' 
     Read the txt file. 
     
     Assumes Tmb flux values in K, with respect to velocity. 
             
     '''
     
     data = DataIO.readCols(filename=self.filename,start_row=0,nans=1)
     if self.filename[-6:] == '.ISPEC':
         del data[0]
         data[0] = data[0]/1000.
     self.contents['velocity'] = data[0]
     self.contents['flux'] = data[1]
     if self.contents['velocity'][0] > self.contents['velocity'][-1]: 
         self.contents['velocity'] = self.contents['velocity'][::-1]
         self.contents['flux'] = self.contents['flux'][::-1]
     self.contents['date_obs'] = 'N.A.'
     self.contents['vlsr'] = None
示例#23
0
    def readLineFit(self, **kwargs):
        '''
        Read the data from the line fit procedure.
        
        @keyword kwargs: Extra keywords for the readCols method.
                        
                         (default: dict())
        @type kwargs: dict
        
        @return: The line fit columns are returned.
        @rtype: list[array]
        
        '''

        fn = os.path.join(self.path_instrument,self.star_name,\
                          self.path_linefit,'lineFitResults')
        if not self.path_linefit or not os.path.isfile(fn):
            self.linefit = None
            return
        dd = DataIO.readCols(fn, make_array=0, **kwargs)
        return dd
示例#24
0
    def readKappas(self, species):

        """
        Read kappas (cm2/g) and Q_ext/a (cm-1) for a dust species from the 
        MCMax INPUT files. 
        
        This also reads the absorption and scattering kappas separately. 
        
        @param species: The dust species (from Dust.dat)
        @type species: string
                        
        """

        if self.waves.has_key(species):
            return
        try:
            ispecies = self.lspecies.index(species)
        except ValueError:
            print "Species not found in Dust.dat."
            return
        fn = os.path.join(cc.path.mopac, self.lfilenames[ispecies])
        sd = self.lspec_dens[ispecies]
        if fn[-9:] == ".particle":
            part_file = DataIO.readFile(filename=fn, delimiter=" ")
            wav = array([float(q[0]) for q in part_file if len(q) == 4])
            kappa = [
                array([float(q[1]) for q in part_file if len(q) == 4]),
                array([float(q[2]) for q in part_file if len(q) == 4]),
                array([float(q[3]) for q in part_file if len(q) == 4]),
            ]
        else:
            part_file = DataIO.readCols(filename=fn)
            wav = part_file[0]
            kappa = part_file[1:]
        self.spec_dens[species] = sd
        self.fns[species] = fn
        self.waves[species] = wav
        self.kappas[species] = kappa
        self.qext_a[species] = array(kappa) * 4 / 3.0 * sd
示例#25
0
 def parseImpact(self):
     
     ''' 
     Parse sphinx file 1, line intensities at line center (!) as a function 
     of impact parameter. 
     
     The output is stored in dict self['sph1'].
     
     Note that the headers of the sph1 file state the last two columns are
     summed intensities. This is not true! It is the intensity at line 
     center.
     
     '''
     
     
     self['sph1'] = dict()
     data = DataIO.readCols(self.fn.replace('*','1'),start_row=1)
     self['sph1']['p'] = data[0]
     self['sph1']['norm_intens'] = data[1] 
     self['sph1']['weighted_intens'] = data[2] 
     self['sph1']['weighted_intens_p^-2'] = data[3]
     self['sph1']['intens'] = data[4]
示例#26
0
 def readLineFit(self,**kwargs):
     
     '''
     Read the data from the line fit procedure.
     
     @keyword kwargs: Extra keywords for the readCols method.
                     
                      (default: dict())
     @type kwargs: dict
     
     @return: The line fit columns are returned.
     @rtype: list[array]
     
     '''
     
     fn = os.path.join(self.path_instrument,self.star_name,\
                       self.path_linefit,'lineFitResults')
     if not self.path_linefit or not os.path.isfile(fn):
         self.linefit = None
         return
     dd = DataIO.readCols(fn,make_array=0,**kwargs)
     return dd
示例#27
0
 def readKappas(self,species):
     
     """
     Read kappas (cm2/g) and Q_ext/a (cm-1) for a dust species from the 
     MCMax INPUT files. 
     
     This also reads the absorption and scattering kappas separately. 
     
     @param species: The dust species (from Dust.dat)
     @type species: string
                     
     """
     
     if self.waves.has_key(species):
         return
     try:
         ispecies = self.lspecies.index(species)
     except ValueError:
         print 'Species not found in Dust.dat.'
         return
     fn = os.path.join(cc.path.mopac,self.lfilenames[ispecies])
     sd = self.lspec_dens[ispecies]
     if fn[-9:] == '.particle':
         part_file = DataIO.readFile(filename=fn,delimiter=' ') 
         wav = array([float(q[0]) 
                      for q in part_file if len(q) == 4]) 
         kappa = [array([float(q[1]) 
                         for q in part_file if len(q) == 4]),
                  array([float(q[2]) 
                         for q in part_file if len(q) == 4]),
                  array([float(q[3]) 
                         for q in part_file if len(q) == 4])]
     else: 
         part_file = DataIO.readCols(filename=fn)
         wav = part_file[0]
         kappa = part_file[1:]
     self.waves[species] = wav
     self.kappas[species] = kappa
     self.qext_a[species] = array(kappa) * 4/3. * sd
示例#28
0
    def makeDict(self, path=None):
        '''
        Return a dict with molecule string, and other relevant parameters.
        
        @keyword path: If a different path is needed, it can be passed here, 
                       for files. For instance, when making dictionaries for 
                       Molecule() objects in the case of supercomputer copies.
                      
                       (default: None)
        @type path: string
        
        '''

        new_dict = dict([('MOLECULE',str(self).replace('MOLECULE=','')),\
                         ('ITERA',self.itera),\
                         ('ABUN_MOLEC',self.abun_molec),\
                         ('ABUN_MOLEC_RINNER',self.abun_molec_rinner),\
                         ('ABUN_MOLEC_RE', self.abun_molec_re),\
                         ('RMAX_MOLEC',self.rmax_molec),\
                         ('LTE_REQUEST',self.lte_request),\
                         ('OUTER_R_MODE',self.outer_r_mode),\
                         ('USE_COLLIS_RADIAT_SWITCH',self.use_collis_radiat_switch),\
                         ('R_OUTER',self.r_outer)])
        for par,isot in [('RATIO_16O_TO_18O','18O'),\
                         ('RATIO_16O_TO_17O','17O'),\
                         ('RATIO_12C_TO_13C','13C'),\
                         ('OPR','p1H')]:
            if isot in self.molecule:
                new_dict[par] = getattr(self, par.lower())
        if self.dust_to_gas_change_ml_sp:
            new_dict['CHANGE_DUST_TO_GAS_FOR_ML_SP'] \
                    = 1
            new_dict['DUST_TO_GAS_CHANGE_ML_SP'] \
                    = self.dust_to_gas_change_ml_sp
        if self.enhance_abundance_factor:
            new_dict['ENHANCE_ABUNDANCE_FACTOR'] \
                    = self.enhance_abundance_factor
            new_dict['NUMBER_INPUT_ABUNDANCE_VALUES'] \
                    = len(DataIO.readCols(filename=self.abundance_filename)[0])
            new_dict['KEYWORD_TABLE'] = 1
            new_dict['MOLECULE_TABLE'] \
                    = self.molecule_full[:self.molecule_full.index('.')]
            new_dict['ISOTOPE_TABLE'] = self.molecule_full
            if path <> None:
                new_dict['ABUNDANCE_FILENAME'] \
                   = '"%s"'%os.path.join(path,\
                            os.path.split(self.abundance_filename)[1])
            else:
                new_dict['ABUNDANCE_FILENAME'] \
                   = '"%s"'%self.abundance_filename
        if self.set_keyword_change_abundance:
            new_dict['SET_KEYWORD_CHANGE_ABUNDANCE'] \
                    = self.set_keyword_change_abundance
            if path <> None:
                new_dict['CHANGE_FRACTION_FILENAME'] \
                   = '"%s"'%os.path.join(path,\
                            os.path.split(self.change_fraction_filename)[1])
            else:
                new_dict['CHANGE_FRACTION_FILENAME'] \
                   = '"%s"'%self.change_fraction_filename
        if self.set_keyword_change_temperature:
            new_dict['SET_KEYWORD_CHANGE_TEMPERATURE'] \
                    = self.set_keyword_change_temperature
            if path <> None:
                new_dict['NEW_TEMPERATURE_FILENAME'] \
                   = '"%s"'%os.path.join(path,\
                            os.path.split(self.new_temperature_filename)[1])
            else:
                new_dict['NEW_TEMPERATURE_FILENAME'] \
                   = '"%s"'%self.new_temperature_filename
        if self.starfile:
            new_dict['USE_STARFILE'] = 1
            if path <> None:
                starfile = os.path.join(path, os.path.split(self.starfile)[1])
                new_dict['STARFILE'] = '"%s"' % starfile
            else:
                new_dict['STARFILE'] = '"%s"' % self.starfile
        return new_dict
示例#29
0
    def __read(self):
        '''
        Read the MOLECULE_radiat file and set a dictionary for the instance
        with all the information. 
        
        Done on creation of an instance of the class.
        
        '''

        radiat = DataIO.readCols(filename=self.filename, make_array=0)[0]
        self.dict = {}
        #- The starting indices for the next step are determined incrementally,
        #- with a right term added + arbitrary number of zeroes at the end of
        #- each step in the loop
        step_sizes = [
            self.molecule.nline, self.molecule.nline,
            self.molecule.ny_up + self.molecule.ny_low,
            self.molecule.ny_up + self.molecule.ny_low, self.molecule.nline,
            self.molecule.nline
        ]
        if sum(step_sizes) == len(radiat):
            nozeroes = True
        else:
            nozeroes = False

        #- The ending indices are always the starting index + this index
        pars = ['EINSTEIN', 'FREQUENCY', 'WEIGHT', 'ENERGY', 'LOWER', 'UPPER']
        i = 0
        for delta, par in zip(step_sizes, pars):
            #- grab list from input
            self.dict[par] = radiat[i:i + delta]
            #- Determine starting index of the next list
            try:
                #- if no zeroes present: don't look for zeroes
                #- (important cuz an energy level may be zero)
                i = nozeroes \
                        and (i + delta) \
                        or DataIO.findNumber(i+delta,radiat)
            except IndexError:
                if par == 'UPPER':
                    #- This is the last step, you expect an index error here,
                    #- since it's the end of the file
                    if not (len(radiat) == i + delta
                            or radiat[i + delta] == 0):
                        #- If the next number is zero, or if the file ends here,
                        #- everything is OK: Move on, otherwise raise error.
                        raise IndexError("When reading %s,"%self.filename + \
                                         "the level indices were " + \
                                         "formatted incorrectly. Aborting...")
                else:
                    #- Too early to get this error! Aborting!
                    raise IndexError('When reading %s,'%self.filename + \
                                     'file ended too soon before'+\
                                     ' definition of all parameters. '+\
                                     'Aborting...')

        #- if zeroes are present, one ofthe energy levels may also be really zero
        #- check this and correct for it here.
        if self.dict['ENERGY'][-1] == 0.0:
            self.dict['ENERGY'] = self.dict['ENERGY'][0:-1]
            self.dict['ENERGY'][0:0] = [0.0]
        #Another check up...
        if sum(step_sizes) != sum([len(self.dict[par]) for par in pars]):
            raise IndexError('Fewer or more entries found for all the ' + \
                             'parameters in %s than expected. Aborting...'\
                             %self.filename)
        self.dict['LOWER'] = [int(x) for x in self.dict['LOWER']]
        self.dict['UPPER'] = [int(x) for x in self.dict['UPPER']]
示例#30
0
def fitLP(filename=None,lprof=None,theory=0,show=0,cfg='',convert_ms_kms=0,\
          vary_pars=['vexp'],i_vexp=15.0,i_gamma=1.0,do_gauss=0):
    '''
    Fit a line profile with a soft parabola, and a Gaussian component if 
    required. 
    
    The method automatically checks if a second component is needed (eg an 
    extra absorption component). An estimate of the expansion velocity (width 
    of the profile) and an improved guess of the vlsr are given. 
    
    A guess for the gas terminal velocity is returned, as well as its error and
    the fitted profile (sp/gaussian, and if applicable extra gaussian and the 
    full fit). 
    
    @keyword filename: The filename to the data file of the line profile. If 
                       None a line profile object is expected. 
                       
                       (default: None)
    @type filename: string
    @keyword lprof: A line profile object (LPDataReader or inheriting classes)
                    If None, a filename is expected! If not None, the results
                    are saved in this object as well as returned upon method 
                    call
                    
                    (default: None)
    @type lprof: LPDataReader()
    @keyword convert_ms_kms: Convert velocity grid from m/s to km/s.
    
                             (default: 0)
    @type convert_ms_kms: bool
    @keyword theory: If theoretical profile, and filename is given, set vlsr to
                     0 and read two columns. lprof not relevant if True.
                     
                     (default: 0)
    @type theory: bool
    @keyword vary_pars: The soft parabola parameters varied (can only be vexp
                        or gamma for now). The initial values for parameters
                        listed here are not used. If 'gamma' is requested, a 
                        reasonable guess for i_vexp when calling the method 
                        will improve the fitting results. This is done for the 
                        first guess only! If a Gaussian absorption is present
                        improving these first guesses won't make much of a 
                        difference. However, the first guess value for gamma
                        is still used. Vexp is always varied if absorption is 
                        present.
                        
                        (default: ['vexp'])                        
    @type vary_pars: list[string]
    @keyword i_vexp: The initial guess for the expansion velocity. Not relevant
                     if vexp is included in vary_pars.
                     
                     (default: 15.0)
    @type i_vexp: float
    @keyword i_gamma: The initial guess for the gamma parameter of soft parab.
                      Not relevant if gamma is included in vary_pars.
                      
                      (default: 1.0)
    @type i_gamma: float
    @keyword do_gauss: Force a Gaussian fit regardless of soft parabola fit 
                       results. Still does the soft parabola fit first to allow
                       for comparison of parameters.
                        
                       (default: 0)
    @type do_gauss: bool
    @keyword show: Show the results of the fit
                    
                   (default: 0)
    @type show: bool
    
    @return: dictionary including [vexp,evexp,gamma,egamma,fitprof,gaussian,\
             fullfit,dintint,fgintint] 
    @rtype: dict[float,float,float,float,funclib.Function(),\
                 funclib.Function(),funclib.Function()]
    
    '''

    print '*******************************************'
    if theory and filename <> None:
        d = DataIO.readCols(filename=filename)
        vel = d[0]
        flux = d[1]
        vlsr = 0.0
    else:
        if filename is None:
            filename = lprof.filename
        print '** Fitting line profile in %s.' % filename
        if lprof is None:
            lprof = readLineProfile(filename)
        vel = lprof.getVelocity()
        flux = lprof.getFlux()
        vel = vel[-np.isnan(flux)]
        flux = flux[-np.isnan(flux)]
        vlsr = lprof.getVlsr()

    if convert_ms_kms:
        vel = vel / 1000.
    #-- Initial values: [peak tmb,vlsr,vexp,gamma]
    #   For the central peak value, get a first guess from the data
    #   Attempt multiple vexp values and return the best fitting case.
    #   The initial values are given, with an arbitrary value for the vexp key
    i_mid = argmin(np.abs(vel - vlsr))
    peak = mean(flux[i_mid - 2:i_mid + 3])

    #-- Vary vexp or gamma if requested. If not requested i_vexp or i_gamma are
    #   used.
    #   Multiple values for gamma are tried and the best fitting model
    #   is then chosen based on the relative error of the fitted gamma.
    if 'gamma' in vary_pars:
        igammas = array([-0.5, -0.1, 0.1, 0.5, 1.0, 2.0, 4.0])
        firstguess = varyInitialFit(vel,flux,[peak,vlsr,i_vexp,0.0],index=3,\
                                    values=igammas,vary_window=1,vary=[1,1,1,1],\
                                    function=funclib.soft_parabola)
        i_gamma = firstguess.get_parameters()[0][3]
    #-- varyInitialFit adapts the velocity window itself. No more
    #   assumptions needed for the expansion velocity
    ivexps = array([50., 40., 30., 25., 20., 15., 10.])
    if 'vexp' in vary_pars:
        firstguess = varyInitialFit(vel,flux,[peak,vlsr,0.,i_gamma],index=2,\
                                    values=ivexps,vary_window=1,vary=[1,1,1,1],\
                                    function=funclib.soft_parabola)

    vexp = abs(firstguess.get_parameters()[0][2])
    window = 2.
    print 'First guess fit, using a soft parabola:'
    print firstguess.param2str(accuracy=5)

    #-- If vexp > 100, replace with 50. This value is unrealistic, and might be
    #   improved with an extra Gaussian. If not, it will be replaced with a
    #   full Gaussian fit anyway
    if vexp > 100: vexp = 50.
    #-- Check whether irregularities are present in the profile.
    #   Initial parameters for a gaussian are returned if true.
    #   For this, a broad selection is made of the profile, to allow for a
    #   decent noise determination outside the line profile
    keep = np.abs(vel - vlsr) <= (2 * window * vexp)
    velsel, fluxsel = vel[keep], flux[keep]
    include_gauss = checkLPShape(velsel,
                                 fluxsel,
                                 vlsr,
                                 vexp,
                                 window,
                                 show=show)

    #-- Do the fit of the line again, including an extra gaussian if
    #   irregularities are present.
    if include_gauss <> None:
        #-- fit soft para model + gaussian
        #   1. Set up new soft parabola for several guesses of vexp
        ivexps = list(ivexps)
        initial = [peak, vlsr, 0., i_gamma]
        all_init = [[p] * len(ivexps) for i, p in enumerate(initial) if i != 2]
        all_init.insert(2, ivexps)
        functions = [funclib.soft_parabola() for i in ivexps]
        [
            ff.setup_parameters(values=initi)
            for ff, initi in zip(functions, zip(*all_init))
        ]
        #   2. setup gaussian
        gaussians = [funclib.gauss() for ff in functions]
        #   initial guesses assuming an interstellar absorption line from the
        #   checkLPShape method
        [
            gg.setup_parameters(values=include_gauss,
                                vary=[True, True, True, False])
            for gg in gaussians
        ]
        #   3. combine soft para + gaussian, and minimize fit
        mymodels = [
            fit.Model(functions=[ff, gg])
            for ff, gg in zip(functions, gaussians)
        ]
        [fit.minimize(vel[np.abs(vel-vlsr)<=(init[2]*1.5)],\
                      flux[np.abs(vel-vlsr)<=(init[2]*1.5)],\
                      mymodel)
         for mymodel,init in zip(mymodels,zip(*all_init))]
        #   4. Select the best fitting result based on the error on vexp
        mymodels = [fg for fg in mymodels if fg.get_parameters()[1][2] != 0.]
        functions = [
            ff for fg, ff in zip(mymodels, functions)
            if fg.get_parameters()[1][2] != 0.
        ]
        gaussians = [
            gg for fg, gg in zip(mymodels, gaussians)
            if fg.get_parameters()[1][2] != 0.
        ]
        fitvalues = array([fg.get_parameters()[0][2] for fg in mymodels])
        fiterrors = array([fg.get_parameters()[1][2] for fg in mymodels])
        mymodel = mymodels[argmin(abs(fiterrors / fitvalues))]
        finalfit = functions[argmin(abs(fiterrors / fitvalues))]
        gaussian = gaussians[argmin(abs(fiterrors / fitvalues))]
        print 'Improved fit, including extra Gaussian:'
        print mymodel.param2str(accuracy=5)
    else:
        #-- if gamma is requested to be varied, allow another iteration on
        #   gamma with the best vexp guess we already have.
        if 'gamma' in vary_pars:
            finalfit = varyInitialFit(vel,flux,[peak,vlsr,vexp,0.0],\
                                      index=3,values=igammas,vary_window=1,\
                                      function=funclib.soft_parabola,\
                                      vary=[True,True,True,True])
            print 'Final fit with soft parabola, second gamma iteration:'
            print finalfit.param2str(accuracy=5)
        #-- firstguess is best we can do at the moment
        else:
            finalfit = firstguess

    #-- If the relative error on vexp is larger than 30%, usually something
    #   funky is going on in the emission line. Try a Gaussian instead.
    fvlsr = finalfit.get_parameters()[0][1]
    fevlsr = finalfit.get_parameters()[1][1]
    vexp = abs(finalfit.get_parameters()[0][2])
    evexp = abs(finalfit.get_parameters()[1][2])
    gamma = finalfit.get_parameters()[0][3]
    egamma = finalfit.get_parameters()[1][3]
    #-- Gamma has to be positive. If it isnt, dont bother with Gaussian
    #   (double peaked line profile will not be fitted well with a Gaussian!)
    if (evexp/vexp > 0.40 and gamma > 0) or (evexp/vexp > 0.20 and vexp> 30.) \
            or do_gauss:
        #-- Go back to default window to try a Gaussian fit
        #keep = np.abs(vel-vlsr)<=(80)
        #velselg,fluxselg = vel[keep],flux[keep]
        do_gauss = 1
        include_gauss = None
        #-- FWHM is twice vexp!
        sigmas = 2 * ivexps / (2. * sqrt(2. * log(2.)))
        finalfit = varyInitialFit(vel,flux,[peak,vlsr,0.,0.],index=2,\
                                  values=sigmas,function=funclib.gauss,\
                                  vary_window=1,vary=[True,True,True,False])
        vexp = abs(
            finalfit.get_parameters()[0][2]) * (2. * sqrt(2. * log(2.))) / 2.
        evexp = abs(
            finalfit.get_parameters()[1][2]) * (2. * sqrt(2. * log(2.))) / 2.
        fvlsr = finalfit.get_parameters()[0][1]
        fevlsr = finalfit.get_parameters()[1][1]
        gamma, egamma = None, None
        window = 3.
        print 'Improved fit, using a gaussian instead of soft parabola:'
        print finalfit.param2str(accuracy=5)

    #-- Compute numerical integrations.
    #   After fitting, window for integration should be 0.6*window. vexp is
    #   not expected to be too small anymore as in checkLPShape
    keep = np.abs(vel - vlsr) <= (0.6 * window * vexp)
    velsel = vel[keep]
    flux_first = firstguess.evaluate(velsel)
    flux_final = finalfit.evaluate(velsel)
    dimb = trapz(y=flux[keep], x=velsel)
    fi_final = trapz(y=flux_final, x=velsel)
    print('I_mb (emission line data): %f'\
          %dimb)
    print('I_mb (SP -- initial guess): %f'\
          %trapz(y=flux_first,x=velsel))
    print('I_mb (SP -- final guess): %f'\
          %fi_final)
    if include_gauss <> None:
        fitted_flux = mymodel.evaluate(velsel)
        print('I_mb (SP + Gauss fit): %f'\
              %trapz(y=fitted_flux,x=velsel))
    print('Final v_exp guess: %.4f +/- %.4f km/s' % (vexp, evexp))
    if gamma <> None:
        print('Final gamma guess: %.4f +/- %.4f' % (gamma, egamma))
    print('Final vlsr guess: %.4f +/- %.4f' % (fvlsr, fevlsr))
    fwhm = getLPDataFWHM(lprof)
    print('The FWHM is %.2f km/s.' % (fwhm))

    #-- plot
    if show or cfg:
        plt.clf()
        #-- improve velocity window for plotting
        keep = np.abs(vel - vlsr) <= (1.5 * window * vexp)
        velsel, fluxsel = vel[keep], flux[keep]
        vel_highres = np.linspace(velsel[0], velsel[-1], 10000)
        flux_final_highres = finalfit.evaluate(vel_highres)
        flux_first_highres = firstguess.evaluate(vel_highres)
        if include_gauss <> None:
            flux_full_highres = mymodel.evaluate(vel_highres)
        if show:
            plt.step(velsel,fluxsel,'-r',where='mid',lw=3,\
                     label='Observed profile')
            plt.plot(vel_highres,flux_first_highres,'b-',lw=3,\
                     label='First guess')
            plt.plot(vel_highres,flux_final_highres,'g--',lw=3,\
                     label='Improved guess')
            if include_gauss <> None:
                plt.plot(vel_highres,flux_full_highres,'g-',lw=2,\
                         label='Full fit (including Gaussian)')
            leg = plt.legend(loc='best', fancybox=True)
            leg.get_frame().set_alpha(0.5)
            plt.show()
        if cfg:
            pf = '%s_fitted_%s'%(do_gauss and 'gaussFit' or 'SPFit',\
                                 os.path.split(filename)[1])
            keytags = ['Observed profile', 'Improved guess']
            line_types = [
                '-r',
                '-b',
            ]
            x = [velsel, vel_highres]
            y = [fluxsel, flux_final_highres]
            if include_gauss <> None:
                line_types.append('g--')
                x.append(vel_highres)
                y.append(flux_full_highres)
                keytags.append('Full fit (including Gaussian)')
            pf = Plotting2.plotCols(x=x,y=y,filename=pf,cfg=cfg,linewidth=5,\
                                    yaxis='$T_\mathrm{mb}\ (\mathrm{K})$',\
                                    xaxis='$v (\mathrm{km}/\mathrm{s})$',\
                                    keytags=keytags,line_types=line_types,\
                                    histoplot=[0])
            print 'Your figure can be found at %s .' % pf
    #-- Collecting all relevant results and returning.
    results = dict()
    #-- If a Gaussian was used for the main profile fit
    results['do_gauss'] = do_gauss
    #-- Fitted parameters and errors
    results['vlsr'] = fvlsr
    results['evlsr'] = fevlsr
    results['vexp'] = vexp
    results['evexp'] = evexp
    results['fwhm'] = fwhm
    #-- Gamma is None if no soft parabola was fitted
    results['gamma'] = gamma
    results['egamma'] = egamma

    #-- Integrated line strengths: main line fit, data themselves, fit window
    results['fgintint'] = fi_final
    results['dintint'] = dimb
    results['intwindow'] = window * 0.6

    #-- Saving parameters for later evaluation. Full fit is accessible by
    #   making the functions separately and setting pars, then using fit.Model
    results['fitprof'] = (do_gauss and 'gauss' or 'soft_parabola',\
                          list(finalfit.get_parameters()[0]))
    if include_gauss <> None:
        results['fitabs'] = ('gauss', list(gaussian.get_parameters()[0]))
    else:
        results['fitabs'] = None

    return results
示例#31
0
    def readDustInfo(self):
        """
        Read all column densities, min/max temperatures and min/max radii for 
        the species involved in the MCMax model.
        
        Note that the self.coldens dictionary does not give real column 
        densities! This dict merely gives column densities in a prescribed 
        shell with given min and max radius, in order to compare with the H2 
        col density. 
        
        """

        dens = self.star.getDustDensity()
        temp = self.star.getDustTemperature()
        compf = os.path.join(cc.path.mcmax,self.star.path_mcmax,'models',\
                             self.star['LAST_MCMAX_MODEL'],'composition.dat')
        comp = DataIO.readCols(compf)
        self.rad = comp.pop(0) * self.au
        self.r_outer = self.rad[-1]

        for species in self.star.getDustList():
            #- Save the actual density profile for this dust species, as well
            #- as calculating the full column density of a dust species.
            self.dustfractions[species] = comp.pop(0)
            self.compd[species] = self.dustfractions[species] * dens
            self.fullcoldens[species] = trapz(x=self.rad,
                                              y=self.compd[species])
            #- Determine the column density from 90% of the dust species formed
            #- onward, based on the mass fractions!
            #- Not before, because the comparison with H2 must be made,
            #- and this will skew the result if not solely looking at where the
            #- dust has (almost) all been formed.
            #- We also save min amd max radii, for use with the H2 calculation
            a_species = self.star['A_%s' % species]
            maxdens = max(self.compd[species])
            mindens = maxdens * 10**(-10)
            radsel = self.rad[(self.dustfractions[species]>0.9*a_species)*\
                              (self.compd[species]>mindens)]
            denssel = self.compd[species]\
                                [(self.dustfractions[species]>0.9*a_species)*\
                                 (self.compd[species]>mindens)]
            self.coldens[species] = trapz(x=radsel, y=denssel)
            if radsel.size:
                self.r_min_cd[species] = radsel[0]
                self.r_max_cd[species] = radsel[-1]
            else:
                print 'Threshold dust mass fraction not reached for %s.' % species
                self.r_min_cd[species] = 0
                self.r_max_cd[species] = 0
            #- Determine the actual destruction radius and temperature.
            #- Taken where the density reaches 1% of the maximum density
            #- (not mass fraction).
            self.r_des[species] = self.rad[self.compd[species] > (maxdens *
                                                                  0.01)][0]
            self.t_des[species] = temp[self.compd[species] > (maxdens *
                                                              0.01)][0]

            #- e-10 as limit for minimum is ok, because if shell is 100000 R*
            #- the mass conservation dictates ~ (10^5)^2 = 10^10 (r^2 law)
            #- decrease in density. Shells this big dont occur anyway.
            self.r_max[species] = self.rad[self.compd[species] > mindens][-1]
            self.t_min[species] = temp[self.compd[species] > mindens][-1]
示例#32
0
def fitLP(
    filename=None,
    lprof=None,
    theory=0,
    show=0,
    cfg="",
    convert_ms_kms=0,
    vary_pars=["vexp"],
    i_vexp=15.0,
    i_gamma=1.0,
    do_gauss=0,
):

    """
    Fit a line profile with a soft parabola, and a Gaussian component if 
    required. 
    
    The method automatically checks if a second component is needed (eg an 
    extra absorption component). An estimate of the expansion velocity (width 
    of the profile) and an improved guess of the vlsr are given. 
    
    A guess for the gas terminal velocity is returned, as well as its error and
    the fitted profile (sp/gaussian, and if applicable extra gaussian and the 
    full fit). 
    
    @keyword filename: The filename to the data file of the line profile. If 
                       None a line profile object is expected. 
                       
                       (default: None)
    @type filename: string
    @keyword lprof: A line profile object (LPDataReader or inheriting classes)
                    If None, a filename is expected! If not None, the results
                    are saved in this object as well as returned upon method 
                    call
                    
                    (default: None)
    @type lprof: LPDataReader()
    @keyword convert_ms_kms: Convert velocity grid from m/s to km/s.
    
                             (default: 0)
    @type convert_ms_kms: bool
    @keyword theory: If theoretical profile, and filename is given, set vlsr to
                     0 and read two columns. lprof not relevant if True.
                     
                     (default: 0)
    @type theory: bool
    @keyword vary_pars: The soft parabola parameters varied (can only be vexp
                        or gamma for now). The initial values for parameters
                        listed here are not used. If 'gamma' is requested, a 
                        reasonable guess for i_vexp when calling the method 
                        will improve the fitting results. This is done for the 
                        first guess only! If a Gaussian absorption is present
                        improving these first guesses won't make much of a 
                        difference. However, the first guess value for gamma
                        is still used. Vexp is always varied if absorption is 
                        present.
                        
                        (default: ['vexp'])                        
    @type vary_pars: list[string]
    @keyword i_vexp: The initial guess for the expansion velocity. Not relevant
                     if vexp is included in vary_pars.
                     
                     (default: 15.0)
    @type i_vexp: float
    @keyword i_gamma: The initial guess for the gamma parameter of soft parab.
                      Not relevant if gamma is included in vary_pars.
                      
                      (default: 1.0)
    @type i_gamma: float
    @keyword do_gauss: Force a Gaussian fit regardless of soft parabola fit 
                       results. Still does the soft parabola fit first to allow
                       for comparison of parameters.
                        
                       (default: 0)
    @type do_gauss: bool
    @keyword show: Show the results of the fit
                    
                   (default: 0)
    @type show: bool
    
    @return: dictionary including [vexp,evexp,gamma,egamma,fitprof,gaussian,\
             fullfit,dintint,fgintint] 
    @rtype: dict[float,float,float,float,funclib.Function(),\
                 funclib.Function(),funclib.Function()]
    
    """

    print "*******************************************"
    if theory and filename <> None:
        d = DataIO.readCols(filename=filename)
        vel = d[0]
        flux = d[1]
        vlsr = 0.0
    else:
        if filename is None:
            filename = lprof.filename
        print "** Fitting line profile in %s." % filename
        if lprof is None:
            lprof = readLineProfile(filename)
        vel = lprof.getVelocity()
        flux = lprof.getFlux()
        vel = vel[-np.isnan(flux)]
        flux = flux[-np.isnan(flux)]
        vlsr = lprof.getVlsr()

    if convert_ms_kms:
        vel = vel / 1000.0
    # -- Initial values: [peak tmb,vlsr,vexp,gamma]
    #   For the central peak value, get a first guess from the data
    #   Attempt multiple vexp values and return the best fitting case.
    #   The initial values are given, with an arbitrary value for the vexp key
    i_mid = argmin(np.abs(vel - vlsr))
    peak = mean(flux[i_mid - 2 : i_mid + 3])

    # -- Vary vexp or gamma if requested. If not requested i_vexp or i_gamma are
    #   used.
    #   Multiple values for gamma are tried and the best fitting model
    #   is then chosen based on the relative error of the fitted gamma.
    if "gamma" in vary_pars:
        igammas = array([-0.5, -0.1, 0.1, 0.5, 1.0, 2.0, 4.0])
        firstguess = varyInitialFit(
            vel,
            flux,
            [peak, vlsr, i_vexp, 0.0],
            index=3,
            values=igammas,
            vary_window=1,
            vary=[1, 1, 1, 1],
            function=funclib.soft_parabola,
        )
        i_gamma = firstguess.get_parameters()[0][3]
    # -- varyInitialFit adapts the velocity window itself. No more
    #   assumptions needed for the expansion velocity
    ivexps = array([50.0, 40.0, 30.0, 25.0, 20.0, 15.0, 10.0])
    if "vexp" in vary_pars:
        firstguess = varyInitialFit(
            vel,
            flux,
            [peak, vlsr, 0.0, i_gamma],
            index=2,
            values=ivexps,
            vary_window=1,
            vary=[1, 1, 1, 1],
            function=funclib.soft_parabola,
        )

    vexp = abs(firstguess.get_parameters()[0][2])
    window = 2.0
    print "First guess fit, using a soft parabola:"
    print firstguess.param2str(accuracy=5)

    # -- If vexp > 100, replace with 50. This value is unrealistic, and might be
    #   improved with an extra Gaussian. If not, it will be replaced with a
    #   full Gaussian fit anyway
    if vexp > 100:
        vexp = 50.0
    # -- Check whether irregularities are present in the profile.
    #   Initial parameters for a gaussian are returned if true.
    #   For this, a broad selection is made of the profile, to allow for a
    #   decent noise determination outside the line profile
    keep = np.abs(vel - vlsr) <= (2 * window * vexp)
    velsel, fluxsel = vel[keep], flux[keep]
    include_gauss = checkLPShape(velsel, fluxsel, vlsr, vexp, window, show=show)

    # -- Do the fit of the line again, including an extra gaussian if
    #   irregularities are present.
    if include_gauss <> None:
        # -- fit soft para model + gaussian
        #   1. Set up new soft parabola for several guesses of vexp
        ivexps = list(ivexps)
        initial = [peak, vlsr, 0.0, i_gamma]
        all_init = [[p] * len(ivexps) for i, p in enumerate(initial) if i != 2]
        all_init.insert(2, ivexps)
        functions = [funclib.soft_parabola() for i in ivexps]
        [ff.setup_parameters(values=initi) for ff, initi in zip(functions, zip(*all_init))]
        #   2. setup gaussian
        gaussians = [funclib.gauss() for ff in functions]
        #   initial guesses assuming an interstellar absorption line from the
        #   checkLPShape method
        [gg.setup_parameters(values=include_gauss, vary=[True, True, True, False]) for gg in gaussians]
        #   3. combine soft para + gaussian, and minimize fit
        mymodels = [fit.Model(functions=[ff, gg]) for ff, gg in zip(functions, gaussians)]
        [
            fit.minimize(
                vel[np.abs(vel - vlsr) <= (init[2] * 1.5)], flux[np.abs(vel - vlsr) <= (init[2] * 1.5)], mymodel
            )
            for mymodel, init in zip(mymodels, zip(*all_init))
        ]
        #   4. Select the best fitting result based on the error on vexp
        mymodels = [fg for fg in mymodels if fg.get_parameters()[1][2] != 0.0]
        functions = [ff for fg, ff in zip(mymodels, functions) if fg.get_parameters()[1][2] != 0.0]
        gaussians = [gg for fg, gg in zip(mymodels, gaussians) if fg.get_parameters()[1][2] != 0.0]
        fitvalues = array([fg.get_parameters()[0][2] for fg in mymodels])
        fiterrors = array([fg.get_parameters()[1][2] for fg in mymodels])
        mymodel = mymodels[argmin(abs(fiterrors / fitvalues))]
        finalfit = functions[argmin(abs(fiterrors / fitvalues))]
        gaussian = gaussians[argmin(abs(fiterrors / fitvalues))]
        print "Improved fit, including extra Gaussian:"
        print mymodel.param2str(accuracy=5)
    else:
        # -- if gamma is requested to be varied, allow another iteration on
        #   gamma with the best vexp guess we already have.
        if "gamma" in vary_pars:
            finalfit = varyInitialFit(
                vel,
                flux,
                [peak, vlsr, vexp, 0.0],
                index=3,
                values=igammas,
                vary_window=1,
                function=funclib.soft_parabola,
                vary=[True, True, True, True],
            )
            print "Final fit with soft parabola, second gamma iteration:"
            print finalfit.param2str(accuracy=5)
        # -- firstguess is best we can do at the moment
        else:
            finalfit = firstguess

    # -- If the relative error on vexp is larger than 30%, usually something
    #   funky is going on in the emission line. Try a Gaussian instead.
    fvlsr = finalfit.get_parameters()[0][1]
    fevlsr = finalfit.get_parameters()[1][1]
    vexp = abs(finalfit.get_parameters()[0][2])
    evexp = abs(finalfit.get_parameters()[1][2])
    gamma = finalfit.get_parameters()[0][3]
    egamma = finalfit.get_parameters()[1][3]
    # -- Gamma has to be positive. If it isnt, dont bother with Gaussian
    #   (double peaked line profile will not be fitted well with a Gaussian!)
    if (evexp / vexp > 0.40 and gamma > 0) or (evexp / vexp > 0.20 and vexp > 30.0) or do_gauss:
        # -- Go back to default window to try a Gaussian fit
        # keep = np.abs(vel-vlsr)<=(80)
        # velselg,fluxselg = vel[keep],flux[keep]
        do_gauss = 1
        include_gauss = None
        # -- FWHM is twice vexp!
        sigmas = 2 * ivexps / (2.0 * sqrt(2.0 * log(2.0)))
        finalfit = varyInitialFit(
            vel,
            flux,
            [peak, vlsr, 0.0, 0.0],
            index=2,
            values=sigmas,
            function=funclib.gauss,
            vary_window=1,
            vary=[True, True, True, False],
        )
        vexp = abs(finalfit.get_parameters()[0][2]) * (2.0 * sqrt(2.0 * log(2.0))) / 2.0
        evexp = abs(finalfit.get_parameters()[1][2]) * (2.0 * sqrt(2.0 * log(2.0))) / 2.0
        fvlsr = finalfit.get_parameters()[0][1]
        fevlsr = finalfit.get_parameters()[1][1]
        gamma, egamma = None, None
        window = 3.0
        print "Improved fit, using a gaussian instead of soft parabola:"
        print finalfit.param2str(accuracy=5)

    # -- Compute numerical integrations.
    #   After fitting, window for integration should be 0.6*window. vexp is
    #   not expected to be too small anymore as in checkLPShape
    keep = np.abs(vel - vlsr) <= (0.6 * window * vexp)
    velsel = vel[keep]
    flux_first = firstguess.evaluate(velsel)
    flux_final = finalfit.evaluate(velsel)
    dimb = trapz(y=flux[keep], x=velsel)
    fi_final = trapz(y=flux_final, x=velsel)
    print ("I_mb (emission line data): %f" % dimb)
    print ("I_mb (SP -- initial guess): %f" % trapz(y=flux_first, x=velsel))
    print ("I_mb (SP -- final guess): %f" % fi_final)
    if include_gauss <> None:
        fitted_flux = mymodel.evaluate(velsel)
        print ("I_mb (SP + Gauss fit): %f" % trapz(y=fitted_flux, x=velsel))
    print ("Final v_exp guess: %.4f +/- %.4f km/s" % (vexp, evexp))
    if gamma <> None:
        print ("Final gamma guess: %.4f +/- %.4f" % (gamma, egamma))
    print ("Final vlsr guess: %.4f +/- %.4f" % (fvlsr, fevlsr))
    fwhm = getLPDataFWHM(lprof)
    print ("The FWHM is %.2f km/s." % (fwhm))

    # -- plot
    if show or cfg:
        plt.clf()
        # -- improve velocity window for plotting
        keep = np.abs(vel - vlsr) <= (1.5 * window * vexp)
        velsel, fluxsel = vel[keep], flux[keep]
        vel_highres = np.linspace(velsel[0], velsel[-1], 10000)
        flux_final_highres = finalfit.evaluate(vel_highres)
        flux_first_highres = firstguess.evaluate(vel_highres)
        if include_gauss <> None:
            flux_full_highres = mymodel.evaluate(vel_highres)
        if show:
            plt.step(velsel, fluxsel, "-r", where="mid", lw=3, label="Observed profile")
            plt.plot(vel_highres, flux_first_highres, "b-", lw=3, label="First guess")
            plt.plot(vel_highres, flux_final_highres, "g--", lw=3, label="Improved guess")
            if include_gauss <> None:
                plt.plot(vel_highres, flux_full_highres, "g-", lw=2, label="Full fit (including Gaussian)")
            leg = plt.legend(loc="best", fancybox=True)
            leg.get_frame().set_alpha(0.5)
            plt.show()
        if cfg:
            pf = "%s_fitted_%s" % (do_gauss and "gaussFit" or "SPFit", os.path.split(filename)[1])
            keytags = ["Observed profile", "Improved guess"]
            line_types = ["-r", "-b"]
            x = [velsel, vel_highres]
            y = [fluxsel, flux_final_highres]
            if include_gauss <> None:
                line_types.append("g--")
                x.append(vel_highres)
                y.append(flux_full_highres)
                keytags.append("Full fit (including Gaussian)")
            pf = Plotting2.plotCols(
                x=x,
                y=y,
                filename=pf,
                cfg=cfg,
                linewidth=5,
                yaxis="$T_\mathrm{mb}\ (\mathrm{K})$",
                xaxis="$v (\mathrm{km}/\mathrm{s})$",
                keytags=keytags,
                line_types=line_types,
                histoplot=[0],
            )
            print "Your figure can be found at %s ." % pf
    # -- Collecting all relevant results and returning.
    results = dict()
    # -- If a Gaussian was used for the main profile fit
    results["do_gauss"] = do_gauss
    # -- Fitted parameters and errors
    results["vlsr"] = fvlsr
    results["evlsr"] = fevlsr
    results["vexp"] = vexp
    results["evexp"] = evexp
    results["fwhm"] = fwhm
    # -- Gamma is None if no soft parabola was fitted
    results["gamma"] = gamma
    results["egamma"] = egamma

    # -- Integrated line strengths: main line fit, data themselves, fit window
    results["fgintint"] = fi_final
    results["dintint"] = dimb
    results["intwindow"] = window * 0.6

    # -- Saving parameters for later evaluation. Full fit is accessible by
    #   making the functions separately and setting pars, then using fit.Model
    results["fitprof"] = (do_gauss and "gauss" or "soft_parabola", list(finalfit.get_parameters()[0]))
    if include_gauss <> None:
        results["fitabs"] = ("gauss", list(gaussian.get_parameters()[0]))
    else:
        results["fitabs"] = None

    return results
示例#33
0
    def makeDict(self,path=None,in_progress=0):
        
        '''
        Return a dict with molecule string, and other relevant parameters.
        
        @keyword path: If a different path is needed, it can be passed here, 
                       for files. For instance, when making dictionaries for 
                       Molecule() objects in the case of supercomputer copies.
                      
                       (default: None)
        @type path: string
        @keyword in_progress: add an extra dict entry "IN_PROGRESS" if the 
                              molecule is still being calculated somewhere.
                              
                              (default: 0)
        @type in_progress: bool
        
        @return: The molecule dictionary including all relevant, defining 
                 information
        @rtype: dict()
        
        '''
        
        dd = dict([('MOLECULE',str(self).replace('MOLECULE=','')),\
                   ('ITERA',self.itera),\
                   ('ABUN_MOLEC',self.abun_molec),\
                   ('ABUN_MOLEC_RINNER',self.abun_molec_rinner),\
                   ('ABUN_MOLEC_RE', self.abun_molec_re),\
                   ('RMAX_MOLEC',self.rmax_molec),\
                   ('LTE_REQUEST',self.lte_request),\
                   ('OUTER_R_MODE',self.outer_r_mode),\
                   ('USE_COLLIS_RADIAT_SWITCH',self.use_collis_radiat_switch),\
                   ('R_OUTER',self.r_outer),\
                   ('USE_NO_MASER_OPTION',self.use_no_maser_option),\
                   ('USE_MASER_IN_SPHINX',self.use_maser_in_sphinx),\
                   ('FEHLER',self.fehler),\
                   ('XDEX',self.xdex),\
                   ('N_FREQ',self.n_freq),\
                   ('START_APPROX',self.start_approx),\
                   ('USE_FRACTION_LEVEL_CORR',self.use_fraction_level_corr),\
                   ('FRACTION_LEVEL_CORR',self.fraction_level_corr),\
                   ('NUMBER_LEVEL_MAX_CORR',self.number_level_max_corr)
                   ])
        
        for par,isot in [('RATIO_16O_TO_18O','18O'),\
                         ('RATIO_16O_TO_17O','17O'),\
                         ('RATIO_12C_TO_13C','13C'),\
                         ('OPR','p1H')]:
            if isot in self.molecule:
                dd[par] = getattr(self,par.lower())
        if self.dust_to_gas_change_ml_sp:
            dd['CHANGE_DUST_TO_GAS_FOR_ML_SP'] = 1
            dd['DUST_TO_GAS_CHANGE_ML_SP'] = self.dust_to_gas_change_ml_sp

        if self.enhance_abundance_factor:
            dd['ENHANCE_ABUNDANCE_FACTOR'] = self.enhance_abundance_factor
            niav = len(DataIO.readCols(filename=self.abundance_filename)[0])
            dd['NUMBER_INPUT_ABUNDANCE_VALUES'] = niav
            dd['KEYWORD_TABLE'] = 1
            moltab = self.molecule_full[:self.molecule_full.index('.')]
            dd['MOLECULE_TABLE'] = moltab 
            dd['ISOTOPE_TABLE'] = self.molecule_full
            if not path is None:
                afn = os.path.join(path,\
                                   os.path.split(self.abundance_filename)[1])
            else:
                afn = self.abundance_filename
            dd['ABUNDANCE_FILENAME'] = '"{}"'.format(afn)

        if self.set_keyword_change_abundance:
            dd['SET_KEYWORD_CHANGE_ABUNDANCE'] \
                            = self.set_keyword_change_abundance
            if not path is None:
                cffn = os.path.join(path,\
                                os.path.split(self.change_fraction_filename)[1])
            else:
                cffn = self.change_fraction_filename
            dd['CHANGE_FRACTION_FILENAME'] = '"{}"'.format(cffn)

        if self.set_keyword_change_temperature:
            dd['SET_KEYWORD_CHANGE_TEMPERATURE'] \
                            = self.set_keyword_change_temperature
            if not path is None:
                tfn = os.path.join(path,\
                                os.path.split(self.new_temperature_filename)[1])
            else:
                tfn = self.new_temperature_filename
            dd['NEW_TEMPERATURE_FILENAME'] = '"{}"'.format(tfn)

        if self.starfile:
            dd['USE_STARFILE'] = 1
            if not path is None:
                sfn = os.path.join(path,os.path.split(self.starfile)[1])
                
            else:
                sfn = self.starfile
            dd['STARFILE'] = '"{}"'.format(sfn)
        
        if int(in_progress):
            dd['IN_PROGRESS'] = 1   

        return dd        
示例#34
0
 def makeDict(self,path=None):
     
     '''
     Return a dict with molecule string, and other relevant parameters.
     
     @keyword path: If a different path is needed, it can be passed here, 
                    for files. For instance, when making dictionaries for 
                    Molecule() objects in the case of supercomputer copies.
                   
                    (default: None)
     @type path: string
     
     '''
     
     new_dict = dict([('MOLECULE',str(self).replace('MOLECULE=','')),\
                      ('ITERA',self.itera),\
                      ('ABUN_MOLEC',self.abun_molec),\
                      ('ABUN_MOLEC_RINNER',self.abun_molec_rinner),\
                      ('ABUN_MOLEC_RE', self.abun_molec_re),\
                      ('RMAX_MOLEC',self.rmax_molec),\
                      ('LTE_REQUEST',self.lte_request),\
                      ('OUTER_R_MODE',self.outer_r_mode),\
                      ('USE_COLLIS_RADIAT_SWITCH',self.use_collis_radiat_switch),\
                      ('R_OUTER',self.r_outer)])
     for par,isot in [('RATIO_16O_TO_18O','18O'),\
                      ('RATIO_16O_TO_17O','17O'),\
                      ('RATIO_12C_TO_13C','13C'),\
                      ('OPR','p1H')]:
         if isot in self.molecule:
             new_dict[par] = getattr(self,par.lower())
     if self.dust_to_gas_change_ml_sp:
         new_dict['CHANGE_DUST_TO_GAS_FOR_ML_SP'] \
                 = 1
         new_dict['DUST_TO_GAS_CHANGE_ML_SP'] \
                 = self.dust_to_gas_change_ml_sp
     if self.enhance_abundance_factor:
         new_dict['ENHANCE_ABUNDANCE_FACTOR'] \
                 = self.enhance_abundance_factor
         new_dict['NUMBER_INPUT_ABUNDANCE_VALUES'] \
                 = len(DataIO.readCols(filename=self.abundance_filename)[0])
         new_dict['KEYWORD_TABLE'] = 1
         new_dict['MOLECULE_TABLE'] \
                 = self.molecule_full[:self.molecule_full.index('.')]
         new_dict['ISOTOPE_TABLE'] = self.molecule_full
         if path <> None:
              new_dict['ABUNDANCE_FILENAME'] \
                 = '"%s"'%os.path.join(path,\
                          os.path.split(self.abundance_filename)[1])
         else:
              new_dict['ABUNDANCE_FILENAME'] \
                 = '"%s"'%self.abundance_filename
     if self.set_keyword_change_abundance:
         new_dict['SET_KEYWORD_CHANGE_ABUNDANCE'] \
                 = self.set_keyword_change_abundance
         if path <> None:
              new_dict['CHANGE_FRACTION_FILENAME'] \
                 = '"%s"'%os.path.join(path,\
                          os.path.split(self.change_fraction_filename)[1])
         else:
              new_dict['CHANGE_FRACTION_FILENAME'] \
                 = '"%s"'%self.change_fraction_filename
     if self.set_keyword_change_temperature:
         new_dict['SET_KEYWORD_CHANGE_TEMPERATURE'] \
                 = self.set_keyword_change_temperature
         if path <> None:
              new_dict['NEW_TEMPERATURE_FILENAME'] \
                 = '"%s"'%os.path.join(path,\
                          os.path.split(self.new_temperature_filename)[1])
         else:
              new_dict['NEW_TEMPERATURE_FILENAME'] \
                 = '"%s"'%self.new_temperature_filename
     if self.starfile:
         new_dict['USE_STARFILE'] = 1
         if path <> None:
             starfile = os.path.join(path,os.path.split(self.starfile)[1])
             new_dict['STARFILE'] = '"%s"'%starfile
         else:
             new_dict['STARFILE'] = '"%s"'%self.starfile
     return new_dict