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

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

changed label of taps and plot default title, and fixed loading text data

  • Property mode set to 100644
File size: 59.1 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 = "Grid" + 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                            return
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                                    return
939                                    #continue 
940                        """
941                        wx.PostEvent(self.parent.parent,
942                                     NewPlotEvent(action="clear",
943                                                  group_id=str(group_id),
944                                                  title=title))
945                        """ 
946                        wx.PostEvent(self.parent.parent, 
947                                     NewPlotEvent(plot=new_plot, 
948                                                group_id=str(new_plot.group_id),
949                                                title=title)) 
950                        msg = "Plotting the View Fit Results  completed!"
951                        wx.PostEvent( self.parent.parent, 
952                                      StatusEvent(status=msg)) 
953                else:
954                   
955                    msg = "Row %s , " % str(row)
956                    msg += "Column %s is NOT " % str(label)
957                    msg += "the results of fits to view..."
958                    #raise ValueError, msg
959                    wx.PostEvent(self.parent.parent, 
960                         StatusEvent(status=msg, info="error")) 
961                    #time.sleep(0.5)
962                    return
963                    #continue
964   
965       
966     
967   
968    def on_plot(self, event):
969        """
970        Evaluate the contains of textcrtl and plot result
971        """ 
972        pos = self.notebook.GetSelection()
973        grid = self.notebook.GetPage(pos)
974        column_names = {}
975        if grid is not None:
976            column_names = self.notebook.get_column_labels()
977        #evaluate x
978        sentence = self.x_axis_label.GetValue()
979        try:
980            if sentence.strip() == "":
981                msg = "Select column values for x axis"
982                raise ValueError, msg
983        except:
984             wx.PostEvent(self.parent.parent, 
985                             StatusEvent(status=msg, info="error")) 
986             return
987
988        dict = parse_string(sentence, column_names.keys())
989        sentence = self.get_sentence(dict, sentence, column_names)
990        try:
991            x = eval(sentence)
992        except:
993            msg = "Need a proper x-range."
994            wx.PostEvent(self.parent.parent, 
995                             StatusEvent(status=msg, info="error")) 
996            return
997        #evaluate y
998        sentence = self.y_axis_label.GetValue()
999        if sentence.strip() == "":
1000            msg = "select value for y axis"
1001            raise ValueError, msg
1002        dict = parse_string(sentence, column_names.keys())
1003        sentence = self.get_sentence(dict, sentence, column_names)
1004        try:
1005            y = eval(sentence)
1006        except:
1007            msg = "Need a proper y-range."
1008            wx.PostEvent(self.parent.parent, 
1009                             StatusEvent(status=msg, info="error")) 
1010            return
1011        #evaluate y
1012        sentence = self.dy_axis_label.GetValue()
1013        dy = None
1014        if sentence.strip() != "":
1015            dict = parse_string(sentence, column_names.keys())
1016            sentence = self.get_sentence(dict, sentence, column_names)
1017            try:
1018                dy = eval(sentence)
1019            except:
1020                msg = "Need a proper dy-range."
1021                wx.PostEvent(self.parent.parent, 
1022                                 StatusEvent(status=msg, info="error")) 
1023                return
1024        if len(x) != len(y) or (len(x) == 0 or len(y) == 0):
1025            msg = "Need same length for X and Y axis and both greater than 0"
1026            msg += " to plot.\n"
1027            msg += "Got X length = %s, Y length = %s" % (str(len(x)),
1028                                                          str(len(y)))
1029            wx.PostEvent(self.parent.parent, 
1030                             StatusEvent(status=msg, info="error")) 
1031            return
1032        if dy != None and (len(y) != len(dy)): 
1033            msg = "Need same length for Y and dY axis and both greater than 0"
1034            msg += " to plot.\n"
1035            msg += "Got Y length = %s, dY length = %s" % (str(len(y)),
1036                                                          str(len(dy)))
1037            wx.PostEvent(self.parent.parent, 
1038                             StatusEvent(status=msg, info="error")) 
1039            return
1040        #plotting
1041        new_plot = Data1D(x=x, y=y, dy=dy)
1042        new_plot.id =  wx.NewId()
1043        new_plot.group_id = wx.NewId()
1044        y_title = self.y_axis_title.GetValue()
1045        x_title = self.x_axis_title.GetValue()
1046        title = "%s_vs_%s" % (y_title, 
1047                              x_title)
1048        new_plot.xaxis(x_title, 
1049                       self.x_axis_unit.GetValue())
1050        new_plot.yaxis(y_title, 
1051                       self.y_axis_unit.GetValue())
1052        try:
1053            title = y_title.strip()
1054            title += self.notebook.GetPageText(pos)
1055            new_plot.name = title
1056            new_plot.xtransform = "x"
1057            new_plot.ytransform  = "y" 
1058            #new_plot.is_data = False
1059            wx.PostEvent(self.parent.parent, 
1060                        NewPlotEvent(plot=new_plot, 
1061                        group_id=str(new_plot.group_id), title =title)) 
1062            msg = "Plotting completed!"
1063            wx.PostEvent( self.parent.parent, 
1064                                      StatusEvent(status=msg))   
1065        except:
1066             wx.PostEvent(self.parent.parent, 
1067                             StatusEvent(status=msg, info="error")) 
1068   
1069    def get_sentence(self, dict, sentence, column_names):
1070        """
1071        Get sentence from dict
1072        """
1073        for tok, (col_name, list) in dict.iteritems():
1074            col = column_names[col_name]
1075            axis = self.get_plot_axis(col, list)
1076            sentence = sentence.replace(tok, 
1077                                        "numpy.array(%s)" % str(axis))
1078        for key, value in FUNC_DICT.iteritems():
1079            sentence = sentence.replace(key.lower(), value)
1080        return sentence
1081           
1082    def layout_grid(self):
1083        """
1084        Draw the area related to the grid
1085        """
1086        self.notebook = Notebook(parent=self)
1087        self.notebook.set_data(self._data_inputs, self._data_outputs)
1088        self.grid_sizer.Add(self.notebook, 1, wx.EXPAND, 0)
1089       
1090    def layout_plotting_area(self):
1091        """
1092        Draw area containing options to plot
1093        """
1094        view_description = wx.StaticBox(self, -1, 'Plot Fits/Residuals')
1095        note = "To plot the fits (or residuals), click the 'View Fits' button"
1096        note += "\n after highlighting the Data names (or Chi2 values)."
1097        note_text = wx.StaticText(self, -1, note)
1098        boxsizer1 = wx.StaticBoxSizer(view_description, wx.HORIZONTAL)
1099        self.x_axis_title = wx.TextCtrl(self, -1)
1100        self.y_axis_title = wx.TextCtrl(self, -1)
1101        self.x_axis_label = wx.TextCtrl(self, -1, size=(200, -1))
1102        self.y_axis_label = wx.TextCtrl(self, -1, size=(200, -1))
1103        self.dy_axis_label = wx.TextCtrl(self, -1, size=(200, -1))
1104        self.x_axis_add = wx.Button(self, -1, "Add")
1105        self.x_axis_add.Bind(event=wx.EVT_BUTTON, handler=self.on_edit_axis, 
1106                            id=self.x_axis_add.GetId())
1107        self.y_axis_add = wx.Button(self, -1, "Add")
1108        self.y_axis_add.Bind(event=wx.EVT_BUTTON, handler=self.on_edit_axis, 
1109                            id=self.y_axis_add.GetId())
1110        self.dy_axis_add = wx.Button(self, -1, "Add")
1111        self.dy_axis_add.Bind(event=wx.EVT_BUTTON, handler=self.on_edit_axis, 
1112                            id=self.dy_axis_add.GetId())
1113        self.x_axis_unit = wx.TextCtrl(self, -1)
1114        self.y_axis_unit = wx.TextCtrl(self, -1)
1115        self.view_button = wx.Button(self, -1, "View Fits")
1116        view_tip = "Highlight the data set or the Chi2 column first."
1117        self.view_button.SetToolTipString(view_tip)
1118        wx.EVT_BUTTON(self, self.view_button.GetId(), self.on_view)
1119        self.plot_button = wx.Button(self, -1, "Plot")
1120        plot_tip = "Highlight a column for each axis and \n"
1121        plot_tip += "click the Add buttons first."
1122       
1123        self.plot_button.SetToolTipString(plot_tip)
1124        boxsizer1.AddMany([(note_text, 0, wx.LEFT, 10),
1125                           (self.view_button, 0, wx.LEFT|wx.RIGHT, 10)])
1126        self.button_sizer.AddMany([(boxsizer1, 0, 
1127                                    wx.LEFT|wx.RIGHT|wx.BOTTOM, 10), 
1128                                   (self.plot_button, 0, 
1129                                    wx.LEFT|wx.TOP|wx.BOTTOM|wx.EXPAND, 12)])
1130       
1131        wx.EVT_BUTTON(self, self.plot_button.GetId(), self.on_plot)
1132        self.plotting_sizer.AddMany([
1133                    (wx.StaticText(self, -1, 
1134                                   "X-axis Label\nSelection Range"), 1,
1135                      wx.TOP|wx.BOTTOM|wx.LEFT, 10),
1136                    (self.x_axis_label, 1, wx.TOP|wx.BOTTOM, 10),
1137                    (self.x_axis_add, 1, wx.TOP|wx.BOTTOM|wx.RIGHT, 10),
1138                    (wx.StaticText(self, -1, "X-axis Label"), 1, 
1139                     wx.TOP|wx.BOTTOM|wx.LEFT, 10),
1140                    (self.x_axis_title, 1, wx.TOP|wx.BOTTOM, 10),
1141                    (wx.StaticText(self, -1 , "X-axis Unit"), 1, 
1142                     wx.TOP|wx.BOTTOM, 10),
1143                    (self.x_axis_unit, 1, wx.TOP|wx.BOTTOM, 10),
1144                    (wx.StaticText(self, -1, 
1145                                   "Y-axis Label\nSelection Range"), 1, 
1146                     wx.BOTTOM|wx.LEFT, 10),
1147                    (self.y_axis_label, wx.BOTTOM, 10),
1148                    (self.y_axis_add, 1, wx.BOTTOM|wx.RIGHT, 10),
1149                    (wx.StaticText(self, -1, "Y-axis Label"), 1, 
1150                     wx.BOTTOM|wx.LEFT, 10),
1151                    (self.y_axis_title,  wx.BOTTOM, 10),
1152                    (wx.StaticText(self, -1 , "Y-axis Unit"), 1, wx.BOTTOM, 10),
1153                    (self.y_axis_unit, 1, wx.BOTTOM, 10),
1154                    (wx.StaticText(self, -1, 
1155                                   "dY-Bar (Optional)\nSelection Range"), 
1156                                   1, wx.BOTTOM|wx.LEFT, 10),
1157                    (self.dy_axis_label, wx.BOTTOM, 10),
1158                    (self.dy_axis_add, 1, wx.BOTTOM|wx.RIGHT, 10),
1159                      (-1, -1),
1160                      (-1, -1),
1161                      (-1, -1),
1162                      (-1, -1),
1163                      (-1, -1),
1164                      (-1, -1),
1165                      (-1, 1)])
1166   
1167    def on_edit_axis(self, event):
1168        """
1169        Get the selected column on  the visible grid and set values for axis
1170        """
1171        try:
1172            cell_list = self.notebook.on_edit_axis()
1173        except:
1174            msg = str(sys.exc_value)
1175            wx.PostEvent(self.parent.parent, 
1176                             StatusEvent(status=msg, info="error")) 
1177            return 
1178        label, title = self.create_axis_label(cell_list)
1179        tcrtl = event.GetEventObject()
1180        if tcrtl == self.x_axis_add:
1181            self.edit_axis_helper(self.x_axis_label, self.x_axis_title,
1182                                   label, title)
1183        elif tcrtl == self.y_axis_add:
1184            self.edit_axis_helper(self.y_axis_label, self.y_axis_title,
1185                                   label, title)
1186        elif tcrtl == self.dy_axis_add:
1187            self.edit_axis_helper(self.dy_axis_label, None,
1188                                   label, None)
1189           
1190    def create_axis_label(self, cell_list):
1191        """
1192        Receive a list of cells and  create a string presenting the selected
1193        cells.
1194        :param cell_list: list of tuple
1195       
1196        """
1197        if self.notebook is not None:
1198            return self.notebook.create_axis_label(cell_list)
1199   
1200    def edit_axis_helper(self, tcrtl_label, tcrtl_title, label, title):
1201        """
1202        get controls to modify
1203        """
1204        if label != None:
1205            tcrtl_label.SetValue(str(label))
1206        if title != None:
1207            tcrtl_title.SetValue(str(title))
1208       
1209    def add_column(self):
1210        """
1211        """
1212        if self.notebook is not None:
1213            self.notebook.add_column()
1214       
1215    def on_remove_column(self):
1216        """
1217        """
1218        if self.notebook is not None:
1219            self.notebook.on_remove_column()
1220       
1221       
1222class GridFrame(wx.Frame):
1223    def __init__(self, parent=None, data_inputs=None, data_outputs=None, id=-1, 
1224                 title="Grid Window", size=(800, 500)):
1225        wx.Frame.__init__(self, parent=parent, id=id, title=title, size=size)
1226        self.parent = parent
1227        self.panel = GridPanel(self, data_inputs, data_outputs)
1228        menubar = wx.MenuBar()
1229        self.SetMenuBar(menubar)
1230       
1231        self.curr_col = None
1232        self.curr_grid = None
1233        self.curr_col_name = ""
1234        file = wx.Menu()
1235        menubar.Append(file, "&File")
1236       
1237        hint = "Open file containing batch results"
1238        open_menu = file.Append(wx.NewId(), 'Open ', hint)
1239        wx.EVT_MENU(self, open_menu.GetId(), self.on_open)
1240       
1241        hint = "Open the the current grid into excel"
1242        open_excel_menu = file.Append(wx.NewId(), 'Open with Excel', hint)
1243        wx.EVT_MENU(self, open_excel_menu.GetId(), self.open_with_excel)
1244        file.AppendSeparator()
1245        save_menu = file.Append(wx.NewId(), 'Save As', 'Save into File')
1246        wx.EVT_MENU(self, save_menu.GetId(), self.on_save_page)
1247       
1248        self.edit = wx.Menu()
1249        hint = "Insert column before the selected column"
1250        self.insert_before_menu = wx.Menu()
1251        self.insert_sub_menu = self.edit.AppendSubMenu(self.insert_before_menu, 
1252                                                      'Insert Before', hint)
1253 
1254        hint = "Remove the selected column"
1255        self.remove_menu = self.edit.Append(-1, 'Remove Column', hint)
1256        wx.EVT_MENU(self, self.remove_menu.GetId(), self.on_remove_column)
1257       
1258        self.Bind(wx.EVT_MENU_OPEN, self.on_menu_open)
1259        menubar.Append(self.edit, "&Edit")
1260        self.Bind(wx.EVT_CLOSE, self.on_close)
1261    def GetLabelText(self, id):
1262        """
1263        """
1264        for item in self.insert_before_menu.GetMenuItems():
1265            m_id = item.GetId() 
1266            if m_id == id:
1267                return item.GetLabel() 
1268   
1269    def on_remove_column(self, event):
1270        """
1271        """
1272        pos = self.panel.notebook.GetSelection()
1273        grid = self.panel.notebook.GetPage(pos)
1274        grid.on_remove_column(event=None)
1275       
1276    def on_menu_open(self, event):
1277        """
1278       
1279        """
1280        if self.edit == event.GetMenu():
1281            #get the selected column
1282            pos = self.panel.notebook.GetSelection()
1283            grid = self.panel.notebook.GetPage(pos)
1284            col_list = grid.GetSelectedCols()
1285            if len(col_list) > 0:
1286                self.remove_menu.Enable(True)
1287            else:
1288                self.remove_menu.Enable(False)
1289            if len(col_list) == 0 or len(col_list) > 1:
1290                self.insert_sub_menu.Enable(False)
1291               
1292                label = "Insert Column Before"
1293                self.insert_sub_menu.SetText(label)
1294            else:
1295                self.insert_sub_menu.Enable(True)
1296               
1297                col = col_list[0]
1298                #GetColLabelValue(self, col)
1299                col_name = grid.GetCellValue(row=0, col=col)
1300                label = "Insert Column Before " + str(col_name)
1301                self.insert_sub_menu.SetText(label)
1302                for item in self.insert_before_menu.GetMenuItems():
1303                    self.insert_before_menu.DeleteItem(item)
1304                grid.insert_col_menu(menu=self.insert_before_menu, 
1305                                     label=col_name, window=self)
1306        event.Skip()
1307       
1308 
1309       
1310    def on_save_page(self, event):
1311        """
1312        """
1313        if self.parent is not None:
1314            pos = self.panel.notebook.GetSelection()
1315            grid = self.panel.notebook.GetPage(pos)
1316            if grid.file_name is None or grid.file_name.strip() == "" or \
1317                grid.data is None or len(grid.data) == 0:
1318                name = self.panel.notebook.GetPageText(pos)
1319                msg = " %s has not data to save" % str(name)
1320                wx.PostEvent(self.parent, 
1321                             StatusEvent(status=msg, info="error")) 
1322           
1323                return
1324            reader, ext = os.path.splitext(grid.file_name)
1325            path = None
1326            if self.parent is not None: 
1327                location = os.path.dirname(grid.file_name)
1328                dlg = wx.FileDialog(self, "Save Project file",
1329                            location, grid.file_name, ext, wx.SAVE)
1330                path = None
1331                if dlg.ShowModal() == wx.ID_OK:
1332                    path = dlg.GetPath()
1333                dlg.Destroy()
1334                if path != None:
1335                    if self.parent is not None:
1336                        data = grid.get_grid_view()
1337                        self.parent.write_batch_tofile(data=data, 
1338                                               file_name=path,
1339                                               details=grid.details)
1340   
1341    def on_open(self, event):
1342        """
1343        Open file containg batch result
1344        """
1345        if self.parent is not None:
1346            self.parent.on_read_batch_tofile(event)
1347           
1348    def open_with_excel(self, event):
1349        """
1350        open excel and display batch result in Excel
1351        """
1352        if self.parent is not None:
1353            pos = self.panel.notebook.GetSelection()
1354            grid = self.panel.notebook.GetPage(pos)
1355            data = grid.get_grid_view()
1356            if grid.file_name is None or grid.file_name.strip() == "" or \
1357                grid.data is None or len(grid.data) == 0:
1358                name = self.panel.notebook.GetPageText(pos)
1359                msg = " %s has not data to open on excel" % str(name)
1360                wx.PostEvent(self.parent, 
1361                             StatusEvent(status=msg, info="error")) 
1362           
1363                return
1364            self.parent.open_with_externalapp(data=data,
1365                                              file_name=grid.file_name, 
1366                                              details=grid.details)
1367           
1368    def on_close(self, event):
1369        """
1370        """
1371        self.Hide()
1372       
1373   
1374    def on_append_column(self, event):
1375        """
1376        Append a new column to the grid
1377        """
1378        self.panel.add_column()
1379       
1380    def set_data(self, data_inputs, data_outputs, details="", file_name=None):
1381        """
1382        """
1383       
1384        self.panel.notebook.set_data(data_inputs=data_inputs, 
1385                            file_name=file_name,
1386                            details=details,
1387                            data_outputs=data_outputs)
1388     
1389     
1390class BatchOutputFrame(wx.Frame):
1391    """
1392    Allow to select where the result of batch will be displayed or stored
1393    """
1394    def __init__(self, parent, data_inputs, data_outputs, file_name="",
1395                 details="", *args, **kwds):
1396        """
1397        :param parent: Window instantiating this dialog
1398        :param result: result to display in a grid or export to an external
1399                application.
1400        """
1401        #kwds['style'] = wx.CAPTION|wx.SYSTEM_MENU
1402        wx.Frame.__init__(self, parent, *args, **kwds)
1403        self.parent = parent
1404        self.panel = wx.Panel(self)
1405        self.file_name = file_name
1406        self.details = details
1407        self.data_inputs = data_inputs
1408        self.data_outputs = data_outputs
1409        self.data = {}
1410        for item in (self.data_outputs, self.data_inputs):
1411            self.data.update(item)
1412        self.flag = 1
1413        self.SetSize((300, 200))
1414        self.local_app_selected = None
1415        self.external_app_selected = None
1416        self.save_to_file = None
1417        self._do_layout()
1418   
1419    def _do_layout(self):
1420        """
1421        Draw the content of the current dialog window
1422        """
1423        vbox = wx.BoxSizer(wx.VERTICAL)
1424        box_description = wx.StaticBox(self.panel, -1, str("Batch Outputs"))
1425        hint_sizer = wx.StaticBoxSizer(box_description, wx.VERTICAL)
1426        selection_sizer = wx.GridBagSizer(5, 5)
1427        button_sizer = wx.BoxSizer(wx.HORIZONTAL)
1428        text = "Open with %s" % self.parent.application_name
1429        self.local_app_selected = wx.RadioButton(self.panel, -1, text,
1430                                                style=wx.RB_GROUP)
1431        self.Bind(wx.EVT_RADIOBUTTON, self.onselect,
1432                    id=self.local_app_selected.GetId())
1433        text = "Open with Excel"
1434        self.external_app_selected  = wx.RadioButton(self.panel, -1, text)
1435        self.Bind(wx.EVT_RADIOBUTTON, self.onselect,
1436                    id=self.external_app_selected.GetId())
1437        text = "Save to File"
1438        self.save_to_file = wx.CheckBox(self.panel, -1, text)
1439        self.Bind(wx.EVT_CHECKBOX, self.onselect,
1440                    id=self.save_to_file.GetId())
1441        self.local_app_selected.SetValue(True)
1442        self.external_app_selected.SetValue(False)
1443        self.save_to_file.SetValue(False)
1444        button_close = wx.Button(self.panel, -1, "Close")
1445        button_close.Bind(wx.EVT_BUTTON, id=button_close.GetId(),
1446                           handler=self.on_close)
1447        button_apply = wx.Button(self.panel, -1, "Apply")
1448        button_apply.Bind(wx.EVT_BUTTON, id=button_apply.GetId(),
1449                        handler=self.on_apply)
1450        button_apply.SetFocus()
1451        hint = ""
1452        hint_sizer.Add(wx.StaticText(self.panel, -1, hint))
1453        hint_sizer.Add(selection_sizer)
1454        #draw area containing radio buttons
1455        ix = 0
1456        iy = 0
1457        selection_sizer.Add(self.local_app_selected, (iy, ix),
1458                           (1, 1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
1459        iy += 1
1460        selection_sizer.Add(self.external_app_selected, (iy, ix),
1461                           (1, 1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
1462        iy += 1
1463        selection_sizer.Add(self.save_to_file, (iy, ix),
1464                           (1, 1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
1465        #contruction the sizer contaning button
1466        button_sizer.Add((20, 20), 1, wx.EXPAND|wx.ADJUST_MINSIZE, 0)
1467
1468        button_sizer.Add(button_close, 0,
1469                        wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
1470        button_sizer.Add(button_apply, 0,
1471                                wx.LEFT|wx.RIGHT|wx.ADJUST_MINSIZE, 10)
1472        vbox.Add(hint_sizer, 0, wx.EXPAND|wx.ALL, 10)
1473        vbox.Add(wx.StaticLine(self.panel, -1),  0, wx.EXPAND, 0)
1474        vbox.Add(button_sizer, 0, wx.TOP|wx.BOTTOM, 10)
1475        self.SetSizer(vbox)
1476       
1477    def on_apply(self, event):
1478        """
1479        Get the user selection and display output to the selected application
1480        """
1481        if self.flag == 1:
1482            self.parent.open_with_localapp(data_inputs=self.data_inputs,
1483                                           data_outputs=self.data_outputs)
1484        elif self.flag == 2:
1485            self.parent.open_with_externalapp(data=self.data, 
1486                                              file_name=self.file_name,
1487                                              details=self.details)
1488    def on_close(self, event):
1489        """
1490        close the Window
1491        """
1492        self.Close()
1493       
1494    def onselect(self, event=None):
1495        """
1496        Receive event and display data into third party application
1497        or save data to file.
1498       
1499        """
1500        if self.save_to_file.GetValue():
1501            reader, ext = os.path.splitext(self.file_name)
1502            path = None
1503            location = os.getcwd()
1504            if self.parent is not None: 
1505                location = os.path.dirname(self.file_name)
1506                dlg = wx.FileDialog(self, "Save Project file",
1507                            location, self.file_name, ext, wx.SAVE)
1508                path = None
1509                if dlg.ShowModal() == wx.ID_OK:
1510                    path = dlg.GetPath()
1511                dlg.Destroy()
1512                if path != None:
1513                    if self.parent is not None and  self.data is not None:
1514                        self.parent.write_batch_tofile(data=self.data, 
1515                                                       file_name=path,
1516                                                       details=self.details)
1517        if self.local_app_selected.GetValue():
1518            self.flag = 1
1519        else:
1520            self.flag = 2
1521        return self.flag
1522   
1523 
1524       
1525if __name__ == "__main__":
1526    app = wx.App()
1527   
1528    try:
1529        data = {}
1530        j = 0
1531        for i in range(4):
1532            j += 1
1533            data["index"+str(i)] = [i/j, i*j, i, i+j]
1534       
1535        data_input =  copy.deepcopy(data)   
1536        data_input["index5"] = [10, 20, 40, 50]
1537        frame = GridFrame(data_outputs=data, data_inputs=data_input)
1538        frame.Show(True)
1539    except:
1540        print sys.exc_value
1541       
1542    app.MainLoop()
Note: See TracBrowser for help on using the repository browser.