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

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

added tip for viewfits

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