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

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

added tip for viewfits

  • Property mode set to 100644
File size: 58.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:
[3553ad2]169            if flag:
170                label_row = row
171            else:
172                label_row = 0
[08dc9e87]173            self.axis_label = self.GetCellValue(label_row, col)
174            self.selected_cols.append(col)
[4e0dfe4]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
[49ad00b]211        else:
[4e0dfe4]212            self.selected_cells.append(cell)
213            self.selected_rows.append(row)
[dadf255]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))
[4e0dfe4]218     
[49ad00b]219    def on_left_click(self, event):
220        """
221        Catch the left click on label mouse event
222        """
[647df0d1]223        event.Skip()
[49ad00b]224        flag = event.CmdDown() or event.ControlDown()
[4e0dfe4]225       
[49ad00b]226        col = event.GetCol()
[63dc6e5]227        row = event.GetRow()
[4e0dfe4]228        if not (flag):
[dadf255]229            self.selected_cols = []
[75790dc]230            self.selected_rows = []
[dadf255]231            self.selected_cells = []
232            self.axis_label = ""
[08dc9e87]233            self.axis_value = []
[63dc6e5]234            self.plottable_list = []
[75790dc]235            self.plottable_cells = []
[63dc6e5]236            self.plottable_flag = False
[75790dc]237       
[63dc6e5]238        self.last_selected_col = col
239        self.last_selected_row = row
[75790dc]240        if row != -1 and row not in self.selected_rows:
241             self.selected_rows.append(row)
242             
[647df0d1]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)
[08dc9e87]249                    else:
250                        if flag:
251                             self.selected_cells.remove(cell)
[647df0d1]252            self.selected_cols.append(col)
253            self.axis_value = []
254            for cell_row, cell_col in self.selected_cells:
[4e0dfe4]255                val = self.GetCellValue(cell_row, cell_col)
256                if not val:
257                    self.axis_value.append(self.GetCellValue(cell_row, cell_col))
[647df0d1]258            self.axis_label = self.GetCellValue(0, col)
[25b7bf9]259            if not self.axis_label:
260                self.axis_label = " "
[75790dc]261       
[24adb89]262    def on_right_click(self, event):
[9c8f3ad]263        """
264        Catch the right click mouse
265        """
[656d65d]266       
[24adb89]267        col = event.GetCol()
[c151afc]268        row = event.GetRow()
[9ccb7e1]269        # Ignore the index column
[c151afc]270        if col < 0 or row != -1:
[9ccb7e1]271            return
[656d65d]272        self.selected_cols = []
273        self.selected_cols.append(col)
[24adb89]274        # Slicer plot popup menu
275        slicerpop = wx.Menu()
[656d65d]276        col_label_menu  = wx.Menu()
[1c86a37]277        c_name = self.GetCellValue(0, col) 
278        label = "Insert column before %s " % str(c_name)
[656d65d]279        slicerpop.AppendSubMenu(col_label_menu , 
[1c86a37]280                                 '&%s' % str(label), str(label))
[71fa9028]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)
[b18cf3d]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       
[656d65d]297        id = wx.NewId()   
298        hint = 'Remove selected column %s'
[71fa9028]299        slicerpop.Append(id, '&Remove Column', hint)
[656d65d]300        wx.EVT_MENU(self, id, self.on_remove_column)
[24adb89]301       
[656d65d]302        pos = wx.GetMousePosition()
[24adb89]303        pos = self.ScreenToClient(pos)
304        self.PopupMenu(slicerpop, pos)
[647df0d1]305        event.Skip()
[24adb89]306       
[71fa9028]307    def insert_col_menu(self, menu, label, window):
308        """
309        """
[5531a46]310        if self.data is None:
311            return
[71fa9028]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)
[fb0de166]317        row = 0
318        col_name = [self.GetCellValue(row, col) 
[71fa9028]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           
[b18cf3d]328    def insert_after_col_menu(self, menu, label, window):
329        """
330        """
[5531a46]331        if self.data is None:
332            return
[b18cf3d]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                               
[71fa9028]349    def on_remove_column(self, event=None):
[656d65d]350        """
351        """
352        if self.selected_cols is not None or len(self.selected_cols) > 0:
353            col = self.selected_cols[0]
[71fa9028]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)
[656d65d]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)
[71fa9028]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
[b18cf3d]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
[71fa9028]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:
[6dad639]417                label = value#format_number(value, high=True)
[b18cf3d]418                self.SetCellValue(cell_row, col, str(label))
[71fa9028]419                cell_row += 1
[b18cf3d]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()
[656d65d]425       
[24adb89]426    def on_set_x_axis(self, event):
[9c8f3ad]427        """
428        """
[24adb89]429        self.panel.set_xaxis(x=self.axis_value, label=self.axis_label)
430   
431    def on_set_y_axis(self, event):
[9c8f3ad]432        """
433        """
[24adb89]434        self.panel.set_yaxis(y=self.axis_value, label=self.axis_label)     
435           
[71fa9028]436    def set_data(self, data_inputs, data_outputs, details, file_name):
[24adb89]437        """
[9c8f3ad]438        Add data to the grid
[dadf255]439        :param data_inputs: data to use from the context menu of the grid
440        :param data_ouputs: default columns deplayed
[24adb89]441        """
[71fa9028]442        self.file_name = file_name
443        self.details = details
444       
[8523a1f2]445        if data_outputs is None:
446            data_outputs = {}
447        self.data_outputs = data_outputs
[71fa9028]448        if data_inputs is None:
[8523a1f2]449            data_inputs = {}
450        self.data_inputs = data_inputs
[656d65d]451        self.data = {}
452        for item in (self.data_outputs, self.data_inputs):
453            self.data.update(item)
[5531a46]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)
[8523a1f2]459        if  len(self.data_outputs) > 0:
[9c8f3ad]460            self._cols = self.GetNumberCols()
461            self._rows = self.GetNumberRows()
[8523a1f2]462            self.col_names = self.data_outputs.keys()
[24adb89]463            self.col_names.sort() 
[9c8f3ad]464            nbr_user_cols = len(self.col_names)
465            #Add more columns to the grid if necessary
466            if nbr_user_cols > self._cols:
[ed2d86e]467                new_col_nbr = nbr_user_cols -  self._cols + 1
[9c8f3ad]468                self.AppendCols(new_col_nbr, True)
469            #Add more rows to the grid if necessary 
[ed2d86e]470            nbr_user_row = len(self.data_outputs.values()[0])
[9c8f3ad]471            if nbr_user_row > self._rows + 1:
[ed2d86e]472                new_row_nbr =  nbr_user_row - self._rows + 1
[9c8f3ad]473                self.AppendRows(new_row_nbr, True)
474            # add data to the grid   
[ed2d86e]475            wx.CallAfter(self.set_grid_values)
[1c86a37]476        self.ForceRefresh()
[ed2d86e]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                         
[71fa9028]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] = []
[c27a111]523                for row in range(1, self.max_row_touse):
[71fa9028]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   
[24adb89]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,
[f4b37d1]543                    style=wx.aui.AUI_NB_WINDOWLIST_BUTTON| 
544                    wx.aui.AUI_BUTTON_DOWN|
[9c8f3ad]545                    wx.aui.AUI_NB_DEFAULT_STYLE|
546                    wx.CLIP_CHILDREN)
[24adb89]547        PanelBase.__init__(self, parent)
[9c8f3ad]548        self.enable_close_button()
[24adb89]549        self.parent = parent
550        self.manager = manager
551        self.data = data
[d03a356]552        #add empty page
553        self.add_empty_page()
554       
[9c8f3ad]555        self.Bind(wx.aui.EVT_AUINOTEBOOK_PAGE_CLOSE, self.on_close_page)
[7ad194fa]556   
[d03a356]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)
[63f4b8e]563        title = "Batch" + str(self.GetPageCount())
[d03a356]564        self.SetPageText(pos, title)
565        self.SetSelection(pos)
[f4b37d1]566        return grid , pos
[d03a356]567       
[9c8f3ad]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)
[9680906d]585             
586    def on_edit_axis(self):
587        """
[08dc9e87]588        Return the select cell of a given selected column. Check that all cells
589        are from the same column
[9680906d]590        """
591        pos = self.GetSelection()
592        grid = self.GetPage(pos)
[4e0dfe4]593        #grid.selected_cols = [grid.GetSelectedRows()]#
[08dc9e87]594        if len(grid.selected_cols) >= 1:
[49ad00b]595            col = grid.selected_cols[0]
[08dc9e87]596            for c in grid.selected_cols:
597                if c != col:
[7ad194fa]598                    msg = "Edit axis doesn't understand this selection.\n"
[08dc9e87]599                    msg += "Please select only one column"
[7ad194fa]600                    raise ValueError, msg
[08dc9e87]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       
[dadf255]612        return grid.selected_cells
613       
[7ad194fa]614   
[904830e]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()):
[25b7bf9]624            label = grid.GetColLabelValue(int(col))
625            #label = grid.GetCellValue(row, col)
[904830e]626            if label.strip() != "" :
627                labels[label.strip()] = col
628        return labels
629       
[7ad194fa]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
[9680906d]635       
[7ad194fa]636        """
637        pos = self.GetSelection()
638        grid = self.GetPage(pos)
639        label = ""
640        col_name = ""
[dadf255]641        def create_label(col_name,  row_min=None, row_max=None):
642            """
643            """
[4e0dfe4]644            result = " "
[dadf255]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) + ":"
[08dc9e87]652                    result += str(row_max) + "]"
653            return str(result)
[dadf255]654           
[7ad194fa]655        if len(cell_list) > 0:
[dadf255]656            if len(cell_list) == 1:
657                 row_min, col  = cell_list[0]   
[25b7bf9]658                 col_name =  grid.GetColLabelValue(int(col))#grid.GetCellValue(0, col)
659                 col_title = grid.GetCellValue(0, col)
[dadf255]660                 label = create_label(col_name, row_min+1 , row_min+1)
[25b7bf9]661                 return  label,  col_title
[dadf255]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]
[25b7bf9]668                col_name =  grid.GetColLabelValue(int(col))#grid.GetCellValue(0, col)
669                col_title = grid.GetCellValue(0, col)
[dadf255]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))
[08dc9e87]676                            if index -1 >= 0:
[dadf255]677                                new_row, _ = temp_list[index-1]
[4e0dfe4]678                                if not new_row==None and new_row!=' ' :
679                                    label += create_label(col_name, None, int(new_row) +1)
680                                else:
681                                    label += "]"
[dadf255]682                                label += ","
683                            if index + 1 < len(temp_list):
684                                new_row, _ = temp_list[index + 1]
[4e0dfe4]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)
[dadf255]692                    index += 1
[4e0dfe4]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
[7ad194fa]702   
[9c8f3ad]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()
[24adb89]710       
[71fa9028]711    def set_data(self, data_inputs, data_outputs, details="", file_name=None):
[8523a1f2]712        if data_outputs is None or data_outputs == {}:
[24adb89]713            return
[98fdccd]714        inputs, outputs = self.get_odered_results(data_inputs, data_outputs)
[f4b37d1]715        for pos in range(self.GetPageCount()):
716            grid = self.GetPage(pos)
717            if grid.data is None:
718                #Found empty page
[98fdccd]719                grid.set_data(data_inputs=inputs, 
720                              data_outputs=outputs,
[71fa9028]721                              details=details,
722                              file_name=file_name) 
[f4b37d1]723                self.SetSelection(pos) 
724                return
725               
726        grid, pos = self.add_empty_page()
[98fdccd]727        grid.set_data(data_inputs=inputs, 
728                      data_outputs=outputs,
[a84ca2a]729                      file_name=file_name,
730                      details=details)
[98fdccd]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
[e25d908]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
[98fdccd]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
[f4b37d1]760   
[9c8f3ad]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       
[24adb89]769class GridPanel(SPanel):
[8523a1f2]770    def __init__(self, parent, data_inputs=None,
771                 data_outputs=None, *args, **kwds):
[24adb89]772        SPanel.__init__(self, parent , *args, **kwds)
[f4b37d1]773       
[24adb89]774        self.vbox = wx.BoxSizer(wx.VERTICAL)
775       
[9680906d]776        self.plotting_sizer = wx.FlexGridSizer(3, 7, 10, 5)
[75790dc]777        self.button_sizer = wx.BoxSizer(wx.HORIZONTAL)
[24adb89]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),
[75790dc]781                           (self.plotting_sizer),
[3e1177d]782                           (self.button_sizer, 0, wx.BOTTOM, 10)])
[24adb89]783        self.parent = parent
[8523a1f2]784        self._data_inputs = data_inputs
785        self._data_outputs = data_outputs
[24adb89]786        self.x = []
787        self.= []
[9130227]788        self.dy  = []
[24adb89]789        self.x_axis_label = None
790        self.y_axis_label = None
[9130227]791        self.dy_axis_label = None
[904830e]792        self.x_axis_title = None
793        self.y_axis_title = None
[24adb89]794        self.x_axis_unit = None
795        self.y_axis_unit = None
[75790dc]796        self.view_button = None
[24adb89]797        self.plot_button = None
[904830e]798        self.notebook = None
[23477c6]799       
[24adb89]800        self.layout_grid()
801        self.layout_plotting_area()
802        self.SetSizer(self.vbox)
[98fdccd]803
[904830e]804    def set_xaxis(self, label="", x=None):
805        """
806        """
[24adb89]807        if x is None:
808            x = []
809        self.x = x
[904830e]810        self.x_axis_label.SetValue("%s[:]" % str(label))
811        self.x_axis_title.SetValue(str(label))
[24adb89]812       
[904830e]813    def set_yaxis(self, label="", y=None):
814        """
815        """
[24adb89]816        if y is None:
817            y = []
818        self.y = y
[904830e]819        self.y_axis_label.SetValue("%s[:]" % str(label))
820        self.y_axis_title.SetValue(str(label))
[24adb89]821       
[9130227]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               
[904830e]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:
[c911f34]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:
[dadf255]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, 
[75790dc]850                             StatusEvent(status=msg, info="error")) 
[c911f34]851            else:
852                axis.append(None) 
[904830e]853        return axis
854   
[75790dc]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)
[9400de6]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
[23155ba]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
[75790dc]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]
[344c5d8]881                if row > len(values) or row < 1:
[9400de6]882                    msg = "Invalid cell was chosen." 
883                    wx.PostEvent(self.parent.parent, StatusEvent(status=msg, 
884                                                                info="error"))
[1ec979d]885                    time.sleep(0.5)
[9400de6]886                    continue
[344c5d8]887                else:
888                     value = values[row -1]
[75790dc]889                if issubclass(value.__class__, BatchCell):
[fe98127]890                    if value.object is None or len(value.object) == 0:
891                        msg = "Row %s , " % str(row)
[c27a111]892                        msg += "Column %s is NOT " % str(label)
893                        msg += "the results of fits to view..."
[fe98127]894                        #raise ValueError, msg
895                        wx.PostEvent(self.parent.parent, StatusEvent(status=msg, 
896                                                                info="error")) 
897                        return
[75790dc]898                    for new_plot in value.object:
[fe98127]899                        if new_plot is None or \
[1f83477]900                         not issubclass(new_plot.__class__, 
[fe98127]901                                        plottables.Plottable):
[75790dc]902                            msg = "Row %s , " % str(row)
[c27a111]903                            msg += "Column %s is NOT " % str(label)
904                            msg += "the results of fits to view..."
[75790dc]905                            #raise ValueError, msg
906                            wx.PostEvent(self.parent.parent, 
907                                 StatusEvent(status=msg, info="error")) 
[1ec979d]908                            time.sleep(0.5)
[7d47789]909                            continue
[63f4b8e]910                        #new_plot.name =  title + ': ' + new_plot.title
[75790dc]911                        if issubclass(new_plot.__class__, Data1D):
[23477c6]912                            if label in grid.list_plot_panels.keys():
913                                group_id = grid.list_plot_panels[label]
[fd51a7c]914                            else:
[5d192cd]915                                group_id = str(new_plot.group_id) + str(grid.uid)
[23477c6]916                                grid.list_plot_panels[label] = group_id
[fd51a7c]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)
[75790dc]920                        else:
[18a6556]921                            if label.lower() in ["data", "chi2"]:
[75790dc]922                                if len(grid.selected_cells) != 1:
[b18cf3d]923                                    msg = "2D View: Please select one data set"
[4e0dfe4]924                                    msg += " at a time for View Fit Results."
[75790dc]925                                    wx.PostEvent(self.parent.parent, 
926                                                 StatusEvent(status=msg,
[1ec979d]927                                                              info="error"))
928                                    time.sleep(0.5) 
[7d47789]929                                    continue 
[23477c6]930                        """
[75790dc]931                        wx.PostEvent(self.parent.parent,
[fd51a7c]932                                     NewPlotEvent(action="clear",
933                                                  group_id=str(group_id),
[23477c6]934                                                  title=title))
935                        """ 
[fd51a7c]936                        wx.PostEvent(self.parent.parent, 
[75790dc]937                                     NewPlotEvent(plot=new_plot, 
[1ec979d]938                                                group_id=str(new_plot.group_id),
939                                                title=title)) 
[4e0dfe4]940                        msg = "Plotting the View Fit Results  completed!"
[c27a111]941                        wx.PostEvent( self.parent.parent, 
942                                      StatusEvent(status=msg)) 
[75790dc]943                else:
944                   
945                    msg = "Row %s , " % str(row)
[c27a111]946                    msg += "Column %s is NOT " % str(label)
947                    msg += "the results of fits to view..."
[75790dc]948                    #raise ValueError, msg
949                    wx.PostEvent(self.parent.parent, 
950                         StatusEvent(status=msg, info="error")) 
[1ec979d]951                    time.sleep(0.5)
[665fd06]952                    continue
[75790dc]953   
954       
955     
956   
[24adb89]957    def on_plot(self, event):
958        """
[904830e]959        Evaluate the contains of textcrtl and plot result
[24adb89]960        """ 
[904830e]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()
[08dc9e87]966        #evaluate x
[904830e]967        sentence = self.x_axis_label.GetValue()
[1c86a37]968        try:
969            if sentence.strip() == "":
[08dc9e87]970                msg = "Select column values for x axis"
[1c86a37]971                raise ValueError, msg
972        except:
973             wx.PostEvent(self.parent.parent, 
974                             StatusEvent(status=msg, info="error")) 
975             return
[08dc9e87]976
[904830e]977        dict = parse_string(sentence, column_names.keys())
[9130227]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
[904830e]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())
[9130227]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):
[08dc9e87]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
[9130227]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
[904830e]1029        #plotting
[9130227]1030        new_plot = Data1D(x=x, y=y, dy=dy)
[24adb89]1031        new_plot.id =  wx.NewId()
1032        new_plot.group_id = wx.NewId()
[904830e]1033        title = "%s vs %s" % (self.y_axis_title.GetValue(), 
1034                              self.x_axis_title.GetValue())
[1ec979d]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())
[904830e]1039        try:
1040            title = self.notebook.GetPageText(pos)
[dadf255]1041            new_plot.name = title
[1c86a37]1042            new_plot.xtransform = "x"
1043            new_plot.ytransform  = "y" 
[904830e]1044            wx.PostEvent(self.parent.parent, 
[1ec979d]1045                        NewPlotEvent(plot=new_plot, 
[c27a111]1046                        group_id=str(new_plot.group_id), title =title)) 
1047            msg = "Plotting completed!"
1048            wx.PostEvent( self.parent.parent, 
1049                                      StatusEvent(status=msg))   
[904830e]1050        except:
[dadf255]1051             wx.PostEvent(self.parent.parent, 
[75790dc]1052                             StatusEvent(status=msg, info="error")) 
[9130227]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           
[24adb89]1067    def layout_grid(self):
1068        """
1069        Draw the area related to the grid
1070        """
[904830e]1071        self.notebook = Notebook(parent=self)
[8523a1f2]1072        self.notebook.set_data(self._data_inputs, self._data_outputs)
[904830e]1073        self.grid_sizer.Add(self.notebook, 1, wx.EXPAND, 0)
[24adb89]1074       
1075    def layout_plotting_area(self):
1076        """
1077        Draw area containing options to plot
1078        """
[3e1177d]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)
[904830e]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))
[9130227]1088        self.dy_axis_label = wx.TextCtrl(self, -1, size=(200, -1))
[9680906d]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())
[9130227]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())
[24adb89]1098        self.x_axis_unit = wx.TextCtrl(self, -1)
1099        self.y_axis_unit = wx.TextCtrl(self, -1)
[4e0dfe4]1100        self.view_button = wx.Button(self, -1, "View Fits")
[7d47789]1101        view_tip = "Highlight the data set or the Chi2 column first."
[b18cf3d]1102        self.view_button.SetToolTipString(view_tip)
[75790dc]1103        wx.EVT_BUTTON(self, self.view_button.GetId(), self.on_view)
[24adb89]1104        self.plot_button = wx.Button(self, -1, "Plot")
[7d47789]1105        plot_tip = "Highlight a column for each axis and \n"
1106        plot_tip += "click the Add buttons first."
[3e1177d]1107       
[b18cf3d]1108        self.plot_button.SetToolTipString(plot_tip)
[3e1177d]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)])
[75790dc]1115       
[24adb89]1116        wx.EVT_BUTTON(self, self.plot_button.GetId(), self.on_plot)
[9680906d]1117        self.plotting_sizer.AddMany([
[9bfa73f]1118                    (wx.StaticText(self, -1, 
1119                                   "X-axis Label\nSelection Range"), 1,
[904830e]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),
[9bfa73f]1123                    (wx.StaticText(self, -1, "X-axis Label"), 1, 
[904830e]1124                     wx.TOP|wx.BOTTOM|wx.LEFT, 10),
1125                    (self.x_axis_title, 1, wx.TOP|wx.BOTTOM, 10),
[7124300]1126                    (wx.StaticText(self, -1 , "X-axis Unit"), 1, 
[904830e]1127                     wx.TOP|wx.BOTTOM, 10),
1128                    (self.x_axis_unit, 1, wx.TOP|wx.BOTTOM, 10),
[9bfa73f]1129                    (wx.StaticText(self, -1, 
1130                                   "Y-axis Label\nSelection Range"), 1, 
[904830e]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),
[9bfa73f]1134                    (wx.StaticText(self, -1, "Y-axis Label"), 1, 
[904830e]1135                     wx.BOTTOM|wx.LEFT, 10),
1136                    (self.y_axis_title,  wx.BOTTOM, 10),
[9bfa73f]1137                    (wx.StaticText(self, -1 , "Y-axis Unit"), 1, wx.BOTTOM, 10),
[904830e]1138                    (self.y_axis_unit, 1, wx.BOTTOM, 10),
[9130227]1139                    (wx.StaticText(self, -1, 
[3553ad2]1140                                   "dY-Bar (Optional)\nSelection Range"), 
1141                                   1, wx.BOTTOM|wx.LEFT, 10),
[9130227]1142                    (self.dy_axis_label, wx.BOTTOM, 10),
1143                    (self.dy_axis_add, 1, wx.BOTTOM|wx.RIGHT, 10),
[9680906d]1144                      (-1, -1),
1145                      (-1, -1),
1146                      (-1, -1),
1147                      (-1, -1),
1148                      (-1, -1),
1149                      (-1, -1),
[75790dc]1150                      (-1, 1)])
[24adb89]1151   
[9680906d]1152    def on_edit_axis(self, event):
1153        """
1154        Get the selected column on  the visible grid and set values for axis
1155        """
[08dc9e87]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 
[904830e]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)
[9130227]1171        elif tcrtl == self.dy_axis_add:
1172            self.edit_axis_helper(self.dy_axis_label, None,
1173                                   label, None)
[904830e]1174           
[7ad194fa]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
[24adb89]1180       
[7ad194fa]1181        """
[904830e]1182        if self.notebook is not None:
1183            return self.notebook.create_axis_label(cell_list)
[7ad194fa]1184   
[904830e]1185    def edit_axis_helper(self, tcrtl_label, tcrtl_title, label, title):
[9680906d]1186        """
[904830e]1187        get controls to modify
[9680906d]1188        """
[9130227]1189        if label != None:
1190            tcrtl_label.SetValue(str(label))
1191        if title != None:
1192            tcrtl_title.SetValue(str(title))
[904830e]1193       
[24adb89]1194    def add_column(self):
[9c8f3ad]1195        """
1196        """
[904830e]1197        if self.notebook is not None:
1198            self.notebook.add_column()
[24adb89]1199       
[9c8f3ad]1200    def on_remove_column(self):
1201        """
1202        """
[904830e]1203        if self.notebook is not None:
1204            self.notebook.on_remove_column()
[9c8f3ad]1205       
[24adb89]1206       
1207class GridFrame(wx.Frame):
[8523a1f2]1208    def __init__(self, parent=None, data_inputs=None, data_outputs=None, id=-1, 
[cf0eb8e]1209                 title="Batch Window", size=(800, 500)):
[24adb89]1210        wx.Frame.__init__(self, parent=parent, id=id, title=title, size=size)
1211        self.parent = parent
[8523a1f2]1212        self.panel = GridPanel(self, data_inputs, data_outputs)
[24adb89]1213        menubar = wx.MenuBar()
1214        self.SetMenuBar(menubar)
[71fa9028]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")
[cb26857]1245        self.Bind(wx.EVT_CLOSE, self.on_close)
[71fa9028]1246    def GetLabelText(self, id):
[656d65d]1247        """
1248        """
[71fa9028]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):
[cb26857]1255        """
1256        """
[71fa9028]1257        pos = self.panel.notebook.GetSelection()
1258        grid = self.panel.notebook.GetPage(pos)
1259        grid.on_remove_column(event=None)
[cb26857]1260       
[71fa9028]1261    def on_menu_open(self, event):
[9c8f3ad]1262        """
[71fa9028]1263       
[9c8f3ad]1264        """
[71fa9028]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)
[a5e749f]1274            if len(col_list) == 0 or len(col_list) > 1:
[71fa9028]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()
[9c8f3ad]1292       
[71fa9028]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)
[7b48b08]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
[71fa9028]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):
[656d65d]1327        """
[71fa9028]1328        Open file containg batch result
[656d65d]1329        """
[71fa9028]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()
[7b48b08]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
[71fa9028]1349            self.parent.open_with_externalapp(data=data,
[a5e749f]1350                                              file_name=grid.file_name, 
1351                                              details=grid.details)
[71fa9028]1352           
1353    def on_close(self, event):
1354        """
1355        """
1356        self.Hide()
[656d65d]1357       
[71fa9028]1358   
[656d65d]1359    def on_append_column(self, event):
[cb26857]1360        """
[9c8f3ad]1361        Append a new column to the grid
[cb26857]1362        """
[24adb89]1363        self.panel.add_column()
[cb26857]1364       
[71fa9028]1365    def set_data(self, data_inputs, data_outputs, details="", file_name=None):
[cb26857]1366        """
1367        """
[a84ca2a]1368       
1369        self.panel.notebook.set_data(data_inputs=data_inputs, 
[71fa9028]1370                            file_name=file_name,
1371                            details=details,
1372                            data_outputs=data_outputs)
[24adb89]1373     
1374     
[83eb1b52]1375class BatchOutputFrame(wx.Frame):
[73197d0]1376    """
1377    Allow to select where the result of batch will be displayed or stored
1378    """
[8523a1f2]1379    def __init__(self, parent, data_inputs, data_outputs, file_name="",
[850525c]1380                 details="", *args, **kwds):
[73197d0]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        """
[850525c]1386        #kwds['style'] = wx.CAPTION|wx.SYSTEM_MENU
[83eb1b52]1387        wx.Frame.__init__(self, parent, *args, **kwds)
[73197d0]1388        self.parent = parent
[83eb1b52]1389        self.panel = wx.Panel(self)
[850525c]1390        self.file_name = file_name
1391        self.details = details
[8523a1f2]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)
[73197d0]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()
[8523a1f2]1403   
[73197d0]1404    def _do_layout(self):
1405        """
1406        Draw the content of the current dialog window
1407        """
1408        vbox = wx.BoxSizer(wx.VERTICAL)
[83eb1b52]1409        box_description = wx.StaticBox(self.panel, -1, str("Batch Outputs"))
[73197d0]1410        hint_sizer = wx.StaticBoxSizer(box_description, wx.VERTICAL)
[83eb1b52]1411        selection_sizer = wx.GridBagSizer(5, 5)
[73197d0]1412        button_sizer = wx.BoxSizer(wx.HORIZONTAL)
[caf3a08f]1413        text = "Open with %s" % self.parent.application_name
[83eb1b52]1414        self.local_app_selected = wx.RadioButton(self.panel, -1, text,
[73197d0]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"
[83eb1b52]1419        self.external_app_selected  = wx.RadioButton(self.panel, -1, text)
[73197d0]1420        self.Bind(wx.EVT_RADIOBUTTON, self.onselect,
1421                    id=self.external_app_selected.GetId())
[caf3a08f]1422        text = "Save to File"
[83eb1b52]1423        self.save_to_file = wx.CheckBox(self.panel, -1, text)
[73197d0]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)
[83eb1b52]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()
[73197d0]1436        hint = ""
[83eb1b52]1437        hint_sizer.Add(wx.StaticText(self.panel, -1, hint))
[73197d0]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)
[caf3a08f]1452
1453        button_sizer.Add(button_close, 0,
1454                        wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
[83eb1b52]1455        button_sizer.Add(button_apply, 0,
[73197d0]1456                                wx.LEFT|wx.RIGHT|wx.ADJUST_MINSIZE, 10)
[a5e749f]1457        vbox.Add(hint_sizer, 0, wx.EXPAND|wx.ALL, 10)
[83eb1b52]1458        vbox.Add(wx.StaticLine(self.panel, -1),  0, wx.EXPAND, 0)
[a5e749f]1459        vbox.Add(button_sizer, 0, wx.TOP|wx.BOTTOM, 10)
[73197d0]1460        self.SetSizer(vbox)
1461       
[83eb1b52]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:
[8523a1f2]1467            self.parent.open_with_localapp(data_inputs=self.data_inputs,
[a5e749f]1468                                           data_outputs=self.data_outputs)
[83eb1b52]1469        elif self.flag == 2:
1470            self.parent.open_with_externalapp(data=self.data, 
[a5e749f]1471                                              file_name=self.file_name,
1472                                              details=self.details)
[83eb1b52]1473    def on_close(self, event):
1474        """
1475        close the Window
1476        """
1477        self.Close()
1478       
[73197d0]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():
[850525c]1486            reader, ext = os.path.splitext(self.file_name)
1487            path = None
1488            location = os.getcwd()
1489            if self.parent is not None: 
[83eb1b52]1490                location = os.path.dirname(self.file_name)
[850525c]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:
[83eb1b52]1499                        self.parent.write_batch_tofile(data=self.data, 
[a5e749f]1500                                                       file_name=path,
1501                                                       details=self.details)
[850525c]1502        if self.local_app_selected.GetValue():
[73197d0]1503            self.flag = 1
1504        else:
1505            self.flag = 2
1506        return self.flag
1507   
1508 
1509       
[24adb89]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]
[656d65d]1519       
1520        data_input =  copy.deepcopy(data)   
[a5e749f]1521        data_input["index5"] = [10, 20, 40, 50]
[656d65d]1522        frame = GridFrame(data_outputs=data, data_inputs=data_input)
[24adb89]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.