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

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

make sure residuals ans data are plotted using the same graph for each batch page

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