Skip to content

feat: add illicofor rank_genes_groups#4038

Draft
ilan-gold wants to merge 8 commits intoig/exp_post_aggfrom
ig/illico
Draft

feat: add illicofor rank_genes_groups#4038
ilan-gold wants to merge 8 commits intoig/exp_post_aggfrom
ig/illico

Conversation

@ilan-gold
Copy link
Copy Markdown
Contributor

@ilan-gold ilan-gold commented Apr 7, 2026

TODOs:

See: https://github.com/scverse/scanpy/actions/runs/24088645078/job/70268566419?pr=4038


@ilan-gold ilan-gold changed the title feat: add illico feat: add illicofor rank_genes_groups Apr 7, 2026
@codecov
Copy link
Copy Markdown

codecov bot commented Apr 7, 2026

❌ 8 Tests Failed:

Tests completed Failed Passed Skipped
2410 8 2402 339
View the top 3 failed test(s) by shortest run time
tests/test_rank_genes_groups.py::test_illico[True-ovr-benjamini-hochberg]
Stack Traces | 0.094s run time
test = 'ovr', corr_method = 'benjamini-hochberg', exp_post_agg = True

    #x1B[0m#x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[33m"#x1B[39;49;00m#x1B[33mcorr_method#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, [#x1B[33m"#x1B[39;49;00m#x1B[33mbenjamini-hochberg#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mbonferroni#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[33m"#x1B[39;49;00m#x1B[33mtest#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, [#x1B[33m"#x1B[39;49;00m#x1B[33movo#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33movr#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[33m"#x1B[39;49;00m#x1B[33mexp_post_agg#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, [#x1B[94mTrue#x1B[39;49;00m, #x1B[94mFalse#x1B[39;49;00m])#x1B[90m#x1B[39;49;00m
    #x1B[90m# Beause illico does not add 1e-9 to its values before log?#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
    #x1B[37m@pytest#x1B[39;49;00m.mark.filterwarnings(#x1B[33m"#x1B[39;49;00m#x1B[33mignore:invalid value encountered:RuntimeWarning#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
    #x1B[37m@needs#x1B[39;49;00m.illico#x1B[90m#x1B[39;49;00m
    #x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92mtest_illico#x1B[39;49;00m(test, corr_method, exp_post_agg):#x1B[90m#x1B[39;49;00m
        #x1B[94mfrom#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[04m#x1B[96millico#x1B[39;49;00m#x1B[04m#x1B[96m.#x1B[39;49;00m#x1B[04m#x1B[96masymptotic_wilcoxon#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[94mimport#x1B[39;49;00m asymptotic_wilcoxon#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        pbmc = pbmc68k_reduced()#x1B[90m#x1B[39;49;00m
        reference = pbmc.obs[#x1B[33m"#x1B[39;49;00m#x1B[33mbulk_labels#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m].iloc[#x1B[94m0#x1B[39;49;00m] #x1B[94mif#x1B[39;49;00m test == #x1B[33m"#x1B[39;49;00m#x1B[33movo#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[94melse#x1B[39;49;00m #x1B[94mNone#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        asy_results = asymptotic_wilcoxon(#x1B[90m#x1B[39;49;00m
            adata=pbmc.copy(),#x1B[90m#x1B[39;49;00m
            group_keys=#x1B[33m"#x1B[39;49;00m#x1B[33mbulk_labels#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            is_log1p=#x1B[94mTrue#x1B[39;49;00m,  #x1B[90m# Scanpy assumes log1p#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            exp_post_agg=exp_post_agg,  #x1B[90m# Post-aggregation exponentiation is needed to match Scanpy's fold change output#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            reference=reference,#x1B[90m#x1B[39;49;00m
            use_continuity=#x1B[94mFalse#x1B[39;49;00m,  #x1B[90m# False because scanpy does not apply continuity correction#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            tie_correct=#x1B[94mFalse#x1B[39;49;00m,  #x1B[90m# False because scanpy takes a lot of time to adjust#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            n_threads=#x1B[94m1#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            batch_size=#x1B[94m16#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            alternative=#x1B[33m"#x1B[39;49;00m#x1B[33mtwo-sided#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,  #x1B[90m# Scanpy only implments two-sided test#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            use_rust=#x1B[94mFalse#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            return_as_scanpy=#x1B[94mTrue#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            corr_method=corr_method,#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        sc.tl.rank_genes_groups(#x1B[90m#x1B[39;49;00m
            pbmc,#x1B[90m#x1B[39;49;00m
            groupby=#x1B[33m"#x1B[39;49;00m#x1B[33mbulk_labels#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            method=#x1B[33m"#x1B[39;49;00m#x1B[33mwilcoxon#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            reference=reference #x1B[94mif#x1B[39;49;00m test == #x1B[33m"#x1B[39;49;00m#x1B[33movo#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[94melse#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mrest#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            n_genes=pbmc.n_vars,#x1B[90m#x1B[39;49;00m
            tie_correct=#x1B[94mFalse#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            corr_method=corr_method,#x1B[90m#x1B[39;49;00m
            exp_post_agg=exp_post_agg,#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
        scanpy_results = pbmc.uns[#x1B[33m"#x1B[39;49;00m#x1B[33mrank_genes_groups#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m]#x1B[90m#x1B[39;49;00m
        #x1B[94massert#x1B[39;49;00m #x1B[96mset#x1B[39;49;00m(asy_results.keys()) == #x1B[96mset#x1B[39;49;00m(scanpy_results.keys()), (#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mOutput keys do not match Scanpy#x1B[39;49;00m#x1B[33m'#x1B[39;49;00m#x1B[33ms output format.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        #x1B[94mfor#x1B[39;49;00m k, ref #x1B[95min#x1B[39;49;00m scanpy_results.items():#x1B[90m#x1B[39;49;00m
            #x1B[94mif#x1B[39;49;00m k #x1B[95min#x1B[39;49;00m [#x1B[33m"#x1B[39;49;00m#x1B[33mparams#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mnames#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m]:#x1B[90m#x1B[39;49;00m
                #x1B[90m# We can skip names ordering check as if incorrect, other values will mismatch#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
                #x1B[94mcontinue#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            res = np.array(asy_results[k].tolist())#x1B[90m#x1B[39;49;00m
            ref_arr = np.array(ref.tolist())#x1B[90m#x1B[39;49;00m
            mask = np.isfinite(ref_arr) * np.isfinite(#x1B[90m#x1B[39;49;00m
                res#x1B[90m#x1B[39;49;00m
            )  #x1B[90m# Mask to ignore inf values in the comparison#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
>           np.testing.assert_allclose(#x1B[90m#x1B[39;49;00m
                ref_arr[mask],#x1B[90m#x1B[39;49;00m
                res[mask],#x1B[90m#x1B[39;49;00m
                rtol=#x1B[94m0#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
                atol=#x1B[94m1e-2#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
                err_msg=#x1B[33mf#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[33mMismatch in #x1B[39;49;00m#x1B[33m'#x1B[39;49;00m#x1B[33m{#x1B[39;49;00mk#x1B[33m}#x1B[39;49;00m#x1B[33m'#x1B[39;49;00m#x1B[33m values between asymptotic_wilcoxon and Scanpy outputs.#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           AssertionError: #x1B[0m
#x1B[1m#x1B[31mE           Not equal to tolerance rtol=0, atol=0.01#x1B[0m
#x1B[1m#x1B[31mE           Mismatch in 'logfoldchanges' values between asymptotic_wilcoxon and Scanpy outputs.#x1B[0m
#x1B[1m#x1B[31mE           Mismatched elements: 2312 / 2312 (100%)#x1B[0m
#x1B[1m#x1B[31mE           First 5 mismatches are at indices:#x1B[0m
#x1B[1m#x1B[31mE            [0]: 2.1622095108032227 (ACTUAL), 8.325858550559252 (DESIRED)#x1B[0m
#x1B[1m#x1B[31mE            [1]: 2.266411781311035 (ACTUAL), 6.944732752970783 (DESIRED)#x1B[0m
#x1B[1m#x1B[31mE            [2]: 2.150602340698242 (ACTUAL), 6.198874226594939 (DESIRED)#x1B[0m
#x1B[1m#x1B[31mE            [3]: 1.0153250694274902 (ACTUAL), 8.931626867097355 (DESIRED)#x1B[0m
#x1B[1m#x1B[31mE            [4]: 2.227607011795044 (ACTUAL), 7.944156338754546 (DESIRED)#x1B[0m
#x1B[1m#x1B[31mE           Max absolute difference among violations: 40.99379987#x1B[0m
#x1B[1m#x1B[31mE           Max relative difference among violations: 243.68797012#x1B[0m
#x1B[1m#x1B[31mE            ACTUAL: array([  2.16221 ,   2.266412,   2.150602, ..., -32.089317,  -2.914431,#x1B[0m
#x1B[1m#x1B[31mE                   -4.218185], shape=(2312,))#x1B[0m
#x1B[1m#x1B[31mE            DESIRED: array([8.325859, 6.944733, 6.198874, ..., 5.312698, 4.749682, 4.925329],#x1B[0m
#x1B[1m#x1B[31mE                 shape=(2312,))#x1B[0m

#x1B[1m#x1B[31mtests/test_rank_genes_groups.py#x1B[0m:369: AssertionError
tests/test_rank_genes_groups.py::test_illico[True-ovo-bonferroni]
Stack Traces | 0.106s run time
test = 'ovo', corr_method = 'bonferroni', exp_post_agg = True

    #x1B[0m#x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[33m"#x1B[39;49;00m#x1B[33mcorr_method#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, [#x1B[33m"#x1B[39;49;00m#x1B[33mbenjamini-hochberg#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mbonferroni#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[33m"#x1B[39;49;00m#x1B[33mtest#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, [#x1B[33m"#x1B[39;49;00m#x1B[33movo#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33movr#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[33m"#x1B[39;49;00m#x1B[33mexp_post_agg#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, [#x1B[94mTrue#x1B[39;49;00m, #x1B[94mFalse#x1B[39;49;00m])#x1B[90m#x1B[39;49;00m
    #x1B[90m# Beause illico does not add 1e-9 to its values before log?#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
    #x1B[37m@pytest#x1B[39;49;00m.mark.filterwarnings(#x1B[33m"#x1B[39;49;00m#x1B[33mignore:invalid value encountered:RuntimeWarning#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
    #x1B[37m@needs#x1B[39;49;00m.illico#x1B[90m#x1B[39;49;00m
    #x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92mtest_illico#x1B[39;49;00m(test, corr_method, exp_post_agg):#x1B[90m#x1B[39;49;00m
        #x1B[94mfrom#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[04m#x1B[96millico#x1B[39;49;00m#x1B[04m#x1B[96m.#x1B[39;49;00m#x1B[04m#x1B[96masymptotic_wilcoxon#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[94mimport#x1B[39;49;00m asymptotic_wilcoxon#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        pbmc = pbmc68k_reduced()#x1B[90m#x1B[39;49;00m
        reference = pbmc.obs[#x1B[33m"#x1B[39;49;00m#x1B[33mbulk_labels#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m].iloc[#x1B[94m0#x1B[39;49;00m] #x1B[94mif#x1B[39;49;00m test == #x1B[33m"#x1B[39;49;00m#x1B[33movo#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[94melse#x1B[39;49;00m #x1B[94mNone#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        asy_results = asymptotic_wilcoxon(#x1B[90m#x1B[39;49;00m
            adata=pbmc.copy(),#x1B[90m#x1B[39;49;00m
            group_keys=#x1B[33m"#x1B[39;49;00m#x1B[33mbulk_labels#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            is_log1p=#x1B[94mTrue#x1B[39;49;00m,  #x1B[90m# Scanpy assumes log1p#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            exp_post_agg=exp_post_agg,  #x1B[90m# Post-aggregation exponentiation is needed to match Scanpy's fold change output#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            reference=reference,#x1B[90m#x1B[39;49;00m
            use_continuity=#x1B[94mFalse#x1B[39;49;00m,  #x1B[90m# False because scanpy does not apply continuity correction#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            tie_correct=#x1B[94mFalse#x1B[39;49;00m,  #x1B[90m# False because scanpy takes a lot of time to adjust#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            n_threads=#x1B[94m1#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            batch_size=#x1B[94m16#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            alternative=#x1B[33m"#x1B[39;49;00m#x1B[33mtwo-sided#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,  #x1B[90m# Scanpy only implments two-sided test#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            use_rust=#x1B[94mFalse#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            return_as_scanpy=#x1B[94mTrue#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            corr_method=corr_method,#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        sc.tl.rank_genes_groups(#x1B[90m#x1B[39;49;00m
            pbmc,#x1B[90m#x1B[39;49;00m
            groupby=#x1B[33m"#x1B[39;49;00m#x1B[33mbulk_labels#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            method=#x1B[33m"#x1B[39;49;00m#x1B[33mwilcoxon#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            reference=reference #x1B[94mif#x1B[39;49;00m test == #x1B[33m"#x1B[39;49;00m#x1B[33movo#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[94melse#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mrest#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            n_genes=pbmc.n_vars,#x1B[90m#x1B[39;49;00m
            tie_correct=#x1B[94mFalse#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            corr_method=corr_method,#x1B[90m#x1B[39;49;00m
            exp_post_agg=exp_post_agg,#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
        scanpy_results = pbmc.uns[#x1B[33m"#x1B[39;49;00m#x1B[33mrank_genes_groups#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m]#x1B[90m#x1B[39;49;00m
        #x1B[94massert#x1B[39;49;00m #x1B[96mset#x1B[39;49;00m(asy_results.keys()) == #x1B[96mset#x1B[39;49;00m(scanpy_results.keys()), (#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mOutput keys do not match Scanpy#x1B[39;49;00m#x1B[33m'#x1B[39;49;00m#x1B[33ms output format.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        #x1B[94mfor#x1B[39;49;00m k, ref #x1B[95min#x1B[39;49;00m scanpy_results.items():#x1B[90m#x1B[39;49;00m
            #x1B[94mif#x1B[39;49;00m k #x1B[95min#x1B[39;49;00m [#x1B[33m"#x1B[39;49;00m#x1B[33mparams#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mnames#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m]:#x1B[90m#x1B[39;49;00m
                #x1B[90m# We can skip names ordering check as if incorrect, other values will mismatch#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
                #x1B[94mcontinue#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            res = np.array(asy_results[k].tolist())#x1B[90m#x1B[39;49;00m
            ref_arr = np.array(ref.tolist())#x1B[90m#x1B[39;49;00m
            mask = np.isfinite(ref_arr) * np.isfinite(#x1B[90m#x1B[39;49;00m
                res#x1B[90m#x1B[39;49;00m
            )  #x1B[90m# Mask to ignore inf values in the comparison#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
>           np.testing.assert_allclose(#x1B[90m#x1B[39;49;00m
                ref_arr[mask],#x1B[90m#x1B[39;49;00m
                res[mask],#x1B[90m#x1B[39;49;00m
                rtol=#x1B[94m0#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
                atol=#x1B[94m1e-2#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
                err_msg=#x1B[33mf#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[33mMismatch in #x1B[39;49;00m#x1B[33m'#x1B[39;49;00m#x1B[33m{#x1B[39;49;00mk#x1B[33m}#x1B[39;49;00m#x1B[33m'#x1B[39;49;00m#x1B[33m values between asymptotic_wilcoxon and Scanpy outputs.#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           AssertionError: #x1B[0m
#x1B[1m#x1B[31mE           Not equal to tolerance rtol=0, atol=0.01#x1B[0m
#x1B[1m#x1B[31mE           Mismatch in 'scores' values between asymptotic_wilcoxon and Scanpy outputs.#x1B[0m
#x1B[1m#x1B[31mE           Mismatched elements: 3663 / 6885 (53.2%)#x1B[0m
#x1B[1m#x1B[31mE           First 5 mismatches are at indices:#x1B[0m
#x1B[1m#x1B[31mE            [0]: 11.072574615478516 (ACTUAL), 4.644743632414249 (DESIRED)#x1B[0m
#x1B[1m#x1B[31mE            [1]: 4.6447434425354 (ACTUAL), 6.721074116167737 (DESIRED)#x1B[0m
#x1B[1m#x1B[31mE            [2]: 6.718207836151123 (ACTUAL), 10.398656939894483 (DESIRED)#x1B[0m
#x1B[1m#x1B[31mE            [3]: 10.398656845092773 (ACTUAL), 9.144648336760273 (DESIRED)#x1B[0m
#x1B[1m#x1B[31mE            [4]: 9.1428804397583 (ACTUAL), 0.0 (DESIRED)#x1B[0m
#x1B[1m#x1B[31mE           Max absolute difference among violations: 9.80768871#x1B[0m
#x1B[1m#x1B[31mE           Max relative difference among violations: 30.41916947#x1B[0m
#x1B[1m#x1B[31mE            ACTUAL: array([ 11.072575,   4.644743,   6.718208, ...,  -5.931427,  -8.632237,#x1B[0m
#x1B[1m#x1B[31mE                  -12.954482], shape=(6885,))#x1B[0m
#x1B[1m#x1B[31mE            DESIRED: array([  4.644744,   6.721074,  10.398657, ...,  -5.931426,  -8.632238,#x1B[0m
#x1B[1m#x1B[31mE                  -12.954482], shape=(6885,))#x1B[0m

#x1B[1m#x1B[31mtests/test_rank_genes_groups.py#x1B[0m:369: AssertionError
tests/test_rank_genes_groups.py::test_illico[True-ovo-benjamini-hochberg]
Stack Traces | 0.113s run time
test = 'ovo', corr_method = 'benjamini-hochberg', exp_post_agg = True

    #x1B[0m#x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[33m"#x1B[39;49;00m#x1B[33mcorr_method#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, [#x1B[33m"#x1B[39;49;00m#x1B[33mbenjamini-hochberg#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mbonferroni#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[33m"#x1B[39;49;00m#x1B[33mtest#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, [#x1B[33m"#x1B[39;49;00m#x1B[33movo#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33movr#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[33m"#x1B[39;49;00m#x1B[33mexp_post_agg#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, [#x1B[94mTrue#x1B[39;49;00m, #x1B[94mFalse#x1B[39;49;00m])#x1B[90m#x1B[39;49;00m
    #x1B[90m# Beause illico does not add 1e-9 to its values before log?#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
    #x1B[37m@pytest#x1B[39;49;00m.mark.filterwarnings(#x1B[33m"#x1B[39;49;00m#x1B[33mignore:invalid value encountered:RuntimeWarning#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
    #x1B[37m@needs#x1B[39;49;00m.illico#x1B[90m#x1B[39;49;00m
    #x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92mtest_illico#x1B[39;49;00m(test, corr_method, exp_post_agg):#x1B[90m#x1B[39;49;00m
        #x1B[94mfrom#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[04m#x1B[96millico#x1B[39;49;00m#x1B[04m#x1B[96m.#x1B[39;49;00m#x1B[04m#x1B[96masymptotic_wilcoxon#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[94mimport#x1B[39;49;00m asymptotic_wilcoxon#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        pbmc = pbmc68k_reduced()#x1B[90m#x1B[39;49;00m
        reference = pbmc.obs[#x1B[33m"#x1B[39;49;00m#x1B[33mbulk_labels#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m].iloc[#x1B[94m0#x1B[39;49;00m] #x1B[94mif#x1B[39;49;00m test == #x1B[33m"#x1B[39;49;00m#x1B[33movo#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[94melse#x1B[39;49;00m #x1B[94mNone#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        asy_results = asymptotic_wilcoxon(#x1B[90m#x1B[39;49;00m
            adata=pbmc.copy(),#x1B[90m#x1B[39;49;00m
            group_keys=#x1B[33m"#x1B[39;49;00m#x1B[33mbulk_labels#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            is_log1p=#x1B[94mTrue#x1B[39;49;00m,  #x1B[90m# Scanpy assumes log1p#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            exp_post_agg=exp_post_agg,  #x1B[90m# Post-aggregation exponentiation is needed to match Scanpy's fold change output#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            reference=reference,#x1B[90m#x1B[39;49;00m
            use_continuity=#x1B[94mFalse#x1B[39;49;00m,  #x1B[90m# False because scanpy does not apply continuity correction#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            tie_correct=#x1B[94mFalse#x1B[39;49;00m,  #x1B[90m# False because scanpy takes a lot of time to adjust#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            n_threads=#x1B[94m1#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            batch_size=#x1B[94m16#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            alternative=#x1B[33m"#x1B[39;49;00m#x1B[33mtwo-sided#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,  #x1B[90m# Scanpy only implments two-sided test#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            use_rust=#x1B[94mFalse#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            return_as_scanpy=#x1B[94mTrue#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            corr_method=corr_method,#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        sc.tl.rank_genes_groups(#x1B[90m#x1B[39;49;00m
            pbmc,#x1B[90m#x1B[39;49;00m
            groupby=#x1B[33m"#x1B[39;49;00m#x1B[33mbulk_labels#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            method=#x1B[33m"#x1B[39;49;00m#x1B[33mwilcoxon#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            reference=reference #x1B[94mif#x1B[39;49;00m test == #x1B[33m"#x1B[39;49;00m#x1B[33movo#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[94melse#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mrest#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            n_genes=pbmc.n_vars,#x1B[90m#x1B[39;49;00m
            tie_correct=#x1B[94mFalse#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            corr_method=corr_method,#x1B[90m#x1B[39;49;00m
            exp_post_agg=exp_post_agg,#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
        scanpy_results = pbmc.uns[#x1B[33m"#x1B[39;49;00m#x1B[33mrank_genes_groups#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m]#x1B[90m#x1B[39;49;00m
        #x1B[94massert#x1B[39;49;00m #x1B[96mset#x1B[39;49;00m(asy_results.keys()) == #x1B[96mset#x1B[39;49;00m(scanpy_results.keys()), (#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mOutput keys do not match Scanpy#x1B[39;49;00m#x1B[33m'#x1B[39;49;00m#x1B[33ms output format.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        #x1B[94mfor#x1B[39;49;00m k, ref #x1B[95min#x1B[39;49;00m scanpy_results.items():#x1B[90m#x1B[39;49;00m
            #x1B[94mif#x1B[39;49;00m k #x1B[95min#x1B[39;49;00m [#x1B[33m"#x1B[39;49;00m#x1B[33mparams#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mnames#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m]:#x1B[90m#x1B[39;49;00m
                #x1B[90m# We can skip names ordering check as if incorrect, other values will mismatch#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
                #x1B[94mcontinue#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            res = np.array(asy_results[k].tolist())#x1B[90m#x1B[39;49;00m
            ref_arr = np.array(ref.tolist())#x1B[90m#x1B[39;49;00m
            mask = np.isfinite(ref_arr) * np.isfinite(#x1B[90m#x1B[39;49;00m
                res#x1B[90m#x1B[39;49;00m
            )  #x1B[90m# Mask to ignore inf values in the comparison#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
>           np.testing.assert_allclose(#x1B[90m#x1B[39;49;00m
                ref_arr[mask],#x1B[90m#x1B[39;49;00m
                res[mask],#x1B[90m#x1B[39;49;00m
                rtol=#x1B[94m0#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
                atol=#x1B[94m1e-2#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
                err_msg=#x1B[33mf#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[33mMismatch in #x1B[39;49;00m#x1B[33m'#x1B[39;49;00m#x1B[33m{#x1B[39;49;00mk#x1B[33m}#x1B[39;49;00m#x1B[33m'#x1B[39;49;00m#x1B[33m values between asymptotic_wilcoxon and Scanpy outputs.#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           AssertionError: #x1B[0m
#x1B[1m#x1B[31mE           Not equal to tolerance rtol=0, atol=0.01#x1B[0m
#x1B[1m#x1B[31mE           Mismatch in 'scores' values between asymptotic_wilcoxon and Scanpy outputs.#x1B[0m
#x1B[1m#x1B[31mE           Mismatched elements: 3663 / 6885 (53.2%)#x1B[0m
#x1B[1m#x1B[31mE           First 5 mismatches are at indices:#x1B[0m
#x1B[1m#x1B[31mE            [0]: 11.072574615478516 (ACTUAL), 4.644743632414249 (DESIRED)#x1B[0m
#x1B[1m#x1B[31mE            [1]: 4.6447434425354 (ACTUAL), 6.721074116167737 (DESIRED)#x1B[0m
#x1B[1m#x1B[31mE            [2]: 6.718207836151123 (ACTUAL), 10.398656939894483 (DESIRED)#x1B[0m
#x1B[1m#x1B[31mE            [3]: 10.398656845092773 (ACTUAL), 9.144648336760273 (DESIRED)#x1B[0m
#x1B[1m#x1B[31mE            [4]: 9.1428804397583 (ACTUAL), 0.0 (DESIRED)#x1B[0m
#x1B[1m#x1B[31mE           Max absolute difference among violations: 9.80768871#x1B[0m
#x1B[1m#x1B[31mE           Max relative difference among violations: 30.41916947#x1B[0m
#x1B[1m#x1B[31mE            ACTUAL: array([ 11.072575,   4.644743,   6.718208, ...,  -5.931427,  -8.632237,#x1B[0m
#x1B[1m#x1B[31mE                  -12.954482], shape=(6885,))#x1B[0m
#x1B[1m#x1B[31mE            DESIRED: array([  4.644744,   6.721074,  10.398657, ...,  -5.931426,  -8.632238,#x1B[0m
#x1B[1m#x1B[31mE                  -12.954482], shape=(6885,))#x1B[0m

#x1B[1m#x1B[31mtests/test_rank_genes_groups.py#x1B[0m:369: AssertionError
tests/test_rank_genes_groups.py::test_illico[False-ovo-benjamini-hochberg]
Stack Traces | 0.123s run time
test = 'ovo', corr_method = 'benjamini-hochberg', exp_post_agg = False

    #x1B[0m#x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[33m"#x1B[39;49;00m#x1B[33mcorr_method#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, [#x1B[33m"#x1B[39;49;00m#x1B[33mbenjamini-hochberg#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mbonferroni#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[33m"#x1B[39;49;00m#x1B[33mtest#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, [#x1B[33m"#x1B[39;49;00m#x1B[33movo#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33movr#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[33m"#x1B[39;49;00m#x1B[33mexp_post_agg#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, [#x1B[94mTrue#x1B[39;49;00m, #x1B[94mFalse#x1B[39;49;00m])#x1B[90m#x1B[39;49;00m
    #x1B[90m# Beause illico does not add 1e-9 to its values before log?#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
    #x1B[37m@pytest#x1B[39;49;00m.mark.filterwarnings(#x1B[33m"#x1B[39;49;00m#x1B[33mignore:invalid value encountered:RuntimeWarning#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
    #x1B[37m@needs#x1B[39;49;00m.illico#x1B[90m#x1B[39;49;00m
    #x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92mtest_illico#x1B[39;49;00m(test, corr_method, exp_post_agg):#x1B[90m#x1B[39;49;00m
        #x1B[94mfrom#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[04m#x1B[96millico#x1B[39;49;00m#x1B[04m#x1B[96m.#x1B[39;49;00m#x1B[04m#x1B[96masymptotic_wilcoxon#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[94mimport#x1B[39;49;00m asymptotic_wilcoxon#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        pbmc = pbmc68k_reduced()#x1B[90m#x1B[39;49;00m
        reference = pbmc.obs[#x1B[33m"#x1B[39;49;00m#x1B[33mbulk_labels#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m].iloc[#x1B[94m0#x1B[39;49;00m] #x1B[94mif#x1B[39;49;00m test == #x1B[33m"#x1B[39;49;00m#x1B[33movo#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[94melse#x1B[39;49;00m #x1B[94mNone#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        asy_results = asymptotic_wilcoxon(#x1B[90m#x1B[39;49;00m
            adata=pbmc.copy(),#x1B[90m#x1B[39;49;00m
            group_keys=#x1B[33m"#x1B[39;49;00m#x1B[33mbulk_labels#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            is_log1p=#x1B[94mTrue#x1B[39;49;00m,  #x1B[90m# Scanpy assumes log1p#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            exp_post_agg=exp_post_agg,  #x1B[90m# Post-aggregation exponentiation is needed to match Scanpy's fold change output#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            reference=reference,#x1B[90m#x1B[39;49;00m
            use_continuity=#x1B[94mFalse#x1B[39;49;00m,  #x1B[90m# False because scanpy does not apply continuity correction#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            tie_correct=#x1B[94mFalse#x1B[39;49;00m,  #x1B[90m# False because scanpy takes a lot of time to adjust#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            n_threads=#x1B[94m1#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            batch_size=#x1B[94m16#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            alternative=#x1B[33m"#x1B[39;49;00m#x1B[33mtwo-sided#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,  #x1B[90m# Scanpy only implments two-sided test#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            use_rust=#x1B[94mFalse#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            return_as_scanpy=#x1B[94mTrue#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            corr_method=corr_method,#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        sc.tl.rank_genes_groups(#x1B[90m#x1B[39;49;00m
            pbmc,#x1B[90m#x1B[39;49;00m
            groupby=#x1B[33m"#x1B[39;49;00m#x1B[33mbulk_labels#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            method=#x1B[33m"#x1B[39;49;00m#x1B[33mwilcoxon#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            reference=reference #x1B[94mif#x1B[39;49;00m test == #x1B[33m"#x1B[39;49;00m#x1B[33movo#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[94melse#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mrest#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            n_genes=pbmc.n_vars,#x1B[90m#x1B[39;49;00m
            tie_correct=#x1B[94mFalse#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            corr_method=corr_method,#x1B[90m#x1B[39;49;00m
            exp_post_agg=exp_post_agg,#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
        scanpy_results = pbmc.uns[#x1B[33m"#x1B[39;49;00m#x1B[33mrank_genes_groups#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m]#x1B[90m#x1B[39;49;00m
        #x1B[94massert#x1B[39;49;00m #x1B[96mset#x1B[39;49;00m(asy_results.keys()) == #x1B[96mset#x1B[39;49;00m(scanpy_results.keys()), (#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mOutput keys do not match Scanpy#x1B[39;49;00m#x1B[33m'#x1B[39;49;00m#x1B[33ms output format.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        #x1B[94mfor#x1B[39;49;00m k, ref #x1B[95min#x1B[39;49;00m scanpy_results.items():#x1B[90m#x1B[39;49;00m
            #x1B[94mif#x1B[39;49;00m k #x1B[95min#x1B[39;49;00m [#x1B[33m"#x1B[39;49;00m#x1B[33mparams#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mnames#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m]:#x1B[90m#x1B[39;49;00m
                #x1B[90m# We can skip names ordering check as if incorrect, other values will mismatch#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
                #x1B[94mcontinue#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            res = np.array(asy_results[k].tolist())#x1B[90m#x1B[39;49;00m
            ref_arr = np.array(ref.tolist())#x1B[90m#x1B[39;49;00m
            mask = np.isfinite(ref_arr) * np.isfinite(#x1B[90m#x1B[39;49;00m
                res#x1B[90m#x1B[39;49;00m
            )  #x1B[90m# Mask to ignore inf values in the comparison#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
>           np.testing.assert_allclose(#x1B[90m#x1B[39;49;00m
                ref_arr[mask],#x1B[90m#x1B[39;49;00m
                res[mask],#x1B[90m#x1B[39;49;00m
                rtol=#x1B[94m0#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
                atol=#x1B[94m1e-2#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
                err_msg=#x1B[33mf#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[33mMismatch in #x1B[39;49;00m#x1B[33m'#x1B[39;49;00m#x1B[33m{#x1B[39;49;00mk#x1B[33m}#x1B[39;49;00m#x1B[33m'#x1B[39;49;00m#x1B[33m values between asymptotic_wilcoxon and Scanpy outputs.#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           AssertionError: #x1B[0m
#x1B[1m#x1B[31mE           Not equal to tolerance rtol=0, atol=0.01#x1B[0m
#x1B[1m#x1B[31mE           Mismatch in 'scores' values between asymptotic_wilcoxon and Scanpy outputs.#x1B[0m
#x1B[1m#x1B[31mE           Mismatched elements: 3663 / 6885 (53.2%)#x1B[0m
#x1B[1m#x1B[31mE           First 5 mismatches are at indices:#x1B[0m
#x1B[1m#x1B[31mE            [0]: 11.072574615478516 (ACTUAL), 4.644743632414249 (DESIRED)#x1B[0m
#x1B[1m#x1B[31mE            [1]: 4.6447434425354 (ACTUAL), 6.721074116167737 (DESIRED)#x1B[0m
#x1B[1m#x1B[31mE            [2]: 6.718207836151123 (ACTUAL), 10.398656939894483 (DESIRED)#x1B[0m
#x1B[1m#x1B[31mE            [3]: 10.398656845092773 (ACTUAL), 9.144648336760273 (DESIRED)#x1B[0m
#x1B[1m#x1B[31mE            [4]: 9.1428804397583 (ACTUAL), 0.0 (DESIRED)#x1B[0m
#x1B[1m#x1B[31mE           Max absolute difference among violations: 9.80768871#x1B[0m
#x1B[1m#x1B[31mE           Max relative difference among violations: 30.41916947#x1B[0m
#x1B[1m#x1B[31mE            ACTUAL: array([ 11.072575,   4.644743,   6.718208, ...,  -5.931427,  -8.632237,#x1B[0m
#x1B[1m#x1B[31mE                  -12.954482], shape=(6885,))#x1B[0m
#x1B[1m#x1B[31mE            DESIRED: array([  4.644744,   6.721074,  10.398657, ...,  -5.931426,  -8.632238,#x1B[0m
#x1B[1m#x1B[31mE                  -12.954482], shape=(6885,))#x1B[0m

#x1B[1m#x1B[31mtests/test_rank_genes_groups.py#x1B[0m:369: AssertionError
tests/test_rank_genes_groups.py::test_illico[False-ovr-benjamini-hochberg]
Stack Traces | 0.153s run time
test = 'ovr', corr_method = 'benjamini-hochberg', exp_post_agg = False

    #x1B[0m#x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[33m"#x1B[39;49;00m#x1B[33mcorr_method#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, [#x1B[33m"#x1B[39;49;00m#x1B[33mbenjamini-hochberg#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mbonferroni#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[33m"#x1B[39;49;00m#x1B[33mtest#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, [#x1B[33m"#x1B[39;49;00m#x1B[33movo#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33movr#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[33m"#x1B[39;49;00m#x1B[33mexp_post_agg#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, [#x1B[94mTrue#x1B[39;49;00m, #x1B[94mFalse#x1B[39;49;00m])#x1B[90m#x1B[39;49;00m
    #x1B[90m# Beause illico does not add 1e-9 to its values before log?#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
    #x1B[37m@pytest#x1B[39;49;00m.mark.filterwarnings(#x1B[33m"#x1B[39;49;00m#x1B[33mignore:invalid value encountered:RuntimeWarning#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
    #x1B[37m@needs#x1B[39;49;00m.illico#x1B[90m#x1B[39;49;00m
    #x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92mtest_illico#x1B[39;49;00m(test, corr_method, exp_post_agg):#x1B[90m#x1B[39;49;00m
        #x1B[94mfrom#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[04m#x1B[96millico#x1B[39;49;00m#x1B[04m#x1B[96m.#x1B[39;49;00m#x1B[04m#x1B[96masymptotic_wilcoxon#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[94mimport#x1B[39;49;00m asymptotic_wilcoxon#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        pbmc = pbmc68k_reduced()#x1B[90m#x1B[39;49;00m
        reference = pbmc.obs[#x1B[33m"#x1B[39;49;00m#x1B[33mbulk_labels#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m].iloc[#x1B[94m0#x1B[39;49;00m] #x1B[94mif#x1B[39;49;00m test == #x1B[33m"#x1B[39;49;00m#x1B[33movo#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[94melse#x1B[39;49;00m #x1B[94mNone#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        asy_results = asymptotic_wilcoxon(#x1B[90m#x1B[39;49;00m
            adata=pbmc.copy(),#x1B[90m#x1B[39;49;00m
            group_keys=#x1B[33m"#x1B[39;49;00m#x1B[33mbulk_labels#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            is_log1p=#x1B[94mTrue#x1B[39;49;00m,  #x1B[90m# Scanpy assumes log1p#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            exp_post_agg=exp_post_agg,  #x1B[90m# Post-aggregation exponentiation is needed to match Scanpy's fold change output#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            reference=reference,#x1B[90m#x1B[39;49;00m
            use_continuity=#x1B[94mFalse#x1B[39;49;00m,  #x1B[90m# False because scanpy does not apply continuity correction#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            tie_correct=#x1B[94mFalse#x1B[39;49;00m,  #x1B[90m# False because scanpy takes a lot of time to adjust#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            n_threads=#x1B[94m1#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            batch_size=#x1B[94m16#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            alternative=#x1B[33m"#x1B[39;49;00m#x1B[33mtwo-sided#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,  #x1B[90m# Scanpy only implments two-sided test#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            use_rust=#x1B[94mFalse#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            return_as_scanpy=#x1B[94mTrue#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            corr_method=corr_method,#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        sc.tl.rank_genes_groups(#x1B[90m#x1B[39;49;00m
            pbmc,#x1B[90m#x1B[39;49;00m
            groupby=#x1B[33m"#x1B[39;49;00m#x1B[33mbulk_labels#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            method=#x1B[33m"#x1B[39;49;00m#x1B[33mwilcoxon#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            reference=reference #x1B[94mif#x1B[39;49;00m test == #x1B[33m"#x1B[39;49;00m#x1B[33movo#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[94melse#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mrest#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            n_genes=pbmc.n_vars,#x1B[90m#x1B[39;49;00m
            tie_correct=#x1B[94mFalse#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            corr_method=corr_method,#x1B[90m#x1B[39;49;00m
            exp_post_agg=exp_post_agg,#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
        scanpy_results = pbmc.uns[#x1B[33m"#x1B[39;49;00m#x1B[33mrank_genes_groups#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m]#x1B[90m#x1B[39;49;00m
        #x1B[94massert#x1B[39;49;00m #x1B[96mset#x1B[39;49;00m(asy_results.keys()) == #x1B[96mset#x1B[39;49;00m(scanpy_results.keys()), (#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mOutput keys do not match Scanpy#x1B[39;49;00m#x1B[33m'#x1B[39;49;00m#x1B[33ms output format.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        #x1B[94mfor#x1B[39;49;00m k, ref #x1B[95min#x1B[39;49;00m scanpy_results.items():#x1B[90m#x1B[39;49;00m
            #x1B[94mif#x1B[39;49;00m k #x1B[95min#x1B[39;49;00m [#x1B[33m"#x1B[39;49;00m#x1B[33mparams#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mnames#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m]:#x1B[90m#x1B[39;49;00m
                #x1B[90m# We can skip names ordering check as if incorrect, other values will mismatch#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
                #x1B[94mcontinue#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            res = np.array(asy_results[k].tolist())#x1B[90m#x1B[39;49;00m
            ref_arr = np.array(ref.tolist())#x1B[90m#x1B[39;49;00m
            mask = np.isfinite(ref_arr) * np.isfinite(#x1B[90m#x1B[39;49;00m
                res#x1B[90m#x1B[39;49;00m
            )  #x1B[90m# Mask to ignore inf values in the comparison#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
>           np.testing.assert_allclose(#x1B[90m#x1B[39;49;00m
                ref_arr[mask],#x1B[90m#x1B[39;49;00m
                res[mask],#x1B[90m#x1B[39;49;00m
                rtol=#x1B[94m0#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
                atol=#x1B[94m1e-2#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
                err_msg=#x1B[33mf#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[33mMismatch in #x1B[39;49;00m#x1B[33m'#x1B[39;49;00m#x1B[33m{#x1B[39;49;00mk#x1B[33m}#x1B[39;49;00m#x1B[33m'#x1B[39;49;00m#x1B[33m values between asymptotic_wilcoxon and Scanpy outputs.#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           AssertionError: #x1B[0m
#x1B[1m#x1B[31mE           Not equal to tolerance rtol=0, atol=0.01#x1B[0m
#x1B[1m#x1B[31mE           Mismatch in 'logfoldchanges' values between asymptotic_wilcoxon and Scanpy outputs.#x1B[0m
#x1B[1m#x1B[31mE           Mismatched elements: 5541 / 5557 (99.7%)#x1B[0m
#x1B[1m#x1B[31mE           First 5 mismatches are at indices:#x1B[0m
#x1B[1m#x1B[31mE            [0]: 2.2793736457824707 (ACTUAL), 3.2955667155262343 (DESIRED)#x1B[0m
#x1B[1m#x1B[31mE            [1]: 2.5374081134796143 (ACTUAL), -2.136890187851761 (DESIRED)#x1B[0m
#x1B[1m#x1B[31mE            [2]: 1.7644909620285034 (ACTUAL), 3.3424527163983333 (DESIRED)#x1B[0m
#x1B[1m#x1B[31mE            [3]: 3.211545467376709 (ACTUAL), 3.397135551262183 (DESIRED)#x1B[0m
#x1B[1m#x1B[31mE            [4]: 1.7379240989685059 (ACTUAL), -1.045845431282527 (DESIRED)#x1B[0m
#x1B[1m#x1B[31mE           Max absolute difference among violations: 31.65372012#x1B[0m
#x1B[1m#x1B[31mE           Max relative difference among violations: 462.6924988#x1B[0m
#x1B[1m#x1B[31mE            ACTUAL: array([ 2.279374,  2.537408,  1.764491, ..., -1.005601, -0.9857  ,#x1B[0m
#x1B[1m#x1B[31mE                  -0.697857], shape=(5557,))#x1B[0m
#x1B[1m#x1B[31mE            DESIRED: array([ 3.295567, -2.13689 ,  3.342453, ..., -6.307728, -6.367315,#x1B[0m
#x1B[1m#x1B[31mE                  -0.450996], shape=(5557,))#x1B[0m

#x1B[1m#x1B[31mtests/test_rank_genes_groups.py#x1B[0m:369: AssertionError
tests/test_rank_genes_groups.py::test_illico[False-ovr-bonferroni]
Stack Traces | 0.154s run time
test = 'ovr', corr_method = 'bonferroni', exp_post_agg = False

    #x1B[0m#x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[33m"#x1B[39;49;00m#x1B[33mcorr_method#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, [#x1B[33m"#x1B[39;49;00m#x1B[33mbenjamini-hochberg#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mbonferroni#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[33m"#x1B[39;49;00m#x1B[33mtest#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, [#x1B[33m"#x1B[39;49;00m#x1B[33movo#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33movr#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[33m"#x1B[39;49;00m#x1B[33mexp_post_agg#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, [#x1B[94mTrue#x1B[39;49;00m, #x1B[94mFalse#x1B[39;49;00m])#x1B[90m#x1B[39;49;00m
    #x1B[90m# Beause illico does not add 1e-9 to its values before log?#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
    #x1B[37m@pytest#x1B[39;49;00m.mark.filterwarnings(#x1B[33m"#x1B[39;49;00m#x1B[33mignore:invalid value encountered:RuntimeWarning#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
    #x1B[37m@needs#x1B[39;49;00m.illico#x1B[90m#x1B[39;49;00m
    #x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92mtest_illico#x1B[39;49;00m(test, corr_method, exp_post_agg):#x1B[90m#x1B[39;49;00m
        #x1B[94mfrom#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[04m#x1B[96millico#x1B[39;49;00m#x1B[04m#x1B[96m.#x1B[39;49;00m#x1B[04m#x1B[96masymptotic_wilcoxon#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[94mimport#x1B[39;49;00m asymptotic_wilcoxon#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        pbmc = pbmc68k_reduced()#x1B[90m#x1B[39;49;00m
        reference = pbmc.obs[#x1B[33m"#x1B[39;49;00m#x1B[33mbulk_labels#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m].iloc[#x1B[94m0#x1B[39;49;00m] #x1B[94mif#x1B[39;49;00m test == #x1B[33m"#x1B[39;49;00m#x1B[33movo#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[94melse#x1B[39;49;00m #x1B[94mNone#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        asy_results = asymptotic_wilcoxon(#x1B[90m#x1B[39;49;00m
            adata=pbmc.copy(),#x1B[90m#x1B[39;49;00m
            group_keys=#x1B[33m"#x1B[39;49;00m#x1B[33mbulk_labels#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            is_log1p=#x1B[94mTrue#x1B[39;49;00m,  #x1B[90m# Scanpy assumes log1p#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            exp_post_agg=exp_post_agg,  #x1B[90m# Post-aggregation exponentiation is needed to match Scanpy's fold change output#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            reference=reference,#x1B[90m#x1B[39;49;00m
            use_continuity=#x1B[94mFalse#x1B[39;49;00m,  #x1B[90m# False because scanpy does not apply continuity correction#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            tie_correct=#x1B[94mFalse#x1B[39;49;00m,  #x1B[90m# False because scanpy takes a lot of time to adjust#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            n_threads=#x1B[94m1#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            batch_size=#x1B[94m16#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            alternative=#x1B[33m"#x1B[39;49;00m#x1B[33mtwo-sided#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,  #x1B[90m# Scanpy only implments two-sided test#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            use_rust=#x1B[94mFalse#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            return_as_scanpy=#x1B[94mTrue#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            corr_method=corr_method,#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        sc.tl.rank_genes_groups(#x1B[90m#x1B[39;49;00m
            pbmc,#x1B[90m#x1B[39;49;00m
            groupby=#x1B[33m"#x1B[39;49;00m#x1B[33mbulk_labels#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            method=#x1B[33m"#x1B[39;49;00m#x1B[33mwilcoxon#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            reference=reference #x1B[94mif#x1B[39;49;00m test == #x1B[33m"#x1B[39;49;00m#x1B[33movo#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[94melse#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mrest#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            n_genes=pbmc.n_vars,#x1B[90m#x1B[39;49;00m
            tie_correct=#x1B[94mFalse#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            corr_method=corr_method,#x1B[90m#x1B[39;49;00m
            exp_post_agg=exp_post_agg,#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
        scanpy_results = pbmc.uns[#x1B[33m"#x1B[39;49;00m#x1B[33mrank_genes_groups#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m]#x1B[90m#x1B[39;49;00m
        #x1B[94massert#x1B[39;49;00m #x1B[96mset#x1B[39;49;00m(asy_results.keys()) == #x1B[96mset#x1B[39;49;00m(scanpy_results.keys()), (#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mOutput keys do not match Scanpy#x1B[39;49;00m#x1B[33m'#x1B[39;49;00m#x1B[33ms output format.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        #x1B[94mfor#x1B[39;49;00m k, ref #x1B[95min#x1B[39;49;00m scanpy_results.items():#x1B[90m#x1B[39;49;00m
            #x1B[94mif#x1B[39;49;00m k #x1B[95min#x1B[39;49;00m [#x1B[33m"#x1B[39;49;00m#x1B[33mparams#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mnames#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m]:#x1B[90m#x1B[39;49;00m
                #x1B[90m# We can skip names ordering check as if incorrect, other values will mismatch#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
                #x1B[94mcontinue#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            res = np.array(asy_results[k].tolist())#x1B[90m#x1B[39;49;00m
            ref_arr = np.array(ref.tolist())#x1B[90m#x1B[39;49;00m
            mask = np.isfinite(ref_arr) * np.isfinite(#x1B[90m#x1B[39;49;00m
                res#x1B[90m#x1B[39;49;00m
            )  #x1B[90m# Mask to ignore inf values in the comparison#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
>           np.testing.assert_allclose(#x1B[90m#x1B[39;49;00m
                ref_arr[mask],#x1B[90m#x1B[39;49;00m
                res[mask],#x1B[90m#x1B[39;49;00m
                rtol=#x1B[94m0#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
                atol=#x1B[94m1e-2#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
                err_msg=#x1B[33mf#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[33mMismatch in #x1B[39;49;00m#x1B[33m'#x1B[39;49;00m#x1B[33m{#x1B[39;49;00mk#x1B[33m}#x1B[39;49;00m#x1B[33m'#x1B[39;49;00m#x1B[33m values between asymptotic_wilcoxon and Scanpy outputs.#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           AssertionError: #x1B[0m
#x1B[1m#x1B[31mE           Not equal to tolerance rtol=0, atol=0.01#x1B[0m
#x1B[1m#x1B[31mE           Mismatch in 'logfoldchanges' values between asymptotic_wilcoxon and Scanpy outputs.#x1B[0m
#x1B[1m#x1B[31mE           Mismatched elements: 5541 / 5557 (99.7%)#x1B[0m
#x1B[1m#x1B[31mE           First 5 mismatches are at indices:#x1B[0m
#x1B[1m#x1B[31mE            [0]: 2.2793736457824707 (ACTUAL), 3.2955667155262343 (DESIRED)#x1B[0m
#x1B[1m#x1B[31mE            [1]: 2.5374081134796143 (ACTUAL), -2.136890187851761 (DESIRED)#x1B[0m
#x1B[1m#x1B[31mE            [2]: 1.7644909620285034 (ACTUAL), 3.3424527163983333 (DESIRED)#x1B[0m
#x1B[1m#x1B[31mE            [3]: 3.211545467376709 (ACTUAL), 3.397135551262183 (DESIRED)#x1B[0m
#x1B[1m#x1B[31mE            [4]: 1.7379240989685059 (ACTUAL), -1.045845431282527 (DESIRED)#x1B[0m
#x1B[1m#x1B[31mE           Max absolute difference among violations: 31.65372012#x1B[0m
#x1B[1m#x1B[31mE           Max relative difference among violations: 462.6924988#x1B[0m
#x1B[1m#x1B[31mE            ACTUAL: array([ 2.279374,  2.537408,  1.764491, ..., -1.005601, -0.9857  ,#x1B[0m
#x1B[1m#x1B[31mE                  -0.697857], shape=(5557,))#x1B[0m
#x1B[1m#x1B[31mE            DESIRED: array([ 3.295567, -2.13689 ,  3.342453, ..., -6.307728, -6.367315,#x1B[0m
#x1B[1m#x1B[31mE                  -0.450996], shape=(5557,))#x1B[0m

#x1B[1m#x1B[31mtests/test_rank_genes_groups.py#x1B[0m:369: AssertionError
tests/test_rank_genes_groups.py::test_illico[True-ovr-bonferroni]
Stack Traces | 5.21s run time
test = 'ovr', corr_method = 'bonferroni', exp_post_agg = True

    #x1B[0m#x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[33m"#x1B[39;49;00m#x1B[33mcorr_method#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, [#x1B[33m"#x1B[39;49;00m#x1B[33mbenjamini-hochberg#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mbonferroni#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[33m"#x1B[39;49;00m#x1B[33mtest#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, [#x1B[33m"#x1B[39;49;00m#x1B[33movo#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33movr#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[33m"#x1B[39;49;00m#x1B[33mexp_post_agg#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, [#x1B[94mTrue#x1B[39;49;00m, #x1B[94mFalse#x1B[39;49;00m])#x1B[90m#x1B[39;49;00m
    #x1B[90m# Beause illico does not add 1e-9 to its values before log?#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
    #x1B[37m@pytest#x1B[39;49;00m.mark.filterwarnings(#x1B[33m"#x1B[39;49;00m#x1B[33mignore:invalid value encountered:RuntimeWarning#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
    #x1B[37m@needs#x1B[39;49;00m.illico#x1B[90m#x1B[39;49;00m
    #x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92mtest_illico#x1B[39;49;00m(test, corr_method, exp_post_agg):#x1B[90m#x1B[39;49;00m
        #x1B[94mfrom#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[04m#x1B[96millico#x1B[39;49;00m#x1B[04m#x1B[96m.#x1B[39;49;00m#x1B[04m#x1B[96masymptotic_wilcoxon#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[94mimport#x1B[39;49;00m asymptotic_wilcoxon#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        pbmc = pbmc68k_reduced()#x1B[90m#x1B[39;49;00m
        reference = pbmc.obs[#x1B[33m"#x1B[39;49;00m#x1B[33mbulk_labels#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m].iloc[#x1B[94m0#x1B[39;49;00m] #x1B[94mif#x1B[39;49;00m test == #x1B[33m"#x1B[39;49;00m#x1B[33movo#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[94melse#x1B[39;49;00m #x1B[94mNone#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        asy_results = asymptotic_wilcoxon(#x1B[90m#x1B[39;49;00m
            adata=pbmc.copy(),#x1B[90m#x1B[39;49;00m
            group_keys=#x1B[33m"#x1B[39;49;00m#x1B[33mbulk_labels#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            is_log1p=#x1B[94mTrue#x1B[39;49;00m,  #x1B[90m# Scanpy assumes log1p#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            exp_post_agg=exp_post_agg,  #x1B[90m# Post-aggregation exponentiation is needed to match Scanpy's fold change output#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            reference=reference,#x1B[90m#x1B[39;49;00m
            use_continuity=#x1B[94mFalse#x1B[39;49;00m,  #x1B[90m# False because scanpy does not apply continuity correction#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            tie_correct=#x1B[94mFalse#x1B[39;49;00m,  #x1B[90m# False because scanpy takes a lot of time to adjust#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            n_threads=#x1B[94m1#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            batch_size=#x1B[94m16#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            alternative=#x1B[33m"#x1B[39;49;00m#x1B[33mtwo-sided#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,  #x1B[90m# Scanpy only implments two-sided test#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            use_rust=#x1B[94mFalse#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            return_as_scanpy=#x1B[94mTrue#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            corr_method=corr_method,#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        sc.tl.rank_genes_groups(#x1B[90m#x1B[39;49;00m
            pbmc,#x1B[90m#x1B[39;49;00m
            groupby=#x1B[33m"#x1B[39;49;00m#x1B[33mbulk_labels#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            method=#x1B[33m"#x1B[39;49;00m#x1B[33mwilcoxon#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            reference=reference #x1B[94mif#x1B[39;49;00m test == #x1B[33m"#x1B[39;49;00m#x1B[33movo#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[94melse#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mrest#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            n_genes=pbmc.n_vars,#x1B[90m#x1B[39;49;00m
            tie_correct=#x1B[94mFalse#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            corr_method=corr_method,#x1B[90m#x1B[39;49;00m
            exp_post_agg=exp_post_agg,#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
        scanpy_results = pbmc.uns[#x1B[33m"#x1B[39;49;00m#x1B[33mrank_genes_groups#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m]#x1B[90m#x1B[39;49;00m
        #x1B[94massert#x1B[39;49;00m #x1B[96mset#x1B[39;49;00m(asy_results.keys()) == #x1B[96mset#x1B[39;49;00m(scanpy_results.keys()), (#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mOutput keys do not match Scanpy#x1B[39;49;00m#x1B[33m'#x1B[39;49;00m#x1B[33ms output format.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        #x1B[94mfor#x1B[39;49;00m k, ref #x1B[95min#x1B[39;49;00m scanpy_results.items():#x1B[90m#x1B[39;49;00m
            #x1B[94mif#x1B[39;49;00m k #x1B[95min#x1B[39;49;00m [#x1B[33m"#x1B[39;49;00m#x1B[33mparams#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mnames#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m]:#x1B[90m#x1B[39;49;00m
                #x1B[90m# We can skip names ordering check as if incorrect, other values will mismatch#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
                #x1B[94mcontinue#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            res = np.array(asy_results[k].tolist())#x1B[90m#x1B[39;49;00m
            ref_arr = np.array(ref.tolist())#x1B[90m#x1B[39;49;00m
            mask = np.isfinite(ref_arr) * np.isfinite(#x1B[90m#x1B[39;49;00m
                res#x1B[90m#x1B[39;49;00m
            )  #x1B[90m# Mask to ignore inf values in the comparison#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
>           np.testing.assert_allclose(#x1B[90m#x1B[39;49;00m
                ref_arr[mask],#x1B[90m#x1B[39;49;00m
                res[mask],#x1B[90m#x1B[39;49;00m
                rtol=#x1B[94m0#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
                atol=#x1B[94m1e-2#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
                err_msg=#x1B[33mf#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[33mMismatch in #x1B[39;49;00m#x1B[33m'#x1B[39;49;00m#x1B[33m{#x1B[39;49;00mk#x1B[33m}#x1B[39;49;00m#x1B[33m'#x1B[39;49;00m#x1B[33m values between asymptotic_wilcoxon and Scanpy outputs.#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           AssertionError: #x1B[0m
#x1B[1m#x1B[31mE           Not equal to tolerance rtol=0, atol=0.01#x1B[0m
#x1B[1m#x1B[31mE           Mismatch in 'logfoldchanges' values between asymptotic_wilcoxon and Scanpy outputs.#x1B[0m
#x1B[1m#x1B[31mE           Mismatched elements: 2312 / 2312 (100%)#x1B[0m
#x1B[1m#x1B[31mE           First 5 mismatches are at indices:#x1B[0m
#x1B[1m#x1B[31mE            [0]: 2.1622095108032227 (ACTUAL), 8.325858550559252 (DESIRED)#x1B[0m
#x1B[1m#x1B[31mE            [1]: 2.266411781311035 (ACTUAL), 6.944732752970783 (DESIRED)#x1B[0m
#x1B[1m#x1B[31mE            [2]: 2.150602340698242 (ACTUAL), 6.198874226594939 (DESIRED)#x1B[0m
#x1B[1m#x1B[31mE            [3]: 1.0153250694274902 (ACTUAL), 8.931626867097355 (DESIRED)#x1B[0m
#x1B[1m#x1B[31mE            [4]: 2.227607011795044 (ACTUAL), 7.944156338754546 (DESIRED)#x1B[0m
#x1B[1m#x1B[31mE           Max absolute difference among violations: 40.99379987#x1B[0m
#x1B[1m#x1B[31mE           Max relative difference among violations: 243.68797012#x1B[0m
#x1B[1m#x1B[31mE            ACTUAL: array([  2.16221 ,   2.266412,   2.150602, ..., -32.089317,  -2.914431,#x1B[0m
#x1B[1m#x1B[31mE                   -4.218185], shape=(2312,))#x1B[0m
#x1B[1m#x1B[31mE            DESIRED: array([8.325859, 6.944733, 6.198874, ..., 5.312698, 4.749682, 4.925329],#x1B[0m
#x1B[1m#x1B[31mE                 shape=(2312,))#x1B[0m

#x1B[1m#x1B[31mtests/test_rank_genes_groups.py#x1B[0m:369: AssertionError
tests/test_rank_genes_groups.py::test_illico[False-ovo-bonferroni]
Stack Traces | 16.9s run time
test = 'ovo', corr_method = 'bonferroni', exp_post_agg = False

    #x1B[0m#x1B[37m@pytest#x1B[39;49;00m.mark.parametrize(#x1B[33m"#x1B[39;49;00m#x1B[33mcorr_method#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, [#x1B[33m"#x1B[39;49;00m#x1B[33mbenjamini-hochberg#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mbonferroni#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[33m"#x1B[39;49;00m#x1B[33mtest#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, [#x1B[33m"#x1B[39;49;00m#x1B[33movo#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33movr#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[33m"#x1B[39;49;00m#x1B[33mexp_post_agg#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, [#x1B[94mTrue#x1B[39;49;00m, #x1B[94mFalse#x1B[39;49;00m])#x1B[90m#x1B[39;49;00m
    #x1B[90m# Beause illico does not add 1e-9 to its values before log?#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
    #x1B[37m@pytest#x1B[39;49;00m.mark.filterwarnings(#x1B[33m"#x1B[39;49;00m#x1B[33mignore:invalid value encountered:RuntimeWarning#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m)#x1B[90m#x1B[39;49;00m
    #x1B[37m@needs#x1B[39;49;00m.illico#x1B[90m#x1B[39;49;00m
    #x1B[94mdef#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[92mtest_illico#x1B[39;49;00m(test, corr_method, exp_post_agg):#x1B[90m#x1B[39;49;00m
        #x1B[94mfrom#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[04m#x1B[96millico#x1B[39;49;00m#x1B[04m#x1B[96m.#x1B[39;49;00m#x1B[04m#x1B[96masymptotic_wilcoxon#x1B[39;49;00m#x1B[90m #x1B[39;49;00m#x1B[94mimport#x1B[39;49;00m asymptotic_wilcoxon#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        pbmc = pbmc68k_reduced()#x1B[90m#x1B[39;49;00m
        reference = pbmc.obs[#x1B[33m"#x1B[39;49;00m#x1B[33mbulk_labels#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m].iloc[#x1B[94m0#x1B[39;49;00m] #x1B[94mif#x1B[39;49;00m test == #x1B[33m"#x1B[39;49;00m#x1B[33movo#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[94melse#x1B[39;49;00m #x1B[94mNone#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        asy_results = asymptotic_wilcoxon(#x1B[90m#x1B[39;49;00m
            adata=pbmc.copy(),#x1B[90m#x1B[39;49;00m
            group_keys=#x1B[33m"#x1B[39;49;00m#x1B[33mbulk_labels#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            is_log1p=#x1B[94mTrue#x1B[39;49;00m,  #x1B[90m# Scanpy assumes log1p#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            exp_post_agg=exp_post_agg,  #x1B[90m# Post-aggregation exponentiation is needed to match Scanpy's fold change output#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            reference=reference,#x1B[90m#x1B[39;49;00m
            use_continuity=#x1B[94mFalse#x1B[39;49;00m,  #x1B[90m# False because scanpy does not apply continuity correction#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            tie_correct=#x1B[94mFalse#x1B[39;49;00m,  #x1B[90m# False because scanpy takes a lot of time to adjust#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            n_threads=#x1B[94m1#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            batch_size=#x1B[94m16#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            alternative=#x1B[33m"#x1B[39;49;00m#x1B[33mtwo-sided#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,  #x1B[90m# Scanpy only implments two-sided test#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            use_rust=#x1B[94mFalse#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            return_as_scanpy=#x1B[94mTrue#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            corr_method=corr_method,#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        sc.tl.rank_genes_groups(#x1B[90m#x1B[39;49;00m
            pbmc,#x1B[90m#x1B[39;49;00m
            groupby=#x1B[33m"#x1B[39;49;00m#x1B[33mbulk_labels#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            method=#x1B[33m"#x1B[39;49;00m#x1B[33mwilcoxon#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            reference=reference #x1B[94mif#x1B[39;49;00m test == #x1B[33m"#x1B[39;49;00m#x1B[33movo#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m #x1B[94melse#x1B[39;49;00m #x1B[33m"#x1B[39;49;00m#x1B[33mrest#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            n_genes=pbmc.n_vars,#x1B[90m#x1B[39;49;00m
            tie_correct=#x1B[94mFalse#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
            corr_method=corr_method,#x1B[90m#x1B[39;49;00m
            exp_post_agg=exp_post_agg,#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
        scanpy_results = pbmc.uns[#x1B[33m"#x1B[39;49;00m#x1B[33mrank_genes_groups#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m]#x1B[90m#x1B[39;49;00m
        #x1B[94massert#x1B[39;49;00m #x1B[96mset#x1B[39;49;00m(asy_results.keys()) == #x1B[96mset#x1B[39;49;00m(scanpy_results.keys()), (#x1B[90m#x1B[39;49;00m
            #x1B[33m"#x1B[39;49;00m#x1B[33mOutput keys do not match Scanpy#x1B[39;49;00m#x1B[33m'#x1B[39;49;00m#x1B[33ms output format.#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
        )#x1B[90m#x1B[39;49;00m
    #x1B[90m#x1B[39;49;00m
        #x1B[94mfor#x1B[39;49;00m k, ref #x1B[95min#x1B[39;49;00m scanpy_results.items():#x1B[90m#x1B[39;49;00m
            #x1B[94mif#x1B[39;49;00m k #x1B[95min#x1B[39;49;00m [#x1B[33m"#x1B[39;49;00m#x1B[33mparams#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m, #x1B[33m"#x1B[39;49;00m#x1B[33mnames#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m]:#x1B[90m#x1B[39;49;00m
                #x1B[90m# We can skip names ordering check as if incorrect, other values will mismatch#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
                #x1B[94mcontinue#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
            res = np.array(asy_results[k].tolist())#x1B[90m#x1B[39;49;00m
            ref_arr = np.array(ref.tolist())#x1B[90m#x1B[39;49;00m
            mask = np.isfinite(ref_arr) * np.isfinite(#x1B[90m#x1B[39;49;00m
                res#x1B[90m#x1B[39;49;00m
            )  #x1B[90m# Mask to ignore inf values in the comparison#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
>           np.testing.assert_allclose(#x1B[90m#x1B[39;49;00m
                ref_arr[mask],#x1B[90m#x1B[39;49;00m
                res[mask],#x1B[90m#x1B[39;49;00m
                rtol=#x1B[94m0#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
                atol=#x1B[94m1e-2#x1B[39;49;00m,#x1B[90m#x1B[39;49;00m
                err_msg=#x1B[33mf#x1B[39;49;00m#x1B[33m"#x1B[39;49;00m#x1B[33mMismatch in #x1B[39;49;00m#x1B[33m'#x1B[39;49;00m#x1B[33m{#x1B[39;49;00mk#x1B[33m}#x1B[39;49;00m#x1B[33m'#x1B[39;49;00m#x1B[33m values between asymptotic_wilcoxon and Scanpy outputs.#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           AssertionError: #x1B[0m
#x1B[1m#x1B[31mE           Not equal to tolerance rtol=0, atol=0.01#x1B[0m
#x1B[1m#x1B[31mE           Mismatch in 'scores' values between asymptotic_wilcoxon and Scanpy outputs.#x1B[0m
#x1B[1m#x1B[31mE           Mismatched elements: 3663 / 6885 (53.2%)#x1B[0m
#x1B[1m#x1B[31mE           First 5 mismatches are at indices:#x1B[0m
#x1B[1m#x1B[31mE            [0]: 11.072574615478516 (ACTUAL), 4.644743632414249 (DESIRED)#x1B[0m
#x1B[1m#x1B[31mE            [1]: 4.6447434425354 (ACTUAL), 6.721074116167737 (DESIRED)#x1B[0m
#x1B[1m#x1B[31mE            [2]: 6.718207836151123 (ACTUAL), 10.398656939894483 (DESIRED)#x1B[0m
#x1B[1m#x1B[31mE            [3]: 10.398656845092773 (ACTUAL), 9.144648336760273 (DESIRED)#x1B[0m
#x1B[1m#x1B[31mE            [4]: 9.1428804397583 (ACTUAL), 0.0 (DESIRED)#x1B[0m
#x1B[1m#x1B[31mE           Max absolute difference among violations: 9.80768871#x1B[0m
#x1B[1m#x1B[31mE           Max relative difference among violations: 30.41916947#x1B[0m
#x1B[1m#x1B[31mE            ACTUAL: array([ 11.072575,   4.644743,   6.718208, ...,  -5.931427,  -8.632237,#x1B[0m
#x1B[1m#x1B[31mE                  -12.954482], shape=(6885,))#x1B[0m
#x1B[1m#x1B[31mE            DESIRED: array([  4.644744,   6.721074,  10.398657, ...,  -5.931426,  -8.632238,#x1B[0m
#x1B[1m#x1B[31mE                  -12.954482], shape=(6885,))#x1B[0m

#x1B[1m#x1B[31mtests/test_rank_genes_groups.py#x1B[0m:369: AssertionError

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

@remydubois
Copy link
Copy Markdown

Hey, good catch for the OVO column ordering. I have no idea where the bug comes from, it seems to be related to group labels for PBMC that numpy sorts in a weird way. I will try to get a fix in the coming days.

@remydubois
Copy link
Copy Markdown

So it seems to be due to np.argsort and np.sort not sorting the weird characters (" ", "+", "/", "#", etc) of the bulk_labels the same way. I will ship a fix sometime today or this weekend.

NB: I spent a bit of time looking into the PBMC dataset and it seems rather unusual: a lot of values are negative leading to non-defined logfoldchanges, on top of which there seems to be very little value diversity in the dataset. As a result, a lot of genes end up with identical ranksum, but because illico and scanpy do not compute z-score the exact same way (mathematically equivalent but programmatically different), gene ordering is impacted. The gene ordering impacts the position of NaN values in the results, but non-NaN values do match because they are very similar. I am not sure as if this dataset is a good test case.

NB2: details of the programmatic differences:
illico does:

U = ranksum - n_tgt * (n_tgt+ 1)/2
z = U - n_ref * n_tgt / 2

scanpy does:

z = 
ranksum - n_tgt * (n_tgt + 1 + n_ref) / 2

Those are mathematically equivalent but result in differences of the order of 1.e-9 approximately, changing gene orders when ranksums are equal.

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.

2 participants