Source code for schrodinger.application.phase.packages.hypo_refine.project_utils

"""
Module with phase_hypo_refine project-related functionality.

Copyright Schrodinger LLC, All Rights Reserved.
"""

import csv
import os
import tempfile
import zipfile

from schrodinger.application.phase.packages import conformer_reader
from schrodinger.application.phase.packages import phase_utils
from schrodinger.infra import phase
from schrodinger.utils import fileutils


[docs]def create_project(infile, fd, conf_options, dest_dir=None): """ Creates a multi-conformer zipped Phase project from a Maestro/SD file. :param infile: Input Maestro/SD file :type infile: str :param fd: Feature definitions :type fd: list of phase.PhpFeatureDefinition :param conf_options: Conformer generation options :type conf_options: phase.PhpConfOptions :param dest_dir: Directory in which to create the project (default: cwd). :type dest_dir: str :return: Zipped project name including any leading path :rtype: str """ project_path = derive_project_name(infile) job_base = fileutils.get_basename(project_path) job_name = job_base + "_new_project" fd_file = job_name + ".def" if dest_dir: project_path = os.path.join(dest_dir, project_path) fd_file = os.path.join(dest_dir, fd_file) project = phase.PhpProject() project.saveFeatureDefToFile(fd, fd_file) read_mode = phase.FILE_SINGLE_CONF title_prop = "" act_prop = "" save = False hypo_fmt = "single" energy_prop = "" project.newProject(project_path, infile, fd_file, read_mode, title_prop, act_prop, job_name, save, hypo_fmt, energy_prop) fileutils.force_remove(fd_file) job_name = job_base + "_generate_confs" project.generateConfs(conf_options, job_name, save) project.closeProject() return zip_project(project_path, dest_dir)
[docs]def create_projects(args, dest_dir=None): """ Creates any required zipped projects from Maestro/SD files in args. No action is taken for an argument which already corresponds to a zipped project. args.actives and args.decoys are replaced with the zipped project names if zipped projects are created. If args.valid is set, the actives2 and/or decoys2 values are similarly replaced. :param args: argparser.Namespace with command line arguments :type args: argparser.Namespace :param dest_dir: Directory in which to create projects (default: cwd). :type dest_dir: str """ hypo = phase.PhpHypoAdaptor(args.hypo) fd = hypo.getFd() conf_options = conformer_reader.get_confgen_options(args) zipped_projects = {} for key, infile in get_screen_dict(args).items(): if phase_utils.is_phase_project_path(infile, zipped=True): zipped_projects[key] = infile else: zipped_projects[key] = create_project(infile, fd, conf_options, dest_dir) args.actives = zipped_projects["actives"] args.decoys = zipped_projects["decoys"] if args.valid: args.valid = "\"{}\",\"{}\"".format(zipped_projects["actives2"], zipped_projects["decoys2"])
[docs]def derive_project_name(file_path, zipped=False): """ Determines the name of the Phase project to associate with the supplied Maestro file, SD file, or zipped project name. For example, if file_path is "/home/jsmith/actives.maegz", the returned value would be "actives.phprj". If zipped is True, the returned value would be "actives.phzip". :param file_path: Name of Maestro/SD file or zipped project :type file_path: str :return: Project name derived from file_path :rtype: str """ project_base = fileutils.get_basename(file_path) if zipped: return project_base + phase.PHASE_ZPRJ_FILE_EXT return project_base + phase.PHASE_PRJ_FILE_EXT
[docs]def get_ligand_titles(zipped_project, unique=False): """ Extracts ligand titles from a zipped project. If unique is True, only unique titles will be returned. :param zipped_project: Name of zipped project :type zipped_project: str :param unique: Whether to return only unique titles :type unique: bool :return: Ligand titles :rtype: list(str) """ titles = [] summary_file = phase_utils.get_internal_zip_path( phase.PHASE_PROJECT_LIGANDS_DB, phase.PHASE_DATABASE_SUMMARY) summary_zip, summary_disk = get_project_file_names(zipped_project, summary_file) with tempfile.TemporaryDirectory() as tmpdir_name: with zipfile.ZipFile(zipped_project, 'r') as zfile: zfile.extract(summary_zip, tmpdir_name) summary_tmpdir = os.path.join(tmpdir_name, summary_disk) with open(summary_tmpdir, 'r') as csv_fh: reader = csv.DictReader(csv_fh) for row in reader: titles.append(row['title']) if unique: # Make titles unique, but preserve original order title_dict = {} for title in titles: title_dict[title] = "" titles = list(title_dict.keys()) return titles
[docs]def get_project_file_names(project_path, file_name): """ Returns the appropriate file name to use, zip_file_path, to extract the indicated file from the provided zipped Phase project, and the file name to use, disk_file_path, to access the extracted file on disk. Use forward slashes in file_name if it's located in a subdirectory of the project, e.g., hypotheses/AADRR_1.phypo. The returned zip_file_path always contains forward slashes, whereas disk_file_path contains the appropriate platform-dependent separators. :param project_path: Path to zipped project :type project_path: str :param file_name: Name of file in archive :type file_name: str :return: tuple of zip_file_path, disk_file_path :rtype: str, str """ project_dir = derive_project_name(project_path) zip_file_path = phase_utils.get_internal_zip_path(project_dir, file_name) disk_file_path = os.path.join(project_dir, *(file_name.split("/"))) return zip_file_path, disk_file_path
[docs]def get_screen_dict(args): """ Creates a dictionary from the active/decoy files to screen: "actives" --> args.actives "decoys" --> args.decoys "actives2" --> actives2 file extracted from args.valid, if provided "decoys2" --> decoys2 file extracted from args.valid, if provided :param args: Command line arguments :type args: argparse.Namespace :return: Dictionary of active/decoy files keyed as described above :rtype: dict of str:str """ screen_dict = {"actives": args.actives, "decoys": args.decoys} if args.valid: tokens = next(csv.reader([args.valid])) screen_dict["actives2"] = phase_utils.get_proper_path(tokens[0]) screen_dict["decoys2"] = phase_utils.get_proper_path(tokens[1]) return screen_dict
[docs]def zip_project(project_path, dest_dir=None): """ Zips a Phase project, removes the project directory, and returns the name of the zipped project. :param project_path: Path to project (.phprj) :type project_path: str :param dest_dir: Destination directory for zipped project (default: cwd). :type dest_dir: str :return: Zipped project name (.phzip) including any leading path :rtype: str """ zipped_project = os.path.basename( fileutils.splitext(project_path)[0]) + phase.PHASE_ZPRJ_FILE_EXT zip_dir = "." if dest_dir: zip_dir = dest_dir zipped_project = os.path.join(zip_dir, zipped_project) project = phase.PhpProject() project.zipProject(zip_dir, project_path) fileutils.force_rmtree(project_path) return zipped_project