コード例 #1
0
def test_to_topology(molecule):
    """
    Make sure that a topology generated using qubekit matches an openff one.
    """
    mol = Ligand.from_file(file_name=get_data(molecule))
    offmol = OFFMolecule.from_file(file_path=get_data(molecule))
    assert (nx.algorithms.isomorphism.is_isomorphic(
        mol.to_topology(), offmol.to_networkx()) is True)
コード例 #2
0
def test_add_conformers(file_name):
    """
    Load up the bace pdb and then add conformers to it from other file types.
    """
    mol = Ligand.from_file(file_name=get_data("bace0.pdb"))
    mol.coordinates = None
    mol.add_conformer(file_name=get_data(file_name))
    assert mol.coordinates.shape == (mol.n_atoms, 3)
コード例 #3
0
def test_rb_offxml(tmpdir):
    """Make sure an error is raised if we try to create an offxml with a RB torsion."""
    with tmpdir.as_cwd():
        mol = Ligand.from_file(file_name=get_data("cyclohexane.sdf"))
        XML().run(molecule=mol, input_files=[get_data("cyclohexane.xml")])
        # there should be 6 RB terms
        assert mol.RBTorsionForce.n_parameters == 6

        with pytest.raises(NotImplementedError):
            mol.to_offxml("test.offxml")
コード例 #4
0
def test_protein_params(tmpdir):
    """
    Load up the small protein and make sure it is parametrised with the general qube forcefield.
    """
    with tmpdir.as_cwd():
        pro = Protein.from_file(file_name=get_data("capped_leu.pdb"))
        shutil.copy(get_data("capped_leu.pdb"), "capped_leu.pdb")
        xml_pro = XMLProtein()
        new_pro = xml_pro.parametrise_molecule(molecule=pro)
        new_pro.write_parameters("pro.xml")
コード例 #5
0
ファイル: test_forcebalance.py プロジェクト: qubekit/QUBEKit
def biphenyl():
    """
    Load up a biphenyl molecule with some torsiondrive data.
    """
    # load biphenyl
    mol = Ligand.from_file(file_name=get_data("biphenyl.sdf"))
    # load the torsiondrive data
    td_data = TorsionDriveData.from_qdata(
        qdata_file=get_data("biphenyl_qdata.txt"), dihedral=(6, 10, 11, 8))
    mol.add_qm_scan(scan_data=td_data)
    return mol
コード例 #6
0
def test_offxml_round_trip(tmpdir, openff, molecule):
    """
    Test round tripping offxml parameters through qubekit
    """

    with tmpdir.as_cwd():
        mol = Ligand.from_file(get_data(molecule))
        offmol = Molecule.from_file(get_data(molecule))
        openff.run(mol)
        mol.to_offxml("test.offxml")
        # build another openmm system and serialise to compare with deepdiff
        offxml = ForceField("test.offxml")
        assert offxml.author == f"QUBEKit_version_{qubekit.__version__}"
        qubekit_system = offxml.create_openmm_system(
            topology=offmol.to_topology())
        qubekit_xml = xmltodict.parse(
            openmm.XmlSerializer.serialize(qubekit_system))
        with open("qubekit_xml", "w") as output:
            output.write(openmm.XmlSerializer.serialize(qubekit_system))
        openff_system = xmltodict.parse(open("serialised.xml").read())

        offxml_diff = DeepDiff(
            qubekit_xml,
            openff_system,
            ignore_order=True,
            significant_digits=6,
        )
        # the only difference should be in torsions with a 0 barrier height which are excluded from an offxml
        for item in offxml_diff["iterable_item_removed"].values():
            assert item["@k"] == "0"

        # load both systems and compute the energy
        qubekit_top = load_topology(
            mol.to_openmm_topology(),
            system=qubekit_system,
            xyz=mol.openmm_coordinates(),
        )
        qubekit_energy = energy_decomposition_system(qubekit_top,
                                                     qubekit_system,
                                                     platform="Reference")

        ref_system = XmlSerializer.deserializeSystem(
            open("serialised.xml").read())
        parm_top = load_topology(mol.to_openmm_topology(),
                                 system=ref_system,
                                 xyz=mol.openmm_coordinates())
        ref_energy = energy_decomposition_system(parm_top,
                                                 ref_system,
                                                 platform="Reference")
        # compare the decomposed energies of the groups
        for force_group, energy in ref_energy:
            for qube_force, qube_e in qubekit_energy:
                if force_group == qube_force:
                    assert energy == pytest.approx(qube_e, abs=2e-3)
コード例 #7
0
def test_read_rb_terms(tmpdir):
    """
    Make sure we can parameterise a molecules using an xml file with RB torsion terms.
    """
    with tmpdir.as_cwd():
        mol = Ligand.from_file(file_name=get_data("cyclohexane.sdf"))
        XML().run(molecule=mol, input_files=[get_data("cyclohexane.xml")])
        # there should be 6 RB terms
        assert mol.RBTorsionForce.n_parameters == 6
        # and no periodic terms
        assert mol.TorsionForce.n_parameters == 0
コード例 #8
0
def test_parameter_round_trip(method, tmpdir, xml, openff, antechamber):
    """
    Check we can parametrise a molecule then write out the same parameters.
    """

    if method == "openff":
        param_method = openff
    else:
        param_method = antechamber

    with tmpdir.as_cwd():
        mol = Ligand.from_file(get_data("acetone.sdf"))
        param_mol = param_method.run(mol)
        with open("serialised.xml") as old:
            with open("orig.xml", "w") as new:
                new.write(old.read())
        # write out params
        mol.write_parameters(file_name="test.xml")

        # make a second mol
        mol2 = Ligand.from_file(get_data("acetone.sdf"))
        param_mol2 = xml.run(molecule=mol2, input_files=["test.xml"])

        for bond in mol.bonds:
            bond_tuple = (bond.atom1_index, bond.atom2_index)
            bond1 = param_mol.BondForce[bond_tuple]
            bond2 = param_mol2.BondForce[bond_tuple]
            assert bond1.k == pytest.approx(bond2.k)
            assert bond1.length == pytest.approx(bond2.length)

        for angle in mol.angles:
            angle1 = param_mol.AngleForce[angle]
            angle2 = param_mol2.AngleForce[angle]
            assert angle1.k == pytest.approx(angle2.k)
            assert angle2.angle == pytest.approx(angle2.angle)

        for atom in range(mol.n_atoms):
            atom1 = param_mol.NonbondedForce[(atom, )]
            atom2 = param_mol2.NonbondedForce[(atom, )]
            assert atom1.charge == pytest.approx(atom2.charge)
            assert atom1.sigma == pytest.approx(atom2.sigma)
            assert atom1.epsilon == pytest.approx(atom2.epsilon)

        # loop over the round trip mol as we lose some parameters which are 0
        for dihedral in param_mol2.TorsionForce.parameters:
            other_dih = param_mol.TorsionForce[dihedral.atoms]
            for key in dihedral.__fields__:
                # openmm will not load any torsions which have k=0, this causes differences between antechamber and
                # qubekit when the phase is not as expected, this does not change the energy however as k=0
                if (key not in ["atoms", "attributes", "parameter_eval"]
                        and "phase" not in key):
                    assert getattr(dihedral, key) == pytest.approx(
                        getattr(other_dih, key))
コード例 #9
0
def test_parametrise_all(parameter_engine, tmpdir):
    """
    For each parameter engine make sure the molecule is correctly parameterised.
    """
    with tmpdir.as_cwd():
        mol = Ligand.from_file(get_data("pyridine.sdf"))
        mol.parameter_engine = parameter_engine
        if parameter_engine == "xml":
            shutil.copy(get_data("pyridine.xml"), "pyridine.xml")
        param_mol = Execute.parametrise(molecule=mol, verbose=False)
        # make sure parameters have been found
        for i in range(param_mol.n_atoms):
            assert param_mol.NonbondedForce.n_parameters == mol.n_atoms
コード例 #10
0
def test_combine_sites_offxml(xml, tmpdir, rfree_data):
    """
    Make sure an error is raised if we try and combine with vsites.
    """
    with tmpdir.as_cwd():
        pyridine = Ligand.from_file(file_name=get_data("pyridine.sdf"))
        xml.run(molecule=pyridine, input_files=[get_data("pyridine.xml")])
        with pytest.raises(NotImplementedError):
            _combine_molecules_offxml(
                molecules=[pyridine],
                parameters=elements,
                rfree_data=rfree_data,
                filename="test.offxml",
            )
コード例 #11
0
def test_offxml_sites(xml, tmpdir):
    """Make sure an error is raised when we try to create an offxml for a molecule with a virtual site"""
    with tmpdir.as_cwd():
        mol = Ligand.from_file(get_data("pyridine.pdb"))
        xml.run(
            mol,
            input_files=[
                get_data("pyridine.xml"),
            ],
        )

        assert mol.extra_sites.n_sites == 1

        with pytest.raises(NotImplementedError):
            mol.to_offxml("test.offxml")
コード例 #12
0
    def generate_optimise_in(self, target_data: Dict[str, List[str]]) -> None:
        """
        For the given list of targets and entries produce an optimize.in file which contains all of the run time settings to be used in the optimization.
        this uses jinja templates to generate the required file from the template distributed with qubekit.

        Args:
            target_data: A dictionary mapping the target name to the target folders that have been created.
        """
        from jinja2 import Template

        template_file = get_data(os.path.join("templates", "optimize.txt"))
        with open(template_file) as file:
            template = Template(file.read())

        data = self.dict(exclude={"targets", "priors"})
        data["priors"] = self.priors.dict()
        data["fitting_targets"] = target_data
        target_options = {}
        for target in self.targets.values():
            target_options[target.target_name] = target.fb_options()
        data["target_options"] = target_options

        rendered_template = template.render(**data)

        with open("optimize.in", "w") as opt_in:
            opt_in.write(rendered_template)
コード例 #13
0
ファイル: ligand_test.py プロジェクト: qubekit/QUBEKit
def test_no_dihedrals():
    """
    Make sure we return None when no dihedrals are found in the molecule.
    """
    mol = Ligand.from_file(file_name=get_data("water.pdb"))
    assert not mol.dihedrals
    assert mol.n_dihedrals == 0
コード例 #14
0
ファイル: ligand_test.py プロジェクト: qubekit/QUBEKit
def test_find_rotatable_bonds_n_rotatables(molecule, n_rotatables):
    """
    Ensure the number of rotatable bonds found matches the expected.
    """
    mol = Ligand.from_file(get_data(molecule))
    assert (len(mol.find_rotatable_bonds(["[*:1]-[CH3:2]",
                                          "[*:1]-[NH2:2]"])) == n_rotatables)
コード例 #15
0
def test_parameter_tags(tmpdir, force_group, ff_group, key, terms):
    """
    Make sure that the parameter tagger tags correct terms.
    """
    with tmpdir.as_cwd():
        mol = Ligand.from_file(file_name=get_data("biphenyl.sdf"))
        OpenFF().run(molecule=mol)
        # set the parameter tags
        for term in terms:
            f_group = getattr(mol, force_group)
            parameter = f_group[term]
            parameter.attributes = {"test tag"}
        # make the force field
        ff = mol._build_forcefield()
        classes = [[
            f"{mol.atoms[i].atomic_symbol}{mol.atoms[i].atom_index}"
            for i in term
        ] for term in terms]
        term_length = len(terms[0])
        # now search through and make sure the force groups were tagged
        for group in ff.iter(tag=ff_group):
            for ff_term in group.iter(tag=key):
                ff_class = [
                    ff_term.get(f"class{i}")
                    for i in range(1, 1 + term_length)
                ]
                if ff_class in classes:
                    assert ff_term.get("parametrize") == "test tag"
                else:
                    assert ff_term.get("parametrize", None) is None
コード例 #16
0
def test_parameter_engines(tmpdir, parameter_engine, openff, antechamber):
    """
    Make sure we can parametrise a molecule using antechamber
    """
    if parameter_engine == "openff":
        engine = openff
    else:
        engine = antechamber

    with tmpdir.as_cwd():
        mol = Ligand.from_file(get_data("acetone.sdf"))

        # make sure we have no starting parameters
        assert mol.BondForce.n_parameters == 0
        assert mol.AngleForce.n_parameters == 0
        assert mol.TorsionForce.n_parameters == 0
        assert mol.ImproperTorsionForce.n_parameters == 0
        assert mol.NonbondedForce.n_parameters == 0

        engine.run(mol)
        # make sure the parameters have been set
        assert mol.BondForce.n_parameters != 0
        assert mol.AngleForce.n_parameters != 0
        assert mol.TorsionForce.n_parameters != 0
        assert mol.ImproperTorsionForce.n_parameters != 0
        assert mol.NonbondedForce.n_parameters != 0
コード例 #17
0
ファイル: ligand_test.py プロジェクト: qubekit/QUBEKit
def test_to_rdkit(molecule):
    """
    Make sure we can convert to rdkit.
    We test on bace which has a chiral center and 12-dichloroethene which has a stereo bond.
    """
    from rdkit import Chem

    mol = Ligand.from_file(file_name=get_data(molecule))
    rd_mol = mol.to_rdkit()
    # make sure the atom and bond stereo match
    for atom in rd_mol.GetAtoms():
        qb_atom = mol.atoms[atom.GetIdx()]
        assert atom.GetIsAromatic() is qb_atom.aromatic
        if qb_atom.stereochemistry is not None:
            if qb_atom.stereochemistry == "S":
                assert atom.GetChiralTag() == Chem.CHI_TETRAHEDRAL_CCW
            else:
                assert atom.GetChiralTag() == Chem.CHI_TETRAHEDRAL_CW
    for bond in rd_mol.GetBonds():
        qb_bond = mol.bonds[bond.GetIdx()]
        assert qb_bond.aromatic is bond.GetIsAromatic()
        assert qb_bond.bond_order == bond.GetBondTypeAsDouble()
        if qb_bond.stereochemistry is not None:
            if qb_bond.stereochemistry == "E":
                assert bond.GetStereo() == Chem.BondStereo.STEREOE
            else:
                assert bond.GetStereo() == Chem.BondStereo.STEREOZ
コード例 #18
0
ファイル: test_charges.py プロジェクト: qubekit/QUBEKit
def test_gaussian_solvent_template(tmpdir, water):
    """
    Make sure that the template rendered with solvent settings matches what we expect.
    """
    with tmpdir.as_cwd():
        # get the charge method and implicit solvent engine
        charge_engine = DDECCharges()
        solvent_settings = charge_engine._get_calculation_settings()
        # now make an atomic input for the harness
        task = AtomicInput(
            molecule=water.to_qcschema(),
            driver="energy",
            model={
                "method": "b3lyp-d3bj",
                "basis": "6-311G"
            },
            keywords=solvent_settings,
        )
        # we need the harness as this will render the template
        gaussian_harness = GaussianHarness()
        config = get_config(task_config={"ncores": 1, "memory": 1})
        job_inputs = gaussian_harness.build_input(task, config)
        # make sure the job file matches or expected reference
        with open(get_data("gaussian_solvent_example.com")) as g_out:
            assert g_out.read() == job_inputs["infiles"]["gaussian.com"]
コード例 #19
0
ファイル: ligand_test.py プロジェクト: qubekit/QUBEKit
def test_find_rotatable_bonds_no_rotatables(molecule):
    """
    Ensure rigid molecules, or molecules without any rotatable bonds
    do not have any rotatable bonds.
    """
    mol = Ligand.from_file(get_data(molecule))
    assert mol.find_rotatable_bonds(["[*:1]-[CH3:2]", "[*:1]-[NH2:2]"]) is None
コード例 #20
0
ファイル: seminario_test.py プロジェクト: qubekit/QUBEKit
def test_hessian_unit_regression(tmpdir):
    """
    The modsem method was found to have a bug in the scaling code which caused all angles to be scaled by the same amount.
    Here we try to reproduce some reference values for methanol which has a mix of scaled and non scaled angles.
    """
    with tmpdir.as_cwd():
        # load coords at the qm geometry
        mol = Ligand.parse_file(get_data("methanol.json"))

        mod_sem = ModSeminario()
        mod_sem.run(molecule=mol)

        # check the C-O bond
        assert round(mol.BondForce[(0, 1)].length, ndigits=4) == 0.1413
        # get in kcal/mol like the reference values
        assert round(mol.BondForce[(0, 1)].k, 3) == 246439.036
        # check a O-H bond
        assert round(mol.BondForce[(1, 5)].length, 4) == 0.0957
        assert round(mol.BondForce[(1, 5)].k, 2) == 513819.18

        # check the C-O-H angle
        assert round(mol.AngleForce[(0, 1, 5)].angle, 3) == 1.899
        assert round(mol.AngleForce[(0, 1, 5)].k, 3) == 578.503

        # check a scaled H-C-H angle
        assert round(mol.AngleForce[(2, 0, 3)].angle, 3) == 1.894
        assert round(mol.AngleForce[(2, 0, 3)].k, 3) == 357.05
コード例 #21
0
ファイル: protein_test.py プロジェクト: qubekit/QUBEKit
def test_from_pdb():
    """
    Make sure we can make a protein from a pdb file.
    """
    pro = Protein.from_file(file_name=get_data("capped_leu.pdb"))
    assert pro.n_atoms == 31
    assert pro.coordinates.shape == (pro.n_atoms, 3)
コード例 #22
0
ファイル: ligand_test.py プロジェクト: qubekit/QUBEKit
def test_no_impropers():
    """
    Make sure we return None when no impropers are found in the molecule.
    """
    mol = Ligand.from_file(file_name=get_data("water.pdb"))
    assert mol.improper_torsions is None
    assert mol.n_improper_torsions == 0
コード例 #23
0
def test_single_point_energy(program, basis, method, tmpdir):
    """
    Make sure our qcengine wrapper works correctly.
    """
    if program not in qcengine.list_available_programs():
        pytest.skip(f"{program} missing skipping test.")

    with tmpdir.as_cwd():
        mol = Ligand.from_file(file_name=get_data("water.pdb"))
        engine = QCEngine(
            program=program,
            basis=basis,
            method=method,
            memory=1,
            cores=1,
            driver="energy",
        )
        result = engine.call_qcengine(molecule=mol)
        assert result.driver == "energy"
        assert result.model.basis == basis
        assert result.model.method == method
        assert result.provenance.creator.lower() == program
        # make sure the grid was set to ultrafine for psi4
        if program == "psi4":
            assert result.keywords["dft_spherical_points"] == 590
            assert result.keywords["dft_radial_points"] == 99
コード例 #24
0
ファイル: torsiondrive_test.py プロジェクト: qubekit/QUBEKit
def test_optimise_grid_point_and_update(tmpdir, ethane_state):
    """
    Try and perform a single grid point optimisation.
    """
    with tmpdir.as_cwd():
        mol = Ligand.from_file(get_data("ethane.sdf"))
        tdriver = TorsionDriver(n_workers=1)
        qc_spec = QCOptions(program="rdkit", basis=None, method="uff")
        local_ops = LocalResource(cores=1, memory=1)
        geo_opt = tdriver._build_geometry_optimiser()
        # get the job inputs
        new_jobs = tdriver._get_new_jobs(td_state=ethane_state)
        coords = new_jobs["-60"][0]
        result = optimise_grid_point(
            geometry_optimiser=geo_opt,
            qc_spec=qc_spec,
            local_options=local_ops,
            molecule=mol,
            coordinates=coords,
            dihedral=ethane_state["dihedrals"][0],
            dihedral_angle=-60,
            job_id=0,
        )
        new_state = tdriver._update_state(
            td_state=ethane_state,
            result_data=[
                result,
            ],
        )
        next_jobs = tdriver._get_new_jobs(td_state=new_state)
        assert "-75" in next_jobs
        assert "-45" in next_jobs
コード例 #25
0
ファイル: test_charges.py プロジェクト: am-official/QUBEKit
def test_chargemol_template(tmpdir, version):
    """
    Make sure we can correctly render a chargemol template job.
    """
    with tmpdir.as_cwd():
        mol = Ligand.from_file(get_data("water.pdb"))
        OpenFF().parametrise_molecule(molecule=mol)
        charge_method = DDECCharges(
            apply_symmetry=True,
            basis="sto-3g",
            method="hf",
            cores=1,
            memory=1,
            ddec_version=version,
        )
        # fake the chargemol dir
        os.environ["CHARGEMOL_DIR"] = "test"
        # now render the template
        charge_method._build_chargemol_input(density_file_name="test.wfx",
                                             molecule=mol)
        with open("job_control.txt") as job_file:
            job_data = job_file.readlines()

        assert f"DDEC{version}\n" in job_data
        assert "test.wfx\n" in job_data
        assert "test/atomic_densities/\n" in job_data
        assert f"{mol.charge}\n" in job_data
コード例 #26
0
ファイル: torsiondrive_test.py プロジェクト: qubekit/QUBEKit
def test_get_initial_state(tmpdir, starting_conformations):
    """
    Make sure we can correctly build a starting state using the torsiondrive api.
    """
    with tmpdir.as_cwd():
        mol = Ligand.from_file(get_data("ethane.sdf"))
        bond = mol.find_rotatable_bonds()[0]
        dihedral = mol.dihedrals[bond.indices][0]
        tdriver = TorsionDriver(starting_conformations=starting_conformations)
        # make the scan data
        dihedral_data = TorsionScan(torsion=dihedral, scan_range=(-165, 180))
        td_state = tdriver._create_initial_state(molecule=mol,
                                                 dihedral_data=dihedral_data,
                                                 qc_spec=QCOptions())
        assert td_state["dihedrals"] == [
            dihedral,
        ]
        assert td_state["elements"] == [
            atom.atomic_symbol for atom in mol.atoms
        ]
        assert td_state["dihedral_ranges"] == [
            (-165, 180),
        ]
        assert np.allclose((mol.coordinates * constants.ANGS_TO_BOHR),
                           td_state["init_coords"][0])
        # make sure we have tried to generate conformers
        assert len(td_state["init_coords"]) <= tdriver.starting_conformations
コード例 #27
0
ファイル: torsiondrive_test.py プロジェクト: qubekit/QUBEKit
def test_full_tdrive(tmpdir, workers, capsys):
    """
    Try and run a full torsiondrive for ethane with a cheap rdkit method.
    """
    with tmpdir.as_cwd():

        ethane = Ligand.from_file(get_data("ethane.sdf"))
        # make the scan data
        bond = ethane.find_rotatable_bonds()[0]
        dihedral = ethane.dihedrals[bond.indices][0]
        dihedral_data = TorsionScan(torsion=dihedral, scan_range=(-165, 180))
        qc_spec = QCOptions(program="rdkit", basis=None, method="uff")
        local_ops = LocalResource(cores=workers, memory=2)
        tdriver = TorsionDriver(
            n_workers=workers,
            grid_spacing=60,
        )
        _ = tdriver.run_torsiondrive(
            molecule=ethane,
            dihedral_data=dihedral_data,
            qc_spec=qc_spec,
            local_options=local_ops,
        )
        captured = capsys.readouterr()
        # make sure a fresh torsiondrive is run
        assert "Starting new torsiondrive" in captured.out
コード例 #28
0
ファイル: ligand_test.py プロジェクト: qubekit/QUBEKit
def test_ligand_from_file(file_name):
    """
    For the given file type make sure rdkit can parse it and return the molecule.
    """
    mol = Ligand.from_file(file_name=get_data(file_name))
    assert mol.n_atoms > 1
    assert mol.n_bonds > 1
    assert mol.name is not None
コード例 #29
0
ファイル: test_forcebalance.py プロジェクト: qubekit/QUBEKit
def test_from_qdata():
    """
    Make sure we can create a valid TorsionDriveData from qdata.
    """
    td = TorsionDriveData.from_qdata(dihedral=(6, 10, 11, 8),
                                     qdata_file=get_data("biphenyl_qdata.txt"))
    # validate all angles
    td.validate_angles()
コード例 #30
0
ファイル: ligand_test.py プロジェクト: qubekit/QUBEKit
def test_find_rotatable_bonds_indices_of_bonds():
    mol = Ligand.from_file(get_data("bace0.pdb"))
    rotatables = mol.find_rotatable_bonds(["[*:1]-[CH3:2]", "[*:1]-[NH2:2]"])
    bonds = [(bond.atom1_index, bond.atom2_index) for bond in rotatables]
    expected_bonds = [(12, 13), (5, 13)]
    for bond in bonds:
        assert bond in expected_bonds or tuple(
            reversed(bond)) in expected_bonds