source: sasview/src/sas/perspectives/calculator/data_operator.py @ 25f223b

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 25f223b was b9a5f0e, checked in by krzywon, 10 years ago

90% complete with the conversion.

  • Property mode set to 100644
File size: 34.6 KB
Line 
1"""
2GUI for the data operation
3"""
4import wx
5import sys
6import time
7import numpy
8from sas.dataloader.data_info import Data1D
9from sas.plottools.PlotPanel import PlotPanel
10from sas.plottools.plottables import Graph
11from sas.plottools import transform
12from matplotlib.font_manager import FontProperties
13from sas.guiframe.events import StatusEvent
14from sas.perspectives.calculator import calculator_widgets as widget   
15#Control panel width
16if sys.platform.count("win32") > 0:
17    PANEL_WIDTH = 790
18    PANEL_HEIGTH = 370
19    FONT_VARIANT = 0
20    _BOX_WIDTH = 200
21    ON_MAC = False
22else:
23    _BOX_WIDTH = 230
24    PANEL_WIDTH = 900
25    PANEL_HEIGTH = 430
26    FONT_VARIANT = 1
27    ON_MAC = True
28     
29class DataOperPanel(wx.ScrolledWindow):
30    """
31    """
32    def __init__(self, parent, *args, **kwds):
33        kwds['name'] = "Data Operation"
34        kwds["size"] = (PANEL_WIDTH, PANEL_HEIGTH)
35        wx.ScrolledWindow.__init__(self, parent, *args, **kwds)
36        self.parent = parent
37        #sizers etc.
38        self.main_sizer = None
39        self.name_sizer = None
40        self.button_sizer = None
41        self.data_namectr = None
42        self.numberctr = None
43        self.data1_cbox = None
44        self.operator_cbox = None
45        self.data2_cbox = None
46        self.data_title_tcl = None
47        self.out_pic = None
48        self.equal_pic = None
49        self.data1_pic = None
50        self.operator_pic = None
51        self.data2_pic = None
52        self.output = None
53        self._notes = None
54        #text grayed color
55        self.color = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BACKGROUND)
56        #data
57        self._data = self.get_datalist()
58        self._do_layout()
59        self.fill_data_combox()
60        self.fill_oprator_combox()
61        self.Bind(wx.EVT_PAINT, self.set_panel_on_focus)
62             
63    def _define_structure(self):
64        """
65        define initial sizer
66        """
67        self.main_sizer = wx.BoxSizer(wx.VERTICAL)
68        title = "Data Operation "
69        title += "[ + (add); - (subtract); "
70        title += "* (multiply); / (divide); "
71        title += "| (append) ]"
72        name_box = wx.StaticBox(self, -1, title)
73        self.name_sizer = wx.StaticBoxSizer(name_box, wx.HORIZONTAL)
74        self.button_sizer = wx.BoxSizer(wx.HORIZONTAL)
75     
76    def _layout_name(self):
77        """
78        Do the layout for data name related widgets
79        """
80        new_data_sizer = wx.BoxSizer(wx.VERTICAL)
81        equal_sizer =  wx.BoxSizer(wx.VERTICAL)
82        old_data1_sizer = wx.BoxSizer(wx.VERTICAL)
83        operator_sizer = wx.BoxSizer(wx.VERTICAL)
84        old_data2_sizer = wx.BoxSizer(wx.VERTICAL)
85        data2_hori_sizer = wx.BoxSizer(wx.HORIZONTAL)
86        data_name = wx.StaticText(self, -1, 'Output Data Name') 
87        equal_name = wx.StaticText(self, -1, ' =', size=(50, 25)) 
88        data1_name = wx.StaticText(self, -1, 'Data1')
89        operator_name = wx.StaticText(self, -1, 'Operator')
90        data2_name = wx.StaticText(self, -1, 'Data2 (or Number)')
91        self.data_namectr = wx.TextCtrl(self, -1, size=(_BOX_WIDTH, 25), style=wx.TE_PROCESS_ENTER) 
92        self.data_namectr.SetToolTipString("Hit 'Enter' key after typing.")
93        self.data_namectr.SetValue(str('MyNewDataName'))
94        self.numberctr = wx.TextCtrl(self, -1, size=(_BOX_WIDTH/3, 25), style=wx.TE_PROCESS_ENTER) 
95        self.numberctr.SetToolTipString("Hit 'Enter' key after typing.")
96        self.numberctr.SetValue(str(1.0))
97        self.data1_cbox = wx.ComboBox(self, -1, size=(_BOX_WIDTH, 25), 
98                                      style=wx.CB_READONLY)
99        self.operator_cbox = wx.ComboBox(self, -1, size=(70, 25), 
100                                         style=wx.CB_READONLY)
101        operation_tip = "Add: +, Subtract: -, "
102        operation_tip += "Multiply: *, Divide: /, "
103        operation_tip += "Append(Combine): | "
104        self.operator_cbox.SetToolTipString(operation_tip)
105        self.data2_cbox = wx.ComboBox(self, -1, size=(_BOX_WIDTH*2/3, 25),
106                                       style=wx.CB_READONLY)
107
108        self.out_pic = SmallPanel(self, -1, True, 
109                                    size=(_BOX_WIDTH, _BOX_WIDTH), 
110                                    style=wx.NO_BORDER)
111        self.equal_pic = SmallPanel(self, -1, True, '=', 
112                                    size=(50, _BOX_WIDTH), 
113                                    style=wx.NO_BORDER)
114        self.data1_pic = SmallPanel(self, -1, True, 
115                                    size=(_BOX_WIDTH, _BOX_WIDTH), 
116                                    style=wx.NO_BORDER)
117        self.operator_pic = SmallPanel(self, -1, True, '+',
118                                    size=(70, _BOX_WIDTH), 
119                                    style=wx.NO_BORDER)
120        self.data2_pic = SmallPanel(self, -1, True, 
121                                    size=(_BOX_WIDTH, _BOX_WIDTH), 
122                                    style=wx.NO_BORDER)
123        for ax in self.equal_pic.axes:
124            ax.set_frame_on(False)
125        for ax in self.operator_pic.axes:
126            ax.set_frame_on(False)
127
128        new_data_sizer.AddMany([(data_name, 0, wx.LEFT, 3),
129                                       (self.data_namectr, 0, wx.LEFT, 3),
130                                       (self.out_pic, 0, wx.LEFT, 3)])
131        equal_sizer.AddMany([(13, 13), (equal_name, 0, wx.LEFT, 3),
132                                       (self.equal_pic, 0, wx.LEFT, 3)])
133        old_data1_sizer.AddMany([(data1_name, 0, wx.LEFT, 3),
134                                       (self.data1_cbox, 0, wx.LEFT, 3),
135                                       (self.data1_pic, 0, wx.LEFT, 3)])
136        operator_sizer.AddMany([(operator_name, 0, wx.LEFT, 3),
137                                 (self.operator_cbox, 0, wx.LEFT, 3),
138                                 (self.operator_pic, 0, wx.LEFT, 3)])
139        data2_hori_sizer.AddMany([(self.data2_cbox, 0, wx.LEFT, 0),
140                                       (self.numberctr, 0, wx.RIGHT, 0)])
141        old_data2_sizer.AddMany([(data2_name, 0, wx.LEFT, 3),
142                                       (data2_hori_sizer, 0, wx.LEFT, 3),
143                                       (self.data2_pic, 0, wx.LEFT, 3)])
144        self.name_sizer.AddMany([(new_data_sizer, 0, wx.LEFT|wx.TOP, 5),
145                                       (equal_sizer, 0, wx.TOP, 5),
146                                       (old_data1_sizer, 0, wx.TOP, 5),
147                                       (operator_sizer, 0, wx.TOP, 5),
148                                       (old_data2_sizer, 0, wx.TOP, 5)])
149        self.data2_cbox.Show(True)
150
151        self._show_numctrl(self.numberctr, False)
152       
153        wx.EVT_TEXT_ENTER(self.data_namectr, -1, self.on_name)
154        wx.EVT_TEXT_ENTER(self.numberctr, -1, self.on_number) 
155        wx.EVT_COMBOBOX(self.data1_cbox, -1, self.on_select_data1) 
156        wx.EVT_COMBOBOX(self.operator_cbox, -1, self.on_select_operator) 
157        wx.EVT_COMBOBOX(self.data2_cbox, -1, self.on_select_data2)
158   
159    def _show_numctrl(self, ctrl, enable=True): 
160        """
161        Show/Hide on Win
162        Enable/Disable on MAC
163        """
164        if ON_MAC:
165            ctrl.Enable(enable)
166            children = ctrl.GetChildren()
167            if len(children) > 0:
168                ctrl.GetChildren()[0].SetBackGroundColour(self.color)
169            if enable:
170                wx.EVT_TEXT_ENTER(self.numberctr, -1, self.on_number) 
171        else:
172            if not ctrl.IsEnabled():
173                ctrl.Enable(True)
174            ctrl.Show(enable)
175           
176    def on_name(self, event=None):
177        """
178        On data name typing
179        """
180        if event != None:
181            event.Skip()
182        item = event.GetEventObject()
183        if item.IsEnabled():
184            self._set_textctrl_color(item, 'white')
185        else:
186            self._set_textctrl_color(item, self.color)
187        text = item.GetValue().strip()
188        self._check_newname(text)
189   
190    def _check_newname(self, name=None):
191        """
192        Check name ctr strings
193        """
194        self.send_warnings('')
195        msg = ''
196        if name == None:
197            text = self.data_namectr.GetValue().strip()
198        else:
199            text = name
200        state_list = self.get_datalist().values()
201        name_list = []
202        for state in state_list:
203            if state.data == None:
204                theory_list = state.get_theory()
205                theory, _ = theory_list.values()[0]
206                d_name = str(theory.name)
207            else:
208                d_name = str(state.data.name)
209            name_list.append(d_name)
210        if text in name_list:
211            self._set_textctrl_color(self.data_namectr, 'pink')
212            msg = "DataOperation: The name already exists."
213        if len(text) == 0:
214            self._set_textctrl_color(self.data_namectr, 'pink')
215            msg = "DataOperation: Type the data name first."
216        if self._notes:
217            self.send_warnings(msg, 'error')
218        self.name_sizer.Layout()
219        self.Refresh()
220   
221    def _set_textctrl_color(self, ctrl, color): 
222        """
223        Set TextCtrl color
224        """
225        if ON_MAC:
226            children = ctrl.GetChildren()
227            if len(children) > 0:
228                children[0].SetBackgroundColour(color) 
229        else:
230            ctrl.SetBackgroundColour(color) 
231        self.name_sizer.Layout()
232                     
233    def on_number(self, event=None):
234        """
235        On selecting Number for Data2
236        """
237        self.send_warnings('')
238        item = event.GetEventObject()
239        text = item.GetValue().strip()
240        if self.numberctr.IsShown():
241            if self.numberctr.IsEnabled():
242                self._set_textctrl_color(self.numberctr, 'white')
243                try:
244                    val = float(text)
245                    pos = self.data2_cbox.GetCurrentSelection()
246                    self.data2_cbox.SetClientData(pos, val)
247                except:
248                    self._set_textctrl_color(self.numberctr, 'pink')
249                    msg = "DataOperation: Number requires a float number."
250                    self.send_warnings(msg, 'error')
251                    return
252            else:
253                self._set_textctrl_color(self.numberctr, self.color)
254       
255        self.put_text_pic(self.data2_pic, content=str(val))
256        self.check_data_inputs()
257        if self.output != None:
258            self.output.name = str(self.data_namectr.GetValue())
259        self.draw_output(self.output)
260        self.Refresh()
261       
262    def on_select_data1(self, event=None):
263        """
264        On select data1
265        """
266        self.send_warnings('')
267        item = event.GetEventObject()
268        pos = item.GetCurrentSelection()
269        data = item.GetClientData(pos)
270        if data == None:
271            content = "?"
272            self.put_text_pic(self.data1_pic, content) 
273        else:
274            self.data1_pic.add_image(data)
275        self.check_data_inputs()
276        if self.output != None:
277            self.output.name = str(self.data_namectr.GetValue())
278        self.draw_output(self.output)
279       
280    def on_select_operator(self, event=None):
281        """
282        On Select an Operator
283        """
284        self.send_warnings('')
285        item = event.GetEventObject()
286        text = item.GetValue().strip()
287        self.put_text_pic(self.operator_pic, content=text) 
288        self.check_data_inputs()
289        if self.output != None:
290            self.output.name = str(self.data_namectr.GetValue())
291        self.draw_output(self.output)
292       
293    def on_select_data2(self, event=None):
294        """
295        On Selecting Data2
296        """
297        self.send_warnings('')
298        item = event.GetEventObject()
299        text = item.GetValue().strip().lower()
300        self._show_numctrl(self.numberctr, text=='number')
301        pos = item.GetCurrentSelection()
302        data = item.GetClientData(pos)
303        content = "?"
304        if not (self.numberctr.IsShown() and self.numberctr.IsEnabled()):
305            if data == None:
306                content = "?"
307                self.put_text_pic(self.data2_pic, content)
308            else:
309                self.data2_pic.add_image(data)
310            self.check_data_inputs() 
311        else:
312            content = str(self.numberctr.GetValue().strip())
313            try:
314                content = float(content)
315                data = content
316            except:
317                self._set_textctrl_color(self.numberctr, 'pink')
318                content = "?"
319                data = None
320            item.SetClientData(pos, data)
321            if data != None:
322                self.check_data_inputs()
323               
324            self.put_text_pic(self.data2_pic, content)   
325       
326        if self.output != None:
327            self.output.name = str(self.data_namectr.GetValue())
328        self.draw_output(self.output)
329       
330    def put_text_pic(self, pic=None, content=''): 
331        """
332        Put text to the pic
333        """
334        pic.set_content(content) 
335        pic.add_text()
336        pic.draw()
337                 
338    def check_data_inputs(self):
339        """
340        Check data1 and data2 whether or not they are ready for operation
341        """
342        self._set_textctrl_color(self.data1_cbox, 'white')
343        self._set_textctrl_color(self.data2_cbox, 'white')
344        flag = False
345        pos1 = self.data1_cbox.GetCurrentSelection()
346        data1 = self.data1_cbox.GetClientData(pos1)
347        if data1 == None:
348            self.output = None
349            return flag
350        pos2 = self.data2_cbox.GetCurrentSelection()
351        data2 = self.data2_cbox.GetClientData(pos2)
352       
353        if data2 == None:
354            self.output = None
355            return flag
356        if self.numberctr.IsShown():
357            if self.numberctr.IsEnabled():
358                self._set_textctrl_color(self.numberctr, 'white')
359                try:
360                    float(data2)
361                    if self.operator_cbox.GetValue().strip() == '|':
362                        msg = "DataOperation: This operation can not accept "
363                        msg += "a float number."
364                        self.send_warnings(msg, 'error')
365                        self._set_textctrl_color(self.numberctr, 'pink')
366                        self.output = None
367                        return flag
368                except:
369                    msg = "DataOperation: Number requires a float number."
370                    self.send_warnings(msg, 'error')
371                    self._set_textctrl_color(self.numberctr, 'pink')
372                    self.output = None
373                    return flag
374            else:
375                self._set_textctrl_color(self.numberctr, self.color )
376        elif data1.__class__.__name__ != data2.__class__.__name__:
377            self._set_textctrl_color(self.data1_cbox, 'pink')
378            self._set_textctrl_color(self.data2_cbox, 'pink')
379            msg = "DataOperation: Data types must be same."
380            self.send_warnings(msg, 'error')
381            self.output = None
382            return flag
383        try:
384            self.output = self.make_data_out(data1, data2)
385        except:
386            self._check_newname()
387            self._set_textctrl_color(self.data1_cbox, 'pink')
388            self._set_textctrl_color(self.data2_cbox, 'pink')
389            msg = "DataOperation: Data types must be same."
390            self.send_warnings(msg, 'error')
391            self.output = None
392            return flag
393        return True
394   
395    def make_data_out(self, data1, data2):
396        """
397        Make a temp. data output set
398        """
399        output = None
400        pos = self.operator_cbox.GetCurrentSelection()
401        operator = self.operator_cbox.GetClientData(pos)
402        try:
403            exec "output = data1 %s data2"% operator
404        except:
405            raise
406        return output
407   
408   
409    def draw_output(self, output):
410        """
411        Draw output data(temp)
412        """
413        out = self.out_pic
414        if output == None:
415            content = "?"
416            self.put_text_pic(out, content) 
417        else:
418            out.add_image(output)
419        wx.CallAfter(self.name_sizer.Layout)
420        self.Layout()
421        self.Refresh()
422                   
423    def _layout_button(self): 
424        """
425            Do the layout for the button widgets
426        """ 
427        self.bt_apply = wx.Button(self, -1, "Apply", size=(_BOX_WIDTH/2, -1))
428        app_tip = "Generate the Data and send to Data Explorer."
429        self.bt_apply.SetToolTipString(app_tip)
430        self.bt_apply.Bind(wx.EVT_BUTTON, self.on_click_apply)
431       
432        self.bt_close = wx.Button(self, -1, 'Close', size=(_BOX_WIDTH/2, -1))
433        self.bt_close.Bind(wx.EVT_BUTTON, self.on_close)
434        self.bt_close.SetToolTipString("Close this panel.")
435       
436        self.button_sizer.AddMany([(PANEL_WIDTH/2, 25),
437                                   (self.bt_apply, 0, wx.RIGHT, 10),
438                                   (self.bt_close, 0, wx.RIGHT, 10)])
439       
440    def _do_layout(self):
441        """
442        Draw the current panel
443        """
444        self._define_structure()
445        self._layout_name()
446        self._layout_button()
447        self.main_sizer.AddMany([(self.name_sizer, 0, wx.EXPAND|wx.ALL, 10),
448                                (self.button_sizer, 0,
449                                          wx.EXPAND|wx.TOP|wx.BOTTOM, 5)])
450        self.SetSizer(self.main_sizer)
451        self.SetScrollbars(20, 20, 25, 65)
452        self.SetAutoLayout(True)
453   
454    def set_panel_on_focus(self, event):
455        """
456        On Focus at this window
457        """
458        if event != None:
459            event.Skip()
460        self._data = self.get_datalist()
461        if ON_MAC:
462            self.fill_data_combox()
463        else:
464            children = self.GetChildren()
465            # update the list only when it is on the top
466            if self.FindFocus() in children:
467                self.fill_data_combox()
468         
469    def fill_oprator_combox(self):
470        """
471        fill the current combobox with the operator
472        """   
473        operator_list = [' +', ' -', ' *', " /", " |"]
474        for oper in operator_list:
475            pos = self.operator_cbox.Append(str(oper))
476            self.operator_cbox.SetClientData(pos, str(oper.strip()))
477        self.operator_cbox.SetSelection(0)
478       
479       
480    def fill_data_combox(self):
481        """
482        fill the current combobox with the available data
483        """
484        pos_pre1 = self.data1_cbox.GetCurrentSelection()
485        pos_pre2 = self.data2_cbox.GetCurrentSelection()
486        current1 = self.data1_cbox.GetLabel()
487        current2 = self.data2_cbox.GetLabel()
488        if pos_pre1 < 0:
489            pos_pre1 = 0
490        if pos_pre2 < 0:
491            pos_pre2 = 0
492        self.data1_cbox.Clear()
493        self.data2_cbox.Clear()
494
495        if not self._data:
496            pos = self.data1_cbox.Append('No Data Available')
497            self.data1_cbox.SetSelection(pos)
498            self.data1_cbox.SetClientData(pos, None)
499            pos2 = self.data2_cbox.Append('No Data Available')
500            self.data2_cbox.SetSelection(pos2)
501            self.data2_cbox.SetClientData(pos2, None)
502            return
503        pos1 = self.data1_cbox.Append('Select Data')
504        self.data1_cbox.SetSelection(pos1)
505        self.data1_cbox.SetClientData(pos1, None)
506        pos2 = self.data2_cbox.Append('Select Data')
507        self.data2_cbox.SetSelection(pos2)
508        self.data2_cbox.SetClientData(pos2, None)
509        pos3 = self.data2_cbox.Append('Number')
510        val = None
511        if (self.numberctr.IsShown() and self.numberctr.IsEnabled()):
512            try:
513                val = float(self.numberctr.GetValue())
514            except:
515                val = None
516        self.data2_cbox.SetClientData(pos3, val)
517        dnames = []
518        ids = self._data.keys()
519        for id in ids:
520            if id != None:
521                if self._data[id].data != None:
522                    dnames.append(self._data[id].data.name)
523                else:
524                    theory_list = self._data[id].get_theory()
525                    theory, _ = theory_list.values()[0]
526                    dnames.append(theory.name)
527        ind = numpy.argsort(dnames)
528        if len(ind) > 0:
529            val_list = numpy.array(self._data.values())[ind]
530            for datastate in val_list:
531                data = datastate.data
532                if data != None:
533                    name = data.name
534                    pos1 = self.data1_cbox.Append(str(name))
535                    self.data1_cbox.SetClientData(pos1, data)
536                    pos2 = self.data2_cbox.Append(str(name))
537                    self.data2_cbox.SetClientData(pos2, data)
538                    if str(current1) == str(name):
539                      pos_pre1 = pos1
540                    if str(current2) == str(name):
541                      pos_pre2 = pos2
542                try:
543                    theory_list = datastate.get_theory()
544                    for theory, _ in theory_list.values():
545                        th_name = theory.name
546                        posth1 = self.data1_cbox.Append(str(th_name))
547                        self.data1_cbox.SetClientData(posth1, theory)
548                        posth2 = self.data2_cbox.Append(str(th_name))
549                        self.data2_cbox.SetClientData(posth2, theory)
550                        if str(current1) == str(th_name):
551                            pos_pre1 = posth1
552                        if str(current2) == str(th_name):
553                            pos_pre2 = posth2
554                except:
555                    continue 
556        self.data1_cbox.SetSelection(pos_pre1)
557        self.data2_cbox.SetSelection(pos_pre2)
558   
559    def get_datalist(self):
560        """
561        """
562        data_manager = self.parent.parent.get_data_manager()
563        if data_manager != None:
564            return  data_manager.get_all_data()
565        else:
566            return {}
567           
568    def on_click_apply(self, event):
569        """   
570        changes are saved in data object imported to edit
571        """
572        self.send_warnings('')
573        self.data_namectr.SetBackgroundColour('white')
574        state_list = self.get_datalist().values()
575        name = self.data_namectr.GetValue().strip()
576        name_list = []
577        for state in state_list:
578            if state.data == None:
579                theory_list = state.get_theory()
580                theory, _ = theory_list.values()[0]
581                d_name = str(theory.name)
582            else:
583                d_name = str(state.data.name)
584            name_list.append(d_name)
585        if name in name_list:
586            self._set_textctrl_color(self.data_namectr, 'pink')
587            msg = "The Output Data Name already exists...   "
588            wx.MessageBox(msg, 'Error')
589            return
590        if name == '':
591            self._set_textctrl_color(self.data_namectr, 'pink')
592            msg = "Please type the output data name first...   "
593            wx.MessageBox(msg, 'Error')
594            return
595        if self.output == None:
596            msg = "No Output Data has been generated...   "
597            wx.MessageBox(msg, 'Error')
598            return
599        # send data to data manager
600        self.output.name = name
601        self.output.run = "Data Operation"
602        self.output.instrument = "SasView"
603        self.output.id = str(name) + str(time.time())
604        data = {self.output.id :self.output}
605        self.parent.parent.add_data(data)
606        self.name_sizer.Layout()
607        self.Refresh()
608        #must post event here
609        event.Skip()
610   
611    def disconnect_panels(self):
612        """
613        """
614        self.out_pic.connect.disconnect()
615        self.equal_pic.connect.disconnect()
616        self.data1_pic.connect.disconnect()
617        self.operator_pic.connect.disconnect()
618        self.data2_pic.connect.disconnect()
619   
620    def on_close(self, event):
621        """
622        leave data as it is and close
623        """
624        self.parent.OnClose()
625       
626    def set_plot_unfocus(self):
627        """
628        Unfocus on right click
629        """
630   
631    def send_warnings(self, msg='', info='info'):
632        """
633        Send warning to status bar
634        """
635        wx.PostEvent(self.parent.parent, StatusEvent(status=msg, info=info))
636         
637class SmallPanel(PlotPanel):
638    """
639    PlotPanel for Quick plot and masking plot
640    """
641    def __init__(self, parent, id=-1, is_number=False, content='?', **kwargs):
642        """
643        """ 
644        PlotPanel.__init__(self, parent, id=id, **kwargs)
645        self.is_number = is_number
646        self.content = content
647        self.point = None
648        self.position = (0.4, 0.5)
649        self.scale = 'linear'
650        self.prevXtrans = "x"
651        self.prevYtrans = "y"
652        self.viewModel = "--"
653        self.subplot.set_xticks([])
654        self.subplot.set_yticks([])
655        self.add_text()
656        self.figure.subplots_adjust(left=0.1, bottom=0.1)
657       
658    def set_content(self, content=''):
659        """
660        Set text content
661        """
662        self.content = str(content)
663         
664    def add_toolbar(self):
665        """
666        Add toolbar
667        """
668        # Not implemented
669        pass
670   
671    def on_set_focus(self, event):
672        """
673        send to the parenet the current panel on focus
674        """
675        pass
676
677    def add_image(self, plot):
678        """
679        Add Image
680        """
681        self.content = ''
682        self.textList = []
683        self.plots = {}
684        self.clear()
685        self.point = plot
686        try:
687            self.figure.delaxes(self.figure.axes[0])
688            self.subplot = self.figure.add_subplot(111)
689            #self.figure.delaxes(self.figure.axes[1])
690        except:
691            pass
692        try:
693            name = plot.name
694        except:
695            name = plot.filename
696        self.plots[name] = plot
697
698        #init graph
699        self.graph = Graph()
700
701        #add plot
702        self.graph.add(plot)
703        #draw       
704        self.graph.render(self)
705       
706        try:
707            self.figure.delaxes(self.figure.axes[1])
708        except:
709            pass
710        self.subplot.figure.canvas.resizing = False
711        self.subplot.tick_params(axis='both', labelsize=9)
712        # Draw zero axis lines
713        self.subplot.axhline(linewidth = 1, color='r') 
714        self.subplot.axvline(linewidth = 1, color='r')       
715
716        self.erase_legend()
717        try:
718            # mpl >= 1.1.0
719            self.figure.tight_layout()
720        except:
721            self.figure.subplots_adjust(left=0.1, bottom=0.1)
722        self.subplot.figure.canvas.draw()
723
724    def add_text(self):
725        """
726        Text in the plot
727        """
728        if not self.is_number:
729            return
730
731        self.clear()
732        try:
733            self.figure.delaxes(self.figure.axes[0])
734            self.subplot = self.figure.add_subplot(111)
735            self.figure.delaxes(self.figure.axes[1])
736        except:
737            pass
738        self.subplot.set_xticks([])
739        self.subplot.set_yticks([])
740        label = self.content
741        FONT = FontProperties()
742        xpos, ypos = (0.4, 0.5)
743        font = FONT.copy()
744        font.set_size(14)
745
746        self.textList = []
747        self.subplot.set_xlim((0, 1))
748        self.subplot.set_ylim((0, 1))
749       
750        try:
751            if self.content != '?':
752                float(label)
753        except:
754            self.subplot.set_frame_on(False)
755        try:
756            # mpl >= 1.1.0
757            self.figure.tight_layout()
758        except:
759            self.figure.subplots_adjust(left=0.1, bottom=0.1)
760        if len(label) > 0 and xpos > 0 and ypos > 0:
761            new_text = self.subplot.text(str(xpos), str(ypos), str(label),
762                                           fontproperties=font)
763            self.textList.append(new_text) 
764       
765    def erase_legend(self):
766        """
767        Remove Legend
768        """
769        #for ax in self.axes:
770        self.remove_legend(self.subplot)
771                     
772    def onMouseMotion(self, event):
773        """
774        Disable dragging 2D image
775        """
776   
777    def onWheel(self, event):
778        """
779        """
780     
781    def onLeftDown(self, event):
782        """
783        Disables LeftDown
784        """
785   
786    def onPick(self, event):
787        """
788        Remove Legend
789        """
790        for ax in self.axes:
791            self.remove_legend(ax)
792                       
793   
794    def draw(self):
795        """
796        Draw
797        """
798        if self.dimension == 3:
799            pass
800        else:
801            self.subplot.figure.canvas.resizing = False
802            self.subplot.tick_params(axis='both', labelsize=9)     
803            self.erase_legend()
804            self.subplot.figure.canvas.draw_idle() 
805            try:
806                self.figure.delaxes(self.figure.axes[1])
807            except:
808                pass
809           
810       
811    def onContextMenu(self, event):
812        """
813        Default context menu for a plot panel
814        """
815        id = wx.NewId()
816        slicerpop = wx.Menu()
817        data = self.point
818        if issubclass(data.__class__, Data1D):
819            slicerpop.Append(id, '&Change Scale')
820            wx.EVT_MENU(self, id, self._onProperties)
821        else:
822            slicerpop.Append(id, '&Toggle Linear/Log Scale')
823            wx.EVT_MENU(self, id, self.ontogglescale)     
824        try:
825            # mouse event
826            pos_evt = event.GetPosition()
827            pos = self.ScreenToClient(pos_evt)
828        except:
829            # toolbar event
830            pos_x, pos_y = self.toolbar.GetPositionTuple()
831            pos = (pos_x, pos_y + 5)
832        self.PopupMenu(slicerpop, pos)
833       
834    def ontogglescale(self, event): 
835        """
836        On toggle 2d scale
837        """
838        self._onToggleScale(event) 
839        try:
840            # mpl >= 1.1.0
841            self.figure.tight_layout()
842        except:
843            self.figure.subplots_adjust(left=0.1, bottom=0.1) 
844        try:
845            self.figure.delaxes(self.figure.axes[1])
846        except:
847            pass
848       
849    def _onProperties(self, event):
850        """
851        when clicking on Properties on context menu ,
852        The Property dialog is displayed
853        The user selects a transformation for x or y value and
854        a new plot is displayed
855        """
856        list = []
857        list = self.graph.returnPlottable()
858        if len(list.keys()) > 0:
859            first_item = list.keys()[0]
860            if first_item.x != []:
861                from sas.plottools.PropertyDialog import Properties
862                dial = Properties(self, -1, 'Change Scale')
863                # type of view or model used
864                dial.xvalue.Clear()
865                dial.yvalue.Clear()
866                dial.view.Clear()
867                dial.xvalue.Insert("x", 0)
868                dial.xvalue.Insert("log10(x)", 1)
869                dial.yvalue.Insert("y", 0)
870                dial.yvalue.Insert("log10(y)", 1)
871                dial.view.Insert("--", 0)
872                dial.view.Insert("Linear y vs x", 1)
873                dial.setValues(self.prevXtrans, self.prevYtrans, self.viewModel)
874                dial.Update()
875                if dial.ShowModal() == wx.ID_OK:
876                    self.xLabel, self.yLabel, self.viewModel = dial.getValues()
877                    if self.viewModel == "Linear y vs x":
878                        self.xLabel = "x"
879                        self.yLabel = "y"
880                        self.viewModel = "--"
881                        dial.setValues(self.xLabel, self.yLabel, self.viewModel)
882                    self._onEVT_FUNC_PROPERTY()
883                dial.Destroy()
884         
885    def _onEVT_FUNC_PROPERTY(self, remove_fit=True):
886        """
887        Receive the x and y transformation from myDialog,
888        Transforms x and y in View
889        and set the scale
890        """
891        list = []
892        list = self.graph.returnPlottable()
893        # Changing the scale might be incompatible with
894        # currently displayed data (for instance, going
895        # from ln to log when all plotted values have
896        # negative natural logs).
897        # Go linear and only change the scale at the end.
898        self.set_xscale("linear")
899        self.set_yscale("linear")
900        _xscale = 'linear'
901        _yscale = 'linear'
902        for item in list:
903            item.setLabel(self.xLabel, self.yLabel)
904            # control axis labels from the panel itself
905            yname, yunits = item.get_yaxis()
906            xname, xunits = item.get_xaxis()
907            # Goes through all possible scales
908            # Goes through all possible scales
909            if(self.xLabel == "x"):
910                item.transformX(transform.toX, transform.errToX)
911                self.graph._xaxis_transformed("%s" % xname, "%s" % xunits)
912            if(self.xLabel == "log10(x)"):
913                item.transformX(transform.toX_pos, transform.errToX_pos)
914                _xscale = 'log'
915                self.graph._xaxis_transformed("%s" % xname, "%s" % xunits)
916            if(self.yLabel == "y"):
917                item.transformY(transform.toX, transform.errToX)
918                self.graph._yaxis_transformed("%s" % yname, "%s" % yunits)
919            if(self.yLabel == "log10(y)"):
920                item.transformY(transform.toX_pos, transform.errToX_pos)
921                _yscale = 'log'
922                self.graph._yaxis_transformed("%s" % yname, "%s" % yunits)
923            item.transformView()
924        self.prevXtrans = self.xLabel
925        self.prevYtrans = self.yLabel
926        self.set_xscale(_xscale)
927        self.set_yscale(_yscale)
928        self.draw()
929       
930class DataOperatorWindow(widget.CHILD_FRAME):
931    def __init__(self, parent, manager, *args, **kwds):
932        kwds["size"] = (PANEL_WIDTH, PANEL_HEIGTH)
933        widget.CHILD_FRAME.__init__(self, parent, *args, **kwds)
934        self.parent = parent
935        self.manager = manager
936        self.panel = DataOperPanel(parent=self)
937        wx.EVT_CLOSE(self, self.OnClose)
938        self.SetPosition((25, 150))
939        self.Show()
940   
941    def OnClose(self, event=None): 
942        """
943        On close event
944        """
945        if self.manager != None:
946            self.manager.data_operator_frame = None
947        self.panel.disconnect_panels()
948        self.Destroy()
949
950       
951if __name__ == "__main__":
952
953    app  = wx.App()
954    widget.CHILD_FRAME = wx.Frame
955    window = DataOperatorWindow(parent=None, data=[], title="Data Editor")
956    app.MainLoop()
957 
Note: See TracBrowser for help on using the repository browser.