Source code for schrodinger.application.phase.pt_hypothesis

"""
Module for manipulating hypothesis entries in the project table.
"""

import os

import schrodinger
from schrodinger import project
from schrodinger.application.phase import constants
from schrodinger.application.phase import hypothesis
from schrodinger.infra import mm
from schrodinger.infra import mmproj
from schrodinger.infra import phase
from schrodinger.Qt import QtCore
from schrodinger.structure import Structure
from schrodinger.utils import log

# Logging
logger = log.get_output_logger(__file__)

# Constants
HYP_DATA_FILENAME = "hypothesis.hyp"

maestro = schrodinger.get_maestro()

hypo_monitor = None


[docs]class PhaseHypothesisMonitor(QtCore.QObject): """ This class provides signals that are emitted when hypothesis is changed. These signals should be emitted with the hypothesis entry id. :ivar hypothesisChanged: signal emitted when hypothesis is changed :vartype hypothesisChanged: `QtCore.pyqtSignal` """ hypothesisChanged = QtCore.pyqtSignal(int)
[docs]def get_hypo_monitor(): """ This function returns global PhaseHypothesisMonitor object that should be used to monitor signals emitted when hypothesis is changed. :return: PhaseHypothesisMonitor :rtype: `PhaseHypothesisMonitor` """ global hypo_monitor if hypo_monitor is None: hypo_monitor = PhaseHypothesisMonitor() return hypo_monitor
[docs]def update_hypothesis_entry(hypo, entry_id): """ Updates the structure in the project table for the given entry ID with the current PhaseHypothesis. :param entry_id: entry id to set hypothesis to :type entry_id: int or str """ pt = maestro.project_table_get() if entry_id not in pt: return # Set the hypothesis ID so the property pentrates internal cts hypo.setHypoID(pt[entry_id][phase.PHASE_HYPO_ID]) hypo_ct = Structure(hypo.getHypoCt()) # Only copy over hypothesis specific properties out of the PhaseHypothesis for copy_prop in [phase.PHASE_SITE_TYPES] + constants.base64_properties: if copy_prop in hypo_ct.property: pt[entry_id][copy_prop] = hypo_ct.property[copy_prop] elif copy_prop in pt[entry_id].getStructure().property: del pt[entry_id][copy_prop] # Set the hypothesis ct as the entry structure, not copying properties. This # perserves any current non-hypothesis properties in the entry, as well as # the hypothesis properties set above. pt[entry_id].setStructure(hypo_ct, props=False) # Note that the setStructure call occurs after property changes since # Maestro synchronizes the workspace as soon as an entry structure is # changed. This primaryily affects phase_markers.update_hypothesis_entry, # which cycles any reference cts included in the workspace. # Emit signal that indicates that hypothesis changed get_hypo_monitor().hypothesisChanged.emit(int(entry_id))
def _get_hypothesis_datafile(entry_id): """ Returns the path to a hypothesis data file for a given hypothesis entry ID. If the entry is not a hypothesis, or the HYP_DATA_FILENAME does not exist, return None. :param entry_id: hypothesis entry ID :type entry_id: int :return: path to corresponding HYP_DATA_FILENAME :rtype: str """ pt = maestro.project_table_get() if entry_id not in pt: return None try: entry_dir = mmproj.mmproj_index_entry_get_additional_data_dir( pt, pt[entry_id].index) except IOError as e: logger.warning("Failed to read data directory for entry %s" % entry_id) return None # Return the .hyp datafile should it exist in the additional data directory hypothesis_data_file = os.path.join(entry_dir, HYP_DATA_FILENAME) if not os.path.isfile(hypothesis_data_file): return None return hypothesis_data_file def _get_hypothesis_rows(hypo_entry_id): """ Collects all entries in the group associated with the passed hypothesis entry ID, which contain the same hypothesis ID property value. :param hypo_entry_id: hypothesis entry ID :param hypo_entry_id: int :return: list of rows associated with the given hypothesis :rtype: list of `project.ProjectRow` """ # Only include sub entries with the same phase.PHASE_HYPO_ID pt = maestro.project_table_get() if hypo_entry_id not in pt: return [] if not is_hypothesis_entry(hypo_entry_id): raise RuntimeError("Entry %d is not valid hypothesis." % hypo_entry_id) hypo_id = pt[hypo_entry_id][phase.PHASE_HYPO_ID] # MAE-37599: Extract rows for all entries in this group row_model = pt.project_model.getRowModel() group_id = row_model.getEntryGroupId(int(hypo_entry_id)) # Return the entry itself if not within a group if not group_id: return [pt[hypo_entry_id]] status, group_entry_ids = row_model.getGroupEntryIds(group_id) if status != mmproj.MMPROJ_OK: raise RuntimeError("Unable to extract group entries for %s" % group_id) hypothesis_rows = [] for group_eid in group_entry_ids: row = pt[group_eid] if row[phase.PHASE_HYPO_ID] == hypo_id: hypothesis_rows.append(row) return hypothesis_rows
[docs]def get_hypothesis_from_project(entry_id): """ Gets hypothesis with a given entry id from the project. It creates a hypothesis object from entries within same hypothesis group. :param entry_id: hypothesis ID :type entry_id: int :return: Phase hypothesis :rtype: `PhaseHypothesis` """ sts = [ row.getStructure(copy=False) for row in _get_hypothesis_rows(entry_id) ] hypo_st, ref_st, additional_sts = hypothesis.sorted_hypo_structures(sts) # Added this check for some legacy scripts. If no hypothesis structure # is found return None. if hypo_st is mm.MMCT_INVALID_CT: return None return hypothesis.PhaseHypothesis(hypo_st, ref_st, additional_sts)
[docs]def convert_project_hypotheses(project_handle): """ Converts all hypothesis datafiles in the original Phase format into PhaseHypothesis (PhpHypoAdaptor) objects. If successful, each hypothesis is updated in the project to the new format. If the given entry ID does not have a corresponding hypothesis datafile, nothing is done. :param project_handle: `project.Project` handle :type project_handle: int """ pt = project.Project(project_handle=project_handle) for row in pt.all_rows: entry_id = int(row.entry_id) # Check that the entry is a hypothesis in the old format index = mmproj.mmproj_project_entry_id_to_index(pt.handle, entry_id) if not mmproj.mmproj_phase_entry_has_hypothesis(pt.handle, index): continue # Extract the hypothesis data file from the project hyp_archive = _get_hypothesis_datafile(entry_id) if not hyp_archive: continue # Create a PhaseHypothesis from the archive and the entry structure ref_ct = row.getStructure().handle try: hypo = hypothesis.PhaseHypothesis(row.title, hyp_archive, ref_ct) except phase.PhpException as e: logger.warning("WARNING: " + str(e)) continue # If successful, replace the row with this hypothesis structure pt[entry_id].setStructure(hypo.getHypoCt(), sync_workspace=False)
[docs]def is_hypothesis_entry(entry_id): """ Returns whether project table row is a Phase hypothesis entry or not. :param entry_id: entry ID for row in project table :type entry_id: int or str :return: True if the row is a hypothesis entry, false Otherwise :rtype: bool """ # Return False if maestro unavailable or entry not in PT if not maestro: return False pt = maestro.project_table_get() return pt.project_model.getRowModel().isHypothesisEntry(int(entry_id))
[docs]def get_hypothesis_entry_ids(entry_id): """ Returns entry_ids of all entries in the group associated with the passed hypothesis entry ID. :param hypo_entry_id: hypothesis entry ID :param hypo_entry_id: int :return: list of entry ids associated with the given hypothesis :rtype: list """ return [row.entry_id for row in _get_hypothesis_rows(entry_id)]