def test_different_forcefield_constraints(self, toolkit):
        """Test that the --constrained argument produces different results"""
        from openff.cli.tests.utils import get_data_file_path

        registry = make_registry(toolkit)
        mol = get_data_file_path("molecules/azidoazide.smi")
        constrained = generate_conformers(
            molecule=mol,
            forcefield="openff-1.0.0",
            prefix="parsley100",
            registry=registry,
            constrained=True,
        )
        unconstrained = generate_conformers(
            molecule=mol,
            forcefield="openff-1.0.0",
            prefix="parsley100",
            registry=registry,
            constrained=False,
        )

        assert not np.allclose(
            constrained[0].conformers[0],
            unconstrained[0].conformers[0],
        )
    def test_load_one_mol_mol2_with_charge(self, toolkit):
        """
        Test loading one molecule from a .mol2 file WITHOUT charges

        .. note :: This file was generated via the one-liner below and has nan
            charges, which may or may not be valid.

        ```
        Molecule.from_smiles('CCO').to_file(
            'ethanol_no_charges.mol2',
            file_format='mol2',
        )
        ```
        """
        registry = make_registry(toolkit)
        ethanol_partial_charges = get_data_file_path(
            "molecules/ethanol_no_charges.mol2")
        charges_in = Molecule.from_file(
            ethanol_partial_charges).partial_charges

        mols_out = generate_conformers(
            molecule=ethanol_partial_charges,
            forcefield="openff-1.0.0.offxml",
            registry=registry,
        )

        assert len(mols_out) == 1

        assert not charges_in
        assert not mols_out[0].partial_charges
 def test_load_multi_mol_sdf(self, toolkit):
     """Test the case of an SDF file with multiple molecules"""
     registry = make_registry(toolkit)
     butane_multi = get_data_file_path("molecules/butane_multi.sdf")
     generate_conformers(
         molecule=butane_multi,
         forcefield="openff-1.0.0.offxml",
         registry=registry,
     )
    def test_preserve_stereo_smi(self, toolkit):
        """Test loading a molecule with defined stereo from SMILES and preserving that stereochemistry"""
        registry = make_registry(toolkit)
        mol = get_data_file_path("molecules/dichloroethene_stereo.smi")
        mols_out = generate_conformers(
            molecule=mol,
            forcefield="openff-1.0.0.offxml",
            registry=registry,
        )

        assert Molecule(mol).is_isomorphic_with(mols_out[0])
    def test_load_multi_mol_smi(self, toolkit):
        """Test loading multiple molecules from SMILES in a .smi file"""
        registry = make_registry(toolkit)
        dyes = get_data_file_path("molecules/multi_mols.smi")
        mols_out = generate_conformers(
            molecule=dyes,
            forcefield="openff-1.0.0.offxml",
            registry=registry,
        )

        assert len(mols_out) > 3
    def test_load_one_mol_smi(self, toolkit):
        """Test loading one molecule from SMILES in a .smi file"""
        registry = make_registry(toolkit)
        hexane = get_data_file_path("molecules/hexane.smi")
        mols_out = generate_conformers(
            molecule=hexane,
            forcefield="openff-1.0.0.offxml",
            registry=registry,
        )

        assert len(mols_out) > 1
 def test_available_forcefields(self, toolkit, ff_name):
     """Test that all forcefields available through get_available_forcefields
     can at least do a basic conformer generaiton"""
     # TODO: Possibly ensure this produces non-garbage output,
     #  instead of only "doesn't raise an error we know of"
     registry = make_registry(toolkit)
     mol = get_data_file_path("molecules/ethanol.sdf")
     generate_conformers(
         molecule=mol,
         forcefield=ff_name,
         registry=registry,
     )
    def test_load_ambiguous_stereo_smi(self, toolkit):
        """Test loading a molecule with ambiguous stereo from SMILES and enumerating stereoisomers"""
        # TODO: Should the CLI accept both paths and SMILES as strings, or only files?
        registry = make_registry(toolkit)
        mol = get_data_file_path(
            "molecules/dichloroethene_ambiguous_stereo.smi")
        mols_out = generate_conformers(
            molecule=mol,
            forcefield="openff-1.0.0.offxml",
            registry=registry,
        )

        assert len(mols_out) == 4
    def test_load_one_mol_sdf_without_charge(self, toolkit):
        """Test loading one molecule from a .sdf file WITHOUT charges"""
        registry = make_registry(toolkit)
        ethanol = get_data_file_path("molecules/ethanol.sdf")
        assert Molecule.from_file(ethanol).partial_charges is None

        mols_out = generate_conformers(
            molecule=ethanol,
            forcefield="openff-1.0.0.offxml",
            registry=registry,
        )

        assert len(mols_out) > 1
        assert mols_out[0].partial_charges is not None
    def test_load_one_mol_sdf_with_charge(self, toolkit):
        """Test loading one molecule from a .sdf file WITH charges"""
        registry = make_registry(toolkit)
        ethanol_partial_charges = get_data_file_path(
            "molecules/ethanol_partial_charges.sdf")
        charges_in = Molecule.from_file(
            ethanol_partial_charges).partial_charges
        assert charges_in is not None

        mols_out = generate_conformers(
            molecule=ethanol_partial_charges,
            forcefield="openff-1.0.0.offxml",
            registry=registry,
        )

        assert len(mols_out) > 1
        assert np.allclose(mols_out[0].partial_charges, charges_in)
    def test_get_conformer_energies(self, toolkit):
        registry = make_registry(toolkit)
        mols = get_conformer_energies(
            molecule=get_data_file_path(
                "molecules/ruxolitinib_conformers.sdf"),
            registry=registry,
            forcefield="openff-1.0.0",
            constrained=False,
        )

        for mol in mols:
            for conformer_idx in range(mol.n_conformers):
                original = mol.properties[
                    "original conformer energies (kcal/mol)"]
                minimized = mol.properties[
                    "minimized conformer energies (kcal/mol)"]
                assert minimized < original
    def test_load_one_mol_mol2_without_charge(self, toolkit):
        """Test loading one molecule from a .mol2 file WITH charges"""
        if toolkit != "openeye":
            pytest.skip("Test requires OpenEye toolkit")
        registry = make_registry(toolkit)
        ethanol_partial_charges = get_data_file_path(
            "molecules/ethanol_partial_charges.mol2")
        charges_in = Molecule.from_file(
            ethanol_partial_charges).partial_charges

        mols_out = generate_conformers(
            molecule=ethanol_partial_charges,
            forcefield="openff-1.0.0.offxml",
            registry=registry,
        )

        assert len(mols_out) > 1
        assert np.allclose(mols_out[0].partial_charges, charges_in)
def test_parsing_error():
    """Ensure that failed molecule parsing is caught"""
    from openff.cli.utils.exceptions import MoleculeParsingError

    # Ensure the exception can be raised with no keyword arguments
    exec_msg = "Failed to parse a molecule file."
    with pytest.raises(MoleculeParsingError, match=exec_msg):
        raise MoleculeParsingError

    # Try to parse a MOL2 file with RDKit
    registry = make_registry("rdkit")
    mol = get_data_file_path("molecules/ethanol_no_charges.mol2")
    exec_msg = (
        r"Failed to parse a molecule file. Attempted to parse file "
        ".*ethanol_no_charges.mol2 using toolkit registry containing+.*RDKit")
    with pytest.raises(MoleculeParsingError, match=exec_msg):
        generate_conformers(
            molecule=mol,
            forcefield="openff-1.0.0.offxml",
            registry=registry,
        )
    def test_different_forcefields(self, toolkit):
        """Test that different --forcefield arguments produce different results"""
        from openff.cli.tests.utils import get_data_file_path

        registry = make_registry(toolkit)
        mol = get_data_file_path("molecules/azidoazide.smi")
        parsley_1_0_0 = generate_conformers(
            molecule=mol,
            forcefield="openff-1.0.0",
            prefix="parsley100",
            registry=registry,
        )
        parsley_1_2_0 = generate_conformers(
            molecule=mol,
            forcefield="openff-1.2.0",
            prefix="parsley120",
            registry=registry,
        )

        assert not np.allclose(
            parsley_1_0_0[0].conformers[0],
            parsley_1_2_0[0].conformers[0],
        )
    def test_p_prefix(self, toolkit):
        """Ensure the output file has the -p prefix"""
        registry = make_registry(toolkit)

        ethanol = get_data_file_path("molecules/ethanol.sdf")

        mols_out = generate_conformers(
            molecule=ethanol,
            forcefield="openff-1.0.0.offxml",
            registry=registry,
            prefix="test_ethanol",
        )

        with tempfile.TemporaryDirectory() as tmp_dir:
            with temporary_cd(tmp_dir):
                write_mols(
                    mols=mols_out,
                    toolkit_registry=registry,
                    molecule=ethanol,
                    prefix="test_ethanol",
                )

                assert pathlib.Path("test_ethanol_0.sdf").is_file()
def test_different_toolkits():
    """Test that different --toolkit argumnents produce different results"""
    from openff.cli.tests.utils import get_data_file_path

    rdkit = make_registry("rdkit")
    openeye = make_registry("openeye")
    mol = get_data_file_path("molecules/azidoazide.smi")
    rdkit_results = generate_conformers(
        molecule=mol,
        forcefield="openff-1.0.0",
        prefix="rdkit",
        registry=rdkit,
    )
    openeye_results = generate_conformers(
        molecule=mol,
        forcefield="openff-1.0.0",
        prefix="openeye",
        registry=openeye,
    )

    assert not np.allclose(
        rdkit_results[0].conformers[0],
        openeye_results[0].conformers[0],
    )