source: sasview/calculatorview/perspectives/calculator/collimation_editor.py @ 85e665e

ESS_GUIESS_GUI_DocsESS_GUI_batch_fittingESS_GUI_bumps_abstractionESS_GUI_iss1116ESS_GUI_iss879ESS_GUI_iss959ESS_GUI_openclESS_GUI_orderingESS_GUI_sync_sascalccostrafo411magnetic_scattrelease-4.1.1release-4.1.2release-4.2.2release_4.0.1ticket-1009ticket-1094-headlessticket-1242-2d-resolutionticket-1243ticket-1249ticket885unittest-saveload
Last change on this file since 85e665e was 85e665e, checked in by Gervaise Alina <gervyh@…>, 14 years ago

working on data editor

  • Property mode set to 100644
File size: 22.1 KB
Line 
1
2import wx
3import sys
4from copy import deepcopy
5from DataLoader.loader import Loader
6from DataLoader.data_info import Aperture, Collimation
7from aperture_editor import ApertureDialog
8
9from sans.guiframe.utils import check_float
10_BOX_WIDTH = 60
11
12if sys.platform.count("win32")>0:
13    _STATICBOX_WIDTH = 500
14    PANEL_WIDTH = 530
15    PANEL_HEIGHT = 430
16    FONT_VARIANT = 0
17else:
18    _STATICBOX_WIDTH = 550
19    PANEL_WIDTH = 600
20    PANEL_HEIGHT = 480
21    FONT_VARIANT = 1
22   
23class CollimationDialog(wx.Dialog):
24    def __init__(self, parent=None, manager=None,
25                 collimation=[], *args, **kwds):
26        """
27        """
28        kwds['size'] =(PANEL_WIDTH, PANEL_HEIGHT)
29        kwds['title'] = "Collimation Editor"
30        wx.Dialog.__init__(self, parent=parent, *args, **kwds)
31        self.parent = parent
32        self.manager = manager
33        self._collimation = collimation
34        self._reset_collimation = deepcopy(collimation)
35        self._notes = ""
36        self._description = "Edit collimation"
37        self._do_layout()
38        self.set_values()
39 
40    def _define_structure(self):
41        """
42            define initial sizer
43        """
44        self.main_sizer = wx.BoxSizer(wx.VERTICAL)
45        self.box_collimation = wx.StaticBox(self, -1,str("Edit Selected Collimation"))
46        self.boxsizer_collimation = wx.StaticBoxSizer(self.box_collimation, wx.VERTICAL)
47       
48        collimation_box = wx.StaticBox(self, -1, "Edit Number of Collimations")
49        self.collimation_sizer = wx.StaticBoxSizer(collimation_box, wx.VERTICAL)
50        self.collimation_sizer.SetMinSize((_STATICBOX_WIDTH, -1))
51        self.collimation_button_sizer = wx.BoxSizer(wx.HORIZONTAL)
52        self.collimation_hint_sizer = wx.BoxSizer(wx.HORIZONTAL)
53       
54        self.name_sizer = wx.BoxSizer(wx.HORIZONTAL)
55        self.length_sizer = wx.BoxSizer(wx.HORIZONTAL)
56        self.button_sizer = wx.BoxSizer(wx.HORIZONTAL)
57       
58        aperture_box = wx.StaticBox(self, -1, "Edit Aperture")
59        self.aperture_sizer = wx.StaticBoxSizer(aperture_box, wx.VERTICAL)
60        self.aperture_button_sizer = wx.BoxSizer(wx.HORIZONTAL)
61        self.aperture_hint_sizer = wx.BoxSizer(wx.HORIZONTAL)
62     
63    def _layout_collimation(self):
64        """
65            Do the layout for collimation related widgets
66        """
67        collimation_name_txt = wx.StaticText(self, -1, "Collimation:") 
68        hint_collimation_txt = 'Current available collimation.'
69        collimation_name_txt.SetToolTipString(hint_collimation_txt) 
70        self.collimation_cbox = wx.ComboBox(self, -1, style=wx.CB_READONLY)
71        hint_collimation_name_txt = 'Name of collimations.'
72        self.collimation_cbox.SetToolTipString(hint_collimation_name_txt) 
73   
74        self.bt_add_collimation = wx.Button(self, -1, "Add")
75        self.bt_add_collimation.SetToolTipString("Edit data's collimation.")
76        self.bt_add_collimation.Bind(wx.EVT_BUTTON, self.add_collimation)
77       
78        self.bt_remove_collimation = wx.Button(self, -1, "Remove")
79        self.bt_remove_collimation.SetToolTipString("Remove data's collimation.")
80        self.bt_remove_collimation.Bind(wx.EVT_BUTTON, self.remove_collimation)
81     
82        self.collimation_button_sizer.AddMany([(collimation_name_txt, 0, wx.LEFT, 15),
83                                     (self.collimation_cbox, 0, wx.LEFT, 5),
84                                     (self.bt_add_collimation, 0, wx.LEFT, 10),
85                                     (self.bt_remove_collimation, 0, wx.LEFT, 5)])
86        collimation_hint_txt = 'No collimation is available for this data.'
87        self.collimation_txt = wx.StaticText(self, -1, collimation_hint_txt) 
88        self.collimation_hint_sizer.Add(self.collimation_txt, 0, wx.LEFT, 10)
89        self.collimation_sizer.AddMany([(self.collimation_button_sizer, 0, wx.ALL, 10),
90                                     (self.collimation_hint_sizer, 0, wx.ALL, 10)])
91     
92        self.fill_collimation_combox()
93        self.enable_collimation()
94       
95
96    def _layout_name(self):
97        """
98            Do the layout for collimation name related widgets
99        """
100        #Collimation name [string]
101        name_txt = wx.StaticText(self, -1, 'Name : ') 
102        self.name_tcl = wx.TextCtrl(self, -1, size=(_BOX_WIDTH*5, 20), style=0) 
103        self.name_sizer.AddMany([(name_txt, 0, wx.LEFT|wx.RIGHT, 10),
104                                       (self.name_tcl, 0, wx.EXPAND)])
105       
106    def _layout_length(self):
107        """
108            Do the  layout for length related widgets
109        """
110        #Collimation length
111        length_txt = wx.StaticText(self, -1, 'Length:') 
112        self.length_tcl = wx.TextCtrl(self, -1, size=(_BOX_WIDTH, 20), style=0)   
113        length_unit_txt = wx.StaticText(self, -1, 'Unit: ') 
114        self.length_unit_tcl = wx.TextCtrl(self, -1, size=(_BOX_WIDTH, 20),style=0) 
115        self.length_sizer.AddMany([(length_txt, 0, wx.LEFT|wx.RIGHT, 10),
116                                     (self.length_tcl, 0, wx.LEFT, 12),
117                                     (length_unit_txt, 0, wx.LEFT|wx.RIGHT, 10),
118                                     (self.length_unit_tcl, 0, wx.EXPAND)]) 
119   
120    def _layout_button(self): 
121        """
122            Do the layout for the button widgets
123        """ 
124        self.bt_apply = wx.Button(self, -1,'Apply')
125        self.bt_apply.Bind(wx.EVT_BUTTON, self.on_click_apply)
126        self.bt_apply.SetToolTipString("Apply current changes to collimation.")
127        self.bt_cancel = wx.Button(self, -1,'Cancel')
128        self.bt_cancel.SetToolTipString("Cancel current changes.")
129        self.bt_cancel.Bind(wx.EVT_BUTTON, self.on_click_cancel)
130        self.bt_close = wx.Button(self, wx.ID_CANCEL,'Close')
131        self.bt_close.SetToolTipString("Close window.")
132        self.button_sizer.AddMany([(self.bt_apply, 0, wx.LEFT, 200),
133                                   (self.bt_cancel, 0, wx.LEFT, 10),
134                                   (self.bt_close, 0, wx.LEFT, 10)])
135    def _layout_aperture(self):
136        """
137            Do the layout for aperture related widgets
138        """
139        aperture_name_txt = wx.StaticText(self, -1, "Aperture:") 
140        hint_aperture_txt = 'Current available aperture.'
141        aperture_name_txt.SetToolTipString(hint_aperture_txt) 
142        self.aperture_cbox = wx.ComboBox(self, -1, style=wx.CB_READONLY)
143        hint_aperture_name_txt = 'Name of apertures.'
144        self.aperture_cbox.SetToolTipString(hint_aperture_name_txt) 
145   
146        self.bt_add_aperture = wx.Button(self, -1, "Add")
147        self.bt_add_aperture.SetToolTipString("Edit data's aperture.")
148        self.bt_add_aperture.Bind(wx.EVT_BUTTON, self.add_aperture)
149        self.bt_edit_aperture = wx.Button(self, -1, "Edit")
150        self.bt_edit_aperture.SetToolTipString("Edit data's aperture.")
151        self.bt_edit_aperture.Bind(wx.EVT_BUTTON, self.edit_aperture)
152        self.bt_remove_aperture = wx.Button(self, -1, "Remove")
153        self.bt_remove_aperture.SetToolTipString("Remove data's aperture.")
154        self.bt_remove_aperture.Bind(wx.EVT_BUTTON, self.remove_aperture)
155     
156        self.aperture_button_sizer.AddMany([(aperture_name_txt, 0, wx.LEFT, 15),
157                                     (self.aperture_cbox, 0, wx.LEFT, 5),
158                                     (self.bt_add_aperture, 0, wx.LEFT, 10),
159                                     (self.bt_edit_aperture, 0, wx.LEFT, 5),
160                                     (self.bt_remove_aperture, 0, wx.LEFT, 5)])
161        aperture_hint_txt = 'No aperture is available for this data.'
162        self.aperture_txt = wx.StaticText(self, -1, aperture_hint_txt) 
163        self.aperture_hint_sizer.Add(self.aperture_txt, 0, wx.LEFT, 10)
164        self.aperture_sizer.AddMany([(self.aperture_button_sizer, 0, wx.ALL, 10),
165                                     (self.aperture_hint_sizer, 0, wx.ALL, 10)])
166        self.fill_aperture_combox()
167        self.enable_aperture()
168   
169    def _do_layout(self, data=None):
170        """
171            Draw the current panel
172        """
173        self._define_structure()
174        self._layout_collimation()
175        self._layout_name()
176        self._layout_length()
177        self._layout_aperture()
178        self._layout_button()
179     
180        self.boxsizer_collimation.AddMany([(self.name_sizer, 0,
181                                          wx.EXPAND|wx.TOP|wx.BOTTOM, 5),
182                                          (self.length_sizer, 0,
183                                     wx.EXPAND|wx.TOP|wx.BOTTOM, 5),
184                                     (self.aperture_sizer, 0,
185                                     wx.EXPAND|wx.ALL, 10)])
186        self.main_sizer.AddMany([(self.collimation_sizer, 0, wx.ALL, 10),
187                                  (self.boxsizer_collimation, 0, wx.ALL, 10),
188                                  (self.button_sizer, 0,
189                                    wx.EXPAND|wx.TOP|wx.BOTTOM, 5)])
190        self.SetSizer(self.main_sizer)
191        self.SetAutoLayout(True)
192       
193    def get_current_collimation(self):
194        """
195        """
196        if not self.collimation_cbox.IsEnabled():
197            return None, None, None
198        position = self.collimation_cbox.GetSelection() 
199        if position == wx.NOT_FOUND:
200            return None, None, None
201        collimation_name = self.collimation_cbox.GetStringSelection() 
202        collimation = self.collimation_cbox.GetClientData(position)
203        return collimation, collimation_name, position
204   
205    def fill_collimation_combox(self):
206        """
207            fill the current combobox with the available collimation
208        """
209        if self._collimation is None or self._collimation == []:
210            return
211        for collimation in self._collimation:
212            pos = self.collimation_cbox.Append(str(collimation.name))
213            self.collimation_cbox.SetClientData(pos, collimation)
214            self.collimation_cbox.SetSelection(pos)
215            self.collimation_cbox.SetStringSelection(str(collimation.name)) 
216           
217    def add_collimation(self, event):
218        """
219            Append empty collimation to data's list of collimation
220        """
221       
222        if not self.collimation_cbox.IsEnabled():
223            self.collimation_cbox.Enable()
224        collimation = Collimation()
225        self._collimation.append(collimation)
226        position = self.collimation_cbox.Append(str(collimation.name))
227        self.collimation_cbox.SetClientData(position, collimation)
228        self.collimation_cbox.SetSelection(position) 
229        self.enable_collimation() 
230        self.bt_add_aperture.Enable()
231        self.set_values()
232       
233    def remove_collimation(self, event):
234        """
235            Remove collimation to data's list of collimation
236        """
237        if self.collimation_cbox.IsEnabled():
238            if self.collimation_cbox.GetCount() > 0:
239                position = self.collimation_cbox.GetCurrentSelection()
240                collimation = self.collimation_cbox.GetClientData(position)
241                if collimation in self._collimation:
242                    self._collimation.remove(collimation)
243                    self.collimation_cbox.Delete(position) 
244                    #set the combo box box the next available item
245                    position = self.collimation_cbox.GetCount()
246                    if position > 0:
247                        position -= 1 
248                    self.collimation_cbox.SetSelection(position)
249        if not self._collimation and self.collimation_cbox.GetCount() == 0:       
250            self.bt_add_aperture.Disable() 
251            self.name_tcl.Clear()
252            self.length_tcl.Clear()
253            self.length_unit_tcl.Clear()
254            self.aperture_cbox.Clear()
255            self.aperture_cbox.Disable()
256        #disable or enable the combo box when necessary
257        self.enable_collimation()
258        self.enable_aperture()
259       
260    def enable_collimation(self):
261        """
262            Enable /disable widgets related to collimation
263        """
264        if self._collimation is not None and self.collimation_cbox.GetCount() > 0:
265            self.collimation_cbox.Enable()
266            self.bt_remove_collimation.Enable()
267            n_collimation = self.collimation_cbox.GetCount()
268            collimation_hint_txt = 'collimations available: %s '%str(n_collimation)
269            if len(self._collimation) > 0:
270                self.bt_remove_collimation.Enable()
271            else:
272                self.bt_remove_collimation.Disable()
273        else:
274            self.collimation_cbox.Disable()
275            self.bt_remove_collimation.Disable()
276            collimation_hint_txt = 'No collimation is available for this data.'
277        self.collimation_txt.SetLabel(collimation_hint_txt)
278           
279   
280    def reset_collimation_combobox(self, edited_collimation):
281        """
282            take all edited editor and reset clientdata of collimation combo box
283        """
284        for position in range(self.collimation_cbox.GetCount()):
285            collimation = self.collimation_cbox.GetClientData(position)
286            if collimation == edited_collimation:
287                collimation = edited_collimation
288                self.collimation_cbox.SetString(position, str(collimation.name)) 
289                self.collimation_cbox.SetClientData(position, collimation)
290                self.collimation_cbox.SetStringSelection(str(collimation.name)) 
291         
292    def add_aperture(self, event):
293        """
294            Append empty aperture to data's list of aperture
295        """
296        collimation, _, _ = self.get_current_collimation()
297        if not self.aperture_cbox.IsEnabled():
298            self.aperture_cbox.Enable()
299        aperture = Aperture()
300        collimation.aperture.append(aperture)
301        position = self.aperture_cbox.Append(str(aperture.name))
302        self.aperture_cbox.SetClientData(position, aperture)
303        self.aperture_cbox.SetSelection(position) 
304        self.enable_aperture()
305       
306    def edit_aperture(self, event):
307        """
308            Edit the selected aperture
309        """
310        if self._collimation is None or not self.aperture_cbox.IsEnabled():
311            return 
312        position = self.aperture_cbox.GetSelection() 
313        if position != wx.NOT_FOUND:
314            name = self.aperture_cbox.GetStringSelection() 
315            aperture = self.aperture_cbox.GetClientData(position)
316            dlg = ApertureDialog(parent=self, aperture=aperture)
317            dlg.set_manager(self)
318            dlg.ShowModal()
319           
320    def remove_aperture(self, event):
321        """
322            Remove aperture to data's list of aperture
323        """
324        if self._collimation is None or not self._collimation:
325            return
326        collimation, _, _ = self.get_current_collimation()
327        if self.aperture_cbox.IsEnabled():
328            if self.aperture_cbox.GetCount() > 1:
329                position = self.aperture_cbox.GetCurrentSelection()
330                aperture = self.aperture_cbox.GetClientData(position)
331                if aperture in collimation.aperture:
332                    collimation.aperture.remove(aperture)
333                    self.aperture_cbox.Delete(position) 
334                    #set the combo box box the next available item
335                    position = self.aperture_cbox.GetCount()
336                    if position > 0:
337                        position -= 1 
338                    self.aperture_cbox.SetSelection(position)
339                   
340        #disable or enable the combo box when necessary
341        self.enable_aperture()
342       
343    def set_aperture(self, aperture):
344        """
345            set aperture for data
346        """
347        if self._collimation is None or not self._collimation:
348            return
349        collimation, _, _ = self.get_current_collimation()
350        if collimation.aperture:
351            for item in collimation.aperture:
352                if item == aperture:
353                    item = aperture
354                    self.reset_aperture_combobox(edited_aperture=aperture)
355                    return
356               
357    def enable_aperture(self):
358        """
359            Enable /disable widgets crelated to aperture
360        """
361        collimation, _, _ = self.get_current_collimation()
362        if  self.aperture_cbox.GetCount() > 0:
363            self.aperture_cbox.Enable()
364            self.bt_edit_aperture.Enable()
365            self.bt_remove_aperture.Enable()
366            n_aperture = self.aperture_cbox.GetCount()
367            aperture_hint_txt = 'apertures available: %s '%str(n_aperture)
368            if len(collimation.aperture) > 1:
369                self.bt_remove_aperture.Enable()
370            else:
371                self.bt_remove_aperture.Disable()
372        else:
373            self.aperture_cbox.Disable()
374            self.bt_edit_aperture.Disable()
375            self.bt_remove_aperture.Disable()
376            aperture_hint_txt = 'No aperture is available for this data.'
377        self.aperture_txt.SetLabel(aperture_hint_txt)
378   
379    def reset_aperture_combobox(self, edited_aperture):
380        """
381            take all edited editor and reset clientdata of aperture combo box
382        """
383        for position in range(self.aperture_cbox.GetCount()):
384            aperture = self.aperture_cbox.GetClientData(position)
385            if aperture == edited_aperture:
386                aperture = edited_aperture
387                self.aperture_cbox.SetString(position, str(aperture.name)) 
388                self.aperture_cbox.SetClientData(position, aperture)
389                self.aperture_cbox.SetStringSelection(str(aperture.name)) 
390               
391    def fill_aperture_combox(self):
392        """
393            fill the current combobox with the available aperture
394        """
395        collimation, _, _ = self.get_current_collimation()
396        if collimation is None or not collimation.aperture:
397            return
398       
399        for aperture in collimation.aperture:
400            pos = self.aperture_cbox.Append(str(aperture.name))
401            self.aperture_cbox.SetClientData(pos, aperture)
402            self.aperture_cbox.SetSelection(pos)
403            self.aperture_cbox.SetStringSelection(str(aperture.name)) 
404         
405    def set_manager(self, manager):
406        """   
407            Set manager of this window
408        """
409        self.manager = manager
410       
411    def set_values(self):
412        """
413            take the collimation values of the current data and display them
414            through the panel
415        """
416        collimation, _, _ = self.get_current_collimation()
417        if collimation is None:
418            self.bt_add_aperture.Disable()
419            self.length_tcl.SetValue("")
420            self.name_tcl.SetValue("")
421            self.length_unit_tcl.SetValue("")
422            return
423        #Name
424        self.name_tcl.SetValue(str(collimation.name))
425        #length
426        self.length_tcl.SetValue(str(collimation.length))
427        #Length unit
428        self.length_unit_tcl.SetValue(str(collimation.length_unit))
429       
430    def get_collimation(self):
431        """
432            return the current collimation
433        """
434        return self._collimation
435   
436    def get_notes(self):
437        """
438            return notes
439        """
440        return self._notes
441   
442    def on_change_name(self):
443        """
444            Change name
445        """
446        collimation, collimation_name, position = self.get_current_collimation()
447        if collimation is None: 
448            return
449        #Change the name of the collimation
450        name = self.name_tcl.GetValue().lstrip().rstrip()
451        if name == "" or name == str(None):
452            name = None
453        if collimation.name != name:
454            self._notes += "Change collimation 's "
455            self._notes += "name from %s to %s \n"%(collimation.name, name)
456            collimation.name = name
457            self.collimation_cbox.SetString(position, str(collimation.name)) 
458            self.collimation_cbox.SetClientData(position, collimation)
459            self.collimation_cbox.SetStringSelection(str(collimation.name)) 
460   
461    def on_change_length(self):
462        """
463            Change the length
464        """
465        collimation, collimation_name, position = self.get_current_collimation()
466        if collimation is None: 
467            return
468        #Change length 
469        length = self.length_tcl.GetValue().lstrip().rstrip()
470        if length == "" or length == str(None):
471            length = None
472            collimation.length = length
473        else:
474            if check_float(self.length_tcl):
475                if collimation.length != float(length):
476                    self._notes += "Change Collimation length from "
477                    self._notes += "%s to %s \n"%(collimation.length, length)
478                    collimation.length  = float(length)
479            else:
480                self._notes += "Error: Expected a float for collimation length "
481                self._notes += "won't changes length from "
482                self._notes += "%s to %s"%(collimation.length, length)
483        #change length  unit
484        unit = self.length_unit_tcl.GetValue().lstrip().rstrip()
485        if collimation.length_unit != unit:
486            self._notes += " Change length's unit from "
487            self._notes += "%s to %s"%(collimation.length_unit, unit)
488            collimation.length_unit = unit
489   
490    def on_click_apply(self, event):
491        """
492            Apply user values to the collimation
493        """
494        self.on_change_name()
495        self.on_change_length()
496        self.set_values()
497        if self.manager is not None:
498            self.manager.set_collimation(self._collimation, self._notes)
499       
500    def on_click_cancel(self, event):
501        """
502            leave the collimation as it is and close
503        """
504        self._collimation = deepcopy(self._reset_collimation)
505        self.set_values()
506        if self.manager is not None:
507             self.manager.set_collimation(self._collimation)
508       
509 
510if __name__ =="__main__":
511
512    app  = wx.App()
513    dlg = CollimationDialog(collimation=[Collimation()])
514    dlg.ShowModal()
515    app.MainLoop()
516 
Note: See TracBrowser for help on using the repository browser.