def test_harmonic_standard_state(): """ Test that the expected harmonic standard state correction is close to our approximation Also ensures that PBC bonds are being computed and disabled correctly as expected """ LJ_fluid = testsystems.LennardJonesFluid() receptor_atoms = [0, 1, 2] ligand_atoms = [3, 4, 5] thermodynamic_state = ThermodynamicState(temperature=300.0 * unit.kelvin) restraint = yank.restraints.create_restraints( 'Harmonic', LJ_fluid.topology, thermodynamic_state, LJ_fluid.system, LJ_fluid.positions, receptor_atoms, ligand_atoms) spring_constant = restraint._determine_bond_parameters()[0] # Compute standard-state volume for a single molecule in a box of size (1 L) / (avogadros number) liter = 1000.0 * unit.centimeters**3 # one liter box_volume = liter / (unit.AVOGADRO_CONSTANT_NA * unit.mole ) # standard state volume analytical_shell_volume = (2 * math.pi / (spring_constant * restraint.beta))**(3.0 / 2) analytical_standard_state_G = -math.log( box_volume / analytical_shell_volume) restraint_standard_state_G = restraint.get_standard_state_correction() np.testing.assert_allclose(analytical_standard_state_G, restraint_standard_state_G)
def test_phase_creation(): """Phases are initialized correctly by Yank.create().""" phase_name = 'my-solvent-phase' toluene = testsystems.TolueneImplicit() protocol = AbsoluteAlchemicalFactory.defaultSolventProtocolImplicit() atom_indices = find_components(toluene.system, toluene.topology, 'resname TOL') phase = AlchemicalPhase(phase_name, toluene.system, toluene.topology, toluene.positions, atom_indices, protocol) thermodynamic_state = ThermodynamicState(temperature=300.0*unit.kelvin) # Create new simulation. with enter_temp_directory(): output_dir = 'output' utils.config_root_logger(verbose=False) yank = Yank(store_directory=output_dir) yank.create(thermodynamic_state, phase) # Netcdf dataset has been created nc_path = os.path.join(output_dir, phase_name + '.nc') assert os.path.isfile(nc_path) # Read data try: nc_file = netcdf.Dataset(nc_path, mode='r') metadata_group = nc_file.groups['metadata'] serialized_topology = metadata_group.variables['topology'][0] finally: nc_file.close() # Topology has been stored correctly deserialized_topology = utils.deserialize_topology(serialized_topology) assert deserialized_topology == mdtraj.Topology.from_openmm(toluene.topology)
def test_restraint_dispatch(): """Test dispatch of various restraint types. """ for (restraint_type, restraint_class) in expected_restraints.items(): # Create a test system t = HostGuestNoninteracting() # Create a thermodynamic state encoding temperature thermodynamic_state = ThermodynamicState(temperature=300.0 * unit.kelvin) # Add restraints restraint = yank.restraints.create_restraints( restraint_type, t.topology, thermodynamic_state, t.system, t.positions, t.receptor_atoms, t.ligand_atoms) # Check that we got the right restraint class assert (restraint.__class__.__name__ == restraint_type) assert (restraint.__class__ == restraint_class)
def test_no_alchemical_atoms(): """Test whether Yank raises exception when no alchemical atoms are specified.""" toluene = testsystems.TolueneImplicit() # Create parameters. With the exception of atom_indices, all other # parameters must be legal, we don't want to catch an exception # different than the one we are testing. phase = AlchemicalPhase(name='solvent-implicit', reference_system=toluene.system, reference_topology=toluene.topology, positions=toluene.positions, atom_indices={'ligand': []}, protocol=AbsoluteAlchemicalFactory.defaultSolventProtocolImplicit()) thermodynamic_state = ThermodynamicState(temperature=300.0*unit.kelvin) # Create new simulation. with enter_temp_directory(): yank = Yank(store_directory='output') yank.create(thermodynamic_state, phase)
def notest_hamiltonian_exchange(mpicomm=None, verbose=True): """ Test that free energies and average potential energies of a 3D harmonic oscillator are correctly computed when running HamiltonianExchange. TODO * Integrate with test_replica_exchange. * Test with different combinations of input parameters. """ if verbose and ((not mpicomm) or (mpicomm.rank==0)): sys.stdout.write("Testing Hamiltonian exchange facility with harmonic oscillators: ") # Create test system of harmonic oscillators testsystem = testsystems.HarmonicOscillatorArray() [system, coordinates] = [testsystem.system, testsystem.positions] # Define mass of carbon atom. mass = 12.0 * units.amu # Define thermodynamic states. sigmas = [0.2, 0.3, 0.4] * units.angstroms # standard deviations: beta K = 1/sigma^2 so K = 1/(beta sigma^2) temperature = 300.0 * units.kelvin # temperatures seed_positions = list() analytical_results = list() f_i_analytical = list() # dimensionless free energies u_i_analytical = list() # reduced potential systems = list() # Systems list for HamiltonianExchange for sigma in sigmas: # Compute corresponding spring constant. kB = units.BOLTZMANN_CONSTANT_kB * units.AVOGADRO_CONSTANT_NA kT = kB * temperature # thermal energy beta = 1.0 / kT # inverse temperature K = 1.0 / (beta * sigma**2) # Create harmonic oscillator system. testsystem = testsystems.HarmonicOscillator(K=K, mass=mass, mm=openmm) [system, positions] = [testsystem.system, testsystem.positions] # Append to systems list. systems.append(system) # Append positions. seed_positions.append(positions) # Store analytical results. results = computeHarmonicOscillatorExpectations(K, mass, temperature) analytical_results.append(results) f_i_analytical.append(results['f']) reduced_potential = results['potential']['mean'] / kT u_i_analytical.append(reduced_potential) # DEBUG print("") print(seed_positions) print(analytical_results) print(u_i_analytical) print(f_i_analytical) print("") # Compute analytical Delta_f_ij nstates = len(f_i_analytical) f_i_analytical = numpy.array(f_i_analytical) u_i_analytical = numpy.array(u_i_analytical) s_i_analytical = u_i_analytical - f_i_analytical Delta_f_ij_analytical = numpy.zeros([nstates,nstates], numpy.float64) Delta_u_ij_analytical = numpy.zeros([nstates,nstates], numpy.float64) Delta_s_ij_analytical = numpy.zeros([nstates,nstates], numpy.float64) for i in range(nstates): for j in range(nstates): Delta_f_ij_analytical[i,j] = f_i_analytical[j] - f_i_analytical[i] Delta_u_ij_analytical[i,j] = u_i_analytical[j] - u_i_analytical[i] Delta_s_ij_analytical[i,j] = s_i_analytical[j] - s_i_analytical[i] # Define file for temporary storage. import tempfile # use a temporary file file = tempfile.NamedTemporaryFile(delete=False) store_filename = file.name #print("Storing data in temporary file: %s" % str(store_filename)) # Create reference thermodynamic state. reference_state = ThermodynamicState(systems[0], temperature=temperature) # Create and configure simulation object. simulation = HamiltonianExchange(store_filename, mpicomm=mpicomm) simulation.create(reference_state, systems, seed_positions) simulation.platform = openmm.Platform.getPlatformByName('Reference') simulation.number_of_iterations = 200 simulation.timestep = 2.0 * units.femtoseconds simulation.nsteps_per_iteration = 500 simulation.collision_rate = 9.2 / units.picosecond simulation.verbose = False simulation.show_mixing_statistics = False # Run simulation. utils.config_root_logger(True) simulation.run() # run the simulation utils.config_root_logger(False) # Stop here if not root node. if mpicomm and (mpicomm.rank != 0): return # Analyze simulation to compute free energies. analysis = simulation.analyze() # TODO: Check if deviations exceed tolerance. Delta_f_ij = analysis['Delta_f_ij'] dDelta_f_ij = analysis['dDelta_f_ij'] error = Delta_f_ij - Delta_f_ij_analytical indices = numpy.where(dDelta_f_ij > 0.0) nsigma = numpy.zeros([nstates,nstates], numpy.float32) nsigma[indices] = error[indices] / dDelta_f_ij[indices] MAX_SIGMA = 6.0 # maximum allowed number of standard errors if numpy.any(nsigma > MAX_SIGMA): print("Delta_f_ij") print(Delta_f_ij) print("Delta_f_ij_analytical") print(Delta_f_ij_analytical) print("error") print(error) print("stderr") print(dDelta_f_ij) print("nsigma") print(nsigma) raise Exception("Dimensionless free energy difference exceeds MAX_SIGMA of %.1f" % MAX_SIGMA) error = analysis['Delta_u_ij'] - Delta_u_ij_analytical nsigma = numpy.zeros([nstates,nstates], numpy.float32) nsigma[indices] = error[indices] / dDelta_f_ij[indices] if numpy.any(nsigma > MAX_SIGMA): print("Delta_u_ij") print(analysis['Delta_u_ij']) print("Delta_u_ij_analytical") print(Delta_u_ij_analytical) print("error") print(error) print("nsigma") print(nsigma) raise Exception("Dimensionless potential energy difference exceeds MAX_SIGMA of %.1f" % MAX_SIGMA) if verbose: print("PASSED.") return
def test_replica_exchange(mpicomm=None, verbose=True): """ Test that free energies and average potential energies of a 3D harmonic oscillator are correctly computed by parallel tempering. TODO * Test ParallelTempering and HamiltonianExchange subclasses as well. * Test with different combinations of input parameters. """ if verbose and ((not mpicomm) or (mpicomm.rank==0)): sys.stdout.write("Testing replica exchange facility with harmonic oscillators: ") # Define mass of carbon atom. mass = 12.0 * units.amu # Define thermodynamic states. states = list() # thermodynamic states Ks = [500.00, 400.0, 300.0] * units.kilocalories_per_mole / units.angstroms**2 # spring constants temperatures = [300.0, 350.0, 400.0] * units.kelvin # temperatures seed_positions = list() analytical_results = list() f_i_analytical = list() # dimensionless free energies u_i_analytical = list() # reduced potential for (K, temperature) in zip(Ks, temperatures): # Create harmonic oscillator system. testsystem = testsystems.HarmonicOscillator(K=K, mass=mass, mm=openmm) [system, positions] = [testsystem.system, testsystem.positions] # Create thermodynamic state. state = ThermodynamicState(system=system, temperature=temperature) # Append thermodynamic state and positions. states.append(state) seed_positions.append(positions) # Store analytical results. results = computeHarmonicOscillatorExpectations(K, mass, temperature) analytical_results.append(results) f_i_analytical.append(results['f']) kT = kB * temperature # thermal energy reduced_potential = results['potential']['mean'] / kT u_i_analytical.append(reduced_potential) # Compute analytical Delta_f_ij nstates = len(f_i_analytical) f_i_analytical = numpy.array(f_i_analytical) u_i_analytical = numpy.array(u_i_analytical) s_i_analytical = u_i_analytical - f_i_analytical Delta_f_ij_analytical = numpy.zeros([nstates,nstates], numpy.float64) Delta_u_ij_analytical = numpy.zeros([nstates,nstates], numpy.float64) Delta_s_ij_analytical = numpy.zeros([nstates,nstates], numpy.float64) for i in range(nstates): for j in range(nstates): Delta_f_ij_analytical[i,j] = f_i_analytical[j] - f_i_analytical[i] Delta_u_ij_analytical[i,j] = u_i_analytical[j] - u_i_analytical[i] Delta_s_ij_analytical[i,j] = s_i_analytical[j] - s_i_analytical[i] # Define file for temporary storage. import tempfile # use a temporary file file = tempfile.NamedTemporaryFile(delete=False) store_filename = file.name #print("node %d : Storing data in temporary file: %s" % (mpicomm.rank, str(store_filename))) # DEBUG # Create and configure simulation object. simulation = ReplicaExchange(store_filename, mpicomm=mpicomm) simulation.create(states, seed_positions) simulation.platform = openmm.Platform.getPlatformByName('Reference') simulation.minimize = False simulation.number_of_iterations = 200 simulation.nsteps_per_iteration = 500 simulation.timestep = 2.0 * units.femtoseconds simulation.collision_rate = 20.0 / units.picosecond simulation.verbose = False simulation.show_mixing_statistics = False simulation.online_analysis = True # Run simulation. utils.config_root_logger(False) simulation.run() # run the simulation utils.config_root_logger(True) # Stop here if not root node. if mpicomm and (mpicomm.rank != 0): return # Retrieve extant analysis object. online_analysis = simulation.analysis # Analyze simulation to compute free energies. analysis = simulation.analyze() # Check if online analysis is close to final analysis. error = numpy.abs(online_analysis['Delta_f_ij'] - analysis['Delta_f_ij']) derror = (online_analysis['dDelta_f_ij']**2 + analysis['dDelta_f_ij']**2) indices = numpy.where(derror > 0.0) nsigma = numpy.zeros([nstates,nstates], numpy.float32) nsigma[indices] = error[indices] / derror[indices] MAX_SIGMA = 6.0 # maximum allowed number of standard errors if numpy.any(nsigma > MAX_SIGMA): print("Delta_f_ij from online analysis") print(online_analysis['Delta_f_ij']) print("Delta_f_ij from final analysis") print(analysis['Delta_f_ij']) print("error") print(error) print("derror") print(derror) print("nsigma") print(nsigma) raise Exception("Dimensionless free energy differences between online and final analysis exceeds MAX_SIGMA of %.1f" % MAX_SIGMA) # TODO: Check if deviations exceed tolerance. Delta_f_ij = analysis['Delta_f_ij'] dDelta_f_ij = analysis['dDelta_f_ij'] error = numpy.abs(Delta_f_ij - Delta_f_ij_analytical) indices = numpy.where(dDelta_f_ij > 0.0) nsigma = numpy.zeros([nstates,nstates], numpy.float32) nsigma[indices] = error[indices] / dDelta_f_ij[indices] MAX_SIGMA = 6.0 # maximum allowed number of standard errors if numpy.any(nsigma > MAX_SIGMA): print("Delta_f_ij") print(Delta_f_ij) print("Delta_f_ij_analytical") print(Delta_f_ij_analytical) print("error") print(error) print("stderr") print(dDelta_f_ij) print("nsigma") print(nsigma) raise Exception("Dimensionless free energy difference exceeds MAX_SIGMA of %.1f" % MAX_SIGMA) error = analysis['Delta_u_ij'] - Delta_u_ij_analytical nsigma = numpy.zeros([nstates,nstates], numpy.float32) nsigma[indices] = error[indices] / dDelta_f_ij[indices] if numpy.any(nsigma > MAX_SIGMA): print("Delta_u_ij") print(analysis['Delta_u_ij']) print("Delta_u_ij_analytical") print(Delta_u_ij_analytical) print("error") print(error) print("nsigma") print(nsigma) raise Exception("Dimensionless potential energy difference exceeds MAX_SIGMA of %.1f" % MAX_SIGMA) # Clean up. del simulation if verbose: print("PASSED.") return
def notest_LennardJonesPair(box_width_nsigma=6.0): """ Compute binding free energy of two Lennard-Jones particles and compare to numerical result. Parameters ---------- box_width_nsigma : float, optional, default=6.0 Box width is set to this multiple of Lennard-Jones sigma. """ NSIGMA_MAX = 6.0 # number of standard errors tolerated for success # Create Lennard-Jones pair. thermodynamic_state = ThermodynamicState(temperature=300.0*unit.kelvin) kT = kB * thermodynamic_state.temperature sigma = 3.5 * unit.angstroms epsilon = 6.0 * kT test = testsystems.LennardJonesPair(sigma=sigma, epsilon=epsilon) system, positions = test.system, test.positions binding_free_energy = test.get_binding_free_energy(thermodynamic_state) # Create temporary directory for testing. import tempfile store_dir = tempfile.mkdtemp() # Initialize YANK object. options = dict() options['restraint_type'] = None options['number_of_iterations'] = 10 options['platform'] = openmm.Platform.getPlatformByName("Reference") # use Reference platform for speed options['mc_rotation'] = False options['mc_displacement'] = True options['mc_displacement_sigma'] = 1.0 * unit.nanometer options['timestep'] = 2 * unit.femtoseconds options['nsteps_per_iteration'] = 50 # Override receptor mass to keep it stationary. #system.setParticleMass(0, 0) # Override box vectors. box_edge = 6*sigma a = unit.Quantity((box_edge, 0 * unit.angstrom, 0 * unit.angstrom)) b = unit.Quantity((0 * unit.angstrom, box_edge, 0 * unit.angstrom)) c = unit.Quantity((0 * unit.angstrom, 0 * unit.angstrom, box_edge)) system.setDefaultPeriodicBoxVectors(a, b, c) # Override positions positions[0,:] = box_edge/2 positions[1,:] = box_edge/4 phase = 'complex-explicit' # Alchemical protocol. from yank.alchemy import AlchemicalState alchemical_states = list() lambda_values = [0.0, 0.25, 0.50, 0.75, 1.0] for lambda_value in lambda_values: alchemical_state = AlchemicalState() alchemical_state['lambda_electrostatics'] = lambda_value alchemical_state['lambda_sterics'] = lambda_value alchemical_states.append(alchemical_state) protocols = dict() protocols[phase] = alchemical_states # Create phases. alchemical_phase = AlchemicalPhase(phase, system, test.topology, positions, {'complex-explicit': {'ligand': [1]}}, alchemical_states) # Create new simulation. yank = Yank(store_dir, **options) yank.create(thermodynamic_state, alchemical_phase) # Run the simulation. yank.run() # Analyze the data. results = yank.analyze() standard_state_correction = results[phase]['standard_state_correction'] Delta_f = results[phase]['Delta_f_ij'][0,1] - standard_state_correction dDelta_f = results[phase]['dDelta_f_ij'][0,1] nsigma = abs(binding_free_energy/kT - Delta_f) / dDelta_f # Check results against analytical results. # TODO: Incorporate standard state correction output = "\n" output += "Analytical binding free energy : %10.5f +- %10.5f kT\n" % (binding_free_energy / kT, 0) output += "Computed binding free energy (with standard state correction) : %10.5f +- %10.5f kT (nsigma = %3.1f)\n" % (Delta_f, dDelta_f, nsigma) output += "Computed binding free energy (without standard state correction): %10.5f +- %10.5f kT (nsigma = %3.1f)\n" % (Delta_f + standard_state_correction, dDelta_f, nsigma) output += "Standard state correction alone : %10.5f kT\n" % (standard_state_correction) print output #if (nsigma > NSIGMA_MAX): # output += "\n" # output += "Computed binding free energy differs from true binding free energy.\n" # raise Exception(output) return [Delta_f, dDelta_f]
def dispatch_binding(args): """ Set up a binding free energy calculation. Parameters ---------- args : dict Command-line arguments from docopt. """ verbose = args['--verbose'] store_dir = args['--store'] utils.config_root_logger(verbose, log_file_path=os.path.join( store_dir, 'prepare.log')) # # Determine simulation options. # # Specify thermodynamic parameters. temperature = process_unit_bearing_argument(args, '--temperature', unit.kelvin) pressure = process_unit_bearing_argument(args, '--pressure', unit.atmospheres) thermodynamic_state = ThermodynamicState(temperature=temperature, pressure=pressure) # Create systems according to specified setup/import method. if args['amber']: [phases, systems, positions, atom_indices] = setup_binding_amber(args) elif args['gromacs']: [phases, systems, positions, atom_indices] = setup_binding_gromacs(args) else: logger.error( "No valid binding free energy calculation setup command specified: Must be one of ['amber', 'systembuilder']." ) # Trigger help argument to be returned. return False # Report some useful properties. if verbose: if 'complex-explicit' in atom_indices: phase = 'complex-explicit' else: phase = 'complex-implicit' logger.info("TOTAL ATOMS : %9d" % len(atom_indices[phase]['complex'])) logger.info("receptor : %9d" % len(atom_indices[phase]['receptor'])) logger.info("ligand : %9d" % len(atom_indices[phase]['ligand'])) if phase == 'complex-explicit': logger.info("solvent and ions : %9d" % len(atom_indices[phase]['solvent'])) # Initialize YANK object. yank = Yank(store_dir) # Set options. options = dict() if args['--nsteps']: options['nsteps_per_iteration'] = int(args['--nsteps']) if args['--iterations']: options['number_of_iterations'] = int(args['--iterations']) if args['--equilibrate']: options['number_of_equilibration_iterations'] = int( args['--equilibrate']) if args['--online-analysis']: options['online_analysis'] = True if args['--restraints']: yank.restraint_type = args['--restraints'] if args['--randomize-ligand']: options['randomize_ligand'] = True if args['--minimize']: options['minimize'] = True # Allow platform to be optionally specified in order for alchemical tests to be carried out. if args['--platform'] not in [None, 'None']: options['platform'] = openmm.Platform.getPlatformByName( args['--platform']) if args['--precision']: # We need to modify the Platform object. if args['--platform'] is None: raise Exception( "The --platform argument must be specified in order to specify platform precision." ) # Set platform precision. precision = args['--precision'] platform_name = args['--platform'] logger.info( "Setting %s platform to use precision model '%s'." % platform_name, precision) if precision is not None: if platform_name == 'CUDA': options['platform'].setPropertyDefaultValue( 'CudaPrecision', precision) elif platform_name == 'OpenCL': options['platform'].setPropertyDefaultValue( 'OpenCLPrecision', precision) elif platform_name == 'CPU': if precision != 'mixed': raise Exception( "CPU platform does not support precision model '%s'; only 'mixed' is supported." % precision) elif platform_name == 'Reference': if precision != 'double': raise Exception( "Reference platform does not support precision model '%s'; only 'double' is supported." % precision) else: raise Exception( "Platform selection logic is outdated and needs to be updated to add platform '%s'." % platform_name) # Create new simulation. yank.create(phases, systems, positions, atom_indices, thermodynamic_state, options=options) # Report success. return True
# Identify various components. solvated_topology_mdtraj = mdtraj.Topology.from_openmm(solvated_topology_openmm) atom_indices = dict() for component in components: atom_indices[component] = solvated_topology_mdtraj.select(component_dsl[component]) # DEBUG print "Atom indices of ligand:" print atom_indices[phase]['ligand'] alchemical_phases.append(AlchemicalPhase(phase, solvated_system, solvated_topology_openmm, solvated_positions, atom_indices, protocols[phase_prefix])) # Create reference thermodynamic state. from yank.repex import ThermodynamicState # TODO: Fix this weird import path to something more sane, like 'from yank.repex import ThermodynamicState' if is_periodic: thermodynamic_state = ThermodynamicState(temperature=temperature, pressure=pressure) else: thermodynamic_state = ThermodynamicState(temperature=temperature) # TODO: Select protocols. # Create new simulation. yank = Yank(store_dir, **options) yank.create(thermodynamic_state, *alchemical_phases) # TODO: Write PDB files
def dispatch_binding(args): """ Set up a binding free energy calculation. Parameters ---------- args : dict Command-line arguments from docopt. """ verbose = args['--verbose'] store_dir = args['--store'] utils.config_root_logger(verbose, log_file_path=os.path.join( store_dir, 'prepare.log')) # # Determine simulation options. # # Specify thermodynamic parameters. temperature = process_unit_bearing_arg(args, '--temperature', unit.kelvin) pressure = process_unit_bearing_arg(args, '--pressure', unit.atmospheres) thermodynamic_state = ThermodynamicState(temperature=temperature, pressure=pressure) # Create systems according to specified setup/import method. if args['amber']: alchemical_phases = setup_binding_amber(args) elif args['gromacs']: alchemical_phases = setup_binding_gromacs(args) else: logger.error( "No valid binding free energy calculation setup command specified: Must be one of ['amber', 'systembuilder']." ) # Trigger help argument to be returned. return False # Set options. options = dict() if args['--nsteps']: options['nsteps_per_iteration'] = int(args['--nsteps']) if args['--iterations']: options['number_of_iterations'] = int(args['--iterations']) if args['--equilibrate']: options['number_of_equilibration_iterations'] = int( args['--equilibrate']) if args['--online-analysis']: options['online_analysis'] = True if args['--restraints']: options['restraint_type'] = args['--restraints'] if args['--randomize-ligand']: options['randomize_ligand'] = True if args['--minimize']: options['minimize'] = True # Allow platform to be optionally specified in order for alchemical tests to be carried out. if args['--platform'] not in [None, 'None']: options['platform'] = openmm.Platform.getPlatformByName( args['--platform']) if args['--precision']: # We need to modify the Platform object. if args['--platform'] is None: raise Exception( "The --platform argument must be specified in order to specify platform precision." ) # Set platform precision. precision = args['--precision'] platform_name = args['--platform'] logger.info( "Setting %s platform to use precision model '%s'." % platform_name, precision) if precision is not None: if platform_name == 'CUDA': options['platform'].setPropertyDefaultValue( 'CudaPrecision', precision) elif platform_name == 'OpenCL': options['platform'].setPropertyDefaultValue( 'OpenCLPrecision', precision) elif platform_name == 'CPU': if precision != 'mixed': raise Exception( "CPU platform does not support precision model '%s'; only 'mixed' is supported." % precision) elif platform_name == 'Reference': if precision != 'double': raise Exception( "Reference platform does not support precision model '%s'; only 'double' is supported." % precision) else: raise Exception( "Platform selection logic is outdated and needs to be updated to add platform '%s'." % platform_name) # Parse YAML options, CLI options have priority if args['--yaml']: options.update(YamlBuilder(args['--yaml']).yank_options) # Create new simulation. yank = Yank(store_dir, **options) yank.create(thermodynamic_state, *alchemical_phases) # Dump analysis object analysis = [[alchemical_phases[0].name, 1], [alchemical_phases[1].name, -1]] analysis_script_path = os.path.join(store_dir, 'analysis.yaml') with open(analysis_script_path, 'w') as f: yaml.dump(analysis, f) # Report success. return True
def dispatch_binding(args): """ Set up a binding free energy calculation. Parameters ---------- args : dict Command-line arguments from docopt. """ verbose = args['--verbose'] # Specify simulation parameters. nonbondedMethod = getattr(app, args['--nbmethod']) implicitSolvent = getattr(app, args['--gbsa']) if args['--constraints'] == None: args[ '--constraints'] = None # Necessary because there is no 'None' in simtk.openmm.app constraints = getattr(app, args['--constraints']) removeCMMotion = False # Specify thermodynamic parameters. temperature = process_unit_bearing_argument(args, '--temperature', unit.kelvin) pressure = process_unit_bearing_argument(args, '--pressure', unit.atmospheres) thermodynamic_state = ThermodynamicState(temperature=temperature, pressure=pressure) # Create systems according to specified setup/import method. if args['amber']: [phases, systems, positions, atom_indices] = setup_binding_amber(args) elif args['systembuilder']: [phases, systems, positions, atom_indices] = setup_binding_systembuilder(args) else: print "No valid binding free energy calculation setup command specified: Must be one of ['amber', 'systembuilder']." # Trigger help argument to be returned. return False # Report some useful properties. if verbose: if 'complex-explicit' in atom_indices: phase = 'complex-explicit' else: phase = 'complex-implicit' print " TOTAL ATOMS : %9d" % len(atom_indices[phase]['complex']) print " receptor : %9d" % len(atom_indices[phase]['receptor']) print " ligand : %9d" % len(atom_indices[phase]['ligand']) if phase == 'complex-explicit': print " solvent and ions : %9d" % len( atom_indices[phase]['solvent']) # Initialize YANK object. yank = Yank(args['--store'], verbose=verbose) # Set options. options = dict() if args['--iterations']: options['number_of_iterations'] = int(args['--iterations']) if args['--online-analysis']: options['online_analysis'] = True if args['--restraints']: yank.restraint_type = args['--restraints'] if args['--randomize-ligand']: options['randomize_ligand'] = True if args['--platform'] != 'None': options['platform'] = openmm.Platform.getPlatformByName( args['--platform']) if args['--minimize']: options['minimize'] = True # Create new simulation. yank.create(phases, systems, positions, atom_indices, thermodynamic_state, options=options) # Report success. return True