vimol 0.1.2__tar.gz → 0.1.3__tar.gz
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.
- vimol-0.1.3/PKG-INFO +199 -0
- vimol-0.1.3/README.md +163 -0
- {vimol-0.1.2 → vimol-0.1.3}/pyproject.toml +2 -1
- {vimol-0.1.2 → vimol-0.1.3}/src/vimol/__init__.py +7 -2
- vimol-0.1.3/src/vimol/align.py +934 -0
- vimol-0.1.3/src/vimol/app.py +299 -0
- vimol-0.1.3/src/vimol/bonds.py +110 -0
- vimol-0.1.3/src/vimol/data/c60.xyz +62 -0
- {vimol-0.1.2 → vimol-0.1.3}/src/vimol/editor.py +8 -0
- vimol-0.1.3/src/vimol/file_browser.py +65 -0
- {vimol-0.1.2 → vimol-0.1.3}/src/vimol/gl_adapter.py +55 -0
- {vimol-0.1.2 → vimol-0.1.3}/src/vimol/gl_render.py +176 -3
- vimol-0.1.3/src/vimol/glyph_font.py +176 -0
- vimol-0.1.3/src/vimol/glyph_mesh.py +311 -0
- vimol-0.1.3/src/vimol/glyph_outlines.py +171 -0
- vimol-0.1.3/src/vimol/glyphs.py +954 -0
- {vimol-0.1.2 → vimol-0.1.3}/src/vimol/input.py +32 -0
- {vimol-0.1.2 → vimol-0.1.3}/src/vimol/kitty.py +13 -0
- {vimol-0.1.2 → vimol-0.1.3}/src/vimol/molecule.py +27 -0
- {vimol-0.1.2 → vimol-0.1.3}/src/vimol/parsers/pdb.py +10 -0
- {vimol-0.1.2 → vimol-0.1.3}/src/vimol/render.py +108 -47
- vimol-0.1.3/src/vimol/render_glyph.py +409 -0
- vimol-0.1.3/src/vimol/residues.py +399 -0
- {vimol-0.1.2 → vimol-0.1.3}/src/vimol/scene.py +50 -1
- vimol-0.1.3/src/vimol/select.py +267 -0
- vimol-0.1.3/src/vimol/structures.py +802 -0
- {vimol-0.1.2 → vimol-0.1.3}/src/vimol/theme.py +3 -2
- {vimol-0.1.2 → vimol-0.1.3}/src/vimol/viewer.py +1972 -117
- {vimol-0.1.2 → vimol-0.1.3}/src/vimol/widget.py +165 -17
- vimol-0.1.3/src/vimol.egg-info/PKG-INFO +199 -0
- {vimol-0.1.2 → vimol-0.1.3}/src/vimol.egg-info/SOURCES.txt +15 -0
- {vimol-0.1.2 → vimol-0.1.3}/src/vimol.egg-info/requires.txt +3 -0
- vimol-0.1.3/tests/test_add_file.py +380 -0
- vimol-0.1.3/tests/test_align.py +1399 -0
- vimol-0.1.3/tests/test_bonds.py +449 -0
- {vimol-0.1.2 → vimol-0.1.3}/tests/test_editing.py +420 -10
- vimol-0.1.3/tests/test_file_browser.py +84 -0
- vimol-0.1.3/tests/test_glyphs.py +691 -0
- {vimol-0.1.2 → vimol-0.1.3}/tests/test_render_fast.py +33 -8
- {vimol-0.1.2 → vimol-0.1.3}/tests/test_structures.py +56 -0
- {vimol-0.1.2 → vimol-0.1.3}/tests/test_vimol.py +1600 -66
- vimol-0.1.2/PKG-INFO +0 -106
- vimol-0.1.2/README.md +0 -72
- vimol-0.1.2/src/vimol/app.py +0 -268
- vimol-0.1.2/src/vimol/bonds.py +0 -79
- vimol-0.1.2/src/vimol/structures.py +0 -398
- vimol-0.1.2/src/vimol.egg-info/PKG-INFO +0 -106
- {vimol-0.1.2 → vimol-0.1.3}/LICENSE +0 -0
- {vimol-0.1.2 → vimol-0.1.3}/setup.cfg +0 -0
- {vimol-0.1.2 → vimol-0.1.3}/src/vimol/__main__.py +0 -0
- {vimol-0.1.2 → vimol-0.1.3}/src/vimol/_render_fast.py +0 -0
- {vimol-0.1.2 → vimol-0.1.3}/src/vimol/arrows.py +0 -0
- {vimol-0.1.2 → vimol-0.1.3}/src/vimol/camera.py +0 -0
- {vimol-0.1.2 → vimol-0.1.3}/src/vimol/elements.py +0 -0
- {vimol-0.1.2 → vimol-0.1.3}/src/vimol/parsers/__init__.py +0 -0
- {vimol-0.1.2 → vimol-0.1.3}/src/vimol/parsers/mol.py +0 -0
- {vimol-0.1.2 → vimol-0.1.3}/src/vimol/parsers/xyz.py +0 -0
- {vimol-0.1.2 → vimol-0.1.3}/src/vimol/periodic_table.py +0 -0
- {vimol-0.1.2 → vimol-0.1.3}/src/vimol/py.typed +0 -0
- {vimol-0.1.2 → vimol-0.1.3}/src/vimol/templates.py +0 -0
- {vimol-0.1.2 → vimol-0.1.3}/src/vimol.egg-info/dependency_links.txt +0 -0
- {vimol-0.1.2 → vimol-0.1.3}/src/vimol.egg-info/entry_points.txt +0 -0
- {vimol-0.1.2 → vimol-0.1.3}/src/vimol.egg-info/top_level.txt +0 -0
- {vimol-0.1.2 → vimol-0.1.3}/tests/test_gl_render.py +0 -0
- {vimol-0.1.2 → vimol-0.1.3}/tests/test_scene_structures.py +0 -0
vimol-0.1.3/PKG-INFO
ADDED
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: vimol
|
|
3
|
+
Version: 0.1.3
|
|
4
|
+
Summary: A terminal molecular viewer and editor using the Kitty graphics protocol
|
|
5
|
+
Author: vimol contributors
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Keywords: molecular,viewer,editor,terminal,kitty,chemistry,visualization,xyz,pdb,sdf,cli,tui
|
|
8
|
+
Classifier: Development Status :: 4 - Beta
|
|
9
|
+
Classifier: Environment :: Console
|
|
10
|
+
Classifier: Intended Audience :: Science/Research
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: Operating System :: OS Independent
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Topic :: Scientific/Engineering :: Chemistry
|
|
22
|
+
Classifier: Topic :: Scientific/Engineering :: Visualization
|
|
23
|
+
Classifier: Topic :: Multimedia :: Graphics :: Viewers
|
|
24
|
+
Classifier: Typing :: Typed
|
|
25
|
+
Requires-Python: >=3.8
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
License-File: LICENSE
|
|
28
|
+
Requires-Dist: numpy>=1.20
|
|
29
|
+
Requires-Dist: moderngl>=5.6
|
|
30
|
+
Requires-Dist: numba>=0.59
|
|
31
|
+
Provides-Extra: test
|
|
32
|
+
Requires-Dist: pytest>=7; extra == "test"
|
|
33
|
+
Provides-Extra: align
|
|
34
|
+
Requires-Dist: scipy>=1.4; extra == "align"
|
|
35
|
+
Dynamic: license-file
|
|
36
|
+
|
|
37
|
+
# vimol
|
|
38
|
+
|
|
39
|
+
A molecular viewer and editor that runs **in your terminal**. Open an `.xyz`,
|
|
40
|
+
`.pdb`, `.mol` or `.sdf` file and get a shaded, rotatable, editable 3D
|
|
41
|
+
structure right where you are already working — over SSH, in tmux, beside your
|
|
42
|
+
editor.
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
pip install vimol
|
|
46
|
+
vimol molecule.xyz
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+

|
|
50
|
+
|
|
51
|
+
That is the C60 bundled with vimol, which `vimol` opens with no arguments.
|
|
52
|
+
Drag to rotate, scroll to zoom, option-drag empty space to pan, hover an atom
|
|
53
|
+
to identify it, `?` for every binding.
|
|
54
|
+
|
|
55
|
+
You need Python 3.8 or newer and a terminal that speaks the
|
|
56
|
+
[Kitty graphics protocol](https://sw.kovidgoyal.net/kitty/graphics-protocol/) —
|
|
57
|
+
**kitty, Ghostty or WezTerm**. Rendering is pure software (numpy impostor
|
|
58
|
+
raycasting); if a GPU context can be created, an OpenGL path is used
|
|
59
|
+
automatically instead. MIT licensed.
|
|
60
|
+
|
|
61
|
+
## Open a protein that does not know it is one
|
|
62
|
+
|
|
63
|
+

|
|
64
|
+
|
|
65
|
+
An `.xyz` file carries elements and coordinates and nothing else — no residue
|
|
66
|
+
names, no atom names, no chains. Hand vimol one anyway. It looks for the
|
|
67
|
+
`N–Cα–C(=O)` motif in the bond graph, and if it finds a backbone the file opens
|
|
68
|
+
as a cartoon ribbon rather than as a thicket of sticks.
|
|
69
|
+
|
|
70
|
+
Press `6` and each residue is drawn the way a figure would draw it: the
|
|
71
|
+
backbone runs as a ribbon through the Cα atoms, and every side chain links out
|
|
72
|
+
from its Cα to a solid carrying its one-letter code — a plate cut to the shape
|
|
73
|
+
of the ring for the aromatics, a rounded volume built from the real side-chain
|
|
74
|
+
carbons for the rest. Only the carbon skeleton is abstracted. The carboxylate,
|
|
75
|
+
the hydroxyl, the indole N–H and any hydrogen on one of those stay real atoms
|
|
76
|
+
in their element colours, at the exact coordinates in your file.
|
|
77
|
+
|
|
78
|
+
Residue identity is recovered from geometry alone. Walking outward from each Cα
|
|
79
|
+
gives every atom its bond distance from that Cα, which is precisely what the
|
|
80
|
+
Greek letter in a PDB atom name records; the resulting (element, distance)
|
|
81
|
+
signature identifies all twenty residues uniquely. The trp-cage above is PDB
|
|
82
|
+
1RIJ stripped to bare coordinates, and vimol reads it back as
|
|
83
|
+
`ALQELLGQWLKDGGPSSGRPPPS` — character for character the sequence in that
|
|
84
|
+
entry's `SEQRES`. Something with no peptide backbone in it stays
|
|
85
|
+
ball-and-stick and says so.
|
|
86
|
+
|
|
87
|
+
## Line one structure up against a conformer set
|
|
88
|
+
|
|
89
|
+

|
|
90
|
+
|
|
91
|
+
Pass more than one file and they load into a single session, auto-overlaid: the
|
|
92
|
+
active structure in normal element colours, the rest flat-tinted so you can
|
|
93
|
+
tell them apart. Multi-model files — trajectories, NMR ensembles, multi-record
|
|
94
|
+
SDFs — keep every frame, listed down the left. Several files always open in
|
|
95
|
+
ball-and-stick, so add `--style ribbon` when they are proteins, as above.
|
|
96
|
+
|
|
97
|
+
Clicking a file's `ALL` control pulls its whole ensemble into the overlay.
|
|
98
|
+
Then `r` rigidly aligns every tinted structure onto the untinted one and
|
|
99
|
+
reports each RMSD in a `∀RMSD` column beside the list. Above, that is a
|
|
100
|
+
chignolin crystal structure and 72 CREST conformers of it, landing between
|
|
101
|
+
2.1 Å and 3.1 Å. Press `f` to re-fit the view once they are all in one place.
|
|
102
|
+
|
|
103
|
+
To fit on part of a structure instead, press `R` and click atoms on the main
|
|
104
|
+
structure, then `Enter`. vimol finds the matching element-compatible subset in
|
|
105
|
+
each tinted molecule and aligns the whole molecule from that fit, saving it as
|
|
106
|
+
a `⊂RMSD` column you can re-arm later. `Shift+S` offers ready-made selections —
|
|
107
|
+
backbone, backbone + Cβ, heavy atoms, largest ring system — instead of clicking
|
|
108
|
+
atoms yourself.
|
|
109
|
+
`pip install vimol[align]` adds scipy, which speeds up the permutation search;
|
|
110
|
+
without it a numpy fallback does the same work.
|
|
111
|
+
|
|
112
|
+
## Build on a structure
|
|
113
|
+
|
|
114
|
+

|
|
115
|
+
|
|
116
|
+
Editing is on by default. `a` enters append mode, and from there clicking a
|
|
117
|
+
hydrogen grows a new atom in its place, with its own filling hydrogens at
|
|
118
|
+
sensible geometry — one click turns threonine into O-methylthreonine. Clicking
|
|
119
|
+
a heavy atom replaces it, and clicking empty space starts a new molecule. The
|
|
120
|
+
pills in the status bar choose which element and which geometry you are
|
|
121
|
+
building with.
|
|
122
|
+
|
|
123
|
+
Option-drag from one atom to another draws a bond the automatic perception
|
|
124
|
+
would not have made, `x` deletes, `c` relaxes clashes, `u` undoes and `s`
|
|
125
|
+
saves.
|
|
126
|
+
|
|
127
|
+
## Use it as a library
|
|
128
|
+
|
|
129
|
+

|
|
130
|
+
|
|
131
|
+
Three lines put a molecule anywhere on the screen. Build a `Scene` at the pixel
|
|
132
|
+
size you want, park the cursor where its top-left corner belongs, and write:
|
|
133
|
+
|
|
134
|
+
```python
|
|
135
|
+
import os, vimol
|
|
136
|
+
|
|
137
|
+
scene = vimol.Scene(vimol.load("c60.xyz"), 640, 380) # render it off-screen
|
|
138
|
+
scene.style.transparent = True # let the terminal through
|
|
139
|
+
os.write(1, b"\x1b[6;19H" + scene.to_kitty()) # paint at row 6, col 19
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
That is `examples/inset.py`, and the picture above is what it prints.
|
|
143
|
+
`scene.render()` hands you the pixels as a uint8 array instead — `(H, W, 3)`,
|
|
144
|
+
or `(H, W, 4)` with a transparent background as above — and
|
|
145
|
+
`scene.to_png("out.png")` writes a PNG with a stdlib encoder, no Pillow.
|
|
146
|
+
|
|
147
|
+
For a molecule the user can actually turn, keep your own input loop and give
|
|
148
|
+
the widget only the events you want it to have:
|
|
149
|
+
|
|
150
|
+
```python
|
|
151
|
+
from vimol import MoleculeWidget, InputDecoder, MouseEvent
|
|
152
|
+
|
|
153
|
+
widget = MoleculeWidget(mol, width_px, height_px) # no terminal, no loop
|
|
154
|
+
decoder = InputDecoder(pixel=True)
|
|
155
|
+
|
|
156
|
+
for ev in decoder.feed(data): # bytes you read from the tty
|
|
157
|
+
if isinstance(ev, MouseEvent) and inside_my_region(ev):
|
|
158
|
+
widget.handle_mouse(ev, origin=(region_x_px, region_y_px))
|
|
159
|
+
else:
|
|
160
|
+
my_app_handles(ev)
|
|
161
|
+
|
|
162
|
+
os.write(1, widget.to_kitty(cols=region_cols, rows=region_rows))
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
`examples/embed_demo.py` is a complete host application built that way.
|
|
166
|
+
|
|
167
|
+
## Reference
|
|
168
|
+
|
|
169
|
+
| Key | Does |
|
|
170
|
+
|---|---|
|
|
171
|
+
| Drag / arrows / `hjkl` | rotate |
|
|
172
|
+
| Wheel, `+` `-` | zoom |
|
|
173
|
+
| Right or middle drag | pan |
|
|
174
|
+
| `[` `]` | roll |
|
|
175
|
+
| `1` `2` `3` `4` | ball-and-stick, space-filling, licorice, wireframe |
|
|
176
|
+
| `5` `6` | ribbon, lettered residues (proteins) |
|
|
177
|
+
| `f` `z` | re-fit, reset the view |
|
|
178
|
+
| `m` | measure — click 2, 3 or 4 atoms for distance, angle, dihedral |
|
|
179
|
+
| `a` `x` `c` `u` `s` | append, delete, cleanup clashes, undo, save |
|
|
180
|
+
| `r` `R` | align an overlay, or align on picked atoms |
|
|
181
|
+
| `A` `n` `p` | add a file, next and previous structure |
|
|
182
|
+
| `Tab` | focus the structure list |
|
|
183
|
+
| `d` `g` `t` `ctrl-t` | depth cue, hi-quality, transparent background, theme |
|
|
184
|
+
| `?` `q` | help, quit |
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
vimol traj.xyz --spin --style spacefill # spin a trajectory, space-filling
|
|
188
|
+
vimol protein.pdb --style glyph # lettered residues on a ribbon
|
|
189
|
+
vimol a.xyz b.pdb # load both, auto-overlaid
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
Also `--backend cpu|gl|auto`, `--theme dark|light|auto`, `--rotate YAW PITCH`,
|
|
193
|
+
`--frame N`, `--background`, `--transparent`/`--opaque`, `--atom-scale`,
|
|
194
|
+
`--bond-radius`, `--no-depth-cue`, `--no-bonds`, `--bond-tolerance`,
|
|
195
|
+
`--list-formats`.
|
|
196
|
+
|
|
197
|
+
The protein, alignment and editing animations are recorded by
|
|
198
|
+
`scripts/record_demos.py`, which drives a real viewer and rasterizes the bytes
|
|
199
|
+
it writes; `docs/media/demo` holds their inputs.
|
vimol-0.1.3/README.md
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
# vimol
|
|
2
|
+
|
|
3
|
+
A molecular viewer and editor that runs **in your terminal**. Open an `.xyz`,
|
|
4
|
+
`.pdb`, `.mol` or `.sdf` file and get a shaded, rotatable, editable 3D
|
|
5
|
+
structure right where you are already working — over SSH, in tmux, beside your
|
|
6
|
+
editor.
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
pip install vimol
|
|
10
|
+
vimol molecule.xyz
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+

|
|
14
|
+
|
|
15
|
+
That is the C60 bundled with vimol, which `vimol` opens with no arguments.
|
|
16
|
+
Drag to rotate, scroll to zoom, option-drag empty space to pan, hover an atom
|
|
17
|
+
to identify it, `?` for every binding.
|
|
18
|
+
|
|
19
|
+
You need Python 3.8 or newer and a terminal that speaks the
|
|
20
|
+
[Kitty graphics protocol](https://sw.kovidgoyal.net/kitty/graphics-protocol/) —
|
|
21
|
+
**kitty, Ghostty or WezTerm**. Rendering is pure software (numpy impostor
|
|
22
|
+
raycasting); if a GPU context can be created, an OpenGL path is used
|
|
23
|
+
automatically instead. MIT licensed.
|
|
24
|
+
|
|
25
|
+
## Open a protein that does not know it is one
|
|
26
|
+
|
|
27
|
+

|
|
28
|
+
|
|
29
|
+
An `.xyz` file carries elements and coordinates and nothing else — no residue
|
|
30
|
+
names, no atom names, no chains. Hand vimol one anyway. It looks for the
|
|
31
|
+
`N–Cα–C(=O)` motif in the bond graph, and if it finds a backbone the file opens
|
|
32
|
+
as a cartoon ribbon rather than as a thicket of sticks.
|
|
33
|
+
|
|
34
|
+
Press `6` and each residue is drawn the way a figure would draw it: the
|
|
35
|
+
backbone runs as a ribbon through the Cα atoms, and every side chain links out
|
|
36
|
+
from its Cα to a solid carrying its one-letter code — a plate cut to the shape
|
|
37
|
+
of the ring for the aromatics, a rounded volume built from the real side-chain
|
|
38
|
+
carbons for the rest. Only the carbon skeleton is abstracted. The carboxylate,
|
|
39
|
+
the hydroxyl, the indole N–H and any hydrogen on one of those stay real atoms
|
|
40
|
+
in their element colours, at the exact coordinates in your file.
|
|
41
|
+
|
|
42
|
+
Residue identity is recovered from geometry alone. Walking outward from each Cα
|
|
43
|
+
gives every atom its bond distance from that Cα, which is precisely what the
|
|
44
|
+
Greek letter in a PDB atom name records; the resulting (element, distance)
|
|
45
|
+
signature identifies all twenty residues uniquely. The trp-cage above is PDB
|
|
46
|
+
1RIJ stripped to bare coordinates, and vimol reads it back as
|
|
47
|
+
`ALQELLGQWLKDGGPSSGRPPPS` — character for character the sequence in that
|
|
48
|
+
entry's `SEQRES`. Something with no peptide backbone in it stays
|
|
49
|
+
ball-and-stick and says so.
|
|
50
|
+
|
|
51
|
+
## Line one structure up against a conformer set
|
|
52
|
+
|
|
53
|
+

|
|
54
|
+
|
|
55
|
+
Pass more than one file and they load into a single session, auto-overlaid: the
|
|
56
|
+
active structure in normal element colours, the rest flat-tinted so you can
|
|
57
|
+
tell them apart. Multi-model files — trajectories, NMR ensembles, multi-record
|
|
58
|
+
SDFs — keep every frame, listed down the left. Several files always open in
|
|
59
|
+
ball-and-stick, so add `--style ribbon` when they are proteins, as above.
|
|
60
|
+
|
|
61
|
+
Clicking a file's `ALL` control pulls its whole ensemble into the overlay.
|
|
62
|
+
Then `r` rigidly aligns every tinted structure onto the untinted one and
|
|
63
|
+
reports each RMSD in a `∀RMSD` column beside the list. Above, that is a
|
|
64
|
+
chignolin crystal structure and 72 CREST conformers of it, landing between
|
|
65
|
+
2.1 Å and 3.1 Å. Press `f` to re-fit the view once they are all in one place.
|
|
66
|
+
|
|
67
|
+
To fit on part of a structure instead, press `R` and click atoms on the main
|
|
68
|
+
structure, then `Enter`. vimol finds the matching element-compatible subset in
|
|
69
|
+
each tinted molecule and aligns the whole molecule from that fit, saving it as
|
|
70
|
+
a `⊂RMSD` column you can re-arm later. `Shift+S` offers ready-made selections —
|
|
71
|
+
backbone, backbone + Cβ, heavy atoms, largest ring system — instead of clicking
|
|
72
|
+
atoms yourself.
|
|
73
|
+
`pip install vimol[align]` adds scipy, which speeds up the permutation search;
|
|
74
|
+
without it a numpy fallback does the same work.
|
|
75
|
+
|
|
76
|
+
## Build on a structure
|
|
77
|
+
|
|
78
|
+

|
|
79
|
+
|
|
80
|
+
Editing is on by default. `a` enters append mode, and from there clicking a
|
|
81
|
+
hydrogen grows a new atom in its place, with its own filling hydrogens at
|
|
82
|
+
sensible geometry — one click turns threonine into O-methylthreonine. Clicking
|
|
83
|
+
a heavy atom replaces it, and clicking empty space starts a new molecule. The
|
|
84
|
+
pills in the status bar choose which element and which geometry you are
|
|
85
|
+
building with.
|
|
86
|
+
|
|
87
|
+
Option-drag from one atom to another draws a bond the automatic perception
|
|
88
|
+
would not have made, `x` deletes, `c` relaxes clashes, `u` undoes and `s`
|
|
89
|
+
saves.
|
|
90
|
+
|
|
91
|
+
## Use it as a library
|
|
92
|
+
|
|
93
|
+

|
|
94
|
+
|
|
95
|
+
Three lines put a molecule anywhere on the screen. Build a `Scene` at the pixel
|
|
96
|
+
size you want, park the cursor where its top-left corner belongs, and write:
|
|
97
|
+
|
|
98
|
+
```python
|
|
99
|
+
import os, vimol
|
|
100
|
+
|
|
101
|
+
scene = vimol.Scene(vimol.load("c60.xyz"), 640, 380) # render it off-screen
|
|
102
|
+
scene.style.transparent = True # let the terminal through
|
|
103
|
+
os.write(1, b"\x1b[6;19H" + scene.to_kitty()) # paint at row 6, col 19
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
That is `examples/inset.py`, and the picture above is what it prints.
|
|
107
|
+
`scene.render()` hands you the pixels as a uint8 array instead — `(H, W, 3)`,
|
|
108
|
+
or `(H, W, 4)` with a transparent background as above — and
|
|
109
|
+
`scene.to_png("out.png")` writes a PNG with a stdlib encoder, no Pillow.
|
|
110
|
+
|
|
111
|
+
For a molecule the user can actually turn, keep your own input loop and give
|
|
112
|
+
the widget only the events you want it to have:
|
|
113
|
+
|
|
114
|
+
```python
|
|
115
|
+
from vimol import MoleculeWidget, InputDecoder, MouseEvent
|
|
116
|
+
|
|
117
|
+
widget = MoleculeWidget(mol, width_px, height_px) # no terminal, no loop
|
|
118
|
+
decoder = InputDecoder(pixel=True)
|
|
119
|
+
|
|
120
|
+
for ev in decoder.feed(data): # bytes you read from the tty
|
|
121
|
+
if isinstance(ev, MouseEvent) and inside_my_region(ev):
|
|
122
|
+
widget.handle_mouse(ev, origin=(region_x_px, region_y_px))
|
|
123
|
+
else:
|
|
124
|
+
my_app_handles(ev)
|
|
125
|
+
|
|
126
|
+
os.write(1, widget.to_kitty(cols=region_cols, rows=region_rows))
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
`examples/embed_demo.py` is a complete host application built that way.
|
|
130
|
+
|
|
131
|
+
## Reference
|
|
132
|
+
|
|
133
|
+
| Key | Does |
|
|
134
|
+
|---|---|
|
|
135
|
+
| Drag / arrows / `hjkl` | rotate |
|
|
136
|
+
| Wheel, `+` `-` | zoom |
|
|
137
|
+
| Right or middle drag | pan |
|
|
138
|
+
| `[` `]` | roll |
|
|
139
|
+
| `1` `2` `3` `4` | ball-and-stick, space-filling, licorice, wireframe |
|
|
140
|
+
| `5` `6` | ribbon, lettered residues (proteins) |
|
|
141
|
+
| `f` `z` | re-fit, reset the view |
|
|
142
|
+
| `m` | measure — click 2, 3 or 4 atoms for distance, angle, dihedral |
|
|
143
|
+
| `a` `x` `c` `u` `s` | append, delete, cleanup clashes, undo, save |
|
|
144
|
+
| `r` `R` | align an overlay, or align on picked atoms |
|
|
145
|
+
| `A` `n` `p` | add a file, next and previous structure |
|
|
146
|
+
| `Tab` | focus the structure list |
|
|
147
|
+
| `d` `g` `t` `ctrl-t` | depth cue, hi-quality, transparent background, theme |
|
|
148
|
+
| `?` `q` | help, quit |
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
vimol traj.xyz --spin --style spacefill # spin a trajectory, space-filling
|
|
152
|
+
vimol protein.pdb --style glyph # lettered residues on a ribbon
|
|
153
|
+
vimol a.xyz b.pdb # load both, auto-overlaid
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Also `--backend cpu|gl|auto`, `--theme dark|light|auto`, `--rotate YAW PITCH`,
|
|
157
|
+
`--frame N`, `--background`, `--transparent`/`--opaque`, `--atom-scale`,
|
|
158
|
+
`--bond-radius`, `--no-depth-cue`, `--no-bonds`, `--bond-tolerance`,
|
|
159
|
+
`--list-formats`.
|
|
160
|
+
|
|
161
|
+
The protein, alignment and editing animations are recorded by
|
|
162
|
+
`scripts/record_demos.py`, which drives a real viewer and rasterizes the bytes
|
|
163
|
+
it writes; `docs/media/demo` holds their inputs.
|
|
@@ -45,6 +45,7 @@ dependencies = ["numpy>=1.20", "moderngl>=5.6", "numba>=0.59"]
|
|
|
45
45
|
|
|
46
46
|
[project.optional-dependencies]
|
|
47
47
|
test = ["pytest>=7"]
|
|
48
|
+
align = ["scipy>=1.4"]
|
|
48
49
|
|
|
49
50
|
[project.scripts]
|
|
50
51
|
vimol = "vimol.app:main"
|
|
@@ -56,4 +57,4 @@ version = { attr = "vimol.__version__" }
|
|
|
56
57
|
where = ["src"]
|
|
57
58
|
|
|
58
59
|
[tool.setuptools.package-data]
|
|
59
|
-
vimol = ["py.typed"]
|
|
60
|
+
vimol = ["py.typed", "data/c60.xyz"]
|
|
@@ -32,14 +32,19 @@ from . import kitty
|
|
|
32
32
|
from . import elements
|
|
33
33
|
from . import templates
|
|
34
34
|
from . import editor
|
|
35
|
+
from . import select
|
|
36
|
+
from .structures import StructureSet, Structure, Transform, AlignmentResult
|
|
37
|
+
from .align import kabsch, superpose, permutation_search, subset_search
|
|
35
38
|
|
|
36
|
-
__version__ = "0.1.
|
|
39
|
+
__version__ = "0.1.3"
|
|
37
40
|
|
|
38
41
|
__all__ = [
|
|
39
42
|
"Molecule", "VectorField", "Camera", "Renderer", "Style", "Scene", "MoleculeWidget",
|
|
40
43
|
"InputDecoder", "MouseEvent", "KeyEvent", "enable_mouse", "disable_mouse",
|
|
41
44
|
"load", "load_all", "loads", "save", "SUPPORTED_EXTENSIONS", "SAVE_EXTENSIONS",
|
|
42
|
-
"perceive_bonds", "ensure_bonds", "kitty", "elements", "templates", "editor",
|
|
45
|
+
"perceive_bonds", "ensure_bonds", "kitty", "elements", "templates", "editor", "select",
|
|
46
|
+
"StructureSet", "Structure", "Transform", "AlignmentResult", "kabsch",
|
|
47
|
+
"superpose", "permutation_search", "subset_search",
|
|
43
48
|
"view", "__version__",
|
|
44
49
|
]
|
|
45
50
|
|