source: sasview/sansguiframe/src/sans/guiframe/data_processor.py @ 2e9d14c

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 2e9d14c was 71fa9028, checked in by Gervaise Alina <gervyh@…>, 13 years ago

add menu item to data grid

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