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

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

check if the view object is a plottable

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