Exemple #1
0
    def _collect_results(self, td_state: Dict[str, Any],
                         molecule: "Ligand") -> "Ligand":
        """
        After the torsiondrive has been completed collect the results and pack them into the ligand.
        """
        # torsiondrive will only give us the lowest energy for each grid point
        # we have to then work out what the final geometry is from this
        optimised_energies = td_api.collect_lowest_energies(td_state=td_state)
        final_grid = td_state["grid_status"]
        # make a torsiondrive data store assuming 1D only
        torsion_data = TorsionDriveData(
            grid_spacing=self.grid_spacing,
            dihedral=td_state["dihedrals"][0],
            torsion_drive_range=td_state["dihedral_ranges"][0],
        )
        # now grab each grid point in sorted order
        for (
                angle,
                energy,
        ) in sorted(optimised_energies.items()):
            # grab all optimisation done at this angle
            optimisations = final_grid[str(angle[0])]
            # loop over each result and check if the energy matches the lowest
            # results -> (initial geometry, final geometry, final energy)
            for result in optimisations:
                if result[-1] == energy:
                    grid_data = TorsionData(
                        angle=angle[0],
                        geometry=np.array(result[1]) * constants.BOHR_TO_ANGS,
                        energy=energy,
                    )
                    torsion_data.add_grid_point(grid_data=grid_data)
                    break
        # validate the data
        torsion_data.validate_angles()
        # dump to file (qdata.txt and scan.xyz)
        export_torsiondrive_data(molecule=molecule, tdrive_data=torsion_data)
        # dump the qubekit torsion data to file
        torsion_data.to_file("scan_data.json")
        # save to mol
        molecule.add_qm_scan(scan_data=torsion_data)
        # dump the torsiondrive state to file
        self._dump_state(td_state=td_state)
        # now remove all temp folders
        for f in os.listdir("."):
            if os.path.isdir(f):
                shutil.rmtree(f, ignore_errors=True)

        return molecule
    def prep_for_fitting(self, molecule: Ligand) -> List[str]:
        """
        For the given ligand prep the input files ready for torsion profile fitting.

        Args:
            molecule: The molecule object that we need to prep for fitting, this should have qm reference data stored in molecule.qm_scans.

        Note:
            We assume we are already in the targets folder.

        Returns:
            A list of target folder names made by this target.

        Raises:
            MissingReferenceData: If the molecule does not have any torsion drive reference data saved in molecule.qm_scans.
        """
        # make sure we have data
        if not molecule.qm_scans:
            raise MissingReferenceData(
                f"Can not prepare a forcebalance fitting target for {molecule.name} as the reference data is missing!"
            )

        # write out the qdata and other input files for each scan
        target_folders = []
        # keep track of where we start
        base_folder = os.getcwd()

        # loop over each scanned bond and make a target folder
        for scan in molecule.qm_scans:
            task_name = (
                f"{self.target_name}_{scan.central_bond[0]}_{scan.central_bond[1]}"
            )
            target_folders.append(task_name)
            make_and_change_into(name=task_name)
            # make the pdb topology file
            if molecule.has_ub_terms():
                molecule._to_ub_pdb(file_name="molecule")
            else:
                molecule.to_file(file_name="molecule.pdb")
            # write the qdata file
            export_torsiondrive_data(molecule=molecule, tdrive_data=scan)
            # make the metadata
            self.make_metadata(torsiondrive_data=scan)
            # now move back to the base
            os.chdir(base_folder)

        return target_folders
Exemple #3
0
def test_qdata_round_trip(tmpdir):
    """
    Try and round trip a qdata txt file to a TorsionDriveData object and back.
    """
    with tmpdir.as_cwd():
        mol = Ligand.from_file(file_name=get_data("biphenyl.sdf"))
        td_ref = TorsionDriveData.from_qdata(
            dihedral=(6, 10, 11, 8), qdata_file=get_data("biphenyl_qdata.txt"))
        # now write to file
        export_torsiondrive_data(molecule=mol, tdrive_data=td_ref)
        # now make a second object
        td_new = TorsionDriveData.from_qdata(dihedral=(6, 10, 11, 8),
                                             qdata_file="qdata.txt")
        assert td_ref.dihedral == td_new.dihedral
        for angle, ref_result in td_ref.reference_data.items():
            new_result = td_new.reference_data[angle]
            assert ref_result.angle == new_result.angle
            assert ref_result.energy == pytest.approx(new_result.energy)
            assert np.allclose(ref_result.geometry.tolist(),
                               new_result.geometry.tolist())