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

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

make sure error is handle when no data is available on the grid to view in excel or save

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