示例#1
0
    def _do_load_h(self, h, filename):
        r = 0  # counts rows of file
        ii = 0
        species = None
        flag_break = False

        try:
            while True:
                s = h.readline().strip()
                if len(s) == 0:
                    break

                # linelistCN1214V130710.dat
                #
                # Mol vup vlow JLow branch gf       wavenumber  exc (eV) transition (V=violet, R=red)
                # 0   1   2    3    5      6        7
                #---BEGIN SAMPLE---
                #CN1 11 03 034 +  R1   0.4853E-07  40369.070  1.020 V
                #CN1 11 03 035 +  R1   0.5286E-07  40359.670  1.036 V
                #CN1 11 03 036 +  R1   0.5757E-07  40349.879  1.052 V
                #---END SAMPLE---

                tmp = s.split()
                species = self.molecules[tmp[0]]

                line = PlezMolecularLine()

                line.Jl = None
                line.vl = int(tmp[1])
                line.v2l = int(tmp[2])
                line.J2l = float(tmp[3])
                line.lambda_ = 1 / float(
                    tmp[7]) * 1e8  # we assume the wavenumber is in 1/cm
                line.branch = tmp[5]

                species.lines.append(line)

                r += 1
                ii += 1
                if ii == _PROGRESS_INDICATOR_PERIOD:
                    # a99.get_python_logger().info(
                    #      "Loading '{}': {}".format(filename, a99.format_progress(r, num_lines)))
                    ii = 0

        except Exception as e:
            raise RuntimeError("Error around %d%s row of file '%s': \"%s\"" %
                               (r + 1, a99.ordinal_suffix(r + 1), filename,
                                a99.str_exc(e))) from e
示例#2
0
    def _do_load_h(self, h, filename, num_lines=0):
        r = 0  # counts rows of file
        ii = 0
        try:
            self.lines = []
            while True:
                s = h.readline().strip("\n")
                if len(s) == 0:
                    break
                """
                KuruczMolLineOld1 = namedtuple("KuruczMolLineOld1",
                              ["lambda_", "J2l", "Jl", "state2l", "v2l", "spin2l", "statel", "vl",
                               "spinl", ])

                """

                line = KuruczMolLineOld1(
                    float(s[0:9]),
                    float(s[9:15]),
                    float(s[15:21]),
                    s[22:23],
                    int(s[23:25]),
                    int(s[26:27]),
                    s[28:29],
                    int(s[29:31]),
                    int(s[32:33]),
                )

                self.lines.append(line)
                r += 1
                ii += 1
                if ii == _PROGRESS_INDICATOR_PERIOD:
                    a99.get_python_logger().info("Loading '{}': {}".format(
                        filename, a99.format_progress(r, num_lines)))
                    ii = 0

        except Exception as e:
            raise RuntimeError("Error around %d%s row of file '%s': \"%s\"" %
                               (r + 1, a99.ordinal_suffix(r + 1), filename,
                                a99.str_exc(e))) from e
示例#3
0
    def _do_load(self, filename):
        """Clears internal lists and loads from file."""

        with open(filename, "r") as h:

            r = 0  # counts rows of file
            edict = {
            }  # links atomic symbols with Atom objects created (key is atomic symbol)
            try:
                while True:
                    line = AtomicLine()

                    # (EE)(I) --whitespace-- (float) --ignored...--
                    temp = a99.str_vector(h)
                    elem, s_ioni = temp[0][:-1], temp[0][-1]
                    line.lambda_ = float(temp[1])
                    elem = pyfant.adjust_atomic_symbol(elem)
                    key = elem + s_ioni  # will gb.py elements by this key
                    if key in edict:
                        a = edict[key]
                    else:
                        a = edict[key] = Atom()
                        a.elem = elem
                        a.ioni = int(s_ioni)
                        self.atoms.append(a)
                    a.lines.append(line)
                    r += 1

                    [line.kiex, line.algf, line.ch, line.gr, line.ge, line.zinf, line.abondr, finrai] = \
                        a99.float_vector(h)
                    r += 1
                    # last element is end-of-file flag "finrai"
                    if finrai == 1:
                        break
            except Exception as e:
                raise type(e)(("Error around %d%s row of file '%s'" %
                               (r + 1, a99.ordinal_suffix(r + 1), filename)) +
                              ": " + str(e)).with_traceback(sys.exc_info()[2])
示例#4
0
    def _do_load_h(self, h, filename, num_lines=0):
        r = 0  # counts rows of file
        ii = 0
        try:
            self.lines = []
            while True:
                s = h.readline().strip("\n")
                if len(s) == 0:
                    break

                line = KuruczMolLineOld(
                    float(s[0:10]),
                    float(s[10:15]),
                    float(s[15:20]),
                    int(s[20:22]),
                    int(s[22:24]),
                    s[24:25],
                    int(s[25:27]),
                    s[27:28],
                    int(s[28:29]),
                    s[32:33],
                    int(s[33:35]),
                    s[35:36],
                    int(s[36:37]),
                )

                self.lines.append(line)
                r += 1
                ii += 1
                if ii == _PROGRESS_INDICATOR_PERIOD:
                    a99.get_python_logger().info("Loading '{}': {}".format(
                        filename, a99.format_progress(r, num_lines)))
                    ii = 0

        except Exception as e:
            raise RuntimeError("Error around %d%s row of file '%s': \"%s\"" %
                               (r + 1, a99.ordinal_suffix(r + 1), filename,
                                a99.str_exc(e))) from e
示例#5
0
    def _do_load(self, filename):
        """Clears internal lists and loads from file."""

        with open(filename, "r") as h:
            r = 0  # counts rows of file
            try:
                number = int(h.readline())  # not used (see below)
                r += 1
                self.titm = a99.readline_strip(h)
                r += 1

                nv = a99.int_vector(
                    h)  # number of transitions=sets-of-lines for each molecule
                r += 1
                # Uses length of nv vector to know how many molecules to read (ignores "number")
                num_mol = len(nv)

                for im in range(num_mol):
                    nvi = nv[im]

                    m = Molecule()
                    self.molecules.append(m)

                    m.titulo = a99.readline_strip(h)
                    a99.get_python_logger().debug(
                        'Reading %d%s molecule \'%s\'' %
                        (im + 1, a99.ordinal_suffix(im + 1), m.titulo))

                    parts = [s.strip() for s in m.titulo.split("#")]
                    m.description = parts[0]
                    if len(parts) > 1:
                        # Found 'structure' in m.titulo
                        m.symbols = [
                            basic.adjust_atomic_symbol(s) for s in [
                                s.strip() for s in parts[1].split(" ")
                                if len(s.strip()) > 0
                            ]
                        ]
                    else:
                        # Will try to guess molecule by m.titulo's contents
                        temp = basic.description_to_symbols(parts[0])
                        m.symbols = temp or []
                    transitions = []
                    if len(parts) > 2:
                        numbers = [
                            int(float(x))
                            for x in re.findall('([0-9.]+)', parts[2])
                        ]
                        transitions = list(zip(numbers[0::2], numbers[1::2]))

                    r += 1
                    m.fe, m.do, m.mm, m.am, m.bm, m.ua, m.ub, m.te, m.cro = a99.float_vector(
                        h)
                    r += 1

                    h.readline()  # Skips line which is blank in file
                    # In readers.f90 the variables are ise, a0, a1, a2 a3, a4, als
                    # but the pfant does not use them.
                    r += 1

                    m.s = float(h.readline())
                    r += 1

                    # These vectors must have nvi elements
                    s_v, r_inc = a99.multirow_str_vector(h, nvi, r)
                    r += r_inc
                    qqv = list(map(float, s_v))
                    s_v, r_inc = a99.multirow_str_vector(h, nvi, r)
                    r += r_inc
                    ggv = list(map(float, s_v))
                    s_v, r_inc = a99.multirow_str_vector(h, nvi, r)
                    r += r_inc
                    bbv = list(map(float, s_v))
                    s_v, r_inc = a99.multirow_str_vector(h, nvi, r)
                    r += r_inc
                    ddv = list(map(float, s_v))
                    s_v, r_inc = a99.multirow_str_vector(h, nvi, r)
                    r += r_inc
                    fact = list(map(float, s_v))
                    for name in ["qqv", "ggv", "bbv", "ddv", "fact"]:
                        v = eval(name)
                        if len(v) != nvi:
                            raise RuntimeError(
                                'Attribute %s of molecule #%d must be a vector with %d elements (has %d)'
                                % (name, im + 1, nvi, len(v)))

                    # creates sets of lines and appends to molecule
                    for isol, (q, g, b, d,
                               f) in enumerate(zip(qqv, ggv, bbv, ddv, fact)):
                        o = SetOfLines()
                        o.qqv = q
                        o.ggv = g
                        o.bbv = b
                        o.ddv = d
                        o.fact = f
                        if isol < len(transitions):
                            o.vl, o.v2l = transitions[isol]
                        m.sol.append(o)

                    # Now reads lines
                    sol_iter = iter(
                        m.sol
                    )  # iterator to change the current set-of-lines with the "numlin" flag
                    o = next(sol_iter)  # current set-of-lines
                    # o.lmbdam, o.sj, o.jj, o.branch = [], [], [], []
                    while True:
                        # Someone added "*" signs as a 6th column of some lines
                        # which was causing my reading to crash.
                        # Therefore I read the line and discard beyond the 5th column before
                        # converting to float
                        temp = a99.str_vector(h)
                        lmbdam = float(temp[0])
                        sj = float(temp[1])
                        jj = float(temp[2])
                        # Alphanumeric now iz = int(temp[3])
                        iz = temp[3]
                        numlin = int(temp[4])

                        r += 1

                        o.lmbdam.append(lmbdam)
                        o.sj.append(sj)
                        o.jj.append(jj)
                        o.branch.append(iz)

                        if numlin > 0:
                            if numlin == 9:
                                break
                            o = next(sol_iter)

                    a99.get_python_logger().info("Loading '{}': {}".format(
                        filename, a99.format_progress(im + 1, num_mol)))

                    if im + 1 == num_mol:
                        break

                    # im += 1
            except Exception as e:
                raise type(e)(("Error around %d%s row of file '%s'" %
                               (r + 1, a99.ordinal_suffix(r + 1), filename)) +
                              ": " + str(e)).with_traceback(sys.exc_info()[2])
示例#6
0
    def _do_load(self, filename):
        def strip(s):
            return s.decode("ascii").strip()

        def I(s):
            return s.decode("ascii")  # Identity

        my_struct = struct.Struct(
            "14s 13s 12s 4s 6s 6s 3s 12s 4s 6s 6s 3s 13s 2x 3s 1x 1s 1x 1s 6s 2x"
        )
        func_map = [
            float, float, float, int, float, float, int, float, int, float,
            float, int, float, strip, I, I, strip
        ]

        filesize = os.path.getsize(filename)
        num_lines = float(filesize) / 120

        if num_lines != int(num_lines):
            raise RuntimeError(
                "Fractionary number of lines: {}, not a FilePlezTiO".format(
                    num_lines))
        num_lines = int(num_lines)

        with open(filename, "rb") as h:
            try:
                r = 0  # counts rows of file
                ii = 0  # progress feedback auxiliary variable
                while True:
                    s = h.readline()

                    # print(s)
                    # break
                    if len(s) == 0:
                        break  # # EOF: blank line or references section

                    # Filtering part

                    gf = float(s[14:27])
                    J2l = float(s[43:49])
                    vl = int(s[70:74])
                    v2l = int(s[49:53])

                    # gf = float(bits[1])
                    # J2l = float(bits[4])
                    # vl = float(bits[8])
                    # v2l = float(bits[3])

                    # gf = args[1]
                    # J2l = args[4]
                    # vl = args[8]
                    # v2l = args[3]

                    if not (gf >= self.min_gf and J2l <= self.max_J2l
                            and vl <= self.max_vl and v2l <= self.max_v2l):
                        r += 1
                        continue

                    bits = my_struct.unpack_from(s)

                    args = [func(x) for func, x in zip(func_map, bits)]
                    line = PlezTiOLine(*args)
                    self.lines.append(line)
                    r += 1

                    # args = [func(x) for func, x in zip(func_map, bits)]
                    # line = PlezTiOLine(*bits)
                    # self.lines.append(line)

                    #           1         2         3         4         5         6         7         8         9        10        11
                    # 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678
                    #
                    #    lambda_air(A)   gf         Elow(cm-1)  vl  Jl    Nl  syml  Eup(cm-1) vu   Ju    Nu  symu  gamrad    mol trans branch
                    #      3164.8716 0.769183E-11   3459.6228   0   5.0   5.0  0  35047.3396  15   6.0   6.0  0 1.821557E+07|'TiO a f  R    '
                    # 12345678901234                                                                                        | 12345678901234
                    # 0             1234567890123                                                                           |
                    #               1            123456789012                                                               |
                    #                            2           1234                                                           |
                    #                                        3   123456                                                     |
                    #                                            4     123456                                               |
                    #                                                  5     123                                            |
                    #                                                        6  123456789012                                |
                    #                                                           7           1234                            |
                    #                                                                       8   123456                      |
                    #                                                                           9     123456                |
                    #                                                                                 10    123             |
                    #                                                                                       11 1234567890123|
                    #                                                                                          12           2x
                    #                                                                                                         123 1 1 123456
                    #                                                                                                         13  141516

                    ii += 1
                    if ii > 12345:
                        a99.get_python_logger().info("Loading '{}': {}".format(
                            filename, a99.format_progress(r + 1, num_lines)))
                        ii = 0

            except Exception as e:
                raise type(e)(("Error around %d%s row of file '%s'" %
                               (r + 1, a99.ordinal_suffix(r + 1), filename)) +
                              ": " + str(e)).with_traceback(sys.exc_info()[2])
示例#7
0
 def append_error(msg):
     log.errors.append("#{}{} line: {}".format(i + 1, a99.ordinal_suffix(i + 1), str(msg)))
示例#8
0
def vald3_to_sols(molconsts, file_vald3, qgbd_calculator):
    """
    Converts HITRAN molecular lines data to PFANT "sets of lines"

    Args:
        molconsts: a dict-like object combining field values from tables 'molecule', 'state',
                    and 'pfantmol' from a FileMolDB database
        file_vald3: FileVald3 instance with only one species
        qgbd_calculator: callable that can calculate "qv", "gv", "bv", "dv",
                         e.g., calc_qbdg_tio_like()

    Returns: (a list of ftpyfant.SetOfLines objects, a MolConversionLog object)
    """

    def append_error(msg):
        log.errors.append("#{}{} line: {}".format(i + 1, a99.ordinal_suffix(i + 1), str(msg)))

    # C     BAND (v',v'')=(VL,V2L)
    # C     WN: vacuum wavenumber   WL : air wavelength
    # C     J2L: lower state angular momentum number
    # C     iso: isotope/ 26: 12C16O, 36: 13C16O, 27: 12C17O, 28: 12C18O
    # C     ramo: branch, for P: ID=1, for R: ID=2
    # C     name: file name/ coisovLv2L
    # C     HL: Honl-London factor
    # C     FR: oscillator strength

    if not isinstance(file_vald3, pyfant.FileVald3):
        raise TypeError("Invalid type for argument 'file_vald3': {}".format(type(file_vald3)))
    if len(file_vald3) > 1:
        raise ValueError("Argument 'file_vald3' must have only one species, but it has {}".format(len(file_vald3)))

    lines = file_vald3.speciess[0].lines
    n = len(lines)

    S = molconsts.get_S2l()
    DELTAK = molconsts.get_deltak()

    sols = OrderedDict()  # one item per (vl, v2l) pair
    log = MolConversionLog(n)

    for i, line in enumerate(lines):
        assert isinstance(line, pyfant.Vald3Line)
        try:
            wl = line.lambda_
            # Br, J2l = f_group(data["local_lower_quanta"][i])
            # Jl = _Jl(Br, J2l)
            # V = f_class(data["global_upper_quanta"][i])
            # V_ = f_class(data["global_lower_quanta"][i])
            # A = data["a"][i]

            # A seguir normalizacion de factor de Honl-london (HLN)
            Normaliza = 1/((2.0*line.J2l+1)*(2.0*S+1)*(2.0-DELTAK))

            # A seguir teremos a forca de oscilador
            # mas q sera normalizada segundo o programa da Beatriz
            # gf = Normaliza*1.499*(2*Jl+1)*A/(nu**2)  <-- this was for HITRAN
            gf_pfant = Normaliza*10**line.loggf

            J2l_pfant = int(line.J2l)  # ojo, estamos colocando J2L-0.5!
        except Exception as e:
            log.errors.append("#{}{} line: {}".format(i+1, a99.ordinal_suffix(i+1), str(e)))
            continue

        sol_key = "%3d%3d" % (line.vl, line.v2l)  # (v', v'') transition (v_sup, v_inf)
        if sol_key not in sols:
            qgbd = qgbd_calculator(molconsts, line.v2l)
            qqv = qgbd["qv"]
            ggv = qgbd["gv"]
            bbv = qgbd["bv"]
            ddv = qgbd["dv"]
            sols[sol_key] = pyfant.SetOfLines(line.vl, line.v2l, qqv, ggv, bbv, ddv, 1.)

        sol = sols[sol_key]
        # TODO assuming singlet!!!
        sol.append_line(wl, gf_pfant, J2l_pfant, ph.singlet.quanta_to_branch(line.Jl, line.J2l))

    return (list(sols.values()), log)
示例#9
0
    def _do_load_h(self, h, filename):
        # ---SAMPLE FILE---
        #                                                                    Lande factors      Damping parameters
        # Elm Ion      WL_air(A)   log gf* E_low(eV) J lo  E_up(eV) J up  lower  upper   mean   Rad.  Stark  Waals
        # 'OH 1',       16401.409,  -8.587,  4.0602, 39.5,  4.8160, 39.5,99.000,99.000,99.000, 0.000, 0.000, 0.000,
        # '  Hb                                                     2s2.3s2.1p3          X,2,1,f,40,3'
        # '  Hb                                                 2s2.3s2.1p3              X,2,1,f,39,7'

        r = 0  # counts rows of file
        self.speciess = defaultdict(lambda: defaultdict(lambda: []))
        try:
            # Uses header as "magic characters"
            s = h.readline().strip("\n")
            if s != "                                                                   Lande factors      Damping parameters":
                raise RuntimeError(
                    "This doesn't appear to be a VALD3 extended-format atomic/molecular lines file"
                )
            r += 1
            h.readline()
            r += 1

            while True:
                # Line 1/4
                # ========
                #
                s = h.readline().strip()
                if len(s) == 0 or not s.startswith("'"):
                    # EOF: blank line or references section
                    break

                fields = s.split(",")
                formula, s_ioni = fields[0][1:-1].split(" ")

                if formula in _symbols:
                    r += 1
                    # Atom, skips altogether (skips next three lines and loops)
                    for _ in range(3):
                        h.readline()
                        r += 1
                    continue

                line = Vald3MolecularLine(
                    lambda_=float(fields[1]),
                    loggf=float(fields[2]),
                    Jl=float(fields[6]),  # J_up
                    J2l=float(fields[4])  # J_lo
                )
                r += 1

                # Line 2/4 and 3/4
                # ================
                #
                # Parses "molecular system" TODO rename this term later
                # TODO dunno what comes first, vl or v2l, but if it follows the file header,
                # v2l (v lower) should come first, because "J lo" comes before "J up" in the file header
                s = h.readline().strip()
                r += 1
                sys00, sys01, sys02, v2l = _parse_system(s)
                s = h.readline().strip()
                r += 1
                sys10, sys11, sys12, vl = _parse_system(s)

                species_key = (formula, int(s_ioni))
                sol_key = Vald3SolKey(vl, v2l, sys00, sys01, sys02, sys10,
                                      sys11, sys12)
                self.speciess[species_key][sol_key].append(line)

                # Line 4/4 (citation line (skips))
                # ================================
                #
                h.readline()
                r += 1

        except Exception as e:
            raise type(e)(("Error around %d%s row of file '%s'" %
                           (r + 1, a99.ordinal_suffix(r + 1), filename)) +
                          ": " + str(e)).with_traceback(sys.exc_info()[2])
示例#10
0
def vald3_to_atoms(file_obj):
    """
    Converts data from a VALD3 file into a FileAtoms object.

    Args:
      file_obj: file-like object, e.g., returned by open()

    Returns: a FileAtoms object

    VALD3 website: http://vald.astro.uu.se/
    """

    _logger = a99.get_python_logger()

    def log_skipping(r, reason, row):
        _logger.info("Skipping row #%d (%s)" % (r, reason))
        _logger.info(str(row))

    reader = csv.reader(file_obj)
    ret = pyfant.FileAtoms()
    edict = {
    }  # links atomic symbols with Atom objects created (key is atomic symbol)
    r = 0
    num_skip_ioni, num_skip_mol = 0, 0
    try:
        for row in reader:
            r += 1
            if len(row) <= 12:  # Condition to detect row of interest
                continue

            elem = row[0][1:row[0].index(" ")]
            if not elem in _Symbols:
                # skips molecule
                num_skip_mol += 1
                continue

            # # Collects information and creates atomic line object.
            # Note: Variable names follow Fortran source variable names.

            s_ioni = row[0][-2]
            ioni = int(s_ioni)  # not used, stays as file validation

            if ioni > 2:
                # log_skipping(r, "ionization > 2", row)
                num_skip_ioni += 1
                continue

            _waals = float(row[12])
            if _waals > 0:
                # If the van der Waals damping parameter is > 0, it means
                # something else, see the documentation at
                # http://www.astro.uu.se/valdwiki/Vald3Format:
                #  "if >0 : two parameters as defined in Barklem et al.
                #   2000A&AS..142..467B : integer part is cross-section sigma,
                #   fractional part is velocity parameter alpha"
                # Therefore, we fall back.
                _waals = 0

            line = pyfant.AtomicLine()
            line.lambda_ = float(row[1])
            line.algf = float(row[2])
            line.kiex = float(row[3])
            if _waals == 0:
                line.ch = 0.3e-31
            else:
                try:
                    # Formula supplied by Elvis Cantelli:
                    # extracted from cross-entropy code by P. Barklem
                    line.ch = 10**(2.5 * _waals - 12.32)
                except:
                    # Catches error to log _waals value that gave rise to error
                    _logger.critical("Error calculating ch: waals=%g" % _waals)
                    raise

            # Setting gr to zero will cause PFANT to calculate it using a formula.
            # See pfantlib.f90::read_atoms() for the formula.
            line.gr = 0.0
            # ge is not present in VALD3 file.
            # it enters as a multiplicative term in popadelh(). The original
            # atom4070g.dat and atoms.dat all had ge=0 for all lines.
            line.ge = 0.0
            # Attention: zinf must be tuned later using tune-zinf.py
            line.zinf = 0.5
            # Never used in PFANT
            line.abondr = 1

            # # Stores line in object
            elem = pyfant.adjust_atomic_symbol(elem)
            key = elem + s_ioni  # will group elements by this key
            if key in edict:
                a = edict[key]
            else:
                a = edict[key] = pyfant.Atom()
                a.elem = elem
                a.ioni = int(s_ioni)
                ret.atoms.append(a)
            a.lines.append(line)
    except Exception as e:
        raise type(e)(("Error around %d%s row of VALD3 file" %
                       (r, a99.ordinal_suffix(r))) + ": " +
                      str(e)).with_traceback(sys.exc_info()[2])
    _logger.debug("VALD3-to-atoms conversion successful!")
    _logger.info("Number of lines skipped (molecules): %d" % num_skip_mol)
    _logger.info("Number of lines skipped (ioni > 2): %d" % num_skip_ioni)
    _logger.debug("Number of (element+ioni): %s" % len(ret))
    _logger.debug("Total number of atomic lines: %d" %
                  (sum(len(a) for a in ret.atoms), ))
    return ret
示例#11
0
    def _do_load_h(self, h, filename, num_lines=0):
        r = 0  # counts rows of file
        ii = 0
        try:
            self.lines = []
            while True:
                s = h.readline().strip("\n")
                if len(s) == 0:
                    break

                # Kurucz: "negative energies are predicted or extrapolated"
                # (http: // kurucz.harvard.edu / linelists.html)
                E2l = float(s[22:32])
                if E2l < 0:
                    E2l = -E2l
                El = float(s[37:48])
                if El < 0:
                    El = -El

                try:
                    spin2l = int(s[57:58])
                except ValueError:
                    spin2l = 0

                try:
                    spinl = int(s[65:66])
                except ValueError:
                    spinl = 0

                line = KuruczMolLine(
                    float(s[0:10]) * 10,
                    float(s[10:17]),
                    float(s[17:22]),
                    E2l,
                    float(s[32:37]),
                    El,
                    int(s[48:50]),
                    int(s[50:52]),
                    s[53:54],
                    int(s[54:56]),
                    s[56:57],
                    spin2l,
                    s[61:62],
                    int(s[62:64]),
                    s[64:65],
                    spinl,
                    int(s[68:70]),
                )

                self.lines.append(line)
                r += 1
                ii += 1
                if ii == _PROGRESS_INDICATOR_PERIOD:
                    a99.get_python_logger().info("Loading '{}': {}".format(
                        filename, a99.format_progress(r, num_lines)))
                    ii = 0

        except Exception as e:
            # f = type(e)(("Error around %d%s row of file '%s'" %
            #              (r + 1, a99.ordinal_suffix(r + 1), filename)) + ": " + str(
            #     e)).with_traceback(sys.exc_info()[2])
            raise RuntimeError("Error around %d%s row of file '%s': \"%s\"" %
                               (r + 1, a99.ordinal_suffix(r + 1), filename,
                                a99.str_exc(e))) from e
示例#12
0
def turbospectrum_to_atoms(file_obj):
    """
    Converts data from a TurboSpectrum file into a FileAtoms object.

    Args:
      file_obj: file-like object, e.g., returned by open()

    Returns: a FileAtoms object
    """

    _logger = a99.get_python_logger()

    def log_skipping(r, reason, row):
        _logger.info("Skipping row #%d (%s)" % (r, reason))
        _logger.info(str(row))

    ret = pyfant.FileAtoms()
    edict = {}  # links atomic symbols with Atom objects created (key is atomic symbol + ionization)
    r = 0  # number of current row
    num_skip_ioni, num_skip_mol = 0, 0
    state = _X_EL0
    try:
        for row in file_obj:
            r += 1

            if state < _X_LINE_OR_EL0:
                if row[0] != "'":
                    raise ParseError("Expecting element specification, but found something else")

            if state == _X_EL0:
                #' 3.000              '    1       110
                #0123456
                elem = _Symbols[int(row[1:3])]
                ioni = int(row[4:7])+1
                state = _X_EL1
            elif state == _X_EL1:
                state = _X_LINE_OR_EL0
            elif state == _X_LINE_OR_EL0:
                if row[0] == "'":
                    elem = _Symbols[int(row[1:3])]
                    ioni = int(row[4:7]) + 1
                    state = _X_EL1
                else:
                    if ioni > 2:
                        # log_skipping(r, "ionization > 2", row)
                        num_skip_ioni += 1
                        continue

                    #'Li I '
                    #  4601.843  1.848  -5.804  2.50    6.0  5.01E+07 'p' 'f'   0.0    1.0 'Li I    2p  2P    4f  2F     SEN    '
                    #0         1         2         3
                    #01234567890123456789012345678901234567890

                    rr = row.split()

                    _waals = float(rr[3])
                    if _waals > 0:
                        _waals = 0

                    line = pyfant.AtomicLine()
                    line.lambda_ = float(rr[0])
                    line.kiex = float(rr[1])
                    line.algf = float(rr[2])
                    if _waals == 0:
                        line.ch = 0.3e-31
                    else:
                        try:
                            # Formula supplied by Elvis Cantelli:
                            # extracted from cross-entropy code by P. Barklem
                            line.ch = 10**(2.5*_waals-12.32)
                        except:
                            # Catches error to log _waals value that gave rise to error
                            _logger.critical("Error calculating ch: waals=%g" % _waals)
                            raise

                    # Setting gr to zero will cause PFANT to calculate it using a formula.
                    # See pfantlib.f90::read_atoms() for the formula.
                    line.gr = 0.0
                    # ge is not present in VALD3 file.
                    # it enters as a multiplicative term in popadelh(). The original
                    # atom4070g.dat and atoms.dat all had ge=0 for all lines.
                    line.ge = 0.0
                    # Attention: zinf must be tuned later using tune-zinf.py
                    line.zinf = 0.5
                    # Never used in PFANT
                    line.abondr = 1

                    key = f"{elem:2}{ioni:1}"  # will group elements by this key
                    if key in edict:
                        a = edict[key]
                    else:
                        a = edict[key] = pyfant.Atom()
                        a.elem = pyfant.adjust_atomic_symbol(elem)
                        a.ioni = ioni
                        ret.atoms.append(a)
                    a.lines.append(line)

    except Exception as e:
        raise type(e)(("Error around %d%s row of TurboSpectrum file" %
            (r, a99.ordinal_suffix(r)))+": "+str(e)).with_traceback(sys.exc_info()[2])
    _logger.debug("VALD3-to-atoms conversion successful!")
    _logger.info("Number of lines skipped (molecules): %d" % num_skip_mol)
    _logger.info("Number of lines skipped (ioni > 2): %d" % num_skip_ioni)
    _logger.debug("Number of (element+ioni): %s" % len(ret))
    _logger.debug("Total number of atomic lines: %d" % (sum(len(a) for a in ret.atoms),))
    return ret
示例#13
0
    def _do_load_h(self, h, filename):
        r = 0  # counts rows of file
        ii = 0

        expr_branch = re.compile(
            "[PQRS]\d*")  # regular expression to find the branch

        # states
        EXP_SPECIES = 0  # expecting species definition
        EXP_NAME = 1  # expecting name of species
        EXP_ANY = 2

        state = EXP_SPECIES
        is_atom = None
        species = None
        flag_break = False

        try:
            while True:
                s = h.readline().strip()
                if len(s) == 0:
                    flag_break = True

                if not flag_break:
                    if s[0] == "'":
                        if state == EXP_SPECIES or state == EXP_ANY:
                            # New species to come

                            # Determine whether atom or molecule
                            atnumber = int(s[1:s.index(".")])
                            is_atom = atnumber <= 92

                            state = EXP_NAME

                        elif EXP_NAME:
                            name = s.strip("'")
                            species = self.atoms[
                                name] if is_atom else self.molecules[name]

                            a99.get_python_logger().info(
                                "Loading '{}': species '{}'".format(
                                    filename, name))

                            state = EXP_ANY

                    else:
                        if state != EXP_ANY:
                            raise RuntimeError("Not expecting line right now")
                        # It is a line

                        # Read 6 numeric values then something between quotes
                        line = PlezAtomicLine(
                        ) if is_atom else PlezMolecularLine()

                        line.lambda_, line.chiex, line.loggf, line.gu, line.fdamp, line.raddmp = \
                            [float(x) for x in s[:s.index("'")].split()]

                        if not is_atom:
                            # Get the branch

                            tmp = s[s.index("'"):].strip("'").split()
                            _branch = tmp[0]

                            line.branch = expr_branch.search(_branch).group()
                            line.Jl = float(tmp[2])
                            line.vl = int(tmp[1])
                            line.v2l = int(tmp[6])
                            line.J2l = float(tmp[7])

                        species.lines.append(line)

                if flag_break:
                    break

                r += 1
                ii += 1
                if ii == _PROGRESS_INDICATOR_PERIOD:
                    # a99.get_python_logger().info(
                    #      "Loading '{}': {}".format(filename, a99.format_progress(r, num_lines)))
                    ii = 0

        except Exception as e:
            raise RuntimeError("Error around %d%s row of file '%s': \"%s\"" %
                               (r + 1, a99.ordinal_suffix(r + 1), filename,
                                a99.str_exc(e))) from e