cljff.add(pol_tip4p, MGIdx(0))
cljff.add(waters, MGIdx(1))

system = System()
system.add(cljff)

print(system.energies())

polchgs = PolariseCharges(cljff[MGIdx(0)], cljff.components().coulomb(),
                          CoulombProbe(1*mod_electron))

system.add(polchgs)
system.add(polchgs.selfEnergyFF())

print("Applying the polarisation constraint...")
system.applyConstraints()

print(system.energies())

pol_tip4p = system[MGIdx(0)][pol_tip4p.number()].molecule()

print("MM charges\n",tip4p.property("charge"), \
                     tip4p.evaluate().charge({"charge":"charge"}))
print("Fixed charges\n",pol_tip4p.property("fixed_charge"), \
                        pol_tip4p.evaluate().charge({"charge":"fixed_charge"}))
print("Induced charges\n",pol_tip4p.property("induced_charge"), \
                          pol_tip4p.evaluate().charge({"charge":"induced_charge"}))
print("New charges\n",pol_tip4p.property("charge"), \
                      pol_tip4p.evaluate().charge({"charge":"charge"}))

grid = RegularGrid(tip4p.evaluate().center(), 10, 1.0*angstrom)
Exemple #2
0
def loadQMMMSystem():
    """This function is called to set up the system. It sets everything
       up, then returns a System object that holds the configured system"""

    print("Loading the system...")

    t = QTime()

    if os.path.exists(s3file.val):
        print("Loading existing s3 file %s..." % s3file.val)
        loadsys = Sire.Stream.load(s3file.val)

    else:
        print("Loading from Amber files %s / %s..." %
              (topfile.val, crdfile.val))
        # Add the name of the ligand to the list of solute molecules
        sys_scheme = NamingScheme()
        sys_scheme.addSoluteResidueName(ligand_name.val)

        # Load up the system. This will automatically find the protein, solute, water, solvent
        # and ion molecules and assign them to different groups
        loadsys = createSystem(topfile.val, crdfile.val, sys_scheme)
        ligand_mol = findMolecule(loadsys, ligand_name.val)

        if ligand_mol is None:
            print(
                "Cannot find the ligand (%s) in the set of loaded molecules!" %
                ligand_name.val)
            sys.exit(-1)

        # Center the system with the ligand at (0,0,0)
        loadsys = centerSystem(loadsys, ligand_mol)
        ligand_mol = loadsys[ligand_mol.number()][0].molecule()

        if reflection_radius.val is None:
            loadsys = addFlexibility(loadsys, naming_scheme=sys_scheme)
        else:
            loadsys = addFlexibility(loadsys,
                                     Vector(0),
                                     reflection_radius.val,
                                     naming_scheme=sys_scheme)

        Sire.Stream.save(loadsys, s3file.val)

    ligand_mol = findMolecule(loadsys, ligand_name.val)

    if ligand_mol is None:
        print("Cannot find the ligand (%s) in the set of loaded molecules!" %
              ligand_name.val)
        sys.exit(-1)

    # Now build the QM/MM system
    system = System("QMMM system")

    if loadsys.containsProperty("reflection center"):
        reflect_center = loadsys.property("reflection center").toVector()[0]
        reflect_radius = float(
            str(loadsys.property("reflection sphere radius")))

        system.setProperty("reflection center",
                           AtomCoords(CoordGroup(1, reflect_center)))
        system.setProperty("reflection sphere radius",
                           VariantProperty(reflect_radius))
        space = Cartesian()
    else:
        space = loadsys.property("space")

    if loadsys.containsProperty("average solute translation delta"):
        system.setProperty("average solute translation delta", \
                           loadsys.property("average solute translation delta"))

    if loadsys.containsProperty("average solute rotation delta"):
        system.setProperty("average solute rotation delta", \
                           loadsys.property("average solute rotation delta"))

    # create a molecule group to hold all molecules
    all_group = MoleculeGroup("all")

    # create a molecule group for the ligand
    ligand_group = MoleculeGroup("ligand")
    ligand_group.add(ligand_mol)
    all_group.add(ligand_mol)

    groups = []
    groups.append(ligand_group)

    # pull out the groups that we want from the two systems

    # create a group to hold all of the fixed molecules in the bound leg
    fixed_group = MoleculeGroup("fixed_molecules")
    if MGName("fixed_molecules") in loadsys.mgNames():
        fixed_group.add(loadsys[MGName("fixed_molecules")])

    if save_pdb.val:
        # write a PDB of the fixed atoms in the bound and free legs
        if not os.path.exists(outdir.val):
            os.makedirs(outdir.val)

        PDB().write(fixed_group, "%s/fixed.pdb" % outdir.val)

    # create a group to hold all of the mobile solute molecules
    mobile_solutes_group = MoleculeGroup("mobile_solutes")
    if MGName("mobile_solutes") in loadsys.mgNames():
        mobile_solutes_group.add(loadsys[MGName("mobile_solutes")])
        mobile_solutes_group.remove(ligand_mol)
        if mobile_solutes_group.nMolecules() > 0:
            all_group.add(mobile_solutes_group)

    groups.append(mobile_solutes_group)

    # create a group to hold all of the mobile solvent molecules
    mobile_solvents_group = MoleculeGroup("mobile_solvents")
    if MGName("mobile_solvents") in loadsys.mgNames():
        mols = loadsys[MGName("mobile_solvents")]
        for molnum in mols.molNums():
            solvent_mol = mols[molnum][0].molecule()
            mobile_solvents_group.add(solvent_mol)

        all_group.add(mobile_solvents_group)

        print("The number of mobile solvent molecules is %d." %
              mobile_solvents_group.nMolecules())

    groups.append(mobile_solvents_group)

    # create the groups to hold all of the protein molecules. We will use "extract" to
    # pull out only those protein atoms that are in the mobile region
    protein_intra_group = MoleculeGroup("protein_intra_group")
    mobile_proteins_group = MoleculeGroup("proteins")
    mobile_protein_sidechains_group = MoleculeGroup("mobile_sidechains")
    mobile_protein_backbones_group = MoleculeGroup("mobile_backbones")

    if MGName("protein_sidechains") in loadsys.mgNames() or \
       MGName("protein_backbones") in loadsys.mgNames():

        all_proteins = Molecules()

        try:
            protein_sidechains = loadsys[MGName("protein_sidechains")]
            all_proteins.add(protein_sidechains.molecules())
        except:
            protein_sidechains = MoleculeGroup()

        try:
            protein_backbones = loadsys[MGName("protein_backbones")]
            all_proteins.add(protein_backbones.molecules())
        except:
            protein_backbones = MoleculeGroup()

        try:
            boundary_molecules = loadsys[MGName("boundary_molecules")]
            all_proteins.add(boundary_molecules.molecules())
        except:
            boundary_molecules = MoleculeGroup()

        for molnum in all_proteins.molNums():
            protein_mol = Molecule.join(all_proteins[molnum])

            if protein_mol.selectedAll():
                protein_intra_group.add(protein_mol)
                all_group.add(protein_mol)

                mobile_protein = []

                if protein_sidechains.contains(molnum):
                    sidechains = protein_sidechains[molnum]
                    for sidechain in sidechains:
                        mobile_protein_sidechains_group.add(sidechain)

                    mobile_protein += sidechains

                if protein_backbones.contains(molnum):
                    backbones = protein_backbones[molnum]
                    for backbone in backbones:
                        mobile_protein_backbones_group.add(backbone)

                    mobile_protein += backbones

                if len(mobile_protein) > 0:
                    mobile_proteins_group.add(Molecule.join(mobile_protein))

            else:
                # only some of the atoms have been selected. We will extract
                # the mobile atoms and will then update all of the other selections
                print("Extracting the mobile atoms of protein %s" %
                      protein_mol.molecule())
                new_protein_mol = protein_mol.extract()
                print("Extracted %d mobile atoms from %d total atoms..." % \
                                        (new_protein_mol.nAtoms(), protein_mol.molecule().nAtoms()))

                protein_intra_group.add(new_protein_mol)
                all_group.add(new_protein_mol)

                mobile_protein_view = new_protein_mol.selection()
                mobile_protein_view = mobile_protein_view.selectNone()

                if protein_sidechains.contains(molnum):
                    sidechains = protein_sidechains[molnum]

                    for sidechain in sidechains:
                        view = new_protein_mol.selection()
                        view = view.selectNone()

                        for atomid in sidechain.selection().selectedAtoms():
                            atom = protein_mol.atom(atomid)
                            resatomid = ResAtomID(atom.residue().number(),
                                                  atom.name())
                            view = view.select(resatomid)
                            mobile_protein_view = mobile_protein_view.select(
                                resatomid)

                        if view.nSelected() > 0:
                            mobile_protein_sidechains_group.add(
                                PartialMolecule(new_protein_mol, view))

                if protein_backbones.contains(molnum):
                    backbones = protein_backbones[molnum]

                    for backbone in backbones:
                        view = new_protein_mol.selection()
                        view = view.selectNone()

                        for atomid in backbone.selection().selectedAtoms():
                            atom = protein_mol.atom(atomid)
                            resatomid = ResAtomID(atom.residue().number(),
                                                  atom.name())
                            view = view.select(resatomid)
                            mobile_protein_view = mobile_protein_view.select(
                                resatomid)

                        if view.nSelected() > 0:
                            mobile_protein_backbones_group.add(
                                PartialMolecule(new_protein_mol, view))

                print("Number of moved protein sidechain residues = %s" %
                      mobile_protein_sidechains_group.nViews())
                print("Number of moved protein backbone residues = %s" %
                      mobile_protein_backbones_group.nViews())

                if mobile_protein_view.nSelected() > 0:
                    mobile_proteins_group.add(
                        PartialMolecule(new_protein_mol, mobile_protein_view))

    groups.append(mobile_protein_backbones_group)
    groups.append(mobile_protein_sidechains_group)
    groups.append(all_group)

    # finished added in all of the proteins
    for group in groups:
        if group.nMolecules() > 0:
            print("Adding group %s" % group.name())
            system.add(group)

    # now add in the forcefields for the system...
    print("Creating the forcefields for the QM/MM system...")

    # first, group together the molecules grouped above into convenient
    # groups for the forcefields

    # group holding just the ligand
    ligand_mols = ligand_group.molecules()

    # group holding all of the mobile atoms
    mobile_mols = mobile_solvents_group.molecules()
    mobile_mols.add(mobile_solutes_group.molecules())
    mobile_mols.add(protein_intra_group.molecules())

    # group holding all of the mobile atoms in the bound leg, excluding the
    # buffer atoms that are fixed, but bonded to mobile atoms
    mobile_buffered_mols = mobile_solvents_group.molecules()
    mobile_buffered_mols.add(mobile_solutes_group.molecules())
    mobile_buffered_mols.add(mobile_proteins_group.molecules())

    # group holding all of the protein molecules that need intramolecular terms calculated
    protein_intra_mols = protein_intra_group.molecules()

    # group holding all of the solute molecules that nede intramolecular terms calculated
    solute_intra_mols = mobile_solutes_group.molecules()

    forcefields = []

    ###
    ### INTRA-ENERGY OF THE LIGAND AND CLUSTER
    ###

    # intramolecular energy of the ligand
    ligand_intraclj = IntraCLJFF("ligand:intraclj")
    ligand_intraclj = setCLJProperties(ligand_intraclj, space)
    ligand_intraclj.add(ligand_mols)

    ligand_intraff = InternalFF("ligand:intra")
    ligand_intraff.add(ligand_mols)

    forcefields.append(ligand_intraclj)
    forcefields.append(ligand_intraff)

    ligand_mm_nrg = ligand_intraclj.components().total(
    ) + ligand_intraff.components().total()

    ###
    ### FORCEFIELDS INVOLVING THE LIGAND/CLUSTER AND OTHER ATOMS
    ###

    # forcefield holding the energy between the ligand and the mobile atoms in the
    # bound leg
    ligand_mobile = InterGroupCLJFF("system:ligand-mobile")
    ligand_mobile = setCLJProperties(ligand_mobile, space)

    ligand_mobile.add(ligand_mols, MGIdx(0))
    ligand_mobile.add(mobile_mols, MGIdx(1))

    qm_ligand = QMMMFF("system:ligand-QM")
    qm_ligand.add(ligand_mols, MGIdx(0))
    qm_ligand = setQMProperties(qm_ligand, space)

    zero_energy = 0

    if not intermolecular_only.val:
        if qm_zero_energy.val is None:
            # calculate the delta value for the system - this is the difference between
            # the MM and QM intramolecular energy of the ligand
            t.start()
            print("\nComparing the MM and QM energies of the ligand...")
            mm_intra = ligand_intraclj.energy().value(
            ) + ligand_intraff.energy().value()
            print("MM energy = %s kcal mol-1 (took %s ms)" %
                  (mm_intra, t.elapsed()))

            t.start()
            zero_sys = System()
            zero_sys.add(qm_ligand)
            qm_intra = zero_sys.energy().value()
            print("QM energy = %s kcal mol-1 (took %s ms)" %
                  (qm_intra, t.elapsed()))

            print("\nSetting the QM zero energy to %s kcal mol-1" %
                  (qm_intra - mm_intra))
            qm_ligand.setZeroEnergy((qm_intra - mm_intra) * kcal_per_mol)
            zero_energy = qm_intra - mm_intra
        else:
            print("\nManually setting the QM zero energy to %s" %
                  qm_zero_energy.val)
            qm_ligand.setZeroEnergy(qm_zero_energy.val)
            zero_energy = qm_zero_energy.val

    qm_ligand.add(mobile_mols, MGIdx(1))

    ligand_mm_nrg += ligand_mobile.components().total()
    ligand_qm_nrg = qm_ligand.components().total() + ligand_mobile.components(
    ).lj()

    if intermolecular_only.val:
        # the QM model still uses the MM intramolecular energy of the ligand
        ligand_qm_nrg += ligand_intraclj.components().total(
        ) + ligand_intraff.components().total()

    forcefields.append(ligand_mobile)
    forcefields.append(qm_ligand)

    if fixed_group.nMolecules() > 0:
        # there are fixed molecules

        # Whether or not to disable the grid and calculate all energies atomisticly
        if disable_grid:
            # we need to renumber all of the fixed molecules so that they don't clash
            # with the mobile molecules
            print("Renumbering fixed molecules...")
            fixed_group = renumberMolecules(fixed_group)

        # forcefield holding the energy between the ligand and the fixed atoms in the bound leg
        if disable_grid:
            ligand_fixed = InterGroupCLJFF("system:ligand-fixed")
            ligand_fixed = setCLJProperties(ligand_fixed, space)
            ligand_fixed = setFakeGridProperties(ligand_fixed, space)

            ligand_fixed.add(ligand_mols, MGIdx(0))
            ligand_fixed.add(fixed_group, MGIdx(1))

            qm_ligand.add(fixed_group, MGIdx(1))

            ligand_mm_nrg += ligand_fixed.components().total()
            ligand_qm_nrg += ligand_fixed.components().lj()

            forcefields.append(ligand_fixed)

        else:
            ligand_fixed = GridFF2("system:ligand-fixed")
            ligand_fixed = setCLJProperties(ligand_fixed, space)
            ligand_fixed = setGridProperties(ligand_fixed)

            ligand_fixed.add(ligand_mols, MGIdx(0))
            ligand_fixed.addFixedAtoms(fixed_group)

            qm_ligand.addFixedAtoms(fixed_group)

            ligand_mm_nrg += ligand_fixed.components().total()
            ligand_qm_nrg += ligand_fixed.components().lj()

            forcefields.append(ligand_fixed)

    ###
    ### FORCEFIELDS NOT INVOLVING THE LIGAND
    ###

    # forcefield holding the intermolecular energy between all molecules
    mobile_mobile = InterCLJFF("mobile-mobile")
    mobile_mobile = setCLJProperties(mobile_mobile, space)

    mobile_mobile.add(mobile_mols)

    other_nrg = mobile_mobile.components().total()
    forcefields.append(mobile_mobile)

    # forcefield holding the energy between the mobile atoms and
    # the fixed atoms
    if disable_grid.val:
        mobile_fixed = InterGroupCLJFF("mobile-fixed")
        mobile_fixed = setCLJProperties(mobile_fixed)
        mobile_fixed = setFakeGridProperties(mobile_fixed, space)
        mobile_fixed.add(mobile_buffered_mols, MGIdx(0))
        mobile_fixed.add(fixed_group, MGIdx(1))
        other_nrg += mobile_fixed.components().total()
        forcefields.append(mobile_fixed)
    else:
        mobile_fixed = GridFF2("mobile-fixed")
        mobile_fixed = setCLJProperties(mobile_fixed, space)
        mobile_fixed = setGridProperties(mobile_fixed)

        # we use mobile_buffered_group as this group misses out atoms that are bonded
        # to fixed atoms (thus preventing large energies caused by incorrect non-bonded calculations)
        mobile_fixed.add(mobile_buffered_mols, MGIdx(0))
        mobile_fixed.addFixedAtoms(fixed_group)
        other_nrg += mobile_fixed.components().total()
        forcefields.append(mobile_fixed)

    # intramolecular energy of the protein
    if protein_intra_mols.nMolecules() > 0:
        protein_intraclj = IntraCLJFF("protein_intraclj")
        protein_intraclj = setCLJProperties(protein_intraclj, space)

        protein_intraff = InternalFF("protein_intra")

        for molnum in protein_intra_mols.molNums():
            protein_mol = Molecule.join(protein_intra_mols[molnum])
            protein_intraclj.add(protein_mol)
            protein_intraff.add(protein_mol)

        other_nrg += protein_intraclj.components().total()
        other_nrg += protein_intraff.components().total()
        forcefields.append(protein_intraclj)
        forcefields.append(protein_intraff)

    # intramolecular energy of any other solutes
    if solute_intra_mols.nMolecules() > 0:
        solute_intraclj = IntraCLJFF("solute_intraclj")
        solute_intraclj = setCLJProperties(solute_intraclj, space)

        solute_intraff = InternalFF("solute_intra")

        for molnum in solute_intra_mols.molNums():
            solute_mol = Molecule.join(solute_intra_mols[molnum])
            solute_intraclj.add(solute_mol)
            solute_intraff.add(solute_mol)

        other_nrg += solute_intraclj.components().total()
        other_nrg += solute_intraff.components().total()
        forcefields.append(solute_intraclj)
        forcefields.append(solute_intraff)

    ###
    ### NOW ADD THE FORCEFIELDS TO THE SYSTEM
    ###
    ###
    ### SETTING THE FORCEFIELD EXPRESSIONS
    ###

    lam = Symbol("lambda")

    e_slow = ((1 - lam) * ligand_qm_nrg) + (lam * ligand_mm_nrg) + other_nrg
    e_fast = ligand_mm_nrg + other_nrg

    de_by_dlam = ligand_mm_nrg - ligand_qm_nrg

    for forcefield in forcefields:
        system.add(forcefield)

    system.setConstant(lam, 0.0)

    system.setComponent(Symbol("E_{fast}"), e_fast)
    system.setComponent(Symbol("E_{slow}"), e_slow)
    system.setComponent(Symbol("dE/dlam"), de_by_dlam)
    system.setComponent(system.totalComponent(), e_slow)

    system.setProperty("space", space)

    if space.isPeriodic():
        # ensure that all molecules are wrapped into the space with the ligand at the center
        print("Adding in a space wrapper constraint %s, %s" %
              (space, ligand_mol.evaluate().center()))
        system.add(SpaceWrapper(ligand_mol.evaluate().center(), all_group))
        system.applyConstraints()

    print("\nHere are the values of all of the initial energy components...")
    t.start()
    printEnergies(system.energies())
    print("(these took %d ms to evaluate)\n" % t.elapsed())

    # Create a monitor to monitor the free energy average
    system.add("dG/dlam",
               MonitorComponent(Symbol("dE/dlam"), AverageAndStddev()))

    if intermolecular_only.val:
        print(
            "\n\n## This simulation uses QM to model *only* the intermolecular energy between"
        )
        print(
            "## the QM and MM atoms. The intramolecular energy of the QM atoms is still"
        )
        print("## modelled using MM.\n")
    else:
        print(
            "\n\n## This simulation uses QM to model both the intermolecular and intramolecular"
        )
        print(
            "## energies of the QM atoms. Because the this, we have to adjust the 'zero' point"
        )
        print(
            "## of the QM potential. You need to add the value %s kcal mol-1 back onto the"
            % zero_energy)
        print("## QM->MM free energy calculated using this program.\n")

    return system
Exemple #3
0
def createSystemFrom(molecules, space, system_name, naming_scheme = NamingScheme()):
    """Create a new System from the passed molecules and space,
       sorting the molecules into different molecule groups based on the
       passed naming scheme"""

    system = System(system_name)

    # If requested, change the water model for all water molecules
    if water_model.val == "tip4p":
        molnums = molecules.molNums()
        new_molecules = Molecules()

        print("Forcing all water molecules to use the %s water model..." % water_model.val)
        print("Converting %d molecules..." % len(molnums))
        i = 0
        for molnum in molnums:
            molecule = molecules[molnum].molecule()

            if i % 100 == 0:
                print("%d" % i)                
                sys.stdout.flush()

            elif i % 10 == 0:
                print(".", end=' ')
                sys.stdout.flush()

            i += 1

            if molecule.nAtoms() == 3:
                # this could be a TIP3P water
                resname =str(molecule.residue().name().value()).lower()

                if resname == "wat" or resname == "t3p":
                    new_molecule = convertTip3PtoTip4P(molecule)
                    if new_molecule:
                        molecule = new_molecule

            new_molecules.add(molecule)

        print("%d" % i)

        molecules = new_molecules

    nmols = molecules.nMolecules()

    print("Number of molecules == %s" % nmols)
    print("System space == %s" % space)

    if nmols == 0:
        return system

    print("Assigning molecules to molecule groups...")
    solute_group = MoleculeGroup(naming_scheme.solutesGroupName().value())
    protein_group = MoleculeGroup(naming_scheme.proteinsGroupName().value())
    solvent_group = MoleculeGroup(naming_scheme.solventsGroupName().value())
    water_group = MoleculeGroup(naming_scheme.watersGroupName().value())
    ion_group = MoleculeGroup(naming_scheme.ionsGroupName().value())
    all_group = MoleculeGroup(naming_scheme.allMoleculesGroupName().value())

    # The all molecules group has all of the molecules
    all_group.add(molecules)

    system.add(all_group)

    # Run through each molecule and decide what type it is...
    molnums = molecules.molNums()
    molnums.sort()

    central_molecule = None

    solutes = []
    proteins = []
    solvents = []
    waters = []
    ions = []

    for molnum in molnums:
        molecule = molecules[molnum].molecule()

        resnams = getResidueNames(molecule)

        if naming_scheme.isSolute(resnams):
            solutes.append(molecule)

        elif naming_scheme.isProtein(resnams):
            proteins.append(molecule)

        elif naming_scheme.isWater(resnams):
            waters.append(molecule)

        elif naming_scheme.isIon(resnams):
            ions.append(molecule)

        elif molecule.nResidues() == 1:
            solvents.append(molecule)

        else:
            solutes.append(molecule)

    # Ok - we have now divided everything up into groups
    for solute in solutes:
        solute_group.add(solute)

    for protein in proteins:
        protein_group.add(protein)

    for water in waters:
        solvent_group.add(water)
        water_group.add(water)

    for solvent in solvents:
        solvent_group.add(solvent)
    
    for ion in ions:
        solvent_group.add(ion)
        ion_group.add(ion)

    if solute_group.nMolecules() > 0:
        system.add(solute_group)

    if protein_group.nMolecules() > 0:
        system.add(protein_group)

    if solvent_group.nMolecules() > 0:
        system.add(solvent_group)

    if water_group.nMolecules() > 0:
        system.add(water_group)

    if ion_group.nMolecules() > 0:
        system.add(ion_group)    

    print("Number of solute molecules == %s" % solute_group.nMolecules()) 
    print("Number of protein molecules == %s" % protein_group.nMolecules())
    print("Number of ions == %s" % ion_group.nMolecules())
    print("Number of water molecules == %s" % water_group.nMolecules())
    print("Number of solvent molecules == %s" % solvent_group.nMolecules())
    print("(solvent group is waters + ions + unidentified single-residue molecules)")

    system.setProperty("space", space)
    system.add( SpaceWrapper( Vector(0), all_group ) )
    system.applyConstraints()

    print("Returning the constructed system")

    return system
Exemple #4
0
def loadQMMMSystem():
    """This function is called to set up the system. It sets everything
       up, then returns a System object that holds the configured system"""

    print("Loading the system...")

    t = QTime()

    if os.path.exists(s3file.val):
        print("Loading existing s3 file %s..." % s3file.val)
        loadsys = Sire.Stream.load(s3file.val)

    else:
        print("Loading from Amber files %s / %s..." % (topfile.val, crdfile.val))
        # Add the name of the ligand to the list of solute molecules
        sys_scheme = NamingScheme()
        sys_scheme.addSoluteResidueName(ligand_name.val)

        # Load up the system. This will automatically find the protein, solute, water, solvent
        # and ion molecules and assign them to different groups
        loadsys = createSystem(topfile.val, crdfile.val, sys_scheme)
        ligand_mol = findMolecule(loadsys, ligand_name.val)

        if ligand_mol is None:
            print("Cannot find the ligand (%s) in the set of loaded molecules!" % ligand_name.val)
            sys.exit(-1)

        # Center the system with the ligand at (0,0,0)
        loadsys = centerSystem(loadsys, ligand_mol)
        ligand_mol = loadsys[ligand_mol.number()].molecule()

        if reflection_radius.val is None:
            loadsys = addFlexibility(loadsys, naming_scheme=sys_scheme )
        else:
            loadsys = addFlexibility(loadsys, Vector(0), reflection_radius.val, naming_scheme=sys_scheme)

        Sire.Stream.save(loadsys, s3file.val)

    ligand_mol = findMolecule(loadsys, ligand_name.val)

    if ligand_mol is None:
        print("Cannot find the ligand (%s) in the set of loaded molecules!" % ligand_name.val)
        sys.exit(-1)

    # Now build the QM/MM system
    system = System("QMMM system")

    if loadsys.containsProperty("reflection center"):
        reflect_center = loadsys.property("reflection center").toVector()[0]
        reflect_radius = float(str(loadsys.property("reflection sphere radius")))

        system.setProperty("reflection center", AtomCoords(CoordGroup(1,reflect_center)))
        system.setProperty("reflection sphere radius", VariantProperty(reflect_radius))
        space = Cartesian()
    else:
        space = loadsys.property("space")

    if loadsys.containsProperty("average solute translation delta"):
        system.setProperty("average solute translation delta", \
                           loadsys.property("average solute translation delta"))

    if loadsys.containsProperty("average solute rotation delta"):
        system.setProperty("average solute rotation delta", \
                           loadsys.property("average solute rotation delta"))

    # create a molecule group to hold all molecules
    all_group = MoleculeGroup("all")

    # create a molecule group for the ligand
    ligand_group = MoleculeGroup("ligand")
    ligand_group.add(ligand_mol)
    all_group.add(ligand_mol)

    groups = []
    groups.append(ligand_group)

    # pull out the groups that we want from the two systems

    # create a group to hold all of the fixed molecules in the bound leg
    fixed_group = MoleculeGroup("fixed_molecules")
    if MGName("fixed_molecules") in loadsys.mgNames():
        fixed_group.add( loadsys[ MGName("fixed_molecules") ] )

    if save_pdb.val:
        # write a PDB of the fixed atoms in the bound and free legs
        if not os.path.exists(outdir.val):
            os.makedirs(outdir.val)

        PDB().write(fixed_group, "%s/fixed.pdb" % outdir.val)

    # create a group to hold all of the mobile solute molecules
    mobile_solutes_group = MoleculeGroup("mobile_solutes")
    if MGName("mobile_solutes") in loadsys.mgNames():
        mobile_solutes_group.add( loadsys[MGName("mobile_solutes")] )
        mobile_solutes_group.remove(ligand_mol)
        if mobile_solutes_group.nMolecules() > 0:
            all_group.add(mobile_solutes_group)
    
    groups.append(mobile_solutes_group)

    # create a group to hold all of the mobile solvent molecules
    mobile_solvents_group = MoleculeGroup("mobile_solvents")
    if MGName("mobile_solvents") in loadsys.mgNames():
        mols = loadsys[MGName("mobile_solvents")]
        for molnum in mols.molNums():
            solvent_mol = mols[molnum].molecule()
            mobile_solvents_group.add(solvent_mol)

        all_group.add(mobile_solvents_group)

        print("The number of mobile solvent molecules is %d." % mobile_solvents_group.nMolecules())

    groups.append(mobile_solvents_group)

    # create the groups to hold all of the protein molecules. We will use "extract" to 
    # pull out only those protein atoms that are in the mobile region
    protein_intra_group = MoleculeGroup("protein_intra_group")
    mobile_proteins_group = MoleculeGroup("proteins")
    mobile_protein_sidechains_group = MoleculeGroup("mobile_sidechains")
    mobile_protein_backbones_group = MoleculeGroup("mobile_backbones")

    if MGName("protein_sidechains") in loadsys.mgNames() or \
       MGName("protein_backbones") in loadsys.mgNames():

        all_proteins = Molecules()

        try:
            protein_sidechains = loadsys[MGName("protein_sidechains")]
            all_proteins.add(protein_sidechains.molecules())
        except:
            protein_sidechains = MoleculeGroup()

        try:
            protein_backbones = loadsys[MGName("protein_backbones")]
            all_proteins.add(protein_backbones.molecules())
        except:
            protein_backbones = MoleculeGroup()

        try:
            boundary_molecules = loadsys[MGName("boundary_molecules")]
            all_proteins.add(boundary_molecules.molecules())
        except:
            boundary_molecules = MoleculeGroup()

        for molnum in all_proteins.molNums():
            protein_mol = all_proteins[molnum].join()
            
            if protein_mol.selectedAll():
                protein_intra_group.add(protein_mol)
                all_group.add(protein_mol)

                mobile_protein = None                

                try:
                    mobile_protein = protein_sidechains[molnum]
                    mobile_protein_sidechains_group.add( mobile_protein )
                except:
                    pass

                try:
                    if mobile_protein is None:
                        mobile_protein = protein_backbones[molnum]
                        mobile_protein_backbones_group.add( mobile_protein )
                    else:
                        mobile_protein.add( protein_backbones[molnum].selection() )
                        mobile_protein_backbones_group.add( protein_backbones[molnum] )
                except:
                    pass

                if not (mobile_protein is None):
                    mobile_proteins_group.add( mobile_protein.join() )

            else:
                # only some of the atoms have been selected. We will extract
                # the mobile atoms and will then update all of the other selections
                print("Extracting the mobile atoms of protein %s" % protein_mol)
                new_protein_mol = protein_mol.extract()
                print("Extracted %d mobile atoms from %d total atoms..." % \
                                        (new_protein_mol.nAtoms(), protein_mol.molecule().nAtoms()))

                protein_intra_group.add(new_protein_mol)
                all_group.add( new_protein_mol )

                mobile_protein_view = new_protein_mol.selection()
                mobile_protein_view = mobile_protein_view.selectNone()

                try:
                    sidechains = protein_sidechains[molnum]

                    for i in range(0,sidechains.nViews()):
                        view = new_protein_mol.selection()
                        view = view.selectNone()

                        for atomid in sidechains.viewAt(i).selectedAtoms():
                            atom = protein_mol.atom(atomid)
                            resatomid = ResAtomID( atom.residue().number(), atom.name() )
                            view = view.select( resatomid )
                            mobile_protein_view = mobile_protein_view.select( resatomid )

                        if view.nSelected() > 0:
                            mobile_protein_sidechains_group.add( PartialMolecule(new_protein_mol, view) )
                except:
                    pass

                try:
                    backbones = protein_backbones[molnum]

                    for i in range(0,backbones.nViews()):
                        view = new_protein_mol.selection()
                        view = view.selectNone()

                        for atomid in backbones.viewAt(i).selectedAtoms():
                            atom = protein_mol.atom(atomid)
                            resatomid = ResAtomID( atom.residue().number(), atom.name() )
                            view = view.select( resatomid )
                            mobile_protein_view = mobile_protein_view.select( resatomid )

                        if view.nSelected() > 0:
                            mobile_protein_backbones_group.add( PartialMolecule(new_protein_mol, view) )
                except:
                    pass

                if mobile_protein_view.nSelected() > 0:
                    mobile_proteins_group.add( PartialMolecule(new_protein_mol, mobile_protein_view) )

    groups.append(mobile_protein_backbones_group)
    groups.append(mobile_protein_sidechains_group)
    groups.append(all_group)

    # finished added in all of the proteins
    for group in groups:
        if group.nMolecules() > 0:
            print("Adding group %s" % group.name())
            system.add(group)

    # now add in the forcefields for the system...
    print("Creating the forcefields for the QM/MM system...")

    # first, group together the molecules grouped above into convenient
    # groups for the forcefields

    # group holding just the ligand
    ligand_mols = ligand_group.molecules()

    # group holding all of the mobile atoms
    mobile_mols = mobile_solvents_group.molecules()
    mobile_mols.add( mobile_solutes_group.molecules() )
    mobile_mols.add( protein_intra_group.molecules() )

    # group holding all of the mobile atoms in the bound leg, excluding the 
    # buffer atoms that are fixed, but bonded to mobile atoms
    mobile_buffered_mols = mobile_solvents_group.molecules()
    mobile_buffered_mols.add( mobile_solutes_group.molecules() )
    mobile_buffered_mols.add( mobile_proteins_group.molecules() )

    # group holding all of the protein molecules that need intramolecular terms calculated
    protein_intra_mols = protein_intra_group.molecules()

    # group holding all of the solute molecules that nede intramolecular terms calculated
    solute_intra_mols = mobile_solutes_group.molecules()

    forcefields = []

    ###
    ### INTRA-ENERGY OF THE LIGAND AND CLUSTER
    ###
    
    # intramolecular energy of the ligand
    ligand_intraclj = IntraCLJFF("ligand:intraclj")
    ligand_intraclj = setCLJProperties(ligand_intraclj, space)
    ligand_intraclj.add(ligand_mols)

    ligand_intraff = InternalFF("ligand:intra")
    ligand_intraff.add(ligand_mols)

    forcefields.append(ligand_intraclj)
    forcefields.append(ligand_intraff)

    ligand_mm_nrg = ligand_intraclj.components().total() + ligand_intraff.components().total()

    ###
    ### FORCEFIELDS INVOLVING THE LIGAND/CLUSTER AND OTHER ATOMS
    ###

    # forcefield holding the energy between the ligand and the mobile atoms in the
    # bound leg
    ligand_mobile = InterGroupCLJFF("system:ligand-mobile")
    ligand_mobile = setCLJProperties(ligand_mobile, space)

    ligand_mobile.add(ligand_mols, MGIdx(0))
    ligand_mobile.add(mobile_mols, MGIdx(1))

    qm_ligand = QMMMFF("system:ligand-QM")    
    qm_ligand = setQMProperties(qm_ligand, space)

    qm_ligand.add(ligand_mols, MGIdx(0))

    zero_energy = 0

    if not intermolecular_only.val:
        if qm_zero_energy.val is None:
            # calculate the delta value for the system - this is the difference between
            # the MM and QM intramolecular energy of the ligand
            t.start()
            print("\nComparing the MM and QM energies of the ligand...")
            mm_intra = ligand_intraclj.energy().value() + ligand_intraff.energy().value()
            print("MM energy = %s kcal mol-1 (took %s ms)" % (mm_intra, t.elapsed()))

            t.start()
            qm_intra = qm_ligand.energy().value()
            print("QM energy = %s kcal mol-1 (took %s ms)" % (qm_intra, t.elapsed()))

            print("\nSetting the QM zero energy to %s kcal mol-1" % (qm_intra - mm_intra))
            qm_ligand.setZeroEnergy( (qm_intra-mm_intra) * kcal_per_mol )
            zero_energy = qm_intra - mm_intra
        else:
            print("\nManually setting the QM zero energy to %s" % qm_zero_energy.val)
            qm_ligand.setZeroEnergy( qm_zero_energy.val )
            zero_energy = qm_zero_energy.val

    qm_ligand.add(mobile_mols, MGIdx(1))

    ligand_mm_nrg += ligand_mobile.components().total()
    ligand_qm_nrg = qm_ligand.components().total() + ligand_mobile.components().lj()

    if intermolecular_only.val:
        # the QM model still uses the MM intramolecular energy of the ligand
        ligand_qm_nrg += ligand_intraclj.components().total() + ligand_intraff.components().total()

    forcefields.append(ligand_mobile)
    forcefields.append(qm_ligand)

    if fixed_group.nMolecules() > 0:
        # there are fixed molecules

        # Whether or not to disable the grid and calculate all energies atomisticly
        if disable_grid:
            # we need to renumber all of the fixed molecules so that they don't clash
            # with the mobile molecules
            print("Renumbering fixed molecules...")
            fixed_group = renumberMolecules(fixed_group)

        # forcefield holding the energy between the ligand and the fixed atoms in the bound leg
        if disable_grid:
            ligand_fixed = InterGroupCLJFF("system:ligand-fixed")
            ligand_fixed = setCLJProperties(ligand_fixed, space)
            ligand_fixed = setFakeGridProperties(ligand_fixed, space)

            ligand_fixed.add(ligand_mols, MGIdx(0))
            ligand_fixed.add(fixed_group, MGIdx(1))

            qm_ligand.add(fixed_group, MGIdx(1))

            ligand_mm_nrg += ligand_fixed.components().total()
            ligand_qm_nrg += ligand_fixed.components().lj()

            forcefields.append(ligand_fixed)

        else:
            ligand_fixed = GridFF("system:ligand-fixed")
            ligand_fixed = setCLJProperties(ligand_fixed, space)
            ligand_fixed = setGridProperties(ligand_fixed)

            ligand_fixed.add(ligand_mols, MGIdx(0))
            ligand_fixed.addFixedAtoms( fixed_group )

            qm_ligand.addFixedAtoms( fixed_group )

            ligand_mm_nrg += ligand_fixed.components().total()
            ligand_qm_nrg += ligand_fixed.components().lj()

            forcefields.append(ligand_fixed)

    ###
    ### FORCEFIELDS NOT INVOLVING THE LIGAND
    ###

    # forcefield holding the intermolecular energy between all molecules
    mobile_mobile = InterCLJFF("mobile-mobile")
    mobile_mobile = setCLJProperties(mobile_mobile, space)

    mobile_mobile.add(mobile_mols)

    other_nrg = mobile_mobile.components().total()
    forcefields.append(mobile_mobile)

    # forcefield holding the energy between the mobile atoms and  
    # the fixed atoms
    if disable_grid.val:
        mobile_fixed = InterGroupCLJFF("mobile-fixed")
        mobile_fixed = setCLJProperties(mobile_fixed)
        mobile_fixed = setFakeGridProperties(mobile_fixed, space)
        mobile_fixed.add(mobile_buffered_mols, MGIdx(0))
        mobile_fixed.add(fixed_group, MGIdx(1))
        other_nrg += mobile_fixed.components().total()
        forcefields.append(mobile_fixed)
    else:
        mobile_fixed = GridFF("mobile-fixed")
        mobile_fixed = setCLJProperties(mobile_fixed, space)
        mobile_fixed = setGridProperties(mobile_fixed)

        # we use mobile_buffered_group as this group misses out atoms that are bonded
        # to fixed atoms (thus preventing large energies caused by incorrect non-bonded calculations)
        mobile_fixed.add(mobile_buffered_mols, MGIdx(0))
        mobile_fixed.addFixedAtoms(fixed_group)
        other_nrg += mobile_fixed.components().total()
        forcefields.append(mobile_fixed)

    # intramolecular energy of the protein
    if protein_intra_mols.nMolecules() > 0:
        protein_intraclj = IntraCLJFF("protein_intraclj")
        protein_intraclj = setCLJProperties(protein_intraclj, space)

        protein_intraff = InternalFF("protein_intra")

        for molnum in protein_intra_mols.molNums():
            protein_mol = protein_intra_mols[molnum].join()
            protein_intraclj.add(protein_mol)
            protein_intraff.add(protein_mol)

        other_nrg += protein_intraclj.components().total()
        other_nrg += protein_intraff.components().total()
        forcefields.append(protein_intraclj)
        forcefields.append(protein_intraff)

    # intramolecular energy of any other solutes
    if solute_intra_mols.nMolecules() > 0:
        solute_intraclj = IntraCLJFF("solute_intraclj")
        solute_intraclj = setCLJProperties(solute_intraclj, space)

        solute_intraff = InternalFF("solute_intra")

        for molnum in solute_intra_mols.molNums():
            solute_mol = solute_intra_mols[molnum].join()
            solute_intraclj.add(solute_mol)
            solute_intraff.add(solute_mol)

        other_nrg += solute_intraclj.components().total()
        other_nrg += solute_intraff.components().total()
        forcefields.append(solute_intraclj)
        forcefields.append(solute_intraff)

    ###
    ### NOW ADD THE FORCEFIELDS TO THE SYSTEM
    ###
    ###
    ### SETTING THE FORCEFIELD EXPRESSIONS
    ###

    lam = Symbol("lambda")

    e_slow = ((1-lam) * ligand_qm_nrg) + (lam * ligand_mm_nrg) + other_nrg
    e_fast = ligand_mm_nrg + other_nrg

    de_by_dlam = ligand_mm_nrg - ligand_qm_nrg

    for forcefield in forcefields:
        system.add(forcefield)

    system.setConstant(lam, 0.0)

    system.setComponent(Symbol("E_{fast}"), e_fast)
    system.setComponent(Symbol("E_{slow}"), e_slow)
    system.setComponent(Symbol("dE/dlam"), de_by_dlam)
    system.setComponent( system.totalComponent(), e_slow )
 
    system.setProperty("space", space)
    
    if space.isPeriodic():
        # ensure that all molecules are wrapped into the space with the ligand at the center
        print("Adding in a space wrapper constraint %s, %s" % (space, ligand_mol.evaluate().center()))
        system.add( SpaceWrapper( ligand_mol.evaluate().center(), all_group ) )
        system.applyConstraints()

    print("\nHere are the values of all of the initial energy components...")
    t.start()
    printEnergies(system.energies())
    print("(these took %d ms to evaluate)\n" % t.elapsed())

    # Create a monitor to monitor the free energy average
    system.add( "dG/dlam", MonitorComponent(Symbol("dE/dlam"), AverageAndStddev()) )

    if intermolecular_only.val:
        print("\n\n## This simulation uses QM to model *only* the intermolecular energy between")
        print("## the QM and MM atoms. The intramolecular energy of the QM atoms is still")
        print("## modelled using MM.\n")
    else:
        print("\n\n## This simulation uses QM to model both the intermolecular and intramolecular")
        print("## energies of the QM atoms. Because the this, we have to adjust the 'zero' point")
        print("## of the QM potential. You need to add the value %s kcal mol-1 back onto the" % zero_energy)
        print("## QM->MM free energy calculated using this program.\n")

    return system
Exemple #5
0
def createSystemFrom(molecules,
                     space,
                     system_name,
                     naming_scheme=NamingScheme()):
    """Create a new System from the passed molecules and space,
       sorting the molecules into different molecule groups based on the
       passed naming scheme"""

    system = System(system_name)

    # If requested, change the water model for all water molecules
    if water_model.val == "tip4p":
        molnums = molecules.molNums()
        new_molecules = Molecules()

        print("Forcing all water molecules to use the %s water model..." %
              water_model.val)
        print("Converting %d molecules..." % len(molnums))
        i = 0
        for molnum in molnums:
            molecule = molecules[molnum].molecule()

            if i % 100 == 0:
                print("%d" % i)
                sys.stdout.flush()

            elif i % 10 == 0:
                print(".", end=' ')
                sys.stdout.flush()

            i += 1

            if molecule.nAtoms() == 3:
                # this could be a TIP3P water
                resname = str(molecule.residue().name().value()).lower()

                if resname == "wat" or resname == "t3p":
                    new_molecule = convertTip3PtoTip4P(molecule)
                    if new_molecule:
                        molecule = new_molecule

            new_molecules.add(molecule)

        print("%d" % i)

        molecules = new_molecules

    nmols = molecules.nMolecules()

    print("Number of molecules == %s" % nmols)
    print("System space == %s" % space)

    if nmols == 0:
        return system

    print("Assigning molecules to molecule groups...")
    solute_group = MoleculeGroup(naming_scheme.solutesGroupName().value())
    protein_group = MoleculeGroup(naming_scheme.proteinsGroupName().value())
    solvent_group = MoleculeGroup(naming_scheme.solventsGroupName().value())
    water_group = MoleculeGroup(naming_scheme.watersGroupName().value())
    ion_group = MoleculeGroup(naming_scheme.ionsGroupName().value())
    all_group = MoleculeGroup(naming_scheme.allMoleculesGroupName().value())

    # The all molecules group has all of the molecules
    all_group.add(molecules)

    system.add(all_group)

    # Run through each molecule and decide what type it is...
    molnums = molecules.molNums()
    molnums.sort()

    central_molecule = None

    solutes = []
    proteins = []
    solvents = []
    waters = []
    ions = []

    for molnum in molnums:
        molecule = molecules[molnum].molecule()

        resnams = getResidueNames(molecule)

        if naming_scheme.isSolute(resnams):
            solutes.append(molecule)

        elif naming_scheme.isProtein(resnams):
            proteins.append(molecule)

        elif naming_scheme.isWater(resnams):
            waters.append(molecule)

        elif naming_scheme.isIon(resnams):
            ions.append(molecule)

        elif molecule.nResidues() == 1:
            solvents.append(molecule)

        else:
            solutes.append(molecule)

    # Ok - we have now divided everything up into groups
    for solute in solutes:
        solute_group.add(solute)

    for protein in proteins:
        protein_group.add(protein)

    for water in waters:
        solvent_group.add(water)
        water_group.add(water)

    for solvent in solvents:
        solvent_group.add(solvent)

    for ion in ions:
        solvent_group.add(ion)
        ion_group.add(ion)

    if solute_group.nMolecules() > 0:
        system.add(solute_group)

    if protein_group.nMolecules() > 0:
        system.add(protein_group)

    if solvent_group.nMolecules() > 0:
        system.add(solvent_group)

    if water_group.nMolecules() > 0:
        system.add(water_group)

    if ion_group.nMolecules() > 0:
        system.add(ion_group)

    print("Number of solute molecules == %s" % solute_group.nMolecules())
    print("Number of protein molecules == %s" % protein_group.nMolecules())
    print("Number of ions == %s" % ion_group.nMolecules())
    print("Number of water molecules == %s" % water_group.nMolecules())
    print("Number of solvent molecules == %s" % solvent_group.nMolecules())
    print(
        "(solvent group is waters + ions + unidentified single-residue molecules)"
    )

    system.setProperty("space", space)
    system.add(SpaceWrapper(Vector(0), all_group))
    system.applyConstraints()

    print("Returning the constructed system")

    return system
hcl2_group = MoleculeGroup("HCl2", hcl2)

cff = InterCoulombFF("CoulombFF")
cff.add(hcl)
cff.add(hcl2)

print("Energy is %s : Should be about -10.9634 kcal mol-1" % cff.energy())

pottable = PotentialTable(hcl2_group)

cff.potential(pottable)

print("Potential is %s : Should be about [ -47.342 kcal mol-1, -15.380 kcal mol-1 ]" % \
          (str(pottable.getTable(hcl2.number()).toVector())))

pol = PolariseCharges(hcl2_group)

system = System()
system.add(cff)
system.add(hcl2_group)
system.add(pol.selfEnergyFF())
system.add(pol)

system.applyConstraints()

hcl2 = system[hcl2.number()].molecule()

print(system.energies())

print(hcl2.property("induced_charge"))