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