Module deeporigin.src.structures.pocket
Classes
class Pocket (file_path: str = '',
block_type: str = '',
block_content: str = '',
color='red',
name=None,
index: int | None = 0,
props: dict | None = None)-
Expand source code
class Pocket: """ A class representing a molecular pocket structure with various properties and methods for manipulation. This class handles loading, visualization, and analysis of molecular pocket structures, primarily dealing with PDB files. It supports initialization from either a file path or direct content block. Attributes: color (str): Color representation of the pocket (default: "red"). index (int): Index identifier for the pocket (default: 0). props (dict): Dictionary containing pocket properties. name (str): Name identifier for the pocket. file_path (Path): Path to the pocket file. structure (AtomArray): Biotite structure object representing the pocket. coordinates (ndarray): Numpy array of atomic coordinates. block_type (str): Type of structure block (e.g., "pdb"). block_content (str): Content of the structure block. Args: file_path (str, optional): Path to the pocket structure file. block_type (str, optional): Type of structure block. block_content (str, optional): Content of the structure block. color (str, optional): Color for visualization (default: "red"). name (str, optional): Name identifier for the pocket. index (int, optional): Index identifier (default: 0). props (dict, optional): Dictionary of pocket properties. Raises: ValueError: If the structure cannot be loaded. ValueError: If neither or both file_path and block_content are provided. ValueError: If the block_type is not supported (only "pdb" is supported). FileNotFoundError: If the specified file_path doesn't exist. Examples: # Create from file pocket = Pocket(file_path="path/to/pocket.pdb", name="Pocket1") # Create from content pocket = Pocket(block_content="...", block_type="pdb", name="Pocket2") # Visualize pocket pocket.visualize() # Get pocket center center = pocket.get_center() """ def __init__( self, file_path: str = "", block_type: str = "", block_content: str = "", color="red", name=None, index: Optional[int] = 0, props: Optional[dict] = None, ): self.color = color self.index = index self.props = props self.name = name self.file_path = None self.structure = None self.coordinates = None file_path_obj = Path(file_path).absolute() if file_path else None extension = file_path_obj.suffix.lower() if file_path_obj else "" if not block_type and extension: block_type = extension.lstrip(".") # Remove the leading dot self.block_type = block_type.lower() self.block_content = block_content sources_provided = sum(bool(x) for x in [file_path, block_content]) if sources_provided != 1: raise ValueError("Please provide exactly one of file_path or block_content.") from_block = False try: if file_path: self.file_path = Path(file_path).absolute() if not self.file_path.exists(): raise FileNotFoundError(f"The file {self.file_path} does not exist.") if not self.block_type: self.block_type = self.file_path.suffix.lstrip(".").lower() self.block_content = self.file_path.read_text() pocket_file_dir = self.get_directory() if str(pocket_file_dir) != str(self.file_path.parent): try: destination = Path(pocket_file_dir) / self.file_path.name shutil.copy2(self.file_path, destination) self.file_path = destination except Exception as e: DEFAULT_LOGGER.log_error(f"Failed to copy file to destination: {str(e)}") raise elif block_content: self.block_content = block_content if not self.block_type: raise ValueError("block_type must be provided when initializing with block_content.") from_block = True pocket_file_dir = self.get_directory() if self.block_content: if self.block_type not in ["pdb"]: raise ValueError(f"Only pdb file formats are supported (given {self.block_type})") self.structure = self.load_structure_from_block(self.block_content, self.block_type) if self.structure is None: raise ValueError("Structure could not be loaded.") # Type checking for AtomArrayStack if isinstance(self.structure, AtomArrayStack): self.structure = self.structure[0] DEFAULT_LOGGER.log_info( f"Loaded structure from {self.file_path if self.file_path else 'block content'}. Selected structure index: {0}" ) if self.name is None: if self.file_path: self.name = self.file_path.stem else: self.name = "Unknown_Pocket" directory = Path(pocket_file_dir) num = len(list(directory.glob(f"{self.name}*"))) self.name = f"{self.name}_{num + 1}" self.coordinates = self.structure.coord if from_block: directory = Path(pocket_file_dir) self.file_path = directory / f"{self.name}.{self.block_type}" self.write_to_file(self.file_path) except Exception as e: DEFAULT_LOGGER.log_error(f"Failed to initialize pocket: {str(e)}") raise def load_structure_from_block(self, block_content: str, block_type: str): """ Load molecular structure from a text block content. This method creates a Structure object from a text block containing structural data in a supported format. Args: block_content (str): Text content containing the structure data block_type (str): Format of the structure data (currently only "pdb" supported) Returns: Structure: A Structure object representing the molecular structure Raises: ValueError: If block_type is not supported """ if block_type == "pdb": pdb_file = PDBFile.read(io.StringIO(block_content)) structure = pdb_file.get_structure() else: raise ValueError(f"Unsupported block type: {block_type}") return structure @staticmethod def load_structure(structure_file_path: str): """ Load a protein structure from a PDB file. Args: structure_file_path (str): Path to the PDB file containing the protein structure. Returns: Structure: The loaded protein structure object. Raises: FileNotFoundError: If the specified PDB file does not exist. ValueError: If the PDB file is invalid or cannot be parsed. """ structure_file = PDBFile.read(structure_file_path) structure = structure_file.get_structure() return structure def write_to_file(self, output_path: str, output_format: str = "pdb"): """ Write the current structure to a file in the specified format. This method writes the current structure to a file, with support for different output formats. If the output format is not PDB, it first writes to a temporary PDB file and then converts to the desired format. Args: output_path (str): Path where the structure file should be written. output_format (str, optional): Format of the output file. Defaults to "pdb". Raises: Exception: If writing to file fails, the error is logged via DEFAULT_LOGGER. Example: >>> pocket.write_to_file("structure.pdb") >>> pocket.write_to_file("structure.mol2", output_format="mol2") """ def write_to_pdb_file(structure, output_path): pdb_file = PDBFile() pdb_file.set_structure(structure) pdb_file.write(output_path) try: path = Path(output_path) if not path.parent.exists(): path.parent.mkdir(parents=True, exist_ok=True) if path.suffix.lower() != ".pdb": with tempfile.NamedTemporaryFile(delete=True) as temp: write_to_pdb_file(self.structure, temp.name) convert_file("pdb", temp.name, output_format, output_path) else: write_to_pdb_file(self.structure, output_path) DEFAULT_LOGGER.log_info(f"Current structure written to {output_path}.") except Exception as e: DEFAULT_LOGGER.log_error(f"Failed to write structure to file {output_path}: {str(e)}") @jupyter_visualization def visualize(self): """ Visualizes the protein pocket in 3D using ProteinViewer. This method creates a 3D visualization of the pocket structure using the ProteinViewer class. It configures the visualization with appropriate colors and displays the pocket name and properties. Returns: The rendered 3D visualization of the protein pocket Notes: - Uses the pocket's file path and name for visualization - Applies color coding based on the pocket's index - Falls back to index 0 if the pocket index exceeds available colors - Displays pocket name and properties in the visualization legend """ pocket_paths = [str(self.file_path)] pocket_names = ["Name: " + self.name + " | " + self.pocket_props()] viewer = ProteinViewer("", format="pdb") pocket_config = viewer.get_pocket_visualization_config() # Ensure self.index is within the bounds of surface_colors if self.index >= len(pocket_config.surface_colors): # Log a warning or adjust index appropriately DEFAULT_LOGGER.log_warning(f"Index {self.index} is out of bounds for surface_colors. Resetting to 0.") self.index = 0 # Default to the first color if out of bounds pocket_config.surface_colors = [pocket_config.surface_colors[self.index]] print( "\n|\n".join( colored("■", pocket_config.surface_colors[0]) + " " + pocket_name for pocket_name in pocket_names ) ) return viewer.render_protein_with_pockets(pocket_paths=pocket_paths, pocket_config=pocket_config) def pocket_props(self): """ Formats the properties of a protein pocket into a single string line. Returns: str: A formatted string containing pocket properties in the format: 'Volume: {value}ų | Drugability score: {value}' Returns empty string if no properties are available. """ properties_line = "" if self.props: properties_line = ( f"Volume: {self.props.get('volume', 'N/A')}ų | " f"Drugability score: {self.props.get('drugability_score', 'N/A')}" ) return properties_line def __repr__(self): properties_line = "" if self.props: properties_line = ( f" Volume: {self.props.get('volume', 'N/A')}ų, " f"Total SASA: {self.props.get('total_SASA', 'N/A')} " f"Polar SASA: {self.props.get('polar_SASA', 'N/A')} " f"Polar/Apolar SASA ratio: {self.props.get('polar_apolar_SASA_ratio', 'N/A')} " f"Hydrophobicity: {self.props.get('hydrophobicity', 'N/A')} " f"Polarity: {self.props.get('polarity', 'N/A')} " f"Drugability score: {self.props.get('drugability_score', 'N/A')}" ) return ( f"Pocket:\n Name: {self.name}\n{properties_line} Block type: {self.block_type}\n" "Available Fields: {block_type, block_content, file_path, name, coordinates}" ) def __str__(self): properties_line = "" if self.props: properties_line = ( f" Volume: {self.props.get('volume', 'N/A')}ų, " f"Total SASA: {self.props.get('total_SASA', 'N/A')}, " f"Polar SASA: {self.props.get('polar_SASA', 'N/A')}, " f"Polar/Apolar SASA ratio: {self.props.get('polar_apolar_SASA_ratio', 'N/A')}, " f"Hydrophobicity: {self.props.get('hydrophobicity', 'N/A')}, " f"Polarity: {self.props.get('polarity', 'N/A')}, " f"Drugability score: {self.props.get('drugability_score', 'N/A')}" ) return ( f"Pocket:\n Name: {self.name}\n{properties_line} Block type: {self.block_type}\n" "Available Fields: {block_type, block_content, file_path, name, coordinates}" ) def get_center(self) -> Optional[List[float]]: """ Calculate and return the center coordinates of the pocket. This method computes the arithmetic mean of all coordinates in the pocket to determine its center point. Returns: Optional[List[float]]: A list containing the x, y, z coordinates of the pocket's center. Returns None if coordinates are not available. """ if self.coordinates is None: DEFAULT_LOGGER.log_warning("Coordinates are not available for this Pocket.") return None center = self.coordinates.mean(axis=0) DEFAULT_LOGGER.log_info(f"Calculated center coordinates: {center.tolist()}") return [float(x) for x in center.tolist()] @staticmethod def get_directory() -> str: """ Returns the base directory path for storing pocket-related data. This method creates (if not exists) and returns the path to a 'pockets' directory under the working directory. The directory is created with parent directories if needed. Returns: str: Absolute path to the pockets base directory as a string """ pockets_base_dir = Path(WORKING_DIR) / "pockets" pockets_base_dir.mkdir(parents=True, exist_ok=True) return str(pockets_base_dir) def update_coordinates(self, coords: np.ndarray): """ Updates the coordinates of the pocket structure. Args: coords (np.ndarray): New coordinates to update the pocket structure with. Should be a numpy array containing the coordinate data. Updates: - self.structure.coord: Updates the coordinates in the structure object - self.coordinates: Updates the local coordinates attribute Note: This method performs an in-place update of the coordinates and logs the action. """ self.structure.coord = coords self.coordinates = coords DEFAULT_LOGGER.log_info("Pocket coordinates has been inplaced updated.")
A class representing a molecular pocket structure with various properties and methods for manipulation. This class handles loading, visualization, and analysis of molecular pocket structures, primarily dealing with PDB files. It supports initialization from either a file path or direct content block.
Attributes
color
:str
- Color representation of the pocket (default: "red").
index
:int
- Index identifier for the pocket (default: 0).
props
:dict
- Dictionary containing pocket properties.
name
:str
- Name identifier for the pocket.
file_path
:Path
- Path to the pocket file.
structure
:AtomArray
- Biotite structure object representing the pocket.
coordinates
:ndarray
- Numpy array of atomic coordinates.
block_type
:str
- Type of structure block (e.g., "pdb").
block_content
:str
- Content of the structure block.
Args
file_path
:str
, optional- Path to the pocket structure file.
block_type
:str
, optional- Type of structure block.
block_content
:str
, optional- Content of the structure block.
color
:str
, optional- Color for visualization (default: "red").
name
:str
, optional- Name identifier for the pocket.
index
:int
, optional- Index identifier (default: 0).
props
:dict
, optional- Dictionary of pocket properties.
Raises
ValueError
- If the structure cannot be loaded.
ValueError
- If neither or both file_path and block_content are provided.
ValueError
- If the block_type is not supported (only "pdb" is supported).
FileNotFoundError
- If the specified file_path doesn't exist.
Examples
Create from file
pocket = Pocket(file_path="path/to/pocket.pdb", name="Pocket1")
Create from content
pocket = Pocket(block_content="…", block_type="pdb", name="Pocket2")
Visualize pocket
pocket.visualize()
Get pocket center
center = pocket.get_center()
Static methods
def get_directory() ‑> str
-
Expand source code
@staticmethod def get_directory() -> str: """ Returns the base directory path for storing pocket-related data. This method creates (if not exists) and returns the path to a 'pockets' directory under the working directory. The directory is created with parent directories if needed. Returns: str: Absolute path to the pockets base directory as a string """ pockets_base_dir = Path(WORKING_DIR) / "pockets" pockets_base_dir.mkdir(parents=True, exist_ok=True) return str(pockets_base_dir)
Returns the base directory path for storing pocket-related data.
This method creates (if not exists) and returns the path to a 'pockets' directory under the working directory. The directory is created with parent directories if needed.
Returns
str
- Absolute path to the pockets base directory as a string
def load_structure(structure_file_path: str)
-
Expand source code
@staticmethod def load_structure(structure_file_path: str): """ Load a protein structure from a PDB file. Args: structure_file_path (str): Path to the PDB file containing the protein structure. Returns: Structure: The loaded protein structure object. Raises: FileNotFoundError: If the specified PDB file does not exist. ValueError: If the PDB file is invalid or cannot be parsed. """ structure_file = PDBFile.read(structure_file_path) structure = structure_file.get_structure() return structure
Load a protein structure from a PDB file.
Args
structure_file_path
:str
- Path to the PDB file containing the protein structure.
Returns
Structure
- The loaded protein structure object.
Raises
FileNotFoundError
- If the specified PDB file does not exist.
ValueError
- If the PDB file is invalid or cannot be parsed.
Methods
def get_center(self) ‑> List[float] | None
-
Expand source code
def get_center(self) -> Optional[List[float]]: """ Calculate and return the center coordinates of the pocket. This method computes the arithmetic mean of all coordinates in the pocket to determine its center point. Returns: Optional[List[float]]: A list containing the x, y, z coordinates of the pocket's center. Returns None if coordinates are not available. """ if self.coordinates is None: DEFAULT_LOGGER.log_warning("Coordinates are not available for this Pocket.") return None center = self.coordinates.mean(axis=0) DEFAULT_LOGGER.log_info(f"Calculated center coordinates: {center.tolist()}") return [float(x) for x in center.tolist()]
Calculate and return the center coordinates of the pocket.
This method computes the arithmetic mean of all coordinates in the pocket to determine its center point.
Returns
Optional[List[float]]
- A list containing the x, y, z coordinates of the pocket's center. Returns None if coordinates are not available.
def load_structure_from_block(self, block_content: str, block_type: str)
-
Expand source code
def load_structure_from_block(self, block_content: str, block_type: str): """ Load molecular structure from a text block content. This method creates a Structure object from a text block containing structural data in a supported format. Args: block_content (str): Text content containing the structure data block_type (str): Format of the structure data (currently only "pdb" supported) Returns: Structure: A Structure object representing the molecular structure Raises: ValueError: If block_type is not supported """ if block_type == "pdb": pdb_file = PDBFile.read(io.StringIO(block_content)) structure = pdb_file.get_structure() else: raise ValueError(f"Unsupported block type: {block_type}") return structure
Load molecular structure from a text block content.
This method creates a Structure object from a text block containing structural data in a supported format.
Args
block_content
:str
- Text content containing the structure data
block_type
:str
- Format of the structure data (currently only "pdb" supported)
Returns
Structure
- A Structure object representing the molecular structure
Raises
ValueError
- If block_type is not supported
def pocket_props(self)
-
Expand source code
def pocket_props(self): """ Formats the properties of a protein pocket into a single string line. Returns: str: A formatted string containing pocket properties in the format: 'Volume: {value}ų | Drugability score: {value}' Returns empty string if no properties are available. """ properties_line = "" if self.props: properties_line = ( f"Volume: {self.props.get('volume', 'N/A')}ų | " f"Drugability score: {self.props.get('drugability_score', 'N/A')}" ) return properties_line
Formats the properties of a protein pocket into a single string line.
Returns
str
- A formatted string containing pocket properties in the format: 'Volume: {value}ų | Drugability score: {value}' Returns empty string if no properties are available.
def update_coordinates(self, coords: numpy.ndarray)
-
Expand source code
def update_coordinates(self, coords: np.ndarray): """ Updates the coordinates of the pocket structure. Args: coords (np.ndarray): New coordinates to update the pocket structure with. Should be a numpy array containing the coordinate data. Updates: - self.structure.coord: Updates the coordinates in the structure object - self.coordinates: Updates the local coordinates attribute Note: This method performs an in-place update of the coordinates and logs the action. """ self.structure.coord = coords self.coordinates = coords DEFAULT_LOGGER.log_info("Pocket coordinates has been inplaced updated.")
Updates the coordinates of the pocket structure.
Args
coords
:np.ndarray
- New coordinates to update the pocket structure with. Should be a numpy array containing the coordinate data.
Updates
- self.structure.coord: Updates the coordinates in the structure object
- self.coordinates: Updates the local coordinates attribute
Note
This method performs an in-place update of the coordinates and logs the action.
def visualize(*args, **kwargs)
-
Expand source code
def wrapper(*args, **kwargs): html_visualization = func(*args, **kwargs) return JupyterViewer.visualize(html_visualization)
def write_to_file(self, output_path: str, output_format: str = 'pdb')
-
Expand source code
def write_to_file(self, output_path: str, output_format: str = "pdb"): """ Write the current structure to a file in the specified format. This method writes the current structure to a file, with support for different output formats. If the output format is not PDB, it first writes to a temporary PDB file and then converts to the desired format. Args: output_path (str): Path where the structure file should be written. output_format (str, optional): Format of the output file. Defaults to "pdb". Raises: Exception: If writing to file fails, the error is logged via DEFAULT_LOGGER. Example: >>> pocket.write_to_file("structure.pdb") >>> pocket.write_to_file("structure.mol2", output_format="mol2") """ def write_to_pdb_file(structure, output_path): pdb_file = PDBFile() pdb_file.set_structure(structure) pdb_file.write(output_path) try: path = Path(output_path) if not path.parent.exists(): path.parent.mkdir(parents=True, exist_ok=True) if path.suffix.lower() != ".pdb": with tempfile.NamedTemporaryFile(delete=True) as temp: write_to_pdb_file(self.structure, temp.name) convert_file("pdb", temp.name, output_format, output_path) else: write_to_pdb_file(self.structure, output_path) DEFAULT_LOGGER.log_info(f"Current structure written to {output_path}.") except Exception as e: DEFAULT_LOGGER.log_error(f"Failed to write structure to file {output_path}: {str(e)}")
Write the current structure to a file in the specified format. This method writes the current structure to a file, with support for different output formats. If the output format is not PDB, it first writes to a temporary PDB file and then converts to the desired format.
Args
output_path
:str
- Path where the structure file should be written.
output_format
:str
, optional- Format of the output file. Defaults to "pdb".
Raises
Exception
- If writing to file fails, the error is logged via DEFAULT_LOGGER.
Example
>>> pocket.write_to_file("structure.pdb") >>> pocket.write_to_file("structure.mol2", output_format="mol2")