Skip to content

Comments

feat: support np.random.Generator#3983

Draft
flying-sheep wants to merge 4 commits intomainfrom
pa/rng
Draft

feat: support np.random.Generator#3983
flying-sheep wants to merge 4 commits intomainfrom
pa/rng

Conversation

@flying-sheep
Copy link
Member

@flying-sheep flying-sheep commented Feb 23, 2026

The idea is to make the code behave as closely as possible to how it did, but make it read like modern code:

  1. add decorator that converts random_state into rng argument (deduplicating them and using 0 by default)
  2. add helpers that allow old behavior (e.g. for APIs that only take RandomState)
  3. after this PR: make feat: presets #3653 change the default behavior when a preset is passed.

TODO:

  • add the decorator
  • add helpers for restarting (e.g. if 0 was passed, it’d be reused by the functions called in function body)
  • for the functions that called it: re-add the np.random.seed calls (maybe if isinstance(rng, _FakeRandomGen): gen = legacy_numpy_gen(rng) or so?)
    • partially done, finish the work
  • add spawn to _FakeRandomGen (that does nothing) and use spawn for a tree structure
  • figure out how to handle persistence for new RNG (random_state in adata.uns[thing]["params")

@codecov
Copy link

codecov bot commented Feb 24, 2026

❌ 3 Tests Failed:

Tests completed Failed Passed Skipped
2397 3 2394 349
View the top 3 failed test(s) by shortest run time
tests/test_scrublet.py::test_scrublet_simulate_doublets
Stack Traces | 0.061s run time
#x1B[0m#x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92mtest_scrublet_simulate_doublets#x1B[39;49;00m():#x1B[90m#x1B[39;49;00m
    #x1B[90m    #x1B[39;49;00m#x1B[33m"""Check that doublet simulation runs and simulates some doublets."""#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        adata_obs = pbmc200()#x1B[90m#x1B[39;49;00m
        sc.pp.filter_genes(adata_obs, min_cells=#x1B[94m3#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
        sc.pp.filter_cells(adata_obs, min_genes=#x1B[94m3#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
        adata_obs.layers[#x1B[33m"#x1B[39;49;00m#x1B[33mraw#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m] = adata_obs.X#x1B[90m#x1B[39;49;00m
        sc.pp.normalize_total(adata_obs)#x1B[90m#x1B[39;49;00m
        logged = sc.pp.log1p(adata_obs, copy=#x1B[94mTrue#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        _ = sc.pp.highly_variable_genes(logged)#x1B[90m#x1B[39;49;00m
        adata_obs = adata_obs[:, logged.var[#x1B[33m"#x1B[39;49;00m#x1B[33mhighly_variable#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m]]#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        adata_sim = sc.pp.scrublet_simulate_doublets(#x1B[90m#x1B[39;49;00m
            adata_obs, sim_doublet_ratio=#x1B[94m0.02#x1B[39;49;00m, layer=#x1B[33m"#x1B[39;49;00m#x1B[33mraw#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
>       assert_array_equal(#x1B[90m#x1B[39;49;00m
            adata_sim.obsm[#x1B[33m"#x1B[39;49;00m#x1B[33mdoublet_parents#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
            np.array([[#x1B[94m13#x1B[39;49;00m, #x1B[94m132#x1B[39;49;00m], [#x1B[94m106#x1B[39;49;00m, #x1B[94m43#x1B[39;49;00m], [#x1B[94m152#x1B[39;49;00m, #x1B[94m3#x1B[39;49;00m], [#x1B[94m160#x1B[39;49;00m, #x1B[94m103#x1B[39;49;00m]]),#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31mE       AssertionError: #x1B[0m
#x1B[1m#x1B[31mE       Arrays are not equal#x1B[0m
#x1B[1m#x1B[31mE       #x1B[0m
#x1B[1m#x1B[31mE       Mismatched elements: 8 / 8 (100%)#x1B[0m
#x1B[1m#x1B[31mE       First 5 mismatches are at indices:#x1B[0m
#x1B[1m#x1B[31mE        [0, 0]: 175 (ACTUAL), 13 (DESIRED)#x1B[0m
#x1B[1m#x1B[31mE        [0, 1]: 58 (ACTUAL), 132 (DESIRED)#x1B[0m
#x1B[1m#x1B[31mE        [1, 0]: 94 (ACTUAL), 106 (DESIRED)#x1B[0m
#x1B[1m#x1B[31mE        [1, 1]: 71 (ACTUAL), 43 (DESIRED)#x1B[0m
#x1B[1m#x1B[31mE        [2, 0]: 18 (ACTUAL), 152 (DESIRED)#x1B[0m
#x1B[1m#x1B[31mE       Max absolute difference among violations: 192#x1B[0m
#x1B[1m#x1B[31mE       Max relative difference among violations: 64.#x1B[0m
#x1B[1m#x1B[31mE        ACTUAL: array([[175,  58],#x1B[0m
#x1B[1m#x1B[31mE              [ 94,  71],#x1B[0m
#x1B[1m#x1B[31mE              [ 18, 195],#x1B[0m
#x1B[1m#x1B[31mE              [ 97,  47]])#x1B[0m
#x1B[1m#x1B[31mE        DESIRED: array([[ 13, 132],#x1B[0m
#x1B[1m#x1B[31mE              [106,  43],#x1B[0m
#x1B[1m#x1B[31mE              [152,   3],#x1B[0m
#x1B[1m#x1B[31mE              [160, 103]])#x1B[0m

#x1B[1m#x1B[31mtests/test_scrublet.py#x1B[0m:227: AssertionError
tests/test_plotting.py::test_heatmap_var_as_dict
Stack Traces | 0.262s run time
image_comparer = <function image_comparer.<locals>.save_and_compare at 0x7fa21011ab90>

    #x1B[0m#x1B[37m@needs#x1B[39;49;00m.leidenalg#x1B[90m#x1B[39;49;00m
    #x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92mtest_heatmap_var_as_dict#x1B[39;49;00m(image_comparer) -> #x1B[94mNone#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
        save_and_compare_images = partial(image_comparer, ROOT, tol=#x1B[94m15#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        pbmc = pbmc68k_reduced()#x1B[90m#x1B[39;49;00m
        sc.tl.leiden(#x1B[90m#x1B[39;49;00m
            pbmc,#x1B[90m#x1B[39;49;00m
            key_added=#x1B[33m"#x1B[39;49;00m#x1B[33mclusters#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            resolution=#x1B[94m0.5#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            flavor=#x1B[33m"#x1B[39;49;00m#x1B[33migraph#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            n_iterations=#x1B[94m2#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            directed=#x1B[94mFalse#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
        #x1B[90m# call umap to trigger colors for the clusters#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        sc.pl.umap(pbmc, color=#x1B[33m"#x1B[39;49;00m#x1B[33mclusters#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, show=#x1B[94mFalse#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
        marker_genes_dict = {#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33m3#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m: [#x1B[33m"#x1B[39;49;00m#x1B[33mGNLY#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mNKG7#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33m1#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m: [#x1B[33m"#x1B[39;49;00m#x1B[33mFCER1A#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33m2#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m: [#x1B[33m"#x1B[39;49;00m#x1B[33mCD3D#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33m0#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m: [#x1B[33m"#x1B[39;49;00m#x1B[33mFCGR3A#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33m4#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m: [#x1B[33m"#x1B[39;49;00m#x1B[33mCD79A#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mMS4A1#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
        }#x1B[90m#x1B[39;49;00m
        sc.pl.heatmap(#x1B[90m#x1B[39;49;00m
            adata=pbmc,#x1B[90m#x1B[39;49;00m
            var_names=marker_genes_dict,#x1B[90m#x1B[39;49;00m
            groupby=#x1B[33m"#x1B[39;49;00m#x1B[33mclusters#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            vmin=-#x1B[94m2#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            vmax=#x1B[94m2#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            cmap=#x1B[33m"#x1B[39;49;00m#x1B[33mRdBu_r#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            dendrogram=#x1B[94mTrue#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            swap_axes=#x1B[94mTrue#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            show=#x1B[94mFalse#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
>       save_and_compare_images(#x1B[33m"#x1B[39;49;00m#x1B[33mheatmap_var_as_dict#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31mE       AssertionError: Image files did not match.#x1B[0m
#x1B[1m#x1B[31mE       RMS Value:  25.151928203164957#x1B[0m
#x1B[1m#x1B[31mE       Expected:   file:.../_images/heatmap_var_as_dict/expected.png#x1B[0m
#x1B[1m#x1B[31mE       Actual:     file:.../_images/heatmap_var_as_dict/actual.png#x1B[0m
#x1B[1m#x1B[31mE       Difference: file:.../_images/heatmap_var_as_dict/actual-failed-diff.png#x1B[0m
#x1B[1m#x1B[31mE       Tolerance:  15#x1B[0m

#x1B[1m#x1B[31mtests/test_plotting.py#x1B[0m:147: AssertionError
tests/notebooks/test_pbmc3k.py::test_pbmc3k
Stack Traces | 4.61s run time
subtests = <_pytest.subtests.Subtests object at 0x7f8389d8f770>
image_comparer = <function image_comparer.<locals>.save_and_compare at 0x7f83896a7950>

    #x1B[0m#x1B[37m@needs#x1B[39;49;00m.leidenalg#x1B[90m#x1B[39;49;00m
    #x1B[90m# https://github..../pandas/issues/61928#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
    #x1B[37m@pytest#x1B[39;49;00m.mark.filterwarnings(#x1B[33m"#x1B[39;49;00m#x1B[33mignore:invalid value encountered in cast:RuntimeWarning#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
    #x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92mtest_pbmc3k#x1B[39;49;00m(subtests: pytest.Subtests, image_comparer) -> #x1B[94mNone#x1B[39;49;00m:  #x1B[90m# noqa: PLR0915#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        #x1B[90m# ensure violin plots and other non-determinstic plots have deterministic behavior#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        np.random.seed(#x1B[94m0#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
        save_and_compare_images = partial(image_comparer, ROOT, tol=#x1B[94m20#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
        adata = sc.datasets.pbmc3k()#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        #x1B[90m# Preprocessing#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        sc.pl.highest_expr_genes(adata, n_top=#x1B[94m20#x1B[39;49;00m, show=#x1B[94mFalse#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
        save_and_compare_images(#x1B[33m"#x1B[39;49;00m#x1B[33mhighest_expr_genes#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        sc.pp.filter_cells(adata, min_genes=#x1B[94m200#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
        sc.pp.filter_genes(adata, min_cells=#x1B[94m3#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        mito_genes = [name #x1B[94mfor#x1B[39;49;00m name #x1B[95min#x1B[39;49;00m adata.var_names #x1B[94mif#x1B[39;49;00m name.startswith(#x1B[33m"#x1B[39;49;00m#x1B[33mMT-#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m)]#x1B[90m#x1B[39;49;00m
        #x1B[90m# for each cell compute fraction of counts in mito genes vs. all genes#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        #x1B[90m# the `.A1` is only necessary as X is sparse to transform to a dense array after summing#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        adata.obs[#x1B[33m"#x1B[39;49;00m#x1B[33mpercent_mito#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m] = (#x1B[90m#x1B[39;49;00m
            np.sum(adata[:, mito_genes].X, axis=#x1B[94m1#x1B[39;49;00m).A1 / np.sum(adata.X, axis=#x1B[94m1#x1B[39;49;00m).A1#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
        #x1B[90m# add the total counts per cell as observations-annotation to adata#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        adata.obs[#x1B[33m"#x1B[39;49;00m#x1B[33mn_counts#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m] = adata.X.sum(axis=#x1B[94m1#x1B[39;49;00m).A1#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        #x1B[94mwith#x1B[39;49;00m subtests.test(#x1B[33m"#x1B[39;49;00m#x1B[33mviolin#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m):#x1B[90m#x1B[39;49;00m
            sc.pl.violin(#x1B[90m#x1B[39;49;00m
                adata,#x1B[90m#x1B[39;49;00m
                [#x1B[33m"#x1B[39;49;00m#x1B[33mn_genes#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mn_counts#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mpercent_mito#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
                jitter=#x1B[94mFalse#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
                multi_panel=#x1B[94mTrue#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
                show=#x1B[94mFalse#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            )#x1B[90m#x1B[39;49;00m
            save_and_compare_images(#x1B[33m"#x1B[39;49;00m#x1B[33mviolin#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        #x1B[94mwith#x1B[39;49;00m subtests.test(#x1B[33m"#x1B[39;49;00m#x1B[33mscatter_1#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m):#x1B[90m#x1B[39;49;00m
            sc.pl.scatter(adata, x=#x1B[33m"#x1B[39;49;00m#x1B[33mn_counts#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, y=#x1B[33m"#x1B[39;49;00m#x1B[33mpercent_mito#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, show=#x1B[94mFalse#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
            save_and_compare_images(#x1B[33m"#x1B[39;49;00m#x1B[33mscatter_1#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
        #x1B[94mwith#x1B[39;49;00m subtests.test(#x1B[33m"#x1B[39;49;00m#x1B[33mscatter_2#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m):#x1B[90m#x1B[39;49;00m
            sc.pl.scatter(adata, x=#x1B[33m"#x1B[39;49;00m#x1B[33mn_counts#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, y=#x1B[33m"#x1B[39;49;00m#x1B[33mn_genes#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, show=#x1B[94mFalse#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
            save_and_compare_images(#x1B[33m"#x1B[39;49;00m#x1B[33mscatter_2#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        adata = adata[adata.obs[#x1B[33m"#x1B[39;49;00m#x1B[33mn_genes#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m] < #x1B[94m2500#x1B[39;49;00m, :]#x1B[90m#x1B[39;49;00m
        adata = adata[adata.obs[#x1B[33m"#x1B[39;49;00m#x1B[33mpercent_mito#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m] < #x1B[94m0.05#x1B[39;49;00m, :]#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        adata.raw = sc.pp.log1p(adata, copy=#x1B[94mTrue#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        #x1B[94mwith#x1B[39;49;00m pytest.warns(#x1B[96mFutureWarning#x1B[39;49;00m, match=#x1B[33mr#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[33msc#x1B[39;49;00m#x1B[33m\#x1B[39;49;00m#x1B[33m.pp#x1B[39;49;00m#x1B[33m\#x1B[39;49;00m#x1B[33m.normalize_total#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m):#x1B[90m#x1B[39;49;00m
            sc.pp.normalize_per_cell(adata, counts_per_cell_after=#x1B[94m1e4#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        #x1B[94mwith#x1B[39;49;00m pytest.warns(#x1B[96mFutureWarning#x1B[39;49;00m, match=#x1B[33mr#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[33msc#x1B[39;49;00m#x1B[33m\#x1B[39;49;00m#x1B[33m.pp#x1B[39;49;00m#x1B[33m\#x1B[39;49;00m#x1B[33m.highly_variable_genes#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m):#x1B[90m#x1B[39;49;00m
            filter_result = sc.pp.filter_genes_dispersion(#x1B[90m#x1B[39;49;00m
                adata.X,#x1B[90m#x1B[39;49;00m
                min_mean=#x1B[94m0.0125#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
                max_mean=#x1B[94m3#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
                min_disp=#x1B[94m0.5#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            )#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        #x1B[94mwith#x1B[39;49;00m subtests.test(#x1B[33m"#x1B[39;49;00m#x1B[33mfilter_genes_dispersion#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m):#x1B[90m#x1B[39;49;00m
            #x1B[94mwith#x1B[39;49;00m pytest.warns(#x1B[96mFutureWarning#x1B[39;49;00m, match=#x1B[33mr#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[33msc#x1B[39;49;00m#x1B[33m\#x1B[39;49;00m#x1B[33m.pl#x1B[39;49;00m#x1B[33m\#x1B[39;49;00m#x1B[33m.highly_variable_genes#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m):#x1B[90m#x1B[39;49;00m
                sc.pl.filter_genes_dispersion(filter_result, show=#x1B[94mFalse#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
            save_and_compare_images(#x1B[33m"#x1B[39;49;00m#x1B[33mfilter_genes_dispersion#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        adata = adata[:, filter_result.gene_subset].copy()#x1B[90m#x1B[39;49;00m
        sc.pp.log1p(adata)#x1B[90m#x1B[39;49;00m
        sc.pp.regress_out(adata, [#x1B[33m"#x1B[39;49;00m#x1B[33mn_counts#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mpercent_mito#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m])#x1B[90m#x1B[39;49;00m
        sc.pp.scale(adata, max_value=#x1B[94m10#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        #x1B[90m# PCA#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        sc.pp.pca(adata, svd_solver=#x1B[33m"#x1B[39;49;00m#x1B[33marpack#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
        #x1B[94mwith#x1B[39;49;00m subtests.test(#x1B[33m"#x1B[39;49;00m#x1B[33mpca#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m):#x1B[90m#x1B[39;49;00m
            sc.pl.pca(adata, color=#x1B[33m"#x1B[39;49;00m#x1B[33mCST3#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, show=#x1B[94mFalse#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
            save_and_compare_images(#x1B[33m"#x1B[39;49;00m#x1B[33mpca#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        #x1B[94mwith#x1B[39;49;00m subtests.test(#x1B[33m"#x1B[39;49;00m#x1B[33mpca_variance_ratio#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m):#x1B[90m#x1B[39;49;00m
            sc.pl.pca_variance_ratio(adata, log=#x1B[94mTrue#x1B[39;49;00m, show=#x1B[94mFalse#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
            save_and_compare_images(#x1B[33m"#x1B[39;49;00m#x1B[33mpca_variance_ratio#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        #x1B[90m# Neighbors#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        sc.pp.neighbors(adata, n_neighbors=#x1B[94m10#x1B[39;49;00m, n_pcs=#x1B[94m40#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        #x1B[90m# Clustering the graph#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        sc.tl.leiden(#x1B[90m#x1B[39;49;00m
            adata,#x1B[90m#x1B[39;49;00m
            resolution=#x1B[94m0.9#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            random_state=#x1B[94m1#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            directed=#x1B[94mFalse#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            n_iterations=#x1B[94m2#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            flavor=#x1B[33m"#x1B[39;49;00m#x1B[33migraph#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        #x1B[94mwith#x1B[39;49;00m subtests.test(#x1B[33m"#x1B[39;49;00m#x1B[33mscatter_3#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m):#x1B[90m#x1B[39;49;00m
            sc.pl.scatter(adata, #x1B[33m"#x1B[39;49;00m#x1B[33mCST3#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mNKG7#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, color=#x1B[33m"#x1B[39;49;00m#x1B[33mleiden#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, show=#x1B[94mFalse#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
            save_and_compare_images(#x1B[33m"#x1B[39;49;00m#x1B[33mscatter_3#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        #x1B[90m# Finding marker genes#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        #x1B[90m# Due to incosistency with our test runner vs local, these clusters need to#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        #x1B[90m# be pre-annotated as the numbers for each cluster are not consistent.#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        marker_genes = [#x1B[90m#x1B[39;49;00m
            *[#x1B[33m"#x1B[39;49;00m#x1B[33mRP11-18H21.1#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mGZMK#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mCD79A#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mFCGR3A#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
            *[#x1B[33m"#x1B[39;49;00m#x1B[33mGNLY#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mS100A8#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mFCER1A#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mPPBP#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
        ]#x1B[90m#x1B[39;49;00m
        data_df = adata[:, marker_genes].to_df()#x1B[90m#x1B[39;49;00m
        data_df[#x1B[33m"#x1B[39;49;00m#x1B[33mleiden#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m] = adata.obs[#x1B[33m"#x1B[39;49;00m#x1B[33mleiden#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m]#x1B[90m#x1B[39;49;00m
        max_idxs = data_df.groupby(#x1B[33m"#x1B[39;49;00m#x1B[33mleiden#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, observed=#x1B[94mTrue#x1B[39;49;00m).mean().idxmax()#x1B[90m#x1B[39;49;00m
        #x1B[94mwith#x1B[39;49;00m subtests.test(#x1B[33m"#x1B[39;49;00m#x1B[33mmarker_genes_unique#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m):#x1B[90m#x1B[39;49;00m
            #x1B[94massert#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m max_idxs[marker_genes][#x1B[90m#x1B[39;49;00m
                max_idxs[marker_genes].duplicated(keep=#x1B[94mFalse#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
            ].tolist(), #x1B[33m"#x1B[39;49;00m#x1B[33mNot all marker genes are unique per cluster#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        leiden_relabel = {#x1B[90m#x1B[39;49;00m
            max_idxs[marker_gene]: #x1B[96mstr#x1B[39;49;00m(i) #x1B[94mfor#x1B[39;49;00m i, marker_gene #x1B[95min#x1B[39;49;00m #x1B[96menumerate#x1B[39;49;00m(marker_genes)#x1B[90m#x1B[39;49;00m
        }#x1B[90m#x1B[39;49;00m
        adata.obs[#x1B[33m"#x1B[39;49;00m#x1B[33mleiden_old#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m] = adata.obs[#x1B[33m"#x1B[39;49;00m#x1B[33mleiden#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m].copy()#x1B[90m#x1B[39;49;00m
>       adata.rename_categories(#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mleiden#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, [leiden_relabel[key] #x1B[94mfor#x1B[39;49;00m key #x1B[95min#x1B[39;49;00m #x1B[96msorted#x1B[39;49;00m(leiden_relabel.keys())]#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m

#x1B[1m#x1B[31mtests/notebooks/test_pbmc3k.py#x1B[0m:148: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:1129: in rename_categories
    #x1B[0m#x1B[96mself#x1B[39;49;00m.obs[key] = #x1B[96mself#x1B[39;49;00m.obs[key].cat.rename_categories(categories)#x1B[90m#x1B[39;49;00m
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../pandas/core/accessor.py#x1B[0m:112: in f
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m #x1B[96mself#x1B[39;49;00m._delegate_method(name, *args, **kwargs)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../core/arrays/categorical.py#x1B[0m:2982: in _delegate_method
    #x1B[0mres = method(*args, **kwargs)#x1B[90m#x1B[39;49;00m
          ^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../core/arrays/categorical.py#x1B[0m:1206: in rename_categories
    #x1B[0mcat._set_categories(new_categories)#x1B[90m#x1B[39;49;00m
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = ['0', '1', '0', '2', '4', ..., '6', '1', '1', '1', '0']
Length: 2638
Categories (8, object): ['0', '1', '2', '3', '4', '5', '6', '7']
categories = ['0', '2', '5', '4', '1', '6', ...], fastpath = False

    #x1B[0m#x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92m_set_categories#x1B[39;49;00m(#x1B[96mself#x1B[39;49;00m, categories, fastpath: #x1B[96mbool#x1B[39;49;00m = #x1B[94mFalse#x1B[39;49;00m) -> #x1B[94mNone#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
    #x1B[90m    #x1B[39;49;00m#x1B[33m"""#x1B[39;49;00m
    #x1B[33m    Sets new categories inplace#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m    Parameters#x1B[39;49;00m
    #x1B[33m    ----------#x1B[39;49;00m
    #x1B[33m    fastpath : bool, default False#x1B[39;49;00m
    #x1B[33m       Don't perform validation of the categories for uniqueness or nulls#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m    Examples#x1B[39;49;00m
    #x1B[33m    --------#x1B[39;49;00m
    #x1B[33m    >>> c = pd.Categorical(['a', 'b'])#x1B[39;49;00m
    #x1B[33m    >>> c#x1B[39;49;00m
    #x1B[33m    ['a', 'b']#x1B[39;49;00m
    #x1B[33m    Categories (2, object): ['a', 'b']#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m    >>> c._set_categories(pd.Index(['a', 'c']))#x1B[39;49;00m
    #x1B[33m    >>> c#x1B[39;49;00m
    #x1B[33m    ['a', 'c']#x1B[39;49;00m
    #x1B[33m    Categories (2, object): ['a', 'c']#x1B[39;49;00m
    #x1B[33m    """#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m fastpath:#x1B[90m#x1B[39;49;00m
            new_dtype = CategoricalDtype._from_fastpath(categories, #x1B[96mself#x1B[39;49;00m.ordered)#x1B[90m#x1B[39;49;00m
        #x1B[94melse#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
            new_dtype = CategoricalDtype(categories, ordered=#x1B[96mself#x1B[39;49;00m.ordered)#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m (#x1B[90m#x1B[39;49;00m
            #x1B[95mnot#x1B[39;49;00m fastpath#x1B[90m#x1B[39;49;00m
            #x1B[95mand#x1B[39;49;00m #x1B[96mself#x1B[39;49;00m.dtype.categories #x1B[95mis#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[94mNone#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            #x1B[95mand#x1B[39;49;00m #x1B[96mlen#x1B[39;49;00m(new_dtype.categories) != #x1B[96mlen#x1B[39;49;00m(#x1B[96mself#x1B[39;49;00m.dtype.categories)#x1B[90m#x1B[39;49;00m
        ):#x1B[90m#x1B[39;49;00m
>           #x1B[94mraise#x1B[39;49;00m #x1B[96mValueError#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
                #x1B[33m"#x1B[39;49;00m#x1B[33mnew categories need to have the same number of #x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
                #x1B[33m"#x1B[39;49;00m#x1B[33mitems as the old categories!#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            )#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31mE           ValueError: new categories need to have the same number of items as the old categories!#x1B[0m

#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../core/arrays/categorical.py#x1B[0m:931: ValueError

To view more test analytics, go to the Test Analytics Dashboard
📋 Got 3 mins? Take this short survey to help us improve Test Analytics.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Switch to numpy.random.Generator

1 participant