Partitioning Module =================== The partitioning module implements a novel **radial cytoplasmic partitioning algorithm** that divides the cytoplasm between nuclear envelope (NE) and plasma membrane (PM) into concentric shells. This enables standardized spatial analysis across cells of varying geometries and imaging modalities, addressing a key challenge in quantitative cell biology. Overview -------- Radial partitioning normalizes the cytoplasmic space into radial shells from NE to PM, providing a unified framework for spatial quantification. This approach is particularly powerful for: * **Cross-cell comparisons**: Eliminating biases from variations in nuclear and cellular shapes * **Multi-modal integration**: Enabling direct comparison of organelle distributions across WFM, SIM, SXT, and cryo-ET * **Radial Distribution Function (RDF) analysis**: Quantifying organelle localization patterns with fine-grained spatial resolution Key Features ~~~~~~~~~~~~ * **Pure NE-PM Pair Method**: Fast and interpretable partitioning based on shell point clouds generated from NE-PM pairs * **Boundary Extraction**: Automatic identification and extraction of cellular membrane structure boundary points using Gaussian smoothing * **Spatial Pairing**: NE-PM point mapping based on angular similarity for robust pair generation * **Coordinate Extraction**: Sampling partition coordinates for downstream RDF and interaction analysis * **3D Visualization**: Multi-level visualization tools for partitioning results .. figure:: ../resources/784_5_partition_comparison.png :alt: Partitioning visualization showing original masks and partition results :align: center :width: 80% **Figure 1**: Cellular radial partitioning visualization. Left: Original PM and NE masks; Middle and Right: Radial partitioning results with 8 concentric shells from NE to PM, showing color gradient representation of spatial zones. Partitioning Class ------------------ .. autoclass:: ipa.processing.partitioning.Partitioning :members: :undoc-members: :show-inheritance: :member-order: bysource The ``Partitioning`` class provides the complete workflow for radial cytoplasmic partitioning, from boundary extraction to coordinate sampling. Core Methods ~~~~~~~~~~~~ extract_ne_pm_edges ^^^^^^^^^^^^^^^^^^^ .. automethod:: ipa.processing.partitioning.Partitioning.extract_ne_pm_edges Extracts boundary points from nuclear envelope and plasma membrane masks using Gaussian smoothing for robust edge detection. **Parameters**: - ``pm_mask`` (np.ndarray): Plasma membrane binary mask - ``ne_mask`` (np.ndarray): Nuclear envelope binary mask - ``smooth_sigma`` (float, optional): Gaussian smoothing sigma. Default: 1.0 **Returns**: - ``center`` (np.ndarray): Cell center coordinates (Z, Y, X) - ``ne_edge`` (np.ndarray): NE boundary point coordinates (N, 3) - ``pm_edge`` (np.ndarray): PM boundary point coordinates (M, 3) **Example**: .. code-block:: python from ipa.processing.partitioning import Partitioning from ipa.data_loader import UniversalDataLoader # Initialize partitioner partitioner = Partitioning(root_dir="results/", n_slices=8) # Load masks ne_mask = UniversalDataLoader.load_data("nuclear_envelope.mrc") pm_mask = UniversalDataLoader.load_data("plasma_membrane.mrc") # Extract boundaries center, ne_edge, pm_edge = partitioner.extract_ne_pm_edges(pm_mask, ne_mask) print(f"Cell center: {center}") print(f"NE points: {len(ne_edge)}, PM points: {len(pm_edge)}") create_nepm_radial_partitions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. automethod:: ipa.processing.partitioning.Partitioning.create_nepm_radial_partitions Creates radial partitions using pure NE-PM pair information without EDT guidance. This is the **recommended method** for most applications, offering fast computation with interpretable logic. **Algorithm Overview**: 1. Generate NE-PM point pairs based on angular similarity from cell center 2. Create intermediate shell points along each NE-PM pair at equal intervals 3. Assign cytoplasmic voxels to partitions based on distance to shells with relative position interpolation (60%/40% threshold) 4. Post-process with morphological closing to fill small gaps **Parameters**: - ``ne_edge`` (np.ndarray): NE boundary coordinates (N, 3) - ``pm_edge`` (np.ndarray): PM boundary coordinates (M, 3) - ``shape`` (tuple): Output volume shape (Z, Y, X) - ``n_slices`` (int, optional): Number of radial partitions. Default: 8 - ``pm_mask`` (np.ndarray, optional): Original PM mask for defining cell boundaries - ``ne_mask`` (np.ndarray, optional): Original NE mask for defining nuclear boundaries **Returns**: - ``partition_mask`` (np.ndarray): 3D partition mask where voxel values indicate partition ID (0=background, 1-N=partition IDs) **Biological Significance**: This method creates concentric shells that normalize for cell shape variations, enabling direct comparison of organelle distributions across different cells and imaging modalities. The pure pair-based approach is particularly suitable for SIM/WFM data where cell shapes are relatively regular. **Example**: .. code-block:: python # Create 8 radial partitions partition_mask = partitioner.create_nepm_radial_partitions( ne_edge, pm_edge, shape=volume_shape, n_slices=8, pm_mask=pm_mask, ne_mask=ne_mask ) # Check partition distribution unique_ids = np.unique(partition_mask) print(f"Created {len(unique_ids)-1} partitions") for pid in unique_ids[unique_ids > 0]: count = np.sum(partition_mask == pid) print(f"Partition {pid}: {count} voxels") extract_partition_coordinates ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. automethod:: ipa.processing.partitioning.Partitioning.extract_partition_coordinates Extracts coordinate points from partition mask for downstream RDF analysis. Uses random sampling to reduce memory usage while maintaining spatial distribution patterns. **Parameters**: - ``partition_mask`` (np.ndarray): 3D partition mask - ``sampling_density`` (float, optional): Sampling ratio (0-1). Default: 0.1 (10% of voxels) **Returns**: - ``partition_coords`` (dict): Dictionary mapping partition ID (int) to coordinate arrays (np.ndarray of shape [N, 3]) **Example**: .. code-block:: python # Extract coordinates with 5% sampling partition_coords = partitioner.extract_partition_coordinates( partition_mask, sampling_density=0.05 ) for partition_id, coords in partition_coords.items(): print(f"Partition {partition_id}: {len(coords)} sampled points") save_partition_coords_to_xvg ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. automethod:: ipa.processing.partitioning.Partitioning.save_partition_coords_to_xvg Saves partition coordinates in XVG format for compatibility with analysis modules. XVG is a simple text format that stores 3D coordinates with layer indices. **Parameters**: - ``partition_coords`` (dict): Dictionary of partition coordinates from ``extract_partition_coordinates()`` - ``dataid`` (str): Dataset identifier for filename - ``output_dir`` (str): Output directory path **Output Format**: The XVG file contains lines in the format: ``x y z partition_id``, where coordinates are in voxel units. **Example**: .. code-block:: python # Save coordinates for RDF analysis partitioner.save_partition_coords_to_xvg( partition_coords, dataid="sample_cell_01", output_dir="results/partitions/" ) # Creates: results/partitions/sample_cell_01_partition_coords.xvg Visualization Functions ----------------------- visualize_partitions ~~~~~~~~~~~~~~~~~~~~ .. autofunction:: ipa.processing.partitioning.visualize_partitions Generates 2D slice visualization of partitioning results with customizable color mapping. **Parameters**: - ``partition_list`` (list): List of binary masks for each partition layer - ``slice_idx`` (int): Index of Z-slice to display - ``save_path`` (str, optional): Path to save the figure. If None, displays interactively **Example**: .. code-block:: python from ipa.processing.partitioning import visualize_partitions # Create list of binary masks for each partition partition_list = [partition_mask == i for i in range(1, 9)] # Visualize middle slice visualize_partitions( partition_list=partition_list, slice_idx=partition_mask.shape[0] // 2, save_path="results/partitions_slice.png" ) plot_partition_features ~~~~~~~~~~~~~~~~~~~~~~~ .. autofunction:: ipa.processing.partitioning.plot_partition_features Generates statistical charts showing volume distribution and geometric features of each partition layer. **Parameters**: - ``partition_mask`` (np.ndarray): 3D partition mask - ``save_path`` (str, optional): Path to save the figure **Output**: - Bar chart showing voxel count per partition - Summary statistics table **Example**: .. code-block:: python from ipa.processing.partitioning import plot_partition_features plot_partition_features( partition_mask, save_path="results/partition_statistics.png" ) Complete Workflow Example ------------------------- This example demonstrates the complete partitioning workflow from mask loading to coordinate extraction: .. code-block:: python from ipa.processing.partitioning import Partitioning from ipa.data_loader import UniversalDataLoader import numpy as np # Step 1: Initialize partitioner partitioner = Partitioning( root_dir="results/", n_slices=8, # Create 8 radial partitions num_cores=4 # Use 4 CPU cores for parallel processing ) # Step 2: Load cellular membrane mask data ne_mask = UniversalDataLoader.load_data("data/nuclear_envelope.mrc") pm_mask = UniversalDataLoader.load_data("data/plasma_membrane.mrc") print(f"Loaded masks with shape: {pm_mask.shape}") # Step 3: Extract boundary coordinates center, ne_edge, pm_edge = partitioner.extract_ne_pm_edges(pm_mask, ne_mask) print(f"Detected cell center: {center}") print(f"NE boundary points: {len(ne_edge)}, PM boundary points: {len(pm_edge)}") # Step 4: Create radial partitions using pure NE-PM pair method partition_mask = partitioner.create_nepm_radial_partitions( ne_edge, pm_edge, shape=pm_mask.shape, n_slices=8, pm_mask=pm_mask, ne_mask=ne_mask ) # Check partition distribution unique_ids = np.unique(partition_mask) print(f"Created {len(unique_ids)-1} radial partitions") for pid in sorted(unique_ids[unique_ids > 0]): count = np.sum(partition_mask == pid) print(f" Partition {pid}: {count} voxels") # Step 5: Extract and save coordinate data for RDF analysis partition_coords = partitioner.extract_partition_coordinates( partition_mask, sampling_density=0.05 # Sample 5% of voxels ) partitioner.save_partition_coords_to_xvg( partition_coords, dataid="sample_cell_01", output_dir="results/partitions/" ) print("Partition coordinates saved to: results/partitions/sample_cell_01_partition_coords.xvg") # Step 6: Visualize results from ipa.processing.partitioning import visualize_partitions, plot_partition_features # 2D slice visualization partition_list = [partition_mask == i for i in range(1, 9)] visualize_partitions( partition_list=partition_list, slice_idx=pm_mask.shape[0] // 2, save_path="results/partitions_slice.png" ) # Statistical analysis plot_partition_features( partition_mask, save_path="results/partition_statistics.png" ) Output Data Formats ------------------- XVG Coordinate Files ~~~~~~~~~~~~~~~~~~~~ The XVG format is a simple text-based format for storing 3D coordinates with layer indices. Each line contains: ``` x y z partition_id ``` **Features**: - 3D coordinate points for each partition layer - Layer index markers (1 to N) - Sampling density control via ``sampling_density`` parameter - Compatible with downstream RDF and interaction analysis modules **Example XVG file content**: .. code-block:: text # Partition coordinates for sample_cell_01 # Format: x y z partition_id 45.2 120.5 30.1 1 46.8 121.2 30.5 1 ... 50.3 130.7 35.2 2 ... Usage in Analysis Modules ~~~~~~~~~~~~~~~~~~~~~~~~~ The partition coordinates can be directly used with analysis functions: .. code-block:: python from ipa.analysis import calculate_rdf_from_xvg, load_partition_coords_from_xvg # Load partition coordinates partition_coords = load_partition_coords_from_xvg( "results/partitions/sample_cell_01_partition_coords.xvg" ) # Calculate RDF for ISG rdf_results = calculate_rdf_from_xvg( organelle_mask=isg_mask, partition_coords=partition_coords, radial_positions=radial_positions_dict, bins=8 ) print(f"ISG RDF values: {rdf_results['rdf']}")