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

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 225ed2d was dbb3914, checked in by Jae Cho <jhjcho@…>, 12 years ago

fixing the pylint warnings

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