source: sasview/sansguiframe/src/sans/guiframe/data_processor.py @ 1c86a37

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

update grid according to feedbacks

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