Spaces:
Sleeping
Sleeping
File size: 20,347 Bytes
0fff343 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 | # Prompt β Rich parameter help (click-to-open explainers with diagrams)
Upgrade the "?" help for the 8 Parameters in the Lab from a one-line tooltip into a rich, click-to-open explainer (text + examples + diagrams), aimed at a non-expert reviewer. Presentation/read-only β no logic changes. Reuse the calm theme (bg #FAFAF7, card #FCFBF8, ink #23303A, muted #6E7F8C, border #ECEAE4, accent #3A6B7E, highlight #BC6B2E) and the existing monospace for gene IDs.
## Interaction
- Build ONE reusable component `<ParamHelp short="..." detailed={...} />` so wording can't drift. The "?" button:
- on **hover/focus**, shows the SHORT one-liner (a small tooltip β keep the current text as the short summary);
- on **click**, opens a MODAL dialog with the DETAILED content (text + any diagram).
- Modal: `role="dialog"`, `aria-modal="true"`, labelled by its title; ~640px wide on desktop, full-width with padding and vertical scroll on narrow screens; close on X, Esc, and backdrop click; return focus to the "?" button on close. Calm card styling (border #ECEAE4, fill #FCFBF8, ~14px radius, generous padding). Headings in #23303A, body readable (~14px), muted captions #6E7F8C.
- Apply this ONLY to the 8 Parameters "?" icons. Leave other "?" icons elsewhere (objectives, run id/status) as the existing InfoTip β do not touch them.
- Diagrams are embedded as small SVG components, `width:100%; height:auto` (viewBox scales). Each diagram is used once, in its own parameter.
## Detailed content per parameter
For each: SHORT = hover text; DETAILED = modal body (use the wording below; render line breaks and bullet/example blocks cleanly).
### Generations
SHORT: "How many rounds of 'keep the best, breed, mutate' the engine runs. More rounds refine further, but take longer."
DETAILED:
- What it is: one "generation" is a single round of the engine's loop β score every program, keep the best, then breed and mutate them into the next batch. Generations is how many rounds it runs.
- How it works: the engine starts with random programs (mostly poor) and each round nudges the population toward better ones β like selective breeding.
- More vs fewer: more rounds refine the winners further, but with diminishing returns once it has converged. The harder part is usually *discovering* the right genes in the first place (driven by Population and mutation), not polishing β so extra generations help less once the curve flattens.
- Typical: 30β60.
- Small inline illustration: a 4-step loop "random programs β score each β keep the best β breed & mutate β (back to score)", calm style, arrows; the loop arrow labelled "Γ Generations".
### Population
SHORT: "How many candidate programs compete in each round. A 'program' is a small pipeline built by composing the DSL operators (Select β Reduce β Fit) over the gene data. More programs explores more options, but is slower."
DETAILED:
- What it is: how many candidate programs compete each round. A "program" is a small pipeline built from the DSL operators β Select (pick genes) β Reduce (average them into one score) β Fit (use the score to separate the groups).
- Why it matters: a bigger population samples more genes and structures each round, so it's the main lever for *discovery* β finding the right genes at all. Generations then refine what was found.
- Example β three random programs in a population (opaque gene IDs, monospace):
- `average(g04823, g11201, g00917) β score`
- `average(g15522, g02013) β average(g08840, g00231) β score`
- `average(g07788, g13002, g05340) β score`
- More vs fewer: more explores more options, but each round is slower.
- Typical: 150β300.
### Genes / set
SHORT: "The most genes a single score may use. Smaller keeps programs simple and readable."
DETAILED:
- What it is: a "set" is the group of genes averaged together into a single score. Genes/set is the maximum size of that group.
- Example: `Select(g05347, g00048, g06271) β average β one score` (uses 3; the cap might be 8).
- Smaller vs larger: smaller keeps each score simple and readable; larger lets one score blend more genes.
- It pairs with Max sets: Genes/set is the *width* of each group; Max sets is *how many* groups.
### Max sets
SHORT: "How many separate gene-scores a program may combine (1 or 2). 2 lets it build a small 'score made of scores'."
DETAILED:
- What it is: how many *separate* gene groups a program may build and then combine (1 or 2). They use different genes β not the same ones reused.
- Example (2 sets):
- Set 1: `average(g05347, g00048, g06271) β scoreA`
- Set 2: `average(g15522, g02013) β scoreB`
- Combine: `scoreA β scoreB β final score`
- Why two: to capture a *contrast* β e.g. one group that's low in MSI-H and one that's high; the gap between them can separate better than either alone (like "repair activity minus immune activity"). One set can't express that; two can.
- If one group is enough, the engine can still use 1.
- Diagram (small): two short chains β `matrix β Select β Reduce β scoreA` and `matrix β Select β Reduce β scoreB` β both feeding a `Combine (sub)` node, then a final `score`. Verbs = accent-bordered boxes, scores = amber pills, calm style.
### Ξ» (size penalty)
SHORT: "How hard the engine is penalised for using more genes. Higher pushes it toward fewer genes (simpler answers)."
DETAILED:
- What it is: a "price per gene" that discourages bloated programs. Every program is graded on a single number:
- `fitness = separation β Ξ» Γ (number of genes)`
- so the engine ranks by accuracy *minus* a size tax.
- The key idea β Ξ» is the admission price each gene must beat: with Ξ» = 0.005, a gene is only worth keeping if it adds more than 0.005 of separation.
- Worked example: a 3-gene program scores 0.90 β net 0.90 β 0.015 = 0.885. Add a 4th gene that lifts it to 0.903 (only +0.003) β net 0.883, *lower*, so it's rejected. A 4th gene that lifts it to 0.91 (+0.01) β net 0.890, *higher*, so it's kept.
- Turning the knob: Ξ» = 0 β genes free β bloated, overfit programs. Ξ» small (0.005) β trims useless genes, keeps useful ones. Ξ» large β very lean programs, but may drop useful genes.
- Diagram: the accuracy-vs-genes trade-off (embed the SVG in "DIAGRAMS" below).
### Seed
SHORT: "The starting point for the engine's randomness. The same seed reproduces the exact same run; change it to see a different run."
DETAILED:
- Why randomness: the space of possible programs is astronomically large (picking even 8 genes out of 20,000 is ~10^29 combinations), so the engine can't try them all β it explores with randomness: random starting programs, random mutations, random breeding.
- What the seed is: computers don't make true randomness; a formula generates a sequence of numbers, each from the previous one. The seed is the *starting number* fed into that formula β everything random flows from it. (One common formula: `next = (1664525 Γ current + 1013904223) mod 2Β³Β²`; with seed 42 the first value is 1,083,814,273, then mapped onto a gene position.)
- What it does: think of the seed as one fixed list of dice rolls used in order across the whole run β early rolls pick the starting genes, later rolls drive mutations. Same seed β same list β identical run. Different seed β a different list β a different run.
- Why vary it: because the search has luck in it, run a few seeds (42, 7, 123) and see whether the same genes keep appearing β that tells you a finding is real, not a fluke.
- Diagram: the seed-as-a-fixed-list-of-dice-rolls (embed the SVG below).
### Permutations
SHORT: "How many times we re-run on deliberately scrambled labels to check the result isn't luck. The real result must beat these chance runs (that's the 'permutation p')."
DETAILED:
- What it checks: whether the winning score is real signal or could have come up by luck. The engine searches so hard that some programs separate the groups well by pure coincidence, so a high score alone isn't proof.
- How it works: shuffle the MSI-H / MSS labels across patients at random β this breaks any real geneβlabel link, creating a "no-signal world". Re-score there: any score above 0.5 is pure chance. Repeat many times (this knob = how many) to build a picture of what luck looks like.
- Reading it: permutation p = the fraction of shuffled runs that scored β₯ the real winner. p = 0.005 means only 0.5% of chance runs matched it β very unlikely a fluke. Conventionally p < 0.05 is the "unlikely to be luck" line.
- The knob: with 200 shuffles the smallest p you can report is about 1/200 β 0.005; more permutations give a finer, more trustworthy p.
- Diagram: the "luck pile" vs the real result (embed the SVG below).
### Prefilter top-N
SHORT: "By default the engine searches all ~20,000 genes, so nothing is pre-excluded. Turning this on narrows to the N most promising genes first β faster, but it can drop a real gene that only shows signal in combination."
DETAILED:
- Default (off): the engine searches all ~20,000 genes, so nothing is pre-excluded β the most honest setting for a discovery demo.
- Turning it on: first narrows to the N genes most individually associated with the target (computed name-blind, on the training split only), then searches within that shortlist. Faster, because the space is ~10Γ smaller.
- The trade-off: speed and focus vs completeness. A univariate shortlist can drop a gene that only matters *in combination* (no signal on its own), and it sets a ceiling β if a gene isn't in the shortlist, the engine can never find it.
- Small inline illustration (funnel): "~20,000 genes β keep the N most individually associated β search within N", with a muted note "off by default = no funnel".
## DIAGRAMS (embed verbatim; wrap each so it scales: width:100%, height auto)
### Seed diagram
```svg
<svg viewBox="0 0 720 200" xmlns="http://www.w3.org/2000/svg" role="img" font-family="ui-sans-serif,system-ui,sans-serif">
<title>The seed as one fixed list of dice rolls used in order across the whole run</title>
<desc>Seed 42 produces a fixed sequence of dice rolls; early rolls pick initial genes, later rolls drive a mutation. Same seed gives the same run.</desc>
<rect x="40" y="6" width="74" height="22" rx="11" fill="#3A6B7E"/>
<text x="77" y="21" text-anchor="middle" font-size="12" font-weight="700" fill="#fff">Seed 42</text>
<text x="124" y="22" font-size="12.5" fill="#6E7F8C">β one fixed list of random rolls, used in order:</text>
<rect x="50" y="55" width="48" height="48" rx="9" fill="#FCFBF8" stroke="#3A6B7E" stroke-width="1.5"/>
<circle cx="62" cy="67" r="3.5" fill="#23303A"/><circle cx="74" cy="79" r="3.5" fill="#23303A"/><circle cx="86" cy="91" r="3.5" fill="#23303A"/>
<rect x="112" y="55" width="48" height="48" rx="9" fill="#FCFBF8" stroke="#3A6B7E" stroke-width="1.5"/>
<circle cx="124" cy="67" r="3.5" fill="#23303A"/><circle cx="148" cy="67" r="3.5" fill="#23303A"/><circle cx="136" cy="79" r="3.5" fill="#23303A"/><circle cx="124" cy="91" r="3.5" fill="#23303A"/><circle cx="148" cy="91" r="3.5" fill="#23303A"/>
<rect x="174" y="55" width="48" height="48" rx="9" fill="#FCFBF8" stroke="#3A6B7E" stroke-width="1.5"/>
<circle cx="186" cy="67" r="3.5" fill="#23303A"/><circle cx="210" cy="91" r="3.5" fill="#23303A"/>
<rect x="236" y="55" width="48" height="48" rx="9" fill="#FCFBF8" stroke="#3A6B7E" stroke-width="1.5"/>
<circle cx="248" cy="67" r="3.5" fill="#23303A"/><circle cx="248" cy="79" r="3.5" fill="#23303A"/><circle cx="248" cy="91" r="3.5" fill="#23303A"/><circle cx="272" cy="67" r="3.5" fill="#23303A"/><circle cx="272" cy="79" r="3.5" fill="#23303A"/><circle cx="272" cy="91" r="3.5" fill="#23303A"/>
<line x1="294" y1="52" x2="294" y2="106" stroke="#C7CDD1" stroke-width="1.5" stroke-dasharray="4 4"/>
<rect x="314" y="55" width="48" height="48" rx="9" fill="#FCFBF8" stroke="#3A6B7E" stroke-width="1.5"/>
<circle cx="338" cy="79" r="3.5" fill="#23303A"/>
<rect x="376" y="55" width="48" height="48" rx="9" fill="#FCFBF8" stroke="#3A6B7E" stroke-width="1.5"/>
<circle cx="388" cy="67" r="3.5" fill="#23303A"/><circle cx="412" cy="67" r="3.5" fill="#23303A"/><circle cx="388" cy="91" r="3.5" fill="#23303A"/><circle cx="412" cy="91" r="3.5" fill="#23303A"/>
<text x="446" y="86" font-size="22" fill="#B9B6AE">β¦</text>
<path d="M50,110 L50,116 L284,116 L284,110" fill="none" stroke="#9AA0A6" stroke-width="1.2"/>
<text x="167" y="132" text-anchor="middle" font-size="11.5" fill="#2C5563"><tspan font-weight="700">Generation 0</tspan> β pick the initial programs' genes</text>
<path d="M314,110 L314,116 L424,116 L424,110" fill="none" stroke="#9AA0A6" stroke-width="1.2"/>
<text x="369" y="132" text-anchor="middle" font-size="11.5" fill="#8A4E20"><tspan font-weight="700">Generation 5</tspan> β a mutation</text>
<text x="294" y="150" text-anchor="middle" font-size="10.5" fill="#6E7F8C">β¦ many rolls later β¦</text>
<line x1="40" y1="166" x2="680" y2="166" stroke="#ECEAE4"/>
<text x="40" y="186" font-size="12" fill="#23303A"><tspan font-weight="700">Same seed</tspan> β same list β same run. <tspan fill="#6E7F8C">Change the seed β a different list β a different run.</tspan></text>
</svg>
```
### Ξ» trade-off diagram
```svg
<svg viewBox="0 0 720 410" xmlns="http://www.w3.org/2000/svg" role="img" font-family="ui-sans-serif,system-ui,sans-serif">
<title>How lambda picks the best program size: net fitness = separation minus a per-gene penalty</title>
<desc>Raw separation rises then plateaus; net fitness subtracts lambda times genes and peaks at an intermediate size; a larger lambda moves the peak to fewer genes.</desc>
<g stroke="#ECEAE4" stroke-width="1">
<line x1="70" y1="340" x2="660" y2="340"/><line x1="70" y1="273" x2="660" y2="273"/><line x1="70" y1="207" x2="660" y2="207"/><line x1="70" y1="140" x2="660" y2="140"/><line x1="70" y1="73" x2="660" y2="73"/>
</g>
<g font-size="10" fill="#6E7F8C" text-anchor="end">
<text x="62" y="344">0.5</text><text x="62" y="277">0.6</text><text x="62" y="211">0.7</text><text x="62" y="144">0.8</text><text x="62" y="77">0.9</text>
</g>
<line x1="70" y1="40" x2="70" y2="340" stroke="#D9D6CE" stroke-width="1.5"/>
<line x1="70" y1="340" x2="660" y2="340" stroke="#D9D6CE" stroke-width="1.5"/>
<g font-size="10" fill="#6E7F8C" text-anchor="middle">
<text x="70" y="356">0</text><text x="154" y="356">2</text><text x="238" y="356">4</text><text x="322" y="356">6</text><text x="406" y="356">8</text><text x="491" y="356">10</text><text x="575" y="356">12</text><text x="659" y="356">14</text>
</g>
<text x="365" y="378" text-anchor="middle" font-size="12" fill="#23303A">number of genes in the program</text>
<text x="20" y="190" text-anchor="middle" font-size="12" fill="#23303A" transform="rotate(-90 20,190)">separation (accuracy)</text>
<polyline fill="none" stroke="#3A6B7E" stroke-width="2.5" points="70,340 112,227 154,159 196,117 238,92 280,77 322,67 364,62 406,59 449,57 491,55 575,54 659,53"/>
<text x="500" y="44" font-size="11.5" font-weight="700" fill="#3A6B7E">raw separation</text>
<text x="500" y="59" font-size="10.5" fill="#6E7F8C">rises fast, then plateaus β</text>
<text x="500" y="72" font-size="10.5" fill="#6E7F8C">extra genes barely help</text>
<polyline fill="none" stroke="#BC6B2E" stroke-width="2.5" points="70,340 112,231 154,165 196,127 238,105 280,93 322,87 364,85 406,85 449,87 491,89 575,94 659,100"/>
<line x1="364" y1="85" x2="364" y2="340" stroke="#BC6B2E" stroke-width="1" stroke-dasharray="3 3" opacity="0.5"/>
<circle cx="364" cy="85" r="5" fill="#BC6B2E"/>
<text x="376" y="120" font-size="11" font-weight="700" fill="#8A4E20">peak (Ξ» = 0.005)</text>
<text x="376" y="134" font-size="10.5" fill="#8A4E20">engine keeps ~7 genes</text>
<polyline fill="none" stroke="#D79A6A" stroke-width="2.2" stroke-dasharray="6 4" points="70,340 112,247 154,199 196,177 238,172 280,177 322,187 364,202 406,219 449,237 491,255"/>
<line x1="238" y1="172" x2="238" y2="340" stroke="#D79A6A" stroke-width="1" stroke-dasharray="3 3" opacity="0.5"/>
<circle cx="238" cy="172" r="5" fill="#D79A6A"/>
<text x="250" y="200" font-size="10.5" font-weight="700" fill="#B07636">higher Ξ» = 0.03</text>
<text x="250" y="214" font-size="10.5" fill="#B07636">peak shifts left β ~4 genes</text>
<g font-size="11" fill="#23303A">
<line x1="80" y1="398" x2="104" y2="398" stroke="#3A6B7E" stroke-width="2.5"/><text x="110" y="402">raw separation</text>
<line x1="240" y1="398" x2="264" y2="398" stroke="#BC6B2E" stroke-width="2.5"/><text x="270" y="402">net fitness (Ξ»=0.005)</text>
<line x1="450" y1="398" x2="474" y2="398" stroke="#D79A6A" stroke-width="2.2" stroke-dasharray="6 4"/><text x="480" y="402">net fitness (Ξ»=0.03)</text>
</g>
</svg>
```
### Permutations diagram
```svg
<svg viewBox="0 0 700 380" xmlns="http://www.w3.org/2000/svg" role="img" font-family="ui-sans-serif,system-ui,sans-serif">
<title>Permutation null: scores from 200 shuffled-label runs versus the real result</title>
<desc>A histogram of 200 shuffled-label scores clusters near 0.58, well below the real winning score of 0.89; no shuffle reaches it, giving a permutation p of about 0.005.</desc>
<line x1="70" y1="50" x2="70" y2="320" stroke="#D9D6CE" stroke-width="1.5"/>
<line x1="70" y1="320" x2="640" y2="320" stroke="#D9D6CE" stroke-width="1.5"/>
<g font-size="10" fill="#6E7F8C" text-anchor="middle">
<text x="70" y="336">0.4</text><text x="162" y="336">0.5</text><text x="253" y="336">0.6</text><text x="345" y="336">0.7</text><text x="437" y="336">0.8</text><text x="528" y="336">0.9</text><text x="620" y="336">1.0</text>
</g>
<text x="355" y="358" text-anchor="middle" font-size="12" fill="#23303A">score (separation / AUROC)</text>
<text x="20" y="185" text-anchor="middle" font-size="12" fill="#23303A" transform="rotate(-90 20,185)">number of shuffled runs</text>
<line x1="162" y1="60" x2="162" y2="320" stroke="#C7CDD1" stroke-width="1" stroke-dasharray="4 4"/>
<text x="162" y="72" text-anchor="middle" font-size="9.5" fill="#9AA0A6">0.5 = guessing</text>
<g fill="#CFE0E4">
<rect x="110.4" y="303.1" width="20" height="16.9"/><rect x="133.3" y="277.8" width="20" height="42.2"/><rect x="156.3" y="235.6" width="20" height="84.4"/><rect x="179.2" y="176.6" width="20" height="143.4"/><rect x="202.1" y="109.1" width="20" height="210.9"/><rect x="225" y="58.4" width="20" height="261.6"/><rect x="247.9" y="92.2" width="20" height="227.8"/><rect x="270.8" y="159.7" width="20" height="160.3"/><rect x="293.75" y="218.75" width="20" height="101.25"/><rect x="316.7" y="260.9" width="20" height="59.1"/><rect x="339.6" y="286.25" width="20" height="33.75"/><rect x="362.5" y="303.1" width="20" height="16.9"/>
</g>
<text x="150" y="44" font-size="11.5" font-weight="700" fill="#3A6B7E">200 shuffled-label runs (chance)</text>
<text x="150" y="100" font-size="10.5" fill="#6E7F8C">if there were no real signal,</text>
<text x="150" y="113" font-size="10.5" fill="#6E7F8C">scores land in here</text>
<text x="455" y="250" text-anchor="middle" font-size="10.5" fill="#9AA0A6">no shuffle ever</text>
<text x="455" y="263" text-anchor="middle" font-size="10.5" fill="#9AA0A6">gets this far β</text>
<line x1="519" y1="60" x2="519" y2="320" stroke="#BC6B2E" stroke-width="2.5"/>
<circle cx="519" cy="60" r="5" fill="#BC6B2E"/>
<text x="519" y="48" text-anchor="middle" font-size="12" font-weight="700" fill="#8A4E20">real result: 0.89</text>
<text x="519" y="300" text-anchor="middle" font-size="11" font-weight="700" fill="#8A4E20">p β 0.005</text>
</svg>
```
## "How these parameters relate" chart
- Keep the neat (HTML/flex, wrapping) version already built.
- Enhancement: make each parameter NAME in the chart's pills a button that opens that parameter's ParamHelp modal (same content). So the chart becomes a map into the detailed help.
## Constraints
- Presentation-only; do not change any GP logic or other tooltips.
- One reusable `ParamHelp` component + one reusable modal; diagrams are separate small components used once each.
- Accessible: "?" is a real button (keyboard-activatable); modal has role/aria, Esc + backdrop + X close, focus trap and focus return.
- Responsive: modal scrolls on small screens; diagrams scale to container width.
- These are Client Components ("use client") since they manage open/close state.
|