def test_molecule_checkpoint_full(): mol1 = load_molecule_g03fchk( pkg_resources.resource_filename(__name__, "../data/test/sterck/aa.fchk")) mol1.set_default_graph() mol1.unit_cell = UnitCell(np.identity(3, float)*25) mol1.symbols = [periodic[n].symbol for n in mol1.numbers] with tmpdir(__name__, 'test_molecule_checkpoint_full') as dn: fn_out = os.path.join(dn, "molecule_checkpoint_full.chk") mol1.write_to_file(fn_out) mol2 = Molecule.read_from_file(fn_out) assert mol1.numbers.shape == mol2.numbers.shape assert abs(mol1.numbers - mol2.numbers).max() == 0 assert mol1.coordinates.shape == mol2.coordinates.shape assert abs(mol1.coordinates - mol2.coordinates).max() < 1e-10 assert mol1.masses.shape == mol2.masses.shape assert abs(mol1.masses - mol2.masses).max() < 1e-10 assert abs(mol1.energy - mol2.energy) < 1e-10 assert mol1.gradient.shape == mol2.gradient.shape assert abs(mol1.gradient - mol2.gradient).max() < 1e-10 assert mol1.hessian.shape == mol2.hessian.shape assert abs(mol1.hessian - mol2.hessian).max() < 1e-10 assert mol1.multiplicity == mol2.multiplicity assert mol1.symmetry_number == mol2.symmetry_number assert mol1.periodic == mol2.periodic assert mol1.graph.edges == mol2.graph.edges assert mol1.title == mol2.title assert mol1.unit_cell.matrix.shape == mol2.unit_cell.matrix.shape assert abs(mol1.unit_cell.matrix - mol2.unit_cell.matrix).max() < 1e-10 assert mol1.unit_cell.active.shape == mol2.unit_cell.active.shape assert (mol1.unit_cell.active == mol2.unit_cell.active).all() assert mol1.symbols == mol2.symbols
def fn(): from molmod import UnitCell context.application.model.file_open("test/input/methane_box22_125.xyz") universe = context.application.model.universe context.application.action_manager.record_primitives = False unit_cell = UnitCell( numpy.identity(3, float) * 22 * angstrom, numpy.ones(3, bool)) primitive.SetProperty(universe, "cell", unit_cell) context.application.main.select_nodes([universe]) AutoConnectPhysical = context.application.plugins.get_action( "AutoConnectPhysical") assert AutoConnectPhysical.analyze_selection() AutoConnectPhysical() context.application.main.select_nodes([universe]) FrameMolecules = context.application.plugins.get_action( "FrameMolecules") assert FrameMolecules.analyze_selection() FrameMolecules() Bond = context.application.plugins.get_node("Bond") for frame in universe.children: for bond in frame.children: if isinstance(bond, Bond): bond.calc_vector_dimensions() assert bond.length < 2 * angstrom
def test_molecule_checkpoint_full(): mol1 = load_molecule_g03fchk("test/input/sterck/aa.fchk") mol1.set_default_graph() mol1.unit_cell = UnitCell(np.identity(3, float) * 25) mol1.symbols = [periodic[n].symbol for n in mol1.numbers] mol1.write_to_file("test/output/molecule_checkpoint_full.chk") mol2 = Molecule.read_from_file("test/output/molecule_checkpoint_full.chk") assert mol1.numbers.shape == mol2.numbers.shape assert abs(mol1.numbers - mol2.numbers).max() == 0 assert mol1.coordinates.shape == mol2.coordinates.shape assert abs(mol1.coordinates - mol2.coordinates).max() < 1e-10 assert mol1.masses.shape == mol2.masses.shape assert abs(mol1.masses - mol2.masses).max() < 1e-10 assert abs(mol1.energy - mol2.energy) < 1e-10 assert mol1.gradient.shape == mol2.gradient.shape assert abs(mol1.gradient - mol2.gradient).max() < 1e-10 assert mol1.hessian.shape == mol2.hessian.shape assert abs(mol1.hessian - mol2.hessian).max() < 1e-10 assert mol1.multiplicity == mol2.multiplicity assert mol1.symmetry_number == mol2.symmetry_number assert mol1.periodic == mol2.periodic assert mol1.graph.edges == mol2.graph.edges assert mol1.title == mol2.title assert mol1.unit_cell.matrix.shape == mol2.unit_cell.matrix.shape assert abs(mol1.unit_cell.matrix - mol2.unit_cell.matrix).max() < 1e-10 assert mol1.unit_cell.active.shape == mol2.unit_cell.active.shape assert (mol1.unit_cell.active == mol2.unit_cell.active).all() assert mol1.symbols == mol2.symbols
def do(self): universe = context.application.cache.node # first make sure the cell is right handed if numpy.linalg.det( universe.cell.matrix) < 0 and universe.cell.active.sum() == 3: new_matrix = universe.cell.matrix.copy() temp = new_matrix[:, 0].copy() new_matrix[:, 0] = new_matrix[:, 1] new_matrix[:, 1] = temp new_cell = UnitCell(new_matrix, universe.cell.active) primitive.SetProperty(universe, "cell", new_cell) # then rotate the unit cell box to the normalized frame: rotation = universe.cell.alignment_a for child in context.application.cache.transformed_children: primitive.Transform(child, rotation) new_cell = UnitCell(numpy.dot(rotation.r, universe.cell.matrix), universe.cell.active) primitive.SetProperty(universe, "cell", new_cell)
def create_pattern(): "Read the atom positions and transform them to the flat coordinates" active, inactive = universe.cell.active_inactive a = universe.cell.matrix[:, active[0]] b = universe.cell.matrix[:, active[1]] c = numpy.cross(a, b) tmp_cell = UnitCell(numpy.array([a, b, c]).transpose()) rotation = tmp_cell.alignment_a return [(atom.number, rotation * atom.get_absolute_frame().t) for atom in iter_atoms([universe])]
def fn(): from molmod import UnitCell context.application.model.file_open("test/input/core_objects.zml") unit_cell = UnitCell(numpy.identity(3, float), numpy.ones(3, bool)) context.application.model.universe.cell = unit_cell WrapCellContents = context.application.plugins.get_action("WrapCellContents") assert WrapCellContents.analyze_selection() WrapCellContents() assert len(context.application.action_manager.undo_stack) == 1 WrapCellContents() # This should not result in an effective thing to happen: assert len(context.application.action_manager.undo_stack) == 1
def __call__(self, f): Universe = context.application.plugins.get_node("Universe") universe = Universe() Folder = context.application.plugins.get_node("Folder") folder = Folder() Atom = context.application.plugins.get_node("Atom") counter = 1 atom_index = 0 for line in f: #if len(line) != 81: # raise FilterError("Each line in a PDB file must count 80 characters, error at line %i, len=%i" % (counter, len(line)-1)) if line.startswith("ATOM"): extra = {"index": atom_index} atom_info = periodic[line[76:78].strip()] try: t = numpy.array([ float(line[30:38].strip()), float(line[38:46].strip()), float(line[46:54].strip()) ]) * angstrom except ValueError: raise FilterError( "Error while reading PDB file: could not read coordinates at line %i." % counter) atom = Atom(name=line[12:16].strip(), number=atom_info.number, transformation=Translation(t), extra=extra) universe.add(atom) atom_index += 1 elif line.startswith("CRYST1"): space_group = line[55:66].strip().upper() if space_group != "P 1": raise FilterError( "Error while reading PDB file: only unit cells with space group P 1 are supported." ) a = float(line[6:15].strip()) * angstrom b = float(line[15:24].strip()) * angstrom c = float(line[24:33].strip()) * angstrom alpha = float(line[33:40].strip()) * numpy.pi / 180 beta = float(line[40:47].strip()) * numpy.pi / 180 gamma = float(line[47:54].strip()) * numpy.pi / 180 universe.set_cell( UnitCell.from_parameters3([a, b, c], [alpha, beta, gamma])) counter += 1 return [universe, folder]
def __call__(self, f): Universe = context.application.plugins.get_node("Universe") universe = Universe() Folder = context.application.plugins.get_node("Folder") folder = Folder() Atom = context.application.plugins.get_node("Atom") counter = 1 atom_index = 0 for line in f: #if len(line) != 81: # raise FilterError("Each line in a PDB file must count 80 characters, error at line %i, len=%i" % (counter, len(line)-1)) if line.startswith("ATOM"): extra = {"index": atom_index} atom_info = periodic[line[76:78].strip()] try: t = numpy.array([ float(line[30:38].strip()), float(line[38:46].strip()), float(line[46:54].strip()) ]) * angstrom except ValueError: raise FilterError("Error while reading PDB file: could not read coordinates at line %i." % counter) atom = Atom( name=line[12:16].strip(), number=atom_info.number, transformation=Translation(t), extra=extra ) universe.add(atom) atom_index += 1 elif line.startswith("CRYST1"): space_group = line[55:66].strip().upper() if space_group != "P 1": raise FilterError("Error while reading PDB file: only unit cells with space group P 1 are supported.") a = float(line[6:15].strip())*angstrom b = float(line[15:24].strip())*angstrom c = float(line[24:33].strip())*angstrom alpha = float(line[33:40].strip())*numpy.pi/180 beta = float(line[40:47].strip())*numpy.pi/180 gamma = float(line[47:54].strip())*numpy.pi/180 universe.set_cell(UnitCell.from_parameters3([a, b, c], [alpha, beta, gamma])) counter += 1 return [universe, folder]
def read_from_file(cls, filename): """Construct a Molecule object from a previously saved checkpoint file Arguments: | ``filename`` -- the file to load from Usage:: >>> mol = Molecule.read_from_file("mol.chk") """ from tamkin.io.internal import load_chk # load the file data = load_chk(filename) # check the names of the fields: mandatory_fields = set([ "numbers", "coordinates", "masses", "energy", "gradient", "hessian" ]) if not set(data.iterkeys()).issuperset(mandatory_fields): raise IOError( "The Checkpoint file does not contain the mandatory fields.") # take the mandatory fields constructor_args = {} for mfield in mandatory_fields: constructor_args[mfield] = data[mfield] # take the optional arguments if present opt_fields = [ "multiplicity", "symmetry_number", "periodic", "title", "symbols" ] for ofield in opt_fields: if ofield in data: constructor_args[ofield] = data[ofield] # take the special optional arguments that need conversion if "edges" in data: graph = MolecularGraph(data["edges"], data["numbers"]) constructor_args["graph"] = graph if "cell_vectors" in data: unit_cell = UnitCell(data["cell_vectors"], data.get("cell_active")) constructor_args["unit_cell"] = unit_cell # construct the molecule object return Molecule(**constructor_args)
def __init__(self, filename): """ Arguments: | ``filename`` -- The file to load. """ self.filename = filename # auxiliary skip function def skip_to(f, linestart): while True: line = f.readline() if line.startswith(linestart): return line if len(line) == 0: return with open(filename) as f: # Unit cell parameters line = skip_to(f, ' DIRECT LATTICE VECTOR COMPONENTS (BOHR)') if line is None: raise FileFormatError('Could not find the lattice vectors') f.readline() f.readline() vectors = [] for i in range(3): line = f.readline() vectors.append([float(word) for word in line.split()[1:]]) vectors = np.array(vectors) self.unit_cell = UnitCell(vectors.transpose()) # Atomic numbers and coordinates line = skip_to(f, ' ATOM CARTESIAN COORDINATES (BOHR)') if line is None: raise FileFormatError('Could not find the atomic coordinates') f.readline() f.readline() f.readline() numbers = [] symbols = [] coordinates = [] while True: line = f.readline() if line.startswith(' *****'): break words = line.split() numbers.append(int(words[1])) symbols.append(words[2]) coordinates.append( [float(words[3]), float(words[4]), float(words[5])]) self.mol = Molecule(np.array(numbers), np.array(coordinates), symbols=symbols, unit_cell=self.unit_cell) # Basis set specification line = skip_to(f, ' VARIATIONAL BASIS SET') if line is None: raise FileFormatError('Could not find the basis set') f.readline() f.readline() f.readline() f.readline() f.readline() f.readline() self.basisset = {} last_basis = None last_contraction = None while True: line = f.readline() if line.startswith(' *****'): break if line.startswith(' '): # add info to the last atomic basis set assert last_basis is not None subshell = line[36:40].strip() if len(subshell) == 0: subshell = last_contraction[0] # add a primitive to the contraction exponent = float(line[40:50]) if subshell == 'S': values = exponent, float(line[50:60]) elif subshell == 'SP': values = exponent, float(line[50:60]), float( line[60:70]) else: values = exponent, float(line[70:80]) last_contraction[1].append(values) else: # define a new contraction last_contraction = (subshell, []) last_basis.append(last_contraction) else: # add new atoms symbol = line.split()[1] if symbol not in self.basisset: last_basis = [] self.basisset[symbol] = last_basis # Compute the total number of basis functions (and orbitals). self.num_basis = 0 subshell_counts = {'S': 1, 'P': 3, 'SP': 4, 'D': 5, 'F': 7, 'G': 9} for symbol, basis in self.basisset.items(): symbol_count = symbols.count(symbol) for subshell, contraction in basis: self.num_basis += symbol_count * subshell_counts[subshell] # Density matrix. line = skip_to(f, ' DENSITY MATRIX DIRECT LATTICE') if line is None: raise FileFormatError('Could not find the density matrix') f.readline() f.readline() f.readline() self.density_matrix = np.zeros((self.num_basis, self.num_basis), float) j0 = 0 while j0 < self.num_basis: f.readline() f.readline() f.readline() for i in range(self.num_basis): line = f.readline() words = line.split()[1:] for j1, word in enumerate(words): self.density_matrix[i, j0 + j1] = float(word) j0 += 10
def do(self): # the indices (n,m) that define the tube, see e.g. the wikipedia page # about nanotubes for the interpretation of these indices: # http://en.wikipedia.org/wiki/Carbon_nanotube n = self.parameters.n m = self.parameters.m periodic_tube = isinstance(self.parameters.tube_length, Undefined) universe = context.application.model.universe def define_flat(): "Reads and converts the unit cell vectors from the current model." # some parts of the algorithm have been arranged sub functions like # these, to reduce the number of local variables in self.do. This # should also clarify the code. active, inactive = universe.cell.active_inactive lengths, angles = universe.cell.parameters a = lengths[active[0]] b = lengths[active[1]] theta = angles[inactive[0]] return (numpy.array([a, 0], float), numpy.array([b * numpy.cos(theta), b * numpy.sin(theta)], float)) flat_a, flat_b = define_flat() def create_pattern(): "Read the atom positions and transform them to the flat coordinates" active, inactive = universe.cell.active_inactive a = universe.cell.matrix[:, active[0]] b = universe.cell.matrix[:, active[1]] c = numpy.cross(a, b) tmp_cell = UnitCell(numpy.array([a, b, c]).transpose()) rotation = tmp_cell.alignment_a return [(atom.number, rotation * atom.get_absolute_frame().t) for atom in iter_atoms([universe])] pattern = create_pattern() def define_big_periodic(): "Based on (n,m) calculate the size of the periodic sheet (that will be folded into a tube)." big_a = n * flat_a - m * flat_b norm_a = numpy.linalg.norm(big_a) radius = norm_a / (2 * numpy.pi) big_x = big_a / norm_a big_y = numpy.array([-big_x[1], big_x[0]], float) big_b = None stack_vector = flat_b - flat_a * numpy.dot( big_x, flat_b) / numpy.dot(big_x, flat_a) stack_length = numpy.linalg.norm(stack_vector) nominator = numpy.linalg.norm(stack_vector - flat_b) denominator = numpy.linalg.norm(flat_a) fraction = nominator / denominator stack_size = 1 while True: repeat = fraction * stack_size if stack_length * stack_size > self.parameters.max_length: break if abs(repeat - round(repeat) ) * denominator < self.parameters.max_error: big_b = stack_vector * stack_size break stack_size += 1 if big_b is None: raise UserError( "Could not create a periodic tube shorter than the given maximum length." ) rotation = numpy.array([big_x, big_y], float) return big_a, big_b, rotation, stack_vector, stack_size, radius def define_big_not_periodic(): "Based on (n,m) calculate the size of the non-periodic sheet (that will be folded into a tube)." big_a = n * flat_a - m * flat_b norm_a = numpy.linalg.norm(big_a) radius = norm_a / (2 * numpy.pi) big_x = big_a / norm_a big_y = numpy.array([-big_x[1], big_x[0]], float) stack_vector = flat_b - flat_a * numpy.dot( big_x, flat_b) / numpy.dot(big_x, flat_a) stack_length = numpy.linalg.norm(stack_vector) stack_size = int(self.parameters.tube_length / stack_length) big_b = stack_vector * stack_size rotation = numpy.array([big_x, big_y], float) return big_a, big_b, rotation, stack_vector, stack_size, radius if periodic_tube: big_a, big_b, rotation, stack_vector, stack_size, radius = define_big_periodic( ) else: big_a, big_b, rotation, stack_vector, stack_size, radius = define_big_not_periodic( ) def iter_translations(): "Yields the indices of the periodic images that are part of the tube." to_fractional = numpy.linalg.inv( numpy.array([big_a, big_b]).transpose()) col_len = int( numpy.linalg.norm(big_a + m * stack_vector) / numpy.linalg.norm(flat_a)) + 4 shift = numpy.dot(stack_vector - flat_b, flat_a) / numpy.linalg.norm(flat_a)**2 for row in xrange(-m - 1, stack_size + 1): col_start = int(numpy.floor(row * shift)) - 1 for col in xrange(col_start, col_start + col_len): p = col * flat_a + row * flat_b i = numpy.dot(to_fractional, p) if (i >= 0).all() and (i < 1 - 1e-15).all(): yield p #yield p, (i >= 0).all() and (i < 1).all() def iter_pattern(): for number, coordinate in pattern: yield number, coordinate.copy() # first delete everything the universe: while len(universe.children) > 0: primitive.Delete(universe.children[0]) # add the new atoms Atom = context.application.plugins.get_node("Atom") if self.parameters.flat: rot_a = numpy.dot(rotation, big_a) rot_b = numpy.dot(rotation, big_b) big_matrix = numpy.array([ [rot_a[0], rot_b[0], 0], [rot_a[1], rot_b[1], 0], [0, 0, 10 * angstrom], ], float) big_cell = UnitCell( big_matrix, numpy.array([True, periodic_tube, False], bool)) primitive.SetProperty(universe, "cell", big_cell) for p in iter_translations(): for number, coordinate in iter_pattern(): coordinate[:2] += p coordinate[:2] = numpy.dot(rotation, coordinate[:2]) translation = Translation(coordinate) primitive.Add( Atom(number=number, transformation=translation), universe) else: tube_length = numpy.linalg.norm(big_b) big_matrix = numpy.diag([radius * 2, radius * 2, tube_length]) big_cell = UnitCell( big_matrix, numpy.array([False, False, periodic_tube], bool)) primitive.SetProperty(universe, "cell", big_cell) for p in iter_translations(): for number, coordinate in iter_pattern(): coordinate[:2] += p coordinate[:2] = numpy.dot(rotation, coordinate[:2]) translation = Translation( numpy.array([ (radius + coordinate[2]) * numpy.cos(coordinate[0] / radius), (radius + coordinate[2]) * numpy.sin(coordinate[0] / radius), coordinate[1], ])) primitive.Add( Atom(number=number, transformation=translation), universe)
from zeobuilder.nodes.reference import SpatialReference from zeobuilder.nodes.vector import Vector from zeobuilder.undefined import Undefined from zeobuilder.gui.fields_dialogs import FieldsDialogSimple, DialogFieldInfo from zeobuilder.zml import dump_to_file, load_from_file import zeobuilder.actions.primitive as primitive import zeobuilder.gui.fields as fields import zeobuilder.authors as authors from molmod import Translation, UnitCell, angstrom import numpy, gtk import StringIO default_unit_cell = UnitCell( numpy.identity(3, float) * 10 * angstrom, numpy.zeros(3, bool)) class GLPeriodicContainer(GLContainerBase): # # Properties # def update_vectors(self): for node in self.children: if isinstance(node, GLReferentBase): node.invalidate_draw_list() node.invalidate_boundingbox_list() def set_cell(self, cell, init=False):
def convert_to_value(self, representation): return UnitCell(self.fields[1].convert_to_value(representation[1]), self.fields[0].convert_to_value(representation[0]))
def convert_to_value(self, representation): lengths, angles = ComposedInTable.convert_to_value( self, representation) return UnitCell.from_parameters3(lengths, angles)
def endElement(self, name): if name == "zml_file": return # now that we have gatherd all information of this tag, create an appropriate object # first find the tags involved in this operation current_tag = self.hierarchy[-1][-1] child_tags = [] if not current_tag.being_processed: current_tag = self.hierarchy[-2][-1] child_tags = self.hierarchy[-1] # do it if name == "str": current_tag.value = str(current_tag.content) elif name == "float": current_tag.value = float(current_tag.content) elif name == "int": current_tag.value = int(current_tag.content) elif name == "bool": temp = current_tag.content.lower().strip() if temp == 'true': current_tag.value = True else: current_tag.value = False elif name == "list": current_tag.value = [tag.value for tag in child_tags] elif name == "dict": current_tag.value = dict((tag.label, tag.value) for tag in child_tags) elif name == "tuple": current_tag.value = tuple(tag.value for tag in child_tags) elif name == "shape": current_tag.value = tuple(int(item) for item in current_tag.content.split()) elif name == "cells": current_tag.value = numpy.array([eval(item) for item in current_tag.content.split()]) elif name == "array": child_dict = dict((tag.name, tag.value) for tag in child_tags) current_tag.value = numpy.reshape(child_dict["cells"], child_dict["shape"]) elif name == "grid": current_tag.value = numpy.reshape(numpy.array([eval(item) for item in current_tag.content.split()]), (int(current_tag.attributes["rows"]), int(current_tag.attributes["cols"]), -1)) elif name == "binary": current_tag.value = StringIO.StringIO() current_tag.content.seek(0) base64.decode(current_tag.content, current_tag.value) elif name == "translation": current_tag.value = Translation(child_tags[0].value) elif name == "rotation": current_tag.value = Rotation(child_tags[0].value) elif name == "transformation": child_dict = dict((tag.label, tag.value) for tag in child_tags) current_tag.value = Complete( child_dict["rotation_matrix"], child_dict["translation_vector"], ) elif name == "unit_cell": child_dict = dict((tag.label, tag.value) for tag in child_tags) current_tag.value = UnitCell( child_dict["matrix"], child_dict["active"], ) elif name == "expression": current_tag.value = Expression(current_tag.content) elif name == "reference": current_tag.value = None referent_tag = self.hierarchy[-3][-1] target_ids = self.target_ids.get(referent_tag) if target_ids is None: target_ids = [] self.target_ids[referent_tag] = target_ids target_ids.append(int(current_tag.attributes["to"])) elif name == "model_object": Class = context.application.plugins.get_node(str(current_tag.attributes["class"])) current_tag.state = dict((tag.label, tag.value) for tag in child_tags) current_tag.value = Class() self.model_object_tags[int(current_tag.attributes["id"])] = current_tag else: pass # close the door current_tag.content = None current_tag.close() if len(child_tags) > 0: self.hierarchy.pop()
def convert_to_value(self, representation): lengths, angles = ComposedInTable.convert_to_value(self, representation) return UnitCell.from_parameters3(lengths, angles)