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