Repository navigation
Import CytePool's task functions from the top level, with one name per idea - #69
Merged
Merged
Conversation
parashardhapola
force-pushed
the
39a-api-additions-and-fixes
branch
from
October 27, 2026 17:22
8afa32a to
2ebd988
Compare
parashardhapola
marked this pull request as ready for review
October 27, 2026 17:43
parashardhapola
force-pushed
the
39b-api-renames-and-top-level
branch
from
October 27, 2026 17:43
95ba68f to
8d8b4e6
Compare
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.
Summary
This is the second of two API pull requests. The first added the conveniences that the
guides needed and changed no existing call; this one renames and moves, so that every
change of a name is checked on its own. Nothing is released yet, so the old names are
not kept.
import cytepoolgives the 56 functions and classes an analysis starts from(
from cytepool import limma_voom, camera, meta_analysis, ...), listed with__version__incytepool.__all__and in the package's docstring by question, thedefault first, and documented there, once each. The building blocks on arrays stay
in
cytepool.stats, the figures incytepool.plotting, the parts of a design incytepool.design, andcytepool.normalizationas it is. Eight module files arerenamed after what they compute, so that no module has a top-level function's name
(
cytepool.gseais the function); the functions on arrays of three of them move tocytepool.stats:cytepool.stats.meta_analysis.fit_meta_analysis,cytepool.stats.sumrank.fit_sumrankandcytepool.stats.variance_fractions.variance_fractions.and take a result of
limma_voomorlimma_trendwith a group and a contrast:camera(result, sets, id_column="symbol")tests the group's fit, which the guideshad to rebuild by hand. roast returns one row per set, as mroast does.
StudyResults, in one argument order:meta_analysis(studies),replication(studies, group, contrast),sumrank(studies, group, contrast)andheld_out_prediction(studies, contrast), which, with SumRank's permutations, readsthe cases and controls from the contrast.
plot_forest(meta, feature)draws thestudies' results that the meta-analysis keeps, and marks a study that did not
measure the gene "not measured".
cubes and results ("gene" stays for gene sets and networks),
df_<which>,<qualifier>_p_value,log2_*,signfor a number of -1 or 1,sample_groups,id_columnfor a column of ids andfeature_idsfor the ids of an array, the cube'stables as
samplesandgroupswherever a cube is built,confidence_levelandcompression_level.No computed number changes. An equivalence check ran the first pull request and this
branch in separate processes on the same inputs, each old call made in this branch
through the new call that replaces it and each output read in the old names: 24,388
calls, compared element by element. Every difference it found is an intended one,
checked by its rule: texts that name a renamed thing, calls that now accept None for
an option's default, refusals that name a changed argument, and calls that draw
permutations without a seed, which agree bit for bit once seeded.
Changes
Every public change, with its reason.
The top level
import cytepoolnow gives the 56 functions and classes an analysis starts from, listed with__version__incytepool.__all__and in the package's docstring by question, the default first; before, it held only__version__. Why: the functions and classes an analysis starts from are imported from the top level, by one documented name each; the building blocks stay in cytepool.stats. The API reference documents each of them there, ascytepool.limma_voom. The modules that implement them can still be imported, except the eight renamed below.Modules renamed
cytepool.gseacytepool.gene_set_enrichmentcytepool.over_representationcytepool.over_representation_analysiscytepool.principal_componentscytepool.principal_component_analysiscytepool.variance_partitioningcytepool.variance_componentsandcytepool.stats.variance_fractionscytepool.held_out_predictioncytepool.held_out_studiescytepool.meta_analysiscytepool.meta_analysis_of_studiesandcytepool.stats.meta_analysiscytepool.replicationcytepool.replication_across_studiescytepool.sumrankcytepool.sumrank_across_studiesandcytepool.stats.sumrankcytepool.stats.gene_set_testscytepool.gene_set_testscytepool.stats.rotation_gene_set_testscytepool.rotation_gene_set_testsFunctions and classes moved or renamed
cytepool.gsea.gseacytepool.gseacytepool.over_representation.over_representationcytepool.over_representationcytepool.principal_components.principal_componentscytepool.principal_componentscytepool.principal_components.PrincipalComponentscytepool.PrincipalComponentscytepool.variance_partitioning.variance_partitioningcytepool.variance_partitioningcytepool.variance_partitioning.VariancePartitioningResultcytepool.VariancePartitioningResultcytepool.variance_partitioning.variance_fractionscytepool.stats.variance_fractions.variance_fractionscytepool.variance_partitioning.VarianceFractionscytepool.stats.variance_fractions.VarianceFractionscytepool.held_out_prediction.held_out_predictioncytepool.held_out_predictioncytepool.held_out_prediction.HeldOutPredictioncytepool.HeldOutPredictioncytepool.meta_analysis.differential_expression_meta_analysiscytepool.meta_analysiscytepool.meta_analysis.MetaAnalysisResultcytepool.MetaAnalysisResultcytepool.meta_analysis.meta_analysiscytepool.stats.meta_analysis.fit_meta_analysiscytepool.meta_analysis.MetaAnalysisFitcytepool.stats.meta_analysis.MetaAnalysisFitcytepool.meta_analysis.align_study_resultscytepool.StudyResults.tablecytepool.replication.differential_expression_replicationcytepool.replicationcytepool.replication.ReplicationResultcytepool.ReplicationResultcytepool.sumrank.differential_expression_sumrankcytepool.sumrankcytepool.sumrank.SumRankResultcytepool.SumRankResultcytepool.sumrank.sumrankcytepool.stats.sumrank.fit_sumrankcytepool.sumrank.SumRankFitcytepool.stats.sumrank.SumRankFitcytepool.stats.gene_set_tests.cameracytepool.cameracytepool.stats.gene_set_tests.frycytepool.frycytepool.stats.rotation_gene_set_tests.roastcytepool.roastcytepool.stats.rotation_gene_set_tests.mroastcytepool.mroastcytepool.stats.rotation_gene_set_tests.romercytepool.romercytepool.normalization.log_cpmcytepool.normalization.log2_cpmcytepool.stats.quasi_likelihood.average_log_cpmcytepool.stats.quasi_likelihood.average_log2_cpmcytepool.plotting.plot_gene_variance_fractionscytepool.plotting.plot_feature_variance_fractionsArguments renamed, added or removed
cytepool.from_cellssamplessample_labelscytepool.from_cellsgroupsgroup_labelscytepool.from_cellssample_tablesamplescytepool.from_cellsgroup_tablegroupscytepool.from_anndatasamplesample_columncytepool.from_anndatagroupgroup_columncytepool.from_anndatasample_tablesamplescytepool.from_anndatagroup_tablegroupscytepool.from_mudatasample_tablesamplescytepool.from_mudatagroup_tablegroupscytepool.write_cubelevelcompression_levelcytepool.io.zarr.write_arraylevelcompression_levelcytepool.io.zarr.check_compressionlevelcompression_levelcytepool.normalization.filter_by_expressiongroupsample_groupscytepool.GeneSetssourcenamecytepool.read_gmtsourcenamecytepool.stats.multiple_testing.adjust_p_valuespp_valuescytepool.stats.multiple_testing.proportion_of_true_nullspp_valuescytepool.stats.meta_analysis.fit_meta_analysislevelconfidence_levelcytepool.meta_analysisresultsstudiescytepool.meta_analysislevelconfidence_levelcytepool.replicationcollectionstudiescytepool.replicationresultscytepool.sumrankcollectionstudiescytepool.sumrankresultscytepool.sumrankn_studies_summedcytepool.stats.sumrank.fit_sumrankn_studies_summedcytepool.held_out_predictioncollectionstudiescytepool.held_out_predictionresultscytepool.held_out_predictionn_genesn_featurescytepool.held_out_predictionn_studies_summedcytepool.cameraydatacytepool.cameragene_idsfeature_idscytepool.cameragroupcytepool.cameraid_columncytepool.fryydatacytepool.frygene_idsfeature_idscytepool.frygroupcytepool.fryid_columncytepool.roastydatacytepool.roastgene_idsfeature_idscytepool.roastgroupcytepool.roastid_columncytepool.mroastydatacytepool.mroastgene_idsfeature_idscytepool.mroastgroupcytepool.mroastid_columncytepool.romerydatacytepool.romergene_idsfeature_idscytepool.romergroupcytepool.romerid_columncytepool.gsvagene_idsfeature_idscytepool.gsvaid_columncytepool.ssgseagene_idsfeature_idscytepool.ssgseaid_columncytepool.combined_z_scoresgene_idsfeature_idscytepool.combined_z_scoresid_columncytepool.plagegene_idsfeature_idscytepool.plageid_columncytepool.ulmgene_idsfeature_idscytepool.mlmgene_idsfeature_idscytepool.weighted_aggregategene_idsfeature_idscytepool.propellerf_testf_testscytepool.plotting.plot_barcodegene_idsfeature_idscytepool.plotting.plot_dotplotgenesfeaturescytepool.plotting.plot_feature_variance_fractionsgenesfeaturescytepool.plotting.plot_foreststudiescytepool.plotting.plot_sumrankn_labelstopcytepool.CompositionResultf_testcytepool.StudyResults.tablecollectioncytepool.StudyResults.tableresultscytepool.MetaAnalysisResultstudy_resultscytepool.gsvavalues='log_cpm'values='log2_cpm'cytepool.ssgseavalues='log_cpm'values='log2_cpm'cytepool.combined_z_scoresvalues='log_cpm'values='log2_cpm'cytepool.plagevalues='log_cpm'values='log2_cpm'cytepool.plotting.plot_dotplotstandard_scale='gene'standard_scale='feature'Attributes of results and records
cytepool.stats.empirical_bayes.ModeratedFitprior_dfdf_priorcytepool.stats.empirical_bayes.ModeratedFitlodslog_oddscytepool.stats.empirical_bayes.TreatFitprior_dfdf_priorcytepool.stats.empirical_bayes.SqueezedVariancesprior_dfdf_priorcytepool.stats.dream.ModeratedFixedEffectTestsresidual_dfdf_residualcytepool.stats.dream.ModeratedFixedEffectTestsprior_dfdf_priorcytepool.stats.dream.ModeratedFixedEffectTestslodslog_oddscytepool.stats.quasi_likelihood.QuasiLikelihoodFitprior_dfdf_priorcytepool.stats.quasi_likelihood.QuasiLikelihoodFitaverage_log_cpmaverage_log2_cpmcytepool.stats.quasi_likelihood.QuasiLikelihoodTestlog_fold_changelog2_fold_changecytepool.stats.quasi_likelihood.QuasiLikelihoodTestaverage_log_cpmaverage_log2_cpmcytepool.stats.mixed_models.MixedModelFitresidual_dfdf_residualcytepool.design.checks.DesignReportresidual_dfdf_residualcytepool.stats.voom.VoomResultlog_cpmlog2_cpmcytepool.stats.combined_p_values.CombinedPValuesp_value_upup_p_valuecytepool.stats.combined_p_values.CombinedPValuesp_value_downdown_p_valuecytepool.stats.combined_p_values.CombinedPValuesdirectionsigncytepool.Activitiesp_valuesp_valuecytepool.Activitiesadjusted_p_valuesadjusted_p_valuecytepool.PathwayScoressamplesprofilescytepool.GeneSetssourcenamecytepool.stats.meta_analysis.MetaAnalysisFitlevelconfidence_levelcytepool.MetaAnalysisResultstudy_resultscytepool.CompositionResultf_testf_testscytepool.SumRankResulttablefeaturescytepool.ReplicationResultgenesfeaturescytepool.HeldOutPredictiongenesfeaturescytepool.PrincipalComponentsgenesfeaturesColumns of tables
b_statisticlog_oddsprior_dfdf_prioradjusted_mixed_p_valuemixed_adjusted_p_valuedirectionsignn_genesn_featuresn_genes_same_directionn_features_same_directionn_foundn_features_foundn_found_in_bothn_features_found_in_bothn_testedn_features_testedn_foundn_features_foundtestedanalysedn_featuresn_features_testedn_genes_upn_features_upn_genes_downn_features_downsample_idprofile_idSettings and provenance records
levelconfidence_leveln_genesn_featuresn_studies_summedf_testf_testssourcenameanalysisdifferential_expression_meta_analysismeta_analysisanalysisdifferential_expression_replicationreplicationanalysisdifferential_expression_sumranksumrankvalueslog_cpmlog2_cpmCalls and outputs that changed form
Other changes
renders the method's description from the module that implements it and documents
the top-level names of its topic, as
cytepool.limma_voom, so that every name has oneentry.
cytepool.stats.meta_analysis,cytepool.stats.sumrankandcytepool.stats.variance_fractionsare documented on the pages of their topics, andcytepool.__version__on the index. The pages that explain the statistics, thereference pages, the site's pages and the README name the new functions, arguments
and attributes.
imports come from the top level; the gene sets guide tests the result itself and
builds the regulons with
Network.to_gene_sets(); the pathway activity guide teststhe scores and activities with
limma; the studies guides name the aligned celltypes (
group_names), runanalyse_each_studyand takeStudyResults.matrix; thequality guide draws its trend figures from the result (
fit); the bulk guide readsedgeR's and DESeq2's calls by gene with their
table()methods and draws theirdispersions; the pool cells guide pools an arbitrary set of samples with
Cube.with_columns; the repeated-measures guide filters both models by thecondition,
expression_filter={"sample_groups": "condition"}, so that they test thesame genes, and says why.
labels=True,each sample's label goes above its point, moves in where it would cross the frame and
up where it would overlap another, with a line to its point when it moved, as
plot_sumrankplaces its labels. A PCA plot, drawn to one scale along both axes,widens where the labels need room above, so that no sample leaves the frame. The
quality guide's MDS plot had a label across the frame and labels on top of each
other. The labels keep the samples' order and their points.
table()names F-tests only when a result has some. A result of severalcontrasts without F-tests says "the result has 3 contrasts; name one with contrast",
where differential expression said "contrasts and F-tests" whatever it held.
weightswith a result names arrays only, since romer takes noVoomResult.Choices, and why
gene_setcolumn. roast tests one set, given as a list ofids, which has no name; its row has the columns of mroast's otherwise, and mroast
names its sets.
propeller(f_tests=)takes a factor or a list of factors, each F-test named byits factor, and
dream_voom(f_tests=)keeps its mapping of names to contrasts. Amapping of contrasts for
propeller, and a factor fordream_voom, would testhypotheses that neither function tests today, which need validation of their own
against speckle and variancePartition; this pull request changes no number.
id_columnnamesfor the scores, the activities and the gene-set tests alike;
feature_idsgives theids of an array's columns. A cube took a sequence of ids too, which is refused now
with the way to add a column,
Cube.with_columns(features=...).compression_leveleverywhere a compression level is given: alsocytepool.io.zarr.write_arrayandcheck_compression, whichwrite_cubepasses itto, so that one idea keeps one name down to the file format.
fit_sumranktakesn_studies_summed, assumrankandheld_out_predictiondo, so that the number of studies summed is given alike at both levels.
trendandrobusttake the result's moderation (False for an array), and thegroup, the contrast and the variable a permutation shuffles are read from the
studies' results when they hold one; None given for them was refused before.
(
MetaAnalysisResult.study_results), whichplot_forestdraws. It tells "notmeasured" from "not tested" only for a
StudyResults, whose collection records whateach study measured; for a plain mapping of results it says "not tested", as before.
the group's fit kept, as a named contrast of a rank-deficient group is tested in
limma_voom, and take the trend and robust settings of the result's moderation bydefault; for an array they default to False, as before.
renamed ones, but document nothing themselves:
cytepool.cubeandcytepool.iore-export their names for code that imports them there, with an empty
__all__, andcytepool.designlists its parts but notDesign.argument, attribute or column (
PathwayScores(n_profiles=...),PrincipalComponents(n_features=...),GeneSetswith itsname), so that theguides print what they printed; the language pull request applies the copy rules to
every text at once.
plot_significant_genesandplot_replicated_geneskeep theirnames: they draw genes found, as their pages call them, and renaming figures was
outside the plan.
Validation
Equivalence check. The first API pull request (8afa32a) and this branch ran in
separate processes, each in its own environment, on the same inputs: every public entry
point with its valid call, the inputs of every validation script built from the same
seeds with the calls the scripts make, and edge cases. The inputs call the API as the
first pull request names it. In this branch's process each changed call went through an
adapter to the new call, written from the list of changes above, and each output was
read in the old names (classes, attributes, columns, settings and the names of
analyses), so that both outputs were compared at the same places, element by element,
NaN equal to NaN and any other difference measured in units in the last place. Every
call's arguments were kept, to compare the inputs of calls that take objects with
renamed parts. The intended differences, each with the rule that checks it, were
written down before any result was read; three that the first run found were added
afterwards with their rules, each a consequence of a change listed above (the last
three rows of the table).
24,388 calls in 10,471 cases, 826,881 output parts with 183,085,849 elements; 3,421
differences in 1,073 calls, each explained:
filter_by_expression'ssample_groups, the scores' genes not found, and what the gene-set tests andpropeller(f_tests=)accept) by their own pairs of old and new wordstrendandrobustof camera, fry, roast and mroast;group,contrast,proportion_of_studiesandpermuteof the combining functionsgene_idsisid_columnid_columnheld_out_predictiongiven one ofvariable,caseandcontrolas None, with the other twogseaof a result,weighted_aggregateof a cube or a result, and their edge casesrng=1in both trees: their 46 output arrays identicalroast's adapter rebuilt the first pull request's table of four rows from the new
row, each value taken unchanged from its column and the up_or_down proportion the
larger of proportion_down and proportion_up: the rebuilt tables equal the old ones,
bit for bit. The parts that only this branch has were set aside and counted, 442 in
all: the studies' results a meta-analysis keeps, propeller's F-tests by name, the
profile_idcolumn of pathway scores, the columns of the principal components'table of features other than
position(which holds the old positions, compared),and the setting
n_studies_summedof held-out prediction. No part of the first pullrequest's outputs was set aside.
Not compared, in either tree: the inputs of
validation/sumrank.py, whose scriptimports scikit-learn, which the environments lack (SumRank's entry points and edge
cases are compared). A figure is compared by its axes' labels; its drawing is checked
by the tests and by eye below. The PCA plot's widening for labels came after the
check; it changes no computed value, and the tests below check it.
Inventory. Every public callable of the first pull request's inventory (263 in the
three groups of
tests/test_masked_inputs.py, with 1,037 arguments) is unchanged ornamed in the list of changes above: 31 callables and 58 arguments renamed, moved or
removed, each listed.
Validation scripts. Every script in
validation/was updated to the new names andrun on both trees with the same reference environments. 29 print exactly the first
pull request's output; the other 9 differ only in times they measure (
distributions,pool_cells,cube_reads,negative_binomial_fits,quasi_likelihood,interferon_stimulated_pbmcs, whose peak memory and version line differ too), in twocheck names of
sumrankthat now namefit_sumrank, and in the path and line of awarning or a traceback that the edits moved (
combined_p_values_and_replication,anndata_conversion). No value, tolerance or verdict changed.anndata_conversionstops in both trees at its LIANA reference, which no environment here has, after
pooling, exporting and running the scanpy and decoupler references with the new
arguments. The fixtures in
tests/dataare unchanged (--write-fixtureswas not run;the scripts still write the keys the tests read).
Pages. All 15 notebooks were rewritten and executed again, and every code cell's
printed text was compared with the outputs before this change: every number the same,
except the repeated-measures guide, whose limma-voom model now filters by the
condition as the dream model does (3,651 genes tested instead of 5,125, 2,536 called
instead of 3,168; 2,456 called by both instead of 2,273, with the same correlation of
0.999). Texts differ where they name renamed things: the gene sets'
name:(with thenetwork's file and digest, which
to_gene_setskeeps), the aligned cell types' namesin "Combine studies", a cube's history ("the rows of the sample table given"), and the
line of code that gsea's warning quotes. Both π₁ lines of the replication guide are
unchanged, as that page had been executed with the λ = 0.5 default already, and
roast's p-value in "Gene sets" is the same number, read from
up_p_value. All 42figures were looked at, against the 41 before: 34 are identical. Of the others, three
name the aligned cell types instead of their ontology ids, the forest plot of "Combine
studies" marks the study that did not measure the gene "not measured", the dot plot's
colour bar says "scaled per feature", the bulk guide's figure of dispersions is new,
the quality guide's MDS plot has its labels inside the frame and apart, and the pool
cells guide's second PCA plot has other ticks on its y-axis, as its legend is now
placed once the plot has its scale. No legend covers a point, a line or a label, and
every label and count is inside its frame.
make -C docs check-outputspasses on all15.
Tests
tolerance changed; the two that imported renamed modules import the new files.
the code under test: the top level against its docstring and the modules that
implement each name, and importing it loads no optional library; camera, fry, roast,
mroast and romer of a result against the same test of the group's voom values or
log2 CPM, weights, design rows and contrast passed by hand, with the ids of a column;
their refusals of a dream-voom result and of a design, weights or ids given with a
result, and romer's of voom's observation weights;
held_out_predictionreading thecases from the contrast against the explicit
variable,caseandcontrol, and acontrast that compares no two levels needing them; SumRank's
n_studies_summedagainst the proportion that gives it, its permutations of the factor the contrast
compares against
permutegiven, and the group and contrast left out for studiesthat have one, also for replication; the meta-analysis of a
StudyResultsagainstthat of its results;
plot_foresttelling a study that did not measure a gene fromone that left it out; propeller's F-tests of two factors against each factor's
alone; the principal components' table of features against their positions and the
cube's columns; and the labels of MDS and PCA plots, after the final draw, inside the
frame, apart and on their points, with every sample inside the frame, which fails on
the previous placement.
tests/test_masked_inputs.pyclassifies every renamed, moved and new callable andargument;
tests/test_documentation.pyknows that a top-level name is documented atthe top level and that a module's description may be rendered without its members;
tests/test_private_names.pyfollows the moved files; anddocs/coverage_exemptions.tomlfollows the renames.uv run pytest -q --durations=15: 5156 passed, 18 skipped (zstd needs Python 3.14).OPENBLAS_CORETYPE=Sandybridge, 4 threads,NUMBA_CPU_NAME=generic, a fresh cache): 5156 passed, 18 skipped.ruff check,ruff format --checkandmypypass;make -C docs apiandmake -C docs htmlbuild without a warning.