Spaces:
Sleeping
Sleeping
Upload folder using huggingface_hub
Browse files- CLAUDE.md +81 -0
- web/app/Lab.tsx +90 -56
- web/tsconfig.tsbuildinfo +0 -0
CLAUDE.md
CHANGED
|
@@ -1911,6 +1911,87 @@ Built in chunks. Current state:
|
|
| 1911 |
strongest immune gene at rank 161 (`|corr| = 0.19`). Verdict:
|
| 1912 |
**BORDERLINE** — *"A weak single-gene signal remains; a GP run
|
| 1913 |
might still be informative."*
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1914 |
- **Next:** survival + unsupervised objectives end-to-end; bigger
|
| 1915 |
default Lab budget for the full grammar; cross-cohort validation;
|
| 1916 |
durable run store; mechanism-aware objective; lifting Search's
|
|
|
|
| 1911 |
strongest immune gene at rank 161 (`|corr| = 0.19`). Verdict:
|
| 1912 |
**BORDERLINE** — *"A weak single-gene signal remains; a GP run
|
| 1913 |
might still be informative."*
|
| 1914 |
+
- **Chunk 7 follow-up (done — `scripts/tmb_resid_gp.py` synergy
|
| 1915 |
+
check on MSI-residualized TMB):** Second isolated script that
|
| 1916 |
+
answers whether the DSL finds gene COMBINATIONS beating the best
|
| 1917 |
+
single gene on the "leftover TMB" target the diagnostic borderlined.
|
| 1918 |
+
ONE new file under `scripts/` (biology-aware) + a small helper
|
| 1919 |
+
refactor in `validate/tmb_resid_rank.py` to keep the residual
|
| 1920 |
+
byte-identical between the diagnostic and the GP script.
|
| 1921 |
+
- **`validate.tmb_resid_rank.build_residual_cohort()`** —
|
| 1922 |
+
factored-out public helper returning `(X_named, residual_series,
|
| 1923 |
+
group_stats)`. Both `main()` and `scripts/tmb_resid_gp.py` call
|
| 1924 |
+
it, so any tweak to the within-MSI z-scored `log1p(TMB)` target
|
| 1925 |
+
lives in ONE place. Existing diagnostic behaviour byte-for-byte
|
| 1926 |
+
identical (verified by pytest 130/130).
|
| 1927 |
+
- **`scripts/tmb_resid_gp.py`** — reads the existing processed
|
| 1928 |
+
matrix; imports the residual via `build_residual_cohort()`;
|
| 1929 |
+
`anonymise(X_named)` reuses the sealed map; runs
|
| 1930 |
+
`run_v2_pipeline(M, y, objective=TMB_OBJECTIVE, seed, ...)` per
|
| 1931 |
+
seed with `prefilter_n=None`, `scalar_share_override=0.0`
|
| 1932 |
+
(Vector programs only), `coherence_weight=0.0`, diversity on
|
| 1933 |
+
(`tournament_k=2, p_mutate=0.85, immigrant_fraction=0.10`);
|
| 1934 |
+
default budget `--pop 300 --gens 50 --perms 200` on seeds
|
| 1935 |
+
`[1, 7, 13]`. Per-seed grader reveals only the winner's opaque
|
| 1936 |
+
IDs via `airgap.reveal` (bounded — same discipline as
|
| 1937 |
+
`/evaluate`) and computes the SINGLE-GENE CEILING on the SAME
|
| 1938 |
+
held-out test rows via `_test_ids_for(M, y, seed)` (mirrors the
|
| 1939 |
+
pipeline's continuous split: `make_split(stratify=False,
|
| 1940 |
+
random_state=seed)`) + `_spearman_per_column(X_test, y_test)`.
|
| 1941 |
+
`synergy = combined − ceiling`. Prints per-seed
|
| 1942 |
+
program_repr / revealed genes / combined |spearman| (with
|
| 1943 |
+
n_test) / ceiling / synergy / permutation p, ranges across
|
| 1944 |
+
seeds, then an overall verdict:
|
| 1945 |
+
- `median syn ≥ 0.10 && n_sig ≥ ⌈n/2⌉ && median combined ≥ 0.30`
|
| 1946 |
+
→ **REAL COMBINATORIAL SIGNAL**.
|
| 1947 |
+
- `|median syn| < 0.05 && median combined < 0.50` →
|
| 1948 |
+
**NO SYNERGY**.
|
| 1949 |
+
- `median combined < 0.20 || range ≥ 0.20` →
|
| 1950 |
+
**THE LEFTOVER IS LARGELY NOISE**.
|
| 1951 |
+
- else **BORDERLINE**.
|
| 1952 |
+
- **Airgap.** `engine_v2` sees only opaque IDs; symbols cross the
|
| 1953 |
+
boundary once per seed via a bounded `reveal(winner_ids)` call.
|
| 1954 |
+
No engine / API / UI / dataset change; writes nothing to disk;
|
| 1955 |
+
deleting the script leaves zero trace.
|
| 1956 |
+
- **Verified live.** Smoke `--seeds 1 --pop 60 --gens 10 --perms 20`
|
| 1957 |
+
prints the full per-seed block + ranges + verdict; scipy's
|
| 1958 |
+
`ConstantInputWarning` from degenerate programs (already floored
|
| 1959 |
+
to `WORST_FITNESS` by the engine) is silenced at script scope.
|
| 1960 |
+
`pytest -q` still 130/130.
|
| 1961 |
+
- **Chunk 7 follow-up (done — Groups-the-engine-explored:
|
| 1962 |
+
ascending/descending sort toggle):** Frontend-only. The Groups
|
| 1963 |
+
table (`<ModuleRankingPanel>` in `web/app/Lab.tsx`) sorted
|
| 1964 |
+
descending only; clicking the active sort key now flips direction,
|
| 1965 |
+
clicking a new key resets to descending, and the active button's
|
| 1966 |
+
label appends `↓` / `↑` so the current direction is legible.
|
| 1967 |
+
Implementation: new `SortDir = "asc" | "desc"` state next to
|
| 1968 |
+
`sortKey`; `sortedModules` refactored to a single `valueOf`
|
| 1969 |
+
switch with null / non-finite modules PINNED to the bottom in
|
| 1970 |
+
BOTH directions (so a missing metric never floats to the top on
|
| 1971 |
+
ascending). Reset effect fires on `sortDir` too — flipping
|
| 1972 |
+
direction resets page 0 and closes any expanded row. `tsc
|
| 1973 |
+
--noEmit` clean; no API / airgap / engine change.
|
| 1974 |
+
- **Chunk 7 follow-up (done — Groups-the-engine-explored: plain-
|
| 1975 |
+
English copy pass on the panel + per-column "?" tooltips):**
|
| 1976 |
+
Presentation-only. Two copy rewrites and four new column-header
|
| 1977 |
+
tooltips in `<ModuleRankingPanel>` (`web/app/Lab.tsx`).
|
| 1978 |
+
- Subtitle rewritten to the four-column story ("Every gene group
|
| 1979 |
+
the engine tried, scored four ways so you can judge whole
|
| 1980 |
+
groups, not just single genes") with a one-liner gloss per
|
| 1981 |
+
column. Fixes a literal `’` that was rendering in the
|
| 1982 |
+
old subtitle; straight apostrophes only.
|
| 1983 |
+
- `TIPS.moduleRanking` (the panel-title `?`) rewritten to lead
|
| 1984 |
+
with "Why these columns exist" — the single-gene vs group
|
| 1985 |
+
question the panel is meant to answer — followed by the
|
| 1986 |
+
honest re-scoring caveat.
|
| 1987 |
+
- Each of the four metric column headers (Genetic-programming
|
| 1988 |
+
fitness · Combined AUROC / |ρ| · Coherence · Synergy) now
|
| 1989 |
+
carries a small `<InfoTip>` that says how to READ that column
|
| 1990 |
+
(high vs low), wrapped in
|
| 1991 |
+
`<span className="inline-flex items-center justify-end gap-1">`
|
| 1992 |
+
so it hugs the right edge with the text-right header. Combined
|
| 1993 |
+
header's `metric_kind` conditional preserved inside the wrapper.
|
| 1994 |
+
- `tsc --noEmit` clean; no API / airgap / engine change.
|
| 1995 |
- **Next:** survival + unsupervised objectives end-to-end; bigger
|
| 1996 |
default Lab budget for the full grammar; cross-cohort validation;
|
| 1997 |
durable run store; mechanism-aware objective; lifting Search's
|
web/app/Lab.tsx
CHANGED
|
@@ -233,28 +233,22 @@ const TIPS = {
|
|
| 233 |
"Scalar share = the fraction of programs the engine seeds with a " +
|
| 234 |
"Scalar root (Associate / Effect) versus a Vector root.",
|
| 235 |
moduleRanking:
|
| 236 |
-
"
|
| 237 |
-
"
|
| 238 |
-
"
|
| 239 |
-
"
|
| 240 |
-
"
|
| 241 |
-
"
|
| 242 |
-
"patients
|
| 243 |
-
"
|
| 244 |
-
"
|
| 245 |
-
"
|
| 246 |
-
"
|
| 247 |
-
"
|
| 248 |
-
"
|
| 249 |
-
"
|
| 250 |
-
"
|
| 251 |
-
"
|
| 252 |
-
"stratified confound subgroups (HNSC/HPV).\n\n" +
|
| 253 |
-
"Caveat: Combined AUROC / Coherence / Synergy re-score ~2,900 " +
|
| 254 |
-
"groups on the same small held-out set, so their very top values " +
|
| 255 |
-
"are optimistically biased (the luckiest of thousands). The Genetic-programming " +
|
| 256 |
-
"fitness order (and the badged winner) is the engine's own, " +
|
| 257 |
-
"cross-validated pick — trust it as the reliable choice.",
|
| 258 |
moduleSurvival:
|
| 259 |
"What “Survives” checks: whether a group still separates HPV when " +
|
| 260 |
"you take away a possible confounder — something that travels with " +
|
|
@@ -5836,10 +5830,12 @@ function ModuleRankingPanel({
|
|
| 5836 |
const [loading, setLoading] = useState<boolean>(false);
|
| 5837 |
const [error, setError] = useState<string | null>(null);
|
| 5838 |
type SortKey = "gp_fitness" | "combined" | "coherence" | "synergy";
|
|
|
|
| 5839 |
// Default sort: the engine's own preference order (what the search
|
| 5840 |
// actually picked). The other three are after-the-fact re-score
|
| 5841 |
// lenses.
|
| 5842 |
const [sortKey, setSortKey] = useState<SortKey>("gp_fitness");
|
|
|
|
| 5843 |
const [page, setPage] = useState<number>(0);
|
| 5844 |
// Symbol cache keyed by opaque ID — accumulates across pages so
|
| 5845 |
// re-visiting a page is free.
|
|
@@ -5878,27 +5874,30 @@ function ModuleRankingPanel({
|
|
| 5878 |
const sortedModules = useMemo<RankedModule[]>(() => {
|
| 5879 |
if (!data) return [];
|
| 5880 |
const xs = [...data.modules];
|
| 5881 |
-
|
| 5882 |
-
|
| 5883 |
-
|
| 5884 |
-
|
| 5885 |
-
|
| 5886 |
-
|
| 5887 |
-
|
| 5888 |
-
|
| 5889 |
-
|
| 5890 |
-
);
|
| 5891 |
-
|
| 5892 |
-
|
| 5893 |
-
|
| 5894 |
-
|
| 5895 |
-
);
|
| 5896 |
-
|
|
|
|
|
|
|
|
|
|
| 5897 |
return xs;
|
| 5898 |
// synergyOf depends only on RankedModule's stable per-gene fields,
|
| 5899 |
// so we leave it out of the dep list.
|
| 5900 |
// eslint-disable-next-line react-hooks/exhaustive-deps
|
| 5901 |
-
}, [data, sortKey]);
|
| 5902 |
|
| 5903 |
// Re-sort or re-load resets the page + collapses any open row so an
|
| 5904 |
// expanded "rank N" row doesn't strand once the underlying ranking
|
|
@@ -5906,7 +5905,7 @@ function ModuleRankingPanel({
|
|
| 5906 |
useEffect(() => {
|
| 5907 |
setPage(0);
|
| 5908 |
setExpandedIx(null);
|
| 5909 |
-
}, [sortKey, data]);
|
| 5910 |
|
| 5911 |
// Winner-set equality: unordered set of opaque IDs equal to the
|
| 5912 |
// winner's gene_ids. Used to badge that exact module — connects the
|
|
@@ -5971,14 +5970,16 @@ function ModuleRankingPanel({
|
|
| 5971 |
title="Groups the engine explored"
|
| 5972 |
titleTip={TIPS.moduleRanking}
|
| 5973 |
subtitle={
|
| 5974 |
-
"Every gene group the engine tried
|
| 5975 |
-
"
|
| 5976 |
-
"
|
| 5977 |
-
"
|
| 5978 |
-
"
|
| 5979 |
-
"
|
| 5980 |
-
"
|
| 5981 |
-
"
|
|
|
|
|
|
|
| 5982 |
}
|
| 5983 |
>
|
| 5984 |
{loading && (
|
|
@@ -6012,7 +6013,10 @@ function ModuleRankingPanel({
|
|
| 6012 |
<button
|
| 6013 |
key={k}
|
| 6014 |
type="button"
|
| 6015 |
-
onClick={() =>
|
|
|
|
|
|
|
|
|
|
| 6016 |
aria-pressed={sortKey === k}
|
| 6017 |
className={[
|
| 6018 |
"rounded-md px-2 py-0.5 text-[11px] transition-colors",
|
|
@@ -6021,7 +6025,7 @@ function ModuleRankingPanel({
|
|
| 6021 |
: "border border-border bg-card text-ink hover:border-accent/40",
|
| 6022 |
].join(" ")}
|
| 6023 |
>
|
| 6024 |
-
{label}
|
| 6025 |
</button>
|
| 6026 |
))}
|
| 6027 |
</div>
|
|
@@ -6068,14 +6072,44 @@ function ModuleRankingPanel({
|
|
| 6068 |
<thead className="bg-card text-xs tracking-wide text-muted">
|
| 6069 |
<tr>
|
| 6070 |
<th className="px-3 py-2 text-left w-10">#</th>
|
| 6071 |
-
<th className="px-3 py-2 text-right">Genetic-programming fitness</th>
|
| 6072 |
<th className="px-3 py-2 text-right">
|
| 6073 |
-
|
| 6074 |
-
|
| 6075 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6076 |
</th>
|
| 6077 |
-
<th className="px-3 py-2 text-right">Coherence</th>
|
| 6078 |
-
<th className="px-3 py-2 text-right">Synergy</th>
|
| 6079 |
<th className="px-3 py-2 text-right">Size</th>
|
| 6080 |
<th className="px-3 py-2 text-left">Genes</th>
|
| 6081 |
<th className="px-3 py-2 text-left">Tags</th>
|
|
|
|
| 233 |
"Scalar share = the fraction of programs the engine seeds with a " +
|
| 234 |
"Scalar root (Associate / Effect) versus a Vector root.",
|
| 235 |
moduleRanking:
|
| 236 |
+
"Why these columns exist: once the engine could detect the trait, " +
|
| 237 |
+
"the real question was whether the signal came from a few genes " +
|
| 238 |
+
"working together or from one strong gene, and single-gene " +
|
| 239 |
+
"rankings can't tell you that. These measures judge whole groups " +
|
| 240 |
+
"instead. Coherence tells a genuine co-expressed module from a " +
|
| 241 |
+
"random bag of genes. Combined AUROC scores the group as a group, " +
|
| 242 |
+
"on patients it never saw. Synergy separates real teamwork from " +
|
| 243 |
+
"one good gene with passengers along for the ride. " +
|
| 244 |
+
"Genetic-programming fitness sits beside them as the engine's own " +
|
| 245 |
+
"verdict, so you can compare what the engine actually preferred " +
|
| 246 |
+
"against these after-the-fact re-scores. Together they answer one " +
|
| 247 |
+
"question: is the result carried by gene teamwork or by lone " +
|
| 248 |
+
"strong genes? Note that the re-scores are computed after the " +
|
| 249 |
+
"run, so they can rank groups differently from the engine's own " +
|
| 250 |
+
"picks, and the very top re-score values are optimistically " +
|
| 251 |
+
"biased because they are the best of thousands.",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 252 |
moduleSurvival:
|
| 253 |
"What “Survives” checks: whether a group still separates HPV when " +
|
| 254 |
"you take away a possible confounder — something that travels with " +
|
|
|
|
| 5830 |
const [loading, setLoading] = useState<boolean>(false);
|
| 5831 |
const [error, setError] = useState<string | null>(null);
|
| 5832 |
type SortKey = "gp_fitness" | "combined" | "coherence" | "synergy";
|
| 5833 |
+
type SortDir = "asc" | "desc";
|
| 5834 |
// Default sort: the engine's own preference order (what the search
|
| 5835 |
// actually picked). The other three are after-the-fact re-score
|
| 5836 |
// lenses.
|
| 5837 |
const [sortKey, setSortKey] = useState<SortKey>("gp_fitness");
|
| 5838 |
+
const [sortDir, setSortDir] = useState<SortDir>("desc");
|
| 5839 |
const [page, setPage] = useState<number>(0);
|
| 5840 |
// Symbol cache keyed by opaque ID — accumulates across pages so
|
| 5841 |
// re-visiting a page is free.
|
|
|
|
| 5874 |
const sortedModules = useMemo<RankedModule[]>(() => {
|
| 5875 |
if (!data) return [];
|
| 5876 |
const xs = [...data.modules];
|
| 5877 |
+
const valueOf = (m: RankedModule): number | null | undefined => {
|
| 5878 |
+
switch (sortKey) {
|
| 5879 |
+
case "coherence": return m.coherence;
|
| 5880 |
+
case "gp_fitness": return m.gp_fitness;
|
| 5881 |
+
case "synergy": return synergyOf(m);
|
| 5882 |
+
default: return m.combined_holdout;
|
| 5883 |
+
}
|
| 5884 |
+
};
|
| 5885 |
+
xs.sort((a, b) => {
|
| 5886 |
+
const va = valueOf(a), vb = valueOf(b);
|
| 5887 |
+
const fa = va == null || !Number.isFinite(va);
|
| 5888 |
+
const fb = vb == null || !Number.isFinite(vb);
|
| 5889 |
+
if (fa && fb) return 0;
|
| 5890 |
+
if (fa) return 1;
|
| 5891 |
+
if (fb) return -1;
|
| 5892 |
+
return sortDir === "asc"
|
| 5893 |
+
? (va as number) - (vb as number)
|
| 5894 |
+
: (vb as number) - (va as number);
|
| 5895 |
+
});
|
| 5896 |
return xs;
|
| 5897 |
// synergyOf depends only on RankedModule's stable per-gene fields,
|
| 5898 |
// so we leave it out of the dep list.
|
| 5899 |
// eslint-disable-next-line react-hooks/exhaustive-deps
|
| 5900 |
+
}, [data, sortKey, sortDir]);
|
| 5901 |
|
| 5902 |
// Re-sort or re-load resets the page + collapses any open row so an
|
| 5903 |
// expanded "rank N" row doesn't strand once the underlying ranking
|
|
|
|
| 5905 |
useEffect(() => {
|
| 5906 |
setPage(0);
|
| 5907 |
setExpandedIx(null);
|
| 5908 |
+
}, [sortKey, sortDir, data]);
|
| 5909 |
|
| 5910 |
// Winner-set equality: unordered set of opaque IDs equal to the
|
| 5911 |
// winner's gene_ids. Used to badge that exact module — connects the
|
|
|
|
| 5970 |
title="Groups the engine explored"
|
| 5971 |
titleTip={TIPS.moduleRanking}
|
| 5972 |
subtitle={
|
| 5973 |
+
"Every gene group the engine tried, scored four ways so you can " +
|
| 5974 |
+
"judge whole groups, not just single genes. Genetic-programming " +
|
| 5975 |
+
"fitness: how much the engine itself liked the group. Combined " +
|
| 5976 |
+
"AUROC: how well the group separates the two kinds of tumour on " +
|
| 5977 |
+
"patients it never saw. Coherence: how tightly its genes move " +
|
| 5978 |
+
"together (a real module versus a random bag). Synergy: how much " +
|
| 5979 |
+
"the group beats its single best gene (real teamwork versus one " +
|
| 5980 |
+
"strong gene carrying passengers). The winning program is badged; " +
|
| 5981 |
+
"the Survives flags show whether a group still separates the " +
|
| 5982 |
+
"label under the confound checks."
|
| 5983 |
}
|
| 5984 |
>
|
| 5985 |
{loading && (
|
|
|
|
| 6013 |
<button
|
| 6014 |
key={k}
|
| 6015 |
type="button"
|
| 6016 |
+
onClick={() => {
|
| 6017 |
+
if (sortKey === k) setSortDir((d) => (d === "desc" ? "asc" : "desc"));
|
| 6018 |
+
else { setSortKey(k); setSortDir("desc"); }
|
| 6019 |
+
}}
|
| 6020 |
aria-pressed={sortKey === k}
|
| 6021 |
className={[
|
| 6022 |
"rounded-md px-2 py-0.5 text-[11px] transition-colors",
|
|
|
|
| 6025 |
: "border border-border bg-card text-ink hover:border-accent/40",
|
| 6026 |
].join(" ")}
|
| 6027 |
>
|
| 6028 |
+
{label}{sortKey === k ? (sortDir === "desc" ? " ↓" : " ↑") : ""}
|
| 6029 |
</button>
|
| 6030 |
))}
|
| 6031 |
</div>
|
|
|
|
| 6072 |
<thead className="bg-card text-xs tracking-wide text-muted">
|
| 6073 |
<tr>
|
| 6074 |
<th className="px-3 py-2 text-left w-10">#</th>
|
|
|
|
| 6075 |
<th className="px-3 py-2 text-right">
|
| 6076 |
+
<span className="inline-flex items-center justify-end gap-1">
|
| 6077 |
+
Genetic-programming fitness
|
| 6078 |
+
<InfoTip
|
| 6079 |
+
text="Higher means the engine liked this group more during the search. The very highest are its actual picks; low values are groups it barely looked at."
|
| 6080 |
+
label="How to read Genetic-programming fitness"
|
| 6081 |
+
/>
|
| 6082 |
+
</span>
|
| 6083 |
+
</th>
|
| 6084 |
+
<th className="px-3 py-2 text-right">
|
| 6085 |
+
<span className="inline-flex items-center justify-end gap-1">
|
| 6086 |
+
{data.metric_kind === "auroc"
|
| 6087 |
+
? "Combined AUROC"
|
| 6088 |
+
: "Combined |ρ|"}
|
| 6089 |
+
<InfoTip
|
| 6090 |
+
text="How well the whole group separates the two kinds of tmour on patients it never saw. Around 0.5 is no better than chance; close to 1.0 is a clean split. For a continuous target this is a correlation instead, where further from 0 is stronger."
|
| 6091 |
+
label="How to read Combined AUROC"
|
| 6092 |
+
/>
|
| 6093 |
+
</span>
|
| 6094 |
+
</th>
|
| 6095 |
+
<th className="px-3 py-2 text-right">
|
| 6096 |
+
<span className="inline-flex items-center justify-end gap-1">
|
| 6097 |
+
Coherence
|
| 6098 |
+
<InfoTip
|
| 6099 |
+
text="Higher means the group's genes move together tightly, so it is a real co-expressed module. Low means the genes are largely unrelated, a random bag."
|
| 6100 |
+
label="How to read Coherence"
|
| 6101 |
+
/>
|
| 6102 |
+
</span>
|
| 6103 |
+
</th>
|
| 6104 |
+
<th className="px-3 py-2 text-right">
|
| 6105 |
+
<span className="inline-flex items-center justify-end gap-1">
|
| 6106 |
+
Synergy
|
| 6107 |
+
<InfoTip
|
| 6108 |
+
text="Positive and high means the group genuinely beats its best single gene, real teamwork. Around zero or negative means one strong gene is doing the work and the rest are passengers."
|
| 6109 |
+
label="How to read Synergy"
|
| 6110 |
+
/>
|
| 6111 |
+
</span>
|
| 6112 |
</th>
|
|
|
|
|
|
|
| 6113 |
<th className="px-3 py-2 text-right">Size</th>
|
| 6114 |
<th className="px-3 py-2 text-left">Genes</th>
|
| 6115 |
<th className="px-3 py-2 text-left">Tags</th>
|
web/tsconfig.tsbuildinfo
CHANGED
|
The diff for this file is too large to render.
See raw diff
|
|
|