예제 #1
0
 def pull(self):
     self.nsteps += 1.
     yaml_builder = ExperimentBuilder(self.contents.format('yes',self.init_steps+self.nsteps*self.pull_steps))
     yaml_builder.run_experiments()
     exp_analyzer = ExperimentAnalyzer(str(self.name)+'/experiments')
     analysis_data = exp_analyzer.auto_analyze()
     # the following is the free_energy_diff of the WHOLE simulation, need the average of the last pull_steps
     self.x_n = analysis_data['free_energy']['free_energy_diff']
     return
예제 #2
0
 def __init__(self,name,fe,error,index,simulation,color=np.random.rand(3),init_steps=2000,pull_steps=1000):
     super().__init__(name,fe,error,index,color)
     self.contents = simulation.format(self.name,'resume_simulation: {}',self.index,'{}')
     self.init_steps = init_steps
     self.pull_steps = pull_steps
     yaml_builder = ExperimentBuilder(self.contents.format('no',self.init_steps))
     yaml_builder.run_experiments()
     exp_analyzer = ExperimentAnalyzer(str(self.name)+'/experiments')
     analysis_data = exp_analyzer.auto_analyze()
     self.nu_0 = analysis_data['free_energy']['free_energy_diff']
예제 #3
0
    def _run_yank(directory, available_resources, setup_only):
        """Runs YANK within the specified directory which contains a `yank.yaml`
        input file.

        Parameters
        ----------
        directory: str
            The directory within which to run yank.
        available_resources: ComputeResources
            The compute resources available to yank.
        setup_only: bool
            If true, YANK will only create and validate the setup files,
            but not actually run any simulations. This argument is mainly
            only to be used for testing purposes.

        Returns
        -------
        simtk.pint.Quantity
            The free energy returned by yank.
        simtk.pint.Quantity
            The uncertainty in the free energy returned by yank.
        """

        from yank.experiment import ExperimentBuilder
        from yank.analyze import ExperimentAnalyzer

        from simtk import unit as simtk_unit

        with temporarily_change_directory(directory):

            # Set the default properties on the desired platform
            # before calling into yank.
            setup_platform_with_resources(available_resources)

            exp_builder = ExperimentBuilder("yank.yaml")

            if setup_only is True:
                return (
                    0.0 * simtk_unit.kilojoule_per_mole,
                    0.0 * simtk_unit.kilojoule_per_mole,
                )

            exp_builder.run_experiments()

            analyzer = ExperimentAnalyzer("experiments")
            output = analyzer.auto_analyze()

            free_energy = output["free_energy"]["free_energy_diff_unit"]
            free_energy_uncertainty = output["free_energy"][
                "free_energy_diff_error_unit"]

        return free_energy, free_energy_uncertainty
예제 #4
0
파일: iapetus.py 프로젝트: LaYeqa/iapetus
    def __init__(self,
                 platform_name=None,
                 precision=None,
                 max_n_contexts=None):
        """
        Parameters
        ----------
        platform_name : str, optional, default=None
            Name of platform, or 'fastest' if fastest platform should be automatically selected
        precision : str, optional, default='auto'
            Precision to use, or None to automatically select ('mixed' is used if supported)
        max_n_contexts : int, optional, default=None
            Maximum number of contexts to use
        """
        # Configure ContextCache, platform and precision
        from yank.experiment import ExperimentBuilder
        self.platform = ExperimentBuilder._configure_platform(
            platform_name, precision)

        try:
            openmmtools.cache.global_context_cache.platform = self.platform
        except RuntimeError:
            # The cache has been already used. Empty it before switching platform.
            openmmtools.cache.global_context_cache.empty()
            openmmtools.cache.global_context_cache.platform = self.platform

        if max_n_contexts is not None:
            openmmtools.cache.global_context_cache.capacity = self.max_n_contexts
예제 #5
0
def test_yaml_syntax(path):
    """
    Test syntax only. If successful, `ExperimentBuilder`
    will be able to initialize safely.
    """
    path = EXAMPLES / path
    with omt.utils.temporary_cd(str(path.parent)):
        builder = ExperimentBuilder(script=str(path))
예제 #6
0
    def run(self,
            platform_name=None,
            precision='auto',
            max_n_contexts=None,
            resume=False):
        """
        Run the sampler for a specified number of iterations

        Parameters
        ----------
        platform_name : str, optional, default=None
            Name of platform, or 'fastest' if fastest platform should be automatically selected
        precision : str, optional, default='auto'
            Precision to use, or None to automatically select ('mixed' is used if supported)
        max_n_contexts : int, optional, default=None
            Maximum number of contexts to use
        resume : bool, default=False
                    If True, resume the simulation

        """
        # Configure ContextCache, platform and precision
        from yank.experiment import ExperimentBuilder
        platform = ExperimentBuilder._configure_platform(
            platform_name, precision)

        try:
            openmmtools.cache.global_context_cache.platform = platform
        except RuntimeError:
            # The cache has been already used. Empty it before switching platform.
            openmmtools.cache.global_context_cache.empty()
            openmmtools.cache.global_context_cache.platform = platform

        if max_n_contexts is not None:
            openmmtools.cache.global_context_cache.capacity = max_n_contexts

        if resume:
            # Resume the simulation
            print('Storage {} exists; resuming...'.format(
                self.output_filename))
            from yank.multistate import SAMSSampler, MultiStateReporter
            sampler = SAMSSampler.from_storage(self.output_filename)
            # Run the remainder of the simulation
            if sampler._iteration < self.n_iterations:
                # Resume
                sampler.run()
            else:
                # Extend
                sampler.extend(n_iterations=self.n_iterations)

        else:
            # Set up the simulation if it has not yet been set up
            if not self._setup_complete:
                self._setup()

                # Run the simulation
                self.simulation.run()
예제 #7
0
def test_yaml_syntax_cuda(path):
    """
    Same as test_yaml_syntax, but removing `platform: CUDA`
    to avoid errors unrelated to syntax if the test machine
    does not have CUDA enabled
    """
    path = EXAMPLES / path
    with omt.utils.temporary_cd(str(path.parent)):
        with open(str(path)) as f:
            data = yaml.load(f, Loader=YankLoader)
        del data['options']['platform']
        builder = ExperimentBuilder(script=data)
예제 #8
0
def run_automatic_pipeline(yaml_file_path, complex_name, solvent_name):
    """Run YANK's automatic pipeline."""
    from yank.experiment import ExperimentBuilder
    exp_builder = ExperimentBuilder(yaml_file_path)

    # Modify the output directory of the setup to be consistent
    # with the hardcoded paths in Fluorify and FSim. The searched
    # path is 'input/complex_name/complex_name.pdb' so we also
    # need to modify the name of the system.
    exp_builder.output_dir = '.'
    exp_builder.setup_dir = 'input'

    # Run the automatic pipeline.
    exp_builder.setup_experiments()
    assert len(exp_builder._db.systems
               ) == 1, 'Setting up multiple systems is not currently supported'
    system_name = next(iter(list(exp_builder._db.systems.keys())))

    # Copy YANK setup files to match the Fluorify folder structure.
    for phase_name, user_phase_name in zip(['complex', 'solvent'],
                                           [complex_name, solvent_name]):
        # Create Fluorify directory structure.
        fluorify_phase_dir = os.path.join('input', user_phase_name)
        os.makedirs(fluorify_phase_dir, exist_ok=True)
        for extension in ['.prmtop', '.pdb']:
            yank_file_path = os.path.join(exp_builder.setup_dir, 'systems',
                                          system_name, phase_name + extension)
            fluorify_file_path = os.path.join(fluorify_phase_dir,
                                              user_phase_name + extension)
            shutil.copyfile(yank_file_path, fluorify_file_path)
예제 #9
0
def run_yank(job_id, n_jobs):
    # Direct path to where the input PDBs are
    pdb_dir = "./t3_dry_oct_pdbs"
    # Direct path to where the input XML system files are (will need to change according to what trial directory you're working in)
    openmm_system_dir = "./t3_dry_oct_XMLs"
    
    # Path to YANK template script (YAML file)
    yank_script_template_filepath = 'dry_yank.yaml' #don't need to change this

    # Read in YANK template script.
    with open(yank_script_template_filepath, 'r') as f:
        script_template = f.read()

    # Load cached status calculations.
    molecules_done = read_status()

    # Find all the molecules to run
    # Make a list of JUST the solute/octanol mixures (excludes the solute in water mixtures that are in the same pdb directory as the solute/octanol mixures)
    molecules_files_pattern = os.path.join(pdb_dir, '*_octanol_0.0_1.0_SMIRNOFF_tip3p_equil.pdb')
    molecule_ids = [os.path.basename(molecule_file)[:-4] for molecule_file in glob.glob(molecules_files_pattern)] # makes a list of just the system IDs (ie SM13_octanol_0.0_1.0_SMIRNOFF_tip3p_equil instead of SM13_octanol_0.0_1.0_SMIRNOFF_tip3p_equil.pdb)

    # Sort molecules so that parallel nodes won't make the same calculation.
    molecule_ids = sorted(molecule_ids)

    # Loop through the list of the phase 1 files, which are the solute/octanol mixtures
    # The phase 1 file name will be used to grab the corresponding phase 2 file
    # Create input files.
    for i, molecule_id in enumerate(molecule_ids):
        # Check if the job is assigned to this script and/or if we
        # have already completed this.
        if (i % n_jobs != job_id - 1 or molecule_id in molecules_done):
            print_and_flush('Node {}: Skipping {}'.format(job_id, molecule_id))
            continue

        # specify phase one, which will be the solute in just octanol
        phase1_molecule_id = molecule_id
        # specify phase two, which will be the solute in just water
        phase2_molecule_id = phase1_molecule_id.replace("_octanol_0.0_1.0_SMIRNOFF_tip3p_equil", "_water_0.0_1.0_SMIRNOFF_tip3p_equil")

        # Specify the PDB and XML filepaths
        phase1_PDB_filepath = os.path.join(pdb_dir, phase1_molecule_id + '.pdb') #solute in octanol
        phase2_PDB_filepath = os.path.join(pdb_dir, phase2_molecule_id + '.pdb') #solute in water

        phase1_xml_filepath = os.path.join(openmm_system_dir, phase1_molecule_id[:-6] + '.xml') #solute in octanol/water
        phase2_xml_filepath = os.path.join(openmm_system_dir, phase2_molecule_id[:-6] + '.xml') #solute in water

        # Create yank script.
        phase1_path = str([phase1_xml_filepath, phase1_PDB_filepath])
        phase2_path = str([phase2_xml_filepath, phase2_PDB_filepath])
        
        # Load the PDB and XML files into yank
        script = script_template.format(experiment_dir=molecule_id,
                                        phase1_path=phase1_path,
                                        phase2_path=phase2_path)

        # Run YANK.
        print_and_flush('Node {}: Running {}'.format(job_id, molecule_id))
        yaml_builder = ExperimentBuilder(script)
        yaml_builder.run_experiments()

        # Update completed molecules.
        update_status(molecule_id)
예제 #10
0
파일: repex.py 프로젝트: ajsilveira/repex
def main():
    parser = argparse.ArgumentParser(
        description=
        'Compute a potential of mean force (PMF) for porin permeation.')
    parser.add_argument('--index',
                        dest='index',
                        action='store',
                        type=int,
                        help='Index of ')
    parser.add_argument('--output',
                        dest='output_filename',
                        action='store',
                        default='output.nc',
                        help='output netcdf filename (default: output.nc)')

    args = parser.parse_args()
    index = args.index
    output_filename = args.output_filename

    logger = logging.getLogger(__name__)
    logging.root.setLevel(logging.DEBUG)
    logging.basicConfig(level=logging.DEBUG)
    yank.utils.config_root_logger(verbose=True, log_file_path=None)

    # Configure ContextCache, platform and precision
    from yank.experiment import ExperimentBuilder
    platform = ExperimentBuilder._configure_platform('CUDA', 'mixed')

    try:
        openmmtools.cache.global_context_cache.platform = platform
    except RuntimeError:
        # The cache has been already used. Empty it before switching platform.
        openmmtools.cache.global_context_cache.empty()
        openmmtools.cache.global_context_cache.platform = platform

    # Topology
    pdbx = app.PDBxFile('mem_prot_md_system.pdbx')

    # This system contains the CVforce with parameters different than zero

    with open('openmm_system.xml', 'r') as infile:
        openmm_system = XmlSerializer.deserialize(infile.read())

    ####### Indexes of configurations in trajectory ############################
    configs = [
        39, 141, 276, 406, 562, 668, 833, 1109, 1272, 1417, 1456, 1471, 1537,
        1645, 1777, 1882
    ]

    ####### Indexes of states for series of replica exchange simulations #######
    limits = [(0, 9), (10, 19), (20, 29), (30, 39), (40, 49), (50, 59),
              (60, 69), (70, 79), (80, 89), (90, 99), (100, 109), (110, 119),
              (120, 129), (130, 139), (140, 149), (150, 159)]

    ####### Reading positions from mdtraj trajectory ###########################
    topology = md.Topology.from_openmm(pdbx.topology)
    t = md.load('../../steered_md/comp7/forward/seed_0/steered_forward.nc',
                top=topology)
    positions = t.openmm_positions(configs[index])

    thermodynamic_state_deserialized = states.ThermodynamicState(
        system=openmm_system,
        temperature=310 * unit.kelvin,
        pressure=1.0 * unit.atmospheres)

    sampler_state = states.SamplerState(
        positions=positions,
        box_vectors=t.unitcell_vectors[configs[index], :, :] * unit.nanometer)
    logger.debug(type(sampler_state))
    move = mcmc.LangevinDynamicsMove(timestep=2 * unit.femtosecond,
                                     collision_rate=1.0 / unit.picoseconds,
                                     n_steps=500,
                                     reassign_velocities=False)
    simulation = ReplicaExchangeSampler(mcmc_moves=move,
                                        number_of_iterations=1)
    analysis_particle_indices = topology.select(
        '(protein and mass > 3.0) or (resname MER and mass > 3.0)')
    reporter = MultiStateReporter(
        output_filename,
        checkpoint_interval=2000,
        analysis_particle_indices=analysis_particle_indices)

    first, last = limits[index]
    # Initialize compound thermodynamic states
    protocol = {
        'lambda_restraints': [i / 159 for i in range(first, last + 1)],
        'K_parallel': [
            1250 * unit.kilojoules_per_mole / unit.nanometer**2
            for i in range(first, last + 1)
        ],
        'Kmax': [
            500 * unit.kilojoules_per_mole / unit.nanometer**2
            for i in range(first, last + 1)
        ],
        'Kmin': [
            500 * unit.kilojoules_per_mole / unit.nanometer**2
            for i in range(first, last + 1)
        ]
    }

    my_composable_state = MyComposableState.from_system(openmm_system)

    compound_states = states.create_thermodynamic_state_protocol(
        thermodynamic_state_deserialized,
        protocol=protocol,
        composable_states=[my_composable_state])

    simulation.create(thermodynamic_states=compound_states,
                      sampler_states=[sampler_state],
                      storage=reporter)

    simulation.equilibrate(50, mcmc_moves=move)
    simulation.run()
    ts = simulation._thermodynamic_states[0]
    context, _ = openmmtools.cache.global_context_cache.get_context(ts)

    files_names = [
        'state_{}_{}.log'.format(index, i) for i in range(first, last + 1)
    ]
    files = []
    for i, file in enumerate(files_names):
        files.append(open(file, 'w'))

    mpi.distribute(write_cv,
                   range(simulation.n_replicas),
                   context,
                   simulation,
                   files,
                   send_results_to=None)

    for i in range(10000):
        simulation.extend(n_iterations=2)
        mpi.distribute(write_cv,
                       range(simulation.n_replicas),
                       context,
                       simulation,
                       files,
                       send_results_to=None)
    Kmin = GlobalParameterState.GlobalParameter(
        'Kmin',
        standard_value=10 * unit.kilojoules_per_mole / unit.nanometer**2)


yank.utils.config_root_logger(verbose=True, log_file_path=None)
logger = logging.getLogger(__name__)
logging.root.setLevel(logging.DEBUG)
logging.basicConfig(level=logging.DEBUG)
cv_logger = logging.getLogger(__name__)
cv_logger.setLevel(logging.DEBUG)
handler = logging.FileHandler('cv.log')
cv_logger.addHandler(handler)

from yank.experiment import ExperimentBuilder
platform = ExperimentBuilder._configure_platform('CUDA', 'mixed')

try:
    openmmtools.cache.global_context_cache.platform = platform
except RuntimeError:
    openmmtools.cache.global_context_cache.empty()
    openmmtools.cache.global_context_cache.platform = platform

# Topology
pdb = app.PDBFile('../../../smd/porin-ligand.pdb')

with open('../../../smd/openmm_system_alch.xml', 'r') as infile:
    openmm_system = XmlSerializer.deserialize(infile.read())

topology = md.Topology.from_openmm(pdb.topology)
ligand_atoms = topology.select('(resname CM7)')
예제 #12
0
    def process(self, solvated_system, port):

        try:
            opt = dict(self.opt)

            # Extract the solvated ligand and the solvated complex
            solvated_ligand = solvated_system[0]
            solvated_complex = solvated_system[1]

            # Update cube simulation parameters with the eventually molecule SD tags
            new_args = {dp.GetTag(): dp.GetValue() for dp in oechem.OEGetSDDataPairs(solvated_ligand) if dp.GetTag() in
                        ["temperature", "pressure"]}
            if new_args:
                for k in new_args:
                    try:
                        new_args[k] = float(new_args[k])
                    except:
                        pass
                self.log.info("Updating parameters for molecule: {}\n{}".format(solvated_ligand.GetTitle(), new_args))
                opt.update(new_args)

            # Extract the MD data
            mdData_ligand = data_utils.MDData(solvated_ligand)
            solvated_ligand_structure = mdData_ligand.structure

            mdData_complex = data_utils.MDData(solvated_complex)
            solvated_complex_structure = mdData_complex.structure

            # Create the solvated OpenMM systems
            solvated_complex_omm_sys = solvated_complex_structure.createSystem(nonbondedMethod=app.PME,
                                                                               nonbondedCutoff=opt['nonbondedCutoff'] * unit.angstroms,
                                                                               constraints=app.HBonds,
                                                                               removeCMMotion=False)

            solvated_ligand_omm_sys = solvated_ligand_structure.createSystem(nonbondedMethod=app.PME,
                                                                             nonbondedCutoff=opt['nonbondedCutoff'] * unit.angstroms,
                                                                             constraints=app.HBonds,
                                                                             removeCMMotion=False)

            # Write out all the required files and set-run the Yank experiment
            with TemporaryDirectory() as output_directory:

                opt['Logger'].info("Output Directory {}".format(output_directory))

                solvated_complex_structure_fn = os.path.join(output_directory, "complex.pdb")
                solvated_complex_structure.save(solvated_complex_structure_fn, overwrite=True)

                solvated_ligand_structure_fn = os.path.join(output_directory, "solvent.pdb")
                solvated_ligand_structure.save(solvated_ligand_structure_fn, overwrite=True)

                solvated_complex_omm_serialized = XmlSerializer.serialize(solvated_complex_omm_sys)
                solvated_complex_omm_serialized_fn = os.path.join(output_directory, "complex.xml")
                solvated_complex_f = open(solvated_complex_omm_serialized_fn, 'w')
                solvated_complex_f.write(solvated_complex_omm_serialized)
                solvated_complex_f.close()

                solvated_ligand_omm_serialized = XmlSerializer.serialize(solvated_ligand_omm_sys)
                solvated_ligand_omm_serialized_fn = os.path.join(output_directory, "solvent.xml")
                solvated_ligand_f = open(solvated_ligand_omm_serialized_fn, 'w')
                solvated_ligand_f.write(solvated_ligand_omm_serialized)
                solvated_ligand_f.close()

                # Build the Yank Experiment
                yaml_builder = ExperimentBuilder(yank_binding_template.format(
                    verbose='yes' if opt['verbose'] else 'no',
                    minimize='yes' if opt['minimize'] else 'no',
                    output_directory=output_directory,
                    timestep=opt['timestep'],
                    nsteps_per_iteration=opt['nsteps_per_iteration'],
                    number_iterations=opt['iterations'],
                    temperature=opt['temperature'],
                    pressure=opt['pressure'],
                    complex_pdb_fn=solvated_complex_structure_fn,
                    complex_xml_fn=solvated_complex_omm_serialized_fn,
                    solvent_pdb_fn=solvated_ligand_structure_fn,
                    solvent_xml_fn=solvated_ligand_omm_serialized_fn,
                    restraints=opt['restraints'],
                    ligand_resname=opt['ligand_resname']))

                # Run Yank
                yaml_builder.run_experiments()

                exp_dir = os.path.join(output_directory, "experiments")

                DeltaG_binding, dDeltaG_binding, DeltaH, dDeltaH = yankutils.analyze_directory(exp_dir)

                protein, ligand, water, excipients = oeommutils.split(solvated_ligand,
                                                                      ligand_res_name=opt['ligand_resname'])
                # Add result to the extracted ligand in kcal/mol
                oechem.OESetSDData(ligand, 'DG_yank_binding', str(DeltaG_binding))
                oechem.OESetSDData(ligand, 'dG_yank_binding', str(dDeltaG_binding))

            self.success.emit(ligand)

        except Exception as e:
            # Attach an error message to the molecule that failed
            self.log.error(traceback.format_exc())
            solvated_system[1].SetData('error', str(e))
            # Return failed mol
            self.failure.emit(solvated_system[1])

        return 
예제 #13
0
    def process(self, solvated_system, port):

        try:
            # The copy of the dictionary option as local variable
            # is necessary to avoid filename collisions due to
            # the parallel cube processes
            opt = dict(self.opt)

            # Split the complex in components
            protein, solute, water, excipients = oeommutils.split(solvated_system, ligand_res_name='LIG')

            # Update cube simulation parameters with the eventually molecule SD tags
            new_args = {dp.GetTag(): dp.GetValue() for dp in oechem.OEGetSDDataPairs(solute) if dp.GetTag() in
                        ["temperature", "pressure"]}

            if new_args:
                for k in new_args:
                    try:
                        new_args[k] = float(new_args[k])
                    except:
                        pass
                self.log.info("Updating parameters for molecule: {}\n{}".format(solute.GetTitle(), new_args))
                opt.update(new_args)

            # Extract the MD data
            mdData = data_utils.MDData(solvated_system)
            solvated_structure = mdData.structure

            # Extract the ligand parmed structure
            solute_structure = solvated_structure.split()[0][0]
            solute_structure.box = None

            # Set the ligand title
            solute.SetTitle(solvated_system.GetTitle())

            # Create the solvated and vacuum system
            solvated_omm_sys = solvated_structure.createSystem(nonbondedMethod=app.PME,
                                                               nonbondedCutoff=opt['nonbondedCutoff'] * unit.angstroms,
                                                               constraints=app.HBonds,
                                                               removeCMMotion=False)

            solute_omm_sys = solute_structure.createSystem(nonbondedMethod=app.NoCutoff,
                                                           constraints=app.HBonds,
                                                           removeCMMotion=False)

            # This is a note from:
            # https://github.com/MobleyLab/SMIRNOFF_paper_code/blob/e5012c8fdc4570ca0ec750f7ab81dd7102e813b9/scripts/create_input_files.py#L114
            # Fix switching function.
            for force in solvated_omm_sys.getForces():
                if isinstance(force, openmm.NonbondedForce):
                    force.setUseSwitchingFunction(True)
                    force.setSwitchingDistance((opt['nonbondedCutoff'] - 1.0) * unit.angstrom)

            # Write out all the required files and set-run the Yank experiment
            with TemporaryDirectory() as output_directory:

                opt['Logger'].info("Output Directory {}".format(output_directory))

                solvated_structure_fn = os.path.join(output_directory, "solvated.pdb")
                solvated_structure.save(solvated_structure_fn, overwrite=True)

                solute_structure_fn = os.path.join(output_directory, "solute.pdb")
                solute_structure.save(solute_structure_fn, overwrite=True)

                solvated_omm_sys_serialized = XmlSerializer.serialize(solvated_omm_sys)
                solvated_omm_sys_serialized_fn = os.path.join(output_directory, "solvated.xml")
                solvated_f = open(solvated_omm_sys_serialized_fn, 'w')
                solvated_f.write(solvated_omm_sys_serialized)
                solvated_f.close()

                solute_omm_sys_serialized = XmlSerializer.serialize(solute_omm_sys)
                solute_omm_sys_serialized_fn = os.path.join(output_directory, "solute.xml")
                solute_f = open(solute_omm_sys_serialized_fn, 'w')
                solute_f.write(solute_omm_sys_serialized)
                solute_f.close()

                # Build the Yank Experiment
                yaml_builder = ExperimentBuilder(yank_solvation_template.format(
                                                 verbose='yes' if opt['verbose'] else 'no',
                                                 minimize='yes' if opt['minimize'] else 'no',
                                                 output_directory=output_directory,
                                                 timestep=opt['timestep'],
                                                 nsteps_per_iteration=opt['nsteps_per_iteration'],
                                                 number_iterations=opt['iterations'],
                                                 temperature=opt['temperature'],
                                                 pressure=opt['pressure'],
                                                 solvated_pdb_fn=solvated_structure_fn,
                                                 solvated_xml_fn=solvated_omm_sys_serialized_fn,
                                                 solute_pdb_fn=solute_structure_fn,
                                                 solute_xml_fn=solute_omm_sys_serialized_fn))

                # Run Yank
                yaml_builder.run_experiments()

                exp_dir = os.path.join(output_directory, "experiments")

                # Calculate solvation free energy, solvation Enthalpy and their errors
                DeltaG_solvation, dDeltaG_solvation, DeltaH, dDeltaH = yankutils.analyze_directory(exp_dir)

                # # Add result to the original molecule in kcal/mol
                oechem.OESetSDData(solute, 'DG_yank_solv', str(DeltaG_solvation))
                oechem.OESetSDData(solute, 'dG_yank_solv', str(dDeltaG_solvation))

            # Emit the ligand
            self.success.emit(solute)

        except Exception as e:
            # Attach an error message to the molecule that failed
            self.log.error(traceback.format_exc())
            solvated_system.SetData('error', str(e))
            # Return failed mol
            self.failure.emit(solvated_system)

        return