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

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

edit grid panel labels

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