Clear code smell flagged by vulture, jscpd, and radon/xenon - #559
Merged
Merged
Conversation
Ran the maintainability tools from CLAUDE.md across scrise/ and analysis/ and addressed what they flagged. Dead code (vulture): - Drop analysis.gating.getHiResOldLupus and the cell_type_conv table it alone consumed; no caller, and no dataset in the repo carries the "Cell Type Old" column it reads. - Drop figure3.plot_cell_perc_corr; no caller. - Note in gateThomsonCellsLeiden/Thomson_Doublet docstrings, and beside the marker_genes_* tables, that these are hand-run cache builders and reference data, so their lack of an in-repo caller is deliberate. Duplication (jscpd): - plotting/factors.py: _draw_unit_scaled_heatmap now backs both plot_eigenstate_factors and plot_gene_factors. - plotting/pacmap.py: _plot_continuous_pacmap now backs plot_gene_pacmap and plot_wp_pacmap. - plotting/general.py: _two_gene_frame now backs gene_plot_cells and plot_cell_gene_corr. Complexity (radon/xenon): - rank_selection._resolve_bicv_inputs (C-14) splits into _resolve_dataset_alias, _validate_split_params, _ensure_condition_idxs. - annotation_alignment.score_cell_type_alignment (C-11) hands its per-component loop to _component_metrics. - factor_io._attach_raw_data (C-11) splits into _subset_raw_cells and _subset_raw_genes. No function in scrise/ or analysis/ now ranks worse than B. Along the way: - Document pf2/bicv's condition_key and adata, and plot_condition_factors' control_pattern and control_conditions. - groupDrugs and plot_correlation_cmp_cell_count_perc annotated X as the anndata module rather than anndata.AnnData; figureS9e_f's plot_logistic_regression_component declared -> pd.DataFrame while returning a tuple. ty now reports no diagnostics across scrise/. - Drop 24 unused unpacked `fig` variables in the plotting tests, which were drowning vulture's output: it goes from 37 hits to 11, all of them now genuine documented exceptions. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Ran the maintainability tools from
CLAUDE.mdacrossscrise/andanalysis/and addressed what they flagged. (Note:CLAUDE.mdrefers to acccrise/package; the source actually lives inscrise/andanalysis/, andvulture/radon/xenonaren't in thedevgroup, so I ran them viauv run --with ...rather than touchingpyproject.toml.)Dead code — vulture
Most of the 37 hits were false positives (pytest fixtures, the
fbuildentry point, figure helpers vulture can't trace across modules). Three were real:analysis.gating.getHiResOldLupusand thecell_type_convtable it alone consumed — no caller, and no dataset in the repo carries the"Cell Type Old"column it reads.figure3.plot_cell_perc_corr— no caller.gateThomsonCellsLeiden,Thomson_Doubletand themarker_genes_*tables are the hand-run cache-builder/reference-data exceptionCLAUDE.mddescribes. Left in place, with a short note saying why they have no in-repo caller.Duplication — jscpd
13 clones (1.02% of Python lines), 0 in
analysis/. Three were genuine copy-paste and got shared helpers:plotting/factors.py—_draw_unit_scaled_heatmapbacksplot_eigenstate_factorsandplot_gene_factors(16-line clone).plotting/pacmap.py—_plot_continuous_pacmapbacksplot_gene_pacmapandplot_wp_pacmap(11-line clone).plotting/general.py—_two_gene_framebacksgene_plot_cellsandplot_cell_gene_corr(10-line clone).Three others were left alone on purpose: the
_pf2_utils.py↔factorization.pyhit is a pass-through kwarg signature, and the other two are repeated docstring parameter blocks. Deduplicating those costs documentation without saving logic.Complexity — radon / xenon
Maintainability index was rank A for every file. Seven functions ranked C; the three in library code are now below threshold:
rank_selection._resolve_bicv_inputs(C-14) →_resolve_dataset_alias,_validate_split_params,_ensure_condition_idxs.annotation_alignment.score_cell_type_alignment(C-11) → per-component loop extracted as_component_metrics.factor_io._attach_raw_data(C-11) →_subset_raw_cells/_subset_raw_genes.Still rank C: three test functions and
figureS9a_d.run_benchmarks. These are pre-existing, their complexity is assertion/parametrization chains where splitting hurts readability, andCLAUDE.mdsays to leave those.Along the way
Parametersblocks found three functions with undocumented parameters —pf2andbicv(condition_key,adata) andplot_condition_factors(control_pattern,control_conditions). Now documented.ty):groupDrugsandplot_correlation_cmp_cell_count_percannotatedXas theanndatamodule rather thananndata.AnnData;figureS9e_f.plot_logistic_regression_componentdeclared-> pd.DataFramewhile returning a tuple.tynow reports zero diagnostics acrossscrise/.figvariables in the plotting tests, flagged by both vulture and ruff'sRUF059. This was the highest-value item: it was drowning vulture's output, which drops from 37 hits to 11 — all 11 now genuine documented exceptions, so the report is worth reading again. Also removed one stale# noqa: E402.Verification
ruff checkandruff formatclean;ty check scrise/clean. Full suite: 133 passed, 1 skipped. Every refactored function has existing smoke-test coverage.Deliberately out of scope
Flagging these rather than folding them in, since each is a judgment call:
NPY002legacynp.randomuses (mostlyfigure6.pyand tests) —conftest.pyalready usesdefault_rng, so the codebase is split, but migrating changes the numbers drawn and would move the golden-regression baselines.calculateFMS; paramscellType,doEmbedding,cbarMax,labelType,ThomsonNorm) — renaming is breaking.X/adatadual-alias params onpf2/bicv— part of why_resolve_bicv_inputsranked C; worth retiring if one is a compatibility shim.factor_io.py:110catchesImportError, AttributeError, KeyError, ValueError, OSErrorfor the vsparse→read_h5adfallback. OnlyImportErroris the intended case; the rest silently turn genuine data errors into a path change.tydiagnostics inanalysis/— 5 uninstalled optional deps (cupy,scib,scanorama,harmonypy), most of the rest anndataDataFrame | Dataset2Dunion noise.RET504assign-then-return, mostly in figure scripts — churn.makeFigurepreamble, i.e. the intended template.🤖 Generated with Claude Code