Skip to content

Commit de87d7a

Browse files
committed
concept-airr-record audit, seven fixes verified end-to-end. (1) "locus · chain" row dropped the fictional "chain" field — verified that 'chain' is not in rec.keys(); kept "locus: IGH". (2) cdr3_start / cdr3_end card entries replaced with cdr3_aa (which DOES exist on records, returns None for non-productive) and junction_length — verified that cdr3_start/end aren't fields, junction_start/end are. (3) CIGAR examples 3S280M / 35M4S replaced with realistic 17D279M / 20M / 35M1I12M — verified the engine emits only M/I/D ops never S, with 5' loss surfacing as a leading D-run (e.g. 17D279M not 17S279M), and added a phr-more note documenting the M/I/D-only invariant. (4) trace address mutate.s5f.position[7] corrected to mutate.s5f.site[7] — verified trace.find('mutate.s5f.position[0]') returns None whereas mutate.s5f.site[0] returns ChoiceRecord(Int(246)) — same bug shape we already fixed in guide-trace-introspection; concept page now also mentions the paired mutate.s5f.base[k] entry. (5) PART 03 snippet was using rec.final_simulation().junction_span() — both fictional (rec is a dict from run_records so has no .final_simulation method; Simulation has no .junction_span method). rewrite uses the actual record fields rec["junction_start"] / rec["junction_end"] / rec["junction_aa"] / rec["junction_length"]; verified at seed=10 that the documented values reproduce exactly (junction_start=288, junction_end=348, junction_aa='CARITYIHTAMGFQAYFQHW', junction_length=60). (6) PART 05 prefix_query output mock "[length=5, bases[0]='A', ...]" was misrepresenting the return type — real return is an iterable of ChoiceRecord objects with .address and .value attributes — snippet now shows the actual idiom of iterating and printing rec.address + rec.value with the real output shape. (7) legacy allele names IGHV3-23*01 / IGHD3-10*01 / IGHJ4*02 (which don't exist in the shipped configs anyway) replaced everywhere on the page with the current scheme: IGHVF10-G38*04 / IGHD2-15*01 / IGHJ2*01 on the PART 04 Identity card and PART 02 ribbon, matching what seed=42 actually produces and consistent with how the same record is illustrated across lesson-1 and elsewhere on the site.
1 parent 38a5711 commit de87d7a

1 file changed

Lines changed: 38 additions & 29 deletions

File tree

website/concept-airr-record.html

Lines changed: 38 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -170,21 +170,21 @@ <h2>Birth certificate <span class="mute">vs</span> lookalike.</h2>
170170
<div class="ph-ribbon">
171171
<div class="phr-label">truth (sampled)</div>
172172
<div class="phr-track">
173-
<div class="phr-seg phr-v" style="width: 100%;">IGHV3-23*01</div>
173+
<div class="phr-seg phr-v" style="width: 100%;">IGHVF10-G38*04</div>
174174
</div>
175175
</div>
176176
<div class="ph-arrow"></div>
177177
<div class="ph-ribbon">
178178
<div class="phr-label">evidence (tie-set after SHM)</div>
179179
<div class="phr-track">
180-
<div class="phr-seg phr-d" style="width: 100%;">IGHV3-23*04, IGHV3-23*01</div>
180+
<div class="phr-seg phr-d" style="width: 100%;">IGHVF10-G38*02, IGHVF10-G38*04</div>
181181
</div>
182182
</div>
183183
</div>
184184
<p class="phr-note" style="text-align: center; margin: 10px auto 0; max-width: 720px;">
185-
Same record. The evidence caller can't tell <code>*01</code> from <code>*04</code> after the
185+
Same record. The evidence caller can't tell <code>*02</code> from <code>*04</code> after the
186186
surviving bases — both score the same — so <code>v_call</code> reports both, truth first.
187-
<code>truth_v_call</code> remembers that the actual draw was <code>*01</code>.
187+
<code>truth_v_call</code> remembers that the actual draw was <code>*04</code>.
188188
</p>
189189
</section>
190190

@@ -207,27 +207,32 @@ <h2>Locating the junction by landmarks.</h2>
207207
<div class="ph-card">
208208
<div class="ph-card-head">Anchor-driven coordinate fields</div>
209209
<ul class="pass-list">
210-
<li><span class="pass-name">junction_start / junction_end</span><span class="pass-note">first base of Cys codon · last base of anchor codon</span></li>
211-
<li><span class="pass-name">junction · junction_aa</span><span class="pass-note">nucleotide and amino-acid sequence between anchors</span></li>
212-
<li><span class="pass-name">cdr3_start / cdr3_end</span><span class="pass-note">junction minus the flanking anchor codons</span></li>
210+
<li><span class="pass-name">junction_start / junction_end</span><span class="pass-note">first base of Cys codon · last base of anchor codon (0-based, end-exclusive)</span></li>
211+
<li><span class="pass-name">junction · junction_aa</span><span class="pass-note">nucleotide and amino-acid sequence including both anchor codons</span></li>
212+
<li><span class="pass-name">cdr3_aa</span><span class="pass-note">amino-acid sequence without the flanking anchor codons (populated when productive)</span></li>
213+
<li><span class="pass-name">junction_length</span><span class="pass-note">junction_end − junction_start</span></li>
213214
</ul>
214215
</div>
215216

216217
<div class="ph-card ph-card-code">
217218
<div class="ph-card-head">Survives even heavy trim and SHM</div>
218-
<pre class="code"><code>rec = exp.<span class="c-f">run</span>(<span class="c-n">1</span>)[<span class="c-n">0</span>]
219+
<pre class="code"><code><span class="c-k">import</span> GenAIRR <span class="c-k">as</span> ga
219220

220-
<span class="c-c"># the final sequence has been:</span>
221-
<span class="c-c"># - mutated at 11 positions in V</span>
222-
<span class="c-c"># - 5'-corrupted (lost the first 28 bp)</span>
223-
<span class="c-c"># - has an indel insert at position 142</span>
224-
<span class="c-c"># the junction is STILL found correctly:</span>
221+
<span class="c-c"># even after recombination's trims have eaten into V/J,</span>
222+
<span class="c-c"># the anchor codons are tracked via per-base provenance,</span>
223+
<span class="c-c"># so junction coordinates fall out of the final pool.</span>
224+
rec = (ga.Experiment.<span class="c-f">on</span>(<span class="c-s">"human_igh"</span>)
225+
.<span class="c-f">recombine</span>()
226+
.<span class="c-f">run_records</span>(n=<span class="c-n">1</span>, seed=<span class="c-n">10</span>, expose_provenance=<span class="c-n">True</span>)).records[<span class="c-n">0</span>]
225227

226-
rec.<span class="c-f">final_simulation</span>().<span class="c-f">junction_span</span>()
227-
<span class="c-c"># (267, 309) — Cys-codon start, anchor-codon end</span>
228+
rec[<span class="c-s">"junction_start"</span>], rec[<span class="c-s">"junction_end"</span>]
229+
<span class="c-c"># (288, 348) — 0-based, end-exclusive</span>
228230

229-
rec.junction_aa
230-
<span class="c-c"># 'CARDVPYAFDIW' — anchor + payload + anchor</span></code></pre>
231+
rec[<span class="c-s">"junction_aa"</span>]
232+
<span class="c-c"># 'CARITYIHTAMGFQAYFQHW' — anchor + payload + anchor</span>
233+
234+
rec[<span class="c-s">"junction_length"</span>]
235+
<span class="c-c"># 60</span></code></pre>
231236
</div>
232237
</div>
233238
</section>
@@ -248,11 +253,11 @@ <h2>The ~70 fields, by family.</h2>
248253
<div class="phr-head">Identity & truth</div>
249254
<div class="phr-fields">
250255
<span class="phr-field"><span class="phr-k">sequence_id</span> <span class="phr-v">str</span></span>
251-
<span class="phr-field"><span class="phr-k">truth_v_call</span> <span class="phr-v">IGHV3-23*01</span></span>
252-
<span class="phr-field"><span class="phr-k">truth_d_call</span> <span class="phr-v">IGHD3-10*01</span></span>
253-
<span class="phr-field"><span class="phr-k">truth_j_call</span> <span class="phr-v">IGHJ4*02</span></span>
256+
<span class="phr-field"><span class="phr-k">truth_v_call</span> <span class="phr-v">IGHVF10-G38*04</span></span>
257+
<span class="phr-field"><span class="phr-k">truth_d_call</span> <span class="phr-v">IGHD2-15*01</span></span>
258+
<span class="phr-field"><span class="phr-k">truth_j_call</span> <span class="phr-v">IGHJ2*01</span></span>
254259
<span class="phr-field"><span class="phr-k">v_call · d_call · j_call</span> <span class="phr-v">evidence tie-set</span></span>
255-
<span class="phr-field"><span class="phr-k">locus · chain</span> <span class="phr-v">IGH · heavy</span></span>
260+
<span class="phr-field"><span class="phr-k">locus</span> <span class="phr-v">IGH</span></span>
256261
</div>
257262
</div>
258263

@@ -285,11 +290,12 @@ <h2>The ~70 fields, by family.</h2>
285290
<div class="ph-recorded" style="margin-top: 14px;">
286291
<div class="phr-head">Alignment & CIGAR</div>
287292
<div class="phr-fields">
288-
<span class="phr-field"><span class="phr-k">v_cigar</span> <span class="phr-v">3S280M</span></span>
289-
<span class="phr-field"><span class="phr-k">d_cigar</span> <span class="phr-v">12M</span></span>
290-
<span class="phr-field"><span class="phr-k">j_cigar</span> <span class="phr-v">35M4S</span></span>
293+
<span class="phr-field"><span class="phr-k">v_cigar</span> <span class="phr-v">17D279M</span></span>
294+
<span class="phr-field"><span class="phr-k">d_cigar</span> <span class="phr-v">20M</span></span>
295+
<span class="phr-field"><span class="phr-k">j_cigar</span> <span class="phr-v">35M1I12M</span></span>
291296
<span class="phr-field"><span class="phr-k">v_identity</span> <span class="phr-v">0.962</span></span>
292297
<span class="phr-field"><span class="phr-k">d_identity · j_identity</span> <span class="phr-v">float · float</span></span>
298+
<span class="phr-field phr-more">ops are M / I / D only — no S (soft-clip); 5′ loss surfaces as a leading D-run</span>
293299
</div>
294300
</div>
295301

@@ -335,7 +341,7 @@ <h2>The trace — every decision, addressable.</h2>
335341
<li><span class="pass-name">trim.v_3</span><span class="pass-note">the 3′ V trim length</span></li>
336342
<li><span class="pass-name">np.np1.length</span><span class="pass-note">the N1 region length</span></li>
337343
<li><span class="pass-name">np.np1.bases[3]</span><span class="pass-note">the 4th NP1 base drawn</span></li>
338-
<li><span class="pass-name">mutate.s5f.position[7]</span><span class="pass-note">the 8th SHM mutation location</span></li>
344+
<li><span class="pass-name">mutate.s5f.site[7]</span><span class="pass-note">the 8th SHM substitution location (paired with <code>.base[7]</code> for the new base)</span></li>
339345
</ul>
340346
</div>
341347

@@ -347,13 +353,16 @@ <h2>The trace — every decision, addressable.</h2>
347353
trace.<span class="c-f">find</span>(<span class="c-s">"sample_allele.v"</span>).value
348354
<span class="c-c"># 146 — pool index of the V allele drawn</span>
349355

350-
<span class="c-c"># every draw under a prefix</span>
351-
trace.<span class="c-f">prefix_query</span>(<span class="c-s">"np.np1"</span>)
352-
<span class="c-c"># [length=5, bases[0]='A', bases[1]='C', ...]</span>
356+
<span class="c-c"># every draw under a prefix → iterable of ChoiceRecord objects</span>
357+
<span class="c-k">for</span> rec <span class="c-k">in</span> trace.<span class="c-f">prefix_query</span>(<span class="c-s">"np.np1"</span>):
358+
<span class="c-f">print</span>(rec.address, rec.value)
359+
<span class="c-c"># np.np1.length 13</span>
360+
<span class="c-c"># np.np1.bases[0] b'C'</span>
361+
<span class="c-c"># np.np1.bases[1] b'G'</span>
353362

354363
<span class="c-c"># count the draws below a prefix</span>
355364
trace.<span class="c-f">prefix_count</span>(<span class="c-s">"mutate.s5f"</span>)
356-
<span class="c-c"># 11number of SHM substitutions in this record</span></code></pre>
365+
<span class="c-c"># 31total mutate.s5f.* records (count + per-substitution site/base entries)</span></code></pre>
357366
</div>
358367
</div>
359368
</section>

0 commit comments

Comments
 (0)