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

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

make sure the grid recreate a new page each time there is available result

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