-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtutorial.html
More file actions
775 lines (733 loc) · 44.5 KB
/
Copy pathtutorial.html
File metadata and controls
775 lines (733 loc) · 44.5 KB
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
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
<!doctype html>
<html lang="en" data-theme="dark">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Coda Field Guide — build a connectome analysis pipeline</title>
<!-- one line, so `grep 'meta name="description"'` finds it — see index.html for why. -->
<!-- prettier-ignore -->
<meta name="description" content="A scroll-through introduction to Coda: nodes, wires, fetching data, viewers and saving workflows." />
<link rel="icon" href="./logo.svg" type="image/svg+xml" />
<link rel="apple-touch-icon" href="./apple-touch-icon.png" />
<meta name="theme-color" media="(prefers-color-scheme: light)" content="#f9f9f7" />
<meta name="theme-color" media="(prefers-color-scheme: dark)" content="#171716" />
</head>
<body>
<!-- ==========================================================================
Hero
========================================================================== -->
<header class="hero">
<div class="hero__dots" aria-hidden="true"></div>
<div class="shell hero__inner">
<div class="hero__brand">
<svg width="22" height="22" viewBox="0 0 64 64" fill="currentColor" aria-hidden="true">
<path fill-rule="evenodd" d="M32 12a18 20 0 1 0 0 40 18 20 0 1 0 0-40Zm0 3.6a12.24 16.4 0 1 1 0 32.8 12.24 16.4 0 1 1 0-32.8Z"/>
<rect x="30" y="5" width="4" height="54" rx="2"/>
<rect x="7" y="30" width="50" height="4" rx="2"/>
</svg>
<span>Coda · Field guide</span>
<span class="hero__tag">Beta</span>
</div>
<h1>Next Generation Connectomics Analysis <em>in the Browser</em></h1>
<p class="hero__sub">
A browser-based node editor for connectome data. Wire up the steps — query, traverse,
filter, aggregate, plot — and each one shows its result where it sits.
</p>
<div class="hero__meta">
<span>hemibrain · MANC · optic‑lobe · male‑CNS</span>
<span>no install, no notebook</span>
<span>~10 minutes</span>
</div>
<div class="scrollcue"><span class="scrollcue__line"></span>Scroll — the graph builds itself</div>
</div>
</header>
<!-- ==========================================================================
The build. One canvas, five chapters, one node added per chapter.
The pipeline is a real one: which central-brain cells do lobula columnar
neurons drive, ranked by synapse count.
========================================================================== -->
<main class="shell build" id="build">
<div class="build__stage">
<div class="stage" id="stage" data-beat="0" data-pending="true">
<div class="stage__bar">
<strong>LC outputs by partner type</strong>
<span class="stage__spacer"></span>
<span class="stage__run" id="stagerun">▶ Run 1</span>
</div>
<div class="world" id="world">
<svg class="wires" id="wires" viewBox="0 0 1300 440" aria-hidden="true"></svg>
<!-- 1 · Dataset ------------------------------------------------------ -->
<div class="node" data-cat="dataset" data-from="1" data-key="ds" data-state="ok"
style="left:20px; top:168px; width:150px;">
<svg class="ring" aria-hidden="true"><rect pathLength="1"/></svg>
<div class="node__head"><span class="node__title">Hemibrain</span><span class="node__play">▶</span></div>
<div class="node__ports">
<div class="port">
<span class="port__in"></span>
<span class="port__out">Dataset<i class="sock sock--out" data-fam="dataset" data-shape="square" id="s-ds-out"></i></span>
</div>
</div>
<div class="node__params">
<div class="prow"><span>Version</span><b class="is-picker">Latest (v1.2.1)</b></div>
</div>
<div class="node__foot"><span>hemibrain:v1.2.1</span></div>
</div>
<!-- 2 · Find Neurons ------------------------------------------------- -->
<div class="node" data-cat="query" data-from="0" data-key="find" data-state="blocked"
style="left:228px; top:136px; width:170px;">
<svg class="ring" aria-hidden="true"><rect pathLength="1"/></svg>
<div class="node__head"><span class="node__title">Find Neurons</span><span class="node__play">▶</span></div>
<div class="node__ports">
<div class="port">
<span class="port__in">Dataset<i class="sock sock--in" data-fam="dataset" data-shape="square" id="s-find-in"></i></span>
<span class="port__out">Neurons<i class="sock sock--out" data-fam="table" data-shape="circle" id="s-find-out"></i></span>
</div>
</div>
<div class="node__params">
<div class="prow"><span>Type</span><b>^LC\d+$</b></div>
<div class="prow"><span>Status</span><b class="is-picker">Traced</b></div>
</div>
<div class="node__foot"><span data-foot="find">— · no Dataset connected</span></div>
</div>
<!-- 3 · Connectivity ------------------------------------------------- -->
<div class="node" data-cat="query" data-from="1" data-key="conn" data-state="ok"
style="left:456px; top:136px; width:176px;">
<svg class="ring" aria-hidden="true"><rect pathLength="1"/></svg>
<div class="node__head"><span class="node__title">Connectivity</span><span class="node__play">▶</span></div>
<div class="node__ports">
<div class="port">
<span class="port__in">Dataset<i class="sock sock--in" data-fam="dataset" data-shape="square" id="s-conn-in-ds"></i></span>
<span class="port__out">Table<i class="sock sock--out" data-fam="table" data-shape="ring" id="s-conn-out"></i></span>
</div>
<div class="port">
<span class="port__in">Neurons<i class="sock sock--in" data-fam="table" data-shape="circle" id="s-conn-in-n"></i></span>
<span class="port__out"></span>
</div>
</div>
<div class="node__params">
<div class="prow"><span>Direction</span><b class="is-picker">downstream</b></div>
<div class="prow"><span>Hops</span><b>1</b></div>
</div>
<div class="node__foot"><span data-foot="conn">— · not run yet</span></div>
</div>
<!-- 4 · Filter ------------------------------------------------------- -->
<div class="node" data-cat="transform" data-from="3" data-key="filt" data-state="ok"
style="left:690px; top:162px; width:150px;">
<div class="node__head"><span class="node__title">Filter</span><span class="node__play">▶</span></div>
<div class="node__ports">
<div class="port">
<span class="port__in">Table<i class="sock sock--in" data-fam="table" data-shape="ring" id="s-filt-in"></i></span>
<span class="port__out">Table<i class="sock sock--out" data-fam="table" data-shape="ring" id="s-filt-out"></i></span>
</div>
</div>
<div class="node__params">
<div class="prow"><span>Column</span><b class="is-picker">weight</b></div>
<div class="prow"><span>Keep</span><b>≥ 10</b></div>
</div>
<div class="node__foot"><span>6,431 rows</span></div>
</div>
<!-- 5 · Group By ----------------------------------------------------- -->
<div class="node" data-cat="transform" data-from="3" data-key="grp" data-state="ok"
style="left:896px; top:144px; width:162px;">
<div class="node__head"><span class="node__title">Group By</span><span class="node__play">▶</span></div>
<div class="node__ports">
<div class="port">
<span class="port__in">Table<i class="sock sock--in" data-fam="table" data-shape="ring" id="s-grp-in"></i></span>
<span class="port__out">Table<i class="sock sock--out" data-fam="table" data-shape="ring" id="s-grp-out"></i></span>
</div>
</div>
<div class="node__params">
<div class="prow"><span>Group by</span><b class="is-picker">postType</b></div>
<div class="prow"><span>Aggregate</span><b class="is-picker">sum(weight)</b></div>
</div>
<div class="node__foot"><span>214 rows</span></div>
</div>
<!-- 6 · Bar Chart ---------------------------------------------------- -->
<div class="node" data-cat="visualisation" data-from="4" data-key="chart" data-state="ok"
style="left:1104px; top:112px; width:186px;">
<div class="node__head"><span class="node__title">Bar Chart</span><span class="node__play">▶</span></div>
<div class="node__ports">
<div class="port">
<span class="port__in">Table<i class="sock sock--in" data-fam="table" data-shape="ring" id="s-chart-in"></i></span>
<span class="port__out">Table<i class="sock sock--out" data-fam="table" data-shape="ring"></i></span>
</div>
</div>
<div class="mini">
<i style="--h:88%; --i:0"></i><i style="--h:61%; --i:1"></i><i style="--h:50%; --i:2"></i><i style="--h:37%; --i:3"></i><i style="--h:26%; --i:4"></i>
</div>
<div class="mini-axis"><span>DNp01</span><span>DNp02</span><span>DNp04</span><span>DNp03</span><span>DNp11</span></div>
<div class="node__foot"><span>214 bars · sum(weight)</span></div>
</div>
<!-- Anatomy callouts, chapter 1 only -->
<div class="callout" data-side="l" style="left:48px; top:142px; width:150px; --lead:30px;">what this step does</div>
<div class="callout" data-side="r" style="left:428px; top:142px; --lead:30px;">Run — this node only</div>
<div class="callout" data-side="l" style="left:48px; top:171px; width:150px; --lead:30px;">inputs</div>
<div class="callout" data-side="r" style="left:428px; top:171px; --lead:30px;">outputs</div>
<div class="callout" data-side="r" style="left:428px; top:213px; --lead:30px;">parameters</div>
<div class="callout" data-side="l" style="left:48px; top:253px; width:150px; --lead:30px;">last result</div>
</div>
<!--
Chapter 3. The toolbar is chrome rather than part of the world, so the
camera cannot reach it: this draws the cluster the Run button sits in
over a dimmed canvas instead.
-->
<div class="detail" aria-hidden="true">
<div class="detail__bar">
<span class="tb">Clear</span>
<span class="tb">+ Add <b>Tab</b></span>
<span class="tb">Commands <b>Space</b></span>
<label class="tb tb--check"><i></i> Auto-run</label>
<span class="tb tb--run" data-ring="">▶ Run 2 <b>⇧R</b></span>
</div>
<span class="detail__cap">the whole graph — everything stale, in order</span>
<span class="detail__or">or</span>
<div class="detail__node">
<span>Connectivity</span>
<span class="tb tb--play" data-ring="">▶</span>
</div>
<span class="detail__cap">one node, and only what it depends on</span>
</div>
</div>
</div>
<div class="beats">
<article class="beat" data-beat="0">
<span class="beat__n">Chapter 1</span>
<h2>A node is one step</h2>
<p>
Every step is a card. <code>Find Neurons</code> runs one query: match a type pattern
against a dataset. Here, traced lobula columnar cells — <code>^LC\d+$</code>.
</p>
<p>
Inputs left, outputs right, parameters between them,
the last result along the bottom. <strong>▶</strong> in the header runs this node and
whatever is upstream of it.
</p>
<p>
The stripe down the left edge is run state. Grey here because the
<span class="ty ty--dataset">Dataset</span> input is empty, so there is nothing to run yet.
</p>
</article>
<article class="beat" data-beat="1">
<span class="beat__n">Chapter 2</span>
<h2>Sockets are typed</h2>
<p>
A link carries a typed value, not a file. Each socket declares what it accepts, so a link
that cannot work is refused as you drag it.
</p>
<div class="fig">
<div class="legend">
<div class="legend__row"><span class="swatch"><i class="sock" data-fam="dataset" data-shape="square"></i></span> <b class="ty ty--dataset">Dataset</b> — a connectome at a version</div>
<div class="legend__row"><span class="swatch"><i class="sock" data-fam="table" data-shape="circle"></i></span> <b class="ty ty--table">Neurons</b> — a table guaranteed to carry <code>neuronId</code></div>
<div class="legend__row"><span class="swatch"><i class="sock" data-fam="table" data-shape="ring"></i></span> <b class="ty ty--table">Table</b> — any rows and columns</div>
<div class="legend__row"><span class="swatch"><i class="sock" data-fam="matrix" data-shape="diamond"></i></span> <b class="ty ty--matrix">Matrix</b> — rows × columns of numbers</div>
<div class="legend__row"><span class="swatch swatch--set"><i class="sock" data-fam="geometry" data-shape="circle"></i><i class="sock" data-fam="geometry" data-shape="hex"></i><i class="sock" data-fam="geometry" data-shape="dot"></i></span> <b class="ty ty--geometry">Geometries</b> — skeletons, meshes and point clouds, drawn in 3D</div>
<div class="legend__row"><span class="swatch"><i class="sock" data-fam="transform" data-shape="diamond"></i></span> <b class="ty ty--transform">Transform</b> — a mapping between template spaces</div>
<div class="legend__row"><span class="swatch"><i class="sock" data-fam="layers" data-shape="ring"></i></span> <b class="ty ty--layers">Layers</b> — extra neuroglancer layers to draw alongside</div>
</div>
<p class="fig__cap">
Colour names the <b>material</b> and shape separates the members within it, so a shape repeats
<em>across</em> materials and never inside one: a skeleton and a table of Neurons are
both filled circles, Matrix and Transform both diamonds, the hue says which. One
material can hold several shapes — the three marks above are all Geometries.
</p>
</div>
</article>
<article class="beat" data-beat="2">
<span class="beat__n">Chapter 3</span>
<h2>Execution model</h2>
<p>
Each node has a cost. <strong>Cheap</strong> ones — <code>Filter</code>,
<code>Sort</code>, <code>Group By</code> — re-run automatically after you
edited them. <strong>Expensive</strong> nodes query e.g. a backend and go <em>stale</em> instead.
</p>
<p>
<strong>Run</strong> (<kbd>⇧R</kbd>) executes everything stale, in dependency order.
<strong>▶</strong> on the card itself executes that node and only its upstream. Both report
progress as a gold ring round the card.
</p>
<p>
<strong>Auto-run</strong> means every edit re-runs the whole graph, expensive nodes included.
On by default but can be turned off, so an expensive workflow is under your control.
</p>
<p>
<strong>Clear</strong> removes all results, so you can start over. It does not remove any nodes or wiring.
Also worth trying if a node is stuck in e.g. an error.
</p>
</article>
<article class="beat" data-beat="3">
<span class="beat__n">Chapter 4</span>
<h2>A node for every question</h2>
<p>
Coda provides nodes for complex operations such as <code>Find Neurons</code>,
<code>Connectivity</code>, <code>Paths</code> or <code>Skeletons</code>, and
primitives for basic data processing steps - e.g. <code>Filter</code>, <code>Group By</code>,
<code>Join</code>, <code>Pivot</code> and so on.
</p>
<p>
Use the "<strong>+</strong>" button to add new nodes, or press <kbd>Tab</kbd> to open the node browser.
Search, category chips, and a <strong>port signature</strong> on every row, so you can
see what a node takes and returns before inserting it.
</p>
<div class="surface" style="margin-top:.35rem">
<div class="surface__bar"><strong>Add a node</strong><span>Tab</span></div>
<div class="explore__search">
<span style="color:var(--text-muted)">⚲</span>
<span class="q">netw</span><span class="caret"></span>
<span class="explore__count">3 of 41</span>
</div>
<div class="browser__chips">
<span class="cchip" data-on="true">All</span><span class="cchip">Dataset</span><span class="cchip">Query</span><span class="cchip">Transform</span><span class="cchip">Analysis</span><span class="cchip">Output</span>
</div>
<div class="brow">
<span class="brow__thumb" style="--c:var(--cat-analysis)"><i></i></span>
<span class="brow__main"><span class="brow__name">Build Network</span><span class="brow__sig">Table → Network · cheap</span></span>
</div>
<div class="brow">
<span class="brow__thumb" style="--c:var(--cat-visualisation)"><i></i></span>
<span class="brow__main"><span class="brow__name">Network Viewer</span><span class="brow__sig">Network + Layout → Network, Selected</span></span>
</div>
<div class="brow">
<span class="brow__thumb" style="--c:var(--cat-query)"><i></i></span>
<span class="brow__main"><span class="brow__name">Connectivity</span><span class="brow__sig">Dataset + Neurons → Table · needs Run</span></span>
</div>
</div>
<p class="fig__cap">
<kbd>Space</kbd> is the same set as a compact palette, plus every command. Drag a wire into
empty canvas and the list narrows to what accepts it — then wires up your pick.
</p>
</article>
<article class="beat" data-beat="4">
<span class="beat__n">Chapter 5</span>
<h2>Viewers are interactive</h2>
<p>
<code>Bar Chart</code> draws the table and passes <em>the same table on</em>, so a viewer
drops into the middle of a chain without breaking it. <code>Table</code>,
<code>Heatmap</code>, <code>Scatter Plot</code>, <code>Network Viewer</code>,
<code>3D Viewer</code> and an embedded neuroglancer all behave this way.
</p>
<p>
Several also emit a selection. Lasso points in <code>Scatter Plot</code>, click nodes in
<code>Network Viewer</code>: the picked rows leave by a <b class="ty ty--table">Selected</b> output
and wire onward like anything else.
</p>
<div class="surface" style="margin-top:.35rem">
<div class="surface__bar"><strong>Scatter Plot</strong><span>pre × post · colour by class</span></div>
<div class="plot">
<svg viewBox="0 0 320 176" role="img" aria-label="Scatter plot with a lassoed group of points highlighted">
<g class="plot__grid"><path d="M40 8V152M40 152H312M40 116H312M40 80H312M40 44H312"/></g>
<g class="plot__axis"><path d="M40 152H312M40 8V152"/></g>
<path class="plot__lasso" d="M196 26 244 18 288 44 280 84 232 96 194 70Z"/>
<g class="plot__pt">
<circle cx="58" cy="140" r="3"/><circle cx="70" cy="132" r="3"/><circle cx="66" cy="146" r="3"/>
<circle cx="84" cy="126" r="3"/><circle cx="92" cy="138" r="3"/><circle cx="102" cy="118" r="3"/>
<circle cx="112" cy="130" r="3"/><circle cx="120" cy="110" r="3"/><circle cx="128" cy="124" r="3"/>
<circle cx="138" cy="104" r="3"/><circle cx="146" cy="118" r="3"/><circle cx="154" cy="96" r="3"/>
<circle cx="162" cy="112" r="3"/><circle cx="170" cy="88" r="3"/><circle cx="178" cy="102" r="3"/>
<circle cx="186" cy="120" r="3"/><circle cx="196" cy="94" r="3"/><circle cx="206" cy="110" r="3"/>
<circle cx="216" cy="128" r="3"/><circle cx="228" cy="116" r="3"/><circle cx="240" cy="132" r="3"/>
<circle cx="252" cy="120" r="3"/><circle cx="266" cy="138" r="3"/><circle cx="284" cy="126" r="3"/>
<circle cx="296" cy="144" r="3"/><circle cx="88" cy="150" r="3"/><circle cx="132" cy="142" r="3"/>
<circle cx="176" cy="136" r="3"/>
</g>
<g class="plot__pt" data-picked="true">
<circle cx="212" cy="42" r="3.4"/><circle cx="224" cy="34" r="3.4"/><circle cx="238" cy="46" r="3.4"/>
<circle cx="250" cy="30" r="3.4"/><circle cx="246" cy="62" r="3.4"/><circle cx="262" cy="52" r="3.4"/>
<circle cx="228" cy="66" r="3.4"/><circle cx="266" cy="72" r="3.4"/><circle cx="272" cy="40" r="3.4"/>
<circle cx="210" cy="58" r="3.4"/>
</g>
<text class="plot__lab" x="40" y="166">0</text>
<text class="plot__lab" x="292" y="166">4,000 pre</text>
<text class="plot__lab" x="6" y="16">post</text>
</svg>
</div>
<div class="node__foot" style="border-top:1px solid var(--border)"><span>1,704 points · 10 selected</span><span>⇧drag to lasso</span></div>
</div>
<p class="fig__cap">
A selection is an ordinary param: it lands in the saved file and in every downstream
provenance key. Picking by eye is a step, not a detour out of the pipeline.
</p>
</article>
<article class="beat" data-beat="5">
<span class="beat__n">Chapter 6</span>
<h2>Save it, send it</h2>
<p>
A workflow is a simple JSON file that captures every step, every parameter.
<strong>Save ▸ Download</strong> writes it as a <code>.coda.json</code>.
<strong>Save ▸ Save</strong> stores it in your browser’s local storage,
so you can close the tab and come back later. <strong>Share</strong>
</p>
<p>
A workflow file never contains data/results or your credentials! Whoever opens it gets this pipeline
exactly as you left it, presses Run, and can move a threshold to see what changes.
</p>
</article>
</div>
</main>
<!-- ==========================================================================
Chapter 7 · Explore Dataset feeding Neuron Profile
========================================================================== -->
<section class="chapter">
<div class="shell">
<div class="chapter__head rise">
<span class="beat__n">Chapter 7</span>
<h2>Exploring a connectome</h2>
<p class="lede">
Connectomes are complex datasets. Coda provides a few simple widgets to get started.
</p>
</div>
<div class="stack" style="margin-bottom: clamp(1.75rem, 4vh, 2.75rem);">
<div class="split">
<div class="point rise">
<h3><code>Explore Dataset</code> enables fuzzy search</h3>
<p>
A dataset’s whole neuron table is downloaded once and searched locally. Type something into
the search box and the table filters down to matching rows. Alternatively, use the
simple query language to match on specific columns: <code>type==LC4</code>. Regex also
works: <code>type~^LC[0-9]+$</code>. Select neurons of interest to send them downstream into
your analysis.
</p>
</div>
<div class="point rise" data-delay="1">
<h3><code>Find Neurons</code> for structured search</h3>
<p>
Define and combine filters on any column, and the table updates in real time.
Where the backend supports it, this will run a live query and return the results.
Otherwise, it will filter the local table.
</p>
</div>
</div>
<div class="split">
<div class="point rise" data-delay="2" style="max-width:var(--measure)">
<h3><code>Dataset Summary</code> provides a birds-eye view</h3>
<p>
This nodes summarizes the dataset: annotations, neuron counts, completion rate, etc.
What is shown depends on what the dataset publishes.
</p>
</div>
<div class="point rise" data-delay="2" style="max-width:var(--measure)">
<h3><code>Neuron Profile</code> provides neuron-level summaries</h3>
<p>
Identity, transmitter, synapse totals, strongest partners, the per‑ROI split and the
morphology — one neuron at a time. Page through a collection freely; pin one and it
leaves by <b class="ty ty--table">Current</b>.
</p>
</div>
</div>
</div>
<!-- The two widgets as they sit on a canvas: one feeding the other. -->
<div class="pipe rise" data-delay="1">
<div class="surface">
<div class="surface__bar"><strong>Explore Dataset</strong><span>hemibrain:v1.2.1</span></div>
<div class="explore__search">
<span style="color:var(--text-muted)">⚲</span>
<span class="q">LC4</span><span class="caret"></span>
<span class="explore__count">68 hits</span>
</div>
<div class="explore__rows">
<div class="row" data-picked="true">
<span class="row__tick">✓</span>
<span class="row__thumb"><svg viewBox="0 0 46 38" width="46" height="38" aria-hidden="true"><g fill="none" stroke="var(--text-secondary)" stroke-width="1.1" stroke-linecap="round"><polyline points="8,32 14,24 20,16 26,10"/><polyline points="14,24 9,19"/><polyline points="20,16 26,18"/><polyline points="26,10 32,6"/><polyline points="26,10 31,13"/></g><circle cx="8" cy="32" r="2.6" fill="var(--text-secondary)"/></svg></span>
<span class="row__main">
<span class="row__name">LC4 <span class="row__id">1722342154</span></span>
<span class="row__chips"><i class="chip" data-slot="1">visual projection</i><i class="chip" data-slot="5">soma R</i><i class="chip" data-slot="3">Traced</i><i class="chip" data-slot="4">acetylcholine</i></span>
</span>
</div>
<div class="row" data-picked="true">
<span class="row__tick">✓</span>
<span class="row__thumb"><svg viewBox="0 0 46 38" width="46" height="38" aria-hidden="true"><g fill="none" stroke="var(--text-secondary)" stroke-width="1.1" stroke-linecap="round"><polyline points="9,31 15,23 22,17 29,12"/><polyline points="15,23 11,17"/><polyline points="22,17 27,21"/><polyline points="29,12 35,9"/></g><circle cx="9" cy="31" r="2.6" fill="var(--text-secondary)"/></svg></span>
<span class="row__main">
<span class="row__name">LC4 <span class="row__id">1691981778</span></span>
<span class="row__chips"><i class="chip" data-slot="1">visual projection</i><i class="chip" data-slot="5">soma R</i><i class="chip" data-slot="3">Traced</i><i class="chip" data-slot="4">acetylcholine</i></span>
</span>
</div>
<div class="row">
<span class="row__tick">✓</span>
<span class="row__thumb"><svg viewBox="0 0 46 38" width="46" height="38" aria-hidden="true"><g fill="none" stroke="var(--text-secondary)" stroke-width="1.1" stroke-linecap="round"><polyline points="10,30 16,22 23,18 30,11"/><polyline points="16,22 12,26"/><polyline points="23,18 28,22"/><polyline points="30,11 36,12"/></g><circle cx="10" cy="30" r="2.6" fill="var(--text-secondary)"/></svg></span>
<span class="row__main">
<span class="row__name">LC4 <span class="row__id">1660633120</span></span>
<span class="row__chips"><i class="chip" data-slot="1">visual projection</i><i class="chip" data-slot="5">soma L</i><i class="chip" data-slot="3">Traced</i><i class="chip" data-slot="4">acetylcholine</i></span>
</span>
</div>
<div class="row">
<span class="row__tick">✓</span>
<span class="row__thumb"><svg viewBox="0 0 46 38" width="46" height="38" aria-hidden="true"><g fill="none" stroke="var(--text-secondary)" stroke-width="1.1" stroke-linecap="round"><polyline points="8,33 15,25 21,15 28,9"/><polyline points="21,15 16,12"/><polyline points="28,9 34,11"/></g><circle cx="8" cy="33" r="2.6" fill="var(--text-secondary)"/></svg></span>
<span class="row__main">
<span class="row__name">LC4 <span class="row__id">1629482093</span></span>
<span class="row__chips"><i class="chip" data-slot="1">visual projection</i><i class="chip" data-slot="5">soma L</i><i class="chip" data-slot="3">Traced</i><i class="chip" data-slot="4">acetylcholine</i></span>
</span>
</div>
</div>
<div class="explore__ports">
<div class="explore__port"><b><i class="sock" data-fam="table" data-shape="circle"></i>Hits</b><span>68 rows</span></div>
<div class="explore__port" data-wired="true"><b><i class="sock" data-fam="table" data-shape="circle"></i>Selected</b><span>2 rows</span></div>
<div class="explore__port"><b><i class="sock" data-fam="table" data-shape="circle"></i>All</b><span>the whole index</span></div>
</div>
</div>
<div class="pipe__link" aria-hidden="true">
<em>Selected</em>
<svg viewBox="0 0 78 74" width="78" height="74">
<path d="M0 37H64"/>
<polygon class="head" points="63,31.5 75,37 63,42.5"/>
</svg>
</div>
<div class="surface">
<div class="surface__bar">
<i class="sock" data-fam="table" data-shape="circle" style="position:static;transform:none"></i>
<strong>Neuron Profile</strong><span>2 of 2 ‹ ›</span>
</div>
<div style="display:grid; grid-template-columns:1fr 1fr; gap:1px; background:var(--border);">
<div style="background:var(--surface-2); padding:11px 13px; display:grid; gap:3px;">
<span style="font-family:var(--font-mono); font-size:10px; letter-spacing:.1em; text-transform:uppercase; color:var(--text-muted)">Identity</span>
<b style="font-size:15px; letter-spacing:-.02em">LC4</b>
<span style="font-family:var(--font-mono); font-size:11px; color:var(--text-muted)">1722342154 · soma R</span>
</div>
<div style="background:var(--surface-2); padding:11px 13px; display:grid; gap:3px;">
<span style="font-family:var(--font-mono); font-size:10px; letter-spacing:.1em; text-transform:uppercase; color:var(--text-muted)">Synapses</span>
<b style="font-size:15px; letter-spacing:-.02em; font-variant-numeric:tabular-nums">1,043 <span style="font-size:11px; color:var(--text-muted); font-weight:400">pre</span> · 2,388 <span style="font-size:11px; color:var(--text-muted); font-weight:400">post</span></b>
<span style="font-family:var(--font-mono); font-size:11px; color:var(--text-muted)">acetylcholine</span>
</div>
<div style="background:var(--surface-2); padding:11px 13px; display:grid; gap:5px;">
<span style="font-family:var(--font-mono); font-size:10px; letter-spacing:.1em; text-transform:uppercase; color:var(--text-muted)">Top outputs</span>
<span style="font-family:var(--font-mono); font-size:11px; display:flex; justify-content:space-between"><span>DNp01</span><span style="color:var(--text-muted)">148</span></span>
<span style="font-family:var(--font-mono); font-size:11px; display:flex; justify-content:space-between"><span>DNp02</span><span style="color:var(--text-muted)">96</span></span>
<span style="font-family:var(--font-mono); font-size:11px; display:flex; justify-content:space-between"><span>DNp04</span><span style="color:var(--text-muted)">71</span></span>
</div>
<div style="background:var(--surface-2); padding:11px 13px; display:grid; gap:5px;">
<span style="font-family:var(--font-mono); font-size:10px; letter-spacing:.1em; text-transform:uppercase; color:var(--text-muted)">By region</span>
<span style="font-family:var(--font-mono); font-size:11px; display:flex; justify-content:space-between"><span>PVLP(R)</span><span style="color:var(--text-muted)">61%</span></span>
<span style="font-family:var(--font-mono); font-size:11px; display:flex; justify-content:space-between"><span>LO(R)</span><span style="color:var(--text-muted)">33%</span></span>
<span style="font-family:var(--font-mono); font-size:11px; display:flex; justify-content:space-between"><span>PLP(R)</span><span style="color:var(--text-muted)">6%</span></span>
</div>
</div>
<div class="node__foot" style="border-top:1px solid var(--border)"><span>Current → the pinned neuron</span></div>
</div>
</div>
</div>
</section>
<!-- ==========================================================================
Chapter 8 · Live data
========================================================================== -->
<section class="chapter">
<div class="shell">
<div class="chapter__head rise">
<span class="beat__n">Chapter 8</span>
<h2>Point it at a real connectome</h2>
<p class="lede">
Coda does not host any connectomes itself. Instead, we fetch the data from the primary
sources, such as <a href="https://neuprint.janelia.org">neuprint.janelia.org</a>.
</p>
</div>
<div class="split">
<div class="stack">
<div class="point rise">
<h3>Login or paste a token once</h3>
<p>
Even public connectome datasets often require you to make an account.
When trying to access them via Coda, you will be prompted to either log in with
the same account or paste an authentication token.
</p>
</div>
<div class="point rise" data-delay="1">
<h3>Credentials stay in this browser</h3>
<p>
Held in local storage, never sent to a third party or written into a saved workflow.
A <code>.coda.json</code> you send a colleague carries the analysis and not your
credentials.
</p>
</div>
<div class="point rise" data-delay="2">
<h3>Multiple nodes per dataset</h3>
<p>
Some datasets are hosted on multiple backends. For example, the public release of the
FlyWire dataset is available via both neuPrint and CAVE. Coda supports both but note that
each of these backends has slightly different data and capabilities.
</p>
</div>
<div class="point rise" data-delay="3">
<h3>Credit comes attached</h3>
<p>
Every published dataset node arrives with a <code>Description</code> card wired to it:
what the dataset covers and the papers its authors ask you to cite. Delete it if you
like but please do not forget to give credit where it is due.
</p>
</div>
</div>
<div class="stack">
<div class="surface rise" data-delay="1">
<div class="surface__bar"><strong>Connections</strong><span>neuPrint</span></div>
<div class="field">
<label for="tok">Token</label>
<div class="input" id="tok" data-filled="true">eyJhbGciOiJSUzI1NiIsImtpZCI6IjNkZTgw…</div>
</div>
<div class="btnrow">
<span class="btn-m" data-primary="true">Test</span>
<span class="btn-m">Forget</span>
</div>
<div class="ok-line"><span class="dot-ok"></span>connected · 6 datasets</div>
<div class="dsgrid">
<div class="dscard"><b>Hemibrain</b><span>v1.2.1</span></div>
<div class="dscard"><b>MANC</b><span>v1.2.3</span></div>
<div class="dscard"><b>Optic Lobe</b><span>v1.1</span></div>
<div class="dscard"><b>MaleCNS</b><span>v1.0</span></div>
</div>
</div>
<p class="fig__cap rise" data-delay="2" style="max-width:30rem">
Each type of backend requires a different token. Coda will prompt you the first time
you try to access a dataset, and then store it in local storage for future sessions.
</p>
</div>
</div>
</div>
</section>
<!-- ==========================================================================
Chapter 9 · Getting around
========================================================================== -->
<section class="chapter">
<div class="shell">
<div class="chapter__head rise">
<span class="beat__n">Chapter 9</span>
<h2>Getting around the canvas</h2>
<p class="lede">
Everything can be done with the mouse, but keyboard shortcuts speed up the workflow.
For power-users: <kbd>Space</kbd> brings up a command palette.
</p>
</div>
<div class="split">
<div class="stack">
<div class="rise">
<div class="keys">
<div class="keyrow"><kbd>Space</kbd><span>Commands and nodes, fuzzy‑searched</span></div>
<div class="keyrow"><kbd>Tab</kbd><span>Browse all nodes, with previews</span></div>
<div class="keyrow"><kbd>⇧R</kbd><span>Run everything that is stale</span></div>
<div class="keyrow"><kbd>I</kbd><span>Show or hide the inspector</span></div>
<div class="keyrow"><kbd>H</kbd><span>Collapse the selected cards</span></div>
<div class="keyrow"><kbd>M</kbd><span>Mute the selection</span></div>
<div class="keyrow"><kbd>⌘D</kbd><span>Duplicate the selection</span></div>
<div class="keyrow"><kbd>⌘Z</kbd><span>Undo — including a drag, back to where it began</span></div>
</div>
</div>
<p class="fig__cap rise" data-delay="1" style="max-width:32rem">
Initials work in the palette: <b>ra</b> → Run All, <b>gb</b> → Group By.
</p>
</div>
<div class="stack">
<div class="gestures rise" data-delay="1">
<div class="gesture">
<svg width="34" height="26" viewBox="0 0 34 26" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" aria-hidden="true"><path d="M4 13h26M4 13l4-4M4 13l4 4M30 13l-4-4M30 13l-4 4"/></svg>
<span><strong>Drag</strong> pans. Panning is the common gesture, so it is the bare one.</span>
</div>
<div class="gesture">
<svg width="34" height="26" viewBox="0 0 34 26" fill="none" stroke="currentColor" stroke-width="1.4" aria-hidden="true"><rect x="5" y="5" width="24" height="16" rx="2" stroke-dasharray="3 3"/></svg>
<span><strong>⇧ + drag</strong> draws a selection box.</span>
</div>
<div class="gesture">
<svg width="34" height="26" viewBox="0 0 34 26" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" aria-hidden="true"><circle cx="17" cy="13" r="7"/><path d="M17 9v8M13 13h8"/></svg>
<span><strong>Scroll</strong> zooms. <strong>Double‑click</strong> empty canvas adds a node there.</span>
</div>
<div class="gesture">
<svg width="34" height="26" viewBox="0 0 34 26" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" aria-hidden="true"><circle cx="6" cy="13" r="3" fill="currentColor" stroke="none"/><path d="M9 13c6 0 6-7 12-7"/><circle cx="24" cy="6" r="3"/><path d="M9 14c5 3 8 5 14 5"/></svg>
<span><strong>Drag a wire into empty space</strong> for a list filtered to what accepts it — your pick arrives wired.</span>
</div>
<div class="gesture">
<svg width="34" height="26" viewBox="0 0 34 26" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" aria-hidden="true"><path d="M4 18c8 0 10-10 18-10"/><path d="M20 4l4 4-4 4" stroke-linejoin="round"/></svg>
<span><strong>Drag either end of a wire off its socket</strong> to re-route; right‑click it for a menu. A drop on a socket that refuses snaps back rather than cutting the link.</span>
</div>
<div class="gesture">
<svg width="34" height="26" viewBox="0 0 34 26" fill="none" stroke="currentColor" stroke-width="1.4" aria-hidden="true"><rect x="4" y="6" width="26" height="14" rx="2"/><path d="M4 11h26" stroke-width="1.2"/></svg>
<span>The corner controls <strong>auto-arrange</strong> the graph left to right, once or continuously.</span>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- ==========================================================================
Chapter 10 · Keeping it
========================================================================== -->
<section class="chapter">
<div class="shell">
<div class="chapter__head rise">
<span class="beat__n">Chapter 10</span>
<h2>Where a workflow goes</h2>
<p class="lede">Four places, and one of them has strings attached.</p>
</div>
<div class="cards2 rise">
<div class="savecard" data-durable="true">
<span class="savecard__tag">Save ▸ Download · durable</span>
<h3>A <code>.coda.json</code> file</h3>
<p>
Plain JSON — put it in a repository, a supplement, an email, and
reproduces the pipeline wherever it lands. Results are not in it: the recipe, not the meal.
</p>
</div>
<div class="savecard">
<span class="savecard__tag">Save ▸ In this browser · convenient</span>
<h3>The browser shelf</h3>
<p>
A named copy in this machine, listed under <em>Open</em> and on the start page.
Good for picking up where you left off.
</p>
<p>
<strong>Not a backup!</strong> Per browser and per profile, not synced, empty in a private
window, and cleared with the site data. Anything you would be sorry to lose, download.
</p>
</div>
</div>
<div class="cards2 rise">
<div class="savecard" data-durable="true">
<span class="savecard__tag">Share workflow ▸ Copy to clipboard</span>
<h3>A workflow link</h3>
<p>
The JSON encoded into a shareable link. Paste it into an email or a chat,
or just save it in a note for yourself.
</p>
</div>
<div class="savecard">
<span class="savecard__tag">Save ▸ In this browser · convenient</span>
<h3>The data</h3>
<p>
A workflow file never contains results. If you want to keep the outputs you
have to download them as CSV, SVG, PNG, etc. via the either the
<strong>Download button</strong> in a node's footer, or via the dedicated
<strong>Download node</strong>.
</p>
</div>
</div>
</div>
</section>
<!-- ==========================================================================
Outro
========================================================================== -->
<section class="outro">
<div class="shell">
<h2 class="rise">Open it and add one node.</h2>
<p class="rise" data-delay="1">
Nothing to install, and the demo data needs no accounts. Start from one, take it
apart, point it at your own question.
</p>
<div class="outro__actions rise" data-delay="2">
<a class="cta" data-primary="true" href="https://navis-org.github.io/coda/" target="_blank" rel="noreferrer noopener">Open Coda</a>
<!-- The reference half of the pair: this page teaches the model, that one answers
"what does this node do". Relative, so it works from a subpath deploy. -->
<a class="cta" href="./nodes.html">Node guide</a>
<a class="cta" href="https://github.com/navis-org/coda" target="_blank" rel="noreferrer noopener">Source and docs</a>
<a class="cta" href="https://github.com/navis-org/coda/issues" target="_blank" rel="noreferrer noopener">Report something</a>
</div>
<p class="rise" data-delay="3" style="margin-top:2.25rem; font-size:.92rem;">
Coda is in beta. The core is in place; we’ll keep adding nodes and fixing bugs, but a
workflow saved today should keep opening in later builds.
</p>
</div>
</section>
<footer class="colophon">
<div class="shell">
Coda — connectome data analysis · Fly Connectomics Group, Cambridge<br>
Connectome data published by the FlyEM project at Janelia Research Campus, by the FlyWire
consortium, and by Virtual Fly Brain.<br>
Page views are counted with <a href="https://coda-science.goatcounter.com/">GoatCounter</a>
— no cookies, nothing kept in your browser, and the dashboard is public.
</div>
</footer>
<script type="module" src="/src/tutorial/main.ts"></script>
</body>
</html>