Skip to content

Commit 32e0c1d

Browse files
authored
Built in docs (#81)
* built-in docs * update contribution template
1 parent 8648e01 commit 32e0c1d

34 files changed

+11800
-1
lines changed

.github/pull_request_template.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,7 @@
66
## Actions
77

88
- [ ] Added description of changes to the `[Unreleased]` section of `CHANGELOG.md`
9-
- [ ] (Optional but encouraged) Added example(s) for new feature(s) in this PR (e.g., in `app/api/examples.py` or a Jupyter Notebook)
9+
- [ ] When adding new features:
10+
- [ ] Added example(s) to `app/api/examples.py`
11+
- [ ] Added Jupyter Notebook to `test-data/notebooks` with new features
12+
- [ ] Added MkDocs documentation in `docs`

.github/workflows/docs.yml

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
name: Build & Deploy Docs
2+
3+
on:
4+
push:
5+
branches: master
6+
paths:
7+
- docs/**
8+
- ".github/workflows/docs.yml"
9+
pull_request:
10+
branches: master
11+
paths:
12+
- docs/**
13+
- ".github/workflows/docs.yml"
14+
15+
jobs:
16+
build:
17+
runs-on: ubuntu-latest
18+
steps:
19+
- name: 👨🏼‍💻 checkout
20+
uses: actions/checkout@v4
21+
22+
- name: 🐍 python
23+
uses: actions/setup-python@v5
24+
with:
25+
python-version: "3.10"
26+
27+
- name: ⛓️ dependencies
28+
run: |
29+
pip install mkdocs-material
30+
- name: 🔧 build site
31+
run: |
32+
cd docs
33+
mkdocs build
34+
35+
deploy:
36+
runs-on: ubuntu-latest
37+
needs: build
38+
if: github.ref == 'refs/heads/master'
39+
steps:
40+
- name: 👨🏼‍💻 checkout
41+
uses: actions/checkout@v4
42+
43+
- name: 🐍 python
44+
uses: actions/setup-python@v5
45+
with:
46+
python-version: "3.10"
47+
48+
- name: ⛓️ dependencies
49+
run: |
50+
pip install mkdocs-material
51+
- name: 🔧 build site
52+
run: |
53+
cd docs
54+
mkdocs build
55+
56+
- name: 🚢 deploy docs
57+
uses: peaceiris/actions-gh-pages@v4
58+
with:
59+
deploy_key: ${{ secrets.DOCS_DEPLOY_KEY }}
60+
external_repository: molstar/mol-view-spec-docs
61+
publish_branch: gh-pages
62+
publish_dir: ./docs/site

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,7 @@ preprocessor.env/
222222

223223
# mkdocs documentation
224224
/site
225+
docs/site
225226

226227
# mypy
227228
.mypy_cache/

docs/.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
site/
2+
.idea
3+
.DS_Store

docs/README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# MolViewSpec Documentation
2+
3+
Contributions to the documentations are highly welcome! Please make a pull request with your changes.
4+
5+
Requires Python 3.x to build. To develop locally, from this folder install `mkdocs`:
6+
7+
```bash
8+
pip install mkdocs-material
9+
```
10+
11+
and then serve the docs:
12+
13+
```
14+
mkdocs serve
15+
```

docs/docs/animations.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# MolViewSpec animations
2+
3+
Animations are sequential collections of individual MolViewSpec scenes. You can combine them freely into complex stories
4+
that render scenes one-by-one. The Mol* viewer can interpolate between these states, providing you with a powerful story
5+
telling tool tailored to structural biology.
6+
7+
## Creating snapshots
8+
9+
Use the builder as normal and define the desired scene. Invoke `get_snapshot()` to obtain a snapshot instance (in
10+
contrast to the default way of emitting the generated state description using `get_state()`).
11+
12+
```python
13+
snapshot1 = builder.get_snapshot(
14+
title="1tqn",
15+
description="""
16+
### 1tqn with ligand and electron density map
17+
- 2FO-FC at 1.5σ, blue
18+
- FO-FC (positive) at 3σ, green
19+
- FO-FC (negative) at -3σ, red
20+
""",
21+
)
22+
```
23+
24+
A snapshot can hold additional metadata such as a custom title and description. Markup is supported.
25+
26+
## Combining snapshots
27+
28+
Individual snapshots can then be combined into an animation by providing them in the desired order using the `snapshots`
29+
parameter. Additionally, global metadata can be added that describes shared properties of all snapshots.
30+
31+
```python
32+
states = States(snapshots=[snapshot1, snapshot2], metadata=GlobalMetadata(description="1tqn + Volume Server")).json(
33+
exclude_none=True, indent=2
34+
)
35+
```
36+
37+
The output is valid MolViewSpec JSON that can be opened in Mol*. Mol* will interpolate between individual substates and
38+
add smooth transitions by default. You can further customize this behavior using the `transition_duration_ms` and
39+
`linger_duration_ms` properties.

docs/docs/annotations.md

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
# MolViewSpec annotations
2+
3+
Annotations are used to define substructures (components) and apply colors, labels, or tooltips to them. In contrast to [selectors](./selectors.md), annotations are defined in a separate file, which can then be referenced in the main MVS file.
4+
5+
## MVS annotation files
6+
7+
MVS annotations can be encoded in multiple different formats, but their logic is always the same and in fact very similar to that of selectors.
8+
9+
### JSON format
10+
11+
The simplest example of an annotation in JSON format is just a JSON-encoded [union component expression](./selectors.md) selector. Here is a simple annotation containing 4 **annotation rows**:
12+
13+
```json
14+
[
15+
{ "label_asym_id": "A" },
16+
{ "label_asym_id": "B" },
17+
{ "label_asym_id": "B", "beg_label_seq_id": 100, "end_label_seq_id": 200 },
18+
{ "label_asym_id": "B", "beg_label_seq_id": 150, "end_label_seq_id": 160 }
19+
]
20+
```
21+
22+
However, in a typical annotation, there is at least one extra field that provides the value of the dependent variable (such as color or label) mapped to each annotation row:
23+
24+
```json
25+
[
26+
{ "label_asym_id": "A", "color": "#00ff00" },
27+
{ "label_asym_id": "B", "color": "blue" },
28+
{ "label_asym_id": "B", "beg_label_seq_id": 100, "end_label_seq_id": 200, "color": "skyblue" }
29+
{ "label_asym_id": "B", "beg_label_seq_id": 150, "end_label_seq_id": 160, "color": "lightblue" }
30+
]
31+
```
32+
33+
This particular annotation (when applied via `color_from_uri` node) will apply green color (#00ff00) to the whole chain A and three shades of blue to the chain B. Later annotation rows override earlier rows, therefore residues 1–99 will be blue, 100–149 skyblue, 150–160 lightblue, 161–200 skyblue, and 201–end blue. (Tip: to color all the rest of the structure in one color, add an annotation row with no selector fields (e.g. `{ "color": "yellow" }`) to the beginning of the annotation.)
34+
35+
Real-life annotation files can include huge numbers of annotation rows. To avoid repeating the same field keys in every row, we can convert the array-of-objects into object-of-arrays. This will result in an equivalent annotation but smaller file size:
36+
37+
```json
38+
{
39+
"label_asym_id": ["A", "B", "B", "B"],
40+
"beg_label_seq_id": [null, null, 100, 150],
41+
"end_label_seq_id": [null, null, 200, 160],
42+
"color": ["#00ff00", "blue", "skyblue", "lightblue"]
43+
}
44+
```
45+
46+
A more complex example of JSON annotation is provided in [1h9t_domains.json](./files/1h9t_domains.json).
47+
48+
### CIF format
49+
50+
Annotations can also be encoded using CIF format, a table-based format which is commonly used in structure biology to store structures or any kind of tabular data.
51+
52+
The example from above, encoded as CIF, would look like this:
53+
54+
```cif
55+
data_annotation
56+
loop_
57+
_coloring.label_asym_id
58+
_coloring.beg_label_seq_id
59+
_coloring.end_label_seq_id
60+
_coloring.color
61+
A . . '#00ff00'
62+
B . . 'blue'
63+
B 100 200 'skyblue'
64+
B 150 160 'lightblue'
65+
```
66+
67+
An advantage of the CIF format is that it can include multiple annotation tables in the same file, organized into blocks and categories. Then the MVS file can reference individual tables using `block_header` (or `block_index`) and `category_name` parameters. The column containing the dependent variable can be specified using `field_name` parameter. In this case, we could use `"block_header": "annotation", "category_name": "coloring", "field_name": "color"`.
68+
69+
### BCIF format
70+
71+
This has exactly the same structure as the CIF format, but encoded using [BinaryCIF](https://github.com/molstar/BinaryCIF).
72+
73+
## Referencing MVS annotations in MVS tree
74+
75+
### From URI
76+
77+
MVS annotations can be referenced in `color_from_uri`, `label_from_uri`, `tooltip_from_uri`, and `component_from_uri` nodes in MVS tree.
78+
79+
For example this part of a MVS tree:
80+
81+
```txt
82+
- representation {type: "cartoon"}
83+
- color {selector: {label_asym_id: "A"}, color: "#00ff00"}
84+
- color {selector: {label_asym_id: "B"}, color: "blue"}
85+
- color {selector: {label_asym_id: "B", beg_label_seq_id: 100, end_label_seq_id: 200}, color: "skyblue"}
86+
- color {selector: {label_asym_id: "B", beg_label_seq_id: 150, end_label_seq_id: 160}, color: "lightblue"}
87+
```
88+
89+
can be replaced by:
90+
91+
```txt
92+
- representation {type: "cartoon"}
93+
- color_from_uri {uri: "https://example.org/annotations.json", format: "json", schema: "residue_range"}
94+
```
95+
96+
assuming that the JSON annotation file shown in the previous section is available at `https://example.org/annotations.json`.
97+
98+
#### Relative URIs
99+
100+
The `uri` parameter can also hold a URI reference (relative URI). In such cases, this URI reference is relative to the URI of the MVS file itself (e.g. if the MVS file is available from `https://example.org/spanish/inquisition/expectations.mvsj`, then the relative URI `./annotations.json` is equivalent to `https://example.org/spanish/inquisition/annotations.json`). This is however not applicable in all cases (e.g. the MVS tree can be constructed ad-hoc within a web application, therefore it has no URI; or the MVS file is loaded from a local disk using drag&drop, therefore the relative location is not accessible by the browser).
101+
102+
A special case is when the MVS tree is saved in MVSX format. An MVSX file is a ZIP archive containing the MVS tree in `index.mvsj` and possibly other files. In this case, the relative URIs will resolve to the files within the archive (e.g. `./annotations.json` points to the file `annotations.json` stored in the MSVX archive).
103+
104+
### From source
105+
106+
The MVS annotations can in fact be stored within the same mmCIF file from which the structure coordinates are loaded. To reference these annotations, we can use `color_from_source`, `label_from_source`, `tooltip_from_source`, and `component_from_source` nodes. Example:
107+
108+
```txt
109+
- representation {type: "cartoon"}
110+
- color_from_source {schema: "residue_range", block_header: "annotation", category_name: "coloring"}
111+
```
112+
113+
## Annotation schemas
114+
115+
The `schema` parameter of all `*_from_uri` and `*_from_source` nodes specifies the MVS annotation schema, i.e. a set of fields used to select a substructure. In the example above we are using `residue_range` schema, which uses columns `label_entity_id`, `label_asym_id`, `beg_label_seq_id`, and `end_label_seq_id`. (We didn't provide values for `label_entity_id`, so it is not taken into account even though the schema supports it).
116+
117+
Table of selector field names supported by individual MVS annotation schemas:
118+
119+
| Field \ Schema | whole_structure | entity | chain | residue | residue_range | atom | auth_chain | auth_residue | auth_residue_range | auth_atom | all_atomic |
120+
| :---------------- | :-------------: | :----: | :---: | :-----: | :-----------: | :--: | :--------: | :----------: | :----------------: | :-------: | :--------: |
121+
| label_entity_id | | X | X | X | X | X | | | | | X |
122+
| label_asym_id | | | X | X | X | X | | | | | X |
123+
| label_seq_id | | | | X | | X | | | | | X |
124+
| beg_label_seq_id | | | | | X | | | | | | X |
125+
| end_label_seq_id | | | | | X | | | | | | X |
126+
| label_atom_id | | | | | | X | | | | | X |
127+
| auth_asym_id | | | | | | | X | X | X | X | X |
128+
| auth_seq_id | | | | | | | | X | | X | X |
129+
| pdbx_PDB_ins_code | | | | | | | | X | | X | X |
130+
| beg_auth_seq_id | | | | | | | | | X | | X |
131+
| end_auth_seq_id | | | | | | | | | X | | X |
132+
| auth_atom_id | | | | | | | | | | X | X |
133+
| type_symbol | | | | | | X | | | | X | X |
134+
| atom_id | | | | | | X | | | | X | X |
135+
| atom_index | | | | | | X | | | | X | X |
136+
137+
To include all selector field names that are present in the annotation, one can use `"schema": "all_atomic"` (we could use it in the example above and the result would be the same). In future versions of MVS, non-atomic schemas might be added, to select parts of structures that are not composed of atoms, e.g. coarse models or geometric primitives.
138+
139+
## `group_id` field
140+
141+
The `group_id` field is a special field supported by all MVS annotation schemas. It does not change the sets of atoms selected by individual rows but instead groups annotation rows together to create more complex selections. This is useful when adding labels to our visualization.
142+
143+
The following example (when applied via `label_from_uri` node) will create 7 separate labels, each bound to a single residue:
144+
145+
```cif
146+
data_annotation
147+
loop_
148+
_labels.label_asym_id
149+
_labels.label_seq_id
150+
_labels.color
151+
_labels.label
152+
A 100 pink 'Substrate binding site'
153+
A 150 pink 'Substrate binding site'
154+
A 170 pink 'Substrate binding site'
155+
A 200 blue 'Inhibitor binding site'
156+
A 220 blue 'Inhibitor binding site'
157+
A 300 lime 'Glycosylation site'
158+
A 330 lime 'Glycosylation site'
159+
```
160+
161+
On the other hand, the next example will only create 4 labels ("Substrate binding site" label bound to residues 100, 150, and 170; "Inhibitor binding site" label bound to residues 200 and 220; "Glycosylation site" label bound to residue 300; and "Glycosylation site" label bound to residue 330):
162+
163+
```cif
164+
data_annotation
165+
loop_
166+
_labels.group_id
167+
_labels.label_asym_id
168+
_labels.label_seq_id
169+
_labels.color
170+
_labels.label
171+
1 A 100 pink 'Substrate binding site'
172+
1 A 150 pink 'Substrate binding site'
173+
1 A 170 pink 'Substrate binding site'
174+
2 A 200 blue 'Inhibitor binding site'
175+
2 A 220 blue 'Inhibitor binding site'
176+
. A 300 lime 'Glycosylation site'
177+
. A 330 lime 'Glycosylation site'
178+
```
179+
180+
Note: Annotation rows with empty `group_id` field (`.` in CIF, ommitted field or `null` in JSON) are always treated as separate groups.
181+
182+
Note 2: `group_id` field has no effect on colors, tooltips, components. It only makes any difference for labels.

0 commit comments

Comments
 (0)