Spaces:
Sleeping
Sleeping
| # 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. | |