-
Notifications
You must be signed in to change notification settings - Fork 45
Feat: Enable user defined FDR threshold #212
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -53,6 +53,8 @@ class MetricsEvaluator: | |
| pdex_kwargs: dict[str, Any] | None = None | ||
| Keyword arguments for parallel_differential_expression. | ||
| These will overwrite arguments passed to MetricsEvaluator.__init__ if they conflict. | ||
| fdr_threshold: float = 0.05 | ||
| FDR threshold for DE significance used in DE metrics. | ||
| """ | ||
|
|
||
| def __init__( | ||
|
|
@@ -71,6 +73,7 @@ def __init__( | |
| prefix: str | None = None, | ||
| pdex_kwargs: dict[str, Any] | None = None, | ||
| skip_de: bool = False, | ||
| fdr_threshold: float = 0.05, | ||
| ): | ||
| # Enable a global string cache for categorical columns | ||
| pl.enable_string_cache() | ||
|
|
@@ -107,6 +110,7 @@ def __init__( | |
|
|
||
| self.outdir = outdir | ||
| self.prefix = prefix | ||
| self.fdr_threshold = fdr_threshold | ||
|
|
||
| def compute( | ||
| self, | ||
|
|
@@ -117,9 +121,13 @@ def compute( | |
| write_csv: bool = True, | ||
| break_on_error: bool = False, | ||
| ) -> tuple[pl.DataFrame, pl.DataFrame]: | ||
| # Inject fdr_threshold into DE metric configs | ||
| de_metric_configs = _build_de_metric_configs(self.fdr_threshold) | ||
| merged_configs = {**de_metric_configs, **(metric_configs or {})} | ||
|
|
||
| pipeline = MetricPipeline( | ||
| profile=profile, | ||
| metric_configs=metric_configs, | ||
| metric_configs=merged_configs, | ||
| break_on_error=break_on_error, | ||
| ) | ||
| if skip_metrics is not None: | ||
|
|
@@ -156,6 +164,31 @@ def compute( | |
| return results, agg_results | ||
|
|
||
|
|
||
| def _build_de_metric_configs(fdr_threshold: float) -> dict[str, dict[str, Any]]: | ||
| """Build metric configs with fdr_threshold for all DE metrics that accept it.""" | ||
| de_metrics_with_fdr = [ | ||
| "de_spearman_sig", | ||
| "de_direction_match", | ||
| "de_spearman_lfc_sig", | ||
| "de_sig_genes_recall", | ||
| "de_nsig_counts", | ||
| "pr_auc", | ||
| "roc_auc", | ||
| # overlap/precision metrics | ||
| "overlap_at_N", | ||
| "overlap_at_50", | ||
| "overlap_at_100", | ||
| "overlap_at_200", | ||
| "overlap_at_500", | ||
| "precision_at_N", | ||
| "precision_at_50", | ||
| "precision_at_100", | ||
| "precision_at_200", | ||
| "precision_at_500", | ||
| ] | ||
| return {metric: {"fdr_threshold": fdr_threshold} for metric in de_metrics_with_fdr} | ||
|
Comment on lines
+167
to
+189
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Instead of hardcoding the list of metrics that accept Here's a suggested implementation that uses the import inspect
from .metrics import metrics_registry
from ._types import MetricTypedef _build_de_metric_configs(fdr_threshold: float) -> dict[str, dict[str, Any]]:
"""Build metric configs with fdr_threshold for all DE metrics that accept it."""
de_metrics_with_fdr = []
for metric_name in metrics_registry.list_metrics(MetricType.DE):
metric_info = metrics_registry.get_metric(metric_name)
func_to_inspect = metric_info.func
if metric_info.is_class:
func_to_inspect = func_to_inspect.__init__
sig = inspect.signature(func_to_inspect)
if "fdr_threshold" in sig.parameters:
de_metrics_with_fdr.append(metric_name)
return {metric: {"fdr_threshold": fdr_threshold} for metric in de_metrics_with_fdr} |
||
|
|
||
|
|
||
| def _build_anndata_pair( | ||
| real: ad.AnnData | str, | ||
| pred: ad.AnnData | str, | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This block duplicates logic for setting the
fdr_thresholdthat is now handled within theMetricsEvaluatorclass (in_build_de_metric_configs). To avoid code duplication and improve maintainability, this block should be removed. Thefdr_thresholdfrom the command-line arguments should be passed directly to theMetricsEvaluatorconstructor instead.After removing this, you'll need to update the
MetricsEvaluatorinstantiations in this file to includefdr_threshold=args.fdr_threshold. I cannot suggest this change directly as it is outside the diff.