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

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

Added dy selection for error bar

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