def test_top_poses(n_poses, expected_energies): """ Checks if data_handler extracts the correct number of top poses and associated metrics. Returns ------- Folder with top poses. """ output_folder = "tmp/top_poses" if os.path.exists(output_folder): shutil.rmtree(output_folder) analysis = Analysis( resname="LIG", chain="Z", simulation_output="../pele_platform/Examples/clustering", skip_initial_structures=False, ) top_poses = analysis.generate_top_poses(output_folder, n_poses) top_poses_rounded = [round(pose, 3) for pose in top_poses] # Check if correct energy values were extracted assert len(top_poses) == n_poses for energy in expected_energies: assert energy in top_poses_rounded # Check if correct number of files was saved results = [ os.path.basename(file) for file in glob.glob(os.path.join(output_folder, "*pdb")) ] assert len(results) == n_poses
def test_clustering_methods(method, bandwidth, n_clusters): """ Checks if built-in clustering methods are producing expected number of clusters. Parameters ---------- method : str Built-in clustering method, e.g. "dbscan". bandwidth : float Bandwidth for meanshift (or epsilon for DBSCAN). n_clusters : int Number of clusters for the Gaussian mixture model. Returns ------- Folder with clusters, plots and report. """ working_folder = "clustering_method" results = os.path.join(working_folder, "*pdb") if os.path.exists(working_folder): shutil.rmtree(working_folder) analysis = Analysis( resname="LIG", chain="Z", simulation_output="../pele_platform/Examples/clustering", skip_initial_structures=False) analysis.generate_clusters(working_folder, method, bandwidth=bandwidth, analysis_nclust=n_clusters) assert len(glob.glob(results)) == n_clusters
def test_empty_reports_handling(): """ Checks if we handle reports with no accepted PELE steps to make sure the returned empty coordinates array doesn't cause any errors. """ simulation_output = os.path.join(test_path, "analysis/data/empty_reports_output") analysis = Analysis( simulation_output=simulation_output, chain="Z", resname="LIG", skip_initial_structures=True, ) analysis.generate(path="empty_reports")
def _analysis(self): # TODO create a list of the libraries defined in the current input.yaml # Retrieve water indices to cluster, if running analysis only if self.parameters.only_analysis: self._extract_working_directory() for path in self.parameters.working_dir: if not os.path.exists(path): if not os.path.exists(self.parameters.folder): raise ce.MissingWorkingDir("Missing working_folder parameter. Please set the " "path of the trajectories using the flag working_" "folder in your input.yaml") self._prepare_parameters() self.parameters.water_ids_to_track = water.water_ids_from_conf(self.parameters.control_file) if self.parameters.args.analysis_to_point: self.parameters.analysis_to_point = self.parameters.args.analysis_to_point ana.main( path=self.parameters.folder, atom_coords=self.parameters.analysis_to_point, pattern=os.path.basename(self.parameters.system), ) for path in self.parameters.working_dir: simulation_output = os.path.join(path, 'sampling_result') analysis_folder = os.path.join(path, "results") analysis = Analysis( resname="GRW", chain=self.parameters.chain, simulation_output=simulation_output, be_column=self.parameters.be_column, limit_column=self.parameters.limit_column, traj=self.parameters.traj_name, report=self.parameters.report_name, skip_initial_structures=not self.parameters.test, kde=self.parameters.kde, kde_structs=self.parameters.kde_structs, topology=self.parameters.topology, cpus=self.parameters.cpus, water_ids_to_track=self.parameters.water_ids_to_track, ) analysis.generate( analysis_folder, clustering_type=self.parameters.clustering_method.lower(), bandwidth=self.parameters.bandwidth, analysis_nclust=self.parameters.analysis_nclust, max_top_clusters=self.parameters.max_top_clusters, top_clusters_criterion=self.parameters.top_clusters_criterion, min_population=self.parameters.min_population, representatives_criterion=self.parameters.cluster_representatives_criterion, )
def _analysis(self): self.parameters.analysis_to_point = \ self.parameters.args.analysis_to_point if self.parameters.analysis_to_point and self.parameters.folder: ana.main(path=self.parameters.folder, atom_coords=self.parameters.analysis_to_point, pattern=os.path.basename(self.parameters.system)) # TODO create a list of the libraries defined in the current input.yaml from pele_platform.analysis import Analysis from glob import glob sim_directories = glob( os.path.splitext(self.parameters.system)[0] + '_processed_*' + '*') for sim_directory in sim_directories: simulation_output = os.path.join(sim_directory, 'sampling_result') # Only proceed if sampling_result folder exists if not os.path.isdir(simulation_output): continue analysis_folder = os.path.join(sim_directory, "results") analysis = Analysis( resname='GRW', chain=self.parameters.chain, simulation_output=simulation_output, be_column=self.parameters.be_column, limit_column=self.parameters.limit_column, traj=self.parameters.traj_name, report=self.parameters.report_name, skip_initial_structures=not self.parameters.test, kde=self.parameters.kde, kde_structs=self.parameters.kde_structs, topology=self.parameters.topology, cpus=self.parameters.cpus) analysis.generate( analysis_folder, clustering_type=self.parameters.clustering_method.lower(), bandwidth=self.parameters.bandwidth, analysis_nclust=self.parameters.analysis_nclust, max_top_clusters=self.parameters.max_top_clusters, top_clusters_criterion=self.parameters.top_clusters_criterion, min_population=self.parameters.min_population, representatives_criterion=self.parameters. cluster_representatives_criterion)
def test_residue_checker(path, traj, top): """ Check, if we catch an error when the resname passed to Analysis doesn't exist in the output trajectories. Parameters ----------- path : str Path to the simulation output folder. traj : str Trajectory type (as the user would set in the YAML), e.g. "trajectory.xtc". top : str Path to topology file. Raises -------- ValueError if the residue name is not found in any of the trajectories. """ simulation_output = os.path.join(test_path, path) topology = os.path.join(test_path, top) if top else None with pytest.raises(ValueError): analysis = Analysis( simulation_output=simulation_output, chain="Z", resname="STR", skip_initial_structures=True, traj=traj, topology=topology, )
def get_analysis(output, topology, traj): """ Calls analysis fixture with the right arguments depending on the trajectory type. Parameters ----------- output : str Path to simulation 'output' folder. topology : str Path to the topology file. traj : str Trajectory type: xtc or pdb. """ traj = traj if traj else "pdb" trajectory = f"trajectory.{traj}" analysis = Analysis( resname="LIG", chain="Z", simulation_output=output, skip_initial_structures=False, topology=topology, water_ids_to_track=[("A", 2109), ("A", 2124)], traj=trajectory, ) return analysis
def test_analysis_api(): """ Runs full analysis workflow (with GMM clustering). Returns ------- Returns a directory with top_poses, clusters and plots. """ working_folder = "full_analysis" output = "../pele_platform/Examples/clustering" n_clusts = 3 analysis = Analysis(resname="LIG", chain="Z", simulation_output=output, skip_initial_structures=False) analysis.generate(working_folder, "gaussianmixture", analysis_nclust=n_clusts) # Check if reports exist assert os.path.exists(os.path.join(working_folder, "data.csv")) assert os.path.exists(os.path.join(working_folder, "summary.pdf")) # Check plots plots = glob.glob(os.path.join(working_folder, "plots", "*png")) assert len(plots) == 2 # Check top poses top_poses = glob.glob(os.path.join(working_folder, "top_poses", "*pdb")) assert len(top_poses) == 7 # Check clusters clusters = glob.glob(os.path.join(working_folder, "clusters", "*pdb")) assert len(clusters) == n_clusts # Check if data.csv exists and is not empty data_csv = os.path.join(working_folder, "data.csv") assert os.path.exists(data_csv) with open(data_csv, "r") as file: lines = file.readlines() assert len(lines) == 8 assert lines[ 0] == "Step,numberOfAcceptedPeleSteps,currentEnergy,Binding Energy,sasaLig,epoch,trajectory,Cluster\n"
def test_frag_API_analysis(yaml_file, traj, topology): """ Runs frag simulation (both XTC and PDB) and checks, if it's possible to run Analysis via API. Parameters ----------- yaml_file : str Base name of the input.yaml file in Examples/frag. traj : str Indicate if running "pdb" or "xtc". topology : str Path to the topology file, if running XTC simulation, otherwise None """ # Run frag simulation yaml_file = os.path.join(test_path, "frag", yaml_file) job = main.run_platform_from_yaml(yaml_file) # Run analysis frag_folder = "1w7h_preparation_structure_2w_processed_frag_aminoC1N1" output = os.path.join(frag_folder, "sampling_result") analysis_output = f"analysis_{traj}" traj = f"trajectory.{traj}" if topology: topology = os.path.join(frag_folder, topology) analysis = Analysis(simulation_output=output, resname="GRW", chain="L", traj=traj, topology=topology) analysis.generate(analysis_output) # Check output assert len(glob.glob(os.path.join(analysis_output, "plots", "*png"))) > 0 assert len( glob.glob(os.path.join(analysis_output, "clusters", "cluster*pdb"))) > 0 shutil.rmtree(frag_folder, ignore_errors=True)
def test_check_existing_directory(generate_folders): """ Checks if tester of existing dir Parameters ---------- generate_folders : pytest.fixture Pytest fixture that generates "results" folders for testing """ new_path = Analysis._check_existing_directory("results") assert new_path == "results_3" folders = glob.glob("results*") check_remove_folder(*folders)
def analysis(): """ Creates Analysis object to use in other tests. Returns ------- Analysis object. """ output = "../pele_platform/Examples/clustering" analysis = Analysis(resname="LIG", chain="Z", simulation_output=output, skip_initial_structures=False) return analysis
def run_adaptive(args: YamlParser): """ Main function to prepare and launch the simulation. 1) Create Parameters - variables, folders, logger... 2) Prepare ligand and receptor 3) Launch simulation 4) Analyse simulation """ builder = ParametersBuilder() parameters = builder.build_adaptive_variables(args) parameters.create_files_and_folders() shutil.copy(args.yamlfile, parameters.pele_dir) missing_residues = [] if parameters.adaptive_restart and not parameters.only_analysis: with helpers.cd(parameters.pele_dir): adaptiveSampling.main(parameters.ad_ex_temp) parameters.logger.info("Simulation run successfully (:\n\n") args.adaptive_restart = False elif not parameters.only_analysis and not parameters.restart: parameters.logger.info( "System: {}; Platform Functionality: {}\n\n".format( parameters.residue, parameters.software)) pdb_checker.PDBChecker(parameters.system).check_negative_residues() # Create inputs directory if not os.path.exists(parameters.inputs_dir): os.mkdir(parameters.inputs_dir) if parameters.perturbation: syst = sp.SystemBuilder.build_system( parameters.system, args.mae_lig, args.residue, parameters.pele_dir, inputs_dir=parameters.inputs_dir) else: syst = sp.SystemBuilder(parameters.system, None, None, parameters.pele_dir, inputs_dir=parameters.inputs_dir) parameters.logger.info("Prepare complex {}".format(syst.system)) # If user overrides 'system' with 'input' if parameters.input: parameters.inputs_simulation = [] for input in parameters.input: input_path = os.path.join(parameters.inputs_dir, os.path.basename(input)) shutil.copy(input, input_path) if parameters.no_ppp: input_proc = input_path else: input_proc, missing_residues, _, _, _ = ppp.main( input_path, parameters. inputs_dir, # to ensure it goes to pele_dir/inputs, not pele_dir output_pdb=[ "", ], charge_terminals=args.charge_ter, no_gaps_ter=args.gaps_ter, constrain_smiles=None, ligand_pdb=parameters.ligand_ref) input_proc = os.path.basename(input_proc) input_proc = os.path.join(parameters.inputs_dir, input_proc) parameters.inputs_simulation.append(input_proc) parameters.adap_ex_input = ", ".join([ '"' + input + '"' for input in parameters.inputs_simulation ]).strip('"') # If randomization in necessary (PPI, site_finder, global exploration)... elif args.full or args.randomize or args.ppi or args.site_finder: ligand_positions, box_radius, box_center = rd.randomize_starting_position( parameters, args.box_center, args.box_radius) if parameters.no_ppp: receptor = syst.system else: receptor, missing_residues, _, _, _ = ppp.main( syst.system, parameters. inputs_dir, # to ensure it goes to pele_dir/input, not pele_dir output_pdb=[ "", ], charge_terminals=args.charge_ter, no_gaps_ter=args.gaps_ter, constrain_smiles=None, ligand_pdb=parameters.ligand_ref) inputs = rd.join(receptor, ligand_positions, parameters.residue, output_folder=parameters.inputs_dir) parameters.input = [ os.path.join(parameters.inputs_dir, inp) for inp in inputs ] if args.gpcr_orth or args.out_in: randomization_box_radius, randomization_box_center = rd.set_box( args.final_site if args.final_site else args.orthosteric_site, ligand_positions, parameters.system) if not args.box_center: parameters.box_center = randomization_box_center if not args.box_radius: parameters.box_radius = randomization_box_radius else: parameters.box_center = box_center parameters.box_radius = box_radius parameters.adap_ex_input = ", ".join( ['"' + input + '"' for input in parameters.input]).strip('"') hp.silentremove(ligand_positions) # Prepare System if parameters.no_ppp or parameters.input: # No need to run system through PPP, if we already preprocessed # parameters.input if parameters.input: # If we have more than one input for input in parameters.input: try: shutil.copy(input, parameters.inputs_dir) except shutil.SameFileError: # systems that go through randomization are already moved pass else: shutil.copy(parameters.system, parameters.inputs_dir) else: parameters.nonstandard.extend(hp.find_nonstd_residue(syst.system)) parameters.system, missing_residues, _, _, _ = ppp.main( syst.system, parameters.inputs_dir, output_pdb=[ "", ], charge_terminals=args.charge_ter, no_gaps_ter=args.gaps_ter, mid_chain_nonstd_residue=parameters.nonstandard, skip=parameters.skip_prep, back_constr=parameters.ca_constr, constrain_smiles=None, ligand_pdb=parameters.ligand_ref, ca_interval=parameters.ca_interval) parameters.constraints = alpha_constraints.retrieve_constraints( parameters.system, interval=parameters.ca_interval, back_constr=parameters.ca_constr, ter_constr=parameters.terminal_constr) # Metal constraints if not args.no_metal_constraints: metal_constraints, parameters.external_constraints = mc.main( args.external_constraints, os.path.join( parameters.inputs_dir, parameters.adap_ex_input.split(",")[0].strip().strip('"')), syst.system, permissive=parameters.permissive_metal_constr, all_metals=args.constrain_all_metals, external=parameters.external_constraints, logger=parameters.logger) parameters.external_constraints = hp.retrieve_constraints_for_pele( parameters.external_constraints, parameters.system) metal_constraints_json = hp.retrieve_constraints_for_pele( metal_constraints, os.path.join( parameters.inputs_dir, parameters.adap_ex_input.split(",")[0].strip().strip('"'))) parameters.external_constraints.extend(metal_constraints_json) else: parameters.external_constraints = hp.retrieve_constraints_for_pele( parameters.external_constraints, parameters.system) # Keep JSON ordered by having first title and then constraints if parameters.external_constraints: parameters.constraints = (parameters.constraints[0:1] + parameters.external_constraints + parameters.constraints[1:]) if parameters.remove_constraints: parameters.constraints = "" parameters.logger.info(f"Complex {parameters.system} prepared\n\n") # Ligand/metal and solvent parameters if (parameters.perturbation or parameters.sidechain_perturbation) and parameters.use_peleffy: ligand_parametrizer = parametrizer.Parametrizer.from_parameters( parameters) ligand_parametrizer.parametrize_ligands_from( pdb_file=syst.system, ppp_file=parameters.system) elif (parameters.perturbation or parameters.sidechain_perturbation ) and not parameters.use_peleffy: # Parametrize the ligand ligand_params = lg.LigandParametrization(parameters) ligand_params.generate() # Parametrize missing residues identified by PPP for res, __, _ in missing_residues: if res != args.residue and res not in parameters.skip_ligand_prep: parameters.logger.info( "Creating template for residue {}".format(res)) with hp.cd(parameters.pele_dir): mr.create_template(parameters, res) parameters.logger.info( "Template {}z created\n\n".format(res)) # Covalent residue parametrization should not run in refinement simulation if parameters.covalent_residue and os.path.basename( parameters.pele_dir) != "2_refinement": parametrizer.parametrize_covalent_residue( parameters.pele_data, parameters.pele_dir, parameters.gridres, parameters.residue_type, parameters.residue, ppp_system=parameters.system) if parameters.ligand_conformations: ligand_conformations.LigandConformations( path=parameters.ligand_conformations, system=parameters.system, resname=parameters.residue, forcefield=parameters.forcefield, pele_dir=parameters.pele_dir).generate() # Create simulation box, if performing perturbation if parameters.perturbation and parameters.box: box = bx.BoxSetter(parameters.box_center, parameters.box_radius, parameters.ligand_ref, parameters.logger) parameters.box = box.generate_json() else: parameters.box = "" # Solvent parameters solvent = sv.ImplicitSolvent( parameters.solvent, parameters.obc_tmp, parameters.template_folder, parameters.obc_file, parameters.logger, ) solvent.generate() # Build PCA if parameters.pca_traj: pca_obj = pca.PCA(parameters.pca_traj, parameters.pele_dir) parameters.pca = pca_obj.generate(parameters.logger) # Core constraints based on SMILES string if parameters.constrain_core: smiles_input_pdb = os.path.join( parameters.inputs_dir, parameters.adap_ex_input.split(",")[0]) smiles = smiles_constraints.SmilesConstraints( smiles_input_pdb, parameters.constrain_core, parameters.residue, parameters.chain, parameters.constrain_core_spring) smi_constraint = smiles.run() parameters.constraints = (parameters.constraints[0:1] + smi_constraint + parameters.constraints[1:]) # Waters input_waters = [ input.strip().strip('"') for input in parameters.adap_ex_input.split(",") ] input_waters = [ os.path.join(parameters.inputs_dir, inp) for inp in input_waters ] water_obj = wt.WaterIncluder( input_waters, parameters.n_waters, user_waters=parameters.waters, ligand_perturbation_params=parameters.parameters, water_center=args.water_center, water_radius=parameters.water_radius, allow_empty_selectors=parameters.allow_empty_selectors, water_temp=parameters.water_temp, water_trials=parameters.water_trials, water_overlap=parameters.water_overlap, water_constr=parameters.water_constr, test=parameters.test, water_freq=parameters.water_freq, ligand_residue=parameters.residue) water_obj.run() parameters.parameters = water_obj.ligand_perturbation_params parameters.water_ids_to_track = water_obj.water_ids_to_track # Check if atoms need mapping due to preprocessing args = AtomMapper(args, parameters, syst.system).run() # Metrics builder - builds JSON strings for PELE to be able to # track atom distances, RMSD, etc. metrics = mt.MetricBuilder() parameters.metrics = (metrics.distance_to_atom_json( os.path.join( parameters.inputs_dir, parameters.adap_ex_input.split(",")[0].strip().strip('"'), ), args.atom_dist, ) if args.atom_dist else "") parameters.native = (metrics.rmsd_to_json( args.native, parameters.chain) if args.native else "") parameters.local_nonbonding_energy = metrics.local_nonbonding_energy_json( parameters.covalent_residue, parameters.nonbonding_radius) # metal polarisation if parameters.polarize_metals: mp.change_metal_charges( parameters.template_folder, parameters.forcefield, parameters.polarization_factor, parameters.system, ) # Predict cluster values in a short equilibration if parameters.cluster_conditions == "auto": preequilibration = PreEquilibrator(args, parameters) parameters.cluster_conditions = preequilibration.run() # Point adaptive.conf to input dir parameters.adap_ex_input = os.path.join(parameters.inputs_dir, parameters.adap_ex_input) # Fill in simulation templates adaptive = ad.SimulationBuilder(parameters.ad_ex_temp, parameters.pele_exit_temp, parameters.topology) adaptive.generate_inputs(parameters, water_obj) # Run simulation only if we are not in debug mode if not parameters.debug: parameters.logger.info("Running Simulation") adaptive.run() parameters.logger.info("Simulation run successfully (:\n\n") elif parameters.restart and not parameters.only_analysis: # Start simulation from scratch (unlike adaptive_restart) but use files created in debug mode parameters.logger.info( f"Launching simulation from {parameters.pele_dir}") adaptive = ad.SimulationBuilder(parameters.ad_ex_temp, parameters.pele_exit_temp, parameters.topology) adaptive.run() parameters.logger.info("Simulation run successfully (:\n\n") # Run analysis if parameters.analyse and not parameters.debug: from pele_platform.analysis import Analysis # Retrieve water IDs to track from existing pele.conf, if running analysis only if parameters.only_analysis: parameters.water_ids_to_track = wt.water_ids_from_conf( parameters.pele_temp) analysis_folder = os.path.join(parameters.pele_dir, "results") analysis = Analysis.from_parameters(parameters) analysis.generate( analysis_folder, clustering_type=parameters.clustering_method.lower(), bandwidth=parameters.bandwidth, analysis_nclust=parameters.analysis_nclust, max_top_clusters=parameters.max_top_clusters, min_population=parameters.min_population, max_top_poses=parameters.max_top_poses, top_clusters_criterion=parameters.top_clusters_criterion, representatives_criterion=parameters. cluster_representatives_criterion) return parameters
def run_adaptive(args): """ Main function to prepare and launch the simulation. 1) Create EnviroBuilder - variables, folders, logger... 2) Prepare ligand and receptor 3) Launch simulation 4) Analyse simulation """ builder = ParametersBuilder() parameters = builder.build_adaptive_variables(args) parameters.create_files_and_folders() shutil.copy(args.yamlfile, parameters.pele_dir) if parameters.adaptive_restart and not parameters.only_analysis: with helpers.cd(parameters.pele_dir): adaptiveSampling.main(parameters.ad_ex_temp) parameters.logger.info("Simulation run successfully (:\n\n") elif not parameters.only_analysis: parameters.logger.info( "System: {}; Platform Functionality: {}\n\n".format( parameters.residue, parameters.software)) # Create inputs directory if not os.path.exists(parameters.inputs_dir): os.mkdir(parameters.inputs_dir) if parameters.perturbation: syst = sp.SystemBuilder.build_system( parameters.system, args.mae_lig, args.residue, parameters.pele_dir, inputs_dir=parameters.inputs_dir, ) else: syst = sp.SystemBuilder( parameters.system, None, None, parameters.pele_dir, inputs_dir=parameters.inputs_dir, ) parameters.logger.info("Prepare complex {}".format(syst.system)) # If user overrides 'system' with 'input' if parameters.input: parameters.inputs_simulation = [] for input in parameters.input: input_path = os.path.join(parameters.inputs_dir, os.path.basename(input)) shutil.copy(input, input_path) if parameters.no_ppp: input_proc = input_path else: input_proc = os.path.basename( ppp.main( input_path, parameters. inputs_dir, # to ensure it goes to pele_dir/inputs, not pele_dir output_pdb=[ "", ], charge_terminals=args.charge_ter, no_gaps_ter=args.gaps_ter, constrain_smiles=None, ligand_pdb=parameters.ligand_ref, )[0]) input_proc = os.path.join(parameters.inputs_dir, input_proc) parameters.inputs_simulation.append(input_proc) parameters.adap_ex_input = ", ".join([ '"' + input + '"' for input in parameters.inputs_simulation ]).strip('"') # If randomization in necessary (PPI, site_finder, global exploration)... elif args.full or args.randomize or args.ppi: ligand_positions, box_radius, box_center = rd.randomize_starting_position( parameters.ligand_ref, parameters.receptor, outputfolder=parameters.inputs_dir, nposes=parameters.poses, test=parameters.test, user_center=parameters.center_of_interface, logger=parameters.logger, ) if not args.gpcr_orth: parameters.box_center = box_center parameters.box_radius = box_radius if parameters.no_ppp: receptor = syst.system else: receptor = ppp.main( syst.system, parameters. inputs_dir, # to ensure it goes to pele_dir/input, not pele_dir output_pdb=[ "", ], charge_terminals=args.charge_ter, no_gaps_ter=args.gaps_ter, constrain_smiles=None, ligand_pdb=parameters.ligand_ref, )[0] inputs = rd.join( receptor, ligand_positions, parameters.residue, output_folder=parameters.inputs_dir, ) inputs = [ os.path.join(parameters.inputs_dir, inp) for inp in inputs ] parameters.adap_ex_input = ", ".join( ['"' + input + '"' for input in inputs]).strip('"') hp.silentremove(ligand_positions) # Prepare System if ( parameters.no_ppp or parameters.input ): # No need to run system through PPP, if we already preprocessed parameters.input missing_residues = [] if parameters.input: # If we have more than one input for input in parameters.input: shutil.copy(input, parameters.inputs_dir) else: shutil.copy(parameters.system, parameters.inputs_dir) else: parameters.nonstandard.extend(hp.find_nonstd_residue(syst.system)) parameters.system, missing_residues, _, _, _ = ppp.main( syst.system, parameters.inputs_dir, output_pdb=[ "", ], charge_terminals=args.charge_ter, no_gaps_ter=args.gaps_ter, mid_chain_nonstd_residue=parameters.nonstandard, skip=parameters.skip_prep, back_constr=parameters.ca_constr, constrain_smiles=None, ligand_pdb=parameters.ligand_ref, ca_interval=parameters.ca_interval, ) parameters.constraints = alpha_constraints.retrieve_constraints( parameters.system, interval=parameters.ca_interval, back_constr=parameters.ca_constr, ter_constr=parameters.terminal_constr, ) # Metal constraints if not args.no_metal_constraints: metal_constraints, parameters.external_constraints = mc.main( args.external_constraints, os.path.join( parameters.inputs_dir, parameters.adap_ex_input.split(",")[0].strip().strip('"'), ), syst.system, permissive=parameters.permissive_metal_constr, all_metals=args.constrain_all_metals, external=parameters.external_constraints, logger=parameters.logger, ) parameters.external_constraints = hp.retrieve_constraints_for_pele( parameters.external_constraints, parameters.system) metal_constraints_json = hp.retrieve_constraints_for_pele( metal_constraints, os.path.join( parameters.inputs_dir, parameters.adap_ex_input.split(",")[0].strip().strip('"'), ), ) parameters.external_constraints.extend(metal_constraints_json) else: parameters.external_constraints = hp.retrieve_constraints_for_pele( parameters.external_constraints, parameters.system) # Keep JSON ordered by having first title and then constraints if parameters.external_constraints: parameters.constraints = (parameters.constraints[0:1] + parameters.external_constraints + parameters.constraints[1:]) if parameters.remove_constraints: parameters.constraints = "" parameters.logger.info("Complex {} prepared\n\n".format( parameters.system)) # Ligand parameters and simulation box if parameters.perturbation: ligand_params = lg.LigandParametrization(parameters) ligand_params.generate() box = bx.BoxSetter( parameters.box_center, parameters.box_radius, parameters.ligand_ref, parameters.logger, ) parameters.box = box.generate_json() else: parameters.box = "" # Parametrize missing residues for res, __, _ in missing_residues: if res != args.residue and res not in parameters.skip_ligand_prep: parameters.logger.info( "Creating template for residue {}".format(res)) with hp.cd(parameters.pele_dir): mr.create_template(parameters, res) parameters.logger.info("Template {}z created\n\n".format(res)) # Solvent parameters solvent = sv.ImplicitSolvent( parameters.solvent, parameters.obc_tmp, parameters.template_folder, parameters.obc_file, parameters.logger, ) solvent.generate() # Build PCA if parameters.pca_traj: pca_obj = pca.PCA(parameters.pca_traj, parameters.pele_dir) parameters.pca = pca_obj.generate(parameters.logger) # Core constraints based on SMILES string if parameters.constrain_core: smiles_input_pdb = os.path.join( parameters.inputs_dir, parameters.adap_ex_input.split(",")[0]) smiles = smiles_constraints.SmilesConstraints( smiles_input_pdb, parameters.constrain_core, parameters.residue, parameters.chain, parameters.constrain_core_spring, ) smi_constraint = smiles.run() parameters.constraints = (parameters.constraints[0:1] + smi_constraint + parameters.constraints[1:]) # Waters input_waters = [ input.strip().strip('"') for input in parameters.adap_ex_input.split(",") ] input_waters = [ os.path.join(parameters.inputs_dir, inp) for inp in input_waters ] water_obj = wt.WaterIncluder( input_waters, parameters.n_waters, user_waters=parameters.waters, ligand_perturbation_params=parameters.parameters, water_center=args.water_center, water_radius=parameters.water_radius, allow_empty_selectors=parameters.allow_empty_selectors, water_temp=parameters.water_temp, water_trials=parameters.water_trials, water_overlap=parameters.water_overlap, water_constr=parameters.water_constr, test=parameters.test, water_freq=parameters.water_freq, ligand_residue=parameters.residue, ) water_obj.run() parameters.parameters = water_obj.ligand_perturbation_params # Check if atoms need mapping due to preprocessing args = AtomMapper(args, parameters, syst.system).run() # Metrics builder - builds JSON strings for PELE to be able to track atom distances, RMSD, etc. metrics = mt.MetricBuilder() parameters.metrics = (metrics.distance_to_atom_json( os.path.join( parameters.inputs_dir, parameters.adap_ex_input.split(",")[0].strip().strip('"'), ), args.atom_dist, ) if args.atom_dist else "") parameters.native = (metrics.rsmd_to_json( args.native, parameters.chain) if args.native else "") # interaction restrictions # TODO this is not the place to initialize parameters for the interaction restrictions if args.interaction_restrictions: interaction_restrictions = ir.InteractionRestrictionsBuilder() interaction_restrictions.parse_interaction_restrictions( parameters.system, args.interaction_restrictions) parameters.met_interaction_restrictions = ( interaction_restrictions.metrics_to_json()) parameters.interaction_restrictions = ( interaction_restrictions.conditions_to_json()) else: parameters.met_interaction_restrictions = "" parameters.interaction_restrictions = "" # metal polarisation if parameters.polarize_metals: mp.change_metal_charges( parameters.template_folder, parameters.forcefield, parameters.polarization_factor, parameters.system, ) # Point adaptive.conf to input dir parameters.adap_ex_input = os.path.join(parameters.inputs_dir, parameters.adap_ex_input) # Fill in simulation templates adaptive = ad.SimulationBuilder(parameters.ad_ex_temp, parameters.pele_exit_temp, parameters.topology) adaptive.generate_inputs(parameters, water_obj) # Run simulation only if we are not in debug mode if not parameters.debug: parameters.logger.info("Running Simulation") adaptive.run() parameters.logger.info("Simulation run successfully (:\n\n") # Run analysis if parameters.analyse and not parameters.debug: from pele_platform.analysis import Analysis analysis_folder = os.path.join(parameters.pele_dir, "results") analysis = Analysis.from_parameters(parameters) analysis.generate(analysis_folder, clustering_type=parameters.clustering_method.lower(), bandwidth=parameters.bandwidth, analysis_nclust=parameters.analysis_nclust, max_top_clusters=parameters.max_top_clusters, min_population=parameters.min_population) return parameters