@@ -577,6 +577,86 @@ def compute_covariance_statistics_all_to_all(expr_genes,
577577 return cov_sum , center_ss , neighbor_ss , n_pairs , n_eff
578578
579579
580+ def get_anchor_motif_cell_ids (sq_obj ,
581+ ct : str ,
582+ motif : Union [str , List [str ]],
583+ max_dist : Optional [float ] = None ,
584+ k : Optional [int ] = None ,
585+ min_size : int = 0 ,
586+ ) -> dict :
587+ """
588+ Get cell grouping information for correlation analysis without computing correlations.
589+
590+ Identifies three groups of cells:
591+ 1. Center-neighbor pairs where neighbors belong to the specified motif
592+ 2. Non-neighbor motif cells (distant motif cells)
593+ 3. Center-neighbor pairs for centers without nearby motif
594+
595+ Parameters
596+ ----------
597+ sq_obj :
598+ A spatial_query object.
599+ ct : str
600+ Cell type as the center cells.
601+ motif : Union[str, List[str]]
602+ Motif (names of cell types) to be analyzed.
603+ max_dist : Optional[float], default=None
604+ Maximum distance for considering a cell as a neighbor. Use either max_dist or k.
605+ k : Optional[int], default=None
606+ Number of nearest neighbors. Use either max_dist or k.
607+ min_size : int, default=0
608+ Minimum neighborhood size for each center cell (only used when max_dist is specified).
609+
610+ Returns
611+ -------
612+ cell_groups : dict
613+ Dictionary containing cell pairing information:
614+ - 'center_neighbor_motif_pair': array of shape (n_pairs, 2) with
615+ [center_cell_idx, neighbor_cell_idx] pairs for centers with motif neighbors.
616+ - 'non-neighbor_motif_cells': array of cell indices for distant motif cells.
617+ - 'non_motif_center_neighbor_pair': array of shape (n_pairs, 2) with
618+ [center_cell_idx, neighbor_cell_idx] pairs for centers without nearby motif.
619+ Empty array if fewer than 10 pairs found.
620+ """
621+ motif = motif if isinstance (motif , list ) else [motif ]
622+
623+ # Step 1: Get center-neighbor pairs for motif
624+ neighbor_result = spatial_utils .get_motif_neighbor_cells (
625+ sq_obj = sq_obj , ct = ct , motif = motif , max_dist = max_dist , k = k , min_size = min_size
626+ )
627+ center_neighbor_pairs = neighbor_result ['center_neighbor_pairs' ]
628+ ct_in_motif = neighbor_result ['ct_in_motif' ]
629+
630+ # Step 2: Derive unique cell sets from pairs
631+ center_cells = np .unique (center_neighbor_pairs [:, 0 ])
632+ neighbor_cells = np .unique (center_neighbor_pairs [:, 1 ])
633+
634+ # Step 3: Get non-neighbor motif cells
635+ motif_mask = np .isin (np .array (sq_obj .labels ), motif )
636+ all_motif_cells = np .where (motif_mask )[0 ]
637+ non_neighbor_cells = np .setdiff1d (all_motif_cells , neighbor_cells )
638+
639+ # Remove center type from non-neighbor group for inter-cell-type focus
640+ if ct_in_motif :
641+ center_cell_mask_non = sq_obj .labels [non_neighbor_cells ] == ct
642+ non_neighbor_cells = non_neighbor_cells [~ center_cell_mask_non ]
643+
644+ # Step 4: Get pairs for centers without nearby motif
645+ no_motif_result = spatial_utils .get_all_neighbor_cells (
646+ sq_obj = sq_obj , ct = ct , max_dist = max_dist , k = k , min_size = min_size ,
647+ exclude_centers = center_cells , exclude_neighbors = neighbor_cells ,
648+ )
649+ center_no_motif_pairs = no_motif_result ['center_neighbor_pairs' ]
650+
651+ cell_groups = {
652+ 'center_neighbor_motif_pair' : center_neighbor_pairs ,
653+ 'non-neighbor_motif_cells' : non_neighbor_cells ,
654+ 'non_motif_center_neighbor_pair' : center_no_motif_pairs if len (center_no_motif_pairs ) >= 10 else np .array ([]).reshape (0 , 2 ),
655+ }
656+
657+ return cell_groups
658+
659+
580660def compute_gene_gene_correlation_adata (sq_obj ,
581661 ct : str ,
582662 motif : Union [str , List [str ]],
0 commit comments