def get_system(self, name): if name == "chabazite_octane": molecule = XYZFile("input/chabazite_octane.xyz").get_molecule() unit_cell = UnitCell( numpy.array([ [14.767, 0, 0], [0, 23.686, 0], [0, 0, 13.675], ])*angstrom, numpy.array([True, True, True], bool), ) molecular_graph = MolecularGraph.from_geometry(molecule) return molecule.coordinates, molecular_graph, unit_cell elif name == "sodalite_ethane": molecule = XYZFile("input/sodalite_ethane.xyz").get_molecule() unit_cell = UnitCell( numpy.array([ [8.956, 0, 0], [0, 8.956, 0], [0, 0, 8.956], ])*angstrom, numpy.array([True, True, True], bool), ) molecular_graph = MolecularGraph.from_geometry(molecule) return molecule.coordinates, molecular_graph, unit_cell else: raise Exception("Unknown system.")
def test_one(xyz_fn, checks, reorder=False): mol = XYZFile(xyz_fn).get_molecule() graph = MolecularGraph.from_geometry(mol) zmat_gen = ZMatrixGenerator(graph) if reorder is False: self.assertArraysEqual(zmat_gen.new_index, numpy.arange(mol.size)) self.assertArraysEqual(zmat_gen.old_index, numpy.arange(mol.size)) zmat0 = zmat_gen.cart_to_zmat(mol.coordinates) for field, index, value in checks: self.assertAlmostEqual(zmat0[field][index], value, 2, "%s:%i %f!=%f" % (field,index,zmat0[field][index],value)) numbers0, coordinates0 = zmat_to_cart(zmat0) mol0 = Molecule(numbers0, coordinates0) mol0.write_to_file("output/zmat_%s" % os.path.basename(xyz_fn)) graph0 = MolecularGraph.from_geometry(mol0) zmat_gen0 = ZMatrixGenerator(graph0) self.assertArraysEqual(zmat_gen0.new_index, numpy.arange(mol.size)) self.assertArraysEqual(zmat_gen0.old_index, numpy.arange(mol.size)) zmat1 = zmat_gen0.cart_to_zmat(mol0.coordinates) for field, index, value in checks: self.assertAlmostEqual(zmat1[field][index], value, 2, "%s:%i %f!=%f" % (field,index,zmat1[field][index],value)) numbers1, coordinates1 = zmat_to_cart(zmat1) self.assertArraysEqual(numbers0, numbers1) self.assertArraysAlmostEqual(coordinates0, coordinates1, 1e-5)
def _check_topology(self): ''' Check wether all topology information (bonds, bends, dihedrals, out-of-plane patterns and neighborlist) is present and complete if necessary. ''' assert self.numbers is not None if self.bonds is None: molecule = Molecule(self.numbers, coordinates=self.ref.coords) graph = MolecularGraph.from_geometry(molecule) psf = PSFFile() psf.add_molecule(molecule) self.bonds = np.array(psf.bonds) self.bends = np.array(psf.bends) self.diheds = np.array(psf.dihedrals) self.opdists = find_opdist_patterns(graph) self.nlist = graph.neighbors else: graph = MolecularGraph(self.bonds, self.numbers) psf = PSFFile() psf.add_molecular_graph(graph) if self.bends is None: self.bends = np.array(psf.bends) if self.diheds is None: self.diheds = np.array(psf.dihedrals) if self.opdists is None: self.opdists = find_opdist_patterns(graph) if self.nlist is None: self.nlist = graph.neighbors
def add_molecule(self, molecule, atom_types=None, charges=None, split=True): molecular_graph = MolecularGraph.from_geometry(molecule) self.add_molecular_graph(molecular_graph, atom_types, charges, split)
def set_default_graph(self): """Set self.graph to the default graph. This method is equivalent to:: mol.graph = MolecularGraph.from_geometry(mol) with the default options, and only works if the graph object is not present yet. See :meth:`molmod.molecular_graphs.MolecularGraph.from_geometry` for more fine-grained control over the assignment of bonds. """ self.graph = MolecularGraph.from_geometry(self)
def compute_rotsym(self, threshold=1e-3*angstrom): """Compute the rotational symmetry number. Optional argument: | ``threshold`` -- only when a rotation results in an rmsd below the given threshold, the rotation is considered to transform the molecule onto itself. """ # Generate a graph with a more permissive threshold for bond lengths: # (is convenient in case of transition state geometries) graph = MolecularGraph.from_geometry(self, scaling=1.5) try: return compute_rotsym(self, graph, threshold) except ValueError: raise ValueError("The rotational symmetry number can only be computed when the graph is fully connected.")
def test_consistency(self): molecules = [ XYZFile("input/cyclopentane.xyz").get_molecule(), XYZFile("input/funny.xyz").get_molecule(), ] for m in molecules: m.graph = MolecularGraph.from_geometry(m) dump_cml("output/tmp.cml", molecules) check = load_cml("output/tmp.cml") for m1, m2 in zip(molecules, check): self.assertEqual(m1.title, m2.title) self.assert_((m1.numbers==m2.numbers).all()) self.assert_((m1.coordinates==m2.coordinates).all()) self.assertEqual(m1.graph.num_nodes, m2.graph.num_nodes) self.assertEqual(set(m1.graph.pairs), set(m2.graph.pairs))
def add_molecule(self, molecule, atom_types=None, charges=None, split=True): """Add the graph of the molecule to the data structure The molecular graph is estimated from the molecular geometry based on interatomic distances. Argument: | ``molecule`` -- a Molecule instance Optional arguments: | ``atom_types`` -- a list with atom type strings | ``charges`` -- The net atom charges | ``split`` -- When True, the molecule is split into disconnected molecules [default=True] """ molecular_graph = MolecularGraph.from_geometry(molecule) self.add_molecular_graph(molecular_graph, atom_types, charges, split, molecule)
def yield_test_molecules(self): for filename in ["tpa.xyz", "water.xyz", "thf_single.xyz"]: molecule = XYZFile(os.path.join("input", filename)).get_molecule() molecule.filename = filename graph = MolecularGraph.from_geometry(molecule) yield molecule, graph
CC30A = CritAnd(HasAtomNumber(6), HasNeighborNumbers(6,6,6,6)) CC31A = CritAnd(HasAtomNumber(6), HasNeighborNumbers(6,6,6,1)) CC32A = CritAnd(HasAtomNumber(6), HasNeighborNumbers(6,6,1,1)) CC33A = CritAnd(HasAtomNumber(6), HasNeighborNumbers(6,1,1,1)) atom_filters = { "CC30A": CC30A, "CC31A": CC31A, "CC32A": CC32A, "CC33A": CC33A, "HCA1": CritAnd(HasAtomNumber(1), HasNeighbors(CC31A)), "HCA2": CritAnd(HasAtomNumber(1), HasNeighbors(CC32A)), "HCA3": CritAnd(HasAtomNumber(1), HasNeighbors(CC33A)), } def get_atom_type(index, graph): for atom_type, atom_filter in atom_filters.iteritems(): if atom_filter(index, graph): return atom_type raise ValueError("Unrecognized atom (index %i)." % index) args = sys.argv[1:] molecule = XYZFile(args[0]).get_molecule() graph = MolecularGraph.from_geometry(molecule) atom_types = [get_atom_type(index, graph) for index in xrange(molecule.size)] psf = PSFFile() psf.add_molecular_graph(graph, atom_types=atom_types) psf.write_to_file(args[0].replace(".xyz", ".psf"))
CC30A = CritAnd(HasAtomNumber(6), HasNeighborNumbers(6,6,6,6)) CC31A = CritAnd(HasAtomNumber(6), HasNeighborNumbers(6,6,6,1)) CC32A = CritAnd(HasAtomNumber(6), HasNeighborNumbers(6,6,1,1)) CC33A = CritAnd(HasAtomNumber(6), HasNeighborNumbers(6,1,1,1)) atom_filters = { "CC30A": CC30A, "CC31A": CC31A, "CC32A": CC32A, "CC33A": CC33A, "HCA1": CritAnd(HasAtomNumber(1), HasNeighbors(CC31A)), "HCA2": CritAnd(HasAtomNumber(1), HasNeighbors(CC32A)), "HCA3": CritAnd(HasAtomNumber(1), HasNeighbors(CC33A)), } def get_atom_type(index, graph): for atom_type, atom_filter in atom_filters.items(): if atom_filter(index, graph): return atom_type raise ValueError("Unrecognized atom (index %i)." % index) args = sys.argv[1:] molecule = XYZFile(args[0]).get_molecule() graph = MolecularGraph.from_geometry(molecule) atom_types = [get_atom_type(index, graph) for index in range(molecule.size)] psf = PSFFile() psf.add_molecular_graph(graph, atom_types=atom_types) psf.write_to_file(args[0].replace(".xyz", ".psf"))
def test_graph(self): molecules = self.get_molecules() for molecule in molecules: molecule.graph = MolecularGraph.from_geometry(molecule) molecule.descriptor = DistanceDescriptor(molecule.graph) self.do_test(molecules, margin=0.2, cutoff=10.0)