def write_gsd(structure, filename, ref_distance=1.0, ref_mass=1.0, ref_energy=1.0, rigid_bodies=None): """Output a GSD file (HOOMD v2 default data format). Parameters ---------- structure : parmed.Structure ParmEd Structure object filename : str Path of the output file. ref_distance : float, optional, default=1.0 Reference distance for conversion to reduced units ref_mass : float, optional, default=1.0 Reference mass for conversion to reduced units ref_energy : float, optional, default=1.0 Reference energy for conversion to reduced units rigid_bodies : list of int, optional, default=None List of rigid body information. An integer value is required for each atom corresponding to the index of the rigid body the particle is to be associated with. A value of None indicates the atom is not part of a rigid body. Notes ----- Force field parameters are not written to the GSD file and must be included manually into a HOOMD input script. Work on a HOOMD plugin is underway to read force field parameters from a Foyer XML file. """ import_('gsd') import gsd.hoomd xyz = np.array([[atom.xx, atom.xy, atom.xz] for atom in structure.atoms]) gsd_file = gsd.hoomd.Snapshot() gsd_file.configuration.step = 0 gsd_file.configuration.dimensions = 3 gsd_file.configuration.box = np.hstack((structure.box[:3] / ref_distance, np.zeros(3))) _write_particle_information(gsd_file, structure, xyz, ref_distance, ref_mass, ref_energy, rigid_bodies) if structure.bonds: _write_bond_information(gsd_file, structure) if structure.angles: _write_angle_information(gsd_file, structure) if structure.rb_torsions: _write_dihedral_information(gsd_file, structure) gsd.hoomd.create(filename, gsd_file)
def visualize(self): py3Dmol = import_('py3Dmol') view = py3Dmol.view() rad = { '_BBA': .5, '_BBC': .5, '_BBG': .5, '_BBT': .5, '_HBA': 0.22, '_HBC': 0.22, '_HBG': 0.22, '_HBT': 0.22 } col = { '_BBA': '0xff0000', '_BBC': '0x4bd1cc', '_BBG': '0x696969', '_BBT': '0xdaa520', '_HBA': '0x8b0000', '_HBC': '0x008b8b', '_HBG': '0x2f4f4f', '_HBT': '0xd2691e' } remove_digits = lambda x: ''.join(i for i in x if not i.isdigit() or i == '_') #modified_color_scheme = {} for chain in self.children: for particle in chain.particles(): #particle.name = remove_digits(particle.name).upper() if not particle.name: particle.name = 'UNK' for p in chain.particles(include_ports=False): view.addSphere({ 'center': { 'x': p.pos[0], 'y': p.pos[1], 'z': p.pos[2] }, 'radius': rad[p.name], 'color': col[p.name], 'alpha': 0.9 }) view.zoomTo() view.show() return view
def load_cif(file_or_path=None, wrap_coords=False): """Load a CifFile object into an mbuild.Lattice. Parameters ---------- wrap_coords : bool, False Wrap the lattice points back into the 0-1 acceptable coordinates. Returns ------- mbuild.Lattice """ garnett = import_("garnett") assert isinstance(file_or_path, (str, pathlib.Path)) cif_location = pathlib.Path(file_or_path) reader = garnett.ciffilereader.CifFileReader() with open(cif_location.absolute(), "r") as cif_file: my_cif = reader.read(cif_file) # only need the first frame, not used as a trajectory frame = my_cif[0] # convert angstroms to nanometers lattice_spacing = ( np.linalg.norm(np.asarray(frame.box.get_box_matrix()).T, axis=1) / 10) # create lattice_points dictionary position_dict = defaultdict(list) for elem_id, coords in zip(frame.typeid, frame.cif_coordinates.tolist()): if wrap_coords: for i, pos in enumerate(coords): if 0 > pos > -1: coords[i] = coords[i] + 1 elif 1 < pos < 2: coords[i] = coords[i] - 1 else: pass position_dict[frame.types[elem_id]].append(list(coords)) box_vectors = np.asarray(frame.box.get_box_matrix()).T return Lattice( lattice_spacing=lattice_spacing, lattice_vectors=box_vectors, lattice_points=position_dict, )
def test_from_pybel_molecule(self, extension): pybel = import_('pybel') chol = list( pybel.readfile(extension, get_fn('cholesterol.{}'.format(extension))))[0] # TODO: Actually store the box information cmpd = mb.Compound() cmpd.from_pybel(chol) assert chol.OBMol.NumAtoms() == cmpd.n_particles assert chol.OBMol.NumBonds() == cmpd.n_bonds first_atom = chol.OBMol.GetAtom(1) assert np.allclose(cmpd[0].pos, [ first_atom.GetX() / 10, first_atom.GetY() / 10, first_atom.GetZ() / 10 ])
def test_structure_to_hoomdsimulation(self, ethane): forcefield = import_("foyer.forcefield") hoomd = import_("hoomd") hoomd_simulation = import_("mbuild.formats.hoomd_simulation") ff = forcefield.Forcefield(name='oplsaa') structure = ff.apply(ethane) hoomd_simulation.create_hoomd_simulation(structure) sim_forces = hoomd.context.current.forces pair_force = import_("hoomd.md.pair") charge_force = import_("hoomd.md.charge") special_pair_force = import_("hoomd.md.special_pair") bond_force = import_("hoomd.md.bond") angle_force = import_("hoomd.md.angle") dihedral_force = import_("hoomd.md.dihedral") assert isinstance(sim_forces[0], pair_force.lj) assert isinstance(sim_forces[1], charge_force.pppm) assert isinstance(sim_forces[2], pair_force.ewald) assert isinstance(sim_forces[3], special_pair_force.lj) assert isinstance(sim_forces[4], special_pair_force.coulomb) assert isinstance(sim_forces[5], bond_force.harmonic) assert isinstance(sim_forces[6], angle_force.harmonic) assert isinstance(sim_forces[7], dihedral_force.opls)
def test_lj_to_hoomdsimulation(self): import hoomd from foyer.forcefield import Forcefield from mbuild.formats.hoomd_simulation import create_hoomd_simulation box = mb.Compound() box.add(mb.Compound(name="Ar", pos=[1, 1, 1])) box.add(mb.Compound(name="Ar", pos=[1, 1, 1])) ff = Forcefield(forcefield_files=get_fn("lj.xml")) structure = ff.apply(box) structure.box = [10, 10, 10, 90, 90, 90] sim = hoomd.context.SimulationContext() with sim: create_hoomd_simulation(structure, 2.5) sim_forces = hoomd.context.current.forces pair_force = import_("hoomd.md.pair") assert isinstance(sim_forces[0], pair_force.lj)
def test_compound_from_gsdsnapshot(self, ethane): from mbuild.formats.hoomd_snapshot import ( from_snapshot, to_hoomdsnapshot, ) gsd = import_("gsd") lengths = [5, 5, 5] filled = mb.fill_box(ethane, n_compounds=5, box=mb.Box(lengths)) snap, _ = to_hoomdsnapshot(filled) # copy attributes from the snapshot to a gsd snapshot gsd_snap = gsd.hoomd.Snapshot() gsd_snap.particles.N = snap.particles.N gsd_snap.particles.types = snap.particles.types gsd_snap.particles.typeid = snap.particles.typeid gsd_snap.particles.position = snap.particles.position gsd_snap.configuration.box = np.array([ snap.box.Lx, snap.box.Ly, snap.box.Lz, snap.box.xy, snap.box.xy, snap.box.yz, ]) gsd_snap.bonds.N = snap.bonds.N gsd_snap.bonds.group = snap.bonds.group gsd_snap.particles.charge = snap.particles.charge gsd_snap.validate() new_filled = from_snapshot(gsd_snap, scale=0.1) assert filled.n_bonds == new_filled.n_bonds assert filled.n_particles == new_filled.n_particles assert np.array_equal(filled.box.angles, new_filled.box.angles) assert np.array_equal(filled.box.lengths, new_filled.box.lengths) for i in range(filled.n_particles): assert np.allclose(filled[i].pos, new_filled[i].pos)
def visualize(self, show_ports=False): """Visualize the Compound using nglview. """ nglview = import_('nglview') if run_from_ipython(): structure = self.to_trajectory(show_ports) return nglview.show_mdtraj(structure) else: try: """Visualize the Compound using imolecule. """ import imolecule json_mol = self._to_json(show_ports) imolecule.draw(json_mol, format='json', shader='lambert', drawing_type='ball and stick', camera_type='perspective', element_properties=None) except ImportError: raise RuntimeError( 'Visualization is only supported in Jupyter ' 'Notebooks.')
import itertools import operator import warnings from collections import namedtuple import numpy as np import parmed as pmd import mbuild as mb from mbuild.utils.conversion import RB_to_OPLS from mbuild.utils.io import import_ from mbuild.utils.sorting import natural_sort from .hoomd_snapshot import to_hoomdsnapshot gsd = import_("gsd") gsd.hoomd = import_("gsd.hoomd") hoomd = import_("hoomd") hoomd.md = import_("hoomd.md") def create_hoomd_simulation( structure, r_cut, ref_distance=1.0, ref_mass=1.0, ref_energy=1.0, auto_scale=False, snapshot_kwargs={}, pppm_kwargs={"Nx": 8, "Ny": 8, "Nz": 8, "order": 4}, init_snap=None,
import numpy as np import pytest import mbuild as mb from mbuild.conversion import from_gmso, to_gmso from mbuild.tests.base_test import BaseTest from mbuild.utils.io import has_gmso, import_ if has_gmso: gmso = import_("gmso") @pytest.mark.skipif(not has_gmso, reason="GMSO is not installed") class TestGMSO(BaseTest): def test_to_gmso(self, ethane): gmso_eth = ethane.to_gmso() # Equivalent to to_gmso(ethane) assert isinstance(gmso_eth, gmso.Topology) assert len(gmso_eth.bonds) == ethane.n_bonds for i in range(ethane.n_particles): assert ethane[i].name == gmso_eth.sites[i].name assert np.isclose( ethane[i].xyz, gmso_eth.sites[i].position.value ).all() def test_full_conversion(self, ethane): # Note: at this point, the full conversion may lose some information regarding the hierarchical, # especially, if the original compound has more than 3 layers. gmso_eth = ethane.to_gmso() mb_eth = from_gmso(gmso_eth)
def test_from_pybel_residues(self): pybel = import_('pybel') pybel_mol = list(pybel.readfile('mol2', get_fn('methyl.mol2')))[0] cmpd = mb.Compound() cmpd.from_pybel(pybel_mol) assert 'LIG1' in cmpd.children[0].name
def test_js_utils(self): nglview = import_("nglview") with pytest.raises(TypeError): overwrite_nglview_default(object()) test_widget = nglview.NGLWidget() overwrite_nglview_default(test_widget) assert hasattr(test_widget, "stage") assert isinstance(test_widget._ngl_msg_archive, list) assert len(test_widget._ngl_msg_archive) == 2 assert isinstance(test_widget._ngl_msg_archive[0], dict) message_dict = test_widget._ngl_msg_archive[0] assert message_dict["target"] == "Widget" assert message_dict["type"] == "call_method" assert message_dict["methodName"] == "executeCode" assert message_dict["args"] == [ """ this.stage.mouseControls.add('hoverPick', (stage, pickingProxy) => { let tooltip = this.stage.tooltip; if(pickingProxy && pickingProxy.atom && !pickingProxy.bond){ let atom = pickingProxy.atom; tooltip.innerText = "ATOM: " + atom.qualifiedName() + ", Index: " + atom.index; } }); """ ] message_dict = test_widget._ngl_msg_archive[1] assert message_dict["target"] == "Widget" assert message_dict["type"] == "call_method" assert message_dict["methodName"] == "executeCode" assert message_dict["args"] == [ """ this.stage.signals.clicked.removeAll(); this.stage.signals.clicked.add((pickingProxy) => { if(pickingProxy){ let pickingText = null; this.model.set('picked', {}); this.touch(); let currentPick = {}; if(pickingProxy.atom){ currentPick.atom1 = pickingProxy.atom.toObject(); currentPick.atom1.name = pickingProxy.atom.qualifiedName(); pickingText = "Atom: " + currentPick.atom1.name + ", Index: " + pickingProxy.atom.index; } else if(pickingProxy.bond){ currentPick.bond = pickingProxy.bond.toObject(); currentPick.atom1 = pickingProxy.bond.atom1.toObject(); currentPick.atom1.name = pickingProxy.bond.atom1.qualifiedName(); currentPick.atom2 = pickingProxy.bond.atom2.toObject(); currentPick.atom2.name = pickingProxy.bond.atom2.qualifiedName(); pickingText = "Bond: " + currentPick.atom1.name + `(${pickingProxy.bond.atom1.index})` + " - " + currentPick.atom2.name + `(${pickingProxy.bond.atom2.index})`; } if(pickingProxy.instance){ currentPick.instance = pickingProxy.instance; } var nComponents = this.stage.compList.length; for(let i = 0; i < nComponents; i++){ let comp = this.stage.compList[i]; if(comp.uuid == pickingProxy.component.uuid){ currentPick.component = i; } } this.model.set('picked', currentPick); this.touch(); this.$pickingInfo.text(pickingText); } }); """ ]
def test_import(self): assert np == import_("numpy") with pytest.raises(ImportError): import_("garbagepackagename")
def test_visualize_py3dmol(self, ethane): py3Dmol = import_("py3Dmol") vis_object = ethane._visualize_py3dmol() assert isinstance(vis_object, py3Dmol.view)
def test_compound_to_hoomdsimulation(self, ethane): hoomd_simulation = import_("mbuild.formats.hoomd_simulation") with pytest.raises(ValueError): hoomd_simulation.create_hoomd_simulation(ethane)
def test_bad_input_to_snapshot(self): hoomd_snapshot = import_("mbuild.formats.hoomd_snapshot") with pytest.raises(ValueError): hoomd_snapshot.to_hoomdsnapshot('fake_object')
def write_gsd(structure, filename, ref_distance=1.0, ref_mass=1.0, ref_energy=1.0, rigid_bodies=None, shift_coords=True, write_special_pairs=True): """Output a GSD file (HOOMD v2 default data format). Parameters ---------- structure : parmed.Structure ParmEd Structure object filename : str Path of the output file. ref_distance : float, optional, default=1.0 Reference distance for conversion to reduced units ref_mass : float, optional, default=1.0 Reference mass for conversion to reduced units ref_energy : float, optional, default=1.0 Reference energy for conversion to reduced units rigid_bodies : list of int, optional, default=None List of rigid body information. An integer value is required for each atom corresponding to the index of the rigid body the particle is to be associated with. A value of None indicates the atom is not part of a rigid body. shift_coords : bool, optional, default=True Shift coordinates from (0, L) to (-L/2, L/2) if necessary. write_special_pairs : bool, optional, default=True Writes out special pair information necessary to correctly use the OPLS fudged 1,4 interactions in HOOMD. Notes ----- Force field parameters are not written to the GSD file and must be included manually into a HOOMD input script. Work on a HOOMD plugin is underway to read force field parameters from a Foyer XML file. """ import_('gsd') import gsd.hoomd xyz = np.array([[atom.xx, atom.xy, atom.xz] for atom in structure.atoms]) if shift_coords: xyz = coord_shift(xyz, structure.box[:3]) gsd_file = gsd.hoomd.Snapshot() gsd_file.configuration.step = 0 gsd_file.configuration.dimensions = 3 # Write box information if np.allclose(structure.box[3:6], np.array([90, 90, 90])): gsd_file.configuration.box = np.hstack( (structure.box[:3] / ref_distance, np.zeros(3))) else: a, b, c = structure.box[0:3] / ref_distance alpha, beta, gamma = np.radians(structure.box[3:6]) lx = a xy = b * np.cos(gamma) xz = c * np.cos(beta) ly = np.sqrt(b**2 - xy**2) yz = (b * c * np.cos(alpha) - xy * xz) / ly lz = np.sqrt(c**2 - xz**2 - yz**2) gsd_file.configuration.box = np.array([lx, ly, lz, xy, xz, yz]) _write_particle_information(gsd_file, structure, xyz, ref_distance, ref_mass, ref_energy, rigid_bodies) if write_special_pairs: _write_pair_information(gsd_file, structure) if structure.bonds: _write_bond_information(gsd_file, structure) if structure.angles: _write_angle_information(gsd_file, structure) if structure.rb_torsions: _write_dihedral_information(gsd_file, structure) gsd.hoomd.create(filename, gsd_file)
def _visualize_py3dmol(self, show_ports=False, color_scheme={}, show_atomistic=False, scale=1.0): """ Visualize the Compound using py3Dmol. Allows for visualization of a Compound within a Jupyter Notebook. Modified to show atomistic elements (translucent) with larger CG beads. Parameters ---------- show_ports : bool, optional, default=False Visualize Ports in addition to Particles color_scheme : dict, optional Specify coloring for non-elemental particles keys are strings of the particle names values are strings of the colors i.e. {'_CGBEAD': 'blue'} show_atomistic : show the atomistic structure stored in CG_Compound.atomistic Returns ------ view : py3Dmol.view """ py3Dmol = import_("py3Dmol") atom_names = [] if self.atomistic is not None and show_atomistic: atomistic = mb.clone(self.atomistic) for particle in atomistic.particles(): if not particle.name: particle.name = "UNK" else: if (particle.name != 'Compound') and (particle.name != 'CG_Compound'): atom_names.append(particle.name) coarse = mb.clone(self) modified_color_scheme = {} for name, color in color_scheme.items(): # Py3dmol does some element string conversions, # first character is as-is, rest of the characters are lowercase new_name = name[0] + name[1:].lower() modified_color_scheme[new_name] = color modified_color_scheme[name] = color cg_names = [] for particle in coarse.particles(): if not particle.name: particle.name = "UNK" else: if (particle.name != 'Compound') and (particle.name != 'CG_Compound'): cg_names.append(particle.name) tmp_dir = tempfile.mkdtemp() view = py3Dmol.view() if atom_names: atomistic.save( os.path.join(tmp_dir, "atomistic_tmp.mol2"), show_ports=show_ports, overwrite=True, ) # atomistic with open(os.path.join(tmp_dir, "atomistic_tmp.mol2"), "r") as f: view.addModel(f.read(), "mol2", keepH=True) if cg_names: opacity = 0.6 else: opacity = 1.0 view.setStyle({ "stick": { "radius": 0.2 * scale, "opacity": opacity, "color": "grey" }, "sphere": { "scale": 0.3 * scale, "opacity": opacity, "colorscheme": modified_color_scheme, }, }) # coarse if cg_names: coarse.save( os.path.join(tmp_dir, "coarse_tmp.mol2"), show_ports=show_ports, overwrite=True, ) with open(os.path.join(tmp_dir, "coarse_tmp.mol2"), "r") as f: view.addModel(f.read(), "mol2", keepH=True) if self.atomistic is None: scale = 0.3 * scale else: scale = 0.7 * scale view.setStyle( {"atom": cg_names}, { "stick": { "radius": 0.2 * scale, "opacity": 1, "color": "grey" }, "sphere": { "scale": scale, "opacity": 1, "colorscheme": modified_color_scheme, }, }, ) view.zoomTo() return view
def write_gsd(structure, filename, ref_distance=1.0, ref_mass=1.0, ref_energy=1.0, rigid_bodies=None, shift_coords=True, write_special_pairs=True): """Output a GSD file (HOOMD v2 default data format). Parameters ---------- structure : parmed.Structure ParmEd Structure object filename : str Path of the output file. ref_distance : float, optional, default=1.0 Reference distance for conversion to reduced units ref_mass : float, optional, default=1.0 Reference mass for conversion to reduced units ref_energy : float, optional, default=1.0 Reference energy for conversion to reduced units rigid_bodies : list of int, optional, default=None List of rigid body information. An integer value is required for each atom corresponding to the index of the rigid body the particle is to be associated with. A value of None indicates the atom is not part of a rigid body. shift_coords : bool, optional, default=True Shift coordinates from (0, L) to (-L/2, L/2) if necessary. write_special_pairs : bool, optional, default=True Writes out special pair information necessary to correctly use the OPLS fudged 1,4 interactions in HOOMD. Notes ----- Force field parameters are not written to the GSD file and must be included manually into a HOOMD input script. Work on a HOOMD plugin is underway to read force field parameters from a Foyer XML file. """ import_('gsd') import gsd.hoomd xyz = np.array([[atom.xx, atom.xy, atom.xz] for atom in structure.atoms]) if shift_coords: xyz = coord_shift(xyz, structure.box[:3]) gsd_file = gsd.hoomd.Snapshot() gsd_file.configuration.step = 0 gsd_file.configuration.dimensions = 3 # Write box information if np.allclose(structure.box[3:6], np.array([90, 90, 90])): gsd_file.configuration.box = np.hstack((structure.box[:3] / ref_distance, np.zeros(3))) else: a, b, c = structure.box[0:3] / ref_distance alpha, beta, gamma = np.radians(structure.box[3:6]) lx = a xy = b * np.cos(gamma) xz = c * np.cos(beta) ly = np.sqrt(b**2 - xy**2) yz = (b*c*np.cos(alpha) - xy*xz) / ly lz = np.sqrt(c**2 - xz**2 - yz**2) gsd_file.configuration.box = np.array([lx, ly, lz, xy, xz, yz]) _write_particle_information(gsd_file, structure, xyz, ref_distance, ref_mass, ref_energy, rigid_bodies) if write_special_pairs: _write_pair_information(gsd_file, structure) if structure.bonds: _write_bond_information(gsd_file, structure) if structure.angles: _write_angle_information(gsd_file, structure) if structure.rb_torsions: _write_dihedral_information(gsd_file, structure) gsd.hoomd.create(filename, gsd_file)
def create_lammps_input_script(self, T=4.6, script_num=1, sim_name='test.lammps', time_steps=2e6, atom_style='full', seed_1='42', seed_2='42'): re = import_('re') # Calculate dielectric constant (using equation from Ahmad's soft matter paper) T_real = T * (0.1 / 8.314) * 4184 eps_r = 249.4 - 0.788 * T_real + 0.00072 * (T_real**2) eps_r = np.round(eps_r, decimals=5) # Specify the name of the sample input script sample_name = 'mbuild_ONA/sample.in' # Loop over the total number of scripts and create files for i in range(script_num): # Specify input file name filename = 'test_sample' + str(i + 1) + '.in' # Treat the first input script separately if (i == 0): # Define substitutions subs = [('T_ref', str(T)), ('eps_r', str(eps_r)), ('sample.dcd', sim_name + '.' + str(i + 1) + '.dcd'), ('sample.xyz', sim_name + '.' + str(i + 1) + '.xyz'), ('time_steps_a', str(int(time_steps + 1))), ('time_steps_b', str(int(time_steps))), ('info.dat', 'info' + str(i + 1) + '.dat'), ('atom_style full', 'atom_style ' + atom_style), ('seed_1', seed_1), ('seed_2', seed_2)] else: # Replace relevant fields (Don't forget to replace read_data and data.lammps) subs = [('T_ref', str(T)), ('eps_r', str(eps_r)), ('read_data ' + sim_name, 'read_restart restart.* remap'), ('sample.dcd', sim_name + '.' + str(i + 1) + '.dcd'), ('sample.xyz', sim_name + '.' + str(i + 1) + '.xyz'), ('time_steps_a', str(int(time_steps + 1))), ('time_steps_b', str(int(time_steps))), ('info.dat', 'info' + str(i + 1) + '.dat'), ('atom_style full', 'atom_style ' + atom_style), ('seed_1', seed_1), ('seed_2', seed_2)] # Read sample input script with open(sample_name) as fp: text = fp.read() lines = text.splitlines() for line_no, line in enumerate(lines): for pattern, replace in subs: # Do replacements lines[line_no] = re.sub(pattern, replace, lines[line_no]) # Don't re-assign velocities for i > 0 (Also, don't energy minimize) if (i > 0): del lines[105:109] with open(filename, 'w') as fp: fp.write('\n'.join(lines))
def test_visualize_nglview(self, ethane): nglview = import_("nglview") vis_object = ethane._visualize_nglview() assert isinstance(vis_object.component_0, nglview.component.ComponentViewer)
def ONA_visualize_py3dmol(self, show_ports=False): """Visualize the Compound using py3Dmol. Allows for visualization of a Compound within a Jupyter Notebook. Parameters ---------- show_ports : bool, optional, default=False Visualize Ports in addition to Particles color_scheme : dict, optional Specify coloring for non-elemental particles keys are strings of the particle names values are strings of the colors i.e. {'_CGBEAD': 'blue'} Returns ------ view : py3Dmol.view """ py3Dmol = import_('py3Dmol') remove_digits = lambda x: ''.join(i for i in x if not i.isdigit() or i == '_') #modified_color_scheme = {} for particle in self.particles(): #particle.name = remove_digits(particle.name).upper() if not particle.name: particle.name = 'UNK' view = py3Dmol.view() rad = { '_BBA': .5, '_BBC': .5, '_BBG': .5, '_BBT': .5, '_HBA': 0.22, '_HBC': 0.22, '_HBG': 0.22, '_HBT': 0.22 } col = { '_BBA': '0xff0000', '_BBC': '0x4bd1cc', '_BBG': '0x696969', '_BBT': '0xdaa520', '_HBA': '0x8b0000', '_HBC': '0x008b8b', '_HBG': '0x2f4f4f', '_HBT': '0xd2691e' } for p in self.particles(include_ports=False): view.addSphere({ 'center': { 'x': p.pos[0], 'y': p.pos[1], 'z': p.pos[2] }, 'radius': rad[p.name], 'color': col[p.name], 'alpha': 0.9 }) view.zoomTo() view.show() return view
import warnings import itertools import numpy as np import operator from collections import namedtuple import parmed as pmd import mbuild as mb from mbuild.utils.sorting import natural_sort from mbuild.utils.io import import_ from mbuild.utils.conversion import RB_to_OPLS from .hoomd_snapshot import to_hoomdsnapshot hoomd = import_("hoomd") hoomd.md = import_("hoomd.md") hoomd.md.pair = import_("hoomd.md.pair") hoomd.md.special_pair = import_("hoomd.md.special_pair") hoomd.md.charge = import_("hoomd.md.charge") hoomd.md.bond = import_("hoomd.md.bond") hoomd.md.angle = import_("hoomd.md.angle") hoomd.md.dihedral = import_("hoomd.md.dihedral") hoomd.group = import_("hoomd.group") def create_hoomd_simulation(structure, ref_distance=1.0, ref_mass=1.0, ref_energy=1.0, r_cut=1.2, auto_scale=False,
def visualize(self, show_ports=False): """Visualize the Compound using py3Dmol. Allows for visualization of a Compound within a Jupyter Notebook. Parameters ---------- show_ports : bool, optional, default=False Visualize Ports in addition to Particles color_scheme : dict, optional Specify coloring for non-elemental particles keys are strings of the particle names values are strings of the colors i.e. {'_CGBEAD': 'blue'} Returns ------ view : py3Dmol.view """ py3Dmol = import_('py3Dmol') remove_digits = lambda x: ''.join(i for i in x if not i.isdigit() or i == '_') for particle in self.particles(): if not particle.name: particle.name = 'UNK' view = py3Dmol.view() rad = { '_BBP': .5, '_BBK': .5, '_BBG': .5, '_BBO': .5, '_BBD': .5, '_HBP': 0.22, '_HBG': 0.22, '_INC': .5, '_INA': .5 } col = { '_BBP': '#0000FF', '_BBO': '#FF8000', '_BBG': '#00FF00', '_BBK': '#000000', '_BBD': '#FF0000', '_HBP': '#FFFF00', '_HBG': '#FFFF00', '_INC': '#42C8F5', '_INA': '#F5427E' } for p in self.particles(include_ports=False): view.addSphere({ 'center': { 'x': p.pos[0], 'y': p.pos[1], 'z': p.pos[2] }, 'radius': rad[p.name], 'color': col[p.name], 'alpha': 0.9 }) view.zoomTo() view.show() return view
"""HOOMD snapshot format.""" import operator from collections import namedtuple import numpy as np import parmed as pmd from mbuild.box import Box from mbuild.compound import Compound, Particle from mbuild.utils.geometry import coord_shift from mbuild.utils.io import import_ from mbuild.utils.sorting import natural_sort hoomd = import_("hoomd") hoomd.data = import_("hoomd.data") __all__ = ["to_hoomdsnapshot", "from_snapshot"] def from_snapshot(snapshot, scale=1.0): """Convert a Snapshot to a Compound. Snapshot can be a hoomd.data.Snapshot or a gsd.hoomd.Snapshot. Parameters ---------- snapshot : hoomd._hoomd.SnapshotSystemData_float or gsd.hoomd.Snapshot Snapshot from which to build the mbuild Compound. scale : float, optional, default 1.0 Value by which to scale the length values
def test_import(self): assert np == import_('numpy') with pytest.raises(ImportError): import_('garbagepackagename')
def test_bad_input_to_hoomdsimulation(self): hoomd_simulation = import_("mbuild.formats.hoomd_simulation") with pytest.raises(ValueError): hoomd_simulation.create_hoomd_simulation('fake_object')
import itertools import operator import warnings from collections import namedtuple import numpy as np import parmed as pmd import mbuild as mb from mbuild.utils.conversion import RB_to_OPLS from mbuild.utils.io import import_ from mbuild.utils.sorting import natural_sort from .hoomd_snapshot import _get_hoomd_version, to_hoomdsnapshot hoomd = import_("hoomd") def create_hoomd_forcefield( structure, r_cut, ref_distance=1.0, ref_mass=1.0, ref_energy=1.0, auto_scale=False, snapshot_kwargs={}, pppm_kwargs={ "Nx": 8, "Ny": 8, "Nz": 8, "order": 4
def write_gsd(structure, filename, forcefield, box, ref_distance=1.0, ref_mass=1.0, ref_energy=1.0, write_ff=True): """Output a GSD file (HOOMD default data format). Parameters ---------- structure : parmed.GromacsTopologyFile Parmed structure object filename : str Path of the output file. forcefield : str, default=None Name of the force field to be applied to the compound box : mb.Box Box information to save to XML file ref_distance : float, default=1.0 Reference distance for conversion to reduced units ref_mass : float, default=1.0 Reference mass for conversion to reduced units ref_energy : float, default=1.0 Reference energy for conversion to reduced units write_ff : boolean, default=True Write forcefield parameters to a JSON file, 'parameters.json' """ import_('gsd') import gsd.hoomd xyz = np.array([[atom.xx, atom.xy, atom.xz] for atom in structure.atoms]) # Center box at origin and remap coordinates into box box.lengths *= 10.0 box.maxs *= 10.0 box.mins *= 10.0 box_init = deepcopy(box) box.mins = np.array([-d / 2 for d in box_init.lengths]) box.maxs = np.array([d / 2 for d in box_init.lengths]) shift = [box_init.maxs[i] - max for i, max in enumerate(box.maxs)] for i, pos in enumerate(xyz): for j, coord in enumerate(pos): xyz[i, j] -= shift[j] rep = floor((xyz[i, j] - box.mins[j]) / box.lengths[j]) xyz[i, j] -= (rep * box.lengths[j]) gsd_file = gsd.hoomd.Snapshot() gsd_file.configuration.step = 0 gsd_file.configuration.dimensions = 3 gsd_file.configuration.box = np.hstack( (box.lengths / ref_distance, np.zeros(3))) gsd_file.particles.N = len(structure.atoms) gsd_file.particles.position = xyz / ref_distance if forcefield: types = [atom.type for atom in structure.atoms] else: types = [atom.name for atom in structure.atoms] unique_types = list(set(types)) unique_types.sort(key=_natural_sort) typeids = np.array([unique_types.index(t) for t in types]) gsd_file.particles.types = unique_types gsd_file.particles.typeid = typeids masses = np.array([atom.mass for atom in structure.atoms]) masses[masses == 0] = 1.0 gsd_file.particles.mass = masses / ref_mass charges = np.array([atom.charge for atom in structure.atoms]) e0 = 2.39725e-4 ''' Permittivity of free space = 2.39725e-4 e^2/((kcal/mol)(angstrom)), where e is the elementary charge ''' charge_factor = (4.0 * np.pi * e0 * ref_distance * ref_energy)**0.5 gsd_file.particles.charge = charges / charge_factor bonds = [[bond.atom1.idx, bond.atom2.idx] for bond in structure.bonds] if bonds: bonds = np.asarray(bonds) gsd_file.bonds.N = len(bonds) if len(structure.bond_types) == 0: bond_types = np.zeros(len(bonds), dtype=int) gsd_file.bonds.types = ['0'] else: unique_bond_types = dict( enumerate( OrderedSet([(round(bond.type.k, 3), round(bond.type.req, 3)) for bond in structure.bonds]))) unique_bond_types = OrderedDict([ (y, x) for x, y in unique_bond_types.items() ]) bond_types = [ unique_bond_types[(round(bond.type.k, 3), round(bond.type.req, 3))] for bond in structure.bonds ] gsd_file.bonds.types = [ str(y) for x, y in unique_bond_types.items() ] gsd_file.bonds.typeid = bond_types gsd_file.bonds.group = bonds angles = [[angle.atom1.idx, angle.atom2.idx, angle.atom3.idx] for angle in structure.angles] if angles: angles = np.asarray(angles) gsd_file.angles.N = len(angles) unique_angle_types = dict( enumerate( OrderedSet([(round(angle.type.k, 3), round(angle.type.theteq, 3)) for angle in structure.angles]))) unique_angle_types = OrderedDict([ (y, x) for x, y in unique_angle_types.items() ]) angle_types = [ unique_angle_types[(round(angle.type.k, 3), round(angle.type.theteq, 3))] for angle in structure.angles ] gsd_file.angles.types = [str(y) for x, y in unique_angle_types.items()] gsd_file.angles.typeid = angle_types gsd_file.angles.group = angles dihedrals = [[ dihedral.atom1.idx, dihedral.atom2.idx, dihedral.atom3.idx, dihedral.atom4.idx ] for dihedral in structure.rb_torsions] if dihedrals: dihedrals = np.asarray(dihedrals) gsd_file.dihedrals.N = len(dihedrals) unique_dihedral_types = dict( enumerate( OrderedSet([(round(dihedral.type.c0, 3), round(dihedral.type.c1, 3), round(dihedral.type.c2, 3), round(dihedral.type.c3, 3), round(dihedral.type.c4, 3), round(dihedral.type.c5, 3), round(dihedral.type.scee, 1), round(dihedral.type.scnb, 1)) for dihedral in structure.rb_torsions]))) unique_dihedral_types = OrderedDict([ (y, x) for x, y in unique_dihedral_types.items() ]) dihedral_types = [ unique_dihedral_types[(round(dihedral.type.c0, 3), round(dihedral.type.c1, 3), round(dihedral.type.c2, 3), round(dihedral.type.c3, 3), round(dihedral.type.c4, 3), round(dihedral.type.c5, 3), round(dihedral.type.scee, 1), round(dihedral.type.scnb, 1))] for dihedral in structure.rb_torsions ] gsd_file.dihedrals.types = [ str(y) for x, y in unique_dihedral_types.items() ] gsd_file.dihedrals.typeid = dihedral_types gsd_file.dihedrals.group = dihedrals gsd.hoomd.create(filename, gsd_file) if write_ff: write_forcefield(structure, 'ff.json', ref_distance=ref_distance, ref_energy=ref_energy)