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

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 62ffd8d was 23477c6, checked in by Jae Cho <jhjcho@…>, 13 years ago

update group id

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