OpenStructure
Loading...
Searching...
No Matches
__init__.py
Go to the documentation of this file.
1#------------------------------------------------------------------------------
2# This file is part of the OpenStructure project <www.openstructure.org>
3#
4# Copyright (C) 2008-2020 by the OpenStructure authors
5#
6# This library is free software; you can redistribute it and/or modify it under
7# the terms of the GNU Lesser General Public License as published by the Free
8# Software Foundation; either version 3.0 of the License, or (at your option)
9# any later version.
10# This library is distributed in the hope that it will be useful, but WITHOUT
11# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
13# details.
14#
15# You should have received a copy of the GNU Lesser General Public License
16# along with this library; if not, write to the Free Software Foundation, Inc.,
17# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18#------------------------------------------------------------------------------
19from ._ost_gfx import *
20from .py_gfx_obj import PyGfxObj
21import functools
22
23WHITE=RGB(1.0,1.0,1.0)
24BLACK=RGB(0.0,0.0,0.0)
25GREY=RGB(0.5,0.5,0.5)
26RED=RGB(1.0,0.0,0.0)
27DARKRED=RGB(0.5,0.0,0.0)
28LIGHTRED=RGB(1.0,0.5,0.5)
29GREEN=RGB(0.0,1.0,0.0)
30DARKGREEN=RGB(0.0,0.5,0.0)
31LIGHTGREEN=RGB(0.5,1.0,0.5)
32BLUE=RGB(0.0,0.0,1.0)
33DARKBLUE=RGB(0.0,0.0,0.5)
34LIGHTBLUE=RGB(0.5,0.5,1.0)
35YELLOW=RGB(1.0,1.0,0.0)
36DARKYELLOW=RGB(0.5,0.5,0.0)
37LIGHTYELLOW=RGB(1.0,1.0,0.5)
38CYAN=RGB(0.0,1.0,1.0)
39DARKCYAN=RGB(0.0,0.5,0.5)
40LIGHTCYAN=RGB(0.5,1.0,1.0)
41MAGENTA=RGB(1.0,0.0,1.0)
42DARKMAGENTA=RGB(0.5,0.0,0.5)
43LIGHTMAGENTA=RGB(1.0,0.5,1.0)
44PURPLE=MAGENTA
45DARKPURPLE=DARKMAGENTA
46LIGHTPURPLE=LIGHTMAGENTA
47ORANGE=RGB(1.0,0.5,0.0)
48DARKORANGE=RGB(0.5,0.25,0.0)
49LIGHTORANGE=RGB(1.0,0.75,0.5)
50
51def Stereo(mode,flip=None,alg=None):
52 """
53 Stereo control
54
55 :param mode: 0=off, 1=quad-buffered, 2=interlaced
56 :type mode: int
57 :param flip: invert order of left/right display
58 :type flip: bool
59 :param alg: stereo algorithm (0 or 1)
60 :type param: int
61 """
62 if(flip):
63 Scene().SetStereoFlip(flip)
64 if(alg):
65 Scene().SetStereoAlg(alg)
66
67 Scene().SetStereoMode(mode)
68
69def FitToScreen(gfx_ent, width=None, height=None, margin=0.05):
70 """
71 Setup camera such that it is centered on the graphical entity and the entity
72 fits the entire viewport. The longest axes of the entity are aligned along
73 the x- and y- axes of the screen.
74
75 :param gfx_ent: The graphical entity
76 :type gfx_ent: str or :class:`Entity`
77
78
79 """
80 from ost import geom
81 import math
82 def _XYZ(view, axes):
83 """
84 returns the vectors in x, y and z direction respectively. The smallest
85 vector is in z, then y, and the largest along x.
86 """
87 rows=[axes.GetRow(i) for i in range(3)]
88 lengths=[]
89 for axe in rows:
90 min_proj=geom.Dot(axe, view.atoms[0].pos)
91 max_proj=min_proj
92 for atom in view.atoms[1:]:
93 proj=geom.Dot(axe, atom.pos)
94 min_proj=min(proj, min_proj)
95 max_proj=max(proj, max_proj)
96 lengths.append(max_proj-min_proj)
97 def cmp_x(rhs, lhs):
98 # replaced cmp when porting to Python 3
99 #return cmp(lhs[1], rhs[1])
100 return (lhs[1] > rhs[1]) - (lhs[1] < rhs[1])
101 sorted_axes=sorted(zip(rows, lengths), key=functools.cmp_to_key(cmp_x))
102 return [r*l for r,l in sorted_axes]
103 scene=Scene()
104 if not isinstance(gfx_ent, Entity):
105 gfx_ent=scene[str(gfx_ent)]
106 width=width and width or scene.viewport.width
107 height=height and height or scene.viewport.height
108 atom_positions=geom.Vec3List([atom.pos for atom in gfx_ent.view.atoms])
109 axes=atom_positions.principal_axes
110 sorted_axes=_XYZ(gfx_ent.view, axes)
111 x_bigger_than_y=geom.Length(sorted_axes[0])>geom.Length(sorted_axes[1])
112 if x_bigger_than_y:
113 if width>height:
114 x_axes=geom.Normalize(sorted_axes[0])
115 y_axes=geom.Normalize(sorted_axes[1])
116 else:
117 x_axes=geom.Normalize(sorted_axes[1])
118 y_axes=geom.Normalize(sorted_axes[0])
119 else:
120 if width>height:
121 x_axes=geom.Normalize(sorted_axes[1])
122 y_axes=geom.Normalize(sorted_axes[0])
123 else:
124 x_axes=geom.Normalize(sorted_axes[0])
125 y_axes=geom.Normalize(sorted_axes[1])
126 z_axes=geom.Normalize(geom.Cross(x_axes, y_axes))
127 rotation=geom.Mat3(x_axes[0], x_axes[1], x_axes[2],
128 y_axes[0], y_axes[1], y_axes[2],
129 z_axes[0], z_axes[1], z_axes[2])
130 rtc=geom.Mat4(rotation)
131
132 center=gfx_ent.center
133 aspect=float(width)/float(height)
134 factor_y=1.0/math.tan(math.radians(scene.fov))
135 factor_x=factor_y/aspect
136 z_off=geom.Length(sorted_axes[2])*0.5
137 rtc[0,3]=center[0]
138 rtc[1,3]=center[1]
139 rtc[2,3]=center[2]
140 rtc[3,0]=0
141 rtc[3,1]=0
142 rtc[3,2]=-(max(factor_x*(1+margin)*geom.Length(sorted_axes[0]),
143 factor_y*(1+margin)*geom.Length(sorted_axes[1]))+z_off)
144 scene.SetRTC(rtc)
145
146
148 def __init__(self, node_list, name):
149 self._node_list=node_list
150 self._name=name
151
152 def __iter__(self):
153 for node in self._node_list:
154 yield getattr(node, self._name)
155
156 def __call__(self, *args, **kwargs):
157 for node in self._node_list:
158 bound_method=getattr(node, self._name)
159 bound_method(*args, **kwargs)
160
161class GfxNodeListProxy(object):
162 def __init__(self, node_list):
163 self._nodes=node_list
164
165 def __getattr__(self, name):
166 if name.startswith('_'):
167 return super(GfxNodeListProxy, self).__getattr__(name)
168 return GfxNodeListAttrProxy(self._nodes, name)
169
170 def __setattr__(self, name, value):
171 if name.startswith('_'):
172 super(GfxNodeListProxy, self).__setattr__(name, value)
173 for node in self._nodes:
174 setattr(node, name, value)
175
176def _Match(scene, pattern="*"):
177 import os
178 import fnmatch
179 def _Recurse(path, node, pattern):
180 matches=[]
181 for child in node.children:
182 full_name=os.path.join(path, child.name)
183 if fnmatch.fnmatchcase(full_name, pattern):
184 matches.append(child)
185 matches.extend(_Recurse(full_name, child, pattern))
186 return matches
187 return GfxNodeListProxy(_Recurse("", Scene().root_node, pattern))
188
189SceneSingleton.Match=_Match
190
191def _to_vec3(p):
192 import ost.geom
193 if isinstance(p,ost.geom.Vec3):
194 return p
195 else:
196 try:
197 return ost.geom.Vec3(p[0],p[1],p[2])
198 except:
199 raise TypeError("expected either a sequence or a geom.Vec3 object")
200
201
202def _primlist_add_point(self,pos,color=None):
203 pos=_to_vec3(pos)
204 if not color:
205 color=WHITE
206 self._add_point(pos,color)
207
208def _primlist_add_line(self,pos1,pos2,color1=None,color2=None,color=None):
209 pos1=_to_vec3(pos1)
210 pos2=_to_vec3(pos2)
211 if not color:
212 color=WHITE
213 if not color1:
214 color1=color
215 if not color2:
216 color2=color1
217 self._add_line(pos1,pos2,color1,color2)
218
219def _primlist_add_sphere(self,cen,radius=1.0,color=None):
220 pos=_to_vec3(cen)
221 if not color:
222 color=WHITE
223 self._add_sphere(pos,radius,color)
224
225def _primlist_add_cyl(self,pos1,pos2,radius1=None,radius2=None,radius=None,color1=None,color2=None,color=None,):
226 pos1=_to_vec3(pos1)
227 pos2=_to_vec3(pos2)
228 if radius is None:
229 radius=1.0
230 if radius1 is None:
231 radius1=radius
232 if radius2 is None:
233 radius2=radius1
234 if not color:
235 color=WHITE
236 if not color1:
237 color1=color
238 if not color2:
239 color2=color1
240 self._add_cyl(pos1,pos2,radius1,radius2,color1,color2)
241
242def _primlist_add_text(self,text,pos,color=None,point_size=None):
243 pos=_to_vec3(pos)
244 if not color:
245 color=WHITE
246 if not point_size:
247 point_size=1.0
248 self._add_text(text,pos,color,point_size)
249
250PrimList.AddPoint=_primlist_add_point
251PrimList.AddLine=_primlist_add_line
252PrimList.AddSphere=_primlist_add_sphere
253PrimList.AddCyl=_primlist_add_cyl
254PrimList.AddText=_primlist_add_text
255
256# entity reset
257
258def _entity_reset(self,*args,**kwargs):
259 import ost.mol as mol
260 eh=None
261 ev=None
262 qr=None
263 qf=None
264 for a in args:
265 if isinstance(a,mol.Query):
266 if qr:
267 raise TypeError("Reset: more than one query string given")
268 qr=a
269 elif isinstance(a,mol.EntityHandle):
270 if eh:
271 raise TypeError("Reset: more than one entity handle given")
272 eh=a
273 elif isinstance(a,mol.EntityView):
274 if ev:
275 raise TypeError("Reset: more than one entity view given")
276 ev=a
277 elif isinstance(a,str):
278 if qr:
279 raise TypeError("Reset: more than one query string given")
280 qr=mol.Query(a)
281 elif isinstance(a,int):
282 if qf:
283 raise TypeError("Reset: more than one QueryFlags given")
284 qf=a
285 else:
286 raise TypeError("Reset: unknown option of type '%s' given"%type(a))
287
288 for key,val in kwargs.items():
289 if key=="entity":
290 if not isinstance(val,mol.EntityHandle):
291 raise TypeError("Reset: expected mol.EntityHandle for 'entity' option")
292 if eh:
293 raise TypeError("Reset: more than one entity handle given")
294 eh=val
295 elif key=="view":
296 if not isinstance(val,mol.EntityView):
297 raise TypeError("Reset: expected mol.EntityView for 'view' option")
298 if ev:
299 raise TypeError("Reset: more than one entity view given")
300 ev=val
301 elif key=="query":
302 if isinstance(val,mol.Query):
303 pass
304 elif isinstance(val,str):
305 val=mol.Query(val)
306 else:
307 raise TypeError("Reset: expected mol.Query or string for 'query' option")
308 if qr:
309 raise TypeError("Reset: more than one query string given")
310 qr=val
311 elif key=="query_flags":
312 if not isinstance(val,int):
313 raise TypeError("Reset: expected integer for 'query_flags' option")
314 if qf:
315 raise TypeError("Reset: more than one query flags given")
316 qf=val
317 else:
318 raise TypeError("Reset: unknown key '%s'"%key)
319
320 if eh and ev:
321 raise TypeError("Reset: entity and view are mutually exclusive options")
322
323 if ev:
324 self._reset4(ev)
325 else:
326 if not eh:
327 eh = self.query_view.entity
328 if not qr:
329 qr = self.query_view.query
330 if not qf:
331 qf = self.query_view.GetFlags()
332 self._reset3(eh,qr,qf)
333
334Entity.Reset=_entity_reset
335
336def _scene_export(self,*args,**kwargs):
337 """
338 scene.Export(Exporter)
339 scene.Export("file.png")
340 scene.Export("file.png",(width,height),samples=0,transparency=False)
341 deprecated:
342 scene.Export("file.png",width,height,samples=0,transparency=False)
343 scene.Export("file.png",width,height,transparency)
344 """
345 scene=Scene()
346 tp=False
347 sa=0
348 if "tp" in kwargs:
349 tp=int(kwargs["tp"])
350 if "transparency" in kwargs:
351 tp=int(kwargs["transparency"])
352 if "samples" in kwargs:
353 sa=int(kwargs["samples"])
354
355 if len(args)==1:
356 if isinstance(args[0],Exporter):
357 scene._export_via_exporter(args[0])
358 return
359 elif type(args[0])==type(""):
360 scene._export_screen(args[0],tp)
361 return
362 elif len(args)==2:
363 if type(args[0]==type("")):
364 # assume second argument is a dimension
365 width=int(args[1][0])
366 height=int(args[1][1])
367 scene._export_buffer(args[0],width,height,sa,tp)
368 return
369 elif len(args)==3:
370 if type(args[0]==type("")):
371 width=int(args[1])
372 height=int(args[2])
373 scene._export_buffer(args[0],width,height,sa,tp)
374 return
375 elif len(args)==4:
376 if type(args[0]==type("")):
377 width=int(args[1])
378 height=int(args[2])
379 tp=int(args[3])
380 scene._export_buffer(args[0],width,height,sa,tp)
381 return
382 # getting here indicates an error
383 raise RuntimeError("""invalid arguments to scene.Export; expected one of
384 Export(gfx.Exporter)
385 Export('file.png')
386 Export('file.png',(width,height),samples=0, transparency=False)
387 Export('file.png',width,height,samples=0, transparency=False) -> deprecated
388 Export('file.png',width,height,transparency) -> deprecated
389 """)
390
391SceneSingleton.Export=_scene_export
392
393import __main__ as main_mod
394main_mod.scene=Scene()
395main_mod.scene.Stereo=Stereo
396
397import ost as ost_mod
398ost_mod.scene=Scene()
399ost_mod.scene.Stereo=Stereo
400
401def GostExporter(file,scale=1.0,to_origin=True):
402 e=GostExporter_(file)
403 e.scale=scale
404 e.to_origin=to_origin
405 return e
406
407def ColladaExporter(file,scale=1.0,to_origin=True):
408 e=ColladaExporter_(file)
409 e.scale=scale
410 e.to_origin=to_origin
411 return e
412
414 return go.IsVisible()
415
416def _go_set_vis(go,flag):
417 if flag:
418 go.Show()
419 else:
420 go.Hide()
421
422GfxObj.visible=property(_go_get_vis,_go_set_vis)
423
424
__call__(self, *args, **kwargs)
Definition __init__.py:156
__init__(self, node_list, name)
Definition __init__.py:148
__init__(self, node_list)
Definition __init__.py:162
__setattr__(self, name, value)
Definition __init__.py:170
main class for organization and root for the graphical display
Definition scene.hh:80
Protein or molecule.
definition of EntityView
Selection Query.
Definition query.hh:74
Vec3 Cross(const Vec3 &v1, const Vec3 &v2)
vector cross product
Definition vecmat3_op.hh:85
Real Length(const Vec2 &v)
returns length of vector
Definition vecmat2_op.hh:41
Real DLLEXPORT_OST_GEOM Dot(const Quat &q0, const Quat &q1)
Quat DLLEXPORT_OST_GEOM Normalize(const Quat &q)
_go_set_vis(go, flag)
Definition __init__.py:416
_to_vec3(p)
Definition __init__.py:191
_Match(scene, pattern="*")
Definition __init__.py:176
FitToScreen(gfx_ent, width=None, height=None, margin=0.05)
Definition __init__.py:69
_primlist_add_text(self, text, pos, color=None, point_size=None)
Definition __init__.py:242
_scene_export(self, *args, **kwargs)
Definition __init__.py:336
_primlist_add_line(self, pos1, pos2, color1=None, color2=None, color=None)
Definition __init__.py:208
_primlist_add_point(self, pos, color=None)
Definition __init__.py:202
_primlist_add_cyl(self, pos1, pos2, radius1=None, radius2=None, radius=None, color1=None, color2=None, color=None)
Definition __init__.py:225
_go_get_vis(go)
Definition __init__.py:413
_entity_reset(self, *args, **kwargs)
Definition __init__.py:258
Color DLLEXPORT_OST_GFX RGB(float r, float g, float b)
RGB color spec from floats (0.0-1.0)
_primlist_add_sphere(self, cen, radius=1.0, color=None)
Definition __init__.py:219