Exemple #1
0
def recompute_relax_torsion_profile(scanxyz, pdb_fnm, dihedralstxt,
                                    sysxml_fnm):
    grid_geo_data, _ = read_scan_xyz(scanxyz)
    dihedral_list = read_dihedralstxt(dihedralstxt)
    sysxml_path = os.path.abspath(sysxml_fnm)
    m = Molecule(pdb_fnm)
    # create a new tmp dir for running calculations
    if os.path.exists(tmpdir):
        shutil.rmtree(tmpdir)
    os.mkdir(tmpdir)
    os.chdir(tmpdir)
    # loop over each geometry in each grid
    for grid_id, geo in grid_geo_data.items():
        folder = 'gid_' + '_'.join(f'{d:+03d}' for d in grid_id)
        print(f'Running constrained optimization in {folder}')
        os.mkdir(folder)
        os.chdir(folder)
        # copy files
        m.xyzs = [geo]
        m.write('frame.pdb')
        shutil.copy(sysxml_path, 'openmm_system.xml')
        write_constraints_txt(dihedral_list, grid_id)
        # run geometric
        command = "geometric-optimize openmm_system.xml constraints.txt --openmm --pdb frame.pdb --qccnv --reset --epsilon 0.0 --enforce 0.1 --qdata"
        subprocess.run(command, shell=True, check=True)
        os.chdir('..')
    os.chdir('..')
Exemple #2
0
 def finish(self):
     """ Write qdata.txt and scan.xyz file based on converged scan results """
     m = Molecule()
     m.elem = list(self.engine.M.elem)
     m.qm_energies, m.xyzs, m.comms = [], [], []
     for gid in self.grid_ids:
         m.qm_energies.append(self.grid_energies[gid])
         m.xyzs.append(self.grid_final_geometries[gid])
         m.comms.append("Dihedral %s Energy %.9f" % (str(gid), self.grid_energies[gid]))
     m.write('qdata.txt')
     print("Final scan energies are written to qdata.txt")
     m.write('scan.xyz')
     print("Final scan energies are written to scan.xyz")
 def finish(self):
     """ Write qdata.txt and scan.xyz file based on converged scan results """
     m = Molecule()
     m.elem = list(self.engine.M.elem)
     m.qm_energies, m.xyzs, m.comms = [], [], []
     # only print grid with energies
     for gid in sorted(self.grid_energies.keys()):
         m.qm_energies.append(self.grid_energies[gid])
         m.xyzs.append(self.grid_final_geometries[gid])
         m.comms.append("Dihedral %s Energy %.9f" %
                        (str(gid), self.grid_energies[gid]))
     m.write('qdata.txt')
     print("Final scan energies are written to qdata.txt")
     m.write('scan.xyz')
     print("Final scan energies are written to scan.xyz")
Exemple #4
0
def export_torsiondrive_data(molecule: "Ligand",
                             tdrive_data: "TorsionDriveData") -> None:
    """
    Export the stored torsiondrive data object to a scan.xyz file and qdata.txt file required for ForceBalance.

    Method taken from <https://github.com/lpwgroup/torsiondrive/blob/ac33066edf447e25e4beaf21c098e52ca0fc6649/torsiondrive/dihedral_scanner.py#L655>

    Args:
        molecule: The molecule object which contains the topology.
        tdrive_data: The results of a torsiondrive on the input molecule.
    """
    from geometric.molecule import Molecule as GEOMol

    mol = GEOMol()
    mol.elem = [atom.atomic_symbol for atom in molecule.atoms]
    mol.qm_energies, mol.xyzs, mol.comms = [], [], []
    for angle, grid_data in sorted(tdrive_data.reference_data.items()):
        mol.qm_energies.append(grid_data.energy)
        mol.xyzs.append(grid_data.geometry)
        mol.comms.append(f"Dihedral ({angle},) Energy {grid_data.energy}")
    mol.write("qdata.txt")
    mol.write("scan.xyz")
Exemple #5
0
class EngineOpenMM(QMEngine):
    def load_input(self, input_file):
        """Input file is the name of the pdb file with the coords in we also require that the xml has the same name"""

        self.m_pdb = Molecule(input_file)[0]
        self.M = copy.deepcopy(self.m_pdb)

        xml_name = os.path.splitext(input_file)[0] + '.xml'
        # Check the xml file is present
        assert os.path.exists(
            xml_name
        ) is True, "OpenMM requires a pdb and xml file, ensure you have both in the current folder with the same prefix"
        with open(xml_name) as f:
            self.xml_content = f.read()

    def write_input(self):
        """Write a pdb file with the latest geometry and the input xml file"""

        self.m_pdb.xyzs[0] = self.M.xyzs[0]
        self.m_pdb.write('input.pdb')
        with open('input.xml', 'w') as out:
            out.write(self.xml_content)

    def optimize_geomeTRIC(self):
        """ run the constrained optimization using geomeTRIC package, in 3 steps:
        1. Write a constraints.txt file.
        2. Write a gradient job input file.
        3. Run the job
        """
        # sep 1
        self.write_constraints_txt()
        # step 2
        self.write_input()
        # set3
        self.run(
            'geometric-optimize --prefix tdrive --qccnv --reset --epsilon 0.0 --enforce 0.1 --qdata --pdb '
            'input.pdb --openmm input.xml constraints.txt',
            input_files=['input.xml', 'input.pdb', 'constraints.txt'],
            output_files=['tdrive.log', 'tdrive.xyz', 'qdata.txt'])
 def finish(self):
     """ Write qdata.txt and scan.xyz file based on converged scan results """
     m = Molecule()
     m.elem = list(self.engine.M.elem)
     m.qm_energies, m.xyzs, m.comms = [], [], []
     # optionally writing qm gradients into qdata.txt if avilable
     writing_gradients = False
     if len(self.grid_final_gradients) == len(self.grid_final_geometries):
         m.qm_grads = []
         writing_gradients = True
     # only print grid with energies
     for gid in sorted(self.grid_energies.keys()):
         m.qm_energies.append(self.grid_energies[gid])
         m.xyzs.append(self.grid_final_geometries[gid])
         if writing_gradients:
             m.qm_grads.append(self.grid_final_gradients[gid])
         m.comms.append("Dihedral %s Energy %.9f" %
                        (str(gid), self.grid_energies[gid]))
     m.write('qdata.txt')
     print(
         f"Final scan energies{' and gradients' if writing_gradients else ''} are written to qdata.txt"
     )
     m.write('scan.xyz')
     print("Final scan energies are written to scan.xyz")
Exemple #7
0
class EngineTerachem(QMEngine):
    def load_input(self, input_file):
        """
        Load TeraChem input
        Example input file:

        coordinates start.xyz
        run gradient
        basis 6-31g*
        method rb3lyp
        charge 0
        spinmult 1
        dispersion yes
        scf diis+a
        maxit 50
        """
        self.tera_temp = []
        geo_file = None
        with open(input_file) as terain:
            for line in terain:
                # we don't need to change the temp
                self.tera_temp.append(line)
                linest = line.strip()
                if not linest: continue
                key, value = linest.lower().split(None, 1)
                if key == 'coordinates':
                    geo_file = value
                elif key == 'run':
                    if value == 'gradient':
                        self.temp_type = 'gradient'
                    elif value == 'minimize':
                        self.temp_type = 'optimize'
        # place holder for writing native constraints
        self.tera_temp.append('$!constraints@here')
        # check input
        assert geo_file, 'coordinates key not found in input file %s' % input_file
        if self.native_opt:
            assert self.temp_type == 'optimize', "input_file should be a opt job to use native opt"
        else:
            assert self.temp_type == 'gradient', "input_file should be a gradient job to use geomeTRIC"
        # load molecule from separate file, one frame only
        self.M = Molecule(geo_file)[0]
        # store the name of geo_file
        self.tera_geo_file = geo_file

    def write_input(self):
        """ Write TeraChem input files, i.e. run.in and start.xyz """
        assert hasattr(
            self,
            'tera_temp'), "self.tera_temp not set, call load_input() first"
        assert hasattr(
            self,
            'tera_geo_file'), "self.tera_temp not set, call load_input() first"
        with open('run.in', 'w') as terain:
            for line in self.tera_temp:
                if line == "$!constraints@here":
                    if hasattr(self, 'constraintsStr'):
                        # self.constraintsStr will be set by self.optimize_native()
                        terain.write(self.constraintsStr)
                else:
                    terain.write(line)
        self.M.write(self.tera_geo_file)

    def optimize_native(self):
        """
        Run the constrained optimization.
        1. write a optimization job input file.
        2. run the job
        """
        assert self.temp_type == 'optimize', "To use native optimization, the input file be an opt job"
        if self.extra_constraints is None:
            self.constraintsStr = '\n$constraint_set\n'
            for d1, d2, d3, d4, v in self.dihedral_idx_values:
                # TeraChem use atom index starting from 1
                self.constraintsStr += f"dihedral {float(v)} {d1 + 1}_{d2 + 1}_{d3 + 1}_{d4 + 1}\n"
            self.constraintsStr += '$end\n'
        else:
            self.constraintsStr = build_terachem_constraint_string(
                self.extra_constraints, self.dihedral_idx_values)
        # write input file
        self.write_input()
        # run the job
        self.run('terachem run.in > run.out',
                 input_files=['run.in', self.tera_geo_file],
                 output_files=['run.out', 'scr'])

    def optimize_geomeTRIC(self):
        """ run the constrained optimization using geomeTRIC package, in 3 steps:
        1. Write a constraints.txt file.
        2. Write a gradient job input file.
        3. Run the job
        """
        assert self.temp_type == 'gradient', "To use geomeTRIC package, the input file should have gradient() in it"
        # step 1
        self.write_constraints_txt()
        # step 2
        self.write_input()
        # step 3
        cmd = 'geometric-optimize --prefix tdrive --qccnv --reset --epsilon 0.0 --enforce 0.1 --qdata run.in constraints.txt'
        self.run(cmd,
                 input_files=['run.in', self.tera_geo_file, 'constraints.txt'],
                 output_files=['tdrive.log', 'tdrive.xyz', 'qdata.txt'])

    def load_native_output(self):
        """ Load the optimized geometry and energy into a new molecule object and return """
        m = Molecule('scr/optim.xyz')[-1]
        # read the energy from optim.xyz comment line
        m.qm_energies = [float(m.comms[0].split(maxsplit=1)[0])]
        return m
Exemple #8
0
class EngineTerachem(QMEngine):
    def load_input(self, input_file):
        """
        Load TeraChem input
        Example input file:

        coordinates start.xyz
        run gradient
        basis 6-31g*
        method rb3lyp
        charge 0
        spinmult 1
        dispersion yes
        scf diis+a
        maxit 50
        """
        self.tera_temp = []
        geo_file = None
        with open(input_file) as terain:
            for line in terain:
                # we don't need to change the temp
                self.tera_temp.append(line)
                key, value = line.strip().lower().split(None, 1)
                if key == 'coordinates':
                    geo_file = value
                elif key == 'run':
                    if value == 'gradient':
                        self.temp_type = 'gradient'
                    elif value == 'minimize':
                        self.temp_type = 'optimize'
        # place holder for writing native constraints
        self.tera_temp.append('$!constraints@here')
        # check input
        assert geo_file, 'coordinates key not found in input file %s' % input_file
        if self.native_opt:
            assert self.temp_type == 'optimize', "input_file should be a opt job to use native opt"
        else:
            assert self.temp_type == 'gradient', "input_file should be a gradient job to use geomeTRIC"
        # load molecule from separate file, one frame only
        self.M = Molecule(geo_file)[0]
        # store the name of geo_file
        self.tera_geo_file = geo_file

    def write_input(self):
        """ Write TeraChem input files, i.e. run.in and start.xyz """
        assert hasattr(self, 'tera_temp'), "self.tera_temp not set, call load_input() first"
        assert hasattr(self, 'tera_geo_file'), "self.tera_temp not set, call load_input() first"
        with open('run.in', 'w') as terain:
            for line in self.tera_temp:
                if line == "$!constraints@here":
                    if hasattr(self, 'constraintsStr'):
                        # self.optblockStr will be set by self.optimize_native()
                        terain.write(self.constraintsStr)
                else:
                    terain.write(line)
        self.M.write(self.tera_geo_file)

    def optimize_native(self):
        """
        Run the constrained optimization, following QChem 5.0 manual.
        1. write a optimization job input file.
        2. run the job
        """
        assert self.temp_type == 'optimize', "To use native optimization, the input file be an opt job"
        # add the $opt block
        self.constraintsStr = '\n$constraint_set\n'
        for d1, d2, d3, d4, v in self.dihedral_idx_values:
            # Optking use atom index starting from 1
            self.constraintsStr += 'dihedral %f %d_%d_%d_%d\n' % (v, d1+1, d2+1, d3+1, d4+1)
        self.constraintsStr += '$end\n'
        # write input file
        self.write_input()
        # run the job
        self.run('terachem run.in > run.out', input_files=['run.in', self.tera_geo_file], output_files=['run.out', 'scr'])

    def optimize_geomeTRIC(self):
        """ run the constrained optimization using geomeTRIC package, in 3 steps:
        1. Write a constraints.txt file.
        2. Write a gradient job input file.
        3. Run the job
        """
        assert self.temp_type == 'gradient', "To use geomeTRIC package, the input file should have gradient() in it"
        # step 1
        self.write_constraints_txt()
        # step 2
        self.write_input()
        # step 3
        self.run('geometric-optimize --qccnv --reset --epsilon 0.0 run.in constraints.txt > optimize.log', input_files=['run.in', self.tera_geo_file, 'constraints.txt'], output_files=['optimize.log', 'opt.xyz', 'energy.txt'])

    def load_native_output(self):
        """ Load the optimized geometry and energy into a new molecule object and return """
        m = Molecule('scr/optim.xyz')[-1]
        # read the energy from optim.xyz comment line
        m.qm_energies = [float(m.comms[0].split(None, 1)[0])]
        return m