1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 """The molecule, residue, and spin tree view GUI elements."""
24
25
26
27 import wx
28
29
30 from graphics import fetch_icon
31 from gui.components.menu import build_menu_item
32 from gui.message import Question
33 from gui.string_conv import gui_to_str
34 from gui.uf_objects import Uf_storage; uf_store = Uf_storage()
35 from pipe_control.mol_res_spin import get_molecule_ids, molecule_loop, residue_loop, return_molecule, return_residue, return_spin, spin_loop
36 from pipe_control.pipes import cdp_name, get_pipe
37 from pipe_control.selection import is_mol_selected, is_res_selected, is_spin_selected
38 from status import Status; status = Status()
39
40
41
42 MENU_MOLECULE_MOLECULE_COPY = wx.NewId()
43 MENU_MOLECULE_MOLECULE_DELETE = wx.NewId()
44 MENU_MOLECULE_MOLECULE_DESELECT = wx.NewId()
45 MENU_MOLECULE_MOLECULE_NAME = wx.NewId()
46 MENU_MOLECULE_MOLECULE_SELECT = wx.NewId()
47 MENU_MOLECULE_MOLECULE_TYPE = wx.NewId()
48 MENU_MOLECULE_RESIDUE_CREATE = wx.NewId()
49 MENU_RESIDUE_RESIDUE_COPY = wx.NewId()
50 MENU_RESIDUE_RESIDUE_DELETE = wx.NewId()
51 MENU_RESIDUE_RESIDUE_DESELECT = wx.NewId()
52 MENU_RESIDUE_RESIDUE_NAME = wx.NewId()
53 MENU_RESIDUE_RESIDUE_NUMBER = wx.NewId()
54 MENU_RESIDUE_RESIDUE_SELECT = wx.NewId()
55 MENU_RESIDUE_SPIN_ADD = wx.NewId()
56 MENU_RESIDUE_SPIN_CREATE_PSEUDO = wx.NewId()
57 MENU_ROOT_MOLECULE_CREATE = wx.NewId()
58 MENU_ROOT_LOAD_SPINS = wx.NewId()
59 MENU_SPIN_SPIN_COPY = wx.NewId()
60 MENU_SPIN_SPIN_DELETE = wx.NewId()
61 MENU_SPIN_SPIN_DESELECT = wx.NewId()
62 MENU_SPIN_SPIN_ELEMENT = wx.NewId()
63 MENU_SPIN_SPIN_NAME = wx.NewId()
64 MENU_SPIN_SPIN_NUMBER = wx.NewId()
65 MENU_SPIN_SPIN_SELECT = wx.NewId()
66
67
69 """The tree view class."""
70
71 - def __init__(self, gui, parent=None, id=None):
72 """Set up the tree GUI element.
73
74 @param gui: The gui object.
75 @type gui: wx object
76 @keyword parent: The parent GUI element that this is to be attached to.
77 @type parent: wx object
78 @keyword id: The ID number.
79 @type id: int
80 """
81
82
83 self.gui = gui
84 self.parent = parent
85
86
87 wx.Window.__init__(self, parent, id, style=wx.WANTS_CHARS)
88
89
90 self.icon_size = 22
91
92
93 self.tree = wx.TreeCtrl(parent=self, id=-1, pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.TR_DEFAULT_STYLE)
94
95
96 self.tree_ids = {}
97
98
99 self.Bind(wx.EVT_SIZE, self._resize)
100
101
102 self.root = self.tree.AddRoot("Spin system information")
103 self.tree.SetPyData(self.root, "root")
104
105
106 icon_list = wx.ImageList(self.icon_size, self.icon_size)
107
108
109 self.icon_mol_index = icon_list.Add(wx.Bitmap(fetch_icon("relax.molecule", "22x22"), wx.BITMAP_TYPE_ANY))
110 self.icon_mol_unfold_index = icon_list.Add(wx.Bitmap(fetch_icon("relax.molecule_unfolded", "22x22"), wx.BITMAP_TYPE_ANY))
111 self.icon_res_index = icon_list.Add(wx.Bitmap(fetch_icon("relax.residue", "22x22"), wx.BITMAP_TYPE_ANY))
112 self.icon_spin_index = icon_list.Add(wx.Bitmap(fetch_icon("relax.spin", "22x22"), wx.BITMAP_TYPE_ANY))
113
114
115 self.icon_mol_index_desel = icon_list.Add(wx.Bitmap(fetch_icon("relax.molecule_grey", "22x22"), wx.BITMAP_TYPE_ANY))
116 self.icon_mol_unfold_index_desel = icon_list.Add(wx.Bitmap(fetch_icon("relax.molecule_unfolded_grey", "22x22"), wx.BITMAP_TYPE_ANY))
117 self.icon_res_index_desel = icon_list.Add(wx.Bitmap(fetch_icon("relax.residue_grey", "22x22"), wx.BITMAP_TYPE_ANY))
118 self.icon_spin_index_desel = icon_list.Add(wx.Bitmap(fetch_icon("relax.spin_grey", "22x22"), wx.BITMAP_TYPE_ANY))
119
120
121 self.tree.SetImageList(icon_list)
122
123
124 self.icon_list = icon_list
125
126
127 self.update()
128
129
130 self.tree.Bind(wx.EVT_TREE_SEL_CHANGED, self._selection)
131 self.tree.Bind(wx.EVT_RIGHT_DOWN, self._right_click)
132
133
135 """Resize the tree element.
136
137 @param event: The wx event.
138 @type event: wx event
139 """
140
141
142 width, height = self.GetClientSizeTuple()
143
144
145 self.tree.SetDimensions(0, 0, width, height)
146
147
149 """Handle right clicks in the tree.
150
151 @param event: The wx event.
152 @type event: wx event
153 """
154
155
156 pos = event.GetPosition()
157
158
159 item, flags = self.tree.HitTest(pos)
160
161
162 if not item.IsOk():
163 self.info = None
164 else:
165 self.info = self.tree.GetItemPyData(item)
166
167
168 if self.info == None:
169 self.menu_default()
170
171
172 elif self.info == 'root':
173 self.menu_root()
174
175
176 elif self.info['type'] == 'mol':
177 self.menu_molecule()
178
179
180 elif self.info['type'] == 'res':
181 self.menu_residue()
182
183
184 elif self.info['type'] == 'spin':
185 self.menu_spin()
186
187
189 """Handle changes in selection in the tree.
190
191 @param event: The wx event.
192 @type event: wx event
193 """
194
195
196 item = event.GetItem()
197
198
199 info = self.tree.GetItemPyData(item)
200
201
202 self.gui.spin_viewer.container.display(info)
203
204
206 """Wrapper method.
207
208 @param event: The wx event.
209 @type event: wx event
210 """
211
212
213 uf_store['molecule.copy'](wx_parent=self.gui.spin_viewer, pipe_from=cdp_name(), mol_from=self.info['id'], pipe_to=cdp_name())
214
215
217 """Wrapper method.
218
219 @param event: The wx event.
220 @type event: wx event
221 """
222
223
224 msg = "Are you sure you would like to delete this molecule? This only affects the spin data, all structural data will remain. This operation cannot be undone."
225 if status.show_gui and Question(msg, parent=self.gui.spin_viewer, default=False, size=(400, 170)).ShowModal() == wx.ID_NO:
226 return
227
228
229 self.gui.interpreter.queue('molecule.delete', gui_to_str(self.info['id']))
230
231
233 """Wrapper method.
234
235 @param event: The wx event.
236 @type event: wx event
237 """
238
239
240 msg = "Are you sure you would like to deselect all spins of this molecule?"
241 if status.show_gui and Question(msg, parent=self.gui.spin_viewer, default=False).ShowModal() == wx.ID_NO:
242 return
243
244
245 self.gui.interpreter.queue('deselect.spin', spin_id=gui_to_str(self.info['id']), change_all=False)
246
247
249 """Wrapper method.
250
251 @param event: The wx event.
252 @type event: wx event
253 """
254
255
256 uf_store['molecule.name'](wx_parent=self.gui.spin_viewer, mol_id=self.info['id'])
257
258
277
278
280 """Wrapper method.
281
282 @param event: The wx event.
283 @type event: wx event
284 """
285
286
287 msg = "Are you sure you would like to select all spins of this molecule?"
288 if status.show_gui and Question(msg, parent=self.gui.spin_viewer, default=False).ShowModal() == wx.ID_NO:
289 return
290
291
292 self.gui.interpreter.queue('select.spin', spin_id=gui_to_str(self.info['id']), change_all=False)
293
294
296 """Wrapper method.
297
298 @param event: The wx event.
299 @type event: wx event
300 """
301
302
303 uf_store['residue.create'](wx_parent=self.gui.spin_viewer, mol_name=self.info['mol_name'])
304
305
307 """Wrapper method.
308
309 @param event: The wx event.
310 @type event: wx event
311 """
312
313
314 uf_store['residue.copy'](wx_parent=self.gui.spin_viewer, pipe_from=cdp_name(), res_from=self.info['id'], pipe_to=cdp_name())
315
316
318 """Wrapper method.
319
320 @param event: The wx event.
321 @type event: wx event
322 """
323
324
325 msg = "Are you sure you would like to delete this residue? This only affects the spin data, all structural data will remain. This operation cannot be undone."
326 if status.show_gui and Question(msg, parent=self.gui.spin_viewer, default=False, size=(400, 170)).ShowModal() == wx.ID_NO:
327 return
328
329
330 self.gui.interpreter.queue('residue.delete', gui_to_str(self.info['id']))
331
332
334 """Wrapper method.
335
336 @param event: The wx event.
337 @type event: wx event
338 """
339
340
341 msg = "Are you sure you would like to deselect all spins of this residue?"
342 if status.show_gui and Question(msg, parent=self.gui.spin_viewer, default=False).ShowModal() == wx.ID_NO:
343 return
344
345
346 self.gui.interpreter.queue('deselect.spin', spin_id=gui_to_str(self.info['id']), change_all=False)
347
348
350 """Wrapper method.
351
352 @param event: The wx event.
353 @type event: wx event
354 """
355
356
357 uf_store['residue.name'](wx_parent=self.gui.spin_viewer, res_id=self.info['id'])
358
359
361 """Wrapper method.
362
363 @param event: The wx event.
364 @type event: wx event
365 """
366
367
368 uf_store['residue.number'](wx_parent=self.gui.spin_viewer, res_id=self.info['id'])
369
370
372 """Wrapper method.
373
374 @param event: The wx event.
375 @type event: wx event
376 """
377
378
379 msg = "Are you sure you would like to select all spins of this residue?"
380 if status.show_gui and Question(msg, parent=self.gui.spin_viewer, default=False).ShowModal() == wx.ID_NO:
381 return
382
383
384 self.gui.interpreter.queue('select.spin', spin_id=gui_to_str(self.info['id']), change_all=False)
385
386
388 """Wrapper method.
389
390 @param event: The wx event.
391 @type event: wx event
392 """
393
394
395 uf_store['spin.create'](wx_parent=self.gui.spin_viewer, mol_name=self.info['mol_name'], res_num=self.info['res_num'], res_name=self.info['res_name'])
396
397
399 """Wrapper method.
400
401 @param event: The wx event.
402 @type event: wx event
403 """
404
405
406 uf_store['spin.create_pseudo'](wx_parent=self.gui.spin_viewer, res_id=self.info['id'])
407
408
410 """Wrapper method.
411
412 @param event: The wx event.
413 @type event: wx event
414 """
415
416
417 uf_store['molecule.create'](wx_parent=self.gui.spin_viewer)
418
419
421 """Wrapper method.
422
423 @param event: The wx event.
424 @type event: wx event
425 """
426
427
428 uf_store['spin.copy'](wx_parent=self.gui.spin_viewer, pipe_from=cdp_name(), spin_from=self.info['id'], pipe_to=cdp_name())
429
430
432 """Wrapper method.
433
434 @param event: The wx event.
435 @type event: wx event
436 """
437
438
439 msg = "Are you sure you would like to delete this spin? This only affects the spin data, all structural data will remain. This operation cannot be undone."
440 if status.show_gui and Question(msg, parent=self.gui.spin_viewer, default=False, size=(400, 170)).ShowModal() == wx.ID_NO:
441 return
442
443
444 self.gui.interpreter.queue('spin.delete', gui_to_str(self.info['id']))
445
446
448 """Wrapper method.
449
450 @param event: The wx event.
451 @type event: wx event
452 """
453
454
455 self.gui.interpreter.queue('deselect.spin', spin_id=gui_to_str(self.info['id']), change_all=False)
456
457
473
474
476 """Wrapper method.
477
478 @param event: The wx event.
479 @type event: wx event
480 """
481
482
483 uf_store['spin.name'](wx_parent=self.gui.spin_viewer, spin_id=self.info['id'])
484
485
487 """Wrapper method.
488
489 @param event: The wx event.
490 @type event: wx event
491 """
492
493
494 uf_store['spin.number'](wx_parent=self.gui.spin_viewer, spin_id=self.info['id'])
495
496
498 """Wrapper method.
499
500 @param event: The wx event.
501 @type event: wx event
502 """
503
504
505 self.gui.interpreter.queue('select.spin', spin_id=gui_to_str(self.info['id']), change_all=False)
506
507
509 """Get the python data structure associated with the current item.
510
511 @return: The dictionary of data.
512 @rtype: dict
513 """
514
515
516 item = self.tree.GetSelection()
517
518
519 if not item.IsOk():
520 return
521
522
523 return self.tree.GetItemPyData(item)
524
525
547
548
550 """The right click molecule menu."""
551
552
553 items = []
554
555
556 menu = wx.Menu()
557
558
559 items.append(build_menu_item(menu, id=MENU_MOLECULE_MOLECULE_COPY, text="&Copy the molecule", icon=fetch_icon("oxygen.actions.list-add")))
560 items.append(build_menu_item(menu, id=MENU_MOLECULE_MOLECULE_DELETE, text="De&lete the molecule", icon=fetch_icon("oxygen.actions.list-remove")))
561 items.append(build_menu_item(menu, id=MENU_MOLECULE_MOLECULE_NAME, text="&Name the molecule", icon=fetch_icon("oxygen.actions.edit-rename")))
562 items.append(build_menu_item(menu, id=MENU_MOLECULE_MOLECULE_TYPE, text="Set the molecule &type", icon=fetch_icon("oxygen.actions.edit-rename")))
563 items.append(build_menu_item(menu, id=MENU_MOLECULE_RESIDUE_CREATE, text="Add a &residue", icon=fetch_icon("oxygen.actions.list-add-relax-blue")))
564
565
566 for item in items:
567 menu.AppendItem(item)
568 if status.exec_lock.locked():
569 item.Enable(False)
570
571
572 menu.AppendSeparator()
573
574
575 if self.info['select']:
576 item = build_menu_item(menu, id=MENU_MOLECULE_MOLECULE_DESELECT, text="&Deselect", icon=fetch_icon("relax.molecule_grey"))
577 else:
578 item = build_menu_item(menu, id=MENU_MOLECULE_MOLECULE_SELECT, text="&Select", icon=fetch_icon("relax.molecule"))
579 menu.AppendItem(item)
580 if status.exec_lock.locked():
581 item.Enable(False)
582
583
584 self.Bind(wx.EVT_MENU, self.action_molecule_molecule_copy, id=MENU_MOLECULE_MOLECULE_COPY)
585 self.Bind(wx.EVT_MENU, self.action_molecule_molecule_delete, id=MENU_MOLECULE_MOLECULE_DELETE)
586 self.Bind(wx.EVT_MENU, self.action_molecule_molecule_name, id=MENU_MOLECULE_MOLECULE_NAME)
587 self.Bind(wx.EVT_MENU, self.action_molecule_molecule_type, id=MENU_MOLECULE_MOLECULE_TYPE)
588 self.Bind(wx.EVT_MENU, self.action_molecule_residue_create, id=MENU_MOLECULE_RESIDUE_CREATE)
589 if self.info['select']:
590 self.Bind(wx.EVT_MENU, self.action_molecule_molecule_deselect, id=MENU_MOLECULE_MOLECULE_DESELECT)
591 else:
592 self.Bind(wx.EVT_MENU, self.action_molecule_molecule_select, id=MENU_MOLECULE_MOLECULE_SELECT)
593
594
595 if status.show_gui:
596 self.PopupMenu(menu)
597
598
599 menu.Destroy()
600
601
603 """The right click molecule menu."""
604
605
606 items = []
607
608
609 menu = wx.Menu()
610
611
612 items.append(build_menu_item(menu, id=MENU_RESIDUE_RESIDUE_COPY, text="&Copy the residue", icon=fetch_icon("oxygen.actions.list-add")))
613 items.append(build_menu_item(menu, id=MENU_RESIDUE_RESIDUE_DELETE, text="De&lete the residue", icon=fetch_icon("oxygen.actions.list-remove")))
614 items.append(build_menu_item(menu, id=MENU_RESIDUE_RESIDUE_NAME, text="&Name the residue", icon=fetch_icon("oxygen.actions.edit-rename")))
615 items.append(build_menu_item(menu, id=MENU_RESIDUE_RESIDUE_NUMBER, text="N&umber the residue", icon=fetch_icon("oxygen.actions.edit-rename")))
616 items.append(build_menu_item(menu, id=MENU_RESIDUE_SPIN_ADD, text="&Add a spin", icon=fetch_icon("oxygen.actions.list-add-relax-blue")))
617 items.append(build_menu_item(menu, id=MENU_RESIDUE_SPIN_CREATE_PSEUDO, text="Create a &pseudo-atom", icon=fetch_icon("oxygen.actions.list-add-relax-blue")))
618
619
620 for item in items:
621 menu.AppendItem(item)
622 if status.exec_lock.locked():
623 item.Enable(False)
624
625
626 menu.AppendSeparator()
627
628
629 if self.info['select']:
630 item = build_menu_item(menu, id=MENU_RESIDUE_RESIDUE_DESELECT, text="&Deselect", icon=fetch_icon("relax.residue_grey"))
631 else:
632 item = build_menu_item(menu, id=MENU_RESIDUE_RESIDUE_SELECT, text="&Select", icon=fetch_icon("relax.residue"))
633 menu.AppendItem(item)
634 if status.exec_lock.locked():
635 item.Enable(False)
636
637
638 self.Bind(wx.EVT_MENU, self.action_residue_residue_copy, id=MENU_RESIDUE_RESIDUE_COPY)
639 self.Bind(wx.EVT_MENU, self.action_residue_residue_delete, id=MENU_RESIDUE_RESIDUE_DELETE)
640 self.Bind(wx.EVT_MENU, self.action_residue_residue_name, id=MENU_RESIDUE_RESIDUE_NAME)
641 self.Bind(wx.EVT_MENU, self.action_residue_residue_number, id=MENU_RESIDUE_RESIDUE_NUMBER)
642 self.Bind(wx.EVT_MENU, self.action_residue_spin_add, id=MENU_RESIDUE_SPIN_ADD)
643 self.Bind(wx.EVT_MENU, self.action_residue_spin_create_pseudo, id=MENU_RESIDUE_SPIN_CREATE_PSEUDO)
644 if self.info['select']:
645 self.Bind(wx.EVT_MENU, self.action_residue_residue_deselect, id=MENU_RESIDUE_RESIDUE_DESELECT)
646 else:
647 self.Bind(wx.EVT_MENU, self.action_residue_residue_select, id=MENU_RESIDUE_RESIDUE_SELECT)
648
649
650 if status.show_gui:
651 self.PopupMenu(menu)
652
653
654 menu.Destroy()
655
656
658 """The right click root menu."""
659
660
661 items = []
662
663
664 menu = wx.Menu()
665
666
667 items.append(build_menu_item(menu, id=MENU_ROOT_MOLECULE_CREATE, text="&Add a molecule", icon=fetch_icon("oxygen.actions.list-add-relax-blue")))
668 items.append(build_menu_item(menu, id=MENU_ROOT_LOAD_SPINS, text="&Load spins", icon=fetch_icon("relax.spin", "16x16")))
669
670
671 for item in items:
672 menu.AppendItem(item)
673 if status.exec_lock.locked():
674 item.Enable(False)
675
676
677 self.Bind(wx.EVT_MENU, self.action_root_molecule_create, id=MENU_ROOT_MOLECULE_CREATE)
678 self.Bind(wx.EVT_MENU, self.gui.spin_viewer.load_spins_wizard, id=MENU_ROOT_LOAD_SPINS)
679
680
681 if status.show_gui:
682 self.PopupMenu(menu)
683
684
685 menu.Destroy()
686
687
689 """The right click spin menu."""
690
691
692 items = []
693
694
695 menu = wx.Menu()
696
697
698 items.append(build_menu_item(menu, id=MENU_SPIN_SPIN_COPY, text="&Copy the spin", icon=fetch_icon("oxygen.actions.list-add")))
699 items.append(build_menu_item(menu, id=MENU_SPIN_SPIN_DELETE, text="De&lete the spin", icon=fetch_icon("oxygen.actions.list-remove")))
700 items.append(build_menu_item(menu, id=MENU_SPIN_SPIN_ELEMENT, text="Set the element &type of the spin", icon=fetch_icon("oxygen.actions.edit-rename")))
701 items.append(build_menu_item(menu, id=MENU_SPIN_SPIN_NAME, text="&Name the spin", icon=fetch_icon("oxygen.actions.edit-rename")))
702 items.append(build_menu_item(menu, id=MENU_SPIN_SPIN_NUMBER, text="N&umber the spin", icon=fetch_icon("oxygen.actions.edit-rename")))
703
704
705 for item in items:
706 menu.AppendItem(item)
707 if status.exec_lock.locked():
708 item.Enable(False)
709
710
711 menu.AppendSeparator()
712
713
714 if self.info['select']:
715 item = build_menu_item(menu, id=MENU_SPIN_SPIN_DESELECT, text="&Deselect", icon=fetch_icon("relax.spin_grey"))
716 else:
717 item = build_menu_item(menu, id=MENU_SPIN_SPIN_SELECT, text="&Select", icon=fetch_icon("relax.spin"))
718 menu.AppendItem(item)
719 if status.exec_lock.locked():
720 item.Enable(False)
721
722
723 self.Bind(wx.EVT_MENU, self.action_spin_spin_copy, id=MENU_SPIN_SPIN_COPY)
724 self.Bind(wx.EVT_MENU, self.action_spin_spin_delete, id=MENU_SPIN_SPIN_DELETE)
725 self.Bind(wx.EVT_MENU, self.action_spin_spin_element, id=MENU_SPIN_SPIN_ELEMENT)
726 self.Bind(wx.EVT_MENU, self.action_spin_spin_name, id=MENU_SPIN_SPIN_NAME)
727 self.Bind(wx.EVT_MENU, self.action_spin_spin_number, id=MENU_SPIN_SPIN_NUMBER)
728 if self.info['select']:
729 self.Bind(wx.EVT_MENU, self.action_spin_spin_deselect, id=MENU_SPIN_SPIN_DESELECT)
730 else:
731 self.Bind(wx.EVT_MENU, self.action_spin_spin_select, id=MENU_SPIN_SPIN_SELECT)
732
733
734 if status.show_gui:
735 self.PopupMenu(menu)
736
737
738 menu.Destroy()
739
740
742 """Remove any molecules which have been deleted."""
743
744
745 mol_ids = get_molecule_ids()
746
747
748 prune_list = []
749 for key in self.tree_ids:
750
751 info = self.tree.GetItemPyData(key)
752
753
754 if info == None or 'id' not in info:
755 continue
756
757
758 if info['id'] not in mol_ids:
759 prune_list.append(key)
760
761
762 for key in prune_list:
763 self.tree.Delete(key)
764 self.tree_ids.pop(key)
765
766
768 """Remove any molecules which have been deleted.
769
770 @param mol_branch_id: The molecule branch ID of the wx.TreeCtrl object.
771 @type mol_branch_id: TreeItemId
772 @param mol_id: The molecule identification string.
773 @type mol_id: str
774 """
775
776
777 prune_list = []
778 for key in self.tree_ids[mol_branch_id]:
779
780 info = self.tree.GetItemPyData(key)
781
782
783 if info == None or 'id' not in info:
784 continue
785
786
787 res = return_residue(info['id'])
788
789
790 if res == None or res.name != info['res_name'] or res.num != info['res_num']:
791 prune_list.append(key)
792
793
794 for key in prune_list:
795 self.tree.Delete(key)
796 self.tree_ids[mol_branch_id].pop(key)
797
798
799 - def prune_spin(self, mol_branch_id, res_branch_id, res_id):
800 """Remove any spins which have been deleted.
801
802 @param mol_branch_id: The molecule branch ID of the wx.TreeCtrl object.
803 @type mol_branch_id: TreeItemId
804 @param res_branch_id: The residue branch ID of the wx.TreeCtrl object.
805 @type res_branch_id: TreeItemId
806 @param res_id: The residue identification string.
807 @type res_id: str
808 """
809
810
811 prune_list = []
812 for key in self.tree_ids[mol_branch_id][res_branch_id]:
813
814 info = self.tree.GetItemPyData(key)
815
816
817 if info == None or 'id' not in info:
818 continue
819
820
821 spin = return_spin(spin_id=info['id'])
822
823
824 if spin == None or spin.name != info['spin_name'] or spin.num != info['spin_num']:
825 prune_list.append(key)
826
827
828 for key in prune_list:
829 self.tree.Delete(key)
830 self.tree_ids[mol_branch_id][res_branch_id].pop(key)
831
832
834 """Set the molecule bitmaps.
835
836 @param mol_branch_id: The molecule branch ID of the wx.TreeCtrl object.
837 @type mol_branch_id: TreeItemId
838 @keyword select: The selection flag.
839 @type select: bool
840 """
841
842
843 if select:
844 bmp = self.icon_mol_index
845 bmp_unfold = self.icon_mol_unfold_index
846
847
848 else:
849 bmp = self.icon_mol_index_desel
850 bmp_unfold = self.icon_mol_unfold_index_desel
851
852
853 self.tree.SetItemImage(mol_branch_id, bmp, wx.TreeItemIcon_Normal)
854 self.tree.SetItemImage(mol_branch_id, bmp_unfold, wx.TreeItemIcon_Expanded)
855
856
858 """Set the residue bitmaps.
859
860 @param res_branch_id: The residue branch ID of the wx.TreeCtrl object.
861 @type res_branch_id: TreeItemId
862 @keyword select: The selection flag.
863 @type select: bool
864 """
865
866
867 if select:
868 bmp = self.icon_res_index
869
870
871 else:
872 bmp = self.icon_res_index_desel
873
874
875 self.tree.SetItemImage(res_branch_id, bmp, wx.TreeItemIcon_Normal & wx.TreeItemIcon_Expanded)
876
877
879 """Set the spin bitmaps.
880
881 @param spin_branch_id: The spin branch ID of the wx.TreeCtrl object.
882 @type spin_branch_id: TreeItemId
883 @keyword select: The selection flag.
884 @type select: bool
885 """
886
887
888 if select:
889 bmp = self.icon_spin_index
890
891
892 else:
893 bmp = self.icon_spin_index_desel
894
895
896 self.tree.SetItemImage(spin_branch_id, bmp, wx.TreeItemIcon_Normal & wx.TreeItemIcon_Expanded)
897
898
899 - def update(self, pipe_name=None):
900 """Update the tree view using the given data pipe."""
901
902
903 status.pipe_lock.acquire('spin viewer window')
904 status.spin_lock.acquire('spin viewer window')
905 try:
906
907 if not pipe_name:
908 pipe = cdp
909 else:
910 pipe = get_pipe(pipe_name)
911
912
913 if not pipe:
914 self.tree.DeleteChildren(self.root)
915 return
916
917
918 for mol, mol_id in molecule_loop(return_id=True):
919 self.update_mol(mol, mol_id)
920
921
922 self.prune_mol()
923
924
925 finally:
926 status.pipe_lock.release('spin viewer window')
927 status.spin_lock.release('spin viewer window')
928
929
931 """Update the given molecule in the tree.
932
933 @param mol: The molecule container.
934 @type mol: MoleculeContainer instance
935 @param mol_id: The molecule identification string.
936 @type mol_id: str
937 """
938
939
940 new_mol = True
941 for key in self.tree_ids:
942
943 data = self.tree.GetItemPyData(key)
944
945
946 if data == None or 'id' not in data:
947 continue
948
949
950 if mol_id == data['id']:
951 new_mol = False
952 mol_branch_id = key
953 break
954
955
956 if new_mol:
957
958 mol_branch_id = self.tree.AppendItem(self.root, "Molecule: %s" % mol.name)
959
960
961 data = {
962 'type': 'mol',
963 'mol_name': mol.name,
964 'id': mol_id,
965 'select': is_mol_selected(mol_id)
966 }
967 self.tree.SetPyData(mol_branch_id, data)
968
969
970 self.tree_ids[mol_branch_id] = {}
971
972
973 self.set_bitmap_mol(mol_branch_id, select=data['select'])
974
975
976 else:
977
978 select = is_mol_selected(data['id'])
979
980
981 if select != data['select']:
982
983 data['select'] = select
984
985
986 self.set_bitmap_mol(mol_branch_id, select=data['select'])
987
988
989 for res, res_id in residue_loop(mol_id, return_id=True):
990 self.update_res(mol_branch_id, mol, res, res_id)
991
992
993 if new_mol and data['select']:
994 self.tree.Expand(mol_branch_id)
995
996
997 self.prune_res(mol_branch_id, mol_id)
998
999
1000 self.tree.Expand(self.root)
1001
1002
1003 - def update_res(self, mol_branch_id, mol, res, res_id):
1004 """Update the given residue in the tree.
1005
1006 @param mol_branch_id: The molecule branch ID of the wx.TreeCtrl object.
1007 @type mol_branch_id: TreeItemId
1008 @param mol: The molecule container.
1009 @type mol: MoleculeContainer instance
1010 @param res: The residue container.
1011 @type res: ResidueContainer instance
1012 @param res_id: The residue identification string.
1013 @type res_id: str
1014 """
1015
1016
1017 new_res = True
1018 for key in self.tree_ids[mol_branch_id]:
1019
1020 data = self.tree.GetItemPyData(key)
1021
1022
1023 if data == None or 'id' not in data:
1024 continue
1025
1026
1027 if res_id == data['id'] and res.name == data['res_name'] and res.num == data['res_num']:
1028 new_res = False
1029 res_branch_id = key
1030 break
1031
1032
1033 if new_res:
1034
1035 res_branch_id = self.tree.AppendItem(mol_branch_id, "Residue: %s %s" % (res.num, res.name))
1036
1037
1038 data = {
1039 'type': 'res',
1040 'mol_name': mol.name,
1041 'res_name': res.name,
1042 'res_num': res.num,
1043 'id': res_id,
1044 'select': is_res_selected(res_id)
1045 }
1046 self.tree.SetPyData(res_branch_id, data)
1047
1048
1049 self.tree_ids[mol_branch_id][res_branch_id] = {}
1050
1051
1052 self.set_bitmap_res(res_branch_id, select=data['select'])
1053
1054
1055 else:
1056
1057 select = is_res_selected(data['id'])
1058
1059
1060 if select != data['select']:
1061
1062 data['select'] = select
1063
1064
1065 self.set_bitmap_res(res_branch_id, select=data['select'])
1066
1067
1068 for spin, spin_id in spin_loop(res_id, return_id=True):
1069 self.update_spin(mol_branch_id, res_branch_id, mol, res, spin, spin_id)
1070
1071
1072 if new_res and data['select']:
1073 self.tree.Expand(res_branch_id)
1074
1075
1076 self.prune_spin(mol_branch_id, res_branch_id, res_id)
1077
1078
1079 - def update_spin(self, mol_branch_id, res_branch_id, mol, res, spin, spin_id):
1080 """Update the given spin in the tree.
1081
1082 @param mol_branch_id: The molecule branch ID of the wx.TreeCtrl object.
1083 @type mol_branch_id: TreeItemId
1084 @param res_branch_id: The residue branch ID of the wx.TreeCtrl object.
1085 @type res_branch_id: TreeItemId
1086 @param mol: The molecule container.
1087 @type mol: MoleculeContainer instance
1088 @param res: The residue container.
1089 @type res: ResidueContainer instance
1090 @param spin: The spin container.
1091 @type spin: SpinContainer instance
1092 @param spin_id: The spin identification string.
1093 @type spin_id: str
1094 """
1095
1096
1097 new_spin = True
1098 for key in self.tree_ids[mol_branch_id][res_branch_id]:
1099
1100 data = self.tree.GetItemPyData(key)
1101
1102
1103 if data == None or 'id' not in data:
1104 continue
1105
1106
1107 if spin_id == data['id'] and spin.name == data['spin_name'] and spin.num == data['spin_num']:
1108 new_spin = False
1109 spin_branch_id = key
1110 break
1111
1112
1113 if new_spin:
1114
1115 spin_branch_id = self.tree.AppendItem(res_branch_id, "Spin: %s %s" % (spin.num, spin.name))
1116
1117
1118 data = {
1119 'type': 'spin',
1120 'mol_name': mol.name,
1121 'res_name': res.name,
1122 'res_num': res.num,
1123 'spin_name': spin.name,
1124 'spin_num': spin.num,
1125 'id': spin_id,
1126 'select': is_spin_selected(spin_id)
1127 }
1128 self.tree.SetPyData(spin_branch_id, data)
1129
1130
1131 self.tree_ids[mol_branch_id][res_branch_id][spin_branch_id] = True
1132
1133
1134 self.set_bitmap_spin(spin_branch_id, select=data['select'])
1135
1136
1137 else:
1138
1139 select = is_spin_selected(data['id'])
1140
1141
1142 if select != data['select']:
1143
1144 data['select'] = select
1145
1146
1147 self.set_bitmap_spin(spin_branch_id, select=data['select'])
1148
1149
1150 if new_spin and data['select']:
1151 self.tree.Expand(spin_branch_id)
1152