Beispiel #1
0
    def __init__(self, filename=None, configText=None, type="pw"):
        """
            filename:   (str) -- Absolute or relative filename of file to be parsed
            configText: (str) -- Configuration text to be parsed
            type:       (str) -- Type of the simulation
        """

        self.header = None
        self.namelists = OrderedDict()  # Namelist dictionary
        self.cards = OrderedDict()  # Cards dictionary
        self.attach = None
        self.filename = filename
        self.configText = configText
        self.namelistRef = None
        self.cardRef = None
        self.type = type.lower()
Beispiel #2
0
    def __init__(self, filename=None, configText=None, type="pw"):
        """
        Parameters:
            filename    -- absolute or relative filename to be parsed
            configText  -- configuration text to be parsed
            type        -- type of the simulation
            os          -- operating system defined for carriage return
        """

        self.header = None
        self.namelists = OrderedDict()  # Namelist dictionary
        self.cards = OrderedDict()  # Cards dictionary
        self.attach = None
        self.filename = filename
        self.configText = configText
        self.namelistRef = None
        self.cardRef = None
        self.type = type
Beispiel #3
0
 def __init__(self, qeConf):
     """the structure is initialized from PWSCF config file
        'lattice' and 'structure' are automatically updated"""
     self.filename = qeConf.filename
     self.atomicSpecies = OrderedDict()
     self.formatString = "%# .8f %# .8f %# .8f"
     # optConstraints three 1/0 for each coordinate of each atom
     self.optConstraints = []
     self.qeConf = qeConf
     self.lattice = QELattice()
     self.structure = Structure(lattice=self.lattice.diffpy())
     self.nat = None
     self.ntyp = None
Beispiel #4
0
    def __init__(self, filename=None, config=None, type="pw", parse=True):
        """
        Initializes QEInput by passing either filename or config (not both)
        parameters
        
            filename:   (str) -- Absolute or relative filename of file to be parsed
            config:     (str) -- Configuration text to be parsed
            type:       (str) -- Type of the simulation
        """
        self.filename = filename
        self.config = config
        self._type = type.lower()
        self.filters = []
        self.header = None
        self.namelists = OrderedDict()
        self.cards = OrderedDict()
        self.attach = None  # Specific for 'matdyn', 'dynmat', etc.
        self.qe = None  # DEPRICATED
        self.namelistRef = None
        self.cardRef = None

        self._read(filename, config, parse)
Beispiel #5
0
    def __init__(self, filename=None, config=None, parse=True):
        self._filename = filename
        self._config = config
        # OrderedDict?
        # Header
        self._headerstr = ""  # Non-parsed header
        self._header = OrderedDict()  # Parsed header
        self._inputparams = OrderedDict()  # Dictionary of input parameters
        self._outputparams = OrderedDict()  # Dictionary of output parameters

        # Body
        self._sections = {}  # Sections
        self._defs = {}  # Definitions

        if parse and (self._fileExists() or config):
            self.parse()
Beispiel #6
0
 def setStructureFromQEInput(self):
     """ Loads structure from PWSCF config file"""
     self.atomicSpecies = OrderedDict()
     self.lattice.setLatticeFromPWInput(self.qeConf)
     # self.lattice = QELattice(qeConf = self.qeConf)
     self.structure = Structure(lattice=self.lattice.diffpy())
     self.nat = int(self.qeConf.namelist("system").param("nat"))
     self.ntyp = int(self.qeConf.namelist("system").param("ntyp"))
     atomicLines = self.qeConf.card("atomic_positions").lines()
     self.atomicPositionsType = self.qeConf.card("atomic_positions").arg()
     if self.atomicPositionsType == "bohr" or self.atomicPositionsType == "angstrom":
         raise NotImplementedError
     if self.atomicPositionsType == None:
         self.atomicPositionsType = "alat"
     for line in atomicLines:
         if "!" not in line:
             words = line.split()
             coords = [float(w) for w in words[1:4]]
             constraint = []
             if len(words) > 4:
                 constraint = [int(c) for c in words[4:7]]
             self.optConstraints.append(numpy.array(constraint, dtype=int))
             atomSymbol = words[0]
             if self.atomicPositionsType == "alat":
                 coords = self.lattice.diffpy().fractional(numpy.array(coords[0:3]) * self.lattice.a0)
             if self.atomicPositionsType == "crystal":
                 coords = numpy.array(coords[0:3])
             self.structure.addNewAtom(atomSymbol, xyz=numpy.array(coords[0:3]))
             # parse mass ATOMIC_SPECIES section:
             atomicSpeciesLines = self.qeConf.card("atomic_species").lines()
             for line in atomicSpeciesLines:
                 if "!" not in line:
                     atomicSpeciesWords = line.split()
                     element = atomicSpeciesWords[0]
                     mass = float(atomicSpeciesWords[1])
                     ps = atomicSpeciesWords[2]
                     self.atomicSpecies[element] = AtomicSpecies(element, mass, ps)
Beispiel #7
0
    def setStructureFromPWOutput(self, pwscfOutputFile):
        """
        Loads structure from PWSCF output file. If there was geometry
        optimization (relax or vc-relax), the structure will be reinitialized
        from the last step of the optimization
        """
        file = open(pwscfOutputFile)
        pwscfOut = file.readlines()
        pseudoList = []
        atomList = []
        massList = []
        self.atomicSpecies = OrderedDict()
        self.atomicPositionsType = "alat"
        # parse beginning:
        for i, line in enumerate(pwscfOut):
            if "lattice parameter (a_0)" in line:
                a_0 = float(line.split()[4])
            if "bravais-lattice index" in line:
                ibrav = int(line.split("=")[1])
            if "number of atoms/cell" in line:
                self.nat = int(line.split("=")[1])
            if "number of atomic types" in line:
                self.ntyp = int(line.split("=")[1])
            if "PseudoPot." in line:
                pseudoList.append(line.split("read from file")[1].strip())
            if "atomic species   valence    mass     pseudopotential" in line:
                for j in range(self.ntyp):
                    atomList.append(pwscfOut[i + j + 1].split()[0])
                    massList.append(float(pwscfOut[i + j + 1].split()[2]))
            if "crystal axes: (cart. coord. in units of a_0)" in line:
                latticeVectors = [
                    [float(f) * a_0 for f in pwscfOut[i + 1].split()[3:6]],
                    [float(f) * a_0 for f in pwscfOut[i + 2].split()[3:6]],
                    [float(f) * a_0 for f in pwscfOut[i + 3].split()[3:6]],
                ]
                self.lattice.setLatticeFromQEVectors(ibrav, latticeVectors)
            if "site n.     atom                  positions (a_0 units)" in line:
                self.structure = Structure(lattice=self.lattice.diffpy())
                for n in range(self.nat):
                    words = pwscfOut[i + n + 1].split()
                    atomSymbol = words[1]
                    coords = [float(w) for w in words[6:9]]
                    constraint = []
                    self.optConstraints.append(numpy.array(constraint, dtype=int))
                    # print numpy.array(coords[0:3])*a_0
                    coords = self.lattice.diffpy().fractional(numpy.array(coords[0:3]) * a_0)
                    self.structure.addNewAtom(atomSymbol, xyz=numpy.array(coords[0:3]))

        for a, m, p in zip(atomList, massList, pseudoList):
            self.atomicSpecies[a] = AtomicSpecies(a, m, p)

        # print 'Input structure from output file: ', self.toString()
        # Parse end:
        # Find all geometry optimization steps
        posList = [i for i, line in enumerate(pwscfOut) if "!    total energy" in line]
        lastSection = pwscfOut[posList[-1] :]
        for i, line in enumerate(lastSection):
            if "CELL_PARAMETERS (alat)" in line:
                latticeVectors = [
                    [float(f) * a_0 for f in lastSection[i + 1].split()],
                    [float(f) * a_0 for f in lastSection[i + 2].split()],
                    [float(f) * a_0 for f in lastSection[i + 3].split()],
                ]
                self.lattice.setLatticeFromQEVectors(ibrav, latticeVectors)
                # self.lattice = QELattice(ibrav = ibrav, base = latticeVectors)
                print self.lattice.diffpy().base
            if "ATOMIC_POSITIONS (alat)" in line:
                self.structure = Structure(lattice=self.lattice.diffpy())
                for n in range(self.nat):
                    words = lastSection[i + n + 1].split()
                    atomSymbol = words[0]
                    coords = [float(w) for w in words[1:4]]
                    constraint = []
                    if len(words) > 4:
                        constraint = [int(c) for c in words[4:7]]
                    self.optConstraints.append(numpy.array(constraint, dtype=int))
                    coords = self.lattice.diffpy().fractional(numpy.array(coords[0:3]) * a_0)
                    self.structure.addNewAtom(atomSymbol, xyz=numpy.array(coords[0:3]))
Beispiel #8
0
class QEStructure:
    def __init__(self, qeConf):
        """the structure is initialized from PWSCF config file
           'lattice' and 'structure' are automatically updated"""
        self.filename = qeConf.filename
        self.atomicSpecies = OrderedDict()
        self.formatString = "%# .8f %# .8f %# .8f"
        # optConstraints three 1/0 for each coordinate of each atom
        self.optConstraints = []
        self.qeConf = qeConf
        self.lattice = QELattice()
        self.structure = Structure(lattice=self.lattice.diffpy())
        self.nat = None
        self.ntyp = None

    def parseInput(self):
        self.setStructureFromQEInput()

    def parseOutput(self, pwscfOutputFile):
        self.setStructureFromPWOutput(pwscfOutputFile)

    def setStructureFromPWOutput(self, pwscfOutputFile):
        """
        Loads structure from PWSCF output file. If there was geometry
        optimization (relax or vc-relax), the structure will be reinitialized
        from the last step of the optimization
        """
        file = open(pwscfOutputFile)
        pwscfOut = file.readlines()
        pseudoList = []
        atomList = []
        massList = []
        self.atomicSpecies = OrderedDict()
        self.atomicPositionsType = "alat"
        # parse beginning:
        for i, line in enumerate(pwscfOut):
            if "lattice parameter (a_0)" in line:
                a_0 = float(line.split()[4])
            if "bravais-lattice index" in line:
                ibrav = int(line.split("=")[1])
            if "number of atoms/cell" in line:
                self.nat = int(line.split("=")[1])
            if "number of atomic types" in line:
                self.ntyp = int(line.split("=")[1])
            if "PseudoPot." in line:
                pseudoList.append(line.split("read from file")[1].strip())
            if "atomic species   valence    mass     pseudopotential" in line:
                for j in range(self.ntyp):
                    atomList.append(pwscfOut[i + j + 1].split()[0])
                    massList.append(float(pwscfOut[i + j + 1].split()[2]))
            if "crystal axes: (cart. coord. in units of a_0)" in line:
                latticeVectors = [
                    [float(f) * a_0 for f in pwscfOut[i + 1].split()[3:6]],
                    [float(f) * a_0 for f in pwscfOut[i + 2].split()[3:6]],
                    [float(f) * a_0 for f in pwscfOut[i + 3].split()[3:6]],
                ]
                self.lattice.setLatticeFromQEVectors(ibrav, latticeVectors)
            if "site n.     atom                  positions (a_0 units)" in line:
                self.structure = Structure(lattice=self.lattice.diffpy())
                for n in range(self.nat):
                    words = pwscfOut[i + n + 1].split()
                    atomSymbol = words[1]
                    coords = [float(w) for w in words[6:9]]
                    constraint = []
                    self.optConstraints.append(numpy.array(constraint, dtype=int))
                    # print numpy.array(coords[0:3])*a_0
                    coords = self.lattice.diffpy().fractional(numpy.array(coords[0:3]) * a_0)
                    self.structure.addNewAtom(atomSymbol, xyz=numpy.array(coords[0:3]))

        for a, m, p in zip(atomList, massList, pseudoList):
            self.atomicSpecies[a] = AtomicSpecies(a, m, p)

        # print 'Input structure from output file: ', self.toString()
        # Parse end:
        # Find all geometry optimization steps
        posList = [i for i, line in enumerate(pwscfOut) if "!    total energy" in line]
        lastSection = pwscfOut[posList[-1] :]
        for i, line in enumerate(lastSection):
            if "CELL_PARAMETERS (alat)" in line:
                latticeVectors = [
                    [float(f) * a_0 for f in lastSection[i + 1].split()],
                    [float(f) * a_0 for f in lastSection[i + 2].split()],
                    [float(f) * a_0 for f in lastSection[i + 3].split()],
                ]
                self.lattice.setLatticeFromQEVectors(ibrav, latticeVectors)
                # self.lattice = QELattice(ibrav = ibrav, base = latticeVectors)
                print self.lattice.diffpy().base
            if "ATOMIC_POSITIONS (alat)" in line:
                self.structure = Structure(lattice=self.lattice.diffpy())
                for n in range(self.nat):
                    words = lastSection[i + n + 1].split()
                    atomSymbol = words[0]
                    coords = [float(w) for w in words[1:4]]
                    constraint = []
                    if len(words) > 4:
                        constraint = [int(c) for c in words[4:7]]
                    self.optConstraints.append(numpy.array(constraint, dtype=int))
                    coords = self.lattice.diffpy().fractional(numpy.array(coords[0:3]) * a_0)
                    self.structure.addNewAtom(atomSymbol, xyz=numpy.array(coords[0:3]))

    def setStructureFromQEInput(self):
        """ Loads structure from PWSCF config file"""
        self.atomicSpecies = OrderedDict()
        self.lattice.setLatticeFromPWInput(self.qeConf)
        # self.lattice = QELattice(qeConf = self.qeConf)
        self.structure = Structure(lattice=self.lattice.diffpy())
        self.nat = int(self.qeConf.namelist("system").param("nat"))
        self.ntyp = int(self.qeConf.namelist("system").param("ntyp"))
        atomicLines = self.qeConf.card("atomic_positions").lines()
        self.atomicPositionsType = self.qeConf.card("atomic_positions").arg()
        if self.atomicPositionsType == "bohr" or self.atomicPositionsType == "angstrom":
            raise NotImplementedError
        if self.atomicPositionsType == None:
            self.atomicPositionsType = "alat"
        for line in atomicLines:
            if "!" not in line:
                words = line.split()
                coords = [float(w) for w in words[1:4]]
                constraint = []
                if len(words) > 4:
                    constraint = [int(c) for c in words[4:7]]
                self.optConstraints.append(numpy.array(constraint, dtype=int))
                atomSymbol = words[0]
                if self.atomicPositionsType == "alat":
                    coords = self.lattice.diffpy().fractional(numpy.array(coords[0:3]) * self.lattice.a0)
                if self.atomicPositionsType == "crystal":
                    coords = numpy.array(coords[0:3])
                self.structure.addNewAtom(atomSymbol, xyz=numpy.array(coords[0:3]))
                # parse mass ATOMIC_SPECIES section:
                atomicSpeciesLines = self.qeConf.card("atomic_species").lines()
                for line in atomicSpeciesLines:
                    if "!" not in line:
                        atomicSpeciesWords = line.split()
                        element = atomicSpeciesWords[0]
                        mass = float(atomicSpeciesWords[1])
                        ps = atomicSpeciesWords[2]
                        self.atomicSpecies[element] = AtomicSpecies(element, mass, ps)

    def toString(self):
        s = self.lattice.toString() + "\n"
        if self.atomicPositionsType == "alat":
            s = s + 'Atomic positions in units of lattice parametr "a":\n'
        if self.atomicPositionsType == "crystal":
            s = s + "Atomic positions in crystal coordinates:\n"
        for atom, constraint in zip(self.structure, self.optConstraints):
            if self.atomicPositionsType == "alat":
                coords = self.lattice.diffpy().cartesian(atom.xyz) / self.lattice.a
                coords = self.formatString % (coords[0], coords[1], coords[2])
            else:
                if self.atomicPositionsType == "crystal":
                    coords = self.formatString % (v[0], v[1], v[2]) % (atom.xyz[0], atom.xyz[1], atom.xyz[2])
                else:
                    raise NonImplementedError
            s = s + "%-3s" % atom.element + "    " + coords + "  " + str(constraint)[1:-1] + "\n"

        s = s + "\n"
        for element, specie in self.atomicSpecies.items():
            s = s + specie.toString() + "\n"

        return s

    def updatePWInput(self, qeConf=None):

        if qeConf == None:
            qeConf = self.qeConf

        self.lattice.updatePWInput(qeConf)

        qeConf.namelist("system").remove("ntyp")
        qeConf.namelist("system").remove("nat")
        qeConf.namelist("system").add("ntyp", self.ntyp)
        qeConf.namelist("system").add("nat", self.nat)

        if "atomic_positions" in qeConf.cards:
            qeConf.removeCard("atomic_positions")
        qeConf.createCard("atomic_positions")
        qeConf.card("atomic_positions").setArg(self.atomicPositionsType)
        for atom, constraint in zip(self.structure, self.optConstraints):
            if self.atomicPositionsType == "alat":
                coords = self.lattice.diffpy().cartesian(atom.xyz) / self.lattice.a
                coords = self.formatString % (coords[0], coords[1], coords[2])
            else:
                if self.atomicPositionsType == "crystal":
                    coords = self.formatString % (atom.xyz[0], atom.xyz[1], atom.xyz[2])
                else:
                    raise NonImplementedError
            line = "%-3s" % atom.element + "    " + coords + "  " + str(constraint)[1:-1]
            qeConf.card("atomic_positions").addLine(line)

        # update ATOMIC_SPECIES card
        if "atomic_species" in qeConf.cards:
            qeConf.removeCard("atomic_species")
        qeConf.createCard("atomic_species")
        for element, specie in self.atomicSpecies.items():
            qeConf.card("atomic_species").addLine(specie.toString())

    def save(self, fname=None):
        """Writes/updates structure into PW config file,
           if the file does not exist, new one will be created"""
        if fname != None:
            filename = fname
            self.lattice.save(filename)
            qeConf = QEInput(fname)
            qeConf.parse()
        else:
            filename = self.filename
            self.lattice.save(filename)
            qeConf = self.qeConf
        self.updatePWInput(qeConf)

        qeConf.save(filename)

    def diffpy(self):
        return self.structure
Beispiel #9
0
class McStasComponentParser(object):
    def __init__(self, filename=None, config=None, parse=True):
        self._filename = filename
        self._config = config
        # OrderedDict?
        # Header
        self._headerstr = ""  # Non-parsed header
        self._header = OrderedDict()  # Parsed header
        self._inputparams = OrderedDict()  # Dictionary of input parameters
        self._outputparams = OrderedDict()  # Dictionary of output parameters

        # Body
        self._sections = {}  # Sections
        self._defs = {}  # Definitions

        if parse and (self._fileExists() or config):
            self.parse()

    def parse(self):
        """
        Parses data from config string or file and populates header structure
        """
        configText = self._configText()
        bodyText = self._parseHeader(configText)  # Parse header
        self._parseBody(bodyText)

    def header(self):
        "Returns header"
        return self._header

    def sections(self):
        "Returns sections"
        return self._sections

    def definitions(self):
        "Returns definitions"
        return self._defs

    def inputparams(self):
        "Returns input parameters"
        return self._inputparams

    def outputparams(self):
        "Returns output parameters"
        return self._outputparams

    def toString(self, br="\n"):
        str = ""
        for (key, value) in self._header.iteritems():
            str += "%s: %s%s" % (key, value, br)

        str += br
        for (key, value) in self._sections.iteritems():
            str += "%s: %s%s" % (key, value, br)

        str += br
        for (key, value) in self._defs.iteritems():
            str += "%s: %s%s" % (key, value, br)

        return str

    def _parseHeader(self, origText):
        "Parses header and populates header dictionary"
        p = re.compile(COMMENT, re.DOTALL)
        matches = p.findall(origText)
        if len(matches) < 1:  # No header found
            return origText

        m = matches[0]  # First comment is the header
        self._headerstr = m
        text = self._strip(WINCR, m)  # Strip carriage return
        headertext = self._strip(STAR, text)  # Strip stars

        # Extract sections from headertext (hide them?)
        info = self._sectionText(INFO_SEC, headertext)
        desc = self._sectionText(DESC_SEC, headertext)
        param = self._sectionText(PARAM_SEC, headertext)

        self._parseCompName(headertext)
        self._parseInfoSection(info)
        self._parseDescSection(desc)
        self._parseParamSection(param)

        # Find end position of the header
        end = self._headerEnd(origText)

        return origText[end:]

    def _parseBody(self, bodyText):
        "Parses body and populates body dictionary"
        bodytext = self._cleanupText(bodyText)

        self._parseDefComp(bodytext)
        self._parseDefParams(bodytext)
        self._parseSetParams(bodytext)
        self._parseOutParams(bodytext)
        self._parseStateParams(bodytext)
        self._parsePolParams(bodytext)
        self._parseBodySections(bodytext)

    def _cleanupText(self, text):
        "Cleans up text"
        temptext = self._strip(WINCR, text)  # Strip carriage return
        temptext = self._strip(COMMENT, temptext)  # Strip C comments (/*...*/)
        # Don't strip C++ comments as it make Jiao's hack die :)
        # temptext    = self._strip(CPP_COMMENT, temptext)# Strip C++ comments (//...)

        return temptext

    def _parseDefComp(self, text):
        "Parses Define Component"
        name = ""
        value = self._defValues(DEF_COMP, text)
        if value:
            name = value

        self._defs["name"] = name

    def _parseDefParams(self, text):
        "Parses and sets arameters"
        self._setDefParams(DEF_PARAMS, text, "definition_parameters")

    def _setDefParams(self, regex, text, paramname):
        "Parses and parameters and"
        params = []
        value = self._defValues(regex, text)
        if value:
            params = self._defParams(value)

        self._defs[paramname] = params

    def _defParams(self, line):
        "Returns definition parameters as dictionary"
        # Format: [<type>]{spaces}<variable>{spaces}[={spaces}<value>]
        # Example: line    = "string XX, string  YY =1, ZZ , WW= 2"
        params = []
        items = line.strip(" ()\n").split(",")
        for it in items:
            var = it.strip()
            # Doesn't work well
            # match   = self._defValues(PARAM_VAR, var, None)

            match = self._paramMatch(var)
            assert len(match) == 3
            if match[1] == "":  # If name is empty, return empty list
                return []
            param = {}
            param["type"] = match[0]
            param["name"] = match[1]
            param["value"] = match[2]
            params.append(param)

        return params

    def _paramMatch(self, var):
        """
        Returns tuple: (<type>, <name>, <value>).
        Example: ("string", "filename", "'IE.dat'")
        """
        type = ""
        name = ""
        value = ""
        if not var:
            return (type, name, value)
        parts = var.split("=")
        if len(parts) == 2:
            value = parts[1].strip()  # Get value if it exists
            value = value.strip("\"'")  # Strip quotation marks?

        # Catching pointer variable
        parts2 = parts[0].split("*")
        if len(parts2) == 2:
            type = "%s *" % parts2[0].strip()
            name = parts2[1].strip()
            return (type, name, value)

        # Catching non-pointer variable
        varparts = parts[0].split()
        if len(varparts) == 2:
            type = varparts[0].strip()
            name = varparts[1].strip()
        elif len(varparts) == 1:
            name = varparts[0].strip()

        return (type, name, value)

    def _parseSetParams(self, text):
        "Parses Setting Parameters"
        self._setDefParams(SET_PARAMS, text, "setting_parameters")

    def _parseOutParams(self, text):
        "Parses Output Parameters"
        self._setDefParams(OUT_PARAMS, text, "output_parameters")

    def _parseStateParams(self, text):
        "Parses State Parameters"
        self._setListParams(STATE_PARAMS, text, "state_parameters")

    def _parsePolParams(self, text):
        "Parses Polarization Parameters"
        self._setListParams(POL_PARAMS, text, "polarization_parameters")

    def _setListParams(self, regex, text, paramname):
        "Parses text and populates list parameters in defintion part"
        params = []
        value = self._defValues(regex, text)
        if value:
            items = value.strip(" ()").split(",")  # Strip brackets just in case
            for it in items:  # clean up params
                params.append(it.strip())

        self._defs[paramname] = params

    def _defValues(self, regex, text, flags=re.DOTALL | re.IGNORECASE | re.MULTILINE):
        "Returns matches for regex pattern. Used mostly for definitions"
        p = re.compile(regex)
        if flags:
            p = re.compile(regex, flags)
        matches = p.findall(text)
        if len(matches) < 1:  # No value found
            return None

        m = matches[0]
        if type(m) is str:
            return m.strip()  # If value is string, strip spaces

        return m  # otherwise return as they are

    def _parseBodySections(self, text):
        "Parse body sections"
        for secname in BODY_SECTIONS:
            p = re.compile(sectionRegex(secname), re.DOTALL | re.IGNORECASE)
            matches = p.findall(text)
            secname = secname.lower()  # Turn section name lower case
            if secname == FINALLY.lower():  # Special case for "FINALLY" section
                secname = "finalize"

            if len(matches) < 1:  # No section found
                self._sections[secname] = ""
                continue

            mm = matches[0]
            if len(mm) != 2:  # Section content is empty
                self._sections[secname] = ""
                continue

            self._sections[secname] = mm[1]

    def _configText(self):
        "Take config from file if it exist and readable, or use from config - otherwise"
        configText = ""
        if self._fileExists():
            try:  # Try to read it
                configText = open(self._filename).read()
            except:
                pass  # No exception
            return configText

        if self._config:
            configText = self._config

        return configText  # Empty string

    def _fileExists(self):
        "Checks if file exists"
        if self._filename and os.path.exists(self._filename):
            return True

        return False

    def _strip(self, regex, text):
        "Strips piece of text that matches regex pattern"
        p = re.compile(regex, re.DOTALL | re.MULTILINE)
        s = re.sub(p, "", text)
        return s

    def _parseCompName(self, text):
        p = re.compile(COMP_NAME, re.IGNORECASE)
        namefinds = p.findall(text)
        if not namefinds:
            return ""  # Empty name

        compname = namefinds[0].strip()
        self._header["componentname"] = compname

    # XXX: integrate with _defValue()
    def _sectionText(self, secregex, text, flags=re.DOTALL):
        "Returns section string that matches secregex pattern"
        p = re.compile(secregex)
        if flags:
            p = re.compile(secregex, flags)
        matches = p.findall(text)
        if len(matches) < 1:  # No section found, return empty string
            return ""

        return matches[0]  # Return the first found match

    # XXX: Merge with _populateParams()
    def _parseInfoSection(self, text):
        "Parses info section and populates part of header parameters"
        # XXX: There might be problems that description has ':' character
        #           In this case check if numbr == 2 and afterparam = True
        lines = text.split("\n")

        for l in lines:
            l = l.strip()
            if l == "":
                continue  # Skip empty line

            p = re.compile(PARAM)
            m = p.match(l)

            if m:
                param = m.group(1).strip()
                value = m.group(2).strip()
                paramname = self._paramName(param)
                if not paramname:
                    continue

                paramname = paramname.lower()
                self._header[paramname] = value
            else:
                self._header["simple_description"] = l

    def _paramName(self, param):
        """
        Returns parameter name.
        Note: Only those parameter which are in INFO_PARAMS will be returned
        """
        # Non standard parameter
        if self._isMatch(COPYRIGHT_N, param):
            return "copyright"

        # Standard parameters
        for regex in STD_PARAMS:
            if self._isMatch(regex, param):
                return param

        return None

    def _isMatch(self, regex, text):
        "Returns True if matches, False - otherwise"
        p = re.compile(regex, re.IGNORECASE)
        m = p.match(text)
        if m:
            return True  # There is the match

        return False

    def _parseDescSection(self, text):
        "Parses description section and populates part of header parameters"
        # Find example
        p = re.compile(EXAMPLE, re.DOTALL | re.IGNORECASE)
        matches = p.findall(text)
        example = ""  # Default value
        if len(matches) >= 1:  # No section found, return empty string
            mstr = matches[0]  # Take first match!
            if mstr:
                example = " ".join(mstr.strip(" \n").split("\n"))

        self._header["example"] = example

        # Get full description: strip example and take whatever is left
        text = self._strip(EXAMPLE, text)
        self._header["full_description"] = text.strip()

    def _parseParamSection(self, text):
        "Parses parameter section and populates input and output parameters of header"
        # Get output parameters first!
        outputtext = self._sectionText(OUTPUT_PARAMS, text, flags=re.DOTALL | re.IGNORECASE)
        filteredtext = self._strip(OUTPUT_PARAMS, text)

        # ... and then input parameters
        inputtext = self._sectionText(INPUT_PARAMS, filteredtext, flags=re.DOTALL | re.IGNORECASE)

        self._parseInputSubsection(inputtext)
        self._parseOutputSubsection(outputtext)

    def _parseInputSubsection(self, text):
        "Parses input text and populates input parameters"
        self._inputparams = self._populateParams(IOPARAM, text)
        self._header["input_parameters"] = self._inputparams

    def _parseOutputSubsection(self, text):
        "Parses output text and populates output parameters"
        self._outputparams = self._populateParams(IOPARAM, text)
        self._header["output_parameters"] = self._outputparams

    def _populateParams(self, paramregex, text):
        "Populates dictionary of parameters"
        params = {}
        lines = text.split("\n")

        for l in lines:
            l = l.strip()
            if l == "":
                continue  # Skip empty line

            p = re.compile(paramregex)
            m = p.match(l)

            if m:
                (param, value) = (m.group(1).strip(), m.group(2).strip())
                # XXX: What if value has '\n'?
                if not param:
                    continue

                params[param] = value

        return params

    def _headerEnd(self, origText):
        "Returns end position of the header"
        p = re.compile(COMMENT, re.DOTALL)
        ss = p.search(origText)
        return ss.end()
Beispiel #10
0
 def __init__(self, name):
     """
         name: (str) -- Name of the namelist in lower case. Example: "control"
     """
     self._name = name.lower()  # keeps lower name
     self._params = OrderedDict()  # Replace dictionary by ordered dictionry
Beispiel #11
0
class Namelist(Block):
    def __init__(self, name):
        """
            name: (str) -- Name of the namelist in lower case. Example: "control"
        """
        self._name = name.lower()  # keeps lower name
        self._params = OrderedDict()  # Replace dictionary by ordered dictionry

    def get(self, param, quotes=True):
        """
        Returns paramater value. If no parameter exists, return None.
        When quotes=True quotes are not added to parameter's value.

            param: (str) -- Parameter of the namelist
            quotes: (bool) -- True - if add quotes '' to parameters value,
                              False - otherwise

        Note: replaces param()
        """
        if not self._paramExists(param):
            return None

        param = param.lower()
        if quotes:
            return self._params[param]

        return self._unquote(self._params[param])

    def set(self, param, val, quotes=False):
        """
        Sets existing parameter to the specified value.
        If no parameter exists, create one
        
            param: (str) -- Parameter name
            val: (str) -- Parameter value
            quotes: (bool) -- Add quotes to the value or not
        """
        param = param.lower()
        if quotes:
            val = self._quote(val)

        self._params[param] = val

    # TODO: Rename to params() in the future
    def paramlist(self):
        """
        Returns list of parameter names
        """
        return self._params.keys()

    def remove(self, param):
        """
        Deletes parameter

            param: (str) -- Name of the parameter
        """
        if self._paramExists(param):
            del (self._params[param])

    def exists(self, param):
        """
        Checks if parameter exists in the namelist

            param: (str) -- Name of the parameter
        """
        return self._paramExists(param)

    def _quote(self, val):
        """
        Quotes value with "'" quote mark

            val: (str) -- Value to be quoted
        """
        return "'" + val.strip('"').strip("'") + "'"

    def _unquote(self, val):
        """
        Removes quotes "'" (unquotes) on both sides of the string

            val: (str) -- Value to be unquoted
        """
        return val.strip('"').strip("'")

    def toString(self, indent=4, br="\n"):
        """
        Dumps namelist as a sting
        
            indent: (int) -- Number of spaces in indent for parameters
            br: (str) -- Separator between parameters
        """
        ind = ""
        for i in range(indent):  # Populate indent
            ind += " "

        s = "&%s%s" % (self.name().upper(), br)

        for p in self._params.keys():
            s += "%s%s = %s,%s" % (ind, p, self._params[p], br)

        s += "/%s" % br
        return s

    def _paramExists(self, param):
        """
        Checks if parameter exists in self._params

            param: (str) -- Name of the parameter
        """
        try:
            param = param.lower()
            self._params[param]
            return True
        except KeyError:  # parameter is not present
            return False

    # DEPRICATED METHODS:
    # DEPRICATED: Use get() instead
    def param(self, param, quotes=True):
        return self.get(param, quotes)

    # DEPRICATED: Use set() instead!
    def add(self, param, val, quotes=False):
        self.set(param, val, quotes)

    # DEPRICATED: Use set() instead!
    def editParam(self, param, val):
        self.set(param, val)

    # DEPRICATED: Use set() instead!
    def addParam(self, param, val):
        self.add(param, val)

    # DEPRICATED: Use remove() instead!
    def removeParam(self, param):
        self.remove(param)
Beispiel #12
0
class QEInput(object):
    def __init__(self, filename=None, config=None, type="pw", parse=True):
        """
        Initializes QEInput by passing either filename or config (not both)
        parameters
        
            filename:   (str) -- Absolute or relative filename of file to be parsed
            config:     (str) -- Configuration text to be parsed
            type:       (str) -- Type of the simulation
        """
        self.filename = filename
        self.config = config
        self._type = type.lower()
        self.filters = []
        self.header = None
        self.namelists = OrderedDict()
        self.cards = OrderedDict()
        self.attach = None  # Specific for 'matdyn', 'dynmat', etc.
        self.qe = None  # DEPRICATED
        self.namelistRef = None
        self.cardRef = None

        self._read(filename, config, parse)

    def parse(self):
        """
        Parses the configuration file and stores the values in qe dictionary
        """
        (self.header, self.namelists, self.cards, self.attach) = self.parser.parse()

    def namelist(self, name):
        """
        Returns namelist and adds to self.namelists. Return namelist if it exists.

            name: (str) -- Name of the new namelist
        """
        # If namelist with the name exists, then return it
        name = name.lower()
        if self.namelistExists(name):
            return self.namelists[name]

        return self._createNamelist(name)

    def removeNamelist(self, name):
        """
        Removes namelist if it exists or ignore otherwise

            name: (str) -- Name of the existing namelist
        """
        name = name.lower()
        try:
            del (self.namelists[name])
        except KeyError:  # parameter is not present
            return

    def setNamelist(self, namelist):
        """
        Sets/replaces namelist for self.namelists. It overwrites namelist if it exists
        already. So you this method with caution.

            namelist: (object: Namelist) -- Namelist object
        """
        if not namelist:  # No namelist, just ignore it!
            return

        self.namelists[namelist.name()] = namelist

    def namelistExists(self, name):
        """
        Checks if namelist specified by name (lowered before) exists

            name: (str) -- Name of the namelist
        """
        return self._exists(name, self.namelists.keys())

    def setCard(self, card):
        """
        Adds card to self.cards
        
            card: (object: Card) -- Card object
        """
        if not card:
            return

        self.cards[card.name()] = card

    def removeCard(self, name):
        """
        Remove card if it exists or ignore otherwise

            name: (str) -- Name of the existing card
        """
        name = name.lower()
        try:
            del (self.cards[name])
        except KeyError:  # parameter is not present
            return

    # XXX: Make self.attach protected first!
    #    def attach(self):
    #        "Returns attachment"
    #        return self.attach

    def addAttach(self, text):
        """
        Sets attachment to text. If attachment is not None it still will be
        overwritten

            text: (str) -- Attachment text, usually is appended to the end of the
                            configuration file
        """
        self.attach = text

    def removeAttach(self):
        "Sets attachment to None"
        self.attach = None

    def card(self, name):
        """
        Returns card specified by name if exists or create a new one
        """
        name = name.lower()
        if self.cardExists(name):  # If exists, return card
            return self.cards[name]

        return self._createCard(name)

    def cardExists(self, name):
        "Checks if card specified by name exists"
        return self._exists(name, self.cards.keys())

    def getObject(self, name, dict):
        """
        Returns object specified by name
        
            name: (str) -- Name that identifies an object through name() method
            dict: (dict) -- Dictionary that stores objects as {name: object}
        """
        if not name or not dict:
            return None

        for n in dict.values():
            if n.name() == name:
                return dict[name]

        return None

    def save(self, filename=None):
        """
        Saves the QEInput structure to the configuration file

            filename: (str) -- File name where the configuration is stored to
        """
        default = "config.out"

        if filename is None:
            if self.filename is not None:
                filename = self.filename
            else:
                filename = default

        f = open(filename, "w")
        f.write(self.toString())
        f.close()

    def type(self):
        "Returns type of the configuration file"
        return self._type

    def applyFilter(self, filter, type=POSITIVE):
        """
        Applies filter to the QEInput

            filter: (object: Filter) -- Filter that applies changes to QEInput
        """
        if not filter:  # No filter, just ignore it
            return None

        filter.apply(self, type)  # Apply filter to QEInput
        self.filters.append(filter)

    def toString(self):
        """
        Dumps QEInput structure to string
        """
        s = ""
        if self.header:  # Add header
            s += "%s\n" % self.header

        for name in self.namelistRef:  # Add namelists
            nl = self.getObject(name, self.namelists)
            if nl is not None:
                s += nl.toString()

        for name in self.cardRef:  # Add cards
            c = self.getObject(name, self.cards)
            if c is not None:
                s += c.toString()

        if self.attach:  # Add attribute (e.g. for type='matdyn')
            s += self.attach

        return s

    def structure(self):
        """
        Returns basic atomic structure information as list of tuples.
        Specific for 'pw' type

        Example: [('Ni', '52.98', 'Ni.pbe-nd-rrkjus.UPF'), (...)]
        """
        # Extract structure not from pw type input. Hard to do it from other types
        if self._type != "pw":
            return None

        list = []  # list of structure
        card = self.card("atomic_species")

        for l in card.lines():  # Should have format: "<Label> <Mass> <Pseudo-Potential>"
            l = l.strip()
            if l == "":  # Empty line
                continue
            list.append(l.split())

        return list

    def readFile(self, filename):
        """
        Reads and parses configuration input from file
            filename: (str) -- File name
        """
        self.filename = filename
        self._read(filename=filename)

    def readString(self, config):
        """
        Reads and parses configuration input from string
            config: (str) -- Configuration string
        """
        self.config = config
        self._read(config=config)

    def _read(self, filename=None, config=None, parse=True):
        "Reads and parses configuration input specified by kwds parameters"
        self.parser = QEParser(filename, config, self._type)  # filename, config, type)
        (self.namelistRef, self.cardRef) = self.parser.setReferences()

        if parse and (filename or config):
            QEInput.parse(self)  # Avoid calling method parse() from subclass

        self.qe = [self.header, self.namelists, self.cards, self.attach]

    def _exists(self, name, list):
        "Checks if lowered name is in the list"
        if not name:
            return False

        name = name.lower()
        if name in list:
            return True

        return False

    def _createCard(self, name):
        """
        Creates a new card

            name: (str) -- Name of the card
        """
        if not name in self.cardRef:  # If not standard card, ignore it
            return None

        card = Card(name)
        self.cards[name] = card
        return card

    def _createNamelist(self, name):
        """
        Creates namelist specified by name

            name: (str) -- Name of the namelist
        """
        if not name in self.namelistRef:  # If not standard card, ignore it
            return None

        # Otherwise create a new namelist
        nl = Namelist(name)
        self.namelists[name] = nl
        return nl

    # DEPRICATED: Use namelist() instead
    def createNamelist(self, name):
        return namelist(name)

    # DEPRICATED: Use card() instead
    def createCard(self, name):
        return card(name)

    # DEPRICATED: Use setNamelist() instead
    def addNamelist(self, namelist):
        self.setNamelist(namelist)

    # DEPRICATED: Use setCard() instead
    def addCard(self, card):
        self.setCard(card)
Beispiel #13
0
class QEParser:
    """
    Flexible Parser for Quantum Espresso (QE) configuration files.
    
    It parses the file specified by filename or configuration string and stores
    parameters in namelists, cards and attachment data
    structures that later on can be used in parameters' manipulations
    """

    def __init__(self, filename=None, configText=None, type="pw"):
        """
        Parameters:
            filename    -- absolute or relative filename to be parsed
            configText  -- configuration text to be parsed
            type        -- type of the simulation
            os          -- operating system defined for carriage return
        """

        self.header = None
        self.namelists = OrderedDict()  # Namelist dictionary
        self.cards = OrderedDict()  # Cards dictionary
        self.attach = None
        self.filename = filename
        self.configText = configText
        self.namelistRef = None
        self.cardRef = None
        self.type = type

    def parse(self):
        """Parses string and returns namelists, cards, attachment and header"""
        self.setReferences()

        if self.configText is not None:  # First try use configText
            text = self.configText
        elif self.filename is not None:  # ... then from file
            text = self._getText(self.filename)
        else:
            raise NameError("Dude, set config text or filename")  # Compalain

        self._parseHeader(text)
        self._parseNamelists(text)
        self._parseAttach(text)
        self._parseCards(text)

        return (self.header, self.namelists, self.cards, self.attach)

    def toString(self):
        """Returns string of parsed values"""

        s = ""
        if self.header:
            s += self.header

        for n in self.namelists.keys():
            s += self.namelists[n].toString()

        for c in self.cards.keys():
            s += self.cards[c].toString()

        if self.attach:
            s += self.attach

        return s

    def setReferences(self):
        """Sets reference names for namelists and cards for specified simulation type"""

        input = "input%s" % self.type
        module = _import("inputs.%s" % input)
        self.namelistRef = getattr(module, "namelists")
        self.cardRef = getattr(module, "cards")

        return (self.namelistRef, self.cardRef)

    def _parseHeader(self, text):
        """Cuts the first line if it header"""
        start = self._namelistStart(text)
        if start is not None and start == 0:
            return  # There is no header

        lines = text.splitlines(True)
        if lines:
            self.header = lines[0]

    def _parseNamelists(self, text):
        """Parses text and populates namelist dictionary"""

        namelists = OrderedDict()
        s1 = self._removeComments(text)
        p2 = re.compile(NAMELIST)
        matches = p2.findall(s1)  # Finds all namelist blocks

        for m in matches:
            name = m[0].lower()
            if name in self.namelistRef:
                params = self._parseParams(m[1])  # Parse parameters from a namelist block
                namelists[name.lower()] = params

        self._convertNamelists(namelists)

    def _removeComments(self, text):
        """Removes comments from the text"""
        p = re.compile(COMMENT)
        return re.sub(p, "", text)

    def _convertNamelists(self, namelists):
        """Converts dictionary to Namelist"""
        for name in namelists.keys():
            nl = Namelist(name)
            for p in namelists[name]:
                nl.add(p[0], p[1])

            self.namelists[name] = nl

    def _parseParams(self, text):
        """Parses parameters"""
        params = []
        p = re.compile(EXPRESSION)  # Match expression
        matches = p.findall(text)
        for m in matches:
            pl = self._getParams(m)  # Parameters list
            params.append(pl)

        return params

    def _getParams(self, text):
        """ Takes string like 'a = 2' and returns tuple ('a', 2) """
        s = text.split("=")
        for i in range(len(s)):
            s[i] = s[i].strip()

        param = s[0]
        val = s[1]
        # Assume that there are two values only: (variable, value) pair
        assert len(s) == 2

        return (param, val)

    def _parseAttach(self, text):
        """Special case for simulations that have attachments"""

        if self.type in ATTACHSIM:
            self.attach = self._cutNamelistText(text)

    def _parseCards(self, text):
        """Parses text and populates cards dictionary"""
        if self.type in ATTACHSIM:  # There should not be cards for simulations with attachment
            return

        s = self._cutNamelistText(text)
        self._convertCards(self._getCards(self._rawlist(s)))

    def _cutNamelistText(self, text):
        """Cuts the namelist text"""
        s = text
        end = self._namelistEnd(text)

        if end is not None:
            s = text[end + 1 :]  # Suppose that cards and attachmet starts with new line

        return s

    def _rawlist(self, text):
        """Removes empty lines"""
        rawlist = []

        s = text.splitlines(True)
        for line in s:
            line = line.strip()
            if line != "":
                rawlist.append(line)  # rawlist contains both cardnames and card lines in order

        return rawlist

    def _getCards(self, rawlist):
        cards = OrderedDict()
        cardName = None
        for l in rawlist:
            isCardName = False
            p = re.compile(CARD)
            m = p.match(l)
            if m is not None:  # If card name matches
                firstPart = m.group(1).lower()
                secondPart = m.group(2).strip().lower()  # Catch argument of the card
                if firstPart in self.cardRef:
                    isCardName = True
                    cardName = firstPart
                    cards[cardName] = {}

                    if secondPart != "":
                        cards[cardName]["args"] = secondPart
                    else:
                        cards[cardName]["args"] = None
                    cards[cardName]["values"] = []

            if cardName is not None and not isCardName:
                cards[cardName]["values"].append(l)

        return cards

    def _convertCards(self, cards):
        for cname in cards.keys():
            c = Card(cname)
            c.setArg(cards[cname]["args"])
            for l in cards[cname]["values"]:
                c.addLine(l)

            self.cards[cname] = c

    def _namelistStart(self, text):
        """Returns the start character position of the first namelist in the text"""
        s = self._removeComments(text)
        p = re.compile(NAMELIST)
        matches = p.finditer(s)  # Finds all namelist blocks
        starts = []

        for m in matches:
            starts.append(m.start())

        if len(starts):
            return starts[0]  # Get first value

        return None

    def _namelistEnd(self, text):
        """Returns the end character position of the last namelist in the text"""
        s = self._removeComments(text)
        p = re.compile(NAMELIST)
        matches = p.finditer(s)  # Finds all namelist blocks
        ends = []

        for m in matches:
            ends.append(m.end())

        size = len(ends)
        if size:
            return ends[size - 1]  # Get last position value

        return None

    def _getText(self, filename):
        try:
            f = open(filename)
        except IOError:
            print "I/O error"
        except:
            import sys

            print "Unexpected error:", sys.exc_info()[0]
            raise

        text = f.read()
        f.close()

        return text
Beispiel #14
0
 def __init__(self, name):
     self.__name = name.lower()  # keeps lower name
     self.params = OrderedDict()  # Replace dictionary by ordered dictionry
Beispiel #15
0
class Namelist:
    """Namelist class that corresponds to Namelist in QE config file"""

    def __init__(self, name):
        self.__name = name.lower()  # keeps lower name
        self.params = OrderedDict()  # Replace dictionary by ordered dictionry

    def name(self):
        return self.__name

    def setName(self, name):
        self.__name = name.lower()

    def param(self, param):
        """Returns value of parameter 'param'"""
        if self.__paramExists(param):
            return self.params[param]

    def add(self, param, val):
        # Replaces addParam() Add verification?
        param = param.lower()
        self.params[param] = val

    def set(self, param, val):
        #  Replaces editParam() and addParam(). Merge with add()?
        """Edits parameter. If it doesn't exist, it just ignores it """
        if self.__paramExists(param):
            self.params[param] = val

    def remove(self, param):
        """Deletes parameter"""
        if self.__paramExists(param):
            del (self.params[param])

    def __paramExists(self, param):
        try:
            param = param.lower()
            self.params[param]
            return True
        except KeyError:  # parameter is not present
            return False

    def toString(self, indent="    ", br="\n"):
        # Dump namelist
        # Should I use space?
        s = "&%s%s" % (self.name().upper(), br)

        for p in self.params.keys():
            s += "%s%s = %s,%s" % (indent, p, self.params[p], br)

        s += "/%s" % br
        return s

    # Depricated methods:
    # Depricated
    def addParam(self, param, val):
        self.add(param, val)

    # Depricated
    def editParam(self, param, val):
        self.set(param, val)

    # Depricated
    def removeParam(self, param):
        self.remove()