|
7 | 7 | from pydantic import BaseModel, ConfigDict, Field |
8 | 8 | from pydantic.dataclasses import dataclass |
9 | 9 | from pynndescent import NNDescent |
10 | | -from scipy.stats import chi2_contingency, fisher_exact, gamma |
| 10 | +from scipy.stats import chi2_contingency, fisher_exact, gamma, wilcoxon |
11 | 11 | from scipy.stats.contingency import odds_ratio |
12 | 12 |
|
13 | 13 | from ..computing import compute_weighted_hodge_embedding |
@@ -501,15 +501,15 @@ def summarize_homotopy_coherence( |
501 | 501 | self, |
502 | 502 | mode: Literal["full", "mean", "median"] = "full", |
503 | 503 | mode_match: Literal["max", "mean", "median"] = "max", |
504 | | - ) -> list[Percent_t | None] | Percent_t | None: |
| 504 | + ) -> list[tuple] | Percent_t | None: |
505 | 505 | values = [ |
506 | | - match.summarize_homotopy_coherence(mode=mode_match) |
| 506 | + (match.idx_bootstrap, match.summarize_homotopy_coherence(mode=mode_match)) |
507 | 507 | for match in self.filter_matches(keep="equivalent") |
508 | 508 | ] |
509 | 509 | if mode == "full": |
510 | 510 | return values |
511 | 511 |
|
512 | | - valid_values = [value for value in values if value is not None] |
| 512 | + valid_values = [value[1] for value in values if value[1] is not None] |
513 | 513 | if not valid_values: |
514 | 514 | return None |
515 | 515 | match mode: |
@@ -752,6 +752,35 @@ def chi2_test_presence( |
752 | 752 | pvalues_corrected=pvalues_corrected_presence, |
753 | 753 | ) |
754 | 754 |
|
| 755 | + def wilcoxon_test_presence( |
| 756 | + self, method_pval_correction: MultipleTestCorrectionMethod |
| 757 | + ): |
| 758 | + n_tracks = len(self.loop_tracks) |
| 759 | + presence_matrix = np.zeros([self.num_bootstraps, n_tracks]) |
| 760 | + for ti, trk in self.loop_tracks.items(): |
| 761 | + coherence_values = trk.summarize_homotopy_coherence( |
| 762 | + mode="full", |
| 763 | + mode_match="mean", |
| 764 | + ) |
| 765 | + for bi, cv in coherence_values: |
| 766 | + presence_matrix[bi, ti] = cv if cv else 0 |
| 767 | + presence_global = np.mean(presence_matrix, axis=1) |
| 768 | + pvalues_raw_presence = [] |
| 769 | + for i in range(n_tracks): |
| 770 | + result = wilcoxon( |
| 771 | + x=presence_matrix[:, i], y=presence_global, alternative="greater" |
| 772 | + ) |
| 773 | + pvalues_raw_presence.append(result.pvalue) |
| 774 | + pvalues_corrected_presence = correct_pvalues( |
| 775 | + pvalues_raw_presence, method=method_pval_correction |
| 776 | + ) |
| 777 | + return PresenceTestResult( |
| 778 | + probabilities=[], |
| 779 | + odds_ratios=[], |
| 780 | + pvalues_raw=pvalues_raw_presence, |
| 781 | + pvalues_corrected=pvalues_corrected_presence, |
| 782 | + ) |
| 783 | + |
755 | 784 | def gamma_test_persistence( |
756 | 785 | self, |
757 | 786 | selected_loop_classes: list, |
|
0 commit comments