1
2
3
4
5 """Visualization system for Structure objects.
6 """
7 from __future__ import generators
8
9 import copy
10 import math
11
12 try:
13 import numpy
14 try:
15 from numpy.oldnumeric import linear_algebra as linalg
16 except ImportError:
17 from numpy.linalg import old as linalg
18 except ImportError:
19 import NumericCompat as numpy
20 from NumericCompat import linalg
21
22 import Library
23 import GeometryDict
24 import AtomMath
25 import Structure
26 import Gaussian
27 import Colors
28
29
30
31 PROP_OPACITY_RANGE = "0.0-1.0,0.1"
32 PROP_LINE_RANGE = "1.0-10.0,1.0"
33 PROP_PROBABILTY_RANGE = "1-99,1"
34 PROP_FRAC_RANGE = "0-100,1"
35
36
38 """Property cache/routing dictionary
39 """
41 self.gl_object = gl_object
42
45
46
48 """This value means a property should use its default value.
49 """
50 pass
51
52
54 """Base class for all OpenGL rendering objects. It combines a
55 composite-style tree structure with a system for setting properties.
56 The properties are used for the specific OpenGL drawing objects
57 to control color, position, line width, etc... Implementing properties
58 requres the GLProperties object which is the access object for the
59 properties.
60 """
61
62 PropertyDefault = GLPropertyDefault()
63
65 object.__init__(self)
66
67 self.__globject_parent = None
68 self.__globject_children = []
69
70 self.properties = GLPropertyDict(self)
71 self.__globject_properties_id = str(id(self))
72 self.__globject_properties_name = None
73 self.__globject_properties = []
74 self.__globject_properties_callbacks = []
75
76 self.glo_install_properties()
77
79 """Returns the GLObject name.
80 """
81 if self.__globject_properties_name is not None:
82 return self.__globject_properties_name
83 elif self.__globject_properties_id is not None:
84 return "%s(%s)" % (self.__class__.__name__, self.__globject_properties_id)
85 else:
86 return self.__class__.__name__
87
89 """Sets the GLObject name.
90 """
91 self.__globject_properties_name = name
92
94 assert isinstance(child, GLObject)
95 assert child!=self
96 assert self.glo_is_descendant_of(child) is False
97 assert child.__globject_parent is None
98 child.__globject_parent = self
99 self.__globject_children.append(child)
100
102 """Adds a child GLObject to the beginning of the GLObject's
103 child list.
104 """
105 assert isinstance(child, GLObject)
106 assert child!=self
107 assert self.glo_is_descendant_of(child) is False
108 assert child.__globject_parent is None
109 child.__globject_parent = self
110 self.__globject_children.insert(0, child)
111
113 """Adds a child GLObject to the end of the GLObject's child list.
114 """
115 assert isinstance(child, GLObject)
116 assert child!=self
117 assert self.glo_is_descendant_of(child) is False
118 assert child.__globject_parent is None
119 child.__globject_parent = self
120 self.__globject_children.append(child)
121
123 """Removes the child GLObject.
124 """
125 assert isinstance(child, GLObject)
126 assert child.__globject_parent==self
127 child.__globject_parent = None
128 self.__globject_children.remove(child)
129
131 """The GLObject removes itself from its parent.
132 """
133 parent = self.__globject_parent
134 if parent is None:
135 return
136 parent.glo_remove_child(self)
137
139 """Iterate immediate children.
140 """
141 return iter(self.__globject_children)
142
144 """Preorder Traversal for GLObject composite.
145 """
146 for child1 in self.__globject_children:
147 yield child1
148 for child2 in child1.glo_iter_preorder_traversal():
149 yield child2
150
152 """Returns the depth, the root composite is depth 0.
153 """
154 depth = 0
155 ancestor = self.__globject_parent
156 while ancestor:
157 depth += 1
158 ancestor = ancestor.parent
159 return depth
160
162 """Returns the number of children (degree).
163 """
164 return len(self.__globject_children)
165
173
175 """Returns the root GLObject.
176 """
177 gl_object = self
178 while gl_object.__globject_parent:
179 gl_object = gl_object.__globject_parent
180 return gl_object
181
183 """Returns the parent GLObject.
184 """
185 return self.__globject_parent
186
188 """Returns the tree-path to the composite as a list of its
189 parent composites.
190 """
191 path_list = [self]
192 parent = self.__globject_parent
193 while parent:
194 path_list.insert(0, parent)
195 parent = parent.__globject_parent
196 return path_list
197
199 """Returns the tree-path to the GLObject as a list of its
200 integer indexes.
201 """
202 ipath_list = []
203 child = self
204 parent = child.__globject_parent
205 while parent:
206 ipath_list.insert(0, parent.__globject_children.index(child))
207 child = parent
208 parent = parent.__globject_parent
209 return ipath_list
210
212 """Returns a list of the parent GLObjects back to the root.
213 """
214 parent_list = []
215 composite = self
216 while composite.__globject_parent:
217 composite = composite.__globject_parent
218 parent_list.append(composite)
219 return parent_list
220
222 """Returns the lowest common ancesotry of self and argument
223 composite.
224 """
225 assert isinstance(gl_object, GLObject)
226
227 pl1 = self.glo_get_parent_list()
228 pl2 = gl_object.getParentList()
229 pl1.reverse()
230 pl2.reverse()
231
232 ancestor = None
233 for i in xrange(min(len(pl1), len(pl2))):
234 if pl1[i] == pl2[i]:
235 ancestor = pl1[i]
236 else:
237 break
238
239 return ancestor
240
242 """Returns true if self composite is a decent of argument GLObject.
243 """
244 assert isinstance(gl_object, GLObject)
245
246 ancestor = self.__globject_parent
247 while ancestor:
248 if ancestor==gl_object:
249 return True
250 ancestor = ancestor.__globject_parent
251 return False
252
254 """Set the property name for this GLObject.
255 """
256 self.__globject_properties_id = gl_object_id
257
259 """Returns the properties ID of this object.
260 """
261 return self.__globject_properties_id
262
264 """Called by GLObject.__init__ to install properties.
265 """
266 pass
267
269 """Adds a new property to the GLObject. The prop_desc is a dictionary
270 with attributes describing the property. See comments in source code
271 for a description of the key values for property descriptions.
272 """
273 assert prop_desc["name"] not in self.properties
274
275
276
277 prop_desc["read_only"] = prop_desc.get("read_only", False)
278
279
280
281 prop_desc["update_on_changed"] = prop_desc.get("update_on_changed", True)
282
283
284
285 prop_desc["update_on_set"] = prop_desc.get("update_on_set", False)
286
287
288 prop_desc["update_on_init"] = prop_desc.get("update_on_init", True)
289
290 self.__globject_properties.append(prop_desc)
291
293 """Iterates over all property descriptions.
294 """
295 return iter(self.__globject_properties)
296
298 """Return the property description dictionary for the given
299 property name.
300 """
301 for prop_desc in self.__globject_properties:
302 if prop_desc["name"]==name:
303 return prop_desc
304 return None
305
307 """Link the value of the GLObject's property to the value of
308 a child property.
309 """
310 prop_desc = self.glo_get_property_desc(name)
311 if prop_desc is None:
312 raise ValueError, "GLObject.glo_link_child_property(x, y, z) parent has no property: %s" % (name)
313
314 link_dict = {"gl_object": child_gl_object_id,
315 "name": child_name}
316
317 try:
318 prop_desc["link"].append(link_dict)
319 except KeyError:
320 prop_desc["link"] = [link_dict]
321
323 """Returns the child GLObject matching the given gl_object_id.
324 """
325 for gl_object in self.glo_iter_children():
326 if gl_object.__globject_properties_id==gl_object_id:
327 return gl_object
328 return None
329
331 """Returns the object at the given path, or None if the object does
332 not exist.
333 """
334 child = self
335
336 for glo_id in glo_id_path.split("/"):
337 parent = child
338 child = parent.glo_get_child(glo_id)
339 if child is None:
340 return False
341
342 return child
343
345 """This is a special form of update which propagates all linked
346 values, not just the changed ones.
347 """
348 updates = {}
349 actions = []
350
351 for prop_desc in self.__globject_properties:
352 name = prop_desc["name"]
353
354
355 if args.has_key(name):
356 if isinstance(args[name], GLPropertyDefault):
357 self.properties[name] = prop_desc["default"]
358 else:
359 self.properties[name] = args[name]
360 else:
361 self.properties[name] = prop_desc["default"]
362
363
364 if prop_desc["update_on_init"] is True:
365 updates[name] = self.properties[name]
366
367
368
369 if isinstance(prop_desc["action"], str):
370 if prop_desc["action"] not in actions:
371 actions.append(prop_desc["action"])
372
373 elif isinstance(prop_desc["action"], list):
374 for prop_action in prop_desc["action"]:
375 if prop_action not in actions:
376 actions.append(prop_action)
377
378
379 try:
380 linked_props = prop_desc["link"]
381 except KeyError:
382 pass
383 else:
384 for linked_prop in linked_props:
385 child = self.glo_get_child(linked_prop["gl_object"])
386 child_name = linked_prop["name"]
387 child.glo_update_properties(**{ child_name: self.properties[name] })
388
389 if len(updates)>0:
390 for func in self.__globject_properties_callbacks:
391 func(updates, actions)
392
394 """Update property values and trigger update callbacks.
395 """
396 updates = {}
397 actions = []
398
399
400 for prop_desc in self.__globject_properties:
401 name = prop_desc["name"]
402
403
404 if args.has_key(name) is False:
405 continue
406
407
408
409
410
411
412
413 do_update = False
414
415 if prop_desc["update_on_set"] is True:
416 do_update = True
417
418 elif prop_desc["update_on_changed"] is True:
419
420
421 if isinstance(self.properties[name], numpy.ndarray):
422 if not numpy.allclose(self.properties[name], args[name]):
423 do_update = True
424
425 elif self.properties[name]!=args[name]:
426 do_update = True
427
428 if do_update is True:
429
430 if isinstance(args[name], GLPropertyDefault):
431 self.properties[name] = prop_desc["default"]
432 else:
433 self.properties[name] = args[name]
434
435 updates[name] = self.properties[name]
436
437
438
439 if isinstance(prop_desc["action"], str):
440 if prop_desc["action"] not in actions:
441 actions.append(prop_desc["action"])
442
443 elif isinstance(prop_desc["action"], list):
444 for prop_action in prop_desc["action"]:
445 if prop_action not in actions:
446 actions.append(prop_action)
447
448 if do_update is True:
449
450 try:
451 linked_props = prop_desc["link"]
452 except KeyError:
453 pass
454 else:
455 for linked_prop in linked_props:
456 child = self.glo_get_child(linked_prop["gl_object"])
457 child_name = linked_prop["name"]
458 child.glo_update_properties(**{ child_name: self.properties[name] })
459
460 if len(updates)>0:
461 for func in self.__globject_properties_callbacks:
462 func(updates, actions)
463
465 """
466 """
467 path = glo_id_path.split("/")
468 prop_name = path[-1]
469 path = path[:-1]
470
471
472 child = self
473 for glo_id in path:
474 parent = child
475 child = parent.glo_get_child(glo_id)
476 if child is None:
477 break
478 if child is None:
479 return False
480
481 child.glo_update_properties(**{prop_name: value})
482
484 """Adds a function which is called whenever property values change.
485 The function is called with two arguments: a updates dictionary
486 containing all updated properties and the values they were changed
487 to, and a actions list which contains a unique list of action
488 key words forme self.prop_list = []
489 self.callback_list = [] from the action fields of the updated
490 properties.
491 """
492 self.__globject_properties_callbacks.append(func)
493
495 """Removes the update callback.
496 """
497 self.__globject_properties_callbacks.remove(func)
498
500 """Returns the parent GLStructure object, or None if the GLObject
501 is not a child of a GLStructure.
502 """
503 gl_object = self
504 while gl_object is not None and not isinstance(gl_object, GLStructure):
505 gl_object = gl_object.__globject_parent
506 return gl_object
507
508
510 """Fundamental OpenGL rigid entity.
511 """
512
513 gldl_color_list = Colors.COLOR_NAMES_CAPITALIZED[:]
514
524
533
542
544 self.glo_add_property(
545 { "name" : "visible",
546 "desc": "Visible",
547 "catagory": "Show/Hide",
548 "type": "boolean",
549 "default": True,
550 "action": "redraw" })
551 self.glo_add_property(
552 { "name" : "origin",
553 "desc": "Origin",
554 "type": "array(3)",
555 "hidden": True,
556 "default": numpy.zeros(3, float),
557 "action": "redraw" })
558 self.glo_add_property(
559 { "name" : "axes",
560 "desc": "Rotation Axes",
561 "type": "array(3,3)",
562 "hidden": True,
563 "default": numpy.identity(3, float),
564 "action": "redraw" })
565 self.glo_add_property(
566 { "name" : "rot_x",
567 "desc": "Degrees Rotation About X Axis",
568 "type": "float",
569 "hidden": True,
570 "default": 0.0,
571 "action": "redraw" })
572 self.glo_add_property(
573 { "name" : "rot_y",
574 "desc": "Degrees Rotation About Y Axis",
575 "type": "float",
576 "hidden": True,
577 "default": 0.0,
578 "action": "redraw" })
579 self.glo_add_property(
580 { "name" : "rot_z",
581 "desc": "Degrees Rotation About Z Axis",
582 "type": "float",
583 "hidden": True,
584 "default": 0.0,
585 "action": "redraw" })
586 self.glo_add_property(
587 { "name" : "visible_distance",
588 "desc": "",
589 "type": "float",
590 "hidden": True,
591 "default": 0.0,
592 "action": "redraw" })
593
595 """Properties update callback.
596 """
597
598 if "recompile" in actions:
599 self.gldl_draw_method_delete_compiled_all_drivers()
600 self.gldl_redraw()
601
602
603 elif "redraw" in actions:
604 self.gldl_redraw()
605
606
607
608
609 for draw_method in self.gldl_draw_method_list:
610 if draw_method["recompile_action"] in actions:
611 self.gldl_redraw()
612
613 draw_method["expiration_id"] += 1
614
615
616 op = draw_method["opacity_property"]
617 if op is not None:
618 draw_method["transparent"] = self.properties[op]<1.0
619
621 """Triggers a redraw of the GLViewer
622 """
623 gl_viewer = self.glo_get_root()
624 if isinstance(gl_viewer, GLViewer):
625 gl_viewer.glv_redraw()
626
628 """Returns the root GLViewer object.
629 """
630 return self.glo_get_root()
631
633 """Returns the property value as a RGBF triplet.
634 """
635 try:
636 colorx = self.properties[prop_name]
637 except KeyError:
638 raise KeyError, "gldl_property_color_rgbf: bad prop_name %s" % (prop_name)
639
640 try:
641 return Colors.COLOR_RGBF[colorx.lower()]
642 except KeyError:
643 pass
644
645 try:
646 r, g, b = colorx.split(",")
647 except ValueError:
648 pass
649 else:
650 try:
651 return (float(r), float(g), float(b))
652 except ValueError:
653 return (1.0, 0.0, 0.0)
654
655 raise TypeError, "gldl_property_color_rgbf: bad colorx %s" % (str(colorx))
656
658 """Override in children to install draw methods for a GLDrawList.
659 """
660 pass
661
663 """Installs a draw method to compile and render a OpenGL draw listlist.
664 keys:
665 name: text description of the method
666 func: the method to invoke to render the draw list
667 tranparent: True if the draw list is drawing transparent
668
669 private values:
670 gl_draw_list_id: OpenGL Drawlist ID
671 """
672 assert draw_method.has_key("name")
673 assert draw_method.has_key("func")
674
675 draw_method["transparent"] = draw_method.get("transparent", False)
676 draw_method["no_gl_compile"] = draw_method.get("no_gl_compile", False)
677 draw_method["visible_property"] = draw_method.get("visible_property", None)
678 draw_method["recompile_action"] = draw_method.get("recompile_action", None)
679 draw_method["opacity_property"] = draw_method.get("opacity_property", None)
680 draw_method["multidraw_iter"] = draw_method.get("multipdraw_iter", None)
681 draw_method["multidraw_all_iter"] = draw_method.get("multipdraw_all_iter", None)
682
683
684
685 draw_method["expiration_id"] = 1
686
687
688 draw_method["driver_list"] = []
689
690 self.gldl_draw_method_list.append(draw_method)
691
693 """Returns the draw metod of the given name or None if not found.
694 """
695 for draw_method in self.gldl_draw_method_list:
696 if draw_method["name"]==draw_method_name:
697 return draw_method
698 return None
699
701 """Compiles a draw method.
702 """
703 assert self.driver is not None
704
705 mid = self.driver.glr_compile_start(draw_method)
706 draw_method["func"]()
707 self.driver.glr_compile_end()
708 draw_method["driver_list"].append(self.driver)
709
711 """Deletes the compiled draw list in the current driver.
712 """
713 assert self.driver is not None
714
715 if self.driver.glr_compile_exists(draw_method):
716 self.driver.glr_compile_delete(draw_method)
717 draw_method["driver_list"].remove(self.driver)
718
720 """
721 """
722 for draw_method in self.gldl_draw_method_list:
723 for driver in draw_method["driver_list"]:
724 if driver.glr_compile_exists(draw_method):
725 driver.glr_compile_delete(draw_method)
726
728 """Rotate and translate to the correct position for drawing.
729 """
730 assert self.driver is not None
731
732 self.driver.glr_push_matrix()
733
734 if not numpy.allclose(self.properties["origin"], numpy.zeros(3, float)):
735 self.driver.glr_translate(self.properties["origin"])
736
737 axes = self.properties["axes"]
738 if not numpy.allclose(axes, numpy.identity(3, float)):
739 self.driver.glr_rotate_axis(self.properties["rot_x"], axes[0])
740 self.driver.glr_rotate_axis(self.properties["rot_y"], axes[1])
741 self.driver.glr_rotate_axis(self.properties["rot_z"], axes[2])
742
744 """Pop the roatated/translated position.
745 """
746 assert self.driver is not None
747
748 self.driver.glr_pop_matrix()
749
779
781 """Render all draw methods.
782 """
783 for draw_method in self.gldl_draw_method_list:
784
785
786
787 visable_property_name = draw_method["visible_property"]
788 if visable_property_name is not None:
789 if self.properties[visable_property_name] is False:
790 continue
791
792
793
794 if draw_method["transparent"]!=transparent:
795 continue
796
797
798
799 if draw_method["no_gl_compile"] is True or not self.driver.glr_compile_supported():
800 draw_method["func"]()
801
802 else:
803 if not self.driver.glr_compile_exists(draw_method):
804 self.gldl_draw_method_compile(draw_method)
805
806 elif not self.driver.glr_compile_current(draw_method):
807 self.gldl_draw_method_delete_compiled(draw_method)
808 self.gldl_draw_method_compile(draw_method)
809
810 self.driver.glr_compile_render(draw_method)
811
813 """When implemented as a iterator in a subclass, each time yield
814 is invoked the GLDrawList and all its decendants will be rendered
815 from whatever OpenGL coordinate system is set in the iterator.
816 """
817 yield True
818
820 """Similar to gldl_iter_multidraw_all, but only this GLDrawList is
821 rendered. The decendant GLDrawLists are rendered normally.
822 """
823 yield True
824
826 """Implement in subclass to draw somthing.
827 """
828 pass
829
831 """Implement in subclass to draw transparent objects.
832 """
833 pass
834
835
837 """Draw orthogonal axes in red = x, green = y, blue = z.
838 """
843
845 GLDrawList.glo_install_properties(self)
846
847 self.glo_add_property(
848 { "name": "line_length",
849 "desc": "Axis Length",
850 "catagory": "Show/Hide",
851 "type": "float",
852 "spin": "1.0-500.0,10.0",
853 "default": 20.0,
854 "action": "recompile" })
855 self.glo_add_property(
856 { "name": "line_width",
857 "desc": "Axis Radius",
858 "catagory": "Show/Hide",
859 "type": "float",
860 "spin": "0.0-5.0,0.1",
861 "default": 0.1,
862 "action": "recompile" })
863 self.glo_add_property(
864 { "name": "color_x",
865 "desc": "X Axis Color",
866 "catagory": "Show/Hide",
867 "type": "enum_string",
868 "default": "Red",
869 "enum_list": self.gldl_color_list,
870 "action": "recompile" })
871 self.glo_add_property(
872 { "name": "color_y",
873 "desc": "Y Axis Color",
874 "catagory": "Show/Hide",
875 "type": "enum_string",
876 "default": "Green",
877 "enum_list": self.gldl_color_list,
878 "action": "recompile" })
879 self.glo_add_property(
880 { "name": "color_z",
881 "desc": "Z Axis Color",
882 "catagory": "Show/Hide",
883 "type": "enum_string",
884 "default": "Blue",
885 "enum_list": self.gldl_color_list,
886 "action": "recompile" })
887
893
895 line_length = self.properties["line_length"]
896 line_width = self.properties["line_width"]
897
898 r, g, b = self.gldl_property_color_rgbf("color_x")
899 self.driver.glr_set_material_rgb(r, g, b)
900 self.driver.glr_axis(
901 numpy.zeros(3, float),
902 numpy.array([line_length, 0.0, 0.0]),
903 line_width)
904
905 r, g, b = self.gldl_property_color_rgbf("color_y")
906 self.driver.glr_set_material_rgb(r, g, b)
907 self.driver.glr_axis(
908 numpy.zeros(3, float),
909 numpy.array([0.0, line_length, 0.0]),
910 line_width)
911
912 r, g, b = self.gldl_property_color_rgbf("color_z")
913 self.driver.glr_set_material_rgb(r, g, b)
914 self.driver.glr_axis(
915 numpy.zeros(3, float),
916 numpy.array([0.0, 0.0, line_length]),
917 line_width)
918
919
921 """Draw unit cell.
922 """
924 self.unit_cell = args["unit_cell"]
925
926 GLDrawList.__init__(self, **args)
927 self.glo_set_name("Unit Cell")
928
929 self.glo_init_properties(
930 crystal_system = self.unit_cell.space_group.crystal_system,
931 space_group = self.unit_cell.space_group.pdb_name,
932
933 a = self.unit_cell.a,
934 b = self.unit_cell.b,
935 c = self.unit_cell.c,
936
937 alpha = self.unit_cell.calc_alpha_deg(),
938 beta = self.unit_cell.calc_beta_deg(),
939 gamma = self.unit_cell.calc_gamma_deg(),
940
941 **args)
942
944 GLDrawList.glo_install_properties(self)
945
946 self.glo_add_property(
947 { "name": "radius",
948 "desc": "Radius",
949 "catagory": "Show/Hide",
950 "type": "float",
951 "default": 0.25,
952 "action": "recompile" })
953
954 self.glo_add_property(
955 { "name": "a_color",
956 "desc": "a Cell Divider Color",
957 "catagory": "Show/Hide",
958 "type": "enum_string",
959 "default": "Red",
960 "enum_list": self.gldl_color_list,
961 "action": "recompile" })
962 self.glo_add_property(
963 { "name": "b_color",
964 "desc": "b Cell Divider Color",
965 "catagory": "Show/Hide",
966 "type": "enum_string",
967 "default": "Green",
968 "enum_list": self.gldl_color_list,
969 "action": "recompile" })
970 self.glo_add_property(
971 { "name": "c_color",
972 "desc": "c Cell Divider Color",
973 "catagory": "Show/Hide",
974 "type": "enum_string",
975 "default": "Blue",
976 "enum_list": self.gldl_color_list,
977 "action": "recompile" })
978
979 self.glo_add_property(
980 { "name": "crystal_system",
981 "desc": "Crystal System",
982 "catagory": "Show/Hide",
983 "read_only": True,
984 "type": "string",
985 "default": "",
986 "action": "" })
987 self.glo_add_property(
988 { "name": "space_group",
989 "desc": "Spacegroup",
990 "catagory": "Show/Hide",
991 "read_only": True,
992 "type": "string",
993 "default": "",
994 "action": "" })
995
996 self.glo_add_property(
997 { "name": "a",
998 "desc": "a",
999 "catagory": "Show/Hide",
1000 "read_only": True,
1001 "type": "float",
1002 "default": 0.0,
1003 "action": "" })
1004 self.glo_add_property(
1005 { "name": "b",
1006 "desc": "b",
1007 "catagory": "Show/Hide",
1008 "read_only": True,
1009 "type": "float",
1010 "default": 0.0,
1011 "action": "" })
1012 self.glo_add_property(
1013 { "name": "c",
1014 "desc": "c",
1015 "catagory": "Show/Hide",
1016 "read_only": True,
1017 "type": "float",
1018 "default": 0.0,
1019 "action": "" })
1020
1021 self.glo_add_property(
1022 { "name": "alpha",
1023 "desc": "alpha",
1024 "catagory": "Show/Hide",
1025 "read_only": True,
1026 "type": "float",
1027 "default": 0.0,
1028 "action": "" })
1029 self.glo_add_property(
1030 { "name": "beta",
1031 "desc": "beta",
1032 "catagory": "Show/Hide",
1033 "read_only": True,
1034 "type": "float",
1035 "default": 0.0,
1036 "action": "" })
1037 self.glo_add_property(
1038 { "name": "gamma",
1039 "desc": "gamma",
1040 "catagory": "Show/Hide",
1041 "read_only": True,
1042 "type": "float",
1043 "default": 0.0,
1044 "action": "" })
1045
1051
1054
1055 - def draw_cell(self, x1, y1, z1, x2, y2, z2):
1056 """Draw the unit cell lines in a rectangle starting at fractional
1057 integer coordinates x1, y1, z1, ending at x2, y2, z2. The first set of
1058 coordinates must be <= the second set.
1059 """
1060 assert x1<=x2 and y1<=y2 and z1<=z2
1061
1062 a = self.unit_cell.calc_frac_to_orth(numpy.array([1.0, 0.0, 0.0]))
1063 b = self.unit_cell.calc_frac_to_orth(numpy.array([0.0, 1.0, 0.0]))
1064 c = self.unit_cell.calc_frac_to_orth(numpy.array([0.0, 0.0, 1.0]))
1065
1066 rad = self.properties["radius"]
1067
1068 rf, gf, bf = self.gldl_property_color_rgbf("a_color")
1069 self.driver.glr_set_material_rgb(rf, gf, bf)
1070 for k in xrange(z1, z2+2):
1071 for j in xrange(y1, y2+2):
1072 p1 = x1*a + j*b + k*c
1073 p2 = (x2+1)*a + j*b + k*c
1074 self.driver.glr_tube(p1, p2, rad)
1075
1076 rf, gf, bf = self.gldl_property_color_rgbf("b_color")
1077 self.driver.glr_set_material_rgb(rf, gf, bf)
1078 for k in xrange(z1, z2+2):
1079 for i in xrange(x1, x2+2):
1080 p1 = i*a + y1*b + k*c
1081 p2 = i*a + (y2+1)*b + k*c
1082 self.driver.glr_tube(p1, p2, rad)
1083
1084 rf, gf, bf = self.gldl_property_color_rgbf("c_color")
1085 self.driver.glr_set_material_rgb(rf, gf, bf)
1086 for j in xrange(y1, y2+2):
1087 for i in xrange(x1, x2+2):
1088 p1 = i*a + j*b + z1*c
1089 p2 = i*a + j*b + (z2+1)*c
1090 self.driver.glr_tube(p1, p2, rad)
1091
1092
1094 """OpenGL renderer for a list of atoms. Optional arguments iare:
1095 color, U, U_color.
1096 """
1097 glal_res_type_color_dict = {
1098 "aliphatic": (0.50, 0.50, 0.50),
1099 "aromatic": (0.75, 0.75, 0.75),
1100 "sulfer-containing": (0.20, 1.00, 0.20),
1101 "alchols": (1.00, 0.60, 0.60),
1102 "acids": (1.00, 0.25, 0.25),
1103 "bases": (0.25, 0.25, 1.00),
1104 "amides": (0.60, 0.60, 1.00)}
1105
1122
1124 GLDrawList.glo_install_properties(self)
1125
1126
1127 self.glo_add_property(
1128 { "name": "atom_origin",
1129 "desc": "Atom Calculation Origin",
1130 "type": "array(3)",
1131 "hidden": True,
1132 "default": None,
1133 "action": ["recompile", "recalc_positions"] })
1134 self.glo_add_property(
1135 { "name": "color",
1136 "desc": "Atom Color",
1137 "catagory": "Colors",
1138 "type": "enum_string",
1139 "default": "Color By Element",
1140 "enum_list": self.glal_atom_color_opts,
1141 "action": "" })
1142
1143 self.glo_add_property(
1144 { "name": "color_setting",
1145 "desc": "Atom Color",
1146 "catagory": "Colors",
1147 "type": "string",
1148 "hidden": True,
1149 "default": "Color By Element",
1150 "action": "recompile" })
1151 self.glo_add_property(
1152 { "name": "color_blue",
1153 "desc": "Color Range Blue",
1154 "catagory": "Colors",
1155 "type": "float",
1156 "default": 0.0,
1157 "action": "recompile" })
1158 self.glo_add_property(
1159 { "name": "color_red",
1160 "desc": "Color Range Red",
1161 "catagory": "Colors",
1162 "type": "float",
1163 "default": 1.0,
1164 "action": "recompile" })
1165
1166 self.glo_add_property(
1167 { "name": "symmetry",
1168 "desc": "Show Symmetry Equivelants",
1169 "catagory": "Show/Hide",
1170 "type": "boolean",
1171 "default": False,
1172 "action": "redraw" })
1173 self.glo_add_property(
1174 { "name": "main_chain_visible",
1175 "desc": "Show Main Chain Atoms",
1176 "catagory": "Show/Hide",
1177 "type": "boolean",
1178 "default": True,
1179 "action": ["recompile", "recalc_positions"] })
1180 self.glo_add_property(
1181 { "name": "oatm_visible",
1182 "desc": "Show Main Chain Carbonyl Atoms",
1183 "catagory": "Show/Hide",
1184 "type": "boolean",
1185 "default": True,
1186 "action": ["recompile", "recalc_positions"] })
1187 self.glo_add_property(
1188 { "name": "side_chain_visible",
1189 "desc": "Show Side Chain Atoms",
1190 "catagory": "Show/Hide",
1191 "type": "boolean",
1192 "default": True,
1193 "action": ["recompile", "recalc_positions"] })
1194 self.glo_add_property(
1195 { "name": "hetatm_visible",
1196 "desc": "Show Hetrogen Atoms",
1197 "catagory": "Show/Hide",
1198 "type": "boolean",
1199 "default": True,
1200 "action": ["recompile", "recalc_positions"] })
1201 self.glo_add_property(
1202 { "name": "water_visible",
1203 "desc": "Show Waters",
1204 "catagory": "Show/Hide",
1205 "type": "boolean",
1206 "default": False,
1207 "action": ["recompile", "recalc_positions"] })
1208 self.glo_add_property(
1209 { "name": "hydrogen_visible",
1210 "desc": "Show Hydrogens",
1211 "catagory": "Show/Hide",
1212 "type": "boolean",
1213 "default": False,
1214 "action": ["recompile", "recalc_positions"] })
1215
1216
1217 self.glo_add_property(
1218 { "name": "labels",
1219 "desc": "Show Atom Lables",
1220 "catagory": "Show/Hide",
1221 "type": "boolean",
1222 "default": False,
1223 "action": "recompile_labels" })
1224 self.glo_add_property(
1225 { "name": "label_size",
1226 "desc": "Label Size",
1227 "catagory": "Labels",
1228 "type": "float",
1229 "default": 5.0,
1230 "action": "recompile_labels" })
1231 self.glo_add_property(
1232 { "name": "label_color",
1233 "desc": "Label Color",
1234 "catagory": "Labels",
1235 "type": "enum_string",
1236 "default": "White",
1237 "enum_list": self.gldl_color_list,
1238 "action": "recompile_labels" })
1239 self.glo_add_property(
1240 { "name": "label_style",
1241 "desc": "Label Style",
1242 "catagory": "Labels",
1243 "type": "enum_string",
1244 "default": "Residue",
1245 "enum_list": ["Residue", "All Atoms", "CA Atoms"],
1246 "action": "recompile_labels" })
1247
1248
1249 self.glo_add_property(
1250 { "name": "lines",
1251 "desc": "Draw Atom Bond Lines",
1252 "catagory": "Show/Hide",
1253 "type": "boolean",
1254 "default": True,
1255 "action": "recompile_lines" })
1256 self.glo_add_property(
1257 { "name": "line_width",
1258 "desc": "Bond Line Size",
1259 "catagory": "Bond Lines",
1260 "type": "float",
1261 "spin": PROP_LINE_RANGE,
1262 "default": 1.0,
1263 "action": "recompile_lines" })
1264
1265
1266 self.glo_add_property(
1267 { "name": "ball_stick",
1268 "desc": "Draw Ball/Sticks",
1269 "catagory": "Show/Hide",
1270 "type": "boolean",
1271 "default": False,
1272 "action": "recompile_ball_stick" })
1273 self.glo_add_property(
1274 { "name": "ball_radius",
1275 "desc": "Atom (Ball) Radius",
1276 "catagory": "Ball/Stick",
1277 "type": "float",
1278 "default": 0.1,
1279 "action": "recompile_ball_stick" })
1280 self.glo_add_property(
1281 { "name": "stick_radius",
1282 "desc": "Bond (Stick) Radius",
1283 "catagory": "Ball/Stick",
1284 "type": "float",
1285 "default": 0.1,
1286 "action": "recompile_ball_stick" })
1287
1288
1289 self.glo_add_property(
1290 { "name": "cpk",
1291 "desc": "Draw CPK Spheres",
1292 "catagory": "Show/Hide",
1293 "type": "boolean",
1294 "default": False,
1295 "action": "recompile_cpk" })
1296 self.glo_add_property(
1297 { "name": "cpk_opacity_occupancy",
1298 "desc": "Set Opacity by Atom Occupancy",
1299 "catagory": "CPK",
1300 "type": "boolean",
1301 "default": False,
1302 "action": "recompile_cpk" })
1303 self.glo_add_property(
1304 { "name": "cpk_scale_radius",
1305 "desc": "Scale CPK Radius",
1306 "catagory": "CPK",
1307 "type": "float",
1308 "range": "0.0-5.0,0.1",
1309 "default": 1.0,
1310 "action": "recompile_cpk" })
1311 self.glo_add_property(
1312 { "name": "cpk_opacity",
1313 "desc": "CPK Sphere Opacity",
1314 "catagory": "CPK",
1315 "type": "float",
1316 "range": PROP_OPACITY_RANGE,
1317 "default": 1.00,
1318 "action": "recompile_cpk" })
1319 self.glo_add_property(
1320 { "name": "sphere_quality",
1321 "desc": "CPK Sphere Quality",
1322 "catagory": "CPK",
1323 "type": "integer",
1324 "range": "5-36,5",
1325 "default": 10,
1326 "action": "recompile_cpk" })
1327
1328
1329 self.glo_add_property(
1330 { "name": "trace",
1331 "desc": "Draw Backbone Trace",
1332 "catagory": "Show/Hide",
1333 "type": "boolean",
1334 "default": False,
1335 "action": "recompile_trace" })
1336 self.glo_add_property(
1337 { "name": "trace_radius",
1338 "desc": "Trace Radius",
1339 "catagory": "Trace",
1340 "type": "float",
1341 "default": 0.2,
1342 "action": "recompile_trace" })
1343 self.glo_add_property(
1344 { "name": "trace_color",
1345 "desc": "Trace Color",
1346 "catagory": "Trace",
1347 "type": "enum_string",
1348 "default": "White",
1349 "enum_list": self.gldl_color_list,
1350 "action": "recompile_trace" })
1351
1352
1353 self.glo_add_property(
1354 { "name": "adp_prob",
1355 "desc": "Isoprobability Magnitude",
1356 "catagory": "ADP",
1357 "type": "integer",
1358 "range": PROP_PROBABILTY_RANGE,
1359 "default": 50,
1360 "action": ["recompile_Uaxes", "recompile_Uellipse"] })
1361 self.glo_add_property(
1362 { "name": "U",
1363 "desc": "Show Thermal Axes",
1364 "catagory": "Show/Hide",
1365 "type": "boolean",
1366 "default": False,
1367 "action": "recompile_Uaxes" })
1368 self.glo_add_property(
1369 { "name": "U_color",
1370 "desc": "Thermal Axes Color",
1371 "catagory": "ADP",
1372 "type": "enum_string",
1373 "default": "White",
1374 "enum_list": self.gldl_color_list,
1375 "action": "recompile_Uaxes" })
1376 self.glo_add_property(
1377 { "name": "ellipse",
1378 "desc": "Show Thermal Ellipsoids",
1379 "catagory": "Show/Hide",
1380 "type": "boolean",
1381 "default": False,
1382 "action": "recompile_Uellipse" })
1383 self.glo_add_property(
1384 { "name": "ellipse_opacity",
1385 "desc": "Thermal Ellipsoid Opacity",
1386 "catagory": "ADP",
1387 "type": "float",
1388 "range": PROP_OPACITY_RANGE,
1389 "default": 1.0,
1390 "action": "recompile_Uellipse" })
1391 self.glo_add_property(
1392 { "name": "rms",
1393 "desc": "Show Thermal Peanuts",
1394 "catagory": "Show/Hide",
1395 "type": "boolean",
1396 "default": False,
1397 "action": "recompile_Urms" })
1398 self.glo_add_property(
1399 { "name": "rms_opacity",
1400 "desc": "Peanut Surface Opacity",
1401 "catagory": "ADP",
1402 "type": "float",
1403 "range": PROP_OPACITY_RANGE,
1404 "default": 1.0,
1405 "action": "recompile_Urms" })
1406 self.glo_add_property(
1407 { "name": "show_sig_u",
1408 "desc": "Show +/- SIGUIJ Ellipsoids",
1409 "catagory": "ADP",
1410 "type": "boolean",
1411 "default": False,
1412 "action": "recompile_Uellipse" })
1413 self.glo_add_property(
1414 { "name": "sig_u_opacity",
1415 "desc": "SIGUIJ Ellipsoid Opacity",
1416 "catagory": "ADP",
1417 "type": "float",
1418 "range": PROP_OPACITY_RANGE,
1419 "default": 0.5,
1420 "action": "recompile_Uellipse" })
1421
1423 self.gldl_draw_method_install(
1424 { "name": "labels",
1425 "func": self.glal_draw_labels,
1426 "no_gl_compile": True,
1427 "transparent": False,
1428 "visible_property": "labels",
1429 "recompile_action": "recompile_labels" })
1430 self.gldl_draw_method_install(
1431 { "name": "lines",
1432 "func": self.glal_draw_lines,
1433 "transparent": False,
1434 "visible_property": "lines",
1435 "recompile_action": "recompile_lines" })
1436 self.gldl_draw_method_install(
1437 { "name": "trace",
1438 "func": self.glal_draw_trace,
1439 "transparent": False,
1440 "visible_property": "trace",
1441 "recompile_action": "recompile_trace" })
1442 self.gldl_draw_method_install(
1443 { "name": "ball_stick",
1444 "func": self.glal_draw_ball_stick,
1445 "transparent": False,
1446 "visible_property": "ball_stick",
1447 "recompile_action": "recompile_ball_stick" })
1448 self.gldl_draw_method_install(
1449 { "name": "cpk",
1450 "func": self.glal_draw_cpk,
1451 "visible_property": "cpk",
1452 "opacity_property": "cpk_opacity",
1453 "recompile_action": "recompile_cpk" })
1454 self.gldl_draw_method_install(
1455 { "name": "Uaxes",
1456 "func": self.glal_draw_Uaxes,
1457 "transparent": False,
1458 "visible_property": "U",
1459 "recompile_action": "recompile_Uaxes" })
1460 self.gldl_draw_method_install(
1461 { "name": "Uellipse",
1462 "func": self.glal_draw_Uellipse,
1463 "visible_property": "ellipse",
1464 "opacity_property": "ellipse_opacity",
1465 "recompile_action": "recompile_Uellipse" })
1466 self.gldl_draw_method_install(
1467 { "name": "Urms",
1468 "func": self.glal_draw_Urms,
1469 "visible_property": "rms",
1470 "opacity_property": "rms_opacity",
1471 "recompile_action": "recompile_Urms" })
1472
1474 """Configure the color_value property from the value argument.
1475 """
1476
1477 if value in self.glal_atom_color_opts:
1478
1479 if value=="Color By Temp Factor":
1480
1481
1482 min_tf = None
1483 max_tf = None
1484 for atm in self.glal_iter_atoms():
1485 if min_tf is None:
1486 min_tf = atm.temp_factor
1487 max_tf = atm.temp_factor
1488 continue
1489 min_tf = min(atm.temp_factor, min_tf)
1490 max_tf = max(atm.temp_factor, max_tf)
1491
1492 self.properties.update(
1493 color_blue = min_tf,
1494 color_red = max_tf,
1495 color_setting = value)
1496 return
1497
1498 elif value=="Color By Anisotropy":
1499 self.properties.update(
1500 color_blue = 1.0,
1501 color_red = 0.0,
1502 color_setting = value)
1503 return
1504
1505 try:
1506 self.properties.update(color_setting = Colors.COLOR_RGBF[value.lower()])
1507 except KeyError:
1508 pass
1509 else:
1510 return
1511
1512 self.properties.update(color_setting=value)
1513
1514
1515 try:
1516 r, g, b = value.split(",")
1517 except ValueError:
1518 pass
1519 else:
1520 color_setting = (float(r), float(g), float(b))
1521 self.properties.update(color_setting=color_setting)
1522 return
1523
1525
1526 if "recalc_positions" in actions:
1527 self.glal_hidden_atoms_dict = None
1528 self.glal_visible_atoms_dict = None
1529 self.glal_xyzdict = None
1530
1531
1532 if "color" in updates:
1533 self.glal_update_color_value(updates["color"])
1534
1536 """Specialized draw list invokation to recycle the draw list for
1537 symmetry related copies. Cartesian versions of the symmetry rotation
1538 and translation operators are generated by GLStructure/UnitCell
1539 classes.
1540 """
1541 if self.properties["symmetry"] is False:
1542 yield True
1543
1544 else:
1545
1546 gl_struct = self.glo_get_glstructure()
1547 if gl_struct is None:
1548 yield True
1549
1550 else:
1551 for symop in gl_struct.iter_orth_symops():
1552 self.driver.glr_push_matrix()
1553
1554 if self.properties["atom_origin"] != None:
1555 self.driver.glr_translate(-self.properties["atom_origin"])
1556
1557 self.driver.glr_mult_matrix_Rt(symop.R, symop.t)
1558
1559 if self.properties["atom_origin"] != None:
1560 self.driver.glr_translate(self.properties["atom_origin"])
1561
1562 yield True
1563 self.driver.glr_pop_matrix()
1564
1566 """Implement in a subclass to iterate over all atoms which
1567 need to be drawn.
1568 """
1569 pass
1570
1572 """Implement in a subclass to iterate one Fragment object
1573 at a time, in order. This implementation works with any
1574 implementation of glal_iter_atoms, but is very inefficent.
1575 """
1576 struct = Structure.Structure()
1577 memo = {}
1578
1579 for atm in self.glal_iter_atoms():
1580 struct.add_atom(copy.deepcopy(atm, memo))
1581
1582 for frag in struct.iter_fragments():
1583 yield frag
1584
1586 """Implement in a subclass to iterate one Chain object
1587 at a time, in order. This implementation works with any
1588 implementation of glal_iter_atoms, but is very inefficent.
1589 """
1590 struct = Structure.Structure()
1591 memo = {}
1592
1593 for atm in self.glal_iter_atoms():
1594 struct.add_atom(copy.deepcopy(atm, memo))
1595
1596 for chain in struct.iter_chains():
1597 yield chain
1598
1600 """Implement in a subclass to iterate one Model object
1601 at a time, in order. This implementation works with any
1602 implementation of glal_iter_atoms, but is very inefficent.
1603 """
1604 struct = Structure.Structure()
1605 memo = {}
1606
1607 for atm in self.glal_iter_atoms():
1608 struct.add_atom(copy.deepcopy(atm, memo))
1609
1610 for model in struct.iter_models():
1611 yield model
1612
1614 """Iterate all atoms and yield the tuble (atom, visible_flag).
1615 """
1616 aa_bb_atoms = ("N", "CA", "C", "O")
1617 na_bb_atoms = ("P", "O5*", "C5*", "C4*", "C3*", "O3*")
1618
1619 main_chain_visible = self.properties["main_chain_visible"]
1620 oatm_visible = self.properties["oatm_visible"]
1621 side_chain_visible = self.properties["side_chain_visible"]
1622 hetatm_visible = self.properties["hetatm_visible"]
1623 water_visible = self.properties["water_visible"]
1624 hydrogen_visible = self.properties["hydrogen_visible"]
1625
1626 for atm in self.glal_iter_atoms():
1627 if hydrogen_visible is False:
1628 if atm.element=="H":
1629 yield atm, False
1630 continue
1631
1632 frag = atm.get_fragment()
1633
1634 if frag.is_amino_acid():
1635 if oatm_visible is False and atm.name == "O":
1636 yield atm, False
1637 continue
1638
1639 elif main_chain_visible and side_chain_visible:
1640 yield atm, True
1641 continue
1642
1643 elif main_chain_visible and not side_chain_visible:
1644 if atm.name in aa_bb_atoms:
1645 yield atm, True
1646 continue
1647
1648 elif not main_chain_visible and side_chain_visible:
1649 if atm.name not in aa_bb_atoms:
1650 yield atm, True
1651 continue
1652
1653 yield atm, False
1654 continue
1655
1656 elif frag.is_nucleic_acid():
1657 if main_chain_visible and side_chain_visible:
1658 yield atm, True
1659 continue
1660
1661 elif main_chain_visible and not side_chain_visible:
1662 if atm.name in na_bb_atoms:
1663 yield atm, True
1664 continue
1665
1666 elif not main_chain_visible and side_chain_visible:
1667 if atm.name not in na_bb_atoms:
1668 yield atm, True
1669 continue
1670
1671 yield atm, False
1672 continue
1673
1674 elif frag.is_water() is True:
1675 if water_visible is True:
1676 yield atm, True
1677 continue
1678
1679 yield atm, False
1680 continue
1681
1682 elif hetatm_visible is True:
1683 yield atm, True
1684 continue
1685
1686 else:
1687 yield atm, False
1688 continue
1689
1691 """When a atom selection setting or origin changes, the atom
1692 dictionaries need to be rebuilt.
1693 """
1694 self.glal_hidden_atoms_dict = {}
1695 self.glal_visible_atoms_dict = {}
1696 self.glal_xyzdict = GeometryDict.XYZDict(5.0)
1697
1698 for atm, visible in self.glal_iter_atoms_filtered():
1699 pos = self.glal_calc_position(atm.position)
1700
1701 if visible is True:
1702 self.glal_visible_atoms_dict[atm] = pos
1703 self.glal_xyzdict.add(pos, atm)
1704 else:
1705 self.glal_hidden_atoms_dict[atm] = pos
1706
1708 """Iterate over all visible atoms yielding the 2-tuple (atm, position).
1709 """
1710 if self.glal_visible_atoms_dict is None:
1711 self.glal_rebuild_atom_dicts()
1712
1713 for atm, pos in self.glal_visible_atoms_dict.iteritems():
1714 yield atm, pos
1715
1717 """Calculate a position vector with respect to the
1718 proeprty: atom_origin.
1719 """
1720 if self.properties["atom_origin"] is not None:
1721 return position - self.properties["atom_origin"]
1722 return position
1723
1725 """Return a RGBF 3-tuple color of a color gradient for value.
1726 """
1727 blue = self.properties["color_blue"]
1728 red = self.properties["color_red"]
1729 width = abs(red - blue)
1730
1731 if red>blue:
1732 if value>=red:
1733 return (1.0, 0.0, 0.0)
1734 elif value<=blue:
1735 return (0.0, 0.0, 1.0)
1736
1737 b = 1.0 - ((value - blue) / width)
1738 return (1.0-b, 0.0, b)
1739
1740 else:
1741 if value<=red:
1742 return (1.0, 0.0, 0.0)
1743 elif value>=blue:
1744 return (0.0, 0.0, 1.0)
1745
1746 b = 1.0 - ((value - red) / width)
1747 return (b, 0.0, 1.0-b)
1748
1750 """Sets the open-gl color for the atom.
1751 """
1752
1753 if hasattr(atom, "glal_color"):
1754 return atom.glal_color
1755
1756 setting = self.properties["color_setting"]
1757 if isinstance(setting, tuple):
1758 return setting
1759
1760 if setting=="Color By Element":
1761 element = Library.library_get_element_desc(atom.element)
1762 try:
1763 return element.color_rgbf
1764 except AttributeError:
1765 return Colors.COLOR_RGBF["white"]
1766
1767 elif setting=="Color By Residue Type":
1768 monomer = Library.library_get_monomer_desc(atom.res_name)
1769 try:
1770 return self.glal_res_type_color_dict[monomer.chem_type]
1771 except KeyError:
1772 return Colors.COLOR_RGBF["white"]
1773
1774 elif setting=="Color By Temp Factor":
1775 return self.glal_calc_color_range(atom.temp_factor)
1776
1777 elif setting=="Color By Anisotropy":
1778 return self.glal_calc_color_range(atom.calc_anisotropy())
1779
1780 raise ValueError, "glal_calc_color: bad color setting %s" % (str(setting))
1781
1786
1791
1796
1798 """Return the color to be used for thermal ellipse.
1799 """
1800 return self.glal_calc_color(atom)
1801
1803 """Return the color to be used for thermal peanuts.
1804 """
1805 return self.glal_calc_color(atom)
1806
1808 """Return the ADP U tensor for the atom
1809 """
1810 return atom.get_U()
1811
1813 """Draws atom lables.
1814 """
1815
1816 glr_push_matrix = self.driver.glr_push_matrix
1817 glr_pop_matrix = self.driver.glr_pop_matrix
1818 glr_mult_matrix_R = self.driver.glr_mult_matrix_R
1819 glr_translate = self.driver.glr_translate
1820 glr_text = self.driver.glr_text
1821
1822
1823 style = self.properties["label_style"].lower()
1824 scale = self.properties["label_size"]
1825 self.driver.glr_set_material_rgb(*self.glal_calc_color_label())
1826
1827 viewer = self.gldl_get_glviewer()
1828 R = viewer.properties["R"]
1829 Ri = numpy.transpose(R)
1830
1831
1832
1833 cv = self.properties["origin"]
1834
1835
1836
1837
1838 glr_push_matrix()
1839 glr_mult_matrix_R(Ri)
1840
1841 for atm, pos in self.glal_iter_visible_atoms():
1842
1843
1844 if atm.get_fragment().is_amino_acid():
1845
1846
1847 if style=="residue":
1848 if atm.name!="CA":
1849 continue
1850 text = "%s%s" % (atm.chain_id, atm.fragment_id)
1851
1852
1853 elif style=="ca atoms":
1854 if atm.name!="CA":
1855 continue
1856
1857 if atm.alt_loc=="":
1858 text = "%s %s %s %s" % (
1859 atm.name,
1860 atm.res_name,
1861 atm.fragment_id,
1862 atm.chain_id)
1863 else:
1864 text = "%s(%s) %s %s %s" % (
1865 atm.name,
1866 atm.alt_loc,
1867 atm.res_name,
1868 atm.fragment_id,
1869 atm.chain_id)
1870
1871
1872 elif atm.name=="CA":
1873 if atm.alt_loc=="":
1874 text = "%s %s %s %s" % (
1875 atm.name,
1876 atm.res_name,
1877 atm.fragment_id,
1878 atm.chain_id)
1879 else:
1880 text = "%s(%s) %s %s %s" % (
1881 atm.name,
1882 atm.alt_loc,
1883 atm.res_name,
1884 atm.fragment_id,
1885 atm.chain_id)
1886 else:
1887 if atm.alt_loc=="":
1888 text = atm.name
1889 else:
1890 text = "%s(%s)" % (atm.name, atm.alt_loc)
1891
1892
1893 else:
1894 if atm.alt_loc=="":
1895 text = "%s %s %s %s" % (
1896 atm.name,
1897 atm.res_name,
1898 atm.fragment_id,
1899 atm.chain_id)
1900 else:
1901 text = "%s(%s) %s %s %s" % (
1902 atm.name,
1903 atm.alt_loc,
1904 atm.res_name,
1905 atm.fragment_id,
1906 atm.chain_id)
1907
1908 relative_pos = numpy.dot(R, pos + cv)
1909 glr_push_matrix()
1910 glr_translate(relative_pos + numpy.array([0.0, 0.0, 2.0]))
1911 glr_text(text, scale)
1912 glr_pop_matrix()
1913
1914 glr_pop_matrix()
1915
1938
1954
1956 """Draw the ADP determined probability ellipsoid.
1957 """
1958
1959 glr_set_material_rgba = self.driver.glr_set_material_rgba
1960 glr_Uellipse = self.driver.glr_Uellipse
1961
1962
1963 opacity = self.properties["ellipse_opacity"]
1964 prob = self.properties["adp_prob"]
1965
1966 show_sig_u = self.properties["show_sig_u"]
1967 sig_u_opacity = self.properties["sig_u_opacity"]
1968
1969 for atm, pos in self.glal_iter_visible_atoms():
1970 U = self.glal_calc_U(atm)
1971 if U is None:
1972 continue
1973
1974 r, g, b = self.glal_calc_color_Uellipse(atm)
1975
1976 if show_sig_u is True and atm.sig_U is not None:
1977 glr_set_material_rgba(r, g, b,sig_u_opacity)
1978 glr_Uellipse(pos, U - atm.sig_U, prob)
1979
1980 glr_set_material_rgba(r, g, b, opacity)
1981 glr_Uellipse(pos, U, prob)
1982
1983 if show_sig_u is True and atm.sig_U is not None:
1984 glr_set_material_rgba(r, g, b,sig_u_opacity)
1985 glr_Uellipse(pos, U + atm.sig_U, prob)
1986
2005
2044
2078
2080 """Draws atom with a cross of lines.
2081 """
2082 self.driver.glr_cross(pos, self.glal_calc_color(atm), self.properties["line_width"])
2083
2085 """Draws trace over all polymer backbone atoms.
2086 """
2087
2088 glr_set_material_rgb = self.driver.glr_set_material_rgb
2089 glr_tube = self.driver.glr_tube
2090 glr_sphere = self.driver.glr_sphere
2091
2092
2093 trace_radius = self.properties["trace_radius"]
2094 r, g, b = self.glal_calc_color_trace()
2095
2096 glr_set_material_rgb(r, g, b)
2097
2098 for chain in self.glal_iter_chains():
2099
2100 last_atm = None
2101
2102 for frag in chain.iter_fragments():
2103
2104 if frag.is_amino_acid() is True:
2105 backbone_atoms = ["CA"]
2106 prev_atom_path = ["N", "C", "CA"]
2107 elif frag.is_nucleic_acid() is True:
2108 backbone_atoms = ["P", "O5*", "C5*", "C4*", "C3*", "O3*"]
2109 prev_atom_path = None
2110 else:
2111 last_atm = None
2112 prev_atom_path = None
2113 continue
2114
2115 for name in backbone_atoms:
2116 atm = frag.get_atom(name)
2117 if atm is None:
2118 last_atm = None
2119 continue
2120
2121 if prev_atom_path is not None:
2122 prev_atm = atm.get_bonded_atom(prev_atom_path)
2123 if prev_atm != last_atm:
2124 last_atm = atm
2125 continue
2126
2127 if last_atm is None:
2128 last_atm = atm
2129 continue
2130
2131
2132
2133
2134 if last_atm.alt_loc=="" and atm.alt_loc=="":
2135 lpos = self.glal_calc_position(last_atm.position)
2136 pos = self.glal_calc_position(atm.position)
2137 glr_sphere(lpos, trace_radius, 12)
2138 glr_tube(lpos, pos, trace_radius)
2139
2140 elif last_atm.alt_loc=="" and atm.alt_loc!="":
2141 lpos = self.glal_calc_position(last_atm.position)
2142
2143 for aa in atm.iter_alt_loc():
2144 pos = self.glal_calc_position(aa.position)
2145 glr_sphere(lpos, trace_radius, 12)
2146 glr_tube(lpos, pos, trace_radius)
2147
2148 elif last_atm.alt_loc!="" and atm.alt_loc=="":
2149 pos = self.glal_calc_position(atm.position)
2150
2151 for laa in last_atm.iter_alt_loc():
2152 lpos = self.glal_calc_position(laa.position)
2153 glr_sphere(lpos, trace_radius, 12)
2154 glr_tube(lpos, pos, trace_radius)
2155
2156 elif last_atm.alt_loc!="" and atm.alt_loc!="":
2157 for aa in atm.iter_alt_loc():
2158 for laa in last_atm.iter_alt_loc():
2159 if aa.alt_loc!=laa.alt_loc:
2160 continue
2161 lpos = self.glal_calc_position(laa.position)
2162 pos = self.glal_calc_position(aa.position)
2163 glr_sphere(lpos, trace_radius, 12)
2164 glr_tube(lpos, pos, trace_radius)
2165
2166 last_atm = atm
2167
2168 if last_atm is not None:
2169 for laa in last_atm.iter_alt_loc():
2170 lpos = self.glal_calc_position(laa.position)
2171 glr_sphere(lpos, trace_radius, 10)
2172
2173
2175 """Visualization object for mmLib.Structure.Chain.
2176 """
2181
2184
2186 return "Chain %s" % (self.chain.chain_id)
2187
2190
2192 """The GLAtomList implementation of this is slow.
2193 """
2194 return self.chain.iter_fragments()
2195
2197 """The GLAtomList implementation of this is slow.
2198 """
2199 yield self.chain
2200
2201
2203 """Visualization object for a mmLib.Structure.Structure.
2204 """
2230
2232 GLDrawList.glo_install_properties(self)
2233
2234 self.glo_add_property(
2235 { "name": "axes_visible",
2236 "desc": "Show Cartesian Axes",
2237 "catagory": "Show/Hide",
2238 "type": "boolean",
2239 "default": False,
2240 "action": "redraw" })
2241 self.glo_add_property(
2242 { "name": "unit_cell_visible",
2243 "desc": "Show Unit Cell",
2244 "catagory": "Show/Hide",
2245 "type": "boolean",
2246 "default": False,
2247 "action": "redraw" })
2248 self.glo_add_property(
2249 { "name": "symmetry",
2250 "desc": "Show Symmetry Equivelant",
2251 "catagory": "Show/Hide",
2252 "type": "boolean",
2253 "default": False,
2254 "action": "redraw" })
2255 self.glo_add_property(
2256 { "name": "main_chain_visible",
2257 "desc": "Show Main Chain Atoms",
2258 "catagory": "Show/Hide",
2259 "type": "boolean",
2260 "default": True,
2261 "action": ["recompile", "recalc_positions"] })
2262 self.glo_add_property(
2263 { "name": "oatm_visible",
2264 "desc": "Show Main Chain Carbonyl Atoms",
2265 "catagory": "Show/Hide",
2266 "type": "boolean",
2267 "default": True,
2268 "action": ["recompile", "recalc_positions"] })
2269 self.glo_add_property(
2270 { "name": "side_chain_visible",
2271 "desc": "Show Side Chain Atoms",
2272 "catagory": "Show/Hide",
2273 "type": "boolean",
2274 "default": True,
2275 "action": ["recompile", "recalc_positions"] })
2276 self.glo_add_property(
2277 { "name": "hetatm_visible",
2278 "desc": "Show Hetrogen Atoms",
2279 "catagory": "Show/Hide",
2280 "type": "boolean",
2281 "default": True,
2282 "action": ["recompile", "recalc_positions"] })
2283 self.glo_add_property(
2284 { "name": "water_visible",
2285 "desc": "Show Waters",
2286 "catagory": "Show/Hide",
2287 "type": "boolean",
2288 "default": False,
2289 "action": ["recompile", "recalc_positions"] })
2290 self.glo_add_property(
2291 { "name": "hydrogen_visible",
2292 "desc": "Show Hydrogens",
2293 "catagory": "Show/Hide",
2294 "type": "boolean",
2295 "default": False,
2296 "action": ["recompile", "recalc_positions"] })
2297
2299 return self.struct.structure_id
2300
2302 """Adds a Chain object to the GLStructure.
2303 """
2304 gl_chain = GLChain(chain=chain)
2305 gl_chain.glo_set_properties_id("GLChain_%s" % (chain.chain_id))
2306 self.glo_add_child(gl_chain)
2307
2308 chain_pid = gl_chain.glo_get_properties_id()
2309
2310 self.glo_link_child_property(
2311 "symmetry", chain_pid, "symmetry")
2312
2313 self.glo_link_child_property(
2314 "main_chain_visible", chain_pid, "main_chain_visible")
2315 self.glo_link_child_property(
2316 "oatm_visible", chain_pid, "oatm_visible")
2317 self.glo_link_child_property(
2318 "side_chain_visible", chain_pid, "side_chain_visible")
2319 self.glo_link_child_property(
2320 "hetatm_visible", chain_pid, "hetatm_visible")
2321 self.glo_link_child_property(
2322 "water_visible", chain_pid, "water_visible")
2323 self.glo_link_child_property(
2324 "hydrogen_visible", chain_pid, "hydrogen_visible")
2325
2327 """Iterate orthogonal-space symmetry operations useful for
2328 displaying symmetry-equivelant molecules without having to
2329 calculate new draw lists.
2330 """
2331 if hasattr(self, "orth_symop_cache"):
2332 for symop in self.orth_symop_cache:
2333 yield symop
2334 else:
2335 self.orth_symop_cache = []
2336 uc = self.struct.unit_cell
2337
2338 for symop in uc.iter_struct_orth_symops(self.struct):
2339 self.orth_symop_cache.append(symop)
2340 yield symop
2341
2342
2344 """This class renders a list of GLDrawList (or subclasses of) onto
2345 the given glcontext and gldrawable objects. The glcontext and gldrawable
2346 must be created by the underling GUI toolkit, or perhaps the GLUT
2347 libraries. This class is completely platform and tookit independent
2348 once it is passed the glcontext and gldrawable. The design of this
2349 class and the associated GLDrawList classes incorporates some basic
2350 OpenGL drawing optimizations. The GLDrawList objects are drawn and
2351 compiled into OpenGL draw lists, and have their own
2352 transformation/rotation operators WRT the GLViewer origin, allowing
2353 each GLDrawList to be redrawn very quickly as long as it moves as a
2354 rigid body.
2355 """
2365
2367 GLObject.glo_install_properties(self)
2368
2369
2370 self.glo_add_property(
2371 { "name": "bg_color",
2372 "desc": "Background Color",
2373 "catagory": "Background",
2374 "type": "enum_string",
2375 "default": "Black",
2376 "enum_list": Colors.COLOR_NAMES_CAPITALIZED[:],
2377 "action": "redraw" })
2378
2379
2380 self.glo_add_property(
2381 { "name": "R",
2382 "desc": "View Window Rotation Matrix",
2383 "catagory": "View",
2384 "read_only": True,
2385 "type": "array(3,3)",
2386 "default": numpy.identity(3, float),
2387 "action": "redraw" })
2388 self.glo_add_property(
2389 { "name": "cor",
2390 "desc": "Center of Rotation",
2391 "catagory": "View",
2392 "read_only": True,
2393 "type": "array(3)",
2394 "default": numpy.zeros(3, float),
2395 "action": "redraw" })
2396 self.glo_add_property(
2397 { "name": "width",
2398 "desc": "Window Width",
2399 "catagory": "View",
2400 "read_only": True,
2401 "type": "integer",
2402 "default": 1,
2403 "action": "redraw" })
2404 self.glo_add_property(
2405 { "name": "height",
2406 "desc": "Window Height",
2407 "catagory": "View",
2408 "read_only": True,
2409 "type": "integer",
2410 "default": 1,
2411 "action": "redraw" })
2412 self.glo_add_property(
2413 { "name": "near",
2414 "desc": "Near Clipping Plane",
2415 "catagory": "View",
2416 "type": "float",
2417 "default": -20.0,
2418 "action": "redraw" })
2419 self.glo_add_property(
2420 { "name": "far",
2421 "desc": "Far Clipping Plane",
2422 "catagory": "View",
2423 "type": "float",
2424 "default": 1000.0,
2425 "action": "redraw" })
2426 self.glo_add_property(
2427 { "name": "zoom",
2428 "desc": "Zoom",
2429 "catagory": "View",
2430 "type": "float",
2431 "default": 20.0,
2432 "action": "redraw" })
2433
2434
2435 self.glo_add_property(
2436 { "name": "GL_AMBIENT",
2437 "desc": "Ambient Light",
2438 "catagory": "Lighting",
2439 "type": "float",
2440 "range": "0.0-1.0,0.1",
2441 "default": 0.2,
2442 "action": "redraw" })
2443 self.glo_add_property(
2444 { "name": "GL_SPECULAR",
2445 "desc": "Specular Light",
2446 "catagory": "Lighting",
2447 "type": "float",
2448 "range": "0.0-1.0,0.1",
2449 "default": 1.0,
2450 "action": "redraw" })
2451 self.glo_add_property(
2452 { "name": "GL_DIFFUSE",
2453 "desc": "Diffuse Light",
2454 "catagory": "Lighting",
2455 "type": "float",
2456 "range": "0.0-1.0,0.1",
2457 "default": 1.0,
2458 "action": "redraw" })
2459
2460
2461 self.glo_add_property(
2462 { "name": "GL_LINE_SMOOTH",
2463 "desc": "Smooth Lines",
2464 "catagory": "OpenGL Performance",
2465 "type": "boolean",
2466 "default": False,
2467 "action": "redraw" })
2468 self.glo_add_property(
2469 { "name": "GL_POINT_SMOOTH",
2470 "desc": "Smooth Points",
2471 "catagory": "OpenGL Performance",
2472 "type": "boolean",
2473 "default": False,
2474 "action": "redraw" })
2475 self.glo_add_property(
2476 { "name": "GL_POLYGON_SMOOTH",
2477 "desc": "Smooth Polygons",
2478 "catagory": "OpenGL Performance",
2479 "type": "boolean",
2480 "default": False,
2481 "action": "redraw" })
2482 self.glo_add_property(
2483 { "name": "GL_BLEND",
2484 "desc": "Alpha-Blending (required for Fog)",
2485 "catagory": "OpenGL Performance",
2486 "type": "boolean",
2487 "default": True,
2488 "action": "redraw" })
2489 self.glo_add_property(
2490 { "name": "GL_FOG",
2491 "desc": "Enable Fog",
2492 "catagory": "OpenGL Performance",
2493 "type": "boolean",
2494 "default": True,
2495 "action": "redraw" })
2496
2498
2499
2500 slice = self.properties["near"] - self.properties["far"]
2501 if slice<1.0:
2502 if updates.has_key("near") and updates.has_key("far"):
2503 self.properties.update(far = self.properties["near"] - 1.0)
2504 elif updates.has_key("near") and not updates.has_key("far"):
2505 self.properties.update(near = self.properties["far"] + 1.0)
2506 elif updates.has_key("far") and not updates.has_key("near"):
2507 self.properties.update(far = self.properties["near"] - 1.0)
2508
2509
2510 if "redraw" in actions:
2511 self.glv_redraw()
2512
2519
2526
2528 """Orient the structure based on a moment-of-intertia like tensor
2529 centered at the centroid of the structure.
2530 """
2531 slop = 2.0
2532
2533 def aa_atom_iter(structx):
2534 if structx.count_standard_residues()>0:
2535 for frag in structx.iter_standard_residues():
2536 for atm in frag.iter_atoms():
2537 yield atm
2538 else:
2539 for atm in structx.iter_atoms():
2540 yield atm
2541
2542 try:
2543 centroid = AtomMath.calc_atom_centroid(aa_atom_iter(struct))
2544 except OverflowError:
2545 return None
2546
2547 R = AtomMath.calc_inertia_tensor(aa_atom_iter(struct), centroid)
2548
2549 ori = {}
2550
2551
2552 first_atm = True
2553
2554 min_x = 0.0
2555 max_x = 0.0
2556 min_y = 0.0
2557 max_y = 0.0
2558 min_z = 0.0
2559 max_z = 0.0
2560
2561 for atm in aa_atom_iter(struct):
2562 x = numpy.dot(R, atm.position - centroid)
2563
2564 if first_atm is True:
2565 first_atm = False
2566
2567 min_x = max_x = x[0]
2568 min_y = max_y = x[1]
2569 min_z = max_z = x[2]
2570 else:
2571 min_x = min(min_x, x[0])
2572 max_x = max(max_x, x[0])
2573 min_y = min(min_y, x[1])
2574 max_y = max(max_y, x[1])
2575 min_z = min(min_z, x[2])
2576 max_z = max(max_z, x[2])
2577
2578
2579 min_x -= slop
2580 max_x += slop
2581 min_y -= slop
2582 max_y += slop
2583 min_z -= slop
2584 max_z += slop
2585
2586
2587 target_pwidth = 640
2588
2589 hwidth = max(abs(min_x),abs(max_x))
2590 hheight = max(abs(min_y),abs(max_y))
2591 pheight = target_pwidth * (hheight / hwidth)
2592 hzoom = 2.0 * hwidth
2593
2594 ori["R"] = R
2595 ori["centroid"] = centroid
2596 ori["pwidth"] = target_pwidth
2597 ori["pheight"] = pheight
2598 ori["hzoom"] = hzoom
2599
2600
2601 ori["near"] = max_z
2602 ori["far"] = min_z
2603
2604 return ori
2605
2607 """Adds the visualization for a mmLib.Structure.Structure object
2608 to the GLViewer. It returns the GLStructure object created to
2609 visualize the Structure object.
2610 """
2611 assert isinstance(struct, Structure.Structure)
2612
2613
2614 gl_struct = GLStructure(struct=struct)
2615 self.glv_add_draw_list(gl_struct)
2616
2617 ori = self.glv_calc_struct_orientation(struct)
2618 if ori is not None:
2619 self.properties.update(
2620 R = ori["R"],
2621 cor = ori["centroid"],
2622 zoom = ori["hzoom"],
2623 near = ori["near"],
2624 far = ori["far"])
2625
2626 return gl_struct
2627
2629 """This method is called by GLViewer children to trigger a redraw
2630 in the toolkit embedding the GLViewer object. It needs to be
2631 re-implemented when subclassed to call the tookit's widget redraw
2632 method.
2633 """
2634 pass
2635
2637 """Called once to initalize the GL scene before drawing.
2638 """
2639 pass
2640
2642 """Called to set the size of the OpenGL window this class is
2643 drawing on.
2644 """
2645 self.properties.update(width=width, height=height)
2646
2648 """Adjust near/far clipping planes.
2649 """
2650 width = self.properties["width"]
2651 zoom = self.properties["zoom"]
2652
2653 angstrom_per_pixel = zoom / float(width)
2654
2655 nearA = angstrom_per_pixel * float(near)
2656 farA = angstrom_per_pixel * float(far)
2657
2658 n = self.properties["near"] + nearA
2659 f = self.properties["far"] + farA
2660 self.properties.update(near=n, far=f)
2661
2663 """Adjust zoom levels.
2664 """
2665 width = self.properties["width"]
2666 zoom = self.properties["zoom"]
2667
2668 angstrom_per_pixel = zoom / float(width)
2669
2670 zoom = self.properties["zoom"]
2671 zoom += angstrom_per_pixel * float(z)
2672
2673 if zoom<1.0:
2674 zoom = 1.0
2675
2676 self.properties.update(zoom=zoom)
2677
2679 """Translate in the XY plane.
2680 """
2681
2682
2683
2684 width = self.properties["width"]
2685 zoom = self.properties["zoom"]
2686
2687 angstrom_per_pixel = zoom / float(width)
2688
2689 xA = angstrom_per_pixel * float(x)
2690 yA = angstrom_per_pixel * float(y)
2691
2692
2693 dt = numpy.array((xA, yA, 0.0), float)
2694
2695
2696 R = self.properties["R"]
2697
2698
2699
2700 cor = self.properties["cor"] - numpy.dot(numpy.transpose(R), dt)
2701
2702 self.properties.update(cor=cor)
2703
2705 """Implements a virtual trackball.
2706 """
2707
2708 def project_to_sphere(r, x, y):
2709 d = math.sqrt(x*x + y*y)
2710 if d<(r*0.707):
2711 return math.sqrt(r*r - d*d)
2712 else:
2713 return (r/1.414)**2 / d
2714
2715 width = self.properties["width"]
2716 height = self.properties["height"]
2717
2718
2719
2720 square = min(width, height)
2721 radius = int(square * 0.7)
2722
2723 x1c = x1 - width/2
2724 y1c = y1 - width/2
2725 d = math.sqrt(x1c*x1c + y1c*y1c)
2726
2727
2728 if d>=radius:
2729 x2c = x2 - width/2
2730 y2c = y2 - width/2
2731
2732 p1 = AtomMath.normalize(numpy.array((x1c, y1c, 0.0), float))
2733 p2 = AtomMath.normalize(numpy.array((x2c, y2c, 0.0), float))
2734
2735 c = numpy.cross(p2, p1)
2736
2737 try:
2738 a = AtomMath.normalize(c)
2739 except OverflowError:
2740 return
2741
2742 theta = AtomMath.length(c) * math.pi/2.0
2743
2744
2745 else:
2746
2747 x1 = (2.0*x1 - width) / width
2748 y1 = (height - 2.0*y1) / height
2749 x2 = (2.0*x2 - width) / width
2750 y2 = (height - 2.0*y2) / height
2751
2752 tb_size = 1.0
2753
2754
2755 if x1==x2 and y1==y2:
2756 return
2757
2758 p1 = numpy.array((x1, y1, project_to_sphere(tb_size, x1, y1)), float)
2759 p2 = numpy.array((x2, y2, project_to_sphere(tb_size, x2, y2)), float)
2760
2761 a = numpy.cross(p1, p2)
2762 d = p1 - p2
2763 t = AtomMath.length(d) / (2.0 * tb_size)
2764
2765 if t>1.0:
2766 t - 1.0
2767 if t<-1.0:
2768 t = -1.0
2769
2770 theta = 2.0 * math.asin(t)
2771
2772
2773 Rcur = self.properties["R"]
2774
2775
2776 a = numpy.dot(numpy.transpose(Rcur), a)
2777 qup = AtomMath.rquaternionu(a, theta)
2778
2779
2780
2781 qcur = AtomMath.quaternionrmatrix(Rcur)
2782 qnew = AtomMath.addquaternion(qcur, qup)
2783 Rnew = AtomMath.rmatrixquaternion(qnew)
2784
2785 self.properties.update(R=Rnew)
2786
2788 """Return the R,G,B triplit of the background color.
2789 """
2790 colorx = self.properties["bg_color"].lower()
2791 if Colors.COLOR_RGBF.has_key(colorx):
2792 return Colors.COLOR_RGBF[colorx]
2793
2794 try:
2795 r, g, b = colorx.split(",")
2796 except ValueError:
2797 pass
2798 else:
2799 try:
2800 return (float(r), float(g), float(b))
2801 except ValueError:
2802 pass
2803
2804 return (0.0, 0.0, 0.0)
2805
2807 """Render scene using all drivers.
2808 """
2809 for driver in self.glv_driver_list:
2810 self.glv_render_one(driver)
2811
2813 """Render the scent once with the argument driver.
2814 """
2815
2816 driver.glr_render_begin(
2817 width = self.properties["width"],
2818 height = self.properties["height"],
2819 zoom = self.properties["zoom"],
2820 near = self.properties["near"],
2821 far = self.properties["far"],
2822 bg_color_rgbf = self.glv_background_color_rgbf(),
2823 ambient_light = self.properties["GL_AMBIENT"],
2824 diffuse_light = self.properties["GL_DIFFUSE"],
2825 specular_light = self.properties["GL_SPECULAR"],
2826 gl_line_smooth = self.properties["GL_LINE_SMOOTH"],
2827 gl_point_smooth = self.properties["GL_LINE_SMOOTH"],
2828 gl_polygon_smooth = self.properties["GL_POLYGON_SMOOTH"],
2829 gl_blend = self.properties["GL_BLEND"],
2830 gl_fog = self.properties["GL_FOG"])
2831
2832 R = self.properties["R"]
2833 assert numpy.allclose(linalg.determinant(R), 1.0)
2834
2835 driver.glr_mult_matrix_R(R)
2836 driver.glr_translate(-self.properties["cor"])
2837
2838
2839 for draw_list in self.glo_iter_children():
2840 draw_list.gldl_render(driver)
2841
2842
2843 for draw_list in self.glo_iter_children():
2844 draw_list.gldl_render(driver, True)
2845
2846 driver.glr_render_end()
2847