Troubleshooting

No marker genes remain after filtering

Likely cause: thresholds are too strict or marker genes do not overlap table.var_names.

Inspect: ed.summarize_marker_table(result.markers_df) or read_markers_dataframe(..., return_diagnostics=True).

Action: relax log2fc_min, pval_cutoff, top_n_genes, ribosomal/mitochondrial filters, or fix gene identifiers.

Gene names do not overlap

Likely cause: one table uses symbols and the other uses Ensembl IDs.

Inspect: compare set(markers_df["names"]) with set(table.var_names).

Action: map identifiers upstream and rerun marker loading.

posterior_df is None

Likely cause: list-style marker_genes was used, so Phase 1 acts as a row mask.

Inspect: result.diagnostics["assignment_matrix"].

Action: use a grouped marker table for cell-type-specific priors, or use assignment_df/phase2_result for this workflow.

All rows are unassigned

Likely cause: all score rows are zero, tied, or below minimum_evidence.

Inspect: row maxima in result.assignment_df and result.assigned_labels.

Action: inspect marker overlap, relax assignment settings, or use a different Phase 2 method.

Too many ties

Likely cause: equal score rows or insufficient marker specificity.

Inspect: result.assignment_df.loc[row].sort_values(ascending=False).

Action: use more specific markers, increase marker counts, or adjust tie_tolerance carefully.

Phase 1 priors are all zero

Likely cause: no marker signal passed Phase 1 filtering.

Inspect: result.phase1_result.sum(axis=1) and marker overlap.

Action: use filtering_algorithm="quantile" as a fast exploratory shortcut, relax quantile, or check gene identifiers. The standard Phase 1 workflow uses permutation filtering.

UCell scores are all zero

Likely cause: too few detected positive markers, constant rows, all-zero rows, or overly strict expression_threshold.

Inspect: result.diagnostics["phase2"] and UCell marker counts.

Action: lower min_markers, lower expression_threshold, or review marker roles.

No negative markers are present

Likely cause: marker table has no negative role rows or signed Scanpy inference was not requested.

Inspect: result.markers_df["marker_role"].value_counts().

Action: provide manual negative markers, use reference phase-specific markers, or opt into marker_role_inference="scanpy_signed" for Scanpy-style markers.

Reference marker generation returns no markers

Likely cause: reference thresholds are too strict or too few cells remain per group.

Inspect: diagnostics from prepare_markers or read_markers_dataframe.

Action: relax reference thresholds or check group labels and expression layers.

PyDESeq2 raw-count validation fails

Likely cause: selected layer is not raw non-negative integer counts.

Inspect: adata.layers[layer] values and dtype.

Action: provide layer="counts" or another raw-count layer.

Insufficient pseudobulk replicates

Likely cause: sample_col does not contain enough biological replicates for target/rest comparisons.

Inspect: counts by groupby and sample_col.

Action: use true replicate labels, lower minimums only if scientifically justified, or use a different marker method.

Missing spatial coordinates

Likely cause: visualization or niche detection expected obsm["spatial"].

Inspect: table.obsm.keys() and table.obs.columns.

Action: add coordinates to table.obsm["spatial"] or provide x/y columns for niche detection.

Candidate pruning incompatibility

Likely cause: prior_weight <= 0, list-style marker_genes, or refine_group(mode="phase2").

Inspect: workflow parameters.

Action: disable candidate pruning, use grouped markers, or switch refinement to mode="full".

refine_group finds no eligible locations

Likely cause: parent_threshold is too high or the parent group has no support.

Inspect: parent.priors_df[parent_group] or parent.posterior_df[parent_group].

Action: lower parent_threshold, use the other parent_source, or review parent markers.

Optional SpatialData dependency missing

Likely cause: SpatialData extras are not installed.

Inspect: import errors mentioning spatialdata.

Action: install easydecon[spatial] or pass an AnnData table directly.

Documentation build import failures

Likely cause: missing core dependencies or environment-specific Numba/Scanpy cache behavior.

Inspect: the first Sphinx traceback.

Action: install python -m pip install -e ".[docs]"; if Scanpy import fails in the local environment, run with NUMBA_DISABLE_JIT=1.

High runtime for permutation Phase 1

Likely cause: large num_permutations, subsample_size, or many marker groups.

Inspect: Phase 1 progress bars and parameter values.

Action: use filtering_algorithm="quantile" for iteration when you need a fast exploratory shortcut, then return to permutation filtering for standard analyses.

Memory concerns

Likely cause: large spatial matrices, dense conversions in selected workflows, or high parallelism.

Inspect: matrix sparsity, selected Phase 2 method, and config.n_jobs.

Action: reduce n_jobs, use smaller marker sets, preserve sparse inputs, and avoid unnecessary full-data copies.