示例#1
0
class TestLevel():

    g = 2
    E = 3
    level = atomic_transition.Level(g=g,E=E,number=1)
    
    def test_LTE_level_pop(self):
        T = 50
        Z = 3
        lte_level_pop = self.level.LTE_level_pop(Z=Z,T=T)
        assert lte_level_pop == self.g*np.exp(-self.E/(constants.k*T))/Z
        shape = (5,5)
        T_array = np.ones(shape)*T
        Z_array = np.ones(shape)*Z
        lte_level_pop_array = self.level.LTE_level_pop(Z=Z_array,T=T_array)
        assert lte_level_pop_array.shape == shape
        assert np.all(lte_level_pop==lte_level_pop_array)
示例#2
0
class TestTransition():

    up = atomic_transition.Level(g=1,E=1,number=1)
    low = atomic_transition.Level(g=1,E=0,number=0)
    line_profile_cls = atomic_transition.SquareLineProfile
    A21 = 1
    radiative_transition = atomic_transition.RadiativeTransition(
                             up=up,low=low,A21=A21)
    width_v = 1*constants.kilo
    K21_data=np.array((2,1,4,6,3))
    Tkin_data=np.array((1,2,3,4,5))
    coll_transition = atomic_transition.CollisionalTransition(
                            up=up,low=low,K21_data=K21_data,Tkin_data=Tkin_data)
    test_emission_line = atomic_transition.EmissionLine(
                              up=up,low=low,A21=A21,
                              line_profile_cls=line_profile_cls,
                              width_v=width_v)

    def test_transition(self):
        with pytest.raises(AssertionError):
            atomic_transition.Transition(up=self.low,low=self.up)

    def test_emission_line_constructor(self):
        assert self.test_emission_line.nu0 == self.test_emission_line.line_profile.nu0

    def test_constructor_from_radiative_transition(self):
        emission_line = atomic_transition.EmissionLine.from_radiative_transition(
                               radiative_transition=self.radiative_transition,
                               line_profile_cls=self.line_profile_cls,
                               width_v=self.width_v)
        assert emission_line.nu0 == self.radiative_transition.nu0
        assert emission_line.B12 == self.radiative_transition.B12

    def test_coll_coeffs(self):
        Tkin_interp = np.array((self.Tkin_data[0],self.Tkin_data[-1]))
        coeff = self.coll_transition.coeffs(Tkin_interp)['K21']
        expected_coeff = np.array((self.K21_data[0],self.K21_data[-1]))
        assert np.allclose(coeff,expected_coeff,atol=0)
        intermediate_temp = np.mean(self.Tkin_data[:2])
        intermediate_coeff = self.coll_transition.coeffs(intermediate_temp)['K21']
        boundaries = np.sort(self.K21_data[:2])
        assert boundaries[0] <= intermediate_coeff <= boundaries[1]

    @pytest.mark.filterwarnings('ignore:invalid value','ignore:divide by zero')
    def test_Tex(self):
        assert self.radiative_transition.Tex(x1=0,x2=0) == 0
        assert self.radiative_transition.Tex(x1=1,x2=0) == 0
        assert self.radiative_transition.Tex(x1=0.5,x2=0) == 0

    def tau_nu(self):
        nu = np.ones((2,4,7))*50
        N1 = 1
        N2 = 3
        tau_nu = self.test_emission_line.tau_nu(N1=N1,N2=N2,nu=nu)
        assert tau_nu.shape == nu.shape
        tau_nu_array = self.test_emission_line.tau_nu_array(N1=N1,N2=N2)
        tau_nu_array_explicit = self.test_emission_line.tau_nu(
                                   N1=N1,N2=N2,
                                   nu=self.test_emission_line.line_profile.nu_array)
        assert np.all(tau_nu_array==tau_nu_array_explicit)
        
示例#3
0
def read(datafilepath):
    '''
    Read a LAMDA data file.

    Reads a LAMDA data file and returns the data in the form of a dictionary.
    The LAMDA database can be found at http://home.strw.leidenuniv.nl/~moldata/molformat.html

    Parameters
    ----------
    datafilepath : str
        path to the file

    Returns
    -------
    dict
        Dictionary containing the data read from the file. The dictionary has the
        following keys:
        
        - 'levels': list of levels (instances of the Level class)

        - 'radiative transitions': list of radiative transitions (instances of RadiativeTransition class)

        - 'collisional transitions': dict, containing lists of instances of the CollisionalTransition class for each collision partner appearing in the file

        The elements of these lists are in the order they appear in the file
    '''
    #identifiers used in the LAMDA database files:
    LAMDA_coll_ID = {'1':'H2','2':'para-H2','3':'ortho-H2','4':'e',
                     '5':'H','6':'He','7':'H+'}
    datafile = open(datafilepath,'r')
    levels = []
    rad_transitions = []
    coll_transitions = {}
    for i,line in enumerate(datafile):
        if i<5:
            continue
        if is_comment(line):
            continue
        if line=='' or line=='\n':
            continue
        if i == 5:
            n_levels = int(line)
            continue
        if 6 < i <= 6+n_levels:
            leveldata = [float(string) for string in line.split()[:3]]
            #transforming energy from cm-1 to J; level numbers starting from 0:
            lev = atomic_transition.Level(
                        g=leveldata[2],
                        E=constants.c*constants.h*leveldata[1]/constants.centi,
                        number=int(leveldata[0])-1)
            levels.append(lev)
            continue
        if i == 8+n_levels:
            n_rad_transitions = int(line)
            continue
        if 9+n_levels < i <= 9+n_levels+n_rad_transitions:
            radtransdata = [float(string) for string in line.split()]
            up = next(level for level in levels if level.number==radtransdata[1]-1)
            low = next(level for level in levels if level.number==radtransdata[2]-1)
            rad_trans = atomic_transition.RadiativeTransition(
                                             up=up,low=low,A21=radtransdata[3])
            rad_transitions.append(rad_trans)
            continue
        if i == 11+n_levels+n_rad_transitions:
            coll_partner_offset = 0
            continue
        if i == 13+n_levels+n_rad_transitions + coll_partner_offset:
            coll_ID = LAMDA_coll_ID[line[0]]
            coll_transitions[coll_ID] = []
            continue
        if i == 15+n_levels+n_rad_transitions + coll_partner_offset:
            n_coll_transitions = int(line)
            continue
        if i == 17+n_levels+n_rad_transitions + coll_partner_offset:
            continue #this lines contains the number of temperature elements
        if i == 19+n_levels+n_rad_transitions + coll_partner_offset:
            coll_temperatures = np.array([float(string) for string in line.split()])
            continue
        if 20+n_levels+n_rad_transitions+coll_partner_offset < i <=\
             20+n_levels+n_rad_transitions+coll_partner_offset+n_coll_transitions:
            coll_trans_data = [float(string) for string in line.split()]
            up = next(level for level in levels if level.number==coll_trans_data[1]-1)
            low = next(level for level in levels if level.number==coll_trans_data[2]-1)
            K21_data = np.array(coll_trans_data[3:])*constants.centi**3
            coll_trans = atomic_transition.CollisionalTransition(
                                  up=up,low=low,K21_data=K21_data,
                                  Tkin_data=coll_temperatures)
            coll_transitions[coll_ID].append(coll_trans)
            if i == 20+n_levels+n_rad_transitions+coll_partner_offset+n_coll_transitions:
                coll_partner_offset += 9+n_coll_transitions
                continue
    datafile.close()
    return {'levels':levels,'radiative transitions':rad_transitions,
            'collisional transitions':coll_transitions}
示例#4
0
def read(datafilepath, read_frequencies, read_quantum_numbers=False):
    '''
    Read a LAMDA data file.

    Reads a LAMDA data file and returns the data in the form of a dictionary.
    The LAMDA database can be found at http://home.strw.leidenuniv.nl/~moldata/molformat.html

    Parameters
    ----------
    datafilepath : str
        path to the file

    read_frequencies : bool
        Read the radiative transition frequencies from the file rather than computing
        them from the level energies. This can be useful since frequencies are sometimes
        given with more significant digits. However, the LAMDA standard does not
        require a file to list the frequencies.

    read_quantum_numbers : bool
        Read the quantum numbers from the file. The LAMDA standard does not
        require a file to list quantum numbers though.

    Returns
    -------
    dict
        Dictionary containing the data read from the file. The dictionary has the
        following keys:
        
        - 'levels': list of levels (instances of the Level class)

        - 'radiative transitions': list of radiative transitions (instances of RadiativeTransition class)

        - 'collisional transitions': dict, containing lists of instances of the CollisionalTransition class for each collision partner appearing in the file

        - 'quantum numbers': list containing quantum number string for all levels. Empty if read_quantum_numbers=False

        The elements of these lists are in the order they appear in the file
    '''
    #identifiers used in the LAMDA database files:
    LAMDA_coll_ID = {
        '1': 'H2',
        '2': 'para-H2',
        '3': 'ortho-H2',
        '4': 'e',
        '5': 'H',
        '6': 'He',
        '7': 'H+'
    }
    datafile = open(datafilepath, 'r')
    levels = []
    rad_transitions = []
    coll_transitions = {}
    quantum_numbers = []
    comment_offset = 0
    for i, line in enumerate(datafile):
        if is_comment(line) or line == '' or line == '\n':
            comment_offset += 1
            continue
        if i == 0 + comment_offset:
            continue
        if i == 1 + comment_offset:
            continue
        if i == 2 + comment_offset:
            n_levels = int(line)
            continue
        if 3 + comment_offset <= i < 3 + comment_offset + n_levels:
            line_entries = line.split()
            leveldata = [float(string) for string in line_entries[:3]]
            assert int(leveldata[0]) == i-2-comment_offset,\
                                     'level numeration not consistent'
            #transforming energy from cm-1 to J; level numbers starting from 0:
            lev = atomic_transition.Level(g=leveldata[2],
                                          E=constants.c * constants.h *
                                          leveldata[1] / constants.centi,
                                          number=int(leveldata[0]) - 1)
            levels.append(lev)
            if read_quantum_numbers:
                quantum_numbers.append(line_entries[3])
            continue
        if i == 3 + comment_offset + n_levels:
            n_rad_transitions = int(line)
            continue
        if 4 + comment_offset + n_levels <= i < 4 + comment_offset + n_levels + n_rad_transitions:
            radtransdata = [float(string) for string in line.split()]
            up = next(level for level in levels
                      if level.number == radtransdata[1] - 1)
            low = next(level for level in levels
                       if level.number == radtransdata[2] - 1)
            rad_trans_kwargs = {'up': up, 'low': low, 'A21': radtransdata[3]}
            if read_frequencies:
                rad_trans_kwargs['nu0'] = radtransdata[4] * constants.giga
            rad_trans = atomic_transition.RadiativeTransition(
                **rad_trans_kwargs)
            rad_transitions.append(rad_trans)
            continue
        if i == 4 + comment_offset + n_levels + n_rad_transitions:
            coll_partner_offset = 0
            continue
        if i == 5 + comment_offset + n_levels + n_rad_transitions + coll_partner_offset:
            coll_ID = LAMDA_coll_ID[line[0]]
            coll_transitions[coll_ID] = []
            continue
        if i == 6 + comment_offset + n_levels + n_rad_transitions + coll_partner_offset:
            n_coll_transitions = int(line)
            continue
        if i == 7 + comment_offset + n_levels + n_rad_transitions + coll_partner_offset:
            continue  #this lines contains the number of temperature elements
        if i == 8 + comment_offset + n_levels + n_rad_transitions + coll_partner_offset:
            coll_temperatures = np.array(
                [float(string) for string in line.split()])
            continue
        last_coll_trans_i = 9+comment_offset+n_levels+n_rad_transitions\
                               +coll_partner_offset+n_coll_transitions-1
        if 9+comment_offset+n_levels+n_rad_transitions+coll_partner_offset <= i <=\
                 last_coll_trans_i:
            coll_trans_data = [float(string) for string in line.split()]
            up = next(level for level in levels
                      if level.number == coll_trans_data[1] - 1)
            low = next(level for level in levels
                       if level.number == coll_trans_data[2] - 1)
            K21_data = np.array(coll_trans_data[3:]) * constants.centi**3
            coll_trans = atomic_transition.CollisionalTransition(
                up=up, low=low, K21_data=K21_data, Tkin_data=coll_temperatures)
            coll_transitions[coll_ID].append(coll_trans)
            if i == last_coll_trans_i:
                coll_partner_offset += 4 + n_coll_transitions
                continue
    datafile.close()
    return {
        'levels': levels,
        'radiative transitions': rad_transitions,
        'collisional transitions': coll_transitions,
        'quantum numbers': quantum_numbers
    }