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

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 9e91546 was a5e749f, checked in by Mathieu Doucet <doucetm@…>, 12 years ago

Fixing code style problems and bugs

  • Property mode set to 100644
File size: 55.7 KB
RevLine 
[24adb89]1"""
2Implement grid used to store data
3"""
4import wx
5import numpy
[904830e]6import math
[1ec979d]7import time
[904830e]8import re
[850525c]9import os
[24adb89]10import sys
[7ad194fa]11import copy
[24adb89]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
[1c86a37]17from sans.guiframe.panel_base import PanelBase
18from sans.guiframe.utils import format_number
[24adb89]19from sans.guiframe.events import NewPlotEvent
20from sans.guiframe.events import StatusEvent 
[fe98127]21from danse.common.plottools import plottables
[24adb89]22from sans.guiframe.dataFitting import Data1D
23
[904830e]24FUNC_DICT = {"sqrt": "math.sqrt",
25             "pow": "math.sqrt"}
[73197d0]26
[5425990]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
[75790dc]37        self.object = []
[5425990]38       
[73197d0]39
[904830e]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)
[08dc9e87]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
[904830e]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:
[08dc9e87]72                    # continuous range
[904830e]73                    temp = elt.split(label)
74                    for item in temp:
[08dc9e87]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)
[904830e]81                col_dict[elt] = (label, temp_arr)
82    return col_dict
[24adb89]83
[f4b37d1]84         
85         
86class SPanel(ScrolledPanel):
87    def __init__(self, parent, *args, **kwds):
88        ScrolledPanel.__init__(self, parent , *args, **kwds)
89        self.SetupScrolling() 
90       
[24adb89]91class GridPage(sheet.CSheet):
[9c8f3ad]92    """
93    """
[24adb89]94    def __init__(self, parent, panel=None):
95        """
96        """
97        sheet.CSheet.__init__(self, parent)
[f4b37d1]98       
99        self.AdjustScrollbars()
100        #self.SetLabelBackgroundColour('#DBD4D4')
[fd51a7c]101        self.uid = wx.NewId()
[f4b37d1]102        self.parent = parent
[24adb89]103        self.panel = panel
104        self.col_names = []
[8523a1f2]105        self.data_inputs = {}
106        self.data_outputs = {}
[d03a356]107        self.data = None
[71fa9028]108        self.details = ""
109        self.file_name = None
[9c8f3ad]110        self._cols = 50
[23a1747]111        self._rows = 501
[63dc6e5]112        self.last_selected_row = -1
113        self.last_selected_col = -1
[1c86a37]114        self.col_width = 30
115        self.row_height = 20
[656d65d]116        self.max_row_touse = 0
[49ad00b]117        self.axis_value = []
118        self.axis_label = ""
119        self.selected_cells = []
120        self.selected_cols = []
[75790dc]121        self.selected_rows = []
122        self.plottable_cells = []
[63dc6e5]123        self.plottable_flag = False
[1c86a37]124        self.SetColMinimalAcceptableWidth(self.col_width)
125        self.SetRowMinimalAcceptableHeight(self.row_height)
[23a1747]126        self.SetNumberRows(self._rows)
127        self.SetNumberCols(self._cols)
[f4b37d1]128        self.AutoSize()
[23477c6]129        self.list_plot_panels = {}
[1c86a37]130        self.default_col_width = 75
[5531a46]131        self.EnableEditing(False)
[1c86a37]132        if self.GetNumberCols() > 0:
133            self.default_col_width =  self.GetColSize(0)
[49ad00b]134        self.Bind(wx.grid.EVT_GRID_LABEL_LEFT_CLICK, self.on_left_click)
[24adb89]135        self.Bind(wx.grid.EVT_GRID_LABEL_RIGHT_CLICK, self.on_right_click)
[49ad00b]136        self.Bind(wx.grid.EVT_GRID_CELL_LEFT_CLICK, self.on_selected_cell)
[656d65d]137        self.Bind(wx.grid.EVT_GRID_CMD_CELL_CHANGE, self.on_edit_cell)
[1c86a37]138       
139       
[656d65d]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()
[49ad00b]147       
148    def on_selected_cell(self, event):
149        """
150        Handler catching cell selection
151        """
152        flag = event.CmdDown() or event.ControlDown()
[4e0dfe4]153        flag_shift =  event.ShiftDown()
[904830e]154        row, col = event.GetRow(), event.GetCol()
155        cell = (row, col)
[63dc6e5]156        event.Skip()
[4e0dfe4]157        if not flag and not flag_shift:
[08dc9e87]158            self.selected_cols = []
159            self.selected_rows = []
[49ad00b]160            self.selected_cells = []
[904830e]161            self.axis_label = ""
[08dc9e87]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
[63dc6e5]168        if col >= 0:
[08dc9e87]169            label_row = 0
170            self.axis_label = self.GetCellValue(label_row, col)
171            self.selected_cols.append(col)
[4e0dfe4]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
[49ad00b]208        else:
[4e0dfe4]209            self.selected_cells.append(cell)
210            self.selected_rows.append(row)
[dadf255]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))
[4e0dfe4]215     
[49ad00b]216    def on_left_click(self, event):
217        """
218        Catch the left click on label mouse event
219        """
[647df0d1]220        event.Skip()
[49ad00b]221        flag = event.CmdDown() or event.ControlDown()
[4e0dfe4]222       
[49ad00b]223        col = event.GetCol()
[63dc6e5]224        row = event.GetRow()
[4e0dfe4]225        if not (flag):
[dadf255]226            self.selected_cols = []
[75790dc]227            self.selected_rows = []
[dadf255]228            self.selected_cells = []
229            self.axis_label = ""
[08dc9e87]230            self.axis_value = []
[63dc6e5]231            self.plottable_list = []
[75790dc]232            self.plottable_cells = []
[63dc6e5]233            self.plottable_flag = False
[75790dc]234       
[63dc6e5]235        self.last_selected_col = col
236        self.last_selected_row = row
[75790dc]237        if row != -1 and row not in self.selected_rows:
238             self.selected_rows.append(row)
239             
[647df0d1]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)
[08dc9e87]246                    else:
247                        if flag:
248                             self.selected_cells.remove(cell)
[647df0d1]249            self.selected_cols.append(col)
250            self.axis_value = []
251            for cell_row, cell_col in self.selected_cells:
[4e0dfe4]252                val = self.GetCellValue(cell_row, cell_col)
253                if not val:
254                    self.axis_value.append(self.GetCellValue(cell_row, cell_col))
[647df0d1]255            self.axis_label = self.GetCellValue(0, col)
[25b7bf9]256            if not self.axis_label:
257                self.axis_label = " "
[75790dc]258       
[24adb89]259    def on_right_click(self, event):
[9c8f3ad]260        """
261        Catch the right click mouse
262        """
[656d65d]263       
[24adb89]264        col = event.GetCol()
[656d65d]265        self.selected_cols = []
266        self.selected_cols.append(col)
[24adb89]267        # Slicer plot popup menu
268        slicerpop = wx.Menu()
[656d65d]269        col_label_menu  = wx.Menu()
[1c86a37]270        c_name = self.GetCellValue(0, col) 
271        label = "Insert column before %s " % str(c_name)
[656d65d]272        slicerpop.AppendSubMenu(col_label_menu , 
[1c86a37]273                                 '&%s' % str(label), str(label))
[71fa9028]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)
[b18cf3d]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       
[656d65d]290        id = wx.NewId()   
291        hint = 'Remove selected column %s'
[71fa9028]292        slicerpop.Append(id, '&Remove Column', hint)
[656d65d]293        wx.EVT_MENU(self, id, self.on_remove_column)
[24adb89]294       
[656d65d]295        pos = wx.GetMousePosition()
[24adb89]296        pos = self.ScreenToClient(pos)
297        self.PopupMenu(slicerpop, pos)
[647df0d1]298        event.Skip()
[24adb89]299       
[71fa9028]300    def insert_col_menu(self, menu, label, window):
301        """
302        """
[5531a46]303        if self.data is None:
304            return
[71fa9028]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)
[fb0de166]310        row = 0
311        col_name = [self.GetCellValue(row, col) 
[71fa9028]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           
[b18cf3d]321    def insert_after_col_menu(self, menu, label, window):
322        """
323        """
[5531a46]324        if self.data is None:
325            return
[b18cf3d]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                               
[71fa9028]342    def on_remove_column(self, event=None):
[656d65d]343        """
344        """
345        if self.selected_cols is not None or len(self.selected_cols) > 0:
346            col = self.selected_cols[0]
[71fa9028]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)
[656d65d]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)
[71fa9028]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
[b18cf3d]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
[71fa9028]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:
[6dad639]410                label = value#format_number(value, high=True)
[b18cf3d]411                self.SetCellValue(cell_row, col, str(label))
[71fa9028]412                cell_row += 1
[b18cf3d]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()
[656d65d]418       
[24adb89]419    def on_set_x_axis(self, event):
[9c8f3ad]420        """
421        """
[24adb89]422        self.panel.set_xaxis(x=self.axis_value, label=self.axis_label)
423   
424    def on_set_y_axis(self, event):
[9c8f3ad]425        """
426        """
[24adb89]427        self.panel.set_yaxis(y=self.axis_value, label=self.axis_label)     
428           
[71fa9028]429    def set_data(self, data_inputs, data_outputs, details, file_name):
[24adb89]430        """
[9c8f3ad]431        Add data to the grid
[dadf255]432        :param data_inputs: data to use from the context menu of the grid
433        :param data_ouputs: default columns deplayed
[24adb89]434        """
[71fa9028]435        self.file_name = file_name
436        self.details = details
437       
[8523a1f2]438        if data_outputs is None:
439            data_outputs = {}
440        self.data_outputs = data_outputs
[71fa9028]441        if data_inputs is None:
[8523a1f2]442            data_inputs = {}
443        self.data_inputs = data_inputs
[656d65d]444        self.data = {}
445        for item in (self.data_outputs, self.data_inputs):
446            self.data.update(item)
[5531a46]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)
[8523a1f2]452        if  len(self.data_outputs) > 0:
[9c8f3ad]453            self._cols = self.GetNumberCols()
454            self._rows = self.GetNumberRows()
[8523a1f2]455            self.col_names = self.data_outputs.keys()
[24adb89]456            self.col_names.sort() 
[9c8f3ad]457            nbr_user_cols = len(self.col_names)
458            #Add more columns to the grid if necessary
459            if nbr_user_cols > self._cols:
[ed2d86e]460                new_col_nbr = nbr_user_cols -  self._cols + 1
[9c8f3ad]461                self.AppendCols(new_col_nbr, True)
462            #Add more rows to the grid if necessary 
[ed2d86e]463            nbr_user_row = len(self.data_outputs.values()[0])
[9c8f3ad]464            if nbr_user_row > self._rows + 1:
[ed2d86e]465                new_row_nbr =  nbr_user_row - self._rows + 1
[9c8f3ad]466                self.AppendRows(new_row_nbr, True)
467            # add data to the grid   
[ed2d86e]468            wx.CallAfter(self.set_grid_values)
[1c86a37]469        self.ForceRefresh()
[ed2d86e]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                         
[71fa9028]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] = []
[c27a111]516                for row in range(1, self.max_row_touse):
[71fa9028]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   
[24adb89]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,
[f4b37d1]536                    style=wx.aui.AUI_NB_WINDOWLIST_BUTTON| 
537                    wx.aui.AUI_BUTTON_DOWN|
[9c8f3ad]538                    wx.aui.AUI_NB_DEFAULT_STYLE|
539                    wx.CLIP_CHILDREN)
[24adb89]540        PanelBase.__init__(self, parent)
[9c8f3ad]541        self.enable_close_button()
[24adb89]542        self.parent = parent
543        self.manager = manager
544        self.data = data
[d03a356]545        #add empty page
546        self.add_empty_page()
547       
[9c8f3ad]548        self.Bind(wx.aui.EVT_AUINOTEBOOK_PAGE_CLOSE, self.on_close_page)
[7ad194fa]549   
[d03a356]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)
[63f4b8e]556        title = "Batch" + str(self.GetPageCount())
[d03a356]557        self.SetPageText(pos, title)
558        self.SetSelection(pos)
[f4b37d1]559        return grid , pos
[d03a356]560       
[9c8f3ad]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)
[9680906d]578             
579    def on_edit_axis(self):
580        """
[08dc9e87]581        Return the select cell of a given selected column. Check that all cells
582        are from the same column
[9680906d]583        """
584        pos = self.GetSelection()
585        grid = self.GetPage(pos)
[4e0dfe4]586        #grid.selected_cols = [grid.GetSelectedRows()]#
[08dc9e87]587        if len(grid.selected_cols) >= 1:
[49ad00b]588            col = grid.selected_cols[0]
[08dc9e87]589            for c in grid.selected_cols:
590                if c != col:
[7ad194fa]591                    msg = "Edit axis doesn't understand this selection.\n"
[08dc9e87]592                    msg += "Please select only one column"
[7ad194fa]593                    raise ValueError, msg
[08dc9e87]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       
[dadf255]605        return grid.selected_cells
606       
[7ad194fa]607   
[904830e]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()):
[25b7bf9]617            label = grid.GetColLabelValue(int(col))
618            #label = grid.GetCellValue(row, col)
[904830e]619            if label.strip() != "" :
620                labels[label.strip()] = col
621        return labels
622       
[7ad194fa]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
[9680906d]628       
[7ad194fa]629        """
630        pos = self.GetSelection()
631        grid = self.GetPage(pos)
632        label = ""
633        col_name = ""
[dadf255]634        def create_label(col_name,  row_min=None, row_max=None):
635            """
636            """
[4e0dfe4]637            result = " "
[dadf255]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) + ":"
[08dc9e87]645                    result += str(row_max) + "]"
646            return str(result)
[dadf255]647           
[7ad194fa]648        if len(cell_list) > 0:
[dadf255]649            if len(cell_list) == 1:
650                 row_min, col  = cell_list[0]   
[25b7bf9]651                 col_name =  grid.GetColLabelValue(int(col))#grid.GetCellValue(0, col)
652                 col_title = grid.GetCellValue(0, col)
[dadf255]653                 label = create_label(col_name, row_min+1 , row_min+1)
[25b7bf9]654                 return  label,  col_title
[dadf255]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]
[25b7bf9]661                col_name =  grid.GetColLabelValue(int(col))#grid.GetCellValue(0, col)
662                col_title = grid.GetCellValue(0, col)
[dadf255]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))
[08dc9e87]669                            if index -1 >= 0:
[dadf255]670                                new_row, _ = temp_list[index-1]
[4e0dfe4]671                                if not new_row==None and new_row!=' ' :
672                                    label += create_label(col_name, None, int(new_row) +1)
673                                else:
674                                    label += "]"
[dadf255]675                                label += ","
676                            if index + 1 < len(temp_list):
677                                new_row, _ = temp_list[index + 1]
[4e0dfe4]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)
[dadf255]685                    index += 1
[4e0dfe4]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
[7ad194fa]695   
[9c8f3ad]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()
[24adb89]703       
[71fa9028]704    def set_data(self, data_inputs, data_outputs, details="", file_name=None):
[8523a1f2]705        if data_outputs is None or data_outputs == {}:
[24adb89]706            return
[98fdccd]707        inputs, outputs = self.get_odered_results(data_inputs, data_outputs)
[f4b37d1]708        for pos in range(self.GetPageCount()):
709            grid = self.GetPage(pos)
710            if grid.data is None:
711                #Found empty page
[98fdccd]712                grid.set_data(data_inputs=inputs, 
713                              data_outputs=outputs,
[71fa9028]714                              details=details,
715                              file_name=file_name) 
[f4b37d1]716                self.SetSelection(pos) 
717                return
718               
719        grid, pos = self.add_empty_page()
[98fdccd]720        grid.set_data(data_inputs=inputs, 
721                      data_outputs=outputs,
[a84ca2a]722                      file_name=file_name,
723                      details=details)
[98fdccd]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
[e25d908]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
[98fdccd]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
[f4b37d1]753   
[9c8f3ad]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       
[24adb89]762class GridPanel(SPanel):
[8523a1f2]763    def __init__(self, parent, data_inputs=None,
764                 data_outputs=None, *args, **kwds):
[24adb89]765        SPanel.__init__(self, parent , *args, **kwds)
[f4b37d1]766       
[24adb89]767        self.vbox = wx.BoxSizer(wx.VERTICAL)
768       
[9680906d]769        self.plotting_sizer = wx.FlexGridSizer(3, 7, 10, 5)
[75790dc]770        self.button_sizer = wx.BoxSizer(wx.HORIZONTAL)
[24adb89]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),
[75790dc]774                           (self.plotting_sizer),
775                           (self.button_sizer)])
[24adb89]776        self.parent = parent
[8523a1f2]777        self._data_inputs = data_inputs
778        self._data_outputs = data_outputs
[24adb89]779        self.x = []
780        self.= []
781        self.x_axis_label = None
782        self.y_axis_label = None
[904830e]783        self.x_axis_title = None
784        self.y_axis_title = None
[24adb89]785        self.x_axis_unit = None
786        self.y_axis_unit = None
[75790dc]787        self.view_button = None
[24adb89]788        self.plot_button = None
[904830e]789        self.notebook = None
[23477c6]790       
[24adb89]791        self.layout_grid()
792        self.layout_plotting_area()
793        self.SetSizer(self.vbox)
[98fdccd]794
[904830e]795    def set_xaxis(self, label="", x=None):
796        """
797        """
[24adb89]798        if x is None:
799            x = []
800        self.x = x
[904830e]801        self.x_axis_label.SetValue("%s[:]" % str(label))
802        self.x_axis_title.SetValue(str(label))
[24adb89]803       
[904830e]804    def set_yaxis(self, label="", y=None):
805        """
806        """
[24adb89]807        if y is None:
808            y = []
809        self.y = y
[904830e]810        self.y_axis_label.SetValue("%s[:]" % str(label))
811        self.y_axis_title.SetValue(str(label))
[24adb89]812       
[904830e]813    def get_plot_axis(self, col, list):
814        """
815       
816        """
817        axis = []
818        pos = self.notebook.GetSelection()
819        grid = self.notebook.GetPage(pos)
820        for row in list:
[c911f34]821            label = grid.GetCellValue(0, col)
822            value = grid.GetCellValue(row - 1, col).strip()
823            if value != "":
824                if label.lower().strip() == "data":
825                    axis.append(float(row - 1))
826                else:
[dadf255]827                    try:
828                        axis.append(float(value))
829                    except:
830                        msg = "Invalid data in row %s column %s" % (str(row),
831                                                                    str(col))
832                        wx.PostEvent(self.parent.parent, 
[75790dc]833                             StatusEvent(status=msg, info="error")) 
[c911f34]834            else:
835                axis.append(None) 
[904830e]836        return axis
837   
[75790dc]838    def on_view(self, event):
839        """
840        Get object represented buy the given cell and plot them.
841        """
842        pos = self.notebook.GetSelection()
843        grid = self.notebook.GetPage(pos)
844        title = self.notebook.GetPageText(pos)
[9400de6]845        if len(grid.selected_cells) == 0:
846            msg = "Highlight a Data or Chi2 column first..."
847            wx.PostEvent(self.parent.parent, 
848                             StatusEvent(status=msg, info="error")) 
849            return
[23155ba]850        elif len(grid.selected_cells) > 20:
851            msg = "Too many data (> 20) to plot..."
852            msg += "\n Please select no more than 20 data."
853            dial = wx.MessageDialog(self, msg, 'Plotting', wx.OK)
854            wx.PostEvent(self.parent.parent, 
855                             StatusEvent(status=msg, info="error")) 
856            return
857
[75790dc]858        for cell in grid.selected_cells:
859            row, col = cell
860            label_row = 0
861            label = grid.GetCellValue(label_row, col)
862            if label in grid.data:
863                values = grid.data[label]
[344c5d8]864                if row > len(values) or row < 1:
[9400de6]865                    msg = "Invalid cell was chosen." 
866                    wx.PostEvent(self.parent.parent, StatusEvent(status=msg, 
867                                                                info="error"))
[1ec979d]868                    time.sleep(0.5)
[9400de6]869                    continue
[344c5d8]870                else:
871                     value = values[row -1]
[75790dc]872                if issubclass(value.__class__, BatchCell):
[fe98127]873                    if value.object is None or len(value.object) == 0:
874                        msg = "Row %s , " % str(row)
[c27a111]875                        msg += "Column %s is NOT " % str(label)
876                        msg += "the results of fits to view..."
[fe98127]877                        #raise ValueError, msg
878                        wx.PostEvent(self.parent.parent, StatusEvent(status=msg, 
879                                                                info="error")) 
880                        return
[75790dc]881                    for new_plot in value.object:
[fe98127]882                        if new_plot is None or \
[1f83477]883                         not issubclass(new_plot.__class__, 
[fe98127]884                                        plottables.Plottable):
[75790dc]885                            msg = "Row %s , " % str(row)
[c27a111]886                            msg += "Column %s is NOT " % str(label)
887                            msg += "the results of fits to view..."
[75790dc]888                            #raise ValueError, msg
889                            wx.PostEvent(self.parent.parent, 
890                                 StatusEvent(status=msg, info="error")) 
[1ec979d]891                            time.sleep(0.5)
[7d47789]892                            continue
[63f4b8e]893                        #new_plot.name =  title + ': ' + new_plot.title
[75790dc]894                        if issubclass(new_plot.__class__, Data1D):
[23477c6]895                            if label in grid.list_plot_panels.keys():
896                                group_id = grid.list_plot_panels[label]
[fd51a7c]897                            else:
[5d192cd]898                                group_id = str(new_plot.group_id) + str(grid.uid)
[23477c6]899                                grid.list_plot_panels[label] = group_id
[fd51a7c]900                            if group_id not in new_plot.list_group_id:
901                                new_plot.group_id = group_id
902                                new_plot.list_group_id.append(group_id)
[75790dc]903                        else:
[18a6556]904                            if label.lower() in ["data", "chi2"]:
[75790dc]905                                if len(grid.selected_cells) != 1:
[b18cf3d]906                                    msg = "2D View: Please select one data set"
[4e0dfe4]907                                    msg += " at a time for View Fit Results."
[75790dc]908                                    wx.PostEvent(self.parent.parent, 
909                                                 StatusEvent(status=msg,
[1ec979d]910                                                              info="error"))
911                                    time.sleep(0.5) 
[7d47789]912                                    continue 
[23477c6]913                        """
[75790dc]914                        wx.PostEvent(self.parent.parent,
[fd51a7c]915                                     NewPlotEvent(action="clear",
916                                                  group_id=str(group_id),
[23477c6]917                                                  title=title))
918                        """ 
[fd51a7c]919                        wx.PostEvent(self.parent.parent, 
[75790dc]920                                     NewPlotEvent(plot=new_plot, 
[1ec979d]921                                                group_id=str(new_plot.group_id),
922                                                title=title)) 
[4e0dfe4]923                        msg = "Plotting the View Fit Results  completed!"
[c27a111]924                        wx.PostEvent( self.parent.parent, 
925                                      StatusEvent(status=msg)) 
[75790dc]926                else:
927                   
928                    msg = "Row %s , " % str(row)
[c27a111]929                    msg += "Column %s is NOT " % str(label)
930                    msg += "the results of fits to view..."
[75790dc]931                    #raise ValueError, msg
932                    wx.PostEvent(self.parent.parent, 
933                         StatusEvent(status=msg, info="error")) 
[1ec979d]934                    time.sleep(0.5)
[665fd06]935                    continue
[75790dc]936   
937       
938     
939   
[24adb89]940    def on_plot(self, event):
941        """
[904830e]942        Evaluate the contains of textcrtl and plot result
[24adb89]943        """ 
[904830e]944        pos = self.notebook.GetSelection()
945        grid = self.notebook.GetPage(pos)
946        column_names = {}
947        if grid is not None:
948            column_names = self.notebook.get_column_labels()
[08dc9e87]949        #evaluate x
[904830e]950        sentence = self.x_axis_label.GetValue()
[1c86a37]951        try:
952            if sentence.strip() == "":
[08dc9e87]953                msg = "Select column values for x axis"
[1c86a37]954                raise ValueError, msg
955        except:
956             wx.PostEvent(self.parent.parent, 
957                             StatusEvent(status=msg, info="error")) 
958             return
[08dc9e87]959
[904830e]960        dict = parse_string(sentence, column_names.keys())
961        for tok, (col_name, list) in dict.iteritems():
962            col = column_names[col_name]
963            xaxis = self.get_plot_axis(col, list)
964            sentence = sentence.replace(tok, 
965                                        "numpy.array(%s)" % str(xaxis))
966        for key, value in FUNC_DICT.iteritems():
967            sentence = sentence.replace(key.lower(), value)
968        x = eval(sentence)
969        #evaluate y
970        sentence = self.y_axis_label.GetValue()
971        if sentence.strip() == "":
972            msg = "select value for y axis"
973            raise ValueError, msg
974        dict = parse_string(sentence, column_names.keys())
975        for tok, (col_name, list) in dict.iteritems():
976            col = column_names[col_name]
977            yaxis = self.get_plot_axis(col, list)
978            sentence = sentence.replace(tok, 
979                                        "numpy.array(%s)" % str(yaxis))
980        for key, value in FUNC_DICT.iteritems():
981            sentence = sentence.replace(key, value)
982        y = eval(sentence)
[08dc9e87]983        if len(x) != len(y) and (len(x) == 0 or len(y) == 0):
984            msg = "Need same length for X and Y axis and both greater than 0"
985            msg += " to plot.\n"
986            msg += "Got X length = %s, Y length = %s" % (str(len(x)),
987                                                          str(len(y)))
988            wx.PostEvent(self.parent.parent, 
989                             StatusEvent(status=msg, info="error")) 
990            return
991           
[904830e]992        #plotting
993        new_plot = Data1D(x=x, y=y)
[24adb89]994        new_plot.id =  wx.NewId()
995        new_plot.group_id = wx.NewId()
[904830e]996        title = "%s vs %s" % (self.y_axis_title.GetValue(), 
997                              self.x_axis_title.GetValue())
[1ec979d]998        new_plot.xaxis(self.x_axis_title.GetValue(), 
999                       self.x_axis_unit.GetValue())
1000        new_plot.yaxis(self.y_axis_title.GetValue(), 
1001                       self.y_axis_unit.GetValue())
[904830e]1002        try:
1003            title = self.notebook.GetPageText(pos)
[dadf255]1004            new_plot.name = title
[1c86a37]1005            new_plot.xtransform = "x"
1006            new_plot.ytransform  = "y" 
[904830e]1007            wx.PostEvent(self.parent.parent, 
[1ec979d]1008                        NewPlotEvent(plot=new_plot, 
[c27a111]1009                        group_id=str(new_plot.group_id), title =title)) 
1010            msg = "Plotting completed!"
1011            wx.PostEvent( self.parent.parent, 
1012                                      StatusEvent(status=msg))   
[904830e]1013        except:
[dadf255]1014             wx.PostEvent(self.parent.parent, 
[75790dc]1015                             StatusEvent(status=msg, info="error")) 
[c27a111]1016
[24adb89]1017    def layout_grid(self):
1018        """
1019        Draw the area related to the grid
1020        """
[904830e]1021        self.notebook = Notebook(parent=self)
[8523a1f2]1022        self.notebook.set_data(self._data_inputs, self._data_outputs)
[904830e]1023        self.grid_sizer.Add(self.notebook, 1, wx.EXPAND, 0)
[24adb89]1024       
1025    def layout_plotting_area(self):
1026        """
1027        Draw area containing options to plot
1028        """
[75790dc]1029       
[904830e]1030        self.x_axis_title = wx.TextCtrl(self, -1)
1031        self.y_axis_title = wx.TextCtrl(self, -1)
1032        self.x_axis_label = wx.TextCtrl(self, -1, size=(200, -1))
1033        self.y_axis_label = wx.TextCtrl(self, -1, size=(200, -1))
[9680906d]1034        self.x_axis_add = wx.Button(self, -1, "Add")
1035        self.x_axis_add.Bind(event=wx.EVT_BUTTON, handler=self.on_edit_axis, 
1036                            id=self.x_axis_add.GetId())
1037        self.y_axis_add = wx.Button(self, -1, "Add")
1038        self.y_axis_add.Bind(event=wx.EVT_BUTTON, handler=self.on_edit_axis, 
1039                            id=self.y_axis_add.GetId())
[24adb89]1040        self.x_axis_unit = wx.TextCtrl(self, -1)
1041        self.y_axis_unit = wx.TextCtrl(self, -1)
[4e0dfe4]1042        self.view_button = wx.Button(self, -1, "View Fits")
[7d47789]1043        view_tip = "Highlight the data set or the Chi2 column first."
[b18cf3d]1044        self.view_button.SetToolTipString(view_tip)
[75790dc]1045        wx.EVT_BUTTON(self, self.view_button.GetId(), self.on_view)
[24adb89]1046        self.plot_button = wx.Button(self, -1, "Plot")
[7d47789]1047        plot_tip = "Highlight a column for each axis and \n"
1048        plot_tip += "click the Add buttons first."
[b18cf3d]1049        self.plot_button.SetToolTipString(plot_tip)
[75790dc]1050        self.button_sizer.AddMany( [ (500, 30),
1051                                (self.view_button, 0, wx.RIGHT|wx.BOTTOM, 10),
1052                                (self.plot_button, 0, wx.RIGHT|wx.BOTTOM, 10)])
1053       
[24adb89]1054        wx.EVT_BUTTON(self, self.plot_button.GetId(), self.on_plot)
[9680906d]1055        self.plotting_sizer.AddMany([
[9bfa73f]1056                    (wx.StaticText(self, -1, 
1057                                   "X-axis Label\nSelection Range"), 1,
[904830e]1058                      wx.TOP|wx.BOTTOM|wx.LEFT, 10),
1059                    (self.x_axis_label, 1, wx.TOP|wx.BOTTOM, 10),
1060                    (self.x_axis_add, 1, wx.TOP|wx.BOTTOM|wx.RIGHT, 10),
[9bfa73f]1061                    (wx.StaticText(self, -1, "X-axis Label"), 1, 
[904830e]1062                     wx.TOP|wx.BOTTOM|wx.LEFT, 10),
1063                    (self.x_axis_title, 1, wx.TOP|wx.BOTTOM, 10),
[7124300]1064                    (wx.StaticText(self, -1 , "X-axis Unit"), 1, 
[904830e]1065                     wx.TOP|wx.BOTTOM, 10),
1066                    (self.x_axis_unit, 1, wx.TOP|wx.BOTTOM, 10),
[9bfa73f]1067                    (wx.StaticText(self, -1, 
1068                                   "Y-axis Label\nSelection Range"), 1, 
[904830e]1069                     wx.BOTTOM|wx.LEFT, 10),
1070                    (self.y_axis_label, wx.BOTTOM, 10),
1071                    (self.y_axis_add, 1, wx.BOTTOM|wx.RIGHT, 10),
[9bfa73f]1072                    (wx.StaticText(self, -1, "Y-axis Label"), 1, 
[904830e]1073                     wx.BOTTOM|wx.LEFT, 10),
1074                    (self.y_axis_title,  wx.BOTTOM, 10),
[9bfa73f]1075                    (wx.StaticText(self, -1 , "Y-axis Unit"), 1, wx.BOTTOM, 10),
[904830e]1076                    (self.y_axis_unit, 1, wx.BOTTOM, 10),
[9680906d]1077                      (-1, -1),
1078                      (-1, -1),
1079                      (-1, -1),
1080                      (-1, -1),
1081                      (-1, -1),
1082                      (-1, -1),
[75790dc]1083                      (-1, 1)])
[24adb89]1084   
[9680906d]1085    def on_edit_axis(self, event):
1086        """
1087        Get the selected column on  the visible grid and set values for axis
1088        """
[08dc9e87]1089        try:
1090            cell_list = self.notebook.on_edit_axis()
1091        except:
1092            msg = str(sys.exc_value)
1093            wx.PostEvent(self.parent.parent, 
1094                             StatusEvent(status=msg, info="error")) 
1095            return 
[904830e]1096        label, title = self.create_axis_label(cell_list)
1097        tcrtl = event.GetEventObject()
1098        if tcrtl == self.x_axis_add:
1099            self.edit_axis_helper(self.x_axis_label, self.x_axis_title,
1100                                   label, title)
1101        elif tcrtl == self.y_axis_add:
1102            self.edit_axis_helper(self.y_axis_label, self.y_axis_title,
1103                                   label, title)
1104           
[7ad194fa]1105    def create_axis_label(self, cell_list):
1106        """
1107        Receive a list of cells and  create a string presenting the selected
1108        cells.
1109        :param cell_list: list of tuple
[24adb89]1110       
[7ad194fa]1111        """
[904830e]1112        if self.notebook is not None:
1113            return self.notebook.create_axis_label(cell_list)
[7ad194fa]1114   
[904830e]1115    def edit_axis_helper(self, tcrtl_label, tcrtl_title, label, title):
[9680906d]1116        """
[904830e]1117        get controls to modify
[9680906d]1118        """
[904830e]1119        tcrtl_label.SetValue(str(label))
1120        tcrtl_title.SetValue(str(title))
1121       
[24adb89]1122    def add_column(self):
[9c8f3ad]1123        """
1124        """
[904830e]1125        if self.notebook is not None:
1126            self.notebook.add_column()
[24adb89]1127       
[9c8f3ad]1128    def on_remove_column(self):
1129        """
1130        """
[904830e]1131        if self.notebook is not None:
1132            self.notebook.on_remove_column()
[9c8f3ad]1133       
[24adb89]1134       
1135class GridFrame(wx.Frame):
[8523a1f2]1136    def __init__(self, parent=None, data_inputs=None, data_outputs=None, id=-1, 
[cf0eb8e]1137                 title="Batch Window", size=(800, 500)):
[24adb89]1138        wx.Frame.__init__(self, parent=parent, id=id, title=title, size=size)
1139        self.parent = parent
[8523a1f2]1140        self.panel = GridPanel(self, data_inputs, data_outputs)
[24adb89]1141        menubar = wx.MenuBar()
1142        self.SetMenuBar(menubar)
[71fa9028]1143       
1144        self.curr_col = None
1145        self.curr_grid = None
1146        self.curr_col_name = ""
1147        file = wx.Menu()
1148        menubar.Append(file, "&File")
1149       
1150        hint = "Open file containing batch results"
1151        open_menu = file.Append(wx.NewId(), 'Open ', hint)
1152        wx.EVT_MENU(self, open_menu.GetId(), self.on_open)
1153       
1154        hint = "Open the the current grid into excel"
1155        open_excel_menu = file.Append(wx.NewId(), 'Open with Excel', hint)
1156        wx.EVT_MENU(self, open_excel_menu.GetId(), self.open_with_excel)
1157        file.AppendSeparator()
1158        save_menu = file.Append(wx.NewId(), 'Save As', 'Save into File')
1159        wx.EVT_MENU(self, save_menu.GetId(), self.on_save_page)
1160       
1161        self.edit = wx.Menu()
1162        hint = "Insert column before the selected column"
1163        self.insert_before_menu = wx.Menu()
1164        self.insert_sub_menu = self.edit.AppendSubMenu(self.insert_before_menu, 
1165                                                      'Insert Before', hint)
1166 
1167        hint = "Remove the selected column"
1168        self.remove_menu = self.edit.Append(-1, 'Remove Column', hint)
1169        wx.EVT_MENU(self, self.remove_menu.GetId(), self.on_remove_column)
1170       
1171        self.Bind(wx.EVT_MENU_OPEN, self.on_menu_open)
1172        menubar.Append(self.edit, "&Edit")
[cb26857]1173        self.Bind(wx.EVT_CLOSE, self.on_close)
[71fa9028]1174    def GetLabelText(self, id):
[656d65d]1175        """
1176        """
[71fa9028]1177        for item in self.insert_before_menu.GetMenuItems():
1178            m_id = item.GetId() 
1179            if m_id == id:
1180                return item.GetLabel() 
1181   
1182    def on_remove_column(self, event):
[cb26857]1183        """
1184        """
[71fa9028]1185        pos = self.panel.notebook.GetSelection()
1186        grid = self.panel.notebook.GetPage(pos)
1187        grid.on_remove_column(event=None)
[cb26857]1188       
[71fa9028]1189    def on_menu_open(self, event):
[9c8f3ad]1190        """
[71fa9028]1191       
[9c8f3ad]1192        """
[71fa9028]1193        if self.edit == event.GetMenu():
1194            #get the selected column
1195            pos = self.panel.notebook.GetSelection()
1196            grid = self.panel.notebook.GetPage(pos)
1197            col_list = grid.GetSelectedCols()
1198            if len(col_list) > 0:
1199                self.remove_menu.Enable(True)
1200            else:
1201                self.remove_menu.Enable(False)
[a5e749f]1202            if len(col_list) == 0 or len(col_list) > 1:
[71fa9028]1203                self.insert_sub_menu.Enable(False)
1204               
1205                label = "Insert Column Before"
1206                self.insert_sub_menu.SetText(label)
1207            else:
1208                self.insert_sub_menu.Enable(True)
1209               
1210                col = col_list[0]
1211                #GetColLabelValue(self, col)
1212                col_name = grid.GetCellValue(row=0, col=col)
1213                label = "Insert Column Before " + str(col_name)
1214                self.insert_sub_menu.SetText(label)
1215                for item in self.insert_before_menu.GetMenuItems():
1216                    self.insert_before_menu.DeleteItem(item)
1217                grid.insert_col_menu(menu=self.insert_before_menu, 
1218                                     label=col_name, window=self)
1219        event.Skip()
[9c8f3ad]1220       
[71fa9028]1221 
1222       
1223    def on_save_page(self, event):
1224        """
1225        """
1226        if self.parent is not None:
1227            pos = self.panel.notebook.GetSelection()
1228            grid = self.panel.notebook.GetPage(pos)
[7b48b08]1229            if grid.file_name is None or grid.file_name.strip() == "" or \
1230                grid.data is None or len(grid.data) == 0:
1231                name = self.panel.notebook.GetPageText(pos)
1232                msg = " %s has not data to save" % str(name)
1233                wx.PostEvent(self.parent, 
1234                             StatusEvent(status=msg, info="error")) 
1235           
1236                return
[71fa9028]1237            reader, ext = os.path.splitext(grid.file_name)
1238            path = None
1239            if self.parent is not None: 
1240                location = os.path.dirname(grid.file_name)
1241                dlg = wx.FileDialog(self, "Save Project file",
1242                            location, grid.file_name, ext, wx.SAVE)
1243                path = None
1244                if dlg.ShowModal() == wx.ID_OK:
1245                    path = dlg.GetPath()
1246                dlg.Destroy()
1247                if path != None:
1248                    if self.parent is not None:
1249                        data = grid.get_grid_view()
1250                        self.parent.write_batch_tofile(data=data, 
1251                                               file_name=path,
1252                                               details=grid.details)
1253   
1254    def on_open(self, event):
[656d65d]1255        """
[71fa9028]1256        Open file containg batch result
[656d65d]1257        """
[71fa9028]1258        if self.parent is not None:
1259            self.parent.on_read_batch_tofile(event)
1260           
1261    def open_with_excel(self, event):
1262        """
1263        open excel and display batch result in Excel
1264        """
1265        if self.parent is not None:
1266            pos = self.panel.notebook.GetSelection()
1267            grid = self.panel.notebook.GetPage(pos)
1268            data = grid.get_grid_view()
[7b48b08]1269            if grid.file_name is None or grid.file_name.strip() == "" or \
1270                grid.data is None or len(grid.data) == 0:
1271                name = self.panel.notebook.GetPageText(pos)
1272                msg = " %s has not data to open on excel" % str(name)
1273                wx.PostEvent(self.parent, 
1274                             StatusEvent(status=msg, info="error")) 
1275           
1276                return
[71fa9028]1277            self.parent.open_with_externalapp(data=data,
[a5e749f]1278                                              file_name=grid.file_name, 
1279                                              details=grid.details)
[71fa9028]1280           
1281    def on_close(self, event):
1282        """
1283        """
1284        self.Hide()
[656d65d]1285       
[71fa9028]1286   
[656d65d]1287    def on_append_column(self, event):
[cb26857]1288        """
[9c8f3ad]1289        Append a new column to the grid
[cb26857]1290        """
[24adb89]1291        self.panel.add_column()
[cb26857]1292       
[71fa9028]1293    def set_data(self, data_inputs, data_outputs, details="", file_name=None):
[cb26857]1294        """
1295        """
[a84ca2a]1296       
1297        self.panel.notebook.set_data(data_inputs=data_inputs, 
[71fa9028]1298                            file_name=file_name,
1299                            details=details,
1300                            data_outputs=data_outputs)
[24adb89]1301     
1302     
[83eb1b52]1303class BatchOutputFrame(wx.Frame):
[73197d0]1304    """
1305    Allow to select where the result of batch will be displayed or stored
1306    """
[8523a1f2]1307    def __init__(self, parent, data_inputs, data_outputs, file_name="",
[850525c]1308                 details="", *args, **kwds):
[73197d0]1309        """
1310        :param parent: Window instantiating this dialog
1311        :param result: result to display in a grid or export to an external
1312                application.
1313        """
[850525c]1314        #kwds['style'] = wx.CAPTION|wx.SYSTEM_MENU
[83eb1b52]1315        wx.Frame.__init__(self, parent, *args, **kwds)
[73197d0]1316        self.parent = parent
[83eb1b52]1317        self.panel = wx.Panel(self)
[850525c]1318        self.file_name = file_name
1319        self.details = details
[8523a1f2]1320        self.data_inputs = data_inputs
1321        self.data_outputs = data_outputs
1322        self.data = {}
1323        for item in (self.data_outputs, self.data_inputs):
1324            self.data.update(item)
[73197d0]1325        self.flag = 1
1326        self.SetSize((300, 200))
1327        self.local_app_selected = None
1328        self.external_app_selected = None
1329        self.save_to_file = None
1330        self._do_layout()
[8523a1f2]1331   
[73197d0]1332    def _do_layout(self):
1333        """
1334        Draw the content of the current dialog window
1335        """
1336        vbox = wx.BoxSizer(wx.VERTICAL)
[83eb1b52]1337        box_description = wx.StaticBox(self.panel, -1, str("Batch Outputs"))
[73197d0]1338        hint_sizer = wx.StaticBoxSizer(box_description, wx.VERTICAL)
[83eb1b52]1339        selection_sizer = wx.GridBagSizer(5, 5)
[73197d0]1340        button_sizer = wx.BoxSizer(wx.HORIZONTAL)
[caf3a08f]1341        text = "Open with %s" % self.parent.application_name
[83eb1b52]1342        self.local_app_selected = wx.RadioButton(self.panel, -1, text,
[73197d0]1343                                                style=wx.RB_GROUP)
1344        self.Bind(wx.EVT_RADIOBUTTON, self.onselect,
1345                    id=self.local_app_selected.GetId())
1346        text = "Open with Excel"
[83eb1b52]1347        self.external_app_selected  = wx.RadioButton(self.panel, -1, text)
[73197d0]1348        self.Bind(wx.EVT_RADIOBUTTON, self.onselect,
1349                    id=self.external_app_selected.GetId())
[caf3a08f]1350        text = "Save to File"
[83eb1b52]1351        self.save_to_file = wx.CheckBox(self.panel, -1, text)
[73197d0]1352        self.Bind(wx.EVT_CHECKBOX, self.onselect,
1353                    id=self.save_to_file.GetId())
1354        self.local_app_selected.SetValue(True)
1355        self.external_app_selected.SetValue(False)
1356        self.save_to_file.SetValue(False)
[83eb1b52]1357        button_close = wx.Button(self.panel, -1, "Close")
1358        button_close.Bind(wx.EVT_BUTTON, id=button_close.GetId(),
1359                           handler=self.on_close)
1360        button_apply = wx.Button(self.panel, -1, "Apply")
1361        button_apply.Bind(wx.EVT_BUTTON, id=button_apply.GetId(),
1362                        handler=self.on_apply)
1363        button_apply.SetFocus()
[73197d0]1364        hint = ""
[83eb1b52]1365        hint_sizer.Add(wx.StaticText(self.panel, -1, hint))
[73197d0]1366        hint_sizer.Add(selection_sizer)
1367        #draw area containing radio buttons
1368        ix = 0
1369        iy = 0
1370        selection_sizer.Add(self.local_app_selected, (iy, ix),
1371                           (1, 1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
1372        iy += 1
1373        selection_sizer.Add(self.external_app_selected, (iy, ix),
1374                           (1, 1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
1375        iy += 1
1376        selection_sizer.Add(self.save_to_file, (iy, ix),
1377                           (1, 1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
1378        #contruction the sizer contaning button
1379        button_sizer.Add((20, 20), 1, wx.EXPAND|wx.ADJUST_MINSIZE, 0)
[caf3a08f]1380
1381        button_sizer.Add(button_close, 0,
1382                        wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
[83eb1b52]1383        button_sizer.Add(button_apply, 0,
[73197d0]1384                                wx.LEFT|wx.RIGHT|wx.ADJUST_MINSIZE, 10)
[a5e749f]1385        vbox.Add(hint_sizer, 0, wx.EXPAND|wx.ALL, 10)
[83eb1b52]1386        vbox.Add(wx.StaticLine(self.panel, -1),  0, wx.EXPAND, 0)
[a5e749f]1387        vbox.Add(button_sizer, 0, wx.TOP|wx.BOTTOM, 10)
[73197d0]1388        self.SetSizer(vbox)
1389       
[83eb1b52]1390    def on_apply(self, event):
1391        """
1392        Get the user selection and display output to the selected application
1393        """
1394        if self.flag == 1:
[8523a1f2]1395            self.parent.open_with_localapp(data_inputs=self.data_inputs,
[a5e749f]1396                                           data_outputs=self.data_outputs)
[83eb1b52]1397        elif self.flag == 2:
1398            self.parent.open_with_externalapp(data=self.data, 
[a5e749f]1399                                              file_name=self.file_name,
1400                                              details=self.details)
[83eb1b52]1401    def on_close(self, event):
1402        """
1403        close the Window
1404        """
1405        self.Close()
1406       
[73197d0]1407    def onselect(self, event=None):
1408        """
1409        Receive event and display data into third party application
1410        or save data to file.
1411       
1412        """
1413        if self.save_to_file.GetValue():
[850525c]1414            reader, ext = os.path.splitext(self.file_name)
1415            path = None
1416            location = os.getcwd()
1417            if self.parent is not None: 
[83eb1b52]1418                location = os.path.dirname(self.file_name)
[850525c]1419                dlg = wx.FileDialog(self, "Save Project file",
1420                            location, self.file_name, ext, wx.SAVE)
1421                path = None
1422                if dlg.ShowModal() == wx.ID_OK:
1423                    path = dlg.GetPath()
1424                dlg.Destroy()
1425                if path != None:
1426                    if self.parent is not None and  self.data is not None:
[83eb1b52]1427                        self.parent.write_batch_tofile(data=self.data, 
[a5e749f]1428                                                       file_name=path,
1429                                                       details=self.details)
[850525c]1430        if self.local_app_selected.GetValue():
[73197d0]1431            self.flag = 1
1432        else:
1433            self.flag = 2
1434        return self.flag
1435   
1436 
1437       
[24adb89]1438if __name__ == "__main__":
1439    app = wx.App()
1440   
1441    try:
1442        data = {}
1443        j = 0
1444        for i in range(4):
1445            j += 1
1446            data["index"+str(i)] = [i/j, i*j, i, i+j]
[656d65d]1447       
1448        data_input =  copy.deepcopy(data)   
[a5e749f]1449        data_input["index5"] = [10, 20, 40, 50]
[656d65d]1450        frame = GridFrame(data_outputs=data, data_inputs=data_input)
[24adb89]1451        frame.Show(True)
1452    except:
1453        print sys.exc_value
1454       
1455    app.MainLoop()
Note: See TracBrowser for help on using the repository browser.