source: sasview/sansguiframe/src/sans/guiframe/data_processor.py @ 5722d66

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 5722d66 was fb0de166, checked in by Gervaise Alina <gervyh@…>, 13 years ago

minor refactor

  • Property mode set to 100644
File size: 44.4 KB
Line 
1"""
2Implement grid used to store data
3"""
4import wx
5import numpy
6import math
7import re
8import os
9import sys
10import copy
11from wx.lib.scrolledpanel import ScrolledPanel
12import  wx.grid as  Grid
13import wx.aui
14from wx.aui import AuiNotebook as nb
15import wx.lib.sheet as sheet
16from sans.guiframe.panel_base import PanelBase
17from sans.guiframe.utils import format_number
18from sans.guiframe.events import NewPlotEvent
19from sans.guiframe.events import StatusEvent 
20from sans.guiframe.dataFitting import Data1D
21
22FUNC_DICT = {"sqrt": "math.sqrt",
23             "pow": "math.sqrt"}
24
25class BatchCell:
26    """
27    Object describing a cell in  the grid.
28   
29    """
30    def __init__(self):
31        self.label = ""
32        self.value = None
33        self.col = -1
34        self.row = -1
35        self.object = []
36       
37
38def parse_string(sentence, list):
39    """
40    Return a dictionary of column label and index or row selected
41    :param sentence: String to parse
42    :param list: list of columns label
43    """
44    toks = []
45    p2 = re.compile(r'\d+')
46    p = re.compile(r'[\+\-\*\%\/]')
47    labels = p.split(sentence)
48    col_dict = {}
49    for elt in labels:
50        rang = None
51        temp_arr = []
52        for label in  list:
53            label_pos =  elt.find(label)
54            if label_pos != -1:
55                if elt.count(',') > 0:
56                    new_temp = []
57                    temp = elt.split(label)
58                    for item in temp:
59                        range_pos = item.find(":")
60                        if range_pos != -1:
61                            rang = p2.findall(item)
62                            for i in xrange(int(rang[0]), int(rang[1])+1 ):
63                                new_temp.append(i)
64                    temp_arr += new_temp
65                else:
66                    temp = elt.split(label)
67                    for item in temp:
68                        range_pos = item.find(":")
69                        if range_pos != -1:
70                            rang = p2.findall(item)
71                            for i in xrange(int(rang[0]), int(rang[1])+1 ):
72                                temp_arr.append(i)
73                col_dict[elt] = (label, temp_arr)
74    return col_dict
75
76         
77         
78class SPanel(ScrolledPanel):
79    def __init__(self, parent, *args, **kwds):
80        ScrolledPanel.__init__(self, parent , *args, **kwds)
81        self.SetupScrolling() 
82       
83class GridPage(sheet.CSheet):
84    """
85    """
86    def __init__(self, parent, panel=None):
87        """
88        """
89        sheet.CSheet.__init__(self, parent)
90       
91        self.AdjustScrollbars()
92        #self.SetLabelBackgroundColour('#DBD4D4')
93        self.parent = parent
94        self.panel = panel
95        self.col_names = []
96        self.data_inputs = {}
97        self.data_outputs = {}
98        self.data = None
99        self.details = ""
100        self.file_name = None
101        self._cols = 50
102        self._rows = 51
103        self.last_selected_row = -1
104        self.last_selected_col = -1
105        self.col_width = 30
106        self.row_height = 20
107        self.max_row_touse = 0
108        self.axis_value = []
109        self.axis_label = ""
110        self.selected_cells = []
111        self.selected_cols = []
112        self.selected_rows = []
113        self.plottable_cells = []
114        self.plottable_flag = False
115        self.SetColMinimalAcceptableWidth(self.col_width)
116        self.SetRowMinimalAcceptableHeight(self.row_height)
117        self.SetNumberRows(self._cols)
118        self.SetNumberCols(self._rows)
119        self.AutoSize()
120        self.default_col_width = 75
121        if self.GetNumberCols() > 0:
122            self.default_col_width =  self.GetColSize(0)
123        self.Bind(wx.grid.EVT_GRID_LABEL_LEFT_CLICK, self.on_left_click)
124        self.Bind(wx.grid.EVT_GRID_LABEL_RIGHT_CLICK, self.on_right_click)
125        self.Bind(wx.grid.EVT_GRID_CELL_LEFT_CLICK, self.on_selected_cell)
126        self.Bind(wx.grid.EVT_GRID_CMD_CELL_CHANGE, self.on_edit_cell)
127       
128       
129    def on_edit_cell(self, event):
130        """
131        """
132        row, col = event.GetRow(), event.GetCol()
133        if row > self.max_row_touse:
134            self.max_row_touse = row
135        event.Skip()
136       
137    def on_selected_cell(self, event):
138        """
139        Handler catching cell selection
140        """
141        flag = event.CmdDown() or event.ControlDown()
142        row, col = event.GetRow(), event.GetCol()
143        cell = (row, col)
144        event.Skip()
145        if not flag:
146            self.selected_cells = []
147            self.axis_value = []
148            self.axis_label = ""
149        if col >= 0:
150             self.axis_label = self.GetCellValue(0, col)
151        if cell not in self.selected_cells:
152            if row > 0:
153                self.selected_cells.append(cell)
154        else:
155            if flag:
156                self.selected_cells.remove(cell)
157        self.axis_value = []
158        for cell_row, cell_col in self.selected_cells:
159            if cell_row > 0 and cell_row < self.max_row_touse:
160                self.axis_value.append(self.GetCellValue(cell_row, cell_col))
161       
162   
163               
164    def on_left_click(self, event):
165        """
166        Catch the left click on label mouse event
167        """
168        event.Skip()
169        flag = event.CmdDown() or event.ControlDown()
170        col = event.GetCol()
171        row = event.GetRow()
172        if not flag:
173            self.selected_cols = []
174            self.selected_rows = []
175            self.selected_cells = []
176            self.axis_label = ""
177            self.plottable_list = []
178            self.plottable_cells = []
179            self.plottable_flag = False
180       
181        self.last_selected_col = col
182        self.last_selected_row = row
183        if row != -1 and row not in self.selected_rows:
184             self.selected_rows.append(row)
185             
186        if col != -1:
187            for row in range(1, self.GetNumberRows()+ 1):
188                cell = (row, col)
189                if row > 0 and row < self.max_row_touse:
190                    if cell not in self.selected_cells:
191                        self.selected_cells.append(cell)
192            self.selected_cols.append(col)
193            self.axis_value = []
194            for cell_row, cell_col in self.selected_cells:
195                self.axis_value.append(self.GetCellValue(cell_row, cell_col))
196            self.axis_label = self.GetCellValue(0, col)
197       
198    def on_right_click(self, event):
199        """
200        Catch the right click mouse
201        """
202       
203        col = event.GetCol()
204        self.selected_cols = []
205        self.selected_cols.append(col)
206        # Slicer plot popup menu
207        slicerpop = wx.Menu()
208        col_label_menu  = wx.Menu()
209        c_name = self.GetCellValue(0, col) 
210        label = "Insert column before %s " % str(c_name)
211        slicerpop.AppendSubMenu(col_label_menu , 
212                                 '&%s' % str(label), str(label))
213        col_name = [self.GetCellValue(0, c) 
214                        for c in range(self.GetNumberCols())]
215        row = 0
216        label = self.GetCellValue(row, col)
217        self.insert_col_menu(col_label_menu, label, self)
218        id = wx.NewId()   
219        hint = 'Remove selected column %s'
220        slicerpop.Append(id, '&Remove Column', hint)
221        wx.EVT_MENU(self, id, self.on_remove_column)
222       
223        pos = wx.GetMousePosition()
224        pos = self.ScreenToClient(pos)
225        self.PopupMenu(slicerpop, pos)
226        event.Skip()
227       
228    def insert_col_menu(self, menu, label, window):
229        """
230        """
231        id = wx.NewId()
232        title = "Empty"
233        hint = 'Insert empty column before %s' % str(label)
234        menu.Append(id, title, hint)
235        wx.EVT_MENU(window, id, self.on_insert_column)
236        row = 0
237        col_name = [self.GetCellValue(row, col) 
238                        for col in range(self.GetNumberCols())]
239        for c_name in self.data.keys():
240            if c_name not in col_name:
241                id = wx.NewId()
242                hint = "Insert %s column before the " % str(c_name)
243                hint += " %s column" % str(label)
244                menu.Append(id, '&%s' % str(c_name), hint)
245                wx.EVT_MENU(window, id, self.on_insert_column)
246           
247               
248    def on_remove_column(self, event=None):
249        """
250        """
251        if self.selected_cols is not None or len(self.selected_cols) > 0:
252            col = self.selected_cols[0]
253            self.remove_column(col=col, numCols=1)
254           
255    def remove_column(self, col, numCols=1):
256        """
257        Remove column to the current grid
258        """
259        # add data to the grid   
260        row = 0
261        col_name = self.GetCellValue(row, col)
262        self.data[col_name] = []
263        for row in range(1, self.GetNumberRows() + 1):
264            if row < self.max_row_touse:
265                value = self.GetCellValue(row, col)
266                self.data[col_name].append(value)
267                for k , value_list in self.data.iteritems():
268                    if k != col_name:
269                        length = len(value_list)
270                        if length < self.max_row_touse:
271                            diff = self.max_row_touse - length
272                            for i in range(diff):
273                                self.data[k].append("")
274        self.DeleteCols(pos=col, numCols=numCols, updateLabels=True)
275           
276    def on_insert_column(self, event):
277        """
278        """
279        if self.selected_cols is not None or len(self.selected_cols) > 0:
280            col = self.selected_cols[0]
281            # add data to the grid   
282            row = 0
283            id = event.GetId()
284            col_name = event.GetEventObject().GetLabelText(id)
285            self.insert_column(col=col, col_name=col_name)
286            if  not issubclass(event.GetEventObject().__class__ , wx.Menu):
287                col += 1
288                self.selected_cols[0] += 1
289           
290    def insert_column(self, col, col_name):
291        """
292        """ 
293         
294        row = 0
295        self.InsertCols(pos=col, numCols=1, updateLabels=True)
296        if col_name.strip() != "Empty":
297            self.SetCellValue(row, col, str(col_name.strip()))
298        if col_name in self.data.keys():
299            value_list = self.data[col_name]
300            cell_row =  1
301            for value in value_list:
302                self.SetCellValue(cell_row, col, str(value))
303                cell_row += 1
304       
305       
306    def on_set_x_axis(self, event):
307        """
308        """
309        self.panel.set_xaxis(x=self.axis_value, label=self.axis_label)
310   
311    def on_set_y_axis(self, event):
312        """
313        """
314        self.panel.set_yaxis(y=self.axis_value, label=self.axis_label)     
315           
316    def set_data(self, data_inputs, data_outputs, details, file_name):
317        """
318        Add data to the grid
319        :param data_inputs: data to use from the context menu of the grid
320        :param data_ouputs: default columns deplayed
321        """
322        self.file_name = file_name
323        self.details = details
324       
325        if data_outputs is None:
326            data_outputs = {}
327        self.data_outputs = data_outputs
328        if data_inputs is None:
329            data_inputs = {}
330        self.data_inputs = data_inputs
331        self.data = {}
332        for item in (self.data_outputs, self.data_inputs):
333            self.data.update(item)
334        if  len(self.data_outputs) > 0:
335            self._cols = self.GetNumberCols()
336            self._rows = self.GetNumberRows()
337            self.col_names = self.data_outputs.keys()
338            self.col_names.sort() 
339            nbr_user_cols = len(self.col_names)
340            #Add more columns to the grid if necessary
341            if nbr_user_cols > self._cols:
342                new_col_nbr = nbr_user_cols -  self._cols
343                self.AppendCols(new_col_nbr, True)
344            #Add more rows to the grid if necessary 
345            nbr_user_row = len(self.data_outputs.values())
346            if nbr_user_row > self._rows + 1:
347                new_row_nbr =  nbr_user_row - self._rows
348                self.AppendRows(new_row_nbr, True)
349            # add data to the grid   
350            row = 0
351            col = 0
352            cell_col = 0
353            for col_name in  self.col_names:
354                # use the first row of the grid to add user defined labels
355                self.SetCellValue(row, col, str(col_name))
356                col += 1
357                cell_row =  1
358                value_list = self.data_outputs[col_name]
359               
360                for value in value_list:
361                    label = value
362                    if issubclass(value.__class__, BatchCell):
363                        label = value.label
364                    try:
365                        float(label)
366                        label = format_number(label)
367                    except:
368                        label = str(label)
369                    self.SetCellValue(cell_row, cell_col, label)
370                    self.AutoSizeColumn(cell_col, True)
371                    width = self.GetColSize(cell_col)
372                    if width < self.default_col_width:
373                       self.SetColSize(cell_col, self.default_col_width)
374                   
375                    cell_row += 1
376                cell_col += 1
377                if cell_row > self.max_row_touse:
378                    self.max_row_touse = cell_row
379        self.ForceRefresh()
380       
381    def get_grid_view(self):
382        """
383        Return value contained in the grid
384        """
385        grid_view = {}
386        for col in xrange(self.GetNumberCols()):
387            label = self.GetCellValue(row=0, col=col) 
388            label = label.strip()
389            if label != "":
390                grid_view[label] = []
391                for row in range(1, self.max_row_touse+1):
392                    value = self.GetCellValue(row=row, col=col)
393                    if value != "":
394                        grid_view[label].append(value) 
395                    else:
396                        grid_view[label].append(None) 
397        return grid_view
398   
399class Notebook(nb, PanelBase):
400    """
401    ## Internal name for the AUI manager
402    window_name = "Fit panel"
403    ## Title to appear on top of the window
404    """
405    window_caption = "Notebook "
406   
407    def __init__(self, parent, manager=None, data=None, *args, **kwargs):
408        """
409        """
410        nb.__init__(self, parent, -1,
411                    style=wx.aui.AUI_NB_WINDOWLIST_BUTTON| 
412                    wx.aui.AUI_BUTTON_DOWN|
413                    wx.aui.AUI_NB_DEFAULT_STYLE|
414                    wx.CLIP_CHILDREN)
415        PanelBase.__init__(self, parent)
416        self.enable_close_button()
417        self.parent = parent
418        self.manager = manager
419        self.data = data
420        #add empty page
421        self.add_empty_page()
422       
423        self.Bind(wx.aui.EVT_AUINOTEBOOK_PAGE_CLOSE, self.on_close_page)
424   
425    def add_empty_page(self):
426        """
427        """
428        grid = GridPage(self, panel=self.parent)
429        self.AddPage(grid, "", True)
430        pos = self.GetPageIndex(grid)
431        title = "Batch " + str(self.GetPageCount())
432        self.SetPageText(pos, title)
433        self.SetSelection(pos)
434        return grid , pos
435       
436    def enable_close_button(self):
437        """
438        display the close button on tab for more than 1 tabs else remove the
439        close button
440        """
441        if self.GetPageCount() <= 1:
442            style = self.GetWindowStyleFlag() 
443            flag = wx.aui.AUI_NB_CLOSE_ON_ACTIVE_TAB
444            if style & wx.aui.AUI_NB_CLOSE_ON_ACTIVE_TAB == flag:
445                style = style & ~wx.aui.AUI_NB_CLOSE_ON_ACTIVE_TAB
446                self.SetWindowStyle(style)
447        else:
448            style = self.GetWindowStyleFlag()
449            flag = wx.aui.AUI_NB_CLOSE_ON_ACTIVE_TAB
450            if style & wx.aui.AUI_NB_CLOSE_ON_ACTIVE_TAB != flag:
451                style |= wx.aui.AUI_NB_CLOSE_ON_ACTIVE_TAB
452                self.SetWindowStyle(style)
453             
454    def on_edit_axis(self):
455        """
456        Return the select cell of a given selected column
457        """
458        pos = self.GetSelection()
459        grid = self.GetPage(pos)
460        if len(grid.selected_cols) > 1:
461            msg = "Edit axis doesn't understand this selection.\n"
462            msg += "Please select only one column"
463            raise ValueError, msg
464        if len(grid.selected_cols) == 1:
465            col = grid.selected_cols[0]
466            if len(grid.selected_cells) > 0:
467                cell_row, cell_col = grid.selected_cells[0]
468                if cell_col  != col:
469                    msg = "Edit axis doesn't understand this selection.\n"
470                    msg += "Please select element of the same col"
471                    raise ValueError, msg
472        return grid.selected_cells
473       
474   
475    def get_column_labels(self):
476        """
477        return dictionary of columns labels of the current page
478        """
479        pos = self.GetSelection()
480        grid = self.GetPage(pos)
481        labels = {}
482        row = 0
483        for col in range(grid.GetNumberCols()):
484            label = grid.GetCellValue(row, col)
485            if label.strip() != "" :
486                labels[label.strip()] = col
487        return labels
488       
489    def create_axis_label(self, cell_list):
490        """
491        Receive a list of cells and  create a string presenting the selected
492        cells.
493        :param cell_list: list of tuple
494       
495        """
496        pos = self.GetSelection()
497        grid = self.GetPage(pos)
498        label = ""
499        col_name = ""
500        def create_label(col_name,  row_min=None, row_max=None):
501            """
502            """
503            result = ""
504            if row_min is not  None or row_max is not None:
505                if row_min is None:
506                    result = str(row_max) + "]"
507                elif row_max is None:
508                     result = str(col_name) + "[" + str(row_min) + ":"
509                else:
510                    result = str(col_name) +  "[" + str(row_min) + ":"
511                    result += str(col_name) + str(row_max) + "]"
512            return result
513           
514        if len(cell_list) > 0:
515            if len(cell_list) == 1:
516                 row_min, col  = cell_list[0]   
517                 col_name = grid.GetCellValue(0, col)
518                 label = create_label(col_name, row_min+1 , row_min+1)
519                 return  label,  col_name
520            else:
521                temp_list = copy.deepcopy(cell_list)
522                temp_list.sort()
523                length = len(temp_list)
524                row_min, col  = temp_list[0]   
525                row_max, _  = temp_list[length-1]
526                col_name = grid.GetCellValue(0, col)
527                index = 0
528                for row in xrange(row_min, row_max +1):
529                    if index > 0 and index < len(temp_list):
530                        new_row, _ = temp_list[index]
531                        if row != new_row:
532                            temp_list.insert(index, (None, None))
533                            if index -1 >=0:
534                                new_row, _ = temp_list[index-1]
535                                label += create_label(col_name, None, new_row +1)
536                                label += ","
537                            if index + 1 < len(temp_list):
538                                new_row, _ = temp_list[index + 1]
539                                label += create_label(col_name, new_row+1, None)
540                    if index == 0:
541                        label += create_label(col_name,  row_min+1, None)
542                    elif index == len(temp_list)-1:
543                        label += create_label(col_name, None, row_max+1)
544                    index += 1
545                return label, col_name
546   
547    def on_close_page(self, event):
548        """
549        close the page
550        """
551        if self.GetPageCount() == 1:
552            event.Veto()
553        self.enable_close_button()
554       
555    def set_data(self, data_inputs, data_outputs, details="", file_name=None):
556        if data_outputs is None or data_outputs == {}:
557            return
558       
559        for pos in range(self.GetPageCount()):
560            grid = self.GetPage(pos)
561            if grid.data is None:
562                #Found empty page
563                grid.set_data(data_inputs=data_inputs, 
564                              data_outputs=data_outputs,
565                              details=details,
566                              file_name=file_name) 
567                self.SetSelection(pos) 
568                return
569               
570        grid, pos = self.add_empty_page()
571        grid.set_data(data_inputs=data_inputs, 
572                      data_outputs=data_outputs,
573                      file_name=file_name,
574                      details=details)
575   
576    def add_column(self):
577        """
578        Append a new column to the grid
579        """
580        pos = self.GetSelection()
581        grid = self.GetPage(pos)
582        grid.AppendCols(1, True)
583       
584   
585
586
587
588class GridPanel(SPanel):
589    def __init__(self, parent, data_inputs=None,
590                 data_outputs=None, *args, **kwds):
591        SPanel.__init__(self, parent , *args, **kwds)
592       
593        self.vbox = wx.BoxSizer(wx.VERTICAL)
594       
595        self.plotting_sizer = wx.FlexGridSizer(3, 7, 10, 5)
596        self.button_sizer = wx.BoxSizer(wx.HORIZONTAL)
597        self.grid_sizer = wx.BoxSizer(wx.HORIZONTAL)
598        self.vbox.AddMany([(self.grid_sizer, 1, wx.EXPAND, 0),
599                           (wx.StaticLine(self, -1), 0, wx.EXPAND, 0),
600                           (self.plotting_sizer),
601                           (self.button_sizer)])
602        self.parent = parent
603        self._data_inputs = data_inputs
604        self._data_outputs = data_outputs
605        self.x = []
606        self.= []
607        self.x_axis_label = None
608        self.y_axis_label = None
609        self.x_axis_title = None
610        self.y_axis_title = None
611        self.x_axis_unit = None
612        self.y_axis_unit = None
613        self.view_button = None
614        self.plot_button = None
615        self.notebook = None
616        self.layout_grid()
617        self.layout_plotting_area()
618        self.SetSizer(self.vbox)
619 
620    def set_xaxis(self, label="", x=None):
621        """
622        """
623        if x is None:
624            x = []
625        self.x = x
626        self.x_axis_label.SetValue("%s[:]" % str(label))
627        self.x_axis_title.SetValue(str(label))
628       
629    def set_yaxis(self, label="", y=None):
630        """
631        """
632        if y is None:
633            y = []
634        self.y = y
635        self.y_axis_label.SetValue("%s[:]" % str(label))
636        self.y_axis_title.SetValue(str(label))
637       
638    def get_plot_axis(self, col, list):
639        """
640       
641        """
642        axis = []
643        pos = self.notebook.GetSelection()
644        grid = self.notebook.GetPage(pos)
645        for row in list:
646            label = grid.GetCellValue(0, col)
647            value = grid.GetCellValue(row - 1, col).strip()
648            if value != "":
649                if label.lower().strip() == "data":
650                    axis.append(float(row - 1))
651                else:
652                    try:
653                        axis.append(float(value))
654                    except:
655                        msg = "Invalid data in row %s column %s" % (str(row),
656                                                                    str(col))
657                        wx.PostEvent(self.parent.parent, 
658                             StatusEvent(status=msg, info="error")) 
659            else:
660                axis.append(None) 
661        return axis
662   
663    def on_save_column(self, parent):
664        """
665        """
666        pos = self.notebook.GetSelection()
667        grid = self.notebook.GetPage(pos)
668        if parent is not None and  self.data is not None:
669            parent.write_batch_tofile(data=grid.data, 
670                                               file_name=path,
671                                               details=self.details)
672       
673    def on_view(self, event):
674        """
675        Get object represented buy the given cell and plot them.
676        """
677        pos = self.notebook.GetSelection()
678        grid = self.notebook.GetPage(pos)
679        title = self.notebook.GetPageText(pos)
680       
681       
682        group_id = wx.NewId()
683        for cell in grid.selected_cells:
684            row, col = cell
685            label_row = 0
686            label = grid.GetCellValue(label_row, col)
687            if label in grid.data:
688                values = grid.data[label]
689                value = values[row -1]
690                if issubclass(value.__class__, BatchCell):
691                    for new_plot in value.object:
692                        if new_plot is None:
693                            msg = "Row %s , " % str(row)
694                            msg += "Column %s doesn't have a view" % str(label)
695                            #raise ValueError, msg
696                            wx.PostEvent(self.parent.parent, 
697                                 StatusEvent(status=msg, info="error")) 
698                            return
699                        if issubclass(new_plot.__class__, Data1D):
700                            new_plot.group_id = group_id
701                            new_plot.list_group_id .append(group_id)
702                        else:
703                            if label.lower() in ["data", "chi2"]:
704                                if len(grid.selected_cells) != 1:
705                                    msg = "Can only view one"
706                                    msg += " selected data at once"
707                                    wx.PostEvent(self.parent.parent, 
708                                                 StatusEvent(status=msg,
709                                                              info="error")) 
710                                    return 
711                        wx.PostEvent(self.parent.parent, 
712                                     NewPlotEvent(plot=new_plot, 
713                                  group_id=str(new_plot.group_id),
714                                   title =title)) 
715                else:
716                   
717                    msg = "Row %s , " % str(row)
718                    msg += "Column %s doesn't have a view" % str(label)
719                    #raise ValueError, msg
720                    wx.PostEvent(self.parent.parent, 
721                         StatusEvent(status=msg, info="error")) 
722                    return
723   
724       
725     
726   
727    def on_plot(self, event):
728        """
729        Evaluate the contains of textcrtl and plot result
730        """ 
731        pos = self.notebook.GetSelection()
732        grid = self.notebook.GetPage(pos)
733        column_names = {}
734        if grid is not None:
735            column_names = self.notebook.get_column_labels()
736        #evalue x
737        sentence = self.x_axis_label.GetValue()
738        try:
739            if sentence.strip() == "":
740                msg = "select value for x axis and y axis"
741                raise ValueError, msg
742        except:
743             wx.PostEvent(self.parent.parent, 
744                             StatusEvent(status=msg, info="error")) 
745             return
746       
747       
748        dict = parse_string(sentence, column_names.keys())
749        for tok, (col_name, list) in dict.iteritems():
750            col = column_names[col_name]
751            xaxis = self.get_plot_axis(col, list)
752            sentence = sentence.replace(tok, 
753                                        "numpy.array(%s)" % str(xaxis))
754        for key, value in FUNC_DICT.iteritems():
755            sentence = sentence.replace(key.lower(), value)
756        x = eval(sentence)
757        #evaluate y
758        sentence = self.y_axis_label.GetValue()
759        if sentence.strip() == "":
760            msg = "select value for y axis"
761            raise ValueError, msg
762        dict = parse_string(sentence, column_names.keys())
763        for tok, (col_name, list) in dict.iteritems():
764            col = column_names[col_name]
765            yaxis = self.get_plot_axis(col, list)
766            sentence = sentence.replace(tok, 
767                                        "numpy.array(%s)" % str(yaxis))
768        for key, value in FUNC_DICT.iteritems():
769            sentence = sentence.replace(key, value)
770        y = eval(sentence)
771        #plotting
772        new_plot = Data1D(x=x, y=y)
773        new_plot.id =  wx.NewId()
774        new_plot.group_id = wx.NewId()
775        title = "%s vs %s" % (self.y_axis_title.GetValue(), 
776                              self.x_axis_title.GetValue())
777        new_plot.xaxis(self.x_axis_title.GetValue(), self.x_axis_unit.GetValue())
778        new_plot.yaxis(self.y_axis_title.GetValue(), self.y_axis_unit.GetValue())
779        try:
780            title = self.notebook.GetPageText(pos)
781            new_plot.name = title
782            new_plot.xtransform = "x"
783            new_plot.ytransform  = "y" 
784            wx.PostEvent(self.parent.parent, 
785                             NewPlotEvent(plot=new_plot, 
786                        group_id=str(new_plot.group_id), title =title))   
787        except:
788             wx.PostEvent(self.parent.parent, 
789                             StatusEvent(status=msg, info="error")) 
790       
791    def layout_grid(self):
792        """
793        Draw the area related to the grid
794        """
795        self.notebook = Notebook(parent=self)
796        self.notebook.set_data(self._data_inputs, self._data_outputs)
797        self.grid_sizer.Add(self.notebook, 1, wx.EXPAND, 0)
798       
799    def layout_plotting_area(self):
800        """
801        Draw area containing options to plot
802        """
803       
804        self.x_axis_title = wx.TextCtrl(self, -1)
805        self.y_axis_title = wx.TextCtrl(self, -1)
806        self.x_axis_label = wx.TextCtrl(self, -1, size=(200, -1))
807        self.y_axis_label = wx.TextCtrl(self, -1, size=(200, -1))
808        self.x_axis_add = wx.Button(self, -1, "Add")
809        self.x_axis_add.Bind(event=wx.EVT_BUTTON, handler=self.on_edit_axis, 
810                            id=self.x_axis_add.GetId())
811        self.y_axis_add = wx.Button(self, -1, "Add")
812        self.y_axis_add.Bind(event=wx.EVT_BUTTON, handler=self.on_edit_axis, 
813                            id=self.y_axis_add.GetId())
814        self.x_axis_unit = wx.TextCtrl(self, -1)
815        self.y_axis_unit = wx.TextCtrl(self, -1)
816        self.view_button = wx.Button(self, -1, "View Results")
817        wx.EVT_BUTTON(self, self.view_button.GetId(), self.on_view)
818        self.plot_button = wx.Button(self, -1, "Plot")
819        self.button_sizer.AddMany( [ (500, 30),
820                                (self.view_button, 0, wx.RIGHT|wx.BOTTOM, 10),
821                                (self.plot_button, 0, wx.RIGHT|wx.BOTTOM, 10)])
822       
823        wx.EVT_BUTTON(self, self.plot_button.GetId(), self.on_plot)
824        self.plotting_sizer.AddMany([
825                    (wx.StaticText(self, -1, "x-axis label"), 1,
826                      wx.TOP|wx.BOTTOM|wx.LEFT, 10),
827                    (self.x_axis_label, 1, wx.TOP|wx.BOTTOM, 10),
828                    (self.x_axis_add, 1, wx.TOP|wx.BOTTOM|wx.RIGHT, 10),
829                    (wx.StaticText(self, -1, "x-axis title"), 1, 
830                     wx.TOP|wx.BOTTOM|wx.LEFT, 10),
831                    (self.x_axis_title, 1, wx.TOP|wx.BOTTOM, 10),
832                    (wx.StaticText(self, -1 , "unit"), 1, 
833                     wx.TOP|wx.BOTTOM, 10),
834                    (self.x_axis_unit, 1, wx.TOP|wx.BOTTOM, 10),
835                    (wx.StaticText(self, -1, "y-axis label"), 1, 
836                     wx.BOTTOM|wx.LEFT, 10),
837                    (self.y_axis_label, wx.BOTTOM, 10),
838                    (self.y_axis_add, 1, wx.BOTTOM|wx.RIGHT, 10),
839                    (wx.StaticText(self, -1, "y-axis title"), 1, 
840                     wx.BOTTOM|wx.LEFT, 10),
841                    (self.y_axis_title,  wx.BOTTOM, 10),
842                    (wx.StaticText(self, -1 , "unit"), 1, wx.BOTTOM, 10),
843                    (self.y_axis_unit, 1, wx.BOTTOM, 10),
844                      (-1, -1),
845                      (-1, -1),
846                      (-1, -1),
847                      (-1, -1),
848                      (-1, -1),
849                      (-1, -1),
850                      (-1, 1)])
851   
852    def on_edit_axis(self, event):
853        """
854        Get the selected column on  the visible grid and set values for axis
855        """
856        cell_list = self.notebook.on_edit_axis()
857        label, title = self.create_axis_label(cell_list)
858        tcrtl = event.GetEventObject()
859        if tcrtl == self.x_axis_add:
860            self.edit_axis_helper(self.x_axis_label, self.x_axis_title,
861                                   label, title)
862        elif tcrtl == self.y_axis_add:
863            self.edit_axis_helper(self.y_axis_label, self.y_axis_title,
864                                   label, title)
865           
866    def create_axis_label(self, cell_list):
867        """
868        Receive a list of cells and  create a string presenting the selected
869        cells.
870        :param cell_list: list of tuple
871       
872        """
873        if self.notebook is not None:
874            return self.notebook.create_axis_label(cell_list)
875   
876    def edit_axis_helper(self, tcrtl_label, tcrtl_title, label, title):
877        """
878        get controls to modify
879        """
880        tcrtl_label.SetValue(str(label))
881        tcrtl_title.SetValue(str(title))
882       
883    def add_column(self):
884        """
885        """
886        if self.notebook is not None:
887            self.notebook.add_column()
888       
889    def on_remove_column(self):
890        """
891        """
892        if self.notebook is not None:
893            self.notebook.on_remove_column()
894       
895       
896class GridFrame(wx.Frame):
897    def __init__(self, parent=None, data_inputs=None, data_outputs=None, id=-1, 
898                 title="Batch Results", size=(700, 400)):
899        wx.Frame.__init__(self, parent=parent, id=id, title=title, size=size)
900        self.parent = parent
901        self.panel = GridPanel(self, data_inputs, data_outputs)
902        menubar = wx.MenuBar()
903        self.SetMenuBar(menubar)
904       
905        self.curr_col = None
906        self.curr_grid = None
907        self.curr_col_name = ""
908        file = wx.Menu()
909        menubar.Append(file, "&File")
910       
911        hint = "Open file containing batch results"
912        open_menu = file.Append(wx.NewId(), 'Open ', hint)
913        wx.EVT_MENU(self, open_menu.GetId(), self.on_open)
914       
915        hint = "Open the the current grid into excel"
916        open_excel_menu = file.Append(wx.NewId(), 'Open with Excel', hint)
917        wx.EVT_MENU(self, open_excel_menu.GetId(), self.open_with_excel)
918        file.AppendSeparator()
919        save_menu = file.Append(wx.NewId(), 'Save As', 'Save into File')
920        wx.EVT_MENU(self, save_menu.GetId(), self.on_save_page)
921       
922        self.edit = wx.Menu()
923        hint = "Insert column before the selected column"
924        self.insert_before_menu = wx.Menu()
925        self.insert_sub_menu = self.edit.AppendSubMenu(self.insert_before_menu, 
926                                                      'Insert Before', hint)
927 
928        hint = "Remove the selected column"
929        self.remove_menu = self.edit.Append(-1, 'Remove Column', hint)
930        wx.EVT_MENU(self, self.remove_menu.GetId(), self.on_remove_column)
931       
932        self.Bind(wx.EVT_MENU_OPEN, self.on_menu_open)
933        menubar.Append(self.edit, "&Edit")
934        self.Bind(wx.EVT_CLOSE, self.on_close)
935       
936    def GetLabelText(self, id):
937        """
938        """
939        for item in self.insert_before_menu.GetMenuItems():
940            m_id = item.GetId() 
941            if m_id == id:
942                return item.GetLabel() 
943   
944    def on_remove_column(self, event):
945        """
946        """
947        pos = self.panel.notebook.GetSelection()
948        grid = self.panel.notebook.GetPage(pos)
949        grid.on_remove_column(event=None)
950       
951    def on_menu_open(self, event):
952        """
953       
954        """
955        if self.edit == event.GetMenu():
956            #get the selected column
957            pos = self.panel.notebook.GetSelection()
958            grid = self.panel.notebook.GetPage(pos)
959            col_list = grid.GetSelectedCols()
960            if len(col_list) > 0:
961                self.remove_menu.Enable(True)
962            else:
963                self.remove_menu.Enable(False)
964            if len(col_list)== 0 or len(col_list) > 1:
965                self.insert_sub_menu.Enable(False)
966               
967                label = "Insert Column Before"
968                self.insert_sub_menu.SetText(label)
969            else:
970                self.insert_sub_menu.Enable(True)
971               
972                col = col_list[0]
973                #GetColLabelValue(self, col)
974                col_name = grid.GetCellValue(row=0, col=col)
975                label = "Insert Column Before " + str(col_name)
976                self.insert_sub_menu.SetText(label)
977                for item in self.insert_before_menu.GetMenuItems():
978                    self.insert_before_menu.DeleteItem(item)
979                grid.insert_col_menu(menu=self.insert_before_menu, 
980                                     label=col_name, window=self)
981        event.Skip()
982       
983 
984       
985    def on_save_page(self, event):
986        """
987        """
988        if self.parent is not None:
989            pos = self.panel.notebook.GetSelection()
990            grid = self.panel.notebook.GetPage(pos)
991            reader, ext = os.path.splitext(grid.file_name)
992            path = None
993            if self.parent is not None: 
994                location = os.path.dirname(grid.file_name)
995                dlg = wx.FileDialog(self, "Save Project file",
996                            location, grid.file_name, ext, wx.SAVE)
997                path = None
998                if dlg.ShowModal() == wx.ID_OK:
999                    path = dlg.GetPath()
1000                dlg.Destroy()
1001                if path != None:
1002                    if self.parent is not None:
1003                        data = grid.get_grid_view()
1004                        self.parent.write_batch_tofile(data=data, 
1005                                               file_name=path,
1006                                               details=grid.details)
1007   
1008    def on_open(self, event):
1009        """
1010        Open file containg batch result
1011        """
1012        if self.parent is not None:
1013            self.parent.on_read_batch_tofile(event)
1014           
1015    def open_with_excel(self, event):
1016        """
1017        open excel and display batch result in Excel
1018        """
1019        if self.parent is not None:
1020            pos = self.panel.notebook.GetSelection()
1021            grid = self.panel.notebook.GetPage(pos)
1022            data = grid.get_grid_view()
1023            self.parent.open_with_externalapp(data=data,
1024                                               file_name=grid.file_name, 
1025                                               details=grid.details)
1026           
1027    def on_close(self, event):
1028        """
1029        """
1030        self.Hide()
1031       
1032   
1033    def on_append_column(self, event):
1034        """
1035        Append a new column to the grid
1036        """
1037        self.panel.add_column()
1038       
1039    def set_data(self, data_inputs, data_outputs, details="", file_name=None):
1040        """
1041        """
1042       
1043        self.panel.notebook.set_data(data_inputs=data_inputs, 
1044                            file_name=file_name,
1045                            details=details,
1046                            data_outputs=data_outputs)
1047     
1048     
1049class BatchOutputFrame(wx.Frame):
1050    """
1051    Allow to select where the result of batch will be displayed or stored
1052    """
1053    def __init__(self, parent, data_inputs, data_outputs, file_name="",
1054                 details="", *args, **kwds):
1055        """
1056        :param parent: Window instantiating this dialog
1057        :param result: result to display in a grid or export to an external
1058                application.
1059        """
1060        #kwds['style'] = wx.CAPTION|wx.SYSTEM_MENU
1061        wx.Frame.__init__(self, parent, *args, **kwds)
1062        self.parent = parent
1063        self.panel = wx.Panel(self)
1064        self.file_name = file_name
1065        self.details = details
1066        self.data_inputs = data_inputs
1067        self.data_outputs = data_outputs
1068        self.data = {}
1069        for item in (self.data_outputs, self.data_inputs):
1070            self.data.update(item)
1071        self.flag = 1
1072        self.SetSize((300, 200))
1073        self.local_app_selected = None
1074        self.external_app_selected = None
1075        self.save_to_file = None
1076        self._do_layout()
1077   
1078    def _do_layout(self):
1079        """
1080        Draw the content of the current dialog window
1081        """
1082        vbox = wx.BoxSizer(wx.VERTICAL)
1083        box_description = wx.StaticBox(self.panel, -1, str("Batch Outputs"))
1084        hint_sizer = wx.StaticBoxSizer(box_description, wx.VERTICAL)
1085        selection_sizer = wx.GridBagSizer(5, 5)
1086        button_sizer = wx.BoxSizer(wx.HORIZONTAL)
1087        text = "Open with %s" % self.parent.application_name
1088        self.local_app_selected = wx.RadioButton(self.panel, -1, text,
1089                                                style=wx.RB_GROUP)
1090        self.Bind(wx.EVT_RADIOBUTTON, self.onselect,
1091                    id=self.local_app_selected.GetId())
1092        text = "Open with Excel"
1093        self.external_app_selected  = wx.RadioButton(self.panel, -1, text)
1094        self.Bind(wx.EVT_RADIOBUTTON, self.onselect,
1095                    id=self.external_app_selected.GetId())
1096        text = "Save to File"
1097        self.save_to_file = wx.CheckBox(self.panel, -1, text)
1098        self.Bind(wx.EVT_CHECKBOX, self.onselect,
1099                    id=self.save_to_file.GetId())
1100        self.local_app_selected.SetValue(True)
1101        self.external_app_selected.SetValue(False)
1102        self.save_to_file.SetValue(False)
1103        button_close = wx.Button(self.panel, -1, "Close")
1104        button_close.Bind(wx.EVT_BUTTON, id=button_close.GetId(),
1105                           handler=self.on_close)
1106        button_apply = wx.Button(self.panel, -1, "Apply")
1107        button_apply.Bind(wx.EVT_BUTTON, id=button_apply.GetId(),
1108                        handler=self.on_apply)
1109        button_apply.SetFocus()
1110        hint = ""
1111        hint_sizer.Add(wx.StaticText(self.panel, -1, hint))
1112        hint_sizer.Add(selection_sizer)
1113        #draw area containing radio buttons
1114        ix = 0
1115        iy = 0
1116        selection_sizer.Add(self.local_app_selected, (iy, ix),
1117                           (1, 1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
1118        iy += 1
1119        selection_sizer.Add(self.external_app_selected, (iy, ix),
1120                           (1, 1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
1121        iy += 1
1122        selection_sizer.Add(self.save_to_file, (iy, ix),
1123                           (1, 1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
1124        #contruction the sizer contaning button
1125        button_sizer.Add((20, 20), 1, wx.EXPAND|wx.ADJUST_MINSIZE, 0)
1126
1127        button_sizer.Add(button_close, 0,
1128                        wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
1129        button_sizer.Add(button_apply, 0,
1130                                wx.LEFT|wx.RIGHT|wx.ADJUST_MINSIZE, 10)
1131        vbox.Add(hint_sizer,  0, wx.EXPAND|wx.ALL, 10)
1132        vbox.Add(wx.StaticLine(self.panel, -1),  0, wx.EXPAND, 0)
1133        vbox.Add(button_sizer, 0 , wx.TOP|wx.BOTTOM, 10)
1134        self.SetSizer(vbox)
1135       
1136    def on_apply(self, event):
1137        """
1138        Get the user selection and display output to the selected application
1139        """
1140        if self.flag == 1:
1141            self.parent.open_with_localapp(data_inputs=self.data_inputs,
1142                                            data_outputs=self.data_outputs)
1143        elif self.flag == 2:
1144            self.parent.open_with_externalapp(data=self.data, 
1145                                           file_name=self.file_name,
1146                                           details=self.details)
1147    def on_close(self, event):
1148        """
1149        close the Window
1150        """
1151        self.Close()
1152       
1153    def onselect(self, event=None):
1154        """
1155        Receive event and display data into third party application
1156        or save data to file.
1157       
1158        """
1159        if self.save_to_file.GetValue():
1160            reader, ext = os.path.splitext(self.file_name)
1161            path = None
1162            location = os.getcwd()
1163            if self.parent is not None: 
1164                location = os.path.dirname(self.file_name)
1165                dlg = wx.FileDialog(self, "Save Project file",
1166                            location, self.file_name, ext, wx.SAVE)
1167                path = None
1168                if dlg.ShowModal() == wx.ID_OK:
1169                    path = dlg.GetPath()
1170                dlg.Destroy()
1171                if path != None:
1172                    if self.parent is not None and  self.data is not None:
1173                        self.parent.write_batch_tofile(data=self.data, 
1174                                               file_name=path,
1175                                               details=self.details)
1176        if self.local_app_selected.GetValue():
1177            self.flag = 1
1178        else:
1179            self.flag = 2
1180        return self.flag
1181   
1182 
1183       
1184if __name__ == "__main__":
1185    app = wx.App()
1186   
1187    try:
1188        data = {}
1189        j = 0
1190        for i in range(4):
1191            j += 1
1192            data["index"+str(i)] = [i/j, i*j, i, i+j]
1193       
1194        data_input =  copy.deepcopy(data)   
1195        data_input["index5"] = [10,20,40, 50]
1196        frame = GridFrame(data_outputs=data, data_inputs=data_input)
1197        frame.Show(True)
1198    except:
1199        print sys.exc_value
1200       
1201    app.MainLoop()
Note: See TracBrowser for help on using the repository browser.