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

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

make sure one can view plot

  • Property mode set to 100644
File size: 48.0 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   
732        for cell in grid.selected_cells:
733            row, col = cell
734            label_row = 0
735            label = grid.GetCellValue(label_row, col)
736            if label in grid.data:
737                values = grid.data[label]
738                value = values[row -1]
739                if issubclass(value.__class__, BatchCell):
740                    if value.object is None or len(value.object) == 0:
741                        msg = "Row %s , " % str(row)
742                        msg += "Column %s doesn't have a view" % str(label)
743                        #raise ValueError, msg
744                        wx.PostEvent(self.parent.parent, StatusEvent(status=msg, 
745                                                                info="error")) 
746                        return
747                    for new_plot in value.object:
748                        if new_plot is None or \
749                         not issubclass(new_plot.__class__, 
750                                        plottables.Plottable):
751                            msg = "Row %s , " % str(row)
752                            msg += "Column %s doesn't have a view" % str(label)
753                            #raise ValueError, msg
754                            wx.PostEvent(self.parent.parent, 
755                                 StatusEvent(status=msg, info="error")) 
756                            return
757                       
758                        if issubclass(new_plot.__class__, Data1D):
759                            if label in self.list_plot_panels.keys():
760                                group_id = self.list_plot_panels[label]
761                            else:
762                                group_id = str(grid.uid) + str(new_plot.group_id)
763                                self.list_plot_panels[label] = group_id
764                            if group_id not in new_plot.list_group_id:
765                                new_plot.group_id = group_id
766                                new_plot.list_group_id.append(group_id)
767                        else:
768                            if label.lower() in ["data", "chi2"]:
769                                if len(grid.selected_cells) != 1:
770                                    msg = "2D View: Please select one data set"
771                                    msg += " at a time to view."
772                                    wx.PostEvent(self.parent.parent, 
773                                                 StatusEvent(status=msg,
774                                                              info="error")) 
775                                    return 
776                        wx.PostEvent(self.parent.parent, 
777                                     NewPlotEvent(action="clear",
778                                                  group_id=str(group_id),
779                                                  title=title)) 
780                        wx.PostEvent(self.parent.parent, 
781                                     NewPlotEvent(plot=new_plot, 
782                                                  group_id=str(group_id),
783                                                  title=title)) 
784                else:
785                   
786                    msg = "Row %s , " % str(row)
787                    msg += "Column %s doesn't have a view" % str(label)
788                    #raise ValueError, msg
789                    wx.PostEvent(self.parent.parent, 
790                         StatusEvent(status=msg, info="error")) 
791                    return
792   
793       
794     
795   
796    def on_plot(self, event):
797        """
798        Evaluate the contains of textcrtl and plot result
799        """ 
800        pos = self.notebook.GetSelection()
801        grid = self.notebook.GetPage(pos)
802        column_names = {}
803        if grid is not None:
804            column_names = self.notebook.get_column_labels()
805        #evalue x
806        sentence = self.x_axis_label.GetValue()
807        try:
808            if sentence.strip() == "":
809                msg = "select value for x axis and y axis"
810                raise ValueError, msg
811        except:
812             wx.PostEvent(self.parent.parent, 
813                             StatusEvent(status=msg, info="error")) 
814             return
815       
816       
817        dict = parse_string(sentence, column_names.keys())
818        for tok, (col_name, list) in dict.iteritems():
819            col = column_names[col_name]
820            xaxis = self.get_plot_axis(col, list)
821            sentence = sentence.replace(tok, 
822                                        "numpy.array(%s)" % str(xaxis))
823        for key, value in FUNC_DICT.iteritems():
824            sentence = sentence.replace(key.lower(), value)
825        x = eval(sentence)
826        #evaluate y
827        sentence = self.y_axis_label.GetValue()
828        if sentence.strip() == "":
829            msg = "select value for y axis"
830            raise ValueError, msg
831        dict = parse_string(sentence, column_names.keys())
832        for tok, (col_name, list) in dict.iteritems():
833            col = column_names[col_name]
834            yaxis = self.get_plot_axis(col, list)
835            sentence = sentence.replace(tok, 
836                                        "numpy.array(%s)" % str(yaxis))
837        for key, value in FUNC_DICT.iteritems():
838            sentence = sentence.replace(key, value)
839        y = eval(sentence)
840        #plotting
841        new_plot = Data1D(x=x, y=y)
842        new_plot.id =  wx.NewId()
843        new_plot.group_id = wx.NewId()
844        title = "%s vs %s" % (self.y_axis_title.GetValue(), 
845                              self.x_axis_title.GetValue())
846        new_plot.xaxis(self.x_axis_title.GetValue(), self.x_axis_unit.GetValue())
847        new_plot.yaxis(self.y_axis_title.GetValue(), self.y_axis_unit.GetValue())
848        try:
849            title = self.notebook.GetPageText(pos)
850            new_plot.name = title
851            new_plot.xtransform = "x"
852            new_plot.ytransform  = "y" 
853            wx.PostEvent(self.parent.parent, 
854                             NewPlotEvent(plot=new_plot, 
855                        group_id=str(new_plot.group_id), title =title))   
856        except:
857             wx.PostEvent(self.parent.parent, 
858                             StatusEvent(status=msg, info="error")) 
859       
860    def layout_grid(self):
861        """
862        Draw the area related to the grid
863        """
864        self.notebook = Notebook(parent=self)
865        self.notebook.set_data(self._data_inputs, self._data_outputs)
866        self.grid_sizer.Add(self.notebook, 1, wx.EXPAND, 0)
867       
868    def layout_plotting_area(self):
869        """
870        Draw area containing options to plot
871        """
872       
873        self.x_axis_title = wx.TextCtrl(self, -1)
874        self.y_axis_title = wx.TextCtrl(self, -1)
875        self.x_axis_label = wx.TextCtrl(self, -1, size=(200, -1))
876        self.y_axis_label = wx.TextCtrl(self, -1, size=(200, -1))
877        self.x_axis_add = wx.Button(self, -1, "Add")
878        self.x_axis_add.Bind(event=wx.EVT_BUTTON, handler=self.on_edit_axis, 
879                            id=self.x_axis_add.GetId())
880        self.y_axis_add = wx.Button(self, -1, "Add")
881        self.y_axis_add.Bind(event=wx.EVT_BUTTON, handler=self.on_edit_axis, 
882                            id=self.y_axis_add.GetId())
883        self.x_axis_unit = wx.TextCtrl(self, -1)
884        self.y_axis_unit = wx.TextCtrl(self, -1)
885        self.view_button = wx.Button(self, -1, "View Results")
886        view_tip = "Highlight data sets or Chi2 column first."
887        self.view_button.SetToolTipString(view_tip)
888        wx.EVT_BUTTON(self, self.view_button.GetId(), self.on_view)
889        self.plot_button = wx.Button(self, -1, "Plot")
890        plot_tip = "Highlight column for axis and click the Add button first."
891        self.plot_button.SetToolTipString(plot_tip)
892        self.button_sizer.AddMany( [ (500, 30),
893                                (self.view_button, 0, wx.RIGHT|wx.BOTTOM, 10),
894                                (self.plot_button, 0, wx.RIGHT|wx.BOTTOM, 10)])
895       
896        wx.EVT_BUTTON(self, self.plot_button.GetId(), self.on_plot)
897        self.plotting_sizer.AddMany([
898                    (wx.StaticText(self, -1, "x-axis label"), 1,
899                      wx.TOP|wx.BOTTOM|wx.LEFT, 10),
900                    (self.x_axis_label, 1, wx.TOP|wx.BOTTOM, 10),
901                    (self.x_axis_add, 1, wx.TOP|wx.BOTTOM|wx.RIGHT, 10),
902                    (wx.StaticText(self, -1, "x-axis title"), 1, 
903                     wx.TOP|wx.BOTTOM|wx.LEFT, 10),
904                    (self.x_axis_title, 1, wx.TOP|wx.BOTTOM, 10),
905                    (wx.StaticText(self, -1 , "unit"), 1, 
906                     wx.TOP|wx.BOTTOM, 10),
907                    (self.x_axis_unit, 1, wx.TOP|wx.BOTTOM, 10),
908                    (wx.StaticText(self, -1, "y-axis label"), 1, 
909                     wx.BOTTOM|wx.LEFT, 10),
910                    (self.y_axis_label, wx.BOTTOM, 10),
911                    (self.y_axis_add, 1, wx.BOTTOM|wx.RIGHT, 10),
912                    (wx.StaticText(self, -1, "y-axis title"), 1, 
913                     wx.BOTTOM|wx.LEFT, 10),
914                    (self.y_axis_title,  wx.BOTTOM, 10),
915                    (wx.StaticText(self, -1 , "unit"), 1, wx.BOTTOM, 10),
916                    (self.y_axis_unit, 1, wx.BOTTOM, 10),
917                      (-1, -1),
918                      (-1, -1),
919                      (-1, -1),
920                      (-1, -1),
921                      (-1, -1),
922                      (-1, -1),
923                      (-1, 1)])
924   
925    def on_edit_axis(self, event):
926        """
927        Get the selected column on  the visible grid and set values for axis
928        """
929        cell_list = self.notebook.on_edit_axis()
930        label, title = self.create_axis_label(cell_list)
931        tcrtl = event.GetEventObject()
932        if tcrtl == self.x_axis_add:
933            self.edit_axis_helper(self.x_axis_label, self.x_axis_title,
934                                   label, title)
935        elif tcrtl == self.y_axis_add:
936            self.edit_axis_helper(self.y_axis_label, self.y_axis_title,
937                                   label, title)
938           
939    def create_axis_label(self, cell_list):
940        """
941        Receive a list of cells and  create a string presenting the selected
942        cells.
943        :param cell_list: list of tuple
944       
945        """
946        if self.notebook is not None:
947            return self.notebook.create_axis_label(cell_list)
948   
949    def edit_axis_helper(self, tcrtl_label, tcrtl_title, label, title):
950        """
951        get controls to modify
952        """
953        tcrtl_label.SetValue(str(label))
954        tcrtl_title.SetValue(str(title))
955       
956    def add_column(self):
957        """
958        """
959        if self.notebook is not None:
960            self.notebook.add_column()
961       
962    def on_remove_column(self):
963        """
964        """
965        if self.notebook is not None:
966            self.notebook.on_remove_column()
967       
968       
969class GridFrame(wx.Frame):
970    def __init__(self, parent=None, data_inputs=None, data_outputs=None, id=-1, 
971                 title="Batch Results", size=(700, 400)):
972        wx.Frame.__init__(self, parent=parent, id=id, title=title, size=size)
973        self.parent = parent
974        self.panel = GridPanel(self, data_inputs, data_outputs)
975        menubar = wx.MenuBar()
976        self.SetMenuBar(menubar)
977       
978        self.curr_col = None
979        self.curr_grid = None
980        self.curr_col_name = ""
981        file = wx.Menu()
982        menubar.Append(file, "&File")
983       
984        hint = "Open file containing batch results"
985        open_menu = file.Append(wx.NewId(), 'Open ', hint)
986        wx.EVT_MENU(self, open_menu.GetId(), self.on_open)
987       
988        hint = "Open the the current grid into excel"
989        open_excel_menu = file.Append(wx.NewId(), 'Open with Excel', hint)
990        wx.EVT_MENU(self, open_excel_menu.GetId(), self.open_with_excel)
991        file.AppendSeparator()
992        save_menu = file.Append(wx.NewId(), 'Save As', 'Save into File')
993        wx.EVT_MENU(self, save_menu.GetId(), self.on_save_page)
994       
995        self.edit = wx.Menu()
996        hint = "Insert column before the selected column"
997        self.insert_before_menu = wx.Menu()
998        self.insert_sub_menu = self.edit.AppendSubMenu(self.insert_before_menu, 
999                                                      'Insert Before', hint)
1000 
1001        hint = "Remove the selected column"
1002        self.remove_menu = self.edit.Append(-1, 'Remove Column', hint)
1003        wx.EVT_MENU(self, self.remove_menu.GetId(), self.on_remove_column)
1004       
1005        self.Bind(wx.EVT_MENU_OPEN, self.on_menu_open)
1006        menubar.Append(self.edit, "&Edit")
1007        self.Bind(wx.EVT_CLOSE, self.on_close)
1008       
1009    def GetLabelText(self, id):
1010        """
1011        """
1012        for item in self.insert_before_menu.GetMenuItems():
1013            m_id = item.GetId() 
1014            if m_id == id:
1015                return item.GetLabel() 
1016   
1017    def on_remove_column(self, event):
1018        """
1019        """
1020        pos = self.panel.notebook.GetSelection()
1021        grid = self.panel.notebook.GetPage(pos)
1022        grid.on_remove_column(event=None)
1023       
1024    def on_menu_open(self, event):
1025        """
1026       
1027        """
1028        if self.edit == event.GetMenu():
1029            #get the selected column
1030            pos = self.panel.notebook.GetSelection()
1031            grid = self.panel.notebook.GetPage(pos)
1032            col_list = grid.GetSelectedCols()
1033            if len(col_list) > 0:
1034                self.remove_menu.Enable(True)
1035            else:
1036                self.remove_menu.Enable(False)
1037            if len(col_list)== 0 or len(col_list) > 1:
1038                self.insert_sub_menu.Enable(False)
1039               
1040                label = "Insert Column Before"
1041                self.insert_sub_menu.SetText(label)
1042            else:
1043                self.insert_sub_menu.Enable(True)
1044               
1045                col = col_list[0]
1046                #GetColLabelValue(self, col)
1047                col_name = grid.GetCellValue(row=0, col=col)
1048                label = "Insert Column Before " + str(col_name)
1049                self.insert_sub_menu.SetText(label)
1050                for item in self.insert_before_menu.GetMenuItems():
1051                    self.insert_before_menu.DeleteItem(item)
1052                grid.insert_col_menu(menu=self.insert_before_menu, 
1053                                     label=col_name, window=self)
1054        event.Skip()
1055       
1056 
1057       
1058    def on_save_page(self, event):
1059        """
1060        """
1061        if self.parent is not None:
1062            pos = self.panel.notebook.GetSelection()
1063            grid = self.panel.notebook.GetPage(pos)
1064            reader, ext = os.path.splitext(grid.file_name)
1065            path = None
1066            if self.parent is not None: 
1067                location = os.path.dirname(grid.file_name)
1068                dlg = wx.FileDialog(self, "Save Project file",
1069                            location, grid.file_name, ext, wx.SAVE)
1070                path = None
1071                if dlg.ShowModal() == wx.ID_OK:
1072                    path = dlg.GetPath()
1073                dlg.Destroy()
1074                if path != None:
1075                    if self.parent is not None:
1076                        data = grid.get_grid_view()
1077                        self.parent.write_batch_tofile(data=data, 
1078                                               file_name=path,
1079                                               details=grid.details)
1080   
1081    def on_open(self, event):
1082        """
1083        Open file containg batch result
1084        """
1085        if self.parent is not None:
1086            self.parent.on_read_batch_tofile(event)
1087           
1088    def open_with_excel(self, event):
1089        """
1090        open excel and display batch result in Excel
1091        """
1092        if self.parent is not None:
1093            pos = self.panel.notebook.GetSelection()
1094            grid = self.panel.notebook.GetPage(pos)
1095            data = grid.get_grid_view()
1096            self.parent.open_with_externalapp(data=data,
1097                                               file_name=grid.file_name, 
1098                                               details=grid.details)
1099           
1100    def on_close(self, event):
1101        """
1102        """
1103        self.Hide()
1104       
1105   
1106    def on_append_column(self, event):
1107        """
1108        Append a new column to the grid
1109        """
1110        self.panel.add_column()
1111       
1112    def set_data(self, data_inputs, data_outputs, details="", file_name=None):
1113        """
1114        """
1115       
1116        self.panel.notebook.set_data(data_inputs=data_inputs, 
1117                            file_name=file_name,
1118                            details=details,
1119                            data_outputs=data_outputs)
1120     
1121     
1122class BatchOutputFrame(wx.Frame):
1123    """
1124    Allow to select where the result of batch will be displayed or stored
1125    """
1126    def __init__(self, parent, data_inputs, data_outputs, file_name="",
1127                 details="", *args, **kwds):
1128        """
1129        :param parent: Window instantiating this dialog
1130        :param result: result to display in a grid or export to an external
1131                application.
1132        """
1133        #kwds['style'] = wx.CAPTION|wx.SYSTEM_MENU
1134        wx.Frame.__init__(self, parent, *args, **kwds)
1135        self.parent = parent
1136        self.panel = wx.Panel(self)
1137        self.file_name = file_name
1138        self.details = details
1139        self.data_inputs = data_inputs
1140        self.data_outputs = data_outputs
1141        self.data = {}
1142        for item in (self.data_outputs, self.data_inputs):
1143            self.data.update(item)
1144        self.flag = 1
1145        self.SetSize((300, 200))
1146        self.local_app_selected = None
1147        self.external_app_selected = None
1148        self.save_to_file = None
1149        self._do_layout()
1150   
1151    def _do_layout(self):
1152        """
1153        Draw the content of the current dialog window
1154        """
1155        vbox = wx.BoxSizer(wx.VERTICAL)
1156        box_description = wx.StaticBox(self.panel, -1, str("Batch Outputs"))
1157        hint_sizer = wx.StaticBoxSizer(box_description, wx.VERTICAL)
1158        selection_sizer = wx.GridBagSizer(5, 5)
1159        button_sizer = wx.BoxSizer(wx.HORIZONTAL)
1160        text = "Open with %s" % self.parent.application_name
1161        self.local_app_selected = wx.RadioButton(self.panel, -1, text,
1162                                                style=wx.RB_GROUP)
1163        self.Bind(wx.EVT_RADIOBUTTON, self.onselect,
1164                    id=self.local_app_selected.GetId())
1165        text = "Open with Excel"
1166        self.external_app_selected  = wx.RadioButton(self.panel, -1, text)
1167        self.Bind(wx.EVT_RADIOBUTTON, self.onselect,
1168                    id=self.external_app_selected.GetId())
1169        text = "Save to File"
1170        self.save_to_file = wx.CheckBox(self.panel, -1, text)
1171        self.Bind(wx.EVT_CHECKBOX, self.onselect,
1172                    id=self.save_to_file.GetId())
1173        self.local_app_selected.SetValue(True)
1174        self.external_app_selected.SetValue(False)
1175        self.save_to_file.SetValue(False)
1176        button_close = wx.Button(self.panel, -1, "Close")
1177        button_close.Bind(wx.EVT_BUTTON, id=button_close.GetId(),
1178                           handler=self.on_close)
1179        button_apply = wx.Button(self.panel, -1, "Apply")
1180        button_apply.Bind(wx.EVT_BUTTON, id=button_apply.GetId(),
1181                        handler=self.on_apply)
1182        button_apply.SetFocus()
1183        hint = ""
1184        hint_sizer.Add(wx.StaticText(self.panel, -1, hint))
1185        hint_sizer.Add(selection_sizer)
1186        #draw area containing radio buttons
1187        ix = 0
1188        iy = 0
1189        selection_sizer.Add(self.local_app_selected, (iy, ix),
1190                           (1, 1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
1191        iy += 1
1192        selection_sizer.Add(self.external_app_selected, (iy, ix),
1193                           (1, 1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
1194        iy += 1
1195        selection_sizer.Add(self.save_to_file, (iy, ix),
1196                           (1, 1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
1197        #contruction the sizer contaning button
1198        button_sizer.Add((20, 20), 1, wx.EXPAND|wx.ADJUST_MINSIZE, 0)
1199
1200        button_sizer.Add(button_close, 0,
1201                        wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
1202        button_sizer.Add(button_apply, 0,
1203                                wx.LEFT|wx.RIGHT|wx.ADJUST_MINSIZE, 10)
1204        vbox.Add(hint_sizer,  0, wx.EXPAND|wx.ALL, 10)
1205        vbox.Add(wx.StaticLine(self.panel, -1),  0, wx.EXPAND, 0)
1206        vbox.Add(button_sizer, 0 , wx.TOP|wx.BOTTOM, 10)
1207        self.SetSizer(vbox)
1208       
1209    def on_apply(self, event):
1210        """
1211        Get the user selection and display output to the selected application
1212        """
1213        if self.flag == 1:
1214            self.parent.open_with_localapp(data_inputs=self.data_inputs,
1215                                            data_outputs=self.data_outputs)
1216        elif self.flag == 2:
1217            self.parent.open_with_externalapp(data=self.data, 
1218                                           file_name=self.file_name,
1219                                           details=self.details)
1220    def on_close(self, event):
1221        """
1222        close the Window
1223        """
1224        self.Close()
1225       
1226    def onselect(self, event=None):
1227        """
1228        Receive event and display data into third party application
1229        or save data to file.
1230       
1231        """
1232        if self.save_to_file.GetValue():
1233            reader, ext = os.path.splitext(self.file_name)
1234            path = None
1235            location = os.getcwd()
1236            if self.parent is not None: 
1237                location = os.path.dirname(self.file_name)
1238                dlg = wx.FileDialog(self, "Save Project file",
1239                            location, self.file_name, ext, wx.SAVE)
1240                path = None
1241                if dlg.ShowModal() == wx.ID_OK:
1242                    path = dlg.GetPath()
1243                dlg.Destroy()
1244                if path != None:
1245                    if self.parent is not None and  self.data is not None:
1246                        self.parent.write_batch_tofile(data=self.data, 
1247                                               file_name=path,
1248                                               details=self.details)
1249        if self.local_app_selected.GetValue():
1250            self.flag = 1
1251        else:
1252            self.flag = 2
1253        return self.flag
1254   
1255 
1256       
1257if __name__ == "__main__":
1258    app = wx.App()
1259   
1260    try:
1261        data = {}
1262        j = 0
1263        for i in range(4):
1264            j += 1
1265            data["index"+str(i)] = [i/j, i*j, i, i+j]
1266       
1267        data_input =  copy.deepcopy(data)   
1268        data_input["index5"] = [10,20,40, 50]
1269        frame = GridFrame(data_outputs=data, data_inputs=data_input)
1270        frame.Show(True)
1271    except:
1272        print sys.exc_value
1273       
1274    app.MainLoop()
Note: See TracBrowser for help on using the repository browser.