def __init__(self, filename=None, configText=None, type='pw'): self.namelists = OrderedDict() self.cards = OrderedDict() self.attach = None self.filename = filename self.configText = configText self.namelistRef = None self.cardRef = None self.type = type
def __init__(self, filename=None, config=None, type='pw'): self.filename = filename self.config = config self.parser = QEParser(filename, config, type) self.type = type self.namelists = OrderedDict() self.cards = OrderedDict() self.attach = None # Specific for 'matdyn' self.namelistRef = None self.cardRef = None self.qe = [self.namelists, self.cards, self.attach]
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 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 = self.ntyp = None self.filename = self.qeConf.filename self.optConstraints = [] if 'system' in self.qeConf.namelists: self.nat = int(self.qeConf.namelist('system').param('nat')) self.ntyp = int(self.qeConf.namelist('system').param('ntyp')) if 'atomic_positions' in self.qeConf.cards: 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: if 'atomic_species' in self.qeConf.cards: atomicSpeciesLines = self.qeConf.card('atomic_species').lines() for line in atomicSpeciesLines: if '!' not in line: if line.strip() != '': atomicSpeciesWords = line.split() element = atomicSpeciesWords[0] mass = 0 ps = '' if len(atomicSpeciesWords) > 1 : mass = float(atomicSpeciesWords[1]) if len(atomicSpeciesWords) > 2: ps = atomicSpeciesWords[2] self.atomicSpecies[element] = AtomicSpecies(element, mass, ps)
def _get_atomicSpecies(self): atomicSpecies = OrderedDict() for a in self: atomicSpecies[a.element] = AtomicSpecies(element = a.element, \ mass = a.mass, potential = a.potential) return atomicSpecies
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 _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 __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()
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 """ 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 generate(): inp = open("pseudo.list") # Generate structure pseudo = OrderedDict() str = inp.read() pseudolist = str.split() for name in pseudolist: l = label(name) if l not in pseudo.keys(): # key does not exist pseudo[l] = [] pseudo[l].append(name) out = open("pseudo.py", "w") out.write(toString(pseudo)) inp.close() out.close() print "Done!"
def returnError(metadataName, rootName, duration, message): metadatadict = OrderedDict([("duration", str(duration)), ("error", message), ("idProperty", None), ("successProperty", 'success'), ("totalProperty", 'recordCount'), ("success", False), ("recordCount", 0), ("root", None), ("fields", None)]) responsejson = json.dumps(dict([(metadataName, metadatadict), (rootName, None)]), indent=1) return getJsonResponse(responsejson)
def getValuesForPoint(sceneid, x, y, crs): try: authenticate() lng, lat = utilities.getPointLL(x, y, crs) scene = ee.Image(sceneid) collection = ee.ImageCollection(scene) data = collection.getRegion(ee.Geometry.Point(lng, lat), 30).getInfo() if len(data) == 1: raise GoogleEarthEngineError("No values for point x:" + str(x) + " y: " + str(y) + " for sceneid: " + sceneid) return OrderedDict([(data[0][i], data[1][i]) for i in range (len(data[0]))]) except (EEException, GoogleEarthEngineError): return "Google Earth Engine Error: " + str(sys.exc_info())
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 __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 _parseNamelists(self, text): namelists = OrderedDict() p = re.compile(COMMENT) s1 = re.sub(p, '', text) # Remove comments 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 _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 __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.qeConf.parse() #self.setStructureFromQEInput() self.lattice = None self.structure = None self.nat = None self.ntyp = None
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 __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
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, quotes = True): """Returns value of parameter 'param'""" if self.__paramExists(param): if quotes: return self.params[param] else: return self._unquote(self.params[param]) return self.params[param] return None def add(self, param, val, quotes = False): # Replaces addParam() Add verification? param = param.lower() if quotes: val = self._quote(val) self.params[param] = val def set(self, param, val, quotes = False): # Replaces editParam() and addParam(). Merge with add()? """Edits parameter. If it doesn't exist, it just ignores it """ if self.__paramExists(param): if quotes: val = self._quote(val) self.params[param] = val def remove(self, param): """Deletes parameter""" if self.__paramExists(param): del(self.params[param]) def exists(self,param): return self.__paramExists(param) def _quote(self, val): return "'" + val.strip('"').strip("'") + "'" def _unquote(self, val): return val.strip('"').strip("'") 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 def __paramExists(self, param): try: param = param.lower() self.params[param] return True except KeyError: # parameter is not present return False # 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()
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)
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 self.atomicPositionsType = 'crystal' def atomLabels(self): labels = [] for l in self.atomicSpecies: labels.append(l) return labels 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 = self.ntyp = None self.filename = self.qeConf.filename self.optConstraints = [] if 'system' in self.qeConf.namelists: self.nat = int(self.qeConf.namelist('system').param('nat')) self.ntyp = int(self.qeConf.namelist('system').param('ntyp')) if 'atomic_positions' in self.qeConf.cards: 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: if 'atomic_species' in self.qeConf.cards: atomicSpeciesLines = self.qeConf.card('atomic_species').lines() for line in atomicSpeciesLines: if '!' not in line: if line.strip() != '': atomicSpeciesWords = line.split() element = atomicSpeciesWords[0] mass = 0 ps = '' if len(atomicSpeciesWords) > 1 : mass = float(atomicSpeciesWords[1]) if len(atomicSpeciesWords) > 2: ps = atomicSpeciesWords[2] self.atomicSpecies[element] = AtomicSpecies(element, mass, ps) def load(self, source, **args): task = { 'diffpy': self.setStructureFromDiffpyStructure } if source == 'diffpy': if 'ibrav' in args and args['ibrav'] != 0: task['diffpy'] = self.setReducedStructureFromDiffpyStructure task[source](**args) self.updatePWInput(qeConf = self.qeConf) def setStructureFromDiffpyStructure(self, structure, massList = [], psList = [], ibrav = 0): """ structure - diffpy.Structure object ibrav - Lattice index psList - list of strings with pseudopotential names diffpyStructure object will be modified with reduced atomic positions """ diffpyLattice = structure.lattice self.structure = structure #set lattice and convert to bohr units qeLattice = QELattice(ibrav = 0, a = 1.889725989, base = diffpyLattice.base) self.lattice = qeLattice self.lattice.type = 'generic cubic' atomNames = [] for a in structure: if self._element(a) not in atomNames: atomNames.append(self._element(a)) #print atomNames #print len(massList) for i, elem in enumerate(atomNames): if len(massList) - 1 < i: mass = 0 else: mass = massList[i] if len(psList) - 1 < i: ps = '' else: ps = psList[i] self.atomicSpecies[elem] = AtomicSpecies(elem, mass, ps) for atom in structure: self.optConstraints.append([]) # for i, atom in enumerate(structure): # elem = self._element(atom) # if len(massList) - 1 < i: # mass = 0 # else: # mass = massList[i] # if len(psList) - 1 < i: # ps = '' # else: # ps = psList[i] # self.atomicSpecies[elem] = AtomicSpecies(elem, mass, ps) # self.optConstraints.append([]) # for atom, mass, ps in zip(structure, massList, psList): # elem = self._element(atom) # self.atomicSpecies[elem] = AtomicSpecies(elem, mass, ps) # self.optConstraints.append([]) self.nat = len(structure) self.ntyp = len(self.atomicSpecies) def setReducedStructureFromDiffpyStructure(self, structure, ibrav, massList = [], psList = []): """ structure - diffpy.Structure object ibrav - Lattice index psList - list of strings with pseudopotential names diffpyStructure object will be modified with reduced atomic positions """ #self.atomicSpecies = OrderedDict() #self.optConstraints = [] #self.atomicPositionsType = 'crystal' diffpyLattice = structure.lattice a = diffpyLattice.a b = diffpyLattice.b c = diffpyLattice.c cAB = cosd(diffpyLattice.gamma) cBC = cosd(diffpyLattice.alpha) cAC = cosd(diffpyLattice.beta) qeLattice = QELattice(ibrav = ibrav, a = a, b = b, c = c, cBC = cBC, \ cAC = cAC, cAB = cAB) self.lattice = qeLattice # make a deep copy (does not wok now) #reducedStructure = Structure(diffpyStructure) reducedStructure = structure reducedStructure.placeInLattice(Lattice(base=qeLattice.diffpy().base)) # collect atoms that are at equivalent position to some previous atom duplicates = set([a1 for i0, a0 in enumerate(reducedStructure) for a1 in reducedStructure[i0+1:] if self._element(a0) == self._element(a1) and equalPositions(a0.xyz, a1.xyz, eps=1e-4)]) # Filter out duplicate atoms. Use slice assignment so that # reducedStructure is not replaced with a list. reducedStructure[:] = [a for a in reducedStructure if not a in duplicates] self.structure = reducedStructure atomNames = [] for a in reducedStructure: if self._element(a) not in atomNames: atomNames.append(self._element(a)) #print atomNames #print len(massList) for i, elem in enumerate(atomNames): if len(massList) - 1 < i: mass = 0 else: mass = massList[i] if len(psList) - 1 < i: ps = '' else: ps = psList[i] #print mass, ps # atomDict[a] = # for i, atom in enumerate(reducedStructure): # elem = self._element(atom) # if len(massList) - 1 < i: # mass = 0 # else: # mass = massList[i] # if len(psList) - 1 < i: # ps = '' # else: # ps = psList[i] self.atomicSpecies[elem] = AtomicSpecies(elem, mass, ps) for atom in reducedStructure: self.optConstraints.append([]) # convert to bohr units self.lattice.setLattice(ibrav, self.lattice.a*1.889725989, \ self.lattice.b*1.889725989, self.lattice.c*1.889725989) self.nat = len(reducedStructure) self.ntyp = len(self.atomicSpecies) # use rstrip to avoid duplicate line feed #print reducedStructure.writeStr(format='discus').rstrip() #print reducedStructure.writeStr(format='discus') #print reducedStructure.writeStr().rstrip() #print reducedStructure #self.lattice = setLatticeFromDiffpyLattice(structure.lattice, ibrav) # 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%(atom.xyz[0], atom.xyz[1], atom.xyz[2]) # else: # raise NonImplementedError # s = s + '%-3s'%self._element(atom) + ' ' + coords + ' ' \ # + str(constraint)[1:-1] + '\n' # s = s + '\n' # for element, specie in self.atomicSpecies.items(): # s = s + specie.toString() + '\n' # return s def toString(self, string = None): if string != None: string = self.lattice.toString(string = string) qeConf = QEInput(config = string) qeConf.parse() else: if self.qeConf != None: qeConf = self.qeConf else: qeConf = QEInput(config = '') self.updatePWInput(qeConf) return qeConf.toString() def updatePWInput(self, qeConf = None): if qeConf == None: qeConf = self.qeConf self.lattice.updatePWInput(qeConf) if 'system' not in qeConf.namelists: qeConf.addNamelist('system') qeConf.namelist('system').remove('ntyp') qeConf.namelist('system').remove('nat') if self.ntyp != None: qeConf.namelist('system').add('ntyp', self.ntyp) if self.nat != None: qeConf.namelist('system').add('nat', self.nat) if len(qeConf.namelist('system').params) == 0: qeConf.removeNamelist('system') 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'%self._element(atom) + ' ' + coords + ' ' + str(constraint)[1:-1] qeConf.card('atomic_positions').addLine(line) if len(qeConf.card('atomic_positions').lines()) == 0: qeConf.removeCard('atomic_positions') # 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()) if len(qeConf.card('atomic_species').lines()) == 0: qeConf.removeCard('atomic_species') def save(self, fname = None): """Writes/updates structure into PW config file, if the file does not exist, new one will be created""" filename = fname if fname != None: 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 def _element(self, atom): """ Is needed for suport both diffpy and matter classess """ if 'element' in dir(atom): return atom.element else: if 'symbol' in dir(atom): return atom.symbol else: raise
def getQueryStringParams(querystring): return OrderedDict([(q.split("=")[0], urllib.unquote(q.split("=")[1])) for q in querystring.split("&")])
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 (specific for matdyn) data structures that later on can be used in parameters' manipulations """ def __init__(self, filename=None, configText=None, type='pw'): self.namelists = OrderedDict() self.cards = OrderedDict() self.attach = None self.filename = filename self.configText = configText self.namelistRef = None self.cardRef = None self.type = type def parse(self): self.getReferences() 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._parseNamelists(text) self._parseCards(text) return (self.namelists, self.cards, self.attach) def toString(self): for n in self.namelists.keys(): print self.namelists[n].toString() for c in self.cards.keys(): print self.cards[c].toString() if self.attach: print self.attach def getReferences(self): 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 _parseNamelists(self, text): namelists = OrderedDict() p = re.compile(COMMENT) s1 = re.sub(p, '', text) # Remove comments 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) # Converts from dictionary to Namelist def _convertNamelists(self, namelists): for name in namelists.keys(): nl = Namelist(name) for p in namelists[name]: nl.add(p[0], p[1]) self.namelists[name] = nl # Parses parameters def _parseParams(self, text): 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 _parseCards(self, text): p = re.compile(COMMENT) s1 = re.sub(p, '', text) # Remove comments p2 = re.compile(NAMELIST) s2 = re.sub(p2, '', s1) # Remove namelists # Special case for 'matdyn' if self.type == 'matdyn': self.attach = s2.strip() return rawlist = [] p = re.compile(EMPTY_LINE) s = s2.split('\n') for line in s: line = line.strip() if line != '': rawlist.append( line ) # rawlist contains both cardnames and card lines in order self._convertCards(self._getCards(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 _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
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 """ 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) s = re.sub(p, '', text) return self._removeEmptyLines(s) 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 = self._removeComments(text) end = self._namelistEnd(s) if end is not None: s = s[end + 1:] # Suppose that cards and attachmet starts with new line return s def _rawlist(self, text): """Removes empty lines or lines with white spaces only""" rawlist = [] s = text.splitlines(True) for line in s: stripped = line.strip() if stripped != '': rawlist.append(line) # rawlist contains both cardnames and card lines in order return rawlist def _removeEmptyLines(self, text): """Joins non empty lines or lines with white spaces only in the list to one string""" return ''.join(self._rawlist(text)) 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 Notes: - text should be clear from comments (filtered by _removeComments(text)), otherwise the end character of the last namelist will be incorrect """ 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
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()
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()
#!/usr/bin/env python # Autogenerated script by pseudo-generator.py from orderedDict import OrderedDict PSEUDO = OrderedDict() PSEUDO["Ag"] = ( "Ag.pbe-d-rrkjus.UPF", "Ag.pz-d-rrkjus.UPF", ) PSEUDO["Al"] = ( "Al.blyp-n-van_ak.UPF", "Al.bp-n-van_ak.UPF", "Al.pbe-n-van.UPF", "Al.pbe-rrkj.UPF", "Al.pbe-sp-van.UPF", "Al.pw91-n-van.UPF", "Al.pz-vbc.UPF", ) PSEUDO["Ar"] = ("Ar.pz-rrkj.UPF", ) PSEUDO["As"] = ( "As.pbe-n-van.UPF", "As.pw91-n-van.UPF", "As.pz-bhs.UPF", ) PSEUDO["Au"] = ( "Au.blyp-van_ak.UPF", "Au.bp-van_ak.UPF",
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)
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
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.qeConf.parse() #self.setStructureFromQEInput() self.lattice = None self.structure = None self.nat = None self.ntyp = None def parseInput(self): self.setStructureFromQEInput() def parseOutput(self, pwscfOutputFile): self.setStructureFromPWOutput(pwscfOutputFile) # def _parseAtomicPositions(self, pwscfOut): # for n in range(self.nat): # words = pwscfOut[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)) # print numpy.array(coords[0:3])*a_0 # coords = self.lattice.matter().fractional(numpy.array(coords[0:3])*a_0) # self.structure.addNewAtom(atomSymbol, xyz = numpy.array(coords[0:3])) 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 = QELattice(ibrav = ibrav, base = latticeVectors) if 'site n. atom positions (a_0 units)' in line: self.structure = Structure(lattice = self.lattice.matter()) 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.matter().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 = QELattice(ibrav = ibrav, base = latticeVectors) print self.lattice.matter().base if 'ATOMIC_POSITIONS (alat)' in line: self.structure = Structure(lattice = self.lattice.matter()) 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)) #print numpy.array(coords[0:3])*a_0 coords = self.lattice.matter().fractional(numpy.array(coords[0:3])*a_0) self.structure.addNewAtom(atomSymbol, xyz = numpy.array(coords[0:3])) #self.lattice.ibrav = ibrav #print 'Output structure from output file: ', self.toString() def setStructureFromQEInput(self): """ Loads structure from PWSCF config file""" self.atomicSpecies = OrderedDict() self.lattice = QELattice(qeConf = self.qeConf) self.structure = Structure(lattice = self.lattice.matter()) 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.matter().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.matter().cartesian(atom.xyz)/self.lattice.a coords = self.formatString%(coords[0], coords[1], coords[2]) #coords = str(coords/self.lattice.a)[1:-1] else: if self.atomicPositionsType == 'crystal': #coords = str(atom.xyz)[1:-1] 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.matter().cartesian(atom.xyz)/self.lattice.a coords = self.formatString%(coords[0], coords[1], coords[2]) else: if self.atomicPositionsType == 'crystal': #coords = str(atom.xyz)[1:-1] coords = self.formatString%(atom.xyz[0], atom.xyz[1], atom.xyz[2]) else: raise NonImplementedError line = '%-3s'%atom.element + ' ' + coords + ' ' + str(constraint)[1:-1] # line = 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 #qeConf.parse() self.updatePWInput(qeConf ) qeConf.save(filename) def diffpy(self): return self.structure
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 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 = QELattice(ibrav = ibrav, base = latticeVectors) if 'site n. atom positions (a_0 units)' in line: self.structure = Structure(lattice = self.lattice.matter()) 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.matter().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 = QELattice(ibrav = ibrav, base = latticeVectors) print self.lattice.matter().base if 'ATOMIC_POSITIONS (alat)' in line: self.structure = Structure(lattice = self.lattice.matter()) 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)) #print numpy.array(coords[0:3])*a_0 coords = self.lattice.matter().fractional(numpy.array(coords[0:3])*a_0) self.structure.addNewAtom(atomSymbol, xyz = numpy.array(coords[0:3]))
def _get_atomicSpecies(self): atomicSpecies = OrderedDict() for a in self: atomicSpecies[a.symbol] = AtomicSpecies(symbol = a.symbol, \ mass = a.mass, potential = a.potential) return atomicSpecies
def __init__(self, name): self.__name = name.lower() # keeps lower name self.params = OrderedDict() # Replace dictionary by ordered dictionry
def callservice(conn, schemaname, servicename, querystring): try: t1 = datetime.datetime.now() # log the request logging.basicConfig( filename='../../htdocs/mstmp/REST_Services_Log.log', level=logging.INFO, format='%(asctime)s %(levelname)s %(message)s', ) # logging.info("REST REQUEST: " + web.ctx.home + web.ctx.path + web.ctx.query) # PARSE THE STANDARD OPTIONAL INPUT PARAMETERS # get the input parameters params = getQueryStringParams( querystring ) # the unquoting is to handle encoded parameters (like from extJS - 1,2,3 as a parameter becomes 1%2C2%2C3 # get the standard optional parameters from the url format = params.setdefault('format', 'json') fields = params.setdefault('fields', '').split( "," ) # fields will be passed as an array, e.g. iucn_species_id,wdpa_id includemetadata = params.setdefault('includemetadata', 'true') metadataName = params.setdefault('metadataname', 'metadata') rootName = params.setdefault('rootname', 'records') parseparams = params.setdefault('parseparams', 'true') sortField = params.setdefault('sortfield', '') decimalPlaceLimit = params.setdefault('dplimit', '2') isHadoop = ( 'true' if (servicename[-2:] == '_h') else 'false' ) # if the service is a call to a hadoop method then set a flag # remove the standard optional parameters from the dictionary so we are left with just the parameters required for the function del (params['format'], params['fields'], params['includemetadata'], params['parseparams'], params['metadataname'], params['rootname'], params['sortfield'], params['dplimit']) if 'callback' in params.keys(): del (params['callback']) # check if the service name is valid if not (isValidServiceName(servicename)): raise RESTServicesError('Invalid servicename') # authorise with ecas if needed # if requiresAuthentication(servicename): # if isAuthenticated() == False: # web.ctx.status = '401 Unauthorized' # web.header("Content-Type", "text/html") # return "<html><head></html><body><h1>Authentication required</h1></body></html>" # if it is a Hadoop query then we need to run if first before we actually use the values to get the data from postgresql if (isHadoop.lower() == 'true'): hadoopData = runHadoopQuery(conn, servicename, params) if hadoopData == '[]': hadoopData = '[-1]' servicename = "_" + servicename # now call the postgresql function params.clear() params['species_ids'] = str(hadoopData)[1:-1] # PARSE AND CONVERT THE DATA TYPES OF THE OTHER INPUT PARAMETERS # get all the parameters for the function from postgresql conn.cur.callproc('utils.dopa_rest_getparams', [servicename]) # get the function parameters as a string and split this into a list, e.g. wdpa_id integer, presence_id integer[] --> ['wdpa_id integer', ' presence_id integer[]'] functionparams = conn.cur.fetchone() hasparams = True if functionparams[0] else False if hasparams: functionparams = functionparams[0].split(',') # get the names of the function parameters which are array types arrayparamnames = [ p.strip().split(" ")[0] for p in functionparams if '[' in p ] # convert the array values into lists for key in params.keys(): if key in arrayparamnames: strlist = params[key].split(",") isnum = isNumeric(strlist[0]) if isnum: params[key] = [int(s) for s in strlist] else: params[key] = strlist # get the full list of function parameter names functionparamnames = [ p.strip().split(" ")[0] for p in functionparams ] # check that all parameters are correct invalidparamnames = [ n for n in params.keys() if n not in functionparamnames ] if invalidparamnames and parseparams == 'true': raise RESTServicesError('Invalid parameters: ' + ",".join(invalidparamnames)) # put the input parameters in the right order params = OrderedDict([(n, params[n]) for n in functionparamnames if n in params.keys()]) # GET THE SORT CLAUSE if sortField != "": sortClause = ' ORDER BY "' + sortField + '"' else: sortClause = "" # GET THE FIELDS CLAUSE if fields != ['']: fieldsClause = ",".join(fields) else: fieldsClause = "*" # RUN THE QUERY if hasparams: sql = "SELECT " + fieldsClause + " from " + schemaname + "." + servicename + "(" + ",".join( [n + ":=%(" + n + ")s" for n in params] ) + ")" + sortClause + ";" # run the query using named parameters conn.cur.execute(sql, params) else: sql = "SELECT * from " + schemaname + "." + servicename + "()" + sortClause + ";" conn.cur.execute(sql) rows = conn.cur.fetchall() # PROCESS THE ROWS AND WRITE THEM BACK TO THE CLIENT conn.cur.close() t2 = datetime.datetime.now() # METADATA SECTION OF RESPONSE allfields = [d.name for d in conn.cur.description] if (fields == ['']): fields = allfields fieldcount = len(fields) fieldsdict = [ dict([("name", d.name), ("type", gettypefromtypecode(d.type_code))]) for d in conn.cur.description if (d.name in fields) ] if len(fieldsdict) != len(fields): raise RESTServicesError('Invalid output fields') metadatadict = OrderedDict([ ("duration", str(t2 - t1)), ("error", None), ("idProperty", conn.cur.description[0].name), ("successProperty", 'success'), ("totalProperty", 'recordCount'), ("success", True), ("recordCount", int(conn.cur.rowcount)), ("root", rootName), ("fields", fieldsdict) ]) # RECORDS SECTION OF THE RESPONSE # parse the float values and set the correct number of decimal places according to the decimalPlaceLimit variable - dont include lat/long fields as these must have more decimal places floatColumns = [ i for i, d in enumerate(fieldsdict) if d['type'] == 'float' and d['name'] not in ['lat', 'lng'] ] if len(floatColumns) > 0: for floatColumn in floatColumns: for row in rows: if type(row[floatColumn] ) != NoneType: # check that the data is not null row[floatColumn] = round(row[floatColumn], int(decimalPlaceLimit)) # return the data colsRequired = [allfields.index(field) for field in fields] if format in ['json', 'array']: if format == 'json': recordsdict = [ OrderedDict([(allfields[col], row[col]) for col in range(fieldcount) if (col in colsRequired)]) for row in rows ] else: recordsdict = [[ row[col] for col in range(fieldcount) if (col in colsRequired) ] for row in rows] json.encoder.FLOAT_REPR = lambda f: ( "%.14g" % f ) # this specifies how many decimal places are returned in the json with float values - currently set to 14 - good enough for returning lat/long coordinates if (includemetadata.lower() == 'true'): responsejson = json.dumps(dict([(metadataName, metadatadict), (rootName, recordsdict)]), indent=1, cls=CustomJSONEncoder) else: responsejson = json.dumps(dict([(rootName, recordsdict)]), indent=1, cls=CustomJSONEncoder) return getJsonResponse(responsejson) elif format in ['xml', 'xmlverbose']: root = etree.Element('results') recordsnode = etree.Element(rootName) recordsdicts = [ OrderedDict([ (allfields[col], str(row[col]).decode('utf-8')) for col in range(fieldcount) if (col in colsRequired) and str(row[col]) != 'None' ]) for row in rows ] # if format == 'xml': recordselements = [ etree.Element('record', element) for element in recordsdicts ] for recordelement in recordselements: recordsnode.append(recordelement) else: for recordelement in recordsdicts: record = etree.Element('record') for (n, v) in recordelement.items(): el = etree.Element(n) el.text = v record.append(el) recordsnode.append(record) root.append(recordsnode) web.header("Content-Type", "text/xml") # web.header("Content-Type", "application/Excel") # doesnt work! # web.header("Content-Disposition", "attachment; filename=test.xml") return etree.tostring(root) elif format == 'sms': _twilio = twilio() client = TwilioRestClient( _twilio.twilio_account_sid, _twilio.twilio_auth_token) # use the twilio api account bodystr = 'Hi Andrew - test species data: ' bodystr = bodystr + str(rows[0])[:160 - len(bodystr)] message = client.sms.messages.create(to="+393668084920", from_="+19712647662", body=bodystr) # my mobile return message elif format == 'email': _amazon_ses = amazon_ses() amazonSes = AmazonSES( _amazon_ses.AccessKeyID, _amazon_ses.SecretAccessKey ) # use the amazon simple email service api account message = EmailMessage() message.subject = 'JRC REST Services Information Request' message.bodyHtml = getResultsAsHTML(rows, fieldcount, colsRequired, metadatadict) result = amazonSes.sendEmail('*****@*****.**', '*****@*****.**', message) # to me return result elif format == 'html': htmlData = getResultsAsHTML(rows, fieldcount, colsRequired, metadatadict) web.header("Content-Type", "text/html") return "<html><head></head><body>" + htmlData + "</body></html>" elif format == 'csv': data = [[ row[col] for col in range(fieldcount) if (col in colsRequired) ] for row in rows] colnames = ",".join([f["name"] for f in metadatadict["fields"]]) + "\n" output = colnames + "\n".join([ p for p in [ ",".join(h) for h in [[getStringValue(col) for col in row] for row in data] ] ]) filename = "dataDownload.csv" #hardcoded for now f = open(r'../../htdocs/mstmp/' + filename, 'wb') f.write(output) f.close() web.header("Content-Type", "text/plain") web.header("Content-Disposition", "attachment; filename=%s" % filename) return output elif format == 'pdf': config = pdfkit.configuration( wkhtmltopdf='/usr/local/bin/wkhtmltopdf') web.header("Content-Type", "application/pdf") htmlData = getResultsAsHTML(rows, fieldcount, colsRequired, metadatadict) return pdfkit.from_string(htmlData.decode('utf8'), False, configuration=config, options={ 'quiet': '', 'encoding': "UTF-8" }) else: raise RESTServicesError('Invalid response format: ' + format) except (RESTServicesError, DataError, ProgrammingError, exceptions.TypeError, IndexError, IntegrityError, AmazonError, OperationalError) as e: # web.webapi.internalerror() #returns a internal server error 500 t2 = datetime.datetime.now() msg = "There was an error sending the email. Make sure that the email address has been verified in Amazon Simple Email Services" if type( e) == AmazonError else e.message logging.error(msg + "\n") if type(e) == ProgrammingError: if ("column" in e.message) & ("does not exist" in e.message) & (sortField != ""): msg = "Invalid sortfield parameter: " + sortField return returnError(metadataName, rootName, t2 - t1, msg)
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)
class QEInput(object): """Quantum Espresso configuration class. It can: - Parse existing configuration file - Add, Edit or Remove parameters from/to namelist or card """ # Either filename or config (not both) can be specified def __init__(self, filename=None, config=None, type='pw'): self.header = None self.filename = filename self.config = config self.parser = QEParser(filename, config, type) self.type = type self.namelists = OrderedDict() self.cards = OrderedDict() self.attach = None # Specific for 'matdyn', 'dynmat' self.namelistRef = None self.cardRef = None self.qe = [self.header, self.namelists, self.cards, self.attach] 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 createNamelist(self, name): """Creates namelist and adds to QEInput. """ nl = Namelist(name) self.namelists[name] = nl return nl def addNamelist(self, namelist): """Adds namelist. """ self.namelists[namelist.name()] = namelist def removeNamelist(self, name): try: del (self.namelists[name]) except KeyError: # parameter is not present return def namelist(self, name): "Returns namelist specified by name if exists or create a new one" if self.namelistExists(name): # If exists, return namelist return self.namelists[name] return self.createNamelist(name) # otherwise create a new one def namelistExists(self, name): "Checks if namelist specified by name exists" return self._exists(name, self.namelists.keys()) def createCard(self, name): "Creates card and adds to QEInput. " card = Card(name) self.cards[name] = card return card def addCard(self, card): "Adds card" self.cards[card.name()] = card def removeCard(self, name): try: del (self.cards[name]) except KeyError: # parameter is not present return def attach(self): "Returns attachment" return self.attach def addAttach(self, text): """ Sets attachment to some string. If attachment is not None it still will be overwritten """ 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" 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 that corresponds to 'name'""" for n in dict.values(): if n.name() == name: return dict[name] return None def save(self, filename=None): """ Saves the QEInput to the configuration file""" 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): return self.type def structure(self): """Returns basic structure information as list tuples Example: [('Ni', '52.98', 'Ni.pbe-nd-rrkjus.UPF'), (...)] """ # Hard to extract structure not from pw type input # TODO: Should also have "atomic_species" card 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 toString(self): (self.namelistRef, self.cardRef) = self.parser.setReferences() 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 _exists(self, name, list): if name in list: return True return False
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, quotes=True): """Returns value of parameter 'param'""" if self.__paramExists(param): if quotes: return self.params[param] else: return self._unquote(self.params[param]) return self.params[param] return None def add(self, param, val, quotes=False): "Adds parameter to the namelist" #param = param.lower() # Should be lowered? if quotes: val = self._quote(val) self.params[param] = val def set(self, param, val, quotes=False): # Replaces editParam() and addParam(). Merge with add()? "Sets existing parameter to the specified value. If it doesn't exist, it just ignores it " "" if self.__paramExists(param): if quotes: val = self._quote(val) self.params[param] = val def remove(self, param): """Deletes parameter""" if self.__paramExists(param): del (self.params[param]) def exists(self, param): return self.__paramExists(param) def _quote(self, val): return "'" + val.strip('"').strip("'") + "'" def _unquote(self, val): return val.strip('"').strip("'") 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 def __paramExists(self, param): try: param = param.lower() self.params[param] return True except KeyError: # parameter is not present return False # 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()