Module deeporigin.src.structures.pocket_data
Classes
class PocketData (pocket: List | Pocket | Ligand,
xref_protein: Protein,
box_size: List | None = None,
fit_box: bool | None = None,
padding: int | None = 2)-
Expand source code
class PocketData: def __init__( self, pocket: List | Pocket | Ligand, xref_protein: Protein, box_size: Optional[List] = None, fit_box: Optional[bool] = None, padding: Optional[int] = 2, ): """ Initialize a PocketBox object. This class handles the creation and manipulation of pocket boxes for protein structures. It supports both direct coordinate input and structure-based pocket definitions. Args: pocket (List | Pocket | Ligand): Either a list of 3D coordinates [x,y,z] or a Pocket/Ligand object xref_protein (Protein): Reference protein structure box_size (List, optional): Custom box dimensions [x,y,z] in Angstroms. Defaults to None fit_box (bool, optional): Whether to fit box to pocket dimensions. Defaults to None padding (int, optional): Padding around pocket when fitting box. Defaults to 2 Raises: ValueError: If both box_size and fit_box are specified ValueError: If pocket is a list but doesn't contain 3 numeric elements ValueError: If attempting to fit box to coordinate list ValueError: If pocket is invalid type Note: - If neither box_size nor fit_box specified, defaults to 24Å cubic box - When using Pocket/Ligand objects, PCA alignment is automatically performed """ if box_size and fit_box: raise ValueError("Cannot specify both box_size and [fit_box and padding]") if not box_size and not fit_box: DEFAULT_LOGGER.log_warning("No box size or fit box specified. Defaulting to 24Å box.") box_size = [24, 24, 24] self.__pocket = deepcopy(pocket) if isinstance(self.__pocket, list): if len(self.__pocket) != 3: raise ValueError("If pocket is a list, it must have 3 elements (x, y, z)") for i in self.__pocket: if not isinstance(i, (int, float, np.int32, np.int64, np.float32, np.float64)): raise ValueError("All elements in pocket must be integers or floats") self.__aligner = None if fit_box: raise ValueError("Cannot fit box to list of coordinates") elif isinstance(pocket, (Pocket, Ligand)): self.__aligner = StructureAligner() self.__aligner.calculate_pca(self.__pocket.coordinates) pocket_transformed_coords = self.transform(self.__pocket.coordinates) self.__pocket.update_coordinates(pocket_transformed_coords) else: raise ValueError("Invalid pocket type") self.__padding = padding self.__fit_box = fit_box self.__xref_protein = xref_protein self.__box_center = self._get_center(self.__pocket) self.__box_min_coords, self.__box_max_coords, self.__box_size = self.calculate_box_params(box_size) @classmethod def create_from_residues( cls, xref_protein: Protein, residue_ids: List[str], box_size: Optional[List] = None, fit_box: Optional[bool] = None, padding: Optional[int] = 2, ): """ Creates a pocket data instance from a list of residue IDs. Args: xref_protein (Protein): The reference protein structure. residue_ids (List[str]): List of residue IDs that define the pocket. box_size (Optional[List], optional): Custom box dimensions. Defaults to None. fit_box (Optional[bool], optional): Whether to fit the box to the pocket. Defaults to None. padding (Optional[int], optional): Padding size around the pocket. Defaults to 2. Returns: PocketData: A new pocket data instance centered on the specified residues. Raises: None explicitly, but may log warnings if issues are found with residue selection. """ center, warning, _ = xref_protein.get_center_by_residues(residue_ids) if warning: DEFAULT_LOGGER.log_warning(warning) return cls(pocket=center, xref_protein=xref_protein, box_size=box_size, fit_box=fit_box, padding=padding) @property def pocket(self): """ Gets the pocket data. Returns: The pocket data stored in this instance. """ return self.__pocket @property def xref_protein(self): """ Get the cross-reference protein identifier. Returns: str: The cross-reference protein identifier associated with this pocket. """ return self.__xref_protein @property def padding(self): """ Gets the padding value used for this pocket data. Returns: float: The padding value used for spatial calculations around the pocket """ return self.__padding @property def fit_box(self): """ Gets the fit_box value used for this pocket data. Returns: bool: Whether the box is fitted to the pocket dimensions """ return self.__fit_box @property def box_size(self): """ Returns the size of the box. Returns: float: The size of the box representing the pocket's bounding box dimensions. """ return self.__box_size @property def box_center(self): """ Get the center coordinates of the binding site box. Returns: numpy.ndarray: The 3D coordinates [x, y, z] representing the center of the binding site box. """ return self.__box_center @property def aligner(self): """ Get the aligner instance associated with this pocket data. Returns: object: The aligner object used for structural alignment. """ return self.__aligner @property def box_min_coords(self): """ Returns the minimum coordinates of the box. Returns: list: A list containing the minimum x, y, z coordinates of the box. """ return self.__box_min_coords @property def box_max_coords(self): """ Gets the maximum coordinates of the box defining the pocket. Returns: tuple: A 3D coordinate tuple (x, y, z) representing the maximum bounds of the pocket box. """ return self.__box_max_coords def _get_center(self, pocket: str | Pocket | List[float]): """ Get the center coordinates of a pocket or ligand. Args: pocket (Union[str, Pocket, List[float]]): Input pocket data. Can be: - List[float]: Direct coordinates [x, y, z] - Pocket: Pocket object with get_center() method - Ligand: Ligand object with get_center() method Returns: List[float]: Center coordinates as [x, y, z] Raises: ValueError: If input pocket type is not supported """ if isinstance(pocket, list): pocket = [float(x) for x in pocket] elif isinstance(pocket, (Pocket, Ligand)): pocket = pocket.get_center() else: raise ValueError("Invalid pocket type.") return pocket def transform(self, coords: np.ndarray) -> np.ndarray: """ Transform coordinates using the aligner if available. Args: coords (np.ndarray): Input coordinates to be transformed. Returns: np.ndarray: Transformed coordinates if aligner exists, original coordinates otherwise. """ if self.aligner is None: return coords return self.aligner.align_structure(coords) def inverse_transform(self, coords: np.ndarray) -> np.ndarray: """ Inverse transform coordinates from the PCA-aligned space. Args: coords: Coordinates to inverse transform. Returns: Inverse transformed coordinates. """ if self.aligner is None: return coords return self.aligner.restore_structure(coords) def match_protein(self, protein: Protein) -> bool: """ Check if the protein matches the xref protein. Args: protein: Protein to check. Returns: True if the proteins match, False otherwise. """ if protein != self.xref_protein: raise ValueError("Provided protein does not match xref protein.") def calculate_box_params(self, box_size: Optional[List] = None): if self.fit_box: result = create_bounding_box(self.pocket, padding=self.padding, around_ligand=True) box_min_coords, box_max_coords = list(result["min_coords"]), list(result["max_coords"]) else: box_min_coords, box_max_coords = calculate_box_min_max(box_center=self.box_center, box_dimensions=box_size) if self.fit_box: box_size = calculate_box_dimensions(box_min_coords, box_max_coords) return box_min_coords, box_max_coords, box_size def from_xyz(self): """ Determines if the pocket data is in XYZ format. Returns: bool: True if the pocket data is a list (XYZ format), False if it's a Ligand or Pocket object Raises: ValueError: If the pocket type is invalid """ if isinstance(self.pocket, (Ligand, Pocket)): return False elif isinstance(self.pocket, list): return True else: raise ValueError("Invalid pocket type") @jupyter_visualization def show_box(self, protein: Protein = None, raise_for_protein_mismatch: bool = True) -> str: """ Generates an HTML visualization of the protein structure with a bounding box representation of the pocket. This method creates a visual representation using MolStar viewer, showing either: 1. The protein structure with a ligand and its bounding box (for non-XYZ derived pockets) 2. The protein structure with just the bounding box (for XYZ derived pockets) Args: protein (Protein, optional): The protein structure to visualize. If None, uses the cross-referenced protein. Defaults to None. raise_for_protein_mismatch (bool, optional): Whether to raise an error if the protein doesn't match the pocket's reference protein. Defaults to True. Returns: str: HTML string containing the MolStar viewer visualization. Raises: ProteinMismatchError: If raise_for_protein_mismatch is True and the provided protein doesn't match the pocket's reference protein. """ if protein is None: protein = self.xref_protein if raise_for_protein_mismatch: self.match_protein(protein) protein = deepcopy(protein) aligned_protein_coords = self.transform(protein.structure.coord) protein.update_coordinates(aligned_protein_coords) if not self.from_xyz(): with tempfile.TemporaryDirectory() as temp_dir: tmp_protein_file = Path(temp_dir) / "protein.pdb" tmp_structure_file = Path(temp_dir) / "structure.sdf" protein.write_to_file(str(tmp_protein_file)) self.pocket.write_to_file(str(tmp_structure_file), output_format="sdf") html = DockingMolstarViewer().render_ligand_with_bounding_box( protein_data=str(tmp_protein_file), protein_format="pdb", ligand_data=str(tmp_structure_file), ligand_format="sdf", box={"min": self.box_min_coords, "max": self.box_max_coords}, ) else: protein_file_path = str(protein.file_path) protein_format = getattr(protein, "block_type", "pdb") html = DockingMolstarViewer().render_bounding_box( protein_data=protein_file_path, protein_format=protein_format, box_center=self.box_center, box_size=self.box_size, ) return html
Initialize a PocketBox object. This class handles the creation and manipulation of pocket boxes for protein structures. It supports both direct coordinate input and structure-based pocket definitions.
Args
pocket
:List | Pocket | Ligand
- Either a list of 3D coordinates [x,y,z] or a Pocket/Ligand object
xref_protein
:Protein
- Reference protein structure
box_size
:List
, optional- Custom box dimensions [x,y,z] in Angstroms. Defaults to None
fit_box
:bool
, optional- Whether to fit box to pocket dimensions. Defaults to None
padding
:int
, optional- Padding around pocket when fitting box. Defaults to 2
Raises
ValueError
- If both box_size and fit_box are specified
ValueError
- If pocket is a list but doesn't contain 3 numeric elements
ValueError
- If attempting to fit box to coordinate list
ValueError
- If pocket is invalid type
Note
- If neither box_size nor fit_box specified, defaults to 24Å cubic box
- When using Pocket/Ligand objects, PCA alignment is automatically performed
Static methods
def create_from_residues(xref_protein: Protein,
residue_ids: List[str],
box_size: List | None = None,
fit_box: bool | None = None,
padding: int | None = 2)-
Creates a pocket data instance from a list of residue IDs.
Args
xref_protein
:Protein
- The reference protein structure.
residue_ids
:List[str]
- List of residue IDs that define the pocket.
box_size
:Optional[List]
, optional- Custom box dimensions. Defaults to None.
fit_box
:Optional[bool]
, optional- Whether to fit the box to the pocket. Defaults to None.
padding
:Optional[int]
, optional- Padding size around the pocket. Defaults to 2.
Returns
PocketData
- A new pocket data instance centered on the specified residues.
Raises
None explicitly, but may log warnings if issues are found with residue selection.
Instance variables
prop aligner
-
Expand source code
@property def aligner(self): """ Get the aligner instance associated with this pocket data. Returns: object: The aligner object used for structural alignment. """ return self.__aligner
Get the aligner instance associated with this pocket data.
Returns
object
- The aligner object used for structural alignment.
prop box_center
-
Expand source code
@property def box_center(self): """ Get the center coordinates of the binding site box. Returns: numpy.ndarray: The 3D coordinates [x, y, z] representing the center of the binding site box. """ return self.__box_center
Get the center coordinates of the binding site box.
Returns
numpy.ndarray
- The 3D coordinates [x, y, z] representing the center of the binding site box.
prop box_max_coords
-
Expand source code
@property def box_max_coords(self): """ Gets the maximum coordinates of the box defining the pocket. Returns: tuple: A 3D coordinate tuple (x, y, z) representing the maximum bounds of the pocket box. """ return self.__box_max_coords
Gets the maximum coordinates of the box defining the pocket.
Returns
tuple
- A 3D coordinate tuple (x, y, z) representing the maximum bounds of the pocket box.
prop box_min_coords
-
Expand source code
@property def box_min_coords(self): """ Returns the minimum coordinates of the box. Returns: list: A list containing the minimum x, y, z coordinates of the box. """ return self.__box_min_coords
Returns the minimum coordinates of the box.
Returns
list
- A list containing the minimum x, y, z coordinates of the box.
prop box_size
-
Expand source code
@property def box_size(self): """ Returns the size of the box. Returns: float: The size of the box representing the pocket's bounding box dimensions. """ return self.__box_size
Returns the size of the box.
Returns
float
- The size of the box representing the pocket's bounding box dimensions.
prop fit_box
-
Expand source code
@property def fit_box(self): """ Gets the fit_box value used for this pocket data. Returns: bool: Whether the box is fitted to the pocket dimensions """ return self.__fit_box
Gets the fit_box value used for this pocket data.
Returns
bool
- Whether the box is fitted to the pocket dimensions
prop padding
-
Expand source code
@property def padding(self): """ Gets the padding value used for this pocket data. Returns: float: The padding value used for spatial calculations around the pocket """ return self.__padding
Gets the padding value used for this pocket data.
Returns
float
- The padding value used for spatial calculations around the pocket
prop pocket
-
Expand source code
@property def pocket(self): """ Gets the pocket data. Returns: The pocket data stored in this instance. """ return self.__pocket
Gets the pocket data.
Returns
The pocket data stored in this instance.
prop xref_protein
-
Expand source code
@property def xref_protein(self): """ Get the cross-reference protein identifier. Returns: str: The cross-reference protein identifier associated with this pocket. """ return self.__xref_protein
Get the cross-reference protein identifier.
Returns
str
- The cross-reference protein identifier associated with this pocket.
Methods
def calculate_box_params(self, box_size: List | None = None)
-
Expand source code
def calculate_box_params(self, box_size: Optional[List] = None): if self.fit_box: result = create_bounding_box(self.pocket, padding=self.padding, around_ligand=True) box_min_coords, box_max_coords = list(result["min_coords"]), list(result["max_coords"]) else: box_min_coords, box_max_coords = calculate_box_min_max(box_center=self.box_center, box_dimensions=box_size) if self.fit_box: box_size = calculate_box_dimensions(box_min_coords, box_max_coords) return box_min_coords, box_max_coords, box_size
def from_xyz(self)
-
Expand source code
def from_xyz(self): """ Determines if the pocket data is in XYZ format. Returns: bool: True if the pocket data is a list (XYZ format), False if it's a Ligand or Pocket object Raises: ValueError: If the pocket type is invalid """ if isinstance(self.pocket, (Ligand, Pocket)): return False elif isinstance(self.pocket, list): return True else: raise ValueError("Invalid pocket type")
Determines if the pocket data is in XYZ format.
Returns
bool
- True if the pocket data is a list (XYZ format), False if it's a Ligand or Pocket object
Raises
ValueError
- If the pocket type is invalid
def inverse_transform(self, coords: numpy.ndarray) ‑> numpy.ndarray
-
Expand source code
def inverse_transform(self, coords: np.ndarray) -> np.ndarray: """ Inverse transform coordinates from the PCA-aligned space. Args: coords: Coordinates to inverse transform. Returns: Inverse transformed coordinates. """ if self.aligner is None: return coords return self.aligner.restore_structure(coords)
Inverse transform coordinates from the PCA-aligned space.
Args
coords
- Coordinates to inverse transform.
Returns
Inverse transformed coordinates.
def match_protein(self,
protein: Protein) ‑> bool-
Expand source code
def match_protein(self, protein: Protein) -> bool: """ Check if the protein matches the xref protein. Args: protein: Protein to check. Returns: True if the proteins match, False otherwise. """ if protein != self.xref_protein: raise ValueError("Provided protein does not match xref protein.")
Check if the protein matches the xref protein.
Args
protein
- Protein to check.
Returns
True if the proteins match, False otherwise.
def show_box(*args, **kwargs)
-
Expand source code
def wrapper(*args, **kwargs): html_visualization = func(*args, **kwargs) return JupyterViewer.visualize(html_visualization)
def transform(self, coords: numpy.ndarray) ‑> numpy.ndarray
-
Expand source code
def transform(self, coords: np.ndarray) -> np.ndarray: """ Transform coordinates using the aligner if available. Args: coords (np.ndarray): Input coordinates to be transformed. Returns: np.ndarray: Transformed coordinates if aligner exists, original coordinates otherwise. """ if self.aligner is None: return coords return self.aligner.align_structure(coords)
Transform coordinates using the aligner if available.
Args
coords
:np.ndarray
- Input coordinates to be transformed.
Returns
np.ndarray
- Transformed coordinates if aligner exists, original coordinates otherwise.