Skip to content

Met a compute_transition_matrix error #1260

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
Yiikea opened this issue Apr 6, 2025 · 1 comment
Open

Met a compute_transition_matrix error #1260

Yiikea opened this issue Apr 6, 2025 · 1 comment
Assignees
Labels
bug Something isn't working

Comments

@Yiikea
Copy link

Yiikea commented Apr 6, 2025

Hello CellRank,

Thank you for your excellent work! I'm running RealTimeKernel and met InvalidParameterError: The 'n_neighbors' parameter of KNeighborsTransformer must be an int in the range [1, inf) or None. Got 0 instead. My Anndata has the attribute 'neighbors', and I tried passing the n_neighbors parameter directly but it didn't work.

Could you please help me with this issue?

Thank you!

tp2 = TemporalProblem(adata2)
tp2 = tp2.score_genes_for_marginals(
    gene_set_proliferation="mouse", gene_set_apoptosis="mouse"
)
tp2 = tp2.prepare(time_key="time", joint_attr='X_scVI')
tp2 = tp2.solve(epsilon=1e-3, tau_a=0.95, scale_cost="mean",device='cpu')

adata2.obsm['X_pca'] = adata2.obsm['X_scVI']
tmk2 = RealTimeKernel.from_moscot(tp2)
tmk2.compute_transition_matrix(self_transitions="all", conn_weight=0.2, threshold="auto")
## 100%|██████████| 67[/67] Using automatic `threshold=0.0` WARNING: Coupling at `(0.0, 4.0)` contains `4` empty row(s), e.g., due to unbalancedness or 0s in the source marginals. Using uniform distribution WARNING: n_obs too small: adjusting to `n_neighbors = 1`

InvalidParameterError Traceback (most recent call last)
Cell In[86], line 3
1 adata2.obsm['X_pca'] = adata2.obsm['X_scVI']
2 tmk2 = RealTimeKernel.from_moscot(tp2)
----> 3 tmk2.compute_transition_matrix(self_transitions="all", conn_weight=0.2, threshold="auto")

File [~/.conda/envs/moscot/lib/python3.9/site-packages/cellrank/kernels/_real_time_kernel.py:202], in RealTimeKernel.compute_transition_matrix(self, threshold, self_transitions, conn_weight, conn_kwargs, **kwargs)
199 if threshold is not None:
200 self._sparsify_couplings(self.couplings, threshold=threshold, copy=False)
--> 202 tmap = self._restich_couplings(
203 self.couplings,
204 self_transitions=self_transitions,
205 conn_weight=conn_weight,
206 **conn_kwargs,
207 )
209 self.transition_matrix = tmap.X
210 self._obs = tmap.obs

File [~/.conda/envs/moscot/lib/python3.9/site-packages/cellrank/kernels/_real_time_kernel.py:426], in RealTimeKernel._restich_couplings(self, couplings, self_transitions, conn_weight, **kwargs)
424 continue
425 [src_ix](https://github.com/theislab/cellrank/issues/new?template=bug_report.md#), tgt_ix = self._time_to_ix[src], self._time_to_ix[tgt]
--> 426 blocks[src_ix][src_ix] = conn_weight * _compute_connectivity_tmat(
427 self.adata[coupling.obs_names], **conn_kwargs
428 )
429 blocks[[src_ix](https://github.com/theislab/cellrank/issues/new?template=bug_report.md#)][tgt_ix] = (1 - conn_weight) * _normalize(blocks[[src_ix](https://github.com/theislab/cellrank/issues/new?template=bug_report.md#)][tgt_ix])
430 # fmt: on

File [~/.conda/envs/moscot/lib/python3.9/site-packages/cellrank/kernels/_real_time_kernel.py:626], in _compute_connectivity_tmat(adata, density_normalize, **kwargs)
621 def _compute_connectivity_tmat(
622 adata: AnnData, density_normalize: bool = True, **kwargs: Any
623 ) -> Union[np.ndarray, sp.spmatrix]:
624 from cellrank.kernels import ConnectivityKernel
--> 626 sc.pp.neighbors(adata, **kwargs)
627 return ConnectivityKernel(adata).compute_transition_matrix(density_normalize=density_normalize).transition_matrix

File [~/.conda/envs/moscot/lib/python3.9/site-packages/scanpy/neighbors/**init**.py:191], in neighbors(adata, n_neighbors, n_pcs, use_rep, knn, method, transformer, metric, metric_kwds, random_state, key_added, copy)
189 adata._init_as_actual(adata.copy())
190 neighbors = Neighbors(adata)
--> 191 neighbors.compute_neighbors(
192 n_neighbors,
193 n_pcs=n_pcs,
194 use_rep=use_rep,
195 knn=knn,
196 method=method,
197 transformer=transformer,
198 metric=metric,
199 metric_kwds=metric_kwds,
200 random_state=random_state,
201 )
203 if key_added is None:
204 key_added = "neighbors"

File [~/.conda/envs/moscot/lib/python3.9/site-packages/scanpy/neighbors/**init**.py:576], in Neighbors.compute_neighbors(self, n_neighbors, n_pcs, use_rep, knn, method, transformer, metric, metric_kwds, random_state)
574 self.knn = knn
575 X = _choose_representation(self._adata, use_rep=use_rep, n_pcs=n_pcs)
--> 576 self._distances = transformer.fit_transform(X)
577 knn_indices, knn_distances = _get_indices_distances_from_sparse_matrix(
578 self._distances, n_neighbors
579 )
580 if shortcut:
581 # self._distances is a sparse matrix with a diag of 1, fix that

File [~/.conda/envs/moscot/lib/python3.9/site-packages/sklearn/utils/_set_output.py:319] in _wrap_method_output..wrapped(self, X, *args, **kwargs)
317 [[@wraps](https://github.com/wraps)](https://github.com/wraps)(f)
318 def wrapped(self, X, *args, **kwargs):
--> 319 data_to_wrap = f(self, X, *args, **kwargs)
320 if isinstance(data_to_wrap, tuple):
321 # only wrap the first output for cross decomposition
322 return_tuple = (
323 _wrap_data_with_container(method, data_to_wrap[0], X, self),
324 *data_to_wrap[1:],
325 )

File [~/.conda/envs/moscot/lib/python3.9/site-packages/sklearn/neighbors/_graph.py:481] in KNeighborsTransformer.fit_transform(self, X, y)
459 def fit_transform(self, X, y=None):
460 """Fit to data, then transform it.
461
462 Fits transformer to X and y with optional parameters fit_params
(...)
479 The matrix is of CSR format.
480 """
--> 481 return self.fit(X).transform(X)

File [~/.conda/envs/moscot/lib/python3.9/site-packages/sklearn/base.py:1382] in _fit_context..decorator..wrapper(estimator, *args, **kwargs)
1377 partial_fit_and_fitted = (
1378 fit_method.**name** == "partial_fit" and _is_fitted(estimator)
1379 )
1381 if not global_skip_validation and not partial_fit_and_fitted:
-> 1382 estimator._validate_params()
1384 with config_context(
1385 skip_parameter_validation=(
1386 prefer_skip_nested_validation or global_skip_validation
1387 )
1388 ):
1389 return fit_method(estimator, *args, **kwargs)

File [~/.conda/envs/moscot/lib/python3.9/site-packages/sklearn/base.py:436] in BaseEstimator._validate_params(self)
428 def _validate_params(self):
429 """Validate types and values of constructor parameters
430
431 The expected type and values must be defined in the `_parameter_constraints`
(...)
434 accepted constraints.
435 """
--> 436 validate_parameter_constraints(
437 self._parameter_constraints,
438 self.get_params(deep=False),
439 caller_name=self.**class**.**name**,
440 )

File [~/.conda/envs/moscot/lib/python3.9/site-packages/sklearn/utils/_param_validation.py:98] in validate_parameter_constraints(parameter_constraints, params, caller_name)
92 else:
93 constraints_str = (
94 f"{', '.join([str(c) for c in constraints[:-1]])} or"
95 f" {constraints[-1]}"
96 )
---> 98 raise InvalidParameterError(
99 f"The {param_name!r} parameter of {caller_name} must be"
100 f" {constraints_str}. Got {param_val!r} instead."
101 )

InvalidParameterError: The 'n_neighbors' parameter of KNeighborsTransformer must be an int in the range [1, inf) or None. Got 0 instead.

Versions:

My cellrank version is 2.0.6, python version is 3.9, and scanpy version is 1.10.3.

@Yiikea Yiikea added the bug Something isn't working label Apr 6, 2025
@Yiikea Yiikea marked this as a duplicate of #1256 Apr 6, 2025
@WeilerP
Copy link
Member

WeilerP commented Apr 9, 2025

@Yiikea, I cannot immediately pinpoint the issue. I only see that there seems to be an issue with the coupling between time points 0 and 4; Scanpy throws the warning "n_obs too small: adjusting to n_neighbors = 1" here, i.e., it looks like your data appears to have only one observation - or none at all - in one time point; otherwise, n_neighbors would not be set to 1. You can check the number of observations per time point with

adata2.obs["time"].value_counts()

for example. If each time point has more than one observation, could you please share some details on what your AnnData object looks like, i.e., the fields and some general details about the data, like the time points and a corresponding number of observations, for example?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants