def create_molecular_graph(selected_nodes, parent=None): molecule = create_molecule(selected_nodes, parent) atom_indexes = dict((atom, i) for i, atom in enumerate(molecule.atoms)) bonds = list( bond for bond in iter_bonds(selected_nodes) if bond.children[0].target in atom_indexes and bond.children[1].target in atom_indexes ) pairs = [(atom_indexes[bond.children[0].target], atom_indexes[bond.children[1].target]) for bond in bonds] graph = MolecularGraph(pairs, molecule.numbers) graph.bonds = bonds graph.molecule = molecule return graph
def __init__(self, dihedral, molecule=None, top_indexes=None, potential=None): """ Arguments | ``dihedral`` -- the index of the atoms that define the dihedral angle Optional arguments | ``molecule`` -- a molecule object. required when top_indexes is not given | ``top_indexes`` -- a list of atom indexes involved in the rotor. required when molecule is not given | ``potential`` -- rotational potential info (if this is a hindered rotor). must be a two-tuple containing the angles and the corresponding energies. """ self.dihedral = dihedral if top_indexes is None: # try to deduce the top indexes if molecule is None: raise ValueError("missing arguemt: top_indexes or molecule from which top_indexes can be derived") atom0, atom1 = dihedral[1:3] graph = MolecularGraph.from_geometry(molecule) half0, half1 = graph.get_halfs(atom0, atom1) if len(half1) > len(half0): top_indexes = half0 top_indexes.discard(atom0) else: top_indexes = half1 top_indexes.discard(atom1) top_indexes = tuple(top_indexes) self.top_indexes = top_indexes self.potential = potential
def create_molecular_graph(selected_nodes, parent=None): molecule = create_molecule(selected_nodes, parent) atom_indexes = dict((atom, i) for i, atom in enumerate(molecule.atoms)) bonds = list(bond for bond in iter_bonds(selected_nodes) if bond.children[0].target in atom_indexes and bond.children[1].target in atom_indexes) pairs = [( atom_indexes[bond.children[0].target], atom_indexes[bond.children[1].target], ) for bond in bonds] graph = MolecularGraph(pairs, molecule.numbers) graph.bonds = bonds graph.molecule = molecule return graph
def __init__(self, dihedral, molecule=None, top_indexes=None, potential=None): """ Arguments | ``dihedral`` -- the index of the atoms that define the dihedral angle Optional arguments | ``molecule`` -- a molecule object. required when top_indexes is not given | ``top_indexes`` -- a list of atom indexes involved in the rotor. required when molecule is not given or when the top_indexes can not be derived automatically. | ``potential`` -- rotational potential info (if this is a hindered rotor). must be a two-tuple containing the angles and the corresponding energies. """ self.dihedral = dihedral if top_indexes is None: # try to deduce the top indexes if molecule is None: raise ValueError( "missing arguemt: top_indexes or molecule from which top_indexes can be derived" ) atom0, atom1 = dihedral[1:3] graph = MolecularGraph.from_geometry(molecule) half0, half1 = graph.get_halfs(atom0, atom1) if (len(half0) + len(half1) != molecule.size) or len(half0) == 1 or len(half1) == 1: raise ValueError( "The rotating top could not be assigned properly. Specify the top_indexes manually." ) if len(half1) > len(half0): top_indexes = half0 top_indexes.discard(atom0) else: top_indexes = half1 top_indexes.discard(atom1) top_indexes = tuple(top_indexes) else: # check the sanity of the top indexes if not ((self.dihedral[0] in top_indexes) ^ (self.dihedral[3] in top_indexes)): raise ValueError( 'The top must contain either first or the last atom of the dihedral angle.' ) if ((self.dihedral[1] in top_indexes) | (self.dihedral[2] in top_indexes)): raise ValueError( 'The top may not contain atoms from the central bond of the dihedral angle.' ) self.top_indexes = top_indexes self.potential = potential
def test_bias_pathdeviation_mof5(): # Load the system fn_system = pkg_resources.resource_filename( __name__, '../../data/test/system_mof5.chk') system = System.from_file(fn_system) # Groups that define the COM atypes = set( ['C_B', 'C_B_BR_O', 'O_p', 'B_p', 'C_HTTP', 'C_O_BR_O', 'C_O']) graph = MolecularGraph(system.bonds, system.numbers) indices = graph.independent_vertices groups = [] for layer in [0, 1]: groups.append([ iatom for iatom in indices[layer] if system.get_ffatype(iatom) in atypes ]) # Collective Variables cv0 = CVCOMProjection(system, groups, 0) cv1 = CVCOMProjection(system, groups, 1) # The path, rather random nonsense # This potential has a discontinuous derivative when there is a jump from # one nearest point on the path to the next. This can lead to failure of # the check_gpos_part and check_vtens_part tests when such a jump occurs # in the finite difference approximation. We avoid this by taking a rather # coarse path, so we are always close to the same point of the path. npoints = 20 path = np.zeros((npoints, 3)) path[:, 0] = np.cos(np.linspace(0, np.pi, npoints)) * 0.1 path[:, 1] = np.sin(np.linspace(0, np.pi, npoints)) * -0.1 path[:, 2] = 0.2 * path[:, 0] + path[:, 1]**2 # Test without the harmonic restraint bias = PathDeviationBias([cv0, cv1], path, 0.0) part = ForcePartBias(system) part.add_term(bias) check_gpos_part(system, part) check_vtens_part(system, part) # Test without the harmonic restraint, closest point on path is starting # point of the path bias = PathDeviationBias([cv0, cv1], path[5:], 0.0) index, _, _ = bias.find_nearest_point( np.array([cv.compute() for cv in bias.cvs])) assert index == 0 part = ForcePartBias(system) part.add_term(bias) check_gpos_part(system, part) check_vtens_part(system, part) # Test with the harmonic restraint bias = PathDeviationBias([cv0, cv1], path, 0.5) part = ForcePartBias(system) part.add_term(bias) check_gpos_part(system, part) check_vtens_part(system, part)
def get_precursor_model(): m = XYZFile("test/input/mfi_precursor.xyz").get_molecule() mgraph = MolecularGraph.from_geometry(m) connect_masks = np.array([ number == 8 and len(mgraph.neighbors[index]) == 1 for index, number in enumerate(m.numbers) ], bool) radii = np.array([ periodic[number].vdw_radius * {True: 0.3, False: 1.0}[connect_mask] for number, connect_mask in zip(m.numbers, connect_masks) ], float) radii += np.random.uniform(0, 0.1, radii.shape) return m.coordinates, connect_masks, radii
def collect_molecules(self, parent, universe=None): Atom = context.application.plugins.get_node("Atom") Bond = context.application.plugins.get_node("Bond") Frame = context.application.plugins.get_node("Frame") if universe==None: universe = parent atom_to_index = {} atoms_extra = {} counter = 0 numbers = [] coordinates = [] for child in parent.children: if isinstance(child, Atom): atom_to_index[child] = counter if len(child.extra) > 0: atoms_extra[counter] = child.extra counter += 1 numbers.append(child.number) coordinates.append(child.get_frame_relative_to(universe).t) if len(numbers) > 0: molecule = Molecule(numbers, coordinates, parent.name) molecule.extra = parent.extra molecule.atoms_extra = atoms_extra molecule.bonds_extra = {} pairs = set([]) for child in parent.children: if isinstance(child, Bond): atoms = child.get_targets() pair = frozenset([atom_to_index[atoms[0]], atom_to_index[atoms[1]]]) if len(child.extra) > 0: molecule.bonds_extra[pair] = child.extra pairs.add(pair) if len(pairs) > 0: molecule.graph = MolecularGraph(pairs, molecule.numbers) else: molecule.graph = None result = [molecule] else: result = [] for child in parent.children: if isinstance(child, Frame): result.extend(self.collect_molecules(child, universe)) return result
def __init__(self, dihedral, molecule=None, top_indexes=None, potential=None): """ Arguments | ``dihedral`` -- the index of the atoms that define the dihedral angle Optional arguments | ``molecule`` -- a molecule object. required when top_indexes is not given | ``top_indexes`` -- a list of atom indexes involved in the rotor. required when molecule is not given or when the top_indexes can not be derived automatically. | ``potential`` -- rotational potential info (if this is a hindered rotor). must be a two-tuple containing the angles and the corresponding energies. """ self.dihedral = dihedral if top_indexes is None: # try to deduce the top indexes if molecule is None: raise ValueError("missing arguemt: top_indexes or molecule from which top_indexes can be derived") atom0, atom1 = dihedral[1:3] graph = MolecularGraph.from_geometry(molecule) half0, half1 = graph.get_halfs(atom0, atom1) if (len(half0) + len(half1) != molecule.size) or len(half0) == 1 or len(half1) == 1: raise ValueError("The rotating top could not be assigned properly. Specify the top_indexes manually.") if len(half1) > len(half0): top_indexes = half0 top_indexes.discard(atom0) else: top_indexes = half1 top_indexes.discard(atom1) top_indexes = tuple(top_indexes) else: # check the sanity of the top indexes if not ((self.dihedral[0] in top_indexes) ^ (self.dihedral[3] in top_indexes)): raise ValueError('The top must contain either first or the last atom of the dihedral angle.') if ((self.dihedral[1] in top_indexes) | (self.dihedral[2] in top_indexes)): raise ValueError('The top may not contain atoms from the central bond of the dihedral angle.') self.top_indexes = top_indexes self.potential = potential
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 test_cvcomprojection_mof5(): # Load the system fn_system = pkg_resources.resource_filename( __name__, '../../data/test/system_mof5.chk') system = System.from_file(fn_system) # Groups that define the COM atypes = set( ['C_B', 'C_B_BR_O', 'O_p', 'B_p', 'C_HTTP', 'C_O_BR_O', 'C_O']) graph = MolecularGraph(system.bonds, system.numbers) indices = graph.independent_vertices groups = [] for layer in [0, 1]: groups.append([ iatom for iatom in indices[layer] if system.get_ffatype(iatom) in atypes ]) # Compute the COMs explicitly coms = [(system.pos[group] * system.masses[group].reshape( (-1, 1))).sum(axis=0) / system.masses[group].sum() for group in groups] relcom = coms[1] - coms[0] # Loop over different projections for index in range(3): # Compute using the CollectiveVariable cv = CVCOMProjection(system, groups, index) value = cv.compute() # Compute the projection vector a, b, c = system.cell.rvecs[0], system.cell.rvecs[ 1], system.cell.rvecs[2] if index == 0: u = a.copy() elif index == 1: u = np.cross(np.cross(a, b), a) elif index == 2: u = np.cross(a, b) u /= np.linalg.norm(u) cv_ref = np.dot(relcom, u) assert np.abs(cv_ref - value) < 1e-3 # Check derivatives check_gpos_cv_fd(cv) check_vtens_cv_fd(cv)