source: sasview/calculatorview/src/sans/perspectives/calculator/data_operator.py @ f234d3c

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 f234d3c was f234d3c, checked in by Jae Cho <jhjcho@…>, 12 years ago

adjusting position and max_height mostly on MAC/Linux

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