Ejemplo n.º 1
0
    def _pmdStructureToOEMol(self):
        top = self.structure.topology
        pos = self.structure.positions
        molecule = oeommtools.openmmTop_to_oemol(top, pos, verbose=False)
        oechem.OEPerceiveResidues(molecule)
        oechem.OEFindRingAtomsAndBonds(molecule)

        return molecule
Ejemplo n.º 2
0
Archivo: moves.py Proyecto: sgill2/ncmc
    def _pmdStructureToOEMol(self):
        """Helper function for converting the parmed structure into an OEMolecule."""
        top = self.structure.topology
        pos = self.structure.positions
        molecule = oeommtools.openmmTop_to_oemol(top, pos, verbose=False)
        oechem.OEPerceiveResidues(molecule)
        oechem.OEFindRingAtomsAndBonds(molecule)

        return molecule
Ejemplo n.º 3
0
    def _pmdStructureToOEMol(self):

        from oeommtools.utils import openmmTop_to_oemol
        top = self.structure.topology
        pos = self.structure.positions
        molecule = openmmTop_to_oemol(top, pos, verbose=False)
        OEPerceiveResidues(molecule, OEPreserveResInfo_All)
        OEPerceiveResidues(molecule)
        OEFindRingAtomsAndBonds(molecule)

        return molecule
Ejemplo n.º 4
0
def test_improper_pyramidal(verbose=False):
    """Test implement of impropers on ammonia."""
    from openeye import oeomega
    from openeye import oequacpac
    from oeommtools.utils import oemol_to_openmmTop, openmmTop_to_oemol
    from openforcefield.utils import get_data_file_path, extractPositionsFromOEMol
    # Prepare ammonia
    mol = oechem.OEMol()
    oechem.OESmilesToMol(mol, 'N')
    oechem.OEAddExplicitHydrogens(mol)
    omega = oeomega.OEOmega()
    omega.SetMaxConfs(100)
    omega.SetIncludeInput(False)
    omega.SetStrictStereo(False)
    # Generate charges
    chargeEngine = oequacpac.OEAM1BCCCharges()
    status = omega(mol)
    oequacpac.OEAssignCharges(mol, chargeEngine)
    # Assign atom names
    oechem.OETriposAtomTypes(mol)
    oechem.OETriposAtomNames(mol)
    # Set up minimization
    ff = ForceField('test_forcefields/ammonia_minimal.offxml')
    topology, positions = oemol_to_openmmTop(mol)
    system = ff.createSystem(topology, [mol], verbose=verbose)
    positions = extractPositionsFromOEMol(mol)
    integrator = openmm.VerletIntegrator(2.0 * unit.femtoseconds)
    simulation = app.Simulation(topology, system, integrator)
    simulation.context.setPositions(positions)
    # Minimize energy
    simulation.minimizeEnergy()
    state = simulation.context.getState(getEnergy=True, getPositions=True)
    energy = state.getPotentialEnergy() / unit.kilocalories_per_mole
    newpositions = state.getPositions()
    outmol = openmmTop_to_oemol(topology, state.getPositions())
    # Sum angles around the N atom
    for atom in outmol.GetAtoms(oechem.OEIsInvertibleNitrogen()):
        aidx = atom.GetIdx()
        nbors = list(atom.GetAtoms())
        ang1 = math.degrees(oechem.OEGetAngle(outmol, nbors[0], atom,
                                              nbors[1]))
        ang2 = math.degrees(oechem.OEGetAngle(outmol, nbors[1], atom,
                                              nbors[2]))
        ang3 = math.degrees(oechem.OEGetAngle(outmol, nbors[2], atom,
                                              nbors[0]))
    ang_sum = math.fsum([ang1, ang2, ang3])
    # Check that sum of angles around N is within 1 degree of 353.5
    if abs(ang_sum - 353.5) > 1.0:
        raise Exception(
            "Improper torsion for ammonia differs too much from reference partly pyramidal geometry."
            "The reference case has a sum of H-N-H angles (3x) at 353.5 degrees; the test case has a sum of {}."
            .format(ang_sum))
    def pmdStructureToOEMol(parm, resname):

        from oeommtools.utils import openmmTop_to_oemol
        mask = "!(:%s)" % resname
        structure_LIG = parmed.load_file(
            '../2gmx_wat.prmtop', xyz='../equilibration/rst/step8.rst.125000')
        structure_LIG.strip(mask)
        pos = structure_LIG.positions
        top = structure_LIG.topology
        molecule = openmmTop_to_oemol(top, pos, verbose=False)
        OEPerceiveBondOrders(molecule)
        OEAssignAromaticFlags(molecule)
        OEFindRingAtomsAndBonds(molecule)

        return molecule
Ejemplo n.º 6
0
    def test_openmmTop_to_oemol(self):
        protein = ommutils.get_data_filename('examples', 'data/T4-protein.pdb')

        pdb = app.PDBFile(protein)

        oe_mol = oeommtools.openmmTop_to_oemol(pdb.topology, pdb.positions)

        # Assert
        self.assertEqual(pdb.topology.getNumAtoms(), oe_mol.NumAtoms())

        for (op_at, oe_at) in zip(pdb.topology.atoms(), oe_mol.GetAtoms()):
            self.assertEqual(op_at.index, oe_at.GetIdx())

        oe_pos = [v for k, v in oe_mol.GetCoords().items()]
        np.testing.assert_almost_equal(
            pdb.getPositions(asNumpy=True).in_units_of(unit.angstrom) /
            unit.angstrom,
            np.array(oe_pos),
            decimal=2)
Ejemplo n.º 7
0
    def process(self, mol, port):
        try:
            # Split the complex in components in order to apply the FF
            protein, ligand, water, excipients = utils.split(mol)

            # Unique prefix name used to output parametrization files
            self.opt['prefix_name'] = mol.GetTitle()

            # Apply FF to the Protein
            protein_structure = utils.applyffProtein(protein, self.opt)

            # Apply FF to water molecules
            water_structure = utils.applyffWater(water, self.opt)

            # Apply FF to the excipients
            if excipients.NumAtoms() > 0:
                excipient_structure = utils.applyffExcipients(excipients, self.opt)

                # The excipient order is set equal to the order in related
                # parmed structure to avoid possible atom index mismatching
                excipients = oeommutils.openmmTop_to_oemol(excipient_structure.topology,
                                                           excipient_structure.positions,
                                                           verbose=False)

            # Apply FF to the ligand
            ligand_structure = utils.applyffLigand(ligand, self.opt)

            # Build the Parmed structure
            if excipients.NumAtoms() > 0:
                complex_structure = protein_structure + ligand_structure + \
                                    excipient_structure + water_structure
            else:
                complex_structure = protein_structure + ligand_structure + water_structure

            num_atom_system = protein.NumAtoms() + ligand.NumAtoms() + excipients.NumAtoms() + water.NumAtoms()

            if not num_atom_system == complex_structure.topology.getNumAtoms():
                oechem.OEThrow.Fatal("Parmed and OE topologies mismatch atom number error")

            # Assemble a new OEMol complex in a specific order
            # to match the defined Parmed structure complex
            complx = protein.CreateCopy()
            oechem.OEAddMols(complx, ligand)
            oechem.OEAddMols(complx, excipients)
            oechem.OEAddMols(complx, water)

            complx.SetTitle(mol.GetTitle())

            # Set Parmed structure box_vectors
            vec_data = pack_utils.PackageOEMol.getData(complx, tag='box_vectors')
            vec = pack_utils.PackageOEMol.decodePyObj(vec_data)
            complex_structure.box_vectors = vec

            # Attach the Parmed structure to the complex
            packed_complex = pack_utils.PackageOEMol.pack(complx, complex_structure)

            # Attach the reference positions to the complex
            ref_positions = complex_structure.positions
            packedpos = pack_utils.PackageOEMol.encodePyObj(ref_positions)
            packed_complex.SetData(oechem.OEGetTag('OEMDDataRefPositions'), packedpos)

            # Set atom serial numbers, Ligand name and HETATM flag
            # oechem.OEPerceiveResidues(packed_complex, oechem.OEPreserveResInfo_SerialNumber)
            for at in packed_complex.GetAtoms():
                thisRes = oechem.OEAtomGetResidue(at)
                thisRes.SetSerialNumber(at.GetIdx())
                if thisRes.GetName() == 'UNL':
                    thisRes.SetName("LIG")
                    thisRes.SetHetAtom(True)
                oechem.OEAtomSetResidue(at, thisRes)

            if packed_complex.GetMaxAtomIdx() != complex_structure.topology.getNumAtoms():
                raise ValueError("OEMol complex and Parmed structure mismatch atom numbers")

            # Check if it is possible to create the OpenMM System
            system = complex_structure.createSystem(nonbondedMethod=app.CutoffPeriodic,
                                                    nonbondedCutoff=10.0 * unit.angstroms,
                                                    constraints=app.HBonds,
                                                    removeCMMotion=False)

            self.success.emit(packed_complex)
        except Exception as e:
            # Attach error message to the molecule that failed
            self.log.error(traceback.format_exc())
            mol.SetData('error', str(e))
            # Return failed mol
            self.failure.emit(mol)

        return
Ejemplo n.º 8
0
    def process(self, mol, port):
        try:

            # Split the complex in components in order to apply the FF
            protein, ligand, water, excipients = oeommutils.split(
                mol, ligand_res_name=self.opt['ligand_res_name'])

            self.log.info(
                "\nComplex name: {}\nProtein atom numbers = {}\nLigand atom numbers = {}\n"
                "Water atom numbers = {}\nExcipients atom numbers = {}".format(
                    mol.GetTitle(), protein.NumAtoms(), ligand.NumAtoms(),
                    water.NumAtoms(), excipients.NumAtoms()))

            # Unique prefix name used to output parametrization files
            self.opt['prefix_name'] = mol.GetTitle()

            oe_mol_list = []
            par_mol_list = []

            # Apply FF to the Protein
            if protein.NumAtoms():
                oe_mol_list.append(protein)
                protein_structure = utils.applyffProtein(protein, self.opt)
                par_mol_list.append(protein_structure)

            # Apply FF to the ligand
            if ligand.NumAtoms():
                oe_mol_list.append(ligand)
                ligand_structure = utils.applyffLigand(ligand, self.opt)
                par_mol_list.append(ligand_structure)

            # Apply FF to water molecules
            if water.NumAtoms():
                oe_mol_list.append(water)
                water_structure = utils.applyffWater(water, self.opt)
                par_mol_list.append(water_structure)

            # Apply FF to the excipients
            if excipients.NumAtoms():
                excipient_structure = utils.applyffExcipients(
                    excipients, self.opt)
                par_mol_list.append(excipient_structure)

                # The excipient order is set equal to the order in related
                # parmed structure to avoid possible atom index mismatching
                excipients = oeommutils.openmmTop_to_oemol(
                    excipient_structure.topology,
                    excipient_structure.positions,
                    verbose=False)
                oechem.OEPerceiveBondOrders(excipients)
                oe_mol_list.append(excipients)

            # Build the overall Parmed structure
            complex_structure = parmed.Structure()

            for struc in par_mol_list:
                complex_structure = complex_structure + struc

            complx = oe_mol_list[0].CreateCopy()
            num_atom_system = complx.NumAtoms()

            for idx in range(1, len(oe_mol_list)):
                oechem.OEAddMols(complx, oe_mol_list[idx])
                num_atom_system += oe_mol_list[idx].NumAtoms()

            if not num_atom_system == complex_structure.topology.getNumAtoms():
                oechem.OEThrow.Fatal(
                    "Parmed and OE topologies mismatch atom number error")

            complx.SetTitle(mol.GetTitle())

            # Set Parmed structure box_vectors
            is_periodic = True
            try:
                vec_data = pack_utils.PackageOEMol.getData(complx,
                                                           tag='box_vectors')
                vec = pack_utils.PackageOEMol.decodePyObj(vec_data)
                complex_structure.box_vectors = vec
            except:
                is_periodic = False
                self.log.warn(
                    "System has been parametrize without periodic box vectors for vacuum simulation"
                )

            # Attach the Parmed structure to the complex
            packed_complex = pack_utils.PackageOEMol.pack(
                complx, complex_structure)

            # Attach the reference positions to the complex
            ref_positions = complex_structure.positions
            packedpos = pack_utils.PackageOEMol.encodePyObj(ref_positions)
            packed_complex.SetData(oechem.OEGetTag('OEMDDataRefPositions'),
                                   packedpos)

            # Set atom serial numbers, Ligand name and HETATM flag
            # oechem.OEPerceiveResidues(packed_complex, oechem.OEPreserveResInfo_SerialNumber)
            for at in packed_complex.GetAtoms():
                thisRes = oechem.OEAtomGetResidue(at)
                thisRes.SetSerialNumber(at.GetIdx())
                if thisRes.GetName() == 'UNL':
                    # thisRes.SetName("LIG")
                    thisRes.SetHetAtom(True)
                oechem.OEAtomSetResidue(at, thisRes)

            if packed_complex.GetMaxAtomIdx(
            ) != complex_structure.topology.getNumAtoms():
                raise ValueError(
                    "OEMol complex and Parmed structure mismatch atom numbers")

            # Check if it is possible to create the OpenMM System
            if is_periodic:
                complex_structure.createSystem(
                    nonbondedMethod=app.CutoffPeriodic,
                    nonbondedCutoff=10.0 * unit.angstroms,
                    constraints=app.HBonds,
                    removeCMMotion=False)
            else:
                complex_structure.createSystem(nonbondedMethod=app.NoCutoff,
                                               constraints=app.HBonds,
                                               removeCMMotion=False)

            self.success.emit(packed_complex)
        except Exception as e:
            # Attach error message to the molecule that failed
            self.log.error(traceback.format_exc())
            mol.SetData('error', str(e))
            # Return failed mol
            self.failure.emit(mol)

        return
Ejemplo n.º 9
0
def hydrate(system, opt):
    """
    This function solvates the system by using PDBFixer

    Parameters:
    -----------
    system: OEMol molecule
        The system to solvate
    opt: python dictionary
        The parameters used to solvate the system

    Return:
    -------
    oe_mol: OEMol
        The solvated system
    """
    def BoundingBox(molecule):
        """
        This function calculates the Bounding Box of the passed
        molecule

        molecule: OEMol

        return: bb (numpy array)
            the calculated bounding box is returned as numpy array:
            [(xmin,ymin,zmin), (xmax,ymax,zmax)]
        """
        coords = [v for k, v in molecule.GetCoords().items()]
        np_coords = np.array(coords)
        min_coord = np_coords.min(axis=0)
        max_coord = np_coords.max(axis=0)
        bb = np.array([min_coord, max_coord])
        return bb

    # Create a system copy
    sol_system = system.CreateCopy()

    # Calculate system BoundingBox (Angstrom units)
    BB = BoundingBox(sol_system)

    # Estimation of the box cube length in A
    box_edge = 2.0 * opt['solvent_padding'] + np.max(BB[1] - BB[0])

    # BB center
    xc = (BB[0][0]+BB[1][0])/2.
    yc = (BB[0][1]+BB[1][1])/2.
    zc = (BB[0][2]+BB[1][2])/2.

    delta = np.array([box_edge/2., box_edge/2., box_edge/2.]) - np.array([xc, yc, zc])

    sys_coord_dic = {k: (v+delta) for k, v in sol_system.GetCoords().items()}

    sol_system.SetCoords(sys_coord_dic)

    # Load a fake system to initialize PDBfixer
    filename = resource_filename('pdbfixer', 'tests/data/test.pdb')
    fixer = PDBFixer(filename=filename)

    # Convert between OE and OpenMM topology
    omm_top, omm_pos = oeommutils.oemol_to_openmmTop(sol_system)

    chain_names = []

    for chain in omm_top.chains():
        chain_names.append(chain.id)

    # Set the correct topology to the fake system
    fixer.topology = omm_top
    fixer.positions = omm_pos

    # Solvate the system
    fixer.addSolvent(padding=unit.Quantity(opt['solvent_padding'], unit.angstroms),
                     ionicStrength=unit.Quantity(opt['salt_concentration'], unit.millimolar))

    # The OpenMM topology produced by the solvation fixer has missing bond
    # orders and aromaticity. The following section is creating a new openmm
    # topology made of just water molecules and ions. The new topology is then
    # converted in an OEMol and added to the passed molecule to produce the
    # solvated system

    wat_ion_top = app.Topology()

    # Atom dictionary between the the PDBfixer topology and the water_ion topology
    fixer_atom_to_wat_ion_atom = {}

    for chain in fixer.topology.chains():
        if chain.id not in chain_names:
            n_chain = wat_ion_top.addChain(chain.id)
            for res in chain.residues():
                n_res = wat_ion_top.addResidue(res.name, n_chain)
                for at in res.atoms():
                    n_at = wat_ion_top.addAtom(at.name, at.element, n_res)
                    fixer_atom_to_wat_ion_atom[at] = n_at

    for bond in fixer.topology.bonds():
        at0 = bond[0]
        at1 = bond[1]
        try:
            wat_ion_top.addBond(fixer_atom_to_wat_ion_atom[at0],
                                fixer_atom_to_wat_ion_atom[at1], type=None, order=1)
        except:
            pass

    wat_ion_pos = fixer.positions[len(omm_pos):]

    oe_mol = oeommutils.openmmTop_to_oemol(wat_ion_top, wat_ion_pos)

    # Setting the box vectors
    omm_box_vectors = fixer.topology.getPeriodicBoxVectors()
    box_vectors = utils.PackageOEMol.encodePyObj(omm_box_vectors)
    oe_mol.SetData(oechem.OEGetTag('box_vectors'), box_vectors)

    oechem.OEAddMols(oe_mol, sol_system)

    return oe_mol
Ejemplo n.º 10
0
def simulation(mdData, **opt):
    """
    This supporting function performs: OpenMM Minimization, NVT and NPT
    Molecular Dynamics (MD) simulations

    Parameters
    ----------
    mdData : MDData data object
        The object which recovers the relevant Parmed structure data
        to perform MD
    opt: python dictionary
        A dictionary containing all the MD setting info
    """
    
    if opt['Logger'] is None:
        printfile = sys.stdout
    else:
        printfile = opt['Logger'].file

    # MD data extracted from Parmed
    structure = mdData.structure
    topology = mdData.topology
    positions = mdData.positions
    velocities = mdData.velocities
    box = mdData.box

    # Time step in ps
    stepLen = 0.002 * unit.picoseconds

    # Centering the system to the OpenMM Unit Cell
    if opt['center'] and box is not None:
        opt['Logger'].info("Centering is On")
        # Numpy array in A
        coords = structure.coordinates
        # System Center of Geometry
        cog = np.mean(coords, axis=0)
        # System box vectors
        box_v = structure.box_vectors.in_units_of(unit.angstrom)/unit.angstrom
        box_v = np.array([box_v[0][0], box_v[1][1], box_v[2][2]])
        # Translation vector
        delta = box_v/2 - cog
        # New Coordinates
        new_coords = coords + delta
        structure.coordinates = new_coords
        positions = structure.positions

    # OpenMM system
    if box is not None:
        system = structure.createSystem(nonbondedMethod=eval("app.%s" % opt['nonbondedMethod']),
                                        nonbondedCutoff=opt['nonbondedCutoff']*unit.angstroms,
                                        constraints=eval("app.%s" % opt['constraints']),
                                        removeCMMotion=False)
    else:  # Vacuum
        system = structure.createSystem(nonbondedMethod=app.NoCutoff,
                                        constraints=eval("app.%s" % opt['constraints']),
                                        removeCMMotion=False)

    # OpenMM Integrator
    integrator = openmm.LangevinIntegrator(opt['temperature']*unit.kelvin, 1/unit.picoseconds, stepLen)
    
    if opt['SimType'] == 'npt':
        if box is None:
            oechem.OEThrow.Fatal("NPT simulation without box vector")

        # Add Force Barostat to the system
        system.addForce(openmm.MonteCarloBarostat(opt['pressure']*unit.atmospheres, opt['temperature']*unit.kelvin, 25))

    # Apply restraints
    if opt['restraints']:
        opt['Logger'].info("RESTRAINT mask applied to: {}"
                           "\tRestraint weight: {}".format(opt['restraints'],
                                                           opt['restraintWt'] *
                                                           unit.kilocalories_per_mole/unit.angstroms**2))
        # Select atom to restraint
        res_atom_set = oeommutils.select_oemol_atom_idx_by_language(opt['molecule'], mask=opt['restraints'])
        opt['Logger'].info("Number of restraint atoms: {}".format(len(res_atom_set)))
        # define the custom force to restrain atoms to their starting positions
        force_restr = openmm.CustomExternalForce('k_restr*periodicdistance(x, y, z, x0, y0, z0)^2')
        # Add the restraint weight as a global parameter in kcal/mol/A^2
        force_restr.addGlobalParameter("k_restr", opt['restraintWt']*unit.kilocalories_per_mole/unit.angstroms**2)
        # Define the target xyz coords for the restraint as per-atom (per-particle) parameters
        force_restr.addPerParticleParameter("x0")
        force_restr.addPerParticleParameter("y0")
        force_restr.addPerParticleParameter("z0")

        for idx in range(0, len(positions)):
            if idx in res_atom_set:
                xyz = positions[idx].in_units_of(unit.nanometers)/unit.nanometers
                force_restr.addParticle(idx, xyz)
        
        system.addForce(force_restr)

    # Freeze atoms
    if opt['freeze']:
        opt['Logger'].info("FREEZE mask applied to: {}".format(opt['freeze']))

        freeze_atom_set = oeommutils.select_oemol_atom_idx_by_language(opt['molecule'], mask=opt['freeze'])
        opt['Logger'].info("Number of frozen atoms: {}".format(len(freeze_atom_set)))
        # Set atom masses to zero
        for idx in range(0, len(positions)):
            if idx in freeze_atom_set:
                system.setParticleMass(idx, 0.0)

    if opt['platform'] == 'Auto':
        simulation = app.Simulation(topology, system, integrator)
    else:
        try:
            platform = openmm.Platform.getPlatformByName(opt['platform'])
        except Exception as e:
            oechem.OEThrow.Fatal('The selected platform is not supported: {}'.format(str(e)))

        if opt['platform'] in ['CUDA', 'OpenCL']:
            try:
                # Set platform CUDA or OpenCL precision
                properties = {'Precision': opt['cuda_opencl_precision']}

                simulation = app.Simulation(topology, system, integrator,
                                            platform=platform,
                                            platformProperties=properties)
            except Exception:
                oechem.OEThrow.Fatal('It was not possible to set the {} precision for the {} platform'
                                     .format(opt['cuda_opencl_precision'], opt['platform']))
        else:
            simulation = app.Simulation(topology, system, integrator, platform=platform)

    # Set starting positions and velocities
    simulation.context.setPositions(positions)

    # Set Box dimensions
    if box is not None:
        simulation.context.setPeriodicBoxVectors(box[0], box[1], box[2])

    # If the velocities are not present in the Parmed structure
    # new velocity vectors are generated otherwise the system is
    # restarted from the previous State
    if opt['SimType'] in ['nvt', 'npt']:

        if opt['trajectory_interval']:
            structure.save(opt['outfname']+'.pdb', overwrite=True)
            # GAC ADDED - TESTING
            # Preserve original pdb file residue numbers
            pdbfname_test = opt['outfname'] + '_ordering_test' + '.pdb'
            ofs = oechem.oemolostream(pdbfname_test)
            flavor = ofs.GetFlavor(oechem.OEFormat_PDB) ^ oechem.OEOFlavor_PDB_OrderAtoms
            ofs.SetFlavor(oechem.OEFormat_PDB, flavor)

            new_temp_mol = oeommutils.openmmTop_to_oemol(structure.topology, structure.positions, verbose=False)
            new_pos = new_temp_mol.GetCoords()
            opt['molecule'].SetCoords(new_pos)
            oechem.OEWriteConstMolecule(ofs, opt['molecule'])

        if velocities is not None:
            opt['Logger'].info('RESTARTING simulation from a previous State')
            simulation.context.setVelocities(velocities)
        else:
            # Set the velocities drawing from the Boltzmann distribution at the selected temperature
            opt['Logger'].info('GENERATING a new starting State')
            simulation.context.setVelocitiesToTemperature(opt['temperature']*unit.kelvin)

        # Convert simulation time in steps
        opt['steps'] = int(round(opt['time']/(stepLen.in_units_of(unit.picoseconds)/unit.picoseconds)))
        
        # Set Reporters
        for rep in getReporters(**opt):
            simulation.reporters.append(rep)
            
    # OpenMM platform information
    mmver = openmm.version.version
    mmplat = simulation.context.getPlatform()

    if opt['verbose']:
        # Host information
        from platform import uname
        for k, v in uname()._asdict().items():
            print(k, ':', v, file=printfile)
        # Platform properties
        for prop in mmplat.getPropertyNames():
            val = mmplat.getPropertyValue(simulation.context, prop)
            print(prop, ':', val, file=printfile)
            
    print('OpenMM({}) simulation generated for {} platform'.format(mmver, mmplat.getName()), file=printfile)

    if opt['SimType'] in ['nvt', 'npt']:

        opt['Logger'].info('Running {time} ps = {steps} steps of {SimType} at {temperature} K'.format(**opt))
        
        # Start Simulation
        simulation.step(opt['steps'])

        if box is not None:
            state = simulation.context.getState(getPositions=True, getVelocities=True,
                                                getEnergy=True, enforcePeriodicBox=True)
        else:
            state = simulation.context.getState(getPositions=True, getVelocities=True,
                                                getEnergy=True, enforcePeriodicBox=False)
        
    elif opt['SimType'] == 'min':
        # Start Simulation
        opt['Logger'].info('Minimization steps: {steps}'.format(**opt))

        state = simulation.context.getState(getEnergy=True)

        print('Initial energy = {}'.format(state.getPotentialEnergy().in_units_of(unit.kilocalorie_per_mole)),
              file=printfile)

        simulation.minimizeEnergy(maxIterations=opt['steps'])

        state = simulation.context.getState(getPositions=True, getEnergy=True)
        print('Minimized energy = {}'.format(state.getPotentialEnergy().in_units_of(unit.kilocalorie_per_mole)),
              file=printfile)

    # OpenMM Quantity object
    structure.positions = state.getPositions(asNumpy=False)
    # OpenMM Quantity object
    if box is not None:
        structure.box_vectors = state.getPeriodicBoxVectors()

    if opt['SimType'] in ['nvt', 'npt']:
        # numpy array in units of angstrom/picosecond
        structure.velocities = state.getVelocities(asNumpy=False)

        # If required uploading files to Orion
        _file_processing(**opt)

    # Update the OEMol complex positions to match the new
    # Parmed structure after the simulation
    new_temp_mol = oeommutils.openmmTop_to_oemol(structure.topology, structure.positions, verbose=False)
    new_pos = new_temp_mol.GetCoords()
    opt['molecule'].SetCoords(new_pos)

    return
Ejemplo n.º 11
0
def solvate(system, opt):
    """
    This function solvates the system by using PDBFixer

    Parameters:
    -----------
    system: OEMol molecule
        The system to solvate
    opt: python dictionary
        The parameters used to solvate the system

    Return:
    -------
    oe_mol: OEMol
        The solvated system
    """

    # Load a fake system to initialize PDBfixer
    filename = resource_filename('pdbfixer', 'tests/data/test.pdb')
    fixer = PDBFixer(filename=filename)

    # Convert between OE and OpenMM topology
    omm_top, omm_pos = oeommutils.oemol_to_openmmTop(system)

    chain_names = []

    for chain in omm_top.chains():
        chain_names.append(chain.id)

    # Set the correct topology to the fake system
    fixer.topology = omm_top
    fixer.positions = omm_pos

    # Solvate the system
    fixer.addSolvent(padding=unit.Quantity(opt['solvent_padding'], unit.angstroms),
                     ionicStrength=unit.Quantity(opt['salt_concentration'], unit.millimolar))

    # The OpenMM topology produced by the solvation fixer has missing bond
    # orders and aromaticity. The following section is creating a new openmm
    # topology made of just water molecules and ions. The new topology is then
    # converted in an OEMol and added to the passed molecule to produce the
    # solvated system

    wat_ion_top = app.Topology()

    # Atom dictionary between the the PDBfixer topology and the water_ion topology
    fixer_atom_to_wat_ion_atom = {}

    for chain in fixer.topology.chains():
        if chain.id not in chain_names:
            n_chain = wat_ion_top.addChain(chain.id)
            for res in chain.residues():
                n_res = wat_ion_top.addResidue(res.name, n_chain)
                for at in res.atoms():
                    n_at = wat_ion_top.addAtom(at.name, at.element, n_res)
                    fixer_atom_to_wat_ion_atom[at] = n_at

    for bond in fixer.topology.bonds():
        at0 = bond[0]
        at1 = bond[1]
        try:
            wat_ion_top.addBond(fixer_atom_to_wat_ion_atom[at0],
                                fixer_atom_to_wat_ion_atom[at1], type=None, order=1)
        except:
            pass

    wat_ion_pos = fixer.positions[len(omm_pos):]

    oe_mol = oeommutils.openmmTop_to_oemol(wat_ion_top, wat_ion_pos)

    # Setting the box vectors
    omm_box_vectors = fixer.topology.getPeriodicBoxVectors()
    box_vectors = utils.PackageOEMol.encodePyObj(omm_box_vectors)
    oe_mol.SetData(oechem.OEGetTag('box_vectors'), box_vectors)

    oechem.OEAddMols(oe_mol, system)

    return oe_mol