@czi-sds/mcp 0.19.0 → 0.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -24,12 +24,13 @@ The viewer fills its parent. Mol\* sizes its canvas from the laid-out container,
|
|
|
24
24
|
|
|
25
25
|
### **Default ProteinStructureViewer**
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
The structure to render, as raw PDB or mmCIF (PDBx) text, is the only required prop. Supplying per-residue `plddt` scores on a 0-1 scale colors the structure by confidence and puts the pLDDT key in the legend.
|
|
28
28
|
|
|
29
29
|
**Example: DefaultProteinStructureViewer**
|
|
30
30
|
|
|
31
31
|
```tsx
|
|
32
|
-
//
|
|
32
|
+
// The structure to render, as raw PDB or mmCIF (PDBx) text, is the only
|
|
33
|
+
// required prop. Adding per-residue pLDDT scores on a
|
|
33
34
|
// 0-1 scale colors the structure by confidence and puts the pLDDT key in the
|
|
34
35
|
// legend.
|
|
35
36
|
//
|
|
@@ -244,7 +245,101 @@ function App() {
|
|
|
244
245
|
return (
|
|
245
246
|
<div className="app" style={{ height: 480 }}>
|
|
246
247
|
<ProteinStructureViewer
|
|
247
|
-
|
|
248
|
+
structure={PDB}
|
|
249
|
+
plddt={PLDDT}
|
|
250
|
+
stats={[
|
|
251
|
+
{ label: "Known", value: "62%" },
|
|
252
|
+
{ label: "pTM", value: "0.874" },
|
|
253
|
+
{ label: "Mean pLDDT", value: "0.781" },
|
|
254
|
+
]}
|
|
255
|
+
/>
|
|
256
|
+
</div>
|
|
257
|
+
);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
export default App;
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### PDB and mmCIF
|
|
264
|
+
|
|
265
|
+
`structure` is the structure text, not a filename, and it accepts both legacy PDB and mmCIF (PDBx). The viewer detects the format from the contents: a `data_` block or an `_atom_site.` loop is treated as mmCIF, everything else as PDB. Binary CIF (`.bcif`) is not accepted.
|
|
266
|
+
|
|
267
|
+
**Example: MmcifProteinStructureViewer**
|
|
268
|
+
|
|
269
|
+
```tsx
|
|
270
|
+
// `structure` accepts mmCIF (PDBx) as well as PDB. The viewer detects the
|
|
271
|
+
// format from the text.
|
|
272
|
+
//
|
|
273
|
+
// The structure below is crambin (PDB 1CRN), trimmed to the backbone atoms the
|
|
274
|
+
// polymer cartoon traces. A chain needs enough residues to trace: a single
|
|
275
|
+
// residue renders an empty canvas.
|
|
276
|
+
|
|
277
|
+
import { ProteinStructureViewer } from "@czi-sds/data-viz";
|
|
278
|
+
|
|
279
|
+
const MMCIF = `data_1CRN
|
|
280
|
+
#
|
|
281
|
+
loop_
|
|
282
|
+
_atom_site.group_PDB
|
|
283
|
+
_atom_site.id
|
|
284
|
+
_atom_site.type_symbol
|
|
285
|
+
_atom_site.label_atom_id
|
|
286
|
+
_atom_site.label_alt_id
|
|
287
|
+
_atom_site.label_comp_id
|
|
288
|
+
_atom_site.label_asym_id
|
|
289
|
+
_atom_site.label_entity_id
|
|
290
|
+
_atom_site.label_seq_id
|
|
291
|
+
_atom_site.pdbx_PDB_ins_code
|
|
292
|
+
_atom_site.Cartn_x
|
|
293
|
+
_atom_site.Cartn_y
|
|
294
|
+
_atom_site.Cartn_z
|
|
295
|
+
_atom_site.occupancy
|
|
296
|
+
_atom_site.B_iso_or_equiv
|
|
297
|
+
_atom_site.auth_seq_id
|
|
298
|
+
_atom_site.auth_comp_id
|
|
299
|
+
_atom_site.auth_asym_id
|
|
300
|
+
_atom_site.auth_atom_id
|
|
301
|
+
_atom_site.pdbx_PDB_model_num
|
|
302
|
+
ATOM 1 N N . THR A 1 1 ? 17.047 14.099 3.625 1.00 13.79 1 THR A N 1
|
|
303
|
+
ATOM 2 C CA . THR A 1 1 ? 16.967 12.784 4.338 1.00 10.80 1 THR A CA 1
|
|
304
|
+
ATOM 3 C C . THR A 1 1 ? 15.685 12.755 5.133 1.00 9.19 1 THR A C 1
|
|
305
|
+
ATOM 4 O O . THR A 1 1 ? 15.268 13.825 5.594 1.00 9.85 1 THR A O 1
|
|
306
|
+
ATOM 5 N N . THR A 1 2 ? 15.115 11.555 5.265 1.00 7.81 2 THR A N 1
|
|
307
|
+
ATOM 6 C CA . THR A 1 2 ? 13.856 11.469 6.066 1.00 8.31 2 THR A CA 1
|
|
308
|
+
ATOM 7 C C . THR A 1 2 ? 14.164 10.785 7.379 1.00 5.80 2 THR A C 1
|
|
309
|
+
ATOM 8 O O . THR A 1 2 ? 14.993 9.862 7.443 1.00 6.94 2 THR A O 1
|
|
310
|
+
ATOM 9 N N . CYS A 1 3 ? 13.488 11.241 8.417 1.00 5.24 3 CYS A N 1
|
|
311
|
+
ATOM 10 C CA . CYS A 1 3 ? 13.660 10.707 9.787 1.00 5.39 3 CYS A CA 1
|
|
312
|
+
ATOM 11 C C . CYS A 1 3 ? 12.269 10.431 10.323 1.00 4.45 3 CYS A C 1
|
|
313
|
+
ATOM 12 O O . CYS A 1 3 ? 11.393 11.308 10.185 1.00 6.54 3 CYS A O 1
|
|
314
|
+
ATOM 13 N N . CYS A 1 4 ? 12.019 9.272 10.928 1.00 3.90 4 CYS A N 1
|
|
315
|
+
ATOM 14 C CA . CYS A 1 4 ? 10.646 8.991 11.408 1.00 4.24 4 CYS A CA 1
|
|
316
|
+
ATOM 15 C C . CYS A 1 4 ? 10.654 8.793 12.919 1.00 3.72 4 CYS A C 1
|
|
317
|
+
ATOM 16 O O . CYS A 1 4 ? 11.659 8.296 13.491 1.00 5.30 4 CYS A O 1
|
|
318
|
+
ATOM 17 N N . PRO A 1 5 ? 9.561 9.108 13.563 1.00 3.96 5 PRO A N 1
|
|
319
|
+
ATOM 18 C CA . PRO A 1 5 ? 9.448 9.034 15.012 1.00 4.25 5 PRO A CA 1
|
|
320
|
+
ATOM 19 C C . PRO A 1 5 ? 9.288 7.670 15.606 1.00 4.96 5 PRO A C 1
|
|
321
|
+
ATOM 20 O O . PRO A 1 5 ? 9.490 7.519 16.819 1.00 7.44 5 PRO A O 1
|
|
322
|
+
ATOM 21 N N . SER A 1 6 ? 8.875 6.686 14.796 1.00 4.83 6 SER A N 1
|
|
323
|
+
ATOM 22 C CA . SER A 1 6 ? 8.673 5.314 15.279 1.00 4.45 6 SER A CA 1
|
|
324
|
+
ATOM 23 C C . SER A 1 6 ? 8.753 4.376 14.083 1.00 4.99 6 SER A C 1
|
|
325
|
+
ATOM 24 O O . SER A 1 6 ? 8.726 4.858 12.923 1.00 4.61 6 SER A O 1
|
|
326
|
+
ATOM 25 N N . ILE A 1 7 ? 8.881 3.075 14.358 1.00 4.94 7 ILE A N 1
|
|
327
|
+
ATOM 26 C CA . ILE A 1 7 ? 8.912 2.083 13.258 1.00 6.33 7 ILE A CA 1
|
|
328
|
+
ATOM 27 C C . ILE A 1 7 ? 7.581 2.090 12.506 1.00 5.32 7 ILE A C 1
|
|
329
|
+
ATOM 28 O O . ILE A 1 7 ? 7.670 2.031 11.245 1.00 6.85 7 ILE A O 1
|
|
330
|
+
ATOM 29 N N . VAL A 1 8 ? 6.458 2.162 13.159 1.00 5.02 8 VAL A N 1
|
|
331
|
+
ATOM 30 C CA . VAL A 1 8 ? 5.145 2.209 12.453 1.00 6.93 8 VAL A CA 1
|
|
332
|
+
ATOM 31 C C . VAL A 1 8 ? 5.115 3.379 11.461 1.00 5.39 8 VAL A C 1
|
|
333
|
+
ATOM 32 O O . VAL A 1 8 ? 4.664 3.268 10.343 1.00 6.30 8 VAL A O 1
|
|
334
|
+
#`;
|
|
335
|
+
|
|
336
|
+
const PLDDT = [0.45, 0.515, 0.557, 0.569, 0.567, 0.578, 0.618, 0.681];
|
|
337
|
+
|
|
338
|
+
function App() {
|
|
339
|
+
return (
|
|
340
|
+
<div className="app" style={{ height: 480 }}>
|
|
341
|
+
<ProteinStructureViewer
|
|
342
|
+
structure={MMCIF}
|
|
248
343
|
plddt={PLDDT}
|
|
249
344
|
stats={[
|
|
250
345
|
{ label: "Known", value: "62%" },
|
|
@@ -494,7 +589,7 @@ function App() {
|
|
|
494
589
|
return (
|
|
495
590
|
<div className="app" style={{ height: 480 }}>
|
|
496
591
|
<ProteinStructureViewer
|
|
497
|
-
|
|
592
|
+
structure={PDB}
|
|
498
593
|
residueOverlay={{
|
|
499
594
|
colorScale: PLASMA_COLOR_SCALE,
|
|
500
595
|
label: "Feature activation",
|
|
@@ -520,6 +615,8 @@ Selection is controlled through one prop. Every way of making one - clicking a r
|
|
|
520
615
|
|
|
521
616
|
A `StructureSelection` says what is selected in either of two ways, which combine: `residues` is a list of 0-based indices, and `chains` names whole chains by `chainId`. A drag across the sequence comes back as `residues`, a chain caption as `chains`, so a whole-chain selection survives the round trip at its original size rather than as the hundreds of indices it stands for. The camera frames whatever the selection covers, so a range or a chain is fitted to the view rather than approached as a point.
|
|
522
617
|
|
|
618
|
+
The two are shown differently, because they are different sizes of answer. Selected residues are drawn in ball-and-stick over the cartoon, with the residues around them, which is the point of looking at a site. A selected chain is left exactly as it was and the other chains dim around it - the same way pointing at a chain's name behaves, and for the same reason: a whole chain is already visible, so anything painted over it would only hide it.
|
|
619
|
+
|
|
523
620
|
`onResidueClick` and `onResidueHover` are separate, and still report a single `ResidueRef`: they describe the residue under the pointer, which is a different fact from what the selection covers. Use them for a readout that follows the cursor, and `onSelectionChange` for what the user has actually chosen.
|
|
524
621
|
|
|
525
622
|
A `ResidueRef` carries the residue in each addressing scheme a caller might need. `index` is the viewer's own key, shared with `plddt` and `residueOverlay`, and counts residues in file order straight through a chain break. `chainId` and `seqId` are what the file says, which is what the sequence panel displays and what the system that produced the structure will recognise. On a single chain numbered from 1 the two agree; on a complex they do not, so map a click back onto your own numbering with `chainId` and `seqId` rather than arithmetic on `index`.
|
|
@@ -760,7 +857,7 @@ function App() {
|
|
|
760
857
|
: next
|
|
761
858
|
)
|
|
762
859
|
}
|
|
763
|
-
|
|
860
|
+
structure={PDB}
|
|
764
861
|
plddt={PLDDT}
|
|
765
862
|
selection={selection}
|
|
766
863
|
stats={[
|
|
@@ -778,11 +875,11 @@ export default App;
|
|
|
778
875
|
|
|
779
876
|
### Complexes and chains
|
|
780
877
|
|
|
781
|
-
A multi-chain structure needs nothing special: pass the whole complex as one
|
|
878
|
+
A multi-chain structure needs nothing special: pass the whole complex as one structure string and the viewer finds the chains itself, reporting them through `onChainsChange` as `ChainRef`s. It draws one cartoon per chain, splits the sequence panel into one grid per chain, and - when neither `plddt` nor `residueOverlay` is coloring the structure - paints each chain its own color and shows a chain legend with a swatch and a visibility toggle for each.
|
|
782
879
|
|
|
783
880
|
Visibility works out of the box: the toggles own it unless you pass `hiddenChains`, which takes it over and leaves the toggles reporting through `onChainVisibilityChange`. Hiding a chain removes everything it is drawn with, which also takes it out of reach of hover and click; its sequence stays in the panel, dimmed, so the panel does not reflow on every toggle. `chainColors` overrides the palette per chain.
|
|
784
881
|
|
|
785
|
-
Pointing at a chain's name, in the legend or above its grid in the sequence panel,
|
|
882
|
+
Pointing at a chain's name, in the legend or above its grid in the sequence panel, dims every other chain in the 3D view so the one under the pointer stands out. The hovered chain keeps whatever coloring it already has, rather than being washed in a highlight color that would hide it. Keyboard focus does the same, and nothing is reported to the consumer - it answers "which one is this?" without changing what is selected. `disableChainHighlightOnHover` turns it off.
|
|
786
883
|
|
|
787
884
|
Residue indices run straight through the chain break: on the pair below, barnase occupies 0-109 and barstar 110-198, so `plddt` is one flat array over the whole complex and one `residueOverlay` map spans both chains. Because a file numbers a complex however it likes - barstar here starts at residue 111, not 1 - `index` and `seqId` part company, so map a click back onto your own data with `chainId` and `seqId` rather than arithmetic on `index`.
|
|
788
885
|
|
|
@@ -798,7 +895,7 @@ import { useState } from "react";
|
|
|
798
895
|
|
|
799
896
|
// A two-chain complex: barnase (chain A) with barstar (chain B) bound to it,
|
|
800
897
|
// which is the shape a designed binder arrives in alongside its target. The
|
|
801
|
-
// whole complex goes in as one `
|
|
898
|
+
// whole complex goes in as one `structure` string; the viewer finds the chains and
|
|
802
899
|
// draws one cartoon per chain.
|
|
803
900
|
//
|
|
804
901
|
// Trimmed to the first 30 residues of each chain and to backbone atoms, which
|
|
@@ -1075,7 +1172,7 @@ export default function App(): JSX.Element {
|
|
|
1075
1172
|
// produced the structure will recognise.
|
|
1076
1173
|
console.log(residue.chainId, residue.seqId, residue.index)
|
|
1077
1174
|
}
|
|
1078
|
-
|
|
1175
|
+
structure={PDB}
|
|
1079
1176
|
plddt={PLDDT}
|
|
1080
1177
|
selection={selection}
|
|
1081
1178
|
stats={[
|
|
@@ -1091,7 +1188,7 @@ export default function App(): JSX.Element {
|
|
|
1091
1188
|
|
|
1092
1189
|
### Ligands and ions
|
|
1093
1190
|
|
|
1094
|
-
Whatever a
|
|
1191
|
+
Whatever a structure file carries besides its protein - ligands, ions, glycans, lipids - is drawn as ball-and-stick alongside the cartoon, with no prop to turn on. A cartoon traces a polymer backbone and a heme has none, so the two halves of a chain need two representations between them.
|
|
1095
1192
|
|
|
1096
1193
|
The residue holding a ligand is drawn as sticks too, one bond out, which is what makes the ligand look bound rather than dropped in. Myoglobin's heme is held by His93, and without it the heme floats loose in the middle of a cartoon it is visibly bonded to. Covalent and metallic-coordination bonds both count - the heme's iron is held by the latter - and only the residue that holds the ligand comes, not that residue's own neighbours.
|
|
1097
1194
|
|
|
@@ -1327,7 +1424,7 @@ function App() {
|
|
|
1327
1424
|
return (
|
|
1328
1425
|
<div className="app" style={{ height: 240 }}>
|
|
1329
1426
|
<ProteinStructureViewer
|
|
1330
|
-
|
|
1427
|
+
structure={PDB}
|
|
1331
1428
|
plddt={PLDDT}
|
|
1332
1429
|
showAxes={false}
|
|
1333
1430
|
showLegend={false}
|
|
@@ -1355,7 +1452,7 @@ Passing `download` adds a capture button beneath the reset-camera control, which
|
|
|
1355
1452
|
|
|
1356
1453
|
```tsx
|
|
1357
1454
|
<ProteinStructureViewer
|
|
1358
|
-
|
|
1455
|
+
structure={PDB}
|
|
1359
1456
|
download={{ resolution: "high", filename: "barnase-barstar" }}
|
|
1360
1457
|
/>
|
|
1361
1458
|
```
|
|
@@ -1381,7 +1478,7 @@ Anything named in it wins, and anything left out keeps the viewer's default. So
|
|
|
1381
1478
|
import { PluginConfig } from "molstar/lib/mol-plugin/config";
|
|
1382
1479
|
|
|
1383
1480
|
<ProteinStructureViewer
|
|
1384
|
-
|
|
1481
|
+
structure={PDB}
|
|
1385
1482
|
molstarSpec={{
|
|
1386
1483
|
canvas3d: {
|
|
1387
1484
|
// Slow the trackball down, leaving the rest of it alone.
|
|
@@ -1413,14 +1510,14 @@ The viewer spreads any remaining props onto its root div, so standard HTML attri
|
|
|
1413
1510
|
|
|
1414
1511
|
| Name | Type | Default | Description |
|
|
1415
1512
|
| ------------------------------- | ----------------------------- | ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
1416
|
-
| `
|
|
1513
|
+
| `structure` | `string` | - (required) | The structure to render, as raw PDB or mmCIF (PDBx) text. |
|
|
1417
1514
|
| `plddt` | `number[] \| null` | - | Per-residue pLDDT confidence on a 0-1 scale, in chain order. When supplied, the structure is colored by confidence unless `residueOverlay` takes over. Residues past the end of the array fall back to mid confidence. |
|
|
1418
1515
|
| `residueOverlay` | `ResidueValueOverlay \| null` | - | Per-residue values painted over the structure, replacing pLDDT coloring while set. See the table below for its shape. |
|
|
1419
|
-
| `selection` | `StructureSelection \| null` | `null` | What is selected. Controlled: the camera frames whatever it covers, and clearing it zooms back out. See the table below for its shape.
|
|
1516
|
+
| `selection` | `StructureSelection \| null` | `null` | What is selected. Controlled: the camera frames whatever it covers, and clearing it zooms back out. Residues are drawn in ball-and-stick; a whole chain dims the chains around it instead. See the table below for its shape. |
|
|
1420
1517
|
| `hiddenChains` | `string[]` | - | Chains hidden from the 3D view, by `chainId`. Leave undefined to let the chain legend's toggles own visibility; passing it takes that over, and the toggles then only report through `onChainVisibilityChange`. |
|
|
1421
1518
|
| `chainColors` | `Record<string, string>` | - | Color per chain, by `chainId`, as `#RRGGBB`. Chains left out fall back to the viewer's palette. Only visible while chain coloring is what is on screen, which is when neither `plddt` nor `residueOverlay` is set. |
|
|
1422
1519
|
| `showChainLegend` | `boolean` | `true` | Show the chain legend, which lists each chain with its color and a visibility toggle. Ignored on a single-chain structure, where there is nothing to tell apart or hide. |
|
|
1423
|
-
| `disableChainHighlightOnHover` | `boolean` | `false` | Stop
|
|
1520
|
+
| `disableChainHighlightOnHover` | `boolean` | `false` | Stop other chains from dimming in the 3D view while a chain's name is pointed at, in the legend or above its grid in the sequence panel. Turn it off where the movement is more distracting than the answer is useful. |
|
|
1424
1521
|
| `download` | `StructureDownload \| null` | - | Adds a capture button beneath the reset-camera control, which downloads a PNG of the structure. Omit for no button. See _Downloading an image_ above. |
|
|
1425
1522
|
| `molstarSpec` | `Partial<PluginUISpec>` | - | Mol* plugin spec laid over the viewer's own, which is how the whole of Mol*'s configuration is reachable without a prop here for each setting. Anything named wins; list-valued keys are appended to. Read once at creation, except `canvas3d`, which is re-applied when it changes. See _Configuring Mol\*_ above. |
|
|
1426
1523
|
| `stats` | `(StructureStat \| null)[]` | - | Up to three whole-structure stats shown along the bottom. A `null` entry reserves its column without rendering anything, so the columns never shift as values come and go. |
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
},
|
|
29
29
|
"disableChainHighlightOnHover": {
|
|
30
30
|
"defaultValue": false,
|
|
31
|
-
"description": "Stop
|
|
31
|
+
"description": "Stop other chains from dimming in the 3D view while a chain's name is\npointed at, in the legend or above its grid in the sequence panel.\n\nThe dim is on by default, since on a complex it is how a reader finds out\nwhich chain is which. Turn it off where the movement is more distracting\nthan the answer is useful - a grid of viewers a pointer crosses on its way\nsomewhere else, or a page driving its own highlighting through `selection`.",
|
|
32
32
|
"isRequired": false,
|
|
33
33
|
"type": "boolean"
|
|
34
34
|
},
|
|
@@ -77,9 +77,9 @@
|
|
|
77
77
|
"isRequired": false,
|
|
78
78
|
"type": "string"
|
|
79
79
|
},
|
|
80
|
-
"
|
|
80
|
+
"structure": {
|
|
81
81
|
"defaultValue": "- (required)",
|
|
82
|
-
"description": "Structure to render, as raw PDB text.",
|
|
82
|
+
"description": "Structure to render, as raw PDB or mmCIF (PDBx) text.",
|
|
83
83
|
"isRequired": true,
|
|
84
84
|
"type": "string"
|
|
85
85
|
},
|
|
@@ -95,7 +95,7 @@
|
|
|
95
95
|
},
|
|
96
96
|
"selection": {
|
|
97
97
|
"defaultValue": null,
|
|
98
|
-
"description": "What is selected, or null when nothing is. Controlled: the camera frames\nwhatever the selection covers, and clearing it zooms back out to the\ndefault view.",
|
|
98
|
+
"description": "What is selected, or null when nothing is. Controlled: the camera frames\nwhatever the selection covers, and clearing it zooms back out to the\ndefault view.\n\nResidues are drawn in ball-and-stick over the cartoon; whole chains are\nleft as they are and the chains around them dim, the same as hovering a\nchain's name.",
|
|
99
99
|
"isRequired": false,
|
|
100
100
|
"type": "StructureSelection | null"
|
|
101
101
|
},
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@czi-sds/mcp",
|
|
3
3
|
"description": "The official MCP server for SDS",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.20.0",
|
|
5
5
|
"main": "dist/stdio.js",
|
|
6
6
|
"files": [
|
|
7
7
|
"dist",
|
|
@@ -66,5 +66,5 @@
|
|
|
66
66
|
"turndown": "^7.2.4",
|
|
67
67
|
"typescript": "^5.9.2"
|
|
68
68
|
},
|
|
69
|
-
"gitHead": "
|
|
69
|
+
"gitHead": "f40631b6abb44a4851ba9bc888dfdf703e44a3d4"
|
|
70
70
|
}
|