def dispatch(args): from yank.yank import Yank # TODO: Fix this awkward import syntax. store_directory = args['--store'] # Set override options. options = dict() # Configure MPI, if requested. mpicomm = None if args['--mpi']: mpicomm = utils.initialize_mpi() logger.info("Initialized MPI on %d processes." % (mpicomm.size)) # Configure logger utils.config_root_logger(args['--verbose'], mpicomm=mpicomm, log_file_path=os.path.join(store_directory, 'run.log')) if args['--iterations']: options['number_of_iterations'] = int(args['--iterations']) if args['--online-analysis']: options['online_analysis'] = True 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 YANK object associated with data storage directory. yank = Yank(store_directory, mpicomm=mpicomm, **options) # Set YANK to resume from the store file. phases = None # By default, resume from all phases found in store_directory if args['--phase']: phases=[args['--phase']] yank.resume(phases=phases) # Run simulation. yank.run() return True
def dispatch(args): utils.config_root_logger(args['--verbose']) if args['extract-trajectory']: return dispatch_extract_trajectory(args) analyze.analyze(args['--store']) return True
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] if __name__ == '__main__': from yank import utils utils.config_root_logger(True, log_file_path='test_LennardJones_pair.log') box_width_nsigma_values = np.array([3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0]) Delta_f_n = list() dDelta_f_n = list() for (n, box_width_nsigma) in enumerate(box_width_nsigma_values): [Delta_f, dDelta_f] = notest_LennardJonesPair(box_width_nsigma=box_width_nsigma) Delta_f_n.append(Delta_f) dDelta_f_n.append(dDelta_f) Delta_f_n = np.array(Delta_f_n) dDelta_f_n = np.array(dDelta_f_n) for (box_width_nsigma, Delta_f, dDelta_f) in zip(box_width_nsigma_values, Delta_f_n, dDelta_f_n): print "%8.3f %12.6f %12.6f" % (box_width_nsigma, Delta_f, dDelta_f)
if not os.path.exists(workdir): os.makedirs(workdir) logger.info("Creating path %s" % workdir) # Create directory to store files in. outdir = os.path.join(os.getcwd(), store_dir) if not os.path.exists(outdir): os.makedirs(outdir) logger.info("Creating path %s" % outdir) # ============================================================================== # CONFIGURE LOGGER # ============================================================================== from yank import utils utils.config_root_logger(verbose, log_file_path=os.path.join(setup_dir, 'prepare.log')) # ============================================================================== # PREPARE STRUCTURE # ============================================================================== from pdbfixer import PDBFixer is_periodic = (nonbonded_method not in [app.NoCutoff, app.CutoffNonPeriodic]) # ============================================================================== # Retrieve the PDB file # ============================================================================== if pdb_filename: logger.info("Retrieving PDB '%s'..." % pdb_filename)
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
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"]: [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"]: 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 ) yank.options.cli = options # Parse YAML configuration file and create YankOptions object if args["--yaml"]: yank.options.yaml = YamlBuilder(args["--yaml"]).options # Create new simulation. yank.create(phases, systems, positions, atom_indices, thermodynamic_state) # Report success. return True
# 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] if __name__ == '__main__': from yank import utils utils.config_root_logger(True, log_file_path='test_LennardJones_pair.log') box_width_nsigma_values = np.array( [3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0]) Delta_f_n = list() dDelta_f_n = list() for (n, box_width_nsigma) in enumerate(box_width_nsigma_values): [Delta_f, dDelta_f] = notest_LennardJonesPair(box_width_nsigma=box_width_nsigma) Delta_f_n.append(Delta_f) dDelta_f_n.append(dDelta_f) Delta_f_n = np.array(Delta_f_n) dDelta_f_n = np.array(dDelta_f_n) for (box_width_nsigma, Delta_f, dDelta_f) in zip(box_width_nsigma_values, Delta_f_n, dDelta_f_n):
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 dispatch(args): from yank import analyze utils.config_root_logger(args['--verbose']) success = analyze.print_status(args['--store']) return success
def dispatch(args): from yank import analyze utils.config_root_logger(args['--verbose']) analyze.analyze(args['--store']) return True
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']: [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'])) # 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(phases, systems, positions, atom_indices, thermodynamic_state) # 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'] 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 run_replica_exchange(topology,system,positions,temperature_list=None,simulation_time_step=None,total_simulation_time=1.0 * unit.picosecond,output_data='output.nc',print_frequency=100,verbose_simulation=False,exchange_attempts=None,test_time_step=False,output_directory=None): """ Run a Yank replica exchange simulation using an OpenMM coarse grained model. :param topology: OpenMM Topology :type topology: `Topology() <https://simtk.org/api_docs/openmm/api4_1/python/classsimtk_1_1openmm_1_1app_1_1topology_1_1Topology.html>`_ :param system: OpenMM System() :type system: `System() <https://simtk.org/api_docs/openmm/api4_1/python/classsimtk_1_1openmm_1_1openmm_1_1System.html>`_ :param positions: Positions array for the model we would like to test :type positions: `Quantity() <http://docs.openmm.org/development/api-python/generated/simtk.unit.quantity.Quantity.html>`_ ( np.array( [cgmodel.num_beads,3] ), simtk.unit ) :param temperature_list: List of temperatures for which to perform replica exchange simulations, default = None :type temperature: List( float * simtk.unit.temperature ) :param simulation_time_step: Simulation integration time step :type simulation_time_step: `SIMTK <https://simtk.org/>`_ `Unit() <http://docs.openmm.org/7.1.0/api-python/generated/simtk.unit.unit.Unit.html>`_ :param total_simulation_time: Total run time for individual simulations :type total_simulation_time: `SIMTK <https://simtk.org/>`_ `Unit() <http://docs.openmm.org/7.1.0/api-python/generated/simtk.unit.unit.Unit.html>`_ :param output_data: Name of NETCDF file where we will write simulation data :type output_data: string :param print_frequency: Number of simulation steps to skip when writing to output, Default = 100 :type print_frequence: int :param verbose_simulation: Determines how much output is printed during a simulation run. Default = False :type verbose_simulation: Logical :param exchange_attempts: Number of exchange attempts to make during a replica exchange simulation run, Default = None :type exchange_attempts: int :param test_time_step: Logical variable determining if a test of the time step will be performed, Default = False :type test_time_step: Logical :param output_directory: Path to which we will write the output from simulation runs. :type output_directory: str :returns: - replica_energies ( `Quantity() <http://docs.openmm.org/development/api-python/generated/simtk.unit.quantity.Quantity.html>`_ ( np.float( [number_replicas,number_simulation_steps] ), simtk.unit ) ) - The potential energies for all replicas at all (printed) time steps - replica_positions ( `Quantity() <http://docs.openmm.org/development/api-python/generated/simtk.unit.quantity.Quantity.html>`_ ( np.float( [number_replicas,number_simulation_steps,cgmodel.num_beads,3] ), simtk.unit ) ) - The positions for all replicas at all (printed) time steps - replica_state_indices ( np.int64( [number_replicas,number_simulation_steps] ), simtk.unit ) - The thermodynamic state assignments for all replicas at all (printed) time steps :Example: >>> from foldamers.cg_model.cgmodel import CGModel >>> from cg_openmm.simulation.rep_exch import * >>> cgmodel = CGModel() >>> replica_energies,replica_positions,replica_state_indices = run_replica_exchange(cgmodel.topology,cgmodel.system,cgmodel.positions) """ if simulation_time_step == None: simulation_time_step,force_threshold = get_simulation_time_step(topology,system,positions,temperature_list[-1],total_simulation_time) simulation_steps = int(round(total_simulation_time.__div__(simulation_time_step))) if exchange_attempts == None: if simulation_steps > 10000: exchange_attempts = round(simulation_steps/1000) else: exchange_attempts = 10 if temperature_list == None: temperature_list = [(300.0 * unit.kelvin).__add__(i * unit.kelvin) for i in range(-50,50,10)] num_replicas = len(temperature_list) sampler_states = list() thermodynamic_states = list() # Define thermodynamic states. box_vectors = system.getDefaultPeriodicBoxVectors() for temperature in temperature_list: thermodynamic_state = mmtools.states.ThermodynamicState(system=system, temperature=temperature) thermodynamic_states.append(thermodynamic_state) sampler_states.append(mmtools.states.SamplerState(positions,box_vectors=box_vectors)) # Create and configure simulation object. move = mmtools.mcmc.LangevinDynamicsMove(timestep=simulation_time_step,collision_rate=5.0/unit.picosecond,n_steps=exchange_attempts, reassign_velocities=True) simulation = ReplicaExchangeSampler(mcmc_moves=move, number_of_iterations=exchange_attempts) if os.path.exists(output_data): os.remove(output_data) reporter = MultiStateReporter(output_data, checkpoint_interval=1) simulation.create(thermodynamic_states, sampler_states, reporter) config_root_logger(verbose_simulation) if not test_time_step: num_attempts = 0 while num_attempts < 5: try: simulation.run() #print("Replica exchange simulations succeeded with a time step of: "+str(simulation_time_step)) break except: num_attempts = num_attempts + 1 if num_attempts >= 5: print("Replica exchange simulation attempts failed, try verifying your model/simulation settings.") exit() else: simulation_time_step,force_threshold = get_simulation_time_step(topology,system,positions,temperature_list[-1],total_simulation_time) print("The suggested time step for a simulation with this model is: "+str(simulation_time_step)) while simulation_time_step.__div__(2.0) > 0.001 * unit.femtosecond: try: print("Running replica exchange simulations with Yank...") print("Using a time step of "+str(simulation_time_step)) print("Running each trial simulation for 1000 steps, with 10 exchange attempts.") move = mmtools.mcmc.LangevinDynamicsMove(timestep=simulation_time_step,collision_rate=20.0/unit.picosecond,n_steps=10, reassign_velocities=True) simulation = ReplicaExchangeSampler(replica_mixing_scheme='swap-neighbors',mcmc_moves=move,number_of_iterations=10) reporter = MultiStateReporter(output_data, checkpoint_interval=1) simulation.create(thermodynamic_states, sampler_states, reporter) simulation.run() print("Replica exchange simulations succeeded with a time step of: "+str(simulation_time_step)) break except: del simulation os.remove(output_data) print("Simulation attempt failed with a time step of: "+str(simulation_time_step)) if simulation_time_step.__div__(2.0) > 0.001 * unit.femtosecond: simulation_time_step = simulation_time_step.__div__(2.0) else: print("Error: replica exchange simulation attempt failed with a time step of: "+str(simulation_time_step)) print("Please check the model and simulations settings, and try again.") exit() replica_energies,replica_positions,replica_state_indices = read_replica_exchange_data(system=system,topology=topology,temperature_list=temperature_list,output_data=output_data,print_frequency=print_frequency) steps_per_stage = round(simulation_steps/exchange_attempts) if output_directory != None: plot_replica_exchange_energies(replica_energies,temperature_list,simulation_time_step,steps_per_stage=steps_per_stage,output_directory=output_directory) plot_replica_exchange_summary(replica_state_indices,temperature_list,simulation_time_step,steps_per_stage=steps_per_stage,output_directory=output_directory) else: plot_replica_exchange_energies(replica_energies,temperature_list,simulation_time_step,steps_per_stage=steps_per_stage) plot_replica_exchange_summary(replica_state_indices,temperature_list,simulation_time_step,steps_per_stage=steps_per_stage) return(replica_energies,replica_positions,replica_state_indices)
repex = ReplicaExchange(store_filename='test', nsteps_per_iteration=1e6) assert repex.nsteps_per_iteration == 1000000 assert repex.collision_rate == repex.default_parameters['collision_rate'] @tools.raises(TypeError) def test_unknown_parameters(): """Test ReplicaExchange raises exception on wrong initialization.""" ReplicaExchange(store_filename='test', wrong_parameter=False) #============================================================================================= # MAIN AND TESTS #============================================================================================= if __name__ == "__main__": # Configure logger. utils.config_root_logger(False) # Try MPI, if possible. try: mpicomm = utils.initialize_mpi() if mpicomm.rank == 0: print("MPI initialized successfully.") except Exception as e: print(e) print("Could not start MPI. Using serial code instead.") mpicomm = None # Test simple system of harmonic oscillators. # Disabled until we fix the test # test_hamiltonian_exchange(mpicomm) test_replica_exchange(mpicomm)
print error print "nsigma" print nsigma raise Exception("Dimensionless potential energy difference exceeds MAX_SIGMA of %.1f" % MAX_SIGMA) if verbose: print "PASSED." return #============================================================================================= # MAIN AND TESTS #============================================================================================= if __name__ == "__main__": # Configure logger. from yank import utils utils.config_root_logger(True, log_file_path='debug.log') # Try MPI, if possible. try: from mpi4py import MPI # MPI wrapper hostname = os.uname()[1] mpicomm = MPI.COMM_WORLD if mpicomm.rank == 0: print "MPI initialized successfully." except Exception as e: print e print "Could not start MPI. Using serial code instead." mpicomm = None # Test simple system of harmonic oscillators. test_hamiltonian_exchange(mpicomm)
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 dispatch(args): from yank.yank import Yank # TODO: Fix this awkward import syntax. store_directory = args['--store'] # Set override options. options = dict() # Configure MPI, if requested. mpicomm = None if args['--mpi']: # Initialize MPI. from mpi4py import MPI hostname = os.uname()[1] MPI.COMM_WORLD.barrier() logger.info("Initialized MPI on %d processes." % (MPI.COMM_WORLD.size)) mpicomm = MPI.COMM_WORLD # Configure logger utils.config_root_logger(args['--verbose'], mpicomm=mpicomm, log_file_path=os.path.join(store_directory, 'run.log')) if args['--iterations']: options['number_of_iterations'] = int(args['--iterations']) if args['--online-analysis']: options['online_analysis'] = True 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 YANK object associated with data storage directory. yank = Yank(store_directory, mpicomm=mpicomm, **options) # Set YANK to resume from the store file. phases = None # By default, resume from all phases found in store_directory if args['--phase']: phases=[args['--phase']] yank.resume(phases=phases) # Run simulation. yank.run() return True
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