Skip to content

perf: chan's parallel mean-var algorithm for dask#4123

Draft
ilan-gold wants to merge 6 commits into
ig/two_pass_hvg_v3from
ig/chan_mean_var
Draft

perf: chan's parallel mean-var algorithm for dask#4123
ilan-gold wants to merge 6 commits into
ig/two_pass_hvg_v3from
ig/chan_mean_var

Conversation

@ilan-gold
Copy link
Copy Markdown
Contributor

@ilan-gold ilan-gold commented May 15, 2026

See https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#Parallel_algorithm

Based on a discussion with @zboldyga

This has two benefits - it allows us to calculate mean/var in one pass instead of effectively two (square sum and sum squared) and gets rid of a numerical instability issue that @zboldyga found the solution to (see removed comment)

  • Closes #
  • Tests included or not required because:

@ilan-gold ilan-gold changed the title Ig/chan mean var perf: chan's parallel mean-var algorithm May 15, 2026
@codecov
Copy link
Copy Markdown

codecov Bot commented May 15, 2026

❌ 17 Tests Failed:

Tests completed Failed Passed Skipped
2617 17 2600 160
View the top 3 failed test(s) by shortest run time
tests/test_highly_variable_genes.py::test_subset_inplace_consistency[None-scipy_csr_mat-seurat_v3]
Stack Traces | 0.013s run time
subtests = <_pytest.subtests.Subtests object at 0x7f57c0d2f710>
flavor = 'seurat_v3', array_type = <class 'scipy.sparse._csr.csr_matrix'>
batch_key = None

    #x1B[0m#x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[90m#x1B[39;49;00m
        #x1B[33m"#x1B[39;49;00m#x1B[33mflavor#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
        [#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mseurat#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mcell_ranger#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            pytest.param(#x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, marks=needs.skmisc),#x1B[90m#x1B[39;49;00m
            pytest.param(#x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3_paper#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, marks=needs.skmisc),#x1B[90m#x1B[39;49;00m
        ],#x1B[90m#x1B[39;49;00m
    )#x1B[90m#x1B[39;49;00m
    #x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[90m#x1B[39;49;00m
        #x1B[33m"#x1B[39;49;00m#x1B[33marray_type#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
        [#x1B[90m#x1B[39;49;00m
            p#x1B[90m#x1B[39;49;00m
            #x1B[94mfor#x1B[39;49;00m p #x1B[95min#x1B[39;49;00m ARRAY_TYPES#x1B[90m#x1B[39;49;00m
            #x1B[94mif#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mdask#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[95min#x1B[39;49;00m p.id #x1B[95mor#x1B[39;49;00m (#x1B[33m"#x1B[39;49;00m#x1B[33m1d_chunked#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95min#x1B[39;49;00m p.id #x1B[95mand#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mcsr#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95min#x1B[39;49;00m p.id)#x1B[90m#x1B[39;49;00m
        ],#x1B[90m#x1B[39;49;00m
    )#x1B[90m#x1B[39;49;00m
    #x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[33m"#x1B[39;49;00m#x1B[33mbatch_key#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, [#x1B[94mNone#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mbatch#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_subset_inplace_consistency#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
        subtests: pytest.Subtests,#x1B[90m#x1B[39;49;00m
        flavor: Literal[#x1B[33m"#x1B[39;49;00m#x1B[33mseurat#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mcell_ranger#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3_paper#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
        array_type,#x1B[90m#x1B[39;49;00m
        batch_key: Literal[#x1B[33m"#x1B[39;49;00m#x1B[33mbatch#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m] | #x1B[94mNone#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
    ) -> #x1B[94mNone#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
    #x1B[90m    #x1B[39;49;00m#x1B[33m"""Tests `n_top_genes=n`.#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m    - if `inplace` and `subset` interact correctly#x1B[39;49;00m
    #x1B[33m    - for both the `seurat` and `cell_ranger` flavors#x1B[39;49;00m
    #x1B[33m    - for dask arrays and non-dask arrays#x1B[39;49;00m
    #x1B[33m    - for both with and without batch_key#x1B[39;49;00m
    #x1B[33m    """#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        rng = np.random.default_rng(#x1B[94m0#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
        adata = (#x1B[90m#x1B[39;49;00m
            sc.datasets.blobs(n_observations=#x1B[94m20#x1B[39;49;00m, n_variables=#x1B[94m80#x1B[39;49;00m, rng=rng)#x1B[90m#x1B[39;49;00m
            #x1B[94mif#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[95min#x1B[39;49;00m flavor#x1B[90m#x1B[39;49;00m
            #x1B[94melse#x1B[39;49;00m pbmc3k()[:#x1B[94m1500#x1B[39;49;00m, :#x1B[94m1000#x1B[39;49;00m].copy()#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
        adata.obs[#x1B[33m"#x1B[39;49;00m#x1B[33mbatch#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m] = rng.choice([#x1B[33m"#x1B[39;49;00m#x1B[33ma#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mb#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m], adata.shape[#x1B[94m0#x1B[39;49;00m])#x1B[90m#x1B[39;49;00m
        adata.X = array_type(np.abs(adata.X).astype(#x1B[96mint#x1B[39;49;00m))#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m flavor #x1B[95min#x1B[39;49;00m {#x1B[33m"#x1B[39;49;00m#x1B[33mseurat#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mcell_ranger#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m}:#x1B[90m#x1B[39;49;00m
            sc.pp.normalize_total(adata, target_sum=#x1B[94m1e4#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
            sc.pp.log1p(adata)#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        n_genes = adata.shape[#x1B[94m1#x1B[39;49;00m]#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        adatas: #x1B[96mdict#x1B[39;49;00m[#x1B[96mbool#x1B[39;49;00m, AnnData] = {}#x1B[90m#x1B[39;49;00m
        dfs: #x1B[96mdict#x1B[39;49;00m[#x1B[96mbool#x1B[39;49;00m, pd.DataFrame] = {}#x1B[90m#x1B[39;49;00m
        #x1B[90m# for loops instead of parametrization to compare between settings#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        #x1B[94mfor#x1B[39;49;00m subset, inplace #x1B[95min#x1B[39;49;00m itertools.product([#x1B[94mTrue#x1B[39;49;00m, #x1B[94mFalse#x1B[39;49;00m], repeat=#x1B[94m2#x1B[39;49;00m):#x1B[90m#x1B[39;49;00m
            adata_copy = adata.copy()#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
>           output_df = sc.pp.highly_variable_genes(#x1B[90m#x1B[39;49;00m
                adata_copy,#x1B[90m#x1B[39;49;00m
                flavor=flavor,#x1B[90m#x1B[39;49;00m
                n_top_genes=#x1B[94m15#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
                batch_key=batch_key,#x1B[90m#x1B[39;49;00m
                subset=subset,#x1B[90m#x1B[39;49;00m
                inplace=inplace,#x1B[90m#x1B[39;49;00m
            )#x1B[90m#x1B[39;49;00m

#x1B[1m#x1B[31mtests/test_highly_variable_genes.py#x1B[0m:686: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
#x1B[1m#x1B[.../scanpy/preprocessing/_highly_variable_genes.py#x1B[0m:780: in highly_variable_genes
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m _highly_variable_genes_seurat_v3(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[.../scanpy/preprocessing/_highly_variable_genes.py#x1B[0m:196: in _highly_variable_genes_seurat_v3
    #x1B[0maggregated_mean_var = ad.AnnData(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:254: in __init__
    #x1B[0m#x1B[96mself#x1B[39;49;00m._init_as_actual(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:448: in _init_as_actual
    #x1B[0m#x1B[96mself#x1B[39;49;00m._obs = _gen_dataframe(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../...../_temp/uv-python-dir/cpython-3.14.5-linux-x86_64-gnu/lib/python3.14/functools.py#x1B[0m:982: in wrapper
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m dispatch(args[#x1B[94m0#x1B[39;49;00m].#x1B[91m__class__#x1B[39;49;00m)(*args, **kw)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

anno =    __hvg_v3_batch_info__
0                      0
index_names = ['obs_names', 'row_names']

    #x1B[0m#x1B[37m@_gen_dataframe#x1B[39;49;00m.register(pd.DataFrame)#x1B[90m#x1B[39;49;00m
    #x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92m_gen_dataframe_df#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
        anno: pd.DataFrame,#x1B[90m#x1B[39;49;00m
        index_names: Iterable[#x1B[96mstr#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
        *,#x1B[90m#x1B[39;49;00m
        source: Literal[#x1B[33m"#x1B[39;49;00m#x1B[33mX#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mshape#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
        attr: Literal[#x1B[33m"#x1B[39;49;00m#x1B[33mobs#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mvar#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
        length: #x1B[96mint#x1B[39;49;00m | #x1B[94mNone#x1B[39;49;00m = #x1B[94mNone#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
    ):#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m #x1B[96misinstance#x1B[39;49;00m(anno.index, pd.MultiIndex):#x1B[90m#x1B[39;49;00m
            msg = (#x1B[90m#x1B[39;49;00m
                #x1B[33m"#x1B[39;49;00m#x1B[33mpandas.MultiIndex not supported as index for obs or var on declaration.#x1B[39;49;00m#x1B[33m\n#x1B[39;49;00m#x1B[33m\#x1B[39;49;00m
    #x1B[33m            You can set `obs_names` manually although most operations after will error or convert to str.#x1B[39;49;00m#x1B[33m\n#x1B[39;49;00m#x1B[33m\#x1B[39;49;00m
    #x1B[33m            This behavior will likely be clarified in a future breaking release.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            )#x1B[90m#x1B[39;49;00m
            #x1B[94mraise#x1B[39;49;00m #x1B[96mValueError#x1B[39;49;00m(msg)#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m length #x1B[95mis#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[94mNone#x1B[39;49;00m #x1B[95mand#x1B[39;49;00m length != #x1B[96mlen#x1B[39;49;00m(anno):#x1B[90m#x1B[39;49;00m
            #x1B[94mraise#x1B[39;49;00m _mk_df_error(source, attr, length, #x1B[96mlen#x1B[39;49;00m(anno))#x1B[90m#x1B[39;49;00m
        anno = anno.copy(deep=#x1B[94mFalse#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m is_string_dtype(anno.index[~anno.index.isna()]):#x1B[90m#x1B[39;49;00m
            msg = #x1B[33m"#x1B[39;49;00m#x1B[33mTransforming to str index.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
>           warnings.warn(msg, ImplicitModificationWarning, stacklevel=#x1B[94m2#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31mE           anndata._warnings.ImplicitModificationWarning: Transforming to str index.#x1B[0m

#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/aligned_df.py#x1B[0m:93: ImplicitModificationWarning
tests/test_highly_variable_genes.py::test_subset_inplace_consistency[None-scipy_csr_arr-seurat_v3]
Stack Traces | 0.014s run time
subtests = <_pytest.subtests.Subtests object at 0x7f57c083e8d0>
flavor = 'seurat_v3', array_type = <class 'scipy.sparse._csr.csr_array'>
batch_key = None

    #x1B[0m#x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[90m#x1B[39;49;00m
        #x1B[33m"#x1B[39;49;00m#x1B[33mflavor#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
        [#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mseurat#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mcell_ranger#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            pytest.param(#x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, marks=needs.skmisc),#x1B[90m#x1B[39;49;00m
            pytest.param(#x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3_paper#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, marks=needs.skmisc),#x1B[90m#x1B[39;49;00m
        ],#x1B[90m#x1B[39;49;00m
    )#x1B[90m#x1B[39;49;00m
    #x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[90m#x1B[39;49;00m
        #x1B[33m"#x1B[39;49;00m#x1B[33marray_type#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
        [#x1B[90m#x1B[39;49;00m
            p#x1B[90m#x1B[39;49;00m
            #x1B[94mfor#x1B[39;49;00m p #x1B[95min#x1B[39;49;00m ARRAY_TYPES#x1B[90m#x1B[39;49;00m
            #x1B[94mif#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mdask#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[95min#x1B[39;49;00m p.id #x1B[95mor#x1B[39;49;00m (#x1B[33m"#x1B[39;49;00m#x1B[33m1d_chunked#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95min#x1B[39;49;00m p.id #x1B[95mand#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mcsr#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95min#x1B[39;49;00m p.id)#x1B[90m#x1B[39;49;00m
        ],#x1B[90m#x1B[39;49;00m
    )#x1B[90m#x1B[39;49;00m
    #x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[33m"#x1B[39;49;00m#x1B[33mbatch_key#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, [#x1B[94mNone#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mbatch#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_subset_inplace_consistency#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
        subtests: pytest.Subtests,#x1B[90m#x1B[39;49;00m
        flavor: Literal[#x1B[33m"#x1B[39;49;00m#x1B[33mseurat#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mcell_ranger#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3_paper#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
        array_type,#x1B[90m#x1B[39;49;00m
        batch_key: Literal[#x1B[33m"#x1B[39;49;00m#x1B[33mbatch#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m] | #x1B[94mNone#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
    ) -> #x1B[94mNone#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
    #x1B[90m    #x1B[39;49;00m#x1B[33m"""Tests `n_top_genes=n`.#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m    - if `inplace` and `subset` interact correctly#x1B[39;49;00m
    #x1B[33m    - for both the `seurat` and `cell_ranger` flavors#x1B[39;49;00m
    #x1B[33m    - for dask arrays and non-dask arrays#x1B[39;49;00m
    #x1B[33m    - for both with and without batch_key#x1B[39;49;00m
    #x1B[33m    """#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        rng = np.random.default_rng(#x1B[94m0#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
        adata = (#x1B[90m#x1B[39;49;00m
            sc.datasets.blobs(n_observations=#x1B[94m20#x1B[39;49;00m, n_variables=#x1B[94m80#x1B[39;49;00m, rng=rng)#x1B[90m#x1B[39;49;00m
            #x1B[94mif#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[95min#x1B[39;49;00m flavor#x1B[90m#x1B[39;49;00m
            #x1B[94melse#x1B[39;49;00m pbmc3k()[:#x1B[94m1500#x1B[39;49;00m, :#x1B[94m1000#x1B[39;49;00m].copy()#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
        adata.obs[#x1B[33m"#x1B[39;49;00m#x1B[33mbatch#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m] = rng.choice([#x1B[33m"#x1B[39;49;00m#x1B[33ma#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mb#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m], adata.shape[#x1B[94m0#x1B[39;49;00m])#x1B[90m#x1B[39;49;00m
        adata.X = array_type(np.abs(adata.X).astype(#x1B[96mint#x1B[39;49;00m))#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m flavor #x1B[95min#x1B[39;49;00m {#x1B[33m"#x1B[39;49;00m#x1B[33mseurat#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mcell_ranger#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m}:#x1B[90m#x1B[39;49;00m
            sc.pp.normalize_total(adata, target_sum=#x1B[94m1e4#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
            sc.pp.log1p(adata)#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        n_genes = adata.shape[#x1B[94m1#x1B[39;49;00m]#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        adatas: #x1B[96mdict#x1B[39;49;00m[#x1B[96mbool#x1B[39;49;00m, AnnData] = {}#x1B[90m#x1B[39;49;00m
        dfs: #x1B[96mdict#x1B[39;49;00m[#x1B[96mbool#x1B[39;49;00m, pd.DataFrame] = {}#x1B[90m#x1B[39;49;00m
        #x1B[90m# for loops instead of parametrization to compare between settings#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        #x1B[94mfor#x1B[39;49;00m subset, inplace #x1B[95min#x1B[39;49;00m itertools.product([#x1B[94mTrue#x1B[39;49;00m, #x1B[94mFalse#x1B[39;49;00m], repeat=#x1B[94m2#x1B[39;49;00m):#x1B[90m#x1B[39;49;00m
            adata_copy = adata.copy()#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
>           output_df = sc.pp.highly_variable_genes(#x1B[90m#x1B[39;49;00m
                adata_copy,#x1B[90m#x1B[39;49;00m
                flavor=flavor,#x1B[90m#x1B[39;49;00m
                n_top_genes=#x1B[94m15#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
                batch_key=batch_key,#x1B[90m#x1B[39;49;00m
                subset=subset,#x1B[90m#x1B[39;49;00m
                inplace=inplace,#x1B[90m#x1B[39;49;00m
            )#x1B[90m#x1B[39;49;00m

#x1B[1m#x1B[31mtests/test_highly_variable_genes.py#x1B[0m:686: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
#x1B[1m#x1B[.../scanpy/preprocessing/_highly_variable_genes.py#x1B[0m:780: in highly_variable_genes
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m _highly_variable_genes_seurat_v3(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[.../scanpy/preprocessing/_highly_variable_genes.py#x1B[0m:196: in _highly_variable_genes_seurat_v3
    #x1B[0maggregated_mean_var = ad.AnnData(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:254: in __init__
    #x1B[0m#x1B[96mself#x1B[39;49;00m._init_as_actual(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:448: in _init_as_actual
    #x1B[0m#x1B[96mself#x1B[39;49;00m._obs = _gen_dataframe(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../...../_temp/uv-python-dir/cpython-3.14.5-linux-x86_64-gnu/lib/python3.14/functools.py#x1B[0m:982: in wrapper
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m dispatch(args[#x1B[94m0#x1B[39;49;00m].#x1B[91m__class__#x1B[39;49;00m)(*args, **kw)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

anno =    __hvg_v3_batch_info__
0                      0
index_names = ['obs_names', 'row_names']

    #x1B[0m#x1B[37m@_gen_dataframe#x1B[39;49;00m.register(pd.DataFrame)#x1B[90m#x1B[39;49;00m
    #x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92m_gen_dataframe_df#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
        anno: pd.DataFrame,#x1B[90m#x1B[39;49;00m
        index_names: Iterable[#x1B[96mstr#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
        *,#x1B[90m#x1B[39;49;00m
        source: Literal[#x1B[33m"#x1B[39;49;00m#x1B[33mX#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mshape#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
        attr: Literal[#x1B[33m"#x1B[39;49;00m#x1B[33mobs#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mvar#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
        length: #x1B[96mint#x1B[39;49;00m | #x1B[94mNone#x1B[39;49;00m = #x1B[94mNone#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
    ):#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m #x1B[96misinstance#x1B[39;49;00m(anno.index, pd.MultiIndex):#x1B[90m#x1B[39;49;00m
            msg = (#x1B[90m#x1B[39;49;00m
                #x1B[33m"#x1B[39;49;00m#x1B[33mpandas.MultiIndex not supported as index for obs or var on declaration.#x1B[39;49;00m#x1B[33m\n#x1B[39;49;00m#x1B[33m\#x1B[39;49;00m
    #x1B[33m            You can set `obs_names` manually although most operations after will error or convert to str.#x1B[39;49;00m#x1B[33m\n#x1B[39;49;00m#x1B[33m\#x1B[39;49;00m
    #x1B[33m            This behavior will likely be clarified in a future breaking release.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            )#x1B[90m#x1B[39;49;00m
            #x1B[94mraise#x1B[39;49;00m #x1B[96mValueError#x1B[39;49;00m(msg)#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m length #x1B[95mis#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[94mNone#x1B[39;49;00m #x1B[95mand#x1B[39;49;00m length != #x1B[96mlen#x1B[39;49;00m(anno):#x1B[90m#x1B[39;49;00m
            #x1B[94mraise#x1B[39;49;00m _mk_df_error(source, attr, length, #x1B[96mlen#x1B[39;49;00m(anno))#x1B[90m#x1B[39;49;00m
        anno = anno.copy(deep=#x1B[94mFalse#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m is_string_dtype(anno.index[~anno.index.isna()]):#x1B[90m#x1B[39;49;00m
            msg = #x1B[33m"#x1B[39;49;00m#x1B[33mTransforming to str index.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
>           warnings.warn(msg, ImplicitModificationWarning, stacklevel=#x1B[94m2#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31mE           anndata._warnings.ImplicitModificationWarning: Transforming to str index.#x1B[0m

#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/aligned_df.py#x1B[0m:93: ImplicitModificationWarning
tests/test_highly_variable_genes.py::test_subset_inplace_consistency[None-scipy_csr_arr-seurat_v3_paper]
Stack Traces | 0.015s run time
subtests = <_pytest.subtests.Subtests object at 0x7f57c82b0a70>
flavor = 'seurat_v3_paper', array_type = <class 'scipy.sparse._csr.csr_array'>
batch_key = None

    #x1B[0m#x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[90m#x1B[39;49;00m
        #x1B[33m"#x1B[39;49;00m#x1B[33mflavor#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
        [#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mseurat#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mcell_ranger#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            pytest.param(#x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, marks=needs.skmisc),#x1B[90m#x1B[39;49;00m
            pytest.param(#x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3_paper#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, marks=needs.skmisc),#x1B[90m#x1B[39;49;00m
        ],#x1B[90m#x1B[39;49;00m
    )#x1B[90m#x1B[39;49;00m
    #x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[90m#x1B[39;49;00m
        #x1B[33m"#x1B[39;49;00m#x1B[33marray_type#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
        [#x1B[90m#x1B[39;49;00m
            p#x1B[90m#x1B[39;49;00m
            #x1B[94mfor#x1B[39;49;00m p #x1B[95min#x1B[39;49;00m ARRAY_TYPES#x1B[90m#x1B[39;49;00m
            #x1B[94mif#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mdask#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[95min#x1B[39;49;00m p.id #x1B[95mor#x1B[39;49;00m (#x1B[33m"#x1B[39;49;00m#x1B[33m1d_chunked#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95min#x1B[39;49;00m p.id #x1B[95mand#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mcsr#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95min#x1B[39;49;00m p.id)#x1B[90m#x1B[39;49;00m
        ],#x1B[90m#x1B[39;49;00m
    )#x1B[90m#x1B[39;49;00m
    #x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[33m"#x1B[39;49;00m#x1B[33mbatch_key#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, [#x1B[94mNone#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mbatch#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_subset_inplace_consistency#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
        subtests: pytest.Subtests,#x1B[90m#x1B[39;49;00m
        flavor: Literal[#x1B[33m"#x1B[39;49;00m#x1B[33mseurat#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mcell_ranger#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3_paper#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
        array_type,#x1B[90m#x1B[39;49;00m
        batch_key: Literal[#x1B[33m"#x1B[39;49;00m#x1B[33mbatch#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m] | #x1B[94mNone#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
    ) -> #x1B[94mNone#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
    #x1B[90m    #x1B[39;49;00m#x1B[33m"""Tests `n_top_genes=n`.#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m    - if `inplace` and `subset` interact correctly#x1B[39;49;00m
    #x1B[33m    - for both the `seurat` and `cell_ranger` flavors#x1B[39;49;00m
    #x1B[33m    - for dask arrays and non-dask arrays#x1B[39;49;00m
    #x1B[33m    - for both with and without batch_key#x1B[39;49;00m
    #x1B[33m    """#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        rng = np.random.default_rng(#x1B[94m0#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
        adata = (#x1B[90m#x1B[39;49;00m
            sc.datasets.blobs(n_observations=#x1B[94m20#x1B[39;49;00m, n_variables=#x1B[94m80#x1B[39;49;00m, rng=rng)#x1B[90m#x1B[39;49;00m
            #x1B[94mif#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[95min#x1B[39;49;00m flavor#x1B[90m#x1B[39;49;00m
            #x1B[94melse#x1B[39;49;00m pbmc3k()[:#x1B[94m1500#x1B[39;49;00m, :#x1B[94m1000#x1B[39;49;00m].copy()#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
        adata.obs[#x1B[33m"#x1B[39;49;00m#x1B[33mbatch#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m] = rng.choice([#x1B[33m"#x1B[39;49;00m#x1B[33ma#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mb#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m], adata.shape[#x1B[94m0#x1B[39;49;00m])#x1B[90m#x1B[39;49;00m
        adata.X = array_type(np.abs(adata.X).astype(#x1B[96mint#x1B[39;49;00m))#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m flavor #x1B[95min#x1B[39;49;00m {#x1B[33m"#x1B[39;49;00m#x1B[33mseurat#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mcell_ranger#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m}:#x1B[90m#x1B[39;49;00m
            sc.pp.normalize_total(adata, target_sum=#x1B[94m1e4#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
            sc.pp.log1p(adata)#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        n_genes = adata.shape[#x1B[94m1#x1B[39;49;00m]#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        adatas: #x1B[96mdict#x1B[39;49;00m[#x1B[96mbool#x1B[39;49;00m, AnnData] = {}#x1B[90m#x1B[39;49;00m
        dfs: #x1B[96mdict#x1B[39;49;00m[#x1B[96mbool#x1B[39;49;00m, pd.DataFrame] = {}#x1B[90m#x1B[39;49;00m
        #x1B[90m# for loops instead of parametrization to compare between settings#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        #x1B[94mfor#x1B[39;49;00m subset, inplace #x1B[95min#x1B[39;49;00m itertools.product([#x1B[94mTrue#x1B[39;49;00m, #x1B[94mFalse#x1B[39;49;00m], repeat=#x1B[94m2#x1B[39;49;00m):#x1B[90m#x1B[39;49;00m
            adata_copy = adata.copy()#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
>           output_df = sc.pp.highly_variable_genes(#x1B[90m#x1B[39;49;00m
                adata_copy,#x1B[90m#x1B[39;49;00m
                flavor=flavor,#x1B[90m#x1B[39;49;00m
                n_top_genes=#x1B[94m15#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
                batch_key=batch_key,#x1B[90m#x1B[39;49;00m
                subset=subset,#x1B[90m#x1B[39;49;00m
                inplace=inplace,#x1B[90m#x1B[39;49;00m
            )#x1B[90m#x1B[39;49;00m

#x1B[1m#x1B[31mtests/test_highly_variable_genes.py#x1B[0m:686: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
#x1B[1m#x1B[.../scanpy/preprocessing/_highly_variable_genes.py#x1B[0m:780: in highly_variable_genes
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m _highly_variable_genes_seurat_v3(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[.../scanpy/preprocessing/_highly_variable_genes.py#x1B[0m:196: in _highly_variable_genes_seurat_v3
    #x1B[0maggregated_mean_var = ad.AnnData(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:254: in __init__
    #x1B[0m#x1B[96mself#x1B[39;49;00m._init_as_actual(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:448: in _init_as_actual
    #x1B[0m#x1B[96mself#x1B[39;49;00m._obs = _gen_dataframe(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../...../_temp/uv-python-dir/cpython-3.14.5-linux-x86_64-gnu/lib/python3.14/functools.py#x1B[0m:982: in wrapper
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m dispatch(args[#x1B[94m0#x1B[39;49;00m].#x1B[91m__class__#x1B[39;49;00m)(*args, **kw)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

anno =    __hvg_v3_batch_info__
0                      0
index_names = ['obs_names', 'row_names']

    #x1B[0m#x1B[37m@_gen_dataframe#x1B[39;49;00m.register(pd.DataFrame)#x1B[90m#x1B[39;49;00m
    #x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92m_gen_dataframe_df#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
        anno: pd.DataFrame,#x1B[90m#x1B[39;49;00m
        index_names: Iterable[#x1B[96mstr#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
        *,#x1B[90m#x1B[39;49;00m
        source: Literal[#x1B[33m"#x1B[39;49;00m#x1B[33mX#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mshape#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
        attr: Literal[#x1B[33m"#x1B[39;49;00m#x1B[33mobs#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mvar#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
        length: #x1B[96mint#x1B[39;49;00m | #x1B[94mNone#x1B[39;49;00m = #x1B[94mNone#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
    ):#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m #x1B[96misinstance#x1B[39;49;00m(anno.index, pd.MultiIndex):#x1B[90m#x1B[39;49;00m
            msg = (#x1B[90m#x1B[39;49;00m
                #x1B[33m"#x1B[39;49;00m#x1B[33mpandas.MultiIndex not supported as index for obs or var on declaration.#x1B[39;49;00m#x1B[33m\n#x1B[39;49;00m#x1B[33m\#x1B[39;49;00m
    #x1B[33m            You can set `obs_names` manually although most operations after will error or convert to str.#x1B[39;49;00m#x1B[33m\n#x1B[39;49;00m#x1B[33m\#x1B[39;49;00m
    #x1B[33m            This behavior will likely be clarified in a future breaking release.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            )#x1B[90m#x1B[39;49;00m
            #x1B[94mraise#x1B[39;49;00m #x1B[96mValueError#x1B[39;49;00m(msg)#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m length #x1B[95mis#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[94mNone#x1B[39;49;00m #x1B[95mand#x1B[39;49;00m length != #x1B[96mlen#x1B[39;49;00m(anno):#x1B[90m#x1B[39;49;00m
            #x1B[94mraise#x1B[39;49;00m _mk_df_error(source, attr, length, #x1B[96mlen#x1B[39;49;00m(anno))#x1B[90m#x1B[39;49;00m
        anno = anno.copy(deep=#x1B[94mFalse#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m is_string_dtype(anno.index[~anno.index.isna()]):#x1B[90m#x1B[39;49;00m
            msg = #x1B[33m"#x1B[39;49;00m#x1B[33mTransforming to str index.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
>           warnings.warn(msg, ImplicitModificationWarning, stacklevel=#x1B[94m2#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31mE           anndata._warnings.ImplicitModificationWarning: Transforming to str index.#x1B[0m

#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/aligned_df.py#x1B[0m:93: ImplicitModificationWarning
tests/test_highly_variable_genes.py::test_subset_inplace_consistency[None-scipy_csr_mat-seurat_v3_paper]
Stack Traces | 0.015s run time
subtests = <_pytest.subtests.Subtests object at 0x7f57c0ef9df0>
flavor = 'seurat_v3_paper', array_type = <class 'scipy.sparse._csr.csr_matrix'>
batch_key = None

    #x1B[0m#x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[90m#x1B[39;49;00m
        #x1B[33m"#x1B[39;49;00m#x1B[33mflavor#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
        [#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mseurat#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mcell_ranger#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            pytest.param(#x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, marks=needs.skmisc),#x1B[90m#x1B[39;49;00m
            pytest.param(#x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3_paper#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, marks=needs.skmisc),#x1B[90m#x1B[39;49;00m
        ],#x1B[90m#x1B[39;49;00m
    )#x1B[90m#x1B[39;49;00m
    #x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[90m#x1B[39;49;00m
        #x1B[33m"#x1B[39;49;00m#x1B[33marray_type#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
        [#x1B[90m#x1B[39;49;00m
            p#x1B[90m#x1B[39;49;00m
            #x1B[94mfor#x1B[39;49;00m p #x1B[95min#x1B[39;49;00m ARRAY_TYPES#x1B[90m#x1B[39;49;00m
            #x1B[94mif#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mdask#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[95min#x1B[39;49;00m p.id #x1B[95mor#x1B[39;49;00m (#x1B[33m"#x1B[39;49;00m#x1B[33m1d_chunked#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95min#x1B[39;49;00m p.id #x1B[95mand#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mcsr#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95min#x1B[39;49;00m p.id)#x1B[90m#x1B[39;49;00m
        ],#x1B[90m#x1B[39;49;00m
    )#x1B[90m#x1B[39;49;00m
    #x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[33m"#x1B[39;49;00m#x1B[33mbatch_key#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, [#x1B[94mNone#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mbatch#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_subset_inplace_consistency#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
        subtests: pytest.Subtests,#x1B[90m#x1B[39;49;00m
        flavor: Literal[#x1B[33m"#x1B[39;49;00m#x1B[33mseurat#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mcell_ranger#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3_paper#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
        array_type,#x1B[90m#x1B[39;49;00m
        batch_key: Literal[#x1B[33m"#x1B[39;49;00m#x1B[33mbatch#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m] | #x1B[94mNone#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
    ) -> #x1B[94mNone#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
    #x1B[90m    #x1B[39;49;00m#x1B[33m"""Tests `n_top_genes=n`.#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m    - if `inplace` and `subset` interact correctly#x1B[39;49;00m
    #x1B[33m    - for both the `seurat` and `cell_ranger` flavors#x1B[39;49;00m
    #x1B[33m    - for dask arrays and non-dask arrays#x1B[39;49;00m
    #x1B[33m    - for both with and without batch_key#x1B[39;49;00m
    #x1B[33m    """#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        rng = np.random.default_rng(#x1B[94m0#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
        adata = (#x1B[90m#x1B[39;49;00m
            sc.datasets.blobs(n_observations=#x1B[94m20#x1B[39;49;00m, n_variables=#x1B[94m80#x1B[39;49;00m, rng=rng)#x1B[90m#x1B[39;49;00m
            #x1B[94mif#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[95min#x1B[39;49;00m flavor#x1B[90m#x1B[39;49;00m
            #x1B[94melse#x1B[39;49;00m pbmc3k()[:#x1B[94m1500#x1B[39;49;00m, :#x1B[94m1000#x1B[39;49;00m].copy()#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
        adata.obs[#x1B[33m"#x1B[39;49;00m#x1B[33mbatch#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m] = rng.choice([#x1B[33m"#x1B[39;49;00m#x1B[33ma#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mb#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m], adata.shape[#x1B[94m0#x1B[39;49;00m])#x1B[90m#x1B[39;49;00m
        adata.X = array_type(np.abs(adata.X).astype(#x1B[96mint#x1B[39;49;00m))#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m flavor #x1B[95min#x1B[39;49;00m {#x1B[33m"#x1B[39;49;00m#x1B[33mseurat#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mcell_ranger#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m}:#x1B[90m#x1B[39;49;00m
            sc.pp.normalize_total(adata, target_sum=#x1B[94m1e4#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
            sc.pp.log1p(adata)#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        n_genes = adata.shape[#x1B[94m1#x1B[39;49;00m]#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        adatas: #x1B[96mdict#x1B[39;49;00m[#x1B[96mbool#x1B[39;49;00m, AnnData] = {}#x1B[90m#x1B[39;49;00m
        dfs: #x1B[96mdict#x1B[39;49;00m[#x1B[96mbool#x1B[39;49;00m, pd.DataFrame] = {}#x1B[90m#x1B[39;49;00m
        #x1B[90m# for loops instead of parametrization to compare between settings#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        #x1B[94mfor#x1B[39;49;00m subset, inplace #x1B[95min#x1B[39;49;00m itertools.product([#x1B[94mTrue#x1B[39;49;00m, #x1B[94mFalse#x1B[39;49;00m], repeat=#x1B[94m2#x1B[39;49;00m):#x1B[90m#x1B[39;49;00m
            adata_copy = adata.copy()#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
>           output_df = sc.pp.highly_variable_genes(#x1B[90m#x1B[39;49;00m
                adata_copy,#x1B[90m#x1B[39;49;00m
                flavor=flavor,#x1B[90m#x1B[39;49;00m
                n_top_genes=#x1B[94m15#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
                batch_key=batch_key,#x1B[90m#x1B[39;49;00m
                subset=subset,#x1B[90m#x1B[39;49;00m
                inplace=inplace,#x1B[90m#x1B[39;49;00m
            )#x1B[90m#x1B[39;49;00m

#x1B[1m#x1B[31mtests/test_highly_variable_genes.py#x1B[0m:686: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
#x1B[1m#x1B[.../scanpy/preprocessing/_highly_variable_genes.py#x1B[0m:780: in highly_variable_genes
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m _highly_variable_genes_seurat_v3(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[.../scanpy/preprocessing/_highly_variable_genes.py#x1B[0m:196: in _highly_variable_genes_seurat_v3
    #x1B[0maggregated_mean_var = ad.AnnData(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:254: in __init__
    #x1B[0m#x1B[96mself#x1B[39;49;00m._init_as_actual(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:448: in _init_as_actual
    #x1B[0m#x1B[96mself#x1B[39;49;00m._obs = _gen_dataframe(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../...../_temp/uv-python-dir/cpython-3.14.5-linux-x86_64-gnu/lib/python3.14/functools.py#x1B[0m:982: in wrapper
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m dispatch(args[#x1B[94m0#x1B[39;49;00m].#x1B[91m__class__#x1B[39;49;00m)(*args, **kw)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

anno =    __hvg_v3_batch_info__
0                      0
index_names = ['obs_names', 'row_names']

    #x1B[0m#x1B[37m@_gen_dataframe#x1B[39;49;00m.register(pd.DataFrame)#x1B[90m#x1B[39;49;00m
    #x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92m_gen_dataframe_df#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
        anno: pd.DataFrame,#x1B[90m#x1B[39;49;00m
        index_names: Iterable[#x1B[96mstr#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
        *,#x1B[90m#x1B[39;49;00m
        source: Literal[#x1B[33m"#x1B[39;49;00m#x1B[33mX#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mshape#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
        attr: Literal[#x1B[33m"#x1B[39;49;00m#x1B[33mobs#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mvar#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
        length: #x1B[96mint#x1B[39;49;00m | #x1B[94mNone#x1B[39;49;00m = #x1B[94mNone#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
    ):#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m #x1B[96misinstance#x1B[39;49;00m(anno.index, pd.MultiIndex):#x1B[90m#x1B[39;49;00m
            msg = (#x1B[90m#x1B[39;49;00m
                #x1B[33m"#x1B[39;49;00m#x1B[33mpandas.MultiIndex not supported as index for obs or var on declaration.#x1B[39;49;00m#x1B[33m\n#x1B[39;49;00m#x1B[33m\#x1B[39;49;00m
    #x1B[33m            You can set `obs_names` manually although most operations after will error or convert to str.#x1B[39;49;00m#x1B[33m\n#x1B[39;49;00m#x1B[33m\#x1B[39;49;00m
    #x1B[33m            This behavior will likely be clarified in a future breaking release.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            )#x1B[90m#x1B[39;49;00m
            #x1B[94mraise#x1B[39;49;00m #x1B[96mValueError#x1B[39;49;00m(msg)#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m length #x1B[95mis#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[94mNone#x1B[39;49;00m #x1B[95mand#x1B[39;49;00m length != #x1B[96mlen#x1B[39;49;00m(anno):#x1B[90m#x1B[39;49;00m
            #x1B[94mraise#x1B[39;49;00m _mk_df_error(source, attr, length, #x1B[96mlen#x1B[39;49;00m(anno))#x1B[90m#x1B[39;49;00m
        anno = anno.copy(deep=#x1B[94mFalse#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m is_string_dtype(anno.index[~anno.index.isna()]):#x1B[90m#x1B[39;49;00m
            msg = #x1B[33m"#x1B[39;49;00m#x1B[33mTransforming to str index.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
>           warnings.warn(msg, ImplicitModificationWarning, stacklevel=#x1B[94m2#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31mE           anndata._warnings.ImplicitModificationWarning: Transforming to str index.#x1B[0m

#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/aligned_df.py#x1B[0m:93: ImplicitModificationWarning
tests/test_highly_variable_genes.py::test_dask_consistency[dask_array_sparse-1d_chunked-csr_matrix-batched-seurat_v3]
Stack Traces | 0.016s run time
adata = AnnData object with n_obs × n_vars = 1500 × 1000
    obs: 'batch'
    var: 'gene_ids'
flavor = 'seurat_v3', batch_key = 'batch'
to_dask = <function gen_csr_csc_params_wrapper.<locals>.wrapper at 0x7f57df075380>

    #x1B[0m#x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[90m#x1B[39;49;00m
        #x1B[33m"#x1B[39;49;00m#x1B[33mflavor#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
        [#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mseurat#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mcell_ranger#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            pytest.param(#x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, marks=needs.skmisc),#x1B[90m#x1B[39;49;00m
            pytest.param(#x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3_paper#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, marks=needs.skmisc),#x1B[90m#x1B[39;49;00m
        ],#x1B[90m#x1B[39;49;00m
    )#x1B[90m#x1B[39;49;00m
    #x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[33m"#x1B[39;49;00m#x1B[33mbatch_key#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, [#x1B[94mNone#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mbatch#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m], ids=[#x1B[33m"#x1B[39;49;00m#x1B[33msingle#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mbatched#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m])#x1B[90m#x1B[39;49;00m
    #x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[90m#x1B[39;49;00m
        #x1B[33m"#x1B[39;49;00m#x1B[33mto_dask#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, [p #x1B[94mfor#x1B[39;49;00m p #x1B[95min#x1B[39;49;00m ARRAY_TYPES #x1B[94mif#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33m1d_chunked#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95min#x1B[39;49;00m p.id #x1B[95mand#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mcsr#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95min#x1B[39;49;00m p.id]#x1B[90m#x1B[39;49;00m
    )#x1B[90m#x1B[39;49;00m
    #x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92mtest_dask_consistency#x1B[39;49;00m(adata: AnnData, flavor, batch_key, to_dask):#x1B[90m#x1B[39;49;00m
        #x1B[90m# current blob produces singularities in loess....maybe a bad sign of the data?#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95min#x1B[39;49;00m flavor:#x1B[90m#x1B[39;49;00m
            adata = pbmc3k()[:#x1B[94m1500#x1B[39;49;00m, :#x1B[94m1000#x1B[39;49;00m].copy()#x1B[90m#x1B[39;49;00m
        adata.X = np.abs(adata.X).astype(#x1B[96mint#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m batch_key #x1B[95mis#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[94mNone#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
            adata.obs[batch_key] = np.tile([#x1B[33m"#x1B[39;49;00m#x1B[33ma#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mb#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m], adata.shape[#x1B[94m0#x1B[39;49;00m] // #x1B[94m2#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
        #x1B[90m# seurat_v3 expects counts#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[95min#x1B[39;49;00m flavor:#x1B[90m#x1B[39;49;00m
            sc.pp.normalize_total(adata, target_sum=#x1B[94m1e4#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
            sc.pp.log1p(adata)#x1B[90m#x1B[39;49;00m
        adata_dask = adata.copy()#x1B[90m#x1B[39;49;00m
        adata_dask.X = to_dask(adata_dask.X)#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        #x1B[94mwith#x1B[39;49;00m (#x1B[90m#x1B[39;49;00m
            pytest.warns(#x1B[96mUserWarning#x1B[39;49;00m, match=#x1B[33m"#x1B[39;49;00m#x1B[33mn_top_genes.*normalized dispersions#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
            #x1B[94mif#x1B[39;49;00m flavor == #x1B[33m"#x1B[39;49;00m#x1B[33mcell_ranger#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            #x1B[94melse#x1B[39;49;00m nullcontext()#x1B[90m#x1B[39;49;00m
        ):#x1B[90m#x1B[39;49;00m
>           output_mem, output_dask = (#x1B[90m#x1B[39;49;00m
            ^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
                sc.pp.highly_variable_genes(#x1B[90m#x1B[39;49;00m
                    ad, flavor=flavor, n_top_genes=#x1B[94m15#x1B[39;49;00m, inplace=#x1B[94mFalse#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
                )#x1B[90m#x1B[39;49;00m
                #x1B[94mfor#x1B[39;49;00m ad #x1B[95min#x1B[39;49;00m [adata, adata_dask]#x1B[90m#x1B[39;49;00m
            )#x1B[90m#x1B[39;49;00m

#x1B[1m#x1B[31mtests/test_highly_variable_genes.py#x1B[0m:758: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
#x1B[1m#x1B[31mtests/test_highly_variable_genes.py#x1B[0m:759: in <genexpr>
    #x1B[0msc.pp.highly_variable_genes(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[.../scanpy/preprocessing/_highly_variable_genes.py#x1B[0m:780: in highly_variable_genes
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m _highly_variable_genes_seurat_v3(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[.../scanpy/preprocessing/_highly_variable_genes.py#x1B[0m:196: in _highly_variable_genes_seurat_v3
    #x1B[0maggregated_mean_var = ad.AnnData(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:254: in __init__
    #x1B[0m#x1B[96mself#x1B[39;49;00m._init_as_actual(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:448: in _init_as_actual
    #x1B[0m#x1B[96mself#x1B[39;49;00m._obs = _gen_dataframe(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../...../_temp/uv-python-dir/cpython-3.14.5-linux-x86_64-gnu/lib/python3.14/functools.py#x1B[0m:982: in wrapper
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m dispatch(args[#x1B[94m0#x1B[39;49;00m].#x1B[91m__class__#x1B[39;49;00m)(*args, **kw)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

anno =    __hvg_v3_batch_info__
0                      0
index_names = ['obs_names', 'row_names']

    #x1B[0m#x1B[37m@_gen_dataframe#x1B[39;49;00m.register(pd.DataFrame)#x1B[90m#x1B[39;49;00m
    #x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92m_gen_dataframe_df#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
        anno: pd.DataFrame,#x1B[90m#x1B[39;49;00m
        index_names: Iterable[#x1B[96mstr#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
        *,#x1B[90m#x1B[39;49;00m
        source: Literal[#x1B[33m"#x1B[39;49;00m#x1B[33mX#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mshape#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
        attr: Literal[#x1B[33m"#x1B[39;49;00m#x1B[33mobs#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mvar#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
        length: #x1B[96mint#x1B[39;49;00m | #x1B[94mNone#x1B[39;49;00m = #x1B[94mNone#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
    ):#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m #x1B[96misinstance#x1B[39;49;00m(anno.index, pd.MultiIndex):#x1B[90m#x1B[39;49;00m
            msg = (#x1B[90m#x1B[39;49;00m
                #x1B[33m"#x1B[39;49;00m#x1B[33mpandas.MultiIndex not supported as index for obs or var on declaration.#x1B[39;49;00m#x1B[33m\n#x1B[39;49;00m#x1B[33m\#x1B[39;49;00m
    #x1B[33m            You can set `obs_names` manually although most operations after will error or convert to str.#x1B[39;49;00m#x1B[33m\n#x1B[39;49;00m#x1B[33m\#x1B[39;49;00m
    #x1B[33m            This behavior will likely be clarified in a future breaking release.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            )#x1B[90m#x1B[39;49;00m
            #x1B[94mraise#x1B[39;49;00m #x1B[96mValueError#x1B[39;49;00m(msg)#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m length #x1B[95mis#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[94mNone#x1B[39;49;00m #x1B[95mand#x1B[39;49;00m length != #x1B[96mlen#x1B[39;49;00m(anno):#x1B[90m#x1B[39;49;00m
            #x1B[94mraise#x1B[39;49;00m _mk_df_error(source, attr, length, #x1B[96mlen#x1B[39;49;00m(anno))#x1B[90m#x1B[39;49;00m
        anno = anno.copy(deep=#x1B[94mFalse#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m is_string_dtype(anno.index[~anno.index.isna()]):#x1B[90m#x1B[39;49;00m
            msg = #x1B[33m"#x1B[39;49;00m#x1B[33mTransforming to str index.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
>           warnings.warn(msg, ImplicitModificationWarning, stacklevel=#x1B[94m2#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31mE           anndata._warnings.ImplicitModificationWarning: Transforming to str index.#x1B[0m

#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/aligned_df.py#x1B[0m:93: ImplicitModificationWarning
tests/test_highly_variable_genes.py::test_dask_consistency[dask_array_sparse-1d_chunked-csr_matrix-single-seurat_v3]
Stack Traces | 0.016s run time
adata = AnnData object with n_obs × n_vars = 1500 × 1000
    var: 'gene_ids'
flavor = 'seurat_v3', batch_key = None
to_dask = <function gen_csr_csc_params_wrapper.<locals>.wrapper at 0x7f57df075380>

    #x1B[0m#x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[90m#x1B[39;49;00m
        #x1B[33m"#x1B[39;49;00m#x1B[33mflavor#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
        [#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mseurat#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mcell_ranger#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            pytest.param(#x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, marks=needs.skmisc),#x1B[90m#x1B[39;49;00m
            pytest.param(#x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3_paper#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, marks=needs.skmisc),#x1B[90m#x1B[39;49;00m
        ],#x1B[90m#x1B[39;49;00m
    )#x1B[90m#x1B[39;49;00m
    #x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[33m"#x1B[39;49;00m#x1B[33mbatch_key#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, [#x1B[94mNone#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mbatch#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m], ids=[#x1B[33m"#x1B[39;49;00m#x1B[33msingle#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mbatched#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m])#x1B[90m#x1B[39;49;00m
    #x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[90m#x1B[39;49;00m
        #x1B[33m"#x1B[39;49;00m#x1B[33mto_dask#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, [p #x1B[94mfor#x1B[39;49;00m p #x1B[95min#x1B[39;49;00m ARRAY_TYPES #x1B[94mif#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33m1d_chunked#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95min#x1B[39;49;00m p.id #x1B[95mand#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mcsr#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95min#x1B[39;49;00m p.id]#x1B[90m#x1B[39;49;00m
    )#x1B[90m#x1B[39;49;00m
    #x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92mtest_dask_consistency#x1B[39;49;00m(adata: AnnData, flavor, batch_key, to_dask):#x1B[90m#x1B[39;49;00m
        #x1B[90m# current blob produces singularities in loess....maybe a bad sign of the data?#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95min#x1B[39;49;00m flavor:#x1B[90m#x1B[39;49;00m
            adata = pbmc3k()[:#x1B[94m1500#x1B[39;49;00m, :#x1B[94m1000#x1B[39;49;00m].copy()#x1B[90m#x1B[39;49;00m
        adata.X = np.abs(adata.X).astype(#x1B[96mint#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m batch_key #x1B[95mis#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[94mNone#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
            adata.obs[batch_key] = np.tile([#x1B[33m"#x1B[39;49;00m#x1B[33ma#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mb#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m], adata.shape[#x1B[94m0#x1B[39;49;00m] // #x1B[94m2#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
        #x1B[90m# seurat_v3 expects counts#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[95min#x1B[39;49;00m flavor:#x1B[90m#x1B[39;49;00m
            sc.pp.normalize_total(adata, target_sum=#x1B[94m1e4#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
            sc.pp.log1p(adata)#x1B[90m#x1B[39;49;00m
        adata_dask = adata.copy()#x1B[90m#x1B[39;49;00m
        adata_dask.X = to_dask(adata_dask.X)#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        #x1B[94mwith#x1B[39;49;00m (#x1B[90m#x1B[39;49;00m
            pytest.warns(#x1B[96mUserWarning#x1B[39;49;00m, match=#x1B[33m"#x1B[39;49;00m#x1B[33mn_top_genes.*normalized dispersions#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
            #x1B[94mif#x1B[39;49;00m flavor == #x1B[33m"#x1B[39;49;00m#x1B[33mcell_ranger#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            #x1B[94melse#x1B[39;49;00m nullcontext()#x1B[90m#x1B[39;49;00m
        ):#x1B[90m#x1B[39;49;00m
>           output_mem, output_dask = (#x1B[90m#x1B[39;49;00m
            ^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
                sc.pp.highly_variable_genes(#x1B[90m#x1B[39;49;00m
                    ad, flavor=flavor, n_top_genes=#x1B[94m15#x1B[39;49;00m, inplace=#x1B[94mFalse#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
                )#x1B[90m#x1B[39;49;00m
                #x1B[94mfor#x1B[39;49;00m ad #x1B[95min#x1B[39;49;00m [adata, adata_dask]#x1B[90m#x1B[39;49;00m
            )#x1B[90m#x1B[39;49;00m

#x1B[1m#x1B[31mtests/test_highly_variable_genes.py#x1B[0m:758: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
#x1B[1m#x1B[31mtests/test_highly_variable_genes.py#x1B[0m:759: in <genexpr>
    #x1B[0msc.pp.highly_variable_genes(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[.../scanpy/preprocessing/_highly_variable_genes.py#x1B[0m:780: in highly_variable_genes
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m _highly_variable_genes_seurat_v3(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[.../scanpy/preprocessing/_highly_variable_genes.py#x1B[0m:196: in _highly_variable_genes_seurat_v3
    #x1B[0maggregated_mean_var = ad.AnnData(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:254: in __init__
    #x1B[0m#x1B[96mself#x1B[39;49;00m._init_as_actual(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:448: in _init_as_actual
    #x1B[0m#x1B[96mself#x1B[39;49;00m._obs = _gen_dataframe(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../...../_temp/uv-python-dir/cpython-3.14.5-linux-x86_64-gnu/lib/python3.14/functools.py#x1B[0m:982: in wrapper
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m dispatch(args[#x1B[94m0#x1B[39;49;00m].#x1B[91m__class__#x1B[39;49;00m)(*args, **kw)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

anno =    __hvg_v3_batch_info__
0                      0
index_names = ['obs_names', 'row_names']

    #x1B[0m#x1B[37m@_gen_dataframe#x1B[39;49;00m.register(pd.DataFrame)#x1B[90m#x1B[39;49;00m
    #x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92m_gen_dataframe_df#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
        anno: pd.DataFrame,#x1B[90m#x1B[39;49;00m
        index_names: Iterable[#x1B[96mstr#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
        *,#x1B[90m#x1B[39;49;00m
        source: Literal[#x1B[33m"#x1B[39;49;00m#x1B[33mX#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mshape#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
        attr: Literal[#x1B[33m"#x1B[39;49;00m#x1B[33mobs#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mvar#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
        length: #x1B[96mint#x1B[39;49;00m | #x1B[94mNone#x1B[39;49;00m = #x1B[94mNone#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
    ):#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m #x1B[96misinstance#x1B[39;49;00m(anno.index, pd.MultiIndex):#x1B[90m#x1B[39;49;00m
            msg = (#x1B[90m#x1B[39;49;00m
                #x1B[33m"#x1B[39;49;00m#x1B[33mpandas.MultiIndex not supported as index for obs or var on declaration.#x1B[39;49;00m#x1B[33m\n#x1B[39;49;00m#x1B[33m\#x1B[39;49;00m
    #x1B[33m            You can set `obs_names` manually although most operations after will error or convert to str.#x1B[39;49;00m#x1B[33m\n#x1B[39;49;00m#x1B[33m\#x1B[39;49;00m
    #x1B[33m            This behavior will likely be clarified in a future breaking release.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            )#x1B[90m#x1B[39;49;00m
            #x1B[94mraise#x1B[39;49;00m #x1B[96mValueError#x1B[39;49;00m(msg)#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m length #x1B[95mis#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[94mNone#x1B[39;49;00m #x1B[95mand#x1B[39;49;00m length != #x1B[96mlen#x1B[39;49;00m(anno):#x1B[90m#x1B[39;49;00m
            #x1B[94mraise#x1B[39;49;00m _mk_df_error(source, attr, length, #x1B[96mlen#x1B[39;49;00m(anno))#x1B[90m#x1B[39;49;00m
        anno = anno.copy(deep=#x1B[94mFalse#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m is_string_dtype(anno.index[~anno.index.isna()]):#x1B[90m#x1B[39;49;00m
            msg = #x1B[33m"#x1B[39;49;00m#x1B[33mTransforming to str index.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
>           warnings.warn(msg, ImplicitModificationWarning, stacklevel=#x1B[94m2#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31mE           anndata._warnings.ImplicitModificationWarning: Transforming to str index.#x1B[0m

#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/aligned_df.py#x1B[0m:93: ImplicitModificationWarning
tests/test_highly_variable_genes.py::test_dask_consistency[dask_array_sparse-1d_chunked-csr_matrix-single-seurat_v3_paper]
Stack Traces | 0.016s run time
adata = AnnData object with n_obs × n_vars = 1500 × 1000
    var: 'gene_ids'
flavor = 'seurat_v3_paper', batch_key = None
to_dask = <function gen_csr_csc_params_wrapper.<locals>.wrapper at 0x7f57df075380>

    #x1B[0m#x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[90m#x1B[39;49;00m
        #x1B[33m"#x1B[39;49;00m#x1B[33mflavor#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
        [#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mseurat#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mcell_ranger#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            pytest.param(#x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, marks=needs.skmisc),#x1B[90m#x1B[39;49;00m
            pytest.param(#x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3_paper#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, marks=needs.skmisc),#x1B[90m#x1B[39;49;00m
        ],#x1B[90m#x1B[39;49;00m
    )#x1B[90m#x1B[39;49;00m
    #x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[33m"#x1B[39;49;00m#x1B[33mbatch_key#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, [#x1B[94mNone#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mbatch#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m], ids=[#x1B[33m"#x1B[39;49;00m#x1B[33msingle#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mbatched#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m])#x1B[90m#x1B[39;49;00m
    #x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[90m#x1B[39;49;00m
        #x1B[33m"#x1B[39;49;00m#x1B[33mto_dask#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, [p #x1B[94mfor#x1B[39;49;00m p #x1B[95min#x1B[39;49;00m ARRAY_TYPES #x1B[94mif#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33m1d_chunked#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95min#x1B[39;49;00m p.id #x1B[95mand#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mcsr#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95min#x1B[39;49;00m p.id]#x1B[90m#x1B[39;49;00m
    )#x1B[90m#x1B[39;49;00m
    #x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92mtest_dask_consistency#x1B[39;49;00m(adata: AnnData, flavor, batch_key, to_dask):#x1B[90m#x1B[39;49;00m
        #x1B[90m# current blob produces singularities in loess....maybe a bad sign of the data?#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95min#x1B[39;49;00m flavor:#x1B[90m#x1B[39;49;00m
            adata = pbmc3k()[:#x1B[94m1500#x1B[39;49;00m, :#x1B[94m1000#x1B[39;49;00m].copy()#x1B[90m#x1B[39;49;00m
        adata.X = np.abs(adata.X).astype(#x1B[96mint#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m batch_key #x1B[95mis#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[94mNone#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
            adata.obs[batch_key] = np.tile([#x1B[33m"#x1B[39;49;00m#x1B[33ma#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mb#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m], adata.shape[#x1B[94m0#x1B[39;49;00m] // #x1B[94m2#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
        #x1B[90m# seurat_v3 expects counts#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[95min#x1B[39;49;00m flavor:#x1B[90m#x1B[39;49;00m
            sc.pp.normalize_total(adata, target_sum=#x1B[94m1e4#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
            sc.pp.log1p(adata)#x1B[90m#x1B[39;49;00m
        adata_dask = adata.copy()#x1B[90m#x1B[39;49;00m
        adata_dask.X = to_dask(adata_dask.X)#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        #x1B[94mwith#x1B[39;49;00m (#x1B[90m#x1B[39;49;00m
            pytest.warns(#x1B[96mUserWarning#x1B[39;49;00m, match=#x1B[33m"#x1B[39;49;00m#x1B[33mn_top_genes.*normalized dispersions#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
            #x1B[94mif#x1B[39;49;00m flavor == #x1B[33m"#x1B[39;49;00m#x1B[33mcell_ranger#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            #x1B[94melse#x1B[39;49;00m nullcontext()#x1B[90m#x1B[39;49;00m
        ):#x1B[90m#x1B[39;49;00m
>           output_mem, output_dask = (#x1B[90m#x1B[39;49;00m
            ^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
                sc.pp.highly_variable_genes(#x1B[90m#x1B[39;49;00m
                    ad, flavor=flavor, n_top_genes=#x1B[94m15#x1B[39;49;00m, inplace=#x1B[94mFalse#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
                )#x1B[90m#x1B[39;49;00m
                #x1B[94mfor#x1B[39;49;00m ad #x1B[95min#x1B[39;49;00m [adata, adata_dask]#x1B[90m#x1B[39;49;00m
            )#x1B[90m#x1B[39;49;00m

#x1B[1m#x1B[31mtests/test_highly_variable_genes.py#x1B[0m:758: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
#x1B[1m#x1B[31mtests/test_highly_variable_genes.py#x1B[0m:759: in <genexpr>
    #x1B[0msc.pp.highly_variable_genes(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[.../scanpy/preprocessing/_highly_variable_genes.py#x1B[0m:780: in highly_variable_genes
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m _highly_variable_genes_seurat_v3(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[.../scanpy/preprocessing/_highly_variable_genes.py#x1B[0m:196: in _highly_variable_genes_seurat_v3
    #x1B[0maggregated_mean_var = ad.AnnData(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:254: in __init__
    #x1B[0m#x1B[96mself#x1B[39;49;00m._init_as_actual(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:448: in _init_as_actual
    #x1B[0m#x1B[96mself#x1B[39;49;00m._obs = _gen_dataframe(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../...../_temp/uv-python-dir/cpython-3.14.5-linux-x86_64-gnu/lib/python3.14/functools.py#x1B[0m:982: in wrapper
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m dispatch(args[#x1B[94m0#x1B[39;49;00m].#x1B[91m__class__#x1B[39;49;00m)(*args, **kw)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

anno =    __hvg_v3_batch_info__
0                      0
index_names = ['obs_names', 'row_names']

    #x1B[0m#x1B[37m@_gen_dataframe#x1B[39;49;00m.register(pd.DataFrame)#x1B[90m#x1B[39;49;00m
    #x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92m_gen_dataframe_df#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
        anno: pd.DataFrame,#x1B[90m#x1B[39;49;00m
        index_names: Iterable[#x1B[96mstr#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
        *,#x1B[90m#x1B[39;49;00m
        source: Literal[#x1B[33m"#x1B[39;49;00m#x1B[33mX#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mshape#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
        attr: Literal[#x1B[33m"#x1B[39;49;00m#x1B[33mobs#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mvar#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
        length: #x1B[96mint#x1B[39;49;00m | #x1B[94mNone#x1B[39;49;00m = #x1B[94mNone#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
    ):#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m #x1B[96misinstance#x1B[39;49;00m(anno.index, pd.MultiIndex):#x1B[90m#x1B[39;49;00m
            msg = (#x1B[90m#x1B[39;49;00m
                #x1B[33m"#x1B[39;49;00m#x1B[33mpandas.MultiIndex not supported as index for obs or var on declaration.#x1B[39;49;00m#x1B[33m\n#x1B[39;49;00m#x1B[33m\#x1B[39;49;00m
    #x1B[33m            You can set `obs_names` manually although most operations after will error or convert to str.#x1B[39;49;00m#x1B[33m\n#x1B[39;49;00m#x1B[33m\#x1B[39;49;00m
    #x1B[33m            This behavior will likely be clarified in a future breaking release.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            )#x1B[90m#x1B[39;49;00m
            #x1B[94mraise#x1B[39;49;00m #x1B[96mValueError#x1B[39;49;00m(msg)#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m length #x1B[95mis#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[94mNone#x1B[39;49;00m #x1B[95mand#x1B[39;49;00m length != #x1B[96mlen#x1B[39;49;00m(anno):#x1B[90m#x1B[39;49;00m
            #x1B[94mraise#x1B[39;49;00m _mk_df_error(source, attr, length, #x1B[96mlen#x1B[39;49;00m(anno))#x1B[90m#x1B[39;49;00m
        anno = anno.copy(deep=#x1B[94mFalse#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m is_string_dtype(anno.index[~anno.index.isna()]):#x1B[90m#x1B[39;49;00m
            msg = #x1B[33m"#x1B[39;49;00m#x1B[33mTransforming to str index.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
>           warnings.warn(msg, ImplicitModificationWarning, stacklevel=#x1B[94m2#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31mE           anndata._warnings.ImplicitModificationWarning: Transforming to str index.#x1B[0m

#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/aligned_df.py#x1B[0m:93: ImplicitModificationWarning
tests/test_highly_variable_genes.py::test_subset_inplace_consistency[None-numpy_ndarray-seurat_v3_paper]
Stack Traces | 0.018s run time
subtests = <_pytest.subtests.Subtests object at 0x7f57c0727470>
flavor = 'seurat_v3_paper', array_type = <function asarray at 0x7f57e43833d0>
batch_key = None

    #x1B[0m#x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[90m#x1B[39;49;00m
        #x1B[33m"#x1B[39;49;00m#x1B[33mflavor#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
        [#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mseurat#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mcell_ranger#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            pytest.param(#x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, marks=needs.skmisc),#x1B[90m#x1B[39;49;00m
            pytest.param(#x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3_paper#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, marks=needs.skmisc),#x1B[90m#x1B[39;49;00m
        ],#x1B[90m#x1B[39;49;00m
    )#x1B[90m#x1B[39;49;00m
    #x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[90m#x1B[39;49;00m
        #x1B[33m"#x1B[39;49;00m#x1B[33marray_type#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
        [#x1B[90m#x1B[39;49;00m
            p#x1B[90m#x1B[39;49;00m
            #x1B[94mfor#x1B[39;49;00m p #x1B[95min#x1B[39;49;00m ARRAY_TYPES#x1B[90m#x1B[39;49;00m
            #x1B[94mif#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mdask#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[95min#x1B[39;49;00m p.id #x1B[95mor#x1B[39;49;00m (#x1B[33m"#x1B[39;49;00m#x1B[33m1d_chunked#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95min#x1B[39;49;00m p.id #x1B[95mand#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mcsr#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95min#x1B[39;49;00m p.id)#x1B[90m#x1B[39;49;00m
        ],#x1B[90m#x1B[39;49;00m
    )#x1B[90m#x1B[39;49;00m
    #x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[33m"#x1B[39;49;00m#x1B[33mbatch_key#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, [#x1B[94mNone#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mbatch#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_subset_inplace_consistency#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
        subtests: pytest.Subtests,#x1B[90m#x1B[39;49;00m
        flavor: Literal[#x1B[33m"#x1B[39;49;00m#x1B[33mseurat#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mcell_ranger#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3_paper#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
        array_type,#x1B[90m#x1B[39;49;00m
        batch_key: Literal[#x1B[33m"#x1B[39;49;00m#x1B[33mbatch#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m] | #x1B[94mNone#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
    ) -> #x1B[94mNone#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
    #x1B[90m    #x1B[39;49;00m#x1B[33m"""Tests `n_top_genes=n`.#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m    - if `inplace` and `subset` interact correctly#x1B[39;49;00m
    #x1B[33m    - for both the `seurat` and `cell_ranger` flavors#x1B[39;49;00m
    #x1B[33m    - for dask arrays and non-dask arrays#x1B[39;49;00m
    #x1B[33m    - for both with and without batch_key#x1B[39;49;00m
    #x1B[33m    """#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        rng = np.random.default_rng(#x1B[94m0#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
        adata = (#x1B[90m#x1B[39;49;00m
            sc.datasets.blobs(n_observations=#x1B[94m20#x1B[39;49;00m, n_variables=#x1B[94m80#x1B[39;49;00m, rng=rng)#x1B[90m#x1B[39;49;00m
            #x1B[94mif#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[95min#x1B[39;49;00m flavor#x1B[90m#x1B[39;49;00m
            #x1B[94melse#x1B[39;49;00m pbmc3k()[:#x1B[94m1500#x1B[39;49;00m, :#x1B[94m1000#x1B[39;49;00m].copy()#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
        adata.obs[#x1B[33m"#x1B[39;49;00m#x1B[33mbatch#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m] = rng.choice([#x1B[33m"#x1B[39;49;00m#x1B[33ma#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mb#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m], adata.shape[#x1B[94m0#x1B[39;49;00m])#x1B[90m#x1B[39;49;00m
        adata.X = array_type(np.abs(adata.X).astype(#x1B[96mint#x1B[39;49;00m))#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m flavor #x1B[95min#x1B[39;49;00m {#x1B[33m"#x1B[39;49;00m#x1B[33mseurat#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mcell_ranger#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m}:#x1B[90m#x1B[39;49;00m
            sc.pp.normalize_total(adata, target_sum=#x1B[94m1e4#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
            sc.pp.log1p(adata)#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        n_genes = adata.shape[#x1B[94m1#x1B[39;49;00m]#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        adatas: #x1B[96mdict#x1B[39;49;00m[#x1B[96mbool#x1B[39;49;00m, AnnData] = {}#x1B[90m#x1B[39;49;00m
        dfs: #x1B[96mdict#x1B[39;49;00m[#x1B[96mbool#x1B[39;49;00m, pd.DataFrame] = {}#x1B[90m#x1B[39;49;00m
        #x1B[90m# for loops instead of parametrization to compare between settings#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        #x1B[94mfor#x1B[39;49;00m subset, inplace #x1B[95min#x1B[39;49;00m itertools.product([#x1B[94mTrue#x1B[39;49;00m, #x1B[94mFalse#x1B[39;49;00m], repeat=#x1B[94m2#x1B[39;49;00m):#x1B[90m#x1B[39;49;00m
            adata_copy = adata.copy()#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
>           output_df = sc.pp.highly_variable_genes(#x1B[90m#x1B[39;49;00m
                adata_copy,#x1B[90m#x1B[39;49;00m
                flavor=flavor,#x1B[90m#x1B[39;49;00m
                n_top_genes=#x1B[94m15#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
                batch_key=batch_key,#x1B[90m#x1B[39;49;00m
                subset=subset,#x1B[90m#x1B[39;49;00m
                inplace=inplace,#x1B[90m#x1B[39;49;00m
            )#x1B[90m#x1B[39;49;00m

#x1B[1m#x1B[31mtests/test_highly_variable_genes.py#x1B[0m:686: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
#x1B[1m#x1B[.../scanpy/preprocessing/_highly_variable_genes.py#x1B[0m:780: in highly_variable_genes
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m _highly_variable_genes_seurat_v3(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[.../scanpy/preprocessing/_highly_variable_genes.py#x1B[0m:196: in _highly_variable_genes_seurat_v3
    #x1B[0maggregated_mean_var = ad.AnnData(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:254: in __init__
    #x1B[0m#x1B[96mself#x1B[39;49;00m._init_as_actual(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:448: in _init_as_actual
    #x1B[0m#x1B[96mself#x1B[39;49;00m._obs = _gen_dataframe(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../...../_temp/uv-python-dir/cpython-3.14.5-linux-x86_64-gnu/lib/python3.14/functools.py#x1B[0m:982: in wrapper
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m dispatch(args[#x1B[94m0#x1B[39;49;00m].#x1B[91m__class__#x1B[39;49;00m)(*args, **kw)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

anno =    __hvg_v3_batch_info__
0                      0
index_names = ['obs_names', 'row_names']

    #x1B[0m#x1B[37m@_gen_dataframe#x1B[39;49;00m.register(pd.DataFrame)#x1B[90m#x1B[39;49;00m
    #x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92m_gen_dataframe_df#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
        anno: pd.DataFrame,#x1B[90m#x1B[39;49;00m
        index_names: Iterable[#x1B[96mstr#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
        *,#x1B[90m#x1B[39;49;00m
        source: Literal[#x1B[33m"#x1B[39;49;00m#x1B[33mX#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mshape#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
        attr: Literal[#x1B[33m"#x1B[39;49;00m#x1B[33mobs#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mvar#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
        length: #x1B[96mint#x1B[39;49;00m | #x1B[94mNone#x1B[39;49;00m = #x1B[94mNone#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
    ):#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m #x1B[96misinstance#x1B[39;49;00m(anno.index, pd.MultiIndex):#x1B[90m#x1B[39;49;00m
            msg = (#x1B[90m#x1B[39;49;00m
                #x1B[33m"#x1B[39;49;00m#x1B[33mpandas.MultiIndex not supported as index for obs or var on declaration.#x1B[39;49;00m#x1B[33m\n#x1B[39;49;00m#x1B[33m\#x1B[39;49;00m
    #x1B[33m            You can set `obs_names` manually although most operations after will error or convert to str.#x1B[39;49;00m#x1B[33m\n#x1B[39;49;00m#x1B[33m\#x1B[39;49;00m
    #x1B[33m            This behavior will likely be clarified in a future breaking release.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            )#x1B[90m#x1B[39;49;00m
            #x1B[94mraise#x1B[39;49;00m #x1B[96mValueError#x1B[39;49;00m(msg)#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m length #x1B[95mis#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[94mNone#x1B[39;49;00m #x1B[95mand#x1B[39;49;00m length != #x1B[96mlen#x1B[39;49;00m(anno):#x1B[90m#x1B[39;49;00m
            #x1B[94mraise#x1B[39;49;00m _mk_df_error(source, attr, length, #x1B[96mlen#x1B[39;49;00m(anno))#x1B[90m#x1B[39;49;00m
        anno = anno.copy(deep=#x1B[94mFalse#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m is_string_dtype(anno.index[~anno.index.isna()]):#x1B[90m#x1B[39;49;00m
            msg = #x1B[33m"#x1B[39;49;00m#x1B[33mTransforming to str index.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
>           warnings.warn(msg, ImplicitModificationWarning, stacklevel=#x1B[94m2#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31mE           anndata._warnings.ImplicitModificationWarning: Transforming to str index.#x1B[0m

#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/aligned_df.py#x1B[0m:93: ImplicitModificationWarning
tests/test_highly_variable_genes.py::test_subset_inplace_consistency[None-numpy_ndarray-seurat_v3]
Stack Traces | 0.019s run time
subtests = <_pytest.subtests.Subtests object at 0x7f57c0c90b90>
flavor = 'seurat_v3', array_type = <function asarray at 0x7f57e43833d0>
batch_key = None

    #x1B[0m#x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[90m#x1B[39;49;00m
        #x1B[33m"#x1B[39;49;00m#x1B[33mflavor#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
        [#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mseurat#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mcell_ranger#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            pytest.param(#x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, marks=needs.skmisc),#x1B[90m#x1B[39;49;00m
            pytest.param(#x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3_paper#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, marks=needs.skmisc),#x1B[90m#x1B[39;49;00m
        ],#x1B[90m#x1B[39;49;00m
    )#x1B[90m#x1B[39;49;00m
    #x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[90m#x1B[39;49;00m
        #x1B[33m"#x1B[39;49;00m#x1B[33marray_type#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
        [#x1B[90m#x1B[39;49;00m
            p#x1B[90m#x1B[39;49;00m
            #x1B[94mfor#x1B[39;49;00m p #x1B[95min#x1B[39;49;00m ARRAY_TYPES#x1B[90m#x1B[39;49;00m
            #x1B[94mif#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mdask#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[95min#x1B[39;49;00m p.id #x1B[95mor#x1B[39;49;00m (#x1B[33m"#x1B[39;49;00m#x1B[33m1d_chunked#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95min#x1B[39;49;00m p.id #x1B[95mand#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mcsr#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95min#x1B[39;49;00m p.id)#x1B[90m#x1B[39;49;00m
        ],#x1B[90m#x1B[39;49;00m
    )#x1B[90m#x1B[39;49;00m
    #x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[33m"#x1B[39;49;00m#x1B[33mbatch_key#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, [#x1B[94mNone#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mbatch#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_subset_inplace_consistency#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
        subtests: pytest.Subtests,#x1B[90m#x1B[39;49;00m
        flavor: Literal[#x1B[33m"#x1B[39;49;00m#x1B[33mseurat#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mcell_ranger#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3_paper#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
        array_type,#x1B[90m#x1B[39;49;00m
        batch_key: Literal[#x1B[33m"#x1B[39;49;00m#x1B[33mbatch#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m] | #x1B[94mNone#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
    ) -> #x1B[94mNone#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
    #x1B[90m    #x1B[39;49;00m#x1B[33m"""Tests `n_top_genes=n`.#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m    - if `inplace` and `subset` interact correctly#x1B[39;49;00m
    #x1B[33m    - for both the `seurat` and `cell_ranger` flavors#x1B[39;49;00m
    #x1B[33m    - for dask arrays and non-dask arrays#x1B[39;49;00m
    #x1B[33m    - for both with and without batch_key#x1B[39;49;00m
    #x1B[33m    """#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        rng = np.random.default_rng(#x1B[94m0#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
        adata = (#x1B[90m#x1B[39;49;00m
            sc.datasets.blobs(n_observations=#x1B[94m20#x1B[39;49;00m, n_variables=#x1B[94m80#x1B[39;49;00m, rng=rng)#x1B[90m#x1B[39;49;00m
            #x1B[94mif#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[95min#x1B[39;49;00m flavor#x1B[90m#x1B[39;49;00m
            #x1B[94melse#x1B[39;49;00m pbmc3k()[:#x1B[94m1500#x1B[39;49;00m, :#x1B[94m1000#x1B[39;49;00m].copy()#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
        adata.obs[#x1B[33m"#x1B[39;49;00m#x1B[33mbatch#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m] = rng.choice([#x1B[33m"#x1B[39;49;00m#x1B[33ma#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mb#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m], adata.shape[#x1B[94m0#x1B[39;49;00m])#x1B[90m#x1B[39;49;00m
        adata.X = array_type(np.abs(adata.X).astype(#x1B[96mint#x1B[39;49;00m))#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m flavor #x1B[95min#x1B[39;49;00m {#x1B[33m"#x1B[39;49;00m#x1B[33mseurat#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mcell_ranger#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m}:#x1B[90m#x1B[39;49;00m
            sc.pp.normalize_total(adata, target_sum=#x1B[94m1e4#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
            sc.pp.log1p(adata)#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        n_genes = adata.shape[#x1B[94m1#x1B[39;49;00m]#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        adatas: #x1B[96mdict#x1B[39;49;00m[#x1B[96mbool#x1B[39;49;00m, AnnData] = {}#x1B[90m#x1B[39;49;00m
        dfs: #x1B[96mdict#x1B[39;49;00m[#x1B[96mbool#x1B[39;49;00m, pd.DataFrame] = {}#x1B[90m#x1B[39;49;00m
        #x1B[90m# for loops instead of parametrization to compare between settings#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        #x1B[94mfor#x1B[39;49;00m subset, inplace #x1B[95min#x1B[39;49;00m itertools.product([#x1B[94mTrue#x1B[39;49;00m, #x1B[94mFalse#x1B[39;49;00m], repeat=#x1B[94m2#x1B[39;49;00m):#x1B[90m#x1B[39;49;00m
            adata_copy = adata.copy()#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
>           output_df = sc.pp.highly_variable_genes(#x1B[90m#x1B[39;49;00m
                adata_copy,#x1B[90m#x1B[39;49;00m
                flavor=flavor,#x1B[90m#x1B[39;49;00m
                n_top_genes=#x1B[94m15#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
                batch_key=batch_key,#x1B[90m#x1B[39;49;00m
                subset=subset,#x1B[90m#x1B[39;49;00m
                inplace=inplace,#x1B[90m#x1B[39;49;00m
            )#x1B[90m#x1B[39;49;00m

#x1B[1m#x1B[31mtests/test_highly_variable_genes.py#x1B[0m:686: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
#x1B[1m#x1B[.../scanpy/preprocessing/_highly_variable_genes.py#x1B[0m:780: in highly_variable_genes
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m _highly_variable_genes_seurat_v3(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[.../scanpy/preprocessing/_highly_variable_genes.py#x1B[0m:196: in _highly_variable_genes_seurat_v3
    #x1B[0maggregated_mean_var = ad.AnnData(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:254: in __init__
    #x1B[0m#x1B[96mself#x1B[39;49;00m._init_as_actual(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:448: in _init_as_actual
    #x1B[0m#x1B[96mself#x1B[39;49;00m._obs = _gen_dataframe(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../...../_temp/uv-python-dir/cpython-3.14.5-linux-x86_64-gnu/lib/python3.14/functools.py#x1B[0m:982: in wrapper
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m dispatch(args[#x1B[94m0#x1B[39;49;00m].#x1B[91m__class__#x1B[39;49;00m)(*args, **kw)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

anno =    __hvg_v3_batch_info__
0                      0
index_names = ['obs_names', 'row_names']

    #x1B[0m#x1B[37m@_gen_dataframe#x1B[39;49;00m.register(pd.DataFrame)#x1B[90m#x1B[39;49;00m
    #x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92m_gen_dataframe_df#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
        anno: pd.DataFrame,#x1B[90m#x1B[39;49;00m
        index_names: Iterable[#x1B[96mstr#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
        *,#x1B[90m#x1B[39;49;00m
        source: Literal[#x1B[33m"#x1B[39;49;00m#x1B[33mX#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mshape#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
        attr: Literal[#x1B[33m"#x1B[39;49;00m#x1B[33mobs#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mvar#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
        length: #x1B[96mint#x1B[39;49;00m | #x1B[94mNone#x1B[39;49;00m = #x1B[94mNone#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
    ):#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m #x1B[96misinstance#x1B[39;49;00m(anno.index, pd.MultiIndex):#x1B[90m#x1B[39;49;00m
            msg = (#x1B[90m#x1B[39;49;00m
                #x1B[33m"#x1B[39;49;00m#x1B[33mpandas.MultiIndex not supported as index for obs or var on declaration.#x1B[39;49;00m#x1B[33m\n#x1B[39;49;00m#x1B[33m\#x1B[39;49;00m
    #x1B[33m            You can set `obs_names` manually although most operations after will error or convert to str.#x1B[39;49;00m#x1B[33m\n#x1B[39;49;00m#x1B[33m\#x1B[39;49;00m
    #x1B[33m            This behavior will likely be clarified in a future breaking release.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            )#x1B[90m#x1B[39;49;00m
            #x1B[94mraise#x1B[39;49;00m #x1B[96mValueError#x1B[39;49;00m(msg)#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m length #x1B[95mis#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[94mNone#x1B[39;49;00m #x1B[95mand#x1B[39;49;00m length != #x1B[96mlen#x1B[39;49;00m(anno):#x1B[90m#x1B[39;49;00m
            #x1B[94mraise#x1B[39;49;00m _mk_df_error(source, attr, length, #x1B[96mlen#x1B[39;49;00m(anno))#x1B[90m#x1B[39;49;00m
        anno = anno.copy(deep=#x1B[94mFalse#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m is_string_dtype(anno.index[~anno.index.isna()]):#x1B[90m#x1B[39;49;00m
            msg = #x1B[33m"#x1B[39;49;00m#x1B[33mTransforming to str index.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
>           warnings.warn(msg, ImplicitModificationWarning, stacklevel=#x1B[94m2#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31mE           anndata._warnings.ImplicitModificationWarning: Transforming to str index.#x1B[0m

#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/aligned_df.py#x1B[0m:93: ImplicitModificationWarning
tests/test_highly_variable_genes.py::test_dask_consistency[dask_array_sparse-1d_chunked-csr_matrix-batched-seurat_v3_paper]
Stack Traces | 0.022s run time
adata = AnnData object with n_obs × n_vars = 1500 × 1000
    obs: 'batch'
    var: 'gene_ids'
flavor = 'seurat_v3_paper', batch_key = 'batch'
to_dask = <function gen_csr_csc_params_wrapper.<locals>.wrapper at 0x7f57df075380>

    #x1B[0m#x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[90m#x1B[39;49;00m
        #x1B[33m"#x1B[39;49;00m#x1B[33mflavor#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
        [#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mseurat#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mcell_ranger#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            pytest.param(#x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, marks=needs.skmisc),#x1B[90m#x1B[39;49;00m
            pytest.param(#x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3_paper#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, marks=needs.skmisc),#x1B[90m#x1B[39;49;00m
        ],#x1B[90m#x1B[39;49;00m
    )#x1B[90m#x1B[39;49;00m
    #x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[33m"#x1B[39;49;00m#x1B[33mbatch_key#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, [#x1B[94mNone#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mbatch#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m], ids=[#x1B[33m"#x1B[39;49;00m#x1B[33msingle#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mbatched#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m])#x1B[90m#x1B[39;49;00m
    #x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[90m#x1B[39;49;00m
        #x1B[33m"#x1B[39;49;00m#x1B[33mto_dask#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, [p #x1B[94mfor#x1B[39;49;00m p #x1B[95min#x1B[39;49;00m ARRAY_TYPES #x1B[94mif#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33m1d_chunked#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95min#x1B[39;49;00m p.id #x1B[95mand#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mcsr#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95min#x1B[39;49;00m p.id]#x1B[90m#x1B[39;49;00m
    )#x1B[90m#x1B[39;49;00m
    #x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92mtest_dask_consistency#x1B[39;49;00m(adata: AnnData, flavor, batch_key, to_dask):#x1B[90m#x1B[39;49;00m
        #x1B[90m# current blob produces singularities in loess....maybe a bad sign of the data?#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95min#x1B[39;49;00m flavor:#x1B[90m#x1B[39;49;00m
            adata = pbmc3k()[:#x1B[94m1500#x1B[39;49;00m, :#x1B[94m1000#x1B[39;49;00m].copy()#x1B[90m#x1B[39;49;00m
        adata.X = np.abs(adata.X).astype(#x1B[96mint#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m batch_key #x1B[95mis#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[94mNone#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
            adata.obs[batch_key] = np.tile([#x1B[33m"#x1B[39;49;00m#x1B[33ma#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mb#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m], adata.shape[#x1B[94m0#x1B[39;49;00m] // #x1B[94m2#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
        #x1B[90m# seurat_v3 expects counts#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[95min#x1B[39;49;00m flavor:#x1B[90m#x1B[39;49;00m
            sc.pp.normalize_total(adata, target_sum=#x1B[94m1e4#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
            sc.pp.log1p(adata)#x1B[90m#x1B[39;49;00m
        adata_dask = adata.copy()#x1B[90m#x1B[39;49;00m
        adata_dask.X = to_dask(adata_dask.X)#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        #x1B[94mwith#x1B[39;49;00m (#x1B[90m#x1B[39;49;00m
            pytest.warns(#x1B[96mUserWarning#x1B[39;49;00m, match=#x1B[33m"#x1B[39;49;00m#x1B[33mn_top_genes.*normalized dispersions#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
            #x1B[94mif#x1B[39;49;00m flavor == #x1B[33m"#x1B[39;49;00m#x1B[33mcell_ranger#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            #x1B[94melse#x1B[39;49;00m nullcontext()#x1B[90m#x1B[39;49;00m
        ):#x1B[90m#x1B[39;49;00m
>           output_mem, output_dask = (#x1B[90m#x1B[39;49;00m
            ^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
                sc.pp.highly_variable_genes(#x1B[90m#x1B[39;49;00m
                    ad, flavor=flavor, n_top_genes=#x1B[94m15#x1B[39;49;00m, inplace=#x1B[94mFalse#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
                )#x1B[90m#x1B[39;49;00m
                #x1B[94mfor#x1B[39;49;00m ad #x1B[95min#x1B[39;49;00m [adata, adata_dask]#x1B[90m#x1B[39;49;00m
            )#x1B[90m#x1B[39;49;00m

#x1B[1m#x1B[31mtests/test_highly_variable_genes.py#x1B[0m:758: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
#x1B[1m#x1B[31mtests/test_highly_variable_genes.py#x1B[0m:759: in <genexpr>
    #x1B[0msc.pp.highly_variable_genes(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[.../scanpy/preprocessing/_highly_variable_genes.py#x1B[0m:780: in highly_variable_genes
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m _highly_variable_genes_seurat_v3(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[.../scanpy/preprocessing/_highly_variable_genes.py#x1B[0m:196: in _highly_variable_genes_seurat_v3
    #x1B[0maggregated_mean_var = ad.AnnData(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:254: in __init__
    #x1B[0m#x1B[96mself#x1B[39;49;00m._init_as_actual(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:448: in _init_as_actual
    #x1B[0m#x1B[96mself#x1B[39;49;00m._obs = _gen_dataframe(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../...../_temp/uv-python-dir/cpython-3.14.5-linux-x86_64-gnu/lib/python3.14/functools.py#x1B[0m:982: in wrapper
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m dispatch(args[#x1B[94m0#x1B[39;49;00m].#x1B[91m__class__#x1B[39;49;00m)(*args, **kw)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

anno =    __hvg_v3_batch_info__
0                      0
index_names = ['obs_names', 'row_names']

    #x1B[0m#x1B[37m@_gen_dataframe#x1B[39;49;00m.register(pd.DataFrame)#x1B[90m#x1B[39;49;00m
    #x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92m_gen_dataframe_df#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
        anno: pd.DataFrame,#x1B[90m#x1B[39;49;00m
        index_names: Iterable[#x1B[96mstr#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
        *,#x1B[90m#x1B[39;49;00m
        source: Literal[#x1B[33m"#x1B[39;49;00m#x1B[33mX#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mshape#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
        attr: Literal[#x1B[33m"#x1B[39;49;00m#x1B[33mobs#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mvar#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
        length: #x1B[96mint#x1B[39;49;00m | #x1B[94mNone#x1B[39;49;00m = #x1B[94mNone#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
    ):#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m #x1B[96misinstance#x1B[39;49;00m(anno.index, pd.MultiIndex):#x1B[90m#x1B[39;49;00m
            msg = (#x1B[90m#x1B[39;49;00m
                #x1B[33m"#x1B[39;49;00m#x1B[33mpandas.MultiIndex not supported as index for obs or var on declaration.#x1B[39;49;00m#x1B[33m\n#x1B[39;49;00m#x1B[33m\#x1B[39;49;00m
    #x1B[33m            You can set `obs_names` manually although most operations after will error or convert to str.#x1B[39;49;00m#x1B[33m\n#x1B[39;49;00m#x1B[33m\#x1B[39;49;00m
    #x1B[33m            This behavior will likely be clarified in a future breaking release.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            )#x1B[90m#x1B[39;49;00m
            #x1B[94mraise#x1B[39;49;00m #x1B[96mValueError#x1B[39;49;00m(msg)#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m length #x1B[95mis#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[94mNone#x1B[39;49;00m #x1B[95mand#x1B[39;49;00m length != #x1B[96mlen#x1B[39;49;00m(anno):#x1B[90m#x1B[39;49;00m
            #x1B[94mraise#x1B[39;49;00m _mk_df_error(source, attr, length, #x1B[96mlen#x1B[39;49;00m(anno))#x1B[90m#x1B[39;49;00m
        anno = anno.copy(deep=#x1B[94mFalse#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m is_string_dtype(anno.index[~anno.index.isna()]):#x1B[90m#x1B[39;49;00m
            msg = #x1B[33m"#x1B[39;49;00m#x1B[33mTransforming to str index.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
>           warnings.warn(msg, ImplicitModificationWarning, stacklevel=#x1B[94m2#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31mE           anndata._warnings.ImplicitModificationWarning: Transforming to str index.#x1B[0m

#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/aligned_df.py#x1B[0m:93: ImplicitModificationWarning
tests/test_highly_variable_genes.py::test_subset_inplace_consistency[None-scipy_csc_mat-seurat_v3]
Stack Traces | 0.023s run time
subtests = <_pytest.subtests.Subtests object at 0x7f57c0ea47d0>
flavor = 'seurat_v3', array_type = <class 'scipy.sparse._csc.csc_matrix'>
batch_key = None

    #x1B[0m#x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[90m#x1B[39;49;00m
        #x1B[33m"#x1B[39;49;00m#x1B[33mflavor#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
        [#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mseurat#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mcell_ranger#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            pytest.param(#x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, marks=needs.skmisc),#x1B[90m#x1B[39;49;00m
            pytest.param(#x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3_paper#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, marks=needs.skmisc),#x1B[90m#x1B[39;49;00m
        ],#x1B[90m#x1B[39;49;00m
    )#x1B[90m#x1B[39;49;00m
    #x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[90m#x1B[39;49;00m
        #x1B[33m"#x1B[39;49;00m#x1B[33marray_type#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
        [#x1B[90m#x1B[39;49;00m
            p#x1B[90m#x1B[39;49;00m
            #x1B[94mfor#x1B[39;49;00m p #x1B[95min#x1B[39;49;00m ARRAY_TYPES#x1B[90m#x1B[39;49;00m
            #x1B[94mif#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mdask#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[95min#x1B[39;49;00m p.id #x1B[95mor#x1B[39;49;00m (#x1B[33m"#x1B[39;49;00m#x1B[33m1d_chunked#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95min#x1B[39;49;00m p.id #x1B[95mand#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mcsr#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95min#x1B[39;49;00m p.id)#x1B[90m#x1B[39;49;00m
        ],#x1B[90m#x1B[39;49;00m
    )#x1B[90m#x1B[39;49;00m
    #x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[33m"#x1B[39;49;00m#x1B[33mbatch_key#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, [#x1B[94mNone#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mbatch#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_subset_inplace_consistency#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
        subtests: pytest.Subtests,#x1B[90m#x1B[39;49;00m
        flavor: Literal[#x1B[33m"#x1B[39;49;00m#x1B[33mseurat#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mcell_ranger#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3_paper#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
        array_type,#x1B[90m#x1B[39;49;00m
        batch_key: Literal[#x1B[33m"#x1B[39;49;00m#x1B[33mbatch#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m] | #x1B[94mNone#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
    ) -> #x1B[94mNone#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
    #x1B[90m    #x1B[39;49;00m#x1B[33m"""Tests `n_top_genes=n`.#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m    - if `inplace` and `subset` interact correctly#x1B[39;49;00m
    #x1B[33m    - for both the `seurat` and `cell_ranger` flavors#x1B[39;49;00m
    #x1B[33m    - for dask arrays and non-dask arrays#x1B[39;49;00m
    #x1B[33m    - for both with and without batch_key#x1B[39;49;00m
    #x1B[33m    """#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        rng = np.random.default_rng(#x1B[94m0#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
        adata = (#x1B[90m#x1B[39;49;00m
            sc.datasets.blobs(n_observations=#x1B[94m20#x1B[39;49;00m, n_variables=#x1B[94m80#x1B[39;49;00m, rng=rng)#x1B[90m#x1B[39;49;00m
            #x1B[94mif#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[95min#x1B[39;49;00m flavor#x1B[90m#x1B[39;49;00m
            #x1B[94melse#x1B[39;49;00m pbmc3k()[:#x1B[94m1500#x1B[39;49;00m, :#x1B[94m1000#x1B[39;49;00m].copy()#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
        adata.obs[#x1B[33m"#x1B[39;49;00m#x1B[33mbatch#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m] = rng.choice([#x1B[33m"#x1B[39;49;00m#x1B[33ma#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mb#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m], adata.shape[#x1B[94m0#x1B[39;49;00m])#x1B[90m#x1B[39;49;00m
        adata.X = array_type(np.abs(adata.X).astype(#x1B[96mint#x1B[39;49;00m))#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m flavor #x1B[95min#x1B[39;49;00m {#x1B[33m"#x1B[39;49;00m#x1B[33mseurat#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mcell_ranger#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m}:#x1B[90m#x1B[39;49;00m
            sc.pp.normalize_total(adata, target_sum=#x1B[94m1e4#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
            sc.pp.log1p(adata)#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        n_genes = adata.shape[#x1B[94m1#x1B[39;49;00m]#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        adatas: #x1B[96mdict#x1B[39;49;00m[#x1B[96mbool#x1B[39;49;00m, AnnData] = {}#x1B[90m#x1B[39;49;00m
        dfs: #x1B[96mdict#x1B[39;49;00m[#x1B[96mbool#x1B[39;49;00m, pd.DataFrame] = {}#x1B[90m#x1B[39;49;00m
        #x1B[90m# for loops instead of parametrization to compare between settings#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        #x1B[94mfor#x1B[39;49;00m subset, inplace #x1B[95min#x1B[39;49;00m itertools.product([#x1B[94mTrue#x1B[39;49;00m, #x1B[94mFalse#x1B[39;49;00m], repeat=#x1B[94m2#x1B[39;49;00m):#x1B[90m#x1B[39;49;00m
            adata_copy = adata.copy()#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
>           output_df = sc.pp.highly_variable_genes(#x1B[90m#x1B[39;49;00m
                adata_copy,#x1B[90m#x1B[39;49;00m
                flavor=flavor,#x1B[90m#x1B[39;49;00m
                n_top_genes=#x1B[94m15#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
                batch_key=batch_key,#x1B[90m#x1B[39;49;00m
                subset=subset,#x1B[90m#x1B[39;49;00m
                inplace=inplace,#x1B[90m#x1B[39;49;00m
            )#x1B[90m#x1B[39;49;00m

#x1B[1m#x1B[31mtests/test_highly_variable_genes.py#x1B[0m:686: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
#x1B[1m#x1B[.../scanpy/preprocessing/_highly_variable_genes.py#x1B[0m:780: in highly_variable_genes
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m _highly_variable_genes_seurat_v3(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[.../scanpy/preprocessing/_highly_variable_genes.py#x1B[0m:196: in _highly_variable_genes_seurat_v3
    #x1B[0maggregated_mean_var = ad.AnnData(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:254: in __init__
    #x1B[0m#x1B[96mself#x1B[39;49;00m._init_as_actual(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:448: in _init_as_actual
    #x1B[0m#x1B[96mself#x1B[39;49;00m._obs = _gen_dataframe(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../...../_temp/uv-python-dir/cpython-3.14.5-linux-x86_64-gnu/lib/python3.14/functools.py#x1B[0m:982: in wrapper
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m dispatch(args[#x1B[94m0#x1B[39;49;00m].#x1B[91m__class__#x1B[39;49;00m)(*args, **kw)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

anno =    __hvg_v3_batch_info__
0                      0
index_names = ['obs_names', 'row_names']

    #x1B[0m#x1B[37m@_gen_dataframe#x1B[39;49;00m.register(pd.DataFrame)#x1B[90m#x1B[39;49;00m
    #x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92m_gen_dataframe_df#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
        anno: pd.DataFrame,#x1B[90m#x1B[39;49;00m
        index_names: Iterable[#x1B[96mstr#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
        *,#x1B[90m#x1B[39;49;00m
        source: Literal[#x1B[33m"#x1B[39;49;00m#x1B[33mX#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mshape#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
        attr: Literal[#x1B[33m"#x1B[39;49;00m#x1B[33mobs#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mvar#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
        length: #x1B[96mint#x1B[39;49;00m | #x1B[94mNone#x1B[39;49;00m = #x1B[94mNone#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
    ):#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m #x1B[96misinstance#x1B[39;49;00m(anno.index, pd.MultiIndex):#x1B[90m#x1B[39;49;00m
            msg = (#x1B[90m#x1B[39;49;00m
                #x1B[33m"#x1B[39;49;00m#x1B[33mpandas.MultiIndex not supported as index for obs or var on declaration.#x1B[39;49;00m#x1B[33m\n#x1B[39;49;00m#x1B[33m\#x1B[39;49;00m
    #x1B[33m            You can set `obs_names` manually although most operations after will error or convert to str.#x1B[39;49;00m#x1B[33m\n#x1B[39;49;00m#x1B[33m\#x1B[39;49;00m
    #x1B[33m            This behavior will likely be clarified in a future breaking release.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            )#x1B[90m#x1B[39;49;00m
            #x1B[94mraise#x1B[39;49;00m #x1B[96mValueError#x1B[39;49;00m(msg)#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m length #x1B[95mis#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[94mNone#x1B[39;49;00m #x1B[95mand#x1B[39;49;00m length != #x1B[96mlen#x1B[39;49;00m(anno):#x1B[90m#x1B[39;49;00m
            #x1B[94mraise#x1B[39;49;00m _mk_df_error(source, attr, length, #x1B[96mlen#x1B[39;49;00m(anno))#x1B[90m#x1B[39;49;00m
        anno = anno.copy(deep=#x1B[94mFalse#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m is_string_dtype(anno.index[~anno.index.isna()]):#x1B[90m#x1B[39;49;00m
            msg = #x1B[33m"#x1B[39;49;00m#x1B[33mTransforming to str index.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
>           warnings.warn(msg, ImplicitModificationWarning, stacklevel=#x1B[94m2#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31mE           anndata._warnings.ImplicitModificationWarning: Transforming to str index.#x1B[0m

#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/aligned_df.py#x1B[0m:93: ImplicitModificationWarning
tests/test_highly_variable_genes.py::test_seurat_v3_degenerate
Stack Traces | 0.025s run time
#x1B[0m#x1B[37m@needs#x1B[39;49;00m.skmisc#x1B[90m#x1B[39;49;00m
    #x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92mtest_seurat_v3_degenerate#x1B[39;49;00m() -> #x1B[94mNone#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
    #x1B[90m    #x1B[39;49;00m#x1B[33m"""Tests that the flavor handles all-zero genes."""#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        adata = AnnData(sps.random(#x1B[94m10#x1B[39;49;00m, #x1B[94m1000#x1B[39;49;00m, density=#x1B[94m0.001#x1B[39;49;00m, #x1B[96mformat#x1B[39;49;00m=#x1B[33m"#x1B[39;49;00m#x1B[33mcsr#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, dtype=#x1B[33m"#x1B[39;49;00m#x1B[33mint#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m))#x1B[90m#x1B[39;49;00m
        adata.X.data = np.abs(adata.X.data)#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
>       sc.pp.highly_variable_genes(adata, flavor=#x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m

#x1B[1m#x1B[31mtests/test_highly_variable_genes.py#x1B[0m:510: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
#x1B[1m#x1B[.../scanpy/preprocessing/_highly_variable_genes.py#x1B[0m:780: in highly_variable_genes
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m _highly_variable_genes_seurat_v3(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[.../scanpy/preprocessing/_highly_variable_genes.py#x1B[0m:196: in _highly_variable_genes_seurat_v3
    #x1B[0maggregated_mean_var = ad.AnnData(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:254: in __init__
    #x1B[0m#x1B[96mself#x1B[39;49;00m._init_as_actual(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:448: in _init_as_actual
    #x1B[0m#x1B[96mself#x1B[39;49;00m._obs = _gen_dataframe(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../...../_temp/uv-python-dir/cpython-3.14.5-linux-x86_64-gnu/lib/python3.14/functools.py#x1B[0m:982: in wrapper
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m dispatch(args[#x1B[94m0#x1B[39;49;00m].#x1B[91m__class__#x1B[39;49;00m)(*args, **kw)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

anno =    __hvg_v3_batch_info__
0                      0
index_names = ['obs_names', 'row_names']

    #x1B[0m#x1B[37m@_gen_dataframe#x1B[39;49;00m.register(pd.DataFrame)#x1B[90m#x1B[39;49;00m
    #x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92m_gen_dataframe_df#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
        anno: pd.DataFrame,#x1B[90m#x1B[39;49;00m
        index_names: Iterable[#x1B[96mstr#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
        *,#x1B[90m#x1B[39;49;00m
        source: Literal[#x1B[33m"#x1B[39;49;00m#x1B[33mX#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mshape#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
        attr: Literal[#x1B[33m"#x1B[39;49;00m#x1B[33mobs#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mvar#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
        length: #x1B[96mint#x1B[39;49;00m | #x1B[94mNone#x1B[39;49;00m = #x1B[94mNone#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
    ):#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m #x1B[96misinstance#x1B[39;49;00m(anno.index, pd.MultiIndex):#x1B[90m#x1B[39;49;00m
            msg = (#x1B[90m#x1B[39;49;00m
                #x1B[33m"#x1B[39;49;00m#x1B[33mpandas.MultiIndex not supported as index for obs or var on declaration.#x1B[39;49;00m#x1B[33m\n#x1B[39;49;00m#x1B[33m\#x1B[39;49;00m
    #x1B[33m            You can set `obs_names` manually although most operations after will error or convert to str.#x1B[39;49;00m#x1B[33m\n#x1B[39;49;00m#x1B[33m\#x1B[39;49;00m
    #x1B[33m            This behavior will likely be clarified in a future breaking release.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            )#x1B[90m#x1B[39;49;00m
            #x1B[94mraise#x1B[39;49;00m #x1B[96mValueError#x1B[39;49;00m(msg)#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m length #x1B[95mis#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[94mNone#x1B[39;49;00m #x1B[95mand#x1B[39;49;00m length != #x1B[96mlen#x1B[39;49;00m(anno):#x1B[90m#x1B[39;49;00m
            #x1B[94mraise#x1B[39;49;00m _mk_df_error(source, attr, length, #x1B[96mlen#x1B[39;49;00m(anno))#x1B[90m#x1B[39;49;00m
        anno = anno.copy(deep=#x1B[94mFalse#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m is_string_dtype(anno.index[~anno.index.isna()]):#x1B[90m#x1B[39;49;00m
            msg = #x1B[33m"#x1B[39;49;00m#x1B[33mTransforming to str index.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
>           warnings.warn(msg, ImplicitModificationWarning, stacklevel=#x1B[94m2#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31mE           anndata._warnings.ImplicitModificationWarning: Transforming to str index.#x1B[0m

#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/aligned_df.py#x1B[0m:93: ImplicitModificationWarning
tests/test_highly_variable_genes.py::test_subset_inplace_consistency[None-scipy_csc_mat-seurat_v3_paper]
Stack Traces | 0.029s run time
subtests = <_pytest.subtests.Subtests object at 0x7f57c8129eb0>
flavor = 'seurat_v3_paper', array_type = <class 'scipy.sparse._csc.csc_matrix'>
batch_key = None

    #x1B[0m#x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[90m#x1B[39;49;00m
        #x1B[33m"#x1B[39;49;00m#x1B[33mflavor#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
        [#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mseurat#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mcell_ranger#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            pytest.param(#x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, marks=needs.skmisc),#x1B[90m#x1B[39;49;00m
            pytest.param(#x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3_paper#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, marks=needs.skmisc),#x1B[90m#x1B[39;49;00m
        ],#x1B[90m#x1B[39;49;00m
    )#x1B[90m#x1B[39;49;00m
    #x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[90m#x1B[39;49;00m
        #x1B[33m"#x1B[39;49;00m#x1B[33marray_type#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
        [#x1B[90m#x1B[39;49;00m
            p#x1B[90m#x1B[39;49;00m
            #x1B[94mfor#x1B[39;49;00m p #x1B[95min#x1B[39;49;00m ARRAY_TYPES#x1B[90m#x1B[39;49;00m
            #x1B[94mif#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mdask#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[95min#x1B[39;49;00m p.id #x1B[95mor#x1B[39;49;00m (#x1B[33m"#x1B[39;49;00m#x1B[33m1d_chunked#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95min#x1B[39;49;00m p.id #x1B[95mand#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mcsr#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95min#x1B[39;49;00m p.id)#x1B[90m#x1B[39;49;00m
        ],#x1B[90m#x1B[39;49;00m
    )#x1B[90m#x1B[39;49;00m
    #x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[33m"#x1B[39;49;00m#x1B[33mbatch_key#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, [#x1B[94mNone#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mbatch#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_subset_inplace_consistency#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
        subtests: pytest.Subtests,#x1B[90m#x1B[39;49;00m
        flavor: Literal[#x1B[33m"#x1B[39;49;00m#x1B[33mseurat#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mcell_ranger#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3_paper#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
        array_type,#x1B[90m#x1B[39;49;00m
        batch_key: Literal[#x1B[33m"#x1B[39;49;00m#x1B[33mbatch#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m] | #x1B[94mNone#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
    ) -> #x1B[94mNone#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
    #x1B[90m    #x1B[39;49;00m#x1B[33m"""Tests `n_top_genes=n`.#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m    - if `inplace` and `subset` interact correctly#x1B[39;49;00m
    #x1B[33m    - for both the `seurat` and `cell_ranger` flavors#x1B[39;49;00m
    #x1B[33m    - for dask arrays and non-dask arrays#x1B[39;49;00m
    #x1B[33m    - for both with and without batch_key#x1B[39;49;00m
    #x1B[33m    """#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        rng = np.random.default_rng(#x1B[94m0#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
        adata = (#x1B[90m#x1B[39;49;00m
            sc.datasets.blobs(n_observations=#x1B[94m20#x1B[39;49;00m, n_variables=#x1B[94m80#x1B[39;49;00m, rng=rng)#x1B[90m#x1B[39;49;00m
            #x1B[94mif#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[95min#x1B[39;49;00m flavor#x1B[90m#x1B[39;49;00m
            #x1B[94melse#x1B[39;49;00m pbmc3k()[:#x1B[94m1500#x1B[39;49;00m, :#x1B[94m1000#x1B[39;49;00m].copy()#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
        adata.obs[#x1B[33m"#x1B[39;49;00m#x1B[33mbatch#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m] = rng.choice([#x1B[33m"#x1B[39;49;00m#x1B[33ma#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mb#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m], adata.shape[#x1B[94m0#x1B[39;49;00m])#x1B[90m#x1B[39;49;00m
        adata.X = array_type(np.abs(adata.X).astype(#x1B[96mint#x1B[39;49;00m))#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m flavor #x1B[95min#x1B[39;49;00m {#x1B[33m"#x1B[39;49;00m#x1B[33mseurat#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mcell_ranger#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m}:#x1B[90m#x1B[39;49;00m
            sc.pp.normalize_total(adata, target_sum=#x1B[94m1e4#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
            sc.pp.log1p(adata)#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        n_genes = adata.shape[#x1B[94m1#x1B[39;49;00m]#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        adatas: #x1B[96mdict#x1B[39;49;00m[#x1B[96mbool#x1B[39;49;00m, AnnData] = {}#x1B[90m#x1B[39;49;00m
        dfs: #x1B[96mdict#x1B[39;49;00m[#x1B[96mbool#x1B[39;49;00m, pd.DataFrame] = {}#x1B[90m#x1B[39;49;00m
        #x1B[90m# for loops instead of parametrization to compare between settings#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        #x1B[94mfor#x1B[39;49;00m subset, inplace #x1B[95min#x1B[39;49;00m itertools.product([#x1B[94mTrue#x1B[39;49;00m, #x1B[94mFalse#x1B[39;49;00m], repeat=#x1B[94m2#x1B[39;49;00m):#x1B[90m#x1B[39;49;00m
            adata_copy = adata.copy()#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
>           output_df = sc.pp.highly_variable_genes(#x1B[90m#x1B[39;49;00m
                adata_copy,#x1B[90m#x1B[39;49;00m
                flavor=flavor,#x1B[90m#x1B[39;49;00m
                n_top_genes=#x1B[94m15#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
                batch_key=batch_key,#x1B[90m#x1B[39;49;00m
                subset=subset,#x1B[90m#x1B[39;49;00m
                inplace=inplace,#x1B[90m#x1B[39;49;00m
            )#x1B[90m#x1B[39;49;00m

#x1B[1m#x1B[31mtests/test_highly_variable_genes.py#x1B[0m:686: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
#x1B[1m#x1B[.../scanpy/preprocessing/_highly_variable_genes.py#x1B[0m:780: in highly_variable_genes
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m _highly_variable_genes_seurat_v3(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[.../scanpy/preprocessing/_highly_variable_genes.py#x1B[0m:196: in _highly_variable_genes_seurat_v3
    #x1B[0maggregated_mean_var = ad.AnnData(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:254: in __init__
    #x1B[0m#x1B[96mself#x1B[39;49;00m._init_as_actual(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:448: in _init_as_actual
    #x1B[0m#x1B[96mself#x1B[39;49;00m._obs = _gen_dataframe(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../...../_temp/uv-python-dir/cpython-3.14.5-linux-x86_64-gnu/lib/python3.14/functools.py#x1B[0m:982: in wrapper
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m dispatch(args[#x1B[94m0#x1B[39;49;00m].#x1B[91m__class__#x1B[39;49;00m)(*args, **kw)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

anno =    __hvg_v3_batch_info__
0                      0
index_names = ['obs_names', 'row_names']

    #x1B[0m#x1B[37m@_gen_dataframe#x1B[39;49;00m.register(pd.DataFrame)#x1B[90m#x1B[39;49;00m
    #x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92m_gen_dataframe_df#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
        anno: pd.DataFrame,#x1B[90m#x1B[39;49;00m
        index_names: Iterable[#x1B[96mstr#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
        *,#x1B[90m#x1B[39;49;00m
        source: Literal[#x1B[33m"#x1B[39;49;00m#x1B[33mX#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mshape#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
        attr: Literal[#x1B[33m"#x1B[39;49;00m#x1B[33mobs#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mvar#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
        length: #x1B[96mint#x1B[39;49;00m | #x1B[94mNone#x1B[39;49;00m = #x1B[94mNone#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
    ):#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m #x1B[96misinstance#x1B[39;49;00m(anno.index, pd.MultiIndex):#x1B[90m#x1B[39;49;00m
            msg = (#x1B[90m#x1B[39;49;00m
                #x1B[33m"#x1B[39;49;00m#x1B[33mpandas.MultiIndex not supported as index for obs or var on declaration.#x1B[39;49;00m#x1B[33m\n#x1B[39;49;00m#x1B[33m\#x1B[39;49;00m
    #x1B[33m            You can set `obs_names` manually although most operations after will error or convert to str.#x1B[39;49;00m#x1B[33m\n#x1B[39;49;00m#x1B[33m\#x1B[39;49;00m
    #x1B[33m            This behavior will likely be clarified in a future breaking release.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            )#x1B[90m#x1B[39;49;00m
            #x1B[94mraise#x1B[39;49;00m #x1B[96mValueError#x1B[39;49;00m(msg)#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m length #x1B[95mis#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[94mNone#x1B[39;49;00m #x1B[95mand#x1B[39;49;00m length != #x1B[96mlen#x1B[39;49;00m(anno):#x1B[90m#x1B[39;49;00m
            #x1B[94mraise#x1B[39;49;00m _mk_df_error(source, attr, length, #x1B[96mlen#x1B[39;49;00m(anno))#x1B[90m#x1B[39;49;00m
        anno = anno.copy(deep=#x1B[94mFalse#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m is_string_dtype(anno.index[~anno.index.isna()]):#x1B[90m#x1B[39;49;00m
            msg = #x1B[33m"#x1B[39;49;00m#x1B[33mTransforming to str index.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
>           warnings.warn(msg, ImplicitModificationWarning, stacklevel=#x1B[94m2#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31mE           anndata._warnings.ImplicitModificationWarning: Transforming to str index.#x1B[0m

#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/aligned_df.py#x1B[0m:93: ImplicitModificationWarning
tests/test_highly_variable_genes.py::test_subset_inplace_consistency[None-dask_array_sparse-1d_chunked-csr_matrix-seurat_v3_paper]
Stack Traces | 0.04s run time
subtests = <_pytest.subtests.Subtests object at 0x7f57c0b04ad0>
flavor = 'seurat_v3_paper'
array_type = <function gen_csr_csc_params_wrapper.<locals>.wrapper at 0x7f57df075380>
batch_key = None

    #x1B[0m#x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[90m#x1B[39;49;00m
        #x1B[33m"#x1B[39;49;00m#x1B[33mflavor#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
        [#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mseurat#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mcell_ranger#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            pytest.param(#x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, marks=needs.skmisc),#x1B[90m#x1B[39;49;00m
            pytest.param(#x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3_paper#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, marks=needs.skmisc),#x1B[90m#x1B[39;49;00m
        ],#x1B[90m#x1B[39;49;00m
    )#x1B[90m#x1B[39;49;00m
    #x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[90m#x1B[39;49;00m
        #x1B[33m"#x1B[39;49;00m#x1B[33marray_type#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
        [#x1B[90m#x1B[39;49;00m
            p#x1B[90m#x1B[39;49;00m
            #x1B[94mfor#x1B[39;49;00m p #x1B[95min#x1B[39;49;00m ARRAY_TYPES#x1B[90m#x1B[39;49;00m
            #x1B[94mif#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mdask#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[95min#x1B[39;49;00m p.id #x1B[95mor#x1B[39;49;00m (#x1B[33m"#x1B[39;49;00m#x1B[33m1d_chunked#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95min#x1B[39;49;00m p.id #x1B[95mand#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mcsr#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95min#x1B[39;49;00m p.id)#x1B[90m#x1B[39;49;00m
        ],#x1B[90m#x1B[39;49;00m
    )#x1B[90m#x1B[39;49;00m
    #x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[33m"#x1B[39;49;00m#x1B[33mbatch_key#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, [#x1B[94mNone#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mbatch#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_subset_inplace_consistency#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
        subtests: pytest.Subtests,#x1B[90m#x1B[39;49;00m
        flavor: Literal[#x1B[33m"#x1B[39;49;00m#x1B[33mseurat#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mcell_ranger#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3_paper#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
        array_type,#x1B[90m#x1B[39;49;00m
        batch_key: Literal[#x1B[33m"#x1B[39;49;00m#x1B[33mbatch#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m] | #x1B[94mNone#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
    ) -> #x1B[94mNone#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
    #x1B[90m    #x1B[39;49;00m#x1B[33m"""Tests `n_top_genes=n`.#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m    - if `inplace` and `subset` interact correctly#x1B[39;49;00m
    #x1B[33m    - for both the `seurat` and `cell_ranger` flavors#x1B[39;49;00m
    #x1B[33m    - for dask arrays and non-dask arrays#x1B[39;49;00m
    #x1B[33m    - for both with and without batch_key#x1B[39;49;00m
    #x1B[33m    """#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        rng = np.random.default_rng(#x1B[94m0#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
        adata = (#x1B[90m#x1B[39;49;00m
            sc.datasets.blobs(n_observations=#x1B[94m20#x1B[39;49;00m, n_variables=#x1B[94m80#x1B[39;49;00m, rng=rng)#x1B[90m#x1B[39;49;00m
            #x1B[94mif#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[95min#x1B[39;49;00m flavor#x1B[90m#x1B[39;49;00m
            #x1B[94melse#x1B[39;49;00m pbmc3k()[:#x1B[94m1500#x1B[39;49;00m, :#x1B[94m1000#x1B[39;49;00m].copy()#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
        adata.obs[#x1B[33m"#x1B[39;49;00m#x1B[33mbatch#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m] = rng.choice([#x1B[33m"#x1B[39;49;00m#x1B[33ma#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mb#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m], adata.shape[#x1B[94m0#x1B[39;49;00m])#x1B[90m#x1B[39;49;00m
        adata.X = array_type(np.abs(adata.X).astype(#x1B[96mint#x1B[39;49;00m))#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m flavor #x1B[95min#x1B[39;49;00m {#x1B[33m"#x1B[39;49;00m#x1B[33mseurat#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mcell_ranger#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m}:#x1B[90m#x1B[39;49;00m
            sc.pp.normalize_total(adata, target_sum=#x1B[94m1e4#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
            sc.pp.log1p(adata)#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        n_genes = adata.shape[#x1B[94m1#x1B[39;49;00m]#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        adatas: #x1B[96mdict#x1B[39;49;00m[#x1B[96mbool#x1B[39;49;00m, AnnData] = {}#x1B[90m#x1B[39;49;00m
        dfs: #x1B[96mdict#x1B[39;49;00m[#x1B[96mbool#x1B[39;49;00m, pd.DataFrame] = {}#x1B[90m#x1B[39;49;00m
        #x1B[90m# for loops instead of parametrization to compare between settings#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        #x1B[94mfor#x1B[39;49;00m subset, inplace #x1B[95min#x1B[39;49;00m itertools.product([#x1B[94mTrue#x1B[39;49;00m, #x1B[94mFalse#x1B[39;49;00m], repeat=#x1B[94m2#x1B[39;49;00m):#x1B[90m#x1B[39;49;00m
            adata_copy = adata.copy()#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
>           output_df = sc.pp.highly_variable_genes(#x1B[90m#x1B[39;49;00m
                adata_copy,#x1B[90m#x1B[39;49;00m
                flavor=flavor,#x1B[90m#x1B[39;49;00m
                n_top_genes=#x1B[94m15#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
                batch_key=batch_key,#x1B[90m#x1B[39;49;00m
                subset=subset,#x1B[90m#x1B[39;49;00m
                inplace=inplace,#x1B[90m#x1B[39;49;00m
            )#x1B[90m#x1B[39;49;00m

#x1B[1m#x1B[31mtests/test_highly_variable_genes.py#x1B[0m:686: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
#x1B[1m#x1B[.../scanpy/preprocessing/_highly_variable_genes.py#x1B[0m:780: in highly_variable_genes
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m _highly_variable_genes_seurat_v3(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[.../scanpy/preprocessing/_highly_variable_genes.py#x1B[0m:196: in _highly_variable_genes_seurat_v3
    #x1B[0maggregated_mean_var = ad.AnnData(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:254: in __init__
    #x1B[0m#x1B[96mself#x1B[39;49;00m._init_as_actual(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:448: in _init_as_actual
    #x1B[0m#x1B[96mself#x1B[39;49;00m._obs = _gen_dataframe(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../...../_temp/uv-python-dir/cpython-3.14.5-linux-x86_64-gnu/lib/python3.14/functools.py#x1B[0m:982: in wrapper
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m dispatch(args[#x1B[94m0#x1B[39;49;00m].#x1B[91m__class__#x1B[39;49;00m)(*args, **kw)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

anno =    __hvg_v3_batch_info__
0                      0
index_names = ['obs_names', 'row_names']

    #x1B[0m#x1B[37m@_gen_dataframe#x1B[39;49;00m.register(pd.DataFrame)#x1B[90m#x1B[39;49;00m
    #x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92m_gen_dataframe_df#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
        anno: pd.DataFrame,#x1B[90m#x1B[39;49;00m
        index_names: Iterable[#x1B[96mstr#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
        *,#x1B[90m#x1B[39;49;00m
        source: Literal[#x1B[33m"#x1B[39;49;00m#x1B[33mX#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mshape#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
        attr: Literal[#x1B[33m"#x1B[39;49;00m#x1B[33mobs#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mvar#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
        length: #x1B[96mint#x1B[39;49;00m | #x1B[94mNone#x1B[39;49;00m = #x1B[94mNone#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
    ):#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m #x1B[96misinstance#x1B[39;49;00m(anno.index, pd.MultiIndex):#x1B[90m#x1B[39;49;00m
            msg = (#x1B[90m#x1B[39;49;00m
                #x1B[33m"#x1B[39;49;00m#x1B[33mpandas.MultiIndex not supported as index for obs or var on declaration.#x1B[39;49;00m#x1B[33m\n#x1B[39;49;00m#x1B[33m\#x1B[39;49;00m
    #x1B[33m            You can set `obs_names` manually although most operations after will error or convert to str.#x1B[39;49;00m#x1B[33m\n#x1B[39;49;00m#x1B[33m\#x1B[39;49;00m
    #x1B[33m            This behavior will likely be clarified in a future breaking release.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            )#x1B[90m#x1B[39;49;00m
            #x1B[94mraise#x1B[39;49;00m #x1B[96mValueError#x1B[39;49;00m(msg)#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m length #x1B[95mis#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[94mNone#x1B[39;49;00m #x1B[95mand#x1B[39;49;00m length != #x1B[96mlen#x1B[39;49;00m(anno):#x1B[90m#x1B[39;49;00m
            #x1B[94mraise#x1B[39;49;00m _mk_df_error(source, attr, length, #x1B[96mlen#x1B[39;49;00m(anno))#x1B[90m#x1B[39;49;00m
        anno = anno.copy(deep=#x1B[94mFalse#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m is_string_dtype(anno.index[~anno.index.isna()]):#x1B[90m#x1B[39;49;00m
            msg = #x1B[33m"#x1B[39;49;00m#x1B[33mTransforming to str index.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
>           warnings.warn(msg, ImplicitModificationWarning, stacklevel=#x1B[94m2#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31mE           anndata._warnings.ImplicitModificationWarning: Transforming to str index.#x1B[0m

#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/aligned_df.py#x1B[0m:93: ImplicitModificationWarning
tests/test_highly_variable_genes.py::test_subset_inplace_consistency[None-dask_array_sparse-1d_chunked-csr_matrix-seurat_v3]
Stack Traces | 0.044s run time
subtests = <_pytest.subtests.Subtests object at 0x7f57c82b2cf0>
flavor = 'seurat_v3'
array_type = <function gen_csr_csc_params_wrapper.<locals>.wrapper at 0x7f57df075380>
batch_key = None

    #x1B[0m#x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[90m#x1B[39;49;00m
        #x1B[33m"#x1B[39;49;00m#x1B[33mflavor#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
        [#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mseurat#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mcell_ranger#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            pytest.param(#x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, marks=needs.skmisc),#x1B[90m#x1B[39;49;00m
            pytest.param(#x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3_paper#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, marks=needs.skmisc),#x1B[90m#x1B[39;49;00m
        ],#x1B[90m#x1B[39;49;00m
    )#x1B[90m#x1B[39;49;00m
    #x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[90m#x1B[39;49;00m
        #x1B[33m"#x1B[39;49;00m#x1B[33marray_type#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
        [#x1B[90m#x1B[39;49;00m
            p#x1B[90m#x1B[39;49;00m
            #x1B[94mfor#x1B[39;49;00m p #x1B[95min#x1B[39;49;00m ARRAY_TYPES#x1B[90m#x1B[39;49;00m
            #x1B[94mif#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mdask#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[95min#x1B[39;49;00m p.id #x1B[95mor#x1B[39;49;00m (#x1B[33m"#x1B[39;49;00m#x1B[33m1d_chunked#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95min#x1B[39;49;00m p.id #x1B[95mand#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mcsr#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95min#x1B[39;49;00m p.id)#x1B[90m#x1B[39;49;00m
        ],#x1B[90m#x1B[39;49;00m
    )#x1B[90m#x1B[39;49;00m
    #x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[33m"#x1B[39;49;00m#x1B[33mbatch_key#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, [#x1B[94mNone#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mbatch#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_subset_inplace_consistency#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
        subtests: pytest.Subtests,#x1B[90m#x1B[39;49;00m
        flavor: Literal[#x1B[33m"#x1B[39;49;00m#x1B[33mseurat#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mcell_ranger#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3_paper#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
        array_type,#x1B[90m#x1B[39;49;00m
        batch_key: Literal[#x1B[33m"#x1B[39;49;00m#x1B[33mbatch#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m] | #x1B[94mNone#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
    ) -> #x1B[94mNone#x1B[39;49;00m:#x1B[90m#x1B[39;49;00m
    #x1B[90m    #x1B[39;49;00m#x1B[33m"""Tests `n_top_genes=n`.#x1B[39;49;00m
    #x1B[33m#x1B[39;49;00m
    #x1B[33m    - if `inplace` and `subset` interact correctly#x1B[39;49;00m
    #x1B[33m    - for both the `seurat` and `cell_ranger` flavors#x1B[39;49;00m
    #x1B[33m    - for dask arrays and non-dask arrays#x1B[39;49;00m
    #x1B[33m    - for both with and without batch_key#x1B[39;49;00m
    #x1B[33m    """#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        rng = np.random.default_rng(#x1B[94m0#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
        adata = (#x1B[90m#x1B[39;49;00m
            sc.datasets.blobs(n_observations=#x1B[94m20#x1B[39;49;00m, n_variables=#x1B[94m80#x1B[39;49;00m, rng=rng)#x1B[90m#x1B[39;49;00m
            #x1B[94mif#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[95min#x1B[39;49;00m flavor#x1B[90m#x1B[39;49;00m
            #x1B[94melse#x1B[39;49;00m pbmc3k()[:#x1B[94m1500#x1B[39;49;00m, :#x1B[94m1000#x1B[39;49;00m].copy()#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
        adata.obs[#x1B[33m"#x1B[39;49;00m#x1B[33mbatch#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m] = rng.choice([#x1B[33m"#x1B[39;49;00m#x1B[33ma#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mb#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m], adata.shape[#x1B[94m0#x1B[39;49;00m])#x1B[90m#x1B[39;49;00m
        adata.X = array_type(np.abs(adata.X).astype(#x1B[96mint#x1B[39;49;00m))#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m flavor #x1B[95min#x1B[39;49;00m {#x1B[33m"#x1B[39;49;00m#x1B[33mseurat#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mcell_ranger#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m}:#x1B[90m#x1B[39;49;00m
            sc.pp.normalize_total(adata, target_sum=#x1B[94m1e4#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
            sc.pp.log1p(adata)#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        n_genes = adata.shape[#x1B[94m1#x1B[39;49;00m]#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        adatas: #x1B[96mdict#x1B[39;49;00m[#x1B[96mbool#x1B[39;49;00m, AnnData] = {}#x1B[90m#x1B[39;49;00m
        dfs: #x1B[96mdict#x1B[39;49;00m[#x1B[96mbool#x1B[39;49;00m, pd.DataFrame] = {}#x1B[90m#x1B[39;49;00m
        #x1B[90m# for loops instead of parametrization to compare between settings#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        #x1B[94mfor#x1B[39;49;00m subset, inplace #x1B[95min#x1B[39;49;00m itertools.product([#x1B[94mTrue#x1B[39;49;00m, #x1B[94mFalse#x1B[39;49;00m], repeat=#x1B[94m2#x1B[39;49;00m):#x1B[90m#x1B[39;49;00m
            adata_copy = adata.copy()#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
>           output_df = sc.pp.highly_variable_genes(#x1B[90m#x1B[39;49;00m
                adata_copy,#x1B[90m#x1B[39;49;00m
                flavor=flavor,#x1B[90m#x1B[39;49;00m
                n_top_genes=#x1B[94m15#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
                batch_key=batch_key,#x1B[90m#x1B[39;49;00m
                subset=subset,#x1B[90m#x1B[39;49;00m
                inplace=inplace,#x1B[90m#x1B[39;49;00m
            )#x1B[90m#x1B[39;49;00m

#x1B[1m#x1B[31mtests/test_highly_variable_genes.py#x1B[0m:686: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
#x1B[1m#x1B[.../scanpy/preprocessing/_highly_variable_genes.py#x1B[0m:780: in highly_variable_genes
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m _highly_variable_genes_seurat_v3(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[.../scanpy/preprocessing/_highly_variable_genes.py#x1B[0m:196: in _highly_variable_genes_seurat_v3
    #x1B[0maggregated_mean_var = ad.AnnData(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:254: in __init__
    #x1B[0m#x1B[96mself#x1B[39;49;00m._init_as_actual(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:448: in _init_as_actual
    #x1B[0m#x1B[96mself#x1B[39;49;00m._obs = _gen_dataframe(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../...../_temp/uv-python-dir/cpython-3.14.5-linux-x86_64-gnu/lib/python3.14/functools.py#x1B[0m:982: in wrapper
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m dispatch(args[#x1B[94m0#x1B[39;49;00m].#x1B[91m__class__#x1B[39;49;00m)(*args, **kw)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

anno =    __hvg_v3_batch_info__
0                      0
index_names = ['obs_names', 'row_names']

    #x1B[0m#x1B[37m@_gen_dataframe#x1B[39;49;00m.register(pd.DataFrame)#x1B[90m#x1B[39;49;00m
    #x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92m_gen_dataframe_df#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
        anno: pd.DataFrame,#x1B[90m#x1B[39;49;00m
        index_names: Iterable[#x1B[96mstr#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
        *,#x1B[90m#x1B[39;49;00m
        source: Literal[#x1B[33m"#x1B[39;49;00m#x1B[33mX#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mshape#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
        attr: Literal[#x1B[33m"#x1B[39;49;00m#x1B[33mobs#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mvar#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
        length: #x1B[96mint#x1B[39;49;00m | #x1B[94mNone#x1B[39;49;00m = #x1B[94mNone#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
    ):#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m #x1B[96misinstance#x1B[39;49;00m(anno.index, pd.MultiIndex):#x1B[90m#x1B[39;49;00m
            msg = (#x1B[90m#x1B[39;49;00m
                #x1B[33m"#x1B[39;49;00m#x1B[33mpandas.MultiIndex not supported as index for obs or var on declaration.#x1B[39;49;00m#x1B[33m\n#x1B[39;49;00m#x1B[33m\#x1B[39;49;00m
    #x1B[33m            You can set `obs_names` manually although most operations after will error or convert to str.#x1B[39;49;00m#x1B[33m\n#x1B[39;49;00m#x1B[33m\#x1B[39;49;00m
    #x1B[33m            This behavior will likely be clarified in a future breaking release.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            )#x1B[90m#x1B[39;49;00m
            #x1B[94mraise#x1B[39;49;00m #x1B[96mValueError#x1B[39;49;00m(msg)#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m length #x1B[95mis#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[94mNone#x1B[39;49;00m #x1B[95mand#x1B[39;49;00m length != #x1B[96mlen#x1B[39;49;00m(anno):#x1B[90m#x1B[39;49;00m
            #x1B[94mraise#x1B[39;49;00m _mk_df_error(source, attr, length, #x1B[96mlen#x1B[39;49;00m(anno))#x1B[90m#x1B[39;49;00m
        anno = anno.copy(deep=#x1B[94mFalse#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m is_string_dtype(anno.index[~anno.index.isna()]):#x1B[90m#x1B[39;49;00m
            msg = #x1B[33m"#x1B[39;49;00m#x1B[33mTransforming to str index.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
>           warnings.warn(msg, ImplicitModificationWarning, stacklevel=#x1B[94m2#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31mE           anndata._warnings.ImplicitModificationWarning: Transforming to str index.#x1B[0m

#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/aligned_df.py#x1B[0m:93: ImplicitModificationWarning
tests/test_highly_variable_genes.py::test_seurat_v3_warning
Stack Traces | 0.06s run time
#x1B[0m#x1B[37m@needs#x1B[39;49;00m.skmisc#x1B[90m#x1B[39;49;00m
    #x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92mtest_seurat_v3_warning#x1B[39;49;00m():#x1B[90m#x1B[39;49;00m
        pbmc = pbmc3k()[:#x1B[94m200#x1B[39;49;00m].copy()#x1B[90m#x1B[39;49;00m
        sc.pp.log1p(pbmc)#x1B[90m#x1B[39;49;00m
>       #x1B[94mwith#x1B[39;49;00m pytest.warns(#x1B[90m#x1B[39;49;00m
            #x1B[96mUserWarning#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            match=#x1B[33m"#x1B[39;49;00m#x1B[33m`flavor=#x1B[39;49;00m#x1B[33m'#x1B[39;49;00m#x1B[33mseurat_v3#x1B[39;49;00m#x1B[33m'#x1B[39;49;00m#x1B[33m` expects raw count data, but non-integers were found.#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       anndata._warnings.ImplicitModificationWarning: Transforming to str index.#x1B[0m

#x1B[1m#x1B[31mtests/test_highly_variable_genes.py#x1B[0m:497: ImplicitModificationWarning
tests/test_highly_variable_genes.py::test_compare_to_seurat_v3
Stack Traces | 0.119s run time
#x1B[0m#x1B[37m@needs#x1B[39;49;00m.skmisc#x1B[90m#x1B[39;49;00m
    #x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92mtest_compare_to_seurat_v3#x1B[39;49;00m():#x1B[90m#x1B[39;49;00m
        #x1B[90m### test without batch#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        seurat_hvg_info = pd.read_csv(FILE_V3)#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        pbmc = pbmc3k()#x1B[90m#x1B[39;49;00m
        sc.pp.filter_cells(pbmc, min_genes=#x1B[94m200#x1B[39;49;00m)  #x1B[90m# this doesnt do anything btw#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        sc.pp.filter_genes(pbmc, min_cells=#x1B[94m3#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        pbmc_dense = pbmc.copy()#x1B[90m#x1B[39;49;00m
        pbmc_dense.X = pbmc_dense.X.toarray()#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
>       sc.pp.highly_variable_genes(pbmc, n_top_genes=#x1B[94m1000#x1B[39;49;00m, flavor=#x1B[33m"#x1B[39;49;00m#x1B[33mseurat_v3#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m

#x1B[1m#x1B[31mtests/test_highly_variable_genes.py#x1B[0m:436: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
#x1B[1m#x1B[.../scanpy/preprocessing/_highly_variable_genes.py#x1B[0m:780: in highly_variable_genes
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m _highly_variable_genes_seurat_v3(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[.../scanpy/preprocessing/_highly_variable_genes.py#x1B[0m:196: in _highly_variable_genes_seurat_v3
    #x1B[0maggregated_mean_var = ad.AnnData(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:254: in __init__
    #x1B[0m#x1B[96mself#x1B[39;49;00m._init_as_actual(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/anndata.py#x1B[0m:448: in _init_as_actual
    #x1B[0m#x1B[96mself#x1B[39;49;00m._obs = _gen_dataframe(#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31m../...../_temp/uv-python-dir/cpython-3.14.5-linux-x86_64-gnu/lib/python3.14/functools.py#x1B[0m:982: in wrapper
    #x1B[0m#x1B[94mreturn#x1B[39;49;00m dispatch(args[#x1B[94m0#x1B[39;49;00m].#x1B[91m__class__#x1B[39;49;00m)(*args, **kw)#x1B[90m#x1B[39;49;00m
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^#x1B[90m#x1B[39;49;00m
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

anno =    __hvg_v3_batch_info__
0                      0
index_names = ['obs_names', 'row_names']

    #x1B[0m#x1B[37m@_gen_dataframe#x1B[39;49;00m.register(pd.DataFrame)#x1B[90m#x1B[39;49;00m
    #x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92m_gen_dataframe_df#x1B[39;49;00m(#x1B[90m#x1B[39;49;00m
        anno: pd.DataFrame,#x1B[90m#x1B[39;49;00m
        index_names: Iterable[#x1B[96mstr#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
        *,#x1B[90m#x1B[39;49;00m
        source: Literal[#x1B[33m"#x1B[39;49;00m#x1B[33mX#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mshape#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
        attr: Literal[#x1B[33m"#x1B[39;49;00m#x1B[33mobs#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mvar#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m],#x1B[90m#x1B[39;49;00m
        length: #x1B[96mint#x1B[39;49;00m | #x1B[94mNone#x1B[39;49;00m = #x1B[94mNone#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
    ):#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m #x1B[96misinstance#x1B[39;49;00m(anno.index, pd.MultiIndex):#x1B[90m#x1B[39;49;00m
            msg = (#x1B[90m#x1B[39;49;00m
                #x1B[33m"#x1B[39;49;00m#x1B[33mpandas.MultiIndex not supported as index for obs or var on declaration.#x1B[39;49;00m#x1B[33m\n#x1B[39;49;00m#x1B[33m\#x1B[39;49;00m
    #x1B[33m            You can set `obs_names` manually although most operations after will error or convert to str.#x1B[39;49;00m#x1B[33m\n#x1B[39;49;00m#x1B[33m\#x1B[39;49;00m
    #x1B[33m            This behavior will likely be clarified in a future breaking release.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            )#x1B[90m#x1B[39;49;00m
            #x1B[94mraise#x1B[39;49;00m #x1B[96mValueError#x1B[39;49;00m(msg)#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m length #x1B[95mis#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m #x1B[94mNone#x1B[39;49;00m #x1B[95mand#x1B[39;49;00m length != #x1B[96mlen#x1B[39;49;00m(anno):#x1B[90m#x1B[39;49;00m
            #x1B[94mraise#x1B[39;49;00m _mk_df_error(source, attr, length, #x1B[96mlen#x1B[39;49;00m(anno))#x1B[90m#x1B[39;49;00m
        anno = anno.copy(deep=#x1B[94mFalse#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
        #x1B[94mif#x1B[39;49;00m #x1B[95mnot#x1B[39;49;00m is_string_dtype(anno.index[~anno.index.isna()]):#x1B[90m#x1B[39;49;00m
            msg = #x1B[33m"#x1B[39;49;00m#x1B[33mTransforming to str index.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
>           warnings.warn(msg, ImplicitModificationWarning, stacklevel=#x1B[94m2#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
#x1B[1m#x1B[31mE           anndata._warnings.ImplicitModificationWarning: Transforming to str index.#x1B[0m

#x1B[1m#x1B[31m../../../..../scanpy/B9PcT7QG/hatch-test.stable/lib/python3.14.../anndata/_core/aligned_df.py#x1B[0m:93: ImplicitModificationWarning

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

@ilan-gold ilan-gold changed the title perf: chan's parallel mean-var algorithm perf: chan's parallel mean-var algorithm for dask May 15, 2026
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.

1 participant