-
Notifications
You must be signed in to change notification settings - Fork 256
/
dynamic_mesh.py
131 lines (94 loc) · 3.59 KB
/
dynamic_mesh.py
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
# Author: Takanori Nakane
# License: BSD-2 Clause
# Version: 0.3.20120830
'''
Dynamic Mesh
This script was tested on PyMOL 1.2 and 1.5.
Example:
run dynamic_mesh.py
fetch 1hwk, async=0
fetch 1hwk, 1hwk_map, type=2fofc, async=0
dynamic_mesh 1hwk_map, sym_source=1hwk
show sticks, resn 117
show ribbon
zoom chain A and resn 117
Note: On PyMOL <= 1.4, you have to download the electron density
map from the Uppsala Electron Density Server manually.
'''
from __future__ import print_function
from pymol.callback import Callback
from pymol import cmd
from chempy import cpv
class DynamicMesh(Callback):
def __init__(self, map_name, level, radius, name, sym_source):
self.level = level
self.radius = radius
self.map_name = map_name
self.name = name
self.center_name = cmd.get_unused_name('_center')
self.callback_name = cmd.get_unused_name('_cb')
cmd.set("auto_zoom", 0)
cmd.pseudoatom(self.center_name)
cmd.hide("everything", self.center_name)
symmetry = cmd.get_symmetry(sym_source or map_name)
if symmetry:
cmd.set("map_auto_expand_sym", 1)
cmd.set_symmetry(self.center_name, *symmetry)
cmd.set_key("pgup", self.contour_plus)
cmd.set_key("pgdn", self.contour_minus)
self.update()
def load(self):
cmd.load_callback(self, self.callback_name)
def contour_plus(self, d=0.1):
self.level += d
print("Map level: " + str(self.level))
self.update()
def contour_minus(self):
if self.level < 0.15:
return
self.contour_plus(-0.1)
def update(self):
self.center = cmd.get_position()
cmd.alter_state(0, self.center_name, "(x, y, z) = p", space={'p': self.center})
cmd.isomesh(self.name, self.map_name, self.level, self.center_name, carve=self.radius)
def __call__(self):
if self.name not in cmd.get_names('objects'):
cmd.delete(self.callback_name)
cmd.set_key("pgup", lambda: None)
cmd.set_key("pgdn", lambda: None)
return
tmp = cmd.get_position()
r = cpv.distance_sq(self.center, tmp)
if (r > 0.3): # increase this number if it is too slow
self.update()
def get_extent(self):
tmp = cmd.get_position()
return [[i - self.radius for i in tmp], [i + self.radius for i in tmp]]
def dynamic_mesh(map_name, level=1.0, radius=8, name='dynamic_mesh', sym_source=None):
'''
DESCRIPTION
Make 'dynamic' mesh from volumetric data such as electron density map.
The mesh will dynamically follow the center of the view.
Contour level of isomesh can be changed by PageDown and PageUp keys.
NOTE: Crystallographic operations can be applied to the map.
USAGE
dynamic_mesh map_name [, level [, radius [, name [, sym_source ]]]]
ARGUMENTS
map_name = string: name of volumetric object(map) to display
level = float: contour level of isomesh {default: 1.0}
radius = float: radius of isomesh around the center of the view {default: 8}
name = string: name of mesh object {default: dynamic_mesh}
sym_source = string: name of object from which symmetry
information is derived {default: map_name}
EXAMPLE
fetch 1hwk, async=0
fetch 1hwk, 1hwk_map, type=2fofc, async=0
dynamic_mesh 1hwk_map
SEE ALSO
isomesh
'''
cmd.delete(name)
callback = DynamicMesh(map_name, float(level), float(radius), name, sym_source)
callback.load()
cmd.extend('dynamic_mesh', dynamic_mesh)
cmd.auto_arg[0]['dynamic_mesh'] = cmd.auto_arg[1]['isomesh']