@@ -131,7 +131,7 @@ def generate_bootstrap_indices(
131131 """
132132 Generate bootstrap indices for all groups and all bootstrap iterations.
133133 This matches the CPU implementation's random sampling logic for reproducibility.
134-
134+
135135 Parameters
136136 ----------
137137 cat_offsets : cp.ndarray
@@ -142,31 +142,31 @@ def generate_bootstrap_indices(
142142 Number of bootstrap samples
143143 random_state : int
144144 Random seed for reproducibility
145-
145+
146146 Returns
147147 -------
148148 bootstrap_indices : list[list[cp.ndarray]]
149149 For each bootstrap iteration, list of indices arrays for each group
150150 Shape: [n_bootstrap][k] where each element is cp.ndarray of group_size
151151 """
152152 import numpy as np
153-
153+
154154 # Use same RNG logic as CPU code
155155 rng = np .random .default_rng (random_state )
156-
156+
157157 # Convert to numpy for CPU-based random generation
158158 cat_offsets_np = cat_offsets .get ()
159-
159+
160160 bootstrap_indices = []
161-
161+
162162 for bootstrap_iter in range (n_bootstrap ):
163163 group_indices = []
164-
164+
165165 for group_idx in range (k ):
166166 start_idx = cat_offsets_np [group_idx ]
167167 end_idx = cat_offsets_np [group_idx + 1 ]
168168 group_size = end_idx - start_idx
169-
169+
170170 if group_size > 0 :
171171 # Generate bootstrap indices using same logic as CPU code
172172 # rng.choice(a=X.shape[0], size=X.shape[0], replace=True)
@@ -178,9 +178,9 @@ def generate_bootstrap_indices(
178178 else :
179179 # Empty group
180180 group_indices .append (cp .array ([], dtype = cp .int32 ))
181-
181+
182182 bootstrap_indices .append (group_indices )
183-
183+
184184 return bootstrap_indices
185185
186186
@@ -193,7 +193,7 @@ def _bootstrap_sample_cells_from_indices(
193193) -> tuple [cp .ndarray , cp .ndarray ]:
194194 """
195195 Bootstrap sample cells using pre-generated indices.
196-
196+
197197 Parameters
198198 ----------
199199 cat_offsets : cp.ndarray
@@ -204,32 +204,32 @@ def _bootstrap_sample_cells_from_indices(
204204 Number of groups
205205 bootstrap_group_indices : list[cp.ndarray]
206206 Pre-generated bootstrap indices for each group
207-
207+
208208 Returns
209209 -------
210210 new_cat_offsets, new_cell_indices : tuple[cp.ndarray, cp.ndarray]
211211 New category structure with bootstrapped cells
212212 """
213213 new_cell_indices = []
214214 new_cat_offsets = cp .zeros (k + 1 , dtype = cp .int32 )
215-
215+
216216 for group_idx in range (k ):
217217 start_idx = cat_offsets [group_idx ]
218218 end_idx = cat_offsets [group_idx + 1 ]
219219 group_size = end_idx - start_idx
220-
220+
221221 if group_size > 0 :
222222 # Get original cell indices for this group
223223 group_cells = cell_indices [start_idx :end_idx ]
224-
224+
225225 # Use pre-generated bootstrap indices
226226 bootstrap_indices = bootstrap_group_indices [group_idx ]
227227 bootstrap_cells = group_cells [bootstrap_indices ]
228-
228+
229229 new_cell_indices .extend (bootstrap_cells .get ().tolist ())
230-
230+
231231 new_cat_offsets [group_idx + 1 ] = len (new_cell_indices )
232-
232+
233233 return new_cat_offsets , cp .array (new_cell_indices , dtype = cp .int32 )
234234
235235
@@ -245,7 +245,7 @@ def compute_pairwise_means_gpu_bootstrap(
245245 """
246246 Compute bootstrap statistics for between-group distances.
247247 Uses CPU-compatible random generation for reproducibility.
248-
248+
249249 Returns:
250250 means: [k, k] matrix of bootstrap means
251251 variances: [k, k] matrix of bootstrap variances
@@ -254,9 +254,9 @@ def compute_pairwise_means_gpu_bootstrap(
254254 bootstrap_indices = generate_bootstrap_indices (
255255 cat_offsets , k , n_bootstrap , random_state
256256 )
257-
257+
258258 bootstrap_results = []
259-
259+
260260 for bootstrap_iter in range (n_bootstrap ):
261261 # Use pre-generated indices for this bootstrap iteration
262262 boot_cat_offsets , boot_cell_indices = _bootstrap_sample_cells_from_indices (
@@ -265,7 +265,7 @@ def compute_pairwise_means_gpu_bootstrap(
265265 k = k ,
266266 bootstrap_group_indices = bootstrap_indices [bootstrap_iter ],
267267 )
268-
268+
269269 # Compute distances with bootstrapped samples
270270 pairwise_means = compute_pairwise_means_gpu (
271271 embedding = embedding ,
@@ -274,12 +274,12 @@ def compute_pairwise_means_gpu_bootstrap(
274274 k = k ,
275275 )
276276 bootstrap_results .append (pairwise_means .get ())
277-
277+
278278 # Compute statistics across bootstrap samples
279279 bootstrap_stack = cp .array (bootstrap_results ) # [n_bootstrap, k, k]
280280 means = cp .mean (bootstrap_stack , axis = 0 )
281281 variances = cp .var (bootstrap_stack , axis = 0 )
282-
282+
283283 return means , variances
284284
285285
0 commit comments