Index: test/guiframe/.current_version
===================================================================
--- test/guiframe/.current_version (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,1 +1,0 @@
-0.2.3
Index: test/guiframe/.project
===================================================================
--- test/guiframe/.project (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,17 +1,0 @@
-
-
- guiframe
-
-
-
-
-
- org.python.pydev.PyDevBuilder
-
-
-
-
-
- org.python.pydev.pythonNature
-
-
Index: test/guiframe/.pydevproject
===================================================================
--- test/guiframe/.pydevproject (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,9 +1,0 @@
-
-
-
-
-
-/guiframe/src
-
-python 2.5
-
Index: test/guiframe/MANIFEST.IN
===================================================================
--- test/guiframe/MANIFEST.IN (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,4 +1,0 @@
-graft media
-graft images
-
-
Index: test/guiframe/README.txt
===================================================================
--- test/guiframe/README.txt (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,23 +1,0 @@
-################################################################################
-#This software was developed by the University of Tennessee as part of the
-#Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
-#project funded by the US National Science Foundation.
-#
-#See the license text in license.txt
-#
-#copyright 2008, University of Tennessee
-################################################################################
-
-
-How-to build an application using guiframe:
-
-1- Write a main application script along the lines of dummyapp.py
-2- Write a config script along the lines of config.py, and
- name it local_config.py
-3- Write your plug-ins and place them in a directory called "perspectives".
- - Look at local_perspectives/plotting for an example of a plug-in.
- - A plug-in should define a class named Plugin,
- inheriting from PluginBase in plugin_base.py
-
-4- each panel used in guiframe must inheritation from PanelBase in panel_base.py
-
Index: test/guiframe/__init__.py
===================================================================
--- test/guiframe/__init__.py (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,72 +1,0 @@
-
-
-import os
-from distutils.filelist import findall
-
-def get_data_path(media):
- """
- """
- # Check for data path in the package
- path = os.path.join(os.path.dirname(__file__), media)
- if os.path.isdir(path):
- return path
-
- # Check for data path next to exe/zip file.
- # If we are inside a py2exe zip file, we need to go up
- # to get to the directory containing
- # the media for this module
- path = os.path.dirname(__file__)
- #Look for maximum n_dir up of the current dir to find media
- n_dir = 12
- for i in range(n_dir):
- path, _ = os.path.split(path)
- media_path = os.path.join(path, media)
- if os.path.isdir(media_path):
- module_media_path = os.path.join(media_path, 'icons')
- if os.path.isdir(module_media_path):
- return module_media_path
- return media_path
-
- raise RuntimeError('Could not find guiframe images files')
-
-def get_media_path(media):
- """
- """
- # Check for data path in the package
- path = os.path.join(os.path.dirname(__file__), media)
- if os.path.isdir(path):
- return path
-
- # Check for data path next to exe/zip file.
- # If we are inside a py2exe zip file, we need to go up
- # to get to the directory containing
- # the media for this module
- path = os.path.dirname(__file__)
- #Look for maximum n_dir up of the current dir to find media
- n_dir = 12
- for i in range(n_dir):
- path, _ = os.path.split(path)
- media_path = os.path.join(path, media)
- if os.path.isdir(media_path):
- module_media_path = os.path.join(media_path, 'guiframe_media')
- if os.path.isdir(module_media_path):
- return module_media_path
- return media_path
- raise RuntimeError('Could not find guiframe media files')
-
-def data_files():
- """
- Return the data files associated with guiframe images .
-
- The format is a list of (directory, [files...]) pairs which can be
- used directly in setup(...,data_files=...) for setup.py.
-
- """
- data_files = []
- path = get_data_path(media="images")
- for f in findall(path):
- data_files.append(('images/icons', [f]))
- path = get_media_path(media="media")
- for f in findall(path):
- data_files.append(('media/guiframe_media', [f]))
- return data_files
Index: test/guiframe/aboutbox.py
===================================================================
--- test/guiframe/aboutbox.py (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,274 +1,0 @@
-#!/usr/bin/env python
-########################################################################
-#
-# PDFgui by DANSE Diffraction group
-# Simon J. L. Billinge
-# (c) 2006 trustees of the Michigan State University.
-# All rights reserved.
-#
-# File coded by: Dmitriy Bryndin
-#
-# See AUTHORS.txt for a list of people who contributed.
-# See LICENSE.txt for license information.
-#
-# Modified by U. Tennessee for DANSE/SANS
-########################################################################
-
-# version
-__id__ = "$Id: aboutdialog.py 1193 2007-05-03 17:29:59Z dmitriy $"
-__revision__ = "$Revision: 1193 $"
-
-import wx
-import wx.lib.hyperlink
-import random
-import os.path
-import os
-try:
- # Try to find a local config
- import imp
- path = os.getcwd()
- if(os.path.isfile("%s/%s.py" % (path, 'local_config'))) or \
- (os.path.isfile("%s/%s.pyc" % (path, 'local_config'))):
- fObj, path, descr = imp.find_module('local_config', [path])
- config = imp.load_module('local_config', fObj, path, descr)
- else:
- # Try simply importing local_config
- import local_config as config
-except:
- # Didn't find local config, load the default
- import config
-
-def launchBrowser(url):
- """
- Launches browser and opens specified url
-
- In some cases may require BROWSER environment variable to be set up.
-
- :param url: URL to open
-
- """
- import webbrowser
- webbrowser.open(url)
-
-
-class DialogAbout(wx.Dialog):
- """
- "About" Dialog
-
- Shows product name, current version, authors, and link to the product page.
- Current version is taken from version.py
-
- """
-
- def __init__(self, *args, **kwds):
-
- # begin wxGlade: DialogAbout.__init__
- kwds["style"] = wx.DEFAULT_DIALOG_STYLE
- wx.Dialog.__init__(self, *args, **kwds)
-
- file_dir = os.path.dirname(__file__)
-
- # Mac doesn't display images with transparent background so well,
- # keep it for Windows
- image = file_dir + "/images/angles_flat.png"
-
- if os.path.isfile(config._corner_image):
- image = config._corner_image
-
- if os.name == 'nt':
- self.bitmap_logo = wx.StaticBitmap(self, -1, wx.Bitmap(image))
- else:
- self.bitmap_logo = wx.StaticBitmap(self, -1, wx.Bitmap(image))
-
- self.label_title = wx.StaticText(self, -1, config.__appname__)
- self.label_version = wx.StaticText(self, -1, "")
- self.label_build = wx.StaticText(self, -1, "Build:")
- self.label_svnrevision = wx.StaticText(self, -1, "")
- self.label_copyright = wx.StaticText(self, -1, config._copyright)
- self.label_author = wx.StaticText(self, -1, "authors")
- self.hyperlink = wx.lib.hyperlink.HyperLinkCtrl(self, -1,
- config._homepage,
- URL=config._homepage)
- #self.hyperlink_license = wx.lib.hyperlink.HyperLinkCtrl(self, -1,
- #"Comments? Bugs? Requests?", URL=config._paper)
- self.hyperlink_license = wx.StaticText(self, -1,
- "Comments? Bugs? Requests?")
- self.hyperlink_paper = wx.lib.hyperlink.HyperLinkCtrl(self, -1,
- "Send us a ticket",
- URL=config._license)
- self.hyperlink_download = wx.lib.hyperlink.HyperLinkCtrl(self, -1,
- "Get the latest version",
- URL=config._download)
- self.static_line_1 = wx.StaticLine(self, -1)
- self.label_acknowledgement = wx.StaticText(self, -1,
- config._acknowledgement)
- self.static_line_2 = wx.StaticLine(self, -1)
- self.bitmap_button_nsf = wx.BitmapButton(self, -1,
- wx.NullBitmap)
- self.bitmap_button_danse = wx.BitmapButton(self, -1, wx.NullBitmap)
- self.bitmap_button_msu = wx.BitmapButton(self, -1, wx.NullBitmap)
- self.static_line_3 = wx.StaticLine(self, -1)
- self.button_OK = wx.Button(self, wx.ID_OK, "OK")
-
- self.__set_properties()
- self.__do_layout()
-
- self.Bind(wx.EVT_BUTTON, self.onNsfLogo, self.bitmap_button_nsf)
- self.Bind(wx.EVT_BUTTON, self.onDanseLogo, self.bitmap_button_danse)
- self.Bind(wx.EVT_BUTTON, self.onUTLogo, self.bitmap_button_msu)
- # end wxGlade
- # fill in acknowledgements
- #self.text_ctrl_acknowledgement.SetValue(__acknowledgement__)
- # randomly shuffle authors' names
- random.shuffle(config._authors)
- strLabel = ", ".join(config._authors)
-
- # display version and svn revison numbers
- verwords = config.__version__.split('.')
- version = '.'.join(verwords[:-1])
- revision = verwords[-1]
-
- self.label_author.SetLabel(strLabel)
- self.label_version.SetLabel(config.__version__)#(version)
- self.label_svnrevision.SetLabel(config.__version__)
-
- # set bitmaps for logo buttons
- image = file_dir + "/images/nsf_logo.png"
- if os.path.isfile(config._nsf_logo):
- image = config._nsf_logo
- logo = wx.Bitmap(image)
- self.bitmap_button_nsf.SetBitmapLabel(logo)
-
- image = file_dir + "/images/danse_logo.png"
- if os.path.isfile(config._danse_logo):
- image = config._danse_logo
- logo = wx.Bitmap(image)
- self.bitmap_button_danse.SetBitmapLabel(logo)
-
- image = file_dir + "/images/utlogo.gif"
- if os.path.isfile(config._inst_logo):
- image = config._inst_logo
- logo = wx.Bitmap(image)
- self.bitmap_button_msu.SetBitmapLabel(logo)
-
- # resize dialog window to fit version number nicely
- if wx.VERSION >= (2, 7, 2, 0):
- size = [self.GetEffectiveMinSize()[0], self.GetSize()[1]]
- else:
- size = [self.GetBestFittingSize()[0], self.GetSize()[1]]
- self.Fit()
-
- def __set_properties(self):
- """
- """
- # begin wxGlade: DialogAbout.__set_properties
- self.SetTitle("About")
- self.SetSize((600, 595))
- self.label_title.SetFont(wx.Font(26, wx.DEFAULT, wx.NORMAL,
- wx.BOLD, 0, ""))
- self.label_version.SetFont(wx.Font(26, wx.DEFAULT, wx.NORMAL,
- wx.NORMAL, 0, ""))
- self.hyperlink_paper.Enable(True)
- self.bitmap_button_nsf.SetSize(self.bitmap_button_nsf.GetBestSize())
- self.bitmap_button_danse.SetSize(self.bitmap_button_danse.GetBestSize())
- self.bitmap_button_msu.SetSize(self.bitmap_button_msu.GetBestSize())
- # end wxGlade
-
- def __do_layout(self):
- """
- """
- # begin wxGlade: DialogAbout.__do_layout
- sizer_main = wx.BoxSizer(wx.VERTICAL)
- sizer_button = wx.BoxSizer(wx.HORIZONTAL)
- sizer_logos = wx.BoxSizer(wx.HORIZONTAL)
- sizer_header = wx.BoxSizer(wx.HORIZONTAL)
- sizer_titles = wx.BoxSizer(wx.VERTICAL)
- sizer_build = wx.BoxSizer(wx.HORIZONTAL)
- sizer_title = wx.BoxSizer(wx.HORIZONTAL)
- sizer_header.Add(self.bitmap_logo, 0, wx.EXPAND, 0)
- sizer_title.Add(self.label_title, 0,
- wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 10)
- sizer_title.Add((20, 20), 0, wx.EXPAND|wx.ADJUST_MINSIZE, 0)
- sizer_title.Add(self.label_version, 0,
- wx.RIGHT|wx.ALIGN_BOTTOM|wx.ADJUST_MINSIZE, 10)
- sizer_titles.Add(sizer_title, 0, wx.EXPAND, 0)
- sizer_build.Add(self.label_build, 0,
- wx.LEFT|wx.RIGHT|wx.ADJUST_MINSIZE, 10)
- sizer_build.Add(self.label_svnrevision, 0, wx.ADJUST_MINSIZE, 0)
- sizer_titles.Add(sizer_build, 0, wx.TOP|wx.EXPAND, 5)
- sizer_titles.Add(self.label_copyright, 0,
- wx.LEFT|wx.RIGHT|wx.TOP|wx.ADJUST_MINSIZE, 10)
- sizer_titles.Add(self.label_author, 0,
- wx.LEFT|wx.RIGHT|wx.ADJUST_MINSIZE, 10)
- sizer_titles.Add(self.hyperlink, 0, wx.LEFT|wx.RIGHT, 10)
- sizer_titles.Add((20, 20), 0, wx.ADJUST_MINSIZE, 0)
- sizer_titles.Add(self.hyperlink_license, 0, wx.LEFT|wx.RIGHT, 10)
- sizer_titles.Add(self.hyperlink_paper, 0, wx.LEFT|wx.RIGHT, 10)
- sizer_titles.Add((20, 20), 0, wx.ADJUST_MINSIZE, 0)
- sizer_titles.Add(self.hyperlink_download, 0, wx.LEFT|wx.RIGHT, 10)
- sizer_header.Add(sizer_titles, 0, wx.EXPAND, 0)
- sizer_main.Add(sizer_header, 0, wx.BOTTOM|wx.EXPAND, 3)
- sizer_main.Add(self.static_line_1, 0, wx.EXPAND, 0)
- sizer_main.Add(self.label_acknowledgement, 0,
- wx.LEFT|wx.TOP|wx.BOTTOM|wx.ADJUST_MINSIZE, 7)
- sizer_main.Add(self.static_line_2, 0, wx.EXPAND, 0)
- sizer_logos.Add(self.bitmap_button_nsf, 0, wx.LEFT|wx.ADJUST_MINSIZE, 2)
- sizer_logos.Add(self.bitmap_button_danse, 0,
- wx.LEFT|wx.ADJUST_MINSIZE, 2)
- sizer_logos.Add(self.bitmap_button_msu, 0, wx.LEFT|wx.ADJUST_MINSIZE, 2)
- sizer_logos.Add((50, 50), 0, wx.ADJUST_MINSIZE, 0)
- sizer_main.Add(sizer_logos, 0, wx.EXPAND, 0)
- sizer_main.Add(self.static_line_3, 0, wx.EXPAND, 0)
- sizer_button.Add((20, 20), 1, wx.EXPAND|wx.ADJUST_MINSIZE, 0)
- sizer_button.Add(self.button_OK, 0, wx.RIGHT|wx.ADJUST_MINSIZE, 10)
- sizer_main.Add(sizer_button, 0, wx.EXPAND, 0)
- self.SetAutoLayout(True)
- self.SetSizer(sizer_main)
- self.Layout()
- self.Centre()
- # end wxGlade
-
- def onNsfLogo(self, event):
- """
- """
- # wxGlade: DialogAbout.
- launchBrowser(config._nsf_url)
- event.Skip()
-
- def onDanseLogo(self, event):
- """
- """
- # wxGlade: DialogAbout.
- launchBrowser(config._danse_url)
- event.Skip()
-
- def onUTLogo(self, event):
- """
- """
- # wxGlade: DialogAbout.
- launchBrowser(config._inst_url)
- event.Skip()
-
-# end of class DialogAbout
-
-##### testing code ############################################################
-class MyApp(wx.App):
- """
- """
- def OnInit(self):
- """
- """
- wx.InitAllImageHandlers()
- dialog = DialogAbout(None, -1, "")
- self.SetTopWindow(dialog)
- dialog.ShowModal()
- dialog.Destroy()
- return 1
-
-# end of class MyApp
-
-if __name__ == "__main__":
- app = MyApp(0)
- app.MainLoop()
-
-##### end of testing code #####################################################
Index: test/guiframe/config.py
===================================================================
--- test/guiframe/config.py (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,92 +1,0 @@
-"""
-Application settings
-"""
-import os
-import time
-from sans.guiframe.gui_style import GUIFRAME
-# Version of the application
-__appname__ = "DummyView"
-__version__ = '0.1.0'
-__download_page__ = 'http://danse.chem.utk.edu'
-
-
-# Debug message flag
-__EVT_DEBUG__ = True
-
-# Flag for automated testing
-__TEST__ = False
-
-# Debug message should be written to a file?
-__EVT_DEBUG_2_FILE__ = False
-__EVT_DEBUG_FILENAME__ = "debug.log"
-
-# About box info
-_do_aboutbox = True
-_acknowledgement = \
-'''This software was developed by the University of Tennessee as part of the
-Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
-project funded by the US National Science Foundation.
-
-'''
-_homepage = "http://danse.chem.utk.edu"
-_download = "http://danse.chem.utk.edu/sansview.html"
-_authors = []
-_paper = "http://danse.us/trac/sans/newticket"
-_license = "mailto:sansdanse@gmail.com"
-_nsf_logo = "images/nsf_logo.png"
-_danse_logo = "images/danse_logo.png"
-_inst_logo = "images/utlogo.gif"
-_nsf_url = "http://www.nsf.gov"
-_danse_url = "http://www.cacr.caltech.edu/projects/danse/release/index.html"
-_inst_url = "http://www.utk.edu"
-_corner_image = "images/angles_flat.png"
-_welcome_image = "images/SVwelcome.png"
-_copyright = "(c) 2008, University of Tennessee"
-#edit the lists below of file state your plugin can read
-#for sansview this how you can edit these lists
-#PLUGIN_STATE_EXTENSIONS = ['.prv','.fitv', '.inv']
-#APPLICATION_STATE_EXTENSION = '.svs'
-#PLUGINS_WLIST = ['P(r) files (*.prv)|*.prv',
-# 'Fitting files (*.fitv)|*.fitv',
-# 'Invariant files (*.inv)|*.inv']
-#APPLICATION_WLIST = 'SansView files (*.svs)|*.svs'
-APPLICATION_WLIST = ''
-APPLICATION_STATE_EXTENSION = None
-PLUGINS_WLIST = []
-PLUGIN_STATE_EXTENSIONS = []
-SPLASH_SCREEN_PATH = "images/danse_logo.png"
-DEFAULT_STYLE = GUIFRAME.SINGLE_APPLICATION
-SPLASH_SCREEN_WIDTH = 500
-SPLASH_SCREEN_HEIGHT = 300
-SS_MAX_DISPLAY_TIME = 4000 #4 sec
-PLOPANEL_WIDTH = 350
-PLOPANEL_HEIGTH = 350
-GUIFRAME_WIDTH = 1000
-GUIFRAME_HEIGHT = 800
-SetupIconFile_win = os.path.join("images", "ball.ico")
-SetupIconFile_mac = os.path.join("images", "ball.icns")
-DefaultGroupName = "DANSE"
-OutputBaseFilename = "setupGuiFrame"
-DATAPANEL_WIDTH = 235
-DATAPANEL_HEIGHT = 700
-FIXED_PANEL = True
-DATALOADER_SHOW = True
-CLEANUP_PLOT = False
-WELCOME_PANEL_SHOW = False
-#Show or hide toolbar at the start up
-TOOLBAR_SHOW = True
-# set a default perspective
-DEFAULT_PERSPECTIVE = 'None'
-
-import wx.lib.newevent
-(StatusBarEvent, EVT_STATUS) = wx.lib.newevent.NewEvent()
-
-def printEVT(message):
- if __EVT_DEBUG__:
- print "%g: %s" % (time.clock(), message)
-
- if __EVT_DEBUG_2_FILE__:
- out = open(__EVT_DEBUG_FILENAME__, 'a')
- out.write("%10g: %s\n" % (time.clock(), message))
- out.close()
-
Index: test/guiframe/custom_pstats.py
===================================================================
--- test/guiframe/custom_pstats.py (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,118 +1,0 @@
-
-import cProfile, pstats, os
-def func_std_string(func_name): # match what old profile produced
- if func_name[:2] == ('~', 0):
- # special case for built-in functions
- name = func_name[2]
- if name.startswith('<') and name.endswith('>'):
- return '{%s}' % name[1:-1]
- else:
- return name
- else:
- return "%s:%d(%s)" % func_name
-
-def f8(x):
- return "%8.3f" % x
-
-class CustomPstats(pstats.Stats):
- def __init__(self, *args, **kwds):
- pstats.Stats.__init__(self, *args, **kwds)
-
- def write_stats(self, *amount):
- msg = ''
- for filename in self.files:
- msg += str(filename) + '\n'
- #if self.files: msg += str(self.stream) + '\n'
- indent = ' ' * 8
- for func in self.top_level:
- msg += str(indent)+ str(func_get_function_name(func))+"\n"
-
- msg += str(indent) + str(self.total_calls)+ "function calls" + '\n'
- if self.total_calls != self.prim_calls:
- msg += "(%d primitive calls)" % self.prim_calls + '\n'
- msg += "in %.3f CPU seconds" % self.total_tt + '\n'
- #msg += str(self.stream) + '\n'
-
- width = self.max_name_len
- if self.fcn_list:
- list = self.fcn_list[:]
- temp_msg = " Ordered by: " + self.sort_type + '\n'
- else:
- list = self.stats.keys()
- temp_msg = " Random listing order was used\n"
-
- for selection in amount:
- list, temp_msg = self.eval_print_amount(selection, list, temp_msg)
-
- count = len(list)
-
- if not list:
- width, list = 0, list
- else:
- msg += str(temp_msg) + '\n'
- if count < len(self.stats):
- width = 0
- for func in list:
- if len(func_std_string(func)) > width:
- width = len(func_std_string(func))
-
- width, list = width+2, list
- if list:
- msg += ' ncalls tottime percall cumtime percall'
- msg += ' filename:lineno(function)' + "\n"
- for func in list:
- cc, nc, tt, ct, callers = self.stats[func]
- c = str(nc)
- if nc != cc:
- c = c + '/' + str(cc)
- msg += str( c.rjust(9))
- msg += str(f8(tt))
- if nc == 0:
- msg += str(' '*8)
- else:
- msg += str(f8(tt/nc))
- msg += str(f8(ct))
- if cc == 0:
- msg += str( ' '*80)
- else:
- msg += str(f8(ct/cc))
- msg += " " + str(func_std_string(func)) + '\n'
- msg += str(self.stream) + '\n'
- #msg += str(self.stream) + '\n'
- return self, msg
-
-def profile( fn, name='profile.txt',*args, **kw):
- import cProfile, pstats, os
- global call_result
- def call():
- global call_result
- call_result = fn(*args, **kw)
- cProfile.runctx('call()', dict(call=call), {}, 'profile.txt')
- stats = CustomPstats('profile.txt')
- #sort by cumlative time
- stats.sort_stats('time')
- stats.print_stats(50)
- """
- filename = 'profile_cum_' + name
- _, msg = stats.write_stats(50)
- f = file(filename, 'wb')
- f.write(msg)
- f.close()
- #sort by time
- stats.sort_stats('time')
- _, msg = stats.write_stats(50)
- filename = 'profile_time_' + name
- f = file(filename, 'wb')
- f.write(msg)
- f.close()
- # sort by number of calls
- stats.sort_stats('call')
- _, msg = stats.write_stats(50)
- filename = 'profile_call_' + name
- f = file(filename, 'wb')
- f.write(msg)
- f.close()
- os.unlink('profile.txt')
- """
- return call_result
-
Index: test/guiframe/dataFitting.py
===================================================================
--- test/guiframe/dataFitting.py (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,260 +1,0 @@
-"""
-Adapters for fitting module
-"""
-import copy
-import numpy
-import math
-from data_util.uncertainty import Uncertainty
-from danse.common.plottools.plottables import Data1D as PlotData1D
-from danse.common.plottools.plottables import Data2D as PlotData2D
-from danse.common.plottools.plottables import Theory1D as PlotTheory1D
-
-from DataLoader.data_info import Data1D as LoadData1D
-from DataLoader.data_info import Data2D as LoadData2D
-
-
-class Data1D(PlotData1D, LoadData1D):
- """
- """
- def __init__(self, x=None, y=None, dx=None, dy=None):
- """
- """
- if x is None:
- x = []
- if y is None:
- y = []
- PlotData1D.__init__(self, x, y, dx, dy)
- LoadData1D.__init__(self, x, y, dx, dy)
- self.id = None
- self.list_group_id = []
- self.group_id = None
- self.is_data = True
- self.path = None
- self.xtransform = None
- self.ytransform = None
- self.title = ""
- self.scale = None
-
- def copy_from_datainfo(self, data1d):
- """
- copy values of Data1D of type DataLaoder.Data_info
- """
- self.x = copy.deepcopy(data1d.x)
- self.y = copy.deepcopy(data1d.y)
- self.dy = copy.deepcopy(data1d.dy)
-
- if hasattr(data1d, "dx"):
- self.dx = copy.deepcopy(data1d.dx)
- if hasattr(data1d, "dxl"):
- self.dxl = copy.deepcopy(data1d.dxl)
- if hasattr(data1d, "dxw"):
- self.dxw = copy.deepcopy(data1d.dxw)
-
- self.xaxis(data1d._xaxis, data1d._xunit)
- self.yaxis(data1d._yaxis, data1d._yunit)
- self.title = data1d.title
-
- def __str__(self):
- """
- print data
- """
- _str = "%s\n" % LoadData1D.__str__(self)
-
- return _str
-
- def _perform_operation(self, other, operation):
- """
- """
- # First, check the data compatibility
- dy, dy_other = self._validity_check(other)
- result = Data1D(x=[], y=[], dx=None, dy=None)
- result.clone_without_data(clone=self)
- result.copy_from_datainfo(data1d=self)
- for i in range(len(self.x)):
- result.x[i] = self.x[i]
- if self.dx is not None and len(self.x) == len(self.dx):
- result.dx[i] = self.dx[i]
-
- a = Uncertainty(self.y[i], dy[i]**2)
- if isinstance(other, Data1D):
- b = Uncertainty(other.y[i], dy_other[i]**2)
- else:
- b = other
-
- output = operation(a, b)
- result.y[i] = output.x
- if result.dy is None: result.dy = numpy.zeros(len(self.x))
- result.dy[i] = math.sqrt(math.fabs(output.variance))
- return result
-
-
-
-class Theory1D(PlotTheory1D, LoadData1D):
- """
- """
- def __init__(self, x=None, y=None, dy=None):
- """
- """
- if x is None:
- x = []
- if y is None:
- y = []
- PlotTheory1D.__init__(self, x, y, dy)
- LoadData1D.__init__(self, x, y, dy)
- self.id = None
- self.list_group_id = []
- self.group_id = None
- self.is_data = True
- self.path = None
- self.xtransform = None
- self.ytransform = None
- self.title = ""
- self.scale = None
-
- def copy_from_datainfo(self, data1d):
- """
- copy values of Data1D of type DataLaoder.Data_info
- """
- self.x = copy.deepcopy(data1d.x)
- self.y = copy.deepcopy(data1d.y)
- self.dy = copy.deepcopy(data1d.dy)
- if hasattr(data1d, "dx"):
- self.dx = copy.deepcopy(data1d.dx)
- if hasattr(data1d, "dxl"):
- self.dxl = copy.deepcopy(data1d.dxl)
- if hasattr(data1d, "dxw"):
- self.dxw = copy.deepcopy(data1d.dxw)
- self.xaxis(data1d._xaxis, data1d._xunit)
- self.yaxis(data1d._yaxis, data1d._yunit)
- self.title = data1d.title
-
- def __str__(self):
- """
- print data
- """
- _str = "%s\n" % LoadData1D.__str__(self)
-
- return _str
-
- def _perform_operation(self, other, operation):
- """
- """
- # First, check the data compatibility
- dy, dy_other = self._validity_check(other)
- result = Theory1D(x=[], y=[], dy=None)
- result.clone_without_data(clone=self)
- result.copy_from_datainfo(data1d=self)
- for i in range(len(self.x)):
- result.x[i] = self.x[i]
-
- a = Uncertainty(self.y[i], dy[i]**2)
- if isinstance(other, Data1D):
- b = Uncertainty(other.y[i], dy_other[i]**2)
- else:
- b = other
- output = operation(a, b)
- result.y[i] = output.x
- if result.dy is None:
- result.dy = numpy.zeros(len(self.x))
- result.dy[i] = math.sqrt(math.fabs(output.variance))
- return result
-
-
-class Data2D(PlotData2D, LoadData2D):
- """
- """
- def __init__(self, image=None, err_image=None,
- xmin=None, xmax=None, ymin=None, ymax=None,
- zmin=None, zmax=None, qx_data=None, qy_data=None,
- q_data=None, mask=None, dqx_data=None, dqy_data=None):
- """
- """
- PlotData2D.__init__(self, image=image, err_image=err_image,
- xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax,
- zmin=zmin, zmax=zmax, qx_data=qx_data,
- qy_data=qy_data)
-
- LoadData2D.__init__(self, data=image, err_data=err_image,
- qx_data=qx_data, qy_data=qy_data,
- dqx_data=dqx_data, dqy_data=dqy_data,
- q_data=q_data, mask=mask)
- self.id = None
- self.list_group_id = []
- self.group_id = None
- self.is_data = True
- self.path = None
- self.xtransform = None
- self.ytransform = None
- self.title = ""
- self.scale = None
-
- def copy_from_datainfo(self, data2d):
- """
- copy value of Data2D of type DataLoader.data_info
- """
- self.data = copy.deepcopy(data2d.data)
- self.qx_data = copy.deepcopy(data2d.qx_data)
- self.qy_data = copy.deepcopy(data2d.qy_data)
- self.q_data = copy.deepcopy(data2d.q_data)
- self.mask = copy.deepcopy(data2d.mask)
- self.err_data = copy.deepcopy(data2d.err_data)
- self.x_bins = copy.deepcopy(data2d.x_bins)
- self.y_bins = copy.deepcopy(data2d.y_bins)
- if data2d.dqx_data is not None:
- self.dqx_data = copy.deepcopy(data2d.dqx_data)
- if data2d.dqy_data is not None:
- self.dqy_data = copy.deepcopy(data2d.dqy_data)
- self.xmin = data2d.xmin
- self.xmax = data2d.xmax
- self.ymin = data2d.ymin
- self.ymax = data2d.ymax
- if hasattr(data2d, "zmin"):
- self.zmin = data2d.zmin
- if hasattr(data2d, "zmax"):
- self.zmax = data2d.zmax
- self.xaxis(data2d._xaxis, data2d._xunit)
- self.yaxis(data2d._yaxis, data2d._yunit)
- self.title = data2d.title
-
- def __str__(self):
- """
- print data
- """
- _str = "%s\n" % LoadData2D.__str__(self)
- return _str
-
- def _perform_operation(self, other, operation):
- """
- Perform 2D operations between data sets
-
- :param other: other data set
- :param operation: function defining the operation
-
- """
- # First, check the data compatibility
- dy, dy_other = self._validity_check(other)
-
- result = Data2D(image=None, qx_data=None, qy_data=None,
- err_image=None, xmin=None, xmax=None,
- ymin=None, ymax=None, zmin=None, zmax=None)
-
- result.clone_without_data(clone=self)
- result.copy_from_datainfo(data2d=self)
-
- for i in range(numpy.size(self.data, 0)):
- for j in range(numpy.size(self.data, 1)):
- result.data[i][j] = self.data[i][j]
- if self.err_data is not None and \
- numpy.size(self.data) == numpy.size(self.err_data):
- result.err_data[i][j] = self.err_data[i][j]
-
- a = Uncertainty(self.data[i][j], dy[i][j]**2)
- if isinstance(other, Data2D):
- b = Uncertainty(other.data[i][j], dy_other[i][j]**2)
- else:
- b = other
- output = operation(a, b)
- result.data[i][j] = output.x
- result.err_data[i][j] = math.sqrt(math.fabs(output.variance))
- return result
-
Index: test/guiframe/data_manager.py
===================================================================
--- test/guiframe/data_manager.py (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,296 +1,0 @@
-################################################################################
-#This software was developed by the University of Tennessee as part of the
-#Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
-#project funded by the US National Science Foundation.
-#
-#See the license text in license.txt
-#
-#copyright 2010, University of Tennessee
-################################################################################
-"""
-This module manages all data loaded into the application. Data_manager makes
-available all data loaded for the current perspective.
-
-All modules "creating Data" posts their data to data_manager .
-Data_manager make these new data available for all other perspectives.
-"""
-import logging
-import os
-import copy
-
-from sans.guiframe.data_state import DataState
-from sans.guiframe.utils import parse_name
-import DataLoader.data_info as DataInfo
-from sans.guiframe.dataFitting import Data1D
-from sans.guiframe.dataFitting import Data2D
-import time
-
-class DataManager(object):
- """
- Manage a list of data
- """
- def __init__(self):
- """
- Store opened path and data object created at the loading time
- :param auto_plot: if True the datamanager sends data to plotting
- plugin.
- :param auto_set_data: if True the datamanager sends to the current
- perspective
- """
- self.stored_data = {}
- self.message = ""
- self.data_name_dict = {}
- self.count = 0
- self.list_of_id = []
- self.time_stamp = time.time()
-
- def __str__(self):
- _str = ""
- _str += "No of states is %s \n" % str(len(self.stored_data))
- n_count = 0
- for value in self.stored_data.values():
- n_count += 1
- _str += "State No %s \n" % str(n_count)
- _str += str(value) + "\n"
- return _str
-
- def create_gui_data(self, data, path=None):
- """
- Receive data from loader and create a data to use for guiframe
- """
-
- if issubclass(Data2D, data.__class__):
- new_plot = Data2D(image=None, err_image=None)
- else:
- new_plot = Data1D(x=[], y=[], dx=None, dy=None)
-
- new_plot.copy_from_datainfo(data)
- data.clone_without_data(clone=new_plot)
- #creating a name for data
- name = ""
- title = ""
- file_name = ""
- if path is not None:
- file_name = os.path.basename(path)
- if file_name == "":
- file_name = data.filename
- if data.run:
- run_num = data.run[0]
- name = file_name
- if name == "":
- name = run_num
- name = self.rename(name)
- #find title
- if data.title.strip():
- title = data.title
- if title.strip() == "":
- title = file_name
-
- if new_plot.filename.strip() == "":
- new_plot.filename = file_name
-
- new_plot.name = name
- new_plot.title = title
- ## allow to highlight data when plotted
- new_plot.interactive = True
- ## when 2 data have the same id override the 1 st plotted
- self.time_stamp += 1
- new_plot.id = str(name) + str(self.time_stamp)
- ##group_id specify on which panel to plot this data
- new_plot.group_id = str(name) + str(self.time_stamp)
- new_plot.is_data = True
- new_plot.path = path
- new_plot.list_group_id = []
- ##post data to plot
- # plot data
- return new_plot
-
- def rename(self, name):
- """
- rename data
- """
- ## name of the data allow to differentiate data when plotted
- name = parse_name(name=name, expression="_")
-
- max_char = name.find("[")
- if max_char < 0:
- max_char = len(name)
- name = name[0:max_char]
-
- if name not in self.data_name_dict:
- self.data_name_dict[name] = 0
- else:
- self.data_name_dict[name] += 1
- name = name + " [" + str(self.data_name_dict[name]) + "]"
- return name
-
-
- def add_data(self, data_list):
- """
- receive a list of
- """
- for id, data in data_list.iteritems():
- if id in self.stored_data:
- msg = "Data manager already stores %s" % str(data.name)
- msg += ""
- logging.info(msg)
- data_state = self.stored_data[id]
- data_state.data = data
- else:
- data_state = DataState(data)
- data_state.id = id
- self.stored_data[id] = data_state
-
- def update_data(self, prev_data, new_data):
- """
- """
- if prev_data.id not in self.stored_data.keys():
- return None, {}
- data_state = self.stored_data[prev_data.id]
- self.stored_data[new_data.id] = data_state.clone()
- self.stored_data[new_data.id].data = new_data
- if prev_data.id in self.stored_data.keys():
- del self.stored_data[prev_data.id]
- return prev_data.id, {new_data.id: self.stored_data[new_data.id]}
-
- def update_theory(self, theory, data_id=None, state=None):
- """
- """
- uid = data_id
- if data_id is None and theory is not None:
- uid = theory.id
- if uid in self.stored_data.keys():
- data_state = self.stored_data[uid]
- else:
- data_state = DataState()
- data_state.uid = uid
- data_state.set_theory(theory_data=theory, theory_state=state)
- self.stored_data[uid] = data_state
- return {uid: self.stored_data[uid]}
-
-
- def get_message(self):
- """
- return message
- """
- return self.message
-
- def get_by_id(self, id_list=None):
- """
- """
- _selected_data = {}
- _selected_theory_list = {}
- if id_list is None:
- return
- for d_id in self.stored_data:
- for search_id in id_list:
- data_state = self.stored_data[d_id]
- data = data_state.data
- theory_list = data_state.get_theory()
- if search_id == d_id:
- _selected_data[search_id] = data
- if search_id in theory_list.keys():
- _selected_theory_list[search_id] = theory_list[search_id]
-
- return _selected_data, _selected_theory_list
-
-
- def freeze(self, theory_id):
- """
- """
- return self.freeze_theory(self.stored_data.keys(), theory_id)
-
- def freeze_theory(self, data_id, theory_id):
- """
- """
- selected_theory = {}
- for d_id in data_id:
- if d_id in self.stored_data:
- data_state = self.stored_data[d_id]
- theory_list = data_state.get_theory()
- for t_id in theory_id:
- if t_id in theory_list.keys():
- theory_data, theory_state = theory_list[t_id]
- new_theory = copy.deepcopy(theory_data)
- new_theory.id = time.time()
- new_theory.is_data = True
- selected_theory[new_theory.id] = DataState(new_theory)
- self.stored_data[new_theory.id] = selected_theory[new_theory.id]
-
- return selected_theory
-
-
- def delete_data(self, data_id, theory_id=None, delete_all=False):
- """
- """
- for d_id in data_id:
- if d_id in self.stored_data.keys():
- data_state = self.stored_data[d_id]
- if data_state.data.name in self.data_name_dict:
- del self.data_name_dict[data_state.data.name]
- del self.stored_data[d_id]
-
- self.delete_theory(data_id, theory_id)
- if delete_all:
- self.stored_data = {}
- self.data_name_dict = {}
-
- def delete_theory(self, data_id, theory_id):
- """
- """
- for d_id in data_id:
- if d_id in self.stored_data:
- data_state = self.stored_data[d_id]
- theory_list = data_state.get_theory()
- if theory_id in theory_list.keys():
- del theory_list[theory_id]
-
-
- def delete_by_id(self, id_list=None):
- """
- save data and path
- """
- for id in id_list:
- if id in self.stored_data:
- del self.stored_data[id]
-
-
- def get_by_name(self, name_list=None):
- """
- return a list of data given a list of data names
- """
- _selected_data = {}
- for selected_name in name_list:
- for id, data_state in self.stored_data.iteritems():
- if data_state.data.name == selected_name:
- _selected_data[id] = data_state.data
- return _selected_data
-
- def delete_by_name(self, name_list=None):
- """
- save data and path
- """
- for selected_name in name_list:
- for id, data_state in self.stored_data.iteritems():
- if data_state.data.name == selected_name:
- del self._selected_data[id]
- del self.stored_data[data.id]
-
- def get_data_state(self, data_id):
- """
- Send list of selected data
- """
- _selected_data_state = {}
- for id in data_id:
- if id in self.stored_data.keys():
- _selected_data_state[id] = self.stored_data[id]
- return _selected_data_state
-
- def get_all_data(self):
- """
- return list of all available data
- """
- return self.stored_data
-
-
-
Index: test/guiframe/data_panel.py
===================================================================
--- test/guiframe/data_panel.py (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,1188 +1,0 @@
-################################################################################
-#This software was developed by the University of Tennessee as part of the
-#Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
-#project funded by the US National Science Foundation.
-#
-#See the license text in license.txt
-#
-#copyright 2010, University of Tennessee
-################################################################################
-"""
-This module provides Graphic interface for the data_manager module.
-"""
-import os
-import wx
-# Check version
-toks = wx.__version__.split('.')
-if int(toks[1]) < 9:
- if int(toks[2]) < 12:
- wx_version = 811
- else:
- wx_version = 812
-else:
- wx_version = 900
-import sys
-import warnings
-import logging
-from wx.lib.scrolledpanel import ScrolledPanel
-import wx.lib.agw.customtreectrl as CT
-from sans.guiframe.dataFitting import Data1D
-from sans.guiframe.dataFitting import Data2D
-from sans.guiframe.panel_base import PanelBase
-from sans.guiframe.events import StatusEvent
-from sans.guiframe.events import EVT_DELETE_PLOTPANEL
-from sans.guiframe.events import NewLoadDataEvent
-from sans.guiframe.events import NewPlotEvent
-from sans.guiframe.gui_style import GUIFRAME
-from sans.guiframe.events import NewBatchEvent
-from DataLoader.loader import Loader
-
-try:
- # Try to find a local config
- import imp
- path = os.getcwd()
- if(os.path.isfile("%s/%s.py" % (path, 'local_config'))) or \
- (os.path.isfile("%s/%s.pyc" % (path, 'local_config'))):
- fObj, path, descr = imp.find_module('local_config', [path])
- config = imp.load_module('local_config', fObj, path, descr)
- else:
- # Try simply importing local_config
- import local_config as config
-except:
- # Didn't find local config, load the default
- import config
-
-extension_list = []
-if config.APPLICATION_STATE_EXTENSION is not None:
- extension_list.append(config.APPLICATION_STATE_EXTENSION)
-EXTENSIONS = config.PLUGIN_STATE_EXTENSIONS + extension_list
-PLUGINS_WLIST = config.PLUGINS_WLIST
-APPLICATION_WLIST = config.APPLICATION_WLIST
-
-#Control panel width
-if sys.platform.count("darwin")==0:
- PANEL_WIDTH = 235
- PANEL_HEIGHT = 700
- CBOX_WIDTH = 140
- BUTTON_WIDTH = 80
- FONT_VARIANT = 0
- IS_MAC = False
-else:
- PANEL_WIDTH = 255
- PANEL_HEIGHT = 750
- CBOX_WIDTH = 155
- BUTTON_WIDTH = 100
- FONT_VARIANT = 1
- IS_MAC = True
-
-STYLE_FLAG =wx.RAISED_BORDER|CT.TR_HAS_BUTTONS| CT.TR_HIDE_ROOT|\
- wx.WANTS_CHARS|CT.TR_HAS_VARIABLE_ROW_HEIGHT
-
-
-class DataTreeCtrl(CT.CustomTreeCtrl):
- """
- Check list control to be used for Data Panel
- """
- def __init__(self, parent,*args, **kwds):
- #agwstyle is introduced in wx.2.8.11 but is not working for mac
- if IS_MAC and wx_version < 812:
- try:
- kwds['style'] = STYLE_FLAG
- CT.CustomTreeCtrl.__init__(self, parent, *args, **kwds)
- except:
- del kwds['style']
- CT.CustomTreeCtrl.__init__(self, parent, *args, **kwds)
- else:
- #agwstyle is introduced in wx.2.8.11 .argument working only for windows
- try:
- kwds['agwStyle'] = STYLE_FLAG
- CT.CustomTreeCtrl.__init__(self, parent, *args, **kwds)
- except:
- try:
- del kwds['agwStyle']
- kwds['style'] = STYLE_FLAG
- CT.CustomTreeCtrl.__init__(self, parent, *args, **kwds)
- except:
- del kwds['style']
- CT.CustomTreeCtrl.__init__(self, parent, *args, **kwds)
- self.root = self.AddRoot("Available Data")
-
-class DataPanel(ScrolledPanel, PanelBase):
- """
- This panel displays data available in the application and widgets to
- interact with data.
- """
- ## Internal name for the AUI manager
- window_name = "Data Panel"
- ## Title to appear on top of the window
- window_caption = "Data Explorer"
- #type of window
- window_type = "Data Panel"
- ## Flag to tell the GUI manager that this panel is not
- # tied to any perspective
- #ALWAYS_ON = True
- def __init__(self, parent,
- list=None,
- size=(PANEL_WIDTH, PANEL_HEIGHT),
- list_of_perspective=None, manager=None, *args, **kwds):
- kwds['size']= size
- kwds['style'] = STYLE_FLAG
- ScrolledPanel.__init__(self, parent=parent, *args, **kwds)
- PanelBase.__init__(self)
- self.SetupScrolling()
- #Set window's font size
- self.SetWindowVariant(variant=FONT_VARIANT)
- self.loader = Loader()
- #Default location
- self._default_save_location = None
- self.all_data1d = True
- self.parent = parent
- self.manager = manager
- if list is None:
- list = []
- self.list_of_data = list
- if list_of_perspective is None:
- list_of_perspective = []
- self.list_of_perspective = list_of_perspective
- self.list_rb_perspectives= []
- self.list_cb_data = {}
- self.list_cb_theory = {}
- self.tree_ctrl = None
- self.tree_ctrl_theory = None
- self.perspective_cbox = None
-
- self.owner = None
- self.do_layout()
- self.fill_cbox_analysis(self.list_of_perspective)
- self.Bind(wx.EVT_SHOW, self.on_close_page)
- if self.parent is not None:
- self.parent.Bind(EVT_DELETE_PLOTPANEL, self._on_delete_plot_panel)
-
- def do_layout(self):
- """
- """
- self.define_panel_structure()
- self.layout_selection()
- self.layout_data_list()
- self.layout_button()
- self.layout_batch()
-
- def define_panel_structure(self):
- """
- Define the skeleton of the panel
- """
- w, h = self.parent.GetSize()
- self.vbox = wx.BoxSizer(wx.VERTICAL)
- self.sizer1 = wx.BoxSizer(wx.VERTICAL)
- self.sizer1.SetMinSize((w/13, h*2/5))
-
- self.sizer2 = wx.BoxSizer(wx.VERTICAL)
- self.sizer3 = wx.FlexGridSizer(7, 2, 4, 1)
- self.sizer4 = wx.BoxSizer(wx.HORIZONTAL)
- self.sizer5 = wx.BoxSizer(wx.VERTICAL)
-
- self.vbox.Add(self.sizer5, 0, wx.EXPAND|wx.ALL,1)
- self.vbox.Add(self.sizer1, 0, wx.EXPAND|wx.ALL,0)
- self.vbox.Add(self.sizer2, 0, wx.EXPAND|wx.ALL,1)
- self.vbox.Add(self.sizer3, 0, wx.EXPAND|wx.ALL,5)
- self.vbox.Add(self.sizer4, 0, wx.EXPAND|wx.ALL,5)
-
- self.SetSizer(self.vbox)
-
- def layout_selection(self):
- """
- """
- select_txt = wx.StaticText(self, -1, 'Selection Options')
- select_txt.SetForegroundColour('blue')
- self.selection_cbox = wx.ComboBox(self, -1, style=wx.CB_READONLY)
- list_of_options = ['Select all Data',
- 'Unselect all Data',
- 'Select all Data 1D',
- 'Unselect all Data 1D',
- 'Select all Data 2D',
- 'Unselect all Data 2D' ]
- for option in list_of_options:
- self.selection_cbox.Append(str(option))
- self.selection_cbox.SetValue('Select all Data')
- wx.EVT_COMBOBOX(self.selection_cbox,-1, self._on_selection_type)
- self.sizer5.AddMany([(select_txt,0, wx.ALL,5),
- (self.selection_cbox,0, wx.ALL,5)])
- self.enable_selection()
-
-
- def _on_selection_type(self, event):
- """
- Select data according to patterns
- """
-
- list_of_options = ['Select all Data',
- 'Unselect all Data',
- 'Select all Data 1D',
- 'Unselect all Data 1D',
- 'Select all Data 2D',
- 'Unselect all Data 2D' ]
- option = self.selection_cbox.GetValue()
-
- pos = self.selection_cbox.GetSelection()
- if pos == wx.NOT_FOUND:
- return
- option = self.selection_cbox.GetString(pos)
- for item in self.list_cb_data.values():
- data_ctrl, _, _, _,_, _ = item
- data_id, data_class, _ = self.tree_ctrl.GetItemPyData(data_ctrl)
- if option == 'Select all Data':
- self.tree_ctrl.CheckItem(data_ctrl, True)
- elif option == 'Unselect all Data':
- self.tree_ctrl.CheckItem(data_ctrl, False)
- elif option == 'Select all Data 1D':
- if data_class == 'Data1D':
- self.tree_ctrl.CheckItem(data_ctrl, True)
- elif option == 'Unselect all Data 1D':
- if data_class == 'Data1D':
- self.tree_ctrl.CheckItem(data_ctrl, False)
- elif option == 'Select all Data 1D':
- if data_class == 'Data1D':
- self.tree_ctrl.CheckItem(data_ctrl, True)
- elif option == 'Select all Data 2D':
- if data_class == 'Data2D':
- self.tree_ctrl.CheckItem(data_ctrl, True)
- elif option == 'Unselect all Data 2D':
- if data_class == 'Data2D':
- self.tree_ctrl.CheckItem(data_ctrl, False)
- self.enable_append()
- self.enable_freeze()
- self.enable_plot()
- self.enable_import()
- self.enable_remove()
-
- def layout_button(self):
- """
- Layout widgets related to buttons
- """
- w, _ = self.GetSize()
-
- self.bt_add = wx.Button(self, wx.NewId(), "Load Data",
- size=(BUTTON_WIDTH, -1))
- self.bt_add.SetToolTipString("Load data files")
- wx.EVT_BUTTON(self, self.bt_add.GetId(), self._load_data)
- self.bt_remove = wx.Button(self, wx.NewId(), "Delete Data",
- size=(BUTTON_WIDTH, -1))
- self.bt_remove.SetToolTipString("Delete data from the application")
- wx.EVT_BUTTON(self, self.bt_remove.GetId(), self.on_remove)
- self.bt_import = wx.Button(self, wx.NewId(), "Send To",
- size=(BUTTON_WIDTH, -1))
- self.bt_import.SetToolTipString("Send set of Data to active perspective")
- wx.EVT_BUTTON(self, self.bt_import.GetId(), self.on_import)
- self.perspective_cbox = wx.ComboBox(self, -1,
- style=wx.CB_READONLY)
- #self.perspective_cbox.SetMinSize((CBOX_WIDTH, -1))
- wx.EVT_COMBOBOX(self.perspective_cbox,-1,
- self._on_perspective_selection)
-
- self.bt_append_plot = wx.Button(self, wx.NewId(), "Append Plot To",
- size=(BUTTON_WIDTH, -1))
- self.bt_append_plot.SetToolTipString("Plot the selected data in the active panel")
- wx.EVT_BUTTON(self, self.bt_append_plot.GetId(), self.on_append_plot)
-
- self.bt_plot = wx.Button(self, wx.NewId(), "New Plot",
- size=(BUTTON_WIDTH, -1))
- self.bt_plot.SetToolTipString("To trigger plotting")
- wx.EVT_BUTTON(self, self.bt_plot.GetId(), self.on_plot)
-
- self.bt_freeze = wx.Button(self, wx.NewId(), "Freeze Theory",
- size=(BUTTON_WIDTH, -1))
- self.bt_freeze.SetToolTipString("To trigger freeze a theory")
- wx.EVT_BUTTON(self, self.bt_freeze.GetId(), self.on_freeze)
- #hide plot
- #self.bt_close_plot = wx.Button(self, wx.NewId(), "Delete Plot",
- # size=(BUTTON_WIDTH, -1))
- #self.bt_close_plot.SetToolTipString("Delete the plot panel on focus")
- #wx.EVT_BUTTON(self, self.bt_close_plot.GetId(), self.on_close_plot)
-
- self.cb_plotpanel = wx.ComboBox(self, -1,
- style=wx.CB_READONLY|wx.CB_SORT)
- #self.cb_plotpanel.SetMinSize((CBOX_WIDTH, -1))
- wx.EVT_COMBOBOX(self.cb_plotpanel,-1, self._on_plot_selection)
- self.cb_plotpanel.Disable()
-
- self.sizer3.AddMany([(self.bt_add),
- ((10, 10)),
- (self.bt_remove),
- ((10, 10)),
- (self.bt_import, 0, wx.EXPAND|wx.RIGHT, 5),
- (self.perspective_cbox, wx.EXPAND|wx.ADJUST_MINSIZE, 5),
- (self.bt_append_plot),
- (self.cb_plotpanel, wx.EXPAND|wx.ADJUST_MINSIZE, 5),
- (self.bt_plot),
- ((10, 10)),
- (self.bt_freeze),
- #((10, 10)),
- #(self.bt_close_plot),
- ((10, 10))])
-
- self.sizer3.AddGrowableCol(1, 1)
- self.show_data_button()
- self.enable_remove()
- self.enable_import()
- self.enable_plot()
- self.enable_append()
- self.enable_freeze()
- self.enable_remove_plot()
-
- def layout_batch(self):
- """
- """
- self.rb_single_mode = wx.RadioButton(self, -1, 'Single Mode',
- style=wx.RB_GROUP)
- self.rb_batch_mode = wx.RadioButton(self, -1, 'Batch Mode')
- self.Bind(wx.EVT_RADIOBUTTON, self.on_single_mode,
- id=self.rb_single_mode.GetId())
- self.Bind(wx.EVT_RADIOBUTTON, self.on_batch_mode,
- id=self.rb_batch_mode.GetId())
-
- self.rb_single_mode.SetValue(True)
- self.rb_batch_mode.SetValue(False)
- self.sizer4.AddMany([(self.rb_single_mode,0, wx.ALL,5),
- (self.rb_batch_mode,0, wx.ALL,5)])
-
- def on_single_mode(self, event):
- """
- change guiframe to its single mode
- """
- if self.parent is not None:
- wx.PostEvent(self.parent,
- NewBatchEvent(enable=False))
-
- def on_batch_mode(self, event):
- """
- change guiframe to its batch mode
- """
- if self.parent is not None:
- wx.PostEvent(self.parent,
- NewBatchEvent(enable=True))
-
- def layout_data_list(self):
- """
- Add a listcrtl in the panel
- """
- tree_ctrl_label = wx.StaticText(self, -1, "Data")
- tree_ctrl_label.SetForegroundColour('blue')
- self.tree_ctrl = DataTreeCtrl(parent=self)
- self.tree_ctrl.Bind(CT.EVT_TREE_ITEM_CHECKING, self.on_check_item)
- tree_ctrl_theory_label = wx.StaticText(self, -1, "Theory")
- tree_ctrl_theory_label.SetForegroundColour('blue')
- self.tree_ctrl_theory = DataTreeCtrl(parent=self)
- self.tree_ctrl_theory.Bind(CT.EVT_TREE_ITEM_CHECKING, self.on_check_item)
- self.sizer1.Add(tree_ctrl_label, 0, wx.LEFT, 10)
- self.sizer1.Add(self.tree_ctrl, 1, wx.EXPAND|wx.ALL, 10)
- self.sizer1.Add(tree_ctrl_theory_label, 0, wx.LEFT, 10)
- self.sizer1.Add(self.tree_ctrl_theory, 1, wx.EXPAND|wx.ALL, 10)
-
- def onContextMenu(self, event):
- """
- Retrieve the state selected state
- """
- # Skipping the save state functionality for release 0.9.0
- #return
- pos = event.GetPosition()
- pos = self.ScreenToClient(pos)
- self.PopupMenu(self.popUpMenu, pos)
-
-
- def on_check_item(self, event):
- """
- """
- item = event.GetItem()
- item.Check(not item.IsChecked())
- self.enable_append()
- self.enable_freeze()
- self.enable_plot()
- self.enable_import()
- self.enable_remove()
- event.Skip()
-
- def fill_cbox_analysis(self, plugin):
- """
- fill the combobox with analysis name
- """
- self.list_of_perspective = plugin
- if self.parent is None or \
- not hasattr(self.parent, "get_current_perspective") or \
- len(self.list_of_perspective) == 0:
- return
- if self.parent is not None and self.perspective_cbox is not None:
- for plug in self.list_of_perspective:
- if plug.get_perspective():
- self.perspective_cbox.Append(plug.sub_menu, plug)
-
- curr_pers = self.parent.get_current_perspective()
- self.perspective_cbox.SetStringSelection(curr_pers.sub_menu)
- self.enable_import()
-
- def load_data_list(self, list):
- """
- add need data with its theory under the tree
- """
- if list:
- for state_id, dstate in list.iteritems():
- data = dstate.get_data()
- theory_list = dstate.get_theory()
- if data is not None:
- data_name = str(data.name)
- data_class = data.__class__.__name__
- path = dstate.get_path()
- process_list = data.process
- data_id = data.id
- s_path = str(path)
- if state_id not in self.list_cb_data:
- #new state
- data_c = self.tree_ctrl.InsertItem(self.tree_ctrl.root,0,
- data_name, ct_type=1,
- data=(data_id, data_class, state_id))
- data_c.Check(True)
- d_i_c = self.tree_ctrl.AppendItem(data_c, 'Info')
- i_c_c = self.tree_ctrl.AppendItem(d_i_c,
- 'Type: %s' % data_class)
- p_c_c = self.tree_ctrl.AppendItem(d_i_c,
- "Path: '%s'" % s_path)
- d_p_c = self.tree_ctrl.AppendItem(d_i_c, 'Process')
-
- for process in process_list:
- i_t_c = self.tree_ctrl.AppendItem(d_p_c,
- process.__str__())
- theory_child = self.tree_ctrl.AppendItem(data_c, "THEORIES")
-
- self.list_cb_data[state_id] = [data_c,
- d_i_c,
- i_c_c,
- p_c_c,
- d_p_c,
- theory_child]
- else:
- data_ctrl_list = self.list_cb_data[state_id]
- #This state is already display replace it contains
- data_c, d_i_c, i_c_c, p_c_c, d_p_c, t_c = data_ctrl_list
- self.tree_ctrl.SetItemText(data_c, data_name)
- temp = (data_id, data_class, state_id)
- self.tree_ctrl.SetItemPyData(data_c, temp)
- self.tree_ctrl.SetItemText(i_c_c, 'Type: %s' % data_class)
- self.tree_ctrl.SetItemText(p_c_c, 'Path: %s' % s_path)
- self.tree_ctrl.DeleteChildren(d_p_c)
- for process in process_list:
- i_t_c = self.tree_ctrl.AppendItem(d_p_c,
- process.__str__())
- self.append_theory(state_id, theory_list)
- self.enable_remove()
- self.enable_import()
- self.enable_plot()
- self.enable_freeze()
- self.enable_selection()
-
- def _uncheck_all(self):
- """
- Uncheck all check boxes
- """
- for item in self.list_cb_data.values():
- data_ctrl, _, _, _,_, _ = item
- self.tree_ctrl.CheckItem(data_ctrl, False)
- self.enable_append()
- self.enable_freeze()
- self.enable_plot()
- self.enable_import()
- self.enable_remove()
-
- def append_theory(self, state_id, theory_list):
- """
- append theory object under data from a state of id = state_id
- replace that theory if already displayed
- """
- if not theory_list:
- return
- if state_id not in self.list_cb_data.keys():
- root = self.tree_ctrl_theory.root
- tree = self.tree_ctrl_theory
- else:
- item = self.list_cb_data[state_id]
- data_c, _, _, _, _, _ = item
- root = data_c
- tree = self.tree_ctrl
- if root is not None:
- self.append_theory_helper(tree=tree, root=root,
- state_id=state_id,
- theory_list=theory_list)
-
-
- def append_theory_helper(self, tree, root, state_id, theory_list):
- """
- """
- if state_id in self.list_cb_theory.keys():
- #update current list of theory for this data
- theory_list_ctrl = self.list_cb_theory[state_id]
-
- for theory_id, item in theory_list.iteritems():
- theory_data, theory_state = item
- if theory_data is None:
- name = "Unknown"
- theory_class = "Unknown"
- theory_id = "Unknown"
- temp = (None, None, None)
- else:
- name = theory_data.name
- theory_class = theory_data.__class__.__name__
- theory_id = theory_data.id
- #if theory_state is not None:
- # name = theory_state.model.name
- temp = (theory_id, theory_class, state_id)
- if theory_id not in theory_list_ctrl:
- #add new theory
- t_child = tree.AppendItem(root,
- name, ct_type=1, data=temp)
- t_i_c = tree.AppendItem(t_child, 'Info')
- i_c_c = tree.AppendItem(t_i_c,
- 'Type: %s' % theory_class)
- t_p_c = tree.AppendItem(t_i_c, 'Process')
-
- for process in theory_data.process:
- i_t_c = tree.AppendItem(t_p_c,
- process.__str__())
- theory_list_ctrl[theory_id] = [t_child,
- i_c_c,
- t_p_c]
- else:
- #replace theory
- t_child, i_c_c, t_p_c = theory_list_ctrl[theory_id]
- tree.SetItemText(t_child, name)
- tree.SetItemPyData(t_child, temp)
- tree.SetItemText(i_c_c, 'Type: %s' % theory_class)
- tree.DeleteChildren(t_p_c)
- for process in theory_data.process:
- i_t_c = tree.AppendItem(t_p_c,
- process.__str__())
-
- else:
- #data didn't have a theory associated it before
- theory_list_ctrl = {}
- for theory_id, item in theory_list.iteritems():
- theory_data, theory_state = item
- if theory_data is not None:
- name = theory_data.name
- theory_class = theory_data.__class__.__name__
- theory_id = theory_data.id
- #if theory_state is not None:
- # name = theory_state.model.name
- temp = (theory_id, theory_class, state_id)
- t_child = tree.AppendItem(root,
- name, ct_type=1,
- data=(theory_data.id, theory_class, state_id))
- t_i_c = tree.AppendItem(t_child, 'Info')
- i_c_c = tree.AppendItem(t_i_c,
- 'Type: %s' % theory_class)
- t_p_c = tree.AppendItem(t_i_c, 'Process')
-
- for process in theory_data.process:
- i_t_c = tree.AppendItem(t_p_c,
- process.__str__())
-
- theory_list_ctrl[theory_id] = [t_child, i_c_c, t_p_c]
- #self.list_cb_theory[data_id] = theory_list_ctrl
- self.list_cb_theory[state_id] = theory_list_ctrl
-
-
-
- def set_data_helper(self):
- """
- """
- data_to_plot = []
- state_to_plot = []
- theory_to_plot = []
- for value in self.list_cb_data.values():
- item, _, _, _, _, _ = value
- if item.IsChecked():
- data_id, _, state_id = self.tree_ctrl.GetItemPyData(item)
- data_to_plot.append(data_id)
- if state_id not in state_to_plot:
- state_to_plot.append(state_id)
-
- for theory_dict in self.list_cb_theory.values():
- for key, value in theory_dict.iteritems():
- item, _, _ = value
- if item.IsChecked():
- theory_id, _, state_id = self.tree_ctrl.GetItemPyData(item)
- theory_to_plot.append(theory_id)
- if state_id not in state_to_plot:
- state_to_plot.append(state_id)
- return data_to_plot, theory_to_plot, state_to_plot
-
- def remove_by_id(self, id):
- """
- """
- for item in self.list_cb_data.values():
- data_c, _, _, _, _, theory_child = item
- data_id, _, state_id = self.tree_ctrl.GetItemPyData(data_c)
- if id == data_id:
- self.tree_ctrl.Delete(data_c)
- del self.list_cb_data[state_id]
- del self.list_cb_theory[data_id]
-
- def load_error(self, error=None):
- """
- Pop up an error message.
-
- :param error: details error message to be displayed
- """
- if error is not None or str(error).strip() != "":
- dial = wx.MessageDialog(self.parent, str(error), 'Error Loading File',
- wx.OK | wx.ICON_EXCLAMATION)
- dial.ShowModal()
-
- def _load_data(self, event):
- """
- send an event to the parent to trigger load from plugin module
- """
- if self.parent is not None:
- wx.PostEvent(self.parent, NewLoadDataEvent())
-
-
- def on_remove(self, event):
- """
- Get a list of item checked and remove them from the treectrl
- Ask the parent to remove reference to this item
- """
- data_to_remove, theory_to_remove, _ = self.set_data_helper()
- data_key = []
- theory_key = []
- #remove data from treectrl
- for d_key, item in self.list_cb_data.iteritems():
- data_c, d_i_c, i_c_c, p_c_c, d_p_c, t_c = item
- if data_c.IsChecked():
- self.tree_ctrl.Delete(data_c)
- data_key.append(d_key)
- if d_key in self.list_cb_theory.keys():
- theory_list_ctrl = self.list_cb_theory[d_key]
- theory_to_remove += theory_list_ctrl.keys()
- # Remove theory from treectrl
- for t_key, theory_dict in self.list_cb_theory.iteritems():
- for key, value in theory_dict.iteritems():
- item, _, _ = value
- if item.IsChecked():
- try:
- self.tree_ctrl.Delete(item)
- except:
- pass
- theory_key.append(key)
-
- #Remove data and related theory references
- for key in data_key:
- del self.list_cb_data[key]
- if key in theory_key:
- del self.list_cb_theory[key]
- #remove theory references independently of data
- for key in theory_key:
- for t_key, theory_dict in self.list_cb_theory.iteritems():
- if key in theory_dict:
- for key, value in theory_dict.iteritems():
- item, _, _ = value
- if item.IsChecked():
- try:
- self.tree_ctrl_theory.Delete(item)
- except:
- pass
- del theory_dict[key]
-
-
- self.parent.remove_data(data_id=data_to_remove,
- theory_id=theory_to_remove)
- self.enable_remove()
- self.enable_freeze()
- self.enable_remove_plot()
-
- def on_import(self, event=None):
- """
- Get all select data and set them to the current active perspetive
- """
- data_id, theory_id, state_id = self.set_data_helper()
- temp = data_id + state_id
- self.parent.set_data(data_id=temp, theory_id=theory_id)
-
- def on_append_plot(self, event=None):
- """
- append plot to plot panel on focus
- """
- self._on_plot_selection()
- data_id, theory_id, state_id = self.set_data_helper()
- self.parent.plot_data(data_id=data_id,
- state_id=state_id,
- theory_id=theory_id,
- append=True)
-
- def on_plot(self, event=None):
- """
- Send a list of data names to plot
- """
- data_id, theory_id, state_id = self.set_data_helper()
- self.parent.plot_data(data_id=data_id,
- state_id=state_id,
- theory_id=theory_id,
- append=False)
- self.enable_remove_plot()
-
- def on_close_page(self, event=None):
- """
- On close
- """
- if event != None:
- event.Skip()
- # send parent to update menu with no show nor hide action
- self.parent.show_data_panel(action=False)
-
- def on_freeze(self, event):
- """
- """
- _, theory_id, state_id = self.set_data_helper()
- self.parent.freeze(data_id=state_id, theory_id=theory_id)
-
- def set_active_perspective(self, name):
- """
- set the active perspective
- """
- self.perspective_cbox.SetStringSelection(name)
- self.enable_import()
-
- def _on_delete_plot_panel(self, event):
- """
- get an event with attribute name and caption to delete existing name
- from the combobox of the current panel
- """
- name = event.name
- caption = event.caption
- if self.cb_plotpanel is not None:
- pos = self.cb_plotpanel.FindString(str(caption))
- if pos != wx.NOT_FOUND:
- self.cb_plotpanel.Delete(pos)
- self.enable_append()
-
- def set_panel_on_focus(self, name=None):
- """
- set the plot panel on focus
- """
- for key, value in self.parent.plot_panels.iteritems():
- name_plot_panel = str(value.window_caption)
- if name_plot_panel not in self.cb_plotpanel.GetItems():
- self.cb_plotpanel.Append(name_plot_panel, value)
- if name != None and name == name_plot_panel:
- self.cb_plotpanel.SetStringSelection(name_plot_panel)
- break
- self.enable_append()
- self.enable_remove_plot()
-
- def _on_perspective_selection(self, event=None):
- """
- select the current perspective for guiframe
- """
- selection = self.perspective_cbox.GetSelection()
-
- if self.perspective_cbox.GetValue() != 'None':
- perspective = self.perspective_cbox.GetClientData(selection)
- perspective.on_perspective(event=None)
-
- def _on_plot_selection(self, event=None):
- """
- On source combobox selection
- """
- if event != None:
- combo = event.GetEventObject()
- event.Skip()
- else:
- combo = self.cb_plotpanel
- selection = combo.GetSelection()
-
- if combo.GetValue() != 'None':
- panel = combo.GetClientData(selection)
- self.parent.on_set_plot_focus(panel)
-
- def on_close_plot(self, event):
- """
- clseo the panel on focus
- """
- self.enable_append()
- selection = self.cb_plotpanel.GetSelection()
- if self.cb_plotpanel.GetValue() != 'None':
- panel = self.cb_plotpanel.GetClientData(selection)
- if self.parent is not None and panel is not None:
- wx.PostEvent(self.parent,
- NewPlotEvent(group_id=panel.group_id,
- action="delete"))
- self.enable_remove_plot()
-
- def enable_remove_plot(self):
- """
- enable remove plot button if there is a plot panel on focus
- """
- pass
- #if self.cb_plotpanel.GetCount() == 0:
- # self.bt_close_plot.Disable()
- #else:
- # self.bt_close_plot.Enable()
-
- def enable_remove(self):
- """
- enable or disable remove button
- """
- n_t = self.tree_ctrl.GetCount()
- n_t_t = self.tree_ctrl_theory.GetCount()
- if n_t + n_t_t <= 0:
- self.bt_remove.Disable()
- else:
- self.bt_remove.Enable()
-
- def enable_import(self):
- """
- enable or disable send button
- """
- n_t = 0
- if self.tree_ctrl != None:
- n_t = self.tree_ctrl.GetCount()
- if n_t > 0 and len(self.list_of_perspective) > 0:
- self.bt_import.Enable()
- else:
- self.bt_import.Disable()
- if len(self.list_of_perspective) <= 0 or \
- self.perspective_cbox.GetValue() in ["None",
- "No Active Application"]:
- self.perspective_cbox.Disable()
- else:
- self.perspective_cbox.Enable()
-
- def enable_plot(self):
- """
- enable or disable plot button
- """
- n_t = 0
- n_t_t = 0
- if self.tree_ctrl != None:
- n_t = self.tree_ctrl.GetCount()
- if self.tree_ctrl_theory != None:
- n_t_t = self.tree_ctrl_theory.GetCount()
- if n_t + n_t_t <= 0:
- self.bt_plot.Disable()
- else:
- self.bt_plot.Enable()
- self.enable_append()
-
- def enable_append(self):
- """
- enable or disable append button
- """
- n_t = 0
- n_t_t = 0
- if self.tree_ctrl != None:
- n_t = self.tree_ctrl.GetCount()
- if self.tree_ctrl_theory != None:
- n_t_t = self.tree_ctrl_theory.GetCount()
- if n_t + n_t_t <= 0:
- self.bt_append_plot.Disable()
- self.cb_plotpanel.Disable()
- elif self.cb_plotpanel.GetCount() <= 0:
- self.cb_plotpanel.Disable()
- self.bt_append_plot.Disable()
- else:
- self.bt_append_plot.Enable()
- self.cb_plotpanel.Enable()
-
- def check_theory_to_freeze(self):
- """
- """
- def enable_freeze(self):
- """
- enable or disable the freeze button
- """
- n_t_t = 0
- n_l = 0
- if self.tree_ctrl_theory != None:
- n_t_t = self.tree_ctrl_theory.GetCount()
- n_l = len(self.list_cb_theory)
- if (n_t_t + n_l > 0):
- self.bt_freeze.Enable()
- else:
- self.bt_freeze.Disable()
-
- def enable_selection(self):
- """
- enable or disable combobo box selection
- """
- n_t = 0
- n_t_t = 0
- if self.tree_ctrl != None:
- n_t = self.tree_ctrl.GetCount()
- if self.tree_ctrl_theory != None:
- n_t_t = self.tree_ctrl_theory.GetCount()
- if n_t + n_t_t > 0 and self.selection_cbox != None:
- self.selection_cbox.Enable()
- else:
- self.selection_cbox.Disable()
-
- def show_data_button(self):
- """
- show load data and remove data button if
- dataloader on else hide them
- """
- try:
- gui_style = self.parent.get_style()
- style = gui_style & GUIFRAME.DATALOADER_ON
- if style == GUIFRAME.DATALOADER_ON:
- #self.bt_remove.Show(True)
- self.bt_add.Show(True)
- else:
- #self.bt_remove.Hide()
- self.bt_add.Hide()
- except:
- #self.bt_remove.Hide()
- self.bt_add.Hide()
-
-
-
-WIDTH = 400
-HEIGHT = 300
-
-
-class DataDialog(wx.Dialog):
- """
- Allow file selection at loading time
- """
- def __init__(self, data_list, parent=None, text='', *args, **kwds):
- wx.Dialog.__init__(self, parent, *args, **kwds)
- self.SetTitle("Data Selection")
- self.SetSize((WIDTH, HEIGHT))
- self.list_of_ctrl = []
- if not data_list:
- return
- self._sizer_main = wx.BoxSizer(wx.VERTICAL)
- self._sizer_txt = wx.BoxSizer(wx.VERTICAL)
- self._sizer_button = wx.BoxSizer(wx.HORIZONTAL)
- self.sizer = wx.GridBagSizer(5, 5)
- self._panel = ScrolledPanel(self, style=wx.RAISED_BORDER,
- size=(WIDTH-20, HEIGHT-50))
- self._panel.SetupScrolling()
- self.__do_layout(data_list, text=text)
-
- def __do_layout(self, data_list, text=''):
- """
- layout the dialog
- """
- if not data_list or len(data_list) <= 1:
- return
- #add text
-
- text = "Deleting these file reset some panels.\n"
- text += "Do you want to proceed?\n"
- text_ctrl = wx.StaticText(self, -1, str(text))
- self._sizer_txt.Add(text_ctrl)
- iy = 0
- ix = 0
- data_count = 0
- for (data_name, in_use, sub_menu) in range(len(data_list)):
- if in_use == True:
- ctrl_name = wx.StaticBox(self, -1, str(data_name))
- ctrl_in_use = wx.StaticBox(self, -1, " is used by ")
- plug_name = str(sub_menu) + "\n"
- ctrl_sub_menu = wx.StaticBox(self, -1, plug_name)
- self.sizer.Add(ctrl_name, (iy, ix),
- (1, 1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
- ix += 1
- self._sizer_button.Add(ctrl_in_use, 1,
- wx.EXPAND|wx.ADJUST_MINSIZE, 0)
- ix += 1
- self._sizer_button.Add(plug_name, 1,
- wx.EXPAND|wx.ADJUST_MINSIZE, 0)
- iy += 1
- self._panel.SetSizer(self.sizer)
- #add sizer
- self._sizer_button.Add((20, 20), 1, wx.EXPAND|wx.ADJUST_MINSIZE, 0)
- button_cancel = wx.Button(self, wx.ID_CANCEL, "Cancel")
- self._sizer_button.Add(button_cancel, 0,
- wx.LEFT|wx.RIGHT|wx.ADJUST_MINSIZE, 10)
- button_OK = wx.Button(self, wx.ID_OK, "Ok")
- button_OK.SetFocus()
- self._sizer_button.Add(button_OK, 0,
- wx.LEFT|wx.RIGHT|wx.ADJUST_MINSIZE, 10)
- static_line = wx.StaticLine(self, -1)
-
- self._sizer_txt.Add(self._panel, 1, wx.EXPAND|wx.LEFT|wx.RIGHT, 5)
- self._sizer_main.Add(self._sizer_txt, 1, wx.EXPAND|wx.ALL, 10)
- self._sizer_main.Add(self._data_text_ctrl, 0,
- wx.EXPAND|wx.LEFT|wx.RIGHT, 10)
- self._sizer_main.Add(static_line, 0, wx.EXPAND, 0)
- self._sizer_main.Add(self._sizer_button, 0, wx.EXPAND|wx.ALL, 10)
- self.SetSizer(self._sizer_main)
- self.Layout()
-
- def get_data(self):
- """
- return the selected data
- """
- temp = []
- for item in self.list_of_ctrl:
- cb, data = item
- if cb.GetValue():
- temp.append(data)
- return temp
-
- def _count_selected_data(self, event):
- """
- count selected data
- """
- if event.GetEventObject().GetValue():
- self._nb_selected_data += 1
- else:
- self._nb_selected_data -= 1
- select_data_text = " %s Data selected.\n" % str(self._nb_selected_data)
- self._data_text_ctrl.SetLabel(select_data_text)
- if self._nb_selected_data <= self._max_data:
- self._data_text_ctrl.SetForegroundColour('blue')
- else:
- self._data_text_ctrl.SetForegroundColour('red')
-
-
-
-class DataFrame(wx.Frame):
- ## Internal name for the AUI manager
- window_name = "Data Panel"
- ## Title to appear on top of the window
- window_caption = "Data Panel"
- ## Flag to tell the GUI manager that this panel is not
- # tied to any perspective
- ALWAYS_ON = True
-
- def __init__(self, parent=None, owner=None, manager=None,size=(300, 800),
- list_of_perspective=[],list=[], *args, **kwds):
- kwds['size'] = size
- kwds['id'] = -1
- kwds['title']= "Loaded Data"
- wx.Frame.__init__(self, parent=parent, *args, **kwds)
- self.parent = parent
- self.owner = owner
- self.manager = manager
- self.panel = DataPanel(parent=self,
- #size=size,
- list_of_perspective=list_of_perspective)
-
- def load_data_list(self, list=[]):
- """
- Fill the list inside its panel
- """
- self.panel.load_data_list(list=list)
-
-
-
-from dataFitting import Data1D
-from dataFitting import Data2D, Theory1D
-from data_state import DataState
-import sys
-class State():
- def __init__(self):
- self.msg = ""
- def __str__(self):
- self.msg = "model mane : model1\n"
- self.msg += "params : \n"
- self.msg += "name value\n"
- return msg
-def set_data_state(data=None, path=None, theory=None, state=None):
- dstate = DataState(data=data)
- dstate.set_path(path=path)
- dstate.set_theory(theory, state)
-
- return dstate
-"""'
-data_list = [1:('Data1', 'Data1D', '07/01/2010', "theory1d", "state1"),
- ('Data2', 'Data2D', '07/03/2011', "theory2d", "state1"),
- ('Data3', 'Theory1D', '06/01/2010', "theory1d", "state1"),
- ('Data4', 'Theory2D', '07/01/2010', "theory2d", "state1"),
- ('Data5', 'Theory2D', '07/02/2010', "theory2d", "state1")]
-"""
-if __name__ == "__main__":
-
- app = wx.App()
- try:
- list_of_perspective = [('perspective2', False), ('perspective1', True)]
- data_list = {}
- # state 1
- data = Data2D()
- data.name = "data2"
- data.id = 1
- data.append_empty_process()
- process = data.process[len(data.process)-1]
- process.data = "07/01/2010"
- theory = Data2D()
- theory.id = 34
- theory.name = "theory1"
- path = "path1"
- state = State()
- data_list['1']=set_data_state(data, path,theory, state)
- #state 2
- data = Data2D()
- data.name = "data2"
- data.id = 76
- theory = Data2D()
- theory.id = 78
- theory.name = "CoreShell 07/24/25"
- path = "path2"
- #state3
- state = State()
- data_list['2']=set_data_state(data, path,theory, state)
- data = Data1D()
- data.id = 3
- data.name = "data2"
- theory = Theory1D()
- theory.name = "CoreShell"
- theory.id = 4
- theory.append_empty_process()
- process = theory.process[len(theory.process)-1]
- process.description = "this is my description"
- path = "path3"
- data.append_empty_process()
- process = data.process[len(data.process)-1]
- process.data = "07/22/2010"
- data_list['4']=set_data_state(data, path,theory, state)
- #state 4
- temp_data_list = {}
- data.name = "data5 erasing data2"
- temp_data_list['4'] = set_data_state(data, path,theory, state)
- #state 5
- data = Data2D()
- data.name = "data3"
- data.id = 5
- data.append_empty_process()
- process = data.process[len(data.process)-1]
- process.data = "07/01/2010"
- theory = Theory1D()
- theory.name = "Cylinder"
- path = "path2"
- state = State()
- dstate= set_data_state(data, path,theory, state)
- theory = Theory1D()
- theory.id = 6
- theory.name = "CoreShell"
- dstate.set_theory(theory)
- theory = Theory1D()
- theory.id = 6
- theory.name = "CoreShell replacing coreshell in data3"
- dstate.set_theory(theory)
- data_list['3'] = dstate
- #state 6
- data_list['6']=set_data_state(None, path,theory, state)
- data_list['6']=set_data_state(theory=theory, state=None)
- theory = Theory1D()
- theory.id = 7
- data_list['6']=set_data_state(theory=theory, state=None)
- data_list['7']=set_data_state(theory=theory, state=None)
- window = DataFrame(list=data_list)
- window.load_data_list(list=data_list)
- window.Show(True)
- window.load_data_list(list=temp_data_list)
- except:
- #raise
- print "error",sys.exc_value
-
- app.MainLoop()
-
-
Index: test/guiframe/data_processor.py
===================================================================
--- test/guiframe/data_processor.py (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,288 +1,0 @@
-"""
-Implement grid used to store data
-"""
-import wx
-import numpy
-import sys
-from wx.lib.scrolledpanel import ScrolledPanel
-import wx.grid as Grid
-import wx.aui
-from wx.aui import AuiNotebook as nb
-from sans.guiframe.panel_base import PanelBase
-import wx.lib.sheet as sheet
-
-from sans.guiframe.events import NewPlotEvent
-from sans.guiframe.events import StatusEvent
-from sans.guiframe.dataFitting import Data1D
-
-
-class GridPage(sheet.CSheet):
- def __init__(self, parent, panel=None):
- """
- """
- sheet.CSheet.__init__(self, parent)
- self.SetLabelBackgroundColour('#DBD4D4')
- self.panel = panel
- self.col_names = []
- self._cols = 0
- self._rows = 0
- self.SetNumberRows(self._cols)
- self.SetNumberCols(self._rows)
- self.Bind(wx.grid.EVT_GRID_LABEL_RIGHT_CLICK, self.on_right_click)
- self.axis_value = []
- self.axis_label = ""
-
-
- def on_right_click(self, event):
- print "on double click", event.GetRow(), event.GetCol()
- col = event.GetCol()
- if col != -1 and len(self.col_names) > col:
- label = self.col_names[int(col)]
- self.axis_label = label
- if label in self.data.keys():
- col_val = self.data[label]
- self.axis_value = col_val
- # Slicer plot popup menu
- slicerpop = wx.Menu()
- id = wx.NewId()
- slicerpop.Append(id, '&Set X axis', 'Set X axis')
- wx.EVT_MENU(self, id, self.on_set_x_axis)
-
-
- id = wx.NewId()
- slicerpop.Append(id, '&Set Y axis', 'Set Y axis')
- wx.EVT_MENU(self, id, self.on_set_y_axis)
- pos = event.GetPosition()
- pos = self.ScreenToClient(pos)
- self.PopupMenu(slicerpop, pos)
-
-
-
- def on_set_x_axis(self, event):
- self.panel.set_xaxis(x=self.axis_value, label=self.axis_label)
-
- def on_set_y_axis(self, event):
- self.panel.set_yaxis(y=self.axis_value, label=self.axis_label)
-
- def set_data(self, data):
- """
- """
- if data is None:
- data = {}
- if len(data) > 0:
- self.data = data
- self.col_names = data.keys()
- self.col_names.sort()
- self._cols = len(self.data.keys())
- self._rows = max([len(v) for v in self.data.values()])
- self.SetNumberRows(int(self._rows))
- self.SetNumberCols(int(self._cols))
- for index in range(len(self.col_names)):
- self.SetColLabelValue(index, str(self.col_names[index]))
-
- col = 0
- for value_list in self.data.values():
- for row in range(len(value_list)):
- self.SetCellValue(row, col, str(value_list[row]))
- col += 1
- self.AutoSize()
-
-class Notebook(nb, PanelBase):
- """
- ## Internal name for the AUI manager
- window_name = "Fit panel"
- ## Title to appear on top of the window
- """
- window_caption = "Notebook "
-
- def __init__(self, parent, manager=None, data=None, *args, **kwargs):
- """
- """
- nb.__init__(self, parent, -1,
- style= wx.NB_BOTTOM)
- PanelBase.__init__(self, parent)
-
- self.parent = parent
- self.manager = manager
- self.data = data
-
- def set_data(self, data):
- if data is None:
- return
-
- grid = GridPage(self, panel=self.parent)
- grid.set_data(data)
- self.AddPage(grid, "Batch")
-
-
-class SPanel(ScrolledPanel):
- def __init__(self, parent, *args, **kwds):
- ScrolledPanel.__init__(self, parent , *args, **kwds)
- self.SetupScrolling()
-
-class GridPanel(SPanel):
- def __init__(self, parent,data=None, *args, **kwds):
- SPanel.__init__(self, parent , *args, **kwds)
- self.vbox = wx.BoxSizer(wx.VERTICAL)
-
- self.plotting_sizer = wx.FlexGridSizer(3, 5, 10, 5)
- w, h = self.GetSize()
- #self.panel_grid = SPanel(self, -1, size=(w, -1))
- self.grid_sizer = wx.BoxSizer(wx.HORIZONTAL)
- self.vbox.AddMany([(self.grid_sizer, 1, wx.EXPAND, 0),
- (wx.StaticLine(self, -1), 0, wx.EXPAND, 0),
- (self.plotting_sizer)])
- self.parent = parent
- self._data = data
- self.x = []
- self.y = []
-
- self.x_axis_label = None
- self.y_axis_label = None
- self.x_axis_value = None
- self.y_axis_value = None
- self.x_axis_unit = None
- self.y_axis_unit = None
- self.plot_button = None
- self.grid = None
- self.layout_grid()
- self.layout_plotting_area()
- self.SetSizer(self.vbox)
-
- def set_data(self, data):
- """
- """
- if self.grid is not None:
- self.grid.set_data(data)
-
- def set_xaxis(self, label="", x=None) :
- if x is None:
- x = []
- self.x = x
- self.x_axis_value.SetValue("%s[:]" % str(label))
- self.x_axis_label.SetValue(str(label))
-
- def set_yaxis(self, label="", y=None) :
- if y is None:
- y = []
- self.y = y
- self.y_axis_value.SetValue("%s[:]" % str(label))
- self.y_axis_label.SetValue(str(label))
-
-
-
- def on_plot(self, event):
- """
- plotting
- """
- new_plot = Data1D(x=self.x, y=self.y)
- new_plot.id = wx.NewId()
- new_plot.group_id = wx.NewId()
- title = "%s vs %s" % (self.y_axis_label.GetValue(), self.x_axis_label.GetValue())
- new_plot.xaxis(self.x_axis_label.GetValue(), self.x_axis_unit.GetValue())
- new_plot.yaxis(self.y_axis_label.GetValue(), self.y_axis_unit.GetValue())
- wx.PostEvent(self.parent.parent,
- NewPlotEvent(plot=new_plot, group_id=str(new_plot.group_id), title ="batch"))
- def layout_grid(self):
- """
- Draw the area related to the grid
- """
- self.grid = Notebook(parent=self)
- self.grid.set_data(self._data)
- #self.grid = Table(parent=self, data=self._data)
- #vbox = wx.BoxSizer(wx.HORIZONTAL)
- self.grid_sizer.Add(self.grid, 1, wx.EXPAND, 0)
- #self.panel_grid.SetSizer(vbox)
-
- def layout_grid1(self):
- """
- Draw the area related to the grid
- """
- self.grid = Table(parent=self.panel_grid, data=self._data)
- vbox = wx.BoxSizer(wx.HORIZONTAL)
- vbox.Add(self.grid, 1, wx.EXPAND, 0)
- self.panel_grid.SetSizer(vbox)
-
- def layout_plotting_area(self):
- """
- Draw area containing options to plot
- """
- self.x_axis_label = wx.TextCtrl(self, -1)
-
- self.y_axis_label = wx.TextCtrl(self, -1)
-
- self.x_axis_value = wx.TextCtrl(self, -1)
- self.y_axis_value = wx.TextCtrl(self, -1)
-
- self.x_axis_unit = wx.TextCtrl(self, -1)
- self.y_axis_unit = wx.TextCtrl(self, -1)
- self.plot_button = wx.Button(self, -1, "Plot")
- wx.EVT_BUTTON(self, self.plot_button.GetId(), self.on_plot)
- self.plotting_sizer.AddMany([(wx.StaticText(self, -1, "x"), 1, wx.LEFT, 10),
- (self.x_axis_label, wx.TOP|wx.BOTTOM|wx.LEFT, 10),
- (self.x_axis_value, wx.TOP|wx.BOTTOM|wx.LEFT, 10),
- (wx.StaticText(self, -1 , "unit"), 1, wx.LEFT|wx.RIGHT|wx.ADJUST_MINSIZE|wx.EXPAND, 0),
- (self.x_axis_unit),
- (wx.StaticText(self, -1, "y"), 1, wx.LEFT, 10),
- (self.y_axis_label, wx.TOP|wx.BOTTOM|wx.LEFT, 10),
- (self.y_axis_value, wx.TOP|wx.BOTTOM|wx.LEFT, 10),
- (wx.StaticText(self, -1 , "unit"), 1, wx.LEFT|wx.RIGHT|wx.ADJUST_MINSIZE|wx.EXPAND, 0),
- (self.y_axis_unit),
- (-1, -1),
- (-1, -1),
- (-1, -1),
- (self.plot_button, 1, wx.LEFT, 30)])
-
-
- def add_column(self):
- if self.grid is not None:
- self.grid.add_column()
-
-
-class GridFrame(wx.Frame):
- def __init__(self, parent=None, data=None, id=-1, title="Batch Results", size=(500, 400)):
- wx.Frame.__init__(self, parent=parent, id=id, title=title, size=size)
- self.parent = parent
- self.panel = GridPanel(self, data)
- menubar = wx.MenuBar()
- edit = wx.Menu()
- id_col = wx.NewId()
- edit.Append(id_col, 'Edit', '' )
- menubar.Append(edit, "&New column")
- self.SetMenuBar(menubar)
- wx.EVT_MENU(self, id_col, self.on_add_column)
- self.Bind(wx.EVT_CLOSE, self.on_close)
-
-
- def on_close(self, event):
- """
- """
- self.Hide()
-
- def on_add_column(self, event):
- """
- """
- self.panel.add_column()
-
- def set_data(self, data):
- """
- """
- self.panel.set_data(data)
-
-
-if __name__ == "__main__":
- app = wx.App()
-
- try:
- data = {}
- j = 0
- for i in range(4):
- j += 1
- data["index"+str(i)] = [i/j, i*j, i, i+j]
-
- frame = TestFrame(data=data)
- frame.Show(True)
- except:
- print sys.exc_value
-
- app.MainLoop()
Index: test/guiframe/data_state.py
===================================================================
--- test/guiframe/data_state.py (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,116 +1,0 @@
-################################################################################
-#This software was developed by the University of Tennessee as part of the
-#Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
-#project funded by the US National Science Foundation.
-#
-#See the license text in license.txt
-#
-#copyright 2010, University of Tennessee
-################################################################################
-"""
-"""
-import copy
-
-
-class DataState(object):
- """
- Store information about data
- """
- def __init__(self, data=None, parent=None):
- """
-
- """
- self.parent = parent
- self.data = data
- self.name = ""
- self.path = None
- self.theory_list = {}
- self.message = ""
- self.id = None
-
- def __str__(self):
- _str = ""
- _str += "State with ID : %s \n" % str(self.id)
- if self.data is not None:
- _str += "Data name : %s \n" % str(self.data.name)
- _str += "Data ID : %s \n" % str(self.data.id)
- else:
- _str += "Theory Data: %s \n" % str(self.theory_data)
- if self.theory_data is not None:
- _str += "Data name : %s \n" % str(self.theory_data.name)
- _str += "Theory Data ID : %s \n" % str(self.theory_data.id)
- else:
- _str += "Theory Data: %s \n" % str(self.theory_data)
-
- _str += "Theories available: %s \n" % len(self.theory_list)
- if self.theory_list:
- for id, item in self.theory_list.iteritems():
- theory_data, theory_state = item
- _str += "Theory name : %s \n" % str(theory_data.name)
- _str += "Theory ID : %s \n" % str(id)
- _str += "Theory info: \n"
- _str += str(theory_data)
-
- return _str
-
- def clone(self):
- obj = DataState(copy.deepcopy(self.data))
- obj.parent = self.parent
- obj.name = self.name
- obj.path = self.path
- obj.message = self.message
- obj.id = self.id
- for id, item in self.theory_list.iteritems():
- theory_data, theory_state = item
- state = None
- if theory_state is not None:
- state = theory_state.clone()
- obj.theory_list[id] = [copy.deepcopy(theory_data),
- state]
- return obj
-
- def set_name(self, name):
- self.name = name
-
- def get_name(self):
- return self.name
-
- def set_data(self, data):
- """
- """
- self.data = data
-
-
- def get_data(self):
- """
- """
- return self.data
-
- def set_path(self, path):
- """
- Set the path of the loaded data
- """
- self.path = path
-
- def get_path(self):
- """
- return the path of the loaded data
- """
- return self.path
-
- def set_theory(self, theory_data, theory_state=None):
- """
- """
- self.theory_list[theory_data.id] = [theory_data, theory_state]
- data, state = self.theory_list.values()[0]
-
- def get_theory(self):
- return self.theory_list
-
- def get_message(self):
- """
- return message
- """
- return self.message
-
-
Index: test/guiframe/docs/sphinx/Makefile
===================================================================
--- test/guiframe/docs/sphinx/Makefile (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,130 +1,0 @@
-# Makefile for Sphinx documentation
-#
-
-# You can set these variables from the command line.
-SPHINXOPTS =
-SPHINXBUILD = sphinx-build
-PAPER =
-BUILDDIR = _build
-
-# Internal variables.
-PAPEROPT_a4 = -D latex_paper_size=a4
-PAPEROPT_letter = -D latex_paper_size=letter
-ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
-
-.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest
-
-help:
- @echo "Please use \`make ' where is one of"
- @echo " html to make standalone HTML files"
- @echo " dirhtml to make HTML files named index.html in directories"
- @echo " singlehtml to make a single large HTML file"
- @echo " pickle to make pickle files"
- @echo " json to make JSON files"
- @echo " htmlhelp to make HTML files and a HTML help project"
- @echo " qthelp to make HTML files and a qthelp project"
- @echo " devhelp to make HTML files and a Devhelp project"
- @echo " epub to make an epub"
- @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
- @echo " latexpdf to make LaTeX files and run them through pdflatex"
- @echo " text to make text files"
- @echo " man to make manual pages"
- @echo " changes to make an overview of all changed/added/deprecated items"
- @echo " linkcheck to check all external links for integrity"
- @echo " doctest to run all doctests embedded in the documentation (if enabled)"
-
-clean:
- -rm -rf $(BUILDDIR)/*
-
-html:
- $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
- @echo
- @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
-
-dirhtml:
- $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
- @echo
- @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
-
-singlehtml:
- $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
- @echo
- @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
-
-pickle:
- $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
- @echo
- @echo "Build finished; now you can process the pickle files."
-
-json:
- $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
- @echo
- @echo "Build finished; now you can process the JSON files."
-
-htmlhelp:
- $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
- @echo
- @echo "Build finished; now you can run HTML Help Workshop with the" \
- ".hhp project file in $(BUILDDIR)/htmlhelp."
-
-qthelp:
- $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
- @echo
- @echo "Build finished; now you can run "qcollectiongenerator" with the" \
- ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
- @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/guiframe.qhcp"
- @echo "To view the help file:"
- @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/guiframe.qhc"
-
-devhelp:
- $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
- @echo
- @echo "Build finished."
- @echo "To view the help file:"
- @echo "# mkdir -p $$HOME/.local/share/devhelp/guiframe"
- @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/guiframe"
- @echo "# devhelp"
-
-epub:
- $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
- @echo
- @echo "Build finished. The epub file is in $(BUILDDIR)/epub."
-
-latex:
- $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
- @echo
- @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
- @echo "Run \`make' in that directory to run these through (pdf)latex" \
- "(use \`make latexpdf' here to do that automatically)."
-
-latexpdf: latex
- $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
- @echo "Running LaTeX files through pdflatex..."
- make -C $(BUILDDIR)/latex all-pdf
- @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
-
-text:
- $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
- @echo
- @echo "Build finished. The text files are in $(BUILDDIR)/text."
-
-man:
- $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
- @echo
- @echo "Build finished. The manual pages are in $(BUILDDIR)/man."
-
-changes:
- $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
- @echo
- @echo "The overview file is in $(BUILDDIR)/changes."
-
-linkcheck:
- $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
- @echo
- @echo "Link check complete; look for any errors in the above output " \
- "or in $(BUILDDIR)/linkcheck/output.txt."
-
-doctest:
- $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
- @echo "Testing of doctests in the sources finished, look at the " \
- "results in $(BUILDDIR)/doctest/output.txt."
Index: test/guiframe/docs/sphinx/_extensions/only_directives.py
===================================================================
--- test/guiframe/docs/sphinx/_extensions/only_directives.py (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,63 +1,0 @@
-#
-# A pair of directives for inserting content that will only appear in
-# either html or latex.
-#
-
-from docutils.nodes import Body, Element
-from docutils.parsers.rst import directives
-
-class only_base(Body, Element):
- def dont_traverse(self, *args, **kwargs):
- return []
-
-class html_only(only_base):
- pass
-
-class latex_only(only_base):
- pass
-
-def run(content, node_class, state, content_offset):
- text = '\n'.join(content)
- node = node_class(text)
- state.nested_parse(content, content_offset, node)
- return [node]
-
-def html_only_directive(name, arguments, options, content, lineno,
- content_offset, block_text, state, state_machine):
- return run(content, html_only, state, content_offset)
-
-def latex_only_directive(name, arguments, options, content, lineno,
- content_offset, block_text, state, state_machine):
- return run(content, latex_only, state, content_offset)
-
-def builder_inited(app):
- if app.builder.name == 'html':
- latex_only.traverse = only_base.dont_traverse
- else:
- html_only.traverse = only_base.dont_traverse
-
-def setup(app):
- app.add_directive('htmlonly', html_only_directive, True, (0, 0, 0))
- app.add_directive('latexonly', latex_only_directive, True, (0, 0, 0))
- app.add_node(html_only)
- app.add_node(latex_only)
-
- # This will *really* never see the light of day As it turns out,
- # this results in "broken" image nodes since they never get
- # processed, so best not to do this.
- # app.connect('builder-inited', builder_inited)
-
- # Add visit/depart methods to HTML-Translator:
- def visit_perform(self, node):
- pass
- def depart_perform(self, node):
- pass
- def visit_ignore(self, node):
- node.children = []
- def depart_ignore(self, node):
- node.children = []
-
- app.add_node(html_only, html=(visit_perform, depart_perform))
- app.add_node(html_only, latex=(visit_ignore, depart_ignore))
- app.add_node(latex_only, latex=(visit_perform, depart_perform))
- app.add_node(latex_only, html=(visit_ignore, depart_ignore))
Index: test/guiframe/docs/sphinx/api/aboutbox.rst
===================================================================
--- test/guiframe/docs/sphinx/api/aboutbox.rst (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,15 +1,0 @@
-.. Autogenerated by genmods.py
-
-******************************************************************************
-aboutbox
-******************************************************************************
-
-:mod:`sans.guiframe.aboutbox`
-==============================================================================
-
-.. automodule:: sans.guiframe.aboutbox
- :members:
- :undoc-members:
- :inherited-members:
- :show-inheritance:
-
Index: test/guiframe/docs/sphinx/api/config.rst
===================================================================
--- test/guiframe/docs/sphinx/api/config.rst (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,15 +1,0 @@
-.. Autogenerated by genmods.py
-
-******************************************************************************
-config
-******************************************************************************
-
-:mod:`sans.guiframe.config`
-==============================================================================
-
-.. automodule:: sans.guiframe.config
- :members:
- :undoc-members:
- :inherited-members:
- :show-inheritance:
-
Index: test/guiframe/docs/sphinx/api/dataFitting.rst
===================================================================
--- test/guiframe/docs/sphinx/api/dataFitting.rst (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,15 +1,0 @@
-.. Autogenerated by genmods.py
-
-******************************************************************************
-dataFitting
-******************************************************************************
-
-:mod:`sans.guiframe.dataFitting`
-==============================================================================
-
-.. automodule:: sans.guiframe.dataFitting
- :members:
- :undoc-members:
- :inherited-members:
- :show-inheritance:
-
Index: test/guiframe/docs/sphinx/api/data_loader.rst
===================================================================
--- test/guiframe/docs/sphinx/api/data_loader.rst (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,15 +1,0 @@
-.. Autogenerated by genmods.py
-
-******************************************************************************
-data_loader
-******************************************************************************
-
-:mod:`sans.guiframe.data_loader`
-==============================================================================
-
-.. automodule:: sans.guiframe.data_loader
- :members:
- :undoc-members:
- :inherited-members:
- :show-inheritance:
-
Index: test/guiframe/docs/sphinx/api/dummyapp.rst
===================================================================
--- test/guiframe/docs/sphinx/api/dummyapp.rst (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,15 +1,0 @@
-.. Autogenerated by genmods.py
-
-******************************************************************************
-dummyapp
-******************************************************************************
-
-:mod:`sans.guiframe.dummyapp`
-==============================================================================
-
-.. automodule:: sans.guiframe.dummyapp
- :members:
- :undoc-members:
- :inherited-members:
- :show-inheritance:
-
Index: test/guiframe/docs/sphinx/api/gui_manager.rst
===================================================================
--- test/guiframe/docs/sphinx/api/gui_manager.rst (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,15 +1,0 @@
-.. Autogenerated by genmods.py
-
-******************************************************************************
-gui_manager
-******************************************************************************
-
-:mod:`sans.guiframe.gui_manager`
-==============================================================================
-
-.. automodule:: sans.guiframe.gui_manager
- :members:
- :undoc-members:
- :inherited-members:
- :show-inheritance:
-
Index: test/guiframe/docs/sphinx/api/index.rst
===================================================================
--- test/guiframe/docs/sphinx/api/index.rst (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,25 +1,0 @@
-.. Autogenerated by genmods.py
-
-.. _api-index:
-
-##############################################################################
- Reference
-##############################################################################
-
-.. only:: html
-
- :Release: |version|
- :Date: |today|
-
-.. toctree::
-
- aboutbox.rst
- config.rst
- data_loader.rst
- dataFitting.rst
- dummyapp.rst
- gui_manager.rst
- load_thread.rst
- statusbar.rst
- utils.rst
- version.rst
Index: test/guiframe/docs/sphinx/api/load_thread.rst
===================================================================
--- test/guiframe/docs/sphinx/api/load_thread.rst (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,15 +1,0 @@
-.. Autogenerated by genmods.py
-
-******************************************************************************
-load_thread
-******************************************************************************
-
-:mod:`sans.guiframe.load_thread`
-==============================================================================
-
-.. automodule:: sans.guiframe.load_thread
- :members:
- :undoc-members:
- :inherited-members:
- :show-inheritance:
-
Index: test/guiframe/docs/sphinx/api/local_perspectives/plotting/AnnulusSlicer.rst
===================================================================
--- test/guiframe/docs/sphinx/api/local_perspectives/plotting/AnnulusSlicer.rst (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,15 +1,0 @@
-.. Autogenerated by genmods.py
-
-******************************************************************************
-AnnulusSlicer
-******************************************************************************
-
-:mod:`sans.guiframe.local_perspectives.plotting.AnnulusSlicer`
-==============================================================================
-
-.. automodule:: sans.guiframe.local_perspectives.plotting.AnnulusSlicer
- :members:
- :undoc-members:
- :inherited-members:
- :show-inheritance:
-
Index: test/guiframe/docs/sphinx/api/local_perspectives/plotting/Arc.rst
===================================================================
--- test/guiframe/docs/sphinx/api/local_perspectives/plotting/Arc.rst (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,15 +1,0 @@
-.. Autogenerated by genmods.py
-
-******************************************************************************
-Arc
-******************************************************************************
-
-:mod:`sans.guiframe.local_perspectives.plotting.Arc`
-==============================================================================
-
-.. automodule:: sans.guiframe.local_perspectives.plotting.Arc
- :members:
- :undoc-members:
- :inherited-members:
- :show-inheritance:
-
Index: test/guiframe/docs/sphinx/api/local_perspectives/plotting/AzimutSlicer.rst
===================================================================
--- test/guiframe/docs/sphinx/api/local_perspectives/plotting/AzimutSlicer.rst (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,15 +1,0 @@
-.. Autogenerated by genmods.py
-
-******************************************************************************
-AzimutSlicer
-******************************************************************************
-
-:mod:`sans.guiframe.local_perspectives.plotting.AzimutSlicer`
-==============================================================================
-
-.. automodule:: sans.guiframe.local_perspectives.plotting.AzimutSlicer
- :members:
- :undoc-members:
- :inherited-members:
- :show-inheritance:
-
Index: test/guiframe/docs/sphinx/api/local_perspectives/plotting/BaseInteractor.rst
===================================================================
--- test/guiframe/docs/sphinx/api/local_perspectives/plotting/BaseInteractor.rst (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,15 +1,0 @@
-.. Autogenerated by genmods.py
-
-******************************************************************************
-BaseInteractor
-******************************************************************************
-
-:mod:`sans.guiframe.local_perspectives.plotting.BaseInteractor`
-==============================================================================
-
-.. automodule:: sans.guiframe.local_perspectives.plotting.BaseInteractor
- :members:
- :undoc-members:
- :inherited-members:
- :show-inheritance:
-
Index: test/guiframe/docs/sphinx/api/local_perspectives/plotting/Edge.rst
===================================================================
--- test/guiframe/docs/sphinx/api/local_perspectives/plotting/Edge.rst (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,15 +1,0 @@
-.. Autogenerated by genmods.py
-
-******************************************************************************
-Edge
-******************************************************************************
-
-:mod:`sans.guiframe.local_perspectives.plotting.Edge`
-==============================================================================
-
-.. automodule:: sans.guiframe.local_perspectives.plotting.Edge
- :members:
- :undoc-members:
- :inherited-members:
- :show-inheritance:
-
Index: test/guiframe/docs/sphinx/api/local_perspectives/plotting/Plotter1D.rst
===================================================================
--- test/guiframe/docs/sphinx/api/local_perspectives/plotting/Plotter1D.rst (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,15 +1,0 @@
-.. Autogenerated by genmods.py
-
-******************************************************************************
-Plotter1D
-******************************************************************************
-
-:mod:`sans.guiframe.local_perspectives.plotting.Plotter1D`
-==============================================================================
-
-.. automodule:: sans.guiframe.local_perspectives.plotting.Plotter1D
- :members:
- :undoc-members:
- :inherited-members:
- :show-inheritance:
-
Index: test/guiframe/docs/sphinx/api/local_perspectives/plotting/Plotter2D.rst
===================================================================
--- test/guiframe/docs/sphinx/api/local_perspectives/plotting/Plotter2D.rst (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,15 +1,0 @@
-.. Autogenerated by genmods.py
-
-******************************************************************************
-Plotter2D
-******************************************************************************
-
-:mod:`sans.guiframe.local_perspectives.plotting.Plotter2D`
-==============================================================================
-
-.. automodule:: sans.guiframe.local_perspectives.plotting.Plotter2D
- :members:
- :undoc-members:
- :inherited-members:
- :show-inheritance:
-
Index: test/guiframe/docs/sphinx/api/local_perspectives/plotting/SectorSlicer.rst
===================================================================
--- test/guiframe/docs/sphinx/api/local_perspectives/plotting/SectorSlicer.rst (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,15 +1,0 @@
-.. Autogenerated by genmods.py
-
-******************************************************************************
-SectorSlicer
-******************************************************************************
-
-:mod:`sans.guiframe.local_perspectives.plotting.SectorSlicer`
-==============================================================================
-
-.. automodule:: sans.guiframe.local_perspectives.plotting.SectorSlicer
- :members:
- :undoc-members:
- :inherited-members:
- :show-inheritance:
-
Index: test/guiframe/docs/sphinx/api/local_perspectives/plotting/SlicerParameters.rst
===================================================================
--- test/guiframe/docs/sphinx/api/local_perspectives/plotting/SlicerParameters.rst (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,15 +1,0 @@
-.. Autogenerated by genmods.py
-
-******************************************************************************
-SlicerParameters
-******************************************************************************
-
-:mod:`sans.guiframe.local_perspectives.plotting.SlicerParameters`
-==============================================================================
-
-.. automodule:: sans.guiframe.local_perspectives.plotting.SlicerParameters
- :members:
- :undoc-members:
- :inherited-members:
- :show-inheritance:
-
Index: test/guiframe/docs/sphinx/api/local_perspectives/plotting/binder.rst
===================================================================
--- test/guiframe/docs/sphinx/api/local_perspectives/plotting/binder.rst (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,15 +1,0 @@
-.. Autogenerated by genmods.py
-
-******************************************************************************
-binder
-******************************************************************************
-
-:mod:`sans.guiframe.local_perspectives.plotting.binder`
-==============================================================================
-
-.. automodule:: sans.guiframe.local_perspectives.plotting.binder
- :members:
- :undoc-members:
- :inherited-members:
- :show-inheritance:
-
Index: test/guiframe/docs/sphinx/api/local_perspectives/plotting/boxMask.rst
===================================================================
--- test/guiframe/docs/sphinx/api/local_perspectives/plotting/boxMask.rst (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,15 +1,0 @@
-.. Autogenerated by genmods.py
-
-******************************************************************************
-boxMask
-******************************************************************************
-
-:mod:`sans.guiframe.local_perspectives.plotting.boxMask`
-==============================================================================
-
-.. automodule:: sans.guiframe.local_perspectives.plotting.boxMask
- :members:
- :undoc-members:
- :inherited-members:
- :show-inheritance:
-
Index: test/guiframe/docs/sphinx/api/local_perspectives/plotting/boxSlicer.rst
===================================================================
--- test/guiframe/docs/sphinx/api/local_perspectives/plotting/boxSlicer.rst (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,15 +1,0 @@
-.. Autogenerated by genmods.py
-
-******************************************************************************
-boxSlicer
-******************************************************************************
-
-:mod:`sans.guiframe.local_perspectives.plotting.boxSlicer`
-==============================================================================
-
-.. automodule:: sans.guiframe.local_perspectives.plotting.boxSlicer
- :members:
- :undoc-members:
- :inherited-members:
- :show-inheritance:
-
Index: test/guiframe/docs/sphinx/api/local_perspectives/plotting/boxSum.rst
===================================================================
--- test/guiframe/docs/sphinx/api/local_perspectives/plotting/boxSum.rst (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,15 +1,0 @@
-.. Autogenerated by genmods.py
-
-******************************************************************************
-boxSum
-******************************************************************************
-
-:mod:`sans.guiframe.local_perspectives.plotting.boxSum`
-==============================================================================
-
-.. automodule:: sans.guiframe.local_perspectives.plotting.boxSum
- :members:
- :undoc-members:
- :inherited-members:
- :show-inheritance:
-
Index: test/guiframe/docs/sphinx/api/local_perspectives/plotting/detector_dialog.rst
===================================================================
--- test/guiframe/docs/sphinx/api/local_perspectives/plotting/detector_dialog.rst (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,15 +1,0 @@
-.. Autogenerated by genmods.py
-
-******************************************************************************
-detector_dialog
-******************************************************************************
-
-:mod:`sans.guiframe.local_perspectives.plotting.detector_dialog`
-==============================================================================
-
-.. automodule:: sans.guiframe.local_perspectives.plotting.detector_dialog
- :members:
- :undoc-members:
- :inherited-members:
- :show-inheritance:
-
Index: test/guiframe/docs/sphinx/api/local_perspectives/plotting/index.rst
===================================================================
--- test/guiframe/docs/sphinx/api/local_perspectives/plotting/index.rst (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,33 +1,0 @@
-.. Autogenerated by genmods.py
-
-.. _api-index:
-
-##############################################################################
- Local Perspective: Plotting
-##############################################################################
-
-.. only:: html
-
- :Release: |version|
- :Date: |today|
-
-.. toctree::
-
- AnnulusSlicer.rst
- Arc.rst
- AzimutSlicer.rst
- BaseInteractor.rst
- binder.rst
- boxMask.rst
- boxSlicer.rst
- boxSum.rst
- detector_dialog.rst
- Edge.rst
- masking.rst
- Plotter1D.rst
- Plotter2D.rst
- plotting.rst
- sectorMask.rst
- SectorSlicer.rst
- slicerpanel.rst
- SlicerParameters.rst
Index: test/guiframe/docs/sphinx/api/local_perspectives/plotting/masking.rst
===================================================================
--- test/guiframe/docs/sphinx/api/local_perspectives/plotting/masking.rst (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,15 +1,0 @@
-.. Autogenerated by genmods.py
-
-******************************************************************************
-masking
-******************************************************************************
-
-:mod:`sans.guiframe.local_perspectives.plotting.masking`
-==============================================================================
-
-.. automodule:: sans.guiframe.local_perspectives.plotting.masking
- :members:
- :undoc-members:
- :inherited-members:
- :show-inheritance:
-
Index: test/guiframe/docs/sphinx/api/local_perspectives/plotting/plotting.rst
===================================================================
--- test/guiframe/docs/sphinx/api/local_perspectives/plotting/plotting.rst (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,15 +1,0 @@
-.. Autogenerated by genmods.py
-
-******************************************************************************
-plotting
-******************************************************************************
-
-:mod:`sans.guiframe.local_perspectives.plotting.plotting`
-==============================================================================
-
-.. automodule:: sans.guiframe.local_perspectives.plotting.plotting
- :members:
- :undoc-members:
- :inherited-members:
- :show-inheritance:
-
Index: test/guiframe/docs/sphinx/api/local_perspectives/plotting/sectorMask.rst
===================================================================
--- test/guiframe/docs/sphinx/api/local_perspectives/plotting/sectorMask.rst (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,15 +1,0 @@
-.. Autogenerated by genmods.py
-
-******************************************************************************
-sectorMask
-******************************************************************************
-
-:mod:`sans.guiframe.local_perspectives.plotting.sectorMask`
-==============================================================================
-
-.. automodule:: sans.guiframe.local_perspectives.plotting.sectorMask
- :members:
- :undoc-members:
- :inherited-members:
- :show-inheritance:
-
Index: test/guiframe/docs/sphinx/api/local_perspectives/plotting/slicerpanel.rst
===================================================================
--- test/guiframe/docs/sphinx/api/local_perspectives/plotting/slicerpanel.rst (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,15 +1,0 @@
-.. Autogenerated by genmods.py
-
-******************************************************************************
-slicerpanel
-******************************************************************************
-
-:mod:`sans.guiframe.local_perspectives.plotting.slicerpanel`
-==============================================================================
-
-.. automodule:: sans.guiframe.local_perspectives.plotting.slicerpanel
- :members:
- :undoc-members:
- :inherited-members:
- :show-inheritance:
-
Index: test/guiframe/docs/sphinx/api/statusbar.rst
===================================================================
--- test/guiframe/docs/sphinx/api/statusbar.rst (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,15 +1,0 @@
-.. Autogenerated by genmods.py
-
-******************************************************************************
-statusbar
-******************************************************************************
-
-:mod:`sans.guiframe.statusbar`
-==============================================================================
-
-.. automodule:: sans.guiframe.statusbar
- :members:
- :undoc-members:
- :inherited-members:
- :show-inheritance:
-
Index: test/guiframe/docs/sphinx/api/utils.rst
===================================================================
--- test/guiframe/docs/sphinx/api/utils.rst (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,15 +1,0 @@
-.. Autogenerated by genmods.py
-
-******************************************************************************
-utils
-******************************************************************************
-
-:mod:`sans.guiframe.utils`
-==============================================================================
-
-.. automodule:: sans.guiframe.utils
- :members:
- :undoc-members:
- :inherited-members:
- :show-inheritance:
-
Index: test/guiframe/docs/sphinx/api/version.rst
===================================================================
--- test/guiframe/docs/sphinx/api/version.rst (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,15 +1,0 @@
-.. Autogenerated by genmods.py
-
-******************************************************************************
-version
-******************************************************************************
-
-:mod:`sans.guiframe.version`
-==============================================================================
-
-.. automodule:: sans.guiframe.version
- :members:
- :undoc-members:
- :inherited-members:
- :show-inheritance:
-
Index: test/guiframe/docs/sphinx/conf.py
===================================================================
--- test/guiframe/docs/sphinx/conf.py (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,220 +1,0 @@
-# -*- coding: utf-8 -*-
-#
-# guiframe documentation build configuration file, created by
-# sphinx-quickstart on Thu Jun 03 11:04:06 2010.
-#
-# This file is execfile()d with the current directory set to its containing dir.
-#
-# Note that not all possible configuration values are present in this
-# autogenerated file.
-#
-# All configuration values have a default; values that are commented out
-# serve to show the default.
-
-import sys, os
-
-# If extensions (or modules to document with autodoc) are in another directory,
-# add these directories to sys.path here. If the directory is relative to the
-# documentation root, use os.path.abspath to make it absolute, like shown here.
-sys.path.append(os.path.abspath(os.path.dirname('../../guiframe')))
-path = '../../guiframe/local_perspectives/plotting'
-sys.path.append(os.path.abspath(os.path.dirname(path)))
-sys.path.append(os.path.abspath('_extensions'))
-# -- General configuration -----------------------------------------------------
-
-# If your documentation needs a minimal Sphinx version, state it here.
-#needs_sphinx = '1.0'
-
-# Add any Sphinx extension module names here, as strings. They can be extensions
-# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
-extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest',
- 'sphinx.ext.coverage', 'sphinx.ext.pngmath',
- 'only_directives',
- ]
-# Add any paths that contain templates here, relative to this directory.
-templates_path = ['_templates']
-
-# The suffix of source filenames.
-source_suffix = '.rst'
-
-# The encoding of source files.
-#source_encoding = 'utf-8-sig'
-
-# The master toctree document.
-master_doc = 'index'
-
-# General information about the project.
-project = u'guiframe'
-copyright = u'2010, sans group'
-
-# The version info for the project you're documenting, acts as replacement for
-# |version| and |release|, also used in various other places throughout the
-# built documents.
-#
-# The short X.Y version.
-version = '0.1'
-# The full version, including alpha/beta/rc tags.
-release = '0.1.0'
-
-# The language for content autogenerated by Sphinx. Refer to documentation
-# for a list of supported languages.
-#language = None
-
-# There are two options for replacing |today|: either, you set today to some
-# non-false value, then it is used:
-#today = ''
-# Else, today_fmt is used as the format for a strftime call.
-#today_fmt = '%B %d, %Y'
-
-# List of patterns, relative to source directory, that match files and
-# directories to ignore when looking for source files.
-exclude_patterns = ['_build']
-
-# The reST default role (used for this markup: `text`) to use for all documents.
-#default_role = None
-
-# If true, '()' will be appended to :func: etc. cross-reference text.
-#add_function_parentheses = True
-
-# If true, the current module name will be prepended to all description
-# unit titles (such as .. function::).
-#add_module_names = True
-
-# If true, sectionauthor and moduleauthor directives will be shown in the
-# output. They are ignored by default.
-#show_authors = False
-
-# The name of the Pygments (syntax highlighting) style to use.
-pygments_style = 'sphinx'
-
-# A list of ignored prefixes for module index sorting.
-#modindex_common_prefix = []
-
-
-# -- Options for HTML output ---------------------------------------------------
-
-# The theme to use for HTML and HTML Help pages. Major themes that come with
-# Sphinx are currently 'default' and 'sphinxdoc'.
-html_theme = 'default'
-
-# Theme options are theme-specific and customize the look and feel of a theme
-# further. For a list of options available for each theme, see the
-# documentation.
-#html_theme_options = {}
-
-# Add any paths that contain custom themes here, relative to this directory.
-#html_theme_path = []
-
-# The name for this set of Sphinx documents. If None, it defaults to
-# " v documentation".
-#html_title = None
-
-# A shorter title for the navigation bar. Default is the same as html_title.
-#html_short_title = None
-
-# The name of an image file (relative to this directory) to place at the top
-# of the sidebar.
-#html_logo = None
-
-# The name of an image file (within the static path) to use as favicon of the
-# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
-# pixels large.
-#html_favicon = None
-
-# Add any paths that contain custom static files (such as style sheets) here,
-# relative to this directory. They are copied after the builtin static files,
-# so a file named "default.css" will overwrite the builtin "default.css".
-html_static_path = ['_static']
-
-# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
-# using the given strftime format.
-#html_last_updated_fmt = '%b %d, %Y'
-
-# If true, SmartyPants will be used to convert quotes and dashes to
-# typographically correct entities.
-#html_use_smartypants = True
-
-# Custom sidebar templates, maps document names to template names.
-#html_sidebars = {}
-
-# Additional templates that should be rendered to pages, maps page names to
-# template names.
-#html_additional_pages = {}
-
-# If false, no module index is generated.
-#html_domain_indices = True
-
-# If false, no index is generated.
-#html_use_index = True
-
-# If true, the index is split into individual pages for each letter.
-#html_split_index = False
-
-# If true, links to the reST sources are added to the pages.
-#html_show_sourcelink = True
-
-# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
-#html_show_sphinx = True
-
-# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
-#html_show_copyright = True
-
-# If true, an OpenSearch description file will be output, and all pages will
-# contain a tag referring to it. The value of this option must be the
-# base URL from which the finished HTML is served.
-#html_use_opensearch = ''
-
-# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml").
-#html_file_suffix = ''
-
-# Output file base name for HTML help builder.
-htmlhelp_basename = 'guiframedoc'
-
-
-# -- Options for LaTeX output --------------------------------------------------
-
-# The paper size ('letter' or 'a4').
-#latex_paper_size = 'letter'
-
-# The font size ('10pt', '11pt' or '12pt').
-#latex_font_size = '10pt'
-
-# Grouping the document tree into LaTeX files. List of tuples
-# (source start file, target name, title, author, documentclass [howto/manual]).
-latex_documents = [
- ('index', 'guiframe.tex', u'guiframe Documentation',
- u'sans group', 'manual'),
-]
-
-# The name of an image file (relative to this directory) to place at the top of
-# the title page.
-#latex_logo = None
-
-# For "manual" documents, if this is true, then toplevel headings are parts,
-# not chapters.
-#latex_use_parts = False
-
-# If true, show page references after internal links.
-#latex_show_pagerefs = False
-
-# If true, show URL addresses after external links.
-#latex_show_urls = False
-
-# Additional stuff for the LaTeX preamble.
-#latex_preamble = ''
-
-# Documents to append as an appendix to all manuals.
-#latex_appendices = []
-
-# If false, no module index is generated.
-#latex_domain_indices = True
-
-
-# -- Options for manual page output --------------------------------------------
-
-# One entry per manual page. List of tuples
-# (source start file, name, description, authors, manual section).
-man_pages = [
- ('index', 'guiframe', u'guiframe Documentation',
- [u'sans group'], 1)
-]
Index: test/guiframe/docs/sphinx/genmods.py
===================================================================
--- test/guiframe/docs/sphinx/genmods.py (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,96 +1,0 @@
-from __future__ import with_statement
-import os.path
-
-MODULE_TEMPLATE=""".. Autogenerated by genmods.py
-
-******************************************************************************
-%(name)s
-******************************************************************************
-
-:mod:`%(package)s.%(module)s`
-==============================================================================
-
-.. automodule:: %(package)s.%(module)s
- :members:
- :undoc-members:
- :inherited-members:
- :show-inheritance:
-
-"""
-
-INDEX_TEMPLATE=""".. Autogenerated by genmods.py
-
-.. _api-index:
-
-##############################################################################
- %(package_name)s
-##############################################################################
-
-.. only:: html
-
- :Release: |version|
- :Date: |today|
-
-.. toctree::
-
- %(rsts)s
-"""
-
-
-def genfiles(package, package_name, modules, dir='api'):
-
- if not os.path.exists(dir):
- os.makedirs(dir)
-
- for module,name in modules:
- with open(os.path.join(dir,module+'.rst'), 'w') as f:
- f.write(MODULE_TEMPLATE%locals())
-
- rsts = "\n ".join(module+'.rst' for module,name in modules)
- with open(os.path.join(dir,'index.rst'),'w') as f:
- f.write(INDEX_TEMPLATE%locals())
-
-
-modules=[
- ('aboutbox', 'aboutbox'),
- ('config', 'config'),
- ('data_loader', 'data_loader'),
- ('dataFitting', 'dataFitting'),
- ('dummyapp', 'dummyapp'),
- ('gui_manager', 'gui_manager'),
- ('load_thread', 'load_thread'),
- ('statusbar', 'statusbar'),
- ('utils', 'utils'),
- ('version', 'version'),
-]
-package = 'sans.guiframe'
-package_name='Reference'
-
-if __name__ == "__main__":
- genfiles(package, package_name, modules, dir='api')
-
- modules=[
- ('AnnulusSlicer', 'AnnulusSlicer'),
- ('Arc', 'Arc'),
- ('AzimutSlicer', 'AzimutSlicer'),
- ('BaseInteractor', 'BaseInteractor'),
- ('binder', 'binder'),
- ('boxMask', 'boxMask'),
- ('boxSlicer', 'boxSlicer'),
- ('boxSum', 'boxSum'),
- ('detector_dialog', 'detector_dialog'),
- ('Edge', 'Edge'),
- ('masking', 'masking'),
- ('Plotter1D', 'Plotter1D'),
- ('Plotter2D', 'Plotter2D'),
- ('plotting', 'plotting'),
- ('sectorMask', 'sectorMask'),
- ('SectorSlicer', 'SectorSlicer'),
- ('slicerpanel', 'slicerpanel'),
- ('SlicerParameters', 'SlicerParameters'),
- ]
- package = 'sans.guiframe.local_perspectives.plotting'
- package_name = 'Local Perspective: Plotting'
- genfiles(package, package_name, modules, dir='api/local_perspectives/plotting')
- print "Sphinx: generate .rst files complete..."
-
Index: test/guiframe/docs/sphinx/index.rst
===================================================================
--- test/guiframe/docs/sphinx/index.rst (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,23 +1,0 @@
-.. guiframe documentation master file, created by
- sphinx-quickstart on Thu Jun 03 11:04:06 2010.
- You can adapt this file completely to your liking, but it should at least
- contain the root `toctree` directive.
-
-Welcome to guiframe's documentation!
-====================================
-
-Contents:
-
-.. toctree::
- :maxdepth: 2
-
- api/index.rst
- api/local_perspectives/plotting/index.rst
-
-Indices and tables
-==================
-
-* :ref:`genindex`
-* :ref:`modindex`
-* :ref:`search`
-
Index: test/guiframe/docs/sphinx/make.bat
===================================================================
--- test/guiframe/docs/sphinx/make.bat (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,155 +1,0 @@
-@ECHO OFF
-
-REM Command file for Sphinx documentation
-
-if "%SPHINXBUILD%" == "" (
- set SPHINXBUILD=sphinx-build
-)
-set BUILDDIR=_build
-set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
-if NOT "%PAPER%" == "" (
- set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
-)
-
-if "%1" == "" goto help
-
-if "%1" == "help" (
- :help
- echo.Please use `make ^` where ^ is one of
- echo. html to make standalone HTML files
- echo. dirhtml to make HTML files named index.html in directories
- echo. singlehtml to make a single large HTML file
- echo. pickle to make pickle files
- echo. json to make JSON files
- echo. htmlhelp to make HTML files and a HTML help project
- echo. qthelp to make HTML files and a qthelp project
- echo. devhelp to make HTML files and a Devhelp project
- echo. epub to make an epub
- echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
- echo. text to make text files
- echo. man to make manual pages
- echo. changes to make an overview over all changed/added/deprecated items
- echo. linkcheck to check all external links for integrity
- echo. doctest to run all doctests embedded in the documentation if enabled
- goto end
-)
-
-if "%1" == "clean" (
- for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
- del /q /s %BUILDDIR%\*
- goto end
-)
-
-if "%1" == "html" (
- %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
- echo.
- echo.Build finished. The HTML pages are in %BUILDDIR%/html.
- goto end
-)
-
-if "%1" == "dirhtml" (
- %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
- echo.
- echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
- goto end
-)
-
-if "%1" == "singlehtml" (
- %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
- echo.
- echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
- goto end
-)
-
-if "%1" == "pickle" (
- %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
- echo.
- echo.Build finished; now you can process the pickle files.
- goto end
-)
-
-if "%1" == "json" (
- %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
- echo.
- echo.Build finished; now you can process the JSON files.
- goto end
-)
-
-if "%1" == "htmlhelp" (
- %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
- echo.
- echo.Build finished; now you can run HTML Help Workshop with the ^
-.hhp project file in %BUILDDIR%/htmlhelp.
- goto end
-)
-
-if "%1" == "qthelp" (
- %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
- echo.
- echo.Build finished; now you can run "qcollectiongenerator" with the ^
-.qhcp project file in %BUILDDIR%/qthelp, like this:
- echo.^> qcollectiongenerator %BUILDDIR%\qthelp\guiframe.qhcp
- echo.To view the help file:
- echo.^> assistant -collectionFile %BUILDDIR%\qthelp\guiframe.ghc
- goto end
-)
-
-if "%1" == "devhelp" (
- %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
- echo.
- echo.Build finished.
- goto end
-)
-
-if "%1" == "epub" (
- %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
- echo.
- echo.Build finished. The epub file is in %BUILDDIR%/epub.
- goto end
-)
-
-if "%1" == "latex" (
- %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
- echo.
- echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
- goto end
-)
-
-if "%1" == "text" (
- %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
- echo.
- echo.Build finished. The text files are in %BUILDDIR%/text.
- goto end
-)
-
-if "%1" == "man" (
- %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
- echo.
- echo.Build finished. The manual pages are in %BUILDDIR%/man.
- goto end
-)
-
-if "%1" == "changes" (
- %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
- echo.
- echo.The overview file is in %BUILDDIR%/changes.
- goto end
-)
-
-if "%1" == "linkcheck" (
- %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
- echo.
- echo.Link check complete; look for any errors in the above output ^
-or in %BUILDDIR%/linkcheck/output.txt.
- goto end
-)
-
-if "%1" == "doctest" (
- %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
- echo.
- echo.Testing of doctests in the sources finished, look at the ^
-results in %BUILDDIR%/doctest/output.txt.
- goto end
-)
-
-:end
Index: test/guiframe/dummyapp.py
===================================================================
--- test/guiframe/dummyapp.py (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,125 +1,0 @@
-"""
-Dummy application.
-Allows the user to set an external data manager
-"""
-import gui_manager
-
-from sans.guiframe.plugin_base import PluginBase
-
-class DummyView(gui_manager.ViewApp):
- """
- """
-
-class TestPlugin(PluginBase):
-
- def populate_menu(self, parent):
- """
- Create and return the list of application menu
- items for the plug-in.
- :param parent: parent window
-
- :return: plug-in menu
-
- """
- import wx
- # Create a menu
- plug_menu = wx.Menu()
-
- # Always get event IDs from wx
- id = wx.NewId()
-
- # Fill your menu
- plug_menu.Append(id, '&Do something')
- def _on_do_something(event):
- print "Do something"
- wx.EVT_MENU(self.parent, id, _on_do_something)
-
- # Returns the menu and a name for it.
- return [(plug_menu, "DummyApp")]
-
- def get_panels(self, parent):
- """
- Create and return the list of wx.Panels for your plug-in.
- Define the plug-in perspective.
-
- Panels should inherit from DefaultPanel defined below,
- or should present the same interface. They must define
- "window_caption" and "window_name".
-
- :param parent: parent window
-
- :return: list of panels
-
- """
- ## Save a reference to the parent
- self.parent = parent
-
- # Define a panel
- defaultpanel = gui_manager.DefaultPanel(self.parent, -1)
- defaultpanel.window_name = "Test"
-
- # If needed, add its name to the perspective list
- self.perspective = [defaultpanel.window_name]
-
- # Return the list of panels
- return [defaultpanel]
-
- def get_tools(self):
- """
- Returns a set of menu entries for tools
- """
- def _test_dialog(event):
- import wx
- frame = wx.Dialog(None, -1, 'Test Tool')
- frame.Show(True)
- return [["Tool 1", "This is an example tool", _test_dialog],
- ["Tool 2", "This is another example tool", _test_dialog]]
-
- def get_context_menu(self, graph=None):
- """
- This method is optional.
-
- When the context menu of a plot is rendered, the
- get_context_menu method will be called to give you a
- chance to add a menu item to the context menu.
-
- A ref to a Graph object is passed so that you can
- investigate the plot content and decide whether you
- need to add items to the context menu.
-
- This method returns a list of menu items.
- Each item is itself a list defining the text to
- appear in the menu, a tool-tip help text, and a
- call-back method.
-
- :param graph: the Graph object to which we attach the context menu
-
- :return: a list of menu items with call-back function
- """
- return [["Menu text",
- "Tool-tip help text",
- self._on_context_do_something]]
-
-class SansView():
-
- def __init__(self):
- """
- Initialization
- """
- self.gui = DummyView(0)
-
- fitting_plug = TestPlugin()
- self.gui.add_perspective(fitting_plug)
-
- # Build the GUI
- self.gui.build_gui()
-
- # Set the application manager for the GUI
- self.gui.set_manager(self)
-
- # Start the main loop
- self.gui.MainLoop()
-
-if __name__ == "__main__":
- sansview = SansView()
-
Index: test/guiframe/events.py
===================================================================
--- test/guiframe/events.py (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,30 +1,0 @@
-import wx.lib.newevent
-#send data to data manager
-(NewStoreDataEvent, EVT_NEW_STORE_DATA) = wx.lib.newevent.NewEvent()
-# send data to other perspectives
-(NewLoadedDataEvent, EVT_NEW_LOADED_DATA) = wx.lib.newevent.NewEvent()
-# plot data
-(NewPlotEvent, EVT_NEW_PLOT) = wx.lib.newevent.NewEvent()
-# print the messages on statusbar
-(StatusEvent, EVT_STATUS) = wx.lib.newevent.NewEvent()
-#create a panel slicer
-(SlicerPanelEvent, EVT_SLICER_PANEL) = wx.lib.newevent.NewEvent()
-#print update paramaters for panel slicer
-(SlicerParamUpdateEvent, EVT_SLICER_PARS_UPDATE) = wx.lib.newevent.NewEvent()
-#update the slicer from the panel
-(SlicerParameterEvent, EVT_SLICER_PARS) = wx.lib.newevent.NewEvent()
-#slicer event
-(SlicerEvent, EVT_SLICER) = wx.lib.newevent.NewEvent()
-## event that that destroy panel name in the datapanel combobox
-(DeletePlotPanelEvent, EVT_DELETE_PLOTPANEL) = wx.lib.newevent.NewEvent()
-##event that allow to add more that to the same plot
-(AddManyDataEvent, EVT_ADD_MANY_DATA) = wx.lib.newevent.NewEvent()
-##event for the panel on focus
-(PanelOnFocusEvent, EVT_PANEL_ON_FOCUS) = wx.lib.newevent.NewEvent()
-#book mark event
-(AppendBookmarkEvent, EVT_APPEND_BOOKMARK) = wx.lib.newevent.NewEvent()
-#event to ask dataloader plugin to load data if dataloader plugin exist
-(NewLoadDataEvent, EVT_NEW_LOAD_DATA) = wx.lib.newevent.NewEvent()
-#event to toggle from single model to batch
-(NewBatchEvent, EVT_NEW_BATCH) = wx.lib.newevent.NewEvent()
-
Index: test/guiframe/gui_manager.py
===================================================================
--- test/guiframe/gui_manager.py (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,2748 +1,0 @@
-
-################################################################################
-#This software was developed by the University of Tennessee as part of the
-#Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
-#project funded by the US National Science Foundation.
-#
-#See the license text in license.txt
-#
-#copyright 2008, University of Tennessee
-################################################################################
-
-
-import wx
-import wx.aui
-import os
-import sys
-import xml
-
-
-# Try to find a local config
-import imp
-DATAPATH = os.getcwd()
-tem_path = sys.path[0]
-if os.path.isfile(tem_path):
- tem_path = os.path.dirname(tem_path)
-os.chdir(tem_path)
-PATH_APP = os.getcwd()
-if(os.path.isfile("%s/%s.py" % (PATH_APP, 'local_config'))) or \
- (os.path.isfile("%s/%s.pyc" % (PATH_APP, 'local_config'))):
- fObj, path_config, descr = imp.find_module('local_config', [PATH_APP])
- try:
- config = imp.load_module('local_config', fObj, path_config, descr)
- except:
- # Didn't find local config, load the default
- import config
- finally:
- if fObj:
- fObj.close()
-else:
- # Try simply importing local_config
- import local_config as config
-
-#import compileall
-import py_compile
-
-c_name = os.path.join(PATH_APP, 'custom_config.py')
-if(os.path.isfile("%s/%s.py" % (PATH_APP, 'custom_config'))):
- py_compile.compile(file=c_name)
- #compileall.compile_dir(dir=path, force=True, quiet=0)
- cfObj, path_cconfig, descr = imp.find_module('custom_config', [PATH_APP])
-try:
- custom_config = imp.load_module('custom_config', cfObj, PATH_APP, descr)
-except:
- custom_config = None
-finally:
- if custom_config != None:
- cfObj.close()
-
-
-import warnings
-warnings.simplefilter("ignore")
-
-import logging
-
-from sans.guiframe.events import EVT_STATUS
-from sans.guiframe.events import EVT_APPEND_BOOKMARK
-from sans.guiframe.events import EVT_PANEL_ON_FOCUS
-from sans.guiframe.events import EVT_NEW_LOAD_DATA
-from sans.guiframe.events import StatusEvent
-from sans.guiframe.events import NewPlotEvent
-from sans.guiframe.gui_style import GUIFRAME
-from sans.guiframe.gui_style import GUIFRAME_ID
-#from sans.guiframe.events import NewLoadedDataEvent
-from sans.guiframe.data_panel import DataPanel
-from sans.guiframe.panel_base import PanelBase
-from sans.guiframe.gui_toolbar import GUIToolBar
-from sans.guiframe.data_processor import GridFrame
-from sans.guiframe.events import EVT_NEW_BATCH
-from DataLoader.loader import Loader
-
-
-#read some constants from config
-APPLICATION_STATE_EXTENSION = config.APPLICATION_STATE_EXTENSION
-APPLICATION_NAME = config.__appname__
-SPLASH_SCREEN_PATH = config.SPLASH_SCREEN_PATH
-
-SPLASH_SCREEN_WIDTH = config.SPLASH_SCREEN_WIDTH
-SPLASH_SCREEN_HEIGHT = config.SPLASH_SCREEN_HEIGHT
-SS_MAX_DISPLAY_TIME = config.SS_MAX_DISPLAY_TIME
-
-try:
- DATALOADER_SHOW = custom_config.DATALOADER_SHOW
- TOOLBAR_SHOW = custom_config.TOOLBAR_SHOW
- FIXED_PANEL = custom_config.FIXED_PANEL
- WELCOME_PANEL_SHOW = custom_config.WELCOME_PANEL_SHOW
- PLOPANEL_WIDTH = custom_config.PLOPANEL_WIDTH
- DATAPANEL_WIDTH = custom_config.DATAPANEL_WIDTH
- GUIFRAME_WIDTH = custom_config.GUIFRAME_WIDTH
- GUIFRAME_HEIGHT = custom_config.GUIFRAME_HEIGHT
- DEFAULT_PERSPECTIVE = custom_config.DEFAULT_PERSPECTIVE
- CLEANUP_PLOT = custom_config.CLEANUP_PLOT
-except:
- DATALOADER_SHOW = True
- TOOLBAR_SHOW = True
- FIXED_PANEL = True
- WELCOME_PANEL_SHOW = False
- PLOPANEL_WIDTH = config.PLOPANEL_WIDTH
- DATAPANEL_WIDTH = config.DATAPANEL_WIDTH
- GUIFRAME_WIDTH = config.GUIFRAME_WIDTH
- GUIFRAME_HEIGHT = config.GUIFRAME_HEIGHT
- DEFAULT_PERSPECTIVE = None
- CLEANUP_PLOT = False
-
-DEFAULT_STYLE = config.DEFAULT_STYLE
-
-
-PLOPANEL_HEIGTH = config.PLOPANEL_HEIGTH
-DATAPANEL_HEIGHT = config.DATAPANEL_HEIGHT
-PLUGIN_STATE_EXTENSIONS = config.PLUGIN_STATE_EXTENSIONS
-OPEN_SAVE_MENU = config.OPEN_SAVE_PROJECT_MENU
-VIEW_MENU = config.VIEW_MENU
-EDIT_MENU = config.EDIT_MENU
-extension_list = []
-if APPLICATION_STATE_EXTENSION is not None:
- extension_list.append(APPLICATION_STATE_EXTENSION)
-EXTENSIONS = PLUGIN_STATE_EXTENSIONS + extension_list
-try:
- PLUGINS_WLIST = '|'.join(config.PLUGINS_WLIST)
-except:
- PLUGINS_WLIST = ''
-APPLICATION_WLIST = config.APPLICATION_WLIST
-if sys.platform.count("darwin")==0:
- IS_WIN = True
-else:
- IS_WIN = False
-
-class ViewerFrame(wx.Frame):
- """
- Main application frame
- """
-
- def __init__(self, parent, title,
- size=(GUIFRAME_WIDTH, GUIFRAME_HEIGHT),
- gui_style=DEFAULT_STYLE,
- pos=wx.DefaultPosition):
- """
- Initialize the Frame object
- """
-
- wx.Frame.__init__(self, parent=parent, title=title, pos=pos,size=size)
- # title
- self.title = title
- # Preferred window size
- self._window_width, self._window_height = size
- self.__gui_style = gui_style
- # Logging info
- logging.basicConfig(level=logging.DEBUG,
- format='%(asctime)s %(levelname)s %(message)s',
- filename='sans_app.log',
- filemode='w')
- path = os.path.dirname(__file__)
- temp_path = os.path.join(path,'images')
- ico_file = os.path.join(temp_path,'ball.ico')
- if os.path.isfile(ico_file):
- self.SetIcon(wx.Icon(ico_file, wx.BITMAP_TYPE_ICO))
- else:
- temp_path = os.path.join(os.getcwd(),'images')
- ico_file = os.path.join(temp_path,'ball.ico')
- if os.path.isfile(ico_file):
- self.SetIcon(wx.Icon(ico_file, wx.BITMAP_TYPE_ICO))
- else:
- ico_file = os.path.join(os.path.dirname(os.path.sys.path[0]),
- 'images', 'ball.ico')
- if os.path.isfile(ico_file):
- self.SetIcon(wx.Icon(ico_file, wx.BITMAP_TYPE_ICO))
- self.path = PATH_APP
- ## Application manager
- self._input_file = None
- self.app_manager = None
- self._mgr = None
- #add current perpsective
- self._current_perspective = None
- self._plotting_plugin = None
- self._data_plugin = None
- #Menu bar and item
- self._menubar = None
- self._file_menu = None
- self._data_menu = None
- self._view_menu = None
- self._window_menu = None
- self._data_panel_menu = None
- self._help_menu = None
- self._tool_menu = None
- self._applications_menu_pos = -1
- self._applications_menu_name = None
- self._applications_menu = None
- self._edit_menu = None
- self._toolbar_menu = None
- self._save_appl_menu = None
- #tool bar
- self._toolbar = None
- # number of plugins
- self._num_perspectives = 0
- # plot duck cleanup option
- self.cleanup_plots = CLEANUP_PLOT
- # (un)-focus color
- #self.color = '#b3b3b3'
- ## Find plug-ins
- # Modify this so that we can specify the directory to look into
- self.plugins = []
- #add local plugin
- self.plugins += self._get_local_plugins()
- self.plugins += self._find_plugins()
- ## List of panels
- self.panels = {}
- # List of plot panels
- self.plot_panels = {}
-
- # Default locations
- self._default_save_location = os.getcwd()
-
- # Welcome panel
- self.defaultPanel = None
- #panel on focus
- self.panel_on_focus = None
- #control_panel on focus
- self.cpanel_on_focus = None
- self.loader = Loader()
- #data manager
- from data_manager import DataManager
- self._data_manager = DataManager()
- self._data_panel = DataPanel(parent=self)
- if self.panel_on_focus is not None:
- self._data_panel.set_panel_on_focus(self.panel_on_focus.window_caption)
- # list of plot panels in schedule to full redraw
- self.schedule = False
- #self.callback = True
- self._idle_count = 0
- self.schedule_full_draw_list = []
- self.idletimer = wx.CallLater(1, self._onDrawIdle)
-
- self.batch_frame = GridFrame(parent=self)
- self.batch_frame.Hide()
- # Check for update
- #self._check_update(None)
- # Register the close event so it calls our own method
- wx.EVT_CLOSE(self, self.Close)
- # Register to status events
- self.Bind(EVT_STATUS, self._on_status_event)
- #Register add extra data on the same panel event on load
- self.Bind(EVT_PANEL_ON_FOCUS, self.set_panel_on_focus)
- self.Bind(EVT_APPEND_BOOKMARK, self.append_bookmark)
- self.Bind(EVT_NEW_LOAD_DATA, self.on_load_data)
- self.Bind(EVT_NEW_BATCH, self.on_batch_selection)
- self.setup_custom_conf()
-
- def on_set_batch_result(self, data, name):
- """
- Display data into a grid in batch mode and show the grid
- """
- self.batch_frame.set_data(data)
- self.batch_frame.Show(True)
-
-
- def on_batch_selection(self, event):
- """
- :param event: contains parameter enable . when enable is set to True
- the application is in Batch mode
- else the application is default mode(single mode)
- """
- self.batch_on = event.enable
- for plug in self.plugins:
- plug.set_batch_selection(self.batch_on)
-
- def setup_custom_conf(self):
- """
- Set up custom configuration if exists
- """
- if custom_config == None:
- return
-
- if not FIXED_PANEL:
- self.__gui_style &= (~GUIFRAME.FIXED_PANEL)
- self.__gui_style |= GUIFRAME.FLOATING_PANEL
-
- if not DATALOADER_SHOW:
- self.__gui_style &= (~GUIFRAME.MANAGER_ON)
-
- if not TOOLBAR_SHOW:
- self.__gui_style &= (~GUIFRAME.TOOLBAR_ON)
-
- if WELCOME_PANEL_SHOW:
- self.__gui_style |= GUIFRAME.WELCOME_PANEL_ON
-
- def set_custom_default_perspective(self):
- """
- Set default starting perspective
- """
- if custom_config == None:
- return
- for plugin in self.plugins:
- try:
- if plugin.sub_menu == DEFAULT_PERSPECTIVE:
-
- plugin.on_perspective(event=None)
- #self._check_applications_menu()
- break
- except:
- pass
- return
-
- def on_load_data(self, event):
- """
- received an event to trigger load from data plugin
- """
- if self._data_plugin is not None:
- self._data_plugin.load_data(event)
-
- def get_current_perspective(self):
- """
- return the current perspective
- """
- return self._current_perspective
-
- def set_input_file(self, input_file):
- """
- :param input_file: file to read
- """
- self._input_file = input_file
-
- def get_data_manager(self):
- """
- """
- return self._data_manager
-
- def get_toolbar(self):
- """
- """
- return self._toolbar
-
- def set_panel_on_focus(self, event):
- """
- Store reference to the last panel on focus
- update the toolbar if available
- update edit menu if available
- """
- if event != None:
- self.panel_on_focus = event.panel
- panel_name = 'No panel on focus'
- application_name = 'No Selected Analysis'
- if self.panel_on_focus is not None:
- if self.panel_on_focus not in self.plot_panels.values():
- for ID in self.panels.keys():
- if self.panel_on_focus != self.panels[ID]:
- self.panels[ID].on_kill_focus(None)
-
- if self._data_panel is not None and \
- self.panel_on_focus is not None:
- panel_name = self.panel_on_focus.window_caption
- ID = self.panel_on_focus.uid
- self._data_panel.set_panel_on_focus(ID)
- #update combo
- if self.panel_on_focus in self.plot_panels.values():
- combo = self._data_panel.cb_plotpanel
- combo_title = str(self.panel_on_focus.window_caption)
- combo.SetStringSelection(combo_title)
- combo.SetToolTip( wx.ToolTip(combo_title ))
- elif self.panel_on_focus != self._data_panel:
- cpanel = self.panel_on_focus
- if self.cpanel_on_focus != cpanel:
- self.cpanel_on_focus = self.panel_on_focus
- #update toolbar
- self._update_toolbar_helper()
- #update edit menu
- self.enable_edit_menu()
-
- def reset_bookmark_menu(self, panel):
- """
- Reset Bookmark menu list
-
- : param panel: a control panel or tap where the bookmark is
- """
- cpanel = panel
- if self._toolbar != None and cpanel._bookmark_flag:
- for item in self._toolbar.get_bookmark_items():
- self._toolbar.remove_bookmark_item(item)
- self._toolbar.add_bookmark_default()
- pos = 0
- for bitem in cpanel.popUpMenu.GetMenuItems():
- pos += 1
- if pos < 3:
- continue
- id = bitem.GetId()
- label = bitem.GetLabel()
- self._toolbar.append_bookmark_item(id, label)
- wx.EVT_MENU(self, id, cpanel._back_to_bookmark)
- self._toolbar.Realize()
-
-
- def build_gui(self):
- """
- """
- # set tool bar
- self._setup_tool_bar()
- # Set up the layout
- self._setup_layout()
-
- # Set up the menu
- self._setup_menus()
-
- try:
- self.load_from_cmd(self._input_file)
- except:
- msg = "%s Cannot load file %s\n" %(str(APPLICATION_NAME),
- str(self._input_file))
- msg += str(sys.exc_value) + '\n'
- print msg
- if self._data_panel is not None:
- self._data_panel.fill_cbox_analysis(self.plugins)
- self.post_init()
- # Set Custom default
- self.set_custom_default_perspective()
- # Set up extra custom tool menu
- self._setup_extra_custom()
- #self.Show(True)
- #self._check_update(None)
-
- def _setup_extra_custom(self):
- """
- Set up toolbar and welcome view if needed
- """
- style = self.__gui_style & GUIFRAME.TOOLBAR_ON
- if (style == GUIFRAME.TOOLBAR_ON) & (not self._toolbar.IsShown()):
- self._on_toggle_toolbar()
-
- # Set Custom deafult start page
- welcome_style = self.__gui_style & GUIFRAME.WELCOME_PANEL_ON
- if welcome_style == GUIFRAME.WELCOME_PANEL_ON:
- self.show_welcome_panel(None)
-
- def _setup_layout(self):
- """
- Set up the layout
- """
- # Status bar
- from gui_statusbar import StatusBar
- self.sb = StatusBar(self, wx.ID_ANY)
- self.SetStatusBar(self.sb)
- # Add panel
- default_flag = wx.aui.AUI_MGR_DEFAULT#| wx.aui.AUI_MGR_ALLOW_ACTIVE_PANE
- self._mgr = wx.aui.AuiManager(self, flags=default_flag)
- self._mgr.SetDockSizeConstraint(0.5, 0.5)
- # border color
- #self.b_color = wx.aui.AUI_DOCKART_BORDER_COLOUR
- #self._mgr.GetArtProvider().SetColor(self.b_color, self.color)
- #self._mgr.SetArtProvider(wx.aui.AuiDockArt(wx.AuiDefaultDockArt))
- #print "set", self._dockart.GetColour(13)
- # Load panels
- self._load_panels()
- self.set_default_perspective()
- self._mgr.Update()
-
- def SetStatusText(self, *args, **kwds):
- """
- """
- number = self.sb.get_msg_position()
- wx.Frame.SetStatusText(number=number, *args, **kwds)
-
- def PopStatusText(self, *args, **kwds):
- """
- """
- field = self.sb.get_msg_position()
- wx.Frame.PopStatusText(field=field)
-
- def PushStatusText(self, *args, **kwds):
- """
- """
- field = self.sb.get_msg_position()
- wx.Frame.PushStatusText(self, field=field, string=string)
-
- def add_perspective(self, plugin):
- """
- Add a perspective if it doesn't already
- exist.
- """
- self._num_perspectives += 1
- is_loaded = False
- for item in self.plugins:
- if plugin.__class__ == item.__class__:
- msg = "Plugin %s already loaded" % plugin.sub_menu
- logging.info(msg)
- is_loaded = True
- if not is_loaded:
-
- self.plugins.append(plugin)
-
-
- def _get_local_plugins(self):
- """
- get plugins local to guiframe and others
- """
- plugins = []
- #import guiframe local plugins
- #check if the style contain guiframe.dataloader
- style1 = self.__gui_style & GUIFRAME.DATALOADER_ON
- style2 = self.__gui_style & GUIFRAME.PLOTTING_ON
- if style1 == GUIFRAME.DATALOADER_ON:
- try:
- from sans.guiframe.local_perspectives.data_loader import data_loader
- self._data_plugin = data_loader.Plugin()
- plugins.append(self._data_plugin)
- except:
- msg = "ViewerFrame._get_local_plugins:"
- msg += "cannot import dataloader plugin.\n %s" % sys.exc_value
- logging.error(msg)
- if style2 == GUIFRAME.PLOTTING_ON:
- try:
- from sans.guiframe.local_perspectives.plotting import plotting
- self._plotting_plugin = plotting.Plugin()
- plugins.append(self._plotting_plugin)
- except:
- msg = "ViewerFrame._get_local_plugins:"
- msg += "cannot import plotting plugin.\n %s" % sys.exc_value
- logging.error(msg)
-
- return plugins
-
- def _find_plugins(self, dir="perspectives"):
- """
- Find available perspective plug-ins
-
- :param dir: directory in which to look for plug-ins
-
- :return: list of plug-ins
-
- """
- import imp
- plugins = []
- # Go through files in panels directory
- try:
- list = os.listdir(dir)
- ## the default panel is the panel is the last plugin added
- for item in list:
- toks = os.path.splitext(os.path.basename(item))
- name = ''
- if not toks[0] == '__init__':
- if toks[1] == '.py' or toks[1] == '':
- name = toks[0]
- #check the validity of the module name parsed
- #before trying to import it
- if name is None or name.strip() == '':
- continue
- path = [os.path.abspath(dir)]
- file = ''
- try:
- if toks[1] == '':
- mod_path = '.'.join([dir, name])
- module = __import__(mod_path, globals(),
- locals(), [name])
- else:
- (file, path, info) = imp.find_module(name, path)
- module = imp.load_module( name, file, item, info)
- if hasattr(module, "PLUGIN_ID"):
- try:
- plug = module.Plugin()
- if plug.set_default_perspective():
- self._current_perspective = plug
- plugins.append(plug)
-
- msg = "Found plug-in: %s" % module.PLUGIN_ID
- logging.info(msg)
- except:
- msg = "Error accessing PluginPanel"
- msg += " in %s\n %s" % (name, sys.exc_value)
- config.printEVT(msg)
- except:
- msg = "ViewerFrame._find_plugins: %s" % sys.exc_value
- #print msg
- logging.error(msg)
- finally:
- if not file == None:
- file.close()
- except:
- # Should raise and catch at a higher level and
- # display error on status bar
- pass
-
- return plugins
-
- def set_welcome_panel(self, panel_class):
- """
- Sets the default panel as the given welcome panel
-
- :param panel_class: class of the welcome panel to be instantiated
-
- """
- self.defaultPanel = panel_class(self, -1, style=wx.RAISED_BORDER)
-
- def _get_panels_size(self, p):
- """
- find the proper size of the current panel
- get the proper panel width and height
- """
- panel_height_min = self._window_height
- panel_width_min = self._window_width
- style = self.__gui_style & (GUIFRAME.MANAGER_ON)
- if self._data_panel is not None and (p == self._data_panel):
- panel_width_min = DATAPANEL_WIDTH
- panel_height_min = self._window_height * 0.8
- return panel_width_min, panel_height_min
- if hasattr(p, "CENTER_PANE") and p.CENTER_PANE:
- style = self.__gui_style & (GUIFRAME.PLOTTING_ON|GUIFRAME.MANAGER_ON)
- if style == (GUIFRAME.PLOTTING_ON|GUIFRAME.MANAGER_ON):
- panel_width_min = self._window_width -\
- (DATAPANEL_WIDTH +config.PLOPANEL_WIDTH)
- return panel_width_min, panel_height_min
- return panel_width_min, panel_height_min
-
- def _load_panels(self):
- """
- Load all panels in the panels directory
- """
-
- # Look for plug-in panels
- panels = []
- for item in self.plugins:
- if hasattr(item, "get_panels"):
- ps = item.get_panels(self)
- panels.extend(ps)
-
- # Show a default panel with some help information
- # It also sets the size of the application windows
- #TODO: Use this for slpash screen
- if self.defaultPanel is None:
- self.defaultPanel = DefaultPanel(self, -1, style=wx.RAISED_BORDER)
- # add a blank default panel always present
- self.panels["default"] = self.defaultPanel
- self._mgr.AddPane(self.defaultPanel, wx.aui.AuiPaneInfo().
- Name("default").
- CenterPane().
- #CloseButton(False).
- #MinimizeButton(False).
- # This is where we set the size of
- # the application window
- BestSize(wx.Size(self._window_width,
- self._window_height)).
- Show())
-
- #add data panel
- self.panels["data_panel"] = self._data_panel
- w, h = self._get_panels_size(self._data_panel)
- self._mgr.AddPane(self._data_panel, wx.aui.AuiPaneInfo().
- Name(self._data_panel.window_name).
- Caption(self._data_panel.window_caption).
- Left().
- MinimizeButton().
- CloseButton(IS_WIN).
- TopDockable(False).
- BottomDockable(False).
- LeftDockable(True).
- RightDockable(False).
- BestSize(wx.Size(w, h)).
- Hide())
-
- style = self.__gui_style & GUIFRAME.MANAGER_ON
- data_pane = self._mgr.GetPane(self.panels["data_panel"].window_name)
- if style != GUIFRAME.MANAGER_ON:
- self._mgr.GetPane(self.panels["data_panel"].window_name).Hide()
- else:
- self._mgr.GetPane(self.panels["data_panel"].window_name).Show()
-
- # Add the panels to the AUI manager
- for panel_class in panels:
- p = panel_class
- id = wx.NewId()
- #w, h = self._get_panels_size(p)
- # Check whether we need to put this panel
- # in the center pane
- if hasattr(p, "CENTER_PANE") and p.CENTER_PANE:
- w, h = self._get_panels_size(p)
- if p.CENTER_PANE:
- self.panels[str(id)] = p
- self._mgr.AddPane(p, wx.aui.AuiPaneInfo().
- Name(p.window_name).
- CenterPane().
- Center().
- CloseButton(False).
- Hide())
- else:
- self.panels[str(id)] = p
- self._mgr.AddPane(p, wx.aui.AuiPaneInfo().
- Name(p.window_name).Caption(p.window_caption).
- Right().
- Dock().
- TopDockable().
- BottomDockable().
- LeftDockable().
- RightDockable().
- MinimizeButton().
- Hide())
-
- def update_data(self, prev_data, new_data):
- """
- """
- prev_id, data_state = self._data_manager.update_data(prev_data=prev_data,
- new_data=new_data)
-
- self._data_panel.remove_by_id(prev_id)
- self._data_panel.load_data_list(data_state)
-
- def update_theory(self, data_id, theory, state=None):
- """
- """
- data_state = self._data_manager.update_theory(data_id=data_id,
- theory=theory,
- state=state)
- self._data_panel.load_data_list(data_state)
-
- def onfreeze(self, theory_id):
- """
- """
- data_state_list = self._data_manager.freeze(theory_id)
- self._data_panel.load_data_list(list=data_state_list)
- for data_state in data_state_list.values():
- new_plot = data_state.get_data()
-
- wx.PostEvent(self, NewPlotEvent(plot=new_plot,
- title=new_plot.title))
-
- def freeze(self, data_id, theory_id):
- """
- """
- data_state_list = self._data_manager.freeze_theory(data_id=data_id,
- theory_id=theory_id)
- self._data_panel.load_data_list(list=data_state_list)
- for data_state in data_state_list.values():
- new_plot = data_state.get_data()
- wx.PostEvent(self, NewPlotEvent(plot=new_plot,
- title=new_plot.title))
-
- def delete_data(self, data):
- """
- """
- self._current_perspective.delete_data(data)
-
-
- def get_context_menu(self, plotpanel=None):
- """
- Get the context menu items made available
- by the different plug-ins.
- This function is used by the plotting module
- """
- if plotpanel is None:
- return
- menu_list = []
- for item in self.plugins:
- menu_list.extend(item.get_context_menu(plotpanel=plotpanel))
- return menu_list
-
- def popup_panel(self, p):
- """
- Add a panel object to the AUI manager
-
- :param p: panel object to add to the AUI manager
-
- :return: ID of the event associated with the new panel [int]
-
- """
- ID = wx.NewId()
- self.panels[str(ID)] = p
- count = 0
- for item in self.panels:
- if self.panels[item].window_name.startswith(p.window_name):
- count += 1
- windowname = p.window_name
- caption = p.window_caption
- if count > 0:
- windowname += str(count+1)
- caption += (' '+str(count))
- p.window_name = windowname
- p.window_caption = caption
-
- style1 = self.__gui_style & GUIFRAME.FIXED_PANEL
- style2 = self.__gui_style & GUIFRAME.FLOATING_PANEL
- if style1 == GUIFRAME.FIXED_PANEL:
- self._mgr.AddPane(p, wx.aui.AuiPaneInfo().
- Name(windowname).
- Caption(caption).
- Position(10).
- Floatable().
- Right().
- Dock().
- MinimizeButton().
- Resizable(True).
- # Use a large best size to make sure the AUI
- # manager takes all the available space
- BestSize(wx.Size(PLOPANEL_WIDTH,
- PLOPANEL_HEIGTH)))
-
- self._popup_fixed_panel(p)
-
- elif style2 == GUIFRAME.FLOATING_PANEL:
- self._mgr.AddPane(p, wx.aui.AuiPaneInfo().
- Name(windowname).Caption(caption).
- MinimizeButton().
- Resizable(True).
- # Use a large best size to make sure the AUI
- # manager takes all the available space
- BestSize(wx.Size(PLOPANEL_WIDTH,
- PLOPANEL_HEIGTH)))
-
- self._popup_floating_panel(p)
-
- # Register for showing/hiding the panel
- wx.EVT_MENU(self, ID, self.on_view)
- if p not in self.plot_panels.values() and p.group_id != None:
- self.plot_panels[ID] = p
- if len(self.plot_panels) == 1:
- self.panel_on_focus = p
- self.set_panel_on_focus(None)
- if self._data_panel is not None and \
- self._plotting_plugin is not None:
- ind = self._data_panel.cb_plotpanel.FindString('None')
- if ind != wx.NOT_FOUND:
- self._data_panel.cb_plotpanel.Delete(ind)
- if caption not in self._data_panel.cb_plotpanel.GetItems():
- self._data_panel.cb_plotpanel.Append(str(caption), p)
- return ID
-
- def _setup_menus(self):
- """
- Set up the application menus
- """
- # Menu
- self._menubar = wx.MenuBar()
- self._add_menu_file()
- self._add_menu_edit()
- self._add_menu_view()
- #self._add_menu_data()
- self._add_menu_application()
- self._add_menu_tool()
- self._add_current_plugin_menu()
- self._add_menu_window()
- self._add_help_menu()
- self.SetMenuBar(self._menubar)
-
- def _setup_tool_bar(self):
- """
- add toolbar to the frame
- """
- #set toolbar
- self._toolbar = GUIToolBar(self, -1)
- self.SetToolBar(self._toolbar)
- self._update_toolbar_helper()
- self._on_toggle_toolbar(event=None)
-
- def _update_toolbar_helper(self):
- """
- """
- application_name = 'No Selected Analysis'
- panel_name = 'No Panel on Focus'
- if self._toolbar is None:
- return
- if self.cpanel_on_focus is not None:
- self.reset_bookmark_menu(self.cpanel_on_focus)
- self._toolbar.update_toolbar(self.cpanel_on_focus)
- if self._current_perspective is not None:
- application_name = self._current_perspective.sub_menu
- if self.cpanel_on_focus is not None:
- panel_name = self.cpanel_on_focus.window_caption
-
- self._toolbar.update_button(application_name=application_name,
- panel_name=panel_name)
-
- self._toolbar.Realize()
-
- def _add_menu_tool(self):
- """
- Tools menu
- Go through plug-ins and find tools to populate the tools menu
- """
- style = self.__gui_style & GUIFRAME.CALCULATOR_ON
- if style == GUIFRAME.CALCULATOR_ON:
- self._tool_menu = None
- for item in self.plugins:
- if hasattr(item, "get_tools"):
- for tool in item.get_tools():
- # Only create a menu if we have at least one tool
- if self._tool_menu is None:
- self._tool_menu = wx.Menu()
- id = wx.NewId()
- self._tool_menu.Append(id, tool[0], tool[1])
- wx.EVT_MENU(self, id, tool[2])
- if self._tool_menu is not None:
- self._menubar.Append(self._tool_menu, '&Tool')
-
- def _add_current_plugin_menu(self):
- """
- add current plugin menu
- Look for plug-in menus
- Add available plug-in sub-menus.
- """
- if (self._menubar is None) or (self._current_perspective is None):
- return
- #replace or add a new menu for the current plugin
-
- pos = self._menubar.FindMenu(str(self._applications_menu_name))
- if pos != -1:
- menu_list = self._current_perspective.populate_menu(self)
- if menu_list:
- for (menu, name) in menu_list:
- hidden_menu = self._menubar.Replace(pos, menu, name)
- self._applications_menu_name = name
- #self._applications_menu_pos = pos
- else:
- hidden_menu = self._menubar.Remove(pos)
- self._applications_menu_name = None
- #get the position of the menu when it first added
- self._applications_menu_pos = pos
-
- else:
- menu_list = self._current_perspective.populate_menu(self)
- if menu_list:
- for (menu,name) in menu_list:
- if self._applications_menu_pos == -1:
- self._menubar.Append(menu, name)
- else:
- self._menubar.Insert(self._applications_menu_pos, menu, name)
- self._applications_menu_name = name
-
- def _add_help_menu(self):
- """
- add help menu
- """
- # Help menu
- self._help_menu = wx.Menu()
- style = self.__gui_style & GUIFRAME.WELCOME_PANEL_ON
- if style == GUIFRAME.WELCOME_PANEL_ON or custom_config != None:
- # add the welcome panel menu item
- if self.defaultPanel is not None:
- id = wx.NewId()
- self._help_menu.Append(id, '&Welcome', '')
- self._help_menu.AppendSeparator()
- wx.EVT_MENU(self, id, self.show_welcome_panel)
- # Look for help item in plug-ins
- for item in self.plugins:
- if hasattr(item, "help"):
- id = wx.NewId()
- self._help_menu.Append(id,'&%s Help' % item.sub_menu, '')
- wx.EVT_MENU(self, id, item.help)
- if config._do_tutorial:
- self._help_menu.AppendSeparator()
- id = wx.NewId()
- self._help_menu.Append(id,'&Tutorial', 'Software tutorial')
- wx.EVT_MENU(self, id, self._onTutorial)
-
- if config._do_aboutbox:
- self._help_menu.AppendSeparator()
- id = wx.NewId()
- self._help_menu.Append(id,'&About', 'Software information')
- wx.EVT_MENU(self, id, self._onAbout)
-
- # Checking for updates needs major refactoring to work with py2exe
- # We need to make sure it doesn't hang the application if the server
- # is not up. We also need to make sure there's a proper executable to
- # run if we spawn a new background process.
- #id = wx.NewId()
- #self._help_menu.Append(id,'&Check for update',
- #'Check for the latest version of %s' % config.__appname__)
- #wx.EVT_MENU(self, id, self._check_update)
- self._menubar.Append(self._help_menu, '&Help')
-
- def _add_menu_view(self):
- """
- add menu items under view menu
- """
- if not VIEW_MENU:
- return
- self._view_menu = wx.Menu()
- style = self.__gui_style & GUIFRAME.MANAGER_ON
- id = wx.NewId()
- self._data_panel_menu = self._view_menu.Append(id,
- '&Show Data Explorer', '')
- wx.EVT_MENU(self, id, self.show_data_panel)
- if style == GUIFRAME.MANAGER_ON:
- self._data_panel_menu.SetText('Hide Data Explorer')
- else:
- self._data_panel_menu.SetText('Show Data Explorer')
- self._view_menu.AppendSeparator()
- id = wx.NewId()
- style1 = self.__gui_style & GUIFRAME.TOOLBAR_ON
- if style1 == GUIFRAME.TOOLBAR_ON:
- self._toolbar_menu = self._view_menu.Append(id,'&Hide Toolbar', '')
- else:
- self._toolbar_menu = self._view_menu.Append(id,'&Show Toolbar', '')
- wx.EVT_MENU(self, id, self._on_toggle_toolbar)
-
- if custom_config != None:
- self._view_menu.AppendSeparator()
- id = wx.NewId()
- preference_menu = self._view_menu.Append(id,'Startup Setting', '')
- wx.EVT_MENU(self, id, self._on_preference_menu)
-
- self._menubar.Append(self._view_menu, '&View')
-
- def _on_preference_menu(self, event):
- """
- Build a panel to allow to edit Mask
- """
-
- from sans.guiframe.startup_configuration \
- import StartupConfiguration as ConfDialog
-
- self.panel = ConfDialog(parent=self, gui=self.__gui_style)
- self.panel.ShowModal()
- #wx.PostEvent(self.parent, event)
-
-
- def _add_menu_window(self):
- """
- add a menu window to the menu bar
- Window menu
- Attach a menu item for each panel in our
- panel list that also appears in a plug-in.
-
- Only add the panel menu if there is only one perspective and
- it has more than two panels.
- Note: the first plug-in is always the plotting plug-in.
- The first application
- #plug-in is always the second one in the list.
- """
- self._window_menu = wx.Menu()
- if self._plotting_plugin is not None:
- for (menu, name) in self._plotting_plugin.populate_menu(self):
- self._window_menu.AppendSubMenu(menu, name)
- self._menubar.Append(self._window_menu, '&Graph')
-
- style = self.__gui_style & GUIFRAME.PLOTTING_ON
- if style == GUIFRAME.PLOTTING_ON:
- self._window_menu.AppendSeparator()
- id = wx.NewId()
- preferences_menu = wx.Menu()
- hint = "All plot panels will floating"
- preferences_menu.AppendRadioItem(id, '&Float All', hint)
- wx.EVT_MENU(self, id, self.set_plotpanel_floating)
- style = self.__gui_style & GUIFRAME.FLOATING_PANEL
- f_menu = preferences_menu.FindItemById(id)
- if style == GUIFRAME.FLOATING_PANEL:
- f_checked = True
- else:
- f_checked = False
- f_menu.Check(f_checked)
-
- id = wx.NewId()
- hint = "All plot panels will displayed within the frame"
- preferences_menu.AppendRadioItem(id, '&Dock All', hint)
- wx.EVT_MENU(self, id, self.set_plotpanel_fixed)
- if not f_checked:
- d_menu = preferences_menu.FindItemById(id)
- d_menu.Check(True)
- preferences_menu.AppendSeparator()
- id = wx.NewId()
- hint = "Clean up the dock area for plots on new-plot"
- preferences_menu.AppendCheckItem(id, '&CleanUp Dock on NewPlot', hint)
- wx.EVT_MENU(self, id, self.on_cleanup_dock)
- flag = self.cleanup_plots
- if self.cleanup_plots:
- c_menu = preferences_menu.FindItemById(id)
- c_menu.Check(True)
- self._window_menu.AppendSubMenu(preferences_menu,'&Preferences')
- if self._window_menu.GetMenuItemCount() == 0:
- pos = self._menubar.FindMenu('Graph')
- self._menubar.Remove(pos)
- #wx.EVT_MENU(self, id, self.show_preferences_panel)
- """
- if len(self.plugins) == 2:
- plug = self.plugins[1]
- pers = plug.get_perspective()
-
- if len(pers) > 1:
- self._window_menu = wx.Menu()
- for item in self.panels:
- if item == 'default':
- continue
- panel = self.panels[item]
- if panel.window_name in pers:
- self._window_menu.Append(int(item),
- panel.window_caption,
- "Show %s window" % panel.window_caption)
- wx.EVT_MENU(self, int(item), self.on_view)
- self._menubar.Append(self._window_menu, '&Window')
- """
-
-
- def _add_menu_application(self):
- """
-
- # Attach a menu item for each defined perspective or application.
- # Only add the perspective menu if there are more than one perspectives
- add menu application
- """
- #style = self.__gui_style & GUIFRAME.MULTIPLE_APPLICATIONS
- #if style == GUIFRAME.MULTIPLE_APPLICATIONS:
- if self._num_perspectives > 1:
- plug_data_count = False
- plug_no_data_count = False
- self._applications_menu = wx.Menu()
- pos = 0
- separator = self._applications_menu.AppendSeparator()
- for plug in self.plugins:
- if len(plug.get_perspective()) > 0:
- id = wx.NewId()
- if plug.use_data():
-
- self._applications_menu.InsertCheckItem(pos, id, plug.sub_menu,
- "Switch to analysis: %s" % plug.sub_menu)
- plug_data_count = True
- pos += 1
- else:
- plug_no_data_count = True
- self._applications_menu.AppendCheckItem(id, plug.sub_menu,
- "Switch to analysis: %s" % plug.sub_menu)
- wx.EVT_MENU(self, id, plug.on_perspective)
- #self._applications_menu.
- if (not plug_data_count or not plug_no_data_count):
- self._applications_menu.RemoveItem(separator)
- self._menubar.Append(self._applications_menu, '&Analysis')
- self._check_applications_menu()
-
- def _populate_file_menu(self):
- """
- Insert menu item under file menu
- """
- for plugin in self.plugins:
- if len(plugin.populate_file_menu()) > 0:
- for item in plugin.populate_file_menu():
- m_name, m_hint, m_handler = item
- id = wx.NewId()
- self._file_menu.Append(id, m_name, m_hint)
- wx.EVT_MENU(self, id, m_handler)
- self._file_menu.AppendSeparator()
-
- def _add_menu_file(self):
- """
- add menu file
- """
-
- # File menu
- self._file_menu = wx.Menu()
- #append item from plugin under menu file if necessary
- self._populate_file_menu()
- style = self.__gui_style & GUIFRAME.DATALOADER_ON
- style1 = self.__gui_style & GUIFRAME.MULTIPLE_APPLICATIONS
- if OPEN_SAVE_MENU:
- id = wx.NewId()
- hint_load_file = "read all analysis states saved previously"
- self._save_appl_menu = self._file_menu.Append(id,
- '&Open Project', hint_load_file)
- wx.EVT_MENU(self, id, self._on_open_state_project)
-
- if style1 == GUIFRAME.MULTIPLE_APPLICATIONS:
- # some menu of plugin to be seen under file menu
- hint_load_file = "Read a status files and load"
- hint_load_file += " them into the analysis"
- id = wx.NewId()
- self._save_appl_menu = self._file_menu.Append(id,
- '&Open Analysis', hint_load_file)
- wx.EVT_MENU(self, id, self._on_open_state_application)
- if OPEN_SAVE_MENU:
- self._file_menu.AppendSeparator()
- id = wx.NewId()
- self._file_menu.Append(id, '&Save Project',
- 'Save the state of the whole analysis')
- wx.EVT_MENU(self, id, self._on_save_project)
- if style1 == GUIFRAME.MULTIPLE_APPLICATIONS:
- #self._file_menu.AppendSeparator()
- id = wx.NewId()
- self._save_appl_menu = self._file_menu.Append(id,
- '&Save Analysis',
- 'Save state of the current active analysis panel')
- wx.EVT_MENU(self, id, self._on_save_application)
- self._file_menu.AppendSeparator()
-
- id = wx.NewId()
- self._file_menu.Append(id, '&Quit', 'Exit')
- wx.EVT_MENU(self, id, self.Close)
- # Add sub menus
- self._menubar.Append(self._file_menu, '&File')
-
- def _add_menu_edit(self):
- """
- add menu edit
- """
- if not EDIT_MENU:
- return
- # Edit Menu
- self._edit_menu = wx.Menu()
- self._edit_menu.Append(GUIFRAME_ID.UNDO_ID, '&Undo',
- 'Undo the previous action')
- wx.EVT_MENU(self, GUIFRAME_ID.UNDO_ID, self.on_undo_panel)
- self._edit_menu.Append(GUIFRAME_ID.REDO_ID, '&Redo',
- 'Redo the previous action')
- wx.EVT_MENU(self, GUIFRAME_ID.REDO_ID, self.on_redo_panel)
- self._edit_menu.AppendSeparator()
- self._edit_menu.Append(GUIFRAME_ID.COPY_ID, '&Copy Params',
- 'Copy parameter values')
- wx.EVT_MENU(self, GUIFRAME_ID.COPY_ID, self.on_copy_panel)
- self._edit_menu.Append(GUIFRAME_ID.PASTE_ID, '&Paste Params',
- 'Paste parameter values')
- wx.EVT_MENU(self, GUIFRAME_ID.PASTE_ID, self.on_paste_panel)
- self._edit_menu.AppendSeparator()
-
- self._edit_menu.Append(GUIFRAME_ID.PREVIEW_ID, '&Report Results',
- 'Preview current panel')
- wx.EVT_MENU(self, GUIFRAME_ID.PREVIEW_ID, self.on_preview_panel)
- #self._edit_menu.Append(GUIFRAME_ID.PRINT_ID, '&Print',
- # 'Print current panel')
- #wx.EVT_MENU(self, GUIFRAME_ID.PRINT_ID, self.on_print_panel)
- self._edit_menu.Append(GUIFRAME_ID.RESET_ID, '&Reset Page',
- 'Reset current panel')
- wx.EVT_MENU(self, GUIFRAME_ID.RESET_ID, self.on_reset_panel)
-
- self._menubar.Append(self._edit_menu, '&Edit')
- self.enable_edit_menu()
-
- def get_style(self):
- """
- """
- return self.__gui_style
-
- def _add_menu_data(self):
- """
- Add menu item item data to menu bar
- """
- if self._data_plugin is not None:
- menu_list = self._data_plugin.populate_menu(self)
- if menu_list:
- for (menu, name) in menu_list:
- self._menubar.Append(menu, name)
-
-
- def _on_toggle_toolbar(self, event=None):
- """
- hide or show toolbar
- """
- if self._toolbar is None:
- return
- if self._toolbar.IsShown():
- if self._toolbar_menu is not None:
- self._toolbar_menu.SetItemLabel('Show Toolbar')
- self._toolbar.Hide()
- else:
- if self._toolbar_menu is not None:
- self._toolbar_menu.SetItemLabel('Hide Toolbar')
- self._toolbar.Show()
- self._toolbar.Realize()
-
- def _on_status_event(self, evt):
- """
- Display status message
- """
- # This CallAfter fixes many crashes on MAC.
- wx.CallAfter(self.sb.set_status, evt)
-
- def on_view(self, evt):
- """
- A panel was selected to be shown. If it's not already
- shown, display it.
-
- :param evt: menu event
-
- """
- panel_id = str(evt.GetId())
- self.on_set_plot_focus(self.panels[panel_id])
- self.show_panel(evt.GetId(), 'on')
- wx.CallLater(5, self.set_schedule(True))
- self.set_plot_unfocus()
-
- def on_close_welcome_panel(self):
- """
- Close the welcome panel
- """
- if self.defaultPanel is None:
- return
- default_panel = self._mgr.GetPane(self.panels["default"].window_name)
- if default_panel.IsShown():
- default_panel.Hide()
- # Recover current perspective
- perspective = self._current_perspective
- perspective.on_perspective(event=None)
- self._mgr.Update()
- # Show toolbar
- #style = self.__gui_style & GUIFRAME.TOOLBAR_ON
- #if (style == GUIFRAME.TOOLBAR_ON) & (not self._toolbar.IsShown()):
- # self._on_toggle_toolbar()
-
- def show_welcome_panel(self, event):
- """
- Display the welcome panel
- """
- if self.defaultPanel is None:
- return
- for id, panel in self.panels.iteritems():
- if id == 'default':
- # Show default panel
- if not self._mgr.GetPane(self.panels["default"].window_name).IsShown():
- self._mgr.GetPane(self.panels["default"].window_name).Show(True)
- elif id == "data_panel":
- flag = self._mgr.GetPane(self.panels["data_panel"].window_name).IsShown()
- self._mgr.GetPane(self.panels["data_panel"].window_name).Show(flag)
- elif panel not in self.plot_panels.values() :
- self._mgr.GetPane(self.panels[id].window_name).IsShown()
- self._mgr.GetPane(self.panels[id].window_name).Hide()
- #style = self.__gui_style & GUIFRAME.TOOLBAR_ON
- #if (style == GUIFRAME.TOOLBAR_ON) & (self._toolbar.IsShown()):
- # # self._toolbar.Show(True)
- # self._on_toggle_toolbar()
-
- self._mgr.Update()
-
- def show_panel(self, uid, show=None):
- """
- Shows the panel with the given id
-
- :param uid: unique ID number of the panel to show
-
- """
- ID = str(uid)
- config.printEVT("show_panel: %s" % ID)
- if ID in self.panels.keys():
- if not self._mgr.GetPane(self.panels[ID].window_name).IsShown():
- if show == 'on':
- self._mgr.GetPane(self.panels[ID].window_name).Show()
- elif self.panels[ID].window_caption.split(" ")[0] == \
- "Residuals":
- self._mgr.GetPane(self.panels[ID].window_name).Hide()
- else:
- self._mgr.GetPane(self.panels[ID].window_name).Show()
- # Hide default panel
- self._mgr.GetPane(self.panels["default"].window_name).Hide()
- self._mgr.Update()
- self._redraw_idle()
-
- def hide_panel(self, uid):
- """
- hide panel except default panel
- """
- ID = str(uid)
- caption = self.panels[ID].window_caption
- config.printEVT("hide_panel: %s" % ID)
- if ID in self.panels.keys():
- if self._mgr.GetPane(self.panels[ID].window_name).IsShown():
- self._mgr.GetPane(self.panels[ID].window_name).Hide()
- if self._data_panel is not None and \
- ID in self.plot_panels.keys():
- self._data_panel.cb_plotpanel.Append(str(caption), p)
- # Do not Hide default panel here...
- #self._mgr.GetPane(self.panels["default"].window_name).Hide()
- self._mgr.Update()
-
- def delete_panel(self, uid):
- """
- delete panel given uid
- """
- ID = str(uid)
- config.printEVT("delete_panel: %s" % ID)
- caption = self.panels[ID].window_caption
- if ID in self.panels.keys():
- self.panel_on_focus = None
- panel = self.panels[ID]
- self._plotting_plugin.delete_panel(panel.group_id)
- self._mgr.DetachPane(panel)
- panel.Hide()
- panel.clear()
- panel.Close()
- self._mgr.Update()
- #delete uid number not str(uid)
- if uid in self.plot_panels.keys():
- del self.plot_panels[uid]
- return
-
- def clear_panel(self):
- """
- """
- for item in self.panels:
- try:
- self.panels[item].clear_panel()
- except:
- pass
-
- def create_gui_data(self, data, path=None):
- """
- """
- return self._data_manager.create_gui_data(data, path)
-
- def get_data(self, path):
- """
- """
- message = ""
- log_msg = ''
- output = []
- error_message = ""
- basename = os.path.basename(path)
- root, extension = os.path.splitext(basename)
- if extension.lower() not in EXTENSIONS:
- log_msg = "File Loader cannot "
- log_msg += "load: %s\n" % str(basename)
- log_msg += "Try Data opening...."
- logging.info(log_msg)
- self.load_complete(output=output, error_message=error_message,
- message=log_msg, path=path)
- return
-
- #reading a state file
- for plug in self.plugins:
- reader, ext = plug.get_extensions()
- if reader is not None:
- #read the state of the single plugin
- if extension == ext:
- reader.read(path)
- return
- elif extension == APPLICATION_STATE_EXTENSION:
- reader.read(path)
-
- style = self.__gui_style & GUIFRAME.MANAGER_ON
- if style == GUIFRAME.MANAGER_ON:
- if self._data_panel is not None:
- #data_state = self._data_manager.get_selected_data()
- #self._data_panel.load_data_list(data_state)
- self._mgr.GetPane(self._data_panel.window_name).Show(True)
-
- def load_from_cmd(self, path):
- """
- load data from cmd or application
- """
- if path is None:
- return
- else:
- path = os.path.abspath(path)
- if not os.path.isfile(path) and not os.path.isdir(path):
- return
-
- if os.path.isdir(path):
- self.load_folder(path)
- return
-
- basename = os.path.basename(path)
- root, extension = os.path.splitext(basename)
- if extension.lower() not in EXTENSIONS:
- self.load_data(path)
- else:
- self.load_state(path)
-
- self._default_save_location = os.path.dirname(path)
-
- def load_state(self, path):
- """
- load data from command line or application
- """
- if path and (path is not None) and os.path.isfile(path):
- basename = os.path.basename(path)
- if APPLICATION_STATE_EXTENSION is not None \
- and basename.endswith(APPLICATION_STATE_EXTENSION):
- #Hide current plot_panels i
- for ID in self.plot_panels.keys():
- panel = self._mgr.GetPane(self.plot_panels[ID].window_name)
- if panel.IsShown():
- panel.Hide()
- self.get_data(path)
- if self.defaultPanel is not None and \
- self._mgr.GetPane(self.panels["default"].window_name).IsShown():
- self.on_close_welcome_panel()
-
- def load_data(self, path):
- """
- load data from command line
- """
- if not os.path.isfile(path):
- return
- basename = os.path.basename(path)
- root, extension = os.path.splitext(basename)
- if extension.lower() in EXTENSIONS:
- log_msg = "Data Loader cannot "
- log_msg += "load: %s\n" % str(path)
- log_msg += "Try File opening ...."
- print log_msg
- return
- message = ""
- log_msg = ''
- output = {}
- error_message = ""
- try:
- print "Loading Data...:\n" + str(path) + "\n"
- temp = self.loader.load(path)
- if temp.__class__.__name__ == "list":
- for item in temp:
- data = self.create_gui_data(item, path)
- output[data.id] = data
- else:
- data = self.create_gui_data(temp, path)
- output[data.id] = data
-
- self.add_data(data_list=output)
- except:
- error_message = "Error while loading"
- error_message += " Data from cmd:\n %s\n" % str(path)
- error_message += str(sys.exc_value) + "\n"
- print error_message
-
- def load_folder(self, path):
- """
- Load entire folder
- """
- if not os.path.isdir(path):
- return
- if self._data_plugin is None:
- return
- try:
- if path is not None:
- self._default_save_location = os.path.dirname(path)
- file_list = self._data_plugin.get_file_path(path)
- self._data_plugin.get_data(file_list)
- else:
- return
- except:
- error_message = "Error while loading"
- error_message += " Data folder from cmd:\n %s\n" % str(path)
- error_message += str(sys.exc_value) + "\n"
- print error_message
-
- def _on_open_state_application(self, event):
- """
- """
- path = None
- if self._default_save_location == None:
- self._default_save_location = os.getcwd()
-
- plug_wlist = self._on_open_state_app_helper()
- dlg = wx.FileDialog(self,
- "Choose a file",
- self._default_save_location, "",
- plug_wlist)
- if dlg.ShowModal() == wx.ID_OK:
- path = dlg.GetPath()
- if path is not None:
- self._default_save_location = os.path.dirname(path)
- dlg.Destroy()
- self.load_state(path=path)
-
- def _on_open_state_app_helper(self):
- """
- Helps '_on_open_state_application()' to find the extension of
- the current perspective/application
- """
- # No current perspective or no extension attr
- if self._current_perspective is None:
- return PLUGINS_WLIST
- try:
- # Find the extension of the perspective and get that as 1st item in list
- ind = None
- app_ext = self._current_perspective._extensions
- plug_wlist = config.PLUGINS_WLIST
- for ext in set(plug_wlist):
- if ext.count(app_ext) > 0:
- ind = ext
- break
- # Found the extension
- if ind != None:
- plug_wlist.remove(ind)
- plug_wlist.insert(0, ind)
- try:
- plug_wlist ='|'.join(plug_wlist)
- except:
- plug_wlist = ''
-
- except:
- plug_wlist = PLUGINS_WLIST
-
- return plug_wlist
-
- def _on_open_state_project(self, event):
- """
- """
- path = None
- if self._default_save_location == None:
- self._default_save_location = os.getcwd()
-
- dlg = wx.FileDialog(self,
- "Choose a file",
- self._default_save_location, "",
- APPLICATION_WLIST)
- if dlg.ShowModal() == wx.ID_OK:
- path = dlg.GetPath()
- if path is not None:
- self._default_save_location = os.path.dirname(path)
- dlg.Destroy()
-
- #try:
- # os.popen(path)
- # #self.Close()
- #except:
- self.load_state(path=path)
-
- def _on_save_application(self, event):
- """
- save the state of the current active application
- """
- if self.cpanel_on_focus is not None:
- self.cpanel_on_focus.on_save(event)
-
- def _on_save_project(self, event):
- """
- save the state of the SansView as *.svs
- """
- ## Default file location for save
- self._default_save_location = os.getcwd()
- if self._current_perspective is None:
- return
- reader, ext = self._current_perspective.get_extensions()
- path = None
- extension = '*' + APPLICATION_STATE_EXTENSION
- dlg = wx.FileDialog(self, "Save Project file",
- self._default_save_location, "",
- extension,
- wx.SAVE)
- if dlg.ShowModal() == wx.ID_OK:
- path = dlg.GetPath()
- self._default_save_location = os.path.dirname(path)
- else:
- return None
- dlg.Destroy()
- if path is None:
- return
- # default cansas xml doc
- doc = None
- for panel in self.panels.values():
- temp = panel.save_project(doc)
- if temp is not None:
- doc = temp
-
- # Write the XML document
- extens = APPLICATION_STATE_EXTENSION
- fName = os.path.splitext(path)[0] + extens
- if doc != None:
- fd = open(fName, 'w')
- fd.write(doc.toprettyxml())
- fd.close()
- else:
- msg = "%s cannot read %s\n" % (str(APPLICATION_NAME), str(path))
- logging.error(msg)
-
- def on_save_helper(self, doc, reader, panel, path):
- """
- Save state into a file
- """
- try:
- if reader is not None:
- # case of a panel with multi-pages
- if hasattr(panel, "opened_pages"):
- for uid, page in panel.opened_pages.iteritems():
- data = page.get_data()
- # state must be cloned
- state = page.get_state().clone()
- if data is not None:
- new_doc = reader.write_toXML(data, state)
- if doc != None and hasattr(doc, "firstChild"):
- child = new_doc.firstChild.firstChild
- doc.firstChild.appendChild(child)
- else:
- doc = new_doc
- # case of only a panel
- else:
- data = panel.get_data()
- state = panel.get_state()
- if data is not None:
- new_doc = reader.write_toXML(data, state)
- if doc != None and hasattr(doc, "firstChild"):
- child = new_doc.firstChild.firstChild
- doc.firstChild.appendChild(child)
- else:
- doc = new_doc
- except:
- raise
- #pass
-
- return doc
-
- def quit_guiframe(self):
- """
- Pop up message to make sure the user wants to quit the application
- """
- message = "Do you really want to quit \n"
- message += "this application?"
- dial = wx.MessageDialog(self, message, 'Question',
- wx.YES_NO|wx.YES_DEFAULT|wx.ICON_QUESTION)
- if dial.ShowModal() == wx.ID_YES:
- return True
- else:
- return False
-
- def Close(self, event=None):
- """
- Quit the application
- """
- #flag = self.quit_guiframe()
- if True:
- wx.Exit()
- sys.exit()
-
- def _check_update(self, event=None):
- """
- Check with the deployment server whether a new version
- of the application is available.
- A thread is started for the connecting with the server. The thread calls
- a call-back method when the current version number has been obtained.
- """
- if hasattr(config, "__update_URL__"):
- import version
- checker = version.VersionThread(config.__update_URL__,
- self._process_version,
- baggage=event==None)
- checker.start()
-
- def _process_version(self, version, standalone=True):
- """
- Call-back method for the process of checking for updates.
- This methods is called by a VersionThread object once the current
- version number has been obtained. If the check is being done in the
- background, the user will not be notified unless there's an update.
-
- :param version: version string
- :param standalone: True of the update is being checked in
- the background, False otherwise.
-
- """
- try:
- if cmp(version, config.__version__) > 0:
- msg = "Version %s is available! See the Help "
- msg += "menu to download it." % version
- self.SetStatusText(msg)
- if not standalone:
- import webbrowser
- webbrowser.open(config.__download_page__)
- else:
- if not standalone:
- msg = "You have the latest version"
- msg += " of %s" % config.__appname__
- self.SetStatusText(msg)
- except:
- msg = "guiframe: could not get latest application"
- msg += " version number\n %s" % sys.exc_value
- logging.error(msg)
- if not standalone:
- msg = "Could not connect to the application server."
- msg += " Please try again later."
- self.SetStatusText(msg)
-
- def _onAbout(self, evt):
- """
- Pop up the about dialog
-
- :param evt: menu event
-
- """
- if config._do_aboutbox:
- import aboutbox
- dialog = aboutbox.DialogAbout(None, -1, "")
- dialog.ShowModal()
-
- def _onTutorial(self, evt):
- """
- Pop up the tutorial dialog
-
- :param evt: menu event
-
- """
- if config._do_tutorial:
- path = config.TUTORIAL_PATH
- if IS_WIN:
- try:
- from sans.guiframe.pdfview import PDFFrame
-
- dialog = PDFFrame(None, -1, "Tutorial", path)
- #self.SetTopWindow(dialog)
- dialog.Show(True)
- except:
- msg = "This feature requires 'Adobe pdf Reader'\n"
- msg += "Please install it first (Free)..."
- wx.MessageBox(msg, 'Error')
- else:
- try:
- command = "open "
- command += path
- os.system(command)
- except:
- msg = "This feature requires 'Preview' Application\n"
- msg += "Please install it first..."
- wx.MessageBox(msg, 'Error')
-
-
- def set_manager(self, manager):
- """
- Sets the application manager for this frame
-
- :param manager: frame manager
- """
- self.app_manager = manager
-
- def post_init(self):
- """
- This initialization method is called after the GUI
- has been created and all plug-ins loaded. It calls
- the post_init() method of each plug-in (if it exists)
- so that final initialization can be done.
- """
- for item in self.plugins:
- if hasattr(item, "post_init"):
- item.post_init()
-
- def set_default_perspective(self):
- """
- Choose among the plugin the first plug-in that has
- "set_default_perspective" method and its return value is True will be
- as a default perspective when the welcome page is closed
- """
- for item in self.plugins:
- if hasattr(item, "set_default_perspective"):
- if item.set_default_perspective():
- item.on_perspective(event=None)
- return
-
- def set_perspective(self, panels):
- """
- Sets the perspective of the GUI.
- Opens all the panels in the list, and closes
- all the others.
-
- :param panels: list of panels
- """
- #style = self.__gui_style & GUIFRAME.TOOLBAR_ON
- #if (style == GUIFRAME.TOOLBAR_ON) & (not self._toolbar.IsShown()):
- # self._on_toggle_toolbar()
- for item in self.panels:
- # Check whether this is a sticky panel
- if hasattr(self.panels[item], "ALWAYS_ON"):
- if self.panels[item].ALWAYS_ON:
- continue
-
- if self.panels[item].window_name in panels:
- if not self._mgr.GetPane(self.panels[item].window_name).IsShown():
- self._mgr.GetPane(self.panels[item].window_name).Show()
- else:
- # always show the data panel if enable
- style = self.__gui_style & GUIFRAME.MANAGER_ON
- if (style == GUIFRAME.MANAGER_ON) and self.panels[item] == self._data_panel:
- if 'data_panel' in self.panels.keys():
- flag = self._mgr.GetPane(self.panels['data_panel'].window_name).IsShown()
- self._mgr.GetPane(self.panels['data_panel'].window_name).Show(flag)
- else:
- if self._mgr.GetPane(self.panels[item].window_name).IsShown():
- self._mgr.GetPane(self.panels[item].window_name).Hide()
-
- self._mgr.Update()
-
- def show_data_panel(self, event=None, action=True):
- """
- show the data panel
- """
- if self._data_panel_menu == None:
- return
- label = self._data_panel_menu.GetText()
- if label == 'Show Data Explorer':
- pane = self._mgr.GetPane(self.panels["data_panel"].window_name)
- #if not pane.IsShown():
- if action:
- pane.Show(True)
- self._mgr.Update()
- self.__gui_style = self.__gui_style | GUIFRAME.MANAGER_ON
-
- self._data_panel_menu.SetText('Hide Data Explorer')
- else:
- pane = self._mgr.GetPane(self.panels["data_panel"].window_name)
- #if not pane.IsShown():
- if action:
- pane.Show(False)
- self._mgr.Update()
- self.__gui_style = self.__gui_style & (~GUIFRAME.MANAGER_ON)
- self._data_panel_menu.SetText('Show Data Explorer')
-
- def add_data_helper(self, data_list):
- """
- """
- if self._data_manager is not None:
- self._data_manager.add_data(data_list)
-
- def add_data(self, data_list):
- """
- receive a dictionary of data from loader
- store them its data manager if possible
- send to data the current active perspective if the data panel
- is not active.
- :param data_list: dictionary of data's ID and value Data
- """
- #Store data into manager
- self.add_data_helper(data_list)
- # set data in the data panel
- if self._data_panel is not None:
- data_state = self._data_manager.get_data_state(data_list.keys())
- self._data_panel.load_data_list(data_state)
- #if the data panel is shown wait for the user to press a button
- #to send data to the current perspective. if the panel is not
- #show automatically send the data to the current perspective
- style = self.__gui_style & GUIFRAME.MANAGER_ON
- if style == GUIFRAME.MANAGER_ON:
- #wait for button press from the data panel to set_data
- if self._data_panel is not None:
- self._mgr.GetPane(self._data_panel.window_name).Show(True)
- self._mgr.Update()
- else:
- #automatically send that to the current perspective
- self.set_data(data_id=data_list.keys())
- self.on_close_welcome_panel()
-
- def set_data(self, data_id, theory_id=None):
- """
- set data to current perspective
- """
- list_data, _ = self._data_manager.get_by_id(data_id)
- if self._current_perspective is not None:
- if self.cleanup_plots:
- for uid, panel in self.plot_panels.iteritems():
- #panel = self.plot_panels[uid]
- window = self._mgr.GetPane(panel.window_name)
- # To hide all docked plot panels when set the data
- if not window.IsFloating():
- self.hide_panel(uid)
- self._current_perspective.set_data(list_data.values())
- self.on_close_welcome_panel()
- else:
- msg = "Guiframe does not have a current perspective"
- logging.info(msg)
-
- def set_theory(self, state_id, theory_id=None):
- """
- """
- _, list_theory = self._data_manager.get_by_id(theory_id)
- if self._current_perspective is not None:
- try:
- self._current_perspective.set_theory(list_theory.values())
- except:
- msg = "Guiframe set_theory: \n" + str(sys.exc_value)
- logging.info(msg)
- wx.PostEvent(self, StatusEvent(status=msg, info="error"))
- else:
- msg = "Guiframe does not have a current perspective"
- logging.info(msg)
-
- def plot_data(self, state_id, data_id=None,
- theory_id=None, append=False):
- """
- send a list of data to plot
- """
- total_plot_list = []
- data_list, _ = self._data_manager.get_by_id(data_id)
- _, temp_list_theory = self._data_manager.get_by_id(theory_id)
- total_plot_list = data_list.values()
- for item in temp_list_theory.values():
- theory_data, theory_state = item
- total_plot_list.append(theory_data)
- GROUP_ID = wx.NewId()
- for new_plot in total_plot_list:
- if append:
- if self.panel_on_focus is None:
- message = "cannot append plot. No plot panel on focus!"
- message += "please click on any available plot to set focus"
- wx.PostEvent(self, StatusEvent(status=message,
- info='warning'))
- return
- else:
- if self.enable_add_data(new_plot):
- new_plot.group_id = self.panel_on_focus.group_id
- else:
- message = "Only 1D Data can be append to"
- message += " plot panel containing 1D data.\n"
- message += "%s not be appended.\n" %str(new_plot.name)
- message += "try new plot option.\n"
- wx.PostEvent(self, StatusEvent(status=message,
- info='warning'))
- else:
- if self.cleanup_plots:
- for id, panel in self.plot_panels.iteritems():
- window = self._mgr.GetPane(panel.window_name)
- # To hide all docked plot panels when set the data
- if not window.IsFloating():
- self.hide_panel(id)
- #if not append then new plot
- from sans.guiframe.dataFitting import Data2D
- if issubclass(Data2D, new_plot.__class__):
- #for 2 D always plot in a separated new plot
- new_plot.group_id = wx.NewId()
- else:
- # plot all 1D in a new plot
- new_plot.group_id = GROUP_ID
- title = "PLOT " + str(new_plot.title)
- wx.PostEvent(self, NewPlotEvent(plot=new_plot,
- title=title,
- group_id = new_plot.group_id))
-
- def remove_data(self, data_id, theory_id=None):
- """
- Delete data state if data_id is provide
- delete theory created with data of id data_id if theory_id is provide
- if delete all true: delete the all state
- else delete theory
- """
- temp = data_id + theory_id
- """
- value = [plug.is_in_use(temp) for plug in self.plugins]
- if len(value) > 0:
- print "value"
- return
- from data_panel import DataDialog
- dlg = DataDialog(data_list=data_list, nb_data=MAX_NBR_DATA)
- if dlg.ShowModal() == wx.ID_OK:
- selected_data_list = dlg.get_data()
- dlg.Destroy()
- """
- for plug in self.plugins:
- plug.delete_data(temp)
- total_plot_list = []
- data_list, _ = self._data_manager.get_by_id(data_id)
- _, temp_list_theory = self._data_manager.get_by_id(theory_id)
- total_plot_list = data_list.values()
- for item in temp_list_theory.values():
- theory_data, theory_state = item
- total_plot_list.append(theory_data)
- for new_plot in total_plot_list:
- id = new_plot.id
- for group_id in new_plot.list_group_id:
- wx.PostEvent(self, NewPlotEvent(id=id,
- group_id=group_id,
- action='remove'))
- self._data_manager.delete_data(data_id=data_id,
- theory_id=theory_id)
-
-
- def set_current_perspective(self, perspective):
- """
- set the current active perspective
- """
- self._current_perspective = perspective
- name = "No current analysis selected"
- if self._current_perspective is not None:
- self._add_current_plugin_menu()
- for panel in self.panels.values():
- if hasattr(panel, 'CENTER_PANE') and panel.CENTER_PANE:
- for name in self._current_perspective.get_perspective():
- if name == panel.window_name:
- panel.on_set_focus(event=None)
- break
- name = self._current_perspective.sub_menu
- if self._data_panel is not None:
- self._data_panel.set_active_perspective(name)
- self._check_applications_menu()
- #Set the SansView title
- self._set_title_name(name)
-
-
- def _set_title_name(self, name):
- """
- Set the SansView title w/ the current application name
-
- : param name: application name [string]
- """
- # Set SanView Window title w/ application anme
- title = self.title + " - " + name + " -"
- self.SetTitle(title)
-
- def _check_applications_menu(self):
- """
- check the menu of the current application
- """
- if self._applications_menu is not None:
- for menu in self._applications_menu.GetMenuItems():
- if self._current_perspective is not None:
- name = self._current_perspective.sub_menu
- if menu.IsCheckable():
- if menu.GetLabel() == name:
- menu.Check(True)
- else:
- menu.Check(False)
-
- def set_plotpanel_floating(self, event=None):
- """
- make the plot panel floatable
- """
-
- self.__gui_style &= (~GUIFRAME.FIXED_PANEL)
- self.__gui_style |= GUIFRAME.FLOATING_PANEL
- plot_panel = []
- id = event.GetId()
- menu = self._window_menu.FindItemById(id)
- if self._plotting_plugin is not None:
- plot_panel = self._plotting_plugin.plot_panels.values()
- for p in plot_panel:
- self._popup_floating_panel(p)
- menu.Check(True)
-
- def set_plotpanel_fixed(self, event=None):
- """
- make the plot panel fixed
- """
- self.__gui_style &= (~GUIFRAME.FLOATING_PANEL)
- self.__gui_style |= GUIFRAME.FIXED_PANEL
- plot_panel = []
- id = event.GetId()
- menu = self._window_menu.FindItemById(id)
- if self._plotting_plugin is not None:
- plot_panel = self._plotting_plugin.plot_panels.values()
- for p in plot_panel:
- self._popup_fixed_panel(p)
- menu.Check(True)
-
- def on_cleanup_dock(self, event=None):
- """
- Set Cleanup Dock option
- """
- if event == None:
- return
- id = event.GetId()
- menu = self._window_menu.FindItemById(id)
- Flag = self.cleanup_plots
- if not Flag:
- menu.Check(True)
- self.cleanup_plots = True
- msg = "Cleanup-Dock option set to 'ON'."
- else:
- menu.Check(False)
- self.cleanup_plots = False
- msg = "Cleanup-Dock option set to 'OFF'."
-
- wx.PostEvent(self, StatusEvent(status= msg))
-
- def _popup_fixed_panel(self, p):
- """
- """
- style = self.__gui_style & GUIFRAME.FIXED_PANEL
- if style == GUIFRAME.FIXED_PANEL:
- self._mgr.GetPane(p.window_name).Dock()
- self._mgr.GetPane(p.window_name).Floatable()
- self._mgr.GetPane(p.window_name).Right()
- self._mgr.GetPane(p.window_name).TopDockable(False)
- self._mgr.GetPane(p.window_name).BottomDockable(False)
- self._mgr.GetPane(p.window_name).LeftDockable(False)
- self._mgr.GetPane(p.window_name).RightDockable(True)
- self._mgr.Update()
-
- def _popup_floating_panel(self, p):
- """
- """
- style = self.__gui_style & GUIFRAME.FLOATING_PANEL
- if style == GUIFRAME.FLOATING_PANEL:
- self._mgr.GetPane(p.window_name).Floatable(True)
- self._mgr.GetPane(p.window_name).Float()
- self._mgr.GetPane(p.window_name).Dockable(False)
- self._mgr.Update()
-
- def enable_add_data(self, new_plot):
- """
- Enable append data on a plot panel
- """
-
- if self.panel_on_focus not in self._plotting_plugin.plot_panels.values():
- return
- is_theory = len(self.panel_on_focus.plots) <= 1 and \
- self.panel_on_focus.plots.values()[0].__class__.__name__ == "Theory1D"
-
- is_data2d = hasattr(new_plot, 'data')
-
- is_data1d = self.panel_on_focus.__class__.__name__ == "ModelPanel1D"\
- and self.panel_on_focus.group_id is not None
- has_meta_data = hasattr(new_plot, 'meta_data')
-
- #disable_add_data if the data is being recovered from a saved state file.
- is_state_data = False
- if has_meta_data:
- if 'invstate' in new_plot.meta_data: is_state_data = True
- if 'prstate' in new_plot.meta_data: is_state_data = True
- if 'fitstate' in new_plot.meta_data: is_state_data = True
-
- return is_data1d and not is_data2d and not is_theory and not is_state_data
-
- def enable_edit_menu(self):
- """
- enable menu item under edit menu depending on the panel on focus
- """
- if self.cpanel_on_focus is not None and self._edit_menu is not None:
- flag = self.cpanel_on_focus.get_undo_flag()
- self._edit_menu.Enable(GUIFRAME_ID.UNDO_ID, flag)
- flag = self.cpanel_on_focus.get_redo_flag()
- self._edit_menu.Enable(GUIFRAME_ID.REDO_ID, flag)
- flag = self.cpanel_on_focus.get_copy_flag()
- self._edit_menu.Enable(GUIFRAME_ID.COPY_ID, flag)
- flag = self.cpanel_on_focus.get_paste_flag()
- self._edit_menu.Enable(GUIFRAME_ID.PASTE_ID, flag)
- #flag = self.cpanel_on_focus.get_print_flag()
- #self._edit_menu.Enable(GUIFRAME_ID.PRINT_ID, flag)
- flag = self.cpanel_on_focus.get_preview_flag()
- self._edit_menu.Enable(GUIFRAME_ID.PREVIEW_ID, flag)
- flag = self.cpanel_on_focus.get_reset_flag()
- self._edit_menu.Enable(GUIFRAME_ID.RESET_ID, flag)
- else:
- flag = False
- self._edit_menu.Enable(GUIFRAME_ID.UNDO_ID, flag)
- self._edit_menu.Enable(GUIFRAME_ID.REDO_ID, flag)
- self._edit_menu.Enable(GUIFRAME_ID.COPY_ID, flag)
- self._edit_menu.Enable(GUIFRAME_ID.PASTE_ID, flag)
- #self._edit_menu.Enable(GUIFRAME_ID.PRINT_ID, flag)
- self._edit_menu.Enable(GUIFRAME_ID.PREVIEW_ID, flag)
- self._edit_menu.Enable(GUIFRAME_ID.RESET_ID, flag)
-
- def on_undo_panel(self, event=None):
- """
- undo previous action of the last panel on focus if possible
- """
- if self.cpanel_on_focus is not None:
- self.cpanel_on_focus.on_undo(event)
-
- def on_redo_panel(self, event=None):
- """
- redo the last cancel action done on the last panel on focus
- """
- if self.cpanel_on_focus is not None:
- self.cpanel_on_focus.on_redo(event)
-
- def on_copy_panel(self, event=None):
- """
- copy the last panel on focus if possible
- """
- if self.cpanel_on_focus is not None:
- self.cpanel_on_focus.on_copy(event)
-
- def on_paste_panel(self, event=None):
- """
- paste clipboard to the last panel on focus
- """
- if self.cpanel_on_focus is not None:
- self.cpanel_on_focus.on_paste(event)
-
- def on_bookmark_panel(self, event=None):
- """
- bookmark panel
- """
- if self.cpanel_on_focus is not None:
- self.cpanel_on_focus.on_bookmark(event)
-
- def append_bookmark(self, event=None):
- """
- Bookmark available information of the panel on focus
- """
- self._toolbar.append_bookmark(event)
-
- def on_save_panel(self, event=None):
- """
- save possible information on the current panel
- """
- if self.cpanel_on_focus is not None:
- self.cpanel_on_focus.on_save(event)
-
- def on_preview_panel(self, event=None):
- """
- preview information on the panel on focus
- """
- if self.cpanel_on_focus is not None:
- self.cpanel_on_focus.on_preview(event)
-
- def on_print_panel(self, event=None):
- """
- print available information on the last panel on focus
- """
- if self.cpanel_on_focus is not None:
- self.cpanel_on_focus.on_print(event)
-
- def on_zoom_panel(self, event=None):
- """
- zoom on the current panel if possible
- """
- if self.cpanel_on_focus is not None:
- self.cpanel_on_focus.on_zoom(event)
-
- def on_zoom_in_panel(self, event=None):
- """
- zoom in of the panel on focus
- """
- if self.cpanel_on_focus is not None:
- self.cpanel_on_focus.on_zoom_in(event)
-
- def on_zoom_out_panel(self, event=None):
- """
- zoom out on the panel on focus
- """
- if self.cpanel_on_focus is not None:
- self.cpanel_on_focus.on_zoom_out(event)
-
- def on_drag_panel(self, event=None):
- """
- drag apply to the panel on focus
- """
- if self.cpanel_on_focus is not None:
- self.cpanel_on_focus.on_drag(event)
-
- def on_reset_panel(self, event=None):
- """
- reset the current panel
- """
- if self.cpanel_on_focus is not None:
- self.cpanel_on_focus.on_reset(event)
-
- def enable_undo(self):
- """
- enable undo related control
- """
- if self.cpanel_on_focus is not None:
- self._toolbar.enable_undo(self.cpanel_on_focus)
-
- def enable_redo(self):
- """
- enable redo
- """
- if self.cpanel_on_focus is not None:
- self._toolbar.enable_redo(self.cpanel_on_focus)
-
- def enable_copy(self):
- """
- enable copy related control
- """
- if self.cpanel_on_focus is not None:
- self._toolbar.enable_copy(self.cpanel_on_focus)
-
- def enable_paste(self):
- """
- enable paste
- """
- if self.cpanel_on_focus is not None:
- self._toolbar.enable_paste(self.cpanel_on_focus)
-
- def enable_bookmark(self):
- """
- Bookmark
- """
- if self.cpanel_on_focus is not None:
- self._toolbar.enable_bookmark(self.cpanel_on_focus)
-
- def enable_save(self):
- """
- save
- """
- if self.cpanel_on_focus is not None:
- self._toolbar.enable_save(self.cpanel_on_focus)
-
- def enable_preview(self):
- """
- preview
- """
- if self.cpanel_on_focus is not None:
- self._toolbar.enable_preview(self.cpanel_on_focus)
-
- def enable_print(self):
- """
- print
- """
- if self.cpanel_on_focus is not None:
- self._toolbar.enable_print(self.cpanel_on_focus)
-
- def enable_zoom(self):
- """
- zoom
- """
- if self.cpanel_on_focus is not None:
- self._toolbar.enable_zoom(self.panel_on_focus)
-
- def enable_zoom_in(self):
- """
- zoom in
- """
- if self.cpanel_on_focus is not None:
- self._toolbar.enable_zoom_in(self.panel_on_focus)
-
- def enable_zoom_out(self):
- """
- zoom out
- """
- if self.cpanel_on_focus is not None:
- self._toolbar.enable_zoom_out(self.panel_on_focus)
-
- def enable_drag(self, event=None):
- """
- drag
- """
- if self.cpanel_on_focus is not None:
- self._toolbar.enable_drag(self.panel_on_focus)
-
- def enable_reset(self):
- """
- reset the current panel
- """
- if self.cpanel_on_focus is not None:
- self._toolbar.enable_reset(self.panel_on_focus)
-
- def set_schedule_full_draw(self, panel=None, func='del'):
- """
- Add/subtract the schedule full draw list with the panel given
-
- :param panel: plot panel
- :param func: append or del [string]
- """
-
- # append this panel in the schedule list if not in yet
- if func == 'append':
- if not panel in self.schedule_full_draw_list:
- self.schedule_full_draw_list.append(panel)
- # remove this panel from schedule list
- elif func == 'del':
- if len(self.schedule_full_draw_list) > 0:
- if panel in self.schedule_full_draw_list:
- self.schedule_full_draw_list.remove(panel)
-
- # reset the schdule
- if len(self.schedule_full_draw_list) == 0:
- self.schedule = False
- else:
- self.schedule = True
-
- def full_draw(self):
- """
- Draw the panels with axes in the schedule to full dwar list
- """
- count = len(self.schedule_full_draw_list)
- #if not self.schedule:
- if count < 1:
- self.set_schedule(False)
- return
- else:
- ind = 0
- # if any of the panel is shown do full_draw
- for panel in self.schedule_full_draw_list:
- ind += 1
- if self._mgr.GetPane(panel.window_name).IsShown():
- break
- # otherwise, return
- if ind == count:
- return
-
- #Simple redraw only for a panel shown
- def f_draw(panel):
- """
- Draw A panel in the full dwar list
- """
- try:
- # This checking of GetCapture is to stop redrawing
- # while any panel is capture.
- if self.GetCapture() == None:
- # draw if possible
- panel.set_resizing(False)
- panel.Show(False)
- panel.draw_plot()
-
- # Check if the panel is not shown
- if not self._mgr.GetPane(panel.window_name).IsShown():
- self._mgr.GetPane(panel.window_name).Hide()
- else:
- panel.Show(True)
- except:
- pass
- #print self.callback,self.schedule,self.schedule_full_draw_list
-
- # Draw all panels
- map(f_draw, self.schedule_full_draw_list)
-
- # Reset the attr
- if len(self.schedule_full_draw_list) == 0:
- self.set_schedule(False)
- else:
- self.set_schedule(True)
- # do not update mgr
- #self._mgr.Update()
-
- def set_schedule(self, schedule=False):
- """
- Set schedule
- """
- self.schedule = schedule
-
- def get_schedule(self):
- """
- Get schedule
- """
- return self.schedule
-
- def on_set_plot_focus(self, panel):
- """
- Set focus on a plot panel
- """
- self.set_plot_unfocus()
- panel.on_set_focus(None)
- # set focusing panel
- self.panel_on_focus = panel
- self.set_panel_on_focus(None)
-
- def set_plot_unfocus(self):
- """
- Un focus all plot panels
- """
- for plot in self.plot_panels.values():
- plot.on_kill_focus(None)
-
- def _onDrawIdle(self, *args, **kwargs):
- """
- ReDraw with axes
- """
- try:
- # check if it is time to redraw
- if self.GetCapture() == None:
- # Draw plot, changes resizing too
- self.full_draw()
- except:
- pass
-
- # restart idle
- self._redraw_idle(*args, **kwargs)
-
-
- def _redraw_idle(self, *args, **kwargs):
- """
- Restart Idle
- """
- # restart idle
- self.idletimer.Restart(55, *args, **kwargs)
-
-
-class DefaultPanel(wx.Panel, PanelBase):
- """
- Defines the API for a panels to work with
- the GUI manager
- """
- ## Internal nickname for the window, used by the AUI manager
- window_name = "default"
- ## Name to appear on the window title bar
- window_caption = "Welcome panel"
- ## Flag to tell the AUI manager to put this panel in the center pane
- CENTER_PANE = True
- def __init__(self, parent, *args, **kwds):
- wx.Panel.__init__(self, parent, *args, **kwds)
- PanelBase.__init__(self, parent)
-
-
-
-# Toy application to test this Frame
-class ViewApp(wx.App):
- """
- """
- def OnInit(self):
- """
- """
- pos, size = self.window_placement((GUIFRAME_WIDTH, GUIFRAME_HEIGHT))
- self.frame = ViewerFrame(parent=None,
- title=APPLICATION_NAME,
- pos=pos,
- gui_style = DEFAULT_STYLE,
- size=size)
- self.frame.Hide()
- self.s_screen = None
- temp_path = None
- try:
- # make sure the current dir is App dir when it starts
- temp_path = os.path.dirname(sys.path[0])
- os.chdir(temp_path)
- except:
- pass
- try:
- self.open_file()
- except:
- msg = "%s Could not load " % str(APPLICATION_NAME)
- msg += "input file from command line.\n"
- logging.error(msg)
- # Display a splash screen on top of the frame.
- if len(sys.argv) > 1 and '--time' in sys.argv[1:]:
- log_time("Starting to display the splash screen")
- try:
- if os.path.isfile(SPLASH_SCREEN_PATH):
- self.s_screen = self.display_splash_screen(parent=self.frame,
- path=SPLASH_SCREEN_PATH)
- else:
- self.frame.Show()
- except:
- if self.s_screen is not None:
- self.s_screen.Close()
- msg = "Cannot display splash screen\n"
- msg += str (sys.exc_value)
- logging.error(msg)
- self.frame.Show()
-
- if hasattr(self.frame, 'special'):
- self.frame.special.SetCurrent()
- self.SetTopWindow(self.frame)
-
- return True
-
- def open_file(self):
- """
- open a state file at the start of the application
- """
- input_file = None
- if len(sys.argv) >= 2:
- cmd = sys.argv[0].lower()
- basename = os.path.basename(cmd)
- app_base = str(APPLICATION_NAME).lower()
- if os.path.isfile(cmd) or basename.lower() == app_base:
- app_py = app_base + '.py'
- app_exe = app_base + '.exe'
- app_app = app_base + '.app'
- if basename.lower() in [app_py, app_exe, app_app, app_base]:
- data_base = sys.argv[1]
- input_file = os.path.normpath(os.path.join(DATAPATH,
- data_base))
- if input_file is None:
- return
- if self.frame is not None:
- self.frame.set_input_file(input_file=input_file)
-
-
- def set_manager(self, manager):
- """
- Sets a reference to the application manager
- of the GUI manager (Frame)
- """
- self.frame.set_manager(manager)
-
- def build_gui(self):
- """
- Build the GUI
- """
- #try to load file at the start
- try:
- self.open_file()
- except:
- raise
- self.frame.build_gui()
- #if self.s_screen is not None and self.s_screen.IsShown():
- # self.s_screen.Close()
-
- def set_welcome_panel(self, panel_class):
- """
- Set the welcome panel
-
- :param panel_class: class of the welcome panel to be instantiated
-
- """
- self.frame.set_welcome_panel(panel_class)
-
- def add_perspective(self, perspective):
- """
- Manually add a perspective to the application GUI
- """
- self.frame.add_perspective(perspective)
-
- def window_placement(self, size):
- """
- Determines the position and size of the application frame such that it
- fits on the user's screen without obstructing (or being obstructed by)
- the Windows task bar. The maximum initial size in pixels is bounded by
- WIDTH x HEIGHT. For most monitors, the application
- will be centered on the screen; for very large monitors it will be
- placed on the left side of the screen.
- """
- window_width, window_height = size
- screen_size = wx.GetDisplaySize()
- window_height = window_height if screen_size[1]>window_height else screen_size[1]-10
- window_width = window_width if screen_size[0]> window_width else screen_size[0]-10
- xpos = ypos = 0
-
- # Note that when running Linux and using an Xming (X11) server on a PC
- # with a dual monitor configuration, the reported display size may be
- # that of both monitors combined with an incorrect display count of 1.
- # To avoid displaying this app across both monitors, we check for
- # screen 'too big'. If so, we assume a smaller width which means the
- # application will be placed towards the left hand side of the screen.
-
- _, _, x, y = wx.Display().GetClientArea() # size excludes task bar
- if len(sys.argv) > 1 and '--platform' in sys.argv[1:]:
- w, h = wx.DisplaySize() # size includes task bar area
- # display on left side, not centered on screen
- if x > 1920 and x > (2*y): x = x / 2
- if x > window_width: xpos = (x - window_width)/2
- if y > window_height: ypos = (y - window_height)/2
-
- # Return the suggested position and size for the application frame.
- return (xpos, ypos), (min(x, window_width), min(y, window_height))
-
- def display_splash_screen(self, parent,
- path=SPLASH_SCREEN_PATH):
- """Displays the splash screen. It will exactly cover the main frame."""
-
- # Prepare the picture. On a 2GHz intel cpu, this takes about a second.
- x, y = parent.GetSizeTuple()
- image = wx.Image(path, wx.BITMAP_TYPE_PNG)
- image.Rescale(SPLASH_SCREEN_WIDTH,
- SPLASH_SCREEN_HEIGHT, wx.IMAGE_QUALITY_HIGH)
- bm = image.ConvertToBitmap()
-
- # Create and show the splash screen. It will disappear only when the
- # program has entered the event loop AND either the timeout has expired
- # or the user has left clicked on the screen. Thus any processing
- # performed in this routine (including sleeping) or processing in the
- # calling routine (including doing imports) will prevent the splash
- # screen from disappearing.
- #
- # Note that on Linux, the timeout appears to occur immediately in which
- # case the splash screen disappears upon entering the event loop.
- s_screen = wx.SplashScreen(bitmap=bm,
- splashStyle=(wx.SPLASH_TIMEOUT|
- wx.SPLASH_CENTRE_ON_SCREEN),
- style=(wx.SIMPLE_BORDER|
- wx.FRAME_NO_TASKBAR|
- wx.STAY_ON_TOP),
-
- milliseconds=SS_MAX_DISPLAY_TIME,
- parent=parent,
- id=wx.ID_ANY)
- from gui_statusbar import SPageStatusbar
- statusBar = SPageStatusbar(s_screen)
- s_screen.SetStatusBar(statusBar)
- s_screen.Bind(wx.EVT_CLOSE, self.on_close_splash_screen)
- s_screen.Show()
- return s_screen
-
-
- def on_close_splash_screen(self, event):
- """
- """
- self.frame.Show(True)
- event.Skip()
-
-if __name__ == "__main__":
- app = ViewApp(0)
- app.MainLoop()
-
-
Index: test/guiframe/gui_statusbar.py
===================================================================
--- test/guiframe/gui_statusbar.py (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,337 +1,0 @@
-import wx
-from wx import StatusBar as wxStatusB
-from wx.lib import newevent
-import time
-#numner of fields of the status bar
-NB_FIELDS = 4
-#position of the status bar's fields
-ICON_POSITION = 0
-MSG_POSITION = 1
-GAUGE_POSITION = 2
-CONSOLE_POSITION = 3
-BUTTON_SIZE = 40
-
-CONSOLE_WIDTH = 340
-CONSOLE_HEIGHT = 240
-
-class ConsolePanel(wx.Panel):
- """
- """
- def __init__(self, parent, *args, **kwargs):
- """
- """
- wx.Panel.__init__(self, parent=parent, *args, **kwargs)
- self.parent = parent
- self.sizer = wx.BoxSizer(wx.VERTICAL)
- self.msg_txt = wx.TextCtrl(self, size=(CONSOLE_WIDTH-40,
- CONSOLE_HEIGHT-60),
- style=wx.TE_MULTILINE)
- self.msg_txt.SetEditable(False)
- self.msg_txt.SetValue('No message available')
- self.sizer.Add(self.msg_txt, 1, wx.EXPAND|wx.ALL, 10)
- self.SetSizer(self.sizer)
-
- def set_message(self, status=""):
- """
- """
- msg = status + "\n"
- self.msg_txt.AppendText(str(msg))
-
-class Console(wx.Frame):
- """
- """
- def __init__(self, parent=None, status="", *args, **kwds):
- kwds["size"] = (CONSOLE_WIDTH, CONSOLE_HEIGHT)
- kwds["title"] = "Console"
- wx.Frame.__init__(self, parent=parent, *args, **kwds)
- self.panel = ConsolePanel(self)
- self.panel.set_message(status=status)
- wx.EVT_CLOSE(self, self.Close)
-
-
- def set_multiple_messages(self, messages=[]):
- """
- """
- if messages:
- for status in messages:
- self.panel.set_message(status)
-
- def set_message(self, message):
- """
- """
- self.panel.set_message(str(message))
-
- def Close(self, event):
- """
- """
- self.Hide()
-
-class StatusBar(wxStatusB):
- """
- """
- def __init__(self, parent, *args, **kargs):
- wxStatusB.__init__(self, parent, *args, **kargs)
- """
- Implement statusbar functionalities
- """
- self.parent = parent
- self.parent.SetStatusBarPane(MSG_POSITION)
- #Layout of status bar
- self.SetFieldsCount(NB_FIELDS)
- self.SetStatusWidths([BUTTON_SIZE, -2, -1, BUTTON_SIZE])
- #display default message
- self.msg_position = MSG_POSITION
- #save the position of the gauge
- width, height = self.GetSize()
- self.gauge = wx.Gauge(self, size=(width/10, height-3),
- style=wx.GA_HORIZONTAL)
- self.gauge.Hide()
- #status bar icon
- self.bitmap_bt_warning = wx.BitmapButton(self, -1,
- size=(BUTTON_SIZE,-1),
- style=wx.NO_BORDER)
- console_bmp = wx.ArtProvider.GetBitmap(wx.ART_TIP, wx.ART_TOOLBAR)
- self.bitmap_bt_console = wx.BitmapButton(self, -1,
- size=(BUTTON_SIZE-5, height-4))
- self.bitmap_bt_console.SetBitmapLabel(console_bmp)
- console_hint = "History of status bar messages"
- self.bitmap_bt_console.SetToolTipString(console_hint)
- self.bitmap_bt_console.Bind(wx.EVT_BUTTON, self._onMonitor,
- id=self.bitmap_bt_console.GetId())
-
- self.reposition()
- ## Current progress value of the bar
- self.nb_start = 0
- self.nb_progress = 0
- self.nb_stop = 0
- self.frame = None
- self.list_msg = []
- self.frame = Console(parent=self)
- self.frame.set_multiple_messages(self.list_msg)
- self.frame.Hide()
- self.progress = 0
- self.timer = wx.Timer(self, -1)
- self.timer_stop = wx.Timer(self, -1)
- self.thread = None
- self.Bind(wx.EVT_TIMER, self._on_time, self.timer)
- self.Bind(wx.EVT_TIMER, self._on_time_stop, self.timer_stop)
- self.Bind(wx.EVT_SIZE, self.OnSize)
- self.Bind(wx.EVT_IDLE, self.OnIdle)
-
- def reposition(self):
- """
- """
- rect = self.GetFieldRect(GAUGE_POSITION)
- self.gauge.SetPosition((rect.x + 5, rect.y - 2))
- rect = self.GetFieldRect(ICON_POSITION)
- self.bitmap_bt_warning.SetPosition((rect.x + 5, rect.y - 2))
- rect = self.GetFieldRect(CONSOLE_POSITION)
- self.bitmap_bt_console.SetPosition((rect.x - 5, rect.y - 2))
- self.sizeChanged = False
-
- def OnIdle(self, event):
- """
- """
- if self.sizeChanged:
- self.reposition()
-
- def OnSize(self, evt):
- """
- """
- self.reposition()
- self.sizeChanged = True
-
- def get_msg_position(self):
- """
- """
- return self.msg_position
-
- def SetStatusText(self, text="", number=MSG_POSITION):
- """
- """
- wxStatusB.SetStatusText(self, text, number)
- self.list_msg.append(text)
- icon_bmp = wx.ArtProvider.GetBitmap(wx.ART_INFORMATION, wx.ART_TOOLBAR)
- self.bitmap_bt_warning.SetBitmapLabel(icon_bmp)
-
- if self.frame is not None :
- self.frame.set_message(text)
-
- def PopStatusText(self, *args, **kwds):
- """
- Override status bar
- """
- wxStatusB.PopStatusText(self, field=MSG_POSITION)
-
- def PushStatusText(self, *args, **kwds):
- """
- """
- wxStatusB.PushStatusText(self, field=MSG_POSITION, string=string)
-
- def enable_clear_gauge(self):
- """
- clear the progress bar
- """
- flag = False
- if (self.nb_start <= self.nb_stop) or \
- (self.nb_progress <= self.nb_stop):
- flag = True
- return flag
-
- def _on_time_stop(self, evt):
- """
- Clear the progress bar
-
- :param evt: wx.EVT_TIMER
-
- """
- count = 0
- while(count <= 100):
- count += 1
- self.timer_stop.Stop()
- self.clear_gauge(msg="")
- self.nb_progress = 0
- self.nb_start = 0
- self.nb_stop = 0
-
- def _on_time(self, evt):
- """
- Update the progress bar while the timer is running
-
- :param evt: wx.EVT_TIMER
-
- """
- # Check stop flag that can be set from non main thread
- if self.timer.IsRunning():
- self.gauge.Pulse()
-
- def clear_gauge(self, msg=""):
- """
- Hide the gauge
- """
- self.progress = 0
- self.gauge.SetValue(0)
- self.gauge.Hide()
-
- def set_icon(self, event):
- """
- display icons related to the type of message sent to the statusbar
- when available
- """
- if not hasattr(event, "info"):
- return
- msg = event.info.lower()
- if msg == "warning":
- icon_bmp = wx.ArtProvider.GetBitmap(wx.ART_WARNING, wx.ART_TOOLBAR)
- self.bitmap_bt_warning.SetBitmapLabel(icon_bmp)
- if msg == "error":
- icon_bmp = wx.ArtProvider.GetBitmap(wx.ART_ERROR, wx.ART_TOOLBAR)
- self.bitmap_bt_warning.SetBitmapLabel(icon_bmp)
- if msg == "info":
- icon_bmp = wx.ArtProvider.GetBitmap(wx.ART_INFORMATION,
- wx.ART_TOOLBAR)
- self.bitmap_bt_warning.SetBitmapLabel(icon_bmp)
-
- def set_message(self, event):
- """
- display received message on the statusbar
- """
- if hasattr(event, "status"):
- self.SetStatusText(str(event.status))
-
-
- def set_gauge(self, event):
- """
- change the state of the gauge according the state of the current job
- """
- if not hasattr(event, "type"):
- return
- type = event.type
- self.gauge.Show(True)
- if type.lower() == "start":
- self.nb_start += 1
- #self.timer.Stop()
- self.progress += 10
- self.gauge.SetValue(int(self.progress))
- self.progress += 10
- if self.progress < self.gauge.GetRange() - 20:
- self.gauge.SetValue(int(self.progress))
- if type.lower() == "progress":
- self.nb_progress += 1
- self.timer.Start(1)
- self.gauge.Pulse()
- if type.lower() == "update":
- self.progress += 10
- if self.progress < self.gauge.GetRange()- 20:
- self.gauge.SetValue(int(self.progress))
- if type.lower() == "stop":
- self.nb_stop += 1
- self.gauge.Show(True)
- if self.enable_clear_gauge():
- self.timer.Stop()
- self.progress = 0
- self.gauge.SetValue(90)
- self.timer_stop.Start(3)
-
- def set_status(self, event):
- """
- Update the status bar .
-
- :param type: type of message send.
- type must be in ["start","progress","update","stop"]
- :param msg: the message itself as string
- :param thread: if updatting using a thread status
-
- """
- self.set_message(event=event)
- self.set_icon(event=event)
- self.set_gauge(event=event)
-
- def _onMonitor(self, event):
- """
- Pop up a frame with messages sent to the status bar
- """
- self.frame.Show(True)
-
-
-class SPageStatusbar(wxStatusB):
- def __init__(self, parent, timeout=None, *args, **kwds):
- wxStatusB.__init__(self, parent, *args, **kwds)
- self.SetFieldsCount(1)
- self.timeout = timeout
- self.gauge = wx.Gauge(self,style=wx.GA_HORIZONTAL, size=parent.GetSize())
- rect = self.GetFieldRect(0)
- self.gauge.SetPosition((rect.x , rect.y ))
- if self.timeout is not None:
- self.gauge.SetRange(int(self.timeout))
- self.timer = wx.Timer(self, -1)
- self.Bind(wx.EVT_TIMER, self._on_time, self.timer)
- self.timer.Start(1)
- self.pos = 0
-
- def _on_time(self, evt):
- """
- Update the progress bar while the timer is running
-
- :param evt: wx.EVT_TIMER
-
- """
- # Check stop flag that can be set from non main thread
- if self.timeout is None and self.timer.IsRunning():
- self.gauge.Pulse()
-
-
-if __name__ == "__main__":
- app = wx.PySimpleApp()
- frame = wx.Frame(None, wx.ID_ANY, 'test frame')
- #statusBar = StatusBar(frame, wx.ID_ANY)
- statusBar = SPageStatusbar(frame)
- frame.SetStatusBar(statusBar)
- frame.Show(True)
- #event = MessageEvent()
- #event.type = "progress"
- #event.status = "statusbar...."
- #event.info = "error"
- #statusBar.set_status(event=event)
- app.MainLoop()
-
Index: test/guiframe/gui_style.py
===================================================================
--- test/guiframe/gui_style.py (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,85 +1,0 @@
-
-"""
-Provide the style for guiframe
-"""
-import wx
-import os
-from sans.guiframe import get_data_path
-
-
-class GUIFRAME:
- MANAGER_ON = 1
- FLOATING_PANEL = 2
- FIXED_PANEL = 4
- PLOTTING_ON = 8
- DATALOADER_ON = 16
- TOOLBAR_ON = 32
- CALCULATOR_ON = 256
- SINGLE_APPLICATION = 64
- WELCOME_PANEL_ON = 128
- DEFAULT_STYLE = SINGLE_APPLICATION|DATALOADER_ON|PLOTTING_ON|FIXED_PANEL
- MULTIPLE_APPLICATIONS = DEFAULT_STYLE
-
-class GUIFRAME_ID:
- UNDO_ID = wx.NewId()
- REDO_ID = wx.NewId()
- COPY_ID = wx.NewId()
- PASTE_ID = wx.NewId()
- BOOKMARK_ID = wx.NewId()
- SAVE_ID = wx.NewId()
- ZOOM_IN_ID = wx.NewId()
- ZOOM_OUT_ID = wx.NewId()
- ZOOM_ID = wx.NewId()
- DRAG_ID = wx.NewId()
- RESET_ID = wx.NewId()
- PREVIEW_ID = wx.NewId()
- PRINT_ID = wx.NewId()
- CURRENT_APPLICATION = wx.NewId()
- CURVE_SYMBOL_NUM = 13
-
-class GUIFRAME_ICON:
- PATH = get_data_path(media='images')
- SAVE_ICON_PATH = os.path.join(PATH, 'save.png')
- UNDO_ICON_PATH = os.path.join(PATH, 'undo.png')
- REDO_ICON_PATH = os.path.join(PATH, 'redo.png')
- COPY_ICON_PATH = os.path.join(PATH, 'copy.png')
- PASTE_ICON_PATH = os.path.join(PATH, 'paste.png')
- BOOKMARK_ICON_PATH = os.path.join(PATH, 'bookmark.png')
- ZOOM_IN_ID_PATH = os.path.join(PATH, 'zoom_in.png')
- ZOOM_OUT_ID_PATH = os.path.join(PATH, 'zoom_out.png')
- ZOOM_ID_PATH = os.path.join(PATH, 'search_pan.png')
- DRAG_ID_PATH = os.path.join(PATH, 'drag_hand.png')
- RESET_ID_PATH = os.path.join(PATH, 'reset.png')
- PREVIEW_ID_PATH = os.path.join(PATH, 'report.png')
- PRINT_ID_PATH = os.path.join(PATH, 'printer.png')
-
- SAVE_ICON = wx.Image(os.path.join(PATH, 'save.png'))
- UNDO_ICON = wx.Image(os.path.join(PATH, 'undo.png'))
- REDO_ICON = wx.Image(os.path.join(PATH, 'redo.png'))
- COPY_ICON = wx.Image(os.path.join(PATH, 'copy.png'))
- PASTE_ICON = wx.Image(os.path.join(PATH, 'paste.png'))
- BOOKMARK_ICON = wx.Image(os.path.join(PATH, 'bookmark.png'))
- ZOOM_IN_ICON = wx.Image(os.path.join(PATH, 'zoom_in.png'))
- ZOOM_OUT_ICON = wx.Image(os.path.join(PATH, 'zoom_out.png'))
- ZOOM_ICON = wx.Image(os.path.join(PATH, 'search_pan.png'))
- DRAG_ICON = wx.Image(os.path.join(PATH, 'drag_hand.png'))
- RESET_ICON = wx.Image(os.path.join(PATH, 'reset.png'))
- REPORT_ICON = wx.Image(os.path.join(PATH, 'report.png'))
- PREVIEW_ICON = wx.Image(os.path.join(PATH, 'preview.png'))
- PRINT_ICON = wx.Image(os.path.join(PATH, 'printer.png'))
-
-if __name__ == "__main__":
-
- print GUIFRAME.DEFAULT_STYLE
- print GUIFRAME.FLOATING_PANEL
- print GUIFRAME.SINGLE_APPLICATION
- style = GUIFRAME.MULTIPLE_APPLICATIONS
- style &= GUIFRAME.PLOTTING_ON
- print style == GUIFRAME.PLOTTING_ON
- style1 = GUIFRAME.MULTIPLE_APPLICATIONS
- style1 &= (~GUIFRAME.MANAGER_ON)
- print style1 == GUIFRAME.DEFAULT_STYLE
- print style1
-
-
-
Index: test/guiframe/gui_toolbar.py
===================================================================
--- test/guiframe/gui_toolbar.py (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,305 +1,0 @@
-
-import wx
-import os
-from wx import ToolBar as Tbar
-from wx.lib.platebtn import PlateButton
-from sans.guiframe.gui_style import GUIFRAME_ID
-from sans.guiframe.gui_style import GUIFRAME_ICON
-from wx.lib.platebtn import PB_STYLE_SQUARE, PB_STYLE_DROPARROW
-#Control panel width
-import sys
-if sys.platform.count("darwin")==0:
- FONT_VARIANT = 0
- NAME_BOX = wx.DefaultSize
- TB_H = 21
- IS_MAC = False
-else:
- FONT_VARIANT = 1
- NAME_BOX = (200, 25)
- TB_H = 25
- IS_MAC = True
-
-def clear_image(image):
- w, h = image.GetSize()
- factor = 155
- compress = lambda x: int(x * factor/255.) + factor
- for y in range(h):
- for x in range(w):
- grey = compress(image.GetGreen(x, y))
- image.SetRGB(x, y, grey, grey, grey)
- if image.HasAlpha():
- image.ConvertAlphaToMask()
- return image
-
-class GUIToolBar(Tbar):
- """
- Implement toolbar for guiframe
- """
- def __init__(self, parent, *args, **kwds):
- Tbar.__init__(self, parent, *args, **kwds)
- #Set window's font size
- self.SetWindowVariant(variant=FONT_VARIANT)
- self.parent = parent
- self._bookmark_menu = None
- self._bookmark_bt = None
- self.do_layout()
- self.on_bind_button()
-
- def do_layout(self):
- """
- """
- t_size = TB_H
- tbar_size = (t_size, t_size)
- button_type = wx.ITEM_NORMAL
-
- reset_im = GUIFRAME_ICON.RESET_ICON
- reset_im.Rescale(tbar_size[0], tbar_size[1], wx.IMAGE_QUALITY_HIGH)
- reset_bmp = reset_im.ConvertToBitmap()
- #disable_reset_bmp = clear_image(reset_im).ConvertToBitmap()
- disable_reset_bmp = wx.NullBitmap
- self.AddLabelTool(GUIFRAME_ID.RESET_ID, 'Reset', reset_bmp,
- disable_reset_bmp, button_type,'Reset')
- self.AddSeparator()
- save_im = GUIFRAME_ICON.SAVE_ICON
- save_im.Rescale(tbar_size[0], tbar_size[1], wx.IMAGE_QUALITY_HIGH)
- save_bmp = save_im.ConvertToBitmap()
- disable_save_bmp = wx.NullBitmap
- self.AddLabelTool(GUIFRAME_ID.SAVE_ID, 'Save', save_bmp,
- disable_save_bmp, button_type,'Save')
- self.AddSeparator()
- report_im = GUIFRAME_ICON.REPORT_ICON
- report_im.Rescale(tbar_size[0], tbar_size[1], wx.IMAGE_QUALITY_HIGH)
- report_bmp = report_im.ConvertToBitmap()
- #disable_report_bmp = clear_image(report_im).ConvertToBitmap()
- disable_report_bmp = wx.NullBitmap
- self.AddLabelTool(GUIFRAME_ID.PREVIEW_ID, 'Report', report_bmp,
- disable_report_bmp, button_type,'Report')
- self.AddSeparator()
- #print_im = GUIFRAME_ICON.PRINT_ICON
- #print_im.Rescale(tbar_size[0], tbar_size[1], wx.IMAGE_QUALITY_HIGH)
- #print_bmp = print_im.ConvertToBitmap()
-
- #disable_print_bmp = wx.NullBitmap
- #self.AddLabelTool(GUIFRAME_ID.PRINT_ID, 'Print', print_bmp,
- # disable_print_bmp, button_type, 'Print')
- #self.AddSeparator()
- undo_im = GUIFRAME_ICON.UNDO_ICON
- undo_im.Rescale(tbar_size[0], tbar_size[1], wx.IMAGE_QUALITY_HIGH)
- undo_bmp = undo_im.ConvertToBitmap()
- #disable_undo_bmp = clear_image(undo_im).ConvertToBitmap()
- disable_undo_bmp = wx.NullBitmap
- self.AddLabelTool(GUIFRAME_ID.UNDO_ID, 'Undo', undo_bmp,
- disable_undo_bmp, button_type,'Undo')
- self.AddSeparator()
- redo_im = GUIFRAME_ICON.REDO_ICON
- redo_im.Rescale(tbar_size[0], tbar_size[1], wx.IMAGE_QUALITY_HIGH)
- redo_bmp = redo_im.ConvertToBitmap()
- #disable_redo_bmp = clear_image(redo_im).ConvertToBitmap()
- disable_redo_bmp = wx.NullBitmap
- self.AddLabelTool(GUIFRAME_ID.REDO_ID, 'Redo', redo_bmp,
- disable_redo_bmp, button_type,'Redo')
- self.AddSeparator()
- copy_im = GUIFRAME_ICON.COPY_ICON
- copy_im.Rescale(tbar_size[0], tbar_size[1], wx.IMAGE_QUALITY_HIGH)
- copy_bmp = copy_im.ConvertToBitmap()
- #disable_undo_bmp = clear_image(undo_im).ConvertToBitmap()
- disable_copy_bmp = wx.NullBitmap
- self.AddLabelTool(GUIFRAME_ID.COPY_ID, 'Copy', copy_bmp,
- disable_copy_bmp, button_type,'Copy parameter values')
- self.AddSeparator()
- paste_im = GUIFRAME_ICON.PASTE_ICON
- paste_im.Rescale(tbar_size[0], tbar_size[1], wx.IMAGE_QUALITY_HIGH)
- paste_bmp = paste_im.ConvertToBitmap()
- #disable_redo_bmp = clear_image(redo_im).ConvertToBitmap()
- disable_paste_bmp = wx.NullBitmap
- self.AddLabelTool(GUIFRAME_ID.PASTE_ID, 'Paste', paste_bmp,
- disable_paste_bmp, button_type,'Paste parameter values')
-
- self.AddSeparator()
- #add button for the current application
- #self.button_application = wx.StaticText(self, -1, 'Welcome')
- #self.button_application.SetForegroundColour('black')
- #self.button_application.SetBackgroundColour('#1874CD')
- #hint = 'Active Application'
- #self.button_application.SetToolTipString(hint)
- #self.AddControl(self.button_application)
- #self.AddSeparator()
-
- self._bookmark_bt = PlateButton(self, -1, 'bookmark',
- GUIFRAME_ICON.BOOKMARK_ICON.ConvertToBitmap(),
- style=PB_STYLE_SQUARE|PB_STYLE_DROPARROW)
- self._bookmark_bt.Disable()
- self._bookmark_menu = wx.Menu()
- self.add_bookmark_default()
-
-
- self._bookmark_bt.SetMenu(self._bookmark_menu)
- self.AddControl(self._bookmark_bt)
-
- self.SetToolBitmapSize(tbar_size)
- self.AddSeparator()
- #add button for the panel on focus
- self.button_panel = wx.StaticText(self, -1, 'No Panel',
- pos=wx.DefaultPosition,
- size=NAME_BOX,
- style=wx.SUNKEN_BORDER|wx.ALIGN_LEFT)
- #self.button_panel.SetForegroundColour('black')
- #self.button_panel.SetBackgroundColour('white')
- button_panel_font = self.button_panel.GetFont()
- button_panel_font.SetWeight(wx.BOLD)
- self.button_panel.SetFont(button_panel_font)
- #self.button_panel.SetClientSize((80,20))
- hint = 'Control Panel on Focus'
- self.button_panel.SetToolTipString(hint)
- self.AddControl(self.button_panel)
- self.AddSeparator()
- self.Realize()
-
- def add_bookmark_default(self):
- """
- Add default items in bookmark menu
- """
- id = wx.NewId()
- self._bookmark_menu.Append(id, 'Add bookmark')
- self._bookmark_menu.AppendSeparator()
- wx.EVT_MENU(self, id, self.on_bookmark)
-
- def on_bind_button(self):
- """
- """
- if self.parent is not None:
-
- self.parent.Bind(wx.EVT_TOOL, self.parent.on_redo_panel,
- id=GUIFRAME_ID.REDO_ID)
- self.parent.Bind(wx.EVT_TOOL, self.parent.on_undo_panel,
- id=GUIFRAME_ID.UNDO_ID)
- self.parent.Bind(wx.EVT_TOOL, self.parent.on_copy_panel,
- id=GUIFRAME_ID.COPY_ID)
- self.parent.Bind(wx.EVT_TOOL, self.parent.on_paste_panel,
- id=GUIFRAME_ID.PASTE_ID)
- self.parent.Bind(wx.EVT_TOOL, self.parent.on_reset_panel,
- id=GUIFRAME_ID.RESET_ID)
- self.parent.Bind(wx.EVT_TOOL, self.parent.on_save_panel,
- id=GUIFRAME_ID.SAVE_ID)
- self.parent.Bind(wx.EVT_TOOL, self.parent.on_preview_panel,
- id=GUIFRAME_ID.PREVIEW_ID)
- #self.parent.Bind(wx.EVT_TOOL, self.parent.on_print_panel,
- # id=GUIFRAME_ID.PRINT_ID)
-
- def update_button(self, application_name='', panel_name=''):
- """
- """
- #self.button_application.SetLabel(str(application_name))
- self.button_panel.SetLabel(str(panel_name))
- self.button_panel.SetToolTipString(str(panel_name))
-
- def update_toolbar(self, panel=None):
- """
- """
- if panel is None:
- #self.EnableTool(GUIFRAME_ID.PRINT_ID, False)
- self.EnableTool(GUIFRAME_ID.UNDO_ID,False)
- self.EnableTool(GUIFRAME_ID.REDO_ID, False)
- self.EnableTool(GUIFRAME_ID.COPY_ID,False)
- self.EnableTool(GUIFRAME_ID.PASTE_ID, False)
- self.EnableTool(GUIFRAME_ID.PREVIEW_ID, False)
- self.EnableTool(GUIFRAME_ID.RESET_ID, False)
- self.EnableTool(GUIFRAME_ID.SAVE_ID, False)
- self._bookmark_bt.Disable()
-
- else:
- #self.EnableTool(GUIFRAME_ID.PRINT_ID, panel.get_print_flag())
- self.EnableTool(GUIFRAME_ID.UNDO_ID, panel.get_undo_flag())
- self.EnableTool(GUIFRAME_ID.REDO_ID, panel.get_redo_flag())
- self.EnableTool(GUIFRAME_ID.COPY_ID, panel.get_copy_flag())
- self.EnableTool(GUIFRAME_ID.PASTE_ID, panel.get_paste_flag())
- self.EnableTool(GUIFRAME_ID.PREVIEW_ID, panel.get_preview_flag())
- self.EnableTool(GUIFRAME_ID.RESET_ID, panel.get_reset_flag())
- self.EnableTool(GUIFRAME_ID.SAVE_ID, panel.get_save_flag())
- self._bookmark_bt.Enable(panel.get_bookmark_flag())
- self.Realize()
-
- def enable_undo(self, panel):
- self.EnableTool(GUIFRAME_ID.UNDO_ID, panel.get_undo_flag())
- self.Realize()
-
- def enable_redo(self, panel):
- self.EnableTool(GUIFRAME_ID.REDO_ID, panel.get_redo_flag())
- self.Realize()
-
- def enable_copy(self, panel):
- self.EnableTool(GUIFRAME_ID.COPY_ID, panel.get_copy_flag())
- self.Realize()
-
- def enable_paste(self, panel):
- self.EnableTool(GUIFRAME_ID.PASTE_ID, panel.get_paste_flag())
- self.Realize()
-
- def enable_print(self, panel):
- self.EnableTool(GUIFRAME_ID.PRINT_ID, panel.get_print_flag())
- self.Realize()
-
- def enable_zoom(self, panel):
- self.EnableTool(GUIFRAME_ID.ZOOM_ID, panel.get_zoom_flag())
- self.Realize()
-
- def enable_zoom_in(self, panel):
- self.EnableTool(GUIFRAME_ID.ZOOM_IN_ID, panel.get_zoom_in_flag())
- self.Realize()
-
- def enable_zoom_out(self, panel):
- self.EnableTool(GUIFRAME_ID.ZOOM_OUT_ID, panel.get_zoom_out_flag())
- self.Realize()
-
- def enable_bookmark(self, panel):
- flag = panel.get_bookmark_flag()
- self._bookmark_bt.Enable(flag)
- self.Realize()
-
- def enable_save(self, panel):
- self.EnableTool(GUIFRAME_ID.SAVE_ID, panel.get_save_flag())
- self.Realize()
-
- def enable_reset(self, panel):
- self.EnableTool(GUIFRAME_ID.RESET_ID, panel.get_reset_flag())
- self.Realize()
-
- def enable_preview(self, panel):
- self.EnableTool(GUIFRAME_ID.PREVIEW_ID, panel.get_preview_flag())
- self.Realize()
-
- def on_bookmark(self, event):
- """
- add book mark
- """
- if self.parent is not None:
- self.parent.on_bookmark_panel(event)
-
- def append_bookmark(self, event):
- """
- receive item to append on the toolbar button bookmark
- """
- title = event.title
- hint = event.hint
- handler = event.handler
- id = wx.NewId()
- self._bookmark_menu.Append(id, str(title), str(hint))
- wx.EVT_MENU(self, id, handler)
-
- def remove_bookmark_item(self, item):
- """
- Remove a bookmark item
- """
- self._bookmark_menu.DestroyItem(item)
-
- def get_bookmark_items(self):
- """
- Get bookmark menu items
- """
- return self._bookmark_menu.GetMenuItems()
-
- def append_bookmark_item(self, id, label):
- """
- Append a item in bookmark
- """
- self._bookmark_menu.Append(id, label)
Index: test/guiframe/license.txt
===================================================================
--- test/guiframe/license.txt (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,15 +1,0 @@
-This software was developed by the University of Tennessee as part of the
-Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
-project funded by the US National Science Foundation.
-
-If you use this program to do productive scientific research that leads
-to publication, we ask that you acknowledge use of the program by citing
-the following paper in your publication:
-
-P. Butler, M. Doucet, G. Alina, R. Cortes Hernandez, J. Zhou, P. Kienzle,Jae Hie Cho
-"SANS analysis software", to be published.
-
-See the DANSE project web site for license information:
-http://wiki.cacr.caltech.edu/danse/index.php/Main_Page
-
-copyright 2008, University of Tennessee for the DANSE project
Index: test/guiframe/local_perspectives/data_loader/__init__.py
===================================================================
--- test/guiframe/local_perspectives/data_loader/__init__.py (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,2 +1,0 @@
-PLUGIN_ID = "DataLoader plug-in 1.0"
-from data_loader import *
Index: test/guiframe/local_perspectives/data_loader/data_loader.py
===================================================================
--- test/guiframe/local_perspectives/data_loader/data_loader.py (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,224 +1,0 @@
-
-"""
-plugin DataLoader responsible of loading data
-"""
-import os
-import sys
-import wx
-import logging
-
-from DataLoader.loader import Loader
-import DataLoader.data_info as DataInfo
-from sans.guiframe.plugin_base import PluginBase
-from sans.guiframe.events import StatusEvent
-from sans.guiframe.events import NewPlotEvent
-from sans.guiframe.dataFitting import Data1D
-from sans.guiframe.dataFitting import Data2D
-from sans.guiframe.utils import parse_name
-from sans.guiframe.gui_style import GUIFRAME
-try:
- # Try to find a local config
- import imp
- path = os.getcwd()
- if(os.path.isfile("%s/%s.py" % (path, 'local_config'))) or \
- (os.path.isfile("%s/%s.pyc" % (path, 'local_config'))):
- fObj, path, descr = imp.find_module('local_config', [path])
- config = imp.load_module('local_config', fObj, path, descr)
- else:
- # Try simply importing local_config
- import local_config as config
-except:
- # Didn't find local config, load the default
- import config
-
-extension_list = []
-if config.APPLICATION_STATE_EXTENSION is not None:
- extension_list.append(config.APPLICATION_STATE_EXTENSION)
-EXTENSIONS = config.PLUGIN_STATE_EXTENSIONS + extension_list
-PLUGINS_WLIST = config.PLUGINS_WLIST
-APPLICATION_WLIST = config.APPLICATION_WLIST
-
-
-class Plugin(PluginBase):
-
- def __init__(self, standalone=False):
- PluginBase.__init__(self, name="DataLoader", standalone=standalone)
- #Default location
- self._default_save_location = None
- self.loader = Loader()
- self._data_menu = None
-
- def help(self, evt):
- """
- Show a general help dialog.
- """
- from help_panel import HelpWindow
- frame = HelpWindow(None, -1, 'HelpWindow')
- frame.Show(True)
-
- def populate_file_menu(self):
- """
- get a menu item and append it under file menu of the application
- add load file menu item and load folder item
- """
- #menu for data files
- menu_list = []
- data_file_hint = "load one or more data in the application"
- menu_list = [('&Load Data File(s)', data_file_hint, self.load_data)]
- gui_style = self.parent.get_style()
- style = gui_style & GUIFRAME.MULTIPLE_APPLICATIONS
- style1 = gui_style & GUIFRAME.DATALOADER_ON
- if style == GUIFRAME.MULTIPLE_APPLICATIONS:
- #menu for data from folder
- data_folder_hint = "load multiple data in the application"
- menu_list.append(('&Load Data Folder', data_folder_hint,
- self._load_folder))
- return menu_list
-
-
- def load_data(self, event):
- """
- Load data
- """
- path = None
- if self._default_save_location == None:
- self._default_save_location = os.getcwd()
-
- cards = self.loader.get_wildcards()
- temp = [APPLICATION_WLIST] + PLUGINS_WLIST
- for item in temp:
- if item in cards:
- cards.remove(item)
- wlist = '|'.join(cards)
- style = wx.OPEN|wx.FD_MULTIPLE
- dlg = wx.FileDialog(self.parent,
- "Choose a file",
- self._default_save_location, "",
- wlist,
- style=style)
- if dlg.ShowModal() == wx.ID_OK:
- file_list = dlg.GetPaths()
- if len(file_list) >= 0 and not(file_list[0]is None):
- self._default_save_location = os.path.dirname(file_list[0])
- path = self._default_save_location
- dlg.Destroy()
-
- if path is None or not file_list or file_list[0] is None:
- return
- self.get_data(file_list)
-
-
- def can_load_data(self):
- """
- if return True, then call handler to laod data
- """
- return True
-
-
- def _load_folder(self, event):
- """
- Load entire folder
- """
- path = None
- if self._default_save_location == None:
- self._default_save_location = os.getcwd()
- dlg = wx.DirDialog(self.parent, "Choose a directory",
- self._default_save_location,
- style=wx.DD_DEFAULT_STYLE)
- if dlg.ShowModal() == wx.ID_OK:
- path = dlg.GetPath()
- self._default_save_location = path
- dlg.Destroy()
- if path is not None:
- self._default_save_location = os.path.dirname(path)
- else:
- return
- file_list = self.get_file_path(path)
- self.get_data(file_list)
-
- def load_error(self, error=None):
- """
- Pop up an error message.
-
- :param error: details error message to be displayed
- """
- if error is not None or str(error).strip() != "":
- dial = wx.MessageDialog(self.parent, str(error), 'Error Loading File',
- wx.OK | wx.ICON_EXCLAMATION)
- dial.ShowModal()
-
- def get_file_path(self, path):
- """
- Receive a list containing folder then return a list of file
- """
- if os.path.isdir(path):
- return [os.path.join(os.path.abspath(path),
- file) for file in os.listdir(path)]
-
- def get_data(self, path, format=None):
- """
- """
- message = ""
- log_msg = ''
- output = {}
- error_message = ""
- for p_file in path:
- basename = os.path.basename(p_file)
- root, extension = os.path.splitext(basename)
- if extension.lower() in EXTENSIONS:
- log_msg = "Data Loader cannot "
- log_msg += "load: %s\n" % str(p_file)
- log_msg += """Please try to open that file from "open project" """
- log_msg += """or "open analysis" menu\n"""
- error_message = log_msg + "\n"
- logging.info(log_msg)
- continue
-
- try:
- temp = self.loader.load(p_file, format)
- if temp.__class__.__name__ == "list":
- for item in temp:
- data = self.parent.create_gui_data(item, p_file)
- output[data.id] = data
- else:
- data = self.parent.create_gui_data(temp, p_file)
- output[data.id] = data
- message = "Loading Data..." + str(p_file) + "\n"
- self.load_update(output=output, message=message)
- except:
- error = "Error while loading Data: %s\n" % str(p_file)
- error += str(sys.exc_value) + "\n"
- error_message = "The data file you selected could not be loaded.\n"
- error_message += "Make sure the content of your file"
- error_message += " is properly formatted.\n\n"
- error_message += "When contacting the DANSE team, mention the"
- error_message += " following:\n%s" % str(error)
- self.load_update(output=output, message=error_message)
-
- message = "Loading Data Complete! "
- message += log_msg
- self.load_complete(output=output, error_message=error_message,
- message=message, path=path)
-
- def load_update(self, output=None, message=""):
- """
- print update on the status bar
- """
- if message != "":
- wx.PostEvent(self.parent, StatusEvent(status=message,
- type="progress",
- info="warning"))
- def load_complete(self, output, message="", error_message="", path=None):
- """
- post message to status bar and return list of data
- """
- wx.PostEvent(self.parent, StatusEvent(status=message,
- info="warning",
- type="stop"))
- if error_message != "":
- self.load_error(error_message)
- self.parent.add_data(data_list=output)
-
-
-
-
Index: test/guiframe/local_perspectives/data_loader/help_panel.py
===================================================================
--- test/guiframe/local_perspectives/data_loader/help_panel.py (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,105 +1,0 @@
-#!/usr/bin/python
-"""
-Help panel for data_loader plugins
-"""
-import os
-import wx
-import wx.html as html
-from wx.lib.splitter import MultiSplitterWindow
-from sans.guiframe import get_media_path
-
-class HelpWindow(wx.Frame):
- """
- """
- def __init__(self, parent, title='Plotting Help', pageToOpen=None):
- wx.Frame.__init__(self, parent, title, size=(700, 450))
- """
- contains help info
- """
- splitter = MultiSplitterWindow(self, style=wx.SP_LIVE_UPDATE)
- rpanel = wx.Panel(splitter, -1)
- lpanel = wx.Panel(splitter, -1, style=wx.BORDER_SUNKEN)
-
- vbox = wx.BoxSizer(wx.VERTICAL)
- header = wx.Panel(rpanel, -1)
- header.SetBackgroundColour('#6666FF')
- header.SetForegroundColour('WHITE')
- hbox = wx.BoxSizer(wx.HORIZONTAL)
- st = wx.StaticText(header, -1, 'Contents', (5, 5))
- font = st.GetFont()
- font.SetPointSize(10)
- st.SetFont(font)
- hbox.Add(st, 1, wx.TOP | wx.BOTTOM | wx.LEFT, 5)
- header.SetSizer(hbox)
- vbox.Add(header, 0, wx.EXPAND)
-
- vboxl = wx.BoxSizer(wx.VERTICAL)
- headerl = wx.Panel(lpanel, -1, size=(-1, 20))
-
- headerl.SetBackgroundColour('#6666FF')
- headerl.SetForegroundColour('WHITE')
- hboxl = wx.BoxSizer(wx.HORIZONTAL)
- lst = wx.StaticText(headerl, -1, 'Menu', (5, 5))
- fontl = lst.GetFont()
- fontl.SetPointSize(10)
- lst.SetFont(fontl)
- hboxl.Add(lst, 1, wx.TOP | wx.BOTTOM | wx.LEFT, 5)
- headerl.SetSizer(hboxl)
- vboxl.Add(headerl, 0, wx.EXPAND)
- self.lhelp = html.HtmlWindow(lpanel, -1, style=wx.NO_BORDER)
- self.rhelp = html.HtmlWindow(rpanel, -1, style=wx.NO_BORDER,
- size=(500,-1))
-
- self.path = get_media_path(media='media')
- page1 = """
-
- Select topic on Menu
-
- """
- self.rhelp.SetPage(page1)
- page = """
-
-
-
- """
-
- self.lhelp.SetPage(page)
- self.lhelp.Bind(wx.html.EVT_HTML_LINK_CLICKED, self.OnLinkClicked)
-
- vbox.Add(self.rhelp, 1, wx.EXPAND)
- vboxl.Add(self.lhelp, 1, wx.EXPAND)
- rpanel.SetSizer(vbox)
- lpanel.SetSizer(vboxl)
- lpanel.SetFocus()
-
- vbox1 = wx.BoxSizer(wx.HORIZONTAL)
- vbox1.Add(splitter, 1, wx.EXPAND)
- splitter.AppendWindow(lpanel, 200)
- splitter.AppendWindow(rpanel)
- self.SetSizer(vbox1)
-
- self.Centre()
- self.Show(True)
-
- def OnLinkClicked(self, event):
- """
- Function to diplay html page related to the hyperlinktext selected
- """
- link = event.GetLinkInfo().GetHref()
- link = os.path.join(self.path, link)
- self.rhelp.LoadPage(link)
-
-
-class ViewApp(wx.App):
- def OnInit(self):
- frame = HelpWindow(None, -1, 'HelpWindow')
- frame.Show(True)
- self.SetTopWindow(frame)
- return True
-
-if __name__ == "__main__":
- app = ViewApp(0)
- app.MainLoop()
Index: test/guiframe/local_perspectives/data_loader/load_thread.py
===================================================================
--- test/guiframe/local_perspectives/data_loader/load_thread.py (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,85 +1,0 @@
-
-import time
-import sys
-import os
-
-from data_util.calcthread import CalcThread
-
-
-EXTENSIONS = ['.svs', '.prv', '.inv', '.fitv']
-
-class DataReader(CalcThread):
- """
- Load a data given a filename
- """
- def __init__(self, path, loader,
- flag=True,
- transform_data=None,
- completefn=None,
- updatefn = None,
- yieldtime = 0.01,
- worktime = 0.01
- ):
- CalcThread.__init__(self, completefn,
- updatefn,
- yieldtime,
- worktime)
- self.load_state_flag = flag
- self.transform_data = transform_data
- self.list_path = path
- #Instantiate a loader
- self.loader = loader
- self.message = ""
- self.starttime = 0
- self.updatefn = updatefn
-
- def isquit(self):
- """
- :raise KeyboardInterrupt: when the thread is interrupted
- """
- try:
- CalcThread.isquit(self)
- except KeyboardInterrupt:
- raise KeyboardInterrupt
-
-
- def compute(self):
- """
- read some data
- """
- self.starttime = time.time()
- output = []
- error_message = ""
- for path in self.list_path:
- basename = os.path.basename(path)
- root, extension = os.path.splitext(basename)
- if self.load_state_flag:
- if extension.lower() in EXTENSIONS:
- pass
- else:
- if extension.lower() not in EXTENSIONS:
- pass
- try:
- temp = self.loader.load(path)
- elapsed = time.time() - self.starttime
- if temp.__class__.__name__ == "list":
- for item in temp:
- data = self.transform_data(item, path)
- output.append(data)
- else:
- data = self.transform_data(temp, path)
- output.append(data)
- message = "Loading ..." + str(path) + "\n"
- if self.updatefn is not None:
- self.updatefn(output=output, message=message)
- except:
- error_message = "Error while loading: %s\n" % str(path)
- error_message += str(sys.exc_value) + "\n"
- self.updatefn(output=output, message=error_message)
-
- message = "Loading Complete!"
- self.complete(output=output, error_message=error_message,
- message=message, path=self.list_path)
-
-
-
Index: test/guiframe/local_perspectives/plotting/AnnulusSlicer.py
===================================================================
--- test/guiframe/local_perspectives/plotting/AnnulusSlicer.py (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,612 +1,0 @@
-#TODO: the line slicer should listen to all 2DREFRESH events, get the data and slice it
-# before pushing a new 1D data update.
-
-#
-#TODO: NEED MAJOR REFACTOR
-#
-
-import math
-import wx
-#from copy import deepcopy
-# Debug printout
-from sans.guiframe.events import NewPlotEvent
-from sans.guiframe.events import StatusEvent
-from sans.guiframe.events import SlicerParameterEvent
-from sans.guiframe.events import EVT_SLICER_PARS
-from BaseInteractor import _BaseInteractor
-from sans.guiframe.dataFitting import Data1D
-
-class AnnulusInteractor(_BaseInteractor):
- """
- Select an annulus through a 2D plot.
- This interactor is used to average 2D data with the region
- defined by 2 radius.
- this class is defined by 2 Ringinterators.
- """
- def __init__(self, base, axes, color='black', zorder=3):
-
- _BaseInteractor.__init__(self, base, axes, color=color)
- self.markers = []
- self.axes = axes
- self.base = base
- self.qmax = min(math.fabs(self.base.data2D.xmax),
- math.fabs(self.base.data2D.xmin)) #must be positive
- self.connect = self.base.connect
-
- ## Number of points on the plot
- self.nbins = 20
- #Cursor position of Rings (Left(-1) or Right(1))
- self.xmaxd = self.base.data2D.xmax
- self.xmind = self.base.data2D.xmin
-
- if (self.xmaxd + self.xmind) > 0:
- self.sign = 1
- else:
- self.sign = -1
- # Inner circle
- self.inner_circle = RingInteractor(self, self.base.subplot,
- zorder=zorder,
- r=self.qmax/2.0, sign=self.sign)
- self.inner_circle.qmax = self.qmax
- self.outer_circle = RingInteractor(self, self.base.subplot,
- zorder=zorder+1, r=self.qmax/1.8,
- sign=self.sign)
- self.outer_circle.qmax = self.qmax * 1.2
- self.update()
- self._post_data()
-
- # Bind to slice parameter events
- self.base.Bind(EVT_SLICER_PARS, self._onEVT_SLICER_PARS)
-
- def _onEVT_SLICER_PARS(self, event):
- """
- receive an event containing parameters values to reset the slicer
-
- :param event: event of type SlicerParameterEvent with params as
- attribute
-
- """
- wx.PostEvent(self.base,
- StatusEvent(status="AnnulusSlicer._onEVT_SLICER_PARS"))
- event.Skip()
- if event.type == self.__class__.__name__:
- self.set_params(event.params)
- self.base.update()
-
- def set_layer(self, n):
- """
- Allow adding plot to the same panel
-
- :param n: the number of layer
-
- """
- self.layernum = n
- self.update()
-
- def clear(self):
- """
- Clear the slicer and all connected events related to this slicer
- """
- self.clear_markers()
- self.outer_circle.clear()
- self.inner_circle.clear()
- self.base.connect.clearall()
- self.base.Unbind(EVT_SLICER_PARS)
-
- def update(self):
- """
- Respond to changes in the model by recalculating the profiles and
- resetting the widgets.
- """
- # Update locations
- self.inner_circle.update()
- self.outer_circle.update()
-
- def save(self, ev):
- """
- Remember the roughness for this layer and the next so that we
- can restore on Esc.
- """
- self.base.freeze_axes()
- self.inner_circle.save(ev)
- self.outer_circle.save(ev)
-
- def _post_data(self, nbins=None):
- """
- Uses annulus parameters to plot averaged data into 1D data.
-
- :param nbins: the number of points to plot
-
- """
- #Data to average
- data = self.base.data2D
- # If we have no data, just return
- if data == None:
- return
-
- from DataLoader.manipulations import Ring
- rmin = min(math.fabs(self.inner_circle.get_radius()),
- math.fabs(self.outer_circle.get_radius()))
- rmax = max(math.fabs(self.inner_circle.get_radius()),
- math.fabs(self.outer_circle.get_radius()))
- #if the user does not specify the numbers of points to plot
- # the default number will be nbins= 20
- if nbins == None:
- self.nbins = 20
- else:
- self.nbins = nbins
- ## create the data1D Q average of data2D
- sect = Ring(r_min=rmin, r_max=rmax, nbins=self.nbins)
- sector = sect(self.base.data2D)
-
- if hasattr(sector, "dxl"):
- dxl = sector.dxl
- else:
- dxl = None
- if hasattr(sector, "dxw"):
- dxw = sector.dxw
- else:
- dxw = None
- new_plot = Data1D(x=(sector.x - math.pi) * 180/math.pi,
- y=sector.y, dy=sector.dy)
- new_plot.dxl = dxl
- new_plot.dxw = dxw
- new_plot.name = "AnnulusPhi" +"("+ self.base.data2D.name+")"
-
- new_plot.source = self.base.data2D.source
- #new_plot.info=self.base.data2D.info
- new_plot.interactive = True
- new_plot.detector = self.base.data2D.detector
- # If the data file does not tell us what the axes are, just assume...
- new_plot.xaxis("\\rm{\phi}", 'degrees')
- new_plot.yaxis("\\rm{Intensity} ", "cm^{-1}")
- if hasattr(data, "scale") and data.scale == 'linear' and \
- self.base.data2D.name.count("Residuals") > 0:
- new_plot.ytransform = 'y'
- new_plot.yaxis("\\rm{Residuals} ", "/")
-
- new_plot.group_id = "AnnulusPhi" + self.base.data2D.name
- new_plot.id = None
- #new_plot.is_data= True
- new_plot.xtransform = "x"
- new_plot.ytransform = "y"
- wx.PostEvent(self.base.parent, NewPlotEvent(plot=new_plot,
- title="AnnulusPhi"))
-
- def moveend(self, ev):
- """
- Called when any dragging motion ends.
- Post an event (type =SlicerParameterEvent)
- to plotter 2D with a copy slicer parameters
- Call _post_data method
- """
- self.base.thaw_axes()
- # Post parameters to plotter 2D
- event = SlicerParameterEvent()
- event.type = self.__class__.__name__
- event.params = self.get_params()
- wx.PostEvent(self.base, event)
- # create a 1D data plot
- #self._post_data()
-
- def restore(self):
- """
- Restore the roughness for this layer.
- """
- self.inner_circle.restore()
- self.outer_circle.restore()
-
- def move(self, x, y, ev):
- """
- Process move to a new position, making sure that the move is allowed.
- """
- pass
-
- def set_cursor(self, x, y):
- pass
-
- def get_params(self):
- """
- Store a copy of values of parameters of the slicer into a dictionary.
-
- :return params: the dictionary created
-
- """
- params = {}
- params["inner_radius"] = math.fabs(self.inner_circle._inner_mouse_x)
- params["outer_radius"] = math.fabs(self.outer_circle._inner_mouse_x)
- params["nbins"] = self.nbins
- return params
-
- def set_params(self, params):
- """
- Receive a dictionary and reset the slicer with values contained
- in the values of the dictionary.
-
- :param params: a dictionary containing name of slicer parameters and
- values the user assigned to the slicer.
-
- """
- inner = math.fabs(params["inner_radius"])
- outer = math.fabs(params["outer_radius"])
- self.nbins = int(params["nbins"])
- ## Update the picture
- self.inner_circle.set_cursor(inner, self.inner_circle._inner_mouse_y)
- self.outer_circle.set_cursor(outer, self.outer_circle._inner_mouse_y)
- ## Post the data given the nbins entered by the user
- self._post_data(self.nbins)
-
- def freeze_axes(self):
- """
- """
- self.base.freeze_axes()
-
- def thaw_axes(self):
- """
- """
- self.base.thaw_axes()
-
- def draw(self):
- """
- """
- self.base.draw()
-
-
-class RingInteractor(_BaseInteractor):
- """
- Draw a ring Given a radius
- """
- def __init__(self, base, axes, color='black', zorder=5, r=1.0, sign=1):
- """
- :param: the color of the line that defined the ring
- :param r: the radius of the ring
- :param sign: the direction of motion the the marker
-
- """
- _BaseInteractor.__init__(self, base, axes, color=color)
- self.markers = []
- self.axes = axes
- # Current radius of the ring
- self._inner_mouse_x = r
- #Value of the center of the ring
- self._inner_mouse_y = 0
- # previous value of that radius
- self._inner_save_x = r
- #Save value of the center of the ring
- self._inner_save_y = 0
- #Class instantiating RingIterator class
- self.base = base
- #the direction of the motion of the marker
- self.sign = sign
- ## Create a marker
- try:
- # Inner circle marker
- x_value = [self.sign * math.fabs(self._inner_mouse_x)]
- self.inner_marker = self.axes.plot(x_value,
- [0],
- linestyle='',
- marker='s', markersize=10,
- color=self.color, alpha=0.6,
- pickradius=5, label="pick",
- zorder=zorder,
- visible=True)[0]
- except:
- x_value = [self.sign * math.fabs(self._inner_mouse_x)]
- self.inner_marker = self.axes.plot(x_value,
- [0],
- linestyle='',
- marker='s', markersize=10,
- color=self.color, alpha=0.6,
- label="pick",
- visible=True)[0]
- message = "\nTHIS PROTOTYPE NEEDS THE LATEST"
- message += " VERSION OF MATPLOTLIB\n"
- message += "Get the SVN version that is at "
- message += " least as recent as June 1, 2007"
-
- owner = self.base.base.parent
- wx.PostEvent(owner,
- StatusEvent(status="AnnulusSlicer: %s" % message))
-
- # Draw a circle
- [self.inner_circle] = self.axes.plot([], [],
- linestyle='-', marker='',
- color=self.color)
- # the number of points that make the ring line
- self.npts = 40
-
- self.connect_markers([self.inner_marker])
- self.update()
-
- def set_layer(self, n):
- """
- Allow adding plot to the same panel
-
- :param n: the number of layer
-
- """
- self.layernum = n
- self.update()
-
- def clear(self):
- """
- Clear the slicer and all connected events related to this slicer
- """
- self.clear_markers()
- try:
- self.inner_marker.remove()
- self.inner_circle.remove()
- except:
- # Old version of matplotlib
- for item in range(len(self.axes.lines)):
- del self.axes.lines[0]
-
- def get_radius(self):
- """
- :return self._inner_mouse_x: the current radius of the ring
- """
- return self._inner_mouse_x
-
- def update(self):
- """
- Draw the new roughness on the graph.
- """
- # Plot inner circle
- x = []
- y = []
- for i in range(self.npts):
- phi = 2.0 * math.pi / (self.npts - 1) * i
-
- xval = 1.0 * self._inner_mouse_x * math.cos(phi)
- yval = 1.0 * self._inner_mouse_x * math.sin(phi)
-
- x.append(xval)
- y.append(yval)
-
- self.inner_marker.set(xdata=[self.sign*math.fabs(self._inner_mouse_x)],
- ydata=[0])
- self.inner_circle.set_data(x, y)
-
- def save(self, ev):
- """
- Remember the roughness for this layer and the next so that we
- can restore on Esc.
- """
- self._inner_save_x = self._inner_mouse_x
- self._inner_save_y = self._inner_mouse_y
- self.base.freeze_axes()
-
- def moveend(self, ev):
- """
- Called after a dragging motion
- """
- self.base.moveend(ev)
-
- def restore(self):
- """
- Restore the roughness for this layer.
- """
- self._inner_mouse_x = self._inner_save_x
- self._inner_mouse_y = self._inner_save_y
-
- def move(self, x, y, ev):
- """
- Process move to a new position, making sure that the move is allowed.
- """
- self._inner_mouse_x = x
- self._inner_mouse_y = y
- self.base.base.update()
-
- def set_cursor(self, x, y):
- """
- draw the ring given x, y value
- """
- self.move(x, y, None)
- self.update()
-
-
- def get_params(self):
- """
- Store a copy of values of parameters of the slicer into a dictionary.
-
- :return params: the dictionary created
-
- """
- params = {}
- params["radius"] = math.fabs(self._inner_mouse_x)
- return params
-
- def set_params(self, params):
- """
- Receive a dictionary and reset the slicer with values contained
- in the values of the dictionary.
-
- :param params: a dictionary containing name of slicer parameters and
- values the user assigned to the slicer.
-
- """
- x = params["radius"]
- self.set_cursor(x, self._inner_mouse_y)
-
-class CircularMask(_BaseInteractor):
- """
- Draw a ring Given a radius
- """
- def __init__(self, base, axes, color='grey', zorder=3, side=None):
- """
-
- :param: the color of the line that defined the ring
- :param r: the radius of the ring
- :param sign: the direction of motion the the marker
-
- """
- _BaseInteractor.__init__(self, base, axes, color=color)
- self.markers = []
- self.axes = axes
- self.base = base
- self.is_inside = side
- self.qmax = min(math.fabs(self.base.data.xmax),
- math.fabs(self.base.data.xmin)) #must be positive
- self.connect = self.base.connect
-
- #Cursor position of Rings (Left(-1) or Right(1))
- self.xmaxd = self.base.data.xmax
- self.xmind = self.base.data.xmin
-
- if (self.xmaxd + self.xmind) > 0:
- self.sign = 1
- else:
- self.sign = -1
- # Inner circle
- self.outer_circle = RingInteractor(self, self.base.subplot, 'blue',
- zorder=zorder+1, r=self.qmax/1.8,
- sign=self.sign)
- self.outer_circle.qmax = self.qmax * 1.2
- self.update()
- self._post_data()
-
- # Bind to slice parameter events
- #self.base.Bind(EVT_SLICER_PARS, self._onEVT_SLICER_PARS)
-
- def _onEVT_SLICER_PARS(self, event):
- """
- receive an event containing parameters values to reset the slicer
-
- :param event: event of type SlicerParameterEvent with params as
- attribute
- """
- wx.PostEvent(self.base,
- StatusEvent(status="AnnulusSlicer._onEVT_SLICER_PARS"))
- event.Skip()
- if event.type == self.__class__.__name__:
- self.set_params(event.params)
- self.base.update()
-
- def set_layer(self, n):
- """
- Allow adding plot to the same panel
-
- :param n: the number of layer
-
- """
- self.layernum = n
- self.update()
-
- def clear(self):
- """
- Clear the slicer and all connected events related to this slicer
- """
- self.clear_markers()
- self.outer_circle.clear()
- self.base.connect.clearall()
- #self.base.Unbind(EVT_SLICER_PARS)
-
- def update(self):
- """
- Respond to changes in the model by recalculating the profiles and
- resetting the widgets.
- """
- # Update locations
- self.outer_circle.update()
- #if self.is_inside != None:
- out = self._post_data()
- return out
-
- def save(self, ev):
- """
- Remember the roughness for this layer and the next so that we
- can restore on Esc.
- """
- self.base.freeze_axes()
- self.outer_circle.save(ev)
-
- def _post_data(self):
- """
- Uses annulus parameters to plot averaged data into 1D data.
-
- :param nbins: the number of points to plot
-
- """
- #Data to average
- data = self.base.data
-
- # If we have no data, just return
- if data == None:
- return
- mask = data.mask
- from DataLoader.manipulations import Ringcut
-
- rmin = 0
- rmax = math.fabs(self.outer_circle.get_radius())
-
- ## create the data1D Q average of data2D
- mask = Ringcut(r_min=rmin, r_max= rmax)
-
- if self.is_inside:
- out = (mask(data) == False)
- else:
- out = (mask(data))
- #self.base.data.mask=out
- return out
-
-
- def moveend(self, ev):
- """
- Called when any dragging motion ends.
- Post an event (type =SlicerParameterEvent)
- to plotter 2D with a copy slicer parameters
- Call _post_data method
- """
- self.base.thaw_axes()
- # create a 1D data plot
- self._post_data()
-
- def restore(self):
- """
- Restore the roughness for this layer.
- """
- self.outer_circle.restore()
-
- def move(self, x, y, ev):
- """
- Process move to a new position, making sure that the move is allowed.
- """
- pass
-
- def set_cursor(self, x, y):
- pass
-
- def get_params(self):
- """
- Store a copy of values of parameters of the slicer into a dictionary.
-
- :return params: the dictionary created
-
- """
- params = {}
- params["outer_radius"] = math.fabs(self.outer_circle._inner_mouse_x)
- return params
-
- def set_params(self, params):
- """
- Receive a dictionary and reset the slicer with values contained
- in the values of the dictionary.
-
- :param params: a dictionary containing name of slicer parameters and
- values the user assigned to the slicer.
- """
- outer = math.fabs(params["outer_radius"] )
- ## Update the picture
- self.outer_circle.set_cursor(outer, self.outer_circle._inner_mouse_y)
- ## Post the data given the nbins entered by the user
- self._post_data()
-
- def freeze_axes(self):
- self.base.freeze_axes()
-
- def thaw_axes(self):
- self.base.thaw_axes()
-
- def draw(self):
- self.base.update()
-
Index: test/guiframe/local_perspectives/plotting/Arc.py
===================================================================
--- test/guiframe/local_perspectives/plotting/Arc.py (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,162 +1,0 @@
-
-import math
-import wx
-from copy import deepcopy
-
-from BaseInteractor import _BaseInteractor
-from sans.guiframe.events import NewPlotEvent
-from sans.guiframe.events import StatusEvent
-from sans.guiframe.events import SlicerParameterEvent
-from sans.guiframe.events import EVT_SLICER_PARS
-
-
-class ArcInteractor(_BaseInteractor):
- """
- Select an annulus through a 2D plot
- """
- def __init__(self, base, axes, color='black', zorder=5, r=1.0,
- theta1=math.pi/8, theta2=math.pi/4):
-
- _BaseInteractor.__init__(self, base, axes, color=color)
- self.markers = []
- self.axes = axes
- self._mouse_x = r
- self._mouse_y = 0
-
- self._save_x = r
- self._save_y = 0
-
- self.scale = 10.0
-
- self.theta1 = theta1
- self.theta2 = theta2
- self.radius = r
- [self.arc] = self.axes.plot([], [],
- linestyle='-', marker='',
- color=self.color)
- self.npts = 20
- self.has_move = False
- self.connect_markers([self.arc])
- self.update()
-
- def set_layer(self, n):
- """
- """
- self.layernum = n
- self.update()
-
- def clear(self):
- """
- """
- self.clear_markers()
- try:
- self.marker.remove()
- self.arc.remove()
- except:
- # Old version of matplotlib
- for item in range(len(self.axes.lines)):
- del self.axes.lines[0]
-
- def get_radius(self):
- """
- """
- radius = math.sqrt(math.pow(self._mouse_x, 2) + \
- math.pow(self._mouse_y, 2))
- return radius
-
- def update(self, theta1=None, theta2=None, nbins=None, r=None):
- """
- """
- # Plot inner circle
- x = []
- y = []
- if theta1 != None:
- self.theta1 = theta1
- if theta2 != None:
- self.theta2 = theta2
- #print "ring update theta1 theta2", math.degrees(self.theta1),
- #math.degrees(self.theta2)
- while self.theta2 < self.theta1:
- self.theta2 += (2 * math.pi)
- while self.theta2 >= (self.theta1 + 2 * math.pi):
- self.theta2 -= (2 * math.pi)
- npts = int((self.theta2 - self.theta1)/(math.pi/120))
-
- if r == None:
- self.radius = math.sqrt(math.pow(self._mouse_x, 2) + \
- math.pow(self._mouse_y, 2))
- else:
- self.radius = r
- for i in range(self.npts):
- phi = (self.theta2 - self.theta1)/(self.npts - 1) * i + self.theta1
- xval = 1.0 * self.radius * math.cos(phi)
- yval = 1.0 * self.radius * math.sin(phi)
-
- x.append(xval)
- y.append(yval)
- #self.marker.set(xdata=[self._mouse_x],ydata=[0])
- self.arc.set_data(x, y)
-
- def save(self, ev):
- """
- Remember the roughness for this layer and the next so that we
- can restore on Esc.
- """
- self._save_x = self._mouse_x
- self._save_y = self._mouse_y
- #self._save_x = ev.xdata
- #self._save_y = ev.ydata
- self.base.freeze_axes()
-
- def moveend(self, ev):
- """
- """
- self.has_move = False
-
- event = SlicerParameterEvent()
- event.type = self.__class__.__name__
- event.params = self.get_params()
- #print "in arc moveend params",self.get_params()
- #wx.PostEvent(self.base.base.parent, event)
- self.base.moveend(ev)
-
- def restore(self):
- """
- Restore the roughness for this layer.
- """
- self._mouse_x = self._save_x
- self._mouse_y = self._save_y
-
- def move(self, x, y, ev):
- """
- Process move to a new position, making sure that the move is allowed.
- """
- #print "ring move x, y", x,y
- self._mouse_x = x
- self._mouse_y = y
- self.has_move = True
- self.base.base.update()
-
- def set_cursor(self, radius, phi_min, phi_max, nbins):
- """
- """
- self.theta1 = phi_min
- self.theta2 = phi_max
- self.update(nbins=nbins, r=radius)
-
- def get_params(self):
- """
- """
- params = {}
- params["radius"] = self.radius
- params["theta1"] = self.theta1
- params["theta2"] = self.theta2
- return params
-
- def set_params(self, params):
- """
- """
- x = params["radius"]
- self.set_cursor(x, self._mouse_y)
-
-
Index: test/guiframe/local_perspectives/plotting/AzimutSlicer.py
===================================================================
--- test/guiframe/local_perspectives/plotting/AzimutSlicer.py (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,312 +1,0 @@
-#TODO: the line slicer should listen to all 2DREFRESH events, get the data and slice it
-# before pushing a new 1D data update.
-
-#
-#TODO: NEED MAJOR REFACTOR
-#
-
-
-# Debug printout
-import math
-import wx
-from copy import deepcopy
-from BaseInteractor import _BaseInteractor
-from sans.guiframe.events import NewPlotEvent
-from sans.guiframe.events import StatusEvent
-from sans.guiframe.events import SlicerParameterEvent
-from sans.guiframe.events import EVT_SLICER_PARS
-
-
-class SectorInteractor(_BaseInteractor):
- """
- Select an annulus through a 2D plot
- """
- def __init__(self, base, axes, color='black', zorder=3):
- """
- """
- _BaseInteractor.__init__(self, base, axes, color=color)
- self.markers = []
- self.axes = axes
- self.qmax = self.base.data2D.xmax
- self.connect = self.base.connect
-
- ## Number of points on the plot
- self.nbins = 20
- theta1 = math.pi/8
- theta2 = math.pi/2
- theta1 = 2 * math.pi/3
- theta2 = -2 * math.pi/3
- r1 = self.qmax/2.0
- r2 = self.qmax/1.8
-
- # Inner circle
- from Arc import ArcInteractor
- self.inner_circle = ArcInteractor(self, self.base.subplot,
- zorder=zorder,
- r=self.qmax/2.0,
- theta1=theta1,
- theta2=theta2)
- self.inner_circle.qmax = self.qmax
- self.outer_circle = ArcInteractor(self, self.base.subplot,
- zorder=zorder+1,
- r=self.qmax/1.8,
- theta1=theta1,
- theta2=theta2)
- self.outer_circle.qmax = self.qmax * 1.2
- #self.outer_circle.set_cursor(self.base.qmax/1.8, 0)
- from Edge import RadiusInteractor
- self.right_edge= RadiusInteractor(self, self.base.subplot,
- zorder=zorder+1,
- arc1=self.inner_circle,
- arc2=self.outer_circle,
- theta=theta1)
- self.left_edge= RadiusInteractor(self, self.base.subplot,
- zorder=zorder+1,
- arc1=self.inner_circle,
- arc2=self.outer_circle,
- theta=theta2)
- self.update()
- self._post_data()
- # Bind to slice parameter events
- self.base.parent.Bind(EVT_SLICER_PARS, self._onEVT_SLICER_PARS)
-
- def _onEVT_SLICER_PARS(self, event):
- """
- """
- #printEVT("AnnulusSlicer._onEVT_SLICER_PARS")
- event.Skip()
- if event.type == self.__class__.__name__:
- self.set_params(event.params)
- self.base.update()
-
- def save_data(self, path, image, x, y):
- """
- """
- output = open(path, 'w')
- data_x, data_y = self.get_data(image, x, y)
-
- output.write(" \n")
- for i in range(len(data_x)):
- output.write("%g %g\n" % (data_x[i], data_y[i]))
- output.close()
-
- def set_layer(self, n):
- """
- """
- self.layernum = n
- self.update()
-
- def clear(self):
- """
- """
- self.clear_markers()
- self.outer_circle.clear()
- self.inner_circle.clear()
- self.right_edge.clear()
- self.left_edge.clear()
- #self.base.connect.disconnect()
- self.base.parent.Unbind(EVT_SLICER_PARS)
-
- def update(self):
- """
- Respond to changes in the model by recalculating the profiles and
- resetting the widgets.
- """
- # Update locations
- if self.inner_circle.has_move:
- #print "inner circle has moved"
- self.inner_circle.update()
- r1 = self.inner_circle.get_radius()
- r2 = self.outer_circle.get_radius()
- self.right_edge.update(r1, r2)
- self.left_edge.update(r1, r2)
- if self.outer_circle.has_move:
- #print "outer circle has moved"
- self.outer_circle.update()
- r1 = self.inner_circle.get_radius()
- r2 = self.outer_circle.get_radius()
- self.left_edge.update(r1, r2)
- self.right_edge.update(r1, r2)
- if self.right_edge.has_move:
- #print "right edge has moved"
- self.right_edge.update()
- self.inner_circle.update(theta1=self.right_edge.get_angle(),
- theta2=None)
- self.outer_circle.update(theta1=self.right_edge.get_angle(),
- theta2=None)
- if self.left_edge.has_move:
- #print "left Edge has moved"
- self.left_edge.update()
- self.inner_circle.update(theta1=None,
- theta2=self.left_edge.get_angle())
- self.outer_circle.update(theta1=None,
- theta2=self.left_edge.get_angle())
-
- def save(self, ev):
- """
- Remember the roughness for this layer and the next so that we
- can restore on Esc.
- """
- self.base.freeze_axes()
- self.inner_circle.save(ev)
- self.outer_circle.save(ev)
- self.right_edge.save(ev)
- self.left_edge.save(ev)
-
- def _post_data(self):
- pass
-
- def post_data(self,new_sector ):
- """ post data averaging in Q"""
- if self.inner_circle.get_radius() < self.outer_circle.get_radius():
- rmin = self.inner_circle.get_radius()
- rmax = self.outer_circle.get_radius()
- else:
- rmin = self.outer_circle.get_radius()
- rmax = self.inner_circle.get_radius()
- if self.right_edge.get_angle() < self.left_edge.get_angle():
- phimin = self.right_edge.get_angle()
- phimax = self.left_edge.get_angle()
- else:
- phimin = self.left_edge.get_angle()
- phimax = self.right_edge.get_angle()
- #print "phimin, phimax, rmin ,rmax",math.degrees(phimin),
- # math.degrees(phimax), rmin ,rmax
- #from DataLoader.manipulations import SectorQ
-
- sect = new_sector(r_min=rmin, r_max=rmax,
- phi_min=phimin, phi_max=phimax)
- sector = sect(self.base.data2D)
-
- from sans.guiframe.dataFitting import Data1D
- if hasattr(sector, "dxl"):
- dxl = sector.dxl
- else:
- dxl = None
- if hasattr(sector, "dxw"):
- dxw = sector.dxw
- else:
- dxw = None
- new_plot = Data1D(x=sector.x, y=sector.y, dy=sector.dy,
- dxl=dxl, dxw=dxw)
- new_plot.name = str(new_sector.__name__) + \
- "("+ self.base.data2D.name+")"
- new_plot.source = self.base.data2D.source
- new_plot.interactive = True
- #print "loader output.detector",output.source
- new_plot.detector = self.base.data2D.detector
- # If the data file does not tell us what the axes are, just assume...
- new_plot.xaxis("\\rm{Q}", 'rad')
- new_plot.yaxis("\\rm{Intensity} ", "cm^{-1}")
- new_plot.group_id = str(new_sector.__name__) + self.base.data2D.name
- wx.PostEvent(self.base.parent,
- NewPlotEvent(plot=new_plot, title=str(new_sector.__name__)))
-
- def moveend(self, ev):
- #self.base.thaw_axes()
-
- # Post paramters
- #event = SlicerParameterEvent()
- #event.type = self.__class__.__name__
- #event.params = self.get_params()
- #print "main moveend ", event.params
- #wx.PostEvent(self.base.parent, event)
- #self._post_data()
- pass
-
- def restore(self):
- """
- Restore the roughness for this layer.
- """
- self.inner_circle.restore()
- self.outer_circle.restore()
- self.right_edge.restore()
- self.left_edge.restore()
-
- def move(self, x, y, ev):
- """
- Process move to a new position, making sure that the move is allowed.
- """
- pass
-
- def set_cursor(self, x, y):
- """
- """
- pass
-
- def get_params(self):
- """
- """
- params = {}
- params["r_min"] = self.inner_circle.get_radius()
- params["r_max"] = self.outer_circle.get_radius()
- params["phi_min"] = self.right_edge.get_angle()
- params["phi_max"] = self.left_edge.get_angle()
- params["nbins"] = self.nbins
- return params
-
- def set_params(self, params):
- """
- """
- #print "setparams on main slicer ",params
- inner = params["r_min"]
- outer = params["r_max"]
- phi_min= params["phi_min"]
- phi_max=params["phi_max"]
- self.nbins = int(params["nbins"])
-
- self.inner_circle.set_cursor(inner, phi_min, phi_max,self.nbins)
- self.outer_circle.set_cursor(outer, phi_min, phi_max, self.nbins)
- self.right_edge.set_cursor(inner, outer, phi_min)
- self.left_edge.set_cursor(inner, outer, phi_max)
- self._post_data()
-
- def freeze_axes(self):
- """
- """
- self.base.freeze_axes()
-
- def thaw_axes(self):
- """
- """
- self.base.thaw_axes()
-
- def draw(self):
- """
- """
- self.base.draw()
-
-class SectorInteractorQ(SectorInteractor):
- """
- """
- def __init__(self, base, axes, color='black', zorder=3):
- """
- """
- SectorInteractor.__init__(self, base, axes, color=color)
- self.base=base
- self._post_data()
-
- def _post_data(self):
- """
- """
- from DataLoader.manipulations import SectorQ
- self.post_data(SectorQ)
-
-
-class SectorInteractorPhi(SectorInteractor):
- """
- """
- def __init__(self, base, axes, color='black', zorder=3):
- """
- """
- SectorInteractor.__init__(self, base, axes, color=color)
- self.base=base
- self._post_data()
-
- def _post_data(self):
- """
- """
- from DataLoader.manipulations import SectorPhi
- self.post_data(SectorPhi )
-
-
Index: test/guiframe/local_perspectives/plotting/BaseInteractor.py
===================================================================
--- test/guiframe/local_perspectives/plotting/BaseInteractor.py (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,180 +1,0 @@
-interface_color = 'black'
-disable_color = 'gray'
-active_color = 'red'
-rho_color = 'black'
-mu_color = 'green'
-P_color = 'blue'
-theta_color = 'orange'
-profile_colors = [rho_color, mu_color, P_color, theta_color]
-
-class _BaseInteractor:
- """
- Share some functions between the interface interactor and various layer
- interactors.
-
- Individual interactors need the following functions:
-
- save(ev) - save the current state for later restore
- restore() - restore the old state
- move(x,y,ev) - move the interactor to position x,y
- moveend(ev) - end the drag event
- update() - draw the interactors
-
- The following are provided by the base class:
-
- connect_markers(markers) - register callbacks for all markers
- clear_markers() - remove all items in self.markers
- onHilite(ev) - enter/leave event processing
- onLeave(ev) - enter/leave event processing
- onClick(ev) - mouse click: calls save()
- onRelease(ev) - mouse click ends: calls moveend()
- onDrag(ev) - mouse move: calls move() or restore()
- onKey(ev) - keyboard move: calls move() or restore()
-
- Interactor attributes:
-
- base - model we are operating on
- axes - axes holding the interactor
- color - color of the interactor in non-active state
- markers - list of handles for the interactor
-
- """
- def __init__(self, base, axes, color='black'):
- """
- """
- self.base = base
- self.axes = axes
- self.color = color
- self.clickx = None
- self.clicky = None
- self.markers = []
-
- def clear_markers(self):
- """
- Clear old markers and interfaces.
- """
- for h in self.markers: h.remove()
- if self.markers:
- self.base.connect.clear(*self.markers)
- self.markers = []
-
- def save(self, ev):
- """
- """
- pass
-
- def restore(self, ev):
- """
- """
- pass
-
- def move(self, x, y, ev):
- """
- """
- pass
-
- def moveend(self, ev):
- """
- """
- pass
-
- def connect_markers(self, markers):
- """
- Connect markers to callbacks
- """
-
- for h in markers:
- connect = self.base.connect
- connect('enter', h, self.onHilite)
- connect('leave', h, self.onLeave)
- connect('click', h, self.onClick)
- connect('release', h, self.onRelease)
- connect('drag', h, self.onDrag)
- connect('key', h, self.onKey)
-
- def onHilite(self, ev):
- """
- Hilite the artist reporting the event, indicating that it is
- ready to receive a click.
- """
- ev.artist.set_color(active_color)
- self.base.draw()
- return True
-
- def onLeave(self, ev):
- """
- Restore the artist to the original colour when the cursor leaves.
- """
- ev.artist.set_color(self.color)
- self.base.draw()
- return True
-
- def onClick(self, ev):
- """
- Prepare to move the artist. Calls save() to preserve the state for
- later restore().
- """
- self.clickx, self.clicky = ev.xdata, ev.ydata
- self.save(ev)
- return True
-
- def onRelease(self, ev):
- """
- """
- self.moveend(ev)
- return True
-
- def onDrag(self, ev):
- """
- Move the artist. Calls move() to update the state, or restore() if
- the mouse leaves the window.
- """
- inside, _ = self.axes.contains(ev)
- if inside:
- self.clickx, self.clicky = ev.xdata, ev.ydata
- self.move(ev.xdata, ev.ydata, ev)
- else:
- self.restore()
- self.base.update()
- return True
-
- def onKey(self, ev):
- """
- Respond to keyboard events. Arrow keys move the widget. Escape
- restores it to the position before the last click.
-
- Calls move() to update the state. Calls restore() on escape.
- """
- if ev.key == 'escape':
- self.restore()
- elif ev.key in ['up', 'down', 'right', 'left']:
- dx, dy = self.dpixel(self.clickx, self.clicky, nudge=ev.control)
- if ev.key == 'up':
- self.clicky += dy
- elif ev.key == 'down':
- self.clicky -= dy
- elif ev.key == 'right':
- self.clickx += dx
- else: self.clickx -= dx
- self.move(self.clickx, self.clicky, ev)
- else:
- return False
- self.base.update()
- return True
-
- def dpixel(self, x, y, nudge=False):
- """
- Return the step size in data coordinates for a small
- step in screen coordinates. If nudge is False (default)
- the step size is one pixel. If nudge is True, the step
- size is 0.2 pixels.
- """
- ax = self.axes
- px, py = ax.transData.inverse_xy_tup((x, y))
- if nudge:
- nx, ny = ax.transData.xy_tup((px+0.2, py+0.2))
- else:
- nx, ny = ax.transData.xy_tup((px+1.0, py+1.0))
- dx, dy = nx-x, ny-y
- return dx, dy
-
Index: test/guiframe/local_perspectives/plotting/Edge.py
===================================================================
--- test/guiframe/local_perspectives/plotting/Edge.py (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,143 +1,0 @@
-
-import math
-#import wx
-#from copy import deepcopy
-from BaseInteractor import _BaseInteractor
-#from sans.guiframe.events import NewPlotEvent
-#from sans.guiframe.events import StatusEvent
-#from sans.guiframe.events import SlicerParameterEvent
-#from sans.guiframe.events import EVT_SLICER_PARS
-
-
-class RadiusInteractor(_BaseInteractor):
- """
- Select an annulus through a 2D plot
- """
- def __init__(self, base, axes, color='black', zorder=5, arc1=None,
- arc2=None, theta=math.pi/8):
- """
- """
- _BaseInteractor.__init__(self, base, axes, color=color)
- self.markers = []
- self.axes = axes
- self.r1 = arc1.get_radius()
- self.r2 = arc2.get_radius()
- #print "radius init", self.r1, self.r2
- self.theta = theta
- self.save_theta = theta
- #self.scale = 10.0
- self.move_stop = False
- self.theta_left = None
- self.theta_right = None
- self.arc1 = arc1
- self.arc2 = arc2
- #raise "Version error", message
- x1 = self.r1 * math.cos(self.theta)
- y1 = self.r1 * math.sin(self.theta)
- x2 = self.r2 * math.cos(self.theta)
- y2 = self.r2 * math.sin(self.theta)
- self.line = self.axes.plot([x1, x2], [y1, y2],
- linestyle='-', marker='',
- color=self.color,
- visible=True)[0]
- self.phi = theta
- self.npts = 20
- self.has_move = False
- self.connect_markers([self.line])
- self.update()
-
- def set_layer(self, n):
- """
- """
- self.layernum = n
- self.update()
-
- def clear(self):
- """
- """
- self.clear_markers()
- try:
- self.line.remove()
- except:
- # Old version of matplotlib
- for item in range(len(self.axes.lines)):
- del self.axes.lines[0]
-
- def get_angle(self):
- """
- """
- return self.theta
-
- def update(self, r1=None, r2=None, theta=None):
- """
- Draw the new roughness on the graph.
- """
- if r1 != None:
- self.r1 = r1
- if r2 != None:
- self.r2 = r2
- if theta != None:
- self.theta = theta
- #print "in the edge r1, r2",self.r1,self.r2,math.degrees(self.theta)
- x1 = self.r1 * math.cos(self.theta)
- y1 = self.r1 * math.sin(self.theta)
- x2 = self.r2 * math.cos(self.theta)
- y2 = self.r2 * math.sin(self.theta)
- self.line.set(xdata=[x1, x2], ydata=[y1, y2])
-
- def save(self, ev):
- """
- Remember the roughness for this layer and the next so that we
- can restore on Esc.
- """
- self.save_theta = math.atan2(ev.y,ev.x)
- #self.save_theta= self.theta
- self.base.freeze_axes()
-
- def moveend(self, ev):
- """
- """
- self.has_move = False
- self.base.moveend(ev)
-
- def restore(self, ev):
- """
- Restore the roughness for this layer.
- """
- self.theta = self.save_theta
-
- def move(self, x, y, ev):
- """
- Process move to a new position, making sure that the move is allowed.
- """
- self.theta = math.atan2(y, x)
- self.has_move = True
- self.base.base.update()
-
- def set_cursor(self, r_min, r_max, theta):
- """
- """
- self.theta = theta
- self.r1 = r_min
- self.r2 = r_max
- self.update()
-
- def get_params(self):
- """
- """
- params = {}
- params["radius1"] = self.r1
- params["radius2"] = self.r2
- params["theta"] = self.theta
- return params
-
- def set_params(self, params):
- """
- """
- #print "when here set curcor arc"
- x1 = params["radius1"]
- x2 = params["radius2"]
- theta= params["theta"]
- self.set_cursor(x1, x2, theta)
-
-
Index: test/guiframe/local_perspectives/plotting/Plotter1D.py
===================================================================
--- test/guiframe/local_perspectives/plotting/Plotter1D.py (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,518 +1,0 @@
-
-################################################################################
-#This software was developed by the University of Tennessee as part of the
-#Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
-#project funded by the US National Science Foundation.
-#
-#See the license text in license.txt
-#
-#copyright 2008, University of Tennessee
-################################################################################
-
-
-import wx
-import sys
-import os
-import pylab
-import math
-import numpy
-import time
-
-from danse.common.plottools.PlotPanel import PlotPanel
-#from danse.common.plottools.plottables import Graph
-from sans.guiframe import dataFitting
-from sans.guiframe.events import EVT_NEW_PLOT
-from sans.guiframe.events import StatusEvent
-from sans.guiframe.events import NewPlotEvent
-from sans.guiframe.events import SlicerEvent
-from sans.guiframe.events import PanelOnFocusEvent
-from sans.guiframe.events import EVT_NEW_LOADED_DATA
-from sans.guiframe.utils import PanelMenu
-from sans.guiframe.dataFitting import Data1D
-from sans.guiframe.panel_base import PanelBase
-from binder import BindArtist
-
-DEFAULT_QMAX = 0.05
-DEFAULT_QSTEP = 0.001
-DEFAULT_BEAM = 0.005
-BIN_WIDTH = 1
-
-
-class ModelPanel1D(PlotPanel, PanelBase):
- """
- Plot panel for use with the GUI manager
- """
-
- ## Internal name for the AUI manager
- window_name = "plotpanel"
- ## Title to appear on top of the window
- window_caption = "Plot Panel"
- ## Flag to tell the GUI manager that this panel is not
- # tied to any perspective
- ALWAYS_ON = True
- ## Group ID
- group_id = None
-
- def __init__(self, parent, id=-1, color = None,
- dpi=None, style=wx.NO_FULL_REPAINT_ON_RESIZE, **kwargs):
- PlotPanel.__init__(self, parent, id=id, style=style, **kwargs)
- PanelBase.__init__(self, parent)
- ## Reference to the parent window
- self.parent = parent
- ## Plottables
- self.plots = {}
- #context menu
- self._slicerpop = None
-
- self._available_data = []
- self._menu_add_ids = []
- self._symbol_labels = self.get_symbol_label()
-
- self.hide_menu = None
- ## Unique ID (from gui_manager)
- self.uid = None
- self.x_size = None
- ## Default locations
- self._default_save_location = os.getcwd()
- self.size = None
- ## Graph
- #self.graph = Graph()
- self.graph.xaxis("\\rm{Q}", 'A^{-1}')
- self.graph.yaxis("\\rm{Intensity} ", "cm^{-1}")
- self.graph.render(self)
-
- # In resizing event
- self.resizing = False
- self.canvas.set_resizing(self.resizing)
- self.Bind(wx.EVT_SIZE, self._OnReSize)
- self._add_more_tool()
-
- def get_symbol_label(self):
- """
- Associates label to symbol
- """
- _labels = {}
- i = 0
- _labels['Circle'] = i
- i += 1
- _labels['Cross X '] = i
- i += 1
- _labels['Triangle Down'] = i
- i += 1
- _labels['Triangle Up'] = i
- i += 1
- _labels['Triangle Left'] = i
- i += 1
- _labels['Triangle Right'] = i
- i += 1
- _labels['Cross +'] = i
- i += 1
- _labels['Square'] = i
- i += 1
- _labels['Diamond'] = i
- i += 1
- _labels['Diamond'] = i
- i += 1
- _labels['Hexagon1'] = i
- i += 1
- _labels['Hexagon2'] = i
- i += 1
- _labels['Pentagon'] = i
- i += 1
- _labels['Line'] = i
- return _labels
-
-
- def set_data(self, list=None):
- """
- """
- pass
-
- def _reset(self):
- """
- Resets internal data and graph
- """
- self.graph.reset()
- self.plots = {}
-
- def _OnReSize(self, event):
- """
- On response of the resize of a panel, set axes_visiable False
- """
- # It was found that wx >= 2.9.3 sends an event even if no size changed.
- # So manually recode the size (=x_size) and compare here.
- if self.x_size != None:
- if self.x_size == self.GetSize():
- self.resizing = False
- self.canvas.set_resizing(self.resizing)
- return
- self.x_size = self.GetSize()
-
- # Ready for another event
- # Do not remove this Skip. Otherwise it will get runtime error on wx>=2.9.
- event.Skip()
- # set the resizing flag
- self.resizing = True
- self.canvas.set_resizing(self.resizing)
- self.parent.set_schedule(True)
- pos_x, pos_y = self.GetPositionTuple()
- if pos_x != 0 and pos_y != 0:
- self.size, _ = self.GetClientSizeTuple()
-
- def set_resizing(self, resizing=False):
- """
- Set the resizing (True/False)
- """
- self.resizing = resizing
- #self.canvas.set_resizing(resizing)
-
- def schedule_full_draw(self, func='append'):
- """
- Put self in schedule to full redraw list
- """
- # append/del this panel in the schedule list
- self.parent.set_schedule_full_draw(self, func)
-
-
- def remove_data_by_id(self, id):
- """'
- remove data from plot
- """
- if id in self.plots.keys():
- data = self.plots[id]
- self.graph.delete(data)
- data_manager = self._manager.parent.get_data_manager()
- data_list, theory_list = data_manager.get_by_id(id_list=[id])
-
- if id in data_list.keys():
- data = data_list[id]
- if id in theory_list.keys():
- data = theory_list[id]
-
- del self.plots[id]
- self.graph.render(self)
- self.subplot.figure.canvas.draw_idle()
- if len(self.graph.plottables) == 0:
- #onRemove: graph is empty must be the panel must be destroyed
- self.parent.delete_panel(self.uid)
-
- def plot_data(self, data):
- """
- Data is ready to be displayed
-
- :param event: data event
- """
- if data.id in self.plots.keys():
- #replace
- self.graph.replace(data)
- self.plots[data.id] = data
- else:
- self.plots[data.id] = data
- self.graph.add(self.plots[data.id])
-
- ## Set the view scale for all plots
- self._onEVT_FUNC_PROPERTY()
- ## render the graph<=No need this done in canvas
- #self.graph.render(self)
- #self.subplot.figure.canvas.draw_idle()
-
- def draw_plot(self):
- """
- Draw plot
- """
- self.draw()
-
-
-
- def onLeftDown(self,event):
- """
- left button down and ready to drag
- Display the position of the mouse on the statusbar
- """
- PlotPanel.onLeftDown(self, event)
- ax = event.inaxes
- if ax != None:
- position = "x: %8.3g y: %8.3g" % (event.xdata, event.ydata)
- wx.PostEvent(self.parent, StatusEvent(status=position))
- # unfocus all
- self.parent.set_plot_unfocus()
- #post nd event to notify guiframe that this panel is on focus
- wx.PostEvent(self.parent, PanelOnFocusEvent(panel=self))
-
-
- def _ontoggle_hide_error(self, event):
- """
- Toggle error display to hide or show
- """
-
- selected_plot = self.plots[self.graph.selected_plottable]
- if self.hide_menu.GetText() == "Hide Error":
- selected_plot.hide_error = True
- else:
- selected_plot.hide_error = False
- ## increment graph color
- self.graph.render(self)
- self.subplot.figure.canvas.draw_idle()
-
- def _onRemove(self, event):
- """
- Remove a plottable from the graph and render the graph
-
- :param event: Menu event
-
- """
- ## Check if there is a selected graph to remove
- if self.graph.selected_plottable in self.plots.keys():
- selected_plot = self.plots[self.graph.selected_plottable]
- id = self.graph.selected_plottable
- self.remove_data_by_id(id)
-
- def onContextMenu(self, event):
- """
- 1D plot context menu
-
- :param event: wx context event
-
- """
- self._slicerpop = PanelMenu()
- self._slicerpop.set_plots(self.plots)
- self._slicerpop.set_graph(self.graph)
- # Various plot options
- id = wx.NewId()
- self._slicerpop.Append(id, '&Save Image', 'Save image as PNG')
- wx.EVT_MENU(self, id, self.onSaveImage)
- id = wx.NewId()
- self._slicerpop.Append(id, '&Print Image', 'Print image ')
- wx.EVT_MENU(self, id, self.onPrint)
- id = wx.NewId()
- self._slicerpop.Append(id, '&Print Preview', 'Print preview')
- wx.EVT_MENU(self, id, self.onPrinterPreview)
-
- id = wx.NewId()
- self._slicerpop.Append(id, '&Copy to Clipboard', 'Copy to the clipboard')
- wx.EVT_MENU(self, id, self.OnCopyFigureMenu)
-
- self._slicerpop.AppendSeparator()
-
- #add menu of other plugins
- item_list = self.parent.get_context_menu(self)
-
- if (not item_list == None) and (not len(item_list) == 0):
- for item in item_list:
- try:
- id = wx.NewId()
- self._slicerpop.Append(id, item[0], item[1])
- wx.EVT_MENU(self, id, item[2])
- except:
- msg = "ModelPanel1D.onContextMenu: "
- msg += "bad menu item %s" % sys.exc_value
- wx.PostEvent(self.parent, StatusEvent(status=msg))
- pass
- self._slicerpop.AppendSeparator()
- #id = wx.NewId()
- #self._slicerpop.Append(id, '&Print image', 'Print image')
- if self.graph.selected_plottable in self.plots:
- plot = self.plots[self.graph.selected_plottable]
-
- id = wx.NewId()
- name = plot.name
- self._slicerpop.Append(id, "&Save Points as a File")
- self._slicerpop.AppendSeparator()
- if plot.name != 'SLD':
- wx.EVT_MENU(self, id, self._onSave)
- id = wx.NewId()
- self._slicerpop.Append(id, '&Linear Fit')
- wx.EVT_MENU(self, id, self.onFitting)
- self._slicerpop.AppendSeparator()
-
- id = wx.NewId()
- self._slicerpop.Append(id, "Remove %s Curve" % name)
- wx.EVT_MENU(self, id, self._onRemove)
- if not plot.is_data:
- id = wx.NewId()
- self._slicerpop.Append(id, '&Freeze', 'Freeze')
- wx.EVT_MENU(self, id, self.onFreeze)
- symbol_menu = wx.Menu()
- for label in self._symbol_labels:
- id = wx.NewId()
- symbol_menu.Append(id, str(label), str(label))
- wx.EVT_MENU(self, id, self.onChangeSymbol)
- id = wx.NewId()
- self._slicerpop.AppendMenu(id,'&Modify Symbol', symbol_menu)
- self._slicerpop.AppendSeparator()
-
- id = wx.NewId()
- self.hide_menu = self._slicerpop.Append(id, "Hide Error")
-
- if plot.dy is not None and plot.dy != []:
- if plot.hide_error :
- self.hide_menu.SetText('Show Error')
- else:
- self.hide_menu.SetText('Hide Error')
- else:
- self.hide_menu.Enable(False)
- wx.EVT_MENU(self, id, self._ontoggle_hide_error)
-
- self._slicerpop.AppendSeparator()
- # Option to hide
- #TODO: implement functionality to hide a plottable (legend click)
-
-
- id = wx.NewId()
- self._slicerpop.Append(id, '&Change scale')
- wx.EVT_MENU(self, id, self._onProperties)
- id = wx.NewId()
- self._slicerpop.Append(id, '&Reset Graph')
- wx.EVT_MENU(self, id, self.onResetGraph)
- pos = event.GetPosition()
- pos = self.ScreenToClient(pos)
- self.PopupMenu(self._slicerpop, pos)
-
- def onFreeze(self, event):
- """
- """
- plot = self.plots[self.graph.selected_plottable]
- self.parent.onfreeze([plot.id])
-
- def onChangeSymbol(self, event):
- """
- """
- menu = event.GetEventObject()
- id = event.GetId()
- label = menu.GetLabel(id)
- selected_plot = self.plots[self.graph.selected_plottable]
- selected_plot.symbol = self._symbol_labels[label]
- ## Set the view scale for all plots
- self._onEVT_FUNC_PROPERTY()
- ## render the graph
- #self.graph.render(self)
- #self.subplot.figure.canvas.draw_idle()
-
- def _onsaveTXT(self, path):
- """
- Save file as txt
-
- :TODO: Refactor and remove this method. See TODO in _onSave.
-
- """
- data = self.plots[self.graph.selected_plottable]
-
- if not path == None:
- out = open(path, 'w')
- has_errors = True
- if data.dy == None or data.dy == []:
- has_errors = False
- # Sanity check
- if has_errors:
- try:
- if len(data.y) != len(data.dy):
- has_errors = False
- except:
- has_errors = False
- if has_errors:
- if data.dx != None:
- out.write(" \n")
- else:
- out.write(" \n")
- else:
- out.write(" \n")
-
- for i in range(len(data.x)):
- if has_errors:
- if data.dx != None:
- out.write("%g %g %g %g\n" % (data.x[i],
- data.y[i],
- data.dy[i],
- data.dx[i]))
- else:
- out.write("%g %g %g\n" % (data.x[i],
- data.y[i],
- data.dy[i]))
- else:
- out.write("%g %g\n" % (data.x[i],
- data.y[i]))
- out.close()
- try:
- self._default_save_location = os.path.dirname(path)
- except:
- pass
-
- def _onSave(self, evt):
- """
- Save a data set to a text file
-
- :param evt: Menu event
-
- """
-
- path = None
- wildcard = "Text files (*.txt)|*.txt|"\
- "CanSAS 1D files(*.xml)|*.xml"
- dlg = wx.FileDialog(self, "Choose a file",
- self._default_save_location,
- "", wildcard , wx.SAVE)
-
- if dlg.ShowModal() == wx.ID_OK:
- path = dlg.GetPath()
- # ext_num = 0 for .txt, ext_num = 1 for .xml
- # This is MAC Fix
- ext_num = dlg.GetFilterIndex()
- if ext_num == 0:
- format = '.txt'
- else:
- format = '.xml'
- path = os.path.splitext(path)[0] + format
- mypath = os.path.basename(path)
-
- #TODO: This is bad design. The DataLoader is designed
- #to recognize extensions.
- # It should be a simple matter of calling the .
- #save(file, data, '.xml') method
- # of the DataLoader.loader.Loader class.
- from DataLoader.loader import Loader
- #Instantiate a loader
- loader = Loader()
- data = self.plots[self.graph.selected_plottable]
- format = ".txt"
- if os.path.splitext(mypath)[1].lower() == format:
- # Make sure the ext included in the file name
- # especially on MAC
- fName = os.path.splitext(path)[0] + format
- self._onsaveTXT(fName)
- format = ".xml"
- if os.path.splitext(mypath)[1].lower() == format:
- # Make sure the ext included in the file name
- # especially on MAC
- fName = os.path.splitext(path)[0] + format
- loader.save(fName, data, format)
- try:
- self._default_save_location = os.path.dirname(path)
- except:
- pass
- dlg.Destroy()
-
- def _add_more_tool(self):
- """
- Add refresh button in the tool bar
- """
- if self.parent.__class__.__name__ != 'ViewerFrame':
- return
- self.toolbar.AddSeparator()
- id_delete = wx.NewId()
- delete = wx.ArtProvider.GetBitmap(wx.ART_DELETE, wx.ART_TOOLBAR)
- self.toolbar.AddSimpleTool(id_delete, delete,
- 'Delete', 'permanently Delete')
-
- self.toolbar.Realize()
- wx.EVT_TOOL(self, id_delete, self._on_delete)
-
- def _on_delete(self, event):
- """
- Refreshes the plotpanel on refresh tollbar button
- """
-
- if self.parent is not None:
- wx.PostEvent(self.parent,
- NewPlotEvent(group_id=self.group_id,
- action="delete"))
-
Index: test/guiframe/local_perspectives/plotting/Plotter2D.py
===================================================================
--- test/guiframe/local_perspectives/plotting/Plotter2D.py (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,627 +1,0 @@
-
-################################################################################
-#This software was developed by the University of Tennessee as part of the
-#Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
-#project funded by the US National Science Foundation.
-#
-#See the license text in license.txt
-#
-#copyright 2008, University of Tennessee
-################################################################################
-
-
-import wx
-import sys
-import os
-import math
-import numpy
-import pylab
-import danse.common.plottools
-from danse.common.plottools.PlotPanel import PlotPanel
-from danse.common.plottools.plottables import Graph
-from sans.guiframe.events import EVT_NEW_PLOT
-from sans.guiframe.events import EVT_SLICER_PARS
-from sans.guiframe.events import StatusEvent
-from sans.guiframe.events import NewPlotEvent
-from sans.guiframe.events import PanelOnFocusEvent
-from sans.guiframe.events import SlicerEvent
-from sans.guiframe.utils import PanelMenu
-from binder import BindArtist
-from Plotter1D import ModelPanel1D
-from danse.common.plottools.toolbar import NavigationToolBar
-from sans.guiframe.dataFitting import Data1D
-(InternalEvent, EVT_INTERNAL) = wx.lib.newevent.NewEvent()
-
-DEFAULT_QMAX = 0.05
-DEFAULT_QSTEP = 0.001
-DEFAULT_BEAM = 0.005
-BIN_WIDTH = 1.0
-
-
-class NavigationToolBar2D(NavigationToolBar):
- """
- """
- def __init__(self, canvas, parent=None):
- NavigationToolBar.__init__(self, canvas=canvas, parent=parent)
-
- def delete_option(self):
- """
- remove default toolbar item
- """
- #delete reset button
- self.DeleteToolByPos(0)
- #delete dragging
- self.DeleteToolByPos(2)
- #delete unwanted button that configures subplot parameters
- self.DeleteToolByPos(4)
-
- def add_option(self):
- """
- add item to the toolbar
- """
- #add print button
- id_print = wx.NewId()
- print_bmp = wx.ArtProvider.GetBitmap(wx.ART_PRINT, wx.ART_TOOLBAR)
- self.AddSimpleTool(id_print, print_bmp,
- 'Print', 'Activate printing')
- wx.EVT_TOOL(self, id_print, self.on_print)
-
-
-class ModelPanel2D(ModelPanel1D):
- """
- Plot panel for use with the GUI manager
- """
-
- ## Internal name for the AUI manager
- window_name = "plotpanel"
- ## Title to appear on top of the window
- window_caption = "Plot Panel"
- ## Flag to tell the GUI manager that this panel is not
- # tied to any perspective
- ALWAYS_ON = True
- ## Group ID
- group_id = None
-
-
- def __init__(self, parent, id=-1, data2d=None, color = None,
- dpi=None, style=wx.NO_FULL_REPAINT_ON_RESIZE, **kwargs):
- """
- Initialize the panel
- """
- ModelPanel1D.__init__(self, parent, id=id, style=style, **kwargs)
-
- ## Reference to the parent window
- self.parent = parent
- ## Dictionary containing Plottables
- self.plots = {}
- ## Save reference of the current plotted
- self.data2D = data2d
- ## Unique ID (from gui_manager)
- self.uid = None
- ## Action IDs for internal call-backs
- self.action_ids = {}
- ## Create Artist and bind it
- self.connect = BindArtist(self.subplot.figure)
- ## Beam stop
- self.beamstop_radius = DEFAULT_BEAM
- ## to set the order of lines drawn first.
- self.slicer_z = 5
- ## Reference to the current slicer
- self.slicer = None
- ## event to send slicer info
- self.Bind(EVT_INTERNAL, self._onEVT_INTERNAL)
-
- self.axes_frozen = False
- ## panel that contains result from slicer motion (ex: Boxsum info)
- self.panel_slicer = None
- ## Graph
- self.graph = Graph()
- self.graph.xaxis("\\rm{Q}", 'A^{-1}')
- self.graph.yaxis("\\rm{Intensity} ", "cm^{-1}")
- self.graph.render(self)
- ## store default value of zmin and zmax
- self.default_zmin_ctl = self.zmin_2D
- self.default_zmax_ctl = self.zmax_2D
-
- def onLeftDown(self, event):
- """
- left button down and ready to drag
-
- """
- # Check that the LEFT button was pressed
- if event.button == 1:
- self.leftdown = True
- ax = event.inaxes
- if ax != None:
- self.xInit, self.yInit = event.xdata, event.ydata
- self.plottable_selected(self.data2D.id)
-
- self._manager.set_panel_on_focus(self)
- wx.PostEvent(self.parent, PanelOnFocusEvent(panel=self))
-
- def add_toolbar(self):
- """
- add toolbar
- """
- self.enable_toolbar = True
- self.toolbar = NavigationToolBar2D(parent=self, canvas=self.canvas)
- self.toolbar.Realize()
- # On Windows platform, default window size is incorrect, so set
- # toolbar width to figure width.
- tw, th = self.toolbar.GetSizeTuple()
- fw, fh = self.canvas.GetSizeTuple()
- self.toolbar.SetSize(wx.Size(fw, th))
- self.sizer.Add(self.toolbar, 0, wx.LEFT|wx.EXPAND)
- # update the axes menu on the toolbar
- self.toolbar.update()
-
- def plot_data(self, data):
- """
- Data is ready to be displayed
-
- :TODO: this name should be changed to something more appropriate
- Don't forget that changing this name will mean changing code
- in plotting.py
-
- :param event: data event
- """
- ## Update self.data2d with the current plot
- self.data2D = data
- if data.id in self.plots.keys():
- #replace
- self.graph.replace(data)
- self.plots[data.id] = data
- else:
- self.plots[data.id] = data
- self.graph.add(self.plots[data.id])
- # update qmax with the new xmax of data plotted
- self.qmax = data.xmax
-
- self.slicer = None
- # Check axis labels
- #TODO: Should re-factor this
- ## render the graph with its new content
-
- #data2D: put 'Pixel (Number)' for axis title and unit in case of having no detector info and none in _units
- if len(self.data2D.detector) < 1:
- if len(data._xunit) < 1 and len(data._yunit) < 1:
- data._xaxis = '\\rm{x}'
- data._yaxis = '\\rm{y}'
- data._xunit = 'pixel'
- data._yunit = 'pixel'
- self.graph.xaxis(data._xaxis, data._xunit)
- self.graph.yaxis(data._yaxis, data._yunit)
- self.graph.title(self.data2D.name)
- self.graph.render(self)
- self.draw_plot()
- #self.subplot.figure.canvas.draw_idle()
- ## store default value of zmin and zmax
- self.default_zmin_ctl = self.zmin_2D
- self.default_zmax_ctl = self.zmax_2D
-
- def onContextMenu(self, event):
- """
- 2D plot context menu
-
- :param event: wx context event
-
- """
- slicerpop = PanelMenu()
- slicerpop.set_plots(self.plots)
- slicerpop.set_graph(self.graph)
-
- id = wx.NewId()
- slicerpop.Append(id, '&Save Image')
- wx.EVT_MENU(self, id, self.onSaveImage)
-
- id = wx.NewId()
- slicerpop.Append(id,'&Print Image', 'Print image')
- wx.EVT_MENU(self, id, self.onPrint)
-
- id = wx.NewId()
- slicerpop.Append(id,'&Print Preview', 'Print preview')
- wx.EVT_MENU(self, id, self.onPrinterPreview)
-
- id = wx.NewId()
- slicerpop.Append(id, '&Copy to Clipboard', 'Copy to the clipboard')
- wx.EVT_MENU(self, id, self.OnCopyFigureMenu)
- slicerpop.AppendSeparator()
- # saving data
- plot = self.data2D
- id = wx.NewId()
- name = plot.name
- slicerpop.Append(id, "&Save as a file (DAT)" )
- self.action_ids[str(id)] = plot
- wx.EVT_MENU(self, id, self._onSave)
-
- slicerpop.AppendSeparator()
- if len(self.data2D.detector) == 1:
-
- item_list = self.parent.get_context_menu(self)
- if (not item_list == None) and (not len(item_list) == 0) and\
- self.data2D.name.split(" ")[0] != 'Residuals':
- # The line above; Not for trunk
- for item in item_list:
- try:
- id = wx.NewId()
- slicerpop.Append(id, item[0], item[1])
- wx.EVT_MENU(self, id, item[2])
- except:
- msg = "ModelPanel1D.onContextMenu: "
- msg += "bad menu item %s"%sys.exc_value
- wx.PostEvent(self.parent, StatusEvent(status=msg))
- pass
- slicerpop.AppendSeparator()
-
- id = wx.NewId()
- slicerpop.Append(id, '&Perform circular average')
- wx.EVT_MENU(self, id, self.onCircular) \
- # For Masked Data
- if not plot.mask.all():
- id = wx.NewId()
- slicerpop.Append(id, '&Masked circular average')
- wx.EVT_MENU(self, id, self.onMaskedCircular)
- id = wx.NewId()
- slicerpop.Append(id, '&Sector [Q view]')
- wx.EVT_MENU(self, id, self.onSectorQ)
- id = wx.NewId()
- slicerpop.Append(id, '&Annulus [Phi view ]')
- wx.EVT_MENU(self, id, self.onSectorPhi)
- id = wx.NewId()
- slicerpop.Append(id, '&Box Sum')
- wx.EVT_MENU(self, id, self.onBoxSum)
- id = wx.NewId()
- slicerpop.Append(id, '&Box averaging in Qx')
- wx.EVT_MENU(self, id, self.onBoxavgX)
- id = wx.NewId()
- slicerpop.Append(id, '&Box averaging in Qy')
- wx.EVT_MENU(self, id, self.onBoxavgY)
- if self.slicer != None:
- id = wx.NewId()
- slicerpop.Append(id, '&Clear slicer')
- wx.EVT_MENU(self, id, self.onClearSlicer)
- if self.slicer.__class__.__name__ != "BoxSum":
- id = wx.NewId()
- slicerpop.Append(id, '&Edit Slicer Parameters')
- wx.EVT_MENU(self, id, self._onEditSlicer)
- slicerpop.AppendSeparator()
- id = wx.NewId()
- slicerpop.Append(id, '&2D Color Map')
- wx.EVT_MENU(self, id, self._onEditDetector)
- id = wx.NewId()
- slicerpop.Append(id, '&Toggle Linear/Log scale')
- wx.EVT_MENU(self, id, self._onToggleScale)
- pos = event.GetPosition()
- pos = self.ScreenToClient(pos)
- self.PopupMenu(slicerpop, pos)
-
- def _onEditDetector(self, event):
- """
- Allow to view and edits detector parameters
-
- :param event: wx.menu event
-
- """
- import detector_dialog
- dialog = detector_dialog.DetectorDialog(self, -1,base=self.parent,
- reset_zmin_ctl =self.default_zmin_ctl,
- reset_zmax_ctl = self.default_zmax_ctl,cmap=self.cmap)
- ## info of current detector and data2D
- xnpts = len(self.data2D.x_bins)
- ynpts = len(self.data2D.y_bins)
- xmax = max(self.data2D.xmin, self.data2D.xmax)
- ymax = max(self.data2D.ymin, self.data2D.ymax)
- qmax = math.sqrt(math.pow(xmax, 2) + math.pow(ymax, 2))
- beam = self.data2D.xmin
- ## set dialog window content
- dialog.setContent(xnpts=xnpts,ynpts=ynpts,qmax=qmax,
- beam=self.data2D.xmin,
- zmin = self.zmin_2D,
- zmax = self.zmax_2D)
- if dialog.ShowModal() == wx.ID_OK:
- evt = dialog.getContent()
- self.zmin_2D = evt.zmin
- self.zmax_2D = evt.zmax
- self.cmap = evt.cmap
- dialog.Destroy()
- ## Redraw the current image
- self.image(data=self.data2D.data,
- qx_data=self.data2D.qx_data,
- qy_data=self.data2D.qy_data,
- xmin= self.data2D.xmin,
- xmax= self.data2D.xmax,
- ymin= self.data2D.ymin,
- ymax= self.data2D.ymax,
- zmin= self.zmin_2D,
- zmax= self.zmax_2D,
- cmap= self.cmap,
- color=0, symbol=0, label=self.data2D.name)
- self.subplot.figure.canvas.draw_idle()
-
- def freeze_axes(self):
- """
- """
- self.axes_frozen = True
-
- def thaw_axes(self):
- """
- """
- self.axes_frozen = False
-
- def onMouseMotion(self,event):
- """
- """
- pass
-
- def onWheel(self, event):
- """
- """
- pass
-
- def update(self, draw=True):
- """
- Respond to changes in the model by recalculating the
- profiles and resetting the widgets.
- """
- self.draw_plot()
-
- def _getEmptySlicerEvent(self):
- """
- create an empty slicervent
- """
- return SlicerEvent(type=None, params=None, obj_class=None)
-
- def _onEVT_INTERNAL(self, event):
- """
- Draw the slicer
-
- :param event: wx.lib.newevent (SlicerEvent) containing slicer
- parameter
-
- """
- self._setSlicer(event.slicer)
-
- def _setSlicer(self, slicer):
- """
- Clear the previous slicer and create a new one.Post an internal
- event.
-
- :param slicer: slicer class to create
-
- """
- ## Clear current slicer
- if not self.slicer == None:
- self.slicer.clear()
- ## Create a new slicer
- self.slicer_z += 1
- self.slicer = slicer(self, self.subplot, zorder=self.slicer_z)
- self.subplot.set_ylim(self.data2D.ymin, self.data2D.ymax)
- self.subplot.set_xlim(self.data2D.xmin, self.data2D.xmax)
- ## Draw slicer
- self.update()
- self.slicer.update()
- msg = "Plotter2D._setSlicer %s"%self.slicer.__class__.__name__
- wx.PostEvent(self.parent, StatusEvent(status=msg))
- # Post slicer event
- event = self._getEmptySlicerEvent()
- event.type = self.slicer.__class__.__name__
- event.obj_class = self.slicer.__class__
- event.params = self.slicer.get_params()
- wx.PostEvent(self, event)
-
- def onMaskedCircular(self, event):
- """
- perform circular averaging on Data2D with mask if it exists
-
- :param event: wx.menu event
-
- """
- self.onCircular(event, True)
-
- def onCircular(self, event, ismask=False):
- """
- perform circular averaging on Data2D
-
- :param event: wx.menu event
-
- """
- # Find the best number of bins
- npt = math.sqrt(len(self.data2D.data[numpy.isfinite(self.data2D.data)]))
- npt = math.floor(npt)
- from DataLoader.manipulations import CircularAverage
- ## compute the maximum radius of data2D
- self.qmax = max(math.fabs(self.data2D.xmax),
- math.fabs(self.data2D.xmin))
- self.ymax = max(math.fabs(self.data2D.ymax),
- math.fabs(self.data2D.ymin))
- self.radius = math.sqrt(math.pow(self.qmax, 2)+ math.pow(self.ymax, 2))
- ##Compute beam width
- bin_width = (self.qmax + self.qmax)/npt
- ## Create data1D circular average of data2D
- Circle = CircularAverage(r_min=0, r_max=self.radius,
- bin_width=bin_width)
- circ = Circle(self.data2D, ismask=ismask)
- from sans.guiframe.dataFitting import Data1D
- if hasattr(circ, "dxl"):
- dxl = circ.dxl
- else:
- dxl = None
- if hasattr(circ, "dxw"):
- dxw = circ.dxw
- else:
- dxw = None
-
- new_plot = Data1D(x=circ.x, y=circ.y, dy=circ.dy, dx=circ.dx)
- new_plot.dxl = dxl
- new_plot.dxw = dxw
- new_plot.name = "Circ avg " + self.data2D.name
- new_plot.source = self.data2D.source
- #new_plot.info = self.data2D.info
- new_plot.interactive = True
- new_plot.detector = self.data2D.detector
-
- ## If the data file does not tell us what the axes are, just assume...
- new_plot.xaxis("\\rm{Q}", "A^{-1}")
- if hasattr(self.data2D, "scale") and \
- self.data2D.scale == 'linear':
- new_plot.ytransform = 'y'
- new_plot.yaxis("\\rm{Residuals} ", "normalized")
- else:
- new_plot.yaxis("\\rm{Intensity} ", "cm^{-1}")
-
- new_plot.group_id = "Circ avg " + self.data2D.name
- new_plot.id = "Circ avg " + self.data2D.name
- new_plot.is_data = True
- wx.PostEvent(self.parent,
- NewPlotEvent(plot=new_plot, title=new_plot.name))
-
- def _onEditSlicer(self, event):
- """
- Is available only when a slicer is drawn.Create a dialog
- window where the user can enter value to reset slicer
- parameters.
-
- :param event: wx.menu event
-
- """
- if self.slicer != None:
- from SlicerParameters import SlicerParameterPanel
- dialog = SlicerParameterPanel(self, -1, "Slicer Parameters")
- dialog.set_slicer(self.slicer.__class__.__name__,
- self.slicer.get_params())
- if dialog.ShowModal() == wx.ID_OK:
- dialog.Destroy()
-
- def onSectorQ(self, event):
- """
- Perform sector averaging on Q and draw sector slicer
- """
- from SectorSlicer import SectorInteractor
- self.onClearSlicer(event)
- wx.PostEvent(self, InternalEvent(slicer=SectorInteractor))
-
- def onSectorPhi(self, event):
- """
- Perform sector averaging on Phi and draw annulus slicer
- """
- from AnnulusSlicer import AnnulusInteractor
- self.onClearSlicer(event)
- wx.PostEvent(self, InternalEvent(slicer=AnnulusInteractor))
-
- def onBoxSum(self, event):
- """
- """
- from boxSum import BoxSum
- self.onClearSlicer(event)
- self.slicer_z += 1
- self.slicer = BoxSum(self, self.subplot, zorder=self.slicer_z)
- self.subplot.set_ylim(self.data2D.ymin, self.data2D.ymax)
- self.subplot.set_xlim(self.data2D.xmin, self.data2D.xmax)
- self.update()
- self.slicer.update()
- ## Value used to initially set the slicer panel
- type = self.slicer.__class__.__name__
- params = self.slicer.get_params()
- ## Create a new panel to display results of summation of Data2D
- from slicerpanel import SlicerPanel
- new_panel = SlicerPanel(parent=self.parent, id=-1,
- base=self, type=type,
- params=params, style=wx.RAISED_BORDER)
-
- new_panel.window_caption = self.slicer.__class__.__name__ + " " + \
- str(self.data2D.name)
- new_panel.window_name = self.slicer.__class__.__name__+ " " + \
- str(self.data2D.name)
- ## Store a reference of the new created panel
- self.panel_slicer = new_panel
- ## save the window_caption of the new panel in the current slicer
- self.slicer.set_panel_name(name=new_panel.window_caption)
- ## post slicer panel to guiframe to display it
- from sans.guiframe.events import SlicerPanelEvent
- wx.PostEvent(self.parent, SlicerPanelEvent(panel=self.panel_slicer,
- main_panel=self))
-
- def onBoxavgX(self,event):
- """
- Perform 2D data averaging on Qx
- Create a new slicer .
-
- :param event: wx.menu event
- """
- from boxSlicer import BoxInteractorX
- self.onClearSlicer(event)
- wx.PostEvent(self, InternalEvent(slicer=BoxInteractorX))
-
- def onBoxavgY(self,event):
- """
- Perform 2D data averaging on Qy
- Create a new slicer .
-
- :param event: wx.menu event
-
- """
- from boxSlicer import BoxInteractorY
- self.onClearSlicer(event)
- wx.PostEvent(self, InternalEvent(slicer=BoxInteractorY))
-
- def onClearSlicer(self, event):
- """
- Clear the slicer on the plot
- """
- if not self.slicer == None:
- self.slicer.clear()
- self.subplot.figure.canvas.draw()
- self.slicer = None
- # Post slicer None event
- event = self._getEmptySlicerEvent()
- wx.PostEvent(self, event)
-
- def _onSave(self, evt):
- """
- Save a data set to a dat(text) file
-
- :param evt: Menu event
-
- """
- id = str(evt.GetId())
- if id in self.action_ids:
-
- path = None
- wildcard = "IGOR/DAT 2D file in Q_map (*.dat)|*.DAT"
- dlg = wx.FileDialog(self, "Choose a file",
- self._default_save_location,
- "", wildcard , wx.SAVE)
-
- if dlg.ShowModal() == wx.ID_OK:
- path = dlg.GetPath()
- # ext_num = 0 for .txt, ext_num = 1 for .xml
- # This is MAC Fix
- ext_num = dlg.GetFilterIndex()
- if ext_num == 0:
- format = '.dat'
- else:
- format = ''
- path = os.path.splitext(path)[0] + format
- mypath = os.path.basename(path)
-
- #TODO: This is bad design. The DataLoader is designed
- #to recognize extensions.
- # It should be a simple matter of calling the .
- #save(file, data, '.xml') method
- # of the DataLoader.loader.Loader class.
- from DataLoader.loader import Loader
- #Instantiate a loader
- loader = Loader()
- data = self.data2D
-
- format = ".dat"
- if os.path.splitext(mypath)[1].lower() == format:
- # Make sure the ext included in the file name
- # especially on MAC
- fName = os.path.splitext(path)[0] + format
- loader.save(fName, data, format)
- try:
- self._default_save_location = os.path.dirname(path)
- except:
- pass
- dlg.Destroy()
Index: test/guiframe/local_perspectives/plotting/SectorSlicer.py
===================================================================
--- test/guiframe/local_perspectives/plotting/SectorSlicer.py (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,626 +1,0 @@
-
-import math
-import wx
-#from copy import deepcopy
-from BaseInteractor import _BaseInteractor
-from sans.guiframe.events import NewPlotEvent
-from sans.guiframe.events import StatusEvent
-from sans.guiframe.events import SlicerParameterEvent
-from sans.guiframe.events import EVT_SLICER_PARS
-from sans.guiframe.dataFitting import Data1D
-
-
-class SectorInteractor(_BaseInteractor):
- """
- Draw a sector slicer.Allow to performQ averaging on data 2D
- """
- def __init__(self, base, axes, color='black', zorder=3):
-
- _BaseInteractor.__init__(self, base, axes, color=color)
- ## Class initialization
- self.markers = []
- self.axes = axes
- ## connect the plot to event
- self.connect = self.base.connect
-
- ## compute qmax limit to reset the graph
- x = math.pow(max(self.base.data2D.xmax,
- math.fabs(self.base.data2D.xmin)), 2)
- y = math.pow(max(self.base.data2D.ymax,
- math.fabs(self.base.data2D.ymin)), 2)
- self.qmax = math.sqrt(x + y)
- ## Number of points on the plot
- self.nbins = 20
- ## Angle of the middle line
- self.theta2 = math.pi/3
- ## Absolute value of the Angle between the middle line and any side line
- self.phi = math.pi/12
- ## Middle line
- self.main_line = LineInteractor(self, self.base.subplot, color='blue',
- zorder=zorder, r=self.qmax,
- theta= self.theta2)
- self.main_line.qmax = self.qmax
- ## Right Side line
- self.right_line = SideInteractor(self, self.base.subplot, color='black',
- zorder=zorder, r=self.qmax,
- phi=-1*self.phi, theta2=self.theta2)
- self.right_line.qmax = self.qmax
- ## Left Side line
- self.left_line = SideInteractor(self, self.base.subplot, color='black',
- zorder=zorder, r=self.qmax,
- phi=self.phi, theta2=self.theta2)
- self.left_line.qmax = self.qmax
- ## draw the sector
- self.update()
- self._post_data()
- ## Bind to slice parameter events
- self.base.Bind(EVT_SLICER_PARS, self._onEVT_SLICER_PARS)
-
- def _onEVT_SLICER_PARS(self, event):
- """
- receive an event containing parameters values to reset the slicer
-
- :param event: event of type SlicerParameterEvent with params as
- attribute
-
- """
- wx.PostEvent(self.base.parent,
- StatusEvent(status="SectorSlicer._onEVT_SLICER_PARS"))
- event.Skip()
- if event.type == self.__class__.__name__:
- self.set_params(event.params)
- self.base.update()
-
- def set_layer(self, n):
- """
- Allow adding plot to the same panel
-
- :param n: the number of layer
-
- """
- self.layernum = n
- self.update()
-
- def clear(self):
- """
- Clear the slicer and all connected events related to this slicer
- """
- self.clear_markers()
- self.main_line.clear()
- self.left_line.clear()
- self.right_line.clear()
- self.base.connect.clearall()
- self.base.Unbind(EVT_SLICER_PARS)
-
- def update(self):
- """
- Respond to changes in the model by recalculating the profiles and
- resetting the widgets.
- """
- # Update locations
- ## Check if the middle line was dragged and
- #update the picture accordingly
- if self.main_line.has_move:
- self.main_line.update()
- self.right_line.update(delta=-self.left_line.phi/2,
- mline=self.main_line.theta)
- self.left_line.update(delta=self.left_line.phi/2,
- mline=self.main_line.theta)
- ## Check if the left side has moved and update the slicer accordingly
- if self.left_line.has_move:
- self.main_line.update()
- self.left_line.update(phi=None, delta=None, mline=self.main_line,
- side=True, left=True)
- self.right_line.update(phi=self.left_line.phi, delta=None,
- mline=self.main_line, side=True,
- left=False, right=True)
- ## Check if the right side line has moved and
- #update the slicer accordingly
- if self.right_line.has_move:
- self.main_line.update()
- self.right_line.update(phi=None, delta=None, mline=self.main_line,
- side=True, left=False, right=True)
- self.left_line.update(phi=self.right_line.phi, delta=None,
- mline=self.main_line, side=True, left=False)
-
- def save(self, ev):
- """
- Remember the roughness for this layer and the next so that we
- can restore on Esc.
- """
- self.base.freeze_axes()
- self.main_line.save(ev)
- self.right_line.save(ev)
- self.left_line.save(ev)
-
- def _post_data(self, nbins=None):
- """
- compute sector averaging of data2D into data1D
-
- :param nbins: the number of point to plot for the average 1D data
- """
- ## get the data2D to average
- data = self.base.data2D
- # If we have no data, just return
- if data == None:
- return
- ## Averaging
- from DataLoader.manipulations import SectorQ
- radius = self.qmax
- phimin = -self.left_line.phi + self.main_line.theta
- phimax = self.left_line.phi + self.main_line.theta
- if nbins == None:
- nbins = 20
- sect = SectorQ(r_min=0.0, r_max=radius,
- phi_min=phimin + math.pi,
- phi_max=phimax + math.pi, nbins=nbins)
-
- sector = sect(self.base.data2D)
- ##Create 1D data resulting from average
-
- if hasattr(sector, "dxl"):
- dxl = sector.dxl
- else:
- dxl = None
- if hasattr(sector, "dxw"):
- dxw = sector.dxw
- else:
- dxw = None
- new_plot = Data1D(x=sector.x, y=sector.y, dy=sector.dy, dx=sector.dx)
- new_plot.dxl = dxl
- new_plot.dxw = dxw
- new_plot.name = "SectorQ" + "(" + self.base.data2D.name + ")"
- new_plot.source = self.base.data2D.source
- #new_plot.info=self.base.data2D.info
- new_plot.interactive = True
- new_plot.detector = self.base.data2D.detector
- ## If the data file does not tell us what the axes are, just assume...
- new_plot.xaxis("\\rm{Q}", "A^{-1}")
- new_plot.yaxis("\\rm{Intensity}", "cm^{-1}")
- if hasattr(data, "scale") and data.scale == 'linear' and \
- self.base.data2D.name.count("Residuals") > 0:
- new_plot.ytransform = 'y'
- new_plot.yaxis("\\rm{Residuals} ", "/")
-
- new_plot.group_id = "SectorQ" + self.base.data2D.name
- new_plot.id = None
- new_plot.is_data = True
-
- wx.PostEvent(self.base.parent, NewPlotEvent(plot=new_plot,
- title="SectorQ" + self.base.data2D.name))
-
- def moveend(self, ev):
- """
- Called a dragging motion ends.Get slicer event
- """
- self.base.thaw_axes()
- ## Post parameters
- event = SlicerParameterEvent()
- event.type = self.__class__.__name__
- event.params = self.get_params()
- ## Send slicer paramers to plotter2D
- wx.PostEvent(self.base, event)
-
- def restore(self):
- """
- Restore the roughness for this layer.
- """
- self.main_line.restore()
- self.left_line.restore()
- self.right_line.restore()
-
- def move(self, x, y, ev):
- """
- Process move to a new position, making sure that the move is allowed.
- """
- pass
-
- def set_cursor(self, x, y):
- """
- """
- pass
-
- def get_params(self):
- """
- Store a copy of values of parameters of the slicer into a dictionary.
-
- :return params: the dictionary created
-
- """
- params = {}
- ## Always make sure that the left and the right line are at phi
- ## angle of the middle line
- if math.fabs(self.left_line.phi) != math.fabs(self.right_line.phi):
- msg = "Phi left and phi right are different"
- msg += " %f, %f" % (self.left_line.phi, self.right_line.phi)
- raise ValueError, msg
- params["Phi"] = self.main_line.theta
- params["Delta_Phi"] = math.fabs(self.left_line.phi)
- params["nbins"] = self.nbins
- return params
-
- def set_params(self, params):
- """
- Receive a dictionary and reset the slicer with values contained
- in the values of the dictionary.
-
- :param params: a dictionary containing name of slicer parameters and
- values the user assigned to the slicer.
- """
- main = params["Phi"]
- phi = math.fabs(params["Delta_Phi"])
- self.nbins = int(params["nbins"])
- self.main_line.theta = main
- ## Reset the slicer parameters
- self.main_line.update()
- self.right_line.update(phi=phi, delta=None, mline=self.main_line,
- side=True, right=True)
- self.left_line.update(phi=phi, delta=None,
- mline=self.main_line, side=True)
- ## post the new corresponding data
- self._post_data(nbins=self.nbins)
-
- def freeze_axes(self):
- """
- """
- self.base.freeze_axes()
-
- def thaw_axes(self):
- """
- """
- self.base.thaw_axes()
-
- def draw(self):
- """
- """
- self.base.draw()
-
-
-class SideInteractor(_BaseInteractor):
- """
- Draw an oblique line
-
- :param phi: the phase between the middle line and one side line
- :param theta2: the angle between the middle line and x- axis
-
- """
- def __init__(self, base, axes, color='black', zorder=5, r=1.0,
- phi=math.pi/4, theta2= math.pi/3):
- """
- """
- _BaseInteractor.__init__(self, base, axes, color=color)
- ## Initialize the class
- self.markers = []
- self.axes = axes
- ## compute the value of the angle between the current line and
- ## the x-axis
- self.save_theta = theta2 + phi
- self.theta = theta2 + phi
- ## the value of the middle line angle with respect to the x-axis
- self.theta2 = theta2
- ## Radius to find polar coordinates this line's endpoints
- self.radius = r
- ## phi is the phase between the current line and the middle line
- self.phi = phi
- ## End points polar coordinates
- x1 = self.radius * math.cos(self.theta)
- y1 = self.radius * math.sin(self.theta)
- x2 = -1 * self.radius * math.cos(self.theta)
- y2 = -1 * self.radius * math.sin(self.theta)
- ## defining a new marker
- try:
- self.inner_marker = self.axes.plot([x1/2.5], [y1/2.5], linestyle='',
- marker='s', markersize=10,
- color=self.color, alpha=0.6,
- pickradius=5, label="pick",
- # Prefer this to other lines
- zorder=zorder, visible=True)[0]
- except:
- self.inner_marker = self.axes.plot([x1/2.5],[y1/2.5], linestyle='',
- marker='s', markersize=10,
- color=self.color, alpha=0.6,
- label="pick", visible=True)[0]
- message = "\nTHIS PROTOTYPE NEEDS THE LATEST"
- message += " VERSION OF MATPLOTLIB\n Get the SVN version that"
- message += " is at least as recent as June 1, 2007"
- owner = self.base.base.parent
- wx.PostEvent(owner,
- StatusEvent(status="sectorSlicer: %s" % message))
-
- ## Defining the current line
- self.line = self.axes.plot([x1, x2], [y1, y2],
- linestyle='-', marker='',
- color=self.color, visible=True)[0]
- ## Flag to differentiate the left line from the right line motion
- self.left_moving = False
- ## Flag to define a motion
- self.has_move = False
- ## connecting markers and draw the picture
- self.connect_markers([self.inner_marker, self.line])
-
- def set_layer(self, n):
- """
- Allow adding plot to the same panel
-
- :param n: the number of layer
-
- """
- self.layernum = n
- self.update()
-
- def clear(self):
- """
- Clear the slicer and all connected events related to this slicer
- """
- self.clear_markers()
- try:
- self.line.remove()
- self.inner_marker.remove()
- except:
- # Old version of matplotlib
- for item in range(len(self.axes.lines)):
- del self.axes.lines[0]
-
- def update(self, phi=None, delta=None, mline=None,
- side=False, left= False, right=False):
- """
- Draw oblique line
-
- :param phi: the phase between the middle line and the current line
- :param delta: phi/2 applied only when the mline was moved
-
- """
- #print "update left or right ", self.has_move
- self.left_moving = left
- theta3 = 0
- if phi != None:
- self.phi = phi
- if delta == None:
- delta = 0
- if right:
- self.phi = -1 * math.fabs(self.phi)
- #delta=-delta
- else:
- self.phi = math.fabs(self.phi)
- if side:
- self.theta = mline.theta + self.phi
-
- if mline != None :
- if delta != 0:
- self.theta2 = mline + delta
- else:
- self.theta2 = mline.theta
- if delta == 0:
- theta3 = self.theta + delta
- else:
- theta3 = self.theta2 + delta
- x1 = self.radius * math.cos(theta3)
- y1 = self.radius * math.sin(theta3)
- x2 = -1 * self.radius * math.cos(theta3)
- y2 = -1 * self.radius * math.sin(theta3)
- self.inner_marker.set(xdata=[x1/2.5], ydata=[y1/2.5])
- self.line.set(xdata=[x1, x2], ydata=[y1, y2])
-
- def save(self, ev):
- """
- Remember the roughness for this layer and the next so that we
- can restore on Esc.
- """
- self.save_theta = self.theta
- self.base.freeze_axes()
-
- def moveend(self, ev):
- """
- """
- self.has_move = False
- self.base.moveend(ev)
-
- def restore(self):
- """
- Restore the roughness for this layer.
- """
- self.theta = self.save_theta
-
- def move(self, x, y, ev):
- """
- Process move to a new position, making sure that the move is allowed.
- """
- self.theta = math.atan2(y, x)
- self.has_move = True
- #ToDo: Simplify below
- if not self.left_moving:
- if self.theta2 - self.theta <= 0 and self.theta2 > 0:
- self.restore()
- return
- elif self.theta2 < 0 and self.theta < 0 and \
- self.theta-self.theta2 >= 0:
- self.restore()
- return
- elif self.theta2 < 0 and self.theta > 0 and \
- (self.theta2 + 2 * math.pi - self.theta) >= math.pi/2:
- #print "my theta", self.theta
- self.restore()
- return
- elif self.theta2 < 0 and self.theta < 0 and \
- (self.theta2 - self.theta) >= math.pi/2:
- #print "my theta", self.theta
- self.restore()
- return
- elif self.theta2 > 0 and (self.theta2-self.theta >= math.pi/2 or \
- (self.theta2-self.theta >= math.pi/2)):
- #print "self theta encore"
- self.restore()
- return
- else:
- #print "left move"
- if self.theta < 0 and (self.theta + math.pi*2-self.theta2) <= 0:
- self.restore()
- return
- elif self.theta2 < 0 and (self.theta-self.theta2) <= 0:
- self.restore()
- return
- elif self.theta > 0 and self.theta-self.theta2 <= 0:
- #print "my theta", self.theta
- self.restore()
- return
- elif self.theta-self.theta2 >= math.pi/2 or \
- ((self.theta + math.pi * 2 - self.theta2) >= math.pi/2 and \
- self.theta < 0 and self.theta2 > 0):
- #print "self theta encore"
- self.restore()
- return
-
- self.phi = math.fabs(self.theta2 - self.theta)
- if self.phi > math.pi:
- self.phi = 2 * math.pi - math.fabs(self.theta2 - self.theta)
- self.base.base.update()
-
- def set_cursor(self, x, y):
- """
- """
- self.move(x, y, None)
- self.update()
-
- def get_params(self):
- """
- """
- params = {}
- params["radius"] = self.radius
- params["theta"] = self.theta
- return params
-
- def set_params(self, params):
- """
- """
- x = params["radius"]
- self.set_cursor(x, self._inner_mouse_y)
-
-
-class LineInteractor(_BaseInteractor):
- """
- Select an annulus through a 2D plot
- """
- def __init__(self, base, axes, color='black',
- zorder=5, r=1.0, theta=math.pi/4):
- """
- """
- _BaseInteractor.__init__(self, base, axes, color=color)
-
- self.markers = []
- self.axes = axes
- self.save_theta = theta
- self.theta= theta
- self.radius = r
- self.scale = 10.0
- # Inner circle
- x1 = self.radius * math.cos(self.theta)
- y1 = self.radius * math.sin(self.theta)
- x2 = -1*self.radius * math.cos(self.theta)
- y2 = -1*self.radius * math.sin(self.theta)
- try:
- # Inner circle marker
- self.inner_marker = self.axes.plot([x1/2.5], [y1/2.5], linestyle='',
- marker='s', markersize=10,
- color=self.color, alpha=0.6,
- pickradius=5, label="pick",
- # Prefer this to other lines
- zorder=zorder,
- visible=True)[0]
- except:
- self.inner_marker = self.axes.plot([x1/2.5], [y1/2.5], linestyle='',
- marker='s', markersize=10,
- color=self.color, alpha=0.6,
- label="pick",
- visible=True)[0]
- message = "\nTHIS PROTOTYPE NEEDS THE LATEST VERSION"
- message += " OF MATPLOTLIB\n Get the SVN version that is at"
- message += " least as recent as June 1, 2007"
- self.line = self.axes.plot([x1, x2], [y1, y2],
- linestyle='-', marker='',
- color=self.color, visible=True)[0]
- self.npts = 20
- self.has_move = False
- self.connect_markers([self.inner_marker, self.line])
- self.update()
-
- def set_layer(self, n):
- """
- """
- self.layernum = n
- self.update()
-
- def clear(self):
- """
- """
- self.clear_markers()
- try:
- self.inner_marker.remove()
- self.line.remove()
- except:
- # Old version of matplotlib
- for item in range(len(self.axes.lines)):
- del self.axes.lines[0]
-
- def update(self, theta=None):
- """
- Draw the new roughness on the graph.
- """
-
- if theta != None:
- self.theta = theta
- x1 = self.radius * math.cos(self.theta)
- y1 = self.radius * math.sin(self.theta)
- x2 = -1 * self.radius * math.cos(self.theta)
- y2 = -1 * self.radius * math.sin(self.theta)
-
- self.inner_marker.set(xdata=[x1/2.5], ydata=[y1/2.5])
- self.line.set(xdata=[x1, x2], ydata=[y1, y2])
-
- def save(self, ev):
- """
- Remember the roughness for this layer and the next so that we
- can restore on Esc.
- """
- self.save_theta= self.theta
- self.base.freeze_axes()
-
- def moveend(self, ev):
- """
- """
- self.has_move = False
- self.base.moveend(ev)
-
- def restore(self):
- """
- Restore the roughness for this layer.
- """
- self.theta = self.save_theta
-
- def move(self, x, y, ev):
- """
- Process move to a new position, making sure that the move is allowed.
- """
- self.theta = math.atan2(y, x)
- self.has_move = True
- self.base.base.update()
-
- def set_cursor(self, x, y):
- """
- """
- self.move(x, y, None)
- self.update()
-
- def get_params(self):
- """
- """
- params = {}
- params["radius"] = self.radius
- params["theta"] = self.theta
- return params
-
- def set_params(self, params):
- """
- """
- x = params["radius"]
- self.set_cursor(x, self._inner_mouse_y)
-
Index: test/guiframe/local_perspectives/plotting/SlicerParameters.py
===================================================================
--- test/guiframe/local_perspectives/plotting/SlicerParameters.py (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,149 +1,0 @@
-
-
-import wx
-import wx.lib.newevent
-#from copy import deepcopy
-from sans.guiframe.events import EVT_SLICER_PARS
-from sans.guiframe.utils import format_number
-from sans.guiframe.events import EVT_SLICER
-from sans.guiframe.events import SlicerParameterEvent
-
-
-class SlicerParameterPanel(wx.Dialog):
- """
- Panel class to show the slicer parameters
- """
- #TODO: show units
- #TODO: order parameters properly
-
- def __init__(self, parent, *args, **kwargs):
- wx.Dialog.__init__(self, parent, *args, **kwargs)
- """
- Dialog window that allow to edit parameters slicer
- by entering new values
- """
- self.params = {}
- self.parent = parent
- self.type = None
- self.listeners = []
- self.parameters = []
- self.bck = wx.GridBagSizer(5, 5)
- self.SetSizer(self.bck)
- label = "Right-click on 2D plot for slicer options"
- title = wx.StaticText(self, -1, label, style=wx.ALIGN_LEFT)
- self.bck.Add(title, (0, 0), (1, 2),
- flag=wx.LEFT|wx.ALIGN_CENTER_VERTICAL, border=15)
- # Bindings
- self.parent.Bind(EVT_SLICER, self.onEVT_SLICER)
- self.parent.Bind(EVT_SLICER_PARS, self.onParamChange)
-
- def onEVT_SLICER(self, event):
- """
- Process EVT_SLICER events
- When the slicer changes, update the panel
-
- :param event: EVT_SLICER event
- """
- event.Skip()
- if event.obj_class == None:
- self.set_slicer(None, None)
- else:
- self.set_slicer(event.type, event.params)
-
- def set_slicer(self, type, params):
- """
- Rebuild the panel
- """
- self.bck.Clear(True)
- self.type = type
- if type == None:
- label = "Right-click on 2D plot for slicer options"
- title = wx.StaticText(self, -1, label, style=wx.ALIGN_LEFT)
- self.bck.Add(title, (0, 0), (1, 2),
- flag=wx.LEFT|wx.ALIGN_CENTER_VERTICAL, border=15)
- else:
- title = wx.StaticText(self, -1,
- "Slicer Parameters", style=wx.ALIGN_LEFT)
- self.bck.Add(title, (0, 0), (1, 2),
- flag=wx.LEFT|wx.ALIGN_CENTER_VERTICAL, border=15)
- ix = 0
- iy = 0
- self.parameters = []
- keys = params.keys()
- keys.sort()
- for item in keys:
- iy += 1
- ix = 0
- if not item in ["count", "errors"]:
- text = wx.StaticText(self, -1, item, style=wx.ALIGN_LEFT)
- self.bck.Add(text, (iy, ix), (1, 1),
- wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
- ctl = wx.TextCtrl(self, -1, size=(80, 20),
- style=wx.TE_PROCESS_ENTER)
- hint_msg = "Modify the value of %s to change" % item
- hint_msg += " the 2D slicer"
- ctl.SetToolTipString(hint_msg)
- ix = 1
- ctl.SetValue(format_number(str(params[item])))
- self.Bind(wx.EVT_TEXT_ENTER, self.onTextEnter)
- ctl.Bind(wx.EVT_KILL_FOCUS, self.onTextEnter)
- self.parameters.append([item, ctl])
- self.bck.Add(ctl, (iy, ix), (1, 1),
- wx.EXPAND|wx.ADJUST_MINSIZE, 0)
- ix = 3
- self.bck.Add((20, 20), (iy, ix), (1, 1),
- wx.EXPAND|wx.ADJUST_MINSIZE, 0)
- else:
- text = wx.StaticText(self, -1, item + " : ",
- style=wx.ALIGN_LEFT)
- self.bck.Add(text, (iy, ix), (1, 1),
- wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
- ctl = wx.StaticText(self, -1,
- format_number(str(params[item])),
- style=wx.ALIGN_LEFT)
- ix = 1
- self.bck.Add(ctl, (iy, ix), (1, 1),
- wx.EXPAND|wx.ADJUST_MINSIZE, 0)
- iy += 1
- ix = 1
- self.bck.Add((20, 20), (iy, ix), (1, 1),
- wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
- self.bck.Layout()
- self.bck.Fit(self)
- self.parent.GetSizer().Layout()
-
- def onParamChange(self, evt):
- """
- receive an event end reset value text fields
- inside self.parameters
- """
- evt.Skip()
- if evt.type == "UPDATE":
- for item in self.parameters:
- if item[0] in evt.params:
- item[1].SetValue("%-5.3g" % evt.params[item[0]])
- item[1].Refresh()
-
- def onTextEnter(self, evt):
- """
- Parameters have changed
- """
- params = {}
- has_error = False
- for item in self.parameters:
- try:
- params[item[0]] = float(item[1].GetValue())
- item[1].SetBackgroundColour(
- wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW))
- item[1].Refresh()
- except:
- has_error = True
- item[1].SetBackgroundColour("pink")
- item[1].Refresh()
-
- if has_error == False:
- # Post parameter event
- ##parent hier is plotter2D
- event = SlicerParameterEvent(type=self.type, params=params)
- wx.PostEvent(self.parent, event)
-
Index: test/guiframe/local_perspectives/plotting/__init__.py
===================================================================
--- test/guiframe/local_perspectives/plotting/__init__.py (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,2 +1,0 @@
-PLUGIN_ID = "Plotting plug-in 1.0"
-from plotting import *
Index: test/guiframe/local_perspectives/plotting/binder.py
===================================================================
--- test/guiframe/local_perspectives/plotting/binder.py (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,388 +1,0 @@
-"""
-Extension to MPL to support the binding of artists to key/mouse events.
-"""
-
-class Selection:
- """
- Store and compare selections.
- """
- # TODO: We need some way to check in prop matches, preferably
- # TODO: without imposing structure on prop.
-
- artist = None
- prop = {}
- def __init__(self, artist=None, prop={}):
- self.artist, self.prop = artist, self.prop
-
- def __eq__(self, other):
- return self.artist is other.artist
-
- def __ne__(self, other):
- return self.artist is not other.artist
-
- def __nonzero__(self):
- return self.artist is not None
-
-class BindArtist:
-
- # Track keyboard modifiers for events.
- # TODO: Move keyboard modifier support into the backend. We cannot
- # TODO: properly support it from outside the windowing system since there
- # TODO: is no way to recognized whether shift is held down when the mouse
- # TODO: first clicks on the the application window.
- control, shift, alt, meta = False, False, False, False
-
- # Track doubleclick
- dclick_threshhold = 0.25
- _last_button, _last_time = None, 0
-
- # Mouse/keyboard events we can bind to
- events = ['enter', 'leave', 'motion', 'click', 'dclick', 'drag', 'release',
- 'scroll', 'key', 'keyup']
- # TODO: Need our own event structure
- def __init__(self, figure):
- canvas = figure.canvas
- # Link to keyboard/mouse
- try:
- self._connections = [
- canvas.mpl_connect('motion_notify_event', self._onMotion),
- canvas.mpl_connect('button_press_event', self._onClick),
- canvas.mpl_connect('button_release_event', self._onRelease),
- canvas.mpl_connect('key_press_event', self._onKey),
- canvas.mpl_connect('key_release_event', self._onKeyRelease),
- canvas.mpl_connect('scroll_event', self._onScroll)
- ]
- except:
- #print "bypassing scroll_event: wrong matplotlib version"
- self._connections = [
- canvas.mpl_connect('motion_notify_event', self._onMotion),
- canvas.mpl_connect('button_press_event', self._onClick),
- canvas.mpl_connect('button_release_event', self._onRelease),
- canvas.mpl_connect('key_press_event', self._onKey),
- canvas.mpl_connect('key_release_event', self._onKeyRelease),
- ]
- # Turn off picker if it hasn't already been done
- try:
- canvas.mpl_disconnect(canvas.button_pick_id)
- canvas.mpl_disconnect(canvas.scroll_pick_id)
- except:
- pass
- self.canvas = canvas
- self.figure = figure
- self.clearall()
-
- def clear(self, *artists):
- """
- self.clear(h1,h2,...)
- Remove connections for artists h1, h2, ...
-
- Use clearall() to reset all connections.
-
- """
- for h in artists:
- for a in self.events:
- if h in self._actions[a]:
- del self._actions[a][h]
- if h in self._artists:
- self._artists.remove(h)
- if self._current.artist in artists:
- self._current = Selection()
- if self._hasclick.artist in artists:
- self._hasclick = Selection()
- if self._haskey.artist in artists:
- self._haskey = Selection()
-
- def clearall(self):
- """
- Clear connections to all artists.
-
- Use clear(h1,h2,...) to reset specific artists.
- """
- # Don't monitor any actions
- self._actions = {}
- for action in self.events:
- self._actions[action] = {}
- # Need activity state
- self._artists = []
- self._current = Selection()
- self._hasclick = Selection()
- self._haskey = Selection()
-
- def disconnect(self):
- """
- In case we need to disconnect from the canvas...
- """
- try:
- for cid in self._connections:
- self.canvas.mpl_disconnect(cid)
- except:
- pass
- self._connections = []
-
- def __del__(self):
- self.disconnect()
-
- def __call__(self, trigger, artist, action):
- """Register a callback for an artist to a particular trigger event.
-
- usage:
- self.connect(eventname,artist,action)
-
- where:
- eventname is a string
- artist is the particular graph object to respond to the event
- action(event,**kw) is called when the event is triggered
-
- The action callback is associated with particular artists.
- Different artists will have different kwargs. See documentation
- on the contains() method for each artist. One common properties
- are ind for the index of the item under the cursor, which is
- returned by Line2D and by collections.
-
- The following events are supported:
- enter: mouse cursor moves into the artist or to a new index
- leave: mouse cursor leaves the artist
- click: mouse button pressed on the artist
- drag: mouse button pressed on the artist and cursor moves
- release: mouse button released for the artist
- key: key pressed when mouse is on the artist
- keyrelease: key released for the artist
-
- The event received by action has a number of attributes:
- name is the event name which was triggered
- artist is the object which triggered the event
- x,y are the screen coordinates of the mouse
- xdata,ydata are the graph coordinates of the mouse
- button is the mouse button being pressed/released
- key is the key being pressed/released
- shift,control,alt,meta are flags which are true if the
- corresponding key is pressed at the time of the event.
- details is a dictionary of artist specific details, such as the
- id(s) of the point that were clicked.
-
- When receiving an event, first check the modifier state to be
- sure it applies. E.g., the callback for 'press' might be:
- if event.button == 1 and event.shift: process Shift-click
-
- :TODO: Only receive events with the correct modifiers (e.g., S-click,
- :TODO: or *-click for any modifiers).
- :TODO: Only receive button events for the correct button (e.g., click1
- :TODO: release3, or dclick* for any button)
- :TODO: Support virtual artist, so that and artist can be flagged as
- :TODO: having a tag list and receive the correct events
- :TODO: Support virtual events for binding to button-3 vs shift button-1
- :TODO: without changing callback code
- :TODO: Attach multiple callbacks to the same event?
- :TODO: Clean up interaction with toolbar modes
- :TODO: push/pushclear/pop context so that binding changes
- for the duration
- :TODO: e.g., to support ? context sensitive help
-
- """
- # Check that the trigger is valid
- if trigger not in self._actions:
- raise ValueError, "%s invalid --- valid triggers are %s" \
- % (trigger, ", ".join(self.events))
- # Register the trigger callback
- self._actions[trigger][artist] = action
- #print "==> added",artist,[artist],"to",trigger,":",
- #self._actions[trigger].keys()
- # Maintain a list of all artists
- if artist not in self._artists:
- self._artists.append(artist)
-
- def trigger(self, actor, action, ev):
- """
- Trigger a particular event for the artist. Fallback to axes,
- to figure, and to 'all' if the event is not processed.
- """
- if action not in self.events:
- raise ValueError, "Trigger expects " + ", ".join(self.events)
- # Tag the event with modifiers
- for mod in ('alt', 'control', 'shift', 'meta'):
- setattr(ev, mod, getattr(self, mod))
- setattr(ev, 'artist', None)
- setattr(ev, 'action', action)
- setattr(ev, 'prop', {})
- # Fallback scheme. If the event does not return false, pass to parent.
- processed = False
- artist, prop = actor.artist, actor.prop
- if artist in self._actions[action]:
- ev.artist, ev.prop = artist, prop
- processed = self._actions[action][artist](ev)
- if not processed and ev.inaxes in self._actions[action]:
- ev.artist, ev.prop = ev.inaxes, {}
- processed = self._actions[action][ev.inaxes](ev)
- if not processed and self.figure in self._actions[action]:
- ev.artist, ev.prop = self.figure, {}
- processed = self._actions[action][self.figure](ev)
- if not processed and 'all' in self._actions[action]:
- ev.artist, ev.prop = None, {}
- processed = self._actions[action]['all'](ev)
- return processed
-
- def _find_current(self, event):
- """
- Find the artist who will receive the event. Only search
- registered artists. All others are invisible to the mouse.
- """
- # TODO: sort by zorder of axes then by zorder within axes
- self._artists.sort(cmp=lambda x, y: cmp(y.zorder, x.zorder))
- # print "search"," ".join([str(h) for h in self._artists])
- found = Selection()
- #print "searching in",self._artists
- for artist in self._artists:
- # TODO: should contains() return false if invisible?
- if not artist.get_visible():
- continue
- # TODO: optimization - exclude artists not inaxes
- try:
- inside,prop = artist.contains(event)
- except:
- # Probably an old version of matplotlib
- inside = False
- if inside:
- found.artist, found.prop = artist, prop
- break
- #print "found",found.artist
-
- # TODO: how to check if prop is equal?
- if found != self._current:
- self.trigger(self._current, 'leave', event)
- self.trigger(found, 'enter', event)
- self._current = found
- return found
-
- def _onMotion(self, event):
- """
- Track enter/leave/motion through registered artists; all
- other artists are invisible.
- """
- ## Can't kill double-click on motion since Windows produces
- ## spurious motion events.
- #self._last_button = None
-
- # Dibs on the motion event for the clicked artist
- if self._hasclick:
- # Make sure the x,y data use the coordinate system of the
- # artist rather than the default axes coordinates.
-
- transform = self._hasclick.artist.get_transform()
- #x,y = event.xdata,event.ydata
- x, y = event.x, event.y
- try:
- x, y = transform.inverted().transform_point((x, y))
-
- except:
- x, y = transform.inverse_xy_tup((x, y))
- event.xdata, event.ydata = x, y
- self.trigger(self._hasclick, 'drag', event)
- else:
- found = self._find_current(event)
- #print "found",found.artist
- self.trigger(found, 'motion', event)
-
- def _onClick(self, event):
- """
- Process button click
- """
- import time
-
- # Check for double-click
- event_time = time.time()
- #print event_time,self._last_time,self.dclick_threshhold
- #print (event_time > self._last_time + self.dclick_threshhold)
- #print event.button,self._last_button
- if (event.button != self._last_button) or \
- (event_time > self._last_time + self.dclick_threshhold):
- action = 'click'
- else:
- action = 'dclick'
- self._last_button = event.button
- self._last_time = event_time
-
- # If an artist is already dragging, feed any additional button
- # presses to that artist.
- # TODO: do we want to force a single button model on the user?
- # TODO: that is, once a button is pressed, no other buttons
- # TODO: can come through? I think this belongs in canvas, not here.
- if self._hasclick:
- found = self._hasclick
- else:
- found = self._find_current(event)
- #print "button %d pressed"%event.button
- # Note: it seems like if "click" returns False then hasclick should
- # not be set. The problem is that there are two reasons it can
- # return false: because there is no click action for this artist
- # or because the click action returned false. A related problem
- # is that click actions will go to the canvas if there is no click
- # action for the artist, even if the artist has a drag. I'll leave
- # it to future maintainers to sort out this problem. For now the
- # recommendation is that users should define click if they have
- # drag or release on the artist.
- self.trigger(found, action, event)
- self._hasclick = found
-
- def _onDClick(self, event):
- """
- Process button double click
- """
- # If an artist is already dragging, feed any additional button
- # presses to that artist.
- # TODO: do we want to force a single button model on the user?
- # TODO: that is, once a button is pressed, no other buttons
- # TODO: can come through? I think this belongs in canvas, not here.
- if self._hasclick:
- found = self._hasclick
- else:
- found = self._find_current(event)
- self.trigger(found, 'dclick', event)
- self._hasclick = found
-
- def _onRelease(self, event):
- """
- Process release release
- """
- self.trigger(self._hasclick, 'release', event)
- self._hasclick = Selection()
-
- def _onKey(self, event):
- """
- Process key click
- """
- # TODO: Do we really want keyboard focus separate from mouse focus?
- # TODO: Do we need an explicit focus command for keyboard?
- # TODO: Can we tab between items?
- # TODO: How do unhandled events get propogated to axes, figure and
- # TODO: finally to application? Do we need to implement a full tags
- # TODO: architecture a la Tk?
- # TODO: Do modifiers cause a grab? Does the artist see the modifiers?
- if event.key in ('alt', 'meta', 'control', 'shift'):
- setattr(self, event.key, True)
- return
-
- if self._haskey:
- found = self._haskey
- else:
- found = self._find_current(event)
- self.trigger(found, 'key', event)
- self._haskey = found
-
- def _onKeyRelease(self, event):
- """
- Process key release
- """
- if event.key in ('alt', 'meta', 'control', 'shift'):
- setattr(self, event.key, False)
- return
- if self._haskey:
- self.trigger(self._haskey, 'keyup', event)
- self._haskey = Selection()
-
- def _onScroll(self, event):
- """
- Process scroll event
- """
- found = self._find_current(event)
- self.trigger(found, 'scroll', event)
-
Index: test/guiframe/local_perspectives/plotting/boxMask.py
===================================================================
--- test/guiframe/local_perspectives/plotting/boxMask.py (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,252 +1,0 @@
-
-
-
-import math
-#import wx
-#from copy import deepcopy
-from BaseInteractor import _BaseInteractor
-from boxSum import PointInteractor
-from boxSum import VerticalDoubleLine
-from boxSum import HorizontalDoubleLine
-#from sans.guiframe.events import SlicerParamUpdateEvent
-
-
-class BoxMask(_BaseInteractor):
- """
- BoxMask Class: determine 2 rectangular area to find the pixel of
- a Data inside of box.
-
- Uses PointerInteractor , VerticalDoubleLine,HorizontalDoubleLine.
-
- :param zorder: Artists with lower zorder values are drawn first.
- :param x_min: the minimum value of the x coordinate
- :param x_max: the maximum value of the x coordinate
- :param y_min: the minimum value of the y coordinate
- :param y_max: the maximum value of the y coordinate
-
- """
- def __init__(self, base, axes, color='black', zorder=3, side=None,
- x_min=0.008, x_max=0.008, y_min=0.0025, y_max=0.0025):
- """
- """
- _BaseInteractor.__init__(self, base, axes, color=color)
- ## class initialization
- ## list of Boxmask markers
- self.markers = []
- self.axes = axes
- self.is_inside = side
- ## connect the artist for the motion
- self.connect = self.base.connect
- ## when qmax is reached the selected line is reset
- #the its previous value
- self.qmax = min(self.base.data.xmax, self.base.data.xmin)
- ## Define the box limits
- self.xmin = -1 * 0.5 * min(math.fabs(self.base.data.xmax),
- math.fabs(self.base.data.xmin))
- self.ymin = -1 * 0.5 * min(math.fabs(self.base.data.xmax),
- math.fabs(self.base.data.xmin))
- self.xmax = 0.5 * min(math.fabs(self.base.data.xmax),
- math.fabs(self.base.data.xmin))
- self.ymax = 0.5 * min(math.fabs(self.base.data.xmax),
- math.fabs(self.base.data.xmin))
- ## center of the box
- self.center_x = 0.0002
- self.center_y = 0.0003
- ## Number of points on the plot
- self.nbins = 20
- ## Define initial result the summation
- self.count = 0
- self.error = 0
- self.data = self.base.data
- ## Flag to determine if the current figure has moved
- ## set to False == no motion , set to True== motion
- self.has_move = False
- ## Create Box edges
- self.horizontal_lines = HorizontalDoubleLine(self,
- self.base.subplot,
- color='blue',
- zorder=zorder,
- y=self.ymax,
- x=self.xmax,
- center_x=self.center_x,
- center_y=self.center_y)
- self.horizontal_lines.qmax = self.qmax
-
- self.vertical_lines = VerticalDoubleLine(self,
- self.base.subplot,
- color='grey',
- zorder=zorder,
- y=self.ymax,
- x=self.xmax,
- center_x=self.center_x,
- center_y=self.center_y)
- self.vertical_lines.qmax = self.qmax
-
- self.center = PointInteractor(self,
- self.base.subplot,color='grey',
- zorder=zorder,
- center_x=self.center_x,
- center_y=self.center_y)
- ## Save the name of the slicer panel associate with this slicer
- self.panel_name = ""
- ## Update and post slicer parameters
- self.update()
- self._post_data()
-
- def clear(self):
- """
- Clear the slicer and all connected events related to this slicer
- """
- self.clear_markers()
- self.horizontal_lines.clear()
- self.vertical_lines.clear()
- self.center.clear()
- self.base.connect.clearall()
- #self.base.Unbind(EVT_SLICER_PARS)
-
- def update(self):
- """
- Respond to changes in the model by recalculating the profiles and
- resetting the widgets.
- """
- # check if the center point has moved and update the figure accordingly
- if self.center.has_move:
- self.center.update()
- self.horizontal_lines.update(center=self.center)
- self.vertical_lines.update(center=self.center)
- ## check if the horizontal lines have moved and update
- # the figure accordingly
- if self.horizontal_lines.has_move:
- self.horizontal_lines.update()
- self.vertical_lines.update(y1=self.horizontal_lines.y1,
- y2=self.horizontal_lines.y2,
- height=self.horizontal_lines.half_height)
- ## check if the vertical lines have moved and update
- # the figure accordingly
- if self.vertical_lines.has_move:
- self.vertical_lines.update()
- self.horizontal_lines.update(x1=self.vertical_lines.x1,
- x2=self.vertical_lines.x2,
- width=self.vertical_lines.half_width)
- #if self.is_inside != None:
- out = self._post_data()
- return out
-
- def save(self, ev):
- """
- Remember the roughness for this layer and the next so that we
- can restore on Esc.
- """
- self.base.freeze_axes()
- self.horizontal_lines.save(ev)
- self.vertical_lines.save(ev)
- self.center.save(ev)
-
- def _post_data(self):
- """
- Get the limits of the boxsum and compute the sum of the pixel
- contained in that region and the error on that sum
- """
- from DataLoader.manipulations import Boxcut
- ## Data 2D for which the pixel will be summed
- data = self.base.data
- mask = data.mask
- ## the region of the summation
- x_min = self.horizontal_lines.x2
- x_max = self.horizontal_lines.x1
- y_min = self.vertical_lines.y2
- y_max = self.vertical_lines.y1
- mask = Boxcut(x_min=x_min, x_max=x_max, y_min=y_min, y_max=y_max)
-
- if self.is_inside:
- out = (mask(data) == False)
- else:
- out = (mask(data))
- #self.base.data.mask=out
- return out
-
- def moveend(self, ev):
- """
- After a dragging motion this function is called to compute
- the error and the sum of pixel of a given data 2D
- """
- self.base.thaw_axes()
- ## post
- self._post_data()
-
- def restore(self):
- """
- Restore the roughness for this layer.
- """
- self.horizontal_lines.restore()
- self.vertical_lines.restore()
- self.center.restore()
-
- def move(self, x, y, ev):
- """
- Process move to a new position, making sure that the move is allowed.
- """
- pass
-
- def set_cursor(self, x, y):
- pass
-
- def get_params(self):
- """
- Store a copy of values of parameters of the slicer into a dictionary.
-
- :return params: the dictionary created
-
- """
- params = {}
- params["Width"] = math.fabs(self.vertical_lines.half_width) * 2
- params["Height"] = math.fabs(self.horizontal_lines.half_height) * 2
- params["center_x"] = self.center.x
- params["center_y"] = self.center.y
- return params
-
- def get_mask(self):
- """
- return mask as a result of boxcut
- """
- mask = self.mask
- return mask
-
- def set_params(self, params):
- """
- Receive a dictionary and reset the slicer with values contained
- in the values of the dictionary.
-
- :param params: a dictionary containing name of slicer parameters and
- values the user assigned to the slicer.
- """
- x_max = math.fabs(params["Width"] )/2
- y_max = math.fabs(params["Height"])/2
-
- self.center_x = params["center_x"]
- self.center_y = params["center_y"]
- #update the slicer given values of params
- self.center.update(center_x=self.center_x, center_y=self.center_y)
- self.horizontal_lines.update(center=self.center,
- width=x_max,
- height=y_max)
- self.vertical_lines.update(center=self.center,
- width=x_max,
- height=y_max)
- #compute the new error and sum given values of params
- self._post_data()
-
- def freeze_axes(self):
- self.base.freeze_axes()
-
- def thaw_axes(self):
- self.base.thaw_axes()
-
- def draw(self):
- self.base.update()
-
-class inner_BoxMask(BoxMask):
- def __call__(self):
- self.base.data.mask = (self._post_data()==False)
-
-
Index: test/guiframe/local_perspectives/plotting/boxSlicer.py
===================================================================
--- test/guiframe/local_perspectives/plotting/boxSlicer.py (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,560 +1,0 @@
-
-
-import wx
-#import copy
-#from copy import deepcopy
-import math
-import numpy
-from sans.guiframe.events import NewPlotEvent
-from sans.guiframe.events import StatusEvent
-from sans.guiframe.events import SlicerParameterEvent
-from sans.guiframe.events import EVT_SLICER_PARS
-from BaseInteractor import _BaseInteractor
-from sans.guiframe.dataFitting import Data1D
-#import SlicerParameters
-
-
-class BoxInteractor(_BaseInteractor):
- """
- BoxInteractor define a rectangle that return data1D average of Data2D
- in a rectangle area defined by -x, x ,y, -y
- """
- def __init__(self, base, axes, color='black', zorder=3):
- _BaseInteractor.__init__(self, base, axes, color=color)
- ## Class initialization
- self.markers = []
- self.axes = axes
- ##connecting artist
- self.connect = self.base.connect
- ## determine x y values
- self.x = 0.5 * min(math.fabs(self.base.data2D.xmax),
- math.fabs(self.base.data2D.xmin))
- self.y = 0.5 * min(math.fabs(self.base.data2D.xmax),
- math.fabs(self.base.data2D.xmin))
- ## when reach qmax reset the graph
- self.qmax = max(self.base.data2D.xmax, self.base.data2D.xmin,
- self.base.data2D.ymax, self.base.data2D.ymin)
- ## Number of points on the plot
- self.nbins = 30
- ## If True, I(|Q|) will be return, otherwise,
- #negative q-values are allowed
- self.fold = True
- ## reference of the current Slab averaging
- self.averager = None
- ## Create vertical and horizaontal lines for the rectangle
- self.vertical_lines = VerticalLines(self,
- self.base.subplot,
- color='blue',
- zorder=zorder,
- y=self.y ,
- x=self.x)
- self.vertical_lines.qmax = self.qmax
-
- self.horizontal_lines = HorizontalLines(self,
- self.base.subplot,
- color='green',
- zorder=zorder,
- x=self.x,
- y=self.y)
- self.horizontal_lines.qmax = self.qmax
- ## draw the rectangle and plost the data 1D resulting
- ## of averaging data2D
- self.update()
- self._post_data()
- ## Bind to slice parameter events
- self.base.Bind(EVT_SLICER_PARS, self._onEVT_SLICER_PARS)
-
- def _onEVT_SLICER_PARS(self, event):
- """
- receive an event containing parameters values to reset the slicer
-
- :param event: event of type SlicerParameterEvent with params as
- attribute
- """
- wx.PostEvent(self.base.parent,
- StatusEvent(status="BoxSlicer._onEVT_SLICER_PARS"))
- event.Skip()
- if event.type == self.__class__.__name__:
- self.set_params(event.params)
- self.base.update()
-
- def update_and_post(self):
- """
- Update the slicer and plot the resulting data
- """
- self.update()
- self._post_data()
-
- def set_layer(self, n):
- """
- Allow adding plot to the same panel
-
- :param n: the number of layer
-
- """
- self.layernum = n
- self.update()
-
- def clear(self):
- """
- Clear the slicer and all connected events related to this slicer
- """
- self.averager = None
- self.clear_markers()
- self.horizontal_lines.clear()
- self.vertical_lines.clear()
- self.base.connect.clearall()
- self.base.Unbind(EVT_SLICER_PARS)
-
- def update(self):
- """
- Respond to changes in the model by recalculating the profiles and
- resetting the widgets.
- """
- ##Update the slicer if an horizontal line is dragged
- if self.horizontal_lines.has_move:
- self.horizontal_lines.update()
- self.vertical_lines.update(y=self.horizontal_lines.y)
- ##Update the slicer if a vertical line is dragged
- if self.vertical_lines.has_move:
- self.vertical_lines.update()
- self.horizontal_lines.update(x=self.vertical_lines.x)
-
- def save(self, ev):
- """
- Remember the roughness for this layer and the next so that we
- can restore on Esc.
- """
- self.base.freeze_axes()
- self.vertical_lines.save(ev)
- self.horizontal_lines.save(ev)
-
- def _post_data(self):
- pass
-
- def post_data(self, new_slab=None, nbins=None, direction=None):
- """
- post data averaging in Qx or Qy given new_slab type
-
- :param new_slab: slicer that determine with direction to average
- :param nbins: the number of points plotted when averaging
- :param direction: the direction of averaging
-
- """
- x_min = -1 * math.fabs(self.vertical_lines.x)
- x_max = math.fabs(self.vertical_lines.x)
- y_min = -1 * math.fabs(self.horizontal_lines.y)
- y_max = math.fabs(self.horizontal_lines.y)
-
- if nbins != None:
- self.nbins = nbins
- if self.averager == None:
- if new_slab == None:
- msg = "post data:cannot average , averager is empty"
- raise ValueError, msg
- self.averager = new_slab
- if direction == "X":
- if self.fold:
- x_low = 0
- else:
- x_low = math.fabs(x_min)
- bin_width = (x_max + x_low)/self.nbins
- else:
- if self.fold:
- y_low = 0
- else:
- y_low = math.fabs(y_min)
- bin_width = (y_max + y_low)/self.nbins
- ## Average data2D given Qx or Qy
- box = self.averager(x_min=x_min, x_max=x_max, y_min=y_min, y_max=y_max,
- bin_width=bin_width)
- box.fold = self.fold
- boxavg = box(self.base.data2D)
- #3 Create Data1D to plot
- if hasattr(boxavg, "dxl"):
- dxl = boxavg.dxl
- else:
- dxl = None
- if hasattr(boxavg, "dxw"):
- dxw = boxavg.dxw
- else:
- dxw = None
- new_plot = Data1D(x=boxavg.x, y=boxavg.y, dy=boxavg.dy)
- new_plot.dxl = dxl
- new_plot.dxw = dxw
- new_plot.name = str(self.averager.__name__) + \
- "(" + self.base.data2D.name + ")"
- new_plot.source = self.base.data2D.source
- new_plot.interactive = True
- new_plot.detector = self.base.data2D.detector
- ## If the data file does not tell us what the axes are, just assume...
- new_plot.xaxis("\\rm{Q}", "A^{-1}")
- new_plot.yaxis("\\rm{Intensity} ", "cm^{-1}")
-
- data = self.base.data2D
- if hasattr(data, "scale") and data.scale == 'linear' and \
- self.base.data2D.name.count("Residuals") > 0:
- new_plot.ytransform = 'y'
- new_plot.yaxis("\\rm{Residuals} ", "/")
-
- new_plot.group_id = str(self.averager.__name__) + self.base.data2D.name
- #new_plot.id = str(self.averager.__name__)
- #new_plot.is_data= True
- wx.PostEvent(self.base.parent, NewPlotEvent(plot=new_plot,
- title=str(self.averager.__name__)))
-
- def moveend(self, ev):
- """
- Called after a dragging event.
- Post the slicer new parameters and creates a new Data1D
- corresponding to the new average
- """
- self.base.thaw_axes()
- # Post paramters
- event = SlicerParameterEvent()
- event.type = self.__class__.__name__
- event.params = self.get_params()
- wx.PostEvent(self.base.parent, event)
- # create the new data1D
- self._post_data()
-
- def restore(self):
- """
- Restore the roughness for this layer.
- """
- self.horizontal_lines.restore()
- self.vertical_lines.restore()
-
- def move(self, x, y, ev):
- """
- Process move to a new position, making sure that the move is allowed.
- """
- pass
-
- def set_cursor(self, x, y):
- pass
-
- def get_params(self):
- """
- Store a copy of values of parameters of the slicer into a dictionary.
-
- :return params: the dictionary created
-
- """
- params = {}
- params["x_max"] = math.fabs(self.vertical_lines.x)
- params["y_max"] = math.fabs(self.horizontal_lines.y)
- params["nbins"] = self.nbins
- return params
-
- def set_params(self, params):
- """
- Receive a dictionary and reset the slicer with values contained
- in the values of the dictionary.
-
- :param params: a dictionary containing name of slicer parameters and
- values the user assigned to the slicer.
- """
- self.x = float(math.fabs(params["x_max"]))
- self.y = float(math.fabs(params["y_max"] ))
- self.nbins = params["nbins"]
-
- self.horizontal_lines.update(x=self.x, y=self.y)
- self.vertical_lines.update(x=self.x, y=self.y)
- self.post_data(nbins=None)
-
- def freeze_axes(self):
- """
- """
- self.base.freeze_axes()
-
- def thaw_axes(self):
- """
- """
- self.base.thaw_axes()
-
- def draw(self):
- """
- """
- self.base.draw()
-
-
-class HorizontalLines(_BaseInteractor):
- """
- Draw 2 Horizontal lines centered on (0,0) that can move
- on the x- direction and in opposite direction
- """
- def __init__(self, base, axes, color='black', zorder=5, x=0.5, y=0.5):
- """
- """
- _BaseInteractor.__init__(self, base, axes, color=color)
- ##Class initialization
- self.markers = []
- self.axes = axes
- ## Saving the end points of two lines
- self.x = x
- self.save_x = x
-
- self.y = y
- self.save_y = y
- ## Creating a marker
- try:
- # Inner circle marker
- self.inner_marker = self.axes.plot([0], [self.y], linestyle='',
- marker='s', markersize=10,
- color=self.color, alpha=0.6,
- pickradius=5, label="pick",
- # Prefer this to other lines
- zorder=zorder,
- visible=True)[0]
- except:
- self.inner_marker = self.axes.plot([0], [self.y], linestyle='',
- marker='s', markersize=10,
- color=self.color, alpha=0.6,
- label="pick", visible=True)[0]
- message = "\nTHIS PROTOTYPE NEEDS THE LATEST VERSION "
- message += "OF MATPLOTLIB\n Get the SVN version that"
- message += " is at least as recent as June 1, 2007"
- owner = self.base.base.parent
- wx.PostEvent(owner,
- StatusEvent(status="AnnulusSlicer: %s" % message))
- ## Define 2 horizontal lines
- self.top_line = self.axes.plot([self.x, -self.x], [self.y, self.y],
- linestyle='-', marker='',
- color=self.color, visible=True)[0]
- self.bottom_line = self.axes.plot([self.x, -self.x], [-self.y, -self.y],
- linestyle='-', marker='',
- color=self.color, visible=True)[0]
- ## Flag to check the motion of the lines
- self.has_move = False
- ## Connecting markers to mouse events and draw
- self.connect_markers([self.top_line, self.inner_marker])
- self.update()
-
- def set_layer(self, n):
- """
- Allow adding plot to the same panel
-
- :param n: the number of layer
-
- """
- self.layernum = n
- self.update()
-
- def clear(self):
- """
- Clear this slicer and its markers
- """
- self.clear_markers()
- try:
- self.inner_marker.remove()
- self.top_line.remove()
- self.bottom_line.remove()
- except:
- # Old version of matplotlib
- for item in range(len(self.axes.lines)):
- del self.axes.lines[0]
-
- def update(self, x=None, y=None):
- """
- Draw the new roughness on the graph.
-
- :param x: x-coordinates to reset current class x
- :param y: y-coordinates to reset current class y
-
- """
- ## Reset x, y- coordinates if send as parameters
- if x != None:
- self.x = numpy.sign(self.x) * math.fabs(x)
- if y != None:
- self.y = numpy.sign(self.y) * math.fabs(y)
- ## Draw lines and markers
- self.inner_marker.set(xdata=[0], ydata=[self.y])
- self.top_line.set(xdata=[self.x, -self.x], ydata=[self.y, self.y])
- self.bottom_line.set(xdata=[self.x,-self.x], ydata=[-self.y, -self.y])
-
- def save(self, ev):
- """
- Remember the roughness for this layer and the next so that we
- can restore on Esc.
- """
- self.save_x = self.x
- self.save_y = self.y
- self.base.freeze_axes()
-
- def moveend(self, ev):
- """
- Called after a dragging this edge and set self.has_move to False
- to specify the end of dragging motion
- """
- self.has_move = False
- self.base.moveend(ev)
-
- def restore(self):
- """
- Restore the roughness for this layer.
- """
- self.x = self.save_x
- self.y = self.save_y
-
- def move(self, x, y, ev):
- """
- Process move to a new position, making sure that the move is allowed.
- """
- self.y = y
- self.has_move = True
- self.base.base.update()
-
-
-class VerticalLines(_BaseInteractor):
- """
- Select an annulus through a 2D plot
- """
- def __init__(self, base, axes, color='black', zorder=5, x=0.5, y=0.5):
- """
- """
- _BaseInteractor.__init__(self, base, axes, color=color)
- self.markers = []
- self.axes = axes
- self.x = math.fabs(x)
- self.save_x = self.x
- self.y = math.fabs(y)
- self.save_y = y
- try:
- # Inner circle marker
- self.inner_marker = self.axes.plot([self.x], [0], linestyle='',
- marker='s', markersize=10,
- color=self.color, alpha=0.6,
- pickradius=5, label="pick",
- # Prefer this to other lines
- zorder=zorder, visible=True)[0]
- except:
- self.inner_marker = self.axes.plot([self.x], [0], linestyle='',
- marker='s', markersize=10,
- color=self.color, alpha=0.6,
- label="pick", visible=True)[0]
- message = "\nTHIS PROTOTYPE NEEDS THE LATEST VERSION"
- message += " OF MATPLOTLIB\n Get the SVN version that is"
- message += " at least as recent as June 1, 2007"
-
- self.right_line = self.axes.plot([self.x, self.x],
- [self.y , -self.y],
- linestyle='-', marker='',
- color=self.color, visible=True)[0]
- self.left_line = self.axes.plot([-self.x, -self.x],
- [self.y, -self.y],
- linestyle='-', marker='',
- color=self.color, visible=True)[0]
- self.has_move = False
- self.connect_markers([self.right_line, self.inner_marker])
- self.update()
-
- def set_layer(self, n):
- """
- Allow adding plot to the same panel
-
- :param n: the number of layer
-
- """
- self.layernum = n
- self.update()
-
- def clear(self):
- """
- Clear this slicer and its markers
- """
- self.clear_markers()
- try:
- self.inner_marker.remove()
- self.left_line.remove()
- self.right_line.remove()
- except:
- # Old version of matplotlib
- for item in range(len(self.axes.lines)):
- del self.axes.lines[0]
-
- def update(self, x=None, y=None):
- """
- Draw the new roughness on the graph.
-
- :param x: x-coordinates to reset current class x
- :param y: y-coordinates to reset current class y
-
- """
- ## reset x, y -coordinates if given as parameters
- if x != None:
- self.x = numpy.sign(self.x) * math.fabs(x)
- if y != None:
- self.y = numpy.sign(self.y) * math.fabs(y)
- ## draw lines and markers
- self.inner_marker.set(xdata=[self.x], ydata=[0])
- self.left_line.set(xdata=[-self.x, -self.x], ydata=[self.y, -self.y])
- self.right_line.set(xdata=[self.x, self.x], ydata=[self.y, -self.y])
-
- def save(self, ev):
- """
- Remember the roughness for this layer and the next so that we
- can restore on Esc.
- """
- self.save_x = self.x
- self.save_y = self.y
- self.base.freeze_axes()
-
- def moveend(self, ev):
- """
- Called after a dragging this edge and set self.has_move to False
- to specify the end of dragging motion
- """
- self.has_move = False
- self.base.moveend(ev)
-
- def restore(self):
- """
- Restore the roughness for this layer.
- """
- self.x = self.save_x
- self.y = self.save_y
-
- def move(self, x, y, ev):
- """
- Process move to a new position, making sure that the move is allowed.
- """
- self.has_move = True
- self.x = x
- self.base.base.update()
-
-
-class BoxInteractorX(BoxInteractor):
- """
- Average in Qx direction
- """
- def __init__(self, base, axes, color='black', zorder=3):
- BoxInteractor.__init__(self, base, axes, color=color)
- self.base = base
- self._post_data()
-
- def _post_data(self):
- """
- Post data creating by averaging in Qx direction
- """
- from DataLoader.manipulations import SlabX
- self.post_data(SlabX, direction="X")
-
-
-class BoxInteractorY(BoxInteractor):
- """
- Average in Qy direction
- """
- def __init__(self, base, axes, color='black', zorder=3):
- BoxInteractor.__init__(self, base, axes, color=color)
- self.base = base
- self._post_data()
-
- def _post_data(self):
- """
- Post data creating by averaging in Qy direction
- """
- from DataLoader.manipulations import SlabY
- self.post_data(SlabY, direction="Y")
-
-
Index: test/guiframe/local_perspectives/plotting/boxSum.py
===================================================================
--- test/guiframe/local_perspectives/plotting/boxSum.py (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,833 +1,0 @@
-
-
-
-import math
-import wx
-from copy import deepcopy
-from BaseInteractor import _BaseInteractor
-from sans.guiframe.events import SlicerParamUpdateEvent
-from sans.guiframe.events import EVT_SLICER_PARS
-from sans.guiframe.events import StatusEvent
-
-
-class BoxSum(_BaseInteractor):
- """
- Boxsum Class: determine 2 rectangular area to compute
- the sum of pixel of a Data.
- Uses PointerInteractor , VerticalDoubleLine,HorizontalDoubleLine.
- @param zorder: Artists with lower zorder values are drawn first.
- @param x_min: the minimum value of the x coordinate
- @param x_max: the maximum value of the x coordinate
- @param y_min: the minimum value of the y coordinate
- @param y_max: the maximum value of the y coordinate
-
- """
- def __init__(self, base, axes, color='black', zorder=3, x_min=0.008,
- x_max=0.008, y_min=0.0025, y_max=0.0025):
- """
- """
- _BaseInteractor.__init__(self, base, axes, color=color)
- ## class initialization
- ## list of Boxsmun markers
- self.markers = []
- self.axes = axes
- ## connect the artist for the motion
- self.connect = self.base.connect
- ## when qmax is reached the selected line is reset the its previous value
- self.qmax = min(self.base.data2D.xmax, self.base.data2D.xmin)
- ## Define the boxsum limits
- self.xmin = -1 * 0.5 * min(math.fabs(self.base.data2D.xmax),
- math.fabs(self.base.data2D.xmin))
- self.ymin = -1 * 0.5 * min(math.fabs(self.base.data2D.xmax),
- math.fabs(self.base.data2D.xmin))
- self.xmax = 0.5 * min(math.fabs(self.base.data2D.xmax),
- math.fabs(self.base.data2D.xmin))
- self.ymax = 0.5 * min(math.fabs(self.base.data2D.xmax),
- math.fabs(self.base.data2D.xmin))
- ## center of the boxSum
- self.center_x = 0.0002
- self.center_y = 0.0003
- ## Number of points on the plot
- self.nbins = 20
- ## Define initial result the summation
- self.count = 0
- self.error = 0
- ## Flag to determine if the current figure has moved
- ## set to False == no motion , set to True== motion
- self.has_move = False
- ## Create Boxsum edges
- self.horizontal_lines= HorizontalDoubleLine(self,
- self.base.subplot,
- color='blue',
- zorder=zorder,
- y=self.ymax,
- x=self.xmax,
- center_x=self.center_x,
- center_y=self.center_y)
- self.horizontal_lines.qmax = self.qmax
-
- self.vertical_lines= VerticalDoubleLine(self,
- self.base.subplot,
- color='black',
- zorder=zorder,
- y=self.ymax,
- x=self.xmax,
- center_x=self.center_x,
- center_y=self.center_y)
- self.vertical_lines.qmax = self.qmax
-
- self.center= PointInteractor(self,
- self.base.subplot,color='grey',
- zorder=zorder,
- center_x= self.center_x,
- center_y= self.center_y)
- ## Save the name of the slicer panel associate with this slicer
- self.panel_name = ""
- ## Update and post slicer parameters
- self.update()
- self._post_data()
- ## Bind to slice parameter events
- self.base.Bind(EVT_SLICER_PARS, self._onEVT_SLICER_PARS)
-
- def set_panel_name(self, name):
- """
- Store the name of the panel associated to this slicer
- @param name: the name of this panel
- """
- self.panel_name = name
-
- def _onEVT_SLICER_PARS(self, event):
- """
- receive an event containing parameters values to reset the slicer
- @param event: event of type SlicerParameterEvent with params as
- attribute
- """
- ## Post e message to declare what kind of event has being received
- wx.PostEvent(self.base.parent,
- StatusEvent(status="Boxsum._onEVT_SLICER_PARS"))
- event.Skip()
- ## reset the slicer with the values contains the event.params dictionary
- if event.type == self.__class__.__name__:
- self.set_params(event.params)
- self.base.update()
-
- def set_layer(self, n):
- """
- Allow adding plot to the same panel
- :param n: the number of layer
- """
- self.layernum = n
- self.update()
-
- def clear(self):
- """
- Clear the slicer and all connected events related to this slicer
- """
- self.clear_markers()
- self.horizontal_lines.clear()
- self.vertical_lines.clear()
- self.center.clear()
- self.base.connect.clearall()
- self.base.Unbind(EVT_SLICER_PARS)
-
- def update(self):
- """
- Respond to changes in the model by recalculating the profiles and
- resetting the widgets.
- """
- ## check if the center point has moved and update the figure accordingly
- if self.center.has_move:
- self.center.update()
- self.horizontal_lines.update( center= self.center)
- self.vertical_lines.update( center= self.center)
- ## check if the horizontal lines have moved and
- #update the figure accordingly
- if self.horizontal_lines.has_move:
- self.horizontal_lines.update()
- self.vertical_lines.update(y1=self.horizontal_lines.y1,
- y2=self.horizontal_lines.y2,
- height=self.horizontal_lines.half_height)
- ## check if the vertical lines have moved and
- #update the figure accordingly
- if self.vertical_lines.has_move:
- self.vertical_lines.update()
- self.horizontal_lines.update(x1=self.vertical_lines.x1,
- x2=self.vertical_lines.x2,
- width=self.vertical_lines.half_width)
-
- def save(self, ev):
- """
- Remember the roughness for this layer and the next so that we
- can restore on Esc.
- """
- self.base.freeze_axes()
- self.horizontal_lines.save(ev)
- self.vertical_lines.save(ev)
- self.center.save(ev)
-
- def _post_data(self):
- """
- Get the limits of the boxsum and compute the sum of the pixel
- contained in that region and the error on that sum
- """
- ## Data 2D for which the pixel will be summed
- data = self.base.data2D
- ## the region of the summation
- x_min = self.horizontal_lines.x2
- x_max = self.horizontal_lines.x1
- y_min = self.vertical_lines.y2
- y_max = self.vertical_lines.y1
- ##computation of the sum and its error
- from DataLoader.manipulations import Boxavg
- box = Boxavg(x_min=x_min, x_max=x_max, y_min=y_min, y_max=y_max)
- self.count, self.error = box(self.base.data2D)
-
- def moveend(self, ev):
- """
- After a dragging motion this function is called to compute
- the error and the sum of pixel of a given data 2D
- """
- self.base.thaw_axes()
- ## compute error an d sum of data's pixel
- self._post_data()
- ## Create and event ( posted to guiframe)that set the
- ##current slicer parameter to a panel of name self.panel_name
- self.type = self.__class__.__name__
- params = self.get_params()
- event = SlicerParamUpdateEvent(type=self.type,
- params=params,
- panel_name=self.panel_name)
- wx.PostEvent(self.base.parent, event)
-
- def restore(self):
- """
- Restore the roughness for this layer.
- """
- self.horizontal_lines.restore()
- self.vertical_lines.restore()
- self.center.restore()
-
- def move(self, x, y, ev):
- """
- Process move to a new position, making sure that the move is allowed.
- """
- pass
-
- def set_cursor(self, x, y):
- """
- """
- pass
-
- def get_params(self):
- """
- Store a copy of values of parameters of the slicer into a dictionary.
- :return params: the dictionary created
- """
- params = {}
- params["Width"] = math.fabs(self.vertical_lines.half_width) * 2
- params["Height"] = math.fabs(self.horizontal_lines.half_height) * 2
- params["center_x"] = self.center.x
- params["center_y"] = self.center.y
- params["count"] = self.count
- params["errors"] = self.error
- return params
-
- def get_result(self):
- """
- return the result of box summation
- """
- result = {}
- result["count"] = self.count
- result["error"] = self.error
- return result
-
- def set_params(self, params):
- """
- Receive a dictionary and reset the slicer with values contained
- in the values of the dictionary.
- :param params: a dictionary containing name of slicer parameters and
- values the user assigned to the slicer.
- """
- x_max = math.fabs(params["Width"] )/2
- y_max = math.fabs(params["Height"] )/2
-
- self.center_x = params["center_x"]
- self.center_y = params["center_y"]
- #update the slicer given values of params
- self.center.update(center_x=self.center_x, center_y=self.center_y)
- self.horizontal_lines.update(center=self.center,
- width=x_max, height=y_max)
- self.vertical_lines.update(center=self.center,
- width=x_max, height=y_max)
- #compute the new error and sum given values of params
- self._post_data()
-
- def freeze_axes(self):
- """
- """
- self.base.freeze_axes()
-
- def thaw_axes(self):
- """
- """
- self.base.thaw_axes()
-
- def draw(self):
- """
- """
- self.base.draw()
-
-
-
-class PointInteractor(_BaseInteractor):
- """
- Draw a point that can be dragged with the marker.
- this class controls the motion the center of the BoxSum
- """
- def __init__(self, base, axes, color='black', zorder=5, center_x=0.0,
- center_y=0.0):
- """
- """
- _BaseInteractor.__init__(self, base, axes, color=color)
- ## Initialization the class
- self.markers = []
- self.axes = axes
- # center coordinates
- self.x = center_x
- self.y = center_y
- ## saved value of the center coordinates
- self.save_x = center_x
- self.save_y = center_y
- ## Create a marker
- try:
- self.center_marker = self.axes.plot([self.x],[self.y], linestyle='',
- marker='s', markersize=10,
- color=self.color, alpha=0.6,
- pickradius=5, label="pick",
- # Prefer this to other lines
- zorder=zorder,
- visible=True)[0]
- except:
- self.center_marker = self.axes.plot([self.x],[self.y], linestyle='',
- marker='s', markersize=10,
- color=self.color, alpha=0.6,
- label="pick",
- visible=True)[0]
- message = "\nTHIS PROTOTYPE NEEDS THE LATEST VERSION"
- message += " OF MATPLOTLIB.\n Get the SVN version that is "
- message += "at least as recent as June 1, 2007"
- owner = self.base.base.parent
- wx.PostEvent(owner,
- StatusEvent(status="AnnulusSlicer: %s" % message))
- ## Draw a point
- self.center = self.axes.plot([self.x], [self.y],
- linestyle='-', marker='',
- color=self.color,
- visible=True)[0]
- ## Flag to determine the motion this point
- self.has_move = False
- ## connecting the marker to allow them to move
- self.connect_markers([self.center_marker])
- ## Update the figure
- self.update()
-
- def set_layer(self, n):
- """
- Allow adding plot to the same panel
- @param n: the number of layer
- """
- self.layernum = n
- self.update()
-
- def clear(self):
- """
- Clear this figure and its markers
- """
- self.clear_markers()
- try:
- self.center.remove()
- self.center_marker.remove()
- except:
- # Old version of matplotlib
- for item in range(len(self.axes.lines)):
- del self.axes.lines[0]
-
- def update(self, center_x=None,center_y=None):
- """
- Draw the new roughness on the graph.
- """
- if center_x != None:
- self.x = center_x
- if center_y != None:
- self.y = center_y
- self.center_marker.set(xdata=[self.x], ydata=[self.y])
- self.center.set(xdata=[self.x], ydata=[self.y])
-
- def save(self, ev):
- """
- Remember the roughness for this layer and the next so that we
- can restore on Esc.
- """
- self.save_x = self.x
- self.save_y = self.y
- self.base.freeze_axes()
-
- def moveend(self, ev):
- """
- """
- self.has_move=False
- self.base.moveend(ev)
-
- def restore(self):
- """
- Restore the roughness for this layer.
- """
- self.y = self.save_y
- self.x = self.save_x
-
- def move(self, x, y, ev):
- """
- Process move to a new position, making sure that the move is allowed.
- """
- self.x = x
- self.y = y
- self.has_move = True
- self.base.base.update()
-
- def set_cursor(self, x, y):
- """
- """
- self.move(x, y, None)
- self.update()
-
- def get_params(self):
- """
- """
- params = {}
- params["x"] = self.x
- params["y"] = self.y
- return params
-
- def set_params(self, params):
- """
- """
- center_x = params["x"]
- center_y = params["y"]
- self.update(center_x=center_x, center_y=center_y)
-
-
-class VerticalDoubleLine(_BaseInteractor):
- """
- Draw 2 vertical lines moving in opposite direction and centered on
- a point (PointInteractor)
- """
- def __init__(self, base, axes, color='black', zorder=5, x=0.5,y=0.5,
- center_x=0.0, center_y=0.0):
- """
- """
- _BaseInteractor.__init__(self, base, axes, color=color)
- ## Initialization the class
- self.markers = []
- self.axes = axes
- ## Center coordinates
- self.center_x = center_x
- self.center_y = center_y
- ## defined end points vertical lignes and their saved values
- self.y1 = y + self.center_y
- self.save_y1= self.y1
-
- delta = self.y1 - self.center_y
- self.y2 = self.center_y - delta
- self.save_y2 = self.y2
-
- self.x1 = x + self.center_x
- self.save_x1 = self.x1
-
- delta = self.x1 - self.center_x
- self.x2 = self.center_x - delta
- self.save_x2 = self.x2
- ## save the color of the line
- self.color = color
- ## the height of the rectangle
- self.half_height = math.fabs(y)
- self.save_half_height = math.fabs(y)
- ## the with of the rectangle
- self.half_width = math.fabs(self.x1- self.x2)/2
- self.save_half_width = math.fabs(self.x1- self.x2)/2
- ## Create marker
- try:
- self.right_marker = self.axes.plot([self.x1],[0], linestyle='',
- marker='s', markersize=10,
- color=self.color, alpha=0.6,
- pickradius=5, label="pick",
- # Prefer this to other lines
- zorder=zorder, visible=True)[0]
- except:
- self.right_marker = self.axes.plot([self.x1],[0], linestyle='',
- marker='s', markersize=10,
- color=self.color, alpha=0.6,
- label="pick", visible=True)[0]
- message = "\nTHIS PROTOTYPE NEEDS THE LATEST "
- message += "VERSION OF MATPLOTLIB\n Get the SVN version that"
- message += " is at least as recent as June 1, 2007"
- owner = self.base.base.parent
- wx.PostEvent(owner,
- StatusEvent(status="AnnulusSlicer: %s" % message))
-
- ## define the left and right lines of the rectangle
- self.right_line = self.axes.plot([self.x1, self.x1], [self.y1, self.y2],
- linestyle='-', marker='',
- color=self.color, visible=True)[0]
- self.left_line = self.axes.plot([self.x2, self.x2], [self.y1, self.y2],
- linestyle='-', marker='',
- color=self.color, visible=True)[0]
- ## Flag to determine if the lines have moved
- self.has_move = False
- ## connection the marker and draw the pictures
- self.connect_markers([self.right_marker])
- self.update()
-
- def set_layer(self, n):
- """
- Allow adding plot to the same panel
- :param n: the number of layer
- """
- self.layernum = n
- self.update()
-
- def clear(self):
- """
- Clear this slicer and its markers
- """
- self.clear_markers()
- try:
- self.right_marker.remove()
- self.right_line.remove()
- self.left_line.remove()
- except:
- # Old version of matplotlib
- for item in range(len(self.axes.lines)):
- del self.axes.lines[0]
-
- def update(self, x1=None, x2=None, y1=None, y2=None,width=None,
- height=None, center=None):
- """
- Draw the new roughness on the graph.
- :param x1: new maximum value of x coordinates
- :param x2: new minimum value of x coordinates
- :param y1: new maximum value of y coordinates
- :param y2: new minimum value of y coordinates
- :param width: is the width of the new rectangle
- :param height: is the height of the new rectangle
- :param center: provided x, y coordinates of the center point
- """
- ## save the new height, witdh of the rectangle if given as a param
- if width != None:
- self.half_width = width
- if height != None:
- self.half_height = height
- ## If new center coordinates are given draw the rectangle
- ##given these value
- if center != None:
- self.center_x = center.x
- self.center_y = center.y
- self.x1 = self.half_width + self.center_x
- self.x2= -self.half_width + self.center_x
- self.y1 = self.half_height + self.center_y
- self.y2= -self.half_height + self.center_y
-
- self.right_marker.set(xdata=[self.x1], ydata=[self.center_y])
- self.right_line.set(xdata=[self.x1, self.x1],
- ydata=[self.y1, self.y2])
- self.left_line.set(xdata=[self.x2, self.x2],
- ydata=[self.y1, self.y2])
- return
- ## if x1, y1, y2, y3 are given draw the rectangle with this value
- if x1 != None:
- self.x1 = x1
- if x2 != None:
- self.x2 = x2
- if y1 != None:
- self.y1 = y1
- if y2 != None:
- self.y2 = y2
- ## Draw 2 vertical lines and a marker
- self.right_marker.set(xdata=[self.x1], ydata=[self.center_y])
- self.right_line.set(xdata=[self.x1, self.x1], ydata=[self.y1, self.y2])
- self.left_line.set(xdata=[self.x2, self.x2], ydata=[self.y1, self.y2])
-
- def save(self, ev):
- """
- Remember the roughness for this layer and the next so that we
- can restore on Esc.
- """
- self.save_x2 = self.x2
- self.save_y2 = self.y2
- self.save_x1 = self.x1
- self.save_y1 = self.y1
- self.save_half_height = self.half_height
- self.save_half_width = self.half_width
- self.base.freeze_axes()
-
- def moveend(self, ev):
- """
- After a dragging motion reset the flag self.has_move to False
- """
- self.has_move = False
- self.base.moveend(ev)
-
- def restore(self):
- """
- Restore the roughness for this layer.
- """
- self.y2 = self.save_y2
- self.x2 = self.save_x2
- self.y1 = self.save_y1
- self.x1 = self.save_x1
- self.half_height = self.save_half_height
- self.half_width = self.save_half_width
-
- def move(self, x, y, ev):
- """
- Process move to a new position, making sure that the move is allowed.
- """
- self.x1 = x
- delta = self.x1 - self.center_x
- self.x2 = self.center_x - delta
- self.half_width = math.fabs(self.x1 - self.x2)/2
- self.has_move = True
- self.base.base.update()
-
- def set_cursor(self, x, y):
- """
- Update the figure given x and y
- """
- self.move(x, y, None)
- self.update()
-
- def get_params(self):
- """
- Store a copy of values of parameters of the slicer into a dictionary.
- @return params: the dictionary created
- """
- params = {}
- params["x"] = self.x1
- params["y"] = self.y1
- return params
-
- def set_params(self, params):
- """
- Receive a dictionary and reset the slicer with values contained
- in the values of the dictionary.
- @param params: a dictionary containing name of slicer parameters and
- values the user assigned to the slicer.
- """
- x = params["x"]
- y = params["y"]
- self.update(x=x, y=y, center_x=None, center_y=None)
-
-
-class HorizontalDoubleLine(_BaseInteractor):
- """
- Select an annulus through a 2D plot
- """
- def __init__(self, base, axes, color='black', zorder=5, x=0.5, y=0.5,
- center_x=0.0, center_y=0.0):
-
- _BaseInteractor.__init__(self, base, axes, color=color)
- ## Initialization the class
- self.markers = []
- self.axes = axes
- ## Center coordinates
- self.center_x = center_x
- self.center_y = center_y
- self.y1 = y + self.center_y
- self.save_y1 = self.y1
- delta = self.y1 - self.center_y
- self.y2 = self.center_y - delta
- self.save_y2 = self.y2
- self.x1 = x + self.center_x
- self.save_x1 = self.x1
- delta = self.x1 - self.center_x
- self.x2 = self.center_x - delta
- self.save_x2 = self.x2
- self.color = color
- self.half_height= math.fabs(y)
- self.save_half_height = math.fabs(y)
- self.half_width = math.fabs(x)
- self.save_half_width = math.fabs(x)
- try:
- self.top_marker = self.axes.plot([0], [self.y1], linestyle='',
- marker='s', markersize=10,
- color=self.color, alpha=0.6,
- pickradius=5, label="pick",
- # Prefer this to other lines
- zorder=zorder, visible=True)[0]
- except:
- self.top_marker = self.axes.plot([0], [self.y1], linestyle='',
- marker='s', markersize=10,
- color=self.color, alpha=0.6,
- label="pick", visible=True)[0]
- message = "\nTHIS PROTOTYPE NEEDS THE LATEST VERSION "
- message += "OF MATPLOTLIB\n Get the SVN version "
- message += "that is at least as recent as June 1, 2007"
- owner = self.base.base.parent
- wx.PostEvent(owner,
- StatusEvent(status="AnnulusSlicer: %s" % message))
-
- # Define 2 horizotnal lines
- self.top_line = self.axes.plot([self.x1, -self.x1], [self.y1, self.y1],
- linestyle='-', marker='',
- color=self.color, visible=True)[0]
- self.bottom_line = self.axes.plot([self.x1, -self.x1],
- [self.y2, self.y2],
- linestyle='-', marker='',
- color=self.color, visible=True)[0]
- ## Flag to determine if the lines have moved
- self.has_move = False
- ## connection the marker and draw the pictures
- self.connect_markers([self.top_marker])
- self.update()
-
- def set_layer(self, n):
- """
- Allow adding plot to the same panel
- @param n: the number of layer
- """
- self.layernum = n
- self.update()
-
- def clear(self):
- """
- Clear this figure and its markers
- """
- self.clear_markers()
- try:
- self.top_marker.remove()
- self.bottom_line.remove()
- self.top_line.remove()
- except:
- # Old version of matplotlib
- for item in range(len(self.axes.lines)):
- del self.axes.lines[0]
-
- def update(self, x1=None, x2=None, y1=None, y2=None,
- width=None, height=None, center=None):
- """
- Draw the new roughness on the graph.
- :param x1: new maximum value of x coordinates
- :param x2: new minimum value of x coordinates
- :param y1: new maximum value of y coordinates
- :param y2: new minimum value of y coordinates
- :param width: is the width of the new rectangle
- :param height: is the height of the new rectangle
- :param center: provided x, y coordinates of the center point
- """
- ## save the new height, witdh of the rectangle if given as a param
- if width != None:
- self.half_width = width
- if height!= None:
- self.half_height = height
- ## If new center coordinates are given draw the rectangle
- ##given these value
- if center != None:
- self.center_x = center.x
- self.center_y = center.y
- self.x1 = self.half_width + self.center_x
- self.x2 = -self.half_width + self.center_x
-
- self.y1 = self.half_height + self.center_y
- self.y2 = -self.half_height + self.center_y
-
- self.top_marker.set(xdata=[self.center_x], ydata=[self.y1])
- self.top_line.set(xdata=[self.x1, self.x2],
- ydata=[self.y1, self.y1])
- self.bottom_line.set(xdata=[self.x1, self.x2],
- ydata=[self.y2, self.y2])
- return
- ## if x1, y1, y2, y3 are given draw the rectangle with this value
- if x1 != None:
- self.x1 = x1
- if x2 != None:
- self.x2 = x2
- if y1 != None:
- self.y1 = y1
- if y2 != None:
- self.y2 = y2
- ## Draw 2 vertical lines and a marker
- self.top_marker.set(xdata=[self.center_x], ydata=[self.y1])
- self.top_line.set(xdata=[self.x1, self.x2], ydata=[self.y1, self.y1])
- self.bottom_line.set(xdata=[self.x1, self.x2], ydata=[self.y2, self.y2])
-
- def save(self, ev):
- """
- Remember the roughness for this layer and the next so that we
- can restore on Esc.
- """
- self.save_x2 = self.x2
- self.save_y2 = self.y2
- self.save_x1 = self.x1
- self.save_y1 = self.y1
- self.save_half_height = self.half_height
- self.save_half_width = self.half_width
- self.base.freeze_axes()
-
- def moveend(self, ev):
- """
- After a dragging motion reset the flag self.has_move to False
- """
- self.has_move = False
- self.base.moveend(ev)
-
- def restore(self):
- """
- Restore the roughness for this layer.
- """
- self.y2 = self.save_y2
- self.x2 = self.save_x2
- self.y1 = self.save_y1
- self.x1 = self.save_x1
- self.half_height = self.save_half_height
- self.half_width = self.save_half_width
-
- def move(self, x, y, ev):
- """
- Process move to a new position, making sure that the move is allowed.
- """
- self.y1 = y
- delta = self.y1 - self.center_y
- self.y2 = self.center_y - delta
- self.half_height = math.fabs(self.y1) - self.center_y
- self.has_move = True
- self.base.base.update()
-
- def set_cursor(self, x, y):
- """
- Update the figure given x and y
- """
- self.move(x, y, None)
- self.update()
-
- def get_params(self):
- """
- Store a copy of values of parameters of the slicer into a dictionary.
- :return params: the dictionary created
- """
- params = {}
- params["x"] = self.x
- params["y"] = self.y
- return params
-
- def set_params(self, params):
- """
- Receive a dictionary and reset the slicer with values contained
- in the values of the dictionary.
- :param params: a dictionary containing name of slicer parameters and
- values the user assigned to the slicer.
- """
- x = params["x"]
- y = params["y"]
- self.update(x=x, y=y, center_x=None,center_y=None)
-
-
-
Index: test/guiframe/local_perspectives/plotting/detector_dialog.py
===================================================================
--- test/guiframe/local_perspectives/plotting/detector_dialog.py (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,319 +1,0 @@
-#!/usr/bin/env python
-
-# version
-__id__ = "$Id: aboutdialog.py 1193 2007-05-03 17:29:59Z dmitriy $"
-__revision__ = "$Revision: 1193 $"
-
-import wx
-import sys
-from sans.guiframe.utils import format_number
-from sans.guiframe.events import StatusEvent
-from sans.guiframe.events import NewPlotEvent
-
-import matplotlib
-from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as Canvas
-from matplotlib import pyplot
-from matplotlib import mpl
-from matplotlib import pylab
-#FONT size
-if sys.platform.count("win32") > 0:
- FONT_VARIANT = 0
-else:
- FONT_VARIANT = 1
-
-DEFAULT_CMAP = pylab.cm.jet
-
-class DetectorDialog(wx.Dialog):
- """
- Dialog box to let the user edit detector settings
- """
-
- def __init__(self, parent, id=1, base=None, dpi=None,
- cmap=DEFAULT_CMAP, reset_zmin_ctl = None,
- reset_zmax_ctl = None, *args, **kwds):
- """
- """
- kwds["style"] = wx.DEFAULT_DIALOG_STYLE
- wx.Dialog.__init__(self, parent, id=1, *args, **kwds)
- self.SetWindowVariant(variant=FONT_VARIANT)
- self.parent = base
- self.dpi = dpi
- self.cmap = cmap
- self.reset_zmin_ctl = reset_zmin_ctl
- self.reset_zmax_ctl = reset_zmax_ctl
- self.label_xnpts = wx.StaticText(self, -1, "Detector width in pixels")
- self.label_ynpts = wx.StaticText(self, -1, "Detector Height in pixels")
- self.label_qmax = wx.StaticText(self, -1, "Q max")
- self.label_zmin = wx.StaticText(self, -1,
- "Min amplitude for color map (optional)")
- self.label_zmax = wx.StaticText(self, -1,
- "Max amplitude for color map (optional)")
- self.label_beam = wx.StaticText(self, -1,
- "Beam stop radius in units of q")
- self.xnpts_ctl = wx.StaticText(self, -1, "")
- self.ynpts_ctl = wx.StaticText(self, -1, "")
- self.qmax_ctl = wx.StaticText(self, -1, "")
- self.beam_ctl = wx.StaticText(self, -1, "")
- self.zmin_ctl = wx.TextCtrl(self, -1, size=(60, 20))
- self.zmin_ctl.Bind(wx.EVT_SET_FOCUS, self.onSetFocus)
- self.zmax_ctl = wx.TextCtrl(self, -1, size=(60, 20))
- self.zmax_ctl.Bind(wx.EVT_SET_FOCUS, self.onSetFocus)
- self.static_line_3 = wx.StaticLine(self, -1)
- self.button_Cancel = wx.Button(self, wx.ID_CANCEL, "Cancel")
- self.button_reset = wx.Button(self, wx.NewId(), "Reset")
- self.Bind(wx.EVT_BUTTON, self.resetValues, self.button_reset)
- self.button_OK = wx.Button(self, wx.ID_OK, "OK")
- self.Bind(wx.EVT_BUTTON, self.checkValues, self.button_OK)
- self.__set_properties()
- self.__do_layout()
- self.Fit()
-
- class Event:
- """
- """
- xnpts = 0
- ynpts = 0
- qpax = 0
- beam = 0
- zmin = 0
- zmax = 0
- cmap = None
- sym4 = False
-
- def onSetFocus(self, event):
- """
- Highlight the txtcrtl
- """
- # Get a handle to the TextCtrl
- widget = event.GetEventObject()
- # Select the whole control, after this event resolves
- wx.CallAfter(widget.SetSelection, -1, -1)
-
- def resetValues(self, event):
- """
- reset detector info
- """
- try:
- zmin = self.reset_zmin_ctl
- zmax = self.reset_zmax_ctl
- if zmin == None:
- zmin = ""
- if zmax == None:
- zmax = ""
- self.zmin_ctl.SetValue(str(zmin))
- self.zmax_ctl.SetValue(str(zmax))
- self.cmap = DEFAULT_CMAP
- self.cmap_selector.SetStringSelection("jet")
- self._on_select_cmap(event=None)
- except:
- msg = "error occurs while resetting Detector: %s" % sys.exc_value
- wx.PostEvent(self.parent, StatusEvent(status=msg))
-
- def checkValues(self, event):
- """
- Check the valitidity of zmin and zmax value
- zmax should be a float and zmin less than zmax
- """
- flag = True
- try:
- value = self.zmin_ctl.GetValue()
- #if value and float( value) == 0.0:
- # flag = False
- # wx.PostEvent(self.parent,
- # StatusEvent(status="Enter number greater than zero"))
- # self.zmin_ctl.SetBackgroundColour("pink")
- # self.zmin_ctl.Refresh()
- #else:
- self.zmin_ctl.SetBackgroundColour(wx.WHITE)
- self.zmin_ctl.Refresh()
- except:
- flag = False
- wx.PostEvent(self.parent, StatusEvent(status="Enter float value"))
- self.zmin_ctl.SetBackgroundColour("pink")
- self.zmin_ctl.Refresh()
- try:
- value = self.zmax_ctl.GetValue()
- if value and float(value) == 0.0:
- flag = False
- wx.PostEvent(self.parent,
- StatusEvent(status="Enter number greater than zero"))
- self.zmax_ctl.SetBackgroundColour("pink")
- self.zmax_ctl.Refresh()
- else:
- self.zmax_ctl.SetBackgroundColour(wx.WHITE)
- self.zmax_ctl.Refresh()
- except:
- flag = False
- wx.PostEvent(self.parent, StatusEvent(status="Enter Integer value"))
- self.zmax_ctl.SetBackgroundColour("pink")
- self.zmax_ctl.Refresh()
- if flag:
- event.Skip(True)
-
- def setContent(self, xnpts, ynpts, qmax, beam,
- zmin=None, zmax=None, sym=False):
- """
- received value and displayed them
-
- :param xnpts: the number of point of the x_bins of data
- :param ynpts: the number of point of the y_bins of data
- :param qmax: the maxmimum value of data pixel
- :param beam: the radius of the beam
- :param zmin: the value to get the minimum color
- :param zmax: the value to get the maximum color
- :param sym:
-
- """
- self.xnpts_ctl.SetLabel(str(format_number(xnpts)))
- self.ynpts_ctl.SetLabel(str(format_number(ynpts)))
- self.qmax_ctl.SetLabel(str(format_number(qmax)))
- self.beam_ctl.SetLabel(str(format_number(beam)))
- if zmin != None:
- self.zmin_ctl.SetValue(str(format_number(zmin)))
- if zmax != None:
- self.zmax_ctl.SetValue(str(format_number(zmax)))
-
- def getContent(self):
- """
- return event containing value to reset the detector of a given data
- """
- event = self.Event()
- t_min = self.zmin_ctl.GetValue()
- t_max = self.zmax_ctl.GetValue()
- v_min = None
- v_max = None
- if len(t_min.lstrip()) > 0:
- try:
- v_min = float(t_min)
- except:
- v_min = None
- if len(t_max.lstrip()) > 0:
- try:
- v_max = float(t_max)
- except:
- v_max = None
- event.zmin = v_min
- event.zmax = v_max
- event.cmap = self.cmap
- return event
-
- def __set_properties(self):
- """
- set proprieties of the dialog window
- """
- self.SetTitle("2D Color Map")
- self.SetSize((600, 595))
-
- def __do_layout(self):
- """
- fill the dialog window .
- """
- sizer_main = wx.BoxSizer(wx.VERTICAL)
- sizer_button = wx.BoxSizer(wx.HORIZONTAL)
- sizer_params = wx.GridBagSizer(5, 5)
- sizer_colormap = wx.BoxSizer(wx.VERTICAL)
- sizer_selection = wx.BoxSizer(wx.HORIZONTAL)
-
- iy = 0
- sizer_params.Add(self.label_xnpts, (iy, 0), (1, 1),
- wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
- sizer_params.Add(self.xnpts_ctl, (iy, 1), (1, 1),
- wx.EXPAND|wx.ADJUST_MINSIZE, 0)
- iy += 1
- sizer_params.Add(self.label_ynpts, (iy, 0), (1, 1),
- wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
- sizer_params.Add(self.ynpts_ctl, (iy, 1), (1, 1),
- wx.EXPAND|wx.ADJUST_MINSIZE, 0)
- iy += 1
- sizer_params.Add(self.label_qmax, (iy, 0), (1, 1),
- wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
- sizer_params.Add(self.qmax_ctl, (iy, 1), (1, 1),
- wx.EXPAND|wx.ADJUST_MINSIZE, 0)
- iy += 1
- sizer_params.Add(self.label_beam, (iy, 0), (1, 1),
- wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
- sizer_params.Add(self.beam_ctl, (iy, 1), (1, 1),
- wx.EXPAND|wx.ADJUST_MINSIZE, 0)
- iy += 1
- sizer_params.Add(self.label_zmin, (iy, 0), (1, 1),
- wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
- sizer_params.Add(self.zmin_ctl, (iy, 1), (1, 1),
- wx.EXPAND|wx.ADJUST_MINSIZE, 0)
- iy += 1
- sizer_params.Add(self.label_zmax, (iy, 0), (1, 1),
- wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
- sizer_params.Add(self.zmax_ctl, (iy, 1), (1, 1),
- wx.EXPAND|wx.ADJUST_MINSIZE, 0)
- iy += 1
- self.fig = mpl.figure.Figure(dpi=self.dpi, figsize=(4, 1))
- self.ax1 = self.fig.add_axes([0.05, 0.65, 0.9, 0.15])
- self.norm = mpl.colors.Normalize(vmin=0, vmax=100)
- self.cb1 = mpl.colorbar.ColorbarBase(self.ax1, cmap=self.cmap,
- norm= self.norm,
- orientation='horizontal')
- self.cb1.set_label('Detector Colors')
- self.canvas = Canvas(self, -1, self.fig)
- sizer_colormap.Add(self.canvas, 0, wx.LEFT | wx.EXPAND,5)
- self.cmap_selector = wx.ComboBox(self, -1)
- self.cmap_selector.SetValue(str(self.cmap.name))
- maps = sorted(m for m in pylab.cm.datad if not m.endswith("_r"))
-
- for i, m in enumerate(maps):
- self.cmap_selector.Append(str(m), pylab.get_cmap(m))
-
- wx.EVT_COMBOBOX(self.cmap_selector, -1, self._on_select_cmap)
- sizer_selection.Add(wx.StaticText(self, -1,"Select Cmap: "), 0,
- wx.LEFT|wx.ADJUST_MINSIZE, 5)
- sizer_selection.Add(self.cmap_selector, 0, wx.EXPAND|wx.ALL, 10)
- sizer_main.Add(sizer_params, 0, wx.EXPAND|wx.ALL, 10)
- sizer_main.Add(sizer_selection, 0, wx.EXPAND|wx.ALL, 10)
- sizer_main.Add(sizer_colormap, 1, wx.EXPAND|wx.ALL, 10)
- sizer_main.Add(self.static_line_3, 0, wx.EXPAND, 0)
- sizer_button.Add(self.button_reset, 0, wx.LEFT|wx.ADJUST_MINSIZE, 100)
- sizer_button.Add(self.button_OK, 0, wx.LEFT|wx.ADJUST_MINSIZE, 10)
- sizer_button.Add(self.button_Cancel, 0,
- wx.LEFT|wx.RIGHT|wx.ADJUST_MINSIZE, 10)
- sizer_main.Add(sizer_button, 0, wx.EXPAND|wx.BOTTOM|wx.TOP, 10)
- self.SetAutoLayout(True)
- self.SetSizer(sizer_main)
- self.Layout()
- self.Centre()
- # end wxGlade
-
- def _on_select_cmap(self, event):
- """
- display a new cmap
- """
- cmap_name = self.cmap_selector.GetCurrentSelection()
- current_cmap = self.cmap_selector.GetClientData(cmap_name)
- self.cmap = current_cmap
- self.cb1 = mpl.colorbar.ColorbarBase(self.ax1, cmap=self.cmap,
- norm=self.norm, orientation='horizontal')
- self.canvas.draw()
-
-
-# end of class DialogAbout
-
-##### testing code ############################################################
-class MyApp(wx.App):
- def OnInit(self):
- wx.InitAllImageHandlers()
- dialog = DetectorDialog(None, -1, "")
- self.SetTopWindow(dialog)
- dialog.setContent(xnpts=128, ynpts=128, qmax=20,
- beam=20, zmin=2, zmax=60, sym=False)
- print dialog.ShowModal()
- evt = dialog.getContent()
- if hasattr(evt, "npts"):
- print "number of point: ", evt.npts
- if hasattr(evt,"qmax"):
- print "qmax: ", evt.qmax
- dialog.Destroy()
- return 1
-
-# end of class MyApp
-
-if __name__ == "__main__":
- app = MyApp(0)
- app.MainLoop()
-
Index: test/guiframe/local_perspectives/plotting/help_panel.py
===================================================================
--- test/guiframe/local_perspectives/plotting/help_panel.py (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,111 +1,0 @@
-#!/usr/bin/python
-"""
-Help panel for plotting
-"""
-import os
-import wx
-import wx.html as html
-from wx.lib.splitter import MultiSplitterWindow
-from sans.guiframe import get_media_path
-
-
-class HelpWindow(wx.Frame):
- """
- """
- def __init__(self, parent, title='Plotting Help', pageToOpen=None):
- wx.Frame.__init__(self, parent, title, size=(700, 450))
- """
- contains help info
- """
- splitter = MultiSplitterWindow(self, style=wx.SP_LIVE_UPDATE)
- rpanel = wx.Panel(splitter, -1)
- lpanel = wx.Panel(splitter, -1, style=wx.BORDER_SUNKEN)
-
- vbox = wx.BoxSizer(wx.VERTICAL)
- header = wx.Panel(rpanel, -1)
- header.SetBackgroundColour('#6666FF')
- header.SetForegroundColour('WHITE')
- hbox = wx.BoxSizer(wx.HORIZONTAL)
- st = wx.StaticText(header, -1, 'Contents', (5, 5))
- font = st.GetFont()
- font.SetPointSize(10)
- st.SetFont(font)
- hbox.Add(st, 1, wx.TOP | wx.BOTTOM | wx.LEFT, 5)
- header.SetSizer(hbox)
- vbox.Add(header, 0, wx.EXPAND)
-
- vboxl = wx.BoxSizer(wx.VERTICAL)
- headerl = wx.Panel(lpanel, -1, size=(-1, 20))
-
- headerl.SetBackgroundColour('#6666FF')
- headerl.SetForegroundColour('WHITE')
- hboxl = wx.BoxSizer(wx.HORIZONTAL)
- lst = wx.StaticText(headerl, -1, 'Menu', (5, 5))
- fontl = lst.GetFont()
- fontl.SetPointSize(10)
- lst.SetFont(fontl)
- hboxl.Add(lst, 1, wx.TOP | wx.BOTTOM | wx.LEFT, 5)
- headerl.SetSizer(hboxl)
- vboxl.Add(headerl, 0, wx.EXPAND)
- self.lhelp = html.HtmlWindow(lpanel, -1, style=wx.NO_BORDER)
- self.rhelp = html.HtmlWindow(rpanel, -1, style=wx.NO_BORDER,
- size=(500,-1))
-
- self.path = get_media_path(media='media')
-
- page1 = """
-
- Select topic on Menu
-
- """
- self.rhelp.SetPage(page1)
- page = """
-
-
-
- """
-
- self.lhelp.SetPage(page)
- self.lhelp.Bind(wx.html.EVT_HTML_LINK_CLICKED, self.OnLinkClicked)
-
- vbox.Add(self.rhelp, 1, wx.EXPAND)
- vboxl.Add(self.lhelp, 1, wx.EXPAND)
- rpanel.SetSizer(vbox)
- lpanel.SetSizer(vboxl)
- lpanel.SetFocus()
-
- vbox1 = wx.BoxSizer(wx.HORIZONTAL)
- vbox1.Add(splitter, 1, wx.EXPAND)
- splitter.AppendWindow(lpanel, 200)
- splitter.AppendWindow(rpanel)
- self.SetSizer(vbox1)
-
- self.Centre()
- self.Show(True)
-
- def OnLinkClicked(self, event):
- """
- Function to diplay html page related to the hyperlinktext selected
- """
- link = event.GetLinkInfo().GetHref()
- link = os.path.join(self.path, link)
- self.rhelp.LoadPage(link)
-
-
-class ViewApp(wx.App):
- def OnInit(self):
- frame = HelpWindow(None, -1, 'HelpWindow')
- frame.Show(True)
- self.SetTopWindow(frame)
- return True
-
-if __name__ == "__main__":
- app = ViewApp(0)
- app.MainLoop()
Index: test/guiframe/local_perspectives/plotting/masking.py
===================================================================
--- test/guiframe/local_perspectives/plotting/masking.py (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,588 +1,0 @@
-
-################################################################################
-#This software was developed by the University of Tennessee as part of the
-#Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
-#project funded by the US National Science Foundation.
-#
-#If you use DANSE applications to do scientific research that leads to
-#publication, we ask that you acknowledge the use of the software with the
-#following sentence:
-#
-#This work benefited from DANSE software developed under NSF award DMR-0520547.
-#
-#copyright 2008, University of Tennessee
-################################################################################
-
-
-##Todo: cleaning up, improving the maskplotpanel initialization, and testing.
-import wx
-import sys
-import pylab
-import math
-import copy
-import numpy
-from danse.common.plottools.PlotPanel import PlotPanel
-from danse.common.plottools.plottables import Graph
-from binder import BindArtist
-from sans.guiframe.dataFitting import Data2D
-from boxMask import BoxMask
-from sectorMask import SectorMask
-from sans.guiframe.events import SlicerEvent
-from sans.guiframe.events import StatusEvent
-(InternalEvent, EVT_INTERNAL) = wx.lib.newevent.NewEvent()
-
-DEFAULT_CMAP = pylab.cm.jet
-_BOX_WIDTH = 76
-_SCALE = 1e-6
-_STATICBOX_WIDTH = 380
-PANEL_SIZE = 420
-#SLD panel size
-if sys.platform.count("win32") > 0:
- FONT_VARIANT = 0
-else:
- FONT_VARIANT = 1
-
-
-class MaskPanel(wx.Dialog):
- """
- Provides the Mask Editor GUI.
- """
- ## Internal nickname for the window, used by the AUI manager
- window_name = "Mask Editor"
- ## Name to appear on the window title bar
- window_caption = "Mask Editor"
- ## Flag to tell the AUI manager to put this panel in the center pane
- CENTER_PANE = True
- def __init__(self, parent=None, base=None,
- data=None, id=-1, *args, **kwds):
- kwds["style"] = wx.DEFAULT_DIALOG_STYLE
- kwds["size"] = wx.Size(_STATICBOX_WIDTH * 2, PANEL_SIZE)
- wx.Dialog.__init__(self, parent, id=id, *args, **kwds)
-
- if data != None:
- #Font size
- kwds = []
- self.SetWindowVariant(variant=FONT_VARIANT)
- self.SetTitle("Mask Editor for " + data.name)
- self.parent = base
- self.data = data
- self.str = self.data.__str__()
- ## mask for 2D
- self.mask = data.mask
- self.default_mask = copy.deepcopy(data.mask)
- ## masked data from GUI
- self.slicer_mask = None
- self.slicer = None
- self.slicer_z = 5
- self.data.interactive = True
- ## when 2 data have the same id override the 1 st plotted
- self.name = self.data.name
- # Panel for 2D plot
- self.plotpanel = Maskplotpanel(self, -1,
- style=wx.TRANSPARENT_WINDOW)
- self.cmap = DEFAULT_CMAP
- ## Create Artist and bind it
- self.subplot = self.plotpanel.subplot
- self.connect = BindArtist(self.subplot.figure)
- self._setup_layout()
- self.newplot = Data2D(image=self.data.data)
- self.newplot.setValues(self.data)
- self.plotpanel.add_image(self.newplot)
- self._update_mask(self.mask)
- self.Centre()
- self.Layout()
- # bind evt_close to _draw in fitpage
- self.Bind(wx.EVT_CLOSE, self.OnClose)
-
- def ShowMessage(self, msg=''):
- """
- Show error message when mask covers whole data area
- """
- mssg = 'Erase, redraw or clear the mask. \n\r'
- mssg += 'The data range can not be completely masked... \n\r'
- mssg += msg
- wx.MessageBox(mssg, 'Error', wx.OK | wx.ICON_ERROR)
-
- def _setup_layout(self):
- """
- Set up the layout
- """
- shape = "Select a Shape for Masking:"
- # panel
- sizer = wx.GridBagSizer(10, 10)
- #---------inputs----------------
- shape_txt = wx.StaticText(self, -1, shape)
- sizer.Add(shape_txt, (1, 1), flag=wx.TOP|wx.LEFT|wx.BOTTOM, border=5)
- self.innersector_rb = wx.RadioButton(self, -1, "Double Wings")
- self.Bind(wx.EVT_RADIOBUTTON, self.onInnerSectorMask,
- id=self.innersector_rb.GetId())
- sizer.Add(self.innersector_rb, (2, 1),
- flag=wx.RIGHT|wx.BOTTOM, border=5)
- self.innercircle_rb = wx.RadioButton(self, -1, "Circular Disk")
- self.Bind(wx.EVT_RADIOBUTTON, self.onInnerRingMask,
- id=self.innercircle_rb.GetId())
- sizer.Add(self.innercircle_rb, (3, 1),
- flag=wx.RIGHT|wx.BOTTOM, border=5)
-
- self.innerbox_rb = wx.RadioButton(self, -1, "Rectangular Disk")
- self.Bind(wx.EVT_RADIOBUTTON, self.onInnerBoxMask,
- id=self.innerbox_rb.GetId())
- sizer.Add(self.innerbox_rb, (4, 1), flag=wx.RIGHT|wx.BOTTOM, border=5)
-
- self.outersector_rb = wx.RadioButton(self, -1, "Double Wing Window")
- self.Bind(wx.EVT_RADIOBUTTON, self.onOuterSectorMask,
- id=self.outersector_rb.GetId())
- sizer.Add(self.outersector_rb, (5, 1),
- flag=wx.RIGHT|wx.BOTTOM, border=5)
-
- #outersector_y_txt = wx.StaticText(self, -1, 'Outer Sector')
- self.outercircle_rb = wx.RadioButton(self, -1, "Circular Window")
- self.Bind(wx.EVT_RADIOBUTTON, self.onOuterRingMask,
- id=self.outercircle_rb.GetId())
- sizer.Add(self.outercircle_rb, (6, 1),
- flag=wx.RIGHT|wx.BOTTOM, border=5)
- #outerbox_txt = wx.StaticText(self, -1, 'Outer Box')
- self.outerbox_rb = wx.RadioButton(self, -1, "Rectangular Window")
- self.Bind(wx.EVT_RADIOBUTTON, self.onOuterBoxMask,
- id=self.outerbox_rb.GetId())
- sizer.Add(self.outerbox_rb, (7, 1), flag=wx.RIGHT|wx.BOTTOM, border=5)
- self.innercircle_rb.SetValue(False)
- self.outercircle_rb.SetValue(False)
- self.innerbox_rb.SetValue(False)
- self.outerbox_rb.SetValue(False)
- self.innersector_rb.SetValue(False)
- self.outersector_rb.SetValue(False)
- sizer.Add(self.plotpanel, (0, 2), (13, 13),
- wx.EXPAND|wx.LEFT|wx.RIGHT, 15)
-
- #-----Buttons------------1
- id_button = wx.NewId()
- button_add = wx.Button(self, id_button, "Add")
- button_add.SetToolTipString("Add the mask drawn.")
- button_add.Bind(wx.EVT_BUTTON, self.onAddMask, id=button_add.GetId())
- sizer.Add(button_add, (13, 7))
- id_button = wx.NewId()
- button_erase = wx.Button(self, id_button, "Erase")
- button_erase.SetToolTipString("Erase the mask drawn.")
- button_erase.Bind(wx.EVT_BUTTON, self.onEraseMask,
- id=button_erase.GetId())
- sizer.Add(button_erase, (13, 8))
- id_button = wx.NewId()
- button_reset = wx.Button(self, id_button, "Reset")
- button_reset.SetToolTipString("Reset the mask.")
- button_reset.Bind(wx.EVT_BUTTON, self.onResetMask,
- id=button_reset.GetId())
- sizer.Add(button_reset, (13, 9), flag=wx.RIGHT|wx.BOTTOM, border=15)
- id_button = wx.NewId()
- button_reset = wx.Button(self, id_button, "Clear")
- button_reset.SetToolTipString("Clear all mask.")
- button_reset.Bind(wx.EVT_BUTTON, self.onClearMask,
- id=button_reset.GetId())
- sizer.Add(button_reset, (13, 10), flag=wx.RIGHT|wx.BOTTOM, border=15)
- sizer.AddGrowableCol(3)
- sizer.AddGrowableRow(2)
- self.SetSizerAndFit(sizer)
- self.Centre()
- self.Show(True)
-
- def onInnerBoxMask(self, event=None):
- """
- Call Draw Box Slicer and get mask inside of the box
- """
- #get ready for next evt
- event.Skip()
- #from boxMask import BoxMask
- if event != None:
- self.onClearSlicer(event)
- self.slicer_z += 1
- self.slicer = BoxMask(self, self.subplot,
- zorder=self.slicer_z, side=True)
- self.subplot.set_ylim(self.data.ymin, self.data.ymax)
- self.subplot.set_xlim(self.data.xmin, self.data.xmax)
- self.update()
- self.slicer_mask = self.slicer.update()
-
- def onOuterBoxMask(self, event=None):
- """
- Call Draw Box Slicer and get mask outside of the box
- """
- event.Skip()
- #from boxMask import BoxMask
- if event != None:
- self.onClearSlicer(event)
- self.slicer_z += 1
- self.slicer = BoxMask(self, self.subplot,
- zorder=self.slicer_z, side=False)
- self.subplot.set_ylim(self.data.ymin, self.data.ymax)
- self.subplot.set_xlim(self.data.xmin, self.data.xmax)
- self.update()
- self.slicer_mask = self.slicer.update()
-
- def onInnerSectorMask(self, event=None):
- """
- Call Draw Sector Slicer and get mask inside of the sector
- """
- event.Skip()
- from sectorMask import SectorMask
- if event != None:
- self.onClearSlicer(event)
- self.slicer_z += 1
- self.slicer = SectorMask(self, self.subplot,
- zorder=self.slicer_z, side=True)
- self.subplot.set_ylim(self.data.ymin, self.data.ymax)
- self.subplot.set_xlim(self.data.xmin, self.data.xmax)
- self.update()
- self.slicer_mask = self.slicer.update()
-
- def onOuterSectorMask(self,event=None):
- """
- Call Draw Sector Slicer and get mask outside of the sector
- """
- event.Skip()
- from sectorMask import SectorMask
- if event != None:
- self.onClearSlicer(event)
- self.slicer_z += 1
- self.slicer = SectorMask(self, self.subplot,
- zorder=self.slicer_z, side=False)
- self.subplot.set_ylim(self.data.ymin, self.data.ymax)
- self.subplot.set_xlim(self.data.xmin, self.data.xmax)
- self.update()
- self.slicer_mask = self.slicer.update()
-
- def onInnerRingMask(self, event=None):
- """
- Perform inner circular cut on Phi and draw circular slicer
- """
- event.Skip()
- from AnnulusSlicer import CircularMask
- if event != None:
- self.onClearSlicer(event)
- self.slicer_z += 1
- self.slicer = CircularMask(self, self.subplot,
- zorder=self.slicer_z, side=True)
- self.subplot.set_ylim(self.data.ymin, self.data.ymax)
- self.subplot.set_xlim(self.data.xmin, self.data.xmax)
- self.update()
- self.slicer_mask = self.slicer.update()
-
- def onOuterRingMask(self, event=None):
- """
- Perform outer circular cut on Phi and draw circular slicer
- """
- event.Skip()
- from AnnulusSlicer import CircularMask
- if event != None:
- self.onClearSlicer(event)
- self.slicer_z += 1
- self.slicer = CircularMask(self,self.subplot,
- zorder=self.slicer_z, side=False)
- self.subplot.set_ylim(self.data.ymin, self.data.ymax)
- self.subplot.set_xlim(self.data.xmin, self.data.xmax)
- self.update()
- self.slicer_mask = self.slicer.update()
-
- def onAddMask(self, event):
- """
- Add new mask to old mask
- """
- if not self.slicer == None:
- data = Data2D()
- data = self.data
- self.slicer_mask = self.slicer.update()
- data.mask = self.data.mask & self.slicer_mask
- self._check_display_mask(data.mask, event)
-
- def _check_display_mask(self, mask, event):
- """
- check if the mask valid and update the plot
-
- :param mask: mask data
- """
- ## Redraw the current image
- self._update_mask(mask)
-
- def onEraseMask(self, event):
- """
- Erase new mask from old mask
- """
- if not self.slicer==None:
- self.slicer_mask = self.slicer.update()
- mask = self.data.mask
- mask[self.slicer_mask==False] = True
- self._check_display_mask(mask, event)
-
- def onResetMask(self, event):
- """
- Reset mask to the original mask
- """
- self.slicer_z += 1
- self.slicer = BoxMask(self, self.subplot,
- zorder=self.slicer_z, side=True)
- self.subplot.set_ylim(self.data.ymin, self.data.ymax)
- self.subplot.set_xlim(self.data.xmin, self.data.xmax)
- mask = copy.deepcopy(self.default_mask)
- self.data.mask = mask
- # update mask plot
- self._check_display_mask(mask, event)
-
- def onClearMask(self, event):
- """
- Clear mask
- """
- self.slicer_z += 1
- self.slicer = BoxMask(self, self.subplot,
- zorder=self.slicer_z, side=True)
- self.subplot.set_ylim(self.data.ymin, self.data.ymax)
- self.subplot.set_xlim(self.data.xmin, self.data.xmax)
- #mask = copy.deepcopy(self.default_mask)
- mask = numpy.ones(len(self.data.mask), dtype=bool)
- self.data.mask = mask
- # update mask plot
- self._check_display_mask(mask, event)
-
- def onClearSlicer(self, event):
- """
- Clear the slicer on the plot
- """
- if not self.slicer == None:
- self.slicer.clear()
- self.subplot.figure.canvas.draw()
- self.slicer = None
-
- def _setSlicer(self):
- """
- Clear the previous slicer and create a new one.Post an internal
- event.
-
- :param slicer: slicer class to create
- """
- ## Clear current slicer
- if not self.slicer == None:
- self.slicer.clear()
- ## Create a new slicer
- self.slicer_z += 1
- self.slicer = slicer(self, self.subplot, zorder=self.slicer_z)
- self.subplot.set_ylim(self.data2D.ymin, self.data2D.ymax)
- self.subplot.set_xlim(self.data2D.xmin, self.data2D.xmax)
- ## Draw slicer
- self.update()
- self.slicer.update()
- msg = "Plotter2D._setSlicer %s"%self.slicer.__class__.__name__
- wx.PostEvent(self.parent, StatusEvent(status=msg))
- # Post slicer event
- event = self._getEmptySlicerEvent()
- event.type = self.slicer.__class__.__name__
- event.obj_class = self.slicer.__class__
- event.params = self.slicer.get_params()
- wx.PostEvent(self, event)
-
- def update(self, draw=True):
- """
- Respond to changes in the model by recalculating the
- profiles and resetting the widgets.
- """
- self.plotpanel.draw()
-
- def _set_mask(self, mask):
- """
- Set mask
- """
- self.data.mask = mask
-
- def _update_mask(self,mask):
- """
- Respond to changes in masking
- """
- # the case of liitle numbers of True points
- if (len(mask[mask]) < 10 and self.data != None):
- self.ShowMessage()
- mask = copy.deepcopy(self.mask)
- self.data.mask = mask
- else:
- self.mask = mask
- # make temperary data to plot
- temp_mask = numpy.zeros(len(mask))
- temp_data = copy.deepcopy(self.data)
- # temp_data default is None
- # This method is to distinguish between masked point and data point = 0.
- temp_mask = temp_mask/temp_mask
- temp_mask[mask] = temp_data.data[mask]
- # set temp_data value for self.mask==True, else still None
- #temp_mask[mask] = temp_data[mask]
- temp_data.data[mask==False] = temp_mask[mask==False]
- self.plotpanel.clear()
- if self.slicer != None:
- self.slicer.clear()
- self.slicer = None
- # Post slicer None event
- event = self._getEmptySlicerEvent()
- wx.PostEvent(self, event)
-
- ##use this method
- #set zmax and zmin to plot: Fix it w/ data.
- if self.plotpanel.scale == 'log':
- zmax = math.log(max(self.data.data[self.data.data>0]))
- zmin = math.log(min(self.data.data[self.data.data>0]))
- else:
- zmax = max(self.data.data[self.data.data>0])
- zmin = min(self.data.data[self.data.data>0])
- #plot
- plot = self.plotpanel.image(data=temp_mask,
- qx_data=self.data.qx_data,
- qy_data=self.data.qy_data,
- xmin=self.data.xmin,
- xmax=self.data.xmax,
- ymin=self.data.ymin,
- ymax=self.data.ymax,
- zmin=zmin,
- zmax=zmax,
- cmap=self.cmap,
- color=0, symbol=0, label=self.data.name)
- # axis labels
- self.plotpanel.axes[0].set_xlabel('$\\rm{Q}_{x}(A^{-1})$')
- self.plotpanel.axes[0].set_ylabel('$\\rm{Q}_{y}(A^{-1})$')
- self.plotpanel.render()
- self.plotpanel.subplot.figure.canvas.draw_idle()
-
- def _getEmptySlicerEvent(self):
- """
- create an empty slicervent
- """
- self.innerbox_rb.SetValue(False)
- self.outerbox_rb.SetValue(False)
- self.innersector_rb.SetValue(False)
- self.outersector_rb.SetValue(False)
- self.innercircle_rb.SetValue(False)
- self.outercircle_rb.SetValue(False)
- return SlicerEvent(type=None,
- params=None,
- obj_class=None)
-
- def _draw_model(self, event):
- """
- on_close, update the model2d plot
- """
- pass
-
- def freeze_axes(self):
- """
- freeze axes
- """
- self.plotpanel.axes_frozen = True
-
- def thaw_axes(self):
- """
- thaw axes
- """
- self.plotpanel.axes_frozen = False
-
- def onMouseMotion(self, event):
- """
- onMotion event
- """
- pass
-
- def onWheel(self, event):
- """
- on wheel event
- """
- pass
-
- def OnClose(self, event):
- """
- """
- self.parent._draw_masked_model(event)
-
-class Maskplotpanel(PlotPanel):
- """
- """
- def __init__(self, parent, id=-1, color=None, dpi=None, **kwargs):
- """
- """
- PlotPanel.__init__(self, parent, id=id, color=color, dpi=dpi, **kwargs)
-
- # Keep track of the parent Frame
- self.parent = parent
- # Internal list of plottable names (because graph
- # doesn't have a dictionary of handles for the plottables)
- self.plots = {}
- self.graph = Graph()
-
- def add_toolbar(self):
- """
- Add toolbar
- """
- # Not implemented
- pass
- def on_set_focus(self, event):
- """
- send to the parenet the current panel on focus
- """
- #change the panel background
- #self.SetColor((170, 202, 255))
- self.draw()
-
- def add_image(self, plot):
- """
- Add Image
- """
- self.plots[plot.name] = plot
- #init graph
- self.gaph = Graph()
- #add plot
- self.graph.add(plot)
- #add axes
- self.graph.xaxis('\\rm{Q}_{x} ', 'A^{-1}')
- self.graph.yaxis('\\rm{Q}_{y} ', 'A^{-1}')
- #draw
- self.graph.render(self)
- self.subplot.figure.canvas.draw_idle()
-
- def onMouseMotion(self, event):
- """
- Disable dragging 2D image
- """
- pass
-
- def onContextMenu(self, event):
- """
- Default context menu for a plot panel
- """
- # Slicer plot popup menu
- slicerpop = wx.Menu()
-
- id_cm = wx.NewId()
- slicerpop.Append(id_cm, '&Toggle Linear/Log scale')
- wx.EVT_MENU(self, id_cm, self._onToggleScale)
-
- pos = event.GetPosition()
- pos = self.ScreenToClient(pos)
- self.PopupMenu(slicerpop, pos)
-
-class ViewerFrame(wx.Frame):
- """
- Add comment
- """
- def __init__(self, parent, id, title):
- """
- comment
- :param parent: parent panel/container
- """
- # Initialize the Frame object
- wx.Frame.__init__(self, parent, id, title,
- wx.DefaultPosition, wx.Size(950, 850))
- # Panel for 1D plot
- self.plotpanel = Maskplotpanel(self, -1, style=wx.RAISED_BORDER)
-
-class ViewApp(wx.App):
- def OnInit(self):
- frame = ViewerFrame(None, -1, 'testView')
- frame.Show(True)
- #self.SetTopWindow(frame)
-
- return True
-
-if __name__ == "__main__":
- app = ViewApp(0)
- app.MainLoop()
Index: test/guiframe/local_perspectives/plotting/plotting.py
===================================================================
--- test/guiframe/local_perspectives/plotting/plotting.py (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,346 +1,0 @@
-
-
-
-################################################################################
-#This software was developed by the University of Tennessee as part of the
-#Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
-#project funded by the US National Science Foundation.
-#
-#See the license text in license.txt
-#
-#copyright 2008, University of Tennessee
-################################################################################
-
-import wx
-import sys
-from sans.guiframe.events import EVT_NEW_PLOT
-from sans.guiframe.events import StatusEvent
-from sans.guiframe.events import DeletePlotPanelEvent
-from sans.guiframe.plugin_base import PluginBase
-from sans.guiframe.dataFitting import Data1D
-from sans.guiframe.dataFitting import Data2D
-
-DEFAULT_MENU_ITEM_LABEL = "No graph available"
-DEFAULT_MENU_ITEM_ID = wx.NewId()
-
-if sys.platform.count("darwin")==0:
- IS_WIN = True
-else:
- IS_WIN = False
-
-class Plugin(PluginBase):
- """
- Plug-in class to be instantiated by the GUI manager
- """
-
- def __init__(self, standalone=False):
- PluginBase.__init__(self, name="Plotting", standalone=standalone)
-
- ## Plot panels
- self.plot_panels = {}
- self._panel_on_focus = None
- self.menu_default_id = None
- # Plot menu
- self.menu = None
-
-
- def set_panel_on_focus(self, panel):
- """
- """
- self._panel_on_focus = panel
-
- def is_always_active(self):
- """
- return True is this plugin is always active even if the user is
- switching between perspectives
- """
- return True
-
- def populate_menu(self, parent):
- """
- Create a 'Plot' menu to list the panels
- available for displaying
-
- :param id: next available unique ID for wx events
- :param parent: parent window
-
- """
- self.menu = wx.Menu()
- self.menu.Append(DEFAULT_MENU_ITEM_ID, DEFAULT_MENU_ITEM_LABEL,
- "No graph available")
- self.menu.FindItemByPosition(0).Enable(False)
- return [(self.menu, "Show")]
-
- def get_panels(self, parent):
- """
- Create and return a list of panel objects
- """
- ## Save a reference to the parent
- self.parent = parent
- # Connect to plotting events
- self.parent.Bind(EVT_NEW_PLOT, self._on_plot_event)
- # We have no initial panels for this plug-in
- return []
-
- def _on_show_panel(self, event):
- """show plug-in panel"""
- pass
-
- def remove_plot(self, group_id, id):
- """
- remove plot of ID = id from a panel of group ID =group_id
- """
-
- if group_id in self.plot_panels.keys():
- panel = self.plot_panels[group_id]
- panel.remove_data_by_id(id=id)
- return True
- return False
-
- def clear_panel(self):
- """
- Clear and Hide all plot panels, and remove them from menu
- """
- for group_id in self.plot_panels.keys():
- panel = self.plot_panels[group_id]
- panel.graph.reset()
- self.hide_panel(group_id)
- self.plot_panels = {}
- item = self.menu.FindItemByPosition(0)
- while item != None:
- self.menu.DeleteItem(item)
- try:
- item = self.menu.FindItemByPosition(0)
- except:
- item = None
-
-
- def clear_panel_by_id(self, group_id):
- """
- clear the graph
- """
- if group_id in self.plot_panels.keys():
- panel = self.plot_panels[group_id]
- panel.graph.reset()
- return True
- return False
-
-
- def hide_panel(self, group_id):
- """
- hide panel with group ID = group_id
- """
- if group_id in self.plot_panels.keys():
- panel = self.plot_panels[group_id]
- self.parent.hide_panel(panel.uid)
- return True
- return False
-
- def create_panel_helper(self, new_panel, data, group_id, title=None):
- """
- """
- ## Set group ID if available
- ## Assign data properties to the new create panel
- new_panel.set_manager(self)
- new_panel.group_id = group_id
- if group_id not in data.list_group_id:
- data.list_group_id.append(group_id)
- if title is None:
- title = data.title
- new_panel.window_caption = title
- new_panel.window_name = data.title
- event_id = self.parent.popup_panel(new_panel)
- #remove the default item in the menu
- if len(self.plot_panels) == 0:
- pos = self.menu.FindItem(DEFAULT_MENU_ITEM_LABEL)
- if pos != -1:
- self.menu.Delete(DEFAULT_MENU_ITEM_ID)
-
- self.menu.AppendCheckItem(event_id, new_panel.window_caption,
- "Show %s plot panel" % new_panel.window_caption)
- self.menu.Check(event_id, IS_WIN)
- wx.EVT_MENU(self.parent, event_id, self._on_check_menu)
-
- wx.EVT_SHOW(new_panel, self._on_close_panel)
-
- # Set UID to allow us to reference the panel later
- new_panel.uid = event_id
- # Ship the plottable to its panel
- new_panel.plot_data(data)
- self.plot_panels[new_panel.group_id] = new_panel
-
-
- def create_1d_panel(self, data, group_id):
- """
- """
- # Create a new plot panel if none was available
- if issubclass(data.__class__, Data1D):
- from Plotter1D import ModelPanel1D
- ## get the data representation label of the data to plot
- ## when even the user select "change scale"
- xtransform = data.xtransform
- ytransform = data.ytransform
- ## create a plotpanel for 1D Data
- new_panel = ModelPanel1D(self.parent, -1, xtransform=xtransform,
- ytransform=ytransform, style=wx.RAISED_BORDER)
- return new_panel
-
- msg = "1D Panel of group ID %s could not be created" % str(group_id)
- raise ValueError, msg
-
- def create_2d_panel(self, data, group_id):
- """
- """
- if issubclass(data.__class__, Data2D):
- ##Create a new plotpanel for 2D data
- from Plotter2D import ModelPanel2D
- scale = data.scale
- new_panel = ModelPanel2D(self.parent, id = -1,
- data2d=data, scale = scale,
- style=wx.RAISED_BORDER)
- return new_panel
- msg = "2D Panel of group ID %s could not be created" % str(group_id)
- raise ValueError, msg
-
- def update_panel(self, data, panel):
- """
- update the graph of a given panel
- """
- # Check whether we already have a graph with the same units
- # as the plottable we just received.
- _, x_unit = data.get_xaxis()
- _, y_unit = data.get_yaxis()
- flag_x = (panel.graph.prop["xunit"] is not None) and \
- (panel.graph.prop["xunit"].strip() != "") and\
- (x_unit != panel.graph.prop["xunit"])
- flag_y = (panel.graph.prop["yunit"] is not None) and \
- (panel.graph.prop["yunit"].strip() != "") and\
- (y_unit != panel.graph.prop["yunit"])
- if (flag_x and flag_y):
- msg = "Cannot add %s" % str(data.name)
- msg += " to panel %s\n" % str(panel.window_caption)
- msg += "Please edit %s's units, labels" % str(data.name)
- raise ValueError, msg
- else:
- if panel.group_id not in data.list_group_id:
- data.list_group_id.append(panel.group_id)
- panel.plot_data( data)
- self.parent.show_panel(panel.uid)
-
- def delete_menu_item(self, name, uid):
- """
- """
- #remove menu item
- pos = self.menu.FindItem(name)
- if pos != -1:
- self.menu.Delete(uid)
- if self.menu.GetMenuItemCount() == 0:
- self.menu.Append(DEFAULT_MENU_ITEM_ID, DEFAULT_MENU_ITEM_LABEL,
- "No graph available")
- self.menu.FindItemByPosition(0).Enable(False)
-
- def delete_panel(self, group_id):
- """
- """
- if group_id in self.plot_panels.keys():
- panel = self.plot_panels[group_id]
- uid = panel.uid
- wx.PostEvent(self.parent,
- DeletePlotPanelEvent(name=panel.window_caption,
- caption=panel.window_caption))
- #remove menu item
- self.delete_menu_item(panel.window_caption, panel.uid)
- del self.plot_panels[group_id]
- self.parent.delete_panel(uid)
- return True
- return False
-
- def _on_plot_event(self, event):
- """
- A new plottable is being shipped to the plotting plug-in.
- Check whether we have a panel to put in on, or create
- a new one
-
- :param event: EVT_NEW_PLOT event
-
- """
- if hasattr(event, 'action'):
- group_id = event.group_id
- #remove data from panel
- if event.action.lower() == 'remove':
- id = event.id
- return self.remove_plot(group_id, id)
- if event.action.lower() == 'hide':
- return self.hide_panel(group_id)
- if event.action.lower() == 'delete':
- return self.delete_panel(group_id)
- if event.action.lower() == "clear":
- return self.clear_panel_by_id(group_id)
-
- title = None
- if hasattr(event, 'title'):
- title = event.title
-
- data = event.plot
- group_id = data.group_id
-
- if group_id in self.plot_panels.keys():
- #update a panel graph
- panel = self.plot_panels[group_id]
- self.update_panel(data, panel)
- else:
- #create a new panel
- if issubclass(data.__class__, Data1D):
- new_panel = self.create_1d_panel(data, group_id)
- else:
- new_panel = self.create_2d_panel(data, group_id)
- self.create_panel_helper(new_panel, data, group_id, title)
-
- return
-
- def _on_check_menu(self, event):
- """
- Check mark on menu
- """
- #event.Skip()
- event_id = event.GetId()
-
- if self.menu.IsChecked(event_id):
- self.parent.on_view(event)
- self.menu.Check(event_id, IS_WIN)
- else:
- self.parent.hide_panel(event_id)
- self.menu.Check(event_id, False)
-
- def help(self, evt):
- """
- Show a general help dialog.
- """
- from help_panel import HelpWindow
- frame = HelpWindow(None, -1, 'HelpWindow')
- frame.Show(True)
-
- def _on_close_panel(self, event):
- """
- Update check mark on panel's show and hide event
- """
- event.Skip()
- panel = event.GetEventObject()
- id = panel.uid
- if event.GetShow() and self.parent._mgr.GetPane(panel).IsShown():
- try:
- if self.menu.FindItemById(id) != None:
- if not self.menu.IsChecked(id):
- self.menu.Check(id, True)
- #self.menu.Enable(id, False)
- except:
- # when no such item; may happens after delete
- pass
- else:
- try:
- if self.menu.FindItemById(id) != None:
- if self.menu.IsChecked(id):
- self.menu.Check(id, False)
- #self.menu.Enable(id, True)
- except:
- pass
Index: test/guiframe/local_perspectives/plotting/profile_dialog.py
===================================================================
--- test/guiframe/local_perspectives/plotting/profile_dialog.py (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,261 +1,0 @@
-"""
-SLD Profile Dialog for multifunctional models
-"""
-import wx
-import sys
-from copy import deepcopy
-from danse.common.plottools.plottables import Graph
-from Plotter1D import ModelPanel1D as PlotPanel
-from sans.guiframe.dataFitting import Theory1D
-import pylab
-
-DEFAULT_CMAP = None#pylab.cm.jet
-_BOX_WIDTH = 76
-_STATICBOX_WIDTH = 400
-# X Y offset on plot
-_X_OFF = 15
-_Y_OFF = 0.5
-
-#SLD panel size
-if sys.platform.count("win32") > 0:
- _STATICBOX_WIDTH = 563
- PANEL_SIZE = 425
- FONT_VARIANT = 0
-else:
- _STATICBOX_WIDTH = 605
- PANEL_SIZE = 500
- FONT_VARIANT = 1
-
-
-class SLDPanel(wx.Dialog):
- """
- Provides the SLD profile plot panel.
- """
- ## Internal nickname for the window, used by the AUI manager
- window_name = "SLD Profile"
- ## Name to appear on the window title bar
- window_caption = "SLD Profile"
- ## Flag to tell the AUI manager to put this panel in the center pane
- CENTER_PANE = True
- def __init__(self, parent=None, base=None, data=None, axes =['Radius'],
- id=-1, *args, **kwds):
- kwds["style"] = wx.DEFAULT_DIALOG_STYLE
- kwds["size"] = wx.Size(_STATICBOX_WIDTH, PANEL_SIZE)
- wx.Dialog.__init__(self, parent, id=id, *args, **kwds)
-
- if data != None:
- #Font size
- kwds = []
- self.SetWindowVariant(variant=FONT_VARIANT)
- self.SetTitle("Scattering Length Density Profile")
- self.parent = base
- self.data = data
- self.str = self.data.__str__()
- ## when 2 data have the same id override the 1 st plotted
- self.name = self.data.name
- # Panel for plot
- self.plotpanel = SLDplotpanel(self, axes, -1,
- style=wx.TRANSPARENT_WINDOW)
- self.cmap = DEFAULT_CMAP
- ## Create Artist and bind it
- self.subplot = self.plotpanel.subplot
- # layout
- self._setup_layout()
- # plot
- data_plot = deepcopy(self.data)
- data_plot.dy = self._set_dy_data()
- # unit increase to M times for users
- data_plot.y = self._set_y_data()
-
- self.newplot = Theory1D(data_plot.x, data_plot.y, data_plot.dy)
- self.newplot.dy = None
- self.newplot.name = 'SLD'
- self.plotpanel.add_image(self.newplot)
- self.plotpanel.subplot.set_ylim(min(data_plot.y) - _Y_OFF ,
- max(data_plot.y) + _Y_OFF)
- self.plotpanel.subplot.set_xlim(min(data_plot.x) - _X_OFF,
- max(data_plot.x) + _X_OFF)
- #self.Centre()
- self.Layout()
-
- def _set_dy_data(self):
- """
- make fake dy data
-
- :return dy:
- """
- # set dy as zero
- dy = [0 for y in self.data.y]
- return dy
-
- def _set_y_data(self):
- """
- make y data unit Mega times
-
- :return y_value:
- """
- # changes the unit
- y_value = [yvalue * 1e+006 for yvalue in self.data.y]
-
- return y_value
-
- def _setup_layout(self):
- """
- Set up the layout
- """
- # panel sizer
- sizer = wx.BoxSizer(wx.VERTICAL)
- sizer.Add(self.plotpanel, 0, wx.LEFT|wx.RIGHT, 5)
- sizer.Add(wx.StaticLine(self), 0, wx.ALL|wx.EXPAND, 5)
- sizer.Add((0, 5))
- #-----Button------------1
- id = wx.NewId()
- button_reset = wx.Button(self, id, "Close")
- button_reset.SetToolTipString("Close...")
- button_reset.Bind(wx.EVT_BUTTON, self._close,
- id=button_reset.GetId())
- sizer.Add(button_reset, 0, wx.LEFT, _STATICBOX_WIDTH - 80)
- sizer.Add((0, 10))
- self.SetSizerAndFit(sizer)
- self.Centre()
- self.Show(True)
- button_reset.SetFocus()
-
- def _close(self, event):
- """
- Close the dialog
- """
- self.Close(True)
-
- def _draw_model(self, event):
- """
- on_close, update the model2d plot
- """
- pass
-
- def get_context_menu(self, graph=None):
- """
- When the context menu of a plot is rendered, the
- get_context_menu method will be called to give you a
- chance to add a menu item to the context menu.
- :param graph: the Graph object to which we attach the context menu
-
- :return: a list of menu items with call-back function
- """
- return []
-
- def set_schedule_full_draw(self, panel=None, func=None):
- """
- Set_schedule for full draw
- """
- # Not implemented
- pass
-
- def set_schedule(self, schedule=False):
- """
- Set schedule for redraw
- """
- # Not implemented
- pass
-
- def set_plot_unfocus(self):
- """
- Set_plot unfocus
- """
- # NOt implemented
- pass
-
-
-
-class SLDplotpanel(PlotPanel):
- """
- Panel
- """
- def __init__(self, parent, axes=[], id=-1, color=None, dpi=None,
- **kwargs):
- """
- """
- PlotPanel.__init__(self, parent, id=id, xtransform='x', ytransform='y',
- color=color, dpi=dpi,
- size=(_STATICBOX_WIDTH, PANEL_SIZE-100), **kwargs)
-
- # Keep track of the parent Frame
- self.parent = parent
- # Internal list of plottable names (because graph
- # doesn't have a dictionary of handles for the plottables)
- self.plots = {}
- self.graph = Graph()
- self.axes_label = []
- for idx in range(0, len(axes)):
- self.axes_label.append(axes[idx])
-
- def add_image(self, plot):
- """
- Add image(Theory1D)
- """
- self.plots[plot.name] = plot
- self.plots[plot.name].is_data = False
- #init graph
- #self.gaph = Graph()
- #add plot
- self.graph.add(plot)
- #add axes
- x1_label = self.axes_label[0]
- self.graph.xaxis('\\rm{%s} '% x1_label, 'A')
- self.graph.yaxis('\\rm{SLD} ', '10^{-6}A^{-2}')
- #draw
- self.graph.render(self)
- self.subplot.figure.canvas.draw_idle()
-
- # For latter scale changes
- self.plots[plot.name].xaxis('\\rm{%s} '% x1_label, 'A')
- self.plots[plot.name].yaxis('\\rm{SLD} ', '10^{-6}A^{-2}')
-
- def on_set_focus(self, event):
- """
- send to the parenet the current panel on focus
-
- """
- #Not implemented
- pass
-
- def on_kill_focus(self, event):
- """
- reset the panel color
-
- """
- #Not implemented
- pass
-
- def _add_more_tool(self):
- """
- Not implemented
- """
- pass
-
-class ViewerFrame(wx.Frame):
- """
- Add comment
- """
- def __init__(self, parent, id, title):
- """
- comment
- :param parent: parent panel/container
- """
- # Initialize the Frame object
- wx.Frame.__init__(self, parent, id, title, wx.DefaultPosition,
- wx.Size(_STATICBOX_WIDTH, PANEL_SIZE))
- # Panel for 1D plot
- self.plotpanel = SLDplotpanel(self, -1, style=wx.RAISED_BORDER)
-
-class ViewApp(wx.App):
- def OnInit(self):
- frame = ViewerFrame(None, -1, 'testView')
- frame.Show(True)
- self.SetTopWindow(frame)
-
- return True
-
-if __name__ == "__main__":
- app = ViewApp(0)
- app.MainLoop()
Index: test/guiframe/local_perspectives/plotting/sectorMask.py
===================================================================
--- test/guiframe/local_perspectives/plotting/sectorMask.py (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,220 +1,0 @@
-
-import math
-import wx
-#from copy import deepcopy
-from BaseInteractor import _BaseInteractor
-from SectorSlicer import SideInteractor
-from SectorSlicer import LineInteractor
-from sans.guiframe.events import SlicerParameterEvent
-
-class SectorMask(_BaseInteractor):
- """
- Draw a sector slicer.Allow to find the data 2D inside of the sector lines
- """
- def __init__(self, base, axes, color='gray', zorder=3, side=False):
- """
- """
- _BaseInteractor.__init__(self, base, axes, color=color)
- ## Class initialization
- self.markers = []
- self.axes = axes
- self.is_inside = side
- ## connect the plot to event
- self.connect = self.base.connect
-
- ## compute qmax limit to reset the graph
- x = math.pow(max(self.base.data.xmax,
- math.fabs(self.base.data.xmin)), 2)
- y = math.pow(max(self.base.data.ymax,
- math.fabs(self.base.data.ymin)), 2)
- self.qmax = math.sqrt(x + y)
- ## Number of points on the plot
- self.nbins = 20
- ## Angle of the middle line
- self.theta2 = math.pi/3
- ## Absolute value of the Angle between the middle line and any side line
- self.phi = math.pi/12
-
- ## Middle line
- self.main_line = LineInteractor(self, self.base.subplot, color='blue',
- zorder=zorder, r=self.qmax, theta=self.theta2)
- self.main_line.qmax = self.qmax
- ## Right Side line
- self.right_line = SideInteractor(self, self.base.subplot, color='gray',
- zorder=zorder, r=self.qmax, phi= -1*self.phi,
- theta2=self.theta2)
- self.right_line.qmax = self.qmax
- ## Left Side line
- self.left_line = SideInteractor(self, self.base.subplot, color='gray',
- zorder=zorder, r=self.qmax, phi= self.phi,
- theta2=self.theta2)
- self.left_line.qmax = self.qmax
- ## draw the sector
- self.update()
- self._post_data()
-
- def clear(self):
- """
- Clear the slicer and all connected events related to this slicer
- """
- self.clear_markers()
- self.main_line.clear()
- self.left_line.clear()
- self.right_line.clear()
- self.base.connect.clearall()
- #self.base.Unbind(EVT_SLICER_PARS)
-
- def update(self):
- """
- Respond to changes in the model by recalculating the profiles and
- resetting the widgets.
- """
- # Update locations
- ## Check if the middle line was dragged and
- #update the picture accordingly
- if self.main_line.has_move:
- self.main_line.update()
- self.right_line.update(delta=-self.left_line.phi/2,
- mline=self.main_line.theta)
- self.left_line.update(delta=self.left_line.phi/2,
- mline=self.main_line.theta)
- ## Check if the left side has moved and update the slicer accordingly
- if self.left_line.has_move:
- self.main_line.update()
- self.left_line.update(phi=None, delta=None, mline=self.main_line ,
- side=True, left=True )
- self.right_line.update(phi=self.left_line.phi, delta=None,
- mline=self.main_line, side=True,
- left=False, right=True)
- ## Check if the right side line has moved and
- #update the slicer accordingly
- if self.right_line.has_move:
- self.main_line.update()
- self.right_line.update(phi=None, delta=None, mline=self.main_line,
- side=True, left=False, right=True)
- self.left_line.update(phi=self.right_line.phi, delta=None,
- mline=self.main_line, side=True, left=False)
- #if self.is_inside != None:
- out = self._post_data()
- return out
-
- def save(self, ev):
- """
- Remember the roughness for this layer and the next so that we
- can restore on Esc.
- """
- self.base.freeze_axes()
- self.main_line.save(ev)
- self.right_line.save(ev)
- self.left_line.save(ev)
-
- def _post_data(self):
- """
- compute sector averaging of data into data1D
- """
- ## get the data to average
- data = self.base.data
- # If we have no data, just return
- if data == None:
- return
-
- mask = data.mask
- ## Averaging
- from DataLoader.manipulations import Sectorcut
- radius = self.qmax
- phimin = -self.left_line.phi + self.main_line.theta
- phimax = self.left_line.phi + self.main_line.theta
-
- mask = Sectorcut(phi_min=phimin, phi_max=phimax)
- if self.is_inside:
- out = (mask(data) == False)
- else:
- out = (mask(data))
- #self.base.data.mask=out
- return out
-
- def moveend(self, ev):
- """
- Called a dragging motion ends.Get slicer event
- """
- self.base.thaw_axes()
- ## Post parameters
- event = SlicerParameterEvent()
- event.type = self.__class__.__name__
- event.params = self.get_params()
- ## Send slicer paramers to plotter2D
- wx.PostEvent(self.base, event)
- self._post_data()
-
- def restore(self):
- """
- Restore the roughness for this layer.
- """
- self.main_line.restore()
- self.left_line.restore()
- self.right_line.restore()
-
- def move(self, x, y, ev):
- """
- Process move to a new position, making sure that the move is allowed.
- """
- pass
-
- def set_cursor(self, x, y):
- pass
-
- def get_params(self):
- """
- Store a copy of values of parameters of the slicer into a dictionary.
-
- :return params: the dictionary created
-
- """
- params = {}
- ## Always make sure that the left and the right line are at phi
- ## angle of the middle line
- if math.fabs(self.left_line.phi) != math.fabs(self.right_line.phi):
- msg = "Phi left and phi right are "
- msg += "different %f, %f" % (self.left_line.phi,
- self.right_line.phi)
- raise ValueError, msg
- params["Phi"] = self.main_line.theta
- params["Delta_Phi"] = math.fabs(self.left_line.phi)
- return params
-
- def set_params(self, params):
- """
- Receive a dictionary and reset the slicer with values contained
- in the values of the dictionary.
-
- :param params: a dictionary containing name of slicer parameters and
- values the user assigned to the slicer.
- """
- main = params["Phi"]
- phi = math.fabs(params["Delta_Phi"])
-
- self.main_line.theta = main
- ## Reset the slicer parameters
- self.main_line.update()
- self.right_line.update(phi=phi, delta=None, mline=self.main_line,
- side=True, right=True)
- self.left_line.update(phi=phi, delta=None,
- mline=self.main_line, side=True)
- ## post the new corresponding data
- self._post_data()
-
- def freeze_axes(self):
- """
- """
- self.base.freeze_axes()
-
- def thaw_axes(self):
- """
- """
- self.base.thaw_axes()
-
- def draw(self):
- """
- """
- self.base.update()
-
Index: test/guiframe/local_perspectives/plotting/slicerpanel.py
===================================================================
--- test/guiframe/local_perspectives/plotting/slicerpanel.py (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,164 +1,0 @@
-
-
-import wx
-import wx.lib.newevent
-#from copy import deepcopy
-from sans.guiframe.utils import format_number
-from sans.guiframe.events import SlicerParameterEvent
-from sans.guiframe.events import EVT_SLICER_PARS
-from sans.guiframe.events import EVT_SLICER
-
-from sans.guiframe.panel_base import PanelBase
-
-class SlicerPanel(wx.Panel, PanelBase):
- """
- Panel class to show the slicer parameters
- """
- #TODO: show units
- #TODO: order parameters properly
- ## Internal name for the AUI manager
- window_name = "Slicer panel"
- ## Title to appear on top of the window
- window_caption = "Slicer Panel"
- CENTER_PANE = False
-
- def __init__(self, parent, id=-1, type=None, base=None,
- params=None, *args, **kwargs):
- wx.Panel.__init__(self, parent, id, *args, **kwargs)
- PanelBase.__init__(self)
- ## Initialization of the class
- self.base = base
- if params is None:
- params = {}
- self.params = params
- self.parent = parent
- self.type = type
- self.listeners = []
- self.parameters = []
- self.bck = wx.GridBagSizer(5, 5)
- self.SetSizer(self.bck)
- if type == None and params == None:
- label = "Right-click on 2D plot for slicer options"
- title = wx.StaticText(self, -1, label, style=wx.ALIGN_LEFT)
- self.bck.Add(title, (0, 0), (1, 2),
- flag=wx.LEFT|wx.ALIGN_CENTER_VERTICAL, border=15)
- else:
- self.set_slicer(type, params)
- ## Bindings
- self.parent.Bind(EVT_SLICER, self.onEVT_SLICER)
- self.parent.Bind(EVT_SLICER_PARS, self.onParamChange)
-
- def onEVT_SLICER(self, event):
- """
- Process EVT_SLICER events
- When the slicer changes, update the panel
-
- :param event: EVT_SLICER event
-
- """
- event.Skip()
- if event.obj_class == None:
- self.set_slicer(None, None)
- else:
- self.set_slicer(event.type, event.params)
-
- def set_slicer(self, type, params):
- """
- Rebuild the panel
- """
- self.bck.Clear(True)
- self.type = type
- if type == None:
- label = "Right-click on 2D plot for slicer options"
- title = wx.StaticText(self, -1, label, style=wx.ALIGN_LEFT)
- self.bck.Add(title, (0, 0), (1, 2),
- flag=wx.LEFT|wx.ALIGN_CENTER_VERTICAL, border=15)
- else:
- title = wx.StaticText(self, -1, "Slicer Parameters",
- style=wx.ALIGN_LEFT)
- self.bck.Add(title, (0, 0), (1, 2),
- flag=wx.LEFT|wx.ALIGN_CENTER_VERTICAL, border=15)
- n = 1
- self.parameters = []
- keys = params.keys()
- keys.sort()
- for item in keys:
- if not item.lower() in ["errors", "count"]:
- n += 1
- text = wx.StaticText(self, -1, item, style=wx.ALIGN_LEFT)
- self.bck.Add(text, (n-1, 0),
- flag=wx.LEFT|wx.ALIGN_CENTER_VERTICAL, border=15)
- ctl = wx.TextCtrl(self, -1, size=(80, 20),
- style=wx.TE_PROCESS_ENTER)
- hint_msg = "Modify the value of %s to change " % item
- hint_msg += "the 2D slicer"
- ctl.SetToolTipString(hint_msg)
- ctl.SetValue(str(format_number(params[item])))
- self.Bind(wx.EVT_TEXT_ENTER, self.onTextEnter)
- ctl.Bind(wx.EVT_SET_FOCUS, self.onSetFocus)
- ctl.Bind(wx.EVT_KILL_FOCUS, self.onTextEnter)
- self.parameters.append([item, ctl])
- self.bck.Add(ctl, (n-1, 1), flag=wx.TOP|wx.BOTTOM, border=0)
- for item in keys:
- if item.lower() in ["errors", "count"]:
- n += 1
- text = wx.StaticText(self, -1, item + ": ",
- style=wx.ALIGN_LEFT)
- self.bck.Add(text, (n-1, 0),
- flag=wx.LEFT|wx.ALIGN_CENTER_VERTICAL,
- border=15)
- ctl = wx.StaticText(self, -1,
- str(format_number(params[item])),
- style=wx.ALIGN_LEFT)
- ctl.SetToolTipString("Result %s" % item)
- self.bck.Add(ctl, (n-1, 1), flag=wx.TOP|wx.BOTTOM, border=0)
- self.bck.Layout()
- #self.bck.Fit(self)
- self.Layout()
- self.parent.GetSizer().Layout()
-
- def onSetFocus(self, evt):
- """
- Hightlight the textcrtl
- """
- # Get a handle to the TextCtrl
- widget = evt.GetEventObject()
- # Select the whole control, after this event resolves
- wx.CallAfter(widget.SetSelection, -1, -1)
- return
-
- def onParamChange(self, evt):
- """
- Receive and event and reset the text field contained in self.parameters
-
- """
- evt.Skip()
- for item in self.parameters:
- if item[0] in evt.params:
- item[1].SetValue(format_number(evt.params[item[0]]))
- item[1].Refresh()
-
- def onTextEnter(self, evt):
- """
- Parameters have changed
- """
- params = {}
- has_error = False
- for item in self.parameters:
- try:
- params[item[0]] = float(item[1].GetValue())
- item[1].SetBackgroundColour(
- wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW))
- item[1].Refresh()
- except:
- has_error = True
- item[1].SetBackgroundColour("pink")
- item[1].Refresh()
-
- if has_error == False:
- # Post parameter event
- ## base is guiframe is this case
- event = SlicerParameterEvent(type=self.type, params=params)
- wx.PostEvent(self.base, event)
-
-
Index: test/guiframe/media/Graph_help.html
===================================================================
--- test/guiframe/media/Graph_help.html (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,94 +1,0 @@
-
-
-
-Graph Context Menu
-
-
-
-
- Locating the pointer and right-clicking on a data/theory plot will bring a context menu.
- On the menu, select a menu item.
-
-
-
-
- To reset the graph's axis range, right click on the plot and the context menu pops-up.
- Select Reset Graph and the plot will take its initial range.
- Also the 'home' icon in tool bar will do the same.
-
-
-
-
- Right click on plot. Context menu will pop-up select save image [file name].A dialog
- window opens and write a the name of the file to save and click on Save Image.
-
-
-
-
- From the context menu, select 'Save points as a file' for 1D, or 'Save as a file(DAT)'
- for 2D. Note that two formats, txt and xml, are available in 1D saving.
-
-
-
-
-
-Select the crossed arrows button on the plot panel toolbar to drag the plot.
-To disable dragging mode, unselect the same button on the toolbar.
-
-
-
-
- Highlight the plot and the context menu appears.Select remove [file name] .
- The plot selected will disappear.
-
-
-
-
- Select the rectangle button on the plot panel toolbar to zoom in
- a region of the plot.
-
-
-To disable zoom mode, unselect the same button on the toolbar.
-After zoom in a region, select left arrow or right arrow button on the toolbar
-to set the graph the the previous size.
-If a mouse wheel button is available, zoom in/out by scrolling the mouse wheel
- ( see 'Key combination' help for details).
-
-
-
- If the loaded data is a 1-D data.Changing scale or Data Representation will work as
- followed:right click on the plot window.
- A context menu pops-up and select Change Scale . A dialog window titled
- select the scale of the graph will pop-up then change the x , the y
- and the view values as wish.
- If the loaded data is an image.Right click on the image to pop-up the context
- menu. Select to switch from linear to log scale. The scale
- selected is printed on the statusbar.
-
-
-
-
-
- Linear fit is to perform a line model fitting keeping the scale of the plot.
- Highlight data to fit.
- From the context menu
- select Linear Fit .A dialog window appears.
- Change model initial parameters, data limits
- and hit fit button.
- New parameters values are displayed and the line with the new
- parameters is added to the plot.
-
-
-
-
Index: test/guiframe/media/averaging_help.html
===================================================================
--- test/guiframe/media/averaging_help.html (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,107 +1,0 @@
-
-
-
-2D Data Averaging
-
-
-
- This feature allows you to perform different types of averages on your data,
- and allows you to see what regions of the detector will contribute to
- the average.
- The region to be averaged will be drown and can be modified by dragging the lines around.
-
-
-
-
-
-Right click on 2D data for the context menu to appear. Select one type of averages
-among "sector [Q view]", "Annulus [Phi view]", "Box sum", "Box averaging in Qx ",
-"box averaging on Qy","Perform circular Average".
-
-
-A slicer will appear except for "Perform circular Average"
-that you can drag by clicking on a slicer 's marker.
- When the marker is highlighted in red , it means that the slicer can change size.You can
- also move some of the slicer by simply drag its side when highlighted in red.
- the slicer size will be reset to its previous size if the user try to select a region greater
- than the size of the data.
-
-
- The user can also select a region to average when a slicer has been selected already by right
- clicking on the context menu and selecting Edit Slicer Parameters . The dialog window
- will appears and the user can enter values to selected a region or selected numbers of points to
- plot nbins .
-
-
-
- For Box sum , when the user selects this option, a new panel is created containing
- the result of average of the sum of every pixels contains on that data.The user can also enter
- values to select a region.
-
-
-
-
-It will perform and average in constant q-rings around the (x,y)
- pixel location of the beam center.
-
-
-
-
-
-This operation is same as 'Perform Circular Average' except that the masked region is excluded if masked.
-
-
-
-
-It averages in constant q-arcs. The width of the sector
- is specified in degrees (+/- delta phi) each direction from the central angle (phi).
-
-
-
-
-It performs an average between two q-values centered in (0,0),
- and averaged over a width of a specified number of pixels.
- The data is returned as a function of angle (phi) in degrees.
- Moving one circle of this slicer
- to radius of zero corresponding to a circular averaging on radius qmax ,
- the outer circle.
- The angle zero starts from the positive x-axis direction.
-
-
-
-
-Perform the sum of counts in a 2D region of interest.When editing the slicer ,the user can
-enter the length and the width the rectangle slicer and the coordinates of the center of this
-rectangle.
-
-
-
-Computes average I(Qx) for a region of interest. When editing the slicer ,the user can
-control the length and the width the rectangle slicer.
-The averaged output is calculated from the constant bins with rectangular shape.
-The resultant q values are nominal values, i.e., the central values of each bins on the x-axis.
-
-
-
-
- Computes average I(Qy) for a region of interest.When editing the slicer ,the user can
-control the length and the width the rectangle slicer.
-The averaged output is calculated from the constant bins with rectangular shape.
-The resultant q values are nominal values, i.e., the central values of each bins on the y-axis.
-
-
-
-
-
Index: test/guiframe/media/change_scale_help.html
===================================================================
--- test/guiframe/media/change_scale_help.html (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,16 +1,0 @@
-
-
-Change scale
-
- If the loaded data is a 1-D data.Changing scale or Data Representation will work as
- followed:right click on the plot window.
- A context menu pops-up and select Change Scale . A dialog window titled
- select the scale of the graph will pop-up then change the x , the y
- and the view values as wish.
- If the loaded data is an image.Right click on the image to pop-up the context
- menu. Select to switch from linear to log scale. The scale
- selected is printed on the statusbar.
-
-
-
-
Index: test/guiframe/media/data_explorer_help.html
===================================================================
--- test/guiframe/media/data_explorer_help.html (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,96 +1,0 @@
-
-
-
-Data Explorer Options
-
-
-
-
-Data Explorer is a panel that allows the user more interactions with
-data. Some functionalities provided by the Data Explorer are also available
-through the context menu of plot panels or other menus of the applications.Under
-menu View of the menubar, Data explorer can be toggle from Show to Hide
-when clicking on menu Data Explorer OFF . This latter can be labeled as
-Data Explorer ON if the Data Explorer is not visible.
-
-IMPORTANT! When Data explorer is not visible all data loaded will
-be send directly to the current active application. When data Explorer is shown
-data go fist to the Data Explorer for the user to handle them.
-
-
-
-
-To Load data, click on the button Load Data , then select one or more
-files to load into the application. Close the file dialog that first appears. In
-the list control label Data will be displayed data label with the name
-of each selected file.
- Expending this data by clicking on + sign on each label
-will display available information about this loaded data.
-
-
-
-
-To interact with data, check a data label and click on a button. Checking Data
-make them active for the next operation. Unchecking Data labels will
-deactivate them.
-
-
-There is a combo box labeled Selection Options that allows to activate
-or select multiple data simultaneously.
-
-
-
-
-Remove data button remove all reference of this data into the application.
-
-
-WARNING! Remove data will stop any jobs
-currently using the selected data.
-
-
-
-
-Click on the button Send To to send Data to the current active application.
-Then from the application control panel interact more with that Data.
-
-
-
-Click on the button Append To to append selected Data to a plot panel on
-focus. Next to this button is a combo box containing available panels names.
-Selecting a name from this combo box will set the corresponding lot panel on
-focus. If not plot panel is available, the combo box and button will be disable.
-2D Data cannot be appended to any plot panels . This operation can only be
-performed on 1D data and plot panels currently containing 1D data.
-
-
-
-
-Click on New Plot button to create a new plot panel where selected data
-will be plotted.
-
-
-
-
-Freeze Theory button generate Data from selected theory. This operation
-can only be performed when theory labels are selected.
-
-
-
-Click on Delete Plot to remove all reference of the plot panel on focus.
-User can click on a plot panel or select a name of the plot panel in the corresponding
-combo box to set a plot panel on focus.
-
-
-
-
-
Index: test/guiframe/media/key_help.html
===================================================================
--- test/guiframe/media/key_help.html (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,40 +1,0 @@
-
-
-
-Key Combination
-
-
-
-
-
For a graph panel to float on the top of the SV window:
- Press the Ctrl(Cmd on MAC) key on dragging and placing a panel.
-Or if you want to make all plot panels float, select 'Float' from Graph/Preperences
-in the menu bar. Otherwise choose 'Dock'.
-
-
-
-
-
To get the graph context menu to print, copy, save data, (2D)average, etc.:
- Locate the mouse point on the plot to highlight and
-(Mouse) Right Click to bring up the full menu.
-
-
-
-
-
To Zoom in or out the full plot:
- Locate the mouse point inside the graph which will be the center of the zooming,
-then rotate MouseWheel .
-
-
To Zoom in or out the plot in x or y direction:
- Locate (and click) the mouse point near x (or y) axis just outside of the graph
-and then rotate MouseWheel .
- Note that this works only on the 1D plots.
-
-
-
-
-
Index: test/guiframe/panel_base.py
===================================================================
--- test/guiframe/panel_base.py (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,423 +1,0 @@
-
-
-################################################################################
-#This software was developed by the University of Tennessee as part of the
-#Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
-#project funded by the US National Science Foundation.
-#
-#See the license text in license.txt
-#
-#copyright 2008, University of Tennessee
-################################################################################
-
-
-from sans.guiframe.events import PanelOnFocusEvent
-from sans.guiframe.events import EVT_NEW_BATCH
-import wx
-
-class PanelBase:
- """
- Defines the API for a panels to work with
- the ViewerFrame toolbar and menu bar
- """
- ## Internal nickname for the window, used by the AUI manager
- #window_name = "default"
- ## Name to appear on the window title bar
- #window_caption = "Welcome panel"
- ## Flag to tell the AUI manager to put this panel in the center pane
- group_id = None
- uid = None
-
- def __init__(self, parent=None):
- """
- Initialize some flag that Viewerframe used
- """
- #panel manager
- self._manager = None
- self.parent = parent
- if self.parent is not None and hasattr(self.parent, '_manager'):
- self._manager = self.parent._manager
- self._print_flag = False
- self._undo_flag = False
- self._redo_flag = False
- self._copy_flag = False
- self._paste_flag = False
- self._preview_flag = False
- self._bookmark_flag = False
- self._zoom_in_flag = False
- self._zoom_out_flag = False
- self._zoom_flag = False
- self._save_flag = False
- self._drag_flag = False
- self._reset_flag = False
- self._has_changed = False
- self.batch_on = False
- self.group_id = None
- self.Bind(EVT_NEW_BATCH, self.on_batch_selection)
- self.Bind(wx.EVT_LEFT_DOWN, self.on_set_focus)
- self.Bind(wx.EVT_TEXT_ENTER, self.on_set_focus)
- self.Bind(wx.EVT_MIDDLE_DOWN, self.on_set_focus)
- self.Bind(wx.EVT_RIGHT_DOWN, self.on_set_focus)
-
- def on_batch_selection(self, event):
- """
- :param event: contains parameter enable . when enable is set to True
- the application is in Batch mode
- else the application is default mode(single mode)
- """
- self.batch_on = event.enable
- def save_project(self, doc=None):
- """
- return an xml node containing state of the panel
- that guiframe can write to file
- """
- return None
-
- def has_changed(self):
- """
- """
- return self._has_changed
-
- def _set_print_flag(self, flag=True):
- """
- The derivative class sets the print flag value to indicate that it can
- be printed
- """
- if flag == self._print_flag:
- self._has_changed = False
- return
- self._has_changed = True
- self._print_flag = flag
- if self._manager is not None and self._manager.parent is not None:
- self._manager.parent.cpanel_on_focus = self
- self._manager.parent.enable_print()
-
- def get_print_flag(self):
- """
- Get the print flag to update appropriately the tool bar
- """
- return self._print_flag
-
- def _set_undo_flag(self, flag=True):
- """
- The derivative class sets the undo flag value to indicate that the
- current action done can be canceled
- """
- if flag == self._undo_flag:
- self._has_changed = False
- return
- self._has_changed = True
- self._undo_flag = flag
- if self._manager is not None and self._manager.parent is not None:
- self._manager.parent.cpanel_on_focus = self
- self._manager.parent.enable_undo()
-
- def get_undo_flag(self):
- """
- Get the undo flag to update appropriately the tool bar
- """
- return self._undo_flag
-
- def _set_redo_flag(self, flag=True):
- """
- The derivative class sets the redo flag value to indicate that the
- action done can be recovered
- """
- if flag == self._redo_flag:
- self._has_changed = False
- return
- self._has_changed = True
- self._redo_flag = flag
- if self._manager is not None and self._manager.parent is not None:
- self._manager.parent.cpanel_on_focus = self
- self._manager.parent.enable_redo()
-
- def get_redo_flag(self):
- """
- Get the redo flag to update appropriately the tool bar
- """
- return self._redo_flag
-
- def _set_copy_flag(self, flag=True):
- """
- The derivative class sets the copy flag value to indicate that the
- action done can be recovered
- """
- if flag == self._copy_flag:
- self._has_changed = False
- return
- self._has_changed = True
- self._copy_flag = flag
- if self._manager is not None and self._manager.parent is not None:
- self._manager.parent.cpanel_on_focus = self
- self._manager.parent.enable_copy()
-
- def get_copy_flag(self):
- """
- Get the copy flag to update appropriately the tool bar
- """
- return self._copy_flag
-
- def _set_paste_flag(self, flag=True):
- """
- The derivative class sets the paste flag value to indicate that the
- action done can be recovered
- """
- if flag == self._paste_flag:
- self._has_changed = False
- return
- self._has_changed = True
- self._paste_flag = flag
- if self._manager is not None and self._manager.parent is not None:
- self._manager.parent.cpanel_on_focus = self
- self._manager.parent.enable_paste()
-
- def get_paste_flag(self):
- """
- Get the copy flag to update appropriately the tool bar
- """
- return self._copy_flag
-
- def _set_zoomed_in_flag(self, flag=True):
- """
- The derivative class sets the zoom in flag value to indicate that it
- can be zoomed in
- """
- if self._zoom_in_flag == flag:
- self._has_changed = False
- return
- self._has_changed = True
- self._zoom_in_flag = flag
- if self._manager is not None and self._manager.parent is not None:
- self._manager.parent.cpanel_on_focus = self
- self._manager.parent.enable_zoom_in()
-
- def get_zoom_in_flag(self):
- """
- Get the zoom in flag to update appropriately the tool bar
- """
- return self._zoom_in_flag
-
- def _set_zoomed_out_flag(self, flag=True):
- """
- The derivative class sets the zoom out flag value to indicate that it
- can be zoomed out
- """
- if self._zoom_out_flag == flag:
- self._has_changed = False
- return
- self._has_changed = True
- self._zoom_out_flag = flag
- if self._manager is not None and self._manager.parent is not None:
- self._manager.parent.panel_on_focus = self
- self._manager.parent.enable_zoom_out()
-
- def get_zoom_out_flag(self):
- """
- Get the zoom out flag to update appropriately the tool bar
- """
- return self._zoom_out_flag
-
- def _set_zoom_flag(self, flag=True):
- """
- The derivative class sets the zoom flag value to indicate that it
- can be zoomed
- """
- if flag == self._zoom_flag:
- self._has_changed = False
- return
- self._has_changed = True
- self._zoom_flag = flag
- if self._manager is not None and self._manager.parent is not None:
- self._manager.parent.cpanel_on_focus = self
- self._manager.parent.enable_zoom()
-
- def get_zoom_flag(self):
- """
- Get the zoom flag to update appropriately the tool bar
- """
- return self._zoom_flag
-
- def _set_bookmark_flag(self, flag=True):
- """
- The derivative class sets the bookmark flag value to indicate that it
- can be bookmarked
- """
- if flag == self._bookmark_flag:
- self._has_changed = False
- return
- self._has_changed = True
- self._bookmark_flag = flag
- if self._manager is not None and self._manager.parent is not None:
- self._manager.parent.cpanel_on_focus = self
- self._manager.parent.enable_bookmark()
-
- def get_bookmark_flag(self):
- """
- Get the bookmark flag to update appropriately the tool bar
- """
- return self._bookmark_flag
-
- def _set_preview_flag(self, flag=True):
- """
- The derivative class sets the preview flag value to indicate that it
- can be previewed
- """
- if flag == self._preview_flag:
- self._has_changed = False
- return
- self._has_changed = True
- self._preview_flag = flag
- if self._manager is not None and self._manager.parent is not None:
- self._manager.parent.cpanel_on_focus = self
- self._manager.parent.enable_preview()
-
- def get_preview_flag(self):
- """
- Get the preview flag to update appropriately the tool bar
- """
- return self._preview_flag
-
- def _set_save_flag(self, flag=True):
- """
- The derivative class sets the drag flag value to indicate that it
- can be saved
- """
- if flag == self._save_flag:
- self._has_changed = False
- return
- self._has_changed = True
- self._save_flag = flag
- if self._manager is not None and self._manager.parent is not None:
- self._manager.parent.cpanel_on_focus = self
- self._manager.parent.enable_save()
-
- def get_save_flag(self):
- """
- Get the save flag to update appropriately the tool bar
- """
- return self._save_flag
-
- def _set_drag_flag(self, flag=True):
- """
- The derivative class sets the drag flag value to indicate that
- dragging motion is possible
- """
- if self._drag_flag == flag:
- self._has_changed = False
- return
- self._has_changed = True
- self._drag_flag = flag
- if self._manager is not None and self._manager.parent is not None:
- self._manager.parent.cpanel_on_focus = self
- self._manager.parent.enable_drag()
-
- def get_drag_flag(self):
- """
- Get the drag flag to update appropriately the tool bar
- """
- return self._drag_flag
-
- def _set_reset_flag(self, flag=True):
- """
- The derivative class sets the reset flag value to indicate that it
- can be reset
- """
- if self._reset_flag == flag:
- self._has_changed = False
- return
- self._has_changed = True
- self._reset_flag = flag
- if self._manager is not None and self._manager.parent is not None:
- self._manager.parent.cpanel_on_focus = self
- self._manager.parent.enable_reset()
-
- def get_reset_flag(self):
- """
- Get the reset flag to update appropriately the tool bar
- """
- return self._reset_flag
-
- def on_reset(self, event):
- """
- The derivative class state is restored
- """
- def on_drag(self, event):
- """
- The derivative class allows dragging motion if implemented
- """
- def on_preview(self, event):
- """
- Display a printable version of the class derivative
- """
- def on_save(self, event):
- """
- The state of the derivative class is restored
- """
- def on_redo(self, event):
- """
- The previous action is restored if possible
- """
- def on_undo(self, event):
- """
- The current action is canceled
- """
- def on_copy(self, event):
- """
- The copy action if possible
- """
- def on_paste(self, event):
- """
- The paste action if possible
- """
- def on_bookmark(self, event):
- """
- The derivative class is on bookmark mode if implemented
- """
- def on_zoom_in(self, event):
- """
- The derivative class is on zoom in mode if implemented
- """
- def on_zoom_out(self, event):
- """
- The derivative class is on zoom out mode if implemented
- """
- def on_zoom(self, event):
- """
- The derivative class is on zoom mode (using pane)
- if zoom mode is implemented
- """
- def on_set_focus(self, event=None):
- """
- The derivative class is on focus if implemented
- """
- if self.parent is not None:
- wx.PostEvent(self.parent, PanelOnFocusEvent(panel=self))
-
- def on_kill_focus(self, event=None):
- """
- The derivative class is on unfocus if implemented
- """
- pass
-
- def get_data(self):
- """
- return list of current data
- """
- return
-
- def get_state(self):
- """
- return the current state
- """
- return
-
- def set_manager(self, manager):
- """
- """
- self._manager = manager
-
- def get_manager(self):
- """
- """
- return self._manager
Index: test/guiframe/pdfview.py
===================================================================
--- test/guiframe/pdfview.py (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,120 +1,0 @@
-# Read PDF files by embeding the Adobe Acrobat Reader
-# wx.activex module uses class ActiveX control
-
-import wx
-import os
-if wx.Platform == '__WXMSW__':
- from wx.lib.pdfwin import PDFWindow
-
-class PDFPanel(wx.Panel):
- """
- Panel that contains the pdf reader
- """
- def __init__(self, parent, path=None):
- """
- """
- wx.Panel.__init__(self, parent, id=-1)
-
- self.parent = parent
- self.path = path
- sizer = wx.BoxSizer(wx.VERTICAL)
- btnSizer = wx.BoxSizer(wx.HORIZONTAL)
-
- self.pdf = PDFWindow(self, style=wx.SUNKEN_BORDER)
-
- sizer.Add(self.pdf, proportion=1, flag=wx.EXPAND)
-
- btn = wx.Button(self, wx.NewId(), "Open PDF File")
- self.Bind(wx.EVT_BUTTON, self.OnOpenButton, btn)
- btnSizer.Add(btn, proportion=1, flag=wx.EXPAND|wx.ALL, border=5)
-
- self.pdf.LoadFile(self.path)
- btn = wx.Button(self, wx.NewId(), "Previous Page")
- self.Bind(wx.EVT_BUTTON, self.OnPrevPageButton, btn)
- btnSizer.Add(btn, proportion=1, flag=wx.EXPAND|wx.ALL, border=5)
-
- btn = wx.Button(self, wx.NewId(), "Next Page")
- self.Bind(wx.EVT_BUTTON, self.OnNextPageButton, btn)
- btnSizer.Add(btn, proportion=1, flag=wx.EXPAND|wx.ALL, border=5)
-
- btn = wx.Button(self, wx.NewId(), "Close")
- self.Bind(wx.EVT_BUTTON, self.OnClose, btn)
- btnSizer.Add(btn, proportion=1, flag=wx.EXPAND|wx.ALL, border=5)
- btnSizer.Add((50,-1), proportion=2, flag=wx.EXPAND)
- sizer.Add(btnSizer, proportion=0, flag=wx.EXPAND)
-
- self.SetSizer(sizer)
- self.SetAutoLayout(True)
-
- def OnOpenButton(self, event):
- """
- Open file button
- """
- # make sure you have PDF files available on your drive
- dlg = wx.FileDialog(self, wildcard="*.pdf")
- dlg.SetDirectory(os.path.dirname(self.path))
- if dlg.ShowModal() == wx.ID_OK:
- wx.BeginBusyCursor()
- file = dlg.GetPath()
- self.pdf.LoadFile(file)
- self.parent.SetTitle(os.path.basename(file.split('.')[0]))
- wx.EndBusyCursor()
- dlg.Destroy()
-
- def OnLoad(self, event=None, path=None):
- """
- Load a pdf file
-
- : Param path: full path to the file
- """
- self.pdf.LoadFile(path)
-
-
- def OnPrevPageButton(self, event):
- """
- Goes to Previous page
- """
- self.pdf.gotoPreviousPage()
-
- def OnNextPageButton(self, event):
- """
- Goes to Next page
- """
- self.pdf.gotoNextPage()
-
- def OnClose(self, event):
- """
- Close panel
- """
- self.parent.Destroy()
-
-class PDFFrame(wx.Frame):
- """
- Frame for PDF panel
- """
- def __init__(self, parent, id, title, path):
- """
- Init
-
- :param parent: parent panel/container
- :param path: full path of the pdf file
- """
- # Initialize the Frame object
- wx.Frame.__init__(self, parent, id, title,
- wx.DefaultPosition, wx.Size(600, 830))
- # make an instance of the class
- PDFPanel(self, path)
-
-class ViewApp(wx.App):
- def OnInit(self):
- path = None
- frame = PDFFrame(None, -1, "PDFView", path=path)
-
- frame.Show(True)
- #self.SetTopWindow(frame)
-
- return True
-
-if __name__ == "__main__":
- app = ViewApp(0)
- app.MainLoop()
Index: test/guiframe/plugin_base.py
===================================================================
--- test/guiframe/plugin_base.py (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,252 +1,0 @@
-################################################################################
-#This software was developed by the University of Tennessee as part of the
-#Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
-#project funded by the US National Science Foundation.
-#
-#See the license text in license.txt
-#
-#copyright 2008, University of Tennessee
-################################################################################
-
-class PluginBase:
- """
- This class defines the interface for a Plugin class
- that can be used by the gui_manager.
-
- Plug-ins should be placed in a sub-directory called "perspectives".
- For example, a plug-in called Foo should be place in "perspectives/Foo".
- That directory contains at least two files:
- perspectives/Foo/__init__.py contains two lines:
-
- PLUGIN_ID = "Foo plug-in 1.0"
- from Foo import *
-
- perspectives/Foo/Foo.py contains the definition of the Plugin
- class for the Foo plug-in. The interface of that Plugin class
- should follow the interface of the class you are looking at.
-
- See dummyapp.py for a plugin example.
- """
-
- def __init__(self, name="Test_plugin", standalone=True):
- """
- Abstract class for gui_manager Plugins.
- """
- # Define if the plugin is local to Viewerframe and always active
- self._always_active = False
- ## Plug-in name. It will appear on the application menu.
- self.sub_menu = name
- #standalone flag
- self.standalone = standalone
- ## Reference to the parent window. Filled by get_panels() below.
- self.parent = None
- #plugin state reader
- self.state_reader = None
- self._extensions = ''
- ## List of panels that you would like to open in AUI windows
- # for your plug-in. This defines your plug-in "perspective"
- self.perspective = []
- #flag to tell the current plugin that aaplication is in batch mode
- self.batch_on = False
-
- def clear_panel(self):
- """
- clear all related panels
- """
- def get_extensions(self):
- """
- return state reader and its extensions
- """
- return self.state_reader, self._extensions
-
- def can_load_data(self):
- """
- if return True, then call handler to laod data
- """
- return False
-
- def use_data(self):
- """
- return True if these plugin use data
- """
- return True
-
- def is_in_use(self, data_id):
- """
- get a data id a list of data name if data data is
- currently used by the plugin and the name of the plugin
-
- data_name = 'None'
- in_use = False
- example [(data_name, self.sub_menu)]
- """
- return []
-
- def delete_data(self, data_id):
- """
- Delete all references of data which id are in data_list.
- """
-
- def load_data(self, event):
- """
- Load data
- """
- raise NotImplemented
-
- def load_folder(self, event):
- """
- Load entire folder
- """
- raise NotImplemented
-
- def set_is_active(self, active=False):
- """
- """
- self._always_active = active
-
- def is_always_active(self):
- """
- return True is this plugin is always active and it is local to guiframe
- even if the user is switching between perspectives
- """
- return self._always_active
-
- def populate_file_menu(self):
- """
- Append menu item under file menu item of the frame
- """
- return []
-
- def populate_menu(self, parent):
- """
- Create and return the list of application menu
- items for the plug-in.
-
- :param parent: parent window
-
- :return: plug-in menu
-
- """
- return []
-
- def get_panels(self, parent):
- """
- Create and return the list of wx.Panels for your plug-in.
- Define the plug-in perspective.
-
- Panels should inherit from DefaultPanel defined below,
- or should present the same interface. They must define
- "window_caption" and "window_name".
-
- :param parent: parent window
-
- :return: list of panels
-
- """
- ## Save a reference to the parent
- self.parent = parent
-
- # Return the list of panels
- return []
-
-
- def get_tools(self):
- """
- Returns a set of menu entries for tools
- """
- return []
-
-
- def get_context_menu(self, plotpanel=None):
- """
- This method is optional.
-
- When the context menu of a plot is rendered, the
- get_context_menu method will be called to give you a
- chance to add a menu item to the context menu.
-
- A ref to a plotpanel object is passed so that you can
- investigate the plot content and decide whether you
- need to add items to the context menu.
-
- This method returns a list of menu items.
- Each item is itself a list defining the text to
- appear in the menu, a tool-tip help text, and a
- call-back method.
-
- :param graph: the Graph object to which we attach the context menu
-
- :return: a list of menu items with call-back function
-
- """
- return []
-
- def get_perspective(self):
- """
- Get the list of panel names for this perspective
- """
- return self.perspective
-
- def on_perspective(self, event=None):
- """
- Call back function for the perspective menu item.
- We notify the parent window that the perspective
- has changed.
-
- :param event: menu event
-
- """
- self.parent.set_current_perspective(self)
- self.parent.set_perspective(self.perspective)
-
- def set_batch_selection(self, flag):
- """
- the plugin to its batch state if flag is True
- """
- self.batch_on = flag
- self.on_batch_selection(self.batch_on)
-
- def on_batch_selection(self, flag):
- """
- need to be overwritten by the derivated class
- """
-
- def post_init(self):
- """
- Post initialization call back to close the loose ends
- """
- pass
-
- def set_default_perspective(self):
- """
- Call back method that True to notify the parent that the current plug-in
- can be set as default perspective.
- when returning False, the plug-in is not candidate for an automatic
- default perspective setting
- """
- if self.standalone:
- return True
- return False
-
- def set_state(self, state=None, datainfo=None):
- """
- update state
- """
- def set_data(self, data_list=None):
- """
- receive a list of data and use it in the current perspective
-
- """
- def set_theory(self, theory_list=None):
- """
- :param theory_list: list of information
- related to available theory state
- """
- msg = "%s plugin: does not support import theory" % str(self.sub_menu)
- raise ValueError, msg
-
- def on_set_state_helper(self, event):
- """
- update state
- """
-
Index: test/guiframe/release_notes.txt
===================================================================
--- test/guiframe/release_notes.txt (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,43 +1,0 @@
-First cut at a GUI framework for SANS applications.
-
-Modules should be put in the "perspectives" directory
-of their main application when using this framework.
-
-Documentation to come...
-
-1- Version 0.1.7
-
- - Release date: 7/4/2009
-
- Version 0.1.5
-
- - Release date: 4/21/2009
-
- - Changes:
- * the Plugin.get_context_menu(graph) now takes a Graph object
-
-Dependencies:
- - svn://danse.us/common/releases/plottools-0.1.6
- - svn://danse.us/sans/releases/guicomm-0.1.2
-
-To-do list:
- - Clean up about box
- - Clean up the _find_plugins() function to allow user-defined directory
- - Modify the get_context_menu() function to allow a plug-in to recognize
- its own plots.
- - Provide a hook for a general file loader for the various data formats
- - Add group flag to allow groups of plots (and exclude other plots with
- same units to be plotted in the same Graph. [DONE]
- - If there is only one perspective, drop the perspective menu.
- - If there is only one panel in the Panel menu, drop the menu.
- - Make legend transparent
- - Make sure that when a plottable is sent a second time for update, that we replace the lables too!
- - Add help menu entry for each module
- - Put debug info in log file, because we can't access it from a py2exe executable
- - Allow the application to load perspectives by hand. Then the automatic loading is only
- for additionally installed plug-ins.
- - Fix the damned images directory folder...
- - Allow user to remove a plottable from a graph (from code!)
- - Allow perspectives to recognize their own plots and add context menu items.
- - Catch error when trying to show log of negative or zero plots... update status bar.
-
Index: test/guiframe/sans/__init__.py
===================================================================
--- test/guiframe/sans/__init__.py (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,2 +1,0 @@
-from pkgutil import extend_path
-__path__ = extend_path(__path__, __name__)
Index: test/guiframe/setup.py
===================================================================
--- test/guiframe/setup.py (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,46 +1,0 @@
-
-"""
- Installs the guiframe package
-"""
-
-
-from distutils.core import setup, Extension
-
-from distutils.sysconfig import get_python_lib
-import os
-import sys
-
-
-
-path = os.path.join(os.getcwd(), 'local_perspectives')
-package_dir = { "sans.guiframe":".",
- "sans.guiframe.local_perspectives":"local_perspectives",
- #"sans.guiframe.images":"images",
- # "sans.guiframe.media":"media",
- }
-#package_data = {"sans.guiframe": ['images/*'],
-# "sans.guiframe":'media/*']}
-package_data = {"sans.guiframe": ['images/*', 'media/*']}
-packages = ["sans.guiframe",
- "sans.guiframe.local_perspectives"]
-# build local plugin
-for dir in os.listdir(path):
- if dir not in ['.svn','__init__.py', '__init__.pyc']:
- package_name = "sans.guiframe.local_perspectives." + dir
- packages.append(package_name)
- package_dir[package_name] = "local_perspectives/" + dir
-
-
-setup(
- name="guiframe",
- version = "0.9.1",
- description = "Python module for SANS gui framework",
- author = "University of Tennessee",
- url = "http://danse.chem.utk.edu",
-
- package_dir = package_dir,
-
- packages = packages,
- package_data = package_data,
-
- )
Index: test/guiframe/startup_configuration.py
===================================================================
--- test/guiframe/startup_configuration.py (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,207 +1,0 @@
-
-################################################################################
-#This software was developed by the University of Tennessee as part of the
-#Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
-#project funded by the US National Science Foundation.
-#
-#See the license text in license.txt
-#
-#copyright 2009, University of Tennessee
-################################################################################
-import wx
-import os
-import sys
-import copy
-#import sans.guiframe.gui_manager as gui
-from sans.guiframe.events import StatusEvent
-from sans.guiframe.gui_style import GUIFRAME
-from sans.guiframe import gui_manager as CURRENT
-# default configuration
-DEFAULT_STRINGS = {'GUIFRAME_WIDTH':1150,
- 'GUIFRAME_HEIGHT':840,
- 'PLOPANEL_WIDTH':415,
- 'DATAPANEL_WIDTH':235,
- 'DATALOADER_SHOW':True,
- 'TOOLBAR_SHOW':True,
- 'FIXED_PANEL':True,
- 'WELCOME_PANEL_SHOW':False,
- 'CLEANUP_PLOT':False,
- 'DEFAULT_PERSPECTIVE':'Fitting'}
-try:
- CURRENT_STRINGS = {'GUIFRAME_WIDTH':CURRENT.GUIFRAME_WIDTH,
- 'GUIFRAME_HEIGHT':CURRENT.GUIFRAME_HEIGHT,
- 'PLOPANEL_WIDTH':CURRENT.PLOPANEL_WIDTH,
- 'DATAPANEL_WIDTH':CURRENT.DATAPANEL_WIDTH,
- 'DATALOADER_SHOW':CURRENT.DATALOADER_SHOW,
- 'TOOLBAR_SHOW':CURRENT.TOOLBAR_SHOW,
- 'FIXED_PANEL':CURRENT.FIXED_PANEL,
- 'WELCOME_PANEL_SHOW':CURRENT.WELCOME_PANEL_SHOW,
- 'CLEANUP_PLOT':CURRENT.CLEANUP_PLOT,
- 'DEFAULT_PERSPECTIVE':CURRENT.DEFAULT_PERSPECTIVE}
-except:
- CURRENT_STRINGS = DEFAULT_STRINGS
-
-if sys.platform.count("win32") > 0:
- PANEL_WIDTH = 265
- PANEL_HEIGHT = 235
- FONT_VARIANT = 0
-else:
- PANEL_WIDTH = 285
- PANEL_HEIGHT = 255
- FONT_VARIANT = 1
-
-"""
-Dialog to set Appication startup configuration
-"""
-class StartupConfiguration(wx.Dialog):
- """
- Dialog for Startup Configuration
- """
- def __init__(self, parent, gui, id=-1, title="Startup Setting"):
- wx.Dialog.__init__(self, parent, id, title,
- size=(PANEL_WIDTH, PANEL_HEIGHT))
- # parent
- self.parent = parent
- self.path = parent.path
- self._gui = gui
- # font size
- self.SetWindowVariant(variant=FONT_VARIANT)
- self.current_string = copy.deepcopy(CURRENT_STRINGS)
- self.return_string = {}
- # build layout
- panel = wx.Panel(self, -1)
- vbox = wx.BoxSizer(wx.VERTICAL)
- wx.StaticBox(panel, -1, 'Set View-Configuration', (5, 5),
- (PANEL_WIDTH*0.94, PANEL_HEIGHT*0.7))
- default_bt = wx.RadioButton(panel, -1, 'Default View', (15, 30),
- style=wx.RB_GROUP)
- default_bt.Bind(wx.EVT_RADIOBUTTON, self.OnDefault)
- default_bt.SetValue(True)
- current_bt = wx.RadioButton(panel, -1, 'Current View', (15, 55))
- current_bt.SetValue(False)
- current_bt.Bind(wx.EVT_RADIOBUTTON, self.OnCurrent)
- msg = "\nThis new configuration will take effect after\n"
- msg += "restarting the SansView application..."
- note_txt = wx.StaticText(panel, -1, msg, (15, 75))
- note_txt.SetForegroundColour("black")
- hbox = wx.BoxSizer(wx.HORIZONTAL)
- cancelButton = wx.Button(self, -1, 'Cancel', size=(70, 25))
- hbox.Add(cancelButton, 1, wx.RIGHT, 5)
- cancelButton.Bind(wx.EVT_BUTTON, self.OnCancel)
- okButton = wx.Button(self, -1, 'OK', size=(70, 25))
- hbox.Add(okButton, 1, wx.RIGHT, 5)
- okButton.Bind(wx.EVT_BUTTON, self.OnClose)
- vbox.Add(panel)
-
- vbox.Add(hbox, 1, wx.ALIGN_CENTER | wx.RIGHT | wx.BOTTOM, 5)
- # set sizer
- self.SetSizer(vbox)
- #pos = self.parent.GetPosition()
- #self.SetPosition(pos)
-
- def OnDefault(self, event=None):
- """
- Set to default
- """
- event.Skip()
- # event object and selection
- self.return_string = copy.deepcopy(DEFAULT_STRINGS)
- return self.return_string
-
- def OnCurrent(self, event=None):
- """
- Set to curent setup
- """
- event.Skip()
-
- gui_pw, gui_ph = self.parent.GetSizeTuple()
- self.current_string['GUIFRAME_WIDTH'] = gui_pw
- self.current_string['GUIFRAME_HEIGHT'] = gui_ph
- try:
- p_size = None
- for panel in self.parent.plot_panels.values():
- p_panel = self.parent._mgr.GetPane(panel.window_name)
- if p_panel.IsShown():
- if p_size == None or panel.size > p_size:
- p_size = panel.size
- if p_size == None:
- p_size = CURRENT_STRINGS['PLOPANEL_WIDTH']
- self.current_string['PLOPANEL_WIDTH'] = p_size
-
- data_pw, _ = self.parent.panels["data_panel"].GetSizeTuple()
- if data_pw == None:
- data_pw = CURRENT_STRINGS['DATAPANEL_WIDTH']
- self.current_string['DATAPANEL_WIDTH'] = data_pw
-
- #label = self.parent._data_panel_menu.GetText()
- label = self.parent._mgr.GetPane(\
- self.parent.panels['data_panel'].window_name).IsShown()
- if label:# == 'Hide Data Explorer':
- self.current_string['DATALOADER_SHOW'] = True
- else:
- self.current_string['DATALOADER_SHOW'] = False
-
- if self.parent._toolbar.IsShown():
- self.current_string['TOOLBAR_SHOW'] = True
- else:
- self.current_string['TOOLBAR_SHOW'] = False
-
- style = self._gui & GUIFRAME.FLOATING_PANEL
- if style == GUIFRAME.FLOATING_PANEL:
- self.current_string['FIXED_PANEL'] = False
- else:
- self.current_string['FIXED_PANEL'] = True
-
- if self.parent._mgr.GetPane(self.parent.panels['default'].window_name).IsShown():
- self.current_string['WELCOME_PANEL_SHOW'] = True
- else:
- self.current_string['WELCOME_PANEL_SHOW'] = False
- self.current_string['CLEANUP_PLOT'] = \
- self.parent.cleanup_plots
- perspective = self.parent.get_current_perspective()
- self.current_string['DEFAULT_PERSPECTIVE'] = str(perspective.sub_menu)
-
- except:
- raise
- # event object and selection
- self.return_string = self.current_string
- return self.return_string
-
- def OnCancel(self, event):
- """
- Close event
- """
- # clear event
- event.Skip()
- self.return_string = {}
- self.Destroy()
-
- def OnClose(self, event):
- """
- Close event
- """
- # clear event
- event.Skip()
- fname = os.path.join(self.path, 'custom_config.py')
- self.write_string(fname, self.return_string)
-
- self.Destroy()
-
- def write_string(self, fname, strings):
- """
- Write and Save file
- """
-
- try:
- out_f = open(fname,'w')
- except :
- raise #RuntimeError, "Error: Can not change the configuration..."
- out_f.write("#Application appearance custom configuration\n" )
- for key, item in strings.iteritems():
- if key == 'DEFAULT_PERSPECTIVE':
- out_f.write("%s = '%s'\n" % (key,str(item)))
- else:
- out_f.write("%s = %s\n" % (key,str(item)))
-
- out_f.close()
-
Index: test/guiframe/state_reader.py
===================================================================
--- test/guiframe/state_reader.py (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,1609 +1,0 @@
-
-
-############################################################################
-#This software was developed by the University of Tennessee as part of the
-#Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
-#project funded by the US National Science Foundation.
-#If you use DANSE applications to do scientific research that leads to
-#publication, we ask that you acknowledge the use of the software with the
-#following sentence:
-#This work benefited from DANSE software developed under NSF award DMR-0520547.
-#copyright 2008,2009 University of Tennessee
-#############################################################################
-
-# Known issue: reader not compatible with multiple SASdata entries
-# within a single SASentry. Will raise a runtime error.
-
-#TODO: check that all vectors are written only if they have at
-# least one non-empty value
-#TODO: Writing only allows one SASentry per file.
-# Would be best to allow multiple entries.
-#TODO: Store error list
-#TODO: Allow for additional meta data for each section
-#TODO: Notes need to be implemented. They can be any XML
-# structure in version 1.0
-# Process notes have the same problem.
-#TODO: Unit conversion is not complete (temperature units are missing)
-
-
-import logging
-import numpy
-import os
-import sys
-from sans.guiframe.dataFitting import Data1D
-from sans.guiframe.dataFitting import Data2D
-from DataLoader.data_info import Collimation
-from DataLoader.data_info import Detector
-from DataLoader.data_info import Process
-from DataLoader.data_info import Aperture
-from lxml import etree
-import xml.dom.minidom
-
-has_converter = True
-try:
- from data_util.nxsunit import Converter
-except:
- has_converter = False
-
-STATE_NS = "State/1.0"
-
-def write_node(doc, parent, name, value, attr={}):
- """
- :param doc: document DOM
- :param parent: parent node
- :param name: tag of the element
- :param value: value of the child text node
- :param attr: attribute dictionary
-
- :return: True if something was appended, otherwise False
- """
- if value is not None:
- node = doc.createElement(name)
- node.appendChild(doc.createTextNode(str(value)))
- for item in attr:
- node.setAttribute(item, attr[item])
- parent.appendChild(node)
- return True
- return False
-
-def get_content(location, node):
- """
- Get the first instance of the content of a xpath location.
-
- :param location: xpath location
- :param node: node to start at
-
- :return: Element, or None
- """
- nodes = node.xpath(location, namespaces={'ns': STATE_NODE})
-
- if len(nodes)>0:
- return nodes[0]
- else:
- return None
-
-def get_float(location, node):
- """
- Get the content of a node as a float
-
- :param location: xpath location
- :param node: node to start at
- """
- nodes = node.xpath(location, namespaces={'ns': STATE_NODE})
-
- value = None
- attr = {}
- if len(nodes) > 0:
- try:
- value = float(nodes[0].text)
- except:
- # Could not pass, skip and return None
- msg = "state_reader.get_float: could not "
- msg += " convert '%s' to float" % nodes[0].text
- logging.error(msg)
- if nodes[0].get('unit') is not None:
- attr['unit'] = nodes[0].get('unit')
- return value, attr
-
-
-class Reader1D:
- """
- read state of a plugin and available data
-
- :Dependencies:
- The CanSas reader requires PyXML 0.8.4 or later.
- """
- ## CanSAS version
- version = '1.0'
- ## File type
- type_name = "CanSAS 1D"
- ## Wildcards
- type = []
-
- ## List of allowed extensions
- ext = []
-
- def __init__(self):
- ## List of errors
- self.errors = []
-
- def read(self, path):
- """
- Load data file
-
- :param path: file path
-
- :return: Data1D object if a single SASentry was found,
- or a list of Data1D objects if multiple entries were found,
- or None of nothing was found
-
- :raise RuntimeError: when the file can't be opened
- :raise ValueError: when the length of the data vectors are inconsistent
- """
- output = []
- if os.path.isfile(path):
- basename = os.path.basename(path)
- root, extension = os.path.splitext(basename)
- if extension.lower() in self.ext:
-
- tree = etree.parse(path, parser=etree.ETCompatXMLParser())
- # Check the format version number
- # Specifying the namespace will take care of the file
- # format version
- root = tree.getroot()
-
- entry_list = root.xpath('/ns:SASroot/ns:SASentry',
- namespaces={'ns': STATE_NODE})
-
- for entry in entry_list:
- self.errors = []
- sas_entry = self._parse_entry(entry)
- sas_entry.filename = basename
-
- # Store loading process information
- sas_entry.errors = self.errors
- sas_entry.meta_data['loader'] = self.type_name
- output.append(sas_entry)
-
- else:
- raise RuntimeError, "%s is not a file" % path
- # Return output consistent with the loader's api
- if len(output) == 0:
- #cannot return none when it cannot read
- #return None
- raise RuntimeError, "%s cannot be read \n" % path
- elif len(output) == 1:
- return output[0]
- else:
- return output
-
- def _parse_entry(self, dom):
- """
- Parse a SASentry
-
- :param node: SASentry node
-
- :return: Data1D object
- """
- x = numpy.zeros(0)
- y = numpy.zeros(0)
-
- data_info = Data1D(x, y)
-
- # Look up title
- self._store_content('ns:Title', dom, 'title', data_info)
-
- # Look up run number
- nodes = dom.xpath('ns:Run', namespaces={'ns': STATE_NODE})
- for item in nodes:
- if item.text is not None:
- value = item.text.strip()
- if len(value) > 0:
- data_info.run.append(value)
- if item.get('name') is not None:
- data_info.run_name[value] = item.get('name')
-
- # Look up instrument name
- self._store_content('ns:SASinstrument/ns:name', dom, 'instrument',
- data_info)
-
- # Notes
- note_list = dom.xpath('ns:SASnote', namespaces={'ns': STATE_NODE})
- for note in note_list:
- try:
- if note.text is not None:
- note_value = note.text.strip()
- if len(note_value) > 0:
- data_info.notes.append(note_value)
- except:
- err_mess = "state_reader.read: error processing"
- err_mess += " entry notes\n %s" % sys.exc_value
- self.errors.append(err_mess)
- logging.error(err_mess)
-
- # Sample info ###################
- entry = get_content('ns:SASsample', dom)
- if entry is not None:
- data_info.sample.name = entry.get('name')
-
- self._store_content('ns:SASsample/ns:ID',
- dom, 'ID', data_info.sample)
- self._store_float('ns:SASsample/ns:thickness',
- dom, 'thickness', data_info.sample)
- self._store_float('ns:SASsample/ns:transmission',
- dom, 'transmission', data_info.sample)
- self._store_float('ns:SASsample/ns:temperature',
- dom, 'temperature', data_info.sample)
-
- nodes = dom.xpath('ns:SASsample/ns:details',
- namespaces={'ns': STATE_NODE})
- for item in nodes:
- try:
- if item.text is not None:
- detail_value = item.text.strip()
- if len(detail_value) > 0:
- data_info.sample.details.append(detail_value)
- except:
- err_mess = "state_reader.read: error processing "
- err_mess += " sample details\n %s" % sys.exc_value
- self.errors.append(err_mess)
- logging.error(err_mess)
-
- # Position (as a vector)
- self._store_float('ns:SASsample/ns:position/ns:x',
- dom, 'position.x', data_info.sample)
- self._store_float('ns:SASsample/ns:position/ns:y',
- dom, 'position.y', data_info.sample)
- self._store_float('ns:SASsample/ns:position/ns:z',
- dom, 'position.z', data_info.sample)
-
- # Orientation (as a vector)
- self._store_float('ns:SASsample/ns:orientation/ns:roll',
- dom, 'orientation.x', data_info.sample)
- self._store_float('ns:SASsample/ns:orientation/ns:pitch',
- dom, 'orientation.y', data_info.sample)
- self._store_float('ns:SASsample/ns:orientation/ns:yaw',
- dom, 'orientation.z', data_info.sample)
-
- # Source info ###################
- entry = get_content('ns:SASinstrument/ns:SASsource', dom)
- if entry is not None:
- data_info.source.name = entry.get('name')
-
- self._store_content('ns:SASinstrument/ns:SASsource/ns:radiation',
- dom, 'radiation', data_info.source)
- self._store_content('ns:SASinstrument/ns:SASsource/ns:beam_shape',
- dom, 'beam_shape', data_info.source)
- self._store_float('ns:SASinstrument/ns:SASsource/ns:wavelength',
- dom, 'wavelength', data_info.source)
- self._store_float('ns:SASinstrument/ns:SASsource/ns:wavelength_min',
- dom, 'wavelength_min', data_info.source)
- self._store_float('ns:SASinstrument/ns:SASsource/ns:wavelength_max',
- dom, 'wavelength_max', data_info.source)
- self._store_float('ns:SASinstrument/ns:SASsource/ns:wavelength_spread',
- dom, 'wavelength_spread', data_info.source)
-
- # Beam size (as a vector)
- entry = get_content('ns:SASinstrument/ns:SASsource/ns:beam_size', dom)
- if entry is not None:
- data_info.source.beam_size_name = entry.get('name')
-
- self._store_float('ns:SASinstrument/ns:SASsource/ns:beam_size/ns:x',
- dom, 'beam_size.x', data_info.source)
- self._store_float('ns:SASinstrument/ns:SASsource/ns:beam_size/ns:y',
- dom, 'beam_size.y', data_info.source)
- self._store_float('ns:SASinstrument/ns:SASsource/ns:beam_size/ns:z',
- dom, 'beam_size.z', data_info.source)
-
- # Collimation info ###################
- nodes = dom.xpath('ns:SASinstrument/ns:SAScollimation',
- namespaces={'ns': STATE_NODE})
- for item in nodes:
- collim = Collimation()
- if item.get('name') is not None:
- collim.name = item.get('name')
- self._store_float('ns:length', item, 'length', collim)
-
- # Look for apertures
- apert_list = item.xpath('ns:aperture', namespaces={'ns': STATE_NODE})
- for apert in apert_list:
- aperture = Aperture()
-
- # Get the name and type of the aperture
- aperture.name = apert.get('name')
- aperture.type = apert.get('type')
-
- self._store_float('ns:distance', apert, 'distance', aperture)
-
- entry = get_content('ns:size', apert)
- if entry is not None:
- aperture.size_name = entry.get('name')
-
- self._store_float('ns:size/ns:x', apert, 'size.x', aperture)
- self._store_float('ns:size/ns:y', apert, 'size.y', aperture)
- self._store_float('ns:size/ns:z', apert, 'size.z', aperture)
-
- collim.aperture.append(aperture)
-
- data_info.collimation.append(collim)
-
- # Detector info ######################
- nodes = dom.xpath('ns:SASinstrument/ns:SASdetector',
- namespaces={'ns': STATE_NODE})
- for item in nodes:
-
- detector = Detector()
-
- self._store_content('ns:name', item, 'name', detector)
- self._store_float('ns:SDD', item, 'distance', detector)
-
- # Detector offset (as a vector)
- self._store_float('ns:offset/ns:x', item, 'offset.x', detector)
- self._store_float('ns:offset/ns:y', item, 'offset.y', detector)
- self._store_float('ns:offset/ns:z', item, 'offset.z', detector)
-
- # Detector orientation (as a vector)
- self._store_float('ns:orientation/ns:roll', item, 'orientation.x',
- detector)
- self._store_float('ns:orientation/ns:pitch', item, 'orientation.y',
- detector)
- self._store_float('ns:orientation/ns:yaw', item, 'orientation.z',
- detector)
-
- # Beam center (as a vector)
- self._store_float('ns:beam_center/ns:x', item, 'beam_center.x',
- detector)
- self._store_float('ns:beam_center/ns:y', item, 'beam_center.y',
- detector)
- self._store_float('ns:beam_center/ns:z', item, 'beam_center.z',
- detector)
-
- # Pixel size (as a vector)
- self._store_float('ns:pixel_size/ns:x', item, 'pixel_size.x',
- detector)
- self._store_float('ns:pixel_size/ns:y', item, 'pixel_size.y',
- detector)
- self._store_float('ns:pixel_size/ns:z', item, 'pixel_size.z',
- detector)
-
- self._store_float('ns:slit_length', item, 'slit_length', detector)
-
- data_info.detector.append(detector)
-
- # Processes info ######################
- nodes = dom.xpath('ns:SASprocess', namespaces={'ns': STATE_NODE})
- for item in nodes:
- process = Process()
- self._store_content('ns:name', item, 'name', process)
- self._store_content('ns:date', item, 'date', process)
- self._store_content('ns:description', item, 'description', process)
-
- term_list = item.xpath('ns:term', namespaces={'ns': STATE_NODE})
- for term in term_list:
- try:
- term_attr = {}
- for attr in term.keys():
- term_attr[attr] = term.get(attr).strip()
- if term.text is not None:
- term_attr['value'] = term.text.strip()
- process.term.append(term_attr)
- except:
- err_mess = "state_reader.read: error processing "
- err_mess += " process term\n %s" % sys.exc_value
- self.errors.append(err_mess)
- logging.error(err_mess)
-
- note_list = item.xpath('ns:SASprocessnote',
- namespaces={'ns': STATE_NODE})
- for note in note_list:
- if note.text is not None:
- process.notes.append(note.text.strip())
-
- data_info.process.append(process)
-
-
- # Data info ######################
- nodes = dom.xpath('ns:SASdata', namespaces={'ns': STATE_NODE})
- if len(nodes) > 1:
- msg = "CanSAS reader is not compatible with multiple"
- msg += " SASdata entries"
- raise RuntimeError, msg
-
- nodes = dom.xpath('ns:SASdata/ns:Idata', namespaces={'ns': STATE_NODE})
-
- x = numpy.zeros(0)
- y = numpy.zeros(0)
- dx = numpy.zeros(0)
- dy = numpy.zeros(0)
- dxw = numpy.zeros(0)
- dxl = numpy.zeros(0)
-
- for item in nodes:
- _x, attr = get_float('ns:Q', item)
- _dx, attr_d = get_float('ns:Qdev', item)
- _dxl, attr_l = get_float('ns:dQl', item)
- _dxw, attr_w = get_float('ns:dQw', item)
- if _dx == None:
- _dx = 0.0
- if _dxl == None:
- _dxl = 0.0
- if _dxw == None:
- _dxw = 0.0
-
- if attr.has_key('unit') and \
- attr['unit'].lower() != data_info.x_unit.lower():
- if has_converter==True:
- try:
- data_conv_q = Converter(attr['unit'])
- _x = data_conv_q(_x, units=data_info.x_unit)
- except:
- msg = "CanSAS reader: could not convert "
- msg += "Q unit [%s]; "
- msg += "expecting [%s]\n %s" % (attr['unit'],
- data_info.x_unit, sys.exc_value)
- raise ValueError, msg
-
- else:
- msg = "CanSAS reader: unrecognized Q unit [%s]; "
- msg += "expecting [%s]" % (attr['unit'], data_info.x_unit)
- raise ValueError, msg
-
- # Error in Q
- if attr_d.has_key('unit') and \
- attr_d['unit'].lower() != data_info.x_unit.lower():
- if has_converter==True:
- try:
- data_conv_q = Converter(attr_d['unit'])
- _dx = data_conv_q(_dx, units=data_info.x_unit)
- except:
- msg = "CanSAS reader: could not convert dQ unit [%s];"
- msg += " expecting "
- msg += "[%s]\n %s" % (attr['unit'],
- data_info.x_unit, sys.exc_value)
- raise ValueError, msg
-
- else:
- msg = "CanSAS reader: unrecognized dQ unit [%s]; "
- msg += "expecting [%s]" % (attr['unit'], data_info.x_unit)
- raise ValueError, msg
-
- # Slit length
- if attr_l.has_key('unit') and \
- attr_l['unit'].lower() != data_info.x_unit.lower():
- if has_converter == True:
- try:
- data_conv_q = Converter(attr_l['unit'])
- _dxl = data_conv_q(_dxl, units=data_info.x_unit)
- except:
- msg = "CanSAS reader: could not convert dQl unit [%s];"
- msg += " expecting [%s]\n %s" % (attr['unit'],
- data_info.x_unit, sys.exc_value)
- raise ValueError, msg
-
- else:
- msg = "CanSAS reader: unrecognized dQl unit [%s];"
- msg += " expecting [%s]" % (attr['unit'], data_info.x_unit)
- raise ValueError, msg
-
- # Slit width
- if attr_w.has_key('unit') and \
- attr_w['unit'].lower() != data_info.x_unit.lower():
- if has_converter == True:
- try:
- data_conv_q = Converter(attr_w['unit'])
- _dxw = data_conv_q(_dxw, units=data_info.x_unit)
- except:
- msg = "CanSAS reader: could not convert dQw unit [%s];"
- msg += " expecting [%s]\n %s" % (attr['unit'],
- data_info.x_unit, sys.exc_value)
- raise ValueError, msg
-
- else:
- msg = "CanSAS reader: unrecognized dQw unit [%s];"
- msg += " expecting [%s]" % (attr['unit'], data_info.x_unit)
- raise ValueError, msg
- _y, attr = get_float('ns:I', item)
- _dy, attr_d = get_float('ns:Idev', item)
- if _dy == None:
- _dy = 0.0
- if attr.has_key('unit') and \
- attr['unit'].lower() != data_info.y_unit.lower():
- if has_converter==True:
- try:
- data_conv_i = Converter(attr['unit'])
- _y = data_conv_i(_y, units=data_info.y_unit)
- except:
- msg = "CanSAS reader: could not convert I(q) unit [%s];"
- msg += " expecting [%s]\n %s" % (attr['unit'],
- data_info.y_unit, sys.exc_value)
- raise ValueError, msg
- else:
- msg = "CanSAS reader: unrecognized I(q) unit [%s];"
- msg += " expecting [%s]" % (attr['unit'], data_info.y_unit)
- raise ValueError, msg
-
- if attr_d.has_key('unit') and \
- attr_d['unit'].lower() != data_info.y_unit.lower():
- if has_converter==True:
- try:
- data_conv_i = Converter(attr_d['unit'])
- _dy = data_conv_i(_dy, units=data_info.y_unit)
- except:
- msg = "CanSAS reader: could not convert dI(q) unit "
- msg += "[%s]; expecting [%s]\n %s" % (attr_d['unit'],
- data_info.y_unit, sys.exc_value)
- raise ValueError, msg
- else:
- msg = "CanSAS reader: unrecognized dI(q) unit [%s]; "
- msg += "expecting [%s]" % (attr_d['unit'], data_info.y_unit)
- raise ValueError, msg
-
- if _x is not None and _y is not None:
- x = numpy.append(x, _x)
- y = numpy.append(y, _y)
- dx = numpy.append(dx, _dx)
- dy = numpy.append(dy, _dy)
- dxl = numpy.append(dxl, _dxl)
- dxw = numpy.append(dxw, _dxw)
-
- data_info.x = x
- data_info.y = y
- data_info.dx = dx
- data_info.dy = dy
- data_info.dxl = dxl
- data_info.dxw = dxw
-
- data_conv_q = None
- data_conv_i = None
-
- if has_converter == True and data_info.x_unit != '1/A':
- data_conv_q = Converter('1/A')
- # Test it
- data_conv_q(1.0, output.Q_unit)
-
- if has_converter == True and data_info.y_unit != '1/cm':
- data_conv_i = Converter('1/cm')
- # Test it
- data_conv_i(1.0, output.I_unit)
-
- if data_conv_q is not None:
- data_info.xaxis("\\rm{Q}", data_info.x_unit)
- else:
- data_info.xaxis("\\rm{Q}", 'A^{-1}')
- if data_conv_i is not None:
- data_info.yaxis("\\rm{Intensity}", data_info.y_unit)
- else:
- data_info.yaxis("\\rm{Intensity}","cm^{-1}")
-
- return data_info
-
- def _to_xml_doc(self, datainfo):
- """
- Create an XML document to contain the content of a Data1D
-
- :param datainfo: Data1D object
- """
-
- if not issubclass(datainfo.__class__, Data1D):
- raise RuntimeError, "The cansas writer expects a Data1D instance"
-
- doc = xml.dom.minidom.Document()
- main_node = doc.createElement("SASroot")
- main_node.setAttribute("version", self.version)
- main_node.setAttribute("xmlns", "cansas1d/%s" % self.version)
- main_node.setAttribute("xmlns:xsi",
- "http://www.w3.org/2001/XMLSchema-instance")
- main_node.setAttribute("xsi:schemaLocation",
- "cansas1d/%s http://svn.smallangles.net/svn/canSAS/1dwg/trunk/cansas1d.xsd" % self.version)
-
- doc.appendChild(main_node)
-
- entry_node = doc.createElement("SASentry")
- main_node.appendChild(entry_node)
-
- write_node(doc, entry_node, "Title", datainfo.title)
- for item in datainfo.run:
- runname = {}
- if datainfo.run_name.has_key(item) and \
- len(str(datainfo.run_name[item]))>1:
- runname = {'name': datainfo.run_name[item] }
- write_node(doc, entry_node, "Run", item, runname)
-
- # Data info
- node = doc.createElement("SASdata")
- entry_node.appendChild(node)
-
- for i in range(len(datainfo.x)):
- pt = doc.createElement("Idata")
- node.appendChild(pt)
- write_node(doc, pt, "Q", datainfo.x[i], {'unit':datainfo.x_unit})
- if len(datainfo.y)>=i:
- write_node(doc, pt, "I", datainfo.y[i],
- {'unit':datainfo.y_unit})
- if datainfo.dx != None and len(datainfo.dx) >= i:
- write_node(doc, pt, "Qdev", datainfo.dx[i],
- {'unit':datainfo.x_unit})
- if datainfo.dxl != None and len(datainfo.dxl) >= i:
- write_node(doc, pt, "dQl", datainfo.dxl[i],
- {'unit':datainfo.x_unit})
- if datainfo.dxw != None and len(datainfo.dxw) >= i:
- write_node(doc, pt, "dQw", datainfo.dxw[i],
- {'unit':datainfo.x_unit})
- if datainfo.dy != None and len(datainfo.dy) >= i:
- write_node(doc, pt, "Idev", datainfo.dy[i],
- {'unit':datainfo.y_unit})
- #data gui info
- gui_info = doc.createElement("DataInfoGui")
-
- write_node(doc, gui_info, "group_id", 'group_id')
- for item in datainfo.group_id:
- write_node(doc, gui_info, "group_id", str(item))
- write_node(doc, gui_info, "name", datainfo.name)
- write_node(doc, gui_info, "id", datainfo.id)
- write_node(doc, gui_info, "group_id", datainfo.groud_id)
- write_node(doc, gui_info, "name", datainfo.name)
- write_node(doc, gui_info, "is_data", datainfo.is_data)
- write_node(doc, gui_info, "xtransform", datainfo.xtransform)
- write_node(doc, gui_info, "scale", datainfo.scale)
- write_node(doc, gui_info, "ytransform", datainfo.ytransform)
- write_node(doc, gui_info, "path", datainfo.path)
- node.appendChild(gui_info)
- # Sample info
- sample = doc.createElement("SASsample")
- if datainfo.sample.name is not None:
- sample.setAttribute("name", str(datainfo.sample.name))
- entry_node.appendChild(sample)
- write_node(doc, sample, "ID", str(datainfo.sample.ID))
- write_node(doc, sample, "thickness", datainfo.sample.thickness,
- {"unit":datainfo.sample.thickness_unit})
- write_node(doc, sample, "transmission", datainfo.sample.transmission)
- write_node(doc, sample, "temperature", datainfo.sample.temperature,
- {"unit":datainfo.sample.temperature_unit})
-
- for item in datainfo.sample.details:
- write_node(doc, sample, "details", item)
-
- pos = doc.createElement("position")
- written = write_node(doc, pos, "x", datainfo.sample.position.x,
- {"unit":datainfo.sample.position_unit})
- written = written | write_node(doc, pos, "y",
- datainfo.sample.position.y,
- {"unit":datainfo.sample.position_unit})
- written = written | write_node(doc, pos, "z",
- datainfo.sample.position.z,
- {"unit":datainfo.sample.position_unit})
- if written == True:
- sample.appendChild(pos)
-
- ori = doc.createElement("orientation")
- written = write_node(doc, ori, "roll",
- datainfo.sample.orientation.x,
- {"unit":datainfo.sample.orientation_unit})
- written = written | write_node(doc, ori, "pitch",
- datainfo.sample.orientation.y,
- {"unit":datainfo.sample.orientation_unit})
- written = written | write_node(doc, ori, "yaw",
- datainfo.sample.orientation.z,
- {"unit":datainfo.sample.orientation_unit})
- if written == True:
- sample.appendChild(ori)
-
- # Instrument info
- instr = doc.createElement("SASinstrument")
- entry_node.appendChild(instr)
-
- write_node(doc, instr, "name", datainfo.instrument)
-
- # Source
- source = doc.createElement("SASsource")
- if datainfo.source.name is not None:
- source.setAttribute("name", str(datainfo.source.name))
- instr.appendChild(source)
-
- write_node(doc, source, "radiation", datainfo.source.radiation)
- write_node(doc, source, "beam_shape", datainfo.source.beam_shape)
- size = doc.createElement("beam_size")
- if datainfo.source.beam_size_name is not None:
- size.setAttribute("name", str(datainfo.source.beam_size_name))
- written = write_node(doc, size, "x", datainfo.source.beam_size.x,
- {"unit":datainfo.source.beam_size_unit})
- written = written | write_node(doc, size, "y",
- datainfo.source.beam_size.y,
- {"unit":datainfo.source.beam_size_unit})
- written = written | write_node(doc, size, "z",
- datainfo.source.beam_size.z,
- {"unit":datainfo.source.beam_size_unit})
- if written == True:
- source.appendChild(size)
-
- write_node(doc, source, "wavelength",
- datainfo.source.wavelength,
- {"unit":datainfo.source.wavelength_unit})
- write_node(doc, source, "wavelength_min",
- datainfo.source.wavelength_min,
- {"unit":datainfo.source.wavelength_min_unit})
- write_node(doc, source, "wavelength_max",
- datainfo.source.wavelength_max,
- {"unit":datainfo.source.wavelength_max_unit})
- write_node(doc, source, "wavelength_spread",
- datainfo.source.wavelength_spread,
- {"unit":datainfo.source.wavelength_spread_unit})
-
- # Collimation
- for item in datainfo.collimation:
- coll = doc.createElement("SAScollimation")
- if item.name is not None:
- coll.setAttribute("name", str(item.name))
- instr.appendChild(coll)
-
- write_node(doc, coll, "length", item.length,
- {"unit":item.length_unit})
-
- for apert in item.aperture:
- ap = doc.createElement("aperture")
- if apert.name is not None:
- ap.setAttribute("name", str(apert.name))
- if apert.type is not None:
- ap.setAttribute("type", str(apert.type))
- coll.appendChild(ap)
-
- write_node(doc, ap, "distance", apert.distance,
- {"unit":apert.distance_unit})
-
- size = doc.createElement("size")
- if apert.size_name is not None:
- size.setAttribute("name", str(apert.size_name))
- written = write_node(doc, size, "x", apert.size.x,
- {"unit":apert.size_unit})
- written = written | write_node(doc, size, "y", apert.size.y,
- {"unit":apert.size_unit})
- written = written | write_node(doc, size, "z", apert.size.z,
- {"unit":apert.size_unit})
- if written == True:
- ap.appendChild(size)
-
- # Detectors
- for item in datainfo.detector:
- det = doc.createElement("SASdetector")
- written = write_node(doc, det, "name", item.name)
- written = written | write_node(doc, det, "SDD", item.distance,
- {"unit":item.distance_unit})
- written = written | write_node(doc, det, "slit_length",
- item.slit_length,
- {"unit":item.slit_length_unit})
- if written == True:
- instr.appendChild(det)
-
- off = doc.createElement("offset")
- written = write_node(doc, off, "x", item.offset.x,
- {"unit":item.offset_unit})
- written = written | write_node(doc, off, "y", item.offset.y,
- {"unit":item.offset_unit})
- written = written | write_node(doc, off, "z", item.offset.z,
- {"unit":item.offset_unit})
- if written == True:
- det.appendChild(off)
-
- center = doc.createElement("beam_center")
- written = write_node(doc, center, "x", item.beam_center.x,
- {"unit":item.beam_center_unit})
- written = written | write_node(doc, center, "y",
- item.beam_center.y,
- {"unit":item.beam_center_unit})
- written = written | write_node(doc, center, "z",
- item.beam_center.z,
- {"unit":item.beam_center_unit})
- if written == True:
- det.appendChild(center)
-
- pix = doc.createElement("pixel_size")
- written = write_node(doc, pix, "x", item.pixel_size.x,
- {"unit":item.pixel_size_unit})
- written = written | write_node(doc, pix, "y", item.pixel_size.y,
- {"unit":item.pixel_size_unit})
- written = written | write_node(doc, pix, "z", item.pixel_size.z,
- {"unit":item.pixel_size_unit})
- if written == True:
- det.appendChild(pix)
-
- ori = doc.createElement("orientation")
- written = write_node(doc, ori, "roll", item.orientation.x,
- {"unit":item.orientation_unit})
- written = written | write_node(doc, ori, "pitch",
- item.orientation.y,
- {"unit":item.orientation_unit})
- written = written | write_node(doc, ori, "yaw",
- item.orientation.z,
- {"unit":item.orientation_unit})
- if written == True:
- det.appendChild(ori)
-
-
- # Processes info
- for item in datainfo.process:
- node = doc.createElement("SASprocess")
- entry_node.appendChild(node)
-
- write_node(doc, node, "name", item.name)
- write_node(doc, node, "date", item.date)
- write_node(doc, node, "description", item.description)
- for term in item.term:
- value = term['value']
- del term['value']
- write_node(doc, node, "term", value, term)
- for note in item.notes:
- write_node(doc, node, "SASprocessnote", note)
-
- # Return the document, and the SASentry node associated with
- # the data we just wrote
- return doc, entry_node
-
- def write(self, filename, datainfo):
- """
- Write the content of a Data1D as a CanSAS XML file
-
- :param filename: name of the file to write
- :param datainfo: Data1D object
- """
- # Create XML document
- doc, sasentry = self._to_xml_doc(datainfo)
- # Write the file
- fd = open(filename, 'w')
- fd.write(doc.toprettyxml())
- fd.close()
-
- def _store_float(self, location, node, variable, storage, optional=True):
- """
- Get the content of a xpath location and store
- the result. Check that the units are compatible
- with the destination. The value is expected to
- be a float.
-
- The xpath location might or might not exist.
- If it does not exist, nothing is done
-
- :param location: xpath location to fetch
- :param node: node to read the data from
- :param variable: name of the data member to store it in [string]
- :param storage: data object that has the 'variable' data member
- :param optional: if True, no exception will be raised
- if unit conversion can't be done
-
- :raise ValueError: raised when the units are not recognized
- """
- entry = get_content(location, node)
- try:
- value = float(entry.text)
- except:
- value = None
-
- if value is not None:
- # If the entry has units, check to see that they are
- # compatible with what we currently have in the data object
- units = entry.get('unit')
- if units is not None:
- toks = variable.split('.')
- exec "local_unit = storage.%s_unit" % toks[0]
- if units.lower()!=local_unit.lower():
- if has_converter==True:
- try:
- conv = Converter(units)
- exec "storage.%s = %g" % (variable,
- conv(value, units=local_unit))
- except:
- err_mess = "CanSAS reader: could not convert"
- err_mess += " %s unit [%s]; expecting [%s]\n %s" \
- % (variable, units, local_unit, sys.exc_value)
- self.errors.append(err_mess)
- if optional:
- logging.info(err_mess)
- else:
- raise ValueError, err_mess
- else:
- err_mess = "CanSAS reader: unrecognized %s unit [%s];"
- err_mess += " expecting [%s]" % (variable,
- units, local_unit)
- self.errors.append(err_mess)
- if optional:
- logging.info(err_mess)
- else:
- raise ValueError, err_mess
- else:
- exec "storage.%s = value" % variable
- else:
- exec "storage.%s = value" % variable
-
- def _store_content(self, location, node, variable, storage):
- """
- Get the content of a xpath location and store
- the result. The value is treated as a string.
-
- The xpath location might or might not exist.
- If it does not exist, nothing is done
-
- :param location: xpath location to fetch
- :param node: node to read the data from
- :param variable: name of the data member to store it in [string]
- :param storage: data object that has the 'variable' data member
-
- :return: return a list of errors
- """
- entry = get_content(location, node)
- if entry is not None and entry.text is not None:
- exec "storage.%s = entry.text.strip()" % variable
-
-
-
-class Reader2D:
- """
- Class to load a basic guiframe state
- """
- ## File type
- type_name = "Fitting"
-
- ## Wildcards
- type = ["Fitting files (*.fitv)|*.fitv"
- "SANSView file (*.svs)|*.svs"]
- ## List of allowed extensions
- ext=['.fitv', '.FITV', '.svs', 'SVS']
-
- def __init__(self):
- CansasReader.__init__(self)
- """
- Initialize the call-back method to be called
- after we load a file
-
- :param call_back: call-back method
- :param cansas: True = files will be written/read in CanSAS format
- False = write CanSAS format
-
- """
- ## Call back method to be executed after a file is read
- #self.call_back = call_back
- ## CanSAS format flag
- self.cansas = cansas
- self.state = None
-
- def read(self, path):
- """
- Load a new P(r) inversion state from file
-
- :param path: file path
-
- """
- if self.cansas == True:
- return self._read_cansas(path)
-
- def _to_xml_doc(self, datainfo):
- """
- Create an XML document to contain the content of a Data2D
-
- :param datainfo: Data2D object
-
- """
- if not issubclass(datainfo.__class__, Data2D):
- raise RuntimeError, "The cansas writer expects a Data2D instance"
-
- doc = xml.dom.minidom.Document()
- main_node = doc.createElement("SASroot")
- main_node.setAttribute("version", self.version)
- main_node.setAttribute("xmlns", "cansas1d/%s" % self.version)
- main_node.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance")
- main_node.setAttribute("xsi:schemaLocation", "cansas1d/%s http://svn.smallangles.net/svn/canSAS/1dwg/trunk/cansas1d.xsd" % self.version)
-
- doc.appendChild(main_node)
-
- entry_node = doc.createElement("SASentry")
- main_node.appendChild(entry_node)
-
- write_node(doc, entry_node, "Title", datainfo.title)
- if datainfo is not None:
- write_node(doc, entry_node, "data_class", datainfo.__class__.__name__)
- for item in datainfo.run:
- runname = {}
- if datainfo.run_name.has_key(item) and len(str(datainfo.run_name[item]))>1:
- runname = {'name': datainfo.run_name[item] }
- write_node(doc, entry_node, "Run", item, runname)
- # Data info
- new_node = doc.createElement("SASdata")
- entry_node.appendChild(new_node)
- for item in list_of_data_2d_attr:
- element = doc.createElement(item[0])
- exec "element.setAttribute(item[0], str(datainfo.%s))"%(item[1])
- new_node.appendChild(element)
-
- for item in list_of_data2d_values:
- root_node = doc.createElement(item[0])
- new_node.appendChild(root_node)
-
- exec "temp_list = datainfo.%s"%item[1]
-
- if temp_list is None or len(temp_list)== 0:
- element = doc.createElement(item[0])
- exec "element.appendChild(doc.createTextNode(str(%s)))"%temp_list
- root_node.appendChild(element)
- else:
- for value in temp_list:
- element = doc.createElement(item[0])
- exec "element.setAttribute(item[0], str(%s))"%value
- root_node.appendChild(element)
-
- # Sample info
- sample = doc.createElement("SASsample")
- if datainfo.sample.name is not None:
- sample.setAttribute("name", str(datainfo.sample.name))
- entry_node.appendChild(sample)
- write_node(doc, sample, "ID", str(datainfo.sample.ID))
- write_node(doc, sample, "thickness", datainfo.sample.thickness, {"unit":datainfo.sample.thickness_unit})
- write_node(doc, sample, "transmission", datainfo.sample.transmission)
- write_node(doc, sample, "temperature", datainfo.sample.temperature, {"unit":datainfo.sample.temperature_unit})
-
- for item in datainfo.sample.details:
- write_node(doc, sample, "details", item)
-
- pos = doc.createElement("position")
- written = write_node(doc, pos, "x", datainfo.sample.position.x, {"unit":datainfo.sample.position_unit})
- written = written | write_node(doc, pos, "y", datainfo.sample.position.y, {"unit":datainfo.sample.position_unit})
- written = written | write_node(doc, pos, "z", datainfo.sample.position.z, {"unit":datainfo.sample.position_unit})
- if written == True:
- sample.appendChild(pos)
-
- ori = doc.createElement("orientation")
- written = write_node(doc, ori, "roll", datainfo.sample.orientation.x, {"unit":datainfo.sample.orientation_unit})
- written = written | write_node(doc, ori, "pitch", datainfo.sample.orientation.y, {"unit":datainfo.sample.orientation_unit})
- written = written | write_node(doc, ori, "yaw", datainfo.sample.orientation.z, {"unit":datainfo.sample.orientation_unit})
- if written == True:
- sample.appendChild(ori)
-
- # Instrument info
- instr = doc.createElement("SASinstrument")
- entry_node.appendChild(instr)
-
- write_node(doc, instr, "name", datainfo.instrument)
-
- # Source
- source = doc.createElement("SASsource")
- if datainfo.source.name is not None:
- source.setAttribute("name", str(datainfo.source.name))
- instr.appendChild(source)
-
- write_node(doc, source, "radiation", datainfo.source.radiation)
- write_node(doc, source, "beam_shape", datainfo.source.beam_shape)
- size = doc.createElement("beam_size")
- if datainfo.source.beam_size_name is not None:
- size.setAttribute("name", str(datainfo.source.beam_size_name))
- written = write_node(doc, size, "x", datainfo.source.beam_size.x, {"unit":datainfo.source.beam_size_unit})
- written = written | write_node(doc, size, "y", datainfo.source.beam_size.y, {"unit":datainfo.source.beam_size_unit})
- written = written | write_node(doc, size, "z", datainfo.source.beam_size.z, {"unit":datainfo.source.beam_size_unit})
- if written == True:
- source.appendChild(size)
-
- write_node(doc, source, "wavelength", datainfo.source.wavelength, {"unit":datainfo.source.wavelength_unit})
- write_node(doc, source, "wavelength_min", datainfo.source.wavelength_min, {"unit":datainfo.source.wavelength_min_unit})
- write_node(doc, source, "wavelength_max", datainfo.source.wavelength_max, {"unit":datainfo.source.wavelength_max_unit})
- write_node(doc, source, "wavelength_spread", datainfo.source.wavelength_spread, {"unit":datainfo.source.wavelength_spread_unit})
-
- # Collimation
- for item in datainfo.collimation:
- coll = doc.createElement("SAScollimation")
- if item.name is not None:
- coll.setAttribute("name", str(item.name))
- instr.appendChild(coll)
-
- write_node(doc, coll, "length", item.length, {"unit":item.length_unit})
-
- for apert in item.aperture:
- ap = doc.createElement("aperture")
- if apert.name is not None:
- ap.setAttribute("name", str(apert.name))
- if apert.type is not None:
- ap.setAttribute("type", str(apert.type))
- coll.appendChild(ap)
-
- write_node(doc, ap, "distance", apert.distance, {"unit":apert.distance_unit})
-
- size = doc.createElement("size")
- if apert.size_name is not None:
- size.setAttribute("name", str(apert.size_name))
- written = write_node(doc, size, "x", apert.size.x, {"unit":apert.size_unit})
- written = written | write_node(doc, size, "y", apert.size.y, {"unit":apert.size_unit})
- written = written | write_node(doc, size, "z", apert.size.z, {"unit":apert.size_unit})
- if written == True:
- ap.appendChild(size)
-
- # Detectors
- for item in datainfo.detector:
- det = doc.createElement("SASdetector")
- written = write_node(doc, det, "name", item.name)
- written = written | write_node(doc, det, "SDD", item.distance, {"unit":item.distance_unit})
- written = written | write_node(doc, det, "slit_length", item.slit_length, {"unit":item.slit_length_unit})
- if written == True:
- instr.appendChild(det)
-
- off = doc.createElement("offset")
- written = write_node(doc, off, "x", item.offset.x, {"unit":item.offset_unit})
- written = written | write_node(doc, off, "y", item.offset.y, {"unit":item.offset_unit})
- written = written | write_node(doc, off, "z", item.offset.z, {"unit":item.offset_unit})
- if written == True:
- det.appendChild(off)
-
- center = doc.createElement("beam_center")
- written = write_node(doc, center, "x", item.beam_center.x, {"unit":item.beam_center_unit})
- written = written | write_node(doc, center, "y", item.beam_center.y, {"unit":item.beam_center_unit})
- written = written | write_node(doc, center, "z", item.beam_center.z, {"unit":item.beam_center_unit})
- if written == True:
- det.appendChild(center)
-
- pix = doc.createElement("pixel_size")
- written = write_node(doc, pix, "x", item.pixel_size.x, {"unit":item.pixel_size_unit})
- written = written | write_node(doc, pix, "y", item.pixel_size.y, {"unit":item.pixel_size_unit})
- written = written | write_node(doc, pix, "z", item.pixel_size.z, {"unit":item.pixel_size_unit})
- if written == True:
- det.appendChild(pix)
-
- ori = doc.createElement("orientation")
- written = write_node(doc, ori, "roll", item.orientation.x, {"unit":item.orientation_unit})
- written = written | write_node(doc, ori, "pitch", item.orientation.y, {"unit":item.orientation_unit})
- written = written | write_node(doc, ori, "yaw", item.orientation.z, {"unit":item.orientation_unit})
- if written == True:
- det.appendChild(ori)
-
- # Processes info
- for item in datainfo.process:
- node = doc.createElement("SASprocess")
- entry_node.appendChild(node)
-
- write_node(doc, node, "name", item.name)
- write_node(doc, node, "date", item.date)
- write_node(doc, node, "description", item.description)
- for term in item.term:
- value = term['value']
- del term['value']
- write_node(doc, node, "term", value, term)
- for note in item.notes:
- write_node(doc, node, "SASprocessnote", note)
- # Return the document, and the SASentry node associated with
- # the data we just wrote
- return doc, entry_node
-
- def _parse_state(self, entry, NODE_NAME= 'state'):
- """
- Read a fit result from an XML node
-
- :param entry: XML node to read from
-
- :return: PageState object
- """
- # Create an empty state
- state = None
- # Locate the P(r) node
- try:
- nodes = entry.xpath('ns:%s' % NODE_NAME, namespaces={'ns': STATE_NODE})
- if nodes !=[]:
- # Create an empty state
- state = PageState()
- state.fromXML(node=nodes[0])
- except:
- logging.info("XML document does not contain fitting information.\n %s" % sys.exc_value)
-
- return state
-
-
-
- def _parse_entry(self, dom):
- """
- Parse a SASentry
-
- :param node: SASentry node
-
- :return: Data1D/Data2D object
-
- """
- node = dom.xpath('ns:data_class', namespaces={'ns': STATE_NODE})
- if not node or node[0].text.lstrip().rstrip() != "Data2D":
- return CansasReader._parse_entry(self, dom)
-
- #Parse 2D
- data_info = Data2D()
-
- # Look up title
- self._store_content('ns:Title', dom, 'title', data_info)
-
- # Look up run number
- nodes = dom.xpath('ns:Run', namespaces={'ns': STATE_NODE})
- for item in nodes:
- if item.text is not None:
- value = item.text.strip()
- if len(value) > 0:
- data_info.run.append(value)
- if item.get('name') is not None:
- data_info.run_name[value] = item.get('name')
-
- # Look up instrument name
- self._store_content('ns:SASinstrument/ns:name', dom, 'instrument', data_info)
-
- # Notes
- note_list = dom.xpath('ns:SASnote', namespaces={'ns': STATE_NODE})
- for note in note_list:
- try:
- if note.text is not None:
- note_value = note.text.strip()
- if len(note_value) > 0:
- data_info.notes.append(note_value)
- except:
- err_mess = "state_reader.read: error processing entry notes\n %s" % sys.exc_value
- self.errors.append(err_mess)
- logging.error(err_mess)
-
- # Sample info ###################
- entry = get_content('ns:SASsample', dom)
- if entry is not None:
- data_info.sample.name = entry.get('name')
-
- self._store_content('ns:SASsample/ns:ID',
- dom, 'ID', data_info.sample)
- self._store_float('ns:SASsample/ns:thickness',
- dom, 'thickness', data_info.sample)
- self._store_float('ns:SASsample/ns:transmission',
- dom, 'transmission', data_info.sample)
- self._store_float('ns:SASsample/ns:temperature',
- dom, 'temperature', data_info.sample)
-
- nodes = dom.xpath('ns:SASsample/ns:details', namespaces={'ns': STATE_NODE})
- for item in nodes:
- try:
- if item.text is not None:
- detail_value = item.text.strip()
- if len(detail_value) > 0:
- data_info.sample.details.append(detail_value)
- except:
- err_mess = "state_reader.read: error processing sample details\n %s" % sys.exc_value
- self.errors.append(err_mess)
- logging.error(err_mess)
-
- # Position (as a vector)
- self._store_float('ns:SASsample/ns:position/ns:x',
- dom, 'position.x', data_info.sample)
- self._store_float('ns:SASsample/ns:position/ns:y',
- dom, 'position.y', data_info.sample)
- self._store_float('ns:SASsample/ns:position/ns:z',
- dom, 'position.z', data_info.sample)
-
- # Orientation (as a vector)
- self._store_float('ns:SASsample/ns:orientation/ns:roll',
- dom, 'orientation.x', data_info.sample)
- self._store_float('ns:SASsample/ns:orientation/ns:pitch',
- dom, 'orientation.y', data_info.sample)
- self._store_float('ns:SASsample/ns:orientation/ns:yaw',
- dom, 'orientation.z', data_info.sample)
-
- # Source info ###################
- entry = get_content('ns:SASinstrument/ns:SASsource', dom)
- if entry is not None:
- data_info.source.name = entry.get('name')
-
- self._store_content('ns:SASinstrument/ns:SASsource/ns:radiation',
- dom, 'radiation', data_info.source)
- self._store_content('ns:SASinstrument/ns:SASsource/ns:beam_shape',
- dom, 'beam_shape', data_info.source)
- self._store_float('ns:SASinstrument/ns:SASsource/ns:wavelength',
- dom, 'wavelength', data_info.source)
- self._store_float('ns:SASinstrument/ns:SASsource/ns:wavelength_min',
- dom, 'wavelength_min', data_info.source)
- self._store_float('ns:SASinstrument/ns:SASsource/ns:wavelength_max',
- dom, 'wavelength_max', data_info.source)
- self._store_float('ns:SASinstrument/ns:SASsource/ns:wavelength_spread',
- dom, 'wavelength_spread', data_info.source)
-
- # Beam size (as a vector)
- entry = get_content('ns:SASinstrument/ns:SASsource/ns:beam_size', dom)
- if entry is not None:
- data_info.source.beam_size_name = entry.get('name')
-
- self._store_float('ns:SASinstrument/ns:SASsource/ns:beam_size/ns:x',
- dom, 'beam_size.x', data_info.source)
- self._store_float('ns:SASinstrument/ns:SASsource/ns:beam_size/ns:y',
- dom, 'beam_size.y', data_info.source)
- self._store_float('ns:SASinstrument/ns:SASsource/ns:beam_size/ns:z',
- dom, 'beam_size.z', data_info.source)
-
- # Collimation info ###################
- nodes = dom.xpath('ns:SASinstrument/ns:SAScollimation', namespaces={'ns': STATE_NODE})
- for item in nodes:
- collim = Collimation()
- if item.get('name') is not None:
- collim.name = item.get('name')
- self._store_float('ns:length', item, 'length', collim)
-
- # Look for apertures
- apert_list = item.xpath('ns:aperture', namespaces={'ns': STATE_NODE})
- for apert in apert_list:
- aperture = Aperture()
-
- # Get the name and type of the aperture
- aperture.name = apert.get('name')
- aperture.type = apert.get('type')
-
- self._store_float('ns:distance', apert, 'distance', aperture)
-
- entry = get_content('ns:size', apert)
- if entry is not None:
- aperture.size_name = entry.get('name')
-
- self._store_float('ns:size/ns:x', apert, 'size.x', aperture)
- self._store_float('ns:size/ns:y', apert, 'size.y', aperture)
- self._store_float('ns:size/ns:z', apert, 'size.z', aperture)
-
- collim.aperture.append(aperture)
-
- data_info.collimation.append(collim)
-
- # Detector info ######################
- nodes = dom.xpath('ns:SASinstrument/ns:SASdetector', namespaces={'ns': STATE_NODE})
- for item in nodes:
-
- detector = Detector()
-
- self._store_content('ns:name', item, 'name', detector)
- self._store_float('ns:SDD', item, 'distance', detector)
-
- # Detector offset (as a vector)
- self._store_float('ns:offset/ns:x', item, 'offset.x', detector)
- self._store_float('ns:offset/ns:y', item, 'offset.y', detector)
- self._store_float('ns:offset/ns:z', item, 'offset.z', detector)
-
- # Detector orientation (as a vector)
- self._store_float('ns:orientation/ns:roll', item, 'orientation.x', detector)
- self._store_float('ns:orientation/ns:pitch', item, 'orientation.y', detector)
- self._store_float('ns:orientation/ns:yaw', item, 'orientation.z', detector)
-
- # Beam center (as a vector)
- self._store_float('ns:beam_center/ns:x', item, 'beam_center.x', detector)
- self._store_float('ns:beam_center/ns:y', item, 'beam_center.y', detector)
- self._store_float('ns:beam_center/ns:z', item, 'beam_center.z', detector)
-
- # Pixel size (as a vector)
- self._store_float('ns:pixel_size/ns:x', item, 'pixel_size.x', detector)
- self._store_float('ns:pixel_size/ns:y', item, 'pixel_size.y', detector)
- self._store_float('ns:pixel_size/ns:z', item, 'pixel_size.z', detector)
-
- self._store_float('ns:slit_length', item, 'slit_length', detector)
-
- data_info.detector.append(detector)
-
- # Processes info ######################
- nodes = dom.xpath('ns:SASprocess', namespaces={'ns': STATE_NODE})
- for item in nodes:
- process = Process()
- self._store_content('ns:name', item, 'name', process)
- self._store_content('ns:date', item, 'date', process)
- self._store_content('ns:description', item, 'description', process)
-
- term_list = item.xpath('ns:term', namespaces={'ns': STATE_NODE})
- for term in term_list:
- try:
- term_attr = {}
- for attr in term.keys():
- term_attr[attr] = term.get(attr).strip()
- if term.text is not None:
- term_attr['value'] = term.text.strip()
- process.term.append(term_attr)
- except:
- err_mess = "state_reader.read: error processing process term\n %s" % sys.exc_value
- self.errors.append(err_mess)
- logging.error(err_mess)
-
- note_list = item.xpath('ns:SASprocessnote', namespaces={'ns': STATE_NODE})
- for note in note_list:
- if note.text is not None:
- process.notes.append(note.text.strip())
-
- data_info.process.append(process)
-
-
- # Data info ######################
- nodes = dom.xpath('ns:SASdata', namespaces={'ns': STATE_NODE})
- if len(nodes)>1:
- raise RuntimeError, "CanSAS reader is not compatible with multiple SASdata entries"
-
- for entry in nodes:
- for item in list_of_data_2d_attr:
- #get node
- node = get_content('ns:%s'%item[0], entry)
- exec "data_info.%s = parse_entry_helper(node, item)"%(item[1])
-
- for item in list_of_data2d_values:
- field = get_content('ns:%s'%item[0], entry)
- list = []
- if field is not None:
- list = [parse_entry_helper(node, item) for node in field]
- exec "data_info.%s = numpy.array(list)"%item[0]
-
- return data_info
-
- def _read_cansas(self, path):
- """
- Load data and P(r) information from a CanSAS XML file.
-
- :param path: file path
-
- :return: Data1D object if a single SASentry was found,
- or a list of Data1D objects if multiple entries were found,
- or None of nothing was found
-
- :raise RuntimeError: when the file can't be opened
- :raise ValueError: when the length of the data vectors are inconsistent
-
- """
- output = []
- basename = os.path.basename(path)
- root, extension = os.path.splitext(basename)
- ext = extension.lower()
- try:
- if os.path.isfile(path):
-
- #TODO: eventually remove the check for .xml once
- # the P(r) writer/reader is truly complete.
- if ext in self.ext or \
- ext == '.xml':
-
- tree = etree.parse(path, parser=etree.ETCompatXMLParser())
- # Check the format version number
- # Specifying the namespace will take care of the file format version
- root = tree.getroot()
- entry_list = root.xpath('ns:SASentry', namespaces={'ns': STATE_NODE})
- for entry in entry_list:
- try:
- sas_entry = self._parse_entry(entry)
- except:
- raise
- fitstate = self._parse_state(entry)
-
- #state could be None when .svs file is loaded
- #in this case, skip appending to output
- if fitstate != None:
- sas_entry.meta_data['fitstate'] = fitstate
- sas_entry.filename = fitstate.file
- output.append(sas_entry)
- else:
- self.call_back(format=ext)
- raise RuntimeError, "%s is not a file" % path
-
- # Return output consistent with the loader's api
- if len(output)==0:
- self.call_back(state=None, datainfo=None,format=ext)
- return None
- else:
- for ind in range(len(output)):
- # Call back to post the new state
- state = output[ind].meta_data['fitstate']
- t = time.localtime(state.timestamp)
- time_str = time.strftime("%b %d %H:%M", t)
- # Check that no time stamp is already appended
- max_char = state.file.find("[")
- if max_char < 0:
- max_char = len(state.file)
- original_fname = state.file[0:max_char]
- state.file = original_fname +' [' + time_str + ']'
-
-
- if state is not None and state.is_data is not None:
- exec 'output[%d].is_data = state.is_data'% ind
-
- output[ind].filename = state.file
- state.data = output[ind]
- state.data.name = output[ind].filename #state.data_name
- state.data.id = state.data_id
- if state.is_data is not None:
- state.data.is_data = state.is_data
- if output[ind].run_name is not None and\
- len(output[ind].run_name) != 0 :
- name = output[ind].run_name
- else:
- name=original_fname
- state.data.group_id = name
- #store state in fitting
- self.call_back(state=state, datainfo=output[ind],format=ext)
- self.state= state
- return output
-
- except:
- #self.call_back(format=ext)
- self.state= state
- raise
-
- def write(self, filename, datainfo=None, fitstate=None):
- """
- Write the content of a Data1D as a CanSAS XML file only for standalone
-
- :param filename: name of the file to write
- :param datainfo: Data1D object
- :param fitstate: PageState object
-
- """
- # Sanity check
- if self.cansas == True:
-
- # Add fitting information to the XML document
- doc = self.write_toXML(datainfo, fitstate)
- # Write the XML document
- fd = open(filename, 'w')
- fd.write(doc.toprettyxml())
- fd.close()
- else:
- fitstate.toXML(file=filename)
-
- def write_toXML(self, datainfo=None, state=None):
- """
- Write toXML, a helper for write() , could be used by guimanager._on_save()
-
- : return: xml doc
- """
-
- if state.data is None:
- data = Data2D()
- else:
- #make sure title and data run is filled up.
- if state.data.title == None or state.data.title=='':
- state.data.title = state.data.name
- if state.data.run_name == None or state.data.run_name=={}:
- state.data.run = [str(state.data.name)]
- state.data.run_name[0] = state.data.name
- doc, sasentry = self._to_xml_doc(data)
-
-
- if state is not None:
- state.toXML(doc=doc, file=data.name, entry_node=sasentry)
-
- return doc
-
-if __name__ == "__main__":
- state = PageState(parent=None)
- #state.toXML()
- """
-
- file = open("test_state", "w")
- pickle.dump(state, file)
- print pickle.dumps(state)
- state.data_name = "hello---->"
- pickle.dump(state, file)
- file = open("test_state", "r")
- new_state= pickle.load(file)
- print "new state", new_state
- new_state= pickle.load(file)
- print "new state", new_state
- #print "state", state
- """
- import bsddb
- import pickle
- db= bsddb.btopen('file_state.db', 'c')
- val = (pickle.dumps(state), "hello", "hi")
- db['state1']= pickle.dumps(val)
- print pickle.loads(db['state1'])
- state.data_name = "hello---->22"
- db['state2']= pickle.dumps(state)
- state.data_name = "hello---->2"
- db['state3']= pickle.dumps(state)
- del db['state3']
- state.data_name = "hello---->3"
- db['state4']= pickle.dumps(state)
- new_state = pickle.loads(db['state1'])
- #print db.last()
- db.set_location('state2')
- state.data_name = "hello---->5"
- db['aastate5']= pickle.dumps(state)
- db.keys().sort()
- print pickle.loads(db['state2'])
-
- db.close()
-
- logging.basicConfig(level=logging.ERROR,
- format='%(asctime)s %(levelname)s %(message)s',
- filename='state_reader.log',
- filemode='w')
- reader = Reader()
- print reader.read("../test/cansas1d.xml")
- #print reader.read("../test/latex_smeared.xml")
-
-
-
Index: test/guiframe/test/cansas1d.xml
===================================================================
--- test/guiframe/test/cansas1d.xml (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,141 +1,0 @@
-
-
-
-
- Test title
- 1234
-
-
- 0.02
- 1000
- 3
- 0.01
-
-
-
-
- 0.03
- 1001
- 4
- 0.02
-
-
-
-
-
- SI600-new-long
- 1.03
- 0.327
- 0.0000
-
- 10.00
- 0.00
-
-
- 22.5
- 0.020
-
-
-
- http://chemtools.chem.soton.ac.uk/projects/blog/blogs.php/bit_id/2720
-
-
- Some text here
-
-
-
-
- canSAS instrument
-
- neutron
-
- 12.00
- 13.00
-
- disc
- 6.00
- 0.22
- 1.00
-
- 14.3
-
-
-
- 123.0
-
-
- 50
-
- 11.000
-
-
-
- 1
-
-
-
-
- fictional hybrid
-
-
- 4.150
-
-
- 1.00
- 0.00
- 0.00
-
-
- 1
- 2
-
-
- 322.64
- 327.68
-
-
- 5.00
- 5.00
-
-
-
-
- spol
- 04-Sep-2007 18:35:02
- 10.000
- 180.0
- 0.0
- USER:MASK.COM
-
- AvA1 0.0000E+00 AsA2 1.0000E+00 XvA3 1.0526E+03 XsA4
- 5.2200E-02 XfA5 0.0000E+00
-
-
- S... 13597 0 2.26E+02 2A 5mM 0%D2O Sbak 13594 0 1.13E+02
- H2O Buffer
-
- V... 13552 3 1.00E+00 H2O5m
-
-
- NCNR-IGOR
- 03-SEP-2006 11:42:47
-
- Circular
- SEP06064.SA3_AJJ_L205
- SEP06064.SA3_AJJ_L205
- SEP06064.SA3_AJJ_L205
- SEP06064.SA3_AJJ_L205
- SEP06064.SA3_AJJ_L205
- 1
- 1
- 230.09
- 1
-
-
-
-
-
Index: test/guiframe/test/utest_manipulations.py
===================================================================
--- test/guiframe/test/utest_manipulations.py (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,262 +1,0 @@
-"""
- Unit tests for data manipulations
-"""
-#TODO: what happens if you add a Data1D to a Data2D?
-
-import unittest
-import numpy, math
-from DataLoader.loader import Loader
-from sans.guiframe.dataFitting import Theory1D, Data1D, Data2D
-
-import os.path
-
-class data_info_tests(unittest.TestCase):
-
- def setUp(self):
- self.data = Loader().load("cansas1d.xml")
-
- def test_clone1D(self):
- """
- Test basic cloning
- """
- clone = self.data.clone_without_data()
-
- for i in range(len(self.data.detector)):
- self.assertEqual(self.data.detector[i].distance, clone.detector[i].distance)
-
-class theory1d_tests(unittest.TestCase):
-
- def setUp(self):
- self.data = Loader().load("cansas1d.xml")
-
- def test_clone_theory1D(self):
- """
- Test basic cloning
- """
- theory = Theory1D(x=[], y=[], dy=None)
- theory.clone_without_data(clone=self.data)
- theory.copy_from_datainfo(data1d=self.data)
- for i in range(len(self.data.detector)):
- self.assertEqual(self.data.detector[i].distance, theory.detector[i].distance)
-
- for i in range(len(self.data.x)):
- self.assertEqual(self.data.x[i], theory.x[i])
- self.assertEqual(self.data.y[i], theory.y[i])
- self.assertEqual(self.data.dy[i], theory.dy[i])
-
-class manip_tests(unittest.TestCase):
-
- def setUp(self):
- # Create two data sets to play with
- x_0 = numpy.ones(5)
- for i in range(5):
- x_0[i] = x_0[i]*(i+1.0)
-
- y_0 = 2.0*numpy.ones(5)
- dy_0 = 0.5*numpy.ones(5)
- self.data = Data1D(x_0, y_0, dy=dy_0)
-
- x = self.data.x
- y = numpy.ones(5)
- dy = numpy.ones(5)
- self.data2 = Data1D(x, y, dy=dy)
-
-
- def test_load(self):
- """
- Test whether the test file was loaded properly
- """
- # There should be 5 entries in the file
- self.assertEqual(len(self.data.x), 5)
-
- for i in range(5):
- # The x values should be from 1 to 5
- self.assertEqual(self.data.x[i], float(i+1))
-
- # All y-error values should be 0.5
- self.assertEqual(self.data.dy[i], 0.5)
-
- # All y values should be 2.0
- self.assertEqual(self.data.y[i], 2.0)
-
- def test_add(self):
- result = self.data2+self.data
- for i in range(5):
- self.assertEqual(result.y[i], 3.0)
- self.assertEqual(result.dy[i], math.sqrt(0.5**2+1.0))
-
- def test_sub(self):
- result = self.data2-self.data
- for i in range(5):
- self.assertEqual(result.y[i], -1.0)
- self.assertEqual(result.dy[i], math.sqrt(0.5**2+1.0))
-
- def test_mul(self):
- result = self.data2*self.data
- for i in range(5):
- self.assertEqual(result.y[i], 2.0)
- self.assertEqual(result.dy[i], math.sqrt((0.5*1.0)**2+(1.0*2.0)**2))
-
- def test_div(self):
- result = self.data2/self.data
- for i in range(5):
- self.assertEqual(result.y[i], 0.5)
- self.assertEqual(result.dy[i], math.sqrt((1.0/2.0)**2+(0.5*1.0/4.0)**2))
-
- def test_radd(self):
- result = self.data+3.0
- for i in range(5):
- self.assertEqual(result.y[i], 5.0)
- self.assertEqual(result.dy[i], 0.5)
-
- result = 3.0+self.data
- for i in range(5):
- self.assertEqual(result.y[i], 5.0)
- self.assertEqual(result.dy[i], 0.5)
-
- def test_rsub(self):
- result = self.data-3.0
- for i in range(5):
- self.assertEqual(result.y[i], -1.0)
- self.assertEqual(result.dy[i], 0.5)
-
- result = 3.0-self.data
- for i in range(5):
- self.assertEqual(result.y[i], 1.0)
- self.assertEqual(result.dy[i], 0.5)
-
- def test_rmul(self):
- result = self.data*3.0
- for i in range(5):
- self.assertEqual(result.y[i], 6.0)
- self.assertEqual(result.dy[i], 1.5)
-
- result = 3.0*self.data
- for i in range(5):
- self.assertEqual(result.y[i], 6.0)
- self.assertEqual(result.dy[i], 1.5)
-
- def test_rdiv(self):
- result = self.data/4.0
- for i in range(5):
- self.assertEqual(result.y[i], 0.5)
- self.assertEqual(result.dy[i], 0.125)
-
- result = 6.0/self.data
- for i in range(5):
- self.assertEqual(result.y[i], 3.0)
- self.assertEqual(result.dy[i], 6.0*0.5/4.0)
-
-class manip_2D(unittest.TestCase):
-
- def setUp(self):
- # Create two data sets to play with
- x_0 = 2.0*numpy.ones([5,4])
- dx_0 = 0.5*numpy.ones([5,4])
- self.data = Data2D(x_0, dx_0)
-
- y = numpy.ones([5,4])
- dy = numpy.ones([5,4])
- self.data2 = Data2D(y, dy)
-
-
- def test_load(self):
- """
- Test whether the test file was loaded properly
- """
- # There should be 5 entries in the file
- self.assertEqual(numpy.size(self.data.data, 0), 5)
- self.assertEqual(numpy.size(self.data.data, 1), 4)
-
- for i in range(5):
- for j in range(4):
- # All y-error values should be 0.5
- self.assertEqual(self.data.err_data[i][j], 0.5)
-
- # All y values should be 2.0
- self.assertEqual(self.data.data[i][j], 2.0)
-
- def test_add(self):
- result = self.data2+self.data
- for i in range(5):
- for j in range(4):
- self.assertEqual(result.data[i][j], 3.0)
- self.assertEqual(result.err_data[i][j], math.sqrt(0.5**2+1.0))
-
- def test_sub(self):
- result = self.data2-self.data
- for i in range(5):
- for j in range(4):
- self.assertEqual(result.data[i][j], -1.0)
- self.assertEqual(result.err_data[i][j], math.sqrt(0.5**2+1.0))
-
- def test_mul(self):
- result = self.data2*self.data
- for i in range(5):
- for j in range(4):
- self.assertEqual(result.data[i][j], 2.0)
- self.assertEqual(result.err_data[i][j], math.sqrt((0.5*1.0)**2+(1.0*2.0)**2))
-
- def test_div(self):
- result = self.data2/self.data
- for i in range(5):
- for j in range(4):
- self.assertEqual(result.data[i][j], 0.5)
- self.assertEqual(result.err_data[i][j], math.sqrt((1.0/2.0)**2+(0.5*1.0/4.0)**2))
-
- def test_radd(self):
- result = self.data+3.0
- for i in range(5):
- for j in range(4):
- self.assertEqual(result.data[i][j], 5.0)
- self.assertEqual(result.err_data[i][j], 0.5)
-
- result = 3.0+self.data
- for i in range(5):
- for j in range(4):
- self.assertEqual(result.data[i][j], 5.0)
- self.assertEqual(result.err_data[i][j], 0.5)
-
- def test_rsub(self):
- result = self.data-3.0
- for i in range(5):
- for j in range(4):
- self.assertEqual(result.data[i][j], -1.0)
- self.assertEqual(result.err_data[i][j], 0.5)
-
- result = 3.0-self.data
- for i in range(5):
- for j in range(4):
- self.assertEqual(result.data[i][j], 1.0)
- self.assertEqual(result.err_data[i][j], 0.5)
-
- def test_rmul(self):
- result = self.data*3.0
- for i in range(5):
- for j in range(4):
- self.assertEqual(result.data[i][j], 6.0)
- self.assertEqual(result.err_data[i][j], 1.5)
-
- result = 3.0*self.data
- for i in range(5):
- for j in range(4):
- self.assertEqual(result.data[i][j], 6.0)
- self.assertEqual(result.err_data[i][j], 1.5)
-
- def test_rdiv(self):
- result = self.data/4.0
- for i in range(5):
- for j in range(4):
- self.assertEqual(result.data[i][j], 0.5)
- self.assertEqual(result.err_data[i][j], 0.125)
-
- result = 6.0/self.data
- for i in range(5):
- for j in range(4):
- self.assertEqual(result.data[i][j], 3.0)
- self.assertEqual(result.err_data[i][j], 6.0*0.5/4.0)
-
-
-if __name__ == '__main__':
- unittest.main()
-
Index: test/guiframe/todo.txt
===================================================================
--- test/guiframe/todo.txt (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,1 +1,0 @@
-- Call _check_update in a separate thread
Index: test/guiframe/utils.py
===================================================================
--- test/guiframe/utils.py (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,124 +1,0 @@
-"""
-Contains common classes and functions
-"""
-import wx
-import re
-
-def parse_name(name, expression):
- """
- remove "_" in front of a name
- """
- if re.match(expression, name) is not None:
- word = re.split(expression, name, 1)
- for item in word:
- if item.lstrip().rstrip() != '':
- return item
- else:
- return name
-def format_number(value, high=False):
- """
- Return a float in a standardized, human-readable formatted string
- """
- try:
- value = float(value)
- except:
- output = "NaN"
- return output.lstrip().rstrip()
- if high:
- output = "%-7.5g" % value
- else:
- output = "%-5.3g" % value
- return output.lstrip().rstrip()
-
-def check_float(item):
- """
- :param item: txtcrtl containing a value
- """
- flag = True
- try:
- mini = float(item.GetValue())
- item.SetBackgroundColour(wx.WHITE)
- item.Refresh()
- except:
- flag = False
- item.SetBackgroundColour("pink")
- item.Refresh()
- return flag
-
-
-class PanelMenu(wx.Menu):
- """
- """
- plots = None
- graph = None
-
- def set_plots(self, plots):
- """
- """
- self.plots = plots
-
- def set_graph(self, graph):
- """
- """
- self.graph = graph
-
-
-def split_list(separator, mylist, n=0):
- """
- returns a list of string without white space of separator
-
- :param separator: the string to remove
-
- """
- list = []
- for item in mylist:
- if re.search(separator,item)!= None:
- if n > 0:
- word = re.split(separator, item, int(n))
- else:
- word = re.split(separator, item)
- for new_item in word:
- if new_item.lstrip().rstrip() != '':
- list.append(new_item.lstrip().rstrip())
- return list
-
-def split_text(separator, string1, n=0):
- """
- return a list of string without white space of separator
-
- :param separator: the string to remove
-
- """
- list = []
- if re.search(separator, string1) is not None:
- if n > 0:
- word = re.split(separator,string1,int(n))
- else:
- word = re.split(separator,string1)
- for item in word:
- if item.lstrip().rstrip() != '':
- list.append(item.lstrip().rstrip())
- return list
-
-def look_for_tag(string1, begin, end=None):
- """
- this method remove the begin and end tags given by the user
- from the string .
-
- :param begin: the initial tag
- :param end: the final tag
- :param string: the string to check
-
- :return: begin_flag==True if begin was found,
- end_flag==if end was found else return false, false
-
- """
- begin_flag = False
- end_flag = False
- if re.search(begin,string1) is not None:
- begin_flag = True
- if end is not None:
- if re.search(end,string1) is not None:
- end_flag = True
- return begin_flag, end_flag
-
Index: test/guiframe/version.py
===================================================================
--- test/guiframe/version.py (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,149 +1,0 @@
-
-################################################################################
-#This software was developed by the University of Tennessee as part of the
-#Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
-#project funded by the US National Science Foundation.
-#
-#See the license text in license.txt
-#
-#copyright 2010, University of Tennessee
-################################################################################
-
-
-import sys
-import time
-import subprocess
-import os
-import getopt
-from threading import Thread
-
-## Maximum number of seconds to wait for an answer from the server
-MAX_WAIT_TIME = 20
-## Local storage file name
-VERSION_FILE = '.current_version'
-
-class VersionChecker(object):
- """
- Class of objects used to obtain the current version of an application
- from the deployment server.
- A sub process is started to read the URL associated with the version number.
- The version number is written on file locally before the reading process
- ends, then read when the version number is requested.
-
- The reading of the URL is put in a separate process so that it doesn't
- affect the performance of the application and can be managed and stopped at any time.
- """
- ## Process used to obtain the current application version from the server
- _process = None
- ## Start time of the process of obtaining a version number
- _t_0 = None
-
- def __init__(self, version_url):
- """
- Start the sub-process used to read the version URL
- """
- self._process = subprocess.Popen([sys.executable, __file__,
- '-g', '-u%s' % version_url])
- self._t_0 = time.time()
-
- def is_complete(self):
- """
- Method used to poll the reading process. The process will be killed
- if the wait time is longer than a predefined maximum.
- This method should always be called before get_version() to ensure
- accuracy of the version number that is returned.
- """
- if(time.time() - self._t_0 < MAX_WAIT_TIME):
- if self._process.poll() is not None:
- return True
- return False
- else:
- return False
- #self._process.kill()
- return True
-
- def get_version(self):
- """
- Returns the last version number that was read from the server.
- """
- try:
- f = open(VERSION_FILE, 'r')
- return f.read()
- except:
- return '0.0.0'
-
-class VersionThread(Thread):
- """
- Thread used to start the process of reading the current version of an
- application from the deployment server.
-
- The VersionChecker is user in a Thread to allow the main application
- to continue dealing with UI requests from the user. The main application
- provides a call-back method for when the version number is obtained.
- """
- def __init__ (self, url, call_back=None, baggage=None):
- Thread.__init__(self)
- self._url = url
- self._call_back = call_back
- self._baggage = baggage
-
- def run(self):
- """
- Execute the process of reading the current application version number.
- """
- checker = VersionChecker(self._url)
- while(not checker.is_complete()):
- time.sleep(1)
- self._call_back(checker.get_version(), self._baggage)
-
-def write_version(version, filename=VERSION_FILE):
- """
- Store the version number
- This could be put into a DB if the application has one.
- """
- f = open(filename, 'w')
- f.write(version)
- f.close()
-
-def _get_version_from_server(url):
- """
- Method executed in the independent process used to read the
- current version number from the server.
-
- :param url: URL to read the version number from
-
- """
- import urllib
- import re
- try:
- h = urllib.urlopen(url)
- for line in h.readlines():
- version = line.strip()
- if len(re.findall('\d+\.\d+\.\d+$', version)) > 0:
- write_version(version)
- return
- write_version('0.0.0')
- except:
- write_version('0.0.0')
-
-if __name__ == "__main__":
- _get_version = False
- _url = 'http://danse.chem.utk.edu/prview_version.php'
-
- opts, args = getopt.getopt(sys.argv[1:], "gu:", ["get", "url="])
- for opt, arg in opts:
- if opt in ("-u", "--url"):
- _url = arg
- elif opt in ("-g", "--get"):
- _get_version = True
-
- if _get_version:
- # Get the version number from the URL.
- _get_version_from_server(_url)
- else:
- # Test execution of the reading process
- def _process(version, baggage=None):
- print "Received:", version
- checker = VersionThread(_url, _process)
- checker.start()
-
Index: test/guiframe/widgets/bitmapPopbutton.py
===================================================================
--- test/guiframe/widgets/bitmapPopbutton.py (revision 01dc0679e46cab5054bdaaca21581b0125058978)
+++ (revision )
@@ -1,200 +1,0 @@
-
-import wx
-from wx.lib.popupctl import PopButton
-
-class GuiPopButton(PopButton):
- def __init__(self, parent, *args, **kwrds):
- PopButton.__init__(self, parent, *args, **kwrds)
- self.parent = parent
- self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
-
- def OnLeftDown(self, event):
- if not self.IsEnabled():
- return
- self.didDown = True
- self.up = False
- self.CaptureMouse()
- self.parent.SetFocus()
- self.Refresh()
-
-
-
-class BitmapPopUpButton(wx.PyControl):
- def __init__(self, parent, gui_bitmap=None, gui_size=(-1, -1),*args, **kwrds):
- if kwrds.has_key('value'):
- del kwrds['value']
- style = kwrds.get('style', 0)
- if (style & wx.BORDER_MASK) == 0:
- style |= wx.BORDER_NONE
- kwrds['style'] = wx.BORDER_NONE
- wx.PyControl.__init__(self, parent, *args, **kwrds)
- if gui_bitmap is None:
- gui_bitmap = wx.NullBitmap
- self._button = wx.BitmapButton(parent=self, id=-1,
- bitmap=gui_bitmap, size=gui_size)
- self.bCtrl = GuiPopButton(self, wx.ID_ANY, style=wx.BORDER_NONE)
- print "hello"
- sizer = wx.GridBagSizer()
- self.SetSizer(sizer)
- sizer.Add(self._button, pos=(0, 0))
- sizer.Add(self.bCtrl, pos=(0, 1))
-
- self.pop = None
- self.content = None
-
- self.Bind(wx.EVT_SIZE, self.OnSize)
- self.bCtrl.Bind(wx.EVT_BUTTON, self.OnButton, self.bCtrl)
- self.Bind(wx.EVT_SET_FOCUS, self.OnFocus)
-
- self.SetInitialSize(kwrds.get('size', wx.DefaultSize))
- self.Layout()
- self.SendSizeEvent()
-
- def Create(self, parent, id, bitmap, pos, size, style, validator, name):
- """
- Acutally create the GUI BitmapButton for 2-phase creation.
- """
- raise NotImplemented
-
- def GetBitmapDisabled(self):
- """
- Returns the bitmap for the disabled state
- """
- return self._button.GetBitmapDisabled()
-
- def GetBitmapFocus(self):
- """
- Returns the bitmap for the focused state.
- """
- return self._button.GetBitmapFocus()
-
- def GetBitmapHover(self):
- """
- Returns the bitmap used when
- the mouse is over the button, may be invalid.
- """
- return self._button.GetBitmapHover()
-
- def GetBitmapLabel(self):
- """
- Returns the label bitmap (the one passed to the constructor).
- """
- return self._button.GetBitmapLabel()
-
- def GetBitmapSelected(self) :
- """
- Returns the bitmap for the selected state.
- """
- return self._button.GetBitmapSelected()
-
- def GetMarginX(self):
- """
- """
- return self._button.GetMarginX()
-
- def GetMarginY(self):
- """
- """
- return self._button.GetMarginY()
-
- def SetBitmapDisabled(self, bitmap):
- """
- Sets the bitmap for the disabled button appearance.
- """
- def SetBitmapFocus(self, bitmap):
- """
- Sets the bitmap for the button appearance
- when it has the keyboard focus.
- """
- self._button.SetBitmapFocus(bitmap)
-
- def SetBitmapHover(self, hover):
- """
- Sets the bitmap to be shown when the mouse is over the button.
- """
- self._button.SetBitmapHover(hover)
-
- def SetBitmapLabel(self, bitmap):
- """Sets the bitmap label for the button.
- """
- self._button.SetBitmapLabel(bitmap)
-
- def SetBitmapSelected(self, bitmap):
- """
- """
- self._button.SetBitmapSelected(bitmap)
-
- def SetMargins(self, x, y):
- """
- """
- self._button.SetMargins(x, y)
-
- def OnFocus(self,evt):
- # embedded control should get focus on TAB keypress
- self._button.SetFocus()
- evt.Skip()
-
- def OnSize(self, evt):
- # layout the child widgets
- w,h = self.GetClientSize()
- self._button.SetDimensions(0, 0,
- w - self.marginWidth - self.buttonWidth, h)
- self.bCtrl.SetDimensions(w - self.buttonWidth, 0, self.buttonWidth, h)
-
- def DoGetBestSize(self):
- # calculate the best size of the combined control based on the
- # needs of the child widgets.
- tbs = self._button.GetBestSize()
- return wx.Size(tbs.width + self.marginWidth + self.buttonWidth,
- tbs.height)
- def OnButton(self, evt):
- if not self.pop:
- if self.content:
- self.pop = PopupDialog(self, self.content)
- del self.content
- else:
- print 'No Content to pop'
- if self.pop:
- self.pop.Display()
-
- def Enable(self, flag):
- wx.PyControl.Enable(self,flag)
- self._button.Enable(flag)
- self.bCtrl.Enable(flag)
-
- def SetPopupContent(self, content):
- if not self.pop:
- self.content = content
- self.content.Show(False)
- else:
- self.pop.SetContent(content)
-
- def FormatContent(self):
- pass
-
- def PopDown(self):
- if self.pop:
- self.pop.EndModal(1)
-
- def SetBitmapDisabled(self, bitmap):
- self._button.SetBitmapDisabled(bitmap)
-
- def SetMargins(self, x, y):
- self._button.SetMargins(x, y)
-
- def SetFont(self, font):
- self._button.SetFont(font)
-
- def GetFont(self):
- return self._button.GetFont()
-
- def _get_marginWidth(self):
- if 'wxMac' in wx.PlatformInfo:
- return 6
- else:
- return 3
- marginWidth = property(_get_marginWidth)
-
- def _get_buttonWidth(self):
- return 20
- buttonWidth = property(_get_buttonWidth)
Index: test/test_rename_guiframe/.current_version
===================================================================
--- test/test_rename_guiframe/.current_version (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/.current_version (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,1 @@
+0.2.3
Index: test/test_rename_guiframe/.project
===================================================================
--- test/test_rename_guiframe/.project (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/.project (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,17 @@
+
+
+ guiframe
+
+
+
+
+
+ org.python.pydev.PyDevBuilder
+
+
+
+
+
+ org.python.pydev.pythonNature
+
+
Index: test/test_rename_guiframe/.pydevproject
===================================================================
--- test/test_rename_guiframe/.pydevproject (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/.pydevproject (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,9 @@
+
+
+
+
+
+/guiframe/src
+
+python 2.5
+
Index: test/test_rename_guiframe/MANIFEST.IN
===================================================================
--- test/test_rename_guiframe/MANIFEST.IN (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/MANIFEST.IN (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,4 @@
+graft media
+graft images
+
+
Index: test/test_rename_guiframe/README.txt
===================================================================
--- test/test_rename_guiframe/README.txt (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/README.txt (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,23 @@
+################################################################################
+#This software was developed by the University of Tennessee as part of the
+#Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
+#project funded by the US National Science Foundation.
+#
+#See the license text in license.txt
+#
+#copyright 2008, University of Tennessee
+################################################################################
+
+
+How-to build an application using guiframe:
+
+1- Write a main application script along the lines of dummyapp.py
+2- Write a config script along the lines of config.py, and
+ name it local_config.py
+3- Write your plug-ins and place them in a directory called "perspectives".
+ - Look at local_perspectives/plotting for an example of a plug-in.
+ - A plug-in should define a class named Plugin,
+ inheriting from PluginBase in plugin_base.py
+
+4- each panel used in guiframe must inheritation from PanelBase in panel_base.py
+
Index: test/test_rename_guiframe/__init__.py
===================================================================
--- test/test_rename_guiframe/__init__.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/__init__.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,72 @@
+
+
+import os
+from distutils.filelist import findall
+
+def get_data_path(media):
+ """
+ """
+ # Check for data path in the package
+ path = os.path.join(os.path.dirname(__file__), media)
+ if os.path.isdir(path):
+ return path
+
+ # Check for data path next to exe/zip file.
+ # If we are inside a py2exe zip file, we need to go up
+ # to get to the directory containing
+ # the media for this module
+ path = os.path.dirname(__file__)
+ #Look for maximum n_dir up of the current dir to find media
+ n_dir = 12
+ for i in range(n_dir):
+ path, _ = os.path.split(path)
+ media_path = os.path.join(path, media)
+ if os.path.isdir(media_path):
+ module_media_path = os.path.join(media_path, 'icons')
+ if os.path.isdir(module_media_path):
+ return module_media_path
+ return media_path
+
+ raise RuntimeError('Could not find guiframe images files')
+
+def get_media_path(media):
+ """
+ """
+ # Check for data path in the package
+ path = os.path.join(os.path.dirname(__file__), media)
+ if os.path.isdir(path):
+ return path
+
+ # Check for data path next to exe/zip file.
+ # If we are inside a py2exe zip file, we need to go up
+ # to get to the directory containing
+ # the media for this module
+ path = os.path.dirname(__file__)
+ #Look for maximum n_dir up of the current dir to find media
+ n_dir = 12
+ for i in range(n_dir):
+ path, _ = os.path.split(path)
+ media_path = os.path.join(path, media)
+ if os.path.isdir(media_path):
+ module_media_path = os.path.join(media_path, 'guiframe_media')
+ if os.path.isdir(module_media_path):
+ return module_media_path
+ return media_path
+ raise RuntimeError('Could not find guiframe media files')
+
+def data_files():
+ """
+ Return the data files associated with guiframe images .
+
+ The format is a list of (directory, [files...]) pairs which can be
+ used directly in setup(...,data_files=...) for setup.py.
+
+ """
+ data_files = []
+ path = get_data_path(media="images")
+ for f in findall(path):
+ data_files.append(('images/icons', [f]))
+ path = get_media_path(media="media")
+ for f in findall(path):
+ data_files.append(('media/guiframe_media', [f]))
+ return data_files
Index: test/test_rename_guiframe/aboutbox.py
===================================================================
--- test/test_rename_guiframe/aboutbox.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/aboutbox.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,274 @@
+#!/usr/bin/env python
+########################################################################
+#
+# PDFgui by DANSE Diffraction group
+# Simon J. L. Billinge
+# (c) 2006 trustees of the Michigan State University.
+# All rights reserved.
+#
+# File coded by: Dmitriy Bryndin
+#
+# See AUTHORS.txt for a list of people who contributed.
+# See LICENSE.txt for license information.
+#
+# Modified by U. Tennessee for DANSE/SANS
+########################################################################
+
+# version
+__id__ = "$Id: aboutdialog.py 1193 2007-05-03 17:29:59Z dmitriy $"
+__revision__ = "$Revision: 1193 $"
+
+import wx
+import wx.lib.hyperlink
+import random
+import os.path
+import os
+try:
+ # Try to find a local config
+ import imp
+ path = os.getcwd()
+ if(os.path.isfile("%s/%s.py" % (path, 'local_config'))) or \
+ (os.path.isfile("%s/%s.pyc" % (path, 'local_config'))):
+ fObj, path, descr = imp.find_module('local_config', [path])
+ config = imp.load_module('local_config', fObj, path, descr)
+ else:
+ # Try simply importing local_config
+ import local_config as config
+except:
+ # Didn't find local config, load the default
+ import config
+
+def launchBrowser(url):
+ """
+ Launches browser and opens specified url
+
+ In some cases may require BROWSER environment variable to be set up.
+
+ :param url: URL to open
+
+ """
+ import webbrowser
+ webbrowser.open(url)
+
+
+class DialogAbout(wx.Dialog):
+ """
+ "About" Dialog
+
+ Shows product name, current version, authors, and link to the product page.
+ Current version is taken from version.py
+
+ """
+
+ def __init__(self, *args, **kwds):
+
+ # begin wxGlade: DialogAbout.__init__
+ kwds["style"] = wx.DEFAULT_DIALOG_STYLE
+ wx.Dialog.__init__(self, *args, **kwds)
+
+ file_dir = os.path.dirname(__file__)
+
+ # Mac doesn't display images with transparent background so well,
+ # keep it for Windows
+ image = file_dir + "/images/angles_flat.png"
+
+ if os.path.isfile(config._corner_image):
+ image = config._corner_image
+
+ if os.name == 'nt':
+ self.bitmap_logo = wx.StaticBitmap(self, -1, wx.Bitmap(image))
+ else:
+ self.bitmap_logo = wx.StaticBitmap(self, -1, wx.Bitmap(image))
+
+ self.label_title = wx.StaticText(self, -1, config.__appname__)
+ self.label_version = wx.StaticText(self, -1, "")
+ self.label_build = wx.StaticText(self, -1, "Build:")
+ self.label_svnrevision = wx.StaticText(self, -1, "")
+ self.label_copyright = wx.StaticText(self, -1, config._copyright)
+ self.label_author = wx.StaticText(self, -1, "authors")
+ self.hyperlink = wx.lib.hyperlink.HyperLinkCtrl(self, -1,
+ config._homepage,
+ URL=config._homepage)
+ #self.hyperlink_license = wx.lib.hyperlink.HyperLinkCtrl(self, -1,
+ #"Comments? Bugs? Requests?", URL=config._paper)
+ self.hyperlink_license = wx.StaticText(self, -1,
+ "Comments? Bugs? Requests?")
+ self.hyperlink_paper = wx.lib.hyperlink.HyperLinkCtrl(self, -1,
+ "Send us a ticket",
+ URL=config._license)
+ self.hyperlink_download = wx.lib.hyperlink.HyperLinkCtrl(self, -1,
+ "Get the latest version",
+ URL=config._download)
+ self.static_line_1 = wx.StaticLine(self, -1)
+ self.label_acknowledgement = wx.StaticText(self, -1,
+ config._acknowledgement)
+ self.static_line_2 = wx.StaticLine(self, -1)
+ self.bitmap_button_nsf = wx.BitmapButton(self, -1,
+ wx.NullBitmap)
+ self.bitmap_button_danse = wx.BitmapButton(self, -1, wx.NullBitmap)
+ self.bitmap_button_msu = wx.BitmapButton(self, -1, wx.NullBitmap)
+ self.static_line_3 = wx.StaticLine(self, -1)
+ self.button_OK = wx.Button(self, wx.ID_OK, "OK")
+
+ self.__set_properties()
+ self.__do_layout()
+
+ self.Bind(wx.EVT_BUTTON, self.onNsfLogo, self.bitmap_button_nsf)
+ self.Bind(wx.EVT_BUTTON, self.onDanseLogo, self.bitmap_button_danse)
+ self.Bind(wx.EVT_BUTTON, self.onUTLogo, self.bitmap_button_msu)
+ # end wxGlade
+ # fill in acknowledgements
+ #self.text_ctrl_acknowledgement.SetValue(__acknowledgement__)
+ # randomly shuffle authors' names
+ random.shuffle(config._authors)
+ strLabel = ", ".join(config._authors)
+
+ # display version and svn revison numbers
+ verwords = config.__version__.split('.')
+ version = '.'.join(verwords[:-1])
+ revision = verwords[-1]
+
+ self.label_author.SetLabel(strLabel)
+ self.label_version.SetLabel(config.__version__)#(version)
+ self.label_svnrevision.SetLabel(config.__version__)
+
+ # set bitmaps for logo buttons
+ image = file_dir + "/images/nsf_logo.png"
+ if os.path.isfile(config._nsf_logo):
+ image = config._nsf_logo
+ logo = wx.Bitmap(image)
+ self.bitmap_button_nsf.SetBitmapLabel(logo)
+
+ image = file_dir + "/images/danse_logo.png"
+ if os.path.isfile(config._danse_logo):
+ image = config._danse_logo
+ logo = wx.Bitmap(image)
+ self.bitmap_button_danse.SetBitmapLabel(logo)
+
+ image = file_dir + "/images/utlogo.gif"
+ if os.path.isfile(config._inst_logo):
+ image = config._inst_logo
+ logo = wx.Bitmap(image)
+ self.bitmap_button_msu.SetBitmapLabel(logo)
+
+ # resize dialog window to fit version number nicely
+ if wx.VERSION >= (2, 7, 2, 0):
+ size = [self.GetEffectiveMinSize()[0], self.GetSize()[1]]
+ else:
+ size = [self.GetBestFittingSize()[0], self.GetSize()[1]]
+ self.Fit()
+
+ def __set_properties(self):
+ """
+ """
+ # begin wxGlade: DialogAbout.__set_properties
+ self.SetTitle("About")
+ self.SetSize((600, 595))
+ self.label_title.SetFont(wx.Font(26, wx.DEFAULT, wx.NORMAL,
+ wx.BOLD, 0, ""))
+ self.label_version.SetFont(wx.Font(26, wx.DEFAULT, wx.NORMAL,
+ wx.NORMAL, 0, ""))
+ self.hyperlink_paper.Enable(True)
+ self.bitmap_button_nsf.SetSize(self.bitmap_button_nsf.GetBestSize())
+ self.bitmap_button_danse.SetSize(self.bitmap_button_danse.GetBestSize())
+ self.bitmap_button_msu.SetSize(self.bitmap_button_msu.GetBestSize())
+ # end wxGlade
+
+ def __do_layout(self):
+ """
+ """
+ # begin wxGlade: DialogAbout.__do_layout
+ sizer_main = wx.BoxSizer(wx.VERTICAL)
+ sizer_button = wx.BoxSizer(wx.HORIZONTAL)
+ sizer_logos = wx.BoxSizer(wx.HORIZONTAL)
+ sizer_header = wx.BoxSizer(wx.HORIZONTAL)
+ sizer_titles = wx.BoxSizer(wx.VERTICAL)
+ sizer_build = wx.BoxSizer(wx.HORIZONTAL)
+ sizer_title = wx.BoxSizer(wx.HORIZONTAL)
+ sizer_header.Add(self.bitmap_logo, 0, wx.EXPAND, 0)
+ sizer_title.Add(self.label_title, 0,
+ wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 10)
+ sizer_title.Add((20, 20), 0, wx.EXPAND|wx.ADJUST_MINSIZE, 0)
+ sizer_title.Add(self.label_version, 0,
+ wx.RIGHT|wx.ALIGN_BOTTOM|wx.ADJUST_MINSIZE, 10)
+ sizer_titles.Add(sizer_title, 0, wx.EXPAND, 0)
+ sizer_build.Add(self.label_build, 0,
+ wx.LEFT|wx.RIGHT|wx.ADJUST_MINSIZE, 10)
+ sizer_build.Add(self.label_svnrevision, 0, wx.ADJUST_MINSIZE, 0)
+ sizer_titles.Add(sizer_build, 0, wx.TOP|wx.EXPAND, 5)
+ sizer_titles.Add(self.label_copyright, 0,
+ wx.LEFT|wx.RIGHT|wx.TOP|wx.ADJUST_MINSIZE, 10)
+ sizer_titles.Add(self.label_author, 0,
+ wx.LEFT|wx.RIGHT|wx.ADJUST_MINSIZE, 10)
+ sizer_titles.Add(self.hyperlink, 0, wx.LEFT|wx.RIGHT, 10)
+ sizer_titles.Add((20, 20), 0, wx.ADJUST_MINSIZE, 0)
+ sizer_titles.Add(self.hyperlink_license, 0, wx.LEFT|wx.RIGHT, 10)
+ sizer_titles.Add(self.hyperlink_paper, 0, wx.LEFT|wx.RIGHT, 10)
+ sizer_titles.Add((20, 20), 0, wx.ADJUST_MINSIZE, 0)
+ sizer_titles.Add(self.hyperlink_download, 0, wx.LEFT|wx.RIGHT, 10)
+ sizer_header.Add(sizer_titles, 0, wx.EXPAND, 0)
+ sizer_main.Add(sizer_header, 0, wx.BOTTOM|wx.EXPAND, 3)
+ sizer_main.Add(self.static_line_1, 0, wx.EXPAND, 0)
+ sizer_main.Add(self.label_acknowledgement, 0,
+ wx.LEFT|wx.TOP|wx.BOTTOM|wx.ADJUST_MINSIZE, 7)
+ sizer_main.Add(self.static_line_2, 0, wx.EXPAND, 0)
+ sizer_logos.Add(self.bitmap_button_nsf, 0, wx.LEFT|wx.ADJUST_MINSIZE, 2)
+ sizer_logos.Add(self.bitmap_button_danse, 0,
+ wx.LEFT|wx.ADJUST_MINSIZE, 2)
+ sizer_logos.Add(self.bitmap_button_msu, 0, wx.LEFT|wx.ADJUST_MINSIZE, 2)
+ sizer_logos.Add((50, 50), 0, wx.ADJUST_MINSIZE, 0)
+ sizer_main.Add(sizer_logos, 0, wx.EXPAND, 0)
+ sizer_main.Add(self.static_line_3, 0, wx.EXPAND, 0)
+ sizer_button.Add((20, 20), 1, wx.EXPAND|wx.ADJUST_MINSIZE, 0)
+ sizer_button.Add(self.button_OK, 0, wx.RIGHT|wx.ADJUST_MINSIZE, 10)
+ sizer_main.Add(sizer_button, 0, wx.EXPAND, 0)
+ self.SetAutoLayout(True)
+ self.SetSizer(sizer_main)
+ self.Layout()
+ self.Centre()
+ # end wxGlade
+
+ def onNsfLogo(self, event):
+ """
+ """
+ # wxGlade: DialogAbout.
+ launchBrowser(config._nsf_url)
+ event.Skip()
+
+ def onDanseLogo(self, event):
+ """
+ """
+ # wxGlade: DialogAbout.
+ launchBrowser(config._danse_url)
+ event.Skip()
+
+ def onUTLogo(self, event):
+ """
+ """
+ # wxGlade: DialogAbout.
+ launchBrowser(config._inst_url)
+ event.Skip()
+
+# end of class DialogAbout
+
+##### testing code ############################################################
+class MyApp(wx.App):
+ """
+ """
+ def OnInit(self):
+ """
+ """
+ wx.InitAllImageHandlers()
+ dialog = DialogAbout(None, -1, "")
+ self.SetTopWindow(dialog)
+ dialog.ShowModal()
+ dialog.Destroy()
+ return 1
+
+# end of class MyApp
+
+if __name__ == "__main__":
+ app = MyApp(0)
+ app.MainLoop()
+
+##### end of testing code #####################################################
Index: test/test_rename_guiframe/config.py
===================================================================
--- test/test_rename_guiframe/config.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/config.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,92 @@
+"""
+Application settings
+"""
+import os
+import time
+from sans.guiframe.gui_style import GUIFRAME
+# Version of the application
+__appname__ = "DummyView"
+__version__ = '0.1.0'
+__download_page__ = 'http://danse.chem.utk.edu'
+
+
+# Debug message flag
+__EVT_DEBUG__ = True
+
+# Flag for automated testing
+__TEST__ = False
+
+# Debug message should be written to a file?
+__EVT_DEBUG_2_FILE__ = False
+__EVT_DEBUG_FILENAME__ = "debug.log"
+
+# About box info
+_do_aboutbox = True
+_acknowledgement = \
+'''This software was developed by the University of Tennessee as part of the
+Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
+project funded by the US National Science Foundation.
+
+'''
+_homepage = "http://danse.chem.utk.edu"
+_download = "http://danse.chem.utk.edu/sansview.html"
+_authors = []
+_paper = "http://danse.us/trac/sans/newticket"
+_license = "mailto:sansdanse@gmail.com"
+_nsf_logo = "images/nsf_logo.png"
+_danse_logo = "images/danse_logo.png"
+_inst_logo = "images/utlogo.gif"
+_nsf_url = "http://www.nsf.gov"
+_danse_url = "http://www.cacr.caltech.edu/projects/danse/release/index.html"
+_inst_url = "http://www.utk.edu"
+_corner_image = "images/angles_flat.png"
+_welcome_image = "images/SVwelcome.png"
+_copyright = "(c) 2008, University of Tennessee"
+#edit the lists below of file state your plugin can read
+#for sansview this how you can edit these lists
+#PLUGIN_STATE_EXTENSIONS = ['.prv','.fitv', '.inv']
+#APPLICATION_STATE_EXTENSION = '.svs'
+#PLUGINS_WLIST = ['P(r) files (*.prv)|*.prv',
+# 'Fitting files (*.fitv)|*.fitv',
+# 'Invariant files (*.inv)|*.inv']
+#APPLICATION_WLIST = 'SansView files (*.svs)|*.svs'
+APPLICATION_WLIST = ''
+APPLICATION_STATE_EXTENSION = None
+PLUGINS_WLIST = []
+PLUGIN_STATE_EXTENSIONS = []
+SPLASH_SCREEN_PATH = "images/danse_logo.png"
+DEFAULT_STYLE = GUIFRAME.SINGLE_APPLICATION
+SPLASH_SCREEN_WIDTH = 500
+SPLASH_SCREEN_HEIGHT = 300
+SS_MAX_DISPLAY_TIME = 4000 #4 sec
+PLOPANEL_WIDTH = 350
+PLOPANEL_HEIGTH = 350
+GUIFRAME_WIDTH = 1000
+GUIFRAME_HEIGHT = 800
+SetupIconFile_win = os.path.join("images", "ball.ico")
+SetupIconFile_mac = os.path.join("images", "ball.icns")
+DefaultGroupName = "DANSE"
+OutputBaseFilename = "setupGuiFrame"
+DATAPANEL_WIDTH = 235
+DATAPANEL_HEIGHT = 700
+FIXED_PANEL = True
+DATALOADER_SHOW = True
+CLEANUP_PLOT = False
+WELCOME_PANEL_SHOW = False
+#Show or hide toolbar at the start up
+TOOLBAR_SHOW = True
+# set a default perspective
+DEFAULT_PERSPECTIVE = 'None'
+
+import wx.lib.newevent
+(StatusBarEvent, EVT_STATUS) = wx.lib.newevent.NewEvent()
+
+def printEVT(message):
+ if __EVT_DEBUG__:
+ print "%g: %s" % (time.clock(), message)
+
+ if __EVT_DEBUG_2_FILE__:
+ out = open(__EVT_DEBUG_FILENAME__, 'a')
+ out.write("%10g: %s\n" % (time.clock(), message))
+ out.close()
+
Index: test/test_rename_guiframe/custom_pstats.py
===================================================================
--- test/test_rename_guiframe/custom_pstats.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/custom_pstats.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,118 @@
+
+import cProfile, pstats, os
+def func_std_string(func_name): # match what old profile produced
+ if func_name[:2] == ('~', 0):
+ # special case for built-in functions
+ name = func_name[2]
+ if name.startswith('<') and name.endswith('>'):
+ return '{%s}' % name[1:-1]
+ else:
+ return name
+ else:
+ return "%s:%d(%s)" % func_name
+
+def f8(x):
+ return "%8.3f" % x
+
+class CustomPstats(pstats.Stats):
+ def __init__(self, *args, **kwds):
+ pstats.Stats.__init__(self, *args, **kwds)
+
+ def write_stats(self, *amount):
+ msg = ''
+ for filename in self.files:
+ msg += str(filename) + '\n'
+ #if self.files: msg += str(self.stream) + '\n'
+ indent = ' ' * 8
+ for func in self.top_level:
+ msg += str(indent)+ str(func_get_function_name(func))+"\n"
+
+ msg += str(indent) + str(self.total_calls)+ "function calls" + '\n'
+ if self.total_calls != self.prim_calls:
+ msg += "(%d primitive calls)" % self.prim_calls + '\n'
+ msg += "in %.3f CPU seconds" % self.total_tt + '\n'
+ #msg += str(self.stream) + '\n'
+
+ width = self.max_name_len
+ if self.fcn_list:
+ list = self.fcn_list[:]
+ temp_msg = " Ordered by: " + self.sort_type + '\n'
+ else:
+ list = self.stats.keys()
+ temp_msg = " Random listing order was used\n"
+
+ for selection in amount:
+ list, temp_msg = self.eval_print_amount(selection, list, temp_msg)
+
+ count = len(list)
+
+ if not list:
+ width, list = 0, list
+ else:
+ msg += str(temp_msg) + '\n'
+ if count < len(self.stats):
+ width = 0
+ for func in list:
+ if len(func_std_string(func)) > width:
+ width = len(func_std_string(func))
+
+ width, list = width+2, list
+ if list:
+ msg += ' ncalls tottime percall cumtime percall'
+ msg += ' filename:lineno(function)' + "\n"
+ for func in list:
+ cc, nc, tt, ct, callers = self.stats[func]
+ c = str(nc)
+ if nc != cc:
+ c = c + '/' + str(cc)
+ msg += str( c.rjust(9))
+ msg += str(f8(tt))
+ if nc == 0:
+ msg += str(' '*8)
+ else:
+ msg += str(f8(tt/nc))
+ msg += str(f8(ct))
+ if cc == 0:
+ msg += str( ' '*80)
+ else:
+ msg += str(f8(ct/cc))
+ msg += " " + str(func_std_string(func)) + '\n'
+ msg += str(self.stream) + '\n'
+ #msg += str(self.stream) + '\n'
+ return self, msg
+
+def profile( fn, name='profile.txt',*args, **kw):
+ import cProfile, pstats, os
+ global call_result
+ def call():
+ global call_result
+ call_result = fn(*args, **kw)
+ cProfile.runctx('call()', dict(call=call), {}, 'profile.txt')
+ stats = CustomPstats('profile.txt')
+ #sort by cumlative time
+ stats.sort_stats('time')
+ stats.print_stats(50)
+ """
+ filename = 'profile_cum_' + name
+ _, msg = stats.write_stats(50)
+ f = file(filename, 'wb')
+ f.write(msg)
+ f.close()
+ #sort by time
+ stats.sort_stats('time')
+ _, msg = stats.write_stats(50)
+ filename = 'profile_time_' + name
+ f = file(filename, 'wb')
+ f.write(msg)
+ f.close()
+ # sort by number of calls
+ stats.sort_stats('call')
+ _, msg = stats.write_stats(50)
+ filename = 'profile_call_' + name
+ f = file(filename, 'wb')
+ f.write(msg)
+ f.close()
+ os.unlink('profile.txt')
+ """
+ return call_result
+
Index: test/test_rename_guiframe/dataFitting.py
===================================================================
--- test/test_rename_guiframe/dataFitting.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/dataFitting.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,260 @@
+"""
+Adapters for fitting module
+"""
+import copy
+import numpy
+import math
+from data_util.uncertainty import Uncertainty
+from danse.common.plottools.plottables import Data1D as PlotData1D
+from danse.common.plottools.plottables import Data2D as PlotData2D
+from danse.common.plottools.plottables import Theory1D as PlotTheory1D
+
+from DataLoader.data_info import Data1D as LoadData1D
+from DataLoader.data_info import Data2D as LoadData2D
+
+
+class Data1D(PlotData1D, LoadData1D):
+ """
+ """
+ def __init__(self, x=None, y=None, dx=None, dy=None):
+ """
+ """
+ if x is None:
+ x = []
+ if y is None:
+ y = []
+ PlotData1D.__init__(self, x, y, dx, dy)
+ LoadData1D.__init__(self, x, y, dx, dy)
+ self.id = None
+ self.list_group_id = []
+ self.group_id = None
+ self.is_data = True
+ self.path = None
+ self.xtransform = None
+ self.ytransform = None
+ self.title = ""
+ self.scale = None
+
+ def copy_from_datainfo(self, data1d):
+ """
+ copy values of Data1D of type DataLaoder.Data_info
+ """
+ self.x = copy.deepcopy(data1d.x)
+ self.y = copy.deepcopy(data1d.y)
+ self.dy = copy.deepcopy(data1d.dy)
+
+ if hasattr(data1d, "dx"):
+ self.dx = copy.deepcopy(data1d.dx)
+ if hasattr(data1d, "dxl"):
+ self.dxl = copy.deepcopy(data1d.dxl)
+ if hasattr(data1d, "dxw"):
+ self.dxw = copy.deepcopy(data1d.dxw)
+
+ self.xaxis(data1d._xaxis, data1d._xunit)
+ self.yaxis(data1d._yaxis, data1d._yunit)
+ self.title = data1d.title
+
+ def __str__(self):
+ """
+ print data
+ """
+ _str = "%s\n" % LoadData1D.__str__(self)
+
+ return _str
+
+ def _perform_operation(self, other, operation):
+ """
+ """
+ # First, check the data compatibility
+ dy, dy_other = self._validity_check(other)
+ result = Data1D(x=[], y=[], dx=None, dy=None)
+ result.clone_without_data(clone=self)
+ result.copy_from_datainfo(data1d=self)
+ for i in range(len(self.x)):
+ result.x[i] = self.x[i]
+ if self.dx is not None and len(self.x) == len(self.dx):
+ result.dx[i] = self.dx[i]
+
+ a = Uncertainty(self.y[i], dy[i]**2)
+ if isinstance(other, Data1D):
+ b = Uncertainty(other.y[i], dy_other[i]**2)
+ else:
+ b = other
+
+ output = operation(a, b)
+ result.y[i] = output.x
+ if result.dy is None: result.dy = numpy.zeros(len(self.x))
+ result.dy[i] = math.sqrt(math.fabs(output.variance))
+ return result
+
+
+
+class Theory1D(PlotTheory1D, LoadData1D):
+ """
+ """
+ def __init__(self, x=None, y=None, dy=None):
+ """
+ """
+ if x is None:
+ x = []
+ if y is None:
+ y = []
+ PlotTheory1D.__init__(self, x, y, dy)
+ LoadData1D.__init__(self, x, y, dy)
+ self.id = None
+ self.list_group_id = []
+ self.group_id = None
+ self.is_data = True
+ self.path = None
+ self.xtransform = None
+ self.ytransform = None
+ self.title = ""
+ self.scale = None
+
+ def copy_from_datainfo(self, data1d):
+ """
+ copy values of Data1D of type DataLaoder.Data_info
+ """
+ self.x = copy.deepcopy(data1d.x)
+ self.y = copy.deepcopy(data1d.y)
+ self.dy = copy.deepcopy(data1d.dy)
+ if hasattr(data1d, "dx"):
+ self.dx = copy.deepcopy(data1d.dx)
+ if hasattr(data1d, "dxl"):
+ self.dxl = copy.deepcopy(data1d.dxl)
+ if hasattr(data1d, "dxw"):
+ self.dxw = copy.deepcopy(data1d.dxw)
+ self.xaxis(data1d._xaxis, data1d._xunit)
+ self.yaxis(data1d._yaxis, data1d._yunit)
+ self.title = data1d.title
+
+ def __str__(self):
+ """
+ print data
+ """
+ _str = "%s\n" % LoadData1D.__str__(self)
+
+ return _str
+
+ def _perform_operation(self, other, operation):
+ """
+ """
+ # First, check the data compatibility
+ dy, dy_other = self._validity_check(other)
+ result = Theory1D(x=[], y=[], dy=None)
+ result.clone_without_data(clone=self)
+ result.copy_from_datainfo(data1d=self)
+ for i in range(len(self.x)):
+ result.x[i] = self.x[i]
+
+ a = Uncertainty(self.y[i], dy[i]**2)
+ if isinstance(other, Data1D):
+ b = Uncertainty(other.y[i], dy_other[i]**2)
+ else:
+ b = other
+ output = operation(a, b)
+ result.y[i] = output.x
+ if result.dy is None:
+ result.dy = numpy.zeros(len(self.x))
+ result.dy[i] = math.sqrt(math.fabs(output.variance))
+ return result
+
+
+class Data2D(PlotData2D, LoadData2D):
+ """
+ """
+ def __init__(self, image=None, err_image=None,
+ xmin=None, xmax=None, ymin=None, ymax=None,
+ zmin=None, zmax=None, qx_data=None, qy_data=None,
+ q_data=None, mask=None, dqx_data=None, dqy_data=None):
+ """
+ """
+ PlotData2D.__init__(self, image=image, err_image=err_image,
+ xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax,
+ zmin=zmin, zmax=zmax, qx_data=qx_data,
+ qy_data=qy_data)
+
+ LoadData2D.__init__(self, data=image, err_data=err_image,
+ qx_data=qx_data, qy_data=qy_data,
+ dqx_data=dqx_data, dqy_data=dqy_data,
+ q_data=q_data, mask=mask)
+ self.id = None
+ self.list_group_id = []
+ self.group_id = None
+ self.is_data = True
+ self.path = None
+ self.xtransform = None
+ self.ytransform = None
+ self.title = ""
+ self.scale = None
+
+ def copy_from_datainfo(self, data2d):
+ """
+ copy value of Data2D of type DataLoader.data_info
+ """
+ self.data = copy.deepcopy(data2d.data)
+ self.qx_data = copy.deepcopy(data2d.qx_data)
+ self.qy_data = copy.deepcopy(data2d.qy_data)
+ self.q_data = copy.deepcopy(data2d.q_data)
+ self.mask = copy.deepcopy(data2d.mask)
+ self.err_data = copy.deepcopy(data2d.err_data)
+ self.x_bins = copy.deepcopy(data2d.x_bins)
+ self.y_bins = copy.deepcopy(data2d.y_bins)
+ if data2d.dqx_data is not None:
+ self.dqx_data = copy.deepcopy(data2d.dqx_data)
+ if data2d.dqy_data is not None:
+ self.dqy_data = copy.deepcopy(data2d.dqy_data)
+ self.xmin = data2d.xmin
+ self.xmax = data2d.xmax
+ self.ymin = data2d.ymin
+ self.ymax = data2d.ymax
+ if hasattr(data2d, "zmin"):
+ self.zmin = data2d.zmin
+ if hasattr(data2d, "zmax"):
+ self.zmax = data2d.zmax
+ self.xaxis(data2d._xaxis, data2d._xunit)
+ self.yaxis(data2d._yaxis, data2d._yunit)
+ self.title = data2d.title
+
+ def __str__(self):
+ """
+ print data
+ """
+ _str = "%s\n" % LoadData2D.__str__(self)
+ return _str
+
+ def _perform_operation(self, other, operation):
+ """
+ Perform 2D operations between data sets
+
+ :param other: other data set
+ :param operation: function defining the operation
+
+ """
+ # First, check the data compatibility
+ dy, dy_other = self._validity_check(other)
+
+ result = Data2D(image=None, qx_data=None, qy_data=None,
+ err_image=None, xmin=None, xmax=None,
+ ymin=None, ymax=None, zmin=None, zmax=None)
+
+ result.clone_without_data(clone=self)
+ result.copy_from_datainfo(data2d=self)
+
+ for i in range(numpy.size(self.data, 0)):
+ for j in range(numpy.size(self.data, 1)):
+ result.data[i][j] = self.data[i][j]
+ if self.err_data is not None and \
+ numpy.size(self.data) == numpy.size(self.err_data):
+ result.err_data[i][j] = self.err_data[i][j]
+
+ a = Uncertainty(self.data[i][j], dy[i][j]**2)
+ if isinstance(other, Data2D):
+ b = Uncertainty(other.data[i][j], dy_other[i][j]**2)
+ else:
+ b = other
+ output = operation(a, b)
+ result.data[i][j] = output.x
+ result.err_data[i][j] = math.sqrt(math.fabs(output.variance))
+ return result
+
Index: test/test_rename_guiframe/data_manager.py
===================================================================
--- test/test_rename_guiframe/data_manager.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/data_manager.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,296 @@
+################################################################################
+#This software was developed by the University of Tennessee as part of the
+#Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
+#project funded by the US National Science Foundation.
+#
+#See the license text in license.txt
+#
+#copyright 2010, University of Tennessee
+################################################################################
+"""
+This module manages all data loaded into the application. Data_manager makes
+available all data loaded for the current perspective.
+
+All modules "creating Data" posts their data to data_manager .
+Data_manager make these new data available for all other perspectives.
+"""
+import logging
+import os
+import copy
+
+from sans.guiframe.data_state import DataState
+from sans.guiframe.utils import parse_name
+import DataLoader.data_info as DataInfo
+from sans.guiframe.dataFitting import Data1D
+from sans.guiframe.dataFitting import Data2D
+import time
+
+class DataManager(object):
+ """
+ Manage a list of data
+ """
+ def __init__(self):
+ """
+ Store opened path and data object created at the loading time
+ :param auto_plot: if True the datamanager sends data to plotting
+ plugin.
+ :param auto_set_data: if True the datamanager sends to the current
+ perspective
+ """
+ self.stored_data = {}
+ self.message = ""
+ self.data_name_dict = {}
+ self.count = 0
+ self.list_of_id = []
+ self.time_stamp = time.time()
+
+ def __str__(self):
+ _str = ""
+ _str += "No of states is %s \n" % str(len(self.stored_data))
+ n_count = 0
+ for value in self.stored_data.values():
+ n_count += 1
+ _str += "State No %s \n" % str(n_count)
+ _str += str(value) + "\n"
+ return _str
+
+ def create_gui_data(self, data, path=None):
+ """
+ Receive data from loader and create a data to use for guiframe
+ """
+
+ if issubclass(Data2D, data.__class__):
+ new_plot = Data2D(image=None, err_image=None)
+ else:
+ new_plot = Data1D(x=[], y=[], dx=None, dy=None)
+
+ new_plot.copy_from_datainfo(data)
+ data.clone_without_data(clone=new_plot)
+ #creating a name for data
+ name = ""
+ title = ""
+ file_name = ""
+ if path is not None:
+ file_name = os.path.basename(path)
+ if file_name == "":
+ file_name = data.filename
+ if data.run:
+ run_num = data.run[0]
+ name = file_name
+ if name == "":
+ name = run_num
+ name = self.rename(name)
+ #find title
+ if data.title.strip():
+ title = data.title
+ if title.strip() == "":
+ title = file_name
+
+ if new_plot.filename.strip() == "":
+ new_plot.filename = file_name
+
+ new_plot.name = name
+ new_plot.title = title
+ ## allow to highlight data when plotted
+ new_plot.interactive = True
+ ## when 2 data have the same id override the 1 st plotted
+ self.time_stamp += 1
+ new_plot.id = str(name) + str(self.time_stamp)
+ ##group_id specify on which panel to plot this data
+ new_plot.group_id = str(name) + str(self.time_stamp)
+ new_plot.is_data = True
+ new_plot.path = path
+ new_plot.list_group_id = []
+ ##post data to plot
+ # plot data
+ return new_plot
+
+ def rename(self, name):
+ """
+ rename data
+ """
+ ## name of the data allow to differentiate data when plotted
+ name = parse_name(name=name, expression="_")
+
+ max_char = name.find("[")
+ if max_char < 0:
+ max_char = len(name)
+ name = name[0:max_char]
+
+ if name not in self.data_name_dict:
+ self.data_name_dict[name] = 0
+ else:
+ self.data_name_dict[name] += 1
+ name = name + " [" + str(self.data_name_dict[name]) + "]"
+ return name
+
+
+ def add_data(self, data_list):
+ """
+ receive a list of
+ """
+ for id, data in data_list.iteritems():
+ if id in self.stored_data:
+ msg = "Data manager already stores %s" % str(data.name)
+ msg += ""
+ logging.info(msg)
+ data_state = self.stored_data[id]
+ data_state.data = data
+ else:
+ data_state = DataState(data)
+ data_state.id = id
+ self.stored_data[id] = data_state
+
+ def update_data(self, prev_data, new_data):
+ """
+ """
+ if prev_data.id not in self.stored_data.keys():
+ return None, {}
+ data_state = self.stored_data[prev_data.id]
+ self.stored_data[new_data.id] = data_state.clone()
+ self.stored_data[new_data.id].data = new_data
+ if prev_data.id in self.stored_data.keys():
+ del self.stored_data[prev_data.id]
+ return prev_data.id, {new_data.id: self.stored_data[new_data.id]}
+
+ def update_theory(self, theory, data_id=None, state=None):
+ """
+ """
+ uid = data_id
+ if data_id is None and theory is not None:
+ uid = theory.id
+ if uid in self.stored_data.keys():
+ data_state = self.stored_data[uid]
+ else:
+ data_state = DataState()
+ data_state.uid = uid
+ data_state.set_theory(theory_data=theory, theory_state=state)
+ self.stored_data[uid] = data_state
+ return {uid: self.stored_data[uid]}
+
+
+ def get_message(self):
+ """
+ return message
+ """
+ return self.message
+
+ def get_by_id(self, id_list=None):
+ """
+ """
+ _selected_data = {}
+ _selected_theory_list = {}
+ if id_list is None:
+ return
+ for d_id in self.stored_data:
+ for search_id in id_list:
+ data_state = self.stored_data[d_id]
+ data = data_state.data
+ theory_list = data_state.get_theory()
+ if search_id == d_id:
+ _selected_data[search_id] = data
+ if search_id in theory_list.keys():
+ _selected_theory_list[search_id] = theory_list[search_id]
+
+ return _selected_data, _selected_theory_list
+
+
+ def freeze(self, theory_id):
+ """
+ """
+ return self.freeze_theory(self.stored_data.keys(), theory_id)
+
+ def freeze_theory(self, data_id, theory_id):
+ """
+ """
+ selected_theory = {}
+ for d_id in data_id:
+ if d_id in self.stored_data:
+ data_state = self.stored_data[d_id]
+ theory_list = data_state.get_theory()
+ for t_id in theory_id:
+ if t_id in theory_list.keys():
+ theory_data, theory_state = theory_list[t_id]
+ new_theory = copy.deepcopy(theory_data)
+ new_theory.id = time.time()
+ new_theory.is_data = True
+ selected_theory[new_theory.id] = DataState(new_theory)
+ self.stored_data[new_theory.id] = selected_theory[new_theory.id]
+
+ return selected_theory
+
+
+ def delete_data(self, data_id, theory_id=None, delete_all=False):
+ """
+ """
+ for d_id in data_id:
+ if d_id in self.stored_data.keys():
+ data_state = self.stored_data[d_id]
+ if data_state.data.name in self.data_name_dict:
+ del self.data_name_dict[data_state.data.name]
+ del self.stored_data[d_id]
+
+ self.delete_theory(data_id, theory_id)
+ if delete_all:
+ self.stored_data = {}
+ self.data_name_dict = {}
+
+ def delete_theory(self, data_id, theory_id):
+ """
+ """
+ for d_id in data_id:
+ if d_id in self.stored_data:
+ data_state = self.stored_data[d_id]
+ theory_list = data_state.get_theory()
+ if theory_id in theory_list.keys():
+ del theory_list[theory_id]
+
+
+ def delete_by_id(self, id_list=None):
+ """
+ save data and path
+ """
+ for id in id_list:
+ if id in self.stored_data:
+ del self.stored_data[id]
+
+
+ def get_by_name(self, name_list=None):
+ """
+ return a list of data given a list of data names
+ """
+ _selected_data = {}
+ for selected_name in name_list:
+ for id, data_state in self.stored_data.iteritems():
+ if data_state.data.name == selected_name:
+ _selected_data[id] = data_state.data
+ return _selected_data
+
+ def delete_by_name(self, name_list=None):
+ """
+ save data and path
+ """
+ for selected_name in name_list:
+ for id, data_state in self.stored_data.iteritems():
+ if data_state.data.name == selected_name:
+ del self._selected_data[id]
+ del self.stored_data[data.id]
+
+ def get_data_state(self, data_id):
+ """
+ Send list of selected data
+ """
+ _selected_data_state = {}
+ for id in data_id:
+ if id in self.stored_data.keys():
+ _selected_data_state[id] = self.stored_data[id]
+ return _selected_data_state
+
+ def get_all_data(self):
+ """
+ return list of all available data
+ """
+ return self.stored_data
+
+
+
Index: test/test_rename_guiframe/data_panel.py
===================================================================
--- test/test_rename_guiframe/data_panel.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/data_panel.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,1188 @@
+################################################################################
+#This software was developed by the University of Tennessee as part of the
+#Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
+#project funded by the US National Science Foundation.
+#
+#See the license text in license.txt
+#
+#copyright 2010, University of Tennessee
+################################################################################
+"""
+This module provides Graphic interface for the data_manager module.
+"""
+import os
+import wx
+# Check version
+toks = wx.__version__.split('.')
+if int(toks[1]) < 9:
+ if int(toks[2]) < 12:
+ wx_version = 811
+ else:
+ wx_version = 812
+else:
+ wx_version = 900
+import sys
+import warnings
+import logging
+from wx.lib.scrolledpanel import ScrolledPanel
+import wx.lib.agw.customtreectrl as CT
+from sans.guiframe.dataFitting import Data1D
+from sans.guiframe.dataFitting import Data2D
+from sans.guiframe.panel_base import PanelBase
+from sans.guiframe.events import StatusEvent
+from sans.guiframe.events import EVT_DELETE_PLOTPANEL
+from sans.guiframe.events import NewLoadDataEvent
+from sans.guiframe.events import NewPlotEvent
+from sans.guiframe.gui_style import GUIFRAME
+from sans.guiframe.events import NewBatchEvent
+from DataLoader.loader import Loader
+
+try:
+ # Try to find a local config
+ import imp
+ path = os.getcwd()
+ if(os.path.isfile("%s/%s.py" % (path, 'local_config'))) or \
+ (os.path.isfile("%s/%s.pyc" % (path, 'local_config'))):
+ fObj, path, descr = imp.find_module('local_config', [path])
+ config = imp.load_module('local_config', fObj, path, descr)
+ else:
+ # Try simply importing local_config
+ import local_config as config
+except:
+ # Didn't find local config, load the default
+ import config
+
+extension_list = []
+if config.APPLICATION_STATE_EXTENSION is not None:
+ extension_list.append(config.APPLICATION_STATE_EXTENSION)
+EXTENSIONS = config.PLUGIN_STATE_EXTENSIONS + extension_list
+PLUGINS_WLIST = config.PLUGINS_WLIST
+APPLICATION_WLIST = config.APPLICATION_WLIST
+
+#Control panel width
+if sys.platform.count("darwin")==0:
+ PANEL_WIDTH = 235
+ PANEL_HEIGHT = 700
+ CBOX_WIDTH = 140
+ BUTTON_WIDTH = 80
+ FONT_VARIANT = 0
+ IS_MAC = False
+else:
+ PANEL_WIDTH = 255
+ PANEL_HEIGHT = 750
+ CBOX_WIDTH = 155
+ BUTTON_WIDTH = 100
+ FONT_VARIANT = 1
+ IS_MAC = True
+
+STYLE_FLAG =wx.RAISED_BORDER|CT.TR_HAS_BUTTONS| CT.TR_HIDE_ROOT|\
+ wx.WANTS_CHARS|CT.TR_HAS_VARIABLE_ROW_HEIGHT
+
+
+class DataTreeCtrl(CT.CustomTreeCtrl):
+ """
+ Check list control to be used for Data Panel
+ """
+ def __init__(self, parent,*args, **kwds):
+ #agwstyle is introduced in wx.2.8.11 but is not working for mac
+ if IS_MAC and wx_version < 812:
+ try:
+ kwds['style'] = STYLE_FLAG
+ CT.CustomTreeCtrl.__init__(self, parent, *args, **kwds)
+ except:
+ del kwds['style']
+ CT.CustomTreeCtrl.__init__(self, parent, *args, **kwds)
+ else:
+ #agwstyle is introduced in wx.2.8.11 .argument working only for windows
+ try:
+ kwds['agwStyle'] = STYLE_FLAG
+ CT.CustomTreeCtrl.__init__(self, parent, *args, **kwds)
+ except:
+ try:
+ del kwds['agwStyle']
+ kwds['style'] = STYLE_FLAG
+ CT.CustomTreeCtrl.__init__(self, parent, *args, **kwds)
+ except:
+ del kwds['style']
+ CT.CustomTreeCtrl.__init__(self, parent, *args, **kwds)
+ self.root = self.AddRoot("Available Data")
+
+class DataPanel(ScrolledPanel, PanelBase):
+ """
+ This panel displays data available in the application and widgets to
+ interact with data.
+ """
+ ## Internal name for the AUI manager
+ window_name = "Data Panel"
+ ## Title to appear on top of the window
+ window_caption = "Data Explorer"
+ #type of window
+ window_type = "Data Panel"
+ ## Flag to tell the GUI manager that this panel is not
+ # tied to any perspective
+ #ALWAYS_ON = True
+ def __init__(self, parent,
+ list=None,
+ size=(PANEL_WIDTH, PANEL_HEIGHT),
+ list_of_perspective=None, manager=None, *args, **kwds):
+ kwds['size']= size
+ kwds['style'] = STYLE_FLAG
+ ScrolledPanel.__init__(self, parent=parent, *args, **kwds)
+ PanelBase.__init__(self)
+ self.SetupScrolling()
+ #Set window's font size
+ self.SetWindowVariant(variant=FONT_VARIANT)
+ self.loader = Loader()
+ #Default location
+ self._default_save_location = None
+ self.all_data1d = True
+ self.parent = parent
+ self.manager = manager
+ if list is None:
+ list = []
+ self.list_of_data = list
+ if list_of_perspective is None:
+ list_of_perspective = []
+ self.list_of_perspective = list_of_perspective
+ self.list_rb_perspectives= []
+ self.list_cb_data = {}
+ self.list_cb_theory = {}
+ self.tree_ctrl = None
+ self.tree_ctrl_theory = None
+ self.perspective_cbox = None
+
+ self.owner = None
+ self.do_layout()
+ self.fill_cbox_analysis(self.list_of_perspective)
+ self.Bind(wx.EVT_SHOW, self.on_close_page)
+ if self.parent is not None:
+ self.parent.Bind(EVT_DELETE_PLOTPANEL, self._on_delete_plot_panel)
+
+ def do_layout(self):
+ """
+ """
+ self.define_panel_structure()
+ self.layout_selection()
+ self.layout_data_list()
+ self.layout_button()
+ self.layout_batch()
+
+ def define_panel_structure(self):
+ """
+ Define the skeleton of the panel
+ """
+ w, h = self.parent.GetSize()
+ self.vbox = wx.BoxSizer(wx.VERTICAL)
+ self.sizer1 = wx.BoxSizer(wx.VERTICAL)
+ self.sizer1.SetMinSize((w/13, h*2/5))
+
+ self.sizer2 = wx.BoxSizer(wx.VERTICAL)
+ self.sizer3 = wx.FlexGridSizer(7, 2, 4, 1)
+ self.sizer4 = wx.BoxSizer(wx.HORIZONTAL)
+ self.sizer5 = wx.BoxSizer(wx.VERTICAL)
+
+ self.vbox.Add(self.sizer5, 0, wx.EXPAND|wx.ALL,1)
+ self.vbox.Add(self.sizer1, 0, wx.EXPAND|wx.ALL,0)
+ self.vbox.Add(self.sizer2, 0, wx.EXPAND|wx.ALL,1)
+ self.vbox.Add(self.sizer3, 0, wx.EXPAND|wx.ALL,5)
+ self.vbox.Add(self.sizer4, 0, wx.EXPAND|wx.ALL,5)
+
+ self.SetSizer(self.vbox)
+
+ def layout_selection(self):
+ """
+ """
+ select_txt = wx.StaticText(self, -1, 'Selection Options')
+ select_txt.SetForegroundColour('blue')
+ self.selection_cbox = wx.ComboBox(self, -1, style=wx.CB_READONLY)
+ list_of_options = ['Select all Data',
+ 'Unselect all Data',
+ 'Select all Data 1D',
+ 'Unselect all Data 1D',
+ 'Select all Data 2D',
+ 'Unselect all Data 2D' ]
+ for option in list_of_options:
+ self.selection_cbox.Append(str(option))
+ self.selection_cbox.SetValue('Select all Data')
+ wx.EVT_COMBOBOX(self.selection_cbox,-1, self._on_selection_type)
+ self.sizer5.AddMany([(select_txt,0, wx.ALL,5),
+ (self.selection_cbox,0, wx.ALL,5)])
+ self.enable_selection()
+
+
+ def _on_selection_type(self, event):
+ """
+ Select data according to patterns
+ """
+
+ list_of_options = ['Select all Data',
+ 'Unselect all Data',
+ 'Select all Data 1D',
+ 'Unselect all Data 1D',
+ 'Select all Data 2D',
+ 'Unselect all Data 2D' ]
+ option = self.selection_cbox.GetValue()
+
+ pos = self.selection_cbox.GetSelection()
+ if pos == wx.NOT_FOUND:
+ return
+ option = self.selection_cbox.GetString(pos)
+ for item in self.list_cb_data.values():
+ data_ctrl, _, _, _,_, _ = item
+ data_id, data_class, _ = self.tree_ctrl.GetItemPyData(data_ctrl)
+ if option == 'Select all Data':
+ self.tree_ctrl.CheckItem(data_ctrl, True)
+ elif option == 'Unselect all Data':
+ self.tree_ctrl.CheckItem(data_ctrl, False)
+ elif option == 'Select all Data 1D':
+ if data_class == 'Data1D':
+ self.tree_ctrl.CheckItem(data_ctrl, True)
+ elif option == 'Unselect all Data 1D':
+ if data_class == 'Data1D':
+ self.tree_ctrl.CheckItem(data_ctrl, False)
+ elif option == 'Select all Data 1D':
+ if data_class == 'Data1D':
+ self.tree_ctrl.CheckItem(data_ctrl, True)
+ elif option == 'Select all Data 2D':
+ if data_class == 'Data2D':
+ self.tree_ctrl.CheckItem(data_ctrl, True)
+ elif option == 'Unselect all Data 2D':
+ if data_class == 'Data2D':
+ self.tree_ctrl.CheckItem(data_ctrl, False)
+ self.enable_append()
+ self.enable_freeze()
+ self.enable_plot()
+ self.enable_import()
+ self.enable_remove()
+
+ def layout_button(self):
+ """
+ Layout widgets related to buttons
+ """
+ w, _ = self.GetSize()
+
+ self.bt_add = wx.Button(self, wx.NewId(), "Load Data",
+ size=(BUTTON_WIDTH, -1))
+ self.bt_add.SetToolTipString("Load data files")
+ wx.EVT_BUTTON(self, self.bt_add.GetId(), self._load_data)
+ self.bt_remove = wx.Button(self, wx.NewId(), "Delete Data",
+ size=(BUTTON_WIDTH, -1))
+ self.bt_remove.SetToolTipString("Delete data from the application")
+ wx.EVT_BUTTON(self, self.bt_remove.GetId(), self.on_remove)
+ self.bt_import = wx.Button(self, wx.NewId(), "Send To",
+ size=(BUTTON_WIDTH, -1))
+ self.bt_import.SetToolTipString("Send set of Data to active perspective")
+ wx.EVT_BUTTON(self, self.bt_import.GetId(), self.on_import)
+ self.perspective_cbox = wx.ComboBox(self, -1,
+ style=wx.CB_READONLY)
+ #self.perspective_cbox.SetMinSize((CBOX_WIDTH, -1))
+ wx.EVT_COMBOBOX(self.perspective_cbox,-1,
+ self._on_perspective_selection)
+
+ self.bt_append_plot = wx.Button(self, wx.NewId(), "Append Plot To",
+ size=(BUTTON_WIDTH, -1))
+ self.bt_append_plot.SetToolTipString("Plot the selected data in the active panel")
+ wx.EVT_BUTTON(self, self.bt_append_plot.GetId(), self.on_append_plot)
+
+ self.bt_plot = wx.Button(self, wx.NewId(), "New Plot",
+ size=(BUTTON_WIDTH, -1))
+ self.bt_plot.SetToolTipString("To trigger plotting")
+ wx.EVT_BUTTON(self, self.bt_plot.GetId(), self.on_plot)
+
+ self.bt_freeze = wx.Button(self, wx.NewId(), "Freeze Theory",
+ size=(BUTTON_WIDTH, -1))
+ self.bt_freeze.SetToolTipString("To trigger freeze a theory")
+ wx.EVT_BUTTON(self, self.bt_freeze.GetId(), self.on_freeze)
+ #hide plot
+ #self.bt_close_plot = wx.Button(self, wx.NewId(), "Delete Plot",
+ # size=(BUTTON_WIDTH, -1))
+ #self.bt_close_plot.SetToolTipString("Delete the plot panel on focus")
+ #wx.EVT_BUTTON(self, self.bt_close_plot.GetId(), self.on_close_plot)
+
+ self.cb_plotpanel = wx.ComboBox(self, -1,
+ style=wx.CB_READONLY|wx.CB_SORT)
+ #self.cb_plotpanel.SetMinSize((CBOX_WIDTH, -1))
+ wx.EVT_COMBOBOX(self.cb_plotpanel,-1, self._on_plot_selection)
+ self.cb_plotpanel.Disable()
+
+ self.sizer3.AddMany([(self.bt_add),
+ ((10, 10)),
+ (self.bt_remove),
+ ((10, 10)),
+ (self.bt_import, 0, wx.EXPAND|wx.RIGHT, 5),
+ (self.perspective_cbox, wx.EXPAND|wx.ADJUST_MINSIZE, 5),
+ (self.bt_append_plot),
+ (self.cb_plotpanel, wx.EXPAND|wx.ADJUST_MINSIZE, 5),
+ (self.bt_plot),
+ ((10, 10)),
+ (self.bt_freeze),
+ #((10, 10)),
+ #(self.bt_close_plot),
+ ((10, 10))])
+
+ self.sizer3.AddGrowableCol(1, 1)
+ self.show_data_button()
+ self.enable_remove()
+ self.enable_import()
+ self.enable_plot()
+ self.enable_append()
+ self.enable_freeze()
+ self.enable_remove_plot()
+
+ def layout_batch(self):
+ """
+ """
+ self.rb_single_mode = wx.RadioButton(self, -1, 'Single Mode',
+ style=wx.RB_GROUP)
+ self.rb_batch_mode = wx.RadioButton(self, -1, 'Batch Mode')
+ self.Bind(wx.EVT_RADIOBUTTON, self.on_single_mode,
+ id=self.rb_single_mode.GetId())
+ self.Bind(wx.EVT_RADIOBUTTON, self.on_batch_mode,
+ id=self.rb_batch_mode.GetId())
+
+ self.rb_single_mode.SetValue(True)
+ self.rb_batch_mode.SetValue(False)
+ self.sizer4.AddMany([(self.rb_single_mode,0, wx.ALL,5),
+ (self.rb_batch_mode,0, wx.ALL,5)])
+
+ def on_single_mode(self, event):
+ """
+ change guiframe to its single mode
+ """
+ if self.parent is not None:
+ wx.PostEvent(self.parent,
+ NewBatchEvent(enable=False))
+
+ def on_batch_mode(self, event):
+ """
+ change guiframe to its batch mode
+ """
+ if self.parent is not None:
+ wx.PostEvent(self.parent,
+ NewBatchEvent(enable=True))
+
+ def layout_data_list(self):
+ """
+ Add a listcrtl in the panel
+ """
+ tree_ctrl_label = wx.StaticText(self, -1, "Data")
+ tree_ctrl_label.SetForegroundColour('blue')
+ self.tree_ctrl = DataTreeCtrl(parent=self)
+ self.tree_ctrl.Bind(CT.EVT_TREE_ITEM_CHECKING, self.on_check_item)
+ tree_ctrl_theory_label = wx.StaticText(self, -1, "Theory")
+ tree_ctrl_theory_label.SetForegroundColour('blue')
+ self.tree_ctrl_theory = DataTreeCtrl(parent=self)
+ self.tree_ctrl_theory.Bind(CT.EVT_TREE_ITEM_CHECKING, self.on_check_item)
+ self.sizer1.Add(tree_ctrl_label, 0, wx.LEFT, 10)
+ self.sizer1.Add(self.tree_ctrl, 1, wx.EXPAND|wx.ALL, 10)
+ self.sizer1.Add(tree_ctrl_theory_label, 0, wx.LEFT, 10)
+ self.sizer1.Add(self.tree_ctrl_theory, 1, wx.EXPAND|wx.ALL, 10)
+
+ def onContextMenu(self, event):
+ """
+ Retrieve the state selected state
+ """
+ # Skipping the save state functionality for release 0.9.0
+ #return
+ pos = event.GetPosition()
+ pos = self.ScreenToClient(pos)
+ self.PopupMenu(self.popUpMenu, pos)
+
+
+ def on_check_item(self, event):
+ """
+ """
+ item = event.GetItem()
+ item.Check(not item.IsChecked())
+ self.enable_append()
+ self.enable_freeze()
+ self.enable_plot()
+ self.enable_import()
+ self.enable_remove()
+ event.Skip()
+
+ def fill_cbox_analysis(self, plugin):
+ """
+ fill the combobox with analysis name
+ """
+ self.list_of_perspective = plugin
+ if self.parent is None or \
+ not hasattr(self.parent, "get_current_perspective") or \
+ len(self.list_of_perspective) == 0:
+ return
+ if self.parent is not None and self.perspective_cbox is not None:
+ for plug in self.list_of_perspective:
+ if plug.get_perspective():
+ self.perspective_cbox.Append(plug.sub_menu, plug)
+
+ curr_pers = self.parent.get_current_perspective()
+ self.perspective_cbox.SetStringSelection(curr_pers.sub_menu)
+ self.enable_import()
+
+ def load_data_list(self, list):
+ """
+ add need data with its theory under the tree
+ """
+ if list:
+ for state_id, dstate in list.iteritems():
+ data = dstate.get_data()
+ theory_list = dstate.get_theory()
+ if data is not None:
+ data_name = str(data.name)
+ data_class = data.__class__.__name__
+ path = dstate.get_path()
+ process_list = data.process
+ data_id = data.id
+ s_path = str(path)
+ if state_id not in self.list_cb_data:
+ #new state
+ data_c = self.tree_ctrl.InsertItem(self.tree_ctrl.root,0,
+ data_name, ct_type=1,
+ data=(data_id, data_class, state_id))
+ data_c.Check(True)
+ d_i_c = self.tree_ctrl.AppendItem(data_c, 'Info')
+ i_c_c = self.tree_ctrl.AppendItem(d_i_c,
+ 'Type: %s' % data_class)
+ p_c_c = self.tree_ctrl.AppendItem(d_i_c,
+ "Path: '%s'" % s_path)
+ d_p_c = self.tree_ctrl.AppendItem(d_i_c, 'Process')
+
+ for process in process_list:
+ i_t_c = self.tree_ctrl.AppendItem(d_p_c,
+ process.__str__())
+ theory_child = self.tree_ctrl.AppendItem(data_c, "THEORIES")
+
+ self.list_cb_data[state_id] = [data_c,
+ d_i_c,
+ i_c_c,
+ p_c_c,
+ d_p_c,
+ theory_child]
+ else:
+ data_ctrl_list = self.list_cb_data[state_id]
+ #This state is already display replace it contains
+ data_c, d_i_c, i_c_c, p_c_c, d_p_c, t_c = data_ctrl_list
+ self.tree_ctrl.SetItemText(data_c, data_name)
+ temp = (data_id, data_class, state_id)
+ self.tree_ctrl.SetItemPyData(data_c, temp)
+ self.tree_ctrl.SetItemText(i_c_c, 'Type: %s' % data_class)
+ self.tree_ctrl.SetItemText(p_c_c, 'Path: %s' % s_path)
+ self.tree_ctrl.DeleteChildren(d_p_c)
+ for process in process_list:
+ i_t_c = self.tree_ctrl.AppendItem(d_p_c,
+ process.__str__())
+ self.append_theory(state_id, theory_list)
+ self.enable_remove()
+ self.enable_import()
+ self.enable_plot()
+ self.enable_freeze()
+ self.enable_selection()
+
+ def _uncheck_all(self):
+ """
+ Uncheck all check boxes
+ """
+ for item in self.list_cb_data.values():
+ data_ctrl, _, _, _,_, _ = item
+ self.tree_ctrl.CheckItem(data_ctrl, False)
+ self.enable_append()
+ self.enable_freeze()
+ self.enable_plot()
+ self.enable_import()
+ self.enable_remove()
+
+ def append_theory(self, state_id, theory_list):
+ """
+ append theory object under data from a state of id = state_id
+ replace that theory if already displayed
+ """
+ if not theory_list:
+ return
+ if state_id not in self.list_cb_data.keys():
+ root = self.tree_ctrl_theory.root
+ tree = self.tree_ctrl_theory
+ else:
+ item = self.list_cb_data[state_id]
+ data_c, _, _, _, _, _ = item
+ root = data_c
+ tree = self.tree_ctrl
+ if root is not None:
+ self.append_theory_helper(tree=tree, root=root,
+ state_id=state_id,
+ theory_list=theory_list)
+
+
+ def append_theory_helper(self, tree, root, state_id, theory_list):
+ """
+ """
+ if state_id in self.list_cb_theory.keys():
+ #update current list of theory for this data
+ theory_list_ctrl = self.list_cb_theory[state_id]
+
+ for theory_id, item in theory_list.iteritems():
+ theory_data, theory_state = item
+ if theory_data is None:
+ name = "Unknown"
+ theory_class = "Unknown"
+ theory_id = "Unknown"
+ temp = (None, None, None)
+ else:
+ name = theory_data.name
+ theory_class = theory_data.__class__.__name__
+ theory_id = theory_data.id
+ #if theory_state is not None:
+ # name = theory_state.model.name
+ temp = (theory_id, theory_class, state_id)
+ if theory_id not in theory_list_ctrl:
+ #add new theory
+ t_child = tree.AppendItem(root,
+ name, ct_type=1, data=temp)
+ t_i_c = tree.AppendItem(t_child, 'Info')
+ i_c_c = tree.AppendItem(t_i_c,
+ 'Type: %s' % theory_class)
+ t_p_c = tree.AppendItem(t_i_c, 'Process')
+
+ for process in theory_data.process:
+ i_t_c = tree.AppendItem(t_p_c,
+ process.__str__())
+ theory_list_ctrl[theory_id] = [t_child,
+ i_c_c,
+ t_p_c]
+ else:
+ #replace theory
+ t_child, i_c_c, t_p_c = theory_list_ctrl[theory_id]
+ tree.SetItemText(t_child, name)
+ tree.SetItemPyData(t_child, temp)
+ tree.SetItemText(i_c_c, 'Type: %s' % theory_class)
+ tree.DeleteChildren(t_p_c)
+ for process in theory_data.process:
+ i_t_c = tree.AppendItem(t_p_c,
+ process.__str__())
+
+ else:
+ #data didn't have a theory associated it before
+ theory_list_ctrl = {}
+ for theory_id, item in theory_list.iteritems():
+ theory_data, theory_state = item
+ if theory_data is not None:
+ name = theory_data.name
+ theory_class = theory_data.__class__.__name__
+ theory_id = theory_data.id
+ #if theory_state is not None:
+ # name = theory_state.model.name
+ temp = (theory_id, theory_class, state_id)
+ t_child = tree.AppendItem(root,
+ name, ct_type=1,
+ data=(theory_data.id, theory_class, state_id))
+ t_i_c = tree.AppendItem(t_child, 'Info')
+ i_c_c = tree.AppendItem(t_i_c,
+ 'Type: %s' % theory_class)
+ t_p_c = tree.AppendItem(t_i_c, 'Process')
+
+ for process in theory_data.process:
+ i_t_c = tree.AppendItem(t_p_c,
+ process.__str__())
+
+ theory_list_ctrl[theory_id] = [t_child, i_c_c, t_p_c]
+ #self.list_cb_theory[data_id] = theory_list_ctrl
+ self.list_cb_theory[state_id] = theory_list_ctrl
+
+
+
+ def set_data_helper(self):
+ """
+ """
+ data_to_plot = []
+ state_to_plot = []
+ theory_to_plot = []
+ for value in self.list_cb_data.values():
+ item, _, _, _, _, _ = value
+ if item.IsChecked():
+ data_id, _, state_id = self.tree_ctrl.GetItemPyData(item)
+ data_to_plot.append(data_id)
+ if state_id not in state_to_plot:
+ state_to_plot.append(state_id)
+
+ for theory_dict in self.list_cb_theory.values():
+ for key, value in theory_dict.iteritems():
+ item, _, _ = value
+ if item.IsChecked():
+ theory_id, _, state_id = self.tree_ctrl.GetItemPyData(item)
+ theory_to_plot.append(theory_id)
+ if state_id not in state_to_plot:
+ state_to_plot.append(state_id)
+ return data_to_plot, theory_to_plot, state_to_plot
+
+ def remove_by_id(self, id):
+ """
+ """
+ for item in self.list_cb_data.values():
+ data_c, _, _, _, _, theory_child = item
+ data_id, _, state_id = self.tree_ctrl.GetItemPyData(data_c)
+ if id == data_id:
+ self.tree_ctrl.Delete(data_c)
+ del self.list_cb_data[state_id]
+ del self.list_cb_theory[data_id]
+
+ def load_error(self, error=None):
+ """
+ Pop up an error message.
+
+ :param error: details error message to be displayed
+ """
+ if error is not None or str(error).strip() != "":
+ dial = wx.MessageDialog(self.parent, str(error), 'Error Loading File',
+ wx.OK | wx.ICON_EXCLAMATION)
+ dial.ShowModal()
+
+ def _load_data(self, event):
+ """
+ send an event to the parent to trigger load from plugin module
+ """
+ if self.parent is not None:
+ wx.PostEvent(self.parent, NewLoadDataEvent())
+
+
+ def on_remove(self, event):
+ """
+ Get a list of item checked and remove them from the treectrl
+ Ask the parent to remove reference to this item
+ """
+ data_to_remove, theory_to_remove, _ = self.set_data_helper()
+ data_key = []
+ theory_key = []
+ #remove data from treectrl
+ for d_key, item in self.list_cb_data.iteritems():
+ data_c, d_i_c, i_c_c, p_c_c, d_p_c, t_c = item
+ if data_c.IsChecked():
+ self.tree_ctrl.Delete(data_c)
+ data_key.append(d_key)
+ if d_key in self.list_cb_theory.keys():
+ theory_list_ctrl = self.list_cb_theory[d_key]
+ theory_to_remove += theory_list_ctrl.keys()
+ # Remove theory from treectrl
+ for t_key, theory_dict in self.list_cb_theory.iteritems():
+ for key, value in theory_dict.iteritems():
+ item, _, _ = value
+ if item.IsChecked():
+ try:
+ self.tree_ctrl.Delete(item)
+ except:
+ pass
+ theory_key.append(key)
+
+ #Remove data and related theory references
+ for key in data_key:
+ del self.list_cb_data[key]
+ if key in theory_key:
+ del self.list_cb_theory[key]
+ #remove theory references independently of data
+ for key in theory_key:
+ for t_key, theory_dict in self.list_cb_theory.iteritems():
+ if key in theory_dict:
+ for key, value in theory_dict.iteritems():
+ item, _, _ = value
+ if item.IsChecked():
+ try:
+ self.tree_ctrl_theory.Delete(item)
+ except:
+ pass
+ del theory_dict[key]
+
+
+ self.parent.remove_data(data_id=data_to_remove,
+ theory_id=theory_to_remove)
+ self.enable_remove()
+ self.enable_freeze()
+ self.enable_remove_plot()
+
+ def on_import(self, event=None):
+ """
+ Get all select data and set them to the current active perspetive
+ """
+ data_id, theory_id, state_id = self.set_data_helper()
+ temp = data_id + state_id
+ self.parent.set_data(data_id=temp, theory_id=theory_id)
+
+ def on_append_plot(self, event=None):
+ """
+ append plot to plot panel on focus
+ """
+ self._on_plot_selection()
+ data_id, theory_id, state_id = self.set_data_helper()
+ self.parent.plot_data(data_id=data_id,
+ state_id=state_id,
+ theory_id=theory_id,
+ append=True)
+
+ def on_plot(self, event=None):
+ """
+ Send a list of data names to plot
+ """
+ data_id, theory_id, state_id = self.set_data_helper()
+ self.parent.plot_data(data_id=data_id,
+ state_id=state_id,
+ theory_id=theory_id,
+ append=False)
+ self.enable_remove_plot()
+
+ def on_close_page(self, event=None):
+ """
+ On close
+ """
+ if event != None:
+ event.Skip()
+ # send parent to update menu with no show nor hide action
+ self.parent.show_data_panel(action=False)
+
+ def on_freeze(self, event):
+ """
+ """
+ _, theory_id, state_id = self.set_data_helper()
+ self.parent.freeze(data_id=state_id, theory_id=theory_id)
+
+ def set_active_perspective(self, name):
+ """
+ set the active perspective
+ """
+ self.perspective_cbox.SetStringSelection(name)
+ self.enable_import()
+
+ def _on_delete_plot_panel(self, event):
+ """
+ get an event with attribute name and caption to delete existing name
+ from the combobox of the current panel
+ """
+ name = event.name
+ caption = event.caption
+ if self.cb_plotpanel is not None:
+ pos = self.cb_plotpanel.FindString(str(caption))
+ if pos != wx.NOT_FOUND:
+ self.cb_plotpanel.Delete(pos)
+ self.enable_append()
+
+ def set_panel_on_focus(self, name=None):
+ """
+ set the plot panel on focus
+ """
+ for key, value in self.parent.plot_panels.iteritems():
+ name_plot_panel = str(value.window_caption)
+ if name_plot_panel not in self.cb_plotpanel.GetItems():
+ self.cb_plotpanel.Append(name_plot_panel, value)
+ if name != None and name == name_plot_panel:
+ self.cb_plotpanel.SetStringSelection(name_plot_panel)
+ break
+ self.enable_append()
+ self.enable_remove_plot()
+
+ def _on_perspective_selection(self, event=None):
+ """
+ select the current perspective for guiframe
+ """
+ selection = self.perspective_cbox.GetSelection()
+
+ if self.perspective_cbox.GetValue() != 'None':
+ perspective = self.perspective_cbox.GetClientData(selection)
+ perspective.on_perspective(event=None)
+
+ def _on_plot_selection(self, event=None):
+ """
+ On source combobox selection
+ """
+ if event != None:
+ combo = event.GetEventObject()
+ event.Skip()
+ else:
+ combo = self.cb_plotpanel
+ selection = combo.GetSelection()
+
+ if combo.GetValue() != 'None':
+ panel = combo.GetClientData(selection)
+ self.parent.on_set_plot_focus(panel)
+
+ def on_close_plot(self, event):
+ """
+ clseo the panel on focus
+ """
+ self.enable_append()
+ selection = self.cb_plotpanel.GetSelection()
+ if self.cb_plotpanel.GetValue() != 'None':
+ panel = self.cb_plotpanel.GetClientData(selection)
+ if self.parent is not None and panel is not None:
+ wx.PostEvent(self.parent,
+ NewPlotEvent(group_id=panel.group_id,
+ action="delete"))
+ self.enable_remove_plot()
+
+ def enable_remove_plot(self):
+ """
+ enable remove plot button if there is a plot panel on focus
+ """
+ pass
+ #if self.cb_plotpanel.GetCount() == 0:
+ # self.bt_close_plot.Disable()
+ #else:
+ # self.bt_close_plot.Enable()
+
+ def enable_remove(self):
+ """
+ enable or disable remove button
+ """
+ n_t = self.tree_ctrl.GetCount()
+ n_t_t = self.tree_ctrl_theory.GetCount()
+ if n_t + n_t_t <= 0:
+ self.bt_remove.Disable()
+ else:
+ self.bt_remove.Enable()
+
+ def enable_import(self):
+ """
+ enable or disable send button
+ """
+ n_t = 0
+ if self.tree_ctrl != None:
+ n_t = self.tree_ctrl.GetCount()
+ if n_t > 0 and len(self.list_of_perspective) > 0:
+ self.bt_import.Enable()
+ else:
+ self.bt_import.Disable()
+ if len(self.list_of_perspective) <= 0 or \
+ self.perspective_cbox.GetValue() in ["None",
+ "No Active Application"]:
+ self.perspective_cbox.Disable()
+ else:
+ self.perspective_cbox.Enable()
+
+ def enable_plot(self):
+ """
+ enable or disable plot button
+ """
+ n_t = 0
+ n_t_t = 0
+ if self.tree_ctrl != None:
+ n_t = self.tree_ctrl.GetCount()
+ if self.tree_ctrl_theory != None:
+ n_t_t = self.tree_ctrl_theory.GetCount()
+ if n_t + n_t_t <= 0:
+ self.bt_plot.Disable()
+ else:
+ self.bt_plot.Enable()
+ self.enable_append()
+
+ def enable_append(self):
+ """
+ enable or disable append button
+ """
+ n_t = 0
+ n_t_t = 0
+ if self.tree_ctrl != None:
+ n_t = self.tree_ctrl.GetCount()
+ if self.tree_ctrl_theory != None:
+ n_t_t = self.tree_ctrl_theory.GetCount()
+ if n_t + n_t_t <= 0:
+ self.bt_append_plot.Disable()
+ self.cb_plotpanel.Disable()
+ elif self.cb_plotpanel.GetCount() <= 0:
+ self.cb_plotpanel.Disable()
+ self.bt_append_plot.Disable()
+ else:
+ self.bt_append_plot.Enable()
+ self.cb_plotpanel.Enable()
+
+ def check_theory_to_freeze(self):
+ """
+ """
+ def enable_freeze(self):
+ """
+ enable or disable the freeze button
+ """
+ n_t_t = 0
+ n_l = 0
+ if self.tree_ctrl_theory != None:
+ n_t_t = self.tree_ctrl_theory.GetCount()
+ n_l = len(self.list_cb_theory)
+ if (n_t_t + n_l > 0):
+ self.bt_freeze.Enable()
+ else:
+ self.bt_freeze.Disable()
+
+ def enable_selection(self):
+ """
+ enable or disable combobo box selection
+ """
+ n_t = 0
+ n_t_t = 0
+ if self.tree_ctrl != None:
+ n_t = self.tree_ctrl.GetCount()
+ if self.tree_ctrl_theory != None:
+ n_t_t = self.tree_ctrl_theory.GetCount()
+ if n_t + n_t_t > 0 and self.selection_cbox != None:
+ self.selection_cbox.Enable()
+ else:
+ self.selection_cbox.Disable()
+
+ def show_data_button(self):
+ """
+ show load data and remove data button if
+ dataloader on else hide them
+ """
+ try:
+ gui_style = self.parent.get_style()
+ style = gui_style & GUIFRAME.DATALOADER_ON
+ if style == GUIFRAME.DATALOADER_ON:
+ #self.bt_remove.Show(True)
+ self.bt_add.Show(True)
+ else:
+ #self.bt_remove.Hide()
+ self.bt_add.Hide()
+ except:
+ #self.bt_remove.Hide()
+ self.bt_add.Hide()
+
+
+
+WIDTH = 400
+HEIGHT = 300
+
+
+class DataDialog(wx.Dialog):
+ """
+ Allow file selection at loading time
+ """
+ def __init__(self, data_list, parent=None, text='', *args, **kwds):
+ wx.Dialog.__init__(self, parent, *args, **kwds)
+ self.SetTitle("Data Selection")
+ self.SetSize((WIDTH, HEIGHT))
+ self.list_of_ctrl = []
+ if not data_list:
+ return
+ self._sizer_main = wx.BoxSizer(wx.VERTICAL)
+ self._sizer_txt = wx.BoxSizer(wx.VERTICAL)
+ self._sizer_button = wx.BoxSizer(wx.HORIZONTAL)
+ self.sizer = wx.GridBagSizer(5, 5)
+ self._panel = ScrolledPanel(self, style=wx.RAISED_BORDER,
+ size=(WIDTH-20, HEIGHT-50))
+ self._panel.SetupScrolling()
+ self.__do_layout(data_list, text=text)
+
+ def __do_layout(self, data_list, text=''):
+ """
+ layout the dialog
+ """
+ if not data_list or len(data_list) <= 1:
+ return
+ #add text
+
+ text = "Deleting these file reset some panels.\n"
+ text += "Do you want to proceed?\n"
+ text_ctrl = wx.StaticText(self, -1, str(text))
+ self._sizer_txt.Add(text_ctrl)
+ iy = 0
+ ix = 0
+ data_count = 0
+ for (data_name, in_use, sub_menu) in range(len(data_list)):
+ if in_use == True:
+ ctrl_name = wx.StaticBox(self, -1, str(data_name))
+ ctrl_in_use = wx.StaticBox(self, -1, " is used by ")
+ plug_name = str(sub_menu) + "\n"
+ ctrl_sub_menu = wx.StaticBox(self, -1, plug_name)
+ self.sizer.Add(ctrl_name, (iy, ix),
+ (1, 1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
+ ix += 1
+ self._sizer_button.Add(ctrl_in_use, 1,
+ wx.EXPAND|wx.ADJUST_MINSIZE, 0)
+ ix += 1
+ self._sizer_button.Add(plug_name, 1,
+ wx.EXPAND|wx.ADJUST_MINSIZE, 0)
+ iy += 1
+ self._panel.SetSizer(self.sizer)
+ #add sizer
+ self._sizer_button.Add((20, 20), 1, wx.EXPAND|wx.ADJUST_MINSIZE, 0)
+ button_cancel = wx.Button(self, wx.ID_CANCEL, "Cancel")
+ self._sizer_button.Add(button_cancel, 0,
+ wx.LEFT|wx.RIGHT|wx.ADJUST_MINSIZE, 10)
+ button_OK = wx.Button(self, wx.ID_OK, "Ok")
+ button_OK.SetFocus()
+ self._sizer_button.Add(button_OK, 0,
+ wx.LEFT|wx.RIGHT|wx.ADJUST_MINSIZE, 10)
+ static_line = wx.StaticLine(self, -1)
+
+ self._sizer_txt.Add(self._panel, 1, wx.EXPAND|wx.LEFT|wx.RIGHT, 5)
+ self._sizer_main.Add(self._sizer_txt, 1, wx.EXPAND|wx.ALL, 10)
+ self._sizer_main.Add(self._data_text_ctrl, 0,
+ wx.EXPAND|wx.LEFT|wx.RIGHT, 10)
+ self._sizer_main.Add(static_line, 0, wx.EXPAND, 0)
+ self._sizer_main.Add(self._sizer_button, 0, wx.EXPAND|wx.ALL, 10)
+ self.SetSizer(self._sizer_main)
+ self.Layout()
+
+ def get_data(self):
+ """
+ return the selected data
+ """
+ temp = []
+ for item in self.list_of_ctrl:
+ cb, data = item
+ if cb.GetValue():
+ temp.append(data)
+ return temp
+
+ def _count_selected_data(self, event):
+ """
+ count selected data
+ """
+ if event.GetEventObject().GetValue():
+ self._nb_selected_data += 1
+ else:
+ self._nb_selected_data -= 1
+ select_data_text = " %s Data selected.\n" % str(self._nb_selected_data)
+ self._data_text_ctrl.SetLabel(select_data_text)
+ if self._nb_selected_data <= self._max_data:
+ self._data_text_ctrl.SetForegroundColour('blue')
+ else:
+ self._data_text_ctrl.SetForegroundColour('red')
+
+
+
+class DataFrame(wx.Frame):
+ ## Internal name for the AUI manager
+ window_name = "Data Panel"
+ ## Title to appear on top of the window
+ window_caption = "Data Panel"
+ ## Flag to tell the GUI manager that this panel is not
+ # tied to any perspective
+ ALWAYS_ON = True
+
+ def __init__(self, parent=None, owner=None, manager=None,size=(300, 800),
+ list_of_perspective=[],list=[], *args, **kwds):
+ kwds['size'] = size
+ kwds['id'] = -1
+ kwds['title']= "Loaded Data"
+ wx.Frame.__init__(self, parent=parent, *args, **kwds)
+ self.parent = parent
+ self.owner = owner
+ self.manager = manager
+ self.panel = DataPanel(parent=self,
+ #size=size,
+ list_of_perspective=list_of_perspective)
+
+ def load_data_list(self, list=[]):
+ """
+ Fill the list inside its panel
+ """
+ self.panel.load_data_list(list=list)
+
+
+
+from dataFitting import Data1D
+from dataFitting import Data2D, Theory1D
+from data_state import DataState
+import sys
+class State():
+ def __init__(self):
+ self.msg = ""
+ def __str__(self):
+ self.msg = "model mane : model1\n"
+ self.msg += "params : \n"
+ self.msg += "name value\n"
+ return msg
+def set_data_state(data=None, path=None, theory=None, state=None):
+ dstate = DataState(data=data)
+ dstate.set_path(path=path)
+ dstate.set_theory(theory, state)
+
+ return dstate
+"""'
+data_list = [1:('Data1', 'Data1D', '07/01/2010', "theory1d", "state1"),
+ ('Data2', 'Data2D', '07/03/2011', "theory2d", "state1"),
+ ('Data3', 'Theory1D', '06/01/2010', "theory1d", "state1"),
+ ('Data4', 'Theory2D', '07/01/2010', "theory2d", "state1"),
+ ('Data5', 'Theory2D', '07/02/2010', "theory2d", "state1")]
+"""
+if __name__ == "__main__":
+
+ app = wx.App()
+ try:
+ list_of_perspective = [('perspective2', False), ('perspective1', True)]
+ data_list = {}
+ # state 1
+ data = Data2D()
+ data.name = "data2"
+ data.id = 1
+ data.append_empty_process()
+ process = data.process[len(data.process)-1]
+ process.data = "07/01/2010"
+ theory = Data2D()
+ theory.id = 34
+ theory.name = "theory1"
+ path = "path1"
+ state = State()
+ data_list['1']=set_data_state(data, path,theory, state)
+ #state 2
+ data = Data2D()
+ data.name = "data2"
+ data.id = 76
+ theory = Data2D()
+ theory.id = 78
+ theory.name = "CoreShell 07/24/25"
+ path = "path2"
+ #state3
+ state = State()
+ data_list['2']=set_data_state(data, path,theory, state)
+ data = Data1D()
+ data.id = 3
+ data.name = "data2"
+ theory = Theory1D()
+ theory.name = "CoreShell"
+ theory.id = 4
+ theory.append_empty_process()
+ process = theory.process[len(theory.process)-1]
+ process.description = "this is my description"
+ path = "path3"
+ data.append_empty_process()
+ process = data.process[len(data.process)-1]
+ process.data = "07/22/2010"
+ data_list['4']=set_data_state(data, path,theory, state)
+ #state 4
+ temp_data_list = {}
+ data.name = "data5 erasing data2"
+ temp_data_list['4'] = set_data_state(data, path,theory, state)
+ #state 5
+ data = Data2D()
+ data.name = "data3"
+ data.id = 5
+ data.append_empty_process()
+ process = data.process[len(data.process)-1]
+ process.data = "07/01/2010"
+ theory = Theory1D()
+ theory.name = "Cylinder"
+ path = "path2"
+ state = State()
+ dstate= set_data_state(data, path,theory, state)
+ theory = Theory1D()
+ theory.id = 6
+ theory.name = "CoreShell"
+ dstate.set_theory(theory)
+ theory = Theory1D()
+ theory.id = 6
+ theory.name = "CoreShell replacing coreshell in data3"
+ dstate.set_theory(theory)
+ data_list['3'] = dstate
+ #state 6
+ data_list['6']=set_data_state(None, path,theory, state)
+ data_list['6']=set_data_state(theory=theory, state=None)
+ theory = Theory1D()
+ theory.id = 7
+ data_list['6']=set_data_state(theory=theory, state=None)
+ data_list['7']=set_data_state(theory=theory, state=None)
+ window = DataFrame(list=data_list)
+ window.load_data_list(list=data_list)
+ window.Show(True)
+ window.load_data_list(list=temp_data_list)
+ except:
+ #raise
+ print "error",sys.exc_value
+
+ app.MainLoop()
+
+
Index: test/test_rename_guiframe/data_processor.py
===================================================================
--- test/test_rename_guiframe/data_processor.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/data_processor.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,288 @@
+"""
+Implement grid used to store data
+"""
+import wx
+import numpy
+import sys
+from wx.lib.scrolledpanel import ScrolledPanel
+import wx.grid as Grid
+import wx.aui
+from wx.aui import AuiNotebook as nb
+from sans.guiframe.panel_base import PanelBase
+import wx.lib.sheet as sheet
+
+from sans.guiframe.events import NewPlotEvent
+from sans.guiframe.events import StatusEvent
+from sans.guiframe.dataFitting import Data1D
+
+
+class GridPage(sheet.CSheet):
+ def __init__(self, parent, panel=None):
+ """
+ """
+ sheet.CSheet.__init__(self, parent)
+ self.SetLabelBackgroundColour('#DBD4D4')
+ self.panel = panel
+ self.col_names = []
+ self._cols = 0
+ self._rows = 0
+ self.SetNumberRows(self._cols)
+ self.SetNumberCols(self._rows)
+ self.Bind(wx.grid.EVT_GRID_LABEL_RIGHT_CLICK, self.on_right_click)
+ self.axis_value = []
+ self.axis_label = ""
+
+
+ def on_right_click(self, event):
+ print "on double click", event.GetRow(), event.GetCol()
+ col = event.GetCol()
+ if col != -1 and len(self.col_names) > col:
+ label = self.col_names[int(col)]
+ self.axis_label = label
+ if label in self.data.keys():
+ col_val = self.data[label]
+ self.axis_value = col_val
+ # Slicer plot popup menu
+ slicerpop = wx.Menu()
+ id = wx.NewId()
+ slicerpop.Append(id, '&Set X axis', 'Set X axis')
+ wx.EVT_MENU(self, id, self.on_set_x_axis)
+
+
+ id = wx.NewId()
+ slicerpop.Append(id, '&Set Y axis', 'Set Y axis')
+ wx.EVT_MENU(self, id, self.on_set_y_axis)
+ pos = event.GetPosition()
+ pos = self.ScreenToClient(pos)
+ self.PopupMenu(slicerpop, pos)
+
+
+
+ def on_set_x_axis(self, event):
+ self.panel.set_xaxis(x=self.axis_value, label=self.axis_label)
+
+ def on_set_y_axis(self, event):
+ self.panel.set_yaxis(y=self.axis_value, label=self.axis_label)
+
+ def set_data(self, data):
+ """
+ """
+ if data is None:
+ data = {}
+ if len(data) > 0:
+ self.data = data
+ self.col_names = data.keys()
+ self.col_names.sort()
+ self._cols = len(self.data.keys())
+ self._rows = max([len(v) for v in self.data.values()])
+ self.SetNumberRows(int(self._rows))
+ self.SetNumberCols(int(self._cols))
+ for index in range(len(self.col_names)):
+ self.SetColLabelValue(index, str(self.col_names[index]))
+
+ col = 0
+ for value_list in self.data.values():
+ for row in range(len(value_list)):
+ self.SetCellValue(row, col, str(value_list[row]))
+ col += 1
+ self.AutoSize()
+
+class Notebook(nb, PanelBase):
+ """
+ ## Internal name for the AUI manager
+ window_name = "Fit panel"
+ ## Title to appear on top of the window
+ """
+ window_caption = "Notebook "
+
+ def __init__(self, parent, manager=None, data=None, *args, **kwargs):
+ """
+ """
+ nb.__init__(self, parent, -1,
+ style= wx.NB_BOTTOM)
+ PanelBase.__init__(self, parent)
+
+ self.parent = parent
+ self.manager = manager
+ self.data = data
+
+ def set_data(self, data):
+ if data is None:
+ return
+
+ grid = GridPage(self, panel=self.parent)
+ grid.set_data(data)
+ self.AddPage(grid, "Batch")
+
+
+class SPanel(ScrolledPanel):
+ def __init__(self, parent, *args, **kwds):
+ ScrolledPanel.__init__(self, parent , *args, **kwds)
+ self.SetupScrolling()
+
+class GridPanel(SPanel):
+ def __init__(self, parent,data=None, *args, **kwds):
+ SPanel.__init__(self, parent , *args, **kwds)
+ self.vbox = wx.BoxSizer(wx.VERTICAL)
+
+ self.plotting_sizer = wx.FlexGridSizer(3, 5, 10, 5)
+ w, h = self.GetSize()
+ #self.panel_grid = SPanel(self, -1, size=(w, -1))
+ self.grid_sizer = wx.BoxSizer(wx.HORIZONTAL)
+ self.vbox.AddMany([(self.grid_sizer, 1, wx.EXPAND, 0),
+ (wx.StaticLine(self, -1), 0, wx.EXPAND, 0),
+ (self.plotting_sizer)])
+ self.parent = parent
+ self._data = data
+ self.x = []
+ self.y = []
+
+ self.x_axis_label = None
+ self.y_axis_label = None
+ self.x_axis_value = None
+ self.y_axis_value = None
+ self.x_axis_unit = None
+ self.y_axis_unit = None
+ self.plot_button = None
+ self.grid = None
+ self.layout_grid()
+ self.layout_plotting_area()
+ self.SetSizer(self.vbox)
+
+ def set_data(self, data):
+ """
+ """
+ if self.grid is not None:
+ self.grid.set_data(data)
+
+ def set_xaxis(self, label="", x=None) :
+ if x is None:
+ x = []
+ self.x = x
+ self.x_axis_value.SetValue("%s[:]" % str(label))
+ self.x_axis_label.SetValue(str(label))
+
+ def set_yaxis(self, label="", y=None) :
+ if y is None:
+ y = []
+ self.y = y
+ self.y_axis_value.SetValue("%s[:]" % str(label))
+ self.y_axis_label.SetValue(str(label))
+
+
+
+ def on_plot(self, event):
+ """
+ plotting
+ """
+ new_plot = Data1D(x=self.x, y=self.y)
+ new_plot.id = wx.NewId()
+ new_plot.group_id = wx.NewId()
+ title = "%s vs %s" % (self.y_axis_label.GetValue(), self.x_axis_label.GetValue())
+ new_plot.xaxis(self.x_axis_label.GetValue(), self.x_axis_unit.GetValue())
+ new_plot.yaxis(self.y_axis_label.GetValue(), self.y_axis_unit.GetValue())
+ wx.PostEvent(self.parent.parent,
+ NewPlotEvent(plot=new_plot, group_id=str(new_plot.group_id), title ="batch"))
+ def layout_grid(self):
+ """
+ Draw the area related to the grid
+ """
+ self.grid = Notebook(parent=self)
+ self.grid.set_data(self._data)
+ #self.grid = Table(parent=self, data=self._data)
+ #vbox = wx.BoxSizer(wx.HORIZONTAL)
+ self.grid_sizer.Add(self.grid, 1, wx.EXPAND, 0)
+ #self.panel_grid.SetSizer(vbox)
+
+ def layout_grid1(self):
+ """
+ Draw the area related to the grid
+ """
+ self.grid = Table(parent=self.panel_grid, data=self._data)
+ vbox = wx.BoxSizer(wx.HORIZONTAL)
+ vbox.Add(self.grid, 1, wx.EXPAND, 0)
+ self.panel_grid.SetSizer(vbox)
+
+ def layout_plotting_area(self):
+ """
+ Draw area containing options to plot
+ """
+ self.x_axis_label = wx.TextCtrl(self, -1)
+
+ self.y_axis_label = wx.TextCtrl(self, -1)
+
+ self.x_axis_value = wx.TextCtrl(self, -1)
+ self.y_axis_value = wx.TextCtrl(self, -1)
+
+ self.x_axis_unit = wx.TextCtrl(self, -1)
+ self.y_axis_unit = wx.TextCtrl(self, -1)
+ self.plot_button = wx.Button(self, -1, "Plot")
+ wx.EVT_BUTTON(self, self.plot_button.GetId(), self.on_plot)
+ self.plotting_sizer.AddMany([(wx.StaticText(self, -1, "x"), 1, wx.LEFT, 10),
+ (self.x_axis_label, wx.TOP|wx.BOTTOM|wx.LEFT, 10),
+ (self.x_axis_value, wx.TOP|wx.BOTTOM|wx.LEFT, 10),
+ (wx.StaticText(self, -1 , "unit"), 1, wx.LEFT|wx.RIGHT|wx.ADJUST_MINSIZE|wx.EXPAND, 0),
+ (self.x_axis_unit),
+ (wx.StaticText(self, -1, "y"), 1, wx.LEFT, 10),
+ (self.y_axis_label, wx.TOP|wx.BOTTOM|wx.LEFT, 10),
+ (self.y_axis_value, wx.TOP|wx.BOTTOM|wx.LEFT, 10),
+ (wx.StaticText(self, -1 , "unit"), 1, wx.LEFT|wx.RIGHT|wx.ADJUST_MINSIZE|wx.EXPAND, 0),
+ (self.y_axis_unit),
+ (-1, -1),
+ (-1, -1),
+ (-1, -1),
+ (self.plot_button, 1, wx.LEFT, 30)])
+
+
+ def add_column(self):
+ if self.grid is not None:
+ self.grid.add_column()
+
+
+class GridFrame(wx.Frame):
+ def __init__(self, parent=None, data=None, id=-1, title="Batch Results", size=(500, 400)):
+ wx.Frame.__init__(self, parent=parent, id=id, title=title, size=size)
+ self.parent = parent
+ self.panel = GridPanel(self, data)
+ menubar = wx.MenuBar()
+ edit = wx.Menu()
+ id_col = wx.NewId()
+ edit.Append(id_col, 'Edit', '' )
+ menubar.Append(edit, "&New column")
+ self.SetMenuBar(menubar)
+ wx.EVT_MENU(self, id_col, self.on_add_column)
+ self.Bind(wx.EVT_CLOSE, self.on_close)
+
+
+ def on_close(self, event):
+ """
+ """
+ self.Hide()
+
+ def on_add_column(self, event):
+ """
+ """
+ self.panel.add_column()
+
+ def set_data(self, data):
+ """
+ """
+ self.panel.set_data(data)
+
+
+if __name__ == "__main__":
+ app = wx.App()
+
+ try:
+ data = {}
+ j = 0
+ for i in range(4):
+ j += 1
+ data["index"+str(i)] = [i/j, i*j, i, i+j]
+
+ frame = TestFrame(data=data)
+ frame.Show(True)
+ except:
+ print sys.exc_value
+
+ app.MainLoop()
Index: test/test_rename_guiframe/data_state.py
===================================================================
--- test/test_rename_guiframe/data_state.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/data_state.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,116 @@
+################################################################################
+#This software was developed by the University of Tennessee as part of the
+#Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
+#project funded by the US National Science Foundation.
+#
+#See the license text in license.txt
+#
+#copyright 2010, University of Tennessee
+################################################################################
+"""
+"""
+import copy
+
+
+class DataState(object):
+ """
+ Store information about data
+ """
+ def __init__(self, data=None, parent=None):
+ """
+
+ """
+ self.parent = parent
+ self.data = data
+ self.name = ""
+ self.path = None
+ self.theory_list = {}
+ self.message = ""
+ self.id = None
+
+ def __str__(self):
+ _str = ""
+ _str += "State with ID : %s \n" % str(self.id)
+ if self.data is not None:
+ _str += "Data name : %s \n" % str(self.data.name)
+ _str += "Data ID : %s \n" % str(self.data.id)
+ else:
+ _str += "Theory Data: %s \n" % str(self.theory_data)
+ if self.theory_data is not None:
+ _str += "Data name : %s \n" % str(self.theory_data.name)
+ _str += "Theory Data ID : %s \n" % str(self.theory_data.id)
+ else:
+ _str += "Theory Data: %s \n" % str(self.theory_data)
+
+ _str += "Theories available: %s \n" % len(self.theory_list)
+ if self.theory_list:
+ for id, item in self.theory_list.iteritems():
+ theory_data, theory_state = item
+ _str += "Theory name : %s \n" % str(theory_data.name)
+ _str += "Theory ID : %s \n" % str(id)
+ _str += "Theory info: \n"
+ _str += str(theory_data)
+
+ return _str
+
+ def clone(self):
+ obj = DataState(copy.deepcopy(self.data))
+ obj.parent = self.parent
+ obj.name = self.name
+ obj.path = self.path
+ obj.message = self.message
+ obj.id = self.id
+ for id, item in self.theory_list.iteritems():
+ theory_data, theory_state = item
+ state = None
+ if theory_state is not None:
+ state = theory_state.clone()
+ obj.theory_list[id] = [copy.deepcopy(theory_data),
+ state]
+ return obj
+
+ def set_name(self, name):
+ self.name = name
+
+ def get_name(self):
+ return self.name
+
+ def set_data(self, data):
+ """
+ """
+ self.data = data
+
+
+ def get_data(self):
+ """
+ """
+ return self.data
+
+ def set_path(self, path):
+ """
+ Set the path of the loaded data
+ """
+ self.path = path
+
+ def get_path(self):
+ """
+ return the path of the loaded data
+ """
+ return self.path
+
+ def set_theory(self, theory_data, theory_state=None):
+ """
+ """
+ self.theory_list[theory_data.id] = [theory_data, theory_state]
+ data, state = self.theory_list.values()[0]
+
+ def get_theory(self):
+ return self.theory_list
+
+ def get_message(self):
+ """
+ return message
+ """
+ return self.message
+
+
Index: test/test_rename_guiframe/docs/sphinx/Makefile
===================================================================
--- test/test_rename_guiframe/docs/sphinx/Makefile (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/docs/sphinx/Makefile (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,130 @@
+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS =
+SPHINXBUILD = sphinx-build
+PAPER =
+BUILDDIR = _build
+
+# Internal variables.
+PAPEROPT_a4 = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+
+.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest
+
+help:
+ @echo "Please use \`make ' where is one of"
+ @echo " html to make standalone HTML files"
+ @echo " dirhtml to make HTML files named index.html in directories"
+ @echo " singlehtml to make a single large HTML file"
+ @echo " pickle to make pickle files"
+ @echo " json to make JSON files"
+ @echo " htmlhelp to make HTML files and a HTML help project"
+ @echo " qthelp to make HTML files and a qthelp project"
+ @echo " devhelp to make HTML files and a Devhelp project"
+ @echo " epub to make an epub"
+ @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
+ @echo " latexpdf to make LaTeX files and run them through pdflatex"
+ @echo " text to make text files"
+ @echo " man to make manual pages"
+ @echo " changes to make an overview of all changed/added/deprecated items"
+ @echo " linkcheck to check all external links for integrity"
+ @echo " doctest to run all doctests embedded in the documentation (if enabled)"
+
+clean:
+ -rm -rf $(BUILDDIR)/*
+
+html:
+ $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
+ @echo
+ @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
+
+dirhtml:
+ $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
+ @echo
+ @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
+
+singlehtml:
+ $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
+ @echo
+ @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
+
+pickle:
+ $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
+ @echo
+ @echo "Build finished; now you can process the pickle files."
+
+json:
+ $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
+ @echo
+ @echo "Build finished; now you can process the JSON files."
+
+htmlhelp:
+ $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
+ @echo
+ @echo "Build finished; now you can run HTML Help Workshop with the" \
+ ".hhp project file in $(BUILDDIR)/htmlhelp."
+
+qthelp:
+ $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
+ @echo
+ @echo "Build finished; now you can run "qcollectiongenerator" with the" \
+ ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
+ @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/guiframe.qhcp"
+ @echo "To view the help file:"
+ @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/guiframe.qhc"
+
+devhelp:
+ $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
+ @echo
+ @echo "Build finished."
+ @echo "To view the help file:"
+ @echo "# mkdir -p $$HOME/.local/share/devhelp/guiframe"
+ @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/guiframe"
+ @echo "# devhelp"
+
+epub:
+ $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
+ @echo
+ @echo "Build finished. The epub file is in $(BUILDDIR)/epub."
+
+latex:
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+ @echo
+ @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
+ @echo "Run \`make' in that directory to run these through (pdf)latex" \
+ "(use \`make latexpdf' here to do that automatically)."
+
+latexpdf: latex
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+ @echo "Running LaTeX files through pdflatex..."
+ make -C $(BUILDDIR)/latex all-pdf
+ @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
+
+text:
+ $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
+ @echo
+ @echo "Build finished. The text files are in $(BUILDDIR)/text."
+
+man:
+ $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
+ @echo
+ @echo "Build finished. The manual pages are in $(BUILDDIR)/man."
+
+changes:
+ $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
+ @echo
+ @echo "The overview file is in $(BUILDDIR)/changes."
+
+linkcheck:
+ $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
+ @echo
+ @echo "Link check complete; look for any errors in the above output " \
+ "or in $(BUILDDIR)/linkcheck/output.txt."
+
+doctest:
+ $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
+ @echo "Testing of doctests in the sources finished, look at the " \
+ "results in $(BUILDDIR)/doctest/output.txt."
Index: test/test_rename_guiframe/docs/sphinx/_extensions/only_directives.py
===================================================================
--- test/test_rename_guiframe/docs/sphinx/_extensions/only_directives.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/docs/sphinx/_extensions/only_directives.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,63 @@
+#
+# A pair of directives for inserting content that will only appear in
+# either html or latex.
+#
+
+from docutils.nodes import Body, Element
+from docutils.parsers.rst import directives
+
+class only_base(Body, Element):
+ def dont_traverse(self, *args, **kwargs):
+ return []
+
+class html_only(only_base):
+ pass
+
+class latex_only(only_base):
+ pass
+
+def run(content, node_class, state, content_offset):
+ text = '\n'.join(content)
+ node = node_class(text)
+ state.nested_parse(content, content_offset, node)
+ return [node]
+
+def html_only_directive(name, arguments, options, content, lineno,
+ content_offset, block_text, state, state_machine):
+ return run(content, html_only, state, content_offset)
+
+def latex_only_directive(name, arguments, options, content, lineno,
+ content_offset, block_text, state, state_machine):
+ return run(content, latex_only, state, content_offset)
+
+def builder_inited(app):
+ if app.builder.name == 'html':
+ latex_only.traverse = only_base.dont_traverse
+ else:
+ html_only.traverse = only_base.dont_traverse
+
+def setup(app):
+ app.add_directive('htmlonly', html_only_directive, True, (0, 0, 0))
+ app.add_directive('latexonly', latex_only_directive, True, (0, 0, 0))
+ app.add_node(html_only)
+ app.add_node(latex_only)
+
+ # This will *really* never see the light of day As it turns out,
+ # this results in "broken" image nodes since they never get
+ # processed, so best not to do this.
+ # app.connect('builder-inited', builder_inited)
+
+ # Add visit/depart methods to HTML-Translator:
+ def visit_perform(self, node):
+ pass
+ def depart_perform(self, node):
+ pass
+ def visit_ignore(self, node):
+ node.children = []
+ def depart_ignore(self, node):
+ node.children = []
+
+ app.add_node(html_only, html=(visit_perform, depart_perform))
+ app.add_node(html_only, latex=(visit_ignore, depart_ignore))
+ app.add_node(latex_only, latex=(visit_perform, depart_perform))
+ app.add_node(latex_only, html=(visit_ignore, depart_ignore))
Index: test/test_rename_guiframe/docs/sphinx/api/aboutbox.rst
===================================================================
--- test/test_rename_guiframe/docs/sphinx/api/aboutbox.rst (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/docs/sphinx/api/aboutbox.rst (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,15 @@
+.. Autogenerated by genmods.py
+
+******************************************************************************
+aboutbox
+******************************************************************************
+
+:mod:`sans.guiframe.aboutbox`
+==============================================================================
+
+.. automodule:: sans.guiframe.aboutbox
+ :members:
+ :undoc-members:
+ :inherited-members:
+ :show-inheritance:
+
Index: test/test_rename_guiframe/docs/sphinx/api/config.rst
===================================================================
--- test/test_rename_guiframe/docs/sphinx/api/config.rst (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/docs/sphinx/api/config.rst (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,15 @@
+.. Autogenerated by genmods.py
+
+******************************************************************************
+config
+******************************************************************************
+
+:mod:`sans.guiframe.config`
+==============================================================================
+
+.. automodule:: sans.guiframe.config
+ :members:
+ :undoc-members:
+ :inherited-members:
+ :show-inheritance:
+
Index: test/test_rename_guiframe/docs/sphinx/api/dataFitting.rst
===================================================================
--- test/test_rename_guiframe/docs/sphinx/api/dataFitting.rst (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/docs/sphinx/api/dataFitting.rst (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,15 @@
+.. Autogenerated by genmods.py
+
+******************************************************************************
+dataFitting
+******************************************************************************
+
+:mod:`sans.guiframe.dataFitting`
+==============================================================================
+
+.. automodule:: sans.guiframe.dataFitting
+ :members:
+ :undoc-members:
+ :inherited-members:
+ :show-inheritance:
+
Index: test/test_rename_guiframe/docs/sphinx/api/data_loader.rst
===================================================================
--- test/test_rename_guiframe/docs/sphinx/api/data_loader.rst (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/docs/sphinx/api/data_loader.rst (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,15 @@
+.. Autogenerated by genmods.py
+
+******************************************************************************
+data_loader
+******************************************************************************
+
+:mod:`sans.guiframe.data_loader`
+==============================================================================
+
+.. automodule:: sans.guiframe.data_loader
+ :members:
+ :undoc-members:
+ :inherited-members:
+ :show-inheritance:
+
Index: test/test_rename_guiframe/docs/sphinx/api/dummyapp.rst
===================================================================
--- test/test_rename_guiframe/docs/sphinx/api/dummyapp.rst (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/docs/sphinx/api/dummyapp.rst (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,15 @@
+.. Autogenerated by genmods.py
+
+******************************************************************************
+dummyapp
+******************************************************************************
+
+:mod:`sans.guiframe.dummyapp`
+==============================================================================
+
+.. automodule:: sans.guiframe.dummyapp
+ :members:
+ :undoc-members:
+ :inherited-members:
+ :show-inheritance:
+
Index: test/test_rename_guiframe/docs/sphinx/api/gui_manager.rst
===================================================================
--- test/test_rename_guiframe/docs/sphinx/api/gui_manager.rst (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/docs/sphinx/api/gui_manager.rst (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,15 @@
+.. Autogenerated by genmods.py
+
+******************************************************************************
+gui_manager
+******************************************************************************
+
+:mod:`sans.guiframe.gui_manager`
+==============================================================================
+
+.. automodule:: sans.guiframe.gui_manager
+ :members:
+ :undoc-members:
+ :inherited-members:
+ :show-inheritance:
+
Index: test/test_rename_guiframe/docs/sphinx/api/index.rst
===================================================================
--- test/test_rename_guiframe/docs/sphinx/api/index.rst (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/docs/sphinx/api/index.rst (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,25 @@
+.. Autogenerated by genmods.py
+
+.. _api-index:
+
+##############################################################################
+ Reference
+##############################################################################
+
+.. only:: html
+
+ :Release: |version|
+ :Date: |today|
+
+.. toctree::
+
+ aboutbox.rst
+ config.rst
+ data_loader.rst
+ dataFitting.rst
+ dummyapp.rst
+ gui_manager.rst
+ load_thread.rst
+ statusbar.rst
+ utils.rst
+ version.rst
Index: test/test_rename_guiframe/docs/sphinx/api/load_thread.rst
===================================================================
--- test/test_rename_guiframe/docs/sphinx/api/load_thread.rst (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/docs/sphinx/api/load_thread.rst (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,15 @@
+.. Autogenerated by genmods.py
+
+******************************************************************************
+load_thread
+******************************************************************************
+
+:mod:`sans.guiframe.load_thread`
+==============================================================================
+
+.. automodule:: sans.guiframe.load_thread
+ :members:
+ :undoc-members:
+ :inherited-members:
+ :show-inheritance:
+
Index: test/test_rename_guiframe/docs/sphinx/api/local_perspectives/plotting/AnnulusSlicer.rst
===================================================================
--- test/test_rename_guiframe/docs/sphinx/api/local_perspectives/plotting/AnnulusSlicer.rst (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/docs/sphinx/api/local_perspectives/plotting/AnnulusSlicer.rst (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,15 @@
+.. Autogenerated by genmods.py
+
+******************************************************************************
+AnnulusSlicer
+******************************************************************************
+
+:mod:`sans.guiframe.local_perspectives.plotting.AnnulusSlicer`
+==============================================================================
+
+.. automodule:: sans.guiframe.local_perspectives.plotting.AnnulusSlicer
+ :members:
+ :undoc-members:
+ :inherited-members:
+ :show-inheritance:
+
Index: test/test_rename_guiframe/docs/sphinx/api/local_perspectives/plotting/Arc.rst
===================================================================
--- test/test_rename_guiframe/docs/sphinx/api/local_perspectives/plotting/Arc.rst (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/docs/sphinx/api/local_perspectives/plotting/Arc.rst (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,15 @@
+.. Autogenerated by genmods.py
+
+******************************************************************************
+Arc
+******************************************************************************
+
+:mod:`sans.guiframe.local_perspectives.plotting.Arc`
+==============================================================================
+
+.. automodule:: sans.guiframe.local_perspectives.plotting.Arc
+ :members:
+ :undoc-members:
+ :inherited-members:
+ :show-inheritance:
+
Index: test/test_rename_guiframe/docs/sphinx/api/local_perspectives/plotting/AzimutSlicer.rst
===================================================================
--- test/test_rename_guiframe/docs/sphinx/api/local_perspectives/plotting/AzimutSlicer.rst (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/docs/sphinx/api/local_perspectives/plotting/AzimutSlicer.rst (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,15 @@
+.. Autogenerated by genmods.py
+
+******************************************************************************
+AzimutSlicer
+******************************************************************************
+
+:mod:`sans.guiframe.local_perspectives.plotting.AzimutSlicer`
+==============================================================================
+
+.. automodule:: sans.guiframe.local_perspectives.plotting.AzimutSlicer
+ :members:
+ :undoc-members:
+ :inherited-members:
+ :show-inheritance:
+
Index: test/test_rename_guiframe/docs/sphinx/api/local_perspectives/plotting/BaseInteractor.rst
===================================================================
--- test/test_rename_guiframe/docs/sphinx/api/local_perspectives/plotting/BaseInteractor.rst (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/docs/sphinx/api/local_perspectives/plotting/BaseInteractor.rst (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,15 @@
+.. Autogenerated by genmods.py
+
+******************************************************************************
+BaseInteractor
+******************************************************************************
+
+:mod:`sans.guiframe.local_perspectives.plotting.BaseInteractor`
+==============================================================================
+
+.. automodule:: sans.guiframe.local_perspectives.plotting.BaseInteractor
+ :members:
+ :undoc-members:
+ :inherited-members:
+ :show-inheritance:
+
Index: test/test_rename_guiframe/docs/sphinx/api/local_perspectives/plotting/Edge.rst
===================================================================
--- test/test_rename_guiframe/docs/sphinx/api/local_perspectives/plotting/Edge.rst (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/docs/sphinx/api/local_perspectives/plotting/Edge.rst (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,15 @@
+.. Autogenerated by genmods.py
+
+******************************************************************************
+Edge
+******************************************************************************
+
+:mod:`sans.guiframe.local_perspectives.plotting.Edge`
+==============================================================================
+
+.. automodule:: sans.guiframe.local_perspectives.plotting.Edge
+ :members:
+ :undoc-members:
+ :inherited-members:
+ :show-inheritance:
+
Index: test/test_rename_guiframe/docs/sphinx/api/local_perspectives/plotting/Plotter1D.rst
===================================================================
--- test/test_rename_guiframe/docs/sphinx/api/local_perspectives/plotting/Plotter1D.rst (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/docs/sphinx/api/local_perspectives/plotting/Plotter1D.rst (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,15 @@
+.. Autogenerated by genmods.py
+
+******************************************************************************
+Plotter1D
+******************************************************************************
+
+:mod:`sans.guiframe.local_perspectives.plotting.Plotter1D`
+==============================================================================
+
+.. automodule:: sans.guiframe.local_perspectives.plotting.Plotter1D
+ :members:
+ :undoc-members:
+ :inherited-members:
+ :show-inheritance:
+
Index: test/test_rename_guiframe/docs/sphinx/api/local_perspectives/plotting/Plotter2D.rst
===================================================================
--- test/test_rename_guiframe/docs/sphinx/api/local_perspectives/plotting/Plotter2D.rst (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/docs/sphinx/api/local_perspectives/plotting/Plotter2D.rst (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,15 @@
+.. Autogenerated by genmods.py
+
+******************************************************************************
+Plotter2D
+******************************************************************************
+
+:mod:`sans.guiframe.local_perspectives.plotting.Plotter2D`
+==============================================================================
+
+.. automodule:: sans.guiframe.local_perspectives.plotting.Plotter2D
+ :members:
+ :undoc-members:
+ :inherited-members:
+ :show-inheritance:
+
Index: test/test_rename_guiframe/docs/sphinx/api/local_perspectives/plotting/SectorSlicer.rst
===================================================================
--- test/test_rename_guiframe/docs/sphinx/api/local_perspectives/plotting/SectorSlicer.rst (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/docs/sphinx/api/local_perspectives/plotting/SectorSlicer.rst (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,15 @@
+.. Autogenerated by genmods.py
+
+******************************************************************************
+SectorSlicer
+******************************************************************************
+
+:mod:`sans.guiframe.local_perspectives.plotting.SectorSlicer`
+==============================================================================
+
+.. automodule:: sans.guiframe.local_perspectives.plotting.SectorSlicer
+ :members:
+ :undoc-members:
+ :inherited-members:
+ :show-inheritance:
+
Index: test/test_rename_guiframe/docs/sphinx/api/local_perspectives/plotting/SlicerParameters.rst
===================================================================
--- test/test_rename_guiframe/docs/sphinx/api/local_perspectives/plotting/SlicerParameters.rst (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/docs/sphinx/api/local_perspectives/plotting/SlicerParameters.rst (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,15 @@
+.. Autogenerated by genmods.py
+
+******************************************************************************
+SlicerParameters
+******************************************************************************
+
+:mod:`sans.guiframe.local_perspectives.plotting.SlicerParameters`
+==============================================================================
+
+.. automodule:: sans.guiframe.local_perspectives.plotting.SlicerParameters
+ :members:
+ :undoc-members:
+ :inherited-members:
+ :show-inheritance:
+
Index: test/test_rename_guiframe/docs/sphinx/api/local_perspectives/plotting/binder.rst
===================================================================
--- test/test_rename_guiframe/docs/sphinx/api/local_perspectives/plotting/binder.rst (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/docs/sphinx/api/local_perspectives/plotting/binder.rst (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,15 @@
+.. Autogenerated by genmods.py
+
+******************************************************************************
+binder
+******************************************************************************
+
+:mod:`sans.guiframe.local_perspectives.plotting.binder`
+==============================================================================
+
+.. automodule:: sans.guiframe.local_perspectives.plotting.binder
+ :members:
+ :undoc-members:
+ :inherited-members:
+ :show-inheritance:
+
Index: test/test_rename_guiframe/docs/sphinx/api/local_perspectives/plotting/boxMask.rst
===================================================================
--- test/test_rename_guiframe/docs/sphinx/api/local_perspectives/plotting/boxMask.rst (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/docs/sphinx/api/local_perspectives/plotting/boxMask.rst (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,15 @@
+.. Autogenerated by genmods.py
+
+******************************************************************************
+boxMask
+******************************************************************************
+
+:mod:`sans.guiframe.local_perspectives.plotting.boxMask`
+==============================================================================
+
+.. automodule:: sans.guiframe.local_perspectives.plotting.boxMask
+ :members:
+ :undoc-members:
+ :inherited-members:
+ :show-inheritance:
+
Index: test/test_rename_guiframe/docs/sphinx/api/local_perspectives/plotting/boxSlicer.rst
===================================================================
--- test/test_rename_guiframe/docs/sphinx/api/local_perspectives/plotting/boxSlicer.rst (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/docs/sphinx/api/local_perspectives/plotting/boxSlicer.rst (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,15 @@
+.. Autogenerated by genmods.py
+
+******************************************************************************
+boxSlicer
+******************************************************************************
+
+:mod:`sans.guiframe.local_perspectives.plotting.boxSlicer`
+==============================================================================
+
+.. automodule:: sans.guiframe.local_perspectives.plotting.boxSlicer
+ :members:
+ :undoc-members:
+ :inherited-members:
+ :show-inheritance:
+
Index: test/test_rename_guiframe/docs/sphinx/api/local_perspectives/plotting/boxSum.rst
===================================================================
--- test/test_rename_guiframe/docs/sphinx/api/local_perspectives/plotting/boxSum.rst (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/docs/sphinx/api/local_perspectives/plotting/boxSum.rst (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,15 @@
+.. Autogenerated by genmods.py
+
+******************************************************************************
+boxSum
+******************************************************************************
+
+:mod:`sans.guiframe.local_perspectives.plotting.boxSum`
+==============================================================================
+
+.. automodule:: sans.guiframe.local_perspectives.plotting.boxSum
+ :members:
+ :undoc-members:
+ :inherited-members:
+ :show-inheritance:
+
Index: test/test_rename_guiframe/docs/sphinx/api/local_perspectives/plotting/detector_dialog.rst
===================================================================
--- test/test_rename_guiframe/docs/sphinx/api/local_perspectives/plotting/detector_dialog.rst (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/docs/sphinx/api/local_perspectives/plotting/detector_dialog.rst (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,15 @@
+.. Autogenerated by genmods.py
+
+******************************************************************************
+detector_dialog
+******************************************************************************
+
+:mod:`sans.guiframe.local_perspectives.plotting.detector_dialog`
+==============================================================================
+
+.. automodule:: sans.guiframe.local_perspectives.plotting.detector_dialog
+ :members:
+ :undoc-members:
+ :inherited-members:
+ :show-inheritance:
+
Index: test/test_rename_guiframe/docs/sphinx/api/local_perspectives/plotting/index.rst
===================================================================
--- test/test_rename_guiframe/docs/sphinx/api/local_perspectives/plotting/index.rst (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/docs/sphinx/api/local_perspectives/plotting/index.rst (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,33 @@
+.. Autogenerated by genmods.py
+
+.. _api-index:
+
+##############################################################################
+ Local Perspective: Plotting
+##############################################################################
+
+.. only:: html
+
+ :Release: |version|
+ :Date: |today|
+
+.. toctree::
+
+ AnnulusSlicer.rst
+ Arc.rst
+ AzimutSlicer.rst
+ BaseInteractor.rst
+ binder.rst
+ boxMask.rst
+ boxSlicer.rst
+ boxSum.rst
+ detector_dialog.rst
+ Edge.rst
+ masking.rst
+ Plotter1D.rst
+ Plotter2D.rst
+ plotting.rst
+ sectorMask.rst
+ SectorSlicer.rst
+ slicerpanel.rst
+ SlicerParameters.rst
Index: test/test_rename_guiframe/docs/sphinx/api/local_perspectives/plotting/masking.rst
===================================================================
--- test/test_rename_guiframe/docs/sphinx/api/local_perspectives/plotting/masking.rst (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/docs/sphinx/api/local_perspectives/plotting/masking.rst (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,15 @@
+.. Autogenerated by genmods.py
+
+******************************************************************************
+masking
+******************************************************************************
+
+:mod:`sans.guiframe.local_perspectives.plotting.masking`
+==============================================================================
+
+.. automodule:: sans.guiframe.local_perspectives.plotting.masking
+ :members:
+ :undoc-members:
+ :inherited-members:
+ :show-inheritance:
+
Index: test/test_rename_guiframe/docs/sphinx/api/local_perspectives/plotting/plotting.rst
===================================================================
--- test/test_rename_guiframe/docs/sphinx/api/local_perspectives/plotting/plotting.rst (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/docs/sphinx/api/local_perspectives/plotting/plotting.rst (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,15 @@
+.. Autogenerated by genmods.py
+
+******************************************************************************
+plotting
+******************************************************************************
+
+:mod:`sans.guiframe.local_perspectives.plotting.plotting`
+==============================================================================
+
+.. automodule:: sans.guiframe.local_perspectives.plotting.plotting
+ :members:
+ :undoc-members:
+ :inherited-members:
+ :show-inheritance:
+
Index: test/test_rename_guiframe/docs/sphinx/api/local_perspectives/plotting/sectorMask.rst
===================================================================
--- test/test_rename_guiframe/docs/sphinx/api/local_perspectives/plotting/sectorMask.rst (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/docs/sphinx/api/local_perspectives/plotting/sectorMask.rst (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,15 @@
+.. Autogenerated by genmods.py
+
+******************************************************************************
+sectorMask
+******************************************************************************
+
+:mod:`sans.guiframe.local_perspectives.plotting.sectorMask`
+==============================================================================
+
+.. automodule:: sans.guiframe.local_perspectives.plotting.sectorMask
+ :members:
+ :undoc-members:
+ :inherited-members:
+ :show-inheritance:
+
Index: test/test_rename_guiframe/docs/sphinx/api/local_perspectives/plotting/slicerpanel.rst
===================================================================
--- test/test_rename_guiframe/docs/sphinx/api/local_perspectives/plotting/slicerpanel.rst (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/docs/sphinx/api/local_perspectives/plotting/slicerpanel.rst (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,15 @@
+.. Autogenerated by genmods.py
+
+******************************************************************************
+slicerpanel
+******************************************************************************
+
+:mod:`sans.guiframe.local_perspectives.plotting.slicerpanel`
+==============================================================================
+
+.. automodule:: sans.guiframe.local_perspectives.plotting.slicerpanel
+ :members:
+ :undoc-members:
+ :inherited-members:
+ :show-inheritance:
+
Index: test/test_rename_guiframe/docs/sphinx/api/statusbar.rst
===================================================================
--- test/test_rename_guiframe/docs/sphinx/api/statusbar.rst (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/docs/sphinx/api/statusbar.rst (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,15 @@
+.. Autogenerated by genmods.py
+
+******************************************************************************
+statusbar
+******************************************************************************
+
+:mod:`sans.guiframe.statusbar`
+==============================================================================
+
+.. automodule:: sans.guiframe.statusbar
+ :members:
+ :undoc-members:
+ :inherited-members:
+ :show-inheritance:
+
Index: test/test_rename_guiframe/docs/sphinx/api/utils.rst
===================================================================
--- test/test_rename_guiframe/docs/sphinx/api/utils.rst (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/docs/sphinx/api/utils.rst (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,15 @@
+.. Autogenerated by genmods.py
+
+******************************************************************************
+utils
+******************************************************************************
+
+:mod:`sans.guiframe.utils`
+==============================================================================
+
+.. automodule:: sans.guiframe.utils
+ :members:
+ :undoc-members:
+ :inherited-members:
+ :show-inheritance:
+
Index: test/test_rename_guiframe/docs/sphinx/api/version.rst
===================================================================
--- test/test_rename_guiframe/docs/sphinx/api/version.rst (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/docs/sphinx/api/version.rst (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,15 @@
+.. Autogenerated by genmods.py
+
+******************************************************************************
+version
+******************************************************************************
+
+:mod:`sans.guiframe.version`
+==============================================================================
+
+.. automodule:: sans.guiframe.version
+ :members:
+ :undoc-members:
+ :inherited-members:
+ :show-inheritance:
+
Index: test/test_rename_guiframe/docs/sphinx/conf.py
===================================================================
--- test/test_rename_guiframe/docs/sphinx/conf.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/docs/sphinx/conf.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,220 @@
+# -*- coding: utf-8 -*-
+#
+# guiframe documentation build configuration file, created by
+# sphinx-quickstart on Thu Jun 03 11:04:06 2010.
+#
+# This file is execfile()d with the current directory set to its containing dir.
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+import sys, os
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+sys.path.append(os.path.abspath(os.path.dirname('../../guiframe')))
+path = '../../guiframe/local_perspectives/plotting'
+sys.path.append(os.path.abspath(os.path.dirname(path)))
+sys.path.append(os.path.abspath('_extensions'))
+# -- General configuration -----------------------------------------------------
+
+# If your documentation needs a minimal Sphinx version, state it here.
+#needs_sphinx = '1.0'
+
+# Add any Sphinx extension module names here, as strings. They can be extensions
+# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
+extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest',
+ 'sphinx.ext.coverage', 'sphinx.ext.pngmath',
+ 'only_directives',
+ ]
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix of source filenames.
+source_suffix = '.rst'
+
+# The encoding of source files.
+#source_encoding = 'utf-8-sig'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = u'guiframe'
+copyright = u'2010, sans group'
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+# The short X.Y version.
+version = '0.1'
+# The full version, including alpha/beta/rc tags.
+release = '0.1.0'
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#language = None
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+#today_fmt = '%B %d, %Y'
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+exclude_patterns = ['_build']
+
+# The reST default role (used for this markup: `text`) to use for all documents.
+#default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+# A list of ignored prefixes for module index sorting.
+#modindex_common_prefix = []
+
+
+# -- Options for HTML output ---------------------------------------------------
+
+# The theme to use for HTML and HTML Help pages. Major themes that come with
+# Sphinx are currently 'default' and 'sphinxdoc'.
+html_theme = 'default'
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further. For a list of options available for each theme, see the
+# documentation.
+#html_theme_options = {}
+
+# Add any paths that contain custom themes here, relative to this directory.
+#html_theme_path = []
+
+# The name for this set of Sphinx documents. If None, it defaults to
+# " v documentation".
+#html_title = None
+
+# A shorter title for the navigation bar. Default is the same as html_title.
+#html_short_title = None
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+#html_logo = None
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+#html_favicon = None
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['_static']
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+#html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+#html_sidebars = {}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#html_additional_pages = {}
+
+# If false, no module index is generated.
+#html_domain_indices = True
+
+# If false, no index is generated.
+#html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+#html_split_index = False
+
+# If true, links to the reST sources are added to the pages.
+#html_show_sourcelink = True
+
+# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
+#html_show_sphinx = True
+
+# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
+#html_show_copyright = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a tag referring to it. The value of this option must be the
+# base URL from which the finished HTML is served.
+#html_use_opensearch = ''
+
+# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = ''
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'guiframedoc'
+
+
+# -- Options for LaTeX output --------------------------------------------------
+
+# The paper size ('letter' or 'a4').
+#latex_paper_size = 'letter'
+
+# The font size ('10pt', '11pt' or '12pt').
+#latex_font_size = '10pt'
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title, author, documentclass [howto/manual]).
+latex_documents = [
+ ('index', 'guiframe.tex', u'guiframe Documentation',
+ u'sans group', 'manual'),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+#latex_logo = None
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+#latex_use_parts = False
+
+# If true, show page references after internal links.
+#latex_show_pagerefs = False
+
+# If true, show URL addresses after external links.
+#latex_show_urls = False
+
+# Additional stuff for the LaTeX preamble.
+#latex_preamble = ''
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_domain_indices = True
+
+
+# -- Options for manual page output --------------------------------------------
+
+# One entry per manual page. List of tuples
+# (source start file, name, description, authors, manual section).
+man_pages = [
+ ('index', 'guiframe', u'guiframe Documentation',
+ [u'sans group'], 1)
+]
Index: test/test_rename_guiframe/docs/sphinx/genmods.py
===================================================================
--- test/test_rename_guiframe/docs/sphinx/genmods.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/docs/sphinx/genmods.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,96 @@
+from __future__ import with_statement
+import os.path
+
+MODULE_TEMPLATE=""".. Autogenerated by genmods.py
+
+******************************************************************************
+%(name)s
+******************************************************************************
+
+:mod:`%(package)s.%(module)s`
+==============================================================================
+
+.. automodule:: %(package)s.%(module)s
+ :members:
+ :undoc-members:
+ :inherited-members:
+ :show-inheritance:
+
+"""
+
+INDEX_TEMPLATE=""".. Autogenerated by genmods.py
+
+.. _api-index:
+
+##############################################################################
+ %(package_name)s
+##############################################################################
+
+.. only:: html
+
+ :Release: |version|
+ :Date: |today|
+
+.. toctree::
+
+ %(rsts)s
+"""
+
+
+def genfiles(package, package_name, modules, dir='api'):
+
+ if not os.path.exists(dir):
+ os.makedirs(dir)
+
+ for module,name in modules:
+ with open(os.path.join(dir,module+'.rst'), 'w') as f:
+ f.write(MODULE_TEMPLATE%locals())
+
+ rsts = "\n ".join(module+'.rst' for module,name in modules)
+ with open(os.path.join(dir,'index.rst'),'w') as f:
+ f.write(INDEX_TEMPLATE%locals())
+
+
+modules=[
+ ('aboutbox', 'aboutbox'),
+ ('config', 'config'),
+ ('data_loader', 'data_loader'),
+ ('dataFitting', 'dataFitting'),
+ ('dummyapp', 'dummyapp'),
+ ('gui_manager', 'gui_manager'),
+ ('load_thread', 'load_thread'),
+ ('statusbar', 'statusbar'),
+ ('utils', 'utils'),
+ ('version', 'version'),
+]
+package = 'sans.guiframe'
+package_name='Reference'
+
+if __name__ == "__main__":
+ genfiles(package, package_name, modules, dir='api')
+
+ modules=[
+ ('AnnulusSlicer', 'AnnulusSlicer'),
+ ('Arc', 'Arc'),
+ ('AzimutSlicer', 'AzimutSlicer'),
+ ('BaseInteractor', 'BaseInteractor'),
+ ('binder', 'binder'),
+ ('boxMask', 'boxMask'),
+ ('boxSlicer', 'boxSlicer'),
+ ('boxSum', 'boxSum'),
+ ('detector_dialog', 'detector_dialog'),
+ ('Edge', 'Edge'),
+ ('masking', 'masking'),
+ ('Plotter1D', 'Plotter1D'),
+ ('Plotter2D', 'Plotter2D'),
+ ('plotting', 'plotting'),
+ ('sectorMask', 'sectorMask'),
+ ('SectorSlicer', 'SectorSlicer'),
+ ('slicerpanel', 'slicerpanel'),
+ ('SlicerParameters', 'SlicerParameters'),
+ ]
+ package = 'sans.guiframe.local_perspectives.plotting'
+ package_name = 'Local Perspective: Plotting'
+ genfiles(package, package_name, modules, dir='api/local_perspectives/plotting')
+ print "Sphinx: generate .rst files complete..."
+
Index: test/test_rename_guiframe/docs/sphinx/index.rst
===================================================================
--- test/test_rename_guiframe/docs/sphinx/index.rst (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/docs/sphinx/index.rst (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,23 @@
+.. guiframe documentation master file, created by
+ sphinx-quickstart on Thu Jun 03 11:04:06 2010.
+ You can adapt this file completely to your liking, but it should at least
+ contain the root `toctree` directive.
+
+Welcome to guiframe's documentation!
+====================================
+
+Contents:
+
+.. toctree::
+ :maxdepth: 2
+
+ api/index.rst
+ api/local_perspectives/plotting/index.rst
+
+Indices and tables
+==================
+
+* :ref:`genindex`
+* :ref:`modindex`
+* :ref:`search`
+
Index: test/test_rename_guiframe/docs/sphinx/make.bat
===================================================================
--- test/test_rename_guiframe/docs/sphinx/make.bat (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/docs/sphinx/make.bat (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,155 @@
+@ECHO OFF
+
+REM Command file for Sphinx documentation
+
+if "%SPHINXBUILD%" == "" (
+ set SPHINXBUILD=sphinx-build
+)
+set BUILDDIR=_build
+set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
+if NOT "%PAPER%" == "" (
+ set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
+)
+
+if "%1" == "" goto help
+
+if "%1" == "help" (
+ :help
+ echo.Please use `make ^` where ^ is one of
+ echo. html to make standalone HTML files
+ echo. dirhtml to make HTML files named index.html in directories
+ echo. singlehtml to make a single large HTML file
+ echo. pickle to make pickle files
+ echo. json to make JSON files
+ echo. htmlhelp to make HTML files and a HTML help project
+ echo. qthelp to make HTML files and a qthelp project
+ echo. devhelp to make HTML files and a Devhelp project
+ echo. epub to make an epub
+ echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
+ echo. text to make text files
+ echo. man to make manual pages
+ echo. changes to make an overview over all changed/added/deprecated items
+ echo. linkcheck to check all external links for integrity
+ echo. doctest to run all doctests embedded in the documentation if enabled
+ goto end
+)
+
+if "%1" == "clean" (
+ for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
+ del /q /s %BUILDDIR%\*
+ goto end
+)
+
+if "%1" == "html" (
+ %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
+ echo.
+ echo.Build finished. The HTML pages are in %BUILDDIR%/html.
+ goto end
+)
+
+if "%1" == "dirhtml" (
+ %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
+ echo.
+ echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
+ goto end
+)
+
+if "%1" == "singlehtml" (
+ %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
+ echo.
+ echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
+ goto end
+)
+
+if "%1" == "pickle" (
+ %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
+ echo.
+ echo.Build finished; now you can process the pickle files.
+ goto end
+)
+
+if "%1" == "json" (
+ %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
+ echo.
+ echo.Build finished; now you can process the JSON files.
+ goto end
+)
+
+if "%1" == "htmlhelp" (
+ %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
+ echo.
+ echo.Build finished; now you can run HTML Help Workshop with the ^
+.hhp project file in %BUILDDIR%/htmlhelp.
+ goto end
+)
+
+if "%1" == "qthelp" (
+ %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
+ echo.
+ echo.Build finished; now you can run "qcollectiongenerator" with the ^
+.qhcp project file in %BUILDDIR%/qthelp, like this:
+ echo.^> qcollectiongenerator %BUILDDIR%\qthelp\guiframe.qhcp
+ echo.To view the help file:
+ echo.^> assistant -collectionFile %BUILDDIR%\qthelp\guiframe.ghc
+ goto end
+)
+
+if "%1" == "devhelp" (
+ %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
+ echo.
+ echo.Build finished.
+ goto end
+)
+
+if "%1" == "epub" (
+ %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
+ echo.
+ echo.Build finished. The epub file is in %BUILDDIR%/epub.
+ goto end
+)
+
+if "%1" == "latex" (
+ %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
+ echo.
+ echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
+ goto end
+)
+
+if "%1" == "text" (
+ %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
+ echo.
+ echo.Build finished. The text files are in %BUILDDIR%/text.
+ goto end
+)
+
+if "%1" == "man" (
+ %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
+ echo.
+ echo.Build finished. The manual pages are in %BUILDDIR%/man.
+ goto end
+)
+
+if "%1" == "changes" (
+ %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
+ echo.
+ echo.The overview file is in %BUILDDIR%/changes.
+ goto end
+)
+
+if "%1" == "linkcheck" (
+ %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
+ echo.
+ echo.Link check complete; look for any errors in the above output ^
+or in %BUILDDIR%/linkcheck/output.txt.
+ goto end
+)
+
+if "%1" == "doctest" (
+ %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
+ echo.
+ echo.Testing of doctests in the sources finished, look at the ^
+results in %BUILDDIR%/doctest/output.txt.
+ goto end
+)
+
+:end
Index: test/test_rename_guiframe/dummyapp.py
===================================================================
--- test/test_rename_guiframe/dummyapp.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/dummyapp.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,125 @@
+"""
+Dummy application.
+Allows the user to set an external data manager
+"""
+import gui_manager
+
+from sans.guiframe.plugin_base import PluginBase
+
+class DummyView(gui_manager.ViewApp):
+ """
+ """
+
+class TestPlugin(PluginBase):
+
+ def populate_menu(self, parent):
+ """
+ Create and return the list of application menu
+ items for the plug-in.
+ :param parent: parent window
+
+ :return: plug-in menu
+
+ """
+ import wx
+ # Create a menu
+ plug_menu = wx.Menu()
+
+ # Always get event IDs from wx
+ id = wx.NewId()
+
+ # Fill your menu
+ plug_menu.Append(id, '&Do something')
+ def _on_do_something(event):
+ print "Do something"
+ wx.EVT_MENU(self.parent, id, _on_do_something)
+
+ # Returns the menu and a name for it.
+ return [(plug_menu, "DummyApp")]
+
+ def get_panels(self, parent):
+ """
+ Create and return the list of wx.Panels for your plug-in.
+ Define the plug-in perspective.
+
+ Panels should inherit from DefaultPanel defined below,
+ or should present the same interface. They must define
+ "window_caption" and "window_name".
+
+ :param parent: parent window
+
+ :return: list of panels
+
+ """
+ ## Save a reference to the parent
+ self.parent = parent
+
+ # Define a panel
+ defaultpanel = gui_manager.DefaultPanel(self.parent, -1)
+ defaultpanel.window_name = "Test"
+
+ # If needed, add its name to the perspective list
+ self.perspective = [defaultpanel.window_name]
+
+ # Return the list of panels
+ return [defaultpanel]
+
+ def get_tools(self):
+ """
+ Returns a set of menu entries for tools
+ """
+ def _test_dialog(event):
+ import wx
+ frame = wx.Dialog(None, -1, 'Test Tool')
+ frame.Show(True)
+ return [["Tool 1", "This is an example tool", _test_dialog],
+ ["Tool 2", "This is another example tool", _test_dialog]]
+
+ def get_context_menu(self, graph=None):
+ """
+ This method is optional.
+
+ When the context menu of a plot is rendered, the
+ get_context_menu method will be called to give you a
+ chance to add a menu item to the context menu.
+
+ A ref to a Graph object is passed so that you can
+ investigate the plot content and decide whether you
+ need to add items to the context menu.
+
+ This method returns a list of menu items.
+ Each item is itself a list defining the text to
+ appear in the menu, a tool-tip help text, and a
+ call-back method.
+
+ :param graph: the Graph object to which we attach the context menu
+
+ :return: a list of menu items with call-back function
+ """
+ return [["Menu text",
+ "Tool-tip help text",
+ self._on_context_do_something]]
+
+class SansView():
+
+ def __init__(self):
+ """
+ Initialization
+ """
+ self.gui = DummyView(0)
+
+ fitting_plug = TestPlugin()
+ self.gui.add_perspective(fitting_plug)
+
+ # Build the GUI
+ self.gui.build_gui()
+
+ # Set the application manager for the GUI
+ self.gui.set_manager(self)
+
+ # Start the main loop
+ self.gui.MainLoop()
+
+if __name__ == "__main__":
+ sansview = SansView()
+
Index: test/test_rename_guiframe/events.py
===================================================================
--- test/test_rename_guiframe/events.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/events.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,30 @@
+import wx.lib.newevent
+#send data to data manager
+(NewStoreDataEvent, EVT_NEW_STORE_DATA) = wx.lib.newevent.NewEvent()
+# send data to other perspectives
+(NewLoadedDataEvent, EVT_NEW_LOADED_DATA) = wx.lib.newevent.NewEvent()
+# plot data
+(NewPlotEvent, EVT_NEW_PLOT) = wx.lib.newevent.NewEvent()
+# print the messages on statusbar
+(StatusEvent, EVT_STATUS) = wx.lib.newevent.NewEvent()
+#create a panel slicer
+(SlicerPanelEvent, EVT_SLICER_PANEL) = wx.lib.newevent.NewEvent()
+#print update paramaters for panel slicer
+(SlicerParamUpdateEvent, EVT_SLICER_PARS_UPDATE) = wx.lib.newevent.NewEvent()
+#update the slicer from the panel
+(SlicerParameterEvent, EVT_SLICER_PARS) = wx.lib.newevent.NewEvent()
+#slicer event
+(SlicerEvent, EVT_SLICER) = wx.lib.newevent.NewEvent()
+## event that that destroy panel name in the datapanel combobox
+(DeletePlotPanelEvent, EVT_DELETE_PLOTPANEL) = wx.lib.newevent.NewEvent()
+##event that allow to add more that to the same plot
+(AddManyDataEvent, EVT_ADD_MANY_DATA) = wx.lib.newevent.NewEvent()
+##event for the panel on focus
+(PanelOnFocusEvent, EVT_PANEL_ON_FOCUS) = wx.lib.newevent.NewEvent()
+#book mark event
+(AppendBookmarkEvent, EVT_APPEND_BOOKMARK) = wx.lib.newevent.NewEvent()
+#event to ask dataloader plugin to load data if dataloader plugin exist
+(NewLoadDataEvent, EVT_NEW_LOAD_DATA) = wx.lib.newevent.NewEvent()
+#event to toggle from single model to batch
+(NewBatchEvent, EVT_NEW_BATCH) = wx.lib.newevent.NewEvent()
+
Index: test/test_rename_guiframe/gui_manager.py
===================================================================
--- test/test_rename_guiframe/gui_manager.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/gui_manager.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,2748 @@
+
+################################################################################
+#This software was developed by the University of Tennessee as part of the
+#Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
+#project funded by the US National Science Foundation.
+#
+#See the license text in license.txt
+#
+#copyright 2008, University of Tennessee
+################################################################################
+
+
+import wx
+import wx.aui
+import os
+import sys
+import xml
+
+
+# Try to find a local config
+import imp
+DATAPATH = os.getcwd()
+tem_path = sys.path[0]
+if os.path.isfile(tem_path):
+ tem_path = os.path.dirname(tem_path)
+os.chdir(tem_path)
+PATH_APP = os.getcwd()
+if(os.path.isfile("%s/%s.py" % (PATH_APP, 'local_config'))) or \
+ (os.path.isfile("%s/%s.pyc" % (PATH_APP, 'local_config'))):
+ fObj, path_config, descr = imp.find_module('local_config', [PATH_APP])
+ try:
+ config = imp.load_module('local_config', fObj, path_config, descr)
+ except:
+ # Didn't find local config, load the default
+ import config
+ finally:
+ if fObj:
+ fObj.close()
+else:
+ # Try simply importing local_config
+ import local_config as config
+
+#import compileall
+import py_compile
+
+c_name = os.path.join(PATH_APP, 'custom_config.py')
+if(os.path.isfile("%s/%s.py" % (PATH_APP, 'custom_config'))):
+ py_compile.compile(file=c_name)
+ #compileall.compile_dir(dir=path, force=True, quiet=0)
+ cfObj, path_cconfig, descr = imp.find_module('custom_config', [PATH_APP])
+try:
+ custom_config = imp.load_module('custom_config', cfObj, PATH_APP, descr)
+except:
+ custom_config = None
+finally:
+ if custom_config != None:
+ cfObj.close()
+
+
+import warnings
+warnings.simplefilter("ignore")
+
+import logging
+
+from sans.guiframe.events import EVT_STATUS
+from sans.guiframe.events import EVT_APPEND_BOOKMARK
+from sans.guiframe.events import EVT_PANEL_ON_FOCUS
+from sans.guiframe.events import EVT_NEW_LOAD_DATA
+from sans.guiframe.events import StatusEvent
+from sans.guiframe.events import NewPlotEvent
+from sans.guiframe.gui_style import GUIFRAME
+from sans.guiframe.gui_style import GUIFRAME_ID
+#from sans.guiframe.events import NewLoadedDataEvent
+from sans.guiframe.data_panel import DataPanel
+from sans.guiframe.panel_base import PanelBase
+from sans.guiframe.gui_toolbar import GUIToolBar
+from sans.guiframe.data_processor import GridFrame
+from sans.guiframe.events import EVT_NEW_BATCH
+from DataLoader.loader import Loader
+
+
+#read some constants from config
+APPLICATION_STATE_EXTENSION = config.APPLICATION_STATE_EXTENSION
+APPLICATION_NAME = config.__appname__
+SPLASH_SCREEN_PATH = config.SPLASH_SCREEN_PATH
+
+SPLASH_SCREEN_WIDTH = config.SPLASH_SCREEN_WIDTH
+SPLASH_SCREEN_HEIGHT = config.SPLASH_SCREEN_HEIGHT
+SS_MAX_DISPLAY_TIME = config.SS_MAX_DISPLAY_TIME
+
+try:
+ DATALOADER_SHOW = custom_config.DATALOADER_SHOW
+ TOOLBAR_SHOW = custom_config.TOOLBAR_SHOW
+ FIXED_PANEL = custom_config.FIXED_PANEL
+ WELCOME_PANEL_SHOW = custom_config.WELCOME_PANEL_SHOW
+ PLOPANEL_WIDTH = custom_config.PLOPANEL_WIDTH
+ DATAPANEL_WIDTH = custom_config.DATAPANEL_WIDTH
+ GUIFRAME_WIDTH = custom_config.GUIFRAME_WIDTH
+ GUIFRAME_HEIGHT = custom_config.GUIFRAME_HEIGHT
+ DEFAULT_PERSPECTIVE = custom_config.DEFAULT_PERSPECTIVE
+ CLEANUP_PLOT = custom_config.CLEANUP_PLOT
+except:
+ DATALOADER_SHOW = True
+ TOOLBAR_SHOW = True
+ FIXED_PANEL = True
+ WELCOME_PANEL_SHOW = False
+ PLOPANEL_WIDTH = config.PLOPANEL_WIDTH
+ DATAPANEL_WIDTH = config.DATAPANEL_WIDTH
+ GUIFRAME_WIDTH = config.GUIFRAME_WIDTH
+ GUIFRAME_HEIGHT = config.GUIFRAME_HEIGHT
+ DEFAULT_PERSPECTIVE = None
+ CLEANUP_PLOT = False
+
+DEFAULT_STYLE = config.DEFAULT_STYLE
+
+
+PLOPANEL_HEIGTH = config.PLOPANEL_HEIGTH
+DATAPANEL_HEIGHT = config.DATAPANEL_HEIGHT
+PLUGIN_STATE_EXTENSIONS = config.PLUGIN_STATE_EXTENSIONS
+OPEN_SAVE_MENU = config.OPEN_SAVE_PROJECT_MENU
+VIEW_MENU = config.VIEW_MENU
+EDIT_MENU = config.EDIT_MENU
+extension_list = []
+if APPLICATION_STATE_EXTENSION is not None:
+ extension_list.append(APPLICATION_STATE_EXTENSION)
+EXTENSIONS = PLUGIN_STATE_EXTENSIONS + extension_list
+try:
+ PLUGINS_WLIST = '|'.join(config.PLUGINS_WLIST)
+except:
+ PLUGINS_WLIST = ''
+APPLICATION_WLIST = config.APPLICATION_WLIST
+if sys.platform.count("darwin")==0:
+ IS_WIN = True
+else:
+ IS_WIN = False
+
+class ViewerFrame(wx.Frame):
+ """
+ Main application frame
+ """
+
+ def __init__(self, parent, title,
+ size=(GUIFRAME_WIDTH, GUIFRAME_HEIGHT),
+ gui_style=DEFAULT_STYLE,
+ pos=wx.DefaultPosition):
+ """
+ Initialize the Frame object
+ """
+
+ wx.Frame.__init__(self, parent=parent, title=title, pos=pos,size=size)
+ # title
+ self.title = title
+ # Preferred window size
+ self._window_width, self._window_height = size
+ self.__gui_style = gui_style
+ # Logging info
+ logging.basicConfig(level=logging.DEBUG,
+ format='%(asctime)s %(levelname)s %(message)s',
+ filename='sans_app.log',
+ filemode='w')
+ path = os.path.dirname(__file__)
+ temp_path = os.path.join(path,'images')
+ ico_file = os.path.join(temp_path,'ball.ico')
+ if os.path.isfile(ico_file):
+ self.SetIcon(wx.Icon(ico_file, wx.BITMAP_TYPE_ICO))
+ else:
+ temp_path = os.path.join(os.getcwd(),'images')
+ ico_file = os.path.join(temp_path,'ball.ico')
+ if os.path.isfile(ico_file):
+ self.SetIcon(wx.Icon(ico_file, wx.BITMAP_TYPE_ICO))
+ else:
+ ico_file = os.path.join(os.path.dirname(os.path.sys.path[0]),
+ 'images', 'ball.ico')
+ if os.path.isfile(ico_file):
+ self.SetIcon(wx.Icon(ico_file, wx.BITMAP_TYPE_ICO))
+ self.path = PATH_APP
+ ## Application manager
+ self._input_file = None
+ self.app_manager = None
+ self._mgr = None
+ #add current perpsective
+ self._current_perspective = None
+ self._plotting_plugin = None
+ self._data_plugin = None
+ #Menu bar and item
+ self._menubar = None
+ self._file_menu = None
+ self._data_menu = None
+ self._view_menu = None
+ self._window_menu = None
+ self._data_panel_menu = None
+ self._help_menu = None
+ self._tool_menu = None
+ self._applications_menu_pos = -1
+ self._applications_menu_name = None
+ self._applications_menu = None
+ self._edit_menu = None
+ self._toolbar_menu = None
+ self._save_appl_menu = None
+ #tool bar
+ self._toolbar = None
+ # number of plugins
+ self._num_perspectives = 0
+ # plot duck cleanup option
+ self.cleanup_plots = CLEANUP_PLOT
+ # (un)-focus color
+ #self.color = '#b3b3b3'
+ ## Find plug-ins
+ # Modify this so that we can specify the directory to look into
+ self.plugins = []
+ #add local plugin
+ self.plugins += self._get_local_plugins()
+ self.plugins += self._find_plugins()
+ ## List of panels
+ self.panels = {}
+ # List of plot panels
+ self.plot_panels = {}
+
+ # Default locations
+ self._default_save_location = os.getcwd()
+
+ # Welcome panel
+ self.defaultPanel = None
+ #panel on focus
+ self.panel_on_focus = None
+ #control_panel on focus
+ self.cpanel_on_focus = None
+ self.loader = Loader()
+ #data manager
+ from data_manager import DataManager
+ self._data_manager = DataManager()
+ self._data_panel = DataPanel(parent=self)
+ if self.panel_on_focus is not None:
+ self._data_panel.set_panel_on_focus(self.panel_on_focus.window_caption)
+ # list of plot panels in schedule to full redraw
+ self.schedule = False
+ #self.callback = True
+ self._idle_count = 0
+ self.schedule_full_draw_list = []
+ self.idletimer = wx.CallLater(1, self._onDrawIdle)
+
+ self.batch_frame = GridFrame(parent=self)
+ self.batch_frame.Hide()
+ # Check for update
+ #self._check_update(None)
+ # Register the close event so it calls our own method
+ wx.EVT_CLOSE(self, self.Close)
+ # Register to status events
+ self.Bind(EVT_STATUS, self._on_status_event)
+ #Register add extra data on the same panel event on load
+ self.Bind(EVT_PANEL_ON_FOCUS, self.set_panel_on_focus)
+ self.Bind(EVT_APPEND_BOOKMARK, self.append_bookmark)
+ self.Bind(EVT_NEW_LOAD_DATA, self.on_load_data)
+ self.Bind(EVT_NEW_BATCH, self.on_batch_selection)
+ self.setup_custom_conf()
+
+ def on_set_batch_result(self, data, name):
+ """
+ Display data into a grid in batch mode and show the grid
+ """
+ self.batch_frame.set_data(data)
+ self.batch_frame.Show(True)
+
+
+ def on_batch_selection(self, event):
+ """
+ :param event: contains parameter enable . when enable is set to True
+ the application is in Batch mode
+ else the application is default mode(single mode)
+ """
+ self.batch_on = event.enable
+ for plug in self.plugins:
+ plug.set_batch_selection(self.batch_on)
+
+ def setup_custom_conf(self):
+ """
+ Set up custom configuration if exists
+ """
+ if custom_config == None:
+ return
+
+ if not FIXED_PANEL:
+ self.__gui_style &= (~GUIFRAME.FIXED_PANEL)
+ self.__gui_style |= GUIFRAME.FLOATING_PANEL
+
+ if not DATALOADER_SHOW:
+ self.__gui_style &= (~GUIFRAME.MANAGER_ON)
+
+ if not TOOLBAR_SHOW:
+ self.__gui_style &= (~GUIFRAME.TOOLBAR_ON)
+
+ if WELCOME_PANEL_SHOW:
+ self.__gui_style |= GUIFRAME.WELCOME_PANEL_ON
+
+ def set_custom_default_perspective(self):
+ """
+ Set default starting perspective
+ """
+ if custom_config == None:
+ return
+ for plugin in self.plugins:
+ try:
+ if plugin.sub_menu == DEFAULT_PERSPECTIVE:
+
+ plugin.on_perspective(event=None)
+ #self._check_applications_menu()
+ break
+ except:
+ pass
+ return
+
+ def on_load_data(self, event):
+ """
+ received an event to trigger load from data plugin
+ """
+ if self._data_plugin is not None:
+ self._data_plugin.load_data(event)
+
+ def get_current_perspective(self):
+ """
+ return the current perspective
+ """
+ return self._current_perspective
+
+ def set_input_file(self, input_file):
+ """
+ :param input_file: file to read
+ """
+ self._input_file = input_file
+
+ def get_data_manager(self):
+ """
+ """
+ return self._data_manager
+
+ def get_toolbar(self):
+ """
+ """
+ return self._toolbar
+
+ def set_panel_on_focus(self, event):
+ """
+ Store reference to the last panel on focus
+ update the toolbar if available
+ update edit menu if available
+ """
+ if event != None:
+ self.panel_on_focus = event.panel
+ panel_name = 'No panel on focus'
+ application_name = 'No Selected Analysis'
+ if self.panel_on_focus is not None:
+ if self.panel_on_focus not in self.plot_panels.values():
+ for ID in self.panels.keys():
+ if self.panel_on_focus != self.panels[ID]:
+ self.panels[ID].on_kill_focus(None)
+
+ if self._data_panel is not None and \
+ self.panel_on_focus is not None:
+ panel_name = self.panel_on_focus.window_caption
+ ID = self.panel_on_focus.uid
+ self._data_panel.set_panel_on_focus(ID)
+ #update combo
+ if self.panel_on_focus in self.plot_panels.values():
+ combo = self._data_panel.cb_plotpanel
+ combo_title = str(self.panel_on_focus.window_caption)
+ combo.SetStringSelection(combo_title)
+ combo.SetToolTip( wx.ToolTip(combo_title ))
+ elif self.panel_on_focus != self._data_panel:
+ cpanel = self.panel_on_focus
+ if self.cpanel_on_focus != cpanel:
+ self.cpanel_on_focus = self.panel_on_focus
+ #update toolbar
+ self._update_toolbar_helper()
+ #update edit menu
+ self.enable_edit_menu()
+
+ def reset_bookmark_menu(self, panel):
+ """
+ Reset Bookmark menu list
+
+ : param panel: a control panel or tap where the bookmark is
+ """
+ cpanel = panel
+ if self._toolbar != None and cpanel._bookmark_flag:
+ for item in self._toolbar.get_bookmark_items():
+ self._toolbar.remove_bookmark_item(item)
+ self._toolbar.add_bookmark_default()
+ pos = 0
+ for bitem in cpanel.popUpMenu.GetMenuItems():
+ pos += 1
+ if pos < 3:
+ continue
+ id = bitem.GetId()
+ label = bitem.GetLabel()
+ self._toolbar.append_bookmark_item(id, label)
+ wx.EVT_MENU(self, id, cpanel._back_to_bookmark)
+ self._toolbar.Realize()
+
+
+ def build_gui(self):
+ """
+ """
+ # set tool bar
+ self._setup_tool_bar()
+ # Set up the layout
+ self._setup_layout()
+
+ # Set up the menu
+ self._setup_menus()
+
+ try:
+ self.load_from_cmd(self._input_file)
+ except:
+ msg = "%s Cannot load file %s\n" %(str(APPLICATION_NAME),
+ str(self._input_file))
+ msg += str(sys.exc_value) + '\n'
+ print msg
+ if self._data_panel is not None:
+ self._data_panel.fill_cbox_analysis(self.plugins)
+ self.post_init()
+ # Set Custom default
+ self.set_custom_default_perspective()
+ # Set up extra custom tool menu
+ self._setup_extra_custom()
+ #self.Show(True)
+ #self._check_update(None)
+
+ def _setup_extra_custom(self):
+ """
+ Set up toolbar and welcome view if needed
+ """
+ style = self.__gui_style & GUIFRAME.TOOLBAR_ON
+ if (style == GUIFRAME.TOOLBAR_ON) & (not self._toolbar.IsShown()):
+ self._on_toggle_toolbar()
+
+ # Set Custom deafult start page
+ welcome_style = self.__gui_style & GUIFRAME.WELCOME_PANEL_ON
+ if welcome_style == GUIFRAME.WELCOME_PANEL_ON:
+ self.show_welcome_panel(None)
+
+ def _setup_layout(self):
+ """
+ Set up the layout
+ """
+ # Status bar
+ from gui_statusbar import StatusBar
+ self.sb = StatusBar(self, wx.ID_ANY)
+ self.SetStatusBar(self.sb)
+ # Add panel
+ default_flag = wx.aui.AUI_MGR_DEFAULT#| wx.aui.AUI_MGR_ALLOW_ACTIVE_PANE
+ self._mgr = wx.aui.AuiManager(self, flags=default_flag)
+ self._mgr.SetDockSizeConstraint(0.5, 0.5)
+ # border color
+ #self.b_color = wx.aui.AUI_DOCKART_BORDER_COLOUR
+ #self._mgr.GetArtProvider().SetColor(self.b_color, self.color)
+ #self._mgr.SetArtProvider(wx.aui.AuiDockArt(wx.AuiDefaultDockArt))
+ #print "set", self._dockart.GetColour(13)
+ # Load panels
+ self._load_panels()
+ self.set_default_perspective()
+ self._mgr.Update()
+
+ def SetStatusText(self, *args, **kwds):
+ """
+ """
+ number = self.sb.get_msg_position()
+ wx.Frame.SetStatusText(number=number, *args, **kwds)
+
+ def PopStatusText(self, *args, **kwds):
+ """
+ """
+ field = self.sb.get_msg_position()
+ wx.Frame.PopStatusText(field=field)
+
+ def PushStatusText(self, *args, **kwds):
+ """
+ """
+ field = self.sb.get_msg_position()
+ wx.Frame.PushStatusText(self, field=field, string=string)
+
+ def add_perspective(self, plugin):
+ """
+ Add a perspective if it doesn't already
+ exist.
+ """
+ self._num_perspectives += 1
+ is_loaded = False
+ for item in self.plugins:
+ if plugin.__class__ == item.__class__:
+ msg = "Plugin %s already loaded" % plugin.sub_menu
+ logging.info(msg)
+ is_loaded = True
+ if not is_loaded:
+
+ self.plugins.append(plugin)
+
+
+ def _get_local_plugins(self):
+ """
+ get plugins local to guiframe and others
+ """
+ plugins = []
+ #import guiframe local plugins
+ #check if the style contain guiframe.dataloader
+ style1 = self.__gui_style & GUIFRAME.DATALOADER_ON
+ style2 = self.__gui_style & GUIFRAME.PLOTTING_ON
+ if style1 == GUIFRAME.DATALOADER_ON:
+ try:
+ from sans.guiframe.local_perspectives.data_loader import data_loader
+ self._data_plugin = data_loader.Plugin()
+ plugins.append(self._data_plugin)
+ except:
+ msg = "ViewerFrame._get_local_plugins:"
+ msg += "cannot import dataloader plugin.\n %s" % sys.exc_value
+ logging.error(msg)
+ if style2 == GUIFRAME.PLOTTING_ON:
+ try:
+ from sans.guiframe.local_perspectives.plotting import plotting
+ self._plotting_plugin = plotting.Plugin()
+ plugins.append(self._plotting_plugin)
+ except:
+ msg = "ViewerFrame._get_local_plugins:"
+ msg += "cannot import plotting plugin.\n %s" % sys.exc_value
+ logging.error(msg)
+
+ return plugins
+
+ def _find_plugins(self, dir="perspectives"):
+ """
+ Find available perspective plug-ins
+
+ :param dir: directory in which to look for plug-ins
+
+ :return: list of plug-ins
+
+ """
+ import imp
+ plugins = []
+ # Go through files in panels directory
+ try:
+ list = os.listdir(dir)
+ ## the default panel is the panel is the last plugin added
+ for item in list:
+ toks = os.path.splitext(os.path.basename(item))
+ name = ''
+ if not toks[0] == '__init__':
+ if toks[1] == '.py' or toks[1] == '':
+ name = toks[0]
+ #check the validity of the module name parsed
+ #before trying to import it
+ if name is None or name.strip() == '':
+ continue
+ path = [os.path.abspath(dir)]
+ file = ''
+ try:
+ if toks[1] == '':
+ mod_path = '.'.join([dir, name])
+ module = __import__(mod_path, globals(),
+ locals(), [name])
+ else:
+ (file, path, info) = imp.find_module(name, path)
+ module = imp.load_module( name, file, item, info)
+ if hasattr(module, "PLUGIN_ID"):
+ try:
+ plug = module.Plugin()
+ if plug.set_default_perspective():
+ self._current_perspective = plug
+ plugins.append(plug)
+
+ msg = "Found plug-in: %s" % module.PLUGIN_ID
+ logging.info(msg)
+ except:
+ msg = "Error accessing PluginPanel"
+ msg += " in %s\n %s" % (name, sys.exc_value)
+ config.printEVT(msg)
+ except:
+ msg = "ViewerFrame._find_plugins: %s" % sys.exc_value
+ #print msg
+ logging.error(msg)
+ finally:
+ if not file == None:
+ file.close()
+ except:
+ # Should raise and catch at a higher level and
+ # display error on status bar
+ pass
+
+ return plugins
+
+ def set_welcome_panel(self, panel_class):
+ """
+ Sets the default panel as the given welcome panel
+
+ :param panel_class: class of the welcome panel to be instantiated
+
+ """
+ self.defaultPanel = panel_class(self, -1, style=wx.RAISED_BORDER)
+
+ def _get_panels_size(self, p):
+ """
+ find the proper size of the current panel
+ get the proper panel width and height
+ """
+ panel_height_min = self._window_height
+ panel_width_min = self._window_width
+ style = self.__gui_style & (GUIFRAME.MANAGER_ON)
+ if self._data_panel is not None and (p == self._data_panel):
+ panel_width_min = DATAPANEL_WIDTH
+ panel_height_min = self._window_height * 0.8
+ return panel_width_min, panel_height_min
+ if hasattr(p, "CENTER_PANE") and p.CENTER_PANE:
+ style = self.__gui_style & (GUIFRAME.PLOTTING_ON|GUIFRAME.MANAGER_ON)
+ if style == (GUIFRAME.PLOTTING_ON|GUIFRAME.MANAGER_ON):
+ panel_width_min = self._window_width -\
+ (DATAPANEL_WIDTH +config.PLOPANEL_WIDTH)
+ return panel_width_min, panel_height_min
+ return panel_width_min, panel_height_min
+
+ def _load_panels(self):
+ """
+ Load all panels in the panels directory
+ """
+
+ # Look for plug-in panels
+ panels = []
+ for item in self.plugins:
+ if hasattr(item, "get_panels"):
+ ps = item.get_panels(self)
+ panels.extend(ps)
+
+ # Show a default panel with some help information
+ # It also sets the size of the application windows
+ #TODO: Use this for slpash screen
+ if self.defaultPanel is None:
+ self.defaultPanel = DefaultPanel(self, -1, style=wx.RAISED_BORDER)
+ # add a blank default panel always present
+ self.panels["default"] = self.defaultPanel
+ self._mgr.AddPane(self.defaultPanel, wx.aui.AuiPaneInfo().
+ Name("default").
+ CenterPane().
+ #CloseButton(False).
+ #MinimizeButton(False).
+ # This is where we set the size of
+ # the application window
+ BestSize(wx.Size(self._window_width,
+ self._window_height)).
+ Show())
+
+ #add data panel
+ self.panels["data_panel"] = self._data_panel
+ w, h = self._get_panels_size(self._data_panel)
+ self._mgr.AddPane(self._data_panel, wx.aui.AuiPaneInfo().
+ Name(self._data_panel.window_name).
+ Caption(self._data_panel.window_caption).
+ Left().
+ MinimizeButton().
+ CloseButton(IS_WIN).
+ TopDockable(False).
+ BottomDockable(False).
+ LeftDockable(True).
+ RightDockable(False).
+ BestSize(wx.Size(w, h)).
+ Hide())
+
+ style = self.__gui_style & GUIFRAME.MANAGER_ON
+ data_pane = self._mgr.GetPane(self.panels["data_panel"].window_name)
+ if style != GUIFRAME.MANAGER_ON:
+ self._mgr.GetPane(self.panels["data_panel"].window_name).Hide()
+ else:
+ self._mgr.GetPane(self.panels["data_panel"].window_name).Show()
+
+ # Add the panels to the AUI manager
+ for panel_class in panels:
+ p = panel_class
+ id = wx.NewId()
+ #w, h = self._get_panels_size(p)
+ # Check whether we need to put this panel
+ # in the center pane
+ if hasattr(p, "CENTER_PANE") and p.CENTER_PANE:
+ w, h = self._get_panels_size(p)
+ if p.CENTER_PANE:
+ self.panels[str(id)] = p
+ self._mgr.AddPane(p, wx.aui.AuiPaneInfo().
+ Name(p.window_name).
+ CenterPane().
+ Center().
+ CloseButton(False).
+ Hide())
+ else:
+ self.panels[str(id)] = p
+ self._mgr.AddPane(p, wx.aui.AuiPaneInfo().
+ Name(p.window_name).Caption(p.window_caption).
+ Right().
+ Dock().
+ TopDockable().
+ BottomDockable().
+ LeftDockable().
+ RightDockable().
+ MinimizeButton().
+ Hide())
+
+ def update_data(self, prev_data, new_data):
+ """
+ """
+ prev_id, data_state = self._data_manager.update_data(prev_data=prev_data,
+ new_data=new_data)
+
+ self._data_panel.remove_by_id(prev_id)
+ self._data_panel.load_data_list(data_state)
+
+ def update_theory(self, data_id, theory, state=None):
+ """
+ """
+ data_state = self._data_manager.update_theory(data_id=data_id,
+ theory=theory,
+ state=state)
+ self._data_panel.load_data_list(data_state)
+
+ def onfreeze(self, theory_id):
+ """
+ """
+ data_state_list = self._data_manager.freeze(theory_id)
+ self._data_panel.load_data_list(list=data_state_list)
+ for data_state in data_state_list.values():
+ new_plot = data_state.get_data()
+
+ wx.PostEvent(self, NewPlotEvent(plot=new_plot,
+ title=new_plot.title))
+
+ def freeze(self, data_id, theory_id):
+ """
+ """
+ data_state_list = self._data_manager.freeze_theory(data_id=data_id,
+ theory_id=theory_id)
+ self._data_panel.load_data_list(list=data_state_list)
+ for data_state in data_state_list.values():
+ new_plot = data_state.get_data()
+ wx.PostEvent(self, NewPlotEvent(plot=new_plot,
+ title=new_plot.title))
+
+ def delete_data(self, data):
+ """
+ """
+ self._current_perspective.delete_data(data)
+
+
+ def get_context_menu(self, plotpanel=None):
+ """
+ Get the context menu items made available
+ by the different plug-ins.
+ This function is used by the plotting module
+ """
+ if plotpanel is None:
+ return
+ menu_list = []
+ for item in self.plugins:
+ menu_list.extend(item.get_context_menu(plotpanel=plotpanel))
+ return menu_list
+
+ def popup_panel(self, p):
+ """
+ Add a panel object to the AUI manager
+
+ :param p: panel object to add to the AUI manager
+
+ :return: ID of the event associated with the new panel [int]
+
+ """
+ ID = wx.NewId()
+ self.panels[str(ID)] = p
+ count = 0
+ for item in self.panels:
+ if self.panels[item].window_name.startswith(p.window_name):
+ count += 1
+ windowname = p.window_name
+ caption = p.window_caption
+ if count > 0:
+ windowname += str(count+1)
+ caption += (' '+str(count))
+ p.window_name = windowname
+ p.window_caption = caption
+
+ style1 = self.__gui_style & GUIFRAME.FIXED_PANEL
+ style2 = self.__gui_style & GUIFRAME.FLOATING_PANEL
+ if style1 == GUIFRAME.FIXED_PANEL:
+ self._mgr.AddPane(p, wx.aui.AuiPaneInfo().
+ Name(windowname).
+ Caption(caption).
+ Position(10).
+ Floatable().
+ Right().
+ Dock().
+ MinimizeButton().
+ Resizable(True).
+ # Use a large best size to make sure the AUI
+ # manager takes all the available space
+ BestSize(wx.Size(PLOPANEL_WIDTH,
+ PLOPANEL_HEIGTH)))
+
+ self._popup_fixed_panel(p)
+
+ elif style2 == GUIFRAME.FLOATING_PANEL:
+ self._mgr.AddPane(p, wx.aui.AuiPaneInfo().
+ Name(windowname).Caption(caption).
+ MinimizeButton().
+ Resizable(True).
+ # Use a large best size to make sure the AUI
+ # manager takes all the available space
+ BestSize(wx.Size(PLOPANEL_WIDTH,
+ PLOPANEL_HEIGTH)))
+
+ self._popup_floating_panel(p)
+
+ # Register for showing/hiding the panel
+ wx.EVT_MENU(self, ID, self.on_view)
+ if p not in self.plot_panels.values() and p.group_id != None:
+ self.plot_panels[ID] = p
+ if len(self.plot_panels) == 1:
+ self.panel_on_focus = p
+ self.set_panel_on_focus(None)
+ if self._data_panel is not None and \
+ self._plotting_plugin is not None:
+ ind = self._data_panel.cb_plotpanel.FindString('None')
+ if ind != wx.NOT_FOUND:
+ self._data_panel.cb_plotpanel.Delete(ind)
+ if caption not in self._data_panel.cb_plotpanel.GetItems():
+ self._data_panel.cb_plotpanel.Append(str(caption), p)
+ return ID
+
+ def _setup_menus(self):
+ """
+ Set up the application menus
+ """
+ # Menu
+ self._menubar = wx.MenuBar()
+ self._add_menu_file()
+ self._add_menu_edit()
+ self._add_menu_view()
+ #self._add_menu_data()
+ self._add_menu_application()
+ self._add_menu_tool()
+ self._add_current_plugin_menu()
+ self._add_menu_window()
+ self._add_help_menu()
+ self.SetMenuBar(self._menubar)
+
+ def _setup_tool_bar(self):
+ """
+ add toolbar to the frame
+ """
+ #set toolbar
+ self._toolbar = GUIToolBar(self, -1)
+ self.SetToolBar(self._toolbar)
+ self._update_toolbar_helper()
+ self._on_toggle_toolbar(event=None)
+
+ def _update_toolbar_helper(self):
+ """
+ """
+ application_name = 'No Selected Analysis'
+ panel_name = 'No Panel on Focus'
+ if self._toolbar is None:
+ return
+ if self.cpanel_on_focus is not None:
+ self.reset_bookmark_menu(self.cpanel_on_focus)
+ self._toolbar.update_toolbar(self.cpanel_on_focus)
+ if self._current_perspective is not None:
+ application_name = self._current_perspective.sub_menu
+ if self.cpanel_on_focus is not None:
+ panel_name = self.cpanel_on_focus.window_caption
+
+ self._toolbar.update_button(application_name=application_name,
+ panel_name=panel_name)
+
+ self._toolbar.Realize()
+
+ def _add_menu_tool(self):
+ """
+ Tools menu
+ Go through plug-ins and find tools to populate the tools menu
+ """
+ style = self.__gui_style & GUIFRAME.CALCULATOR_ON
+ if style == GUIFRAME.CALCULATOR_ON:
+ self._tool_menu = None
+ for item in self.plugins:
+ if hasattr(item, "get_tools"):
+ for tool in item.get_tools():
+ # Only create a menu if we have at least one tool
+ if self._tool_menu is None:
+ self._tool_menu = wx.Menu()
+ id = wx.NewId()
+ self._tool_menu.Append(id, tool[0], tool[1])
+ wx.EVT_MENU(self, id, tool[2])
+ if self._tool_menu is not None:
+ self._menubar.Append(self._tool_menu, '&Tool')
+
+ def _add_current_plugin_menu(self):
+ """
+ add current plugin menu
+ Look for plug-in menus
+ Add available plug-in sub-menus.
+ """
+ if (self._menubar is None) or (self._current_perspective is None):
+ return
+ #replace or add a new menu for the current plugin
+
+ pos = self._menubar.FindMenu(str(self._applications_menu_name))
+ if pos != -1:
+ menu_list = self._current_perspective.populate_menu(self)
+ if menu_list:
+ for (menu, name) in menu_list:
+ hidden_menu = self._menubar.Replace(pos, menu, name)
+ self._applications_menu_name = name
+ #self._applications_menu_pos = pos
+ else:
+ hidden_menu = self._menubar.Remove(pos)
+ self._applications_menu_name = None
+ #get the position of the menu when it first added
+ self._applications_menu_pos = pos
+
+ else:
+ menu_list = self._current_perspective.populate_menu(self)
+ if menu_list:
+ for (menu,name) in menu_list:
+ if self._applications_menu_pos == -1:
+ self._menubar.Append(menu, name)
+ else:
+ self._menubar.Insert(self._applications_menu_pos, menu, name)
+ self._applications_menu_name = name
+
+ def _add_help_menu(self):
+ """
+ add help menu
+ """
+ # Help menu
+ self._help_menu = wx.Menu()
+ style = self.__gui_style & GUIFRAME.WELCOME_PANEL_ON
+ if style == GUIFRAME.WELCOME_PANEL_ON or custom_config != None:
+ # add the welcome panel menu item
+ if self.defaultPanel is not None:
+ id = wx.NewId()
+ self._help_menu.Append(id, '&Welcome', '')
+ self._help_menu.AppendSeparator()
+ wx.EVT_MENU(self, id, self.show_welcome_panel)
+ # Look for help item in plug-ins
+ for item in self.plugins:
+ if hasattr(item, "help"):
+ id = wx.NewId()
+ self._help_menu.Append(id,'&%s Help' % item.sub_menu, '')
+ wx.EVT_MENU(self, id, item.help)
+ if config._do_tutorial:
+ self._help_menu.AppendSeparator()
+ id = wx.NewId()
+ self._help_menu.Append(id,'&Tutorial', 'Software tutorial')
+ wx.EVT_MENU(self, id, self._onTutorial)
+
+ if config._do_aboutbox:
+ self._help_menu.AppendSeparator()
+ id = wx.NewId()
+ self._help_menu.Append(id,'&About', 'Software information')
+ wx.EVT_MENU(self, id, self._onAbout)
+
+ # Checking for updates needs major refactoring to work with py2exe
+ # We need to make sure it doesn't hang the application if the server
+ # is not up. We also need to make sure there's a proper executable to
+ # run if we spawn a new background process.
+ #id = wx.NewId()
+ #self._help_menu.Append(id,'&Check for update',
+ #'Check for the latest version of %s' % config.__appname__)
+ #wx.EVT_MENU(self, id, self._check_update)
+ self._menubar.Append(self._help_menu, '&Help')
+
+ def _add_menu_view(self):
+ """
+ add menu items under view menu
+ """
+ if not VIEW_MENU:
+ return
+ self._view_menu = wx.Menu()
+ style = self.__gui_style & GUIFRAME.MANAGER_ON
+ id = wx.NewId()
+ self._data_panel_menu = self._view_menu.Append(id,
+ '&Show Data Explorer', '')
+ wx.EVT_MENU(self, id, self.show_data_panel)
+ if style == GUIFRAME.MANAGER_ON:
+ self._data_panel_menu.SetText('Hide Data Explorer')
+ else:
+ self._data_panel_menu.SetText('Show Data Explorer')
+ self._view_menu.AppendSeparator()
+ id = wx.NewId()
+ style1 = self.__gui_style & GUIFRAME.TOOLBAR_ON
+ if style1 == GUIFRAME.TOOLBAR_ON:
+ self._toolbar_menu = self._view_menu.Append(id,'&Hide Toolbar', '')
+ else:
+ self._toolbar_menu = self._view_menu.Append(id,'&Show Toolbar', '')
+ wx.EVT_MENU(self, id, self._on_toggle_toolbar)
+
+ if custom_config != None:
+ self._view_menu.AppendSeparator()
+ id = wx.NewId()
+ preference_menu = self._view_menu.Append(id,'Startup Setting', '')
+ wx.EVT_MENU(self, id, self._on_preference_menu)
+
+ self._menubar.Append(self._view_menu, '&View')
+
+ def _on_preference_menu(self, event):
+ """
+ Build a panel to allow to edit Mask
+ """
+
+ from sans.guiframe.startup_configuration \
+ import StartupConfiguration as ConfDialog
+
+ self.panel = ConfDialog(parent=self, gui=self.__gui_style)
+ self.panel.ShowModal()
+ #wx.PostEvent(self.parent, event)
+
+
+ def _add_menu_window(self):
+ """
+ add a menu window to the menu bar
+ Window menu
+ Attach a menu item for each panel in our
+ panel list that also appears in a plug-in.
+
+ Only add the panel menu if there is only one perspective and
+ it has more than two panels.
+ Note: the first plug-in is always the plotting plug-in.
+ The first application
+ #plug-in is always the second one in the list.
+ """
+ self._window_menu = wx.Menu()
+ if self._plotting_plugin is not None:
+ for (menu, name) in self._plotting_plugin.populate_menu(self):
+ self._window_menu.AppendSubMenu(menu, name)
+ self._menubar.Append(self._window_menu, '&Graph')
+
+ style = self.__gui_style & GUIFRAME.PLOTTING_ON
+ if style == GUIFRAME.PLOTTING_ON:
+ self._window_menu.AppendSeparator()
+ id = wx.NewId()
+ preferences_menu = wx.Menu()
+ hint = "All plot panels will floating"
+ preferences_menu.AppendRadioItem(id, '&Float All', hint)
+ wx.EVT_MENU(self, id, self.set_plotpanel_floating)
+ style = self.__gui_style & GUIFRAME.FLOATING_PANEL
+ f_menu = preferences_menu.FindItemById(id)
+ if style == GUIFRAME.FLOATING_PANEL:
+ f_checked = True
+ else:
+ f_checked = False
+ f_menu.Check(f_checked)
+
+ id = wx.NewId()
+ hint = "All plot panels will displayed within the frame"
+ preferences_menu.AppendRadioItem(id, '&Dock All', hint)
+ wx.EVT_MENU(self, id, self.set_plotpanel_fixed)
+ if not f_checked:
+ d_menu = preferences_menu.FindItemById(id)
+ d_menu.Check(True)
+ preferences_menu.AppendSeparator()
+ id = wx.NewId()
+ hint = "Clean up the dock area for plots on new-plot"
+ preferences_menu.AppendCheckItem(id, '&CleanUp Dock on NewPlot', hint)
+ wx.EVT_MENU(self, id, self.on_cleanup_dock)
+ flag = self.cleanup_plots
+ if self.cleanup_plots:
+ c_menu = preferences_menu.FindItemById(id)
+ c_menu.Check(True)
+ self._window_menu.AppendSubMenu(preferences_menu,'&Preferences')
+ if self._window_menu.GetMenuItemCount() == 0:
+ pos = self._menubar.FindMenu('Graph')
+ self._menubar.Remove(pos)
+ #wx.EVT_MENU(self, id, self.show_preferences_panel)
+ """
+ if len(self.plugins) == 2:
+ plug = self.plugins[1]
+ pers = plug.get_perspective()
+
+ if len(pers) > 1:
+ self._window_menu = wx.Menu()
+ for item in self.panels:
+ if item == 'default':
+ continue
+ panel = self.panels[item]
+ if panel.window_name in pers:
+ self._window_menu.Append(int(item),
+ panel.window_caption,
+ "Show %s window" % panel.window_caption)
+ wx.EVT_MENU(self, int(item), self.on_view)
+ self._menubar.Append(self._window_menu, '&Window')
+ """
+
+
+ def _add_menu_application(self):
+ """
+
+ # Attach a menu item for each defined perspective or application.
+ # Only add the perspective menu if there are more than one perspectives
+ add menu application
+ """
+ #style = self.__gui_style & GUIFRAME.MULTIPLE_APPLICATIONS
+ #if style == GUIFRAME.MULTIPLE_APPLICATIONS:
+ if self._num_perspectives > 1:
+ plug_data_count = False
+ plug_no_data_count = False
+ self._applications_menu = wx.Menu()
+ pos = 0
+ separator = self._applications_menu.AppendSeparator()
+ for plug in self.plugins:
+ if len(plug.get_perspective()) > 0:
+ id = wx.NewId()
+ if plug.use_data():
+
+ self._applications_menu.InsertCheckItem(pos, id, plug.sub_menu,
+ "Switch to analysis: %s" % plug.sub_menu)
+ plug_data_count = True
+ pos += 1
+ else:
+ plug_no_data_count = True
+ self._applications_menu.AppendCheckItem(id, plug.sub_menu,
+ "Switch to analysis: %s" % plug.sub_menu)
+ wx.EVT_MENU(self, id, plug.on_perspective)
+ #self._applications_menu.
+ if (not plug_data_count or not plug_no_data_count):
+ self._applications_menu.RemoveItem(separator)
+ self._menubar.Append(self._applications_menu, '&Analysis')
+ self._check_applications_menu()
+
+ def _populate_file_menu(self):
+ """
+ Insert menu item under file menu
+ """
+ for plugin in self.plugins:
+ if len(plugin.populate_file_menu()) > 0:
+ for item in plugin.populate_file_menu():
+ m_name, m_hint, m_handler = item
+ id = wx.NewId()
+ self._file_menu.Append(id, m_name, m_hint)
+ wx.EVT_MENU(self, id, m_handler)
+ self._file_menu.AppendSeparator()
+
+ def _add_menu_file(self):
+ """
+ add menu file
+ """
+
+ # File menu
+ self._file_menu = wx.Menu()
+ #append item from plugin under menu file if necessary
+ self._populate_file_menu()
+ style = self.__gui_style & GUIFRAME.DATALOADER_ON
+ style1 = self.__gui_style & GUIFRAME.MULTIPLE_APPLICATIONS
+ if OPEN_SAVE_MENU:
+ id = wx.NewId()
+ hint_load_file = "read all analysis states saved previously"
+ self._save_appl_menu = self._file_menu.Append(id,
+ '&Open Project', hint_load_file)
+ wx.EVT_MENU(self, id, self._on_open_state_project)
+
+ if style1 == GUIFRAME.MULTIPLE_APPLICATIONS:
+ # some menu of plugin to be seen under file menu
+ hint_load_file = "Read a status files and load"
+ hint_load_file += " them into the analysis"
+ id = wx.NewId()
+ self._save_appl_menu = self._file_menu.Append(id,
+ '&Open Analysis', hint_load_file)
+ wx.EVT_MENU(self, id, self._on_open_state_application)
+ if OPEN_SAVE_MENU:
+ self._file_menu.AppendSeparator()
+ id = wx.NewId()
+ self._file_menu.Append(id, '&Save Project',
+ 'Save the state of the whole analysis')
+ wx.EVT_MENU(self, id, self._on_save_project)
+ if style1 == GUIFRAME.MULTIPLE_APPLICATIONS:
+ #self._file_menu.AppendSeparator()
+ id = wx.NewId()
+ self._save_appl_menu = self._file_menu.Append(id,
+ '&Save Analysis',
+ 'Save state of the current active analysis panel')
+ wx.EVT_MENU(self, id, self._on_save_application)
+ self._file_menu.AppendSeparator()
+
+ id = wx.NewId()
+ self._file_menu.Append(id, '&Quit', 'Exit')
+ wx.EVT_MENU(self, id, self.Close)
+ # Add sub menus
+ self._menubar.Append(self._file_menu, '&File')
+
+ def _add_menu_edit(self):
+ """
+ add menu edit
+ """
+ if not EDIT_MENU:
+ return
+ # Edit Menu
+ self._edit_menu = wx.Menu()
+ self._edit_menu.Append(GUIFRAME_ID.UNDO_ID, '&Undo',
+ 'Undo the previous action')
+ wx.EVT_MENU(self, GUIFRAME_ID.UNDO_ID, self.on_undo_panel)
+ self._edit_menu.Append(GUIFRAME_ID.REDO_ID, '&Redo',
+ 'Redo the previous action')
+ wx.EVT_MENU(self, GUIFRAME_ID.REDO_ID, self.on_redo_panel)
+ self._edit_menu.AppendSeparator()
+ self._edit_menu.Append(GUIFRAME_ID.COPY_ID, '&Copy Params',
+ 'Copy parameter values')
+ wx.EVT_MENU(self, GUIFRAME_ID.COPY_ID, self.on_copy_panel)
+ self._edit_menu.Append(GUIFRAME_ID.PASTE_ID, '&Paste Params',
+ 'Paste parameter values')
+ wx.EVT_MENU(self, GUIFRAME_ID.PASTE_ID, self.on_paste_panel)
+ self._edit_menu.AppendSeparator()
+
+ self._edit_menu.Append(GUIFRAME_ID.PREVIEW_ID, '&Report Results',
+ 'Preview current panel')
+ wx.EVT_MENU(self, GUIFRAME_ID.PREVIEW_ID, self.on_preview_panel)
+ #self._edit_menu.Append(GUIFRAME_ID.PRINT_ID, '&Print',
+ # 'Print current panel')
+ #wx.EVT_MENU(self, GUIFRAME_ID.PRINT_ID, self.on_print_panel)
+ self._edit_menu.Append(GUIFRAME_ID.RESET_ID, '&Reset Page',
+ 'Reset current panel')
+ wx.EVT_MENU(self, GUIFRAME_ID.RESET_ID, self.on_reset_panel)
+
+ self._menubar.Append(self._edit_menu, '&Edit')
+ self.enable_edit_menu()
+
+ def get_style(self):
+ """
+ """
+ return self.__gui_style
+
+ def _add_menu_data(self):
+ """
+ Add menu item item data to menu bar
+ """
+ if self._data_plugin is not None:
+ menu_list = self._data_plugin.populate_menu(self)
+ if menu_list:
+ for (menu, name) in menu_list:
+ self._menubar.Append(menu, name)
+
+
+ def _on_toggle_toolbar(self, event=None):
+ """
+ hide or show toolbar
+ """
+ if self._toolbar is None:
+ return
+ if self._toolbar.IsShown():
+ if self._toolbar_menu is not None:
+ self._toolbar_menu.SetItemLabel('Show Toolbar')
+ self._toolbar.Hide()
+ else:
+ if self._toolbar_menu is not None:
+ self._toolbar_menu.SetItemLabel('Hide Toolbar')
+ self._toolbar.Show()
+ self._toolbar.Realize()
+
+ def _on_status_event(self, evt):
+ """
+ Display status message
+ """
+ # This CallAfter fixes many crashes on MAC.
+ wx.CallAfter(self.sb.set_status, evt)
+
+ def on_view(self, evt):
+ """
+ A panel was selected to be shown. If it's not already
+ shown, display it.
+
+ :param evt: menu event
+
+ """
+ panel_id = str(evt.GetId())
+ self.on_set_plot_focus(self.panels[panel_id])
+ self.show_panel(evt.GetId(), 'on')
+ wx.CallLater(5, self.set_schedule(True))
+ self.set_plot_unfocus()
+
+ def on_close_welcome_panel(self):
+ """
+ Close the welcome panel
+ """
+ if self.defaultPanel is None:
+ return
+ default_panel = self._mgr.GetPane(self.panels["default"].window_name)
+ if default_panel.IsShown():
+ default_panel.Hide()
+ # Recover current perspective
+ perspective = self._current_perspective
+ perspective.on_perspective(event=None)
+ self._mgr.Update()
+ # Show toolbar
+ #style = self.__gui_style & GUIFRAME.TOOLBAR_ON
+ #if (style == GUIFRAME.TOOLBAR_ON) & (not self._toolbar.IsShown()):
+ # self._on_toggle_toolbar()
+
+ def show_welcome_panel(self, event):
+ """
+ Display the welcome panel
+ """
+ if self.defaultPanel is None:
+ return
+ for id, panel in self.panels.iteritems():
+ if id == 'default':
+ # Show default panel
+ if not self._mgr.GetPane(self.panels["default"].window_name).IsShown():
+ self._mgr.GetPane(self.panels["default"].window_name).Show(True)
+ elif id == "data_panel":
+ flag = self._mgr.GetPane(self.panels["data_panel"].window_name).IsShown()
+ self._mgr.GetPane(self.panels["data_panel"].window_name).Show(flag)
+ elif panel not in self.plot_panels.values() :
+ self._mgr.GetPane(self.panels[id].window_name).IsShown()
+ self._mgr.GetPane(self.panels[id].window_name).Hide()
+ #style = self.__gui_style & GUIFRAME.TOOLBAR_ON
+ #if (style == GUIFRAME.TOOLBAR_ON) & (self._toolbar.IsShown()):
+ # # self._toolbar.Show(True)
+ # self._on_toggle_toolbar()
+
+ self._mgr.Update()
+
+ def show_panel(self, uid, show=None):
+ """
+ Shows the panel with the given id
+
+ :param uid: unique ID number of the panel to show
+
+ """
+ ID = str(uid)
+ config.printEVT("show_panel: %s" % ID)
+ if ID in self.panels.keys():
+ if not self._mgr.GetPane(self.panels[ID].window_name).IsShown():
+ if show == 'on':
+ self._mgr.GetPane(self.panels[ID].window_name).Show()
+ elif self.panels[ID].window_caption.split(" ")[0] == \
+ "Residuals":
+ self._mgr.GetPane(self.panels[ID].window_name).Hide()
+ else:
+ self._mgr.GetPane(self.panels[ID].window_name).Show()
+ # Hide default panel
+ self._mgr.GetPane(self.panels["default"].window_name).Hide()
+ self._mgr.Update()
+ self._redraw_idle()
+
+ def hide_panel(self, uid):
+ """
+ hide panel except default panel
+ """
+ ID = str(uid)
+ caption = self.panels[ID].window_caption
+ config.printEVT("hide_panel: %s" % ID)
+ if ID in self.panels.keys():
+ if self._mgr.GetPane(self.panels[ID].window_name).IsShown():
+ self._mgr.GetPane(self.panels[ID].window_name).Hide()
+ if self._data_panel is not None and \
+ ID in self.plot_panels.keys():
+ self._data_panel.cb_plotpanel.Append(str(caption), p)
+ # Do not Hide default panel here...
+ #self._mgr.GetPane(self.panels["default"].window_name).Hide()
+ self._mgr.Update()
+
+ def delete_panel(self, uid):
+ """
+ delete panel given uid
+ """
+ ID = str(uid)
+ config.printEVT("delete_panel: %s" % ID)
+ caption = self.panels[ID].window_caption
+ if ID in self.panels.keys():
+ self.panel_on_focus = None
+ panel = self.panels[ID]
+ self._plotting_plugin.delete_panel(panel.group_id)
+ self._mgr.DetachPane(panel)
+ panel.Hide()
+ panel.clear()
+ panel.Close()
+ self._mgr.Update()
+ #delete uid number not str(uid)
+ if uid in self.plot_panels.keys():
+ del self.plot_panels[uid]
+ return
+
+ def clear_panel(self):
+ """
+ """
+ for item in self.panels:
+ try:
+ self.panels[item].clear_panel()
+ except:
+ pass
+
+ def create_gui_data(self, data, path=None):
+ """
+ """
+ return self._data_manager.create_gui_data(data, path)
+
+ def get_data(self, path):
+ """
+ """
+ message = ""
+ log_msg = ''
+ output = []
+ error_message = ""
+ basename = os.path.basename(path)
+ root, extension = os.path.splitext(basename)
+ if extension.lower() not in EXTENSIONS:
+ log_msg = "File Loader cannot "
+ log_msg += "load: %s\n" % str(basename)
+ log_msg += "Try Data opening...."
+ logging.info(log_msg)
+ self.load_complete(output=output, error_message=error_message,
+ message=log_msg, path=path)
+ return
+
+ #reading a state file
+ for plug in self.plugins:
+ reader, ext = plug.get_extensions()
+ if reader is not None:
+ #read the state of the single plugin
+ if extension == ext:
+ reader.read(path)
+ return
+ elif extension == APPLICATION_STATE_EXTENSION:
+ reader.read(path)
+
+ style = self.__gui_style & GUIFRAME.MANAGER_ON
+ if style == GUIFRAME.MANAGER_ON:
+ if self._data_panel is not None:
+ #data_state = self._data_manager.get_selected_data()
+ #self._data_panel.load_data_list(data_state)
+ self._mgr.GetPane(self._data_panel.window_name).Show(True)
+
+ def load_from_cmd(self, path):
+ """
+ load data from cmd or application
+ """
+ if path is None:
+ return
+ else:
+ path = os.path.abspath(path)
+ if not os.path.isfile(path) and not os.path.isdir(path):
+ return
+
+ if os.path.isdir(path):
+ self.load_folder(path)
+ return
+
+ basename = os.path.basename(path)
+ root, extension = os.path.splitext(basename)
+ if extension.lower() not in EXTENSIONS:
+ self.load_data(path)
+ else:
+ self.load_state(path)
+
+ self._default_save_location = os.path.dirname(path)
+
+ def load_state(self, path):
+ """
+ load data from command line or application
+ """
+ if path and (path is not None) and os.path.isfile(path):
+ basename = os.path.basename(path)
+ if APPLICATION_STATE_EXTENSION is not None \
+ and basename.endswith(APPLICATION_STATE_EXTENSION):
+ #Hide current plot_panels i
+ for ID in self.plot_panels.keys():
+ panel = self._mgr.GetPane(self.plot_panels[ID].window_name)
+ if panel.IsShown():
+ panel.Hide()
+ self.get_data(path)
+ if self.defaultPanel is not None and \
+ self._mgr.GetPane(self.panels["default"].window_name).IsShown():
+ self.on_close_welcome_panel()
+
+ def load_data(self, path):
+ """
+ load data from command line
+ """
+ if not os.path.isfile(path):
+ return
+ basename = os.path.basename(path)
+ root, extension = os.path.splitext(basename)
+ if extension.lower() in EXTENSIONS:
+ log_msg = "Data Loader cannot "
+ log_msg += "load: %s\n" % str(path)
+ log_msg += "Try File opening ...."
+ print log_msg
+ return
+ message = ""
+ log_msg = ''
+ output = {}
+ error_message = ""
+ try:
+ print "Loading Data...:\n" + str(path) + "\n"
+ temp = self.loader.load(path)
+ if temp.__class__.__name__ == "list":
+ for item in temp:
+ data = self.create_gui_data(item, path)
+ output[data.id] = data
+ else:
+ data = self.create_gui_data(temp, path)
+ output[data.id] = data
+
+ self.add_data(data_list=output)
+ except:
+ error_message = "Error while loading"
+ error_message += " Data from cmd:\n %s\n" % str(path)
+ error_message += str(sys.exc_value) + "\n"
+ print error_message
+
+ def load_folder(self, path):
+ """
+ Load entire folder
+ """
+ if not os.path.isdir(path):
+ return
+ if self._data_plugin is None:
+ return
+ try:
+ if path is not None:
+ self._default_save_location = os.path.dirname(path)
+ file_list = self._data_plugin.get_file_path(path)
+ self._data_plugin.get_data(file_list)
+ else:
+ return
+ except:
+ error_message = "Error while loading"
+ error_message += " Data folder from cmd:\n %s\n" % str(path)
+ error_message += str(sys.exc_value) + "\n"
+ print error_message
+
+ def _on_open_state_application(self, event):
+ """
+ """
+ path = None
+ if self._default_save_location == None:
+ self._default_save_location = os.getcwd()
+
+ plug_wlist = self._on_open_state_app_helper()
+ dlg = wx.FileDialog(self,
+ "Choose a file",
+ self._default_save_location, "",
+ plug_wlist)
+ if dlg.ShowModal() == wx.ID_OK:
+ path = dlg.GetPath()
+ if path is not None:
+ self._default_save_location = os.path.dirname(path)
+ dlg.Destroy()
+ self.load_state(path=path)
+
+ def _on_open_state_app_helper(self):
+ """
+ Helps '_on_open_state_application()' to find the extension of
+ the current perspective/application
+ """
+ # No current perspective or no extension attr
+ if self._current_perspective is None:
+ return PLUGINS_WLIST
+ try:
+ # Find the extension of the perspective and get that as 1st item in list
+ ind = None
+ app_ext = self._current_perspective._extensions
+ plug_wlist = config.PLUGINS_WLIST
+ for ext in set(plug_wlist):
+ if ext.count(app_ext) > 0:
+ ind = ext
+ break
+ # Found the extension
+ if ind != None:
+ plug_wlist.remove(ind)
+ plug_wlist.insert(0, ind)
+ try:
+ plug_wlist ='|'.join(plug_wlist)
+ except:
+ plug_wlist = ''
+
+ except:
+ plug_wlist = PLUGINS_WLIST
+
+ return plug_wlist
+
+ def _on_open_state_project(self, event):
+ """
+ """
+ path = None
+ if self._default_save_location == None:
+ self._default_save_location = os.getcwd()
+
+ dlg = wx.FileDialog(self,
+ "Choose a file",
+ self._default_save_location, "",
+ APPLICATION_WLIST)
+ if dlg.ShowModal() == wx.ID_OK:
+ path = dlg.GetPath()
+ if path is not None:
+ self._default_save_location = os.path.dirname(path)
+ dlg.Destroy()
+
+ #try:
+ # os.popen(path)
+ # #self.Close()
+ #except:
+ self.load_state(path=path)
+
+ def _on_save_application(self, event):
+ """
+ save the state of the current active application
+ """
+ if self.cpanel_on_focus is not None:
+ self.cpanel_on_focus.on_save(event)
+
+ def _on_save_project(self, event):
+ """
+ save the state of the SansView as *.svs
+ """
+ ## Default file location for save
+ self._default_save_location = os.getcwd()
+ if self._current_perspective is None:
+ return
+ reader, ext = self._current_perspective.get_extensions()
+ path = None
+ extension = '*' + APPLICATION_STATE_EXTENSION
+ dlg = wx.FileDialog(self, "Save Project file",
+ self._default_save_location, "",
+ extension,
+ wx.SAVE)
+ if dlg.ShowModal() == wx.ID_OK:
+ path = dlg.GetPath()
+ self._default_save_location = os.path.dirname(path)
+ else:
+ return None
+ dlg.Destroy()
+ if path is None:
+ return
+ # default cansas xml doc
+ doc = None
+ for panel in self.panels.values():
+ temp = panel.save_project(doc)
+ if temp is not None:
+ doc = temp
+
+ # Write the XML document
+ extens = APPLICATION_STATE_EXTENSION
+ fName = os.path.splitext(path)[0] + extens
+ if doc != None:
+ fd = open(fName, 'w')
+ fd.write(doc.toprettyxml())
+ fd.close()
+ else:
+ msg = "%s cannot read %s\n" % (str(APPLICATION_NAME), str(path))
+ logging.error(msg)
+
+ def on_save_helper(self, doc, reader, panel, path):
+ """
+ Save state into a file
+ """
+ try:
+ if reader is not None:
+ # case of a panel with multi-pages
+ if hasattr(panel, "opened_pages"):
+ for uid, page in panel.opened_pages.iteritems():
+ data = page.get_data()
+ # state must be cloned
+ state = page.get_state().clone()
+ if data is not None:
+ new_doc = reader.write_toXML(data, state)
+ if doc != None and hasattr(doc, "firstChild"):
+ child = new_doc.firstChild.firstChild
+ doc.firstChild.appendChild(child)
+ else:
+ doc = new_doc
+ # case of only a panel
+ else:
+ data = panel.get_data()
+ state = panel.get_state()
+ if data is not None:
+ new_doc = reader.write_toXML(data, state)
+ if doc != None and hasattr(doc, "firstChild"):
+ child = new_doc.firstChild.firstChild
+ doc.firstChild.appendChild(child)
+ else:
+ doc = new_doc
+ except:
+ raise
+ #pass
+
+ return doc
+
+ def quit_guiframe(self):
+ """
+ Pop up message to make sure the user wants to quit the application
+ """
+ message = "Do you really want to quit \n"
+ message += "this application?"
+ dial = wx.MessageDialog(self, message, 'Question',
+ wx.YES_NO|wx.YES_DEFAULT|wx.ICON_QUESTION)
+ if dial.ShowModal() == wx.ID_YES:
+ return True
+ else:
+ return False
+
+ def Close(self, event=None):
+ """
+ Quit the application
+ """
+ #flag = self.quit_guiframe()
+ if True:
+ wx.Exit()
+ sys.exit()
+
+ def _check_update(self, event=None):
+ """
+ Check with the deployment server whether a new version
+ of the application is available.
+ A thread is started for the connecting with the server. The thread calls
+ a call-back method when the current version number has been obtained.
+ """
+ if hasattr(config, "__update_URL__"):
+ import version
+ checker = version.VersionThread(config.__update_URL__,
+ self._process_version,
+ baggage=event==None)
+ checker.start()
+
+ def _process_version(self, version, standalone=True):
+ """
+ Call-back method for the process of checking for updates.
+ This methods is called by a VersionThread object once the current
+ version number has been obtained. If the check is being done in the
+ background, the user will not be notified unless there's an update.
+
+ :param version: version string
+ :param standalone: True of the update is being checked in
+ the background, False otherwise.
+
+ """
+ try:
+ if cmp(version, config.__version__) > 0:
+ msg = "Version %s is available! See the Help "
+ msg += "menu to download it." % version
+ self.SetStatusText(msg)
+ if not standalone:
+ import webbrowser
+ webbrowser.open(config.__download_page__)
+ else:
+ if not standalone:
+ msg = "You have the latest version"
+ msg += " of %s" % config.__appname__
+ self.SetStatusText(msg)
+ except:
+ msg = "guiframe: could not get latest application"
+ msg += " version number\n %s" % sys.exc_value
+ logging.error(msg)
+ if not standalone:
+ msg = "Could not connect to the application server."
+ msg += " Please try again later."
+ self.SetStatusText(msg)
+
+ def _onAbout(self, evt):
+ """
+ Pop up the about dialog
+
+ :param evt: menu event
+
+ """
+ if config._do_aboutbox:
+ import aboutbox
+ dialog = aboutbox.DialogAbout(None, -1, "")
+ dialog.ShowModal()
+
+ def _onTutorial(self, evt):
+ """
+ Pop up the tutorial dialog
+
+ :param evt: menu event
+
+ """
+ if config._do_tutorial:
+ path = config.TUTORIAL_PATH
+ if IS_WIN:
+ try:
+ from sans.guiframe.pdfview import PDFFrame
+
+ dialog = PDFFrame(None, -1, "Tutorial", path)
+ #self.SetTopWindow(dialog)
+ dialog.Show(True)
+ except:
+ msg = "This feature requires 'Adobe pdf Reader'\n"
+ msg += "Please install it first (Free)..."
+ wx.MessageBox(msg, 'Error')
+ else:
+ try:
+ command = "open "
+ command += path
+ os.system(command)
+ except:
+ msg = "This feature requires 'Preview' Application\n"
+ msg += "Please install it first..."
+ wx.MessageBox(msg, 'Error')
+
+
+ def set_manager(self, manager):
+ """
+ Sets the application manager for this frame
+
+ :param manager: frame manager
+ """
+ self.app_manager = manager
+
+ def post_init(self):
+ """
+ This initialization method is called after the GUI
+ has been created and all plug-ins loaded. It calls
+ the post_init() method of each plug-in (if it exists)
+ so that final initialization can be done.
+ """
+ for item in self.plugins:
+ if hasattr(item, "post_init"):
+ item.post_init()
+
+ def set_default_perspective(self):
+ """
+ Choose among the plugin the first plug-in that has
+ "set_default_perspective" method and its return value is True will be
+ as a default perspective when the welcome page is closed
+ """
+ for item in self.plugins:
+ if hasattr(item, "set_default_perspective"):
+ if item.set_default_perspective():
+ item.on_perspective(event=None)
+ return
+
+ def set_perspective(self, panels):
+ """
+ Sets the perspective of the GUI.
+ Opens all the panels in the list, and closes
+ all the others.
+
+ :param panels: list of panels
+ """
+ #style = self.__gui_style & GUIFRAME.TOOLBAR_ON
+ #if (style == GUIFRAME.TOOLBAR_ON) & (not self._toolbar.IsShown()):
+ # self._on_toggle_toolbar()
+ for item in self.panels:
+ # Check whether this is a sticky panel
+ if hasattr(self.panels[item], "ALWAYS_ON"):
+ if self.panels[item].ALWAYS_ON:
+ continue
+
+ if self.panels[item].window_name in panels:
+ if not self._mgr.GetPane(self.panels[item].window_name).IsShown():
+ self._mgr.GetPane(self.panels[item].window_name).Show()
+ else:
+ # always show the data panel if enable
+ style = self.__gui_style & GUIFRAME.MANAGER_ON
+ if (style == GUIFRAME.MANAGER_ON) and self.panels[item] == self._data_panel:
+ if 'data_panel' in self.panels.keys():
+ flag = self._mgr.GetPane(self.panels['data_panel'].window_name).IsShown()
+ self._mgr.GetPane(self.panels['data_panel'].window_name).Show(flag)
+ else:
+ if self._mgr.GetPane(self.panels[item].window_name).IsShown():
+ self._mgr.GetPane(self.panels[item].window_name).Hide()
+
+ self._mgr.Update()
+
+ def show_data_panel(self, event=None, action=True):
+ """
+ show the data panel
+ """
+ if self._data_panel_menu == None:
+ return
+ label = self._data_panel_menu.GetText()
+ if label == 'Show Data Explorer':
+ pane = self._mgr.GetPane(self.panels["data_panel"].window_name)
+ #if not pane.IsShown():
+ if action:
+ pane.Show(True)
+ self._mgr.Update()
+ self.__gui_style = self.__gui_style | GUIFRAME.MANAGER_ON
+
+ self._data_panel_menu.SetText('Hide Data Explorer')
+ else:
+ pane = self._mgr.GetPane(self.panels["data_panel"].window_name)
+ #if not pane.IsShown():
+ if action:
+ pane.Show(False)
+ self._mgr.Update()
+ self.__gui_style = self.__gui_style & (~GUIFRAME.MANAGER_ON)
+ self._data_panel_menu.SetText('Show Data Explorer')
+
+ def add_data_helper(self, data_list):
+ """
+ """
+ if self._data_manager is not None:
+ self._data_manager.add_data(data_list)
+
+ def add_data(self, data_list):
+ """
+ receive a dictionary of data from loader
+ store them its data manager if possible
+ send to data the current active perspective if the data panel
+ is not active.
+ :param data_list: dictionary of data's ID and value Data
+ """
+ #Store data into manager
+ self.add_data_helper(data_list)
+ # set data in the data panel
+ if self._data_panel is not None:
+ data_state = self._data_manager.get_data_state(data_list.keys())
+ self._data_panel.load_data_list(data_state)
+ #if the data panel is shown wait for the user to press a button
+ #to send data to the current perspective. if the panel is not
+ #show automatically send the data to the current perspective
+ style = self.__gui_style & GUIFRAME.MANAGER_ON
+ if style == GUIFRAME.MANAGER_ON:
+ #wait for button press from the data panel to set_data
+ if self._data_panel is not None:
+ self._mgr.GetPane(self._data_panel.window_name).Show(True)
+ self._mgr.Update()
+ else:
+ #automatically send that to the current perspective
+ self.set_data(data_id=data_list.keys())
+ self.on_close_welcome_panel()
+
+ def set_data(self, data_id, theory_id=None):
+ """
+ set data to current perspective
+ """
+ list_data, _ = self._data_manager.get_by_id(data_id)
+ if self._current_perspective is not None:
+ if self.cleanup_plots:
+ for uid, panel in self.plot_panels.iteritems():
+ #panel = self.plot_panels[uid]
+ window = self._mgr.GetPane(panel.window_name)
+ # To hide all docked plot panels when set the data
+ if not window.IsFloating():
+ self.hide_panel(uid)
+ self._current_perspective.set_data(list_data.values())
+ self.on_close_welcome_panel()
+ else:
+ msg = "Guiframe does not have a current perspective"
+ logging.info(msg)
+
+ def set_theory(self, state_id, theory_id=None):
+ """
+ """
+ _, list_theory = self._data_manager.get_by_id(theory_id)
+ if self._current_perspective is not None:
+ try:
+ self._current_perspective.set_theory(list_theory.values())
+ except:
+ msg = "Guiframe set_theory: \n" + str(sys.exc_value)
+ logging.info(msg)
+ wx.PostEvent(self, StatusEvent(status=msg, info="error"))
+ else:
+ msg = "Guiframe does not have a current perspective"
+ logging.info(msg)
+
+ def plot_data(self, state_id, data_id=None,
+ theory_id=None, append=False):
+ """
+ send a list of data to plot
+ """
+ total_plot_list = []
+ data_list, _ = self._data_manager.get_by_id(data_id)
+ _, temp_list_theory = self._data_manager.get_by_id(theory_id)
+ total_plot_list = data_list.values()
+ for item in temp_list_theory.values():
+ theory_data, theory_state = item
+ total_plot_list.append(theory_data)
+ GROUP_ID = wx.NewId()
+ for new_plot in total_plot_list:
+ if append:
+ if self.panel_on_focus is None:
+ message = "cannot append plot. No plot panel on focus!"
+ message += "please click on any available plot to set focus"
+ wx.PostEvent(self, StatusEvent(status=message,
+ info='warning'))
+ return
+ else:
+ if self.enable_add_data(new_plot):
+ new_plot.group_id = self.panel_on_focus.group_id
+ else:
+ message = "Only 1D Data can be append to"
+ message += " plot panel containing 1D data.\n"
+ message += "%s not be appended.\n" %str(new_plot.name)
+ message += "try new plot option.\n"
+ wx.PostEvent(self, StatusEvent(status=message,
+ info='warning'))
+ else:
+ if self.cleanup_plots:
+ for id, panel in self.plot_panels.iteritems():
+ window = self._mgr.GetPane(panel.window_name)
+ # To hide all docked plot panels when set the data
+ if not window.IsFloating():
+ self.hide_panel(id)
+ #if not append then new plot
+ from sans.guiframe.dataFitting import Data2D
+ if issubclass(Data2D, new_plot.__class__):
+ #for 2 D always plot in a separated new plot
+ new_plot.group_id = wx.NewId()
+ else:
+ # plot all 1D in a new plot
+ new_plot.group_id = GROUP_ID
+ title = "PLOT " + str(new_plot.title)
+ wx.PostEvent(self, NewPlotEvent(plot=new_plot,
+ title=title,
+ group_id = new_plot.group_id))
+
+ def remove_data(self, data_id, theory_id=None):
+ """
+ Delete data state if data_id is provide
+ delete theory created with data of id data_id if theory_id is provide
+ if delete all true: delete the all state
+ else delete theory
+ """
+ temp = data_id + theory_id
+ """
+ value = [plug.is_in_use(temp) for plug in self.plugins]
+ if len(value) > 0:
+ print "value"
+ return
+ from data_panel import DataDialog
+ dlg = DataDialog(data_list=data_list, nb_data=MAX_NBR_DATA)
+ if dlg.ShowModal() == wx.ID_OK:
+ selected_data_list = dlg.get_data()
+ dlg.Destroy()
+ """
+ for plug in self.plugins:
+ plug.delete_data(temp)
+ total_plot_list = []
+ data_list, _ = self._data_manager.get_by_id(data_id)
+ _, temp_list_theory = self._data_manager.get_by_id(theory_id)
+ total_plot_list = data_list.values()
+ for item in temp_list_theory.values():
+ theory_data, theory_state = item
+ total_plot_list.append(theory_data)
+ for new_plot in total_plot_list:
+ id = new_plot.id
+ for group_id in new_plot.list_group_id:
+ wx.PostEvent(self, NewPlotEvent(id=id,
+ group_id=group_id,
+ action='remove'))
+ self._data_manager.delete_data(data_id=data_id,
+ theory_id=theory_id)
+
+
+ def set_current_perspective(self, perspective):
+ """
+ set the current active perspective
+ """
+ self._current_perspective = perspective
+ name = "No current analysis selected"
+ if self._current_perspective is not None:
+ self._add_current_plugin_menu()
+ for panel in self.panels.values():
+ if hasattr(panel, 'CENTER_PANE') and panel.CENTER_PANE:
+ for name in self._current_perspective.get_perspective():
+ if name == panel.window_name:
+ panel.on_set_focus(event=None)
+ break
+ name = self._current_perspective.sub_menu
+ if self._data_panel is not None:
+ self._data_panel.set_active_perspective(name)
+ self._check_applications_menu()
+ #Set the SansView title
+ self._set_title_name(name)
+
+
+ def _set_title_name(self, name):
+ """
+ Set the SansView title w/ the current application name
+
+ : param name: application name [string]
+ """
+ # Set SanView Window title w/ application anme
+ title = self.title + " - " + name + " -"
+ self.SetTitle(title)
+
+ def _check_applications_menu(self):
+ """
+ check the menu of the current application
+ """
+ if self._applications_menu is not None:
+ for menu in self._applications_menu.GetMenuItems():
+ if self._current_perspective is not None:
+ name = self._current_perspective.sub_menu
+ if menu.IsCheckable():
+ if menu.GetLabel() == name:
+ menu.Check(True)
+ else:
+ menu.Check(False)
+
+ def set_plotpanel_floating(self, event=None):
+ """
+ make the plot panel floatable
+ """
+
+ self.__gui_style &= (~GUIFRAME.FIXED_PANEL)
+ self.__gui_style |= GUIFRAME.FLOATING_PANEL
+ plot_panel = []
+ id = event.GetId()
+ menu = self._window_menu.FindItemById(id)
+ if self._plotting_plugin is not None:
+ plot_panel = self._plotting_plugin.plot_panels.values()
+ for p in plot_panel:
+ self._popup_floating_panel(p)
+ menu.Check(True)
+
+ def set_plotpanel_fixed(self, event=None):
+ """
+ make the plot panel fixed
+ """
+ self.__gui_style &= (~GUIFRAME.FLOATING_PANEL)
+ self.__gui_style |= GUIFRAME.FIXED_PANEL
+ plot_panel = []
+ id = event.GetId()
+ menu = self._window_menu.FindItemById(id)
+ if self._plotting_plugin is not None:
+ plot_panel = self._plotting_plugin.plot_panels.values()
+ for p in plot_panel:
+ self._popup_fixed_panel(p)
+ menu.Check(True)
+
+ def on_cleanup_dock(self, event=None):
+ """
+ Set Cleanup Dock option
+ """
+ if event == None:
+ return
+ id = event.GetId()
+ menu = self._window_menu.FindItemById(id)
+ Flag = self.cleanup_plots
+ if not Flag:
+ menu.Check(True)
+ self.cleanup_plots = True
+ msg = "Cleanup-Dock option set to 'ON'."
+ else:
+ menu.Check(False)
+ self.cleanup_plots = False
+ msg = "Cleanup-Dock option set to 'OFF'."
+
+ wx.PostEvent(self, StatusEvent(status= msg))
+
+ def _popup_fixed_panel(self, p):
+ """
+ """
+ style = self.__gui_style & GUIFRAME.FIXED_PANEL
+ if style == GUIFRAME.FIXED_PANEL:
+ self._mgr.GetPane(p.window_name).Dock()
+ self._mgr.GetPane(p.window_name).Floatable()
+ self._mgr.GetPane(p.window_name).Right()
+ self._mgr.GetPane(p.window_name).TopDockable(False)
+ self._mgr.GetPane(p.window_name).BottomDockable(False)
+ self._mgr.GetPane(p.window_name).LeftDockable(False)
+ self._mgr.GetPane(p.window_name).RightDockable(True)
+ self._mgr.Update()
+
+ def _popup_floating_panel(self, p):
+ """
+ """
+ style = self.__gui_style & GUIFRAME.FLOATING_PANEL
+ if style == GUIFRAME.FLOATING_PANEL:
+ self._mgr.GetPane(p.window_name).Floatable(True)
+ self._mgr.GetPane(p.window_name).Float()
+ self._mgr.GetPane(p.window_name).Dockable(False)
+ self._mgr.Update()
+
+ def enable_add_data(self, new_plot):
+ """
+ Enable append data on a plot panel
+ """
+
+ if self.panel_on_focus not in self._plotting_plugin.plot_panels.values():
+ return
+ is_theory = len(self.panel_on_focus.plots) <= 1 and \
+ self.panel_on_focus.plots.values()[0].__class__.__name__ == "Theory1D"
+
+ is_data2d = hasattr(new_plot, 'data')
+
+ is_data1d = self.panel_on_focus.__class__.__name__ == "ModelPanel1D"\
+ and self.panel_on_focus.group_id is not None
+ has_meta_data = hasattr(new_plot, 'meta_data')
+
+ #disable_add_data if the data is being recovered from a saved state file.
+ is_state_data = False
+ if has_meta_data:
+ if 'invstate' in new_plot.meta_data: is_state_data = True
+ if 'prstate' in new_plot.meta_data: is_state_data = True
+ if 'fitstate' in new_plot.meta_data: is_state_data = True
+
+ return is_data1d and not is_data2d and not is_theory and not is_state_data
+
+ def enable_edit_menu(self):
+ """
+ enable menu item under edit menu depending on the panel on focus
+ """
+ if self.cpanel_on_focus is not None and self._edit_menu is not None:
+ flag = self.cpanel_on_focus.get_undo_flag()
+ self._edit_menu.Enable(GUIFRAME_ID.UNDO_ID, flag)
+ flag = self.cpanel_on_focus.get_redo_flag()
+ self._edit_menu.Enable(GUIFRAME_ID.REDO_ID, flag)
+ flag = self.cpanel_on_focus.get_copy_flag()
+ self._edit_menu.Enable(GUIFRAME_ID.COPY_ID, flag)
+ flag = self.cpanel_on_focus.get_paste_flag()
+ self._edit_menu.Enable(GUIFRAME_ID.PASTE_ID, flag)
+ #flag = self.cpanel_on_focus.get_print_flag()
+ #self._edit_menu.Enable(GUIFRAME_ID.PRINT_ID, flag)
+ flag = self.cpanel_on_focus.get_preview_flag()
+ self._edit_menu.Enable(GUIFRAME_ID.PREVIEW_ID, flag)
+ flag = self.cpanel_on_focus.get_reset_flag()
+ self._edit_menu.Enable(GUIFRAME_ID.RESET_ID, flag)
+ else:
+ flag = False
+ self._edit_menu.Enable(GUIFRAME_ID.UNDO_ID, flag)
+ self._edit_menu.Enable(GUIFRAME_ID.REDO_ID, flag)
+ self._edit_menu.Enable(GUIFRAME_ID.COPY_ID, flag)
+ self._edit_menu.Enable(GUIFRAME_ID.PASTE_ID, flag)
+ #self._edit_menu.Enable(GUIFRAME_ID.PRINT_ID, flag)
+ self._edit_menu.Enable(GUIFRAME_ID.PREVIEW_ID, flag)
+ self._edit_menu.Enable(GUIFRAME_ID.RESET_ID, flag)
+
+ def on_undo_panel(self, event=None):
+ """
+ undo previous action of the last panel on focus if possible
+ """
+ if self.cpanel_on_focus is not None:
+ self.cpanel_on_focus.on_undo(event)
+
+ def on_redo_panel(self, event=None):
+ """
+ redo the last cancel action done on the last panel on focus
+ """
+ if self.cpanel_on_focus is not None:
+ self.cpanel_on_focus.on_redo(event)
+
+ def on_copy_panel(self, event=None):
+ """
+ copy the last panel on focus if possible
+ """
+ if self.cpanel_on_focus is not None:
+ self.cpanel_on_focus.on_copy(event)
+
+ def on_paste_panel(self, event=None):
+ """
+ paste clipboard to the last panel on focus
+ """
+ if self.cpanel_on_focus is not None:
+ self.cpanel_on_focus.on_paste(event)
+
+ def on_bookmark_panel(self, event=None):
+ """
+ bookmark panel
+ """
+ if self.cpanel_on_focus is not None:
+ self.cpanel_on_focus.on_bookmark(event)
+
+ def append_bookmark(self, event=None):
+ """
+ Bookmark available information of the panel on focus
+ """
+ self._toolbar.append_bookmark(event)
+
+ def on_save_panel(self, event=None):
+ """
+ save possible information on the current panel
+ """
+ if self.cpanel_on_focus is not None:
+ self.cpanel_on_focus.on_save(event)
+
+ def on_preview_panel(self, event=None):
+ """
+ preview information on the panel on focus
+ """
+ if self.cpanel_on_focus is not None:
+ self.cpanel_on_focus.on_preview(event)
+
+ def on_print_panel(self, event=None):
+ """
+ print available information on the last panel on focus
+ """
+ if self.cpanel_on_focus is not None:
+ self.cpanel_on_focus.on_print(event)
+
+ def on_zoom_panel(self, event=None):
+ """
+ zoom on the current panel if possible
+ """
+ if self.cpanel_on_focus is not None:
+ self.cpanel_on_focus.on_zoom(event)
+
+ def on_zoom_in_panel(self, event=None):
+ """
+ zoom in of the panel on focus
+ """
+ if self.cpanel_on_focus is not None:
+ self.cpanel_on_focus.on_zoom_in(event)
+
+ def on_zoom_out_panel(self, event=None):
+ """
+ zoom out on the panel on focus
+ """
+ if self.cpanel_on_focus is not None:
+ self.cpanel_on_focus.on_zoom_out(event)
+
+ def on_drag_panel(self, event=None):
+ """
+ drag apply to the panel on focus
+ """
+ if self.cpanel_on_focus is not None:
+ self.cpanel_on_focus.on_drag(event)
+
+ def on_reset_panel(self, event=None):
+ """
+ reset the current panel
+ """
+ if self.cpanel_on_focus is not None:
+ self.cpanel_on_focus.on_reset(event)
+
+ def enable_undo(self):
+ """
+ enable undo related control
+ """
+ if self.cpanel_on_focus is not None:
+ self._toolbar.enable_undo(self.cpanel_on_focus)
+
+ def enable_redo(self):
+ """
+ enable redo
+ """
+ if self.cpanel_on_focus is not None:
+ self._toolbar.enable_redo(self.cpanel_on_focus)
+
+ def enable_copy(self):
+ """
+ enable copy related control
+ """
+ if self.cpanel_on_focus is not None:
+ self._toolbar.enable_copy(self.cpanel_on_focus)
+
+ def enable_paste(self):
+ """
+ enable paste
+ """
+ if self.cpanel_on_focus is not None:
+ self._toolbar.enable_paste(self.cpanel_on_focus)
+
+ def enable_bookmark(self):
+ """
+ Bookmark
+ """
+ if self.cpanel_on_focus is not None:
+ self._toolbar.enable_bookmark(self.cpanel_on_focus)
+
+ def enable_save(self):
+ """
+ save
+ """
+ if self.cpanel_on_focus is not None:
+ self._toolbar.enable_save(self.cpanel_on_focus)
+
+ def enable_preview(self):
+ """
+ preview
+ """
+ if self.cpanel_on_focus is not None:
+ self._toolbar.enable_preview(self.cpanel_on_focus)
+
+ def enable_print(self):
+ """
+ print
+ """
+ if self.cpanel_on_focus is not None:
+ self._toolbar.enable_print(self.cpanel_on_focus)
+
+ def enable_zoom(self):
+ """
+ zoom
+ """
+ if self.cpanel_on_focus is not None:
+ self._toolbar.enable_zoom(self.panel_on_focus)
+
+ def enable_zoom_in(self):
+ """
+ zoom in
+ """
+ if self.cpanel_on_focus is not None:
+ self._toolbar.enable_zoom_in(self.panel_on_focus)
+
+ def enable_zoom_out(self):
+ """
+ zoom out
+ """
+ if self.cpanel_on_focus is not None:
+ self._toolbar.enable_zoom_out(self.panel_on_focus)
+
+ def enable_drag(self, event=None):
+ """
+ drag
+ """
+ if self.cpanel_on_focus is not None:
+ self._toolbar.enable_drag(self.panel_on_focus)
+
+ def enable_reset(self):
+ """
+ reset the current panel
+ """
+ if self.cpanel_on_focus is not None:
+ self._toolbar.enable_reset(self.panel_on_focus)
+
+ def set_schedule_full_draw(self, panel=None, func='del'):
+ """
+ Add/subtract the schedule full draw list with the panel given
+
+ :param panel: plot panel
+ :param func: append or del [string]
+ """
+
+ # append this panel in the schedule list if not in yet
+ if func == 'append':
+ if not panel in self.schedule_full_draw_list:
+ self.schedule_full_draw_list.append(panel)
+ # remove this panel from schedule list
+ elif func == 'del':
+ if len(self.schedule_full_draw_list) > 0:
+ if panel in self.schedule_full_draw_list:
+ self.schedule_full_draw_list.remove(panel)
+
+ # reset the schdule
+ if len(self.schedule_full_draw_list) == 0:
+ self.schedule = False
+ else:
+ self.schedule = True
+
+ def full_draw(self):
+ """
+ Draw the panels with axes in the schedule to full dwar list
+ """
+ count = len(self.schedule_full_draw_list)
+ #if not self.schedule:
+ if count < 1:
+ self.set_schedule(False)
+ return
+ else:
+ ind = 0
+ # if any of the panel is shown do full_draw
+ for panel in self.schedule_full_draw_list:
+ ind += 1
+ if self._mgr.GetPane(panel.window_name).IsShown():
+ break
+ # otherwise, return
+ if ind == count:
+ return
+
+ #Simple redraw only for a panel shown
+ def f_draw(panel):
+ """
+ Draw A panel in the full dwar list
+ """
+ try:
+ # This checking of GetCapture is to stop redrawing
+ # while any panel is capture.
+ if self.GetCapture() == None:
+ # draw if possible
+ panel.set_resizing(False)
+ panel.Show(False)
+ panel.draw_plot()
+
+ # Check if the panel is not shown
+ if not self._mgr.GetPane(panel.window_name).IsShown():
+ self._mgr.GetPane(panel.window_name).Hide()
+ else:
+ panel.Show(True)
+ except:
+ pass
+ #print self.callback,self.schedule,self.schedule_full_draw_list
+
+ # Draw all panels
+ map(f_draw, self.schedule_full_draw_list)
+
+ # Reset the attr
+ if len(self.schedule_full_draw_list) == 0:
+ self.set_schedule(False)
+ else:
+ self.set_schedule(True)
+ # do not update mgr
+ #self._mgr.Update()
+
+ def set_schedule(self, schedule=False):
+ """
+ Set schedule
+ """
+ self.schedule = schedule
+
+ def get_schedule(self):
+ """
+ Get schedule
+ """
+ return self.schedule
+
+ def on_set_plot_focus(self, panel):
+ """
+ Set focus on a plot panel
+ """
+ self.set_plot_unfocus()
+ panel.on_set_focus(None)
+ # set focusing panel
+ self.panel_on_focus = panel
+ self.set_panel_on_focus(None)
+
+ def set_plot_unfocus(self):
+ """
+ Un focus all plot panels
+ """
+ for plot in self.plot_panels.values():
+ plot.on_kill_focus(None)
+
+ def _onDrawIdle(self, *args, **kwargs):
+ """
+ ReDraw with axes
+ """
+ try:
+ # check if it is time to redraw
+ if self.GetCapture() == None:
+ # Draw plot, changes resizing too
+ self.full_draw()
+ except:
+ pass
+
+ # restart idle
+ self._redraw_idle(*args, **kwargs)
+
+
+ def _redraw_idle(self, *args, **kwargs):
+ """
+ Restart Idle
+ """
+ # restart idle
+ self.idletimer.Restart(55, *args, **kwargs)
+
+
+class DefaultPanel(wx.Panel, PanelBase):
+ """
+ Defines the API for a panels to work with
+ the GUI manager
+ """
+ ## Internal nickname for the window, used by the AUI manager
+ window_name = "default"
+ ## Name to appear on the window title bar
+ window_caption = "Welcome panel"
+ ## Flag to tell the AUI manager to put this panel in the center pane
+ CENTER_PANE = True
+ def __init__(self, parent, *args, **kwds):
+ wx.Panel.__init__(self, parent, *args, **kwds)
+ PanelBase.__init__(self, parent)
+
+
+
+# Toy application to test this Frame
+class ViewApp(wx.App):
+ """
+ """
+ def OnInit(self):
+ """
+ """
+ pos, size = self.window_placement((GUIFRAME_WIDTH, GUIFRAME_HEIGHT))
+ self.frame = ViewerFrame(parent=None,
+ title=APPLICATION_NAME,
+ pos=pos,
+ gui_style = DEFAULT_STYLE,
+ size=size)
+ self.frame.Hide()
+ self.s_screen = None
+ temp_path = None
+ try:
+ # make sure the current dir is App dir when it starts
+ temp_path = os.path.dirname(sys.path[0])
+ os.chdir(temp_path)
+ except:
+ pass
+ try:
+ self.open_file()
+ except:
+ msg = "%s Could not load " % str(APPLICATION_NAME)
+ msg += "input file from command line.\n"
+ logging.error(msg)
+ # Display a splash screen on top of the frame.
+ if len(sys.argv) > 1 and '--time' in sys.argv[1:]:
+ log_time("Starting to display the splash screen")
+ try:
+ if os.path.isfile(SPLASH_SCREEN_PATH):
+ self.s_screen = self.display_splash_screen(parent=self.frame,
+ path=SPLASH_SCREEN_PATH)
+ else:
+ self.frame.Show()
+ except:
+ if self.s_screen is not None:
+ self.s_screen.Close()
+ msg = "Cannot display splash screen\n"
+ msg += str (sys.exc_value)
+ logging.error(msg)
+ self.frame.Show()
+
+ if hasattr(self.frame, 'special'):
+ self.frame.special.SetCurrent()
+ self.SetTopWindow(self.frame)
+
+ return True
+
+ def open_file(self):
+ """
+ open a state file at the start of the application
+ """
+ input_file = None
+ if len(sys.argv) >= 2:
+ cmd = sys.argv[0].lower()
+ basename = os.path.basename(cmd)
+ app_base = str(APPLICATION_NAME).lower()
+ if os.path.isfile(cmd) or basename.lower() == app_base:
+ app_py = app_base + '.py'
+ app_exe = app_base + '.exe'
+ app_app = app_base + '.app'
+ if basename.lower() in [app_py, app_exe, app_app, app_base]:
+ data_base = sys.argv[1]
+ input_file = os.path.normpath(os.path.join(DATAPATH,
+ data_base))
+ if input_file is None:
+ return
+ if self.frame is not None:
+ self.frame.set_input_file(input_file=input_file)
+
+
+ def set_manager(self, manager):
+ """
+ Sets a reference to the application manager
+ of the GUI manager (Frame)
+ """
+ self.frame.set_manager(manager)
+
+ def build_gui(self):
+ """
+ Build the GUI
+ """
+ #try to load file at the start
+ try:
+ self.open_file()
+ except:
+ raise
+ self.frame.build_gui()
+ #if self.s_screen is not None and self.s_screen.IsShown():
+ # self.s_screen.Close()
+
+ def set_welcome_panel(self, panel_class):
+ """
+ Set the welcome panel
+
+ :param panel_class: class of the welcome panel to be instantiated
+
+ """
+ self.frame.set_welcome_panel(panel_class)
+
+ def add_perspective(self, perspective):
+ """
+ Manually add a perspective to the application GUI
+ """
+ self.frame.add_perspective(perspective)
+
+ def window_placement(self, size):
+ """
+ Determines the position and size of the application frame such that it
+ fits on the user's screen without obstructing (or being obstructed by)
+ the Windows task bar. The maximum initial size in pixels is bounded by
+ WIDTH x HEIGHT. For most monitors, the application
+ will be centered on the screen; for very large monitors it will be
+ placed on the left side of the screen.
+ """
+ window_width, window_height = size
+ screen_size = wx.GetDisplaySize()
+ window_height = window_height if screen_size[1]>window_height else screen_size[1]-10
+ window_width = window_width if screen_size[0]> window_width else screen_size[0]-10
+ xpos = ypos = 0
+
+ # Note that when running Linux and using an Xming (X11) server on a PC
+ # with a dual monitor configuration, the reported display size may be
+ # that of both monitors combined with an incorrect display count of 1.
+ # To avoid displaying this app across both monitors, we check for
+ # screen 'too big'. If so, we assume a smaller width which means the
+ # application will be placed towards the left hand side of the screen.
+
+ _, _, x, y = wx.Display().GetClientArea() # size excludes task bar
+ if len(sys.argv) > 1 and '--platform' in sys.argv[1:]:
+ w, h = wx.DisplaySize() # size includes task bar area
+ # display on left side, not centered on screen
+ if x > 1920 and x > (2*y): x = x / 2
+ if x > window_width: xpos = (x - window_width)/2
+ if y > window_height: ypos = (y - window_height)/2
+
+ # Return the suggested position and size for the application frame.
+ return (xpos, ypos), (min(x, window_width), min(y, window_height))
+
+ def display_splash_screen(self, parent,
+ path=SPLASH_SCREEN_PATH):
+ """Displays the splash screen. It will exactly cover the main frame."""
+
+ # Prepare the picture. On a 2GHz intel cpu, this takes about a second.
+ x, y = parent.GetSizeTuple()
+ image = wx.Image(path, wx.BITMAP_TYPE_PNG)
+ image.Rescale(SPLASH_SCREEN_WIDTH,
+ SPLASH_SCREEN_HEIGHT, wx.IMAGE_QUALITY_HIGH)
+ bm = image.ConvertToBitmap()
+
+ # Create and show the splash screen. It will disappear only when the
+ # program has entered the event loop AND either the timeout has expired
+ # or the user has left clicked on the screen. Thus any processing
+ # performed in this routine (including sleeping) or processing in the
+ # calling routine (including doing imports) will prevent the splash
+ # screen from disappearing.
+ #
+ # Note that on Linux, the timeout appears to occur immediately in which
+ # case the splash screen disappears upon entering the event loop.
+ s_screen = wx.SplashScreen(bitmap=bm,
+ splashStyle=(wx.SPLASH_TIMEOUT|
+ wx.SPLASH_CENTRE_ON_SCREEN),
+ style=(wx.SIMPLE_BORDER|
+ wx.FRAME_NO_TASKBAR|
+ wx.STAY_ON_TOP),
+
+ milliseconds=SS_MAX_DISPLAY_TIME,
+ parent=parent,
+ id=wx.ID_ANY)
+ from gui_statusbar import SPageStatusbar
+ statusBar = SPageStatusbar(s_screen)
+ s_screen.SetStatusBar(statusBar)
+ s_screen.Bind(wx.EVT_CLOSE, self.on_close_splash_screen)
+ s_screen.Show()
+ return s_screen
+
+
+ def on_close_splash_screen(self, event):
+ """
+ """
+ self.frame.Show(True)
+ event.Skip()
+
+if __name__ == "__main__":
+ app = ViewApp(0)
+ app.MainLoop()
+
+
Index: test/test_rename_guiframe/gui_statusbar.py
===================================================================
--- test/test_rename_guiframe/gui_statusbar.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/gui_statusbar.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,337 @@
+import wx
+from wx import StatusBar as wxStatusB
+from wx.lib import newevent
+import time
+#numner of fields of the status bar
+NB_FIELDS = 4
+#position of the status bar's fields
+ICON_POSITION = 0
+MSG_POSITION = 1
+GAUGE_POSITION = 2
+CONSOLE_POSITION = 3
+BUTTON_SIZE = 40
+
+CONSOLE_WIDTH = 340
+CONSOLE_HEIGHT = 240
+
+class ConsolePanel(wx.Panel):
+ """
+ """
+ def __init__(self, parent, *args, **kwargs):
+ """
+ """
+ wx.Panel.__init__(self, parent=parent, *args, **kwargs)
+ self.parent = parent
+ self.sizer = wx.BoxSizer(wx.VERTICAL)
+ self.msg_txt = wx.TextCtrl(self, size=(CONSOLE_WIDTH-40,
+ CONSOLE_HEIGHT-60),
+ style=wx.TE_MULTILINE)
+ self.msg_txt.SetEditable(False)
+ self.msg_txt.SetValue('No message available')
+ self.sizer.Add(self.msg_txt, 1, wx.EXPAND|wx.ALL, 10)
+ self.SetSizer(self.sizer)
+
+ def set_message(self, status=""):
+ """
+ """
+ msg = status + "\n"
+ self.msg_txt.AppendText(str(msg))
+
+class Console(wx.Frame):
+ """
+ """
+ def __init__(self, parent=None, status="", *args, **kwds):
+ kwds["size"] = (CONSOLE_WIDTH, CONSOLE_HEIGHT)
+ kwds["title"] = "Console"
+ wx.Frame.__init__(self, parent=parent, *args, **kwds)
+ self.panel = ConsolePanel(self)
+ self.panel.set_message(status=status)
+ wx.EVT_CLOSE(self, self.Close)
+
+
+ def set_multiple_messages(self, messages=[]):
+ """
+ """
+ if messages:
+ for status in messages:
+ self.panel.set_message(status)
+
+ def set_message(self, message):
+ """
+ """
+ self.panel.set_message(str(message))
+
+ def Close(self, event):
+ """
+ """
+ self.Hide()
+
+class StatusBar(wxStatusB):
+ """
+ """
+ def __init__(self, parent, *args, **kargs):
+ wxStatusB.__init__(self, parent, *args, **kargs)
+ """
+ Implement statusbar functionalities
+ """
+ self.parent = parent
+ self.parent.SetStatusBarPane(MSG_POSITION)
+ #Layout of status bar
+ self.SetFieldsCount(NB_FIELDS)
+ self.SetStatusWidths([BUTTON_SIZE, -2, -1, BUTTON_SIZE])
+ #display default message
+ self.msg_position = MSG_POSITION
+ #save the position of the gauge
+ width, height = self.GetSize()
+ self.gauge = wx.Gauge(self, size=(width/10, height-3),
+ style=wx.GA_HORIZONTAL)
+ self.gauge.Hide()
+ #status bar icon
+ self.bitmap_bt_warning = wx.BitmapButton(self, -1,
+ size=(BUTTON_SIZE,-1),
+ style=wx.NO_BORDER)
+ console_bmp = wx.ArtProvider.GetBitmap(wx.ART_TIP, wx.ART_TOOLBAR)
+ self.bitmap_bt_console = wx.BitmapButton(self, -1,
+ size=(BUTTON_SIZE-5, height-4))
+ self.bitmap_bt_console.SetBitmapLabel(console_bmp)
+ console_hint = "History of status bar messages"
+ self.bitmap_bt_console.SetToolTipString(console_hint)
+ self.bitmap_bt_console.Bind(wx.EVT_BUTTON, self._onMonitor,
+ id=self.bitmap_bt_console.GetId())
+
+ self.reposition()
+ ## Current progress value of the bar
+ self.nb_start = 0
+ self.nb_progress = 0
+ self.nb_stop = 0
+ self.frame = None
+ self.list_msg = []
+ self.frame = Console(parent=self)
+ self.frame.set_multiple_messages(self.list_msg)
+ self.frame.Hide()
+ self.progress = 0
+ self.timer = wx.Timer(self, -1)
+ self.timer_stop = wx.Timer(self, -1)
+ self.thread = None
+ self.Bind(wx.EVT_TIMER, self._on_time, self.timer)
+ self.Bind(wx.EVT_TIMER, self._on_time_stop, self.timer_stop)
+ self.Bind(wx.EVT_SIZE, self.OnSize)
+ self.Bind(wx.EVT_IDLE, self.OnIdle)
+
+ def reposition(self):
+ """
+ """
+ rect = self.GetFieldRect(GAUGE_POSITION)
+ self.gauge.SetPosition((rect.x + 5, rect.y - 2))
+ rect = self.GetFieldRect(ICON_POSITION)
+ self.bitmap_bt_warning.SetPosition((rect.x + 5, rect.y - 2))
+ rect = self.GetFieldRect(CONSOLE_POSITION)
+ self.bitmap_bt_console.SetPosition((rect.x - 5, rect.y - 2))
+ self.sizeChanged = False
+
+ def OnIdle(self, event):
+ """
+ """
+ if self.sizeChanged:
+ self.reposition()
+
+ def OnSize(self, evt):
+ """
+ """
+ self.reposition()
+ self.sizeChanged = True
+
+ def get_msg_position(self):
+ """
+ """
+ return self.msg_position
+
+ def SetStatusText(self, text="", number=MSG_POSITION):
+ """
+ """
+ wxStatusB.SetStatusText(self, text, number)
+ self.list_msg.append(text)
+ icon_bmp = wx.ArtProvider.GetBitmap(wx.ART_INFORMATION, wx.ART_TOOLBAR)
+ self.bitmap_bt_warning.SetBitmapLabel(icon_bmp)
+
+ if self.frame is not None :
+ self.frame.set_message(text)
+
+ def PopStatusText(self, *args, **kwds):
+ """
+ Override status bar
+ """
+ wxStatusB.PopStatusText(self, field=MSG_POSITION)
+
+ def PushStatusText(self, *args, **kwds):
+ """
+ """
+ wxStatusB.PushStatusText(self, field=MSG_POSITION, string=string)
+
+ def enable_clear_gauge(self):
+ """
+ clear the progress bar
+ """
+ flag = False
+ if (self.nb_start <= self.nb_stop) or \
+ (self.nb_progress <= self.nb_stop):
+ flag = True
+ return flag
+
+ def _on_time_stop(self, evt):
+ """
+ Clear the progress bar
+
+ :param evt: wx.EVT_TIMER
+
+ """
+ count = 0
+ while(count <= 100):
+ count += 1
+ self.timer_stop.Stop()
+ self.clear_gauge(msg="")
+ self.nb_progress = 0
+ self.nb_start = 0
+ self.nb_stop = 0
+
+ def _on_time(self, evt):
+ """
+ Update the progress bar while the timer is running
+
+ :param evt: wx.EVT_TIMER
+
+ """
+ # Check stop flag that can be set from non main thread
+ if self.timer.IsRunning():
+ self.gauge.Pulse()
+
+ def clear_gauge(self, msg=""):
+ """
+ Hide the gauge
+ """
+ self.progress = 0
+ self.gauge.SetValue(0)
+ self.gauge.Hide()
+
+ def set_icon(self, event):
+ """
+ display icons related to the type of message sent to the statusbar
+ when available
+ """
+ if not hasattr(event, "info"):
+ return
+ msg = event.info.lower()
+ if msg == "warning":
+ icon_bmp = wx.ArtProvider.GetBitmap(wx.ART_WARNING, wx.ART_TOOLBAR)
+ self.bitmap_bt_warning.SetBitmapLabel(icon_bmp)
+ if msg == "error":
+ icon_bmp = wx.ArtProvider.GetBitmap(wx.ART_ERROR, wx.ART_TOOLBAR)
+ self.bitmap_bt_warning.SetBitmapLabel(icon_bmp)
+ if msg == "info":
+ icon_bmp = wx.ArtProvider.GetBitmap(wx.ART_INFORMATION,
+ wx.ART_TOOLBAR)
+ self.bitmap_bt_warning.SetBitmapLabel(icon_bmp)
+
+ def set_message(self, event):
+ """
+ display received message on the statusbar
+ """
+ if hasattr(event, "status"):
+ self.SetStatusText(str(event.status))
+
+
+ def set_gauge(self, event):
+ """
+ change the state of the gauge according the state of the current job
+ """
+ if not hasattr(event, "type"):
+ return
+ type = event.type
+ self.gauge.Show(True)
+ if type.lower() == "start":
+ self.nb_start += 1
+ #self.timer.Stop()
+ self.progress += 10
+ self.gauge.SetValue(int(self.progress))
+ self.progress += 10
+ if self.progress < self.gauge.GetRange() - 20:
+ self.gauge.SetValue(int(self.progress))
+ if type.lower() == "progress":
+ self.nb_progress += 1
+ self.timer.Start(1)
+ self.gauge.Pulse()
+ if type.lower() == "update":
+ self.progress += 10
+ if self.progress < self.gauge.GetRange()- 20:
+ self.gauge.SetValue(int(self.progress))
+ if type.lower() == "stop":
+ self.nb_stop += 1
+ self.gauge.Show(True)
+ if self.enable_clear_gauge():
+ self.timer.Stop()
+ self.progress = 0
+ self.gauge.SetValue(90)
+ self.timer_stop.Start(3)
+
+ def set_status(self, event):
+ """
+ Update the status bar .
+
+ :param type: type of message send.
+ type must be in ["start","progress","update","stop"]
+ :param msg: the message itself as string
+ :param thread: if updatting using a thread status
+
+ """
+ self.set_message(event=event)
+ self.set_icon(event=event)
+ self.set_gauge(event=event)
+
+ def _onMonitor(self, event):
+ """
+ Pop up a frame with messages sent to the status bar
+ """
+ self.frame.Show(True)
+
+
+class SPageStatusbar(wxStatusB):
+ def __init__(self, parent, timeout=None, *args, **kwds):
+ wxStatusB.__init__(self, parent, *args, **kwds)
+ self.SetFieldsCount(1)
+ self.timeout = timeout
+ self.gauge = wx.Gauge(self,style=wx.GA_HORIZONTAL, size=parent.GetSize())
+ rect = self.GetFieldRect(0)
+ self.gauge.SetPosition((rect.x , rect.y ))
+ if self.timeout is not None:
+ self.gauge.SetRange(int(self.timeout))
+ self.timer = wx.Timer(self, -1)
+ self.Bind(wx.EVT_TIMER, self._on_time, self.timer)
+ self.timer.Start(1)
+ self.pos = 0
+
+ def _on_time(self, evt):
+ """
+ Update the progress bar while the timer is running
+
+ :param evt: wx.EVT_TIMER
+
+ """
+ # Check stop flag that can be set from non main thread
+ if self.timeout is None and self.timer.IsRunning():
+ self.gauge.Pulse()
+
+
+if __name__ == "__main__":
+ app = wx.PySimpleApp()
+ frame = wx.Frame(None, wx.ID_ANY, 'test frame')
+ #statusBar = StatusBar(frame, wx.ID_ANY)
+ statusBar = SPageStatusbar(frame)
+ frame.SetStatusBar(statusBar)
+ frame.Show(True)
+ #event = MessageEvent()
+ #event.type = "progress"
+ #event.status = "statusbar...."
+ #event.info = "error"
+ #statusBar.set_status(event=event)
+ app.MainLoop()
+
Index: test/test_rename_guiframe/gui_style.py
===================================================================
--- test/test_rename_guiframe/gui_style.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/gui_style.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,85 @@
+
+"""
+Provide the style for guiframe
+"""
+import wx
+import os
+from sans.guiframe import get_data_path
+
+
+class GUIFRAME:
+ MANAGER_ON = 1
+ FLOATING_PANEL = 2
+ FIXED_PANEL = 4
+ PLOTTING_ON = 8
+ DATALOADER_ON = 16
+ TOOLBAR_ON = 32
+ CALCULATOR_ON = 256
+ SINGLE_APPLICATION = 64
+ WELCOME_PANEL_ON = 128
+ DEFAULT_STYLE = SINGLE_APPLICATION|DATALOADER_ON|PLOTTING_ON|FIXED_PANEL
+ MULTIPLE_APPLICATIONS = DEFAULT_STYLE
+
+class GUIFRAME_ID:
+ UNDO_ID = wx.NewId()
+ REDO_ID = wx.NewId()
+ COPY_ID = wx.NewId()
+ PASTE_ID = wx.NewId()
+ BOOKMARK_ID = wx.NewId()
+ SAVE_ID = wx.NewId()
+ ZOOM_IN_ID = wx.NewId()
+ ZOOM_OUT_ID = wx.NewId()
+ ZOOM_ID = wx.NewId()
+ DRAG_ID = wx.NewId()
+ RESET_ID = wx.NewId()
+ PREVIEW_ID = wx.NewId()
+ PRINT_ID = wx.NewId()
+ CURRENT_APPLICATION = wx.NewId()
+ CURVE_SYMBOL_NUM = 13
+
+class GUIFRAME_ICON:
+ PATH = get_data_path(media='images')
+ SAVE_ICON_PATH = os.path.join(PATH, 'save.png')
+ UNDO_ICON_PATH = os.path.join(PATH, 'undo.png')
+ REDO_ICON_PATH = os.path.join(PATH, 'redo.png')
+ COPY_ICON_PATH = os.path.join(PATH, 'copy.png')
+ PASTE_ICON_PATH = os.path.join(PATH, 'paste.png')
+ BOOKMARK_ICON_PATH = os.path.join(PATH, 'bookmark.png')
+ ZOOM_IN_ID_PATH = os.path.join(PATH, 'zoom_in.png')
+ ZOOM_OUT_ID_PATH = os.path.join(PATH, 'zoom_out.png')
+ ZOOM_ID_PATH = os.path.join(PATH, 'search_pan.png')
+ DRAG_ID_PATH = os.path.join(PATH, 'drag_hand.png')
+ RESET_ID_PATH = os.path.join(PATH, 'reset.png')
+ PREVIEW_ID_PATH = os.path.join(PATH, 'report.png')
+ PRINT_ID_PATH = os.path.join(PATH, 'printer.png')
+
+ SAVE_ICON = wx.Image(os.path.join(PATH, 'save.png'))
+ UNDO_ICON = wx.Image(os.path.join(PATH, 'undo.png'))
+ REDO_ICON = wx.Image(os.path.join(PATH, 'redo.png'))
+ COPY_ICON = wx.Image(os.path.join(PATH, 'copy.png'))
+ PASTE_ICON = wx.Image(os.path.join(PATH, 'paste.png'))
+ BOOKMARK_ICON = wx.Image(os.path.join(PATH, 'bookmark.png'))
+ ZOOM_IN_ICON = wx.Image(os.path.join(PATH, 'zoom_in.png'))
+ ZOOM_OUT_ICON = wx.Image(os.path.join(PATH, 'zoom_out.png'))
+ ZOOM_ICON = wx.Image(os.path.join(PATH, 'search_pan.png'))
+ DRAG_ICON = wx.Image(os.path.join(PATH, 'drag_hand.png'))
+ RESET_ICON = wx.Image(os.path.join(PATH, 'reset.png'))
+ REPORT_ICON = wx.Image(os.path.join(PATH, 'report.png'))
+ PREVIEW_ICON = wx.Image(os.path.join(PATH, 'preview.png'))
+ PRINT_ICON = wx.Image(os.path.join(PATH, 'printer.png'))
+
+if __name__ == "__main__":
+
+ print GUIFRAME.DEFAULT_STYLE
+ print GUIFRAME.FLOATING_PANEL
+ print GUIFRAME.SINGLE_APPLICATION
+ style = GUIFRAME.MULTIPLE_APPLICATIONS
+ style &= GUIFRAME.PLOTTING_ON
+ print style == GUIFRAME.PLOTTING_ON
+ style1 = GUIFRAME.MULTIPLE_APPLICATIONS
+ style1 &= (~GUIFRAME.MANAGER_ON)
+ print style1 == GUIFRAME.DEFAULT_STYLE
+ print style1
+
+
+
Index: test/test_rename_guiframe/gui_toolbar.py
===================================================================
--- test/test_rename_guiframe/gui_toolbar.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/gui_toolbar.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,305 @@
+
+import wx
+import os
+from wx import ToolBar as Tbar
+from wx.lib.platebtn import PlateButton
+from sans.guiframe.gui_style import GUIFRAME_ID
+from sans.guiframe.gui_style import GUIFRAME_ICON
+from wx.lib.platebtn import PB_STYLE_SQUARE, PB_STYLE_DROPARROW
+#Control panel width
+import sys
+if sys.platform.count("darwin")==0:
+ FONT_VARIANT = 0
+ NAME_BOX = wx.DefaultSize
+ TB_H = 21
+ IS_MAC = False
+else:
+ FONT_VARIANT = 1
+ NAME_BOX = (200, 25)
+ TB_H = 25
+ IS_MAC = True
+
+def clear_image(image):
+ w, h = image.GetSize()
+ factor = 155
+ compress = lambda x: int(x * factor/255.) + factor
+ for y in range(h):
+ for x in range(w):
+ grey = compress(image.GetGreen(x, y))
+ image.SetRGB(x, y, grey, grey, grey)
+ if image.HasAlpha():
+ image.ConvertAlphaToMask()
+ return image
+
+class GUIToolBar(Tbar):
+ """
+ Implement toolbar for guiframe
+ """
+ def __init__(self, parent, *args, **kwds):
+ Tbar.__init__(self, parent, *args, **kwds)
+ #Set window's font size
+ self.SetWindowVariant(variant=FONT_VARIANT)
+ self.parent = parent
+ self._bookmark_menu = None
+ self._bookmark_bt = None
+ self.do_layout()
+ self.on_bind_button()
+
+ def do_layout(self):
+ """
+ """
+ t_size = TB_H
+ tbar_size = (t_size, t_size)
+ button_type = wx.ITEM_NORMAL
+
+ reset_im = GUIFRAME_ICON.RESET_ICON
+ reset_im.Rescale(tbar_size[0], tbar_size[1], wx.IMAGE_QUALITY_HIGH)
+ reset_bmp = reset_im.ConvertToBitmap()
+ #disable_reset_bmp = clear_image(reset_im).ConvertToBitmap()
+ disable_reset_bmp = wx.NullBitmap
+ self.AddLabelTool(GUIFRAME_ID.RESET_ID, 'Reset', reset_bmp,
+ disable_reset_bmp, button_type,'Reset')
+ self.AddSeparator()
+ save_im = GUIFRAME_ICON.SAVE_ICON
+ save_im.Rescale(tbar_size[0], tbar_size[1], wx.IMAGE_QUALITY_HIGH)
+ save_bmp = save_im.ConvertToBitmap()
+ disable_save_bmp = wx.NullBitmap
+ self.AddLabelTool(GUIFRAME_ID.SAVE_ID, 'Save', save_bmp,
+ disable_save_bmp, button_type,'Save')
+ self.AddSeparator()
+ report_im = GUIFRAME_ICON.REPORT_ICON
+ report_im.Rescale(tbar_size[0], tbar_size[1], wx.IMAGE_QUALITY_HIGH)
+ report_bmp = report_im.ConvertToBitmap()
+ #disable_report_bmp = clear_image(report_im).ConvertToBitmap()
+ disable_report_bmp = wx.NullBitmap
+ self.AddLabelTool(GUIFRAME_ID.PREVIEW_ID, 'Report', report_bmp,
+ disable_report_bmp, button_type,'Report')
+ self.AddSeparator()
+ #print_im = GUIFRAME_ICON.PRINT_ICON
+ #print_im.Rescale(tbar_size[0], tbar_size[1], wx.IMAGE_QUALITY_HIGH)
+ #print_bmp = print_im.ConvertToBitmap()
+
+ #disable_print_bmp = wx.NullBitmap
+ #self.AddLabelTool(GUIFRAME_ID.PRINT_ID, 'Print', print_bmp,
+ # disable_print_bmp, button_type, 'Print')
+ #self.AddSeparator()
+ undo_im = GUIFRAME_ICON.UNDO_ICON
+ undo_im.Rescale(tbar_size[0], tbar_size[1], wx.IMAGE_QUALITY_HIGH)
+ undo_bmp = undo_im.ConvertToBitmap()
+ #disable_undo_bmp = clear_image(undo_im).ConvertToBitmap()
+ disable_undo_bmp = wx.NullBitmap
+ self.AddLabelTool(GUIFRAME_ID.UNDO_ID, 'Undo', undo_bmp,
+ disable_undo_bmp, button_type,'Undo')
+ self.AddSeparator()
+ redo_im = GUIFRAME_ICON.REDO_ICON
+ redo_im.Rescale(tbar_size[0], tbar_size[1], wx.IMAGE_QUALITY_HIGH)
+ redo_bmp = redo_im.ConvertToBitmap()
+ #disable_redo_bmp = clear_image(redo_im).ConvertToBitmap()
+ disable_redo_bmp = wx.NullBitmap
+ self.AddLabelTool(GUIFRAME_ID.REDO_ID, 'Redo', redo_bmp,
+ disable_redo_bmp, button_type,'Redo')
+ self.AddSeparator()
+ copy_im = GUIFRAME_ICON.COPY_ICON
+ copy_im.Rescale(tbar_size[0], tbar_size[1], wx.IMAGE_QUALITY_HIGH)
+ copy_bmp = copy_im.ConvertToBitmap()
+ #disable_undo_bmp = clear_image(undo_im).ConvertToBitmap()
+ disable_copy_bmp = wx.NullBitmap
+ self.AddLabelTool(GUIFRAME_ID.COPY_ID, 'Copy', copy_bmp,
+ disable_copy_bmp, button_type,'Copy parameter values')
+ self.AddSeparator()
+ paste_im = GUIFRAME_ICON.PASTE_ICON
+ paste_im.Rescale(tbar_size[0], tbar_size[1], wx.IMAGE_QUALITY_HIGH)
+ paste_bmp = paste_im.ConvertToBitmap()
+ #disable_redo_bmp = clear_image(redo_im).ConvertToBitmap()
+ disable_paste_bmp = wx.NullBitmap
+ self.AddLabelTool(GUIFRAME_ID.PASTE_ID, 'Paste', paste_bmp,
+ disable_paste_bmp, button_type,'Paste parameter values')
+
+ self.AddSeparator()
+ #add button for the current application
+ #self.button_application = wx.StaticText(self, -1, 'Welcome')
+ #self.button_application.SetForegroundColour('black')
+ #self.button_application.SetBackgroundColour('#1874CD')
+ #hint = 'Active Application'
+ #self.button_application.SetToolTipString(hint)
+ #self.AddControl(self.button_application)
+ #self.AddSeparator()
+
+ self._bookmark_bt = PlateButton(self, -1, 'bookmark',
+ GUIFRAME_ICON.BOOKMARK_ICON.ConvertToBitmap(),
+ style=PB_STYLE_SQUARE|PB_STYLE_DROPARROW)
+ self._bookmark_bt.Disable()
+ self._bookmark_menu = wx.Menu()
+ self.add_bookmark_default()
+
+
+ self._bookmark_bt.SetMenu(self._bookmark_menu)
+ self.AddControl(self._bookmark_bt)
+
+ self.SetToolBitmapSize(tbar_size)
+ self.AddSeparator()
+ #add button for the panel on focus
+ self.button_panel = wx.StaticText(self, -1, 'No Panel',
+ pos=wx.DefaultPosition,
+ size=NAME_BOX,
+ style=wx.SUNKEN_BORDER|wx.ALIGN_LEFT)
+ #self.button_panel.SetForegroundColour('black')
+ #self.button_panel.SetBackgroundColour('white')
+ button_panel_font = self.button_panel.GetFont()
+ button_panel_font.SetWeight(wx.BOLD)
+ self.button_panel.SetFont(button_panel_font)
+ #self.button_panel.SetClientSize((80,20))
+ hint = 'Control Panel on Focus'
+ self.button_panel.SetToolTipString(hint)
+ self.AddControl(self.button_panel)
+ self.AddSeparator()
+ self.Realize()
+
+ def add_bookmark_default(self):
+ """
+ Add default items in bookmark menu
+ """
+ id = wx.NewId()
+ self._bookmark_menu.Append(id, 'Add bookmark')
+ self._bookmark_menu.AppendSeparator()
+ wx.EVT_MENU(self, id, self.on_bookmark)
+
+ def on_bind_button(self):
+ """
+ """
+ if self.parent is not None:
+
+ self.parent.Bind(wx.EVT_TOOL, self.parent.on_redo_panel,
+ id=GUIFRAME_ID.REDO_ID)
+ self.parent.Bind(wx.EVT_TOOL, self.parent.on_undo_panel,
+ id=GUIFRAME_ID.UNDO_ID)
+ self.parent.Bind(wx.EVT_TOOL, self.parent.on_copy_panel,
+ id=GUIFRAME_ID.COPY_ID)
+ self.parent.Bind(wx.EVT_TOOL, self.parent.on_paste_panel,
+ id=GUIFRAME_ID.PASTE_ID)
+ self.parent.Bind(wx.EVT_TOOL, self.parent.on_reset_panel,
+ id=GUIFRAME_ID.RESET_ID)
+ self.parent.Bind(wx.EVT_TOOL, self.parent.on_save_panel,
+ id=GUIFRAME_ID.SAVE_ID)
+ self.parent.Bind(wx.EVT_TOOL, self.parent.on_preview_panel,
+ id=GUIFRAME_ID.PREVIEW_ID)
+ #self.parent.Bind(wx.EVT_TOOL, self.parent.on_print_panel,
+ # id=GUIFRAME_ID.PRINT_ID)
+
+ def update_button(self, application_name='', panel_name=''):
+ """
+ """
+ #self.button_application.SetLabel(str(application_name))
+ self.button_panel.SetLabel(str(panel_name))
+ self.button_panel.SetToolTipString(str(panel_name))
+
+ def update_toolbar(self, panel=None):
+ """
+ """
+ if panel is None:
+ #self.EnableTool(GUIFRAME_ID.PRINT_ID, False)
+ self.EnableTool(GUIFRAME_ID.UNDO_ID,False)
+ self.EnableTool(GUIFRAME_ID.REDO_ID, False)
+ self.EnableTool(GUIFRAME_ID.COPY_ID,False)
+ self.EnableTool(GUIFRAME_ID.PASTE_ID, False)
+ self.EnableTool(GUIFRAME_ID.PREVIEW_ID, False)
+ self.EnableTool(GUIFRAME_ID.RESET_ID, False)
+ self.EnableTool(GUIFRAME_ID.SAVE_ID, False)
+ self._bookmark_bt.Disable()
+
+ else:
+ #self.EnableTool(GUIFRAME_ID.PRINT_ID, panel.get_print_flag())
+ self.EnableTool(GUIFRAME_ID.UNDO_ID, panel.get_undo_flag())
+ self.EnableTool(GUIFRAME_ID.REDO_ID, panel.get_redo_flag())
+ self.EnableTool(GUIFRAME_ID.COPY_ID, panel.get_copy_flag())
+ self.EnableTool(GUIFRAME_ID.PASTE_ID, panel.get_paste_flag())
+ self.EnableTool(GUIFRAME_ID.PREVIEW_ID, panel.get_preview_flag())
+ self.EnableTool(GUIFRAME_ID.RESET_ID, panel.get_reset_flag())
+ self.EnableTool(GUIFRAME_ID.SAVE_ID, panel.get_save_flag())
+ self._bookmark_bt.Enable(panel.get_bookmark_flag())
+ self.Realize()
+
+ def enable_undo(self, panel):
+ self.EnableTool(GUIFRAME_ID.UNDO_ID, panel.get_undo_flag())
+ self.Realize()
+
+ def enable_redo(self, panel):
+ self.EnableTool(GUIFRAME_ID.REDO_ID, panel.get_redo_flag())
+ self.Realize()
+
+ def enable_copy(self, panel):
+ self.EnableTool(GUIFRAME_ID.COPY_ID, panel.get_copy_flag())
+ self.Realize()
+
+ def enable_paste(self, panel):
+ self.EnableTool(GUIFRAME_ID.PASTE_ID, panel.get_paste_flag())
+ self.Realize()
+
+ def enable_print(self, panel):
+ self.EnableTool(GUIFRAME_ID.PRINT_ID, panel.get_print_flag())
+ self.Realize()
+
+ def enable_zoom(self, panel):
+ self.EnableTool(GUIFRAME_ID.ZOOM_ID, panel.get_zoom_flag())
+ self.Realize()
+
+ def enable_zoom_in(self, panel):
+ self.EnableTool(GUIFRAME_ID.ZOOM_IN_ID, panel.get_zoom_in_flag())
+ self.Realize()
+
+ def enable_zoom_out(self, panel):
+ self.EnableTool(GUIFRAME_ID.ZOOM_OUT_ID, panel.get_zoom_out_flag())
+ self.Realize()
+
+ def enable_bookmark(self, panel):
+ flag = panel.get_bookmark_flag()
+ self._bookmark_bt.Enable(flag)
+ self.Realize()
+
+ def enable_save(self, panel):
+ self.EnableTool(GUIFRAME_ID.SAVE_ID, panel.get_save_flag())
+ self.Realize()
+
+ def enable_reset(self, panel):
+ self.EnableTool(GUIFRAME_ID.RESET_ID, panel.get_reset_flag())
+ self.Realize()
+
+ def enable_preview(self, panel):
+ self.EnableTool(GUIFRAME_ID.PREVIEW_ID, panel.get_preview_flag())
+ self.Realize()
+
+ def on_bookmark(self, event):
+ """
+ add book mark
+ """
+ if self.parent is not None:
+ self.parent.on_bookmark_panel(event)
+
+ def append_bookmark(self, event):
+ """
+ receive item to append on the toolbar button bookmark
+ """
+ title = event.title
+ hint = event.hint
+ handler = event.handler
+ id = wx.NewId()
+ self._bookmark_menu.Append(id, str(title), str(hint))
+ wx.EVT_MENU(self, id, handler)
+
+ def remove_bookmark_item(self, item):
+ """
+ Remove a bookmark item
+ """
+ self._bookmark_menu.DestroyItem(item)
+
+ def get_bookmark_items(self):
+ """
+ Get bookmark menu items
+ """
+ return self._bookmark_menu.GetMenuItems()
+
+ def append_bookmark_item(self, id, label):
+ """
+ Append a item in bookmark
+ """
+ self._bookmark_menu.Append(id, label)
Index: test/test_rename_guiframe/license.txt
===================================================================
--- test/test_rename_guiframe/license.txt (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/license.txt (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,15 @@
+This software was developed by the University of Tennessee as part of the
+Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
+project funded by the US National Science Foundation.
+
+If you use this program to do productive scientific research that leads
+to publication, we ask that you acknowledge use of the program by citing
+the following paper in your publication:
+
+P. Butler, M. Doucet, G. Alina, R. Cortes Hernandez, J. Zhou, P. Kienzle,Jae Hie Cho
+"SANS analysis software", to be published.
+
+See the DANSE project web site for license information:
+http://wiki.cacr.caltech.edu/danse/index.php/Main_Page
+
+copyright 2008, University of Tennessee for the DANSE project
Index: test/test_rename_guiframe/local_perspectives/data_loader/__init__.py
===================================================================
--- test/test_rename_guiframe/local_perspectives/data_loader/__init__.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/local_perspectives/data_loader/__init__.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,2 @@
+PLUGIN_ID = "DataLoader plug-in 1.0"
+from data_loader import *
Index: test/test_rename_guiframe/local_perspectives/data_loader/data_loader.py
===================================================================
--- test/test_rename_guiframe/local_perspectives/data_loader/data_loader.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/local_perspectives/data_loader/data_loader.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,224 @@
+
+"""
+plugin DataLoader responsible of loading data
+"""
+import os
+import sys
+import wx
+import logging
+
+from DataLoader.loader import Loader
+import DataLoader.data_info as DataInfo
+from sans.guiframe.plugin_base import PluginBase
+from sans.guiframe.events import StatusEvent
+from sans.guiframe.events import NewPlotEvent
+from sans.guiframe.dataFitting import Data1D
+from sans.guiframe.dataFitting import Data2D
+from sans.guiframe.utils import parse_name
+from sans.guiframe.gui_style import GUIFRAME
+try:
+ # Try to find a local config
+ import imp
+ path = os.getcwd()
+ if(os.path.isfile("%s/%s.py" % (path, 'local_config'))) or \
+ (os.path.isfile("%s/%s.pyc" % (path, 'local_config'))):
+ fObj, path, descr = imp.find_module('local_config', [path])
+ config = imp.load_module('local_config', fObj, path, descr)
+ else:
+ # Try simply importing local_config
+ import local_config as config
+except:
+ # Didn't find local config, load the default
+ import config
+
+extension_list = []
+if config.APPLICATION_STATE_EXTENSION is not None:
+ extension_list.append(config.APPLICATION_STATE_EXTENSION)
+EXTENSIONS = config.PLUGIN_STATE_EXTENSIONS + extension_list
+PLUGINS_WLIST = config.PLUGINS_WLIST
+APPLICATION_WLIST = config.APPLICATION_WLIST
+
+
+class Plugin(PluginBase):
+
+ def __init__(self, standalone=False):
+ PluginBase.__init__(self, name="DataLoader", standalone=standalone)
+ #Default location
+ self._default_save_location = None
+ self.loader = Loader()
+ self._data_menu = None
+
+ def help(self, evt):
+ """
+ Show a general help dialog.
+ """
+ from help_panel import HelpWindow
+ frame = HelpWindow(None, -1, 'HelpWindow')
+ frame.Show(True)
+
+ def populate_file_menu(self):
+ """
+ get a menu item and append it under file menu of the application
+ add load file menu item and load folder item
+ """
+ #menu for data files
+ menu_list = []
+ data_file_hint = "load one or more data in the application"
+ menu_list = [('&Load Data File(s)', data_file_hint, self.load_data)]
+ gui_style = self.parent.get_style()
+ style = gui_style & GUIFRAME.MULTIPLE_APPLICATIONS
+ style1 = gui_style & GUIFRAME.DATALOADER_ON
+ if style == GUIFRAME.MULTIPLE_APPLICATIONS:
+ #menu for data from folder
+ data_folder_hint = "load multiple data in the application"
+ menu_list.append(('&Load Data Folder', data_folder_hint,
+ self._load_folder))
+ return menu_list
+
+
+ def load_data(self, event):
+ """
+ Load data
+ """
+ path = None
+ if self._default_save_location == None:
+ self._default_save_location = os.getcwd()
+
+ cards = self.loader.get_wildcards()
+ temp = [APPLICATION_WLIST] + PLUGINS_WLIST
+ for item in temp:
+ if item in cards:
+ cards.remove(item)
+ wlist = '|'.join(cards)
+ style = wx.OPEN|wx.FD_MULTIPLE
+ dlg = wx.FileDialog(self.parent,
+ "Choose a file",
+ self._default_save_location, "",
+ wlist,
+ style=style)
+ if dlg.ShowModal() == wx.ID_OK:
+ file_list = dlg.GetPaths()
+ if len(file_list) >= 0 and not(file_list[0]is None):
+ self._default_save_location = os.path.dirname(file_list[0])
+ path = self._default_save_location
+ dlg.Destroy()
+
+ if path is None or not file_list or file_list[0] is None:
+ return
+ self.get_data(file_list)
+
+
+ def can_load_data(self):
+ """
+ if return True, then call handler to laod data
+ """
+ return True
+
+
+ def _load_folder(self, event):
+ """
+ Load entire folder
+ """
+ path = None
+ if self._default_save_location == None:
+ self._default_save_location = os.getcwd()
+ dlg = wx.DirDialog(self.parent, "Choose a directory",
+ self._default_save_location,
+ style=wx.DD_DEFAULT_STYLE)
+ if dlg.ShowModal() == wx.ID_OK:
+ path = dlg.GetPath()
+ self._default_save_location = path
+ dlg.Destroy()
+ if path is not None:
+ self._default_save_location = os.path.dirname(path)
+ else:
+ return
+ file_list = self.get_file_path(path)
+ self.get_data(file_list)
+
+ def load_error(self, error=None):
+ """
+ Pop up an error message.
+
+ :param error: details error message to be displayed
+ """
+ if error is not None or str(error).strip() != "":
+ dial = wx.MessageDialog(self.parent, str(error), 'Error Loading File',
+ wx.OK | wx.ICON_EXCLAMATION)
+ dial.ShowModal()
+
+ def get_file_path(self, path):
+ """
+ Receive a list containing folder then return a list of file
+ """
+ if os.path.isdir(path):
+ return [os.path.join(os.path.abspath(path),
+ file) for file in os.listdir(path)]
+
+ def get_data(self, path, format=None):
+ """
+ """
+ message = ""
+ log_msg = ''
+ output = {}
+ error_message = ""
+ for p_file in path:
+ basename = os.path.basename(p_file)
+ root, extension = os.path.splitext(basename)
+ if extension.lower() in EXTENSIONS:
+ log_msg = "Data Loader cannot "
+ log_msg += "load: %s\n" % str(p_file)
+ log_msg += """Please try to open that file from "open project" """
+ log_msg += """or "open analysis" menu\n"""
+ error_message = log_msg + "\n"
+ logging.info(log_msg)
+ continue
+
+ try:
+ temp = self.loader.load(p_file, format)
+ if temp.__class__.__name__ == "list":
+ for item in temp:
+ data = self.parent.create_gui_data(item, p_file)
+ output[data.id] = data
+ else:
+ data = self.parent.create_gui_data(temp, p_file)
+ output[data.id] = data
+ message = "Loading Data..." + str(p_file) + "\n"
+ self.load_update(output=output, message=message)
+ except:
+ error = "Error while loading Data: %s\n" % str(p_file)
+ error += str(sys.exc_value) + "\n"
+ error_message = "The data file you selected could not be loaded.\n"
+ error_message += "Make sure the content of your file"
+ error_message += " is properly formatted.\n\n"
+ error_message += "When contacting the DANSE team, mention the"
+ error_message += " following:\n%s" % str(error)
+ self.load_update(output=output, message=error_message)
+
+ message = "Loading Data Complete! "
+ message += log_msg
+ self.load_complete(output=output, error_message=error_message,
+ message=message, path=path)
+
+ def load_update(self, output=None, message=""):
+ """
+ print update on the status bar
+ """
+ if message != "":
+ wx.PostEvent(self.parent, StatusEvent(status=message,
+ type="progress",
+ info="warning"))
+ def load_complete(self, output, message="", error_message="", path=None):
+ """
+ post message to status bar and return list of data
+ """
+ wx.PostEvent(self.parent, StatusEvent(status=message,
+ info="warning",
+ type="stop"))
+ if error_message != "":
+ self.load_error(error_message)
+ self.parent.add_data(data_list=output)
+
+
+
+
Index: test/test_rename_guiframe/local_perspectives/data_loader/help_panel.py
===================================================================
--- test/test_rename_guiframe/local_perspectives/data_loader/help_panel.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/local_perspectives/data_loader/help_panel.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,105 @@
+#!/usr/bin/python
+"""
+Help panel for data_loader plugins
+"""
+import os
+import wx
+import wx.html as html
+from wx.lib.splitter import MultiSplitterWindow
+from sans.guiframe import get_media_path
+
+class HelpWindow(wx.Frame):
+ """
+ """
+ def __init__(self, parent, title='Plotting Help', pageToOpen=None):
+ wx.Frame.__init__(self, parent, title, size=(700, 450))
+ """
+ contains help info
+ """
+ splitter = MultiSplitterWindow(self, style=wx.SP_LIVE_UPDATE)
+ rpanel = wx.Panel(splitter, -1)
+ lpanel = wx.Panel(splitter, -1, style=wx.BORDER_SUNKEN)
+
+ vbox = wx.BoxSizer(wx.VERTICAL)
+ header = wx.Panel(rpanel, -1)
+ header.SetBackgroundColour('#6666FF')
+ header.SetForegroundColour('WHITE')
+ hbox = wx.BoxSizer(wx.HORIZONTAL)
+ st = wx.StaticText(header, -1, 'Contents', (5, 5))
+ font = st.GetFont()
+ font.SetPointSize(10)
+ st.SetFont(font)
+ hbox.Add(st, 1, wx.TOP | wx.BOTTOM | wx.LEFT, 5)
+ header.SetSizer(hbox)
+ vbox.Add(header, 0, wx.EXPAND)
+
+ vboxl = wx.BoxSizer(wx.VERTICAL)
+ headerl = wx.Panel(lpanel, -1, size=(-1, 20))
+
+ headerl.SetBackgroundColour('#6666FF')
+ headerl.SetForegroundColour('WHITE')
+ hboxl = wx.BoxSizer(wx.HORIZONTAL)
+ lst = wx.StaticText(headerl, -1, 'Menu', (5, 5))
+ fontl = lst.GetFont()
+ fontl.SetPointSize(10)
+ lst.SetFont(fontl)
+ hboxl.Add(lst, 1, wx.TOP | wx.BOTTOM | wx.LEFT, 5)
+ headerl.SetSizer(hboxl)
+ vboxl.Add(headerl, 0, wx.EXPAND)
+ self.lhelp = html.HtmlWindow(lpanel, -1, style=wx.NO_BORDER)
+ self.rhelp = html.HtmlWindow(rpanel, -1, style=wx.NO_BORDER,
+ size=(500,-1))
+
+ self.path = get_media_path(media='media')
+ page1 = """
+
+ Select topic on Menu
+
+ """
+ self.rhelp.SetPage(page1)
+ page = """
+
+
+
+ """
+
+ self.lhelp.SetPage(page)
+ self.lhelp.Bind(wx.html.EVT_HTML_LINK_CLICKED, self.OnLinkClicked)
+
+ vbox.Add(self.rhelp, 1, wx.EXPAND)
+ vboxl.Add(self.lhelp, 1, wx.EXPAND)
+ rpanel.SetSizer(vbox)
+ lpanel.SetSizer(vboxl)
+ lpanel.SetFocus()
+
+ vbox1 = wx.BoxSizer(wx.HORIZONTAL)
+ vbox1.Add(splitter, 1, wx.EXPAND)
+ splitter.AppendWindow(lpanel, 200)
+ splitter.AppendWindow(rpanel)
+ self.SetSizer(vbox1)
+
+ self.Centre()
+ self.Show(True)
+
+ def OnLinkClicked(self, event):
+ """
+ Function to diplay html page related to the hyperlinktext selected
+ """
+ link = event.GetLinkInfo().GetHref()
+ link = os.path.join(self.path, link)
+ self.rhelp.LoadPage(link)
+
+
+class ViewApp(wx.App):
+ def OnInit(self):
+ frame = HelpWindow(None, -1, 'HelpWindow')
+ frame.Show(True)
+ self.SetTopWindow(frame)
+ return True
+
+if __name__ == "__main__":
+ app = ViewApp(0)
+ app.MainLoop()
Index: test/test_rename_guiframe/local_perspectives/data_loader/load_thread.py
===================================================================
--- test/test_rename_guiframe/local_perspectives/data_loader/load_thread.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/local_perspectives/data_loader/load_thread.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,85 @@
+
+import time
+import sys
+import os
+
+from data_util.calcthread import CalcThread
+
+
+EXTENSIONS = ['.svs', '.prv', '.inv', '.fitv']
+
+class DataReader(CalcThread):
+ """
+ Load a data given a filename
+ """
+ def __init__(self, path, loader,
+ flag=True,
+ transform_data=None,
+ completefn=None,
+ updatefn = None,
+ yieldtime = 0.01,
+ worktime = 0.01
+ ):
+ CalcThread.__init__(self, completefn,
+ updatefn,
+ yieldtime,
+ worktime)
+ self.load_state_flag = flag
+ self.transform_data = transform_data
+ self.list_path = path
+ #Instantiate a loader
+ self.loader = loader
+ self.message = ""
+ self.starttime = 0
+ self.updatefn = updatefn
+
+ def isquit(self):
+ """
+ :raise KeyboardInterrupt: when the thread is interrupted
+ """
+ try:
+ CalcThread.isquit(self)
+ except KeyboardInterrupt:
+ raise KeyboardInterrupt
+
+
+ def compute(self):
+ """
+ read some data
+ """
+ self.starttime = time.time()
+ output = []
+ error_message = ""
+ for path in self.list_path:
+ basename = os.path.basename(path)
+ root, extension = os.path.splitext(basename)
+ if self.load_state_flag:
+ if extension.lower() in EXTENSIONS:
+ pass
+ else:
+ if extension.lower() not in EXTENSIONS:
+ pass
+ try:
+ temp = self.loader.load(path)
+ elapsed = time.time() - self.starttime
+ if temp.__class__.__name__ == "list":
+ for item in temp:
+ data = self.transform_data(item, path)
+ output.append(data)
+ else:
+ data = self.transform_data(temp, path)
+ output.append(data)
+ message = "Loading ..." + str(path) + "\n"
+ if self.updatefn is not None:
+ self.updatefn(output=output, message=message)
+ except:
+ error_message = "Error while loading: %s\n" % str(path)
+ error_message += str(sys.exc_value) + "\n"
+ self.updatefn(output=output, message=error_message)
+
+ message = "Loading Complete!"
+ self.complete(output=output, error_message=error_message,
+ message=message, path=self.list_path)
+
+
+
Index: test/test_rename_guiframe/local_perspectives/plotting/AnnulusSlicer.py
===================================================================
--- test/test_rename_guiframe/local_perspectives/plotting/AnnulusSlicer.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/local_perspectives/plotting/AnnulusSlicer.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,612 @@
+#TODO: the line slicer should listen to all 2DREFRESH events, get the data and slice it
+# before pushing a new 1D data update.
+
+#
+#TODO: NEED MAJOR REFACTOR
+#
+
+import math
+import wx
+#from copy import deepcopy
+# Debug printout
+from sans.guiframe.events import NewPlotEvent
+from sans.guiframe.events import StatusEvent
+from sans.guiframe.events import SlicerParameterEvent
+from sans.guiframe.events import EVT_SLICER_PARS
+from BaseInteractor import _BaseInteractor
+from sans.guiframe.dataFitting import Data1D
+
+class AnnulusInteractor(_BaseInteractor):
+ """
+ Select an annulus through a 2D plot.
+ This interactor is used to average 2D data with the region
+ defined by 2 radius.
+ this class is defined by 2 Ringinterators.
+ """
+ def __init__(self, base, axes, color='black', zorder=3):
+
+ _BaseInteractor.__init__(self, base, axes, color=color)
+ self.markers = []
+ self.axes = axes
+ self.base = base
+ self.qmax = min(math.fabs(self.base.data2D.xmax),
+ math.fabs(self.base.data2D.xmin)) #must be positive
+ self.connect = self.base.connect
+
+ ## Number of points on the plot
+ self.nbins = 20
+ #Cursor position of Rings (Left(-1) or Right(1))
+ self.xmaxd = self.base.data2D.xmax
+ self.xmind = self.base.data2D.xmin
+
+ if (self.xmaxd + self.xmind) > 0:
+ self.sign = 1
+ else:
+ self.sign = -1
+ # Inner circle
+ self.inner_circle = RingInteractor(self, self.base.subplot,
+ zorder=zorder,
+ r=self.qmax/2.0, sign=self.sign)
+ self.inner_circle.qmax = self.qmax
+ self.outer_circle = RingInteractor(self, self.base.subplot,
+ zorder=zorder+1, r=self.qmax/1.8,
+ sign=self.sign)
+ self.outer_circle.qmax = self.qmax * 1.2
+ self.update()
+ self._post_data()
+
+ # Bind to slice parameter events
+ self.base.Bind(EVT_SLICER_PARS, self._onEVT_SLICER_PARS)
+
+ def _onEVT_SLICER_PARS(self, event):
+ """
+ receive an event containing parameters values to reset the slicer
+
+ :param event: event of type SlicerParameterEvent with params as
+ attribute
+
+ """
+ wx.PostEvent(self.base,
+ StatusEvent(status="AnnulusSlicer._onEVT_SLICER_PARS"))
+ event.Skip()
+ if event.type == self.__class__.__name__:
+ self.set_params(event.params)
+ self.base.update()
+
+ def set_layer(self, n):
+ """
+ Allow adding plot to the same panel
+
+ :param n: the number of layer
+
+ """
+ self.layernum = n
+ self.update()
+
+ def clear(self):
+ """
+ Clear the slicer and all connected events related to this slicer
+ """
+ self.clear_markers()
+ self.outer_circle.clear()
+ self.inner_circle.clear()
+ self.base.connect.clearall()
+ self.base.Unbind(EVT_SLICER_PARS)
+
+ def update(self):
+ """
+ Respond to changes in the model by recalculating the profiles and
+ resetting the widgets.
+ """
+ # Update locations
+ self.inner_circle.update()
+ self.outer_circle.update()
+
+ def save(self, ev):
+ """
+ Remember the roughness for this layer and the next so that we
+ can restore on Esc.
+ """
+ self.base.freeze_axes()
+ self.inner_circle.save(ev)
+ self.outer_circle.save(ev)
+
+ def _post_data(self, nbins=None):
+ """
+ Uses annulus parameters to plot averaged data into 1D data.
+
+ :param nbins: the number of points to plot
+
+ """
+ #Data to average
+ data = self.base.data2D
+ # If we have no data, just return
+ if data == None:
+ return
+
+ from DataLoader.manipulations import Ring
+ rmin = min(math.fabs(self.inner_circle.get_radius()),
+ math.fabs(self.outer_circle.get_radius()))
+ rmax = max(math.fabs(self.inner_circle.get_radius()),
+ math.fabs(self.outer_circle.get_radius()))
+ #if the user does not specify the numbers of points to plot
+ # the default number will be nbins= 20
+ if nbins == None:
+ self.nbins = 20
+ else:
+ self.nbins = nbins
+ ## create the data1D Q average of data2D
+ sect = Ring(r_min=rmin, r_max=rmax, nbins=self.nbins)
+ sector = sect(self.base.data2D)
+
+ if hasattr(sector, "dxl"):
+ dxl = sector.dxl
+ else:
+ dxl = None
+ if hasattr(sector, "dxw"):
+ dxw = sector.dxw
+ else:
+ dxw = None
+ new_plot = Data1D(x=(sector.x - math.pi) * 180/math.pi,
+ y=sector.y, dy=sector.dy)
+ new_plot.dxl = dxl
+ new_plot.dxw = dxw
+ new_plot.name = "AnnulusPhi" +"("+ self.base.data2D.name+")"
+
+ new_plot.source = self.base.data2D.source
+ #new_plot.info=self.base.data2D.info
+ new_plot.interactive = True
+ new_plot.detector = self.base.data2D.detector
+ # If the data file does not tell us what the axes are, just assume...
+ new_plot.xaxis("\\rm{\phi}", 'degrees')
+ new_plot.yaxis("\\rm{Intensity} ", "cm^{-1}")
+ if hasattr(data, "scale") and data.scale == 'linear' and \
+ self.base.data2D.name.count("Residuals") > 0:
+ new_plot.ytransform = 'y'
+ new_plot.yaxis("\\rm{Residuals} ", "/")
+
+ new_plot.group_id = "AnnulusPhi" + self.base.data2D.name
+ new_plot.id = None
+ #new_plot.is_data= True
+ new_plot.xtransform = "x"
+ new_plot.ytransform = "y"
+ wx.PostEvent(self.base.parent, NewPlotEvent(plot=new_plot,
+ title="AnnulusPhi"))
+
+ def moveend(self, ev):
+ """
+ Called when any dragging motion ends.
+ Post an event (type =SlicerParameterEvent)
+ to plotter 2D with a copy slicer parameters
+ Call _post_data method
+ """
+ self.base.thaw_axes()
+ # Post parameters to plotter 2D
+ event = SlicerParameterEvent()
+ event.type = self.__class__.__name__
+ event.params = self.get_params()
+ wx.PostEvent(self.base, event)
+ # create a 1D data plot
+ #self._post_data()
+
+ def restore(self):
+ """
+ Restore the roughness for this layer.
+ """
+ self.inner_circle.restore()
+ self.outer_circle.restore()
+
+ def move(self, x, y, ev):
+ """
+ Process move to a new position, making sure that the move is allowed.
+ """
+ pass
+
+ def set_cursor(self, x, y):
+ pass
+
+ def get_params(self):
+ """
+ Store a copy of values of parameters of the slicer into a dictionary.
+
+ :return params: the dictionary created
+
+ """
+ params = {}
+ params["inner_radius"] = math.fabs(self.inner_circle._inner_mouse_x)
+ params["outer_radius"] = math.fabs(self.outer_circle._inner_mouse_x)
+ params["nbins"] = self.nbins
+ return params
+
+ def set_params(self, params):
+ """
+ Receive a dictionary and reset the slicer with values contained
+ in the values of the dictionary.
+
+ :param params: a dictionary containing name of slicer parameters and
+ values the user assigned to the slicer.
+
+ """
+ inner = math.fabs(params["inner_radius"])
+ outer = math.fabs(params["outer_radius"])
+ self.nbins = int(params["nbins"])
+ ## Update the picture
+ self.inner_circle.set_cursor(inner, self.inner_circle._inner_mouse_y)
+ self.outer_circle.set_cursor(outer, self.outer_circle._inner_mouse_y)
+ ## Post the data given the nbins entered by the user
+ self._post_data(self.nbins)
+
+ def freeze_axes(self):
+ """
+ """
+ self.base.freeze_axes()
+
+ def thaw_axes(self):
+ """
+ """
+ self.base.thaw_axes()
+
+ def draw(self):
+ """
+ """
+ self.base.draw()
+
+
+class RingInteractor(_BaseInteractor):
+ """
+ Draw a ring Given a radius
+ """
+ def __init__(self, base, axes, color='black', zorder=5, r=1.0, sign=1):
+ """
+ :param: the color of the line that defined the ring
+ :param r: the radius of the ring
+ :param sign: the direction of motion the the marker
+
+ """
+ _BaseInteractor.__init__(self, base, axes, color=color)
+ self.markers = []
+ self.axes = axes
+ # Current radius of the ring
+ self._inner_mouse_x = r
+ #Value of the center of the ring
+ self._inner_mouse_y = 0
+ # previous value of that radius
+ self._inner_save_x = r
+ #Save value of the center of the ring
+ self._inner_save_y = 0
+ #Class instantiating RingIterator class
+ self.base = base
+ #the direction of the motion of the marker
+ self.sign = sign
+ ## Create a marker
+ try:
+ # Inner circle marker
+ x_value = [self.sign * math.fabs(self._inner_mouse_x)]
+ self.inner_marker = self.axes.plot(x_value,
+ [0],
+ linestyle='',
+ marker='s', markersize=10,
+ color=self.color, alpha=0.6,
+ pickradius=5, label="pick",
+ zorder=zorder,
+ visible=True)[0]
+ except:
+ x_value = [self.sign * math.fabs(self._inner_mouse_x)]
+ self.inner_marker = self.axes.plot(x_value,
+ [0],
+ linestyle='',
+ marker='s', markersize=10,
+ color=self.color, alpha=0.6,
+ label="pick",
+ visible=True)[0]
+ message = "\nTHIS PROTOTYPE NEEDS THE LATEST"
+ message += " VERSION OF MATPLOTLIB\n"
+ message += "Get the SVN version that is at "
+ message += " least as recent as June 1, 2007"
+
+ owner = self.base.base.parent
+ wx.PostEvent(owner,
+ StatusEvent(status="AnnulusSlicer: %s" % message))
+
+ # Draw a circle
+ [self.inner_circle] = self.axes.plot([], [],
+ linestyle='-', marker='',
+ color=self.color)
+ # the number of points that make the ring line
+ self.npts = 40
+
+ self.connect_markers([self.inner_marker])
+ self.update()
+
+ def set_layer(self, n):
+ """
+ Allow adding plot to the same panel
+
+ :param n: the number of layer
+
+ """
+ self.layernum = n
+ self.update()
+
+ def clear(self):
+ """
+ Clear the slicer and all connected events related to this slicer
+ """
+ self.clear_markers()
+ try:
+ self.inner_marker.remove()
+ self.inner_circle.remove()
+ except:
+ # Old version of matplotlib
+ for item in range(len(self.axes.lines)):
+ del self.axes.lines[0]
+
+ def get_radius(self):
+ """
+ :return self._inner_mouse_x: the current radius of the ring
+ """
+ return self._inner_mouse_x
+
+ def update(self):
+ """
+ Draw the new roughness on the graph.
+ """
+ # Plot inner circle
+ x = []
+ y = []
+ for i in range(self.npts):
+ phi = 2.0 * math.pi / (self.npts - 1) * i
+
+ xval = 1.0 * self._inner_mouse_x * math.cos(phi)
+ yval = 1.0 * self._inner_mouse_x * math.sin(phi)
+
+ x.append(xval)
+ y.append(yval)
+
+ self.inner_marker.set(xdata=[self.sign*math.fabs(self._inner_mouse_x)],
+ ydata=[0])
+ self.inner_circle.set_data(x, y)
+
+ def save(self, ev):
+ """
+ Remember the roughness for this layer and the next so that we
+ can restore on Esc.
+ """
+ self._inner_save_x = self._inner_mouse_x
+ self._inner_save_y = self._inner_mouse_y
+ self.base.freeze_axes()
+
+ def moveend(self, ev):
+ """
+ Called after a dragging motion
+ """
+ self.base.moveend(ev)
+
+ def restore(self):
+ """
+ Restore the roughness for this layer.
+ """
+ self._inner_mouse_x = self._inner_save_x
+ self._inner_mouse_y = self._inner_save_y
+
+ def move(self, x, y, ev):
+ """
+ Process move to a new position, making sure that the move is allowed.
+ """
+ self._inner_mouse_x = x
+ self._inner_mouse_y = y
+ self.base.base.update()
+
+ def set_cursor(self, x, y):
+ """
+ draw the ring given x, y value
+ """
+ self.move(x, y, None)
+ self.update()
+
+
+ def get_params(self):
+ """
+ Store a copy of values of parameters of the slicer into a dictionary.
+
+ :return params: the dictionary created
+
+ """
+ params = {}
+ params["radius"] = math.fabs(self._inner_mouse_x)
+ return params
+
+ def set_params(self, params):
+ """
+ Receive a dictionary and reset the slicer with values contained
+ in the values of the dictionary.
+
+ :param params: a dictionary containing name of slicer parameters and
+ values the user assigned to the slicer.
+
+ """
+ x = params["radius"]
+ self.set_cursor(x, self._inner_mouse_y)
+
+class CircularMask(_BaseInteractor):
+ """
+ Draw a ring Given a radius
+ """
+ def __init__(self, base, axes, color='grey', zorder=3, side=None):
+ """
+
+ :param: the color of the line that defined the ring
+ :param r: the radius of the ring
+ :param sign: the direction of motion the the marker
+
+ """
+ _BaseInteractor.__init__(self, base, axes, color=color)
+ self.markers = []
+ self.axes = axes
+ self.base = base
+ self.is_inside = side
+ self.qmax = min(math.fabs(self.base.data.xmax),
+ math.fabs(self.base.data.xmin)) #must be positive
+ self.connect = self.base.connect
+
+ #Cursor position of Rings (Left(-1) or Right(1))
+ self.xmaxd = self.base.data.xmax
+ self.xmind = self.base.data.xmin
+
+ if (self.xmaxd + self.xmind) > 0:
+ self.sign = 1
+ else:
+ self.sign = -1
+ # Inner circle
+ self.outer_circle = RingInteractor(self, self.base.subplot, 'blue',
+ zorder=zorder+1, r=self.qmax/1.8,
+ sign=self.sign)
+ self.outer_circle.qmax = self.qmax * 1.2
+ self.update()
+ self._post_data()
+
+ # Bind to slice parameter events
+ #self.base.Bind(EVT_SLICER_PARS, self._onEVT_SLICER_PARS)
+
+ def _onEVT_SLICER_PARS(self, event):
+ """
+ receive an event containing parameters values to reset the slicer
+
+ :param event: event of type SlicerParameterEvent with params as
+ attribute
+ """
+ wx.PostEvent(self.base,
+ StatusEvent(status="AnnulusSlicer._onEVT_SLICER_PARS"))
+ event.Skip()
+ if event.type == self.__class__.__name__:
+ self.set_params(event.params)
+ self.base.update()
+
+ def set_layer(self, n):
+ """
+ Allow adding plot to the same panel
+
+ :param n: the number of layer
+
+ """
+ self.layernum = n
+ self.update()
+
+ def clear(self):
+ """
+ Clear the slicer and all connected events related to this slicer
+ """
+ self.clear_markers()
+ self.outer_circle.clear()
+ self.base.connect.clearall()
+ #self.base.Unbind(EVT_SLICER_PARS)
+
+ def update(self):
+ """
+ Respond to changes in the model by recalculating the profiles and
+ resetting the widgets.
+ """
+ # Update locations
+ self.outer_circle.update()
+ #if self.is_inside != None:
+ out = self._post_data()
+ return out
+
+ def save(self, ev):
+ """
+ Remember the roughness for this layer and the next so that we
+ can restore on Esc.
+ """
+ self.base.freeze_axes()
+ self.outer_circle.save(ev)
+
+ def _post_data(self):
+ """
+ Uses annulus parameters to plot averaged data into 1D data.
+
+ :param nbins: the number of points to plot
+
+ """
+ #Data to average
+ data = self.base.data
+
+ # If we have no data, just return
+ if data == None:
+ return
+ mask = data.mask
+ from DataLoader.manipulations import Ringcut
+
+ rmin = 0
+ rmax = math.fabs(self.outer_circle.get_radius())
+
+ ## create the data1D Q average of data2D
+ mask = Ringcut(r_min=rmin, r_max= rmax)
+
+ if self.is_inside:
+ out = (mask(data) == False)
+ else:
+ out = (mask(data))
+ #self.base.data.mask=out
+ return out
+
+
+ def moveend(self, ev):
+ """
+ Called when any dragging motion ends.
+ Post an event (type =SlicerParameterEvent)
+ to plotter 2D with a copy slicer parameters
+ Call _post_data method
+ """
+ self.base.thaw_axes()
+ # create a 1D data plot
+ self._post_data()
+
+ def restore(self):
+ """
+ Restore the roughness for this layer.
+ """
+ self.outer_circle.restore()
+
+ def move(self, x, y, ev):
+ """
+ Process move to a new position, making sure that the move is allowed.
+ """
+ pass
+
+ def set_cursor(self, x, y):
+ pass
+
+ def get_params(self):
+ """
+ Store a copy of values of parameters of the slicer into a dictionary.
+
+ :return params: the dictionary created
+
+ """
+ params = {}
+ params["outer_radius"] = math.fabs(self.outer_circle._inner_mouse_x)
+ return params
+
+ def set_params(self, params):
+ """
+ Receive a dictionary and reset the slicer with values contained
+ in the values of the dictionary.
+
+ :param params: a dictionary containing name of slicer parameters and
+ values the user assigned to the slicer.
+ """
+ outer = math.fabs(params["outer_radius"] )
+ ## Update the picture
+ self.outer_circle.set_cursor(outer, self.outer_circle._inner_mouse_y)
+ ## Post the data given the nbins entered by the user
+ self._post_data()
+
+ def freeze_axes(self):
+ self.base.freeze_axes()
+
+ def thaw_axes(self):
+ self.base.thaw_axes()
+
+ def draw(self):
+ self.base.update()
+
Index: test/test_rename_guiframe/local_perspectives/plotting/Arc.py
===================================================================
--- test/test_rename_guiframe/local_perspectives/plotting/Arc.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/local_perspectives/plotting/Arc.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,162 @@
+
+import math
+import wx
+from copy import deepcopy
+
+from BaseInteractor import _BaseInteractor
+from sans.guiframe.events import NewPlotEvent
+from sans.guiframe.events import StatusEvent
+from sans.guiframe.events import SlicerParameterEvent
+from sans.guiframe.events import EVT_SLICER_PARS
+
+
+class ArcInteractor(_BaseInteractor):
+ """
+ Select an annulus through a 2D plot
+ """
+ def __init__(self, base, axes, color='black', zorder=5, r=1.0,
+ theta1=math.pi/8, theta2=math.pi/4):
+
+ _BaseInteractor.__init__(self, base, axes, color=color)
+ self.markers = []
+ self.axes = axes
+ self._mouse_x = r
+ self._mouse_y = 0
+
+ self._save_x = r
+ self._save_y = 0
+
+ self.scale = 10.0
+
+ self.theta1 = theta1
+ self.theta2 = theta2
+ self.radius = r
+ [self.arc] = self.axes.plot([], [],
+ linestyle='-', marker='',
+ color=self.color)
+ self.npts = 20
+ self.has_move = False
+ self.connect_markers([self.arc])
+ self.update()
+
+ def set_layer(self, n):
+ """
+ """
+ self.layernum = n
+ self.update()
+
+ def clear(self):
+ """
+ """
+ self.clear_markers()
+ try:
+ self.marker.remove()
+ self.arc.remove()
+ except:
+ # Old version of matplotlib
+ for item in range(len(self.axes.lines)):
+ del self.axes.lines[0]
+
+ def get_radius(self):
+ """
+ """
+ radius = math.sqrt(math.pow(self._mouse_x, 2) + \
+ math.pow(self._mouse_y, 2))
+ return radius
+
+ def update(self, theta1=None, theta2=None, nbins=None, r=None):
+ """
+ """
+ # Plot inner circle
+ x = []
+ y = []
+ if theta1 != None:
+ self.theta1 = theta1
+ if theta2 != None:
+ self.theta2 = theta2
+ #print "ring update theta1 theta2", math.degrees(self.theta1),
+ #math.degrees(self.theta2)
+ while self.theta2 < self.theta1:
+ self.theta2 += (2 * math.pi)
+ while self.theta2 >= (self.theta1 + 2 * math.pi):
+ self.theta2 -= (2 * math.pi)
+ npts = int((self.theta2 - self.theta1)/(math.pi/120))
+
+ if r == None:
+ self.radius = math.sqrt(math.pow(self._mouse_x, 2) + \
+ math.pow(self._mouse_y, 2))
+ else:
+ self.radius = r
+ for i in range(self.npts):
+ phi = (self.theta2 - self.theta1)/(self.npts - 1) * i + self.theta1
+ xval = 1.0 * self.radius * math.cos(phi)
+ yval = 1.0 * self.radius * math.sin(phi)
+
+ x.append(xval)
+ y.append(yval)
+ #self.marker.set(xdata=[self._mouse_x],ydata=[0])
+ self.arc.set_data(x, y)
+
+ def save(self, ev):
+ """
+ Remember the roughness for this layer and the next so that we
+ can restore on Esc.
+ """
+ self._save_x = self._mouse_x
+ self._save_y = self._mouse_y
+ #self._save_x = ev.xdata
+ #self._save_y = ev.ydata
+ self.base.freeze_axes()
+
+ def moveend(self, ev):
+ """
+ """
+ self.has_move = False
+
+ event = SlicerParameterEvent()
+ event.type = self.__class__.__name__
+ event.params = self.get_params()
+ #print "in arc moveend params",self.get_params()
+ #wx.PostEvent(self.base.base.parent, event)
+ self.base.moveend(ev)
+
+ def restore(self):
+ """
+ Restore the roughness for this layer.
+ """
+ self._mouse_x = self._save_x
+ self._mouse_y = self._save_y
+
+ def move(self, x, y, ev):
+ """
+ Process move to a new position, making sure that the move is allowed.
+ """
+ #print "ring move x, y", x,y
+ self._mouse_x = x
+ self._mouse_y = y
+ self.has_move = True
+ self.base.base.update()
+
+ def set_cursor(self, radius, phi_min, phi_max, nbins):
+ """
+ """
+ self.theta1 = phi_min
+ self.theta2 = phi_max
+ self.update(nbins=nbins, r=radius)
+
+ def get_params(self):
+ """
+ """
+ params = {}
+ params["radius"] = self.radius
+ params["theta1"] = self.theta1
+ params["theta2"] = self.theta2
+ return params
+
+ def set_params(self, params):
+ """
+ """
+ x = params["radius"]
+ self.set_cursor(x, self._mouse_y)
+
+
Index: test/test_rename_guiframe/local_perspectives/plotting/AzimutSlicer.py
===================================================================
--- test/test_rename_guiframe/local_perspectives/plotting/AzimutSlicer.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/local_perspectives/plotting/AzimutSlicer.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,312 @@
+#TODO: the line slicer should listen to all 2DREFRESH events, get the data and slice it
+# before pushing a new 1D data update.
+
+#
+#TODO: NEED MAJOR REFACTOR
+#
+
+
+# Debug printout
+import math
+import wx
+from copy import deepcopy
+from BaseInteractor import _BaseInteractor
+from sans.guiframe.events import NewPlotEvent
+from sans.guiframe.events import StatusEvent
+from sans.guiframe.events import SlicerParameterEvent
+from sans.guiframe.events import EVT_SLICER_PARS
+
+
+class SectorInteractor(_BaseInteractor):
+ """
+ Select an annulus through a 2D plot
+ """
+ def __init__(self, base, axes, color='black', zorder=3):
+ """
+ """
+ _BaseInteractor.__init__(self, base, axes, color=color)
+ self.markers = []
+ self.axes = axes
+ self.qmax = self.base.data2D.xmax
+ self.connect = self.base.connect
+
+ ## Number of points on the plot
+ self.nbins = 20
+ theta1 = math.pi/8
+ theta2 = math.pi/2
+ theta1 = 2 * math.pi/3
+ theta2 = -2 * math.pi/3
+ r1 = self.qmax/2.0
+ r2 = self.qmax/1.8
+
+ # Inner circle
+ from Arc import ArcInteractor
+ self.inner_circle = ArcInteractor(self, self.base.subplot,
+ zorder=zorder,
+ r=self.qmax/2.0,
+ theta1=theta1,
+ theta2=theta2)
+ self.inner_circle.qmax = self.qmax
+ self.outer_circle = ArcInteractor(self, self.base.subplot,
+ zorder=zorder+1,
+ r=self.qmax/1.8,
+ theta1=theta1,
+ theta2=theta2)
+ self.outer_circle.qmax = self.qmax * 1.2
+ #self.outer_circle.set_cursor(self.base.qmax/1.8, 0)
+ from Edge import RadiusInteractor
+ self.right_edge= RadiusInteractor(self, self.base.subplot,
+ zorder=zorder+1,
+ arc1=self.inner_circle,
+ arc2=self.outer_circle,
+ theta=theta1)
+ self.left_edge= RadiusInteractor(self, self.base.subplot,
+ zorder=zorder+1,
+ arc1=self.inner_circle,
+ arc2=self.outer_circle,
+ theta=theta2)
+ self.update()
+ self._post_data()
+ # Bind to slice parameter events
+ self.base.parent.Bind(EVT_SLICER_PARS, self._onEVT_SLICER_PARS)
+
+ def _onEVT_SLICER_PARS(self, event):
+ """
+ """
+ #printEVT("AnnulusSlicer._onEVT_SLICER_PARS")
+ event.Skip()
+ if event.type == self.__class__.__name__:
+ self.set_params(event.params)
+ self.base.update()
+
+ def save_data(self, path, image, x, y):
+ """
+ """
+ output = open(path, 'w')
+ data_x, data_y = self.get_data(image, x, y)
+
+ output.write(" \n")
+ for i in range(len(data_x)):
+ output.write("%g %g\n" % (data_x[i], data_y[i]))
+ output.close()
+
+ def set_layer(self, n):
+ """
+ """
+ self.layernum = n
+ self.update()
+
+ def clear(self):
+ """
+ """
+ self.clear_markers()
+ self.outer_circle.clear()
+ self.inner_circle.clear()
+ self.right_edge.clear()
+ self.left_edge.clear()
+ #self.base.connect.disconnect()
+ self.base.parent.Unbind(EVT_SLICER_PARS)
+
+ def update(self):
+ """
+ Respond to changes in the model by recalculating the profiles and
+ resetting the widgets.
+ """
+ # Update locations
+ if self.inner_circle.has_move:
+ #print "inner circle has moved"
+ self.inner_circle.update()
+ r1 = self.inner_circle.get_radius()
+ r2 = self.outer_circle.get_radius()
+ self.right_edge.update(r1, r2)
+ self.left_edge.update(r1, r2)
+ if self.outer_circle.has_move:
+ #print "outer circle has moved"
+ self.outer_circle.update()
+ r1 = self.inner_circle.get_radius()
+ r2 = self.outer_circle.get_radius()
+ self.left_edge.update(r1, r2)
+ self.right_edge.update(r1, r2)
+ if self.right_edge.has_move:
+ #print "right edge has moved"
+ self.right_edge.update()
+ self.inner_circle.update(theta1=self.right_edge.get_angle(),
+ theta2=None)
+ self.outer_circle.update(theta1=self.right_edge.get_angle(),
+ theta2=None)
+ if self.left_edge.has_move:
+ #print "left Edge has moved"
+ self.left_edge.update()
+ self.inner_circle.update(theta1=None,
+ theta2=self.left_edge.get_angle())
+ self.outer_circle.update(theta1=None,
+ theta2=self.left_edge.get_angle())
+
+ def save(self, ev):
+ """
+ Remember the roughness for this layer and the next so that we
+ can restore on Esc.
+ """
+ self.base.freeze_axes()
+ self.inner_circle.save(ev)
+ self.outer_circle.save(ev)
+ self.right_edge.save(ev)
+ self.left_edge.save(ev)
+
+ def _post_data(self):
+ pass
+
+ def post_data(self,new_sector ):
+ """ post data averaging in Q"""
+ if self.inner_circle.get_radius() < self.outer_circle.get_radius():
+ rmin = self.inner_circle.get_radius()
+ rmax = self.outer_circle.get_radius()
+ else:
+ rmin = self.outer_circle.get_radius()
+ rmax = self.inner_circle.get_radius()
+ if self.right_edge.get_angle() < self.left_edge.get_angle():
+ phimin = self.right_edge.get_angle()
+ phimax = self.left_edge.get_angle()
+ else:
+ phimin = self.left_edge.get_angle()
+ phimax = self.right_edge.get_angle()
+ #print "phimin, phimax, rmin ,rmax",math.degrees(phimin),
+ # math.degrees(phimax), rmin ,rmax
+ #from DataLoader.manipulations import SectorQ
+
+ sect = new_sector(r_min=rmin, r_max=rmax,
+ phi_min=phimin, phi_max=phimax)
+ sector = sect(self.base.data2D)
+
+ from sans.guiframe.dataFitting import Data1D
+ if hasattr(sector, "dxl"):
+ dxl = sector.dxl
+ else:
+ dxl = None
+ if hasattr(sector, "dxw"):
+ dxw = sector.dxw
+ else:
+ dxw = None
+ new_plot = Data1D(x=sector.x, y=sector.y, dy=sector.dy,
+ dxl=dxl, dxw=dxw)
+ new_plot.name = str(new_sector.__name__) + \
+ "("+ self.base.data2D.name+")"
+ new_plot.source = self.base.data2D.source
+ new_plot.interactive = True
+ #print "loader output.detector",output.source
+ new_plot.detector = self.base.data2D.detector
+ # If the data file does not tell us what the axes are, just assume...
+ new_plot.xaxis("\\rm{Q}", 'rad')
+ new_plot.yaxis("\\rm{Intensity} ", "cm^{-1}")
+ new_plot.group_id = str(new_sector.__name__) + self.base.data2D.name
+ wx.PostEvent(self.base.parent,
+ NewPlotEvent(plot=new_plot, title=str(new_sector.__name__)))
+
+ def moveend(self, ev):
+ #self.base.thaw_axes()
+
+ # Post paramters
+ #event = SlicerParameterEvent()
+ #event.type = self.__class__.__name__
+ #event.params = self.get_params()
+ #print "main moveend ", event.params
+ #wx.PostEvent(self.base.parent, event)
+ #self._post_data()
+ pass
+
+ def restore(self):
+ """
+ Restore the roughness for this layer.
+ """
+ self.inner_circle.restore()
+ self.outer_circle.restore()
+ self.right_edge.restore()
+ self.left_edge.restore()
+
+ def move(self, x, y, ev):
+ """
+ Process move to a new position, making sure that the move is allowed.
+ """
+ pass
+
+ def set_cursor(self, x, y):
+ """
+ """
+ pass
+
+ def get_params(self):
+ """
+ """
+ params = {}
+ params["r_min"] = self.inner_circle.get_radius()
+ params["r_max"] = self.outer_circle.get_radius()
+ params["phi_min"] = self.right_edge.get_angle()
+ params["phi_max"] = self.left_edge.get_angle()
+ params["nbins"] = self.nbins
+ return params
+
+ def set_params(self, params):
+ """
+ """
+ #print "setparams on main slicer ",params
+ inner = params["r_min"]
+ outer = params["r_max"]
+ phi_min= params["phi_min"]
+ phi_max=params["phi_max"]
+ self.nbins = int(params["nbins"])
+
+ self.inner_circle.set_cursor(inner, phi_min, phi_max,self.nbins)
+ self.outer_circle.set_cursor(outer, phi_min, phi_max, self.nbins)
+ self.right_edge.set_cursor(inner, outer, phi_min)
+ self.left_edge.set_cursor(inner, outer, phi_max)
+ self._post_data()
+
+ def freeze_axes(self):
+ """
+ """
+ self.base.freeze_axes()
+
+ def thaw_axes(self):
+ """
+ """
+ self.base.thaw_axes()
+
+ def draw(self):
+ """
+ """
+ self.base.draw()
+
+class SectorInteractorQ(SectorInteractor):
+ """
+ """
+ def __init__(self, base, axes, color='black', zorder=3):
+ """
+ """
+ SectorInteractor.__init__(self, base, axes, color=color)
+ self.base=base
+ self._post_data()
+
+ def _post_data(self):
+ """
+ """
+ from DataLoader.manipulations import SectorQ
+ self.post_data(SectorQ)
+
+
+class SectorInteractorPhi(SectorInteractor):
+ """
+ """
+ def __init__(self, base, axes, color='black', zorder=3):
+ """
+ """
+ SectorInteractor.__init__(self, base, axes, color=color)
+ self.base=base
+ self._post_data()
+
+ def _post_data(self):
+ """
+ """
+ from DataLoader.manipulations import SectorPhi
+ self.post_data(SectorPhi )
+
+
Index: test/test_rename_guiframe/local_perspectives/plotting/BaseInteractor.py
===================================================================
--- test/test_rename_guiframe/local_perspectives/plotting/BaseInteractor.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/local_perspectives/plotting/BaseInteractor.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,180 @@
+interface_color = 'black'
+disable_color = 'gray'
+active_color = 'red'
+rho_color = 'black'
+mu_color = 'green'
+P_color = 'blue'
+theta_color = 'orange'
+profile_colors = [rho_color, mu_color, P_color, theta_color]
+
+class _BaseInteractor:
+ """
+ Share some functions between the interface interactor and various layer
+ interactors.
+
+ Individual interactors need the following functions:
+
+ save(ev) - save the current state for later restore
+ restore() - restore the old state
+ move(x,y,ev) - move the interactor to position x,y
+ moveend(ev) - end the drag event
+ update() - draw the interactors
+
+ The following are provided by the base class:
+
+ connect_markers(markers) - register callbacks for all markers
+ clear_markers() - remove all items in self.markers
+ onHilite(ev) - enter/leave event processing
+ onLeave(ev) - enter/leave event processing
+ onClick(ev) - mouse click: calls save()
+ onRelease(ev) - mouse click ends: calls moveend()
+ onDrag(ev) - mouse move: calls move() or restore()
+ onKey(ev) - keyboard move: calls move() or restore()
+
+ Interactor attributes:
+
+ base - model we are operating on
+ axes - axes holding the interactor
+ color - color of the interactor in non-active state
+ markers - list of handles for the interactor
+
+ """
+ def __init__(self, base, axes, color='black'):
+ """
+ """
+ self.base = base
+ self.axes = axes
+ self.color = color
+ self.clickx = None
+ self.clicky = None
+ self.markers = []
+
+ def clear_markers(self):
+ """
+ Clear old markers and interfaces.
+ """
+ for h in self.markers: h.remove()
+ if self.markers:
+ self.base.connect.clear(*self.markers)
+ self.markers = []
+
+ def save(self, ev):
+ """
+ """
+ pass
+
+ def restore(self, ev):
+ """
+ """
+ pass
+
+ def move(self, x, y, ev):
+ """
+ """
+ pass
+
+ def moveend(self, ev):
+ """
+ """
+ pass
+
+ def connect_markers(self, markers):
+ """
+ Connect markers to callbacks
+ """
+
+ for h in markers:
+ connect = self.base.connect
+ connect('enter', h, self.onHilite)
+ connect('leave', h, self.onLeave)
+ connect('click', h, self.onClick)
+ connect('release', h, self.onRelease)
+ connect('drag', h, self.onDrag)
+ connect('key', h, self.onKey)
+
+ def onHilite(self, ev):
+ """
+ Hilite the artist reporting the event, indicating that it is
+ ready to receive a click.
+ """
+ ev.artist.set_color(active_color)
+ self.base.draw()
+ return True
+
+ def onLeave(self, ev):
+ """
+ Restore the artist to the original colour when the cursor leaves.
+ """
+ ev.artist.set_color(self.color)
+ self.base.draw()
+ return True
+
+ def onClick(self, ev):
+ """
+ Prepare to move the artist. Calls save() to preserve the state for
+ later restore().
+ """
+ self.clickx, self.clicky = ev.xdata, ev.ydata
+ self.save(ev)
+ return True
+
+ def onRelease(self, ev):
+ """
+ """
+ self.moveend(ev)
+ return True
+
+ def onDrag(self, ev):
+ """
+ Move the artist. Calls move() to update the state, or restore() if
+ the mouse leaves the window.
+ """
+ inside, _ = self.axes.contains(ev)
+ if inside:
+ self.clickx, self.clicky = ev.xdata, ev.ydata
+ self.move(ev.xdata, ev.ydata, ev)
+ else:
+ self.restore()
+ self.base.update()
+ return True
+
+ def onKey(self, ev):
+ """
+ Respond to keyboard events. Arrow keys move the widget. Escape
+ restores it to the position before the last click.
+
+ Calls move() to update the state. Calls restore() on escape.
+ """
+ if ev.key == 'escape':
+ self.restore()
+ elif ev.key in ['up', 'down', 'right', 'left']:
+ dx, dy = self.dpixel(self.clickx, self.clicky, nudge=ev.control)
+ if ev.key == 'up':
+ self.clicky += dy
+ elif ev.key == 'down':
+ self.clicky -= dy
+ elif ev.key == 'right':
+ self.clickx += dx
+ else: self.clickx -= dx
+ self.move(self.clickx, self.clicky, ev)
+ else:
+ return False
+ self.base.update()
+ return True
+
+ def dpixel(self, x, y, nudge=False):
+ """
+ Return the step size in data coordinates for a small
+ step in screen coordinates. If nudge is False (default)
+ the step size is one pixel. If nudge is True, the step
+ size is 0.2 pixels.
+ """
+ ax = self.axes
+ px, py = ax.transData.inverse_xy_tup((x, y))
+ if nudge:
+ nx, ny = ax.transData.xy_tup((px+0.2, py+0.2))
+ else:
+ nx, ny = ax.transData.xy_tup((px+1.0, py+1.0))
+ dx, dy = nx-x, ny-y
+ return dx, dy
+
Index: test/test_rename_guiframe/local_perspectives/plotting/Edge.py
===================================================================
--- test/test_rename_guiframe/local_perspectives/plotting/Edge.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/local_perspectives/plotting/Edge.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,143 @@
+
+import math
+#import wx
+#from copy import deepcopy
+from BaseInteractor import _BaseInteractor
+#from sans.guiframe.events import NewPlotEvent
+#from sans.guiframe.events import StatusEvent
+#from sans.guiframe.events import SlicerParameterEvent
+#from sans.guiframe.events import EVT_SLICER_PARS
+
+
+class RadiusInteractor(_BaseInteractor):
+ """
+ Select an annulus through a 2D plot
+ """
+ def __init__(self, base, axes, color='black', zorder=5, arc1=None,
+ arc2=None, theta=math.pi/8):
+ """
+ """
+ _BaseInteractor.__init__(self, base, axes, color=color)
+ self.markers = []
+ self.axes = axes
+ self.r1 = arc1.get_radius()
+ self.r2 = arc2.get_radius()
+ #print "radius init", self.r1, self.r2
+ self.theta = theta
+ self.save_theta = theta
+ #self.scale = 10.0
+ self.move_stop = False
+ self.theta_left = None
+ self.theta_right = None
+ self.arc1 = arc1
+ self.arc2 = arc2
+ #raise "Version error", message
+ x1 = self.r1 * math.cos(self.theta)
+ y1 = self.r1 * math.sin(self.theta)
+ x2 = self.r2 * math.cos(self.theta)
+ y2 = self.r2 * math.sin(self.theta)
+ self.line = self.axes.plot([x1, x2], [y1, y2],
+ linestyle='-', marker='',
+ color=self.color,
+ visible=True)[0]
+ self.phi = theta
+ self.npts = 20
+ self.has_move = False
+ self.connect_markers([self.line])
+ self.update()
+
+ def set_layer(self, n):
+ """
+ """
+ self.layernum = n
+ self.update()
+
+ def clear(self):
+ """
+ """
+ self.clear_markers()
+ try:
+ self.line.remove()
+ except:
+ # Old version of matplotlib
+ for item in range(len(self.axes.lines)):
+ del self.axes.lines[0]
+
+ def get_angle(self):
+ """
+ """
+ return self.theta
+
+ def update(self, r1=None, r2=None, theta=None):
+ """
+ Draw the new roughness on the graph.
+ """
+ if r1 != None:
+ self.r1 = r1
+ if r2 != None:
+ self.r2 = r2
+ if theta != None:
+ self.theta = theta
+ #print "in the edge r1, r2",self.r1,self.r2,math.degrees(self.theta)
+ x1 = self.r1 * math.cos(self.theta)
+ y1 = self.r1 * math.sin(self.theta)
+ x2 = self.r2 * math.cos(self.theta)
+ y2 = self.r2 * math.sin(self.theta)
+ self.line.set(xdata=[x1, x2], ydata=[y1, y2])
+
+ def save(self, ev):
+ """
+ Remember the roughness for this layer and the next so that we
+ can restore on Esc.
+ """
+ self.save_theta = math.atan2(ev.y,ev.x)
+ #self.save_theta= self.theta
+ self.base.freeze_axes()
+
+ def moveend(self, ev):
+ """
+ """
+ self.has_move = False
+ self.base.moveend(ev)
+
+ def restore(self, ev):
+ """
+ Restore the roughness for this layer.
+ """
+ self.theta = self.save_theta
+
+ def move(self, x, y, ev):
+ """
+ Process move to a new position, making sure that the move is allowed.
+ """
+ self.theta = math.atan2(y, x)
+ self.has_move = True
+ self.base.base.update()
+
+ def set_cursor(self, r_min, r_max, theta):
+ """
+ """
+ self.theta = theta
+ self.r1 = r_min
+ self.r2 = r_max
+ self.update()
+
+ def get_params(self):
+ """
+ """
+ params = {}
+ params["radius1"] = self.r1
+ params["radius2"] = self.r2
+ params["theta"] = self.theta
+ return params
+
+ def set_params(self, params):
+ """
+ """
+ #print "when here set curcor arc"
+ x1 = params["radius1"]
+ x2 = params["radius2"]
+ theta= params["theta"]
+ self.set_cursor(x1, x2, theta)
+
+
Index: test/test_rename_guiframe/local_perspectives/plotting/Plotter1D.py
===================================================================
--- test/test_rename_guiframe/local_perspectives/plotting/Plotter1D.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/local_perspectives/plotting/Plotter1D.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,518 @@
+
+################################################################################
+#This software was developed by the University of Tennessee as part of the
+#Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
+#project funded by the US National Science Foundation.
+#
+#See the license text in license.txt
+#
+#copyright 2008, University of Tennessee
+################################################################################
+
+
+import wx
+import sys
+import os
+import pylab
+import math
+import numpy
+import time
+
+from danse.common.plottools.PlotPanel import PlotPanel
+#from danse.common.plottools.plottables import Graph
+from sans.guiframe import dataFitting
+from sans.guiframe.events import EVT_NEW_PLOT
+from sans.guiframe.events import StatusEvent
+from sans.guiframe.events import NewPlotEvent
+from sans.guiframe.events import SlicerEvent
+from sans.guiframe.events import PanelOnFocusEvent
+from sans.guiframe.events import EVT_NEW_LOADED_DATA
+from sans.guiframe.utils import PanelMenu
+from sans.guiframe.dataFitting import Data1D
+from sans.guiframe.panel_base import PanelBase
+from binder import BindArtist
+
+DEFAULT_QMAX = 0.05
+DEFAULT_QSTEP = 0.001
+DEFAULT_BEAM = 0.005
+BIN_WIDTH = 1
+
+
+class ModelPanel1D(PlotPanel, PanelBase):
+ """
+ Plot panel for use with the GUI manager
+ """
+
+ ## Internal name for the AUI manager
+ window_name = "plotpanel"
+ ## Title to appear on top of the window
+ window_caption = "Plot Panel"
+ ## Flag to tell the GUI manager that this panel is not
+ # tied to any perspective
+ ALWAYS_ON = True
+ ## Group ID
+ group_id = None
+
+ def __init__(self, parent, id=-1, color = None,
+ dpi=None, style=wx.NO_FULL_REPAINT_ON_RESIZE, **kwargs):
+ PlotPanel.__init__(self, parent, id=id, style=style, **kwargs)
+ PanelBase.__init__(self, parent)
+ ## Reference to the parent window
+ self.parent = parent
+ ## Plottables
+ self.plots = {}
+ #context menu
+ self._slicerpop = None
+
+ self._available_data = []
+ self._menu_add_ids = []
+ self._symbol_labels = self.get_symbol_label()
+
+ self.hide_menu = None
+ ## Unique ID (from gui_manager)
+ self.uid = None
+ self.x_size = None
+ ## Default locations
+ self._default_save_location = os.getcwd()
+ self.size = None
+ ## Graph
+ #self.graph = Graph()
+ self.graph.xaxis("\\rm{Q}", 'A^{-1}')
+ self.graph.yaxis("\\rm{Intensity} ", "cm^{-1}")
+ self.graph.render(self)
+
+ # In resizing event
+ self.resizing = False
+ self.canvas.set_resizing(self.resizing)
+ self.Bind(wx.EVT_SIZE, self._OnReSize)
+ self._add_more_tool()
+
+ def get_symbol_label(self):
+ """
+ Associates label to symbol
+ """
+ _labels = {}
+ i = 0
+ _labels['Circle'] = i
+ i += 1
+ _labels['Cross X '] = i
+ i += 1
+ _labels['Triangle Down'] = i
+ i += 1
+ _labels['Triangle Up'] = i
+ i += 1
+ _labels['Triangle Left'] = i
+ i += 1
+ _labels['Triangle Right'] = i
+ i += 1
+ _labels['Cross +'] = i
+ i += 1
+ _labels['Square'] = i
+ i += 1
+ _labels['Diamond'] = i
+ i += 1
+ _labels['Diamond'] = i
+ i += 1
+ _labels['Hexagon1'] = i
+ i += 1
+ _labels['Hexagon2'] = i
+ i += 1
+ _labels['Pentagon'] = i
+ i += 1
+ _labels['Line'] = i
+ return _labels
+
+
+ def set_data(self, list=None):
+ """
+ """
+ pass
+
+ def _reset(self):
+ """
+ Resets internal data and graph
+ """
+ self.graph.reset()
+ self.plots = {}
+
+ def _OnReSize(self, event):
+ """
+ On response of the resize of a panel, set axes_visiable False
+ """
+ # It was found that wx >= 2.9.3 sends an event even if no size changed.
+ # So manually recode the size (=x_size) and compare here.
+ if self.x_size != None:
+ if self.x_size == self.GetSize():
+ self.resizing = False
+ self.canvas.set_resizing(self.resizing)
+ return
+ self.x_size = self.GetSize()
+
+ # Ready for another event
+ # Do not remove this Skip. Otherwise it will get runtime error on wx>=2.9.
+ event.Skip()
+ # set the resizing flag
+ self.resizing = True
+ self.canvas.set_resizing(self.resizing)
+ self.parent.set_schedule(True)
+ pos_x, pos_y = self.GetPositionTuple()
+ if pos_x != 0 and pos_y != 0:
+ self.size, _ = self.GetClientSizeTuple()
+
+ def set_resizing(self, resizing=False):
+ """
+ Set the resizing (True/False)
+ """
+ self.resizing = resizing
+ #self.canvas.set_resizing(resizing)
+
+ def schedule_full_draw(self, func='append'):
+ """
+ Put self in schedule to full redraw list
+ """
+ # append/del this panel in the schedule list
+ self.parent.set_schedule_full_draw(self, func)
+
+
+ def remove_data_by_id(self, id):
+ """'
+ remove data from plot
+ """
+ if id in self.plots.keys():
+ data = self.plots[id]
+ self.graph.delete(data)
+ data_manager = self._manager.parent.get_data_manager()
+ data_list, theory_list = data_manager.get_by_id(id_list=[id])
+
+ if id in data_list.keys():
+ data = data_list[id]
+ if id in theory_list.keys():
+ data = theory_list[id]
+
+ del self.plots[id]
+ self.graph.render(self)
+ self.subplot.figure.canvas.draw_idle()
+ if len(self.graph.plottables) == 0:
+ #onRemove: graph is empty must be the panel must be destroyed
+ self.parent.delete_panel(self.uid)
+
+ def plot_data(self, data):
+ """
+ Data is ready to be displayed
+
+ :param event: data event
+ """
+ if data.id in self.plots.keys():
+ #replace
+ self.graph.replace(data)
+ self.plots[data.id] = data
+ else:
+ self.plots[data.id] = data
+ self.graph.add(self.plots[data.id])
+
+ ## Set the view scale for all plots
+ self._onEVT_FUNC_PROPERTY()
+ ## render the graph<=No need this done in canvas
+ #self.graph.render(self)
+ #self.subplot.figure.canvas.draw_idle()
+
+ def draw_plot(self):
+ """
+ Draw plot
+ """
+ self.draw()
+
+
+
+ def onLeftDown(self,event):
+ """
+ left button down and ready to drag
+ Display the position of the mouse on the statusbar
+ """
+ PlotPanel.onLeftDown(self, event)
+ ax = event.inaxes
+ if ax != None:
+ position = "x: %8.3g y: %8.3g" % (event.xdata, event.ydata)
+ wx.PostEvent(self.parent, StatusEvent(status=position))
+ # unfocus all
+ self.parent.set_plot_unfocus()
+ #post nd event to notify guiframe that this panel is on focus
+ wx.PostEvent(self.parent, PanelOnFocusEvent(panel=self))
+
+
+ def _ontoggle_hide_error(self, event):
+ """
+ Toggle error display to hide or show
+ """
+
+ selected_plot = self.plots[self.graph.selected_plottable]
+ if self.hide_menu.GetText() == "Hide Error":
+ selected_plot.hide_error = True
+ else:
+ selected_plot.hide_error = False
+ ## increment graph color
+ self.graph.render(self)
+ self.subplot.figure.canvas.draw_idle()
+
+ def _onRemove(self, event):
+ """
+ Remove a plottable from the graph and render the graph
+
+ :param event: Menu event
+
+ """
+ ## Check if there is a selected graph to remove
+ if self.graph.selected_plottable in self.plots.keys():
+ selected_plot = self.plots[self.graph.selected_plottable]
+ id = self.graph.selected_plottable
+ self.remove_data_by_id(id)
+
+ def onContextMenu(self, event):
+ """
+ 1D plot context menu
+
+ :param event: wx context event
+
+ """
+ self._slicerpop = PanelMenu()
+ self._slicerpop.set_plots(self.plots)
+ self._slicerpop.set_graph(self.graph)
+ # Various plot options
+ id = wx.NewId()
+ self._slicerpop.Append(id, '&Save Image', 'Save image as PNG')
+ wx.EVT_MENU(self, id, self.onSaveImage)
+ id = wx.NewId()
+ self._slicerpop.Append(id, '&Print Image', 'Print image ')
+ wx.EVT_MENU(self, id, self.onPrint)
+ id = wx.NewId()
+ self._slicerpop.Append(id, '&Print Preview', 'Print preview')
+ wx.EVT_MENU(self, id, self.onPrinterPreview)
+
+ id = wx.NewId()
+ self._slicerpop.Append(id, '&Copy to Clipboard', 'Copy to the clipboard')
+ wx.EVT_MENU(self, id, self.OnCopyFigureMenu)
+
+ self._slicerpop.AppendSeparator()
+
+ #add menu of other plugins
+ item_list = self.parent.get_context_menu(self)
+
+ if (not item_list == None) and (not len(item_list) == 0):
+ for item in item_list:
+ try:
+ id = wx.NewId()
+ self._slicerpop.Append(id, item[0], item[1])
+ wx.EVT_MENU(self, id, item[2])
+ except:
+ msg = "ModelPanel1D.onContextMenu: "
+ msg += "bad menu item %s" % sys.exc_value
+ wx.PostEvent(self.parent, StatusEvent(status=msg))
+ pass
+ self._slicerpop.AppendSeparator()
+ #id = wx.NewId()
+ #self._slicerpop.Append(id, '&Print image', 'Print image')
+ if self.graph.selected_plottable in self.plots:
+ plot = self.plots[self.graph.selected_plottable]
+
+ id = wx.NewId()
+ name = plot.name
+ self._slicerpop.Append(id, "&Save Points as a File")
+ self._slicerpop.AppendSeparator()
+ if plot.name != 'SLD':
+ wx.EVT_MENU(self, id, self._onSave)
+ id = wx.NewId()
+ self._slicerpop.Append(id, '&Linear Fit')
+ wx.EVT_MENU(self, id, self.onFitting)
+ self._slicerpop.AppendSeparator()
+
+ id = wx.NewId()
+ self._slicerpop.Append(id, "Remove %s Curve" % name)
+ wx.EVT_MENU(self, id, self._onRemove)
+ if not plot.is_data:
+ id = wx.NewId()
+ self._slicerpop.Append(id, '&Freeze', 'Freeze')
+ wx.EVT_MENU(self, id, self.onFreeze)
+ symbol_menu = wx.Menu()
+ for label in self._symbol_labels:
+ id = wx.NewId()
+ symbol_menu.Append(id, str(label), str(label))
+ wx.EVT_MENU(self, id, self.onChangeSymbol)
+ id = wx.NewId()
+ self._slicerpop.AppendMenu(id,'&Modify Symbol', symbol_menu)
+ self._slicerpop.AppendSeparator()
+
+ id = wx.NewId()
+ self.hide_menu = self._slicerpop.Append(id, "Hide Error")
+
+ if plot.dy is not None and plot.dy != []:
+ if plot.hide_error :
+ self.hide_menu.SetText('Show Error')
+ else:
+ self.hide_menu.SetText('Hide Error')
+ else:
+ self.hide_menu.Enable(False)
+ wx.EVT_MENU(self, id, self._ontoggle_hide_error)
+
+ self._slicerpop.AppendSeparator()
+ # Option to hide
+ #TODO: implement functionality to hide a plottable (legend click)
+
+
+ id = wx.NewId()
+ self._slicerpop.Append(id, '&Change scale')
+ wx.EVT_MENU(self, id, self._onProperties)
+ id = wx.NewId()
+ self._slicerpop.Append(id, '&Reset Graph')
+ wx.EVT_MENU(self, id, self.onResetGraph)
+ pos = event.GetPosition()
+ pos = self.ScreenToClient(pos)
+ self.PopupMenu(self._slicerpop, pos)
+
+ def onFreeze(self, event):
+ """
+ """
+ plot = self.plots[self.graph.selected_plottable]
+ self.parent.onfreeze([plot.id])
+
+ def onChangeSymbol(self, event):
+ """
+ """
+ menu = event.GetEventObject()
+ id = event.GetId()
+ label = menu.GetLabel(id)
+ selected_plot = self.plots[self.graph.selected_plottable]
+ selected_plot.symbol = self._symbol_labels[label]
+ ## Set the view scale for all plots
+ self._onEVT_FUNC_PROPERTY()
+ ## render the graph
+ #self.graph.render(self)
+ #self.subplot.figure.canvas.draw_idle()
+
+ def _onsaveTXT(self, path):
+ """
+ Save file as txt
+
+ :TODO: Refactor and remove this method. See TODO in _onSave.
+
+ """
+ data = self.plots[self.graph.selected_plottable]
+
+ if not path == None:
+ out = open(path, 'w')
+ has_errors = True
+ if data.dy == None or data.dy == []:
+ has_errors = False
+ # Sanity check
+ if has_errors:
+ try:
+ if len(data.y) != len(data.dy):
+ has_errors = False
+ except:
+ has_errors = False
+ if has_errors:
+ if data.dx != None:
+ out.write(" \n")
+ else:
+ out.write(" \n")
+ else:
+ out.write(" \n")
+
+ for i in range(len(data.x)):
+ if has_errors:
+ if data.dx != None:
+ out.write("%g %g %g %g\n" % (data.x[i],
+ data.y[i],
+ data.dy[i],
+ data.dx[i]))
+ else:
+ out.write("%g %g %g\n" % (data.x[i],
+ data.y[i],
+ data.dy[i]))
+ else:
+ out.write("%g %g\n" % (data.x[i],
+ data.y[i]))
+ out.close()
+ try:
+ self._default_save_location = os.path.dirname(path)
+ except:
+ pass
+
+ def _onSave(self, evt):
+ """
+ Save a data set to a text file
+
+ :param evt: Menu event
+
+ """
+
+ path = None
+ wildcard = "Text files (*.txt)|*.txt|"\
+ "CanSAS 1D files(*.xml)|*.xml"
+ dlg = wx.FileDialog(self, "Choose a file",
+ self._default_save_location,
+ "", wildcard , wx.SAVE)
+
+ if dlg.ShowModal() == wx.ID_OK:
+ path = dlg.GetPath()
+ # ext_num = 0 for .txt, ext_num = 1 for .xml
+ # This is MAC Fix
+ ext_num = dlg.GetFilterIndex()
+ if ext_num == 0:
+ format = '.txt'
+ else:
+ format = '.xml'
+ path = os.path.splitext(path)[0] + format
+ mypath = os.path.basename(path)
+
+ #TODO: This is bad design. The DataLoader is designed
+ #to recognize extensions.
+ # It should be a simple matter of calling the .
+ #save(file, data, '.xml') method
+ # of the DataLoader.loader.Loader class.
+ from DataLoader.loader import Loader
+ #Instantiate a loader
+ loader = Loader()
+ data = self.plots[self.graph.selected_plottable]
+ format = ".txt"
+ if os.path.splitext(mypath)[1].lower() == format:
+ # Make sure the ext included in the file name
+ # especially on MAC
+ fName = os.path.splitext(path)[0] + format
+ self._onsaveTXT(fName)
+ format = ".xml"
+ if os.path.splitext(mypath)[1].lower() == format:
+ # Make sure the ext included in the file name
+ # especially on MAC
+ fName = os.path.splitext(path)[0] + format
+ loader.save(fName, data, format)
+ try:
+ self._default_save_location = os.path.dirname(path)
+ except:
+ pass
+ dlg.Destroy()
+
+ def _add_more_tool(self):
+ """
+ Add refresh button in the tool bar
+ """
+ if self.parent.__class__.__name__ != 'ViewerFrame':
+ return
+ self.toolbar.AddSeparator()
+ id_delete = wx.NewId()
+ delete = wx.ArtProvider.GetBitmap(wx.ART_DELETE, wx.ART_TOOLBAR)
+ self.toolbar.AddSimpleTool(id_delete, delete,
+ 'Delete', 'permanently Delete')
+
+ self.toolbar.Realize()
+ wx.EVT_TOOL(self, id_delete, self._on_delete)
+
+ def _on_delete(self, event):
+ """
+ Refreshes the plotpanel on refresh tollbar button
+ """
+
+ if self.parent is not None:
+ wx.PostEvent(self.parent,
+ NewPlotEvent(group_id=self.group_id,
+ action="delete"))
+
Index: test/test_rename_guiframe/local_perspectives/plotting/Plotter2D.py
===================================================================
--- test/test_rename_guiframe/local_perspectives/plotting/Plotter2D.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/local_perspectives/plotting/Plotter2D.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,627 @@
+
+################################################################################
+#This software was developed by the University of Tennessee as part of the
+#Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
+#project funded by the US National Science Foundation.
+#
+#See the license text in license.txt
+#
+#copyright 2008, University of Tennessee
+################################################################################
+
+
+import wx
+import sys
+import os
+import math
+import numpy
+import pylab
+import danse.common.plottools
+from danse.common.plottools.PlotPanel import PlotPanel
+from danse.common.plottools.plottables import Graph
+from sans.guiframe.events import EVT_NEW_PLOT
+from sans.guiframe.events import EVT_SLICER_PARS
+from sans.guiframe.events import StatusEvent
+from sans.guiframe.events import NewPlotEvent
+from sans.guiframe.events import PanelOnFocusEvent
+from sans.guiframe.events import SlicerEvent
+from sans.guiframe.utils import PanelMenu
+from binder import BindArtist
+from Plotter1D import ModelPanel1D
+from danse.common.plottools.toolbar import NavigationToolBar
+from sans.guiframe.dataFitting import Data1D
+(InternalEvent, EVT_INTERNAL) = wx.lib.newevent.NewEvent()
+
+DEFAULT_QMAX = 0.05
+DEFAULT_QSTEP = 0.001
+DEFAULT_BEAM = 0.005
+BIN_WIDTH = 1.0
+
+
+class NavigationToolBar2D(NavigationToolBar):
+ """
+ """
+ def __init__(self, canvas, parent=None):
+ NavigationToolBar.__init__(self, canvas=canvas, parent=parent)
+
+ def delete_option(self):
+ """
+ remove default toolbar item
+ """
+ #delete reset button
+ self.DeleteToolByPos(0)
+ #delete dragging
+ self.DeleteToolByPos(2)
+ #delete unwanted button that configures subplot parameters
+ self.DeleteToolByPos(4)
+
+ def add_option(self):
+ """
+ add item to the toolbar
+ """
+ #add print button
+ id_print = wx.NewId()
+ print_bmp = wx.ArtProvider.GetBitmap(wx.ART_PRINT, wx.ART_TOOLBAR)
+ self.AddSimpleTool(id_print, print_bmp,
+ 'Print', 'Activate printing')
+ wx.EVT_TOOL(self, id_print, self.on_print)
+
+
+class ModelPanel2D(ModelPanel1D):
+ """
+ Plot panel for use with the GUI manager
+ """
+
+ ## Internal name for the AUI manager
+ window_name = "plotpanel"
+ ## Title to appear on top of the window
+ window_caption = "Plot Panel"
+ ## Flag to tell the GUI manager that this panel is not
+ # tied to any perspective
+ ALWAYS_ON = True
+ ## Group ID
+ group_id = None
+
+
+ def __init__(self, parent, id=-1, data2d=None, color = None,
+ dpi=None, style=wx.NO_FULL_REPAINT_ON_RESIZE, **kwargs):
+ """
+ Initialize the panel
+ """
+ ModelPanel1D.__init__(self, parent, id=id, style=style, **kwargs)
+
+ ## Reference to the parent window
+ self.parent = parent
+ ## Dictionary containing Plottables
+ self.plots = {}
+ ## Save reference of the current plotted
+ self.data2D = data2d
+ ## Unique ID (from gui_manager)
+ self.uid = None
+ ## Action IDs for internal call-backs
+ self.action_ids = {}
+ ## Create Artist and bind it
+ self.connect = BindArtist(self.subplot.figure)
+ ## Beam stop
+ self.beamstop_radius = DEFAULT_BEAM
+ ## to set the order of lines drawn first.
+ self.slicer_z = 5
+ ## Reference to the current slicer
+ self.slicer = None
+ ## event to send slicer info
+ self.Bind(EVT_INTERNAL, self._onEVT_INTERNAL)
+
+ self.axes_frozen = False
+ ## panel that contains result from slicer motion (ex: Boxsum info)
+ self.panel_slicer = None
+ ## Graph
+ self.graph = Graph()
+ self.graph.xaxis("\\rm{Q}", 'A^{-1}')
+ self.graph.yaxis("\\rm{Intensity} ", "cm^{-1}")
+ self.graph.render(self)
+ ## store default value of zmin and zmax
+ self.default_zmin_ctl = self.zmin_2D
+ self.default_zmax_ctl = self.zmax_2D
+
+ def onLeftDown(self, event):
+ """
+ left button down and ready to drag
+
+ """
+ # Check that the LEFT button was pressed
+ if event.button == 1:
+ self.leftdown = True
+ ax = event.inaxes
+ if ax != None:
+ self.xInit, self.yInit = event.xdata, event.ydata
+ self.plottable_selected(self.data2D.id)
+
+ self._manager.set_panel_on_focus(self)
+ wx.PostEvent(self.parent, PanelOnFocusEvent(panel=self))
+
+ def add_toolbar(self):
+ """
+ add toolbar
+ """
+ self.enable_toolbar = True
+ self.toolbar = NavigationToolBar2D(parent=self, canvas=self.canvas)
+ self.toolbar.Realize()
+ # On Windows platform, default window size is incorrect, so set
+ # toolbar width to figure width.
+ tw, th = self.toolbar.GetSizeTuple()
+ fw, fh = self.canvas.GetSizeTuple()
+ self.toolbar.SetSize(wx.Size(fw, th))
+ self.sizer.Add(self.toolbar, 0, wx.LEFT|wx.EXPAND)
+ # update the axes menu on the toolbar
+ self.toolbar.update()
+
+ def plot_data(self, data):
+ """
+ Data is ready to be displayed
+
+ :TODO: this name should be changed to something more appropriate
+ Don't forget that changing this name will mean changing code
+ in plotting.py
+
+ :param event: data event
+ """
+ ## Update self.data2d with the current plot
+ self.data2D = data
+ if data.id in self.plots.keys():
+ #replace
+ self.graph.replace(data)
+ self.plots[data.id] = data
+ else:
+ self.plots[data.id] = data
+ self.graph.add(self.plots[data.id])
+ # update qmax with the new xmax of data plotted
+ self.qmax = data.xmax
+
+ self.slicer = None
+ # Check axis labels
+ #TODO: Should re-factor this
+ ## render the graph with its new content
+
+ #data2D: put 'Pixel (Number)' for axis title and unit in case of having no detector info and none in _units
+ if len(self.data2D.detector) < 1:
+ if len(data._xunit) < 1 and len(data._yunit) < 1:
+ data._xaxis = '\\rm{x}'
+ data._yaxis = '\\rm{y}'
+ data._xunit = 'pixel'
+ data._yunit = 'pixel'
+ self.graph.xaxis(data._xaxis, data._xunit)
+ self.graph.yaxis(data._yaxis, data._yunit)
+ self.graph.title(self.data2D.name)
+ self.graph.render(self)
+ self.draw_plot()
+ #self.subplot.figure.canvas.draw_idle()
+ ## store default value of zmin and zmax
+ self.default_zmin_ctl = self.zmin_2D
+ self.default_zmax_ctl = self.zmax_2D
+
+ def onContextMenu(self, event):
+ """
+ 2D plot context menu
+
+ :param event: wx context event
+
+ """
+ slicerpop = PanelMenu()
+ slicerpop.set_plots(self.plots)
+ slicerpop.set_graph(self.graph)
+
+ id = wx.NewId()
+ slicerpop.Append(id, '&Save Image')
+ wx.EVT_MENU(self, id, self.onSaveImage)
+
+ id = wx.NewId()
+ slicerpop.Append(id,'&Print Image', 'Print image')
+ wx.EVT_MENU(self, id, self.onPrint)
+
+ id = wx.NewId()
+ slicerpop.Append(id,'&Print Preview', 'Print preview')
+ wx.EVT_MENU(self, id, self.onPrinterPreview)
+
+ id = wx.NewId()
+ slicerpop.Append(id, '&Copy to Clipboard', 'Copy to the clipboard')
+ wx.EVT_MENU(self, id, self.OnCopyFigureMenu)
+ slicerpop.AppendSeparator()
+ # saving data
+ plot = self.data2D
+ id = wx.NewId()
+ name = plot.name
+ slicerpop.Append(id, "&Save as a file (DAT)" )
+ self.action_ids[str(id)] = plot
+ wx.EVT_MENU(self, id, self._onSave)
+
+ slicerpop.AppendSeparator()
+ if len(self.data2D.detector) == 1:
+
+ item_list = self.parent.get_context_menu(self)
+ if (not item_list == None) and (not len(item_list) == 0) and\
+ self.data2D.name.split(" ")[0] != 'Residuals':
+ # The line above; Not for trunk
+ for item in item_list:
+ try:
+ id = wx.NewId()
+ slicerpop.Append(id, item[0], item[1])
+ wx.EVT_MENU(self, id, item[2])
+ except:
+ msg = "ModelPanel1D.onContextMenu: "
+ msg += "bad menu item %s"%sys.exc_value
+ wx.PostEvent(self.parent, StatusEvent(status=msg))
+ pass
+ slicerpop.AppendSeparator()
+
+ id = wx.NewId()
+ slicerpop.Append(id, '&Perform circular average')
+ wx.EVT_MENU(self, id, self.onCircular) \
+ # For Masked Data
+ if not plot.mask.all():
+ id = wx.NewId()
+ slicerpop.Append(id, '&Masked circular average')
+ wx.EVT_MENU(self, id, self.onMaskedCircular)
+ id = wx.NewId()
+ slicerpop.Append(id, '&Sector [Q view]')
+ wx.EVT_MENU(self, id, self.onSectorQ)
+ id = wx.NewId()
+ slicerpop.Append(id, '&Annulus [Phi view ]')
+ wx.EVT_MENU(self, id, self.onSectorPhi)
+ id = wx.NewId()
+ slicerpop.Append(id, '&Box Sum')
+ wx.EVT_MENU(self, id, self.onBoxSum)
+ id = wx.NewId()
+ slicerpop.Append(id, '&Box averaging in Qx')
+ wx.EVT_MENU(self, id, self.onBoxavgX)
+ id = wx.NewId()
+ slicerpop.Append(id, '&Box averaging in Qy')
+ wx.EVT_MENU(self, id, self.onBoxavgY)
+ if self.slicer != None:
+ id = wx.NewId()
+ slicerpop.Append(id, '&Clear slicer')
+ wx.EVT_MENU(self, id, self.onClearSlicer)
+ if self.slicer.__class__.__name__ != "BoxSum":
+ id = wx.NewId()
+ slicerpop.Append(id, '&Edit Slicer Parameters')
+ wx.EVT_MENU(self, id, self._onEditSlicer)
+ slicerpop.AppendSeparator()
+ id = wx.NewId()
+ slicerpop.Append(id, '&2D Color Map')
+ wx.EVT_MENU(self, id, self._onEditDetector)
+ id = wx.NewId()
+ slicerpop.Append(id, '&Toggle Linear/Log scale')
+ wx.EVT_MENU(self, id, self._onToggleScale)
+ pos = event.GetPosition()
+ pos = self.ScreenToClient(pos)
+ self.PopupMenu(slicerpop, pos)
+
+ def _onEditDetector(self, event):
+ """
+ Allow to view and edits detector parameters
+
+ :param event: wx.menu event
+
+ """
+ import detector_dialog
+ dialog = detector_dialog.DetectorDialog(self, -1,base=self.parent,
+ reset_zmin_ctl =self.default_zmin_ctl,
+ reset_zmax_ctl = self.default_zmax_ctl,cmap=self.cmap)
+ ## info of current detector and data2D
+ xnpts = len(self.data2D.x_bins)
+ ynpts = len(self.data2D.y_bins)
+ xmax = max(self.data2D.xmin, self.data2D.xmax)
+ ymax = max(self.data2D.ymin, self.data2D.ymax)
+ qmax = math.sqrt(math.pow(xmax, 2) + math.pow(ymax, 2))
+ beam = self.data2D.xmin
+ ## set dialog window content
+ dialog.setContent(xnpts=xnpts,ynpts=ynpts,qmax=qmax,
+ beam=self.data2D.xmin,
+ zmin = self.zmin_2D,
+ zmax = self.zmax_2D)
+ if dialog.ShowModal() == wx.ID_OK:
+ evt = dialog.getContent()
+ self.zmin_2D = evt.zmin
+ self.zmax_2D = evt.zmax
+ self.cmap = evt.cmap
+ dialog.Destroy()
+ ## Redraw the current image
+ self.image(data=self.data2D.data,
+ qx_data=self.data2D.qx_data,
+ qy_data=self.data2D.qy_data,
+ xmin= self.data2D.xmin,
+ xmax= self.data2D.xmax,
+ ymin= self.data2D.ymin,
+ ymax= self.data2D.ymax,
+ zmin= self.zmin_2D,
+ zmax= self.zmax_2D,
+ cmap= self.cmap,
+ color=0, symbol=0, label=self.data2D.name)
+ self.subplot.figure.canvas.draw_idle()
+
+ def freeze_axes(self):
+ """
+ """
+ self.axes_frozen = True
+
+ def thaw_axes(self):
+ """
+ """
+ self.axes_frozen = False
+
+ def onMouseMotion(self,event):
+ """
+ """
+ pass
+
+ def onWheel(self, event):
+ """
+ """
+ pass
+
+ def update(self, draw=True):
+ """
+ Respond to changes in the model by recalculating the
+ profiles and resetting the widgets.
+ """
+ self.draw_plot()
+
+ def _getEmptySlicerEvent(self):
+ """
+ create an empty slicervent
+ """
+ return SlicerEvent(type=None, params=None, obj_class=None)
+
+ def _onEVT_INTERNAL(self, event):
+ """
+ Draw the slicer
+
+ :param event: wx.lib.newevent (SlicerEvent) containing slicer
+ parameter
+
+ """
+ self._setSlicer(event.slicer)
+
+ def _setSlicer(self, slicer):
+ """
+ Clear the previous slicer and create a new one.Post an internal
+ event.
+
+ :param slicer: slicer class to create
+
+ """
+ ## Clear current slicer
+ if not self.slicer == None:
+ self.slicer.clear()
+ ## Create a new slicer
+ self.slicer_z += 1
+ self.slicer = slicer(self, self.subplot, zorder=self.slicer_z)
+ self.subplot.set_ylim(self.data2D.ymin, self.data2D.ymax)
+ self.subplot.set_xlim(self.data2D.xmin, self.data2D.xmax)
+ ## Draw slicer
+ self.update()
+ self.slicer.update()
+ msg = "Plotter2D._setSlicer %s"%self.slicer.__class__.__name__
+ wx.PostEvent(self.parent, StatusEvent(status=msg))
+ # Post slicer event
+ event = self._getEmptySlicerEvent()
+ event.type = self.slicer.__class__.__name__
+ event.obj_class = self.slicer.__class__
+ event.params = self.slicer.get_params()
+ wx.PostEvent(self, event)
+
+ def onMaskedCircular(self, event):
+ """
+ perform circular averaging on Data2D with mask if it exists
+
+ :param event: wx.menu event
+
+ """
+ self.onCircular(event, True)
+
+ def onCircular(self, event, ismask=False):
+ """
+ perform circular averaging on Data2D
+
+ :param event: wx.menu event
+
+ """
+ # Find the best number of bins
+ npt = math.sqrt(len(self.data2D.data[numpy.isfinite(self.data2D.data)]))
+ npt = math.floor(npt)
+ from DataLoader.manipulations import CircularAverage
+ ## compute the maximum radius of data2D
+ self.qmax = max(math.fabs(self.data2D.xmax),
+ math.fabs(self.data2D.xmin))
+ self.ymax = max(math.fabs(self.data2D.ymax),
+ math.fabs(self.data2D.ymin))
+ self.radius = math.sqrt(math.pow(self.qmax, 2)+ math.pow(self.ymax, 2))
+ ##Compute beam width
+ bin_width = (self.qmax + self.qmax)/npt
+ ## Create data1D circular average of data2D
+ Circle = CircularAverage(r_min=0, r_max=self.radius,
+ bin_width=bin_width)
+ circ = Circle(self.data2D, ismask=ismask)
+ from sans.guiframe.dataFitting import Data1D
+ if hasattr(circ, "dxl"):
+ dxl = circ.dxl
+ else:
+ dxl = None
+ if hasattr(circ, "dxw"):
+ dxw = circ.dxw
+ else:
+ dxw = None
+
+ new_plot = Data1D(x=circ.x, y=circ.y, dy=circ.dy, dx=circ.dx)
+ new_plot.dxl = dxl
+ new_plot.dxw = dxw
+ new_plot.name = "Circ avg " + self.data2D.name
+ new_plot.source = self.data2D.source
+ #new_plot.info = self.data2D.info
+ new_plot.interactive = True
+ new_plot.detector = self.data2D.detector
+
+ ## If the data file does not tell us what the axes are, just assume...
+ new_plot.xaxis("\\rm{Q}", "A^{-1}")
+ if hasattr(self.data2D, "scale") and \
+ self.data2D.scale == 'linear':
+ new_plot.ytransform = 'y'
+ new_plot.yaxis("\\rm{Residuals} ", "normalized")
+ else:
+ new_plot.yaxis("\\rm{Intensity} ", "cm^{-1}")
+
+ new_plot.group_id = "Circ avg " + self.data2D.name
+ new_plot.id = "Circ avg " + self.data2D.name
+ new_plot.is_data = True
+ wx.PostEvent(self.parent,
+ NewPlotEvent(plot=new_plot, title=new_plot.name))
+
+ def _onEditSlicer(self, event):
+ """
+ Is available only when a slicer is drawn.Create a dialog
+ window where the user can enter value to reset slicer
+ parameters.
+
+ :param event: wx.menu event
+
+ """
+ if self.slicer != None:
+ from SlicerParameters import SlicerParameterPanel
+ dialog = SlicerParameterPanel(self, -1, "Slicer Parameters")
+ dialog.set_slicer(self.slicer.__class__.__name__,
+ self.slicer.get_params())
+ if dialog.ShowModal() == wx.ID_OK:
+ dialog.Destroy()
+
+ def onSectorQ(self, event):
+ """
+ Perform sector averaging on Q and draw sector slicer
+ """
+ from SectorSlicer import SectorInteractor
+ self.onClearSlicer(event)
+ wx.PostEvent(self, InternalEvent(slicer=SectorInteractor))
+
+ def onSectorPhi(self, event):
+ """
+ Perform sector averaging on Phi and draw annulus slicer
+ """
+ from AnnulusSlicer import AnnulusInteractor
+ self.onClearSlicer(event)
+ wx.PostEvent(self, InternalEvent(slicer=AnnulusInteractor))
+
+ def onBoxSum(self, event):
+ """
+ """
+ from boxSum import BoxSum
+ self.onClearSlicer(event)
+ self.slicer_z += 1
+ self.slicer = BoxSum(self, self.subplot, zorder=self.slicer_z)
+ self.subplot.set_ylim(self.data2D.ymin, self.data2D.ymax)
+ self.subplot.set_xlim(self.data2D.xmin, self.data2D.xmax)
+ self.update()
+ self.slicer.update()
+ ## Value used to initially set the slicer panel
+ type = self.slicer.__class__.__name__
+ params = self.slicer.get_params()
+ ## Create a new panel to display results of summation of Data2D
+ from slicerpanel import SlicerPanel
+ new_panel = SlicerPanel(parent=self.parent, id=-1,
+ base=self, type=type,
+ params=params, style=wx.RAISED_BORDER)
+
+ new_panel.window_caption = self.slicer.__class__.__name__ + " " + \
+ str(self.data2D.name)
+ new_panel.window_name = self.slicer.__class__.__name__+ " " + \
+ str(self.data2D.name)
+ ## Store a reference of the new created panel
+ self.panel_slicer = new_panel
+ ## save the window_caption of the new panel in the current slicer
+ self.slicer.set_panel_name(name=new_panel.window_caption)
+ ## post slicer panel to guiframe to display it
+ from sans.guiframe.events import SlicerPanelEvent
+ wx.PostEvent(self.parent, SlicerPanelEvent(panel=self.panel_slicer,
+ main_panel=self))
+
+ def onBoxavgX(self,event):
+ """
+ Perform 2D data averaging on Qx
+ Create a new slicer .
+
+ :param event: wx.menu event
+ """
+ from boxSlicer import BoxInteractorX
+ self.onClearSlicer(event)
+ wx.PostEvent(self, InternalEvent(slicer=BoxInteractorX))
+
+ def onBoxavgY(self,event):
+ """
+ Perform 2D data averaging on Qy
+ Create a new slicer .
+
+ :param event: wx.menu event
+
+ """
+ from boxSlicer import BoxInteractorY
+ self.onClearSlicer(event)
+ wx.PostEvent(self, InternalEvent(slicer=BoxInteractorY))
+
+ def onClearSlicer(self, event):
+ """
+ Clear the slicer on the plot
+ """
+ if not self.slicer == None:
+ self.slicer.clear()
+ self.subplot.figure.canvas.draw()
+ self.slicer = None
+ # Post slicer None event
+ event = self._getEmptySlicerEvent()
+ wx.PostEvent(self, event)
+
+ def _onSave(self, evt):
+ """
+ Save a data set to a dat(text) file
+
+ :param evt: Menu event
+
+ """
+ id = str(evt.GetId())
+ if id in self.action_ids:
+
+ path = None
+ wildcard = "IGOR/DAT 2D file in Q_map (*.dat)|*.DAT"
+ dlg = wx.FileDialog(self, "Choose a file",
+ self._default_save_location,
+ "", wildcard , wx.SAVE)
+
+ if dlg.ShowModal() == wx.ID_OK:
+ path = dlg.GetPath()
+ # ext_num = 0 for .txt, ext_num = 1 for .xml
+ # This is MAC Fix
+ ext_num = dlg.GetFilterIndex()
+ if ext_num == 0:
+ format = '.dat'
+ else:
+ format = ''
+ path = os.path.splitext(path)[0] + format
+ mypath = os.path.basename(path)
+
+ #TODO: This is bad design. The DataLoader is designed
+ #to recognize extensions.
+ # It should be a simple matter of calling the .
+ #save(file, data, '.xml') method
+ # of the DataLoader.loader.Loader class.
+ from DataLoader.loader import Loader
+ #Instantiate a loader
+ loader = Loader()
+ data = self.data2D
+
+ format = ".dat"
+ if os.path.splitext(mypath)[1].lower() == format:
+ # Make sure the ext included in the file name
+ # especially on MAC
+ fName = os.path.splitext(path)[0] + format
+ loader.save(fName, data, format)
+ try:
+ self._default_save_location = os.path.dirname(path)
+ except:
+ pass
+ dlg.Destroy()
Index: test/test_rename_guiframe/local_perspectives/plotting/SectorSlicer.py
===================================================================
--- test/test_rename_guiframe/local_perspectives/plotting/SectorSlicer.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/local_perspectives/plotting/SectorSlicer.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,626 @@
+
+import math
+import wx
+#from copy import deepcopy
+from BaseInteractor import _BaseInteractor
+from sans.guiframe.events import NewPlotEvent
+from sans.guiframe.events import StatusEvent
+from sans.guiframe.events import SlicerParameterEvent
+from sans.guiframe.events import EVT_SLICER_PARS
+from sans.guiframe.dataFitting import Data1D
+
+
+class SectorInteractor(_BaseInteractor):
+ """
+ Draw a sector slicer.Allow to performQ averaging on data 2D
+ """
+ def __init__(self, base, axes, color='black', zorder=3):
+
+ _BaseInteractor.__init__(self, base, axes, color=color)
+ ## Class initialization
+ self.markers = []
+ self.axes = axes
+ ## connect the plot to event
+ self.connect = self.base.connect
+
+ ## compute qmax limit to reset the graph
+ x = math.pow(max(self.base.data2D.xmax,
+ math.fabs(self.base.data2D.xmin)), 2)
+ y = math.pow(max(self.base.data2D.ymax,
+ math.fabs(self.base.data2D.ymin)), 2)
+ self.qmax = math.sqrt(x + y)
+ ## Number of points on the plot
+ self.nbins = 20
+ ## Angle of the middle line
+ self.theta2 = math.pi/3
+ ## Absolute value of the Angle between the middle line and any side line
+ self.phi = math.pi/12
+ ## Middle line
+ self.main_line = LineInteractor(self, self.base.subplot, color='blue',
+ zorder=zorder, r=self.qmax,
+ theta= self.theta2)
+ self.main_line.qmax = self.qmax
+ ## Right Side line
+ self.right_line = SideInteractor(self, self.base.subplot, color='black',
+ zorder=zorder, r=self.qmax,
+ phi=-1*self.phi, theta2=self.theta2)
+ self.right_line.qmax = self.qmax
+ ## Left Side line
+ self.left_line = SideInteractor(self, self.base.subplot, color='black',
+ zorder=zorder, r=self.qmax,
+ phi=self.phi, theta2=self.theta2)
+ self.left_line.qmax = self.qmax
+ ## draw the sector
+ self.update()
+ self._post_data()
+ ## Bind to slice parameter events
+ self.base.Bind(EVT_SLICER_PARS, self._onEVT_SLICER_PARS)
+
+ def _onEVT_SLICER_PARS(self, event):
+ """
+ receive an event containing parameters values to reset the slicer
+
+ :param event: event of type SlicerParameterEvent with params as
+ attribute
+
+ """
+ wx.PostEvent(self.base.parent,
+ StatusEvent(status="SectorSlicer._onEVT_SLICER_PARS"))
+ event.Skip()
+ if event.type == self.__class__.__name__:
+ self.set_params(event.params)
+ self.base.update()
+
+ def set_layer(self, n):
+ """
+ Allow adding plot to the same panel
+
+ :param n: the number of layer
+
+ """
+ self.layernum = n
+ self.update()
+
+ def clear(self):
+ """
+ Clear the slicer and all connected events related to this slicer
+ """
+ self.clear_markers()
+ self.main_line.clear()
+ self.left_line.clear()
+ self.right_line.clear()
+ self.base.connect.clearall()
+ self.base.Unbind(EVT_SLICER_PARS)
+
+ def update(self):
+ """
+ Respond to changes in the model by recalculating the profiles and
+ resetting the widgets.
+ """
+ # Update locations
+ ## Check if the middle line was dragged and
+ #update the picture accordingly
+ if self.main_line.has_move:
+ self.main_line.update()
+ self.right_line.update(delta=-self.left_line.phi/2,
+ mline=self.main_line.theta)
+ self.left_line.update(delta=self.left_line.phi/2,
+ mline=self.main_line.theta)
+ ## Check if the left side has moved and update the slicer accordingly
+ if self.left_line.has_move:
+ self.main_line.update()
+ self.left_line.update(phi=None, delta=None, mline=self.main_line,
+ side=True, left=True)
+ self.right_line.update(phi=self.left_line.phi, delta=None,
+ mline=self.main_line, side=True,
+ left=False, right=True)
+ ## Check if the right side line has moved and
+ #update the slicer accordingly
+ if self.right_line.has_move:
+ self.main_line.update()
+ self.right_line.update(phi=None, delta=None, mline=self.main_line,
+ side=True, left=False, right=True)
+ self.left_line.update(phi=self.right_line.phi, delta=None,
+ mline=self.main_line, side=True, left=False)
+
+ def save(self, ev):
+ """
+ Remember the roughness for this layer and the next so that we
+ can restore on Esc.
+ """
+ self.base.freeze_axes()
+ self.main_line.save(ev)
+ self.right_line.save(ev)
+ self.left_line.save(ev)
+
+ def _post_data(self, nbins=None):
+ """
+ compute sector averaging of data2D into data1D
+
+ :param nbins: the number of point to plot for the average 1D data
+ """
+ ## get the data2D to average
+ data = self.base.data2D
+ # If we have no data, just return
+ if data == None:
+ return
+ ## Averaging
+ from DataLoader.manipulations import SectorQ
+ radius = self.qmax
+ phimin = -self.left_line.phi + self.main_line.theta
+ phimax = self.left_line.phi + self.main_line.theta
+ if nbins == None:
+ nbins = 20
+ sect = SectorQ(r_min=0.0, r_max=radius,
+ phi_min=phimin + math.pi,
+ phi_max=phimax + math.pi, nbins=nbins)
+
+ sector = sect(self.base.data2D)
+ ##Create 1D data resulting from average
+
+ if hasattr(sector, "dxl"):
+ dxl = sector.dxl
+ else:
+ dxl = None
+ if hasattr(sector, "dxw"):
+ dxw = sector.dxw
+ else:
+ dxw = None
+ new_plot = Data1D(x=sector.x, y=sector.y, dy=sector.dy, dx=sector.dx)
+ new_plot.dxl = dxl
+ new_plot.dxw = dxw
+ new_plot.name = "SectorQ" + "(" + self.base.data2D.name + ")"
+ new_plot.source = self.base.data2D.source
+ #new_plot.info=self.base.data2D.info
+ new_plot.interactive = True
+ new_plot.detector = self.base.data2D.detector
+ ## If the data file does not tell us what the axes are, just assume...
+ new_plot.xaxis("\\rm{Q}", "A^{-1}")
+ new_plot.yaxis("\\rm{Intensity}", "cm^{-1}")
+ if hasattr(data, "scale") and data.scale == 'linear' and \
+ self.base.data2D.name.count("Residuals") > 0:
+ new_plot.ytransform = 'y'
+ new_plot.yaxis("\\rm{Residuals} ", "/")
+
+ new_plot.group_id = "SectorQ" + self.base.data2D.name
+ new_plot.id = None
+ new_plot.is_data = True
+
+ wx.PostEvent(self.base.parent, NewPlotEvent(plot=new_plot,
+ title="SectorQ" + self.base.data2D.name))
+
+ def moveend(self, ev):
+ """
+ Called a dragging motion ends.Get slicer event
+ """
+ self.base.thaw_axes()
+ ## Post parameters
+ event = SlicerParameterEvent()
+ event.type = self.__class__.__name__
+ event.params = self.get_params()
+ ## Send slicer paramers to plotter2D
+ wx.PostEvent(self.base, event)
+
+ def restore(self):
+ """
+ Restore the roughness for this layer.
+ """
+ self.main_line.restore()
+ self.left_line.restore()
+ self.right_line.restore()
+
+ def move(self, x, y, ev):
+ """
+ Process move to a new position, making sure that the move is allowed.
+ """
+ pass
+
+ def set_cursor(self, x, y):
+ """
+ """
+ pass
+
+ def get_params(self):
+ """
+ Store a copy of values of parameters of the slicer into a dictionary.
+
+ :return params: the dictionary created
+
+ """
+ params = {}
+ ## Always make sure that the left and the right line are at phi
+ ## angle of the middle line
+ if math.fabs(self.left_line.phi) != math.fabs(self.right_line.phi):
+ msg = "Phi left and phi right are different"
+ msg += " %f, %f" % (self.left_line.phi, self.right_line.phi)
+ raise ValueError, msg
+ params["Phi"] = self.main_line.theta
+ params["Delta_Phi"] = math.fabs(self.left_line.phi)
+ params["nbins"] = self.nbins
+ return params
+
+ def set_params(self, params):
+ """
+ Receive a dictionary and reset the slicer with values contained
+ in the values of the dictionary.
+
+ :param params: a dictionary containing name of slicer parameters and
+ values the user assigned to the slicer.
+ """
+ main = params["Phi"]
+ phi = math.fabs(params["Delta_Phi"])
+ self.nbins = int(params["nbins"])
+ self.main_line.theta = main
+ ## Reset the slicer parameters
+ self.main_line.update()
+ self.right_line.update(phi=phi, delta=None, mline=self.main_line,
+ side=True, right=True)
+ self.left_line.update(phi=phi, delta=None,
+ mline=self.main_line, side=True)
+ ## post the new corresponding data
+ self._post_data(nbins=self.nbins)
+
+ def freeze_axes(self):
+ """
+ """
+ self.base.freeze_axes()
+
+ def thaw_axes(self):
+ """
+ """
+ self.base.thaw_axes()
+
+ def draw(self):
+ """
+ """
+ self.base.draw()
+
+
+class SideInteractor(_BaseInteractor):
+ """
+ Draw an oblique line
+
+ :param phi: the phase between the middle line and one side line
+ :param theta2: the angle between the middle line and x- axis
+
+ """
+ def __init__(self, base, axes, color='black', zorder=5, r=1.0,
+ phi=math.pi/4, theta2= math.pi/3):
+ """
+ """
+ _BaseInteractor.__init__(self, base, axes, color=color)
+ ## Initialize the class
+ self.markers = []
+ self.axes = axes
+ ## compute the value of the angle between the current line and
+ ## the x-axis
+ self.save_theta = theta2 + phi
+ self.theta = theta2 + phi
+ ## the value of the middle line angle with respect to the x-axis
+ self.theta2 = theta2
+ ## Radius to find polar coordinates this line's endpoints
+ self.radius = r
+ ## phi is the phase between the current line and the middle line
+ self.phi = phi
+ ## End points polar coordinates
+ x1 = self.radius * math.cos(self.theta)
+ y1 = self.radius * math.sin(self.theta)
+ x2 = -1 * self.radius * math.cos(self.theta)
+ y2 = -1 * self.radius * math.sin(self.theta)
+ ## defining a new marker
+ try:
+ self.inner_marker = self.axes.plot([x1/2.5], [y1/2.5], linestyle='',
+ marker='s', markersize=10,
+ color=self.color, alpha=0.6,
+ pickradius=5, label="pick",
+ # Prefer this to other lines
+ zorder=zorder, visible=True)[0]
+ except:
+ self.inner_marker = self.axes.plot([x1/2.5],[y1/2.5], linestyle='',
+ marker='s', markersize=10,
+ color=self.color, alpha=0.6,
+ label="pick", visible=True)[0]
+ message = "\nTHIS PROTOTYPE NEEDS THE LATEST"
+ message += " VERSION OF MATPLOTLIB\n Get the SVN version that"
+ message += " is at least as recent as June 1, 2007"
+ owner = self.base.base.parent
+ wx.PostEvent(owner,
+ StatusEvent(status="sectorSlicer: %s" % message))
+
+ ## Defining the current line
+ self.line = self.axes.plot([x1, x2], [y1, y2],
+ linestyle='-', marker='',
+ color=self.color, visible=True)[0]
+ ## Flag to differentiate the left line from the right line motion
+ self.left_moving = False
+ ## Flag to define a motion
+ self.has_move = False
+ ## connecting markers and draw the picture
+ self.connect_markers([self.inner_marker, self.line])
+
+ def set_layer(self, n):
+ """
+ Allow adding plot to the same panel
+
+ :param n: the number of layer
+
+ """
+ self.layernum = n
+ self.update()
+
+ def clear(self):
+ """
+ Clear the slicer and all connected events related to this slicer
+ """
+ self.clear_markers()
+ try:
+ self.line.remove()
+ self.inner_marker.remove()
+ except:
+ # Old version of matplotlib
+ for item in range(len(self.axes.lines)):
+ del self.axes.lines[0]
+
+ def update(self, phi=None, delta=None, mline=None,
+ side=False, left= False, right=False):
+ """
+ Draw oblique line
+
+ :param phi: the phase between the middle line and the current line
+ :param delta: phi/2 applied only when the mline was moved
+
+ """
+ #print "update left or right ", self.has_move
+ self.left_moving = left
+ theta3 = 0
+ if phi != None:
+ self.phi = phi
+ if delta == None:
+ delta = 0
+ if right:
+ self.phi = -1 * math.fabs(self.phi)
+ #delta=-delta
+ else:
+ self.phi = math.fabs(self.phi)
+ if side:
+ self.theta = mline.theta + self.phi
+
+ if mline != None :
+ if delta != 0:
+ self.theta2 = mline + delta
+ else:
+ self.theta2 = mline.theta
+ if delta == 0:
+ theta3 = self.theta + delta
+ else:
+ theta3 = self.theta2 + delta
+ x1 = self.radius * math.cos(theta3)
+ y1 = self.radius * math.sin(theta3)
+ x2 = -1 * self.radius * math.cos(theta3)
+ y2 = -1 * self.radius * math.sin(theta3)
+ self.inner_marker.set(xdata=[x1/2.5], ydata=[y1/2.5])
+ self.line.set(xdata=[x1, x2], ydata=[y1, y2])
+
+ def save(self, ev):
+ """
+ Remember the roughness for this layer and the next so that we
+ can restore on Esc.
+ """
+ self.save_theta = self.theta
+ self.base.freeze_axes()
+
+ def moveend(self, ev):
+ """
+ """
+ self.has_move = False
+ self.base.moveend(ev)
+
+ def restore(self):
+ """
+ Restore the roughness for this layer.
+ """
+ self.theta = self.save_theta
+
+ def move(self, x, y, ev):
+ """
+ Process move to a new position, making sure that the move is allowed.
+ """
+ self.theta = math.atan2(y, x)
+ self.has_move = True
+ #ToDo: Simplify below
+ if not self.left_moving:
+ if self.theta2 - self.theta <= 0 and self.theta2 > 0:
+ self.restore()
+ return
+ elif self.theta2 < 0 and self.theta < 0 and \
+ self.theta-self.theta2 >= 0:
+ self.restore()
+ return
+ elif self.theta2 < 0 and self.theta > 0 and \
+ (self.theta2 + 2 * math.pi - self.theta) >= math.pi/2:
+ #print "my theta", self.theta
+ self.restore()
+ return
+ elif self.theta2 < 0 and self.theta < 0 and \
+ (self.theta2 - self.theta) >= math.pi/2:
+ #print "my theta", self.theta
+ self.restore()
+ return
+ elif self.theta2 > 0 and (self.theta2-self.theta >= math.pi/2 or \
+ (self.theta2-self.theta >= math.pi/2)):
+ #print "self theta encore"
+ self.restore()
+ return
+ else:
+ #print "left move"
+ if self.theta < 0 and (self.theta + math.pi*2-self.theta2) <= 0:
+ self.restore()
+ return
+ elif self.theta2 < 0 and (self.theta-self.theta2) <= 0:
+ self.restore()
+ return
+ elif self.theta > 0 and self.theta-self.theta2 <= 0:
+ #print "my theta", self.theta
+ self.restore()
+ return
+ elif self.theta-self.theta2 >= math.pi/2 or \
+ ((self.theta + math.pi * 2 - self.theta2) >= math.pi/2 and \
+ self.theta < 0 and self.theta2 > 0):
+ #print "self theta encore"
+ self.restore()
+ return
+
+ self.phi = math.fabs(self.theta2 - self.theta)
+ if self.phi > math.pi:
+ self.phi = 2 * math.pi - math.fabs(self.theta2 - self.theta)
+ self.base.base.update()
+
+ def set_cursor(self, x, y):
+ """
+ """
+ self.move(x, y, None)
+ self.update()
+
+ def get_params(self):
+ """
+ """
+ params = {}
+ params["radius"] = self.radius
+ params["theta"] = self.theta
+ return params
+
+ def set_params(self, params):
+ """
+ """
+ x = params["radius"]
+ self.set_cursor(x, self._inner_mouse_y)
+
+
+class LineInteractor(_BaseInteractor):
+ """
+ Select an annulus through a 2D plot
+ """
+ def __init__(self, base, axes, color='black',
+ zorder=5, r=1.0, theta=math.pi/4):
+ """
+ """
+ _BaseInteractor.__init__(self, base, axes, color=color)
+
+ self.markers = []
+ self.axes = axes
+ self.save_theta = theta
+ self.theta= theta
+ self.radius = r
+ self.scale = 10.0
+ # Inner circle
+ x1 = self.radius * math.cos(self.theta)
+ y1 = self.radius * math.sin(self.theta)
+ x2 = -1*self.radius * math.cos(self.theta)
+ y2 = -1*self.radius * math.sin(self.theta)
+ try:
+ # Inner circle marker
+ self.inner_marker = self.axes.plot([x1/2.5], [y1/2.5], linestyle='',
+ marker='s', markersize=10,
+ color=self.color, alpha=0.6,
+ pickradius=5, label="pick",
+ # Prefer this to other lines
+ zorder=zorder,
+ visible=True)[0]
+ except:
+ self.inner_marker = self.axes.plot([x1/2.5], [y1/2.5], linestyle='',
+ marker='s', markersize=10,
+ color=self.color, alpha=0.6,
+ label="pick",
+ visible=True)[0]
+ message = "\nTHIS PROTOTYPE NEEDS THE LATEST VERSION"
+ message += " OF MATPLOTLIB\n Get the SVN version that is at"
+ message += " least as recent as June 1, 2007"
+ self.line = self.axes.plot([x1, x2], [y1, y2],
+ linestyle='-', marker='',
+ color=self.color, visible=True)[0]
+ self.npts = 20
+ self.has_move = False
+ self.connect_markers([self.inner_marker, self.line])
+ self.update()
+
+ def set_layer(self, n):
+ """
+ """
+ self.layernum = n
+ self.update()
+
+ def clear(self):
+ """
+ """
+ self.clear_markers()
+ try:
+ self.inner_marker.remove()
+ self.line.remove()
+ except:
+ # Old version of matplotlib
+ for item in range(len(self.axes.lines)):
+ del self.axes.lines[0]
+
+ def update(self, theta=None):
+ """
+ Draw the new roughness on the graph.
+ """
+
+ if theta != None:
+ self.theta = theta
+ x1 = self.radius * math.cos(self.theta)
+ y1 = self.radius * math.sin(self.theta)
+ x2 = -1 * self.radius * math.cos(self.theta)
+ y2 = -1 * self.radius * math.sin(self.theta)
+
+ self.inner_marker.set(xdata=[x1/2.5], ydata=[y1/2.5])
+ self.line.set(xdata=[x1, x2], ydata=[y1, y2])
+
+ def save(self, ev):
+ """
+ Remember the roughness for this layer and the next so that we
+ can restore on Esc.
+ """
+ self.save_theta= self.theta
+ self.base.freeze_axes()
+
+ def moveend(self, ev):
+ """
+ """
+ self.has_move = False
+ self.base.moveend(ev)
+
+ def restore(self):
+ """
+ Restore the roughness for this layer.
+ """
+ self.theta = self.save_theta
+
+ def move(self, x, y, ev):
+ """
+ Process move to a new position, making sure that the move is allowed.
+ """
+ self.theta = math.atan2(y, x)
+ self.has_move = True
+ self.base.base.update()
+
+ def set_cursor(self, x, y):
+ """
+ """
+ self.move(x, y, None)
+ self.update()
+
+ def get_params(self):
+ """
+ """
+ params = {}
+ params["radius"] = self.radius
+ params["theta"] = self.theta
+ return params
+
+ def set_params(self, params):
+ """
+ """
+ x = params["radius"]
+ self.set_cursor(x, self._inner_mouse_y)
+
Index: test/test_rename_guiframe/local_perspectives/plotting/SlicerParameters.py
===================================================================
--- test/test_rename_guiframe/local_perspectives/plotting/SlicerParameters.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/local_perspectives/plotting/SlicerParameters.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,149 @@
+
+
+import wx
+import wx.lib.newevent
+#from copy import deepcopy
+from sans.guiframe.events import EVT_SLICER_PARS
+from sans.guiframe.utils import format_number
+from sans.guiframe.events import EVT_SLICER
+from sans.guiframe.events import SlicerParameterEvent
+
+
+class SlicerParameterPanel(wx.Dialog):
+ """
+ Panel class to show the slicer parameters
+ """
+ #TODO: show units
+ #TODO: order parameters properly
+
+ def __init__(self, parent, *args, **kwargs):
+ wx.Dialog.__init__(self, parent, *args, **kwargs)
+ """
+ Dialog window that allow to edit parameters slicer
+ by entering new values
+ """
+ self.params = {}
+ self.parent = parent
+ self.type = None
+ self.listeners = []
+ self.parameters = []
+ self.bck = wx.GridBagSizer(5, 5)
+ self.SetSizer(self.bck)
+ label = "Right-click on 2D plot for slicer options"
+ title = wx.StaticText(self, -1, label, style=wx.ALIGN_LEFT)
+ self.bck.Add(title, (0, 0), (1, 2),
+ flag=wx.LEFT|wx.ALIGN_CENTER_VERTICAL, border=15)
+ # Bindings
+ self.parent.Bind(EVT_SLICER, self.onEVT_SLICER)
+ self.parent.Bind(EVT_SLICER_PARS, self.onParamChange)
+
+ def onEVT_SLICER(self, event):
+ """
+ Process EVT_SLICER events
+ When the slicer changes, update the panel
+
+ :param event: EVT_SLICER event
+ """
+ event.Skip()
+ if event.obj_class == None:
+ self.set_slicer(None, None)
+ else:
+ self.set_slicer(event.type, event.params)
+
+ def set_slicer(self, type, params):
+ """
+ Rebuild the panel
+ """
+ self.bck.Clear(True)
+ self.type = type
+ if type == None:
+ label = "Right-click on 2D plot for slicer options"
+ title = wx.StaticText(self, -1, label, style=wx.ALIGN_LEFT)
+ self.bck.Add(title, (0, 0), (1, 2),
+ flag=wx.LEFT|wx.ALIGN_CENTER_VERTICAL, border=15)
+ else:
+ title = wx.StaticText(self, -1,
+ "Slicer Parameters", style=wx.ALIGN_LEFT)
+ self.bck.Add(title, (0, 0), (1, 2),
+ flag=wx.LEFT|wx.ALIGN_CENTER_VERTICAL, border=15)
+ ix = 0
+ iy = 0
+ self.parameters = []
+ keys = params.keys()
+ keys.sort()
+ for item in keys:
+ iy += 1
+ ix = 0
+ if not item in ["count", "errors"]:
+ text = wx.StaticText(self, -1, item, style=wx.ALIGN_LEFT)
+ self.bck.Add(text, (iy, ix), (1, 1),
+ wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
+ ctl = wx.TextCtrl(self, -1, size=(80, 20),
+ style=wx.TE_PROCESS_ENTER)
+ hint_msg = "Modify the value of %s to change" % item
+ hint_msg += " the 2D slicer"
+ ctl.SetToolTipString(hint_msg)
+ ix = 1
+ ctl.SetValue(format_number(str(params[item])))
+ self.Bind(wx.EVT_TEXT_ENTER, self.onTextEnter)
+ ctl.Bind(wx.EVT_KILL_FOCUS, self.onTextEnter)
+ self.parameters.append([item, ctl])
+ self.bck.Add(ctl, (iy, ix), (1, 1),
+ wx.EXPAND|wx.ADJUST_MINSIZE, 0)
+ ix = 3
+ self.bck.Add((20, 20), (iy, ix), (1, 1),
+ wx.EXPAND|wx.ADJUST_MINSIZE, 0)
+ else:
+ text = wx.StaticText(self, -1, item + " : ",
+ style=wx.ALIGN_LEFT)
+ self.bck.Add(text, (iy, ix), (1, 1),
+ wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
+ ctl = wx.StaticText(self, -1,
+ format_number(str(params[item])),
+ style=wx.ALIGN_LEFT)
+ ix = 1
+ self.bck.Add(ctl, (iy, ix), (1, 1),
+ wx.EXPAND|wx.ADJUST_MINSIZE, 0)
+ iy += 1
+ ix = 1
+ self.bck.Add((20, 20), (iy, ix), (1, 1),
+ wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
+ self.bck.Layout()
+ self.bck.Fit(self)
+ self.parent.GetSizer().Layout()
+
+ def onParamChange(self, evt):
+ """
+ receive an event end reset value text fields
+ inside self.parameters
+ """
+ evt.Skip()
+ if evt.type == "UPDATE":
+ for item in self.parameters:
+ if item[0] in evt.params:
+ item[1].SetValue("%-5.3g" % evt.params[item[0]])
+ item[1].Refresh()
+
+ def onTextEnter(self, evt):
+ """
+ Parameters have changed
+ """
+ params = {}
+ has_error = False
+ for item in self.parameters:
+ try:
+ params[item[0]] = float(item[1].GetValue())
+ item[1].SetBackgroundColour(
+ wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW))
+ item[1].Refresh()
+ except:
+ has_error = True
+ item[1].SetBackgroundColour("pink")
+ item[1].Refresh()
+
+ if has_error == False:
+ # Post parameter event
+ ##parent hier is plotter2D
+ event = SlicerParameterEvent(type=self.type, params=params)
+ wx.PostEvent(self.parent, event)
+
Index: test/test_rename_guiframe/local_perspectives/plotting/__init__.py
===================================================================
--- test/test_rename_guiframe/local_perspectives/plotting/__init__.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/local_perspectives/plotting/__init__.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,2 @@
+PLUGIN_ID = "Plotting plug-in 1.0"
+from plotting import *
Index: test/test_rename_guiframe/local_perspectives/plotting/binder.py
===================================================================
--- test/test_rename_guiframe/local_perspectives/plotting/binder.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/local_perspectives/plotting/binder.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,388 @@
+"""
+Extension to MPL to support the binding of artists to key/mouse events.
+"""
+
+class Selection:
+ """
+ Store and compare selections.
+ """
+ # TODO: We need some way to check in prop matches, preferably
+ # TODO: without imposing structure on prop.
+
+ artist = None
+ prop = {}
+ def __init__(self, artist=None, prop={}):
+ self.artist, self.prop = artist, self.prop
+
+ def __eq__(self, other):
+ return self.artist is other.artist
+
+ def __ne__(self, other):
+ return self.artist is not other.artist
+
+ def __nonzero__(self):
+ return self.artist is not None
+
+class BindArtist:
+
+ # Track keyboard modifiers for events.
+ # TODO: Move keyboard modifier support into the backend. We cannot
+ # TODO: properly support it from outside the windowing system since there
+ # TODO: is no way to recognized whether shift is held down when the mouse
+ # TODO: first clicks on the the application window.
+ control, shift, alt, meta = False, False, False, False
+
+ # Track doubleclick
+ dclick_threshhold = 0.25
+ _last_button, _last_time = None, 0
+
+ # Mouse/keyboard events we can bind to
+ events = ['enter', 'leave', 'motion', 'click', 'dclick', 'drag', 'release',
+ 'scroll', 'key', 'keyup']
+ # TODO: Need our own event structure
+ def __init__(self, figure):
+ canvas = figure.canvas
+ # Link to keyboard/mouse
+ try:
+ self._connections = [
+ canvas.mpl_connect('motion_notify_event', self._onMotion),
+ canvas.mpl_connect('button_press_event', self._onClick),
+ canvas.mpl_connect('button_release_event', self._onRelease),
+ canvas.mpl_connect('key_press_event', self._onKey),
+ canvas.mpl_connect('key_release_event', self._onKeyRelease),
+ canvas.mpl_connect('scroll_event', self._onScroll)
+ ]
+ except:
+ #print "bypassing scroll_event: wrong matplotlib version"
+ self._connections = [
+ canvas.mpl_connect('motion_notify_event', self._onMotion),
+ canvas.mpl_connect('button_press_event', self._onClick),
+ canvas.mpl_connect('button_release_event', self._onRelease),
+ canvas.mpl_connect('key_press_event', self._onKey),
+ canvas.mpl_connect('key_release_event', self._onKeyRelease),
+ ]
+ # Turn off picker if it hasn't already been done
+ try:
+ canvas.mpl_disconnect(canvas.button_pick_id)
+ canvas.mpl_disconnect(canvas.scroll_pick_id)
+ except:
+ pass
+ self.canvas = canvas
+ self.figure = figure
+ self.clearall()
+
+ def clear(self, *artists):
+ """
+ self.clear(h1,h2,...)
+ Remove connections for artists h1, h2, ...
+
+ Use clearall() to reset all connections.
+
+ """
+ for h in artists:
+ for a in self.events:
+ if h in self._actions[a]:
+ del self._actions[a][h]
+ if h in self._artists:
+ self._artists.remove(h)
+ if self._current.artist in artists:
+ self._current = Selection()
+ if self._hasclick.artist in artists:
+ self._hasclick = Selection()
+ if self._haskey.artist in artists:
+ self._haskey = Selection()
+
+ def clearall(self):
+ """
+ Clear connections to all artists.
+
+ Use clear(h1,h2,...) to reset specific artists.
+ """
+ # Don't monitor any actions
+ self._actions = {}
+ for action in self.events:
+ self._actions[action] = {}
+ # Need activity state
+ self._artists = []
+ self._current = Selection()
+ self._hasclick = Selection()
+ self._haskey = Selection()
+
+ def disconnect(self):
+ """
+ In case we need to disconnect from the canvas...
+ """
+ try:
+ for cid in self._connections:
+ self.canvas.mpl_disconnect(cid)
+ except:
+ pass
+ self._connections = []
+
+ def __del__(self):
+ self.disconnect()
+
+ def __call__(self, trigger, artist, action):
+ """Register a callback for an artist to a particular trigger event.
+
+ usage:
+ self.connect(eventname,artist,action)
+
+ where:
+ eventname is a string
+ artist is the particular graph object to respond to the event
+ action(event,**kw) is called when the event is triggered
+
+ The action callback is associated with particular artists.
+ Different artists will have different kwargs. See documentation
+ on the contains() method for each artist. One common properties
+ are ind for the index of the item under the cursor, which is
+ returned by Line2D and by collections.
+
+ The following events are supported:
+ enter: mouse cursor moves into the artist or to a new index
+ leave: mouse cursor leaves the artist
+ click: mouse button pressed on the artist
+ drag: mouse button pressed on the artist and cursor moves
+ release: mouse button released for the artist
+ key: key pressed when mouse is on the artist
+ keyrelease: key released for the artist
+
+ The event received by action has a number of attributes:
+ name is the event name which was triggered
+ artist is the object which triggered the event
+ x,y are the screen coordinates of the mouse
+ xdata,ydata are the graph coordinates of the mouse
+ button is the mouse button being pressed/released
+ key is the key being pressed/released
+ shift,control,alt,meta are flags which are true if the
+ corresponding key is pressed at the time of the event.
+ details is a dictionary of artist specific details, such as the
+ id(s) of the point that were clicked.
+
+ When receiving an event, first check the modifier state to be
+ sure it applies. E.g., the callback for 'press' might be:
+ if event.button == 1 and event.shift: process Shift-click
+
+ :TODO: Only receive events with the correct modifiers (e.g., S-click,
+ :TODO: or *-click for any modifiers).
+ :TODO: Only receive button events for the correct button (e.g., click1
+ :TODO: release3, or dclick* for any button)
+ :TODO: Support virtual artist, so that and artist can be flagged as
+ :TODO: having a tag list and receive the correct events
+ :TODO: Support virtual events for binding to button-3 vs shift button-1
+ :TODO: without changing callback code
+ :TODO: Attach multiple callbacks to the same event?
+ :TODO: Clean up interaction with toolbar modes
+ :TODO: push/pushclear/pop context so that binding changes
+ for the duration
+ :TODO: e.g., to support ? context sensitive help
+
+ """
+ # Check that the trigger is valid
+ if trigger not in self._actions:
+ raise ValueError, "%s invalid --- valid triggers are %s" \
+ % (trigger, ", ".join(self.events))
+ # Register the trigger callback
+ self._actions[trigger][artist] = action
+ #print "==> added",artist,[artist],"to",trigger,":",
+ #self._actions[trigger].keys()
+ # Maintain a list of all artists
+ if artist not in self._artists:
+ self._artists.append(artist)
+
+ def trigger(self, actor, action, ev):
+ """
+ Trigger a particular event for the artist. Fallback to axes,
+ to figure, and to 'all' if the event is not processed.
+ """
+ if action not in self.events:
+ raise ValueError, "Trigger expects " + ", ".join(self.events)
+ # Tag the event with modifiers
+ for mod in ('alt', 'control', 'shift', 'meta'):
+ setattr(ev, mod, getattr(self, mod))
+ setattr(ev, 'artist', None)
+ setattr(ev, 'action', action)
+ setattr(ev, 'prop', {})
+ # Fallback scheme. If the event does not return false, pass to parent.
+ processed = False
+ artist, prop = actor.artist, actor.prop
+ if artist in self._actions[action]:
+ ev.artist, ev.prop = artist, prop
+ processed = self._actions[action][artist](ev)
+ if not processed and ev.inaxes in self._actions[action]:
+ ev.artist, ev.prop = ev.inaxes, {}
+ processed = self._actions[action][ev.inaxes](ev)
+ if not processed and self.figure in self._actions[action]:
+ ev.artist, ev.prop = self.figure, {}
+ processed = self._actions[action][self.figure](ev)
+ if not processed and 'all' in self._actions[action]:
+ ev.artist, ev.prop = None, {}
+ processed = self._actions[action]['all'](ev)
+ return processed
+
+ def _find_current(self, event):
+ """
+ Find the artist who will receive the event. Only search
+ registered artists. All others are invisible to the mouse.
+ """
+ # TODO: sort by zorder of axes then by zorder within axes
+ self._artists.sort(cmp=lambda x, y: cmp(y.zorder, x.zorder))
+ # print "search"," ".join([str(h) for h in self._artists])
+ found = Selection()
+ #print "searching in",self._artists
+ for artist in self._artists:
+ # TODO: should contains() return false if invisible?
+ if not artist.get_visible():
+ continue
+ # TODO: optimization - exclude artists not inaxes
+ try:
+ inside,prop = artist.contains(event)
+ except:
+ # Probably an old version of matplotlib
+ inside = False
+ if inside:
+ found.artist, found.prop = artist, prop
+ break
+ #print "found",found.artist
+
+ # TODO: how to check if prop is equal?
+ if found != self._current:
+ self.trigger(self._current, 'leave', event)
+ self.trigger(found, 'enter', event)
+ self._current = found
+ return found
+
+ def _onMotion(self, event):
+ """
+ Track enter/leave/motion through registered artists; all
+ other artists are invisible.
+ """
+ ## Can't kill double-click on motion since Windows produces
+ ## spurious motion events.
+ #self._last_button = None
+
+ # Dibs on the motion event for the clicked artist
+ if self._hasclick:
+ # Make sure the x,y data use the coordinate system of the
+ # artist rather than the default axes coordinates.
+
+ transform = self._hasclick.artist.get_transform()
+ #x,y = event.xdata,event.ydata
+ x, y = event.x, event.y
+ try:
+ x, y = transform.inverted().transform_point((x, y))
+
+ except:
+ x, y = transform.inverse_xy_tup((x, y))
+ event.xdata, event.ydata = x, y
+ self.trigger(self._hasclick, 'drag', event)
+ else:
+ found = self._find_current(event)
+ #print "found",found.artist
+ self.trigger(found, 'motion', event)
+
+ def _onClick(self, event):
+ """
+ Process button click
+ """
+ import time
+
+ # Check for double-click
+ event_time = time.time()
+ #print event_time,self._last_time,self.dclick_threshhold
+ #print (event_time > self._last_time + self.dclick_threshhold)
+ #print event.button,self._last_button
+ if (event.button != self._last_button) or \
+ (event_time > self._last_time + self.dclick_threshhold):
+ action = 'click'
+ else:
+ action = 'dclick'
+ self._last_button = event.button
+ self._last_time = event_time
+
+ # If an artist is already dragging, feed any additional button
+ # presses to that artist.
+ # TODO: do we want to force a single button model on the user?
+ # TODO: that is, once a button is pressed, no other buttons
+ # TODO: can come through? I think this belongs in canvas, not here.
+ if self._hasclick:
+ found = self._hasclick
+ else:
+ found = self._find_current(event)
+ #print "button %d pressed"%event.button
+ # Note: it seems like if "click" returns False then hasclick should
+ # not be set. The problem is that there are two reasons it can
+ # return false: because there is no click action for this artist
+ # or because the click action returned false. A related problem
+ # is that click actions will go to the canvas if there is no click
+ # action for the artist, even if the artist has a drag. I'll leave
+ # it to future maintainers to sort out this problem. For now the
+ # recommendation is that users should define click if they have
+ # drag or release on the artist.
+ self.trigger(found, action, event)
+ self._hasclick = found
+
+ def _onDClick(self, event):
+ """
+ Process button double click
+ """
+ # If an artist is already dragging, feed any additional button
+ # presses to that artist.
+ # TODO: do we want to force a single button model on the user?
+ # TODO: that is, once a button is pressed, no other buttons
+ # TODO: can come through? I think this belongs in canvas, not here.
+ if self._hasclick:
+ found = self._hasclick
+ else:
+ found = self._find_current(event)
+ self.trigger(found, 'dclick', event)
+ self._hasclick = found
+
+ def _onRelease(self, event):
+ """
+ Process release release
+ """
+ self.trigger(self._hasclick, 'release', event)
+ self._hasclick = Selection()
+
+ def _onKey(self, event):
+ """
+ Process key click
+ """
+ # TODO: Do we really want keyboard focus separate from mouse focus?
+ # TODO: Do we need an explicit focus command for keyboard?
+ # TODO: Can we tab between items?
+ # TODO: How do unhandled events get propogated to axes, figure and
+ # TODO: finally to application? Do we need to implement a full tags
+ # TODO: architecture a la Tk?
+ # TODO: Do modifiers cause a grab? Does the artist see the modifiers?
+ if event.key in ('alt', 'meta', 'control', 'shift'):
+ setattr(self, event.key, True)
+ return
+
+ if self._haskey:
+ found = self._haskey
+ else:
+ found = self._find_current(event)
+ self.trigger(found, 'key', event)
+ self._haskey = found
+
+ def _onKeyRelease(self, event):
+ """
+ Process key release
+ """
+ if event.key in ('alt', 'meta', 'control', 'shift'):
+ setattr(self, event.key, False)
+ return
+ if self._haskey:
+ self.trigger(self._haskey, 'keyup', event)
+ self._haskey = Selection()
+
+ def _onScroll(self, event):
+ """
+ Process scroll event
+ """
+ found = self._find_current(event)
+ self.trigger(found, 'scroll', event)
+
Index: test/test_rename_guiframe/local_perspectives/plotting/boxMask.py
===================================================================
--- test/test_rename_guiframe/local_perspectives/plotting/boxMask.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/local_perspectives/plotting/boxMask.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,252 @@
+
+
+
+import math
+#import wx
+#from copy import deepcopy
+from BaseInteractor import _BaseInteractor
+from boxSum import PointInteractor
+from boxSum import VerticalDoubleLine
+from boxSum import HorizontalDoubleLine
+#from sans.guiframe.events import SlicerParamUpdateEvent
+
+
+class BoxMask(_BaseInteractor):
+ """
+ BoxMask Class: determine 2 rectangular area to find the pixel of
+ a Data inside of box.
+
+ Uses PointerInteractor , VerticalDoubleLine,HorizontalDoubleLine.
+
+ :param zorder: Artists with lower zorder values are drawn first.
+ :param x_min: the minimum value of the x coordinate
+ :param x_max: the maximum value of the x coordinate
+ :param y_min: the minimum value of the y coordinate
+ :param y_max: the maximum value of the y coordinate
+
+ """
+ def __init__(self, base, axes, color='black', zorder=3, side=None,
+ x_min=0.008, x_max=0.008, y_min=0.0025, y_max=0.0025):
+ """
+ """
+ _BaseInteractor.__init__(self, base, axes, color=color)
+ ## class initialization
+ ## list of Boxmask markers
+ self.markers = []
+ self.axes = axes
+ self.is_inside = side
+ ## connect the artist for the motion
+ self.connect = self.base.connect
+ ## when qmax is reached the selected line is reset
+ #the its previous value
+ self.qmax = min(self.base.data.xmax, self.base.data.xmin)
+ ## Define the box limits
+ self.xmin = -1 * 0.5 * min(math.fabs(self.base.data.xmax),
+ math.fabs(self.base.data.xmin))
+ self.ymin = -1 * 0.5 * min(math.fabs(self.base.data.xmax),
+ math.fabs(self.base.data.xmin))
+ self.xmax = 0.5 * min(math.fabs(self.base.data.xmax),
+ math.fabs(self.base.data.xmin))
+ self.ymax = 0.5 * min(math.fabs(self.base.data.xmax),
+ math.fabs(self.base.data.xmin))
+ ## center of the box
+ self.center_x = 0.0002
+ self.center_y = 0.0003
+ ## Number of points on the plot
+ self.nbins = 20
+ ## Define initial result the summation
+ self.count = 0
+ self.error = 0
+ self.data = self.base.data
+ ## Flag to determine if the current figure has moved
+ ## set to False == no motion , set to True== motion
+ self.has_move = False
+ ## Create Box edges
+ self.horizontal_lines = HorizontalDoubleLine(self,
+ self.base.subplot,
+ color='blue',
+ zorder=zorder,
+ y=self.ymax,
+ x=self.xmax,
+ center_x=self.center_x,
+ center_y=self.center_y)
+ self.horizontal_lines.qmax = self.qmax
+
+ self.vertical_lines = VerticalDoubleLine(self,
+ self.base.subplot,
+ color='grey',
+ zorder=zorder,
+ y=self.ymax,
+ x=self.xmax,
+ center_x=self.center_x,
+ center_y=self.center_y)
+ self.vertical_lines.qmax = self.qmax
+
+ self.center = PointInteractor(self,
+ self.base.subplot,color='grey',
+ zorder=zorder,
+ center_x=self.center_x,
+ center_y=self.center_y)
+ ## Save the name of the slicer panel associate with this slicer
+ self.panel_name = ""
+ ## Update and post slicer parameters
+ self.update()
+ self._post_data()
+
+ def clear(self):
+ """
+ Clear the slicer and all connected events related to this slicer
+ """
+ self.clear_markers()
+ self.horizontal_lines.clear()
+ self.vertical_lines.clear()
+ self.center.clear()
+ self.base.connect.clearall()
+ #self.base.Unbind(EVT_SLICER_PARS)
+
+ def update(self):
+ """
+ Respond to changes in the model by recalculating the profiles and
+ resetting the widgets.
+ """
+ # check if the center point has moved and update the figure accordingly
+ if self.center.has_move:
+ self.center.update()
+ self.horizontal_lines.update(center=self.center)
+ self.vertical_lines.update(center=self.center)
+ ## check if the horizontal lines have moved and update
+ # the figure accordingly
+ if self.horizontal_lines.has_move:
+ self.horizontal_lines.update()
+ self.vertical_lines.update(y1=self.horizontal_lines.y1,
+ y2=self.horizontal_lines.y2,
+ height=self.horizontal_lines.half_height)
+ ## check if the vertical lines have moved and update
+ # the figure accordingly
+ if self.vertical_lines.has_move:
+ self.vertical_lines.update()
+ self.horizontal_lines.update(x1=self.vertical_lines.x1,
+ x2=self.vertical_lines.x2,
+ width=self.vertical_lines.half_width)
+ #if self.is_inside != None:
+ out = self._post_data()
+ return out
+
+ def save(self, ev):
+ """
+ Remember the roughness for this layer and the next so that we
+ can restore on Esc.
+ """
+ self.base.freeze_axes()
+ self.horizontal_lines.save(ev)
+ self.vertical_lines.save(ev)
+ self.center.save(ev)
+
+ def _post_data(self):
+ """
+ Get the limits of the boxsum and compute the sum of the pixel
+ contained in that region and the error on that sum
+ """
+ from DataLoader.manipulations import Boxcut
+ ## Data 2D for which the pixel will be summed
+ data = self.base.data
+ mask = data.mask
+ ## the region of the summation
+ x_min = self.horizontal_lines.x2
+ x_max = self.horizontal_lines.x1
+ y_min = self.vertical_lines.y2
+ y_max = self.vertical_lines.y1
+ mask = Boxcut(x_min=x_min, x_max=x_max, y_min=y_min, y_max=y_max)
+
+ if self.is_inside:
+ out = (mask(data) == False)
+ else:
+ out = (mask(data))
+ #self.base.data.mask=out
+ return out
+
+ def moveend(self, ev):
+ """
+ After a dragging motion this function is called to compute
+ the error and the sum of pixel of a given data 2D
+ """
+ self.base.thaw_axes()
+ ## post
+ self._post_data()
+
+ def restore(self):
+ """
+ Restore the roughness for this layer.
+ """
+ self.horizontal_lines.restore()
+ self.vertical_lines.restore()
+ self.center.restore()
+
+ def move(self, x, y, ev):
+ """
+ Process move to a new position, making sure that the move is allowed.
+ """
+ pass
+
+ def set_cursor(self, x, y):
+ pass
+
+ def get_params(self):
+ """
+ Store a copy of values of parameters of the slicer into a dictionary.
+
+ :return params: the dictionary created
+
+ """
+ params = {}
+ params["Width"] = math.fabs(self.vertical_lines.half_width) * 2
+ params["Height"] = math.fabs(self.horizontal_lines.half_height) * 2
+ params["center_x"] = self.center.x
+ params["center_y"] = self.center.y
+ return params
+
+ def get_mask(self):
+ """
+ return mask as a result of boxcut
+ """
+ mask = self.mask
+ return mask
+
+ def set_params(self, params):
+ """
+ Receive a dictionary and reset the slicer with values contained
+ in the values of the dictionary.
+
+ :param params: a dictionary containing name of slicer parameters and
+ values the user assigned to the slicer.
+ """
+ x_max = math.fabs(params["Width"] )/2
+ y_max = math.fabs(params["Height"])/2
+
+ self.center_x = params["center_x"]
+ self.center_y = params["center_y"]
+ #update the slicer given values of params
+ self.center.update(center_x=self.center_x, center_y=self.center_y)
+ self.horizontal_lines.update(center=self.center,
+ width=x_max,
+ height=y_max)
+ self.vertical_lines.update(center=self.center,
+ width=x_max,
+ height=y_max)
+ #compute the new error and sum given values of params
+ self._post_data()
+
+ def freeze_axes(self):
+ self.base.freeze_axes()
+
+ def thaw_axes(self):
+ self.base.thaw_axes()
+
+ def draw(self):
+ self.base.update()
+
+class inner_BoxMask(BoxMask):
+ def __call__(self):
+ self.base.data.mask = (self._post_data()==False)
+
+
Index: test/test_rename_guiframe/local_perspectives/plotting/boxSlicer.py
===================================================================
--- test/test_rename_guiframe/local_perspectives/plotting/boxSlicer.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/local_perspectives/plotting/boxSlicer.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,560 @@
+
+
+import wx
+#import copy
+#from copy import deepcopy
+import math
+import numpy
+from sans.guiframe.events import NewPlotEvent
+from sans.guiframe.events import StatusEvent
+from sans.guiframe.events import SlicerParameterEvent
+from sans.guiframe.events import EVT_SLICER_PARS
+from BaseInteractor import _BaseInteractor
+from sans.guiframe.dataFitting import Data1D
+#import SlicerParameters
+
+
+class BoxInteractor(_BaseInteractor):
+ """
+ BoxInteractor define a rectangle that return data1D average of Data2D
+ in a rectangle area defined by -x, x ,y, -y
+ """
+ def __init__(self, base, axes, color='black', zorder=3):
+ _BaseInteractor.__init__(self, base, axes, color=color)
+ ## Class initialization
+ self.markers = []
+ self.axes = axes
+ ##connecting artist
+ self.connect = self.base.connect
+ ## determine x y values
+ self.x = 0.5 * min(math.fabs(self.base.data2D.xmax),
+ math.fabs(self.base.data2D.xmin))
+ self.y = 0.5 * min(math.fabs(self.base.data2D.xmax),
+ math.fabs(self.base.data2D.xmin))
+ ## when reach qmax reset the graph
+ self.qmax = max(self.base.data2D.xmax, self.base.data2D.xmin,
+ self.base.data2D.ymax, self.base.data2D.ymin)
+ ## Number of points on the plot
+ self.nbins = 30
+ ## If True, I(|Q|) will be return, otherwise,
+ #negative q-values are allowed
+ self.fold = True
+ ## reference of the current Slab averaging
+ self.averager = None
+ ## Create vertical and horizaontal lines for the rectangle
+ self.vertical_lines = VerticalLines(self,
+ self.base.subplot,
+ color='blue',
+ zorder=zorder,
+ y=self.y ,
+ x=self.x)
+ self.vertical_lines.qmax = self.qmax
+
+ self.horizontal_lines = HorizontalLines(self,
+ self.base.subplot,
+ color='green',
+ zorder=zorder,
+ x=self.x,
+ y=self.y)
+ self.horizontal_lines.qmax = self.qmax
+ ## draw the rectangle and plost the data 1D resulting
+ ## of averaging data2D
+ self.update()
+ self._post_data()
+ ## Bind to slice parameter events
+ self.base.Bind(EVT_SLICER_PARS, self._onEVT_SLICER_PARS)
+
+ def _onEVT_SLICER_PARS(self, event):
+ """
+ receive an event containing parameters values to reset the slicer
+
+ :param event: event of type SlicerParameterEvent with params as
+ attribute
+ """
+ wx.PostEvent(self.base.parent,
+ StatusEvent(status="BoxSlicer._onEVT_SLICER_PARS"))
+ event.Skip()
+ if event.type == self.__class__.__name__:
+ self.set_params(event.params)
+ self.base.update()
+
+ def update_and_post(self):
+ """
+ Update the slicer and plot the resulting data
+ """
+ self.update()
+ self._post_data()
+
+ def set_layer(self, n):
+ """
+ Allow adding plot to the same panel
+
+ :param n: the number of layer
+
+ """
+ self.layernum = n
+ self.update()
+
+ def clear(self):
+ """
+ Clear the slicer and all connected events related to this slicer
+ """
+ self.averager = None
+ self.clear_markers()
+ self.horizontal_lines.clear()
+ self.vertical_lines.clear()
+ self.base.connect.clearall()
+ self.base.Unbind(EVT_SLICER_PARS)
+
+ def update(self):
+ """
+ Respond to changes in the model by recalculating the profiles and
+ resetting the widgets.
+ """
+ ##Update the slicer if an horizontal line is dragged
+ if self.horizontal_lines.has_move:
+ self.horizontal_lines.update()
+ self.vertical_lines.update(y=self.horizontal_lines.y)
+ ##Update the slicer if a vertical line is dragged
+ if self.vertical_lines.has_move:
+ self.vertical_lines.update()
+ self.horizontal_lines.update(x=self.vertical_lines.x)
+
+ def save(self, ev):
+ """
+ Remember the roughness for this layer and the next so that we
+ can restore on Esc.
+ """
+ self.base.freeze_axes()
+ self.vertical_lines.save(ev)
+ self.horizontal_lines.save(ev)
+
+ def _post_data(self):
+ pass
+
+ def post_data(self, new_slab=None, nbins=None, direction=None):
+ """
+ post data averaging in Qx or Qy given new_slab type
+
+ :param new_slab: slicer that determine with direction to average
+ :param nbins: the number of points plotted when averaging
+ :param direction: the direction of averaging
+
+ """
+ x_min = -1 * math.fabs(self.vertical_lines.x)
+ x_max = math.fabs(self.vertical_lines.x)
+ y_min = -1 * math.fabs(self.horizontal_lines.y)
+ y_max = math.fabs(self.horizontal_lines.y)
+
+ if nbins != None:
+ self.nbins = nbins
+ if self.averager == None:
+ if new_slab == None:
+ msg = "post data:cannot average , averager is empty"
+ raise ValueError, msg
+ self.averager = new_slab
+ if direction == "X":
+ if self.fold:
+ x_low = 0
+ else:
+ x_low = math.fabs(x_min)
+ bin_width = (x_max + x_low)/self.nbins
+ else:
+ if self.fold:
+ y_low = 0
+ else:
+ y_low = math.fabs(y_min)
+ bin_width = (y_max + y_low)/self.nbins
+ ## Average data2D given Qx or Qy
+ box = self.averager(x_min=x_min, x_max=x_max, y_min=y_min, y_max=y_max,
+ bin_width=bin_width)
+ box.fold = self.fold
+ boxavg = box(self.base.data2D)
+ #3 Create Data1D to plot
+ if hasattr(boxavg, "dxl"):
+ dxl = boxavg.dxl
+ else:
+ dxl = None
+ if hasattr(boxavg, "dxw"):
+ dxw = boxavg.dxw
+ else:
+ dxw = None
+ new_plot = Data1D(x=boxavg.x, y=boxavg.y, dy=boxavg.dy)
+ new_plot.dxl = dxl
+ new_plot.dxw = dxw
+ new_plot.name = str(self.averager.__name__) + \
+ "(" + self.base.data2D.name + ")"
+ new_plot.source = self.base.data2D.source
+ new_plot.interactive = True
+ new_plot.detector = self.base.data2D.detector
+ ## If the data file does not tell us what the axes are, just assume...
+ new_plot.xaxis("\\rm{Q}", "A^{-1}")
+ new_plot.yaxis("\\rm{Intensity} ", "cm^{-1}")
+
+ data = self.base.data2D
+ if hasattr(data, "scale") and data.scale == 'linear' and \
+ self.base.data2D.name.count("Residuals") > 0:
+ new_plot.ytransform = 'y'
+ new_plot.yaxis("\\rm{Residuals} ", "/")
+
+ new_plot.group_id = str(self.averager.__name__) + self.base.data2D.name
+ #new_plot.id = str(self.averager.__name__)
+ #new_plot.is_data= True
+ wx.PostEvent(self.base.parent, NewPlotEvent(plot=new_plot,
+ title=str(self.averager.__name__)))
+
+ def moveend(self, ev):
+ """
+ Called after a dragging event.
+ Post the slicer new parameters and creates a new Data1D
+ corresponding to the new average
+ """
+ self.base.thaw_axes()
+ # Post paramters
+ event = SlicerParameterEvent()
+ event.type = self.__class__.__name__
+ event.params = self.get_params()
+ wx.PostEvent(self.base.parent, event)
+ # create the new data1D
+ self._post_data()
+
+ def restore(self):
+ """
+ Restore the roughness for this layer.
+ """
+ self.horizontal_lines.restore()
+ self.vertical_lines.restore()
+
+ def move(self, x, y, ev):
+ """
+ Process move to a new position, making sure that the move is allowed.
+ """
+ pass
+
+ def set_cursor(self, x, y):
+ pass
+
+ def get_params(self):
+ """
+ Store a copy of values of parameters of the slicer into a dictionary.
+
+ :return params: the dictionary created
+
+ """
+ params = {}
+ params["x_max"] = math.fabs(self.vertical_lines.x)
+ params["y_max"] = math.fabs(self.horizontal_lines.y)
+ params["nbins"] = self.nbins
+ return params
+
+ def set_params(self, params):
+ """
+ Receive a dictionary and reset the slicer with values contained
+ in the values of the dictionary.
+
+ :param params: a dictionary containing name of slicer parameters and
+ values the user assigned to the slicer.
+ """
+ self.x = float(math.fabs(params["x_max"]))
+ self.y = float(math.fabs(params["y_max"] ))
+ self.nbins = params["nbins"]
+
+ self.horizontal_lines.update(x=self.x, y=self.y)
+ self.vertical_lines.update(x=self.x, y=self.y)
+ self.post_data(nbins=None)
+
+ def freeze_axes(self):
+ """
+ """
+ self.base.freeze_axes()
+
+ def thaw_axes(self):
+ """
+ """
+ self.base.thaw_axes()
+
+ def draw(self):
+ """
+ """
+ self.base.draw()
+
+
+class HorizontalLines(_BaseInteractor):
+ """
+ Draw 2 Horizontal lines centered on (0,0) that can move
+ on the x- direction and in opposite direction
+ """
+ def __init__(self, base, axes, color='black', zorder=5, x=0.5, y=0.5):
+ """
+ """
+ _BaseInteractor.__init__(self, base, axes, color=color)
+ ##Class initialization
+ self.markers = []
+ self.axes = axes
+ ## Saving the end points of two lines
+ self.x = x
+ self.save_x = x
+
+ self.y = y
+ self.save_y = y
+ ## Creating a marker
+ try:
+ # Inner circle marker
+ self.inner_marker = self.axes.plot([0], [self.y], linestyle='',
+ marker='s', markersize=10,
+ color=self.color, alpha=0.6,
+ pickradius=5, label="pick",
+ # Prefer this to other lines
+ zorder=zorder,
+ visible=True)[0]
+ except:
+ self.inner_marker = self.axes.plot([0], [self.y], linestyle='',
+ marker='s', markersize=10,
+ color=self.color, alpha=0.6,
+ label="pick", visible=True)[0]
+ message = "\nTHIS PROTOTYPE NEEDS THE LATEST VERSION "
+ message += "OF MATPLOTLIB\n Get the SVN version that"
+ message += " is at least as recent as June 1, 2007"
+ owner = self.base.base.parent
+ wx.PostEvent(owner,
+ StatusEvent(status="AnnulusSlicer: %s" % message))
+ ## Define 2 horizontal lines
+ self.top_line = self.axes.plot([self.x, -self.x], [self.y, self.y],
+ linestyle='-', marker='',
+ color=self.color, visible=True)[0]
+ self.bottom_line = self.axes.plot([self.x, -self.x], [-self.y, -self.y],
+ linestyle='-', marker='',
+ color=self.color, visible=True)[0]
+ ## Flag to check the motion of the lines
+ self.has_move = False
+ ## Connecting markers to mouse events and draw
+ self.connect_markers([self.top_line, self.inner_marker])
+ self.update()
+
+ def set_layer(self, n):
+ """
+ Allow adding plot to the same panel
+
+ :param n: the number of layer
+
+ """
+ self.layernum = n
+ self.update()
+
+ def clear(self):
+ """
+ Clear this slicer and its markers
+ """
+ self.clear_markers()
+ try:
+ self.inner_marker.remove()
+ self.top_line.remove()
+ self.bottom_line.remove()
+ except:
+ # Old version of matplotlib
+ for item in range(len(self.axes.lines)):
+ del self.axes.lines[0]
+
+ def update(self, x=None, y=None):
+ """
+ Draw the new roughness on the graph.
+
+ :param x: x-coordinates to reset current class x
+ :param y: y-coordinates to reset current class y
+
+ """
+ ## Reset x, y- coordinates if send as parameters
+ if x != None:
+ self.x = numpy.sign(self.x) * math.fabs(x)
+ if y != None:
+ self.y = numpy.sign(self.y) * math.fabs(y)
+ ## Draw lines and markers
+ self.inner_marker.set(xdata=[0], ydata=[self.y])
+ self.top_line.set(xdata=[self.x, -self.x], ydata=[self.y, self.y])
+ self.bottom_line.set(xdata=[self.x,-self.x], ydata=[-self.y, -self.y])
+
+ def save(self, ev):
+ """
+ Remember the roughness for this layer and the next so that we
+ can restore on Esc.
+ """
+ self.save_x = self.x
+ self.save_y = self.y
+ self.base.freeze_axes()
+
+ def moveend(self, ev):
+ """
+ Called after a dragging this edge and set self.has_move to False
+ to specify the end of dragging motion
+ """
+ self.has_move = False
+ self.base.moveend(ev)
+
+ def restore(self):
+ """
+ Restore the roughness for this layer.
+ """
+ self.x = self.save_x
+ self.y = self.save_y
+
+ def move(self, x, y, ev):
+ """
+ Process move to a new position, making sure that the move is allowed.
+ """
+ self.y = y
+ self.has_move = True
+ self.base.base.update()
+
+
+class VerticalLines(_BaseInteractor):
+ """
+ Select an annulus through a 2D plot
+ """
+ def __init__(self, base, axes, color='black', zorder=5, x=0.5, y=0.5):
+ """
+ """
+ _BaseInteractor.__init__(self, base, axes, color=color)
+ self.markers = []
+ self.axes = axes
+ self.x = math.fabs(x)
+ self.save_x = self.x
+ self.y = math.fabs(y)
+ self.save_y = y
+ try:
+ # Inner circle marker
+ self.inner_marker = self.axes.plot([self.x], [0], linestyle='',
+ marker='s', markersize=10,
+ color=self.color, alpha=0.6,
+ pickradius=5, label="pick",
+ # Prefer this to other lines
+ zorder=zorder, visible=True)[0]
+ except:
+ self.inner_marker = self.axes.plot([self.x], [0], linestyle='',
+ marker='s', markersize=10,
+ color=self.color, alpha=0.6,
+ label="pick", visible=True)[0]
+ message = "\nTHIS PROTOTYPE NEEDS THE LATEST VERSION"
+ message += " OF MATPLOTLIB\n Get the SVN version that is"
+ message += " at least as recent as June 1, 2007"
+
+ self.right_line = self.axes.plot([self.x, self.x],
+ [self.y , -self.y],
+ linestyle='-', marker='',
+ color=self.color, visible=True)[0]
+ self.left_line = self.axes.plot([-self.x, -self.x],
+ [self.y, -self.y],
+ linestyle='-', marker='',
+ color=self.color, visible=True)[0]
+ self.has_move = False
+ self.connect_markers([self.right_line, self.inner_marker])
+ self.update()
+
+ def set_layer(self, n):
+ """
+ Allow adding plot to the same panel
+
+ :param n: the number of layer
+
+ """
+ self.layernum = n
+ self.update()
+
+ def clear(self):
+ """
+ Clear this slicer and its markers
+ """
+ self.clear_markers()
+ try:
+ self.inner_marker.remove()
+ self.left_line.remove()
+ self.right_line.remove()
+ except:
+ # Old version of matplotlib
+ for item in range(len(self.axes.lines)):
+ del self.axes.lines[0]
+
+ def update(self, x=None, y=None):
+ """
+ Draw the new roughness on the graph.
+
+ :param x: x-coordinates to reset current class x
+ :param y: y-coordinates to reset current class y
+
+ """
+ ## reset x, y -coordinates if given as parameters
+ if x != None:
+ self.x = numpy.sign(self.x) * math.fabs(x)
+ if y != None:
+ self.y = numpy.sign(self.y) * math.fabs(y)
+ ## draw lines and markers
+ self.inner_marker.set(xdata=[self.x], ydata=[0])
+ self.left_line.set(xdata=[-self.x, -self.x], ydata=[self.y, -self.y])
+ self.right_line.set(xdata=[self.x, self.x], ydata=[self.y, -self.y])
+
+ def save(self, ev):
+ """
+ Remember the roughness for this layer and the next so that we
+ can restore on Esc.
+ """
+ self.save_x = self.x
+ self.save_y = self.y
+ self.base.freeze_axes()
+
+ def moveend(self, ev):
+ """
+ Called after a dragging this edge and set self.has_move to False
+ to specify the end of dragging motion
+ """
+ self.has_move = False
+ self.base.moveend(ev)
+
+ def restore(self):
+ """
+ Restore the roughness for this layer.
+ """
+ self.x = self.save_x
+ self.y = self.save_y
+
+ def move(self, x, y, ev):
+ """
+ Process move to a new position, making sure that the move is allowed.
+ """
+ self.has_move = True
+ self.x = x
+ self.base.base.update()
+
+
+class BoxInteractorX(BoxInteractor):
+ """
+ Average in Qx direction
+ """
+ def __init__(self, base, axes, color='black', zorder=3):
+ BoxInteractor.__init__(self, base, axes, color=color)
+ self.base = base
+ self._post_data()
+
+ def _post_data(self):
+ """
+ Post data creating by averaging in Qx direction
+ """
+ from DataLoader.manipulations import SlabX
+ self.post_data(SlabX, direction="X")
+
+
+class BoxInteractorY(BoxInteractor):
+ """
+ Average in Qy direction
+ """
+ def __init__(self, base, axes, color='black', zorder=3):
+ BoxInteractor.__init__(self, base, axes, color=color)
+ self.base = base
+ self._post_data()
+
+ def _post_data(self):
+ """
+ Post data creating by averaging in Qy direction
+ """
+ from DataLoader.manipulations import SlabY
+ self.post_data(SlabY, direction="Y")
+
+
Index: test/test_rename_guiframe/local_perspectives/plotting/boxSum.py
===================================================================
--- test/test_rename_guiframe/local_perspectives/plotting/boxSum.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/local_perspectives/plotting/boxSum.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,833 @@
+
+
+
+import math
+import wx
+from copy import deepcopy
+from BaseInteractor import _BaseInteractor
+from sans.guiframe.events import SlicerParamUpdateEvent
+from sans.guiframe.events import EVT_SLICER_PARS
+from sans.guiframe.events import StatusEvent
+
+
+class BoxSum(_BaseInteractor):
+ """
+ Boxsum Class: determine 2 rectangular area to compute
+ the sum of pixel of a Data.
+ Uses PointerInteractor , VerticalDoubleLine,HorizontalDoubleLine.
+ @param zorder: Artists with lower zorder values are drawn first.
+ @param x_min: the minimum value of the x coordinate
+ @param x_max: the maximum value of the x coordinate
+ @param y_min: the minimum value of the y coordinate
+ @param y_max: the maximum value of the y coordinate
+
+ """
+ def __init__(self, base, axes, color='black', zorder=3, x_min=0.008,
+ x_max=0.008, y_min=0.0025, y_max=0.0025):
+ """
+ """
+ _BaseInteractor.__init__(self, base, axes, color=color)
+ ## class initialization
+ ## list of Boxsmun markers
+ self.markers = []
+ self.axes = axes
+ ## connect the artist for the motion
+ self.connect = self.base.connect
+ ## when qmax is reached the selected line is reset the its previous value
+ self.qmax = min(self.base.data2D.xmax, self.base.data2D.xmin)
+ ## Define the boxsum limits
+ self.xmin = -1 * 0.5 * min(math.fabs(self.base.data2D.xmax),
+ math.fabs(self.base.data2D.xmin))
+ self.ymin = -1 * 0.5 * min(math.fabs(self.base.data2D.xmax),
+ math.fabs(self.base.data2D.xmin))
+ self.xmax = 0.5 * min(math.fabs(self.base.data2D.xmax),
+ math.fabs(self.base.data2D.xmin))
+ self.ymax = 0.5 * min(math.fabs(self.base.data2D.xmax),
+ math.fabs(self.base.data2D.xmin))
+ ## center of the boxSum
+ self.center_x = 0.0002
+ self.center_y = 0.0003
+ ## Number of points on the plot
+ self.nbins = 20
+ ## Define initial result the summation
+ self.count = 0
+ self.error = 0
+ ## Flag to determine if the current figure has moved
+ ## set to False == no motion , set to True== motion
+ self.has_move = False
+ ## Create Boxsum edges
+ self.horizontal_lines= HorizontalDoubleLine(self,
+ self.base.subplot,
+ color='blue',
+ zorder=zorder,
+ y=self.ymax,
+ x=self.xmax,
+ center_x=self.center_x,
+ center_y=self.center_y)
+ self.horizontal_lines.qmax = self.qmax
+
+ self.vertical_lines= VerticalDoubleLine(self,
+ self.base.subplot,
+ color='black',
+ zorder=zorder,
+ y=self.ymax,
+ x=self.xmax,
+ center_x=self.center_x,
+ center_y=self.center_y)
+ self.vertical_lines.qmax = self.qmax
+
+ self.center= PointInteractor(self,
+ self.base.subplot,color='grey',
+ zorder=zorder,
+ center_x= self.center_x,
+ center_y= self.center_y)
+ ## Save the name of the slicer panel associate with this slicer
+ self.panel_name = ""
+ ## Update and post slicer parameters
+ self.update()
+ self._post_data()
+ ## Bind to slice parameter events
+ self.base.Bind(EVT_SLICER_PARS, self._onEVT_SLICER_PARS)
+
+ def set_panel_name(self, name):
+ """
+ Store the name of the panel associated to this slicer
+ @param name: the name of this panel
+ """
+ self.panel_name = name
+
+ def _onEVT_SLICER_PARS(self, event):
+ """
+ receive an event containing parameters values to reset the slicer
+ @param event: event of type SlicerParameterEvent with params as
+ attribute
+ """
+ ## Post e message to declare what kind of event has being received
+ wx.PostEvent(self.base.parent,
+ StatusEvent(status="Boxsum._onEVT_SLICER_PARS"))
+ event.Skip()
+ ## reset the slicer with the values contains the event.params dictionary
+ if event.type == self.__class__.__name__:
+ self.set_params(event.params)
+ self.base.update()
+
+ def set_layer(self, n):
+ """
+ Allow adding plot to the same panel
+ :param n: the number of layer
+ """
+ self.layernum = n
+ self.update()
+
+ def clear(self):
+ """
+ Clear the slicer and all connected events related to this slicer
+ """
+ self.clear_markers()
+ self.horizontal_lines.clear()
+ self.vertical_lines.clear()
+ self.center.clear()
+ self.base.connect.clearall()
+ self.base.Unbind(EVT_SLICER_PARS)
+
+ def update(self):
+ """
+ Respond to changes in the model by recalculating the profiles and
+ resetting the widgets.
+ """
+ ## check if the center point has moved and update the figure accordingly
+ if self.center.has_move:
+ self.center.update()
+ self.horizontal_lines.update( center= self.center)
+ self.vertical_lines.update( center= self.center)
+ ## check if the horizontal lines have moved and
+ #update the figure accordingly
+ if self.horizontal_lines.has_move:
+ self.horizontal_lines.update()
+ self.vertical_lines.update(y1=self.horizontal_lines.y1,
+ y2=self.horizontal_lines.y2,
+ height=self.horizontal_lines.half_height)
+ ## check if the vertical lines have moved and
+ #update the figure accordingly
+ if self.vertical_lines.has_move:
+ self.vertical_lines.update()
+ self.horizontal_lines.update(x1=self.vertical_lines.x1,
+ x2=self.vertical_lines.x2,
+ width=self.vertical_lines.half_width)
+
+ def save(self, ev):
+ """
+ Remember the roughness for this layer and the next so that we
+ can restore on Esc.
+ """
+ self.base.freeze_axes()
+ self.horizontal_lines.save(ev)
+ self.vertical_lines.save(ev)
+ self.center.save(ev)
+
+ def _post_data(self):
+ """
+ Get the limits of the boxsum and compute the sum of the pixel
+ contained in that region and the error on that sum
+ """
+ ## Data 2D for which the pixel will be summed
+ data = self.base.data2D
+ ## the region of the summation
+ x_min = self.horizontal_lines.x2
+ x_max = self.horizontal_lines.x1
+ y_min = self.vertical_lines.y2
+ y_max = self.vertical_lines.y1
+ ##computation of the sum and its error
+ from DataLoader.manipulations import Boxavg
+ box = Boxavg(x_min=x_min, x_max=x_max, y_min=y_min, y_max=y_max)
+ self.count, self.error = box(self.base.data2D)
+
+ def moveend(self, ev):
+ """
+ After a dragging motion this function is called to compute
+ the error and the sum of pixel of a given data 2D
+ """
+ self.base.thaw_axes()
+ ## compute error an d sum of data's pixel
+ self._post_data()
+ ## Create and event ( posted to guiframe)that set the
+ ##current slicer parameter to a panel of name self.panel_name
+ self.type = self.__class__.__name__
+ params = self.get_params()
+ event = SlicerParamUpdateEvent(type=self.type,
+ params=params,
+ panel_name=self.panel_name)
+ wx.PostEvent(self.base.parent, event)
+
+ def restore(self):
+ """
+ Restore the roughness for this layer.
+ """
+ self.horizontal_lines.restore()
+ self.vertical_lines.restore()
+ self.center.restore()
+
+ def move(self, x, y, ev):
+ """
+ Process move to a new position, making sure that the move is allowed.
+ """
+ pass
+
+ def set_cursor(self, x, y):
+ """
+ """
+ pass
+
+ def get_params(self):
+ """
+ Store a copy of values of parameters of the slicer into a dictionary.
+ :return params: the dictionary created
+ """
+ params = {}
+ params["Width"] = math.fabs(self.vertical_lines.half_width) * 2
+ params["Height"] = math.fabs(self.horizontal_lines.half_height) * 2
+ params["center_x"] = self.center.x
+ params["center_y"] = self.center.y
+ params["count"] = self.count
+ params["errors"] = self.error
+ return params
+
+ def get_result(self):
+ """
+ return the result of box summation
+ """
+ result = {}
+ result["count"] = self.count
+ result["error"] = self.error
+ return result
+
+ def set_params(self, params):
+ """
+ Receive a dictionary and reset the slicer with values contained
+ in the values of the dictionary.
+ :param params: a dictionary containing name of slicer parameters and
+ values the user assigned to the slicer.
+ """
+ x_max = math.fabs(params["Width"] )/2
+ y_max = math.fabs(params["Height"] )/2
+
+ self.center_x = params["center_x"]
+ self.center_y = params["center_y"]
+ #update the slicer given values of params
+ self.center.update(center_x=self.center_x, center_y=self.center_y)
+ self.horizontal_lines.update(center=self.center,
+ width=x_max, height=y_max)
+ self.vertical_lines.update(center=self.center,
+ width=x_max, height=y_max)
+ #compute the new error and sum given values of params
+ self._post_data()
+
+ def freeze_axes(self):
+ """
+ """
+ self.base.freeze_axes()
+
+ def thaw_axes(self):
+ """
+ """
+ self.base.thaw_axes()
+
+ def draw(self):
+ """
+ """
+ self.base.draw()
+
+
+
+class PointInteractor(_BaseInteractor):
+ """
+ Draw a point that can be dragged with the marker.
+ this class controls the motion the center of the BoxSum
+ """
+ def __init__(self, base, axes, color='black', zorder=5, center_x=0.0,
+ center_y=0.0):
+ """
+ """
+ _BaseInteractor.__init__(self, base, axes, color=color)
+ ## Initialization the class
+ self.markers = []
+ self.axes = axes
+ # center coordinates
+ self.x = center_x
+ self.y = center_y
+ ## saved value of the center coordinates
+ self.save_x = center_x
+ self.save_y = center_y
+ ## Create a marker
+ try:
+ self.center_marker = self.axes.plot([self.x],[self.y], linestyle='',
+ marker='s', markersize=10,
+ color=self.color, alpha=0.6,
+ pickradius=5, label="pick",
+ # Prefer this to other lines
+ zorder=zorder,
+ visible=True)[0]
+ except:
+ self.center_marker = self.axes.plot([self.x],[self.y], linestyle='',
+ marker='s', markersize=10,
+ color=self.color, alpha=0.6,
+ label="pick",
+ visible=True)[0]
+ message = "\nTHIS PROTOTYPE NEEDS THE LATEST VERSION"
+ message += " OF MATPLOTLIB.\n Get the SVN version that is "
+ message += "at least as recent as June 1, 2007"
+ owner = self.base.base.parent
+ wx.PostEvent(owner,
+ StatusEvent(status="AnnulusSlicer: %s" % message))
+ ## Draw a point
+ self.center = self.axes.plot([self.x], [self.y],
+ linestyle='-', marker='',
+ color=self.color,
+ visible=True)[0]
+ ## Flag to determine the motion this point
+ self.has_move = False
+ ## connecting the marker to allow them to move
+ self.connect_markers([self.center_marker])
+ ## Update the figure
+ self.update()
+
+ def set_layer(self, n):
+ """
+ Allow adding plot to the same panel
+ @param n: the number of layer
+ """
+ self.layernum = n
+ self.update()
+
+ def clear(self):
+ """
+ Clear this figure and its markers
+ """
+ self.clear_markers()
+ try:
+ self.center.remove()
+ self.center_marker.remove()
+ except:
+ # Old version of matplotlib
+ for item in range(len(self.axes.lines)):
+ del self.axes.lines[0]
+
+ def update(self, center_x=None,center_y=None):
+ """
+ Draw the new roughness on the graph.
+ """
+ if center_x != None:
+ self.x = center_x
+ if center_y != None:
+ self.y = center_y
+ self.center_marker.set(xdata=[self.x], ydata=[self.y])
+ self.center.set(xdata=[self.x], ydata=[self.y])
+
+ def save(self, ev):
+ """
+ Remember the roughness for this layer and the next so that we
+ can restore on Esc.
+ """
+ self.save_x = self.x
+ self.save_y = self.y
+ self.base.freeze_axes()
+
+ def moveend(self, ev):
+ """
+ """
+ self.has_move=False
+ self.base.moveend(ev)
+
+ def restore(self):
+ """
+ Restore the roughness for this layer.
+ """
+ self.y = self.save_y
+ self.x = self.save_x
+
+ def move(self, x, y, ev):
+ """
+ Process move to a new position, making sure that the move is allowed.
+ """
+ self.x = x
+ self.y = y
+ self.has_move = True
+ self.base.base.update()
+
+ def set_cursor(self, x, y):
+ """
+ """
+ self.move(x, y, None)
+ self.update()
+
+ def get_params(self):
+ """
+ """
+ params = {}
+ params["x"] = self.x
+ params["y"] = self.y
+ return params
+
+ def set_params(self, params):
+ """
+ """
+ center_x = params["x"]
+ center_y = params["y"]
+ self.update(center_x=center_x, center_y=center_y)
+
+
+class VerticalDoubleLine(_BaseInteractor):
+ """
+ Draw 2 vertical lines moving in opposite direction and centered on
+ a point (PointInteractor)
+ """
+ def __init__(self, base, axes, color='black', zorder=5, x=0.5,y=0.5,
+ center_x=0.0, center_y=0.0):
+ """
+ """
+ _BaseInteractor.__init__(self, base, axes, color=color)
+ ## Initialization the class
+ self.markers = []
+ self.axes = axes
+ ## Center coordinates
+ self.center_x = center_x
+ self.center_y = center_y
+ ## defined end points vertical lignes and their saved values
+ self.y1 = y + self.center_y
+ self.save_y1= self.y1
+
+ delta = self.y1 - self.center_y
+ self.y2 = self.center_y - delta
+ self.save_y2 = self.y2
+
+ self.x1 = x + self.center_x
+ self.save_x1 = self.x1
+
+ delta = self.x1 - self.center_x
+ self.x2 = self.center_x - delta
+ self.save_x2 = self.x2
+ ## save the color of the line
+ self.color = color
+ ## the height of the rectangle
+ self.half_height = math.fabs(y)
+ self.save_half_height = math.fabs(y)
+ ## the with of the rectangle
+ self.half_width = math.fabs(self.x1- self.x2)/2
+ self.save_half_width = math.fabs(self.x1- self.x2)/2
+ ## Create marker
+ try:
+ self.right_marker = self.axes.plot([self.x1],[0], linestyle='',
+ marker='s', markersize=10,
+ color=self.color, alpha=0.6,
+ pickradius=5, label="pick",
+ # Prefer this to other lines
+ zorder=zorder, visible=True)[0]
+ except:
+ self.right_marker = self.axes.plot([self.x1],[0], linestyle='',
+ marker='s', markersize=10,
+ color=self.color, alpha=0.6,
+ label="pick", visible=True)[0]
+ message = "\nTHIS PROTOTYPE NEEDS THE LATEST "
+ message += "VERSION OF MATPLOTLIB\n Get the SVN version that"
+ message += " is at least as recent as June 1, 2007"
+ owner = self.base.base.parent
+ wx.PostEvent(owner,
+ StatusEvent(status="AnnulusSlicer: %s" % message))
+
+ ## define the left and right lines of the rectangle
+ self.right_line = self.axes.plot([self.x1, self.x1], [self.y1, self.y2],
+ linestyle='-', marker='',
+ color=self.color, visible=True)[0]
+ self.left_line = self.axes.plot([self.x2, self.x2], [self.y1, self.y2],
+ linestyle='-', marker='',
+ color=self.color, visible=True)[0]
+ ## Flag to determine if the lines have moved
+ self.has_move = False
+ ## connection the marker and draw the pictures
+ self.connect_markers([self.right_marker])
+ self.update()
+
+ def set_layer(self, n):
+ """
+ Allow adding plot to the same panel
+ :param n: the number of layer
+ """
+ self.layernum = n
+ self.update()
+
+ def clear(self):
+ """
+ Clear this slicer and its markers
+ """
+ self.clear_markers()
+ try:
+ self.right_marker.remove()
+ self.right_line.remove()
+ self.left_line.remove()
+ except:
+ # Old version of matplotlib
+ for item in range(len(self.axes.lines)):
+ del self.axes.lines[0]
+
+ def update(self, x1=None, x2=None, y1=None, y2=None,width=None,
+ height=None, center=None):
+ """
+ Draw the new roughness on the graph.
+ :param x1: new maximum value of x coordinates
+ :param x2: new minimum value of x coordinates
+ :param y1: new maximum value of y coordinates
+ :param y2: new minimum value of y coordinates
+ :param width: is the width of the new rectangle
+ :param height: is the height of the new rectangle
+ :param center: provided x, y coordinates of the center point
+ """
+ ## save the new height, witdh of the rectangle if given as a param
+ if width != None:
+ self.half_width = width
+ if height != None:
+ self.half_height = height
+ ## If new center coordinates are given draw the rectangle
+ ##given these value
+ if center != None:
+ self.center_x = center.x
+ self.center_y = center.y
+ self.x1 = self.half_width + self.center_x
+ self.x2= -self.half_width + self.center_x
+ self.y1 = self.half_height + self.center_y
+ self.y2= -self.half_height + self.center_y
+
+ self.right_marker.set(xdata=[self.x1], ydata=[self.center_y])
+ self.right_line.set(xdata=[self.x1, self.x1],
+ ydata=[self.y1, self.y2])
+ self.left_line.set(xdata=[self.x2, self.x2],
+ ydata=[self.y1, self.y2])
+ return
+ ## if x1, y1, y2, y3 are given draw the rectangle with this value
+ if x1 != None:
+ self.x1 = x1
+ if x2 != None:
+ self.x2 = x2
+ if y1 != None:
+ self.y1 = y1
+ if y2 != None:
+ self.y2 = y2
+ ## Draw 2 vertical lines and a marker
+ self.right_marker.set(xdata=[self.x1], ydata=[self.center_y])
+ self.right_line.set(xdata=[self.x1, self.x1], ydata=[self.y1, self.y2])
+ self.left_line.set(xdata=[self.x2, self.x2], ydata=[self.y1, self.y2])
+
+ def save(self, ev):
+ """
+ Remember the roughness for this layer and the next so that we
+ can restore on Esc.
+ """
+ self.save_x2 = self.x2
+ self.save_y2 = self.y2
+ self.save_x1 = self.x1
+ self.save_y1 = self.y1
+ self.save_half_height = self.half_height
+ self.save_half_width = self.half_width
+ self.base.freeze_axes()
+
+ def moveend(self, ev):
+ """
+ After a dragging motion reset the flag self.has_move to False
+ """
+ self.has_move = False
+ self.base.moveend(ev)
+
+ def restore(self):
+ """
+ Restore the roughness for this layer.
+ """
+ self.y2 = self.save_y2
+ self.x2 = self.save_x2
+ self.y1 = self.save_y1
+ self.x1 = self.save_x1
+ self.half_height = self.save_half_height
+ self.half_width = self.save_half_width
+
+ def move(self, x, y, ev):
+ """
+ Process move to a new position, making sure that the move is allowed.
+ """
+ self.x1 = x
+ delta = self.x1 - self.center_x
+ self.x2 = self.center_x - delta
+ self.half_width = math.fabs(self.x1 - self.x2)/2
+ self.has_move = True
+ self.base.base.update()
+
+ def set_cursor(self, x, y):
+ """
+ Update the figure given x and y
+ """
+ self.move(x, y, None)
+ self.update()
+
+ def get_params(self):
+ """
+ Store a copy of values of parameters of the slicer into a dictionary.
+ @return params: the dictionary created
+ """
+ params = {}
+ params["x"] = self.x1
+ params["y"] = self.y1
+ return params
+
+ def set_params(self, params):
+ """
+ Receive a dictionary and reset the slicer with values contained
+ in the values of the dictionary.
+ @param params: a dictionary containing name of slicer parameters and
+ values the user assigned to the slicer.
+ """
+ x = params["x"]
+ y = params["y"]
+ self.update(x=x, y=y, center_x=None, center_y=None)
+
+
+class HorizontalDoubleLine(_BaseInteractor):
+ """
+ Select an annulus through a 2D plot
+ """
+ def __init__(self, base, axes, color='black', zorder=5, x=0.5, y=0.5,
+ center_x=0.0, center_y=0.0):
+
+ _BaseInteractor.__init__(self, base, axes, color=color)
+ ## Initialization the class
+ self.markers = []
+ self.axes = axes
+ ## Center coordinates
+ self.center_x = center_x
+ self.center_y = center_y
+ self.y1 = y + self.center_y
+ self.save_y1 = self.y1
+ delta = self.y1 - self.center_y
+ self.y2 = self.center_y - delta
+ self.save_y2 = self.y2
+ self.x1 = x + self.center_x
+ self.save_x1 = self.x1
+ delta = self.x1 - self.center_x
+ self.x2 = self.center_x - delta
+ self.save_x2 = self.x2
+ self.color = color
+ self.half_height= math.fabs(y)
+ self.save_half_height = math.fabs(y)
+ self.half_width = math.fabs(x)
+ self.save_half_width = math.fabs(x)
+ try:
+ self.top_marker = self.axes.plot([0], [self.y1], linestyle='',
+ marker='s', markersize=10,
+ color=self.color, alpha=0.6,
+ pickradius=5, label="pick",
+ # Prefer this to other lines
+ zorder=zorder, visible=True)[0]
+ except:
+ self.top_marker = self.axes.plot([0], [self.y1], linestyle='',
+ marker='s', markersize=10,
+ color=self.color, alpha=0.6,
+ label="pick", visible=True)[0]
+ message = "\nTHIS PROTOTYPE NEEDS THE LATEST VERSION "
+ message += "OF MATPLOTLIB\n Get the SVN version "
+ message += "that is at least as recent as June 1, 2007"
+ owner = self.base.base.parent
+ wx.PostEvent(owner,
+ StatusEvent(status="AnnulusSlicer: %s" % message))
+
+ # Define 2 horizotnal lines
+ self.top_line = self.axes.plot([self.x1, -self.x1], [self.y1, self.y1],
+ linestyle='-', marker='',
+ color=self.color, visible=True)[0]
+ self.bottom_line = self.axes.plot([self.x1, -self.x1],
+ [self.y2, self.y2],
+ linestyle='-', marker='',
+ color=self.color, visible=True)[0]
+ ## Flag to determine if the lines have moved
+ self.has_move = False
+ ## connection the marker and draw the pictures
+ self.connect_markers([self.top_marker])
+ self.update()
+
+ def set_layer(self, n):
+ """
+ Allow adding plot to the same panel
+ @param n: the number of layer
+ """
+ self.layernum = n
+ self.update()
+
+ def clear(self):
+ """
+ Clear this figure and its markers
+ """
+ self.clear_markers()
+ try:
+ self.top_marker.remove()
+ self.bottom_line.remove()
+ self.top_line.remove()
+ except:
+ # Old version of matplotlib
+ for item in range(len(self.axes.lines)):
+ del self.axes.lines[0]
+
+ def update(self, x1=None, x2=None, y1=None, y2=None,
+ width=None, height=None, center=None):
+ """
+ Draw the new roughness on the graph.
+ :param x1: new maximum value of x coordinates
+ :param x2: new minimum value of x coordinates
+ :param y1: new maximum value of y coordinates
+ :param y2: new minimum value of y coordinates
+ :param width: is the width of the new rectangle
+ :param height: is the height of the new rectangle
+ :param center: provided x, y coordinates of the center point
+ """
+ ## save the new height, witdh of the rectangle if given as a param
+ if width != None:
+ self.half_width = width
+ if height!= None:
+ self.half_height = height
+ ## If new center coordinates are given draw the rectangle
+ ##given these value
+ if center != None:
+ self.center_x = center.x
+ self.center_y = center.y
+ self.x1 = self.half_width + self.center_x
+ self.x2 = -self.half_width + self.center_x
+
+ self.y1 = self.half_height + self.center_y
+ self.y2 = -self.half_height + self.center_y
+
+ self.top_marker.set(xdata=[self.center_x], ydata=[self.y1])
+ self.top_line.set(xdata=[self.x1, self.x2],
+ ydata=[self.y1, self.y1])
+ self.bottom_line.set(xdata=[self.x1, self.x2],
+ ydata=[self.y2, self.y2])
+ return
+ ## if x1, y1, y2, y3 are given draw the rectangle with this value
+ if x1 != None:
+ self.x1 = x1
+ if x2 != None:
+ self.x2 = x2
+ if y1 != None:
+ self.y1 = y1
+ if y2 != None:
+ self.y2 = y2
+ ## Draw 2 vertical lines and a marker
+ self.top_marker.set(xdata=[self.center_x], ydata=[self.y1])
+ self.top_line.set(xdata=[self.x1, self.x2], ydata=[self.y1, self.y1])
+ self.bottom_line.set(xdata=[self.x1, self.x2], ydata=[self.y2, self.y2])
+
+ def save(self, ev):
+ """
+ Remember the roughness for this layer and the next so that we
+ can restore on Esc.
+ """
+ self.save_x2 = self.x2
+ self.save_y2 = self.y2
+ self.save_x1 = self.x1
+ self.save_y1 = self.y1
+ self.save_half_height = self.half_height
+ self.save_half_width = self.half_width
+ self.base.freeze_axes()
+
+ def moveend(self, ev):
+ """
+ After a dragging motion reset the flag self.has_move to False
+ """
+ self.has_move = False
+ self.base.moveend(ev)
+
+ def restore(self):
+ """
+ Restore the roughness for this layer.
+ """
+ self.y2 = self.save_y2
+ self.x2 = self.save_x2
+ self.y1 = self.save_y1
+ self.x1 = self.save_x1
+ self.half_height = self.save_half_height
+ self.half_width = self.save_half_width
+
+ def move(self, x, y, ev):
+ """
+ Process move to a new position, making sure that the move is allowed.
+ """
+ self.y1 = y
+ delta = self.y1 - self.center_y
+ self.y2 = self.center_y - delta
+ self.half_height = math.fabs(self.y1) - self.center_y
+ self.has_move = True
+ self.base.base.update()
+
+ def set_cursor(self, x, y):
+ """
+ Update the figure given x and y
+ """
+ self.move(x, y, None)
+ self.update()
+
+ def get_params(self):
+ """
+ Store a copy of values of parameters of the slicer into a dictionary.
+ :return params: the dictionary created
+ """
+ params = {}
+ params["x"] = self.x
+ params["y"] = self.y
+ return params
+
+ def set_params(self, params):
+ """
+ Receive a dictionary and reset the slicer with values contained
+ in the values of the dictionary.
+ :param params: a dictionary containing name of slicer parameters and
+ values the user assigned to the slicer.
+ """
+ x = params["x"]
+ y = params["y"]
+ self.update(x=x, y=y, center_x=None,center_y=None)
+
+
+
Index: test/test_rename_guiframe/local_perspectives/plotting/detector_dialog.py
===================================================================
--- test/test_rename_guiframe/local_perspectives/plotting/detector_dialog.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/local_perspectives/plotting/detector_dialog.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,319 @@
+#!/usr/bin/env python
+
+# version
+__id__ = "$Id: aboutdialog.py 1193 2007-05-03 17:29:59Z dmitriy $"
+__revision__ = "$Revision: 1193 $"
+
+import wx
+import sys
+from sans.guiframe.utils import format_number
+from sans.guiframe.events import StatusEvent
+from sans.guiframe.events import NewPlotEvent
+
+import matplotlib
+from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as Canvas
+from matplotlib import pyplot
+from matplotlib import mpl
+from matplotlib import pylab
+#FONT size
+if sys.platform.count("win32") > 0:
+ FONT_VARIANT = 0
+else:
+ FONT_VARIANT = 1
+
+DEFAULT_CMAP = pylab.cm.jet
+
+class DetectorDialog(wx.Dialog):
+ """
+ Dialog box to let the user edit detector settings
+ """
+
+ def __init__(self, parent, id=1, base=None, dpi=None,
+ cmap=DEFAULT_CMAP, reset_zmin_ctl = None,
+ reset_zmax_ctl = None, *args, **kwds):
+ """
+ """
+ kwds["style"] = wx.DEFAULT_DIALOG_STYLE
+ wx.Dialog.__init__(self, parent, id=1, *args, **kwds)
+ self.SetWindowVariant(variant=FONT_VARIANT)
+ self.parent = base
+ self.dpi = dpi
+ self.cmap = cmap
+ self.reset_zmin_ctl = reset_zmin_ctl
+ self.reset_zmax_ctl = reset_zmax_ctl
+ self.label_xnpts = wx.StaticText(self, -1, "Detector width in pixels")
+ self.label_ynpts = wx.StaticText(self, -1, "Detector Height in pixels")
+ self.label_qmax = wx.StaticText(self, -1, "Q max")
+ self.label_zmin = wx.StaticText(self, -1,
+ "Min amplitude for color map (optional)")
+ self.label_zmax = wx.StaticText(self, -1,
+ "Max amplitude for color map (optional)")
+ self.label_beam = wx.StaticText(self, -1,
+ "Beam stop radius in units of q")
+ self.xnpts_ctl = wx.StaticText(self, -1, "")
+ self.ynpts_ctl = wx.StaticText(self, -1, "")
+ self.qmax_ctl = wx.StaticText(self, -1, "")
+ self.beam_ctl = wx.StaticText(self, -1, "")
+ self.zmin_ctl = wx.TextCtrl(self, -1, size=(60, 20))
+ self.zmin_ctl.Bind(wx.EVT_SET_FOCUS, self.onSetFocus)
+ self.zmax_ctl = wx.TextCtrl(self, -1, size=(60, 20))
+ self.zmax_ctl.Bind(wx.EVT_SET_FOCUS, self.onSetFocus)
+ self.static_line_3 = wx.StaticLine(self, -1)
+ self.button_Cancel = wx.Button(self, wx.ID_CANCEL, "Cancel")
+ self.button_reset = wx.Button(self, wx.NewId(), "Reset")
+ self.Bind(wx.EVT_BUTTON, self.resetValues, self.button_reset)
+ self.button_OK = wx.Button(self, wx.ID_OK, "OK")
+ self.Bind(wx.EVT_BUTTON, self.checkValues, self.button_OK)
+ self.__set_properties()
+ self.__do_layout()
+ self.Fit()
+
+ class Event:
+ """
+ """
+ xnpts = 0
+ ynpts = 0
+ qpax = 0
+ beam = 0
+ zmin = 0
+ zmax = 0
+ cmap = None
+ sym4 = False
+
+ def onSetFocus(self, event):
+ """
+ Highlight the txtcrtl
+ """
+ # Get a handle to the TextCtrl
+ widget = event.GetEventObject()
+ # Select the whole control, after this event resolves
+ wx.CallAfter(widget.SetSelection, -1, -1)
+
+ def resetValues(self, event):
+ """
+ reset detector info
+ """
+ try:
+ zmin = self.reset_zmin_ctl
+ zmax = self.reset_zmax_ctl
+ if zmin == None:
+ zmin = ""
+ if zmax == None:
+ zmax = ""
+ self.zmin_ctl.SetValue(str(zmin))
+ self.zmax_ctl.SetValue(str(zmax))
+ self.cmap = DEFAULT_CMAP
+ self.cmap_selector.SetStringSelection("jet")
+ self._on_select_cmap(event=None)
+ except:
+ msg = "error occurs while resetting Detector: %s" % sys.exc_value
+ wx.PostEvent(self.parent, StatusEvent(status=msg))
+
+ def checkValues(self, event):
+ """
+ Check the valitidity of zmin and zmax value
+ zmax should be a float and zmin less than zmax
+ """
+ flag = True
+ try:
+ value = self.zmin_ctl.GetValue()
+ #if value and float( value) == 0.0:
+ # flag = False
+ # wx.PostEvent(self.parent,
+ # StatusEvent(status="Enter number greater than zero"))
+ # self.zmin_ctl.SetBackgroundColour("pink")
+ # self.zmin_ctl.Refresh()
+ #else:
+ self.zmin_ctl.SetBackgroundColour(wx.WHITE)
+ self.zmin_ctl.Refresh()
+ except:
+ flag = False
+ wx.PostEvent(self.parent, StatusEvent(status="Enter float value"))
+ self.zmin_ctl.SetBackgroundColour("pink")
+ self.zmin_ctl.Refresh()
+ try:
+ value = self.zmax_ctl.GetValue()
+ if value and float(value) == 0.0:
+ flag = False
+ wx.PostEvent(self.parent,
+ StatusEvent(status="Enter number greater than zero"))
+ self.zmax_ctl.SetBackgroundColour("pink")
+ self.zmax_ctl.Refresh()
+ else:
+ self.zmax_ctl.SetBackgroundColour(wx.WHITE)
+ self.zmax_ctl.Refresh()
+ except:
+ flag = False
+ wx.PostEvent(self.parent, StatusEvent(status="Enter Integer value"))
+ self.zmax_ctl.SetBackgroundColour("pink")
+ self.zmax_ctl.Refresh()
+ if flag:
+ event.Skip(True)
+
+ def setContent(self, xnpts, ynpts, qmax, beam,
+ zmin=None, zmax=None, sym=False):
+ """
+ received value and displayed them
+
+ :param xnpts: the number of point of the x_bins of data
+ :param ynpts: the number of point of the y_bins of data
+ :param qmax: the maxmimum value of data pixel
+ :param beam: the radius of the beam
+ :param zmin: the value to get the minimum color
+ :param zmax: the value to get the maximum color
+ :param sym:
+
+ """
+ self.xnpts_ctl.SetLabel(str(format_number(xnpts)))
+ self.ynpts_ctl.SetLabel(str(format_number(ynpts)))
+ self.qmax_ctl.SetLabel(str(format_number(qmax)))
+ self.beam_ctl.SetLabel(str(format_number(beam)))
+ if zmin != None:
+ self.zmin_ctl.SetValue(str(format_number(zmin)))
+ if zmax != None:
+ self.zmax_ctl.SetValue(str(format_number(zmax)))
+
+ def getContent(self):
+ """
+ return event containing value to reset the detector of a given data
+ """
+ event = self.Event()
+ t_min = self.zmin_ctl.GetValue()
+ t_max = self.zmax_ctl.GetValue()
+ v_min = None
+ v_max = None
+ if len(t_min.lstrip()) > 0:
+ try:
+ v_min = float(t_min)
+ except:
+ v_min = None
+ if len(t_max.lstrip()) > 0:
+ try:
+ v_max = float(t_max)
+ except:
+ v_max = None
+ event.zmin = v_min
+ event.zmax = v_max
+ event.cmap = self.cmap
+ return event
+
+ def __set_properties(self):
+ """
+ set proprieties of the dialog window
+ """
+ self.SetTitle("2D Color Map")
+ self.SetSize((600, 595))
+
+ def __do_layout(self):
+ """
+ fill the dialog window .
+ """
+ sizer_main = wx.BoxSizer(wx.VERTICAL)
+ sizer_button = wx.BoxSizer(wx.HORIZONTAL)
+ sizer_params = wx.GridBagSizer(5, 5)
+ sizer_colormap = wx.BoxSizer(wx.VERTICAL)
+ sizer_selection = wx.BoxSizer(wx.HORIZONTAL)
+
+ iy = 0
+ sizer_params.Add(self.label_xnpts, (iy, 0), (1, 1),
+ wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
+ sizer_params.Add(self.xnpts_ctl, (iy, 1), (1, 1),
+ wx.EXPAND|wx.ADJUST_MINSIZE, 0)
+ iy += 1
+ sizer_params.Add(self.label_ynpts, (iy, 0), (1, 1),
+ wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
+ sizer_params.Add(self.ynpts_ctl, (iy, 1), (1, 1),
+ wx.EXPAND|wx.ADJUST_MINSIZE, 0)
+ iy += 1
+ sizer_params.Add(self.label_qmax, (iy, 0), (1, 1),
+ wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
+ sizer_params.Add(self.qmax_ctl, (iy, 1), (1, 1),
+ wx.EXPAND|wx.ADJUST_MINSIZE, 0)
+ iy += 1
+ sizer_params.Add(self.label_beam, (iy, 0), (1, 1),
+ wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
+ sizer_params.Add(self.beam_ctl, (iy, 1), (1, 1),
+ wx.EXPAND|wx.ADJUST_MINSIZE, 0)
+ iy += 1
+ sizer_params.Add(self.label_zmin, (iy, 0), (1, 1),
+ wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
+ sizer_params.Add(self.zmin_ctl, (iy, 1), (1, 1),
+ wx.EXPAND|wx.ADJUST_MINSIZE, 0)
+ iy += 1
+ sizer_params.Add(self.label_zmax, (iy, 0), (1, 1),
+ wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
+ sizer_params.Add(self.zmax_ctl, (iy, 1), (1, 1),
+ wx.EXPAND|wx.ADJUST_MINSIZE, 0)
+ iy += 1
+ self.fig = mpl.figure.Figure(dpi=self.dpi, figsize=(4, 1))
+ self.ax1 = self.fig.add_axes([0.05, 0.65, 0.9, 0.15])
+ self.norm = mpl.colors.Normalize(vmin=0, vmax=100)
+ self.cb1 = mpl.colorbar.ColorbarBase(self.ax1, cmap=self.cmap,
+ norm= self.norm,
+ orientation='horizontal')
+ self.cb1.set_label('Detector Colors')
+ self.canvas = Canvas(self, -1, self.fig)
+ sizer_colormap.Add(self.canvas, 0, wx.LEFT | wx.EXPAND,5)
+ self.cmap_selector = wx.ComboBox(self, -1)
+ self.cmap_selector.SetValue(str(self.cmap.name))
+ maps = sorted(m for m in pylab.cm.datad if not m.endswith("_r"))
+
+ for i, m in enumerate(maps):
+ self.cmap_selector.Append(str(m), pylab.get_cmap(m))
+
+ wx.EVT_COMBOBOX(self.cmap_selector, -1, self._on_select_cmap)
+ sizer_selection.Add(wx.StaticText(self, -1,"Select Cmap: "), 0,
+ wx.LEFT|wx.ADJUST_MINSIZE, 5)
+ sizer_selection.Add(self.cmap_selector, 0, wx.EXPAND|wx.ALL, 10)
+ sizer_main.Add(sizer_params, 0, wx.EXPAND|wx.ALL, 10)
+ sizer_main.Add(sizer_selection, 0, wx.EXPAND|wx.ALL, 10)
+ sizer_main.Add(sizer_colormap, 1, wx.EXPAND|wx.ALL, 10)
+ sizer_main.Add(self.static_line_3, 0, wx.EXPAND, 0)
+ sizer_button.Add(self.button_reset, 0, wx.LEFT|wx.ADJUST_MINSIZE, 100)
+ sizer_button.Add(self.button_OK, 0, wx.LEFT|wx.ADJUST_MINSIZE, 10)
+ sizer_button.Add(self.button_Cancel, 0,
+ wx.LEFT|wx.RIGHT|wx.ADJUST_MINSIZE, 10)
+ sizer_main.Add(sizer_button, 0, wx.EXPAND|wx.BOTTOM|wx.TOP, 10)
+ self.SetAutoLayout(True)
+ self.SetSizer(sizer_main)
+ self.Layout()
+ self.Centre()
+ # end wxGlade
+
+ def _on_select_cmap(self, event):
+ """
+ display a new cmap
+ """
+ cmap_name = self.cmap_selector.GetCurrentSelection()
+ current_cmap = self.cmap_selector.GetClientData(cmap_name)
+ self.cmap = current_cmap
+ self.cb1 = mpl.colorbar.ColorbarBase(self.ax1, cmap=self.cmap,
+ norm=self.norm, orientation='horizontal')
+ self.canvas.draw()
+
+
+# end of class DialogAbout
+
+##### testing code ############################################################
+class MyApp(wx.App):
+ def OnInit(self):
+ wx.InitAllImageHandlers()
+ dialog = DetectorDialog(None, -1, "")
+ self.SetTopWindow(dialog)
+ dialog.setContent(xnpts=128, ynpts=128, qmax=20,
+ beam=20, zmin=2, zmax=60, sym=False)
+ print dialog.ShowModal()
+ evt = dialog.getContent()
+ if hasattr(evt, "npts"):
+ print "number of point: ", evt.npts
+ if hasattr(evt,"qmax"):
+ print "qmax: ", evt.qmax
+ dialog.Destroy()
+ return 1
+
+# end of class MyApp
+
+if __name__ == "__main__":
+ app = MyApp(0)
+ app.MainLoop()
+
Index: test/test_rename_guiframe/local_perspectives/plotting/help_panel.py
===================================================================
--- test/test_rename_guiframe/local_perspectives/plotting/help_panel.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/local_perspectives/plotting/help_panel.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,111 @@
+#!/usr/bin/python
+"""
+Help panel for plotting
+"""
+import os
+import wx
+import wx.html as html
+from wx.lib.splitter import MultiSplitterWindow
+from sans.guiframe import get_media_path
+
+
+class HelpWindow(wx.Frame):
+ """
+ """
+ def __init__(self, parent, title='Plotting Help', pageToOpen=None):
+ wx.Frame.__init__(self, parent, title, size=(700, 450))
+ """
+ contains help info
+ """
+ splitter = MultiSplitterWindow(self, style=wx.SP_LIVE_UPDATE)
+ rpanel = wx.Panel(splitter, -1)
+ lpanel = wx.Panel(splitter, -1, style=wx.BORDER_SUNKEN)
+
+ vbox = wx.BoxSizer(wx.VERTICAL)
+ header = wx.Panel(rpanel, -1)
+ header.SetBackgroundColour('#6666FF')
+ header.SetForegroundColour('WHITE')
+ hbox = wx.BoxSizer(wx.HORIZONTAL)
+ st = wx.StaticText(header, -1, 'Contents', (5, 5))
+ font = st.GetFont()
+ font.SetPointSize(10)
+ st.SetFont(font)
+ hbox.Add(st, 1, wx.TOP | wx.BOTTOM | wx.LEFT, 5)
+ header.SetSizer(hbox)
+ vbox.Add(header, 0, wx.EXPAND)
+
+ vboxl = wx.BoxSizer(wx.VERTICAL)
+ headerl = wx.Panel(lpanel, -1, size=(-1, 20))
+
+ headerl.SetBackgroundColour('#6666FF')
+ headerl.SetForegroundColour('WHITE')
+ hboxl = wx.BoxSizer(wx.HORIZONTAL)
+ lst = wx.StaticText(headerl, -1, 'Menu', (5, 5))
+ fontl = lst.GetFont()
+ fontl.SetPointSize(10)
+ lst.SetFont(fontl)
+ hboxl.Add(lst, 1, wx.TOP | wx.BOTTOM | wx.LEFT, 5)
+ headerl.SetSizer(hboxl)
+ vboxl.Add(headerl, 0, wx.EXPAND)
+ self.lhelp = html.HtmlWindow(lpanel, -1, style=wx.NO_BORDER)
+ self.rhelp = html.HtmlWindow(rpanel, -1, style=wx.NO_BORDER,
+ size=(500,-1))
+
+ self.path = get_media_path(media='media')
+
+ page1 = """
+
+ Select topic on Menu
+
+ """
+ self.rhelp.SetPage(page1)
+ page = """
+
+
+
+ """
+
+ self.lhelp.SetPage(page)
+ self.lhelp.Bind(wx.html.EVT_HTML_LINK_CLICKED, self.OnLinkClicked)
+
+ vbox.Add(self.rhelp, 1, wx.EXPAND)
+ vboxl.Add(self.lhelp, 1, wx.EXPAND)
+ rpanel.SetSizer(vbox)
+ lpanel.SetSizer(vboxl)
+ lpanel.SetFocus()
+
+ vbox1 = wx.BoxSizer(wx.HORIZONTAL)
+ vbox1.Add(splitter, 1, wx.EXPAND)
+ splitter.AppendWindow(lpanel, 200)
+ splitter.AppendWindow(rpanel)
+ self.SetSizer(vbox1)
+
+ self.Centre()
+ self.Show(True)
+
+ def OnLinkClicked(self, event):
+ """
+ Function to diplay html page related to the hyperlinktext selected
+ """
+ link = event.GetLinkInfo().GetHref()
+ link = os.path.join(self.path, link)
+ self.rhelp.LoadPage(link)
+
+
+class ViewApp(wx.App):
+ def OnInit(self):
+ frame = HelpWindow(None, -1, 'HelpWindow')
+ frame.Show(True)
+ self.SetTopWindow(frame)
+ return True
+
+if __name__ == "__main__":
+ app = ViewApp(0)
+ app.MainLoop()
Index: test/test_rename_guiframe/local_perspectives/plotting/masking.py
===================================================================
--- test/test_rename_guiframe/local_perspectives/plotting/masking.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/local_perspectives/plotting/masking.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,588 @@
+
+################################################################################
+#This software was developed by the University of Tennessee as part of the
+#Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
+#project funded by the US National Science Foundation.
+#
+#If you use DANSE applications to do scientific research that leads to
+#publication, we ask that you acknowledge the use of the software with the
+#following sentence:
+#
+#This work benefited from DANSE software developed under NSF award DMR-0520547.
+#
+#copyright 2008, University of Tennessee
+################################################################################
+
+
+##Todo: cleaning up, improving the maskplotpanel initialization, and testing.
+import wx
+import sys
+import pylab
+import math
+import copy
+import numpy
+from danse.common.plottools.PlotPanel import PlotPanel
+from danse.common.plottools.plottables import Graph
+from binder import BindArtist
+from sans.guiframe.dataFitting import Data2D
+from boxMask import BoxMask
+from sectorMask import SectorMask
+from sans.guiframe.events import SlicerEvent
+from sans.guiframe.events import StatusEvent
+(InternalEvent, EVT_INTERNAL) = wx.lib.newevent.NewEvent()
+
+DEFAULT_CMAP = pylab.cm.jet
+_BOX_WIDTH = 76
+_SCALE = 1e-6
+_STATICBOX_WIDTH = 380
+PANEL_SIZE = 420
+#SLD panel size
+if sys.platform.count("win32") > 0:
+ FONT_VARIANT = 0
+else:
+ FONT_VARIANT = 1
+
+
+class MaskPanel(wx.Dialog):
+ """
+ Provides the Mask Editor GUI.
+ """
+ ## Internal nickname for the window, used by the AUI manager
+ window_name = "Mask Editor"
+ ## Name to appear on the window title bar
+ window_caption = "Mask Editor"
+ ## Flag to tell the AUI manager to put this panel in the center pane
+ CENTER_PANE = True
+ def __init__(self, parent=None, base=None,
+ data=None, id=-1, *args, **kwds):
+ kwds["style"] = wx.DEFAULT_DIALOG_STYLE
+ kwds["size"] = wx.Size(_STATICBOX_WIDTH * 2, PANEL_SIZE)
+ wx.Dialog.__init__(self, parent, id=id, *args, **kwds)
+
+ if data != None:
+ #Font size
+ kwds = []
+ self.SetWindowVariant(variant=FONT_VARIANT)
+ self.SetTitle("Mask Editor for " + data.name)
+ self.parent = base
+ self.data = data
+ self.str = self.data.__str__()
+ ## mask for 2D
+ self.mask = data.mask
+ self.default_mask = copy.deepcopy(data.mask)
+ ## masked data from GUI
+ self.slicer_mask = None
+ self.slicer = None
+ self.slicer_z = 5
+ self.data.interactive = True
+ ## when 2 data have the same id override the 1 st plotted
+ self.name = self.data.name
+ # Panel for 2D plot
+ self.plotpanel = Maskplotpanel(self, -1,
+ style=wx.TRANSPARENT_WINDOW)
+ self.cmap = DEFAULT_CMAP
+ ## Create Artist and bind it
+ self.subplot = self.plotpanel.subplot
+ self.connect = BindArtist(self.subplot.figure)
+ self._setup_layout()
+ self.newplot = Data2D(image=self.data.data)
+ self.newplot.setValues(self.data)
+ self.plotpanel.add_image(self.newplot)
+ self._update_mask(self.mask)
+ self.Centre()
+ self.Layout()
+ # bind evt_close to _draw in fitpage
+ self.Bind(wx.EVT_CLOSE, self.OnClose)
+
+ def ShowMessage(self, msg=''):
+ """
+ Show error message when mask covers whole data area
+ """
+ mssg = 'Erase, redraw or clear the mask. \n\r'
+ mssg += 'The data range can not be completely masked... \n\r'
+ mssg += msg
+ wx.MessageBox(mssg, 'Error', wx.OK | wx.ICON_ERROR)
+
+ def _setup_layout(self):
+ """
+ Set up the layout
+ """
+ shape = "Select a Shape for Masking:"
+ # panel
+ sizer = wx.GridBagSizer(10, 10)
+ #---------inputs----------------
+ shape_txt = wx.StaticText(self, -1, shape)
+ sizer.Add(shape_txt, (1, 1), flag=wx.TOP|wx.LEFT|wx.BOTTOM, border=5)
+ self.innersector_rb = wx.RadioButton(self, -1, "Double Wings")
+ self.Bind(wx.EVT_RADIOBUTTON, self.onInnerSectorMask,
+ id=self.innersector_rb.GetId())
+ sizer.Add(self.innersector_rb, (2, 1),
+ flag=wx.RIGHT|wx.BOTTOM, border=5)
+ self.innercircle_rb = wx.RadioButton(self, -1, "Circular Disk")
+ self.Bind(wx.EVT_RADIOBUTTON, self.onInnerRingMask,
+ id=self.innercircle_rb.GetId())
+ sizer.Add(self.innercircle_rb, (3, 1),
+ flag=wx.RIGHT|wx.BOTTOM, border=5)
+
+ self.innerbox_rb = wx.RadioButton(self, -1, "Rectangular Disk")
+ self.Bind(wx.EVT_RADIOBUTTON, self.onInnerBoxMask,
+ id=self.innerbox_rb.GetId())
+ sizer.Add(self.innerbox_rb, (4, 1), flag=wx.RIGHT|wx.BOTTOM, border=5)
+
+ self.outersector_rb = wx.RadioButton(self, -1, "Double Wing Window")
+ self.Bind(wx.EVT_RADIOBUTTON, self.onOuterSectorMask,
+ id=self.outersector_rb.GetId())
+ sizer.Add(self.outersector_rb, (5, 1),
+ flag=wx.RIGHT|wx.BOTTOM, border=5)
+
+ #outersector_y_txt = wx.StaticText(self, -1, 'Outer Sector')
+ self.outercircle_rb = wx.RadioButton(self, -1, "Circular Window")
+ self.Bind(wx.EVT_RADIOBUTTON, self.onOuterRingMask,
+ id=self.outercircle_rb.GetId())
+ sizer.Add(self.outercircle_rb, (6, 1),
+ flag=wx.RIGHT|wx.BOTTOM, border=5)
+ #outerbox_txt = wx.StaticText(self, -1, 'Outer Box')
+ self.outerbox_rb = wx.RadioButton(self, -1, "Rectangular Window")
+ self.Bind(wx.EVT_RADIOBUTTON, self.onOuterBoxMask,
+ id=self.outerbox_rb.GetId())
+ sizer.Add(self.outerbox_rb, (7, 1), flag=wx.RIGHT|wx.BOTTOM, border=5)
+ self.innercircle_rb.SetValue(False)
+ self.outercircle_rb.SetValue(False)
+ self.innerbox_rb.SetValue(False)
+ self.outerbox_rb.SetValue(False)
+ self.innersector_rb.SetValue(False)
+ self.outersector_rb.SetValue(False)
+ sizer.Add(self.plotpanel, (0, 2), (13, 13),
+ wx.EXPAND|wx.LEFT|wx.RIGHT, 15)
+
+ #-----Buttons------------1
+ id_button = wx.NewId()
+ button_add = wx.Button(self, id_button, "Add")
+ button_add.SetToolTipString("Add the mask drawn.")
+ button_add.Bind(wx.EVT_BUTTON, self.onAddMask, id=button_add.GetId())
+ sizer.Add(button_add, (13, 7))
+ id_button = wx.NewId()
+ button_erase = wx.Button(self, id_button, "Erase")
+ button_erase.SetToolTipString("Erase the mask drawn.")
+ button_erase.Bind(wx.EVT_BUTTON, self.onEraseMask,
+ id=button_erase.GetId())
+ sizer.Add(button_erase, (13, 8))
+ id_button = wx.NewId()
+ button_reset = wx.Button(self, id_button, "Reset")
+ button_reset.SetToolTipString("Reset the mask.")
+ button_reset.Bind(wx.EVT_BUTTON, self.onResetMask,
+ id=button_reset.GetId())
+ sizer.Add(button_reset, (13, 9), flag=wx.RIGHT|wx.BOTTOM, border=15)
+ id_button = wx.NewId()
+ button_reset = wx.Button(self, id_button, "Clear")
+ button_reset.SetToolTipString("Clear all mask.")
+ button_reset.Bind(wx.EVT_BUTTON, self.onClearMask,
+ id=button_reset.GetId())
+ sizer.Add(button_reset, (13, 10), flag=wx.RIGHT|wx.BOTTOM, border=15)
+ sizer.AddGrowableCol(3)
+ sizer.AddGrowableRow(2)
+ self.SetSizerAndFit(sizer)
+ self.Centre()
+ self.Show(True)
+
+ def onInnerBoxMask(self, event=None):
+ """
+ Call Draw Box Slicer and get mask inside of the box
+ """
+ #get ready for next evt
+ event.Skip()
+ #from boxMask import BoxMask
+ if event != None:
+ self.onClearSlicer(event)
+ self.slicer_z += 1
+ self.slicer = BoxMask(self, self.subplot,
+ zorder=self.slicer_z, side=True)
+ self.subplot.set_ylim(self.data.ymin, self.data.ymax)
+ self.subplot.set_xlim(self.data.xmin, self.data.xmax)
+ self.update()
+ self.slicer_mask = self.slicer.update()
+
+ def onOuterBoxMask(self, event=None):
+ """
+ Call Draw Box Slicer and get mask outside of the box
+ """
+ event.Skip()
+ #from boxMask import BoxMask
+ if event != None:
+ self.onClearSlicer(event)
+ self.slicer_z += 1
+ self.slicer = BoxMask(self, self.subplot,
+ zorder=self.slicer_z, side=False)
+ self.subplot.set_ylim(self.data.ymin, self.data.ymax)
+ self.subplot.set_xlim(self.data.xmin, self.data.xmax)
+ self.update()
+ self.slicer_mask = self.slicer.update()
+
+ def onInnerSectorMask(self, event=None):
+ """
+ Call Draw Sector Slicer and get mask inside of the sector
+ """
+ event.Skip()
+ from sectorMask import SectorMask
+ if event != None:
+ self.onClearSlicer(event)
+ self.slicer_z += 1
+ self.slicer = SectorMask(self, self.subplot,
+ zorder=self.slicer_z, side=True)
+ self.subplot.set_ylim(self.data.ymin, self.data.ymax)
+ self.subplot.set_xlim(self.data.xmin, self.data.xmax)
+ self.update()
+ self.slicer_mask = self.slicer.update()
+
+ def onOuterSectorMask(self,event=None):
+ """
+ Call Draw Sector Slicer and get mask outside of the sector
+ """
+ event.Skip()
+ from sectorMask import SectorMask
+ if event != None:
+ self.onClearSlicer(event)
+ self.slicer_z += 1
+ self.slicer = SectorMask(self, self.subplot,
+ zorder=self.slicer_z, side=False)
+ self.subplot.set_ylim(self.data.ymin, self.data.ymax)
+ self.subplot.set_xlim(self.data.xmin, self.data.xmax)
+ self.update()
+ self.slicer_mask = self.slicer.update()
+
+ def onInnerRingMask(self, event=None):
+ """
+ Perform inner circular cut on Phi and draw circular slicer
+ """
+ event.Skip()
+ from AnnulusSlicer import CircularMask
+ if event != None:
+ self.onClearSlicer(event)
+ self.slicer_z += 1
+ self.slicer = CircularMask(self, self.subplot,
+ zorder=self.slicer_z, side=True)
+ self.subplot.set_ylim(self.data.ymin, self.data.ymax)
+ self.subplot.set_xlim(self.data.xmin, self.data.xmax)
+ self.update()
+ self.slicer_mask = self.slicer.update()
+
+ def onOuterRingMask(self, event=None):
+ """
+ Perform outer circular cut on Phi and draw circular slicer
+ """
+ event.Skip()
+ from AnnulusSlicer import CircularMask
+ if event != None:
+ self.onClearSlicer(event)
+ self.slicer_z += 1
+ self.slicer = CircularMask(self,self.subplot,
+ zorder=self.slicer_z, side=False)
+ self.subplot.set_ylim(self.data.ymin, self.data.ymax)
+ self.subplot.set_xlim(self.data.xmin, self.data.xmax)
+ self.update()
+ self.slicer_mask = self.slicer.update()
+
+ def onAddMask(self, event):
+ """
+ Add new mask to old mask
+ """
+ if not self.slicer == None:
+ data = Data2D()
+ data = self.data
+ self.slicer_mask = self.slicer.update()
+ data.mask = self.data.mask & self.slicer_mask
+ self._check_display_mask(data.mask, event)
+
+ def _check_display_mask(self, mask, event):
+ """
+ check if the mask valid and update the plot
+
+ :param mask: mask data
+ """
+ ## Redraw the current image
+ self._update_mask(mask)
+
+ def onEraseMask(self, event):
+ """
+ Erase new mask from old mask
+ """
+ if not self.slicer==None:
+ self.slicer_mask = self.slicer.update()
+ mask = self.data.mask
+ mask[self.slicer_mask==False] = True
+ self._check_display_mask(mask, event)
+
+ def onResetMask(self, event):
+ """
+ Reset mask to the original mask
+ """
+ self.slicer_z += 1
+ self.slicer = BoxMask(self, self.subplot,
+ zorder=self.slicer_z, side=True)
+ self.subplot.set_ylim(self.data.ymin, self.data.ymax)
+ self.subplot.set_xlim(self.data.xmin, self.data.xmax)
+ mask = copy.deepcopy(self.default_mask)
+ self.data.mask = mask
+ # update mask plot
+ self._check_display_mask(mask, event)
+
+ def onClearMask(self, event):
+ """
+ Clear mask
+ """
+ self.slicer_z += 1
+ self.slicer = BoxMask(self, self.subplot,
+ zorder=self.slicer_z, side=True)
+ self.subplot.set_ylim(self.data.ymin, self.data.ymax)
+ self.subplot.set_xlim(self.data.xmin, self.data.xmax)
+ #mask = copy.deepcopy(self.default_mask)
+ mask = numpy.ones(len(self.data.mask), dtype=bool)
+ self.data.mask = mask
+ # update mask plot
+ self._check_display_mask(mask, event)
+
+ def onClearSlicer(self, event):
+ """
+ Clear the slicer on the plot
+ """
+ if not self.slicer == None:
+ self.slicer.clear()
+ self.subplot.figure.canvas.draw()
+ self.slicer = None
+
+ def _setSlicer(self):
+ """
+ Clear the previous slicer and create a new one.Post an internal
+ event.
+
+ :param slicer: slicer class to create
+ """
+ ## Clear current slicer
+ if not self.slicer == None:
+ self.slicer.clear()
+ ## Create a new slicer
+ self.slicer_z += 1
+ self.slicer = slicer(self, self.subplot, zorder=self.slicer_z)
+ self.subplot.set_ylim(self.data2D.ymin, self.data2D.ymax)
+ self.subplot.set_xlim(self.data2D.xmin, self.data2D.xmax)
+ ## Draw slicer
+ self.update()
+ self.slicer.update()
+ msg = "Plotter2D._setSlicer %s"%self.slicer.__class__.__name__
+ wx.PostEvent(self.parent, StatusEvent(status=msg))
+ # Post slicer event
+ event = self._getEmptySlicerEvent()
+ event.type = self.slicer.__class__.__name__
+ event.obj_class = self.slicer.__class__
+ event.params = self.slicer.get_params()
+ wx.PostEvent(self, event)
+
+ def update(self, draw=True):
+ """
+ Respond to changes in the model by recalculating the
+ profiles and resetting the widgets.
+ """
+ self.plotpanel.draw()
+
+ def _set_mask(self, mask):
+ """
+ Set mask
+ """
+ self.data.mask = mask
+
+ def _update_mask(self,mask):
+ """
+ Respond to changes in masking
+ """
+ # the case of liitle numbers of True points
+ if (len(mask[mask]) < 10 and self.data != None):
+ self.ShowMessage()
+ mask = copy.deepcopy(self.mask)
+ self.data.mask = mask
+ else:
+ self.mask = mask
+ # make temperary data to plot
+ temp_mask = numpy.zeros(len(mask))
+ temp_data = copy.deepcopy(self.data)
+ # temp_data default is None
+ # This method is to distinguish between masked point and data point = 0.
+ temp_mask = temp_mask/temp_mask
+ temp_mask[mask] = temp_data.data[mask]
+ # set temp_data value for self.mask==True, else still None
+ #temp_mask[mask] = temp_data[mask]
+ temp_data.data[mask==False] = temp_mask[mask==False]
+ self.plotpanel.clear()
+ if self.slicer != None:
+ self.slicer.clear()
+ self.slicer = None
+ # Post slicer None event
+ event = self._getEmptySlicerEvent()
+ wx.PostEvent(self, event)
+
+ ##use this method
+ #set zmax and zmin to plot: Fix it w/ data.
+ if self.plotpanel.scale == 'log':
+ zmax = math.log(max(self.data.data[self.data.data>0]))
+ zmin = math.log(min(self.data.data[self.data.data>0]))
+ else:
+ zmax = max(self.data.data[self.data.data>0])
+ zmin = min(self.data.data[self.data.data>0])
+ #plot
+ plot = self.plotpanel.image(data=temp_mask,
+ qx_data=self.data.qx_data,
+ qy_data=self.data.qy_data,
+ xmin=self.data.xmin,
+ xmax=self.data.xmax,
+ ymin=self.data.ymin,
+ ymax=self.data.ymax,
+ zmin=zmin,
+ zmax=zmax,
+ cmap=self.cmap,
+ color=0, symbol=0, label=self.data.name)
+ # axis labels
+ self.plotpanel.axes[0].set_xlabel('$\\rm{Q}_{x}(A^{-1})$')
+ self.plotpanel.axes[0].set_ylabel('$\\rm{Q}_{y}(A^{-1})$')
+ self.plotpanel.render()
+ self.plotpanel.subplot.figure.canvas.draw_idle()
+
+ def _getEmptySlicerEvent(self):
+ """
+ create an empty slicervent
+ """
+ self.innerbox_rb.SetValue(False)
+ self.outerbox_rb.SetValue(False)
+ self.innersector_rb.SetValue(False)
+ self.outersector_rb.SetValue(False)
+ self.innercircle_rb.SetValue(False)
+ self.outercircle_rb.SetValue(False)
+ return SlicerEvent(type=None,
+ params=None,
+ obj_class=None)
+
+ def _draw_model(self, event):
+ """
+ on_close, update the model2d plot
+ """
+ pass
+
+ def freeze_axes(self):
+ """
+ freeze axes
+ """
+ self.plotpanel.axes_frozen = True
+
+ def thaw_axes(self):
+ """
+ thaw axes
+ """
+ self.plotpanel.axes_frozen = False
+
+ def onMouseMotion(self, event):
+ """
+ onMotion event
+ """
+ pass
+
+ def onWheel(self, event):
+ """
+ on wheel event
+ """
+ pass
+
+ def OnClose(self, event):
+ """
+ """
+ self.parent._draw_masked_model(event)
+
+class Maskplotpanel(PlotPanel):
+ """
+ """
+ def __init__(self, parent, id=-1, color=None, dpi=None, **kwargs):
+ """
+ """
+ PlotPanel.__init__(self, parent, id=id, color=color, dpi=dpi, **kwargs)
+
+ # Keep track of the parent Frame
+ self.parent = parent
+ # Internal list of plottable names (because graph
+ # doesn't have a dictionary of handles for the plottables)
+ self.plots = {}
+ self.graph = Graph()
+
+ def add_toolbar(self):
+ """
+ Add toolbar
+ """
+ # Not implemented
+ pass
+ def on_set_focus(self, event):
+ """
+ send to the parenet the current panel on focus
+ """
+ #change the panel background
+ #self.SetColor((170, 202, 255))
+ self.draw()
+
+ def add_image(self, plot):
+ """
+ Add Image
+ """
+ self.plots[plot.name] = plot
+ #init graph
+ self.gaph = Graph()
+ #add plot
+ self.graph.add(plot)
+ #add axes
+ self.graph.xaxis('\\rm{Q}_{x} ', 'A^{-1}')
+ self.graph.yaxis('\\rm{Q}_{y} ', 'A^{-1}')
+ #draw
+ self.graph.render(self)
+ self.subplot.figure.canvas.draw_idle()
+
+ def onMouseMotion(self, event):
+ """
+ Disable dragging 2D image
+ """
+ pass
+
+ def onContextMenu(self, event):
+ """
+ Default context menu for a plot panel
+ """
+ # Slicer plot popup menu
+ slicerpop = wx.Menu()
+
+ id_cm = wx.NewId()
+ slicerpop.Append(id_cm, '&Toggle Linear/Log scale')
+ wx.EVT_MENU(self, id_cm, self._onToggleScale)
+
+ pos = event.GetPosition()
+ pos = self.ScreenToClient(pos)
+ self.PopupMenu(slicerpop, pos)
+
+class ViewerFrame(wx.Frame):
+ """
+ Add comment
+ """
+ def __init__(self, parent, id, title):
+ """
+ comment
+ :param parent: parent panel/container
+ """
+ # Initialize the Frame object
+ wx.Frame.__init__(self, parent, id, title,
+ wx.DefaultPosition, wx.Size(950, 850))
+ # Panel for 1D plot
+ self.plotpanel = Maskplotpanel(self, -1, style=wx.RAISED_BORDER)
+
+class ViewApp(wx.App):
+ def OnInit(self):
+ frame = ViewerFrame(None, -1, 'testView')
+ frame.Show(True)
+ #self.SetTopWindow(frame)
+
+ return True
+
+if __name__ == "__main__":
+ app = ViewApp(0)
+ app.MainLoop()
Index: test/test_rename_guiframe/local_perspectives/plotting/plotting.py
===================================================================
--- test/test_rename_guiframe/local_perspectives/plotting/plotting.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/local_perspectives/plotting/plotting.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,346 @@
+
+
+
+################################################################################
+#This software was developed by the University of Tennessee as part of the
+#Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
+#project funded by the US National Science Foundation.
+#
+#See the license text in license.txt
+#
+#copyright 2008, University of Tennessee
+################################################################################
+
+import wx
+import sys
+from sans.guiframe.events import EVT_NEW_PLOT
+from sans.guiframe.events import StatusEvent
+from sans.guiframe.events import DeletePlotPanelEvent
+from sans.guiframe.plugin_base import PluginBase
+from sans.guiframe.dataFitting import Data1D
+from sans.guiframe.dataFitting import Data2D
+
+DEFAULT_MENU_ITEM_LABEL = "No graph available"
+DEFAULT_MENU_ITEM_ID = wx.NewId()
+
+if sys.platform.count("darwin")==0:
+ IS_WIN = True
+else:
+ IS_WIN = False
+
+class Plugin(PluginBase):
+ """
+ Plug-in class to be instantiated by the GUI manager
+ """
+
+ def __init__(self, standalone=False):
+ PluginBase.__init__(self, name="Plotting", standalone=standalone)
+
+ ## Plot panels
+ self.plot_panels = {}
+ self._panel_on_focus = None
+ self.menu_default_id = None
+ # Plot menu
+ self.menu = None
+
+
+ def set_panel_on_focus(self, panel):
+ """
+ """
+ self._panel_on_focus = panel
+
+ def is_always_active(self):
+ """
+ return True is this plugin is always active even if the user is
+ switching between perspectives
+ """
+ return True
+
+ def populate_menu(self, parent):
+ """
+ Create a 'Plot' menu to list the panels
+ available for displaying
+
+ :param id: next available unique ID for wx events
+ :param parent: parent window
+
+ """
+ self.menu = wx.Menu()
+ self.menu.Append(DEFAULT_MENU_ITEM_ID, DEFAULT_MENU_ITEM_LABEL,
+ "No graph available")
+ self.menu.FindItemByPosition(0).Enable(False)
+ return [(self.menu, "Show")]
+
+ def get_panels(self, parent):
+ """
+ Create and return a list of panel objects
+ """
+ ## Save a reference to the parent
+ self.parent = parent
+ # Connect to plotting events
+ self.parent.Bind(EVT_NEW_PLOT, self._on_plot_event)
+ # We have no initial panels for this plug-in
+ return []
+
+ def _on_show_panel(self, event):
+ """show plug-in panel"""
+ pass
+
+ def remove_plot(self, group_id, id):
+ """
+ remove plot of ID = id from a panel of group ID =group_id
+ """
+
+ if group_id in self.plot_panels.keys():
+ panel = self.plot_panels[group_id]
+ panel.remove_data_by_id(id=id)
+ return True
+ return False
+
+ def clear_panel(self):
+ """
+ Clear and Hide all plot panels, and remove them from menu
+ """
+ for group_id in self.plot_panels.keys():
+ panel = self.plot_panels[group_id]
+ panel.graph.reset()
+ self.hide_panel(group_id)
+ self.plot_panels = {}
+ item = self.menu.FindItemByPosition(0)
+ while item != None:
+ self.menu.DeleteItem(item)
+ try:
+ item = self.menu.FindItemByPosition(0)
+ except:
+ item = None
+
+
+ def clear_panel_by_id(self, group_id):
+ """
+ clear the graph
+ """
+ if group_id in self.plot_panels.keys():
+ panel = self.plot_panels[group_id]
+ panel.graph.reset()
+ return True
+ return False
+
+
+ def hide_panel(self, group_id):
+ """
+ hide panel with group ID = group_id
+ """
+ if group_id in self.plot_panels.keys():
+ panel = self.plot_panels[group_id]
+ self.parent.hide_panel(panel.uid)
+ return True
+ return False
+
+ def create_panel_helper(self, new_panel, data, group_id, title=None):
+ """
+ """
+ ## Set group ID if available
+ ## Assign data properties to the new create panel
+ new_panel.set_manager(self)
+ new_panel.group_id = group_id
+ if group_id not in data.list_group_id:
+ data.list_group_id.append(group_id)
+ if title is None:
+ title = data.title
+ new_panel.window_caption = title
+ new_panel.window_name = data.title
+ event_id = self.parent.popup_panel(new_panel)
+ #remove the default item in the menu
+ if len(self.plot_panels) == 0:
+ pos = self.menu.FindItem(DEFAULT_MENU_ITEM_LABEL)
+ if pos != -1:
+ self.menu.Delete(DEFAULT_MENU_ITEM_ID)
+
+ self.menu.AppendCheckItem(event_id, new_panel.window_caption,
+ "Show %s plot panel" % new_panel.window_caption)
+ self.menu.Check(event_id, IS_WIN)
+ wx.EVT_MENU(self.parent, event_id, self._on_check_menu)
+
+ wx.EVT_SHOW(new_panel, self._on_close_panel)
+
+ # Set UID to allow us to reference the panel later
+ new_panel.uid = event_id
+ # Ship the plottable to its panel
+ new_panel.plot_data(data)
+ self.plot_panels[new_panel.group_id] = new_panel
+
+
+ def create_1d_panel(self, data, group_id):
+ """
+ """
+ # Create a new plot panel if none was available
+ if issubclass(data.__class__, Data1D):
+ from Plotter1D import ModelPanel1D
+ ## get the data representation label of the data to plot
+ ## when even the user select "change scale"
+ xtransform = data.xtransform
+ ytransform = data.ytransform
+ ## create a plotpanel for 1D Data
+ new_panel = ModelPanel1D(self.parent, -1, xtransform=xtransform,
+ ytransform=ytransform, style=wx.RAISED_BORDER)
+ return new_panel
+
+ msg = "1D Panel of group ID %s could not be created" % str(group_id)
+ raise ValueError, msg
+
+ def create_2d_panel(self, data, group_id):
+ """
+ """
+ if issubclass(data.__class__, Data2D):
+ ##Create a new plotpanel for 2D data
+ from Plotter2D import ModelPanel2D
+ scale = data.scale
+ new_panel = ModelPanel2D(self.parent, id = -1,
+ data2d=data, scale = scale,
+ style=wx.RAISED_BORDER)
+ return new_panel
+ msg = "2D Panel of group ID %s could not be created" % str(group_id)
+ raise ValueError, msg
+
+ def update_panel(self, data, panel):
+ """
+ update the graph of a given panel
+ """
+ # Check whether we already have a graph with the same units
+ # as the plottable we just received.
+ _, x_unit = data.get_xaxis()
+ _, y_unit = data.get_yaxis()
+ flag_x = (panel.graph.prop["xunit"] is not None) and \
+ (panel.graph.prop["xunit"].strip() != "") and\
+ (x_unit != panel.graph.prop["xunit"])
+ flag_y = (panel.graph.prop["yunit"] is not None) and \
+ (panel.graph.prop["yunit"].strip() != "") and\
+ (y_unit != panel.graph.prop["yunit"])
+ if (flag_x and flag_y):
+ msg = "Cannot add %s" % str(data.name)
+ msg += " to panel %s\n" % str(panel.window_caption)
+ msg += "Please edit %s's units, labels" % str(data.name)
+ raise ValueError, msg
+ else:
+ if panel.group_id not in data.list_group_id:
+ data.list_group_id.append(panel.group_id)
+ panel.plot_data( data)
+ self.parent.show_panel(panel.uid)
+
+ def delete_menu_item(self, name, uid):
+ """
+ """
+ #remove menu item
+ pos = self.menu.FindItem(name)
+ if pos != -1:
+ self.menu.Delete(uid)
+ if self.menu.GetMenuItemCount() == 0:
+ self.menu.Append(DEFAULT_MENU_ITEM_ID, DEFAULT_MENU_ITEM_LABEL,
+ "No graph available")
+ self.menu.FindItemByPosition(0).Enable(False)
+
+ def delete_panel(self, group_id):
+ """
+ """
+ if group_id in self.plot_panels.keys():
+ panel = self.plot_panels[group_id]
+ uid = panel.uid
+ wx.PostEvent(self.parent,
+ DeletePlotPanelEvent(name=panel.window_caption,
+ caption=panel.window_caption))
+ #remove menu item
+ self.delete_menu_item(panel.window_caption, panel.uid)
+ del self.plot_panels[group_id]
+ self.parent.delete_panel(uid)
+ return True
+ return False
+
+ def _on_plot_event(self, event):
+ """
+ A new plottable is being shipped to the plotting plug-in.
+ Check whether we have a panel to put in on, or create
+ a new one
+
+ :param event: EVT_NEW_PLOT event
+
+ """
+ if hasattr(event, 'action'):
+ group_id = event.group_id
+ #remove data from panel
+ if event.action.lower() == 'remove':
+ id = event.id
+ return self.remove_plot(group_id, id)
+ if event.action.lower() == 'hide':
+ return self.hide_panel(group_id)
+ if event.action.lower() == 'delete':
+ return self.delete_panel(group_id)
+ if event.action.lower() == "clear":
+ return self.clear_panel_by_id(group_id)
+
+ title = None
+ if hasattr(event, 'title'):
+ title = event.title
+
+ data = event.plot
+ group_id = data.group_id
+
+ if group_id in self.plot_panels.keys():
+ #update a panel graph
+ panel = self.plot_panels[group_id]
+ self.update_panel(data, panel)
+ else:
+ #create a new panel
+ if issubclass(data.__class__, Data1D):
+ new_panel = self.create_1d_panel(data, group_id)
+ else:
+ new_panel = self.create_2d_panel(data, group_id)
+ self.create_panel_helper(new_panel, data, group_id, title)
+
+ return
+
+ def _on_check_menu(self, event):
+ """
+ Check mark on menu
+ """
+ #event.Skip()
+ event_id = event.GetId()
+
+ if self.menu.IsChecked(event_id):
+ self.parent.on_view(event)
+ self.menu.Check(event_id, IS_WIN)
+ else:
+ self.parent.hide_panel(event_id)
+ self.menu.Check(event_id, False)
+
+ def help(self, evt):
+ """
+ Show a general help dialog.
+ """
+ from help_panel import HelpWindow
+ frame = HelpWindow(None, -1, 'HelpWindow')
+ frame.Show(True)
+
+ def _on_close_panel(self, event):
+ """
+ Update check mark on panel's show and hide event
+ """
+ event.Skip()
+ panel = event.GetEventObject()
+ id = panel.uid
+ if event.GetShow() and self.parent._mgr.GetPane(panel).IsShown():
+ try:
+ if self.menu.FindItemById(id) != None:
+ if not self.menu.IsChecked(id):
+ self.menu.Check(id, True)
+ #self.menu.Enable(id, False)
+ except:
+ # when no such item; may happens after delete
+ pass
+ else:
+ try:
+ if self.menu.FindItemById(id) != None:
+ if self.menu.IsChecked(id):
+ self.menu.Check(id, False)
+ #self.menu.Enable(id, True)
+ except:
+ pass
Index: test/test_rename_guiframe/local_perspectives/plotting/profile_dialog.py
===================================================================
--- test/test_rename_guiframe/local_perspectives/plotting/profile_dialog.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/local_perspectives/plotting/profile_dialog.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,261 @@
+"""
+SLD Profile Dialog for multifunctional models
+"""
+import wx
+import sys
+from copy import deepcopy
+from danse.common.plottools.plottables import Graph
+from Plotter1D import ModelPanel1D as PlotPanel
+from sans.guiframe.dataFitting import Theory1D
+import pylab
+
+DEFAULT_CMAP = None#pylab.cm.jet
+_BOX_WIDTH = 76
+_STATICBOX_WIDTH = 400
+# X Y offset on plot
+_X_OFF = 15
+_Y_OFF = 0.5
+
+#SLD panel size
+if sys.platform.count("win32") > 0:
+ _STATICBOX_WIDTH = 563
+ PANEL_SIZE = 425
+ FONT_VARIANT = 0
+else:
+ _STATICBOX_WIDTH = 605
+ PANEL_SIZE = 500
+ FONT_VARIANT = 1
+
+
+class SLDPanel(wx.Dialog):
+ """
+ Provides the SLD profile plot panel.
+ """
+ ## Internal nickname for the window, used by the AUI manager
+ window_name = "SLD Profile"
+ ## Name to appear on the window title bar
+ window_caption = "SLD Profile"
+ ## Flag to tell the AUI manager to put this panel in the center pane
+ CENTER_PANE = True
+ def __init__(self, parent=None, base=None, data=None, axes =['Radius'],
+ id=-1, *args, **kwds):
+ kwds["style"] = wx.DEFAULT_DIALOG_STYLE
+ kwds["size"] = wx.Size(_STATICBOX_WIDTH, PANEL_SIZE)
+ wx.Dialog.__init__(self, parent, id=id, *args, **kwds)
+
+ if data != None:
+ #Font size
+ kwds = []
+ self.SetWindowVariant(variant=FONT_VARIANT)
+ self.SetTitle("Scattering Length Density Profile")
+ self.parent = base
+ self.data = data
+ self.str = self.data.__str__()
+ ## when 2 data have the same id override the 1 st plotted
+ self.name = self.data.name
+ # Panel for plot
+ self.plotpanel = SLDplotpanel(self, axes, -1,
+ style=wx.TRANSPARENT_WINDOW)
+ self.cmap = DEFAULT_CMAP
+ ## Create Artist and bind it
+ self.subplot = self.plotpanel.subplot
+ # layout
+ self._setup_layout()
+ # plot
+ data_plot = deepcopy(self.data)
+ data_plot.dy = self._set_dy_data()
+ # unit increase to M times for users
+ data_plot.y = self._set_y_data()
+
+ self.newplot = Theory1D(data_plot.x, data_plot.y, data_plot.dy)
+ self.newplot.dy = None
+ self.newplot.name = 'SLD'
+ self.plotpanel.add_image(self.newplot)
+ self.plotpanel.subplot.set_ylim(min(data_plot.y) - _Y_OFF ,
+ max(data_plot.y) + _Y_OFF)
+ self.plotpanel.subplot.set_xlim(min(data_plot.x) - _X_OFF,
+ max(data_plot.x) + _X_OFF)
+ #self.Centre()
+ self.Layout()
+
+ def _set_dy_data(self):
+ """
+ make fake dy data
+
+ :return dy:
+ """
+ # set dy as zero
+ dy = [0 for y in self.data.y]
+ return dy
+
+ def _set_y_data(self):
+ """
+ make y data unit Mega times
+
+ :return y_value:
+ """
+ # changes the unit
+ y_value = [yvalue * 1e+006 for yvalue in self.data.y]
+
+ return y_value
+
+ def _setup_layout(self):
+ """
+ Set up the layout
+ """
+ # panel sizer
+ sizer = wx.BoxSizer(wx.VERTICAL)
+ sizer.Add(self.plotpanel, 0, wx.LEFT|wx.RIGHT, 5)
+ sizer.Add(wx.StaticLine(self), 0, wx.ALL|wx.EXPAND, 5)
+ sizer.Add((0, 5))
+ #-----Button------------1
+ id = wx.NewId()
+ button_reset = wx.Button(self, id, "Close")
+ button_reset.SetToolTipString("Close...")
+ button_reset.Bind(wx.EVT_BUTTON, self._close,
+ id=button_reset.GetId())
+ sizer.Add(button_reset, 0, wx.LEFT, _STATICBOX_WIDTH - 80)
+ sizer.Add((0, 10))
+ self.SetSizerAndFit(sizer)
+ self.Centre()
+ self.Show(True)
+ button_reset.SetFocus()
+
+ def _close(self, event):
+ """
+ Close the dialog
+ """
+ self.Close(True)
+
+ def _draw_model(self, event):
+ """
+ on_close, update the model2d plot
+ """
+ pass
+
+ def get_context_menu(self, graph=None):
+ """
+ When the context menu of a plot is rendered, the
+ get_context_menu method will be called to give you a
+ chance to add a menu item to the context menu.
+ :param graph: the Graph object to which we attach the context menu
+
+ :return: a list of menu items with call-back function
+ """
+ return []
+
+ def set_schedule_full_draw(self, panel=None, func=None):
+ """
+ Set_schedule for full draw
+ """
+ # Not implemented
+ pass
+
+ def set_schedule(self, schedule=False):
+ """
+ Set schedule for redraw
+ """
+ # Not implemented
+ pass
+
+ def set_plot_unfocus(self):
+ """
+ Set_plot unfocus
+ """
+ # NOt implemented
+ pass
+
+
+
+class SLDplotpanel(PlotPanel):
+ """
+ Panel
+ """
+ def __init__(self, parent, axes=[], id=-1, color=None, dpi=None,
+ **kwargs):
+ """
+ """
+ PlotPanel.__init__(self, parent, id=id, xtransform='x', ytransform='y',
+ color=color, dpi=dpi,
+ size=(_STATICBOX_WIDTH, PANEL_SIZE-100), **kwargs)
+
+ # Keep track of the parent Frame
+ self.parent = parent
+ # Internal list of plottable names (because graph
+ # doesn't have a dictionary of handles for the plottables)
+ self.plots = {}
+ self.graph = Graph()
+ self.axes_label = []
+ for idx in range(0, len(axes)):
+ self.axes_label.append(axes[idx])
+
+ def add_image(self, plot):
+ """
+ Add image(Theory1D)
+ """
+ self.plots[plot.name] = plot
+ self.plots[plot.name].is_data = False
+ #init graph
+ #self.gaph = Graph()
+ #add plot
+ self.graph.add(plot)
+ #add axes
+ x1_label = self.axes_label[0]
+ self.graph.xaxis('\\rm{%s} '% x1_label, 'A')
+ self.graph.yaxis('\\rm{SLD} ', '10^{-6}A^{-2}')
+ #draw
+ self.graph.render(self)
+ self.subplot.figure.canvas.draw_idle()
+
+ # For latter scale changes
+ self.plots[plot.name].xaxis('\\rm{%s} '% x1_label, 'A')
+ self.plots[plot.name].yaxis('\\rm{SLD} ', '10^{-6}A^{-2}')
+
+ def on_set_focus(self, event):
+ """
+ send to the parenet the current panel on focus
+
+ """
+ #Not implemented
+ pass
+
+ def on_kill_focus(self, event):
+ """
+ reset the panel color
+
+ """
+ #Not implemented
+ pass
+
+ def _add_more_tool(self):
+ """
+ Not implemented
+ """
+ pass
+
+class ViewerFrame(wx.Frame):
+ """
+ Add comment
+ """
+ def __init__(self, parent, id, title):
+ """
+ comment
+ :param parent: parent panel/container
+ """
+ # Initialize the Frame object
+ wx.Frame.__init__(self, parent, id, title, wx.DefaultPosition,
+ wx.Size(_STATICBOX_WIDTH, PANEL_SIZE))
+ # Panel for 1D plot
+ self.plotpanel = SLDplotpanel(self, -1, style=wx.RAISED_BORDER)
+
+class ViewApp(wx.App):
+ def OnInit(self):
+ frame = ViewerFrame(None, -1, 'testView')
+ frame.Show(True)
+ self.SetTopWindow(frame)
+
+ return True
+
+if __name__ == "__main__":
+ app = ViewApp(0)
+ app.MainLoop()
Index: test/test_rename_guiframe/local_perspectives/plotting/sectorMask.py
===================================================================
--- test/test_rename_guiframe/local_perspectives/plotting/sectorMask.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/local_perspectives/plotting/sectorMask.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,220 @@
+
+import math
+import wx
+#from copy import deepcopy
+from BaseInteractor import _BaseInteractor
+from SectorSlicer import SideInteractor
+from SectorSlicer import LineInteractor
+from sans.guiframe.events import SlicerParameterEvent
+
+class SectorMask(_BaseInteractor):
+ """
+ Draw a sector slicer.Allow to find the data 2D inside of the sector lines
+ """
+ def __init__(self, base, axes, color='gray', zorder=3, side=False):
+ """
+ """
+ _BaseInteractor.__init__(self, base, axes, color=color)
+ ## Class initialization
+ self.markers = []
+ self.axes = axes
+ self.is_inside = side
+ ## connect the plot to event
+ self.connect = self.base.connect
+
+ ## compute qmax limit to reset the graph
+ x = math.pow(max(self.base.data.xmax,
+ math.fabs(self.base.data.xmin)), 2)
+ y = math.pow(max(self.base.data.ymax,
+ math.fabs(self.base.data.ymin)), 2)
+ self.qmax = math.sqrt(x + y)
+ ## Number of points on the plot
+ self.nbins = 20
+ ## Angle of the middle line
+ self.theta2 = math.pi/3
+ ## Absolute value of the Angle between the middle line and any side line
+ self.phi = math.pi/12
+
+ ## Middle line
+ self.main_line = LineInteractor(self, self.base.subplot, color='blue',
+ zorder=zorder, r=self.qmax, theta=self.theta2)
+ self.main_line.qmax = self.qmax
+ ## Right Side line
+ self.right_line = SideInteractor(self, self.base.subplot, color='gray',
+ zorder=zorder, r=self.qmax, phi= -1*self.phi,
+ theta2=self.theta2)
+ self.right_line.qmax = self.qmax
+ ## Left Side line
+ self.left_line = SideInteractor(self, self.base.subplot, color='gray',
+ zorder=zorder, r=self.qmax, phi= self.phi,
+ theta2=self.theta2)
+ self.left_line.qmax = self.qmax
+ ## draw the sector
+ self.update()
+ self._post_data()
+
+ def clear(self):
+ """
+ Clear the slicer and all connected events related to this slicer
+ """
+ self.clear_markers()
+ self.main_line.clear()
+ self.left_line.clear()
+ self.right_line.clear()
+ self.base.connect.clearall()
+ #self.base.Unbind(EVT_SLICER_PARS)
+
+ def update(self):
+ """
+ Respond to changes in the model by recalculating the profiles and
+ resetting the widgets.
+ """
+ # Update locations
+ ## Check if the middle line was dragged and
+ #update the picture accordingly
+ if self.main_line.has_move:
+ self.main_line.update()
+ self.right_line.update(delta=-self.left_line.phi/2,
+ mline=self.main_line.theta)
+ self.left_line.update(delta=self.left_line.phi/2,
+ mline=self.main_line.theta)
+ ## Check if the left side has moved and update the slicer accordingly
+ if self.left_line.has_move:
+ self.main_line.update()
+ self.left_line.update(phi=None, delta=None, mline=self.main_line ,
+ side=True, left=True )
+ self.right_line.update(phi=self.left_line.phi, delta=None,
+ mline=self.main_line, side=True,
+ left=False, right=True)
+ ## Check if the right side line has moved and
+ #update the slicer accordingly
+ if self.right_line.has_move:
+ self.main_line.update()
+ self.right_line.update(phi=None, delta=None, mline=self.main_line,
+ side=True, left=False, right=True)
+ self.left_line.update(phi=self.right_line.phi, delta=None,
+ mline=self.main_line, side=True, left=False)
+ #if self.is_inside != None:
+ out = self._post_data()
+ return out
+
+ def save(self, ev):
+ """
+ Remember the roughness for this layer and the next so that we
+ can restore on Esc.
+ """
+ self.base.freeze_axes()
+ self.main_line.save(ev)
+ self.right_line.save(ev)
+ self.left_line.save(ev)
+
+ def _post_data(self):
+ """
+ compute sector averaging of data into data1D
+ """
+ ## get the data to average
+ data = self.base.data
+ # If we have no data, just return
+ if data == None:
+ return
+
+ mask = data.mask
+ ## Averaging
+ from DataLoader.manipulations import Sectorcut
+ radius = self.qmax
+ phimin = -self.left_line.phi + self.main_line.theta
+ phimax = self.left_line.phi + self.main_line.theta
+
+ mask = Sectorcut(phi_min=phimin, phi_max=phimax)
+ if self.is_inside:
+ out = (mask(data) == False)
+ else:
+ out = (mask(data))
+ #self.base.data.mask=out
+ return out
+
+ def moveend(self, ev):
+ """
+ Called a dragging motion ends.Get slicer event
+ """
+ self.base.thaw_axes()
+ ## Post parameters
+ event = SlicerParameterEvent()
+ event.type = self.__class__.__name__
+ event.params = self.get_params()
+ ## Send slicer paramers to plotter2D
+ wx.PostEvent(self.base, event)
+ self._post_data()
+
+ def restore(self):
+ """
+ Restore the roughness for this layer.
+ """
+ self.main_line.restore()
+ self.left_line.restore()
+ self.right_line.restore()
+
+ def move(self, x, y, ev):
+ """
+ Process move to a new position, making sure that the move is allowed.
+ """
+ pass
+
+ def set_cursor(self, x, y):
+ pass
+
+ def get_params(self):
+ """
+ Store a copy of values of parameters of the slicer into a dictionary.
+
+ :return params: the dictionary created
+
+ """
+ params = {}
+ ## Always make sure that the left and the right line are at phi
+ ## angle of the middle line
+ if math.fabs(self.left_line.phi) != math.fabs(self.right_line.phi):
+ msg = "Phi left and phi right are "
+ msg += "different %f, %f" % (self.left_line.phi,
+ self.right_line.phi)
+ raise ValueError, msg
+ params["Phi"] = self.main_line.theta
+ params["Delta_Phi"] = math.fabs(self.left_line.phi)
+ return params
+
+ def set_params(self, params):
+ """
+ Receive a dictionary and reset the slicer with values contained
+ in the values of the dictionary.
+
+ :param params: a dictionary containing name of slicer parameters and
+ values the user assigned to the slicer.
+ """
+ main = params["Phi"]
+ phi = math.fabs(params["Delta_Phi"])
+
+ self.main_line.theta = main
+ ## Reset the slicer parameters
+ self.main_line.update()
+ self.right_line.update(phi=phi, delta=None, mline=self.main_line,
+ side=True, right=True)
+ self.left_line.update(phi=phi, delta=None,
+ mline=self.main_line, side=True)
+ ## post the new corresponding data
+ self._post_data()
+
+ def freeze_axes(self):
+ """
+ """
+ self.base.freeze_axes()
+
+ def thaw_axes(self):
+ """
+ """
+ self.base.thaw_axes()
+
+ def draw(self):
+ """
+ """
+ self.base.update()
+
Index: test/test_rename_guiframe/local_perspectives/plotting/slicerpanel.py
===================================================================
--- test/test_rename_guiframe/local_perspectives/plotting/slicerpanel.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/local_perspectives/plotting/slicerpanel.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,164 @@
+
+
+import wx
+import wx.lib.newevent
+#from copy import deepcopy
+from sans.guiframe.utils import format_number
+from sans.guiframe.events import SlicerParameterEvent
+from sans.guiframe.events import EVT_SLICER_PARS
+from sans.guiframe.events import EVT_SLICER
+
+from sans.guiframe.panel_base import PanelBase
+
+class SlicerPanel(wx.Panel, PanelBase):
+ """
+ Panel class to show the slicer parameters
+ """
+ #TODO: show units
+ #TODO: order parameters properly
+ ## Internal name for the AUI manager
+ window_name = "Slicer panel"
+ ## Title to appear on top of the window
+ window_caption = "Slicer Panel"
+ CENTER_PANE = False
+
+ def __init__(self, parent, id=-1, type=None, base=None,
+ params=None, *args, **kwargs):
+ wx.Panel.__init__(self, parent, id, *args, **kwargs)
+ PanelBase.__init__(self)
+ ## Initialization of the class
+ self.base = base
+ if params is None:
+ params = {}
+ self.params = params
+ self.parent = parent
+ self.type = type
+ self.listeners = []
+ self.parameters = []
+ self.bck = wx.GridBagSizer(5, 5)
+ self.SetSizer(self.bck)
+ if type == None and params == None:
+ label = "Right-click on 2D plot for slicer options"
+ title = wx.StaticText(self, -1, label, style=wx.ALIGN_LEFT)
+ self.bck.Add(title, (0, 0), (1, 2),
+ flag=wx.LEFT|wx.ALIGN_CENTER_VERTICAL, border=15)
+ else:
+ self.set_slicer(type, params)
+ ## Bindings
+ self.parent.Bind(EVT_SLICER, self.onEVT_SLICER)
+ self.parent.Bind(EVT_SLICER_PARS, self.onParamChange)
+
+ def onEVT_SLICER(self, event):
+ """
+ Process EVT_SLICER events
+ When the slicer changes, update the panel
+
+ :param event: EVT_SLICER event
+
+ """
+ event.Skip()
+ if event.obj_class == None:
+ self.set_slicer(None, None)
+ else:
+ self.set_slicer(event.type, event.params)
+
+ def set_slicer(self, type, params):
+ """
+ Rebuild the panel
+ """
+ self.bck.Clear(True)
+ self.type = type
+ if type == None:
+ label = "Right-click on 2D plot for slicer options"
+ title = wx.StaticText(self, -1, label, style=wx.ALIGN_LEFT)
+ self.bck.Add(title, (0, 0), (1, 2),
+ flag=wx.LEFT|wx.ALIGN_CENTER_VERTICAL, border=15)
+ else:
+ title = wx.StaticText(self, -1, "Slicer Parameters",
+ style=wx.ALIGN_LEFT)
+ self.bck.Add(title, (0, 0), (1, 2),
+ flag=wx.LEFT|wx.ALIGN_CENTER_VERTICAL, border=15)
+ n = 1
+ self.parameters = []
+ keys = params.keys()
+ keys.sort()
+ for item in keys:
+ if not item.lower() in ["errors", "count"]:
+ n += 1
+ text = wx.StaticText(self, -1, item, style=wx.ALIGN_LEFT)
+ self.bck.Add(text, (n-1, 0),
+ flag=wx.LEFT|wx.ALIGN_CENTER_VERTICAL, border=15)
+ ctl = wx.TextCtrl(self, -1, size=(80, 20),
+ style=wx.TE_PROCESS_ENTER)
+ hint_msg = "Modify the value of %s to change " % item
+ hint_msg += "the 2D slicer"
+ ctl.SetToolTipString(hint_msg)
+ ctl.SetValue(str(format_number(params[item])))
+ self.Bind(wx.EVT_TEXT_ENTER, self.onTextEnter)
+ ctl.Bind(wx.EVT_SET_FOCUS, self.onSetFocus)
+ ctl.Bind(wx.EVT_KILL_FOCUS, self.onTextEnter)
+ self.parameters.append([item, ctl])
+ self.bck.Add(ctl, (n-1, 1), flag=wx.TOP|wx.BOTTOM, border=0)
+ for item in keys:
+ if item.lower() in ["errors", "count"]:
+ n += 1
+ text = wx.StaticText(self, -1, item + ": ",
+ style=wx.ALIGN_LEFT)
+ self.bck.Add(text, (n-1, 0),
+ flag=wx.LEFT|wx.ALIGN_CENTER_VERTICAL,
+ border=15)
+ ctl = wx.StaticText(self, -1,
+ str(format_number(params[item])),
+ style=wx.ALIGN_LEFT)
+ ctl.SetToolTipString("Result %s" % item)
+ self.bck.Add(ctl, (n-1, 1), flag=wx.TOP|wx.BOTTOM, border=0)
+ self.bck.Layout()
+ #self.bck.Fit(self)
+ self.Layout()
+ self.parent.GetSizer().Layout()
+
+ def onSetFocus(self, evt):
+ """
+ Hightlight the textcrtl
+ """
+ # Get a handle to the TextCtrl
+ widget = evt.GetEventObject()
+ # Select the whole control, after this event resolves
+ wx.CallAfter(widget.SetSelection, -1, -1)
+ return
+
+ def onParamChange(self, evt):
+ """
+ Receive and event and reset the text field contained in self.parameters
+
+ """
+ evt.Skip()
+ for item in self.parameters:
+ if item[0] in evt.params:
+ item[1].SetValue(format_number(evt.params[item[0]]))
+ item[1].Refresh()
+
+ def onTextEnter(self, evt):
+ """
+ Parameters have changed
+ """
+ params = {}
+ has_error = False
+ for item in self.parameters:
+ try:
+ params[item[0]] = float(item[1].GetValue())
+ item[1].SetBackgroundColour(
+ wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW))
+ item[1].Refresh()
+ except:
+ has_error = True
+ item[1].SetBackgroundColour("pink")
+ item[1].Refresh()
+
+ if has_error == False:
+ # Post parameter event
+ ## base is guiframe is this case
+ event = SlicerParameterEvent(type=self.type, params=params)
+ wx.PostEvent(self.base, event)
+
+
Index: test/test_rename_guiframe/media/Graph_help.html
===================================================================
--- test/test_rename_guiframe/media/Graph_help.html (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/media/Graph_help.html (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,94 @@
+
+
+
+Graph Context Menu
+
+
+
+
+ Locating the pointer and right-clicking on a data/theory plot will bring a context menu.
+ On the menu, select a menu item.
+
+
+
+
+ To reset the graph's axis range, right click on the plot and the context menu pops-up.
+ Select Reset Graph and the plot will take its initial range.
+ Also the 'home' icon in tool bar will do the same.
+
+
+
+
+ Right click on plot. Context menu will pop-up select save image [file name].A dialog
+ window opens and write a the name of the file to save and click on Save Image.
+
+
+
+
+ From the context menu, select 'Save points as a file' for 1D, or 'Save as a file(DAT)'
+ for 2D. Note that two formats, txt and xml, are available in 1D saving.
+
+
+
+
+
+Select the crossed arrows button on the plot panel toolbar to drag the plot.
+To disable dragging mode, unselect the same button on the toolbar.
+
+
+
+
+ Highlight the plot and the context menu appears.Select remove [file name] .
+ The plot selected will disappear.
+
+
+
+
+ Select the rectangle button on the plot panel toolbar to zoom in
+ a region of the plot.
+
+
+To disable zoom mode, unselect the same button on the toolbar.
+After zoom in a region, select left arrow or right arrow button on the toolbar
+to set the graph the the previous size.
+If a mouse wheel button is available, zoom in/out by scrolling the mouse wheel
+ ( see 'Key combination' help for details).
+
+
+
+ If the loaded data is a 1-D data.Changing scale or Data Representation will work as
+ followed:right click on the plot window.
+ A context menu pops-up and select Change Scale . A dialog window titled
+ select the scale of the graph will pop-up then change the x , the y
+ and the view values as wish.
+ If the loaded data is an image.Right click on the image to pop-up the context
+ menu. Select to switch from linear to log scale. The scale
+ selected is printed on the statusbar.
+
+
+
+
+
+ Linear fit is to perform a line model fitting keeping the scale of the plot.
+ Highlight data to fit.
+ From the context menu
+ select Linear Fit .A dialog window appears.
+ Change model initial parameters, data limits
+ and hit fit button.
+ New parameters values are displayed and the line with the new
+ parameters is added to the plot.
+
+
+
+
Index: test/test_rename_guiframe/media/averaging_help.html
===================================================================
--- test/test_rename_guiframe/media/averaging_help.html (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/media/averaging_help.html (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,107 @@
+
+
+
+2D Data Averaging
+
+
+
+ This feature allows you to perform different types of averages on your data,
+ and allows you to see what regions of the detector will contribute to
+ the average.
+ The region to be averaged will be drown and can be modified by dragging the lines around.
+
+
+
+
+
+Right click on 2D data for the context menu to appear. Select one type of averages
+among "sector [Q view]", "Annulus [Phi view]", "Box sum", "Box averaging in Qx ",
+"box averaging on Qy","Perform circular Average".
+
+
+A slicer will appear except for "Perform circular Average"
+that you can drag by clicking on a slicer 's marker.
+ When the marker is highlighted in red , it means that the slicer can change size.You can
+ also move some of the slicer by simply drag its side when highlighted in red.
+ the slicer size will be reset to its previous size if the user try to select a region greater
+ than the size of the data.
+
+
+ The user can also select a region to average when a slicer has been selected already by right
+ clicking on the context menu and selecting Edit Slicer Parameters . The dialog window
+ will appears and the user can enter values to selected a region or selected numbers of points to
+ plot nbins .
+
+
+
+ For Box sum , when the user selects this option, a new panel is created containing
+ the result of average of the sum of every pixels contains on that data.The user can also enter
+ values to select a region.
+
+
+
+
+It will perform and average in constant q-rings around the (x,y)
+ pixel location of the beam center.
+
+
+
+
+
+This operation is same as 'Perform Circular Average' except that the masked region is excluded if masked.
+
+
+
+
+It averages in constant q-arcs. The width of the sector
+ is specified in degrees (+/- delta phi) each direction from the central angle (phi).
+
+
+
+
+It performs an average between two q-values centered in (0,0),
+ and averaged over a width of a specified number of pixels.
+ The data is returned as a function of angle (phi) in degrees.
+ Moving one circle of this slicer
+ to radius of zero corresponding to a circular averaging on radius qmax ,
+ the outer circle.
+ The angle zero starts from the positive x-axis direction.
+
+
+
+
+Perform the sum of counts in a 2D region of interest.When editing the slicer ,the user can
+enter the length and the width the rectangle slicer and the coordinates of the center of this
+rectangle.
+
+
+
+Computes average I(Qx) for a region of interest. When editing the slicer ,the user can
+control the length and the width the rectangle slicer.
+The averaged output is calculated from the constant bins with rectangular shape.
+The resultant q values are nominal values, i.e., the central values of each bins on the x-axis.
+
+
+
+
+ Computes average I(Qy) for a region of interest.When editing the slicer ,the user can
+control the length and the width the rectangle slicer.
+The averaged output is calculated from the constant bins with rectangular shape.
+The resultant q values are nominal values, i.e., the central values of each bins on the y-axis.
+
+
+
+
+
Index: test/test_rename_guiframe/media/change_scale_help.html
===================================================================
--- test/test_rename_guiframe/media/change_scale_help.html (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/media/change_scale_help.html (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,16 @@
+
+
+Change scale
+
+ If the loaded data is a 1-D data.Changing scale or Data Representation will work as
+ followed:right click on the plot window.
+ A context menu pops-up and select Change Scale . A dialog window titled
+ select the scale of the graph will pop-up then change the x , the y
+ and the view values as wish.
+ If the loaded data is an image.Right click on the image to pop-up the context
+ menu. Select to switch from linear to log scale. The scale
+ selected is printed on the statusbar.
+
+
+
+
Index: test/test_rename_guiframe/media/data_explorer_help.html
===================================================================
--- test/test_rename_guiframe/media/data_explorer_help.html (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/media/data_explorer_help.html (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,96 @@
+
+
+
+Data Explorer Options
+
+
+
+
+Data Explorer is a panel that allows the user more interactions with
+data. Some functionalities provided by the Data Explorer are also available
+through the context menu of plot panels or other menus of the applications.Under
+menu View of the menubar, Data explorer can be toggle from Show to Hide
+when clicking on menu Data Explorer OFF . This latter can be labeled as
+Data Explorer ON if the Data Explorer is not visible.
+
+IMPORTANT! When Data explorer is not visible all data loaded will
+be send directly to the current active application. When data Explorer is shown
+data go fist to the Data Explorer for the user to handle them.
+
+
+
+
+To Load data, click on the button Load Data , then select one or more
+files to load into the application. Close the file dialog that first appears. In
+the list control label Data will be displayed data label with the name
+of each selected file.
+ Expending this data by clicking on + sign on each label
+will display available information about this loaded data.
+
+
+
+
+To interact with data, check a data label and click on a button. Checking Data
+make them active for the next operation. Unchecking Data labels will
+deactivate them.
+
+
+There is a combo box labeled Selection Options that allows to activate
+or select multiple data simultaneously.
+
+
+
+
+Remove data button remove all reference of this data into the application.
+
+
+WARNING! Remove data will stop any jobs
+currently using the selected data.
+
+
+
+
+Click on the button Send To to send Data to the current active application.
+Then from the application control panel interact more with that Data.
+
+
+
+Click on the button Append To to append selected Data to a plot panel on
+focus. Next to this button is a combo box containing available panels names.
+Selecting a name from this combo box will set the corresponding lot panel on
+focus. If not plot panel is available, the combo box and button will be disable.
+2D Data cannot be appended to any plot panels . This operation can only be
+performed on 1D data and plot panels currently containing 1D data.
+
+
+
+
+Click on New Plot button to create a new plot panel where selected data
+will be plotted.
+
+
+
+
+Freeze Theory button generate Data from selected theory. This operation
+can only be performed when theory labels are selected.
+
+
+
+Click on Delete Plot to remove all reference of the plot panel on focus.
+User can click on a plot panel or select a name of the plot panel in the corresponding
+combo box to set a plot panel on focus.
+
+
+
+
+
Index: test/test_rename_guiframe/media/key_help.html
===================================================================
--- test/test_rename_guiframe/media/key_help.html (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/media/key_help.html (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,40 @@
+
+
+
+Key Combination
+
+
+
+
+
For a graph panel to float on the top of the SV window:
+ Press the Ctrl(Cmd on MAC) key on dragging and placing a panel.
+Or if you want to make all plot panels float, select 'Float' from Graph/Preperences
+in the menu bar. Otherwise choose 'Dock'.
+
+
+
+
+
To get the graph context menu to print, copy, save data, (2D)average, etc.:
+ Locate the mouse point on the plot to highlight and
+(Mouse) Right Click to bring up the full menu.
+
+
+
+
+
To Zoom in or out the full plot:
+ Locate the mouse point inside the graph which will be the center of the zooming,
+then rotate MouseWheel .
+
+
To Zoom in or out the plot in x or y direction:
+ Locate (and click) the mouse point near x (or y) axis just outside of the graph
+and then rotate MouseWheel .
+ Note that this works only on the 1D plots.
+
+
+
+
+
Index: test/test_rename_guiframe/panel_base.py
===================================================================
--- test/test_rename_guiframe/panel_base.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/panel_base.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,423 @@
+
+
+################################################################################
+#This software was developed by the University of Tennessee as part of the
+#Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
+#project funded by the US National Science Foundation.
+#
+#See the license text in license.txt
+#
+#copyright 2008, University of Tennessee
+################################################################################
+
+
+from sans.guiframe.events import PanelOnFocusEvent
+from sans.guiframe.events import EVT_NEW_BATCH
+import wx
+
+class PanelBase:
+ """
+ Defines the API for a panels to work with
+ the ViewerFrame toolbar and menu bar
+ """
+ ## Internal nickname for the window, used by the AUI manager
+ #window_name = "default"
+ ## Name to appear on the window title bar
+ #window_caption = "Welcome panel"
+ ## Flag to tell the AUI manager to put this panel in the center pane
+ group_id = None
+ uid = None
+
+ def __init__(self, parent=None):
+ """
+ Initialize some flag that Viewerframe used
+ """
+ #panel manager
+ self._manager = None
+ self.parent = parent
+ if self.parent is not None and hasattr(self.parent, '_manager'):
+ self._manager = self.parent._manager
+ self._print_flag = False
+ self._undo_flag = False
+ self._redo_flag = False
+ self._copy_flag = False
+ self._paste_flag = False
+ self._preview_flag = False
+ self._bookmark_flag = False
+ self._zoom_in_flag = False
+ self._zoom_out_flag = False
+ self._zoom_flag = False
+ self._save_flag = False
+ self._drag_flag = False
+ self._reset_flag = False
+ self._has_changed = False
+ self.batch_on = False
+ self.group_id = None
+ self.Bind(EVT_NEW_BATCH, self.on_batch_selection)
+ self.Bind(wx.EVT_LEFT_DOWN, self.on_set_focus)
+ self.Bind(wx.EVT_TEXT_ENTER, self.on_set_focus)
+ self.Bind(wx.EVT_MIDDLE_DOWN, self.on_set_focus)
+ self.Bind(wx.EVT_RIGHT_DOWN, self.on_set_focus)
+
+ def on_batch_selection(self, event):
+ """
+ :param event: contains parameter enable . when enable is set to True
+ the application is in Batch mode
+ else the application is default mode(single mode)
+ """
+ self.batch_on = event.enable
+ def save_project(self, doc=None):
+ """
+ return an xml node containing state of the panel
+ that guiframe can write to file
+ """
+ return None
+
+ def has_changed(self):
+ """
+ """
+ return self._has_changed
+
+ def _set_print_flag(self, flag=True):
+ """
+ The derivative class sets the print flag value to indicate that it can
+ be printed
+ """
+ if flag == self._print_flag:
+ self._has_changed = False
+ return
+ self._has_changed = True
+ self._print_flag = flag
+ if self._manager is not None and self._manager.parent is not None:
+ self._manager.parent.cpanel_on_focus = self
+ self._manager.parent.enable_print()
+
+ def get_print_flag(self):
+ """
+ Get the print flag to update appropriately the tool bar
+ """
+ return self._print_flag
+
+ def _set_undo_flag(self, flag=True):
+ """
+ The derivative class sets the undo flag value to indicate that the
+ current action done can be canceled
+ """
+ if flag == self._undo_flag:
+ self._has_changed = False
+ return
+ self._has_changed = True
+ self._undo_flag = flag
+ if self._manager is not None and self._manager.parent is not None:
+ self._manager.parent.cpanel_on_focus = self
+ self._manager.parent.enable_undo()
+
+ def get_undo_flag(self):
+ """
+ Get the undo flag to update appropriately the tool bar
+ """
+ return self._undo_flag
+
+ def _set_redo_flag(self, flag=True):
+ """
+ The derivative class sets the redo flag value to indicate that the
+ action done can be recovered
+ """
+ if flag == self._redo_flag:
+ self._has_changed = False
+ return
+ self._has_changed = True
+ self._redo_flag = flag
+ if self._manager is not None and self._manager.parent is not None:
+ self._manager.parent.cpanel_on_focus = self
+ self._manager.parent.enable_redo()
+
+ def get_redo_flag(self):
+ """
+ Get the redo flag to update appropriately the tool bar
+ """
+ return self._redo_flag
+
+ def _set_copy_flag(self, flag=True):
+ """
+ The derivative class sets the copy flag value to indicate that the
+ action done can be recovered
+ """
+ if flag == self._copy_flag:
+ self._has_changed = False
+ return
+ self._has_changed = True
+ self._copy_flag = flag
+ if self._manager is not None and self._manager.parent is not None:
+ self._manager.parent.cpanel_on_focus = self
+ self._manager.parent.enable_copy()
+
+ def get_copy_flag(self):
+ """
+ Get the copy flag to update appropriately the tool bar
+ """
+ return self._copy_flag
+
+ def _set_paste_flag(self, flag=True):
+ """
+ The derivative class sets the paste flag value to indicate that the
+ action done can be recovered
+ """
+ if flag == self._paste_flag:
+ self._has_changed = False
+ return
+ self._has_changed = True
+ self._paste_flag = flag
+ if self._manager is not None and self._manager.parent is not None:
+ self._manager.parent.cpanel_on_focus = self
+ self._manager.parent.enable_paste()
+
+ def get_paste_flag(self):
+ """
+ Get the copy flag to update appropriately the tool bar
+ """
+ return self._copy_flag
+
+ def _set_zoomed_in_flag(self, flag=True):
+ """
+ The derivative class sets the zoom in flag value to indicate that it
+ can be zoomed in
+ """
+ if self._zoom_in_flag == flag:
+ self._has_changed = False
+ return
+ self._has_changed = True
+ self._zoom_in_flag = flag
+ if self._manager is not None and self._manager.parent is not None:
+ self._manager.parent.cpanel_on_focus = self
+ self._manager.parent.enable_zoom_in()
+
+ def get_zoom_in_flag(self):
+ """
+ Get the zoom in flag to update appropriately the tool bar
+ """
+ return self._zoom_in_flag
+
+ def _set_zoomed_out_flag(self, flag=True):
+ """
+ The derivative class sets the zoom out flag value to indicate that it
+ can be zoomed out
+ """
+ if self._zoom_out_flag == flag:
+ self._has_changed = False
+ return
+ self._has_changed = True
+ self._zoom_out_flag = flag
+ if self._manager is not None and self._manager.parent is not None:
+ self._manager.parent.panel_on_focus = self
+ self._manager.parent.enable_zoom_out()
+
+ def get_zoom_out_flag(self):
+ """
+ Get the zoom out flag to update appropriately the tool bar
+ """
+ return self._zoom_out_flag
+
+ def _set_zoom_flag(self, flag=True):
+ """
+ The derivative class sets the zoom flag value to indicate that it
+ can be zoomed
+ """
+ if flag == self._zoom_flag:
+ self._has_changed = False
+ return
+ self._has_changed = True
+ self._zoom_flag = flag
+ if self._manager is not None and self._manager.parent is not None:
+ self._manager.parent.cpanel_on_focus = self
+ self._manager.parent.enable_zoom()
+
+ def get_zoom_flag(self):
+ """
+ Get the zoom flag to update appropriately the tool bar
+ """
+ return self._zoom_flag
+
+ def _set_bookmark_flag(self, flag=True):
+ """
+ The derivative class sets the bookmark flag value to indicate that it
+ can be bookmarked
+ """
+ if flag == self._bookmark_flag:
+ self._has_changed = False
+ return
+ self._has_changed = True
+ self._bookmark_flag = flag
+ if self._manager is not None and self._manager.parent is not None:
+ self._manager.parent.cpanel_on_focus = self
+ self._manager.parent.enable_bookmark()
+
+ def get_bookmark_flag(self):
+ """
+ Get the bookmark flag to update appropriately the tool bar
+ """
+ return self._bookmark_flag
+
+ def _set_preview_flag(self, flag=True):
+ """
+ The derivative class sets the preview flag value to indicate that it
+ can be previewed
+ """
+ if flag == self._preview_flag:
+ self._has_changed = False
+ return
+ self._has_changed = True
+ self._preview_flag = flag
+ if self._manager is not None and self._manager.parent is not None:
+ self._manager.parent.cpanel_on_focus = self
+ self._manager.parent.enable_preview()
+
+ def get_preview_flag(self):
+ """
+ Get the preview flag to update appropriately the tool bar
+ """
+ return self._preview_flag
+
+ def _set_save_flag(self, flag=True):
+ """
+ The derivative class sets the drag flag value to indicate that it
+ can be saved
+ """
+ if flag == self._save_flag:
+ self._has_changed = False
+ return
+ self._has_changed = True
+ self._save_flag = flag
+ if self._manager is not None and self._manager.parent is not None:
+ self._manager.parent.cpanel_on_focus = self
+ self._manager.parent.enable_save()
+
+ def get_save_flag(self):
+ """
+ Get the save flag to update appropriately the tool bar
+ """
+ return self._save_flag
+
+ def _set_drag_flag(self, flag=True):
+ """
+ The derivative class sets the drag flag value to indicate that
+ dragging motion is possible
+ """
+ if self._drag_flag == flag:
+ self._has_changed = False
+ return
+ self._has_changed = True
+ self._drag_flag = flag
+ if self._manager is not None and self._manager.parent is not None:
+ self._manager.parent.cpanel_on_focus = self
+ self._manager.parent.enable_drag()
+
+ def get_drag_flag(self):
+ """
+ Get the drag flag to update appropriately the tool bar
+ """
+ return self._drag_flag
+
+ def _set_reset_flag(self, flag=True):
+ """
+ The derivative class sets the reset flag value to indicate that it
+ can be reset
+ """
+ if self._reset_flag == flag:
+ self._has_changed = False
+ return
+ self._has_changed = True
+ self._reset_flag = flag
+ if self._manager is not None and self._manager.parent is not None:
+ self._manager.parent.cpanel_on_focus = self
+ self._manager.parent.enable_reset()
+
+ def get_reset_flag(self):
+ """
+ Get the reset flag to update appropriately the tool bar
+ """
+ return self._reset_flag
+
+ def on_reset(self, event):
+ """
+ The derivative class state is restored
+ """
+ def on_drag(self, event):
+ """
+ The derivative class allows dragging motion if implemented
+ """
+ def on_preview(self, event):
+ """
+ Display a printable version of the class derivative
+ """
+ def on_save(self, event):
+ """
+ The state of the derivative class is restored
+ """
+ def on_redo(self, event):
+ """
+ The previous action is restored if possible
+ """
+ def on_undo(self, event):
+ """
+ The current action is canceled
+ """
+ def on_copy(self, event):
+ """
+ The copy action if possible
+ """
+ def on_paste(self, event):
+ """
+ The paste action if possible
+ """
+ def on_bookmark(self, event):
+ """
+ The derivative class is on bookmark mode if implemented
+ """
+ def on_zoom_in(self, event):
+ """
+ The derivative class is on zoom in mode if implemented
+ """
+ def on_zoom_out(self, event):
+ """
+ The derivative class is on zoom out mode if implemented
+ """
+ def on_zoom(self, event):
+ """
+ The derivative class is on zoom mode (using pane)
+ if zoom mode is implemented
+ """
+ def on_set_focus(self, event=None):
+ """
+ The derivative class is on focus if implemented
+ """
+ if self.parent is not None:
+ wx.PostEvent(self.parent, PanelOnFocusEvent(panel=self))
+
+ def on_kill_focus(self, event=None):
+ """
+ The derivative class is on unfocus if implemented
+ """
+ pass
+
+ def get_data(self):
+ """
+ return list of current data
+ """
+ return
+
+ def get_state(self):
+ """
+ return the current state
+ """
+ return
+
+ def set_manager(self, manager):
+ """
+ """
+ self._manager = manager
+
+ def get_manager(self):
+ """
+ """
+ return self._manager
Index: test/test_rename_guiframe/pdfview.py
===================================================================
--- test/test_rename_guiframe/pdfview.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/pdfview.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,120 @@
+# Read PDF files by embeding the Adobe Acrobat Reader
+# wx.activex module uses class ActiveX control
+
+import wx
+import os
+if wx.Platform == '__WXMSW__':
+ from wx.lib.pdfwin import PDFWindow
+
+class PDFPanel(wx.Panel):
+ """
+ Panel that contains the pdf reader
+ """
+ def __init__(self, parent, path=None):
+ """
+ """
+ wx.Panel.__init__(self, parent, id=-1)
+
+ self.parent = parent
+ self.path = path
+ sizer = wx.BoxSizer(wx.VERTICAL)
+ btnSizer = wx.BoxSizer(wx.HORIZONTAL)
+
+ self.pdf = PDFWindow(self, style=wx.SUNKEN_BORDER)
+
+ sizer.Add(self.pdf, proportion=1, flag=wx.EXPAND)
+
+ btn = wx.Button(self, wx.NewId(), "Open PDF File")
+ self.Bind(wx.EVT_BUTTON, self.OnOpenButton, btn)
+ btnSizer.Add(btn, proportion=1, flag=wx.EXPAND|wx.ALL, border=5)
+
+ self.pdf.LoadFile(self.path)
+ btn = wx.Button(self, wx.NewId(), "Previous Page")
+ self.Bind(wx.EVT_BUTTON, self.OnPrevPageButton, btn)
+ btnSizer.Add(btn, proportion=1, flag=wx.EXPAND|wx.ALL, border=5)
+
+ btn = wx.Button(self, wx.NewId(), "Next Page")
+ self.Bind(wx.EVT_BUTTON, self.OnNextPageButton, btn)
+ btnSizer.Add(btn, proportion=1, flag=wx.EXPAND|wx.ALL, border=5)
+
+ btn = wx.Button(self, wx.NewId(), "Close")
+ self.Bind(wx.EVT_BUTTON, self.OnClose, btn)
+ btnSizer.Add(btn, proportion=1, flag=wx.EXPAND|wx.ALL, border=5)
+ btnSizer.Add((50,-1), proportion=2, flag=wx.EXPAND)
+ sizer.Add(btnSizer, proportion=0, flag=wx.EXPAND)
+
+ self.SetSizer(sizer)
+ self.SetAutoLayout(True)
+
+ def OnOpenButton(self, event):
+ """
+ Open file button
+ """
+ # make sure you have PDF files available on your drive
+ dlg = wx.FileDialog(self, wildcard="*.pdf")
+ dlg.SetDirectory(os.path.dirname(self.path))
+ if dlg.ShowModal() == wx.ID_OK:
+ wx.BeginBusyCursor()
+ file = dlg.GetPath()
+ self.pdf.LoadFile(file)
+ self.parent.SetTitle(os.path.basename(file.split('.')[0]))
+ wx.EndBusyCursor()
+ dlg.Destroy()
+
+ def OnLoad(self, event=None, path=None):
+ """
+ Load a pdf file
+
+ : Param path: full path to the file
+ """
+ self.pdf.LoadFile(path)
+
+
+ def OnPrevPageButton(self, event):
+ """
+ Goes to Previous page
+ """
+ self.pdf.gotoPreviousPage()
+
+ def OnNextPageButton(self, event):
+ """
+ Goes to Next page
+ """
+ self.pdf.gotoNextPage()
+
+ def OnClose(self, event):
+ """
+ Close panel
+ """
+ self.parent.Destroy()
+
+class PDFFrame(wx.Frame):
+ """
+ Frame for PDF panel
+ """
+ def __init__(self, parent, id, title, path):
+ """
+ Init
+
+ :param parent: parent panel/container
+ :param path: full path of the pdf file
+ """
+ # Initialize the Frame object
+ wx.Frame.__init__(self, parent, id, title,
+ wx.DefaultPosition, wx.Size(600, 830))
+ # make an instance of the class
+ PDFPanel(self, path)
+
+class ViewApp(wx.App):
+ def OnInit(self):
+ path = None
+ frame = PDFFrame(None, -1, "PDFView", path=path)
+
+ frame.Show(True)
+ #self.SetTopWindow(frame)
+
+ return True
+
+if __name__ == "__main__":
+ app = ViewApp(0)
+ app.MainLoop()
Index: test/test_rename_guiframe/plugin_base.py
===================================================================
--- test/test_rename_guiframe/plugin_base.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/plugin_base.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,252 @@
+################################################################################
+#This software was developed by the University of Tennessee as part of the
+#Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
+#project funded by the US National Science Foundation.
+#
+#See the license text in license.txt
+#
+#copyright 2008, University of Tennessee
+################################################################################
+
+class PluginBase:
+ """
+ This class defines the interface for a Plugin class
+ that can be used by the gui_manager.
+
+ Plug-ins should be placed in a sub-directory called "perspectives".
+ For example, a plug-in called Foo should be place in "perspectives/Foo".
+ That directory contains at least two files:
+ perspectives/Foo/__init__.py contains two lines:
+
+ PLUGIN_ID = "Foo plug-in 1.0"
+ from Foo import *
+
+ perspectives/Foo/Foo.py contains the definition of the Plugin
+ class for the Foo plug-in. The interface of that Plugin class
+ should follow the interface of the class you are looking at.
+
+ See dummyapp.py for a plugin example.
+ """
+
+ def __init__(self, name="Test_plugin", standalone=True):
+ """
+ Abstract class for gui_manager Plugins.
+ """
+ # Define if the plugin is local to Viewerframe and always active
+ self._always_active = False
+ ## Plug-in name. It will appear on the application menu.
+ self.sub_menu = name
+ #standalone flag
+ self.standalone = standalone
+ ## Reference to the parent window. Filled by get_panels() below.
+ self.parent = None
+ #plugin state reader
+ self.state_reader = None
+ self._extensions = ''
+ ## List of panels that you would like to open in AUI windows
+ # for your plug-in. This defines your plug-in "perspective"
+ self.perspective = []
+ #flag to tell the current plugin that aaplication is in batch mode
+ self.batch_on = False
+
+ def clear_panel(self):
+ """
+ clear all related panels
+ """
+ def get_extensions(self):
+ """
+ return state reader and its extensions
+ """
+ return self.state_reader, self._extensions
+
+ def can_load_data(self):
+ """
+ if return True, then call handler to laod data
+ """
+ return False
+
+ def use_data(self):
+ """
+ return True if these plugin use data
+ """
+ return True
+
+ def is_in_use(self, data_id):
+ """
+ get a data id a list of data name if data data is
+ currently used by the plugin and the name of the plugin
+
+ data_name = 'None'
+ in_use = False
+ example [(data_name, self.sub_menu)]
+ """
+ return []
+
+ def delete_data(self, data_id):
+ """
+ Delete all references of data which id are in data_list.
+ """
+
+ def load_data(self, event):
+ """
+ Load data
+ """
+ raise NotImplemented
+
+ def load_folder(self, event):
+ """
+ Load entire folder
+ """
+ raise NotImplemented
+
+ def set_is_active(self, active=False):
+ """
+ """
+ self._always_active = active
+
+ def is_always_active(self):
+ """
+ return True is this plugin is always active and it is local to guiframe
+ even if the user is switching between perspectives
+ """
+ return self._always_active
+
+ def populate_file_menu(self):
+ """
+ Append menu item under file menu item of the frame
+ """
+ return []
+
+ def populate_menu(self, parent):
+ """
+ Create and return the list of application menu
+ items for the plug-in.
+
+ :param parent: parent window
+
+ :return: plug-in menu
+
+ """
+ return []
+
+ def get_panels(self, parent):
+ """
+ Create and return the list of wx.Panels for your plug-in.
+ Define the plug-in perspective.
+
+ Panels should inherit from DefaultPanel defined below,
+ or should present the same interface. They must define
+ "window_caption" and "window_name".
+
+ :param parent: parent window
+
+ :return: list of panels
+
+ """
+ ## Save a reference to the parent
+ self.parent = parent
+
+ # Return the list of panels
+ return []
+
+
+ def get_tools(self):
+ """
+ Returns a set of menu entries for tools
+ """
+ return []
+
+
+ def get_context_menu(self, plotpanel=None):
+ """
+ This method is optional.
+
+ When the context menu of a plot is rendered, the
+ get_context_menu method will be called to give you a
+ chance to add a menu item to the context menu.
+
+ A ref to a plotpanel object is passed so that you can
+ investigate the plot content and decide whether you
+ need to add items to the context menu.
+
+ This method returns a list of menu items.
+ Each item is itself a list defining the text to
+ appear in the menu, a tool-tip help text, and a
+ call-back method.
+
+ :param graph: the Graph object to which we attach the context menu
+
+ :return: a list of menu items with call-back function
+
+ """
+ return []
+
+ def get_perspective(self):
+ """
+ Get the list of panel names for this perspective
+ """
+ return self.perspective
+
+ def on_perspective(self, event=None):
+ """
+ Call back function for the perspective menu item.
+ We notify the parent window that the perspective
+ has changed.
+
+ :param event: menu event
+
+ """
+ self.parent.set_current_perspective(self)
+ self.parent.set_perspective(self.perspective)
+
+ def set_batch_selection(self, flag):
+ """
+ the plugin to its batch state if flag is True
+ """
+ self.batch_on = flag
+ self.on_batch_selection(self.batch_on)
+
+ def on_batch_selection(self, flag):
+ """
+ need to be overwritten by the derivated class
+ """
+
+ def post_init(self):
+ """
+ Post initialization call back to close the loose ends
+ """
+ pass
+
+ def set_default_perspective(self):
+ """
+ Call back method that True to notify the parent that the current plug-in
+ can be set as default perspective.
+ when returning False, the plug-in is not candidate for an automatic
+ default perspective setting
+ """
+ if self.standalone:
+ return True
+ return False
+
+ def set_state(self, state=None, datainfo=None):
+ """
+ update state
+ """
+ def set_data(self, data_list=None):
+ """
+ receive a list of data and use it in the current perspective
+
+ """
+ def set_theory(self, theory_list=None):
+ """
+ :param theory_list: list of information
+ related to available theory state
+ """
+ msg = "%s plugin: does not support import theory" % str(self.sub_menu)
+ raise ValueError, msg
+
+ def on_set_state_helper(self, event):
+ """
+ update state
+ """
+
Index: test/test_rename_guiframe/release_notes.txt
===================================================================
--- test/test_rename_guiframe/release_notes.txt (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/release_notes.txt (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,43 @@
+First cut at a GUI framework for SANS applications.
+
+Modules should be put in the "perspectives" directory
+of their main application when using this framework.
+
+Documentation to come...
+
+1- Version 0.1.7
+
+ - Release date: 7/4/2009
+
+ Version 0.1.5
+
+ - Release date: 4/21/2009
+
+ - Changes:
+ * the Plugin.get_context_menu(graph) now takes a Graph object
+
+Dependencies:
+ - svn://danse.us/common/releases/plottools-0.1.6
+ - svn://danse.us/sans/releases/guicomm-0.1.2
+
+To-do list:
+ - Clean up about box
+ - Clean up the _find_plugins() function to allow user-defined directory
+ - Modify the get_context_menu() function to allow a plug-in to recognize
+ its own plots.
+ - Provide a hook for a general file loader for the various data formats
+ - Add group flag to allow groups of plots (and exclude other plots with
+ same units to be plotted in the same Graph. [DONE]
+ - If there is only one perspective, drop the perspective menu.
+ - If there is only one panel in the Panel menu, drop the menu.
+ - Make legend transparent
+ - Make sure that when a plottable is sent a second time for update, that we replace the lables too!
+ - Add help menu entry for each module
+ - Put debug info in log file, because we can't access it from a py2exe executable
+ - Allow the application to load perspectives by hand. Then the automatic loading is only
+ for additionally installed plug-ins.
+ - Fix the damned images directory folder...
+ - Allow user to remove a plottable from a graph (from code!)
+ - Allow perspectives to recognize their own plots and add context menu items.
+ - Catch error when trying to show log of negative or zero plots... update status bar.
+
Index: test/test_rename_guiframe/sans/__init__.py
===================================================================
--- test/test_rename_guiframe/sans/__init__.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/sans/__init__.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,2 @@
+from pkgutil import extend_path
+__path__ = extend_path(__path__, __name__)
Index: test/test_rename_guiframe/setup.py
===================================================================
--- test/test_rename_guiframe/setup.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/setup.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,46 @@
+
+"""
+ Installs the guiframe package
+"""
+
+
+from distutils.core import setup, Extension
+
+from distutils.sysconfig import get_python_lib
+import os
+import sys
+
+
+
+path = os.path.join(os.getcwd(), 'local_perspectives')
+package_dir = { "sans.guiframe":".",
+ "sans.guiframe.local_perspectives":"local_perspectives",
+ #"sans.guiframe.images":"images",
+ # "sans.guiframe.media":"media",
+ }
+#package_data = {"sans.guiframe": ['images/*'],
+# "sans.guiframe":'media/*']}
+package_data = {"sans.guiframe": ['images/*', 'media/*']}
+packages = ["sans.guiframe",
+ "sans.guiframe.local_perspectives"]
+# build local plugin
+for dir in os.listdir(path):
+ if dir not in ['.svn','__init__.py', '__init__.pyc']:
+ package_name = "sans.guiframe.local_perspectives." + dir
+ packages.append(package_name)
+ package_dir[package_name] = "local_perspectives/" + dir
+
+
+setup(
+ name="guiframe",
+ version = "0.9.1",
+ description = "Python module for SANS gui framework",
+ author = "University of Tennessee",
+ url = "http://danse.chem.utk.edu",
+
+ package_dir = package_dir,
+
+ packages = packages,
+ package_data = package_data,
+
+ )
Index: test/test_rename_guiframe/startup_configuration.py
===================================================================
--- test/test_rename_guiframe/startup_configuration.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/startup_configuration.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,207 @@
+
+################################################################################
+#This software was developed by the University of Tennessee as part of the
+#Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
+#project funded by the US National Science Foundation.
+#
+#See the license text in license.txt
+#
+#copyright 2009, University of Tennessee
+################################################################################
+import wx
+import os
+import sys
+import copy
+#import sans.guiframe.gui_manager as gui
+from sans.guiframe.events import StatusEvent
+from sans.guiframe.gui_style import GUIFRAME
+from sans.guiframe import gui_manager as CURRENT
+# default configuration
+DEFAULT_STRINGS = {'GUIFRAME_WIDTH':1150,
+ 'GUIFRAME_HEIGHT':840,
+ 'PLOPANEL_WIDTH':415,
+ 'DATAPANEL_WIDTH':235,
+ 'DATALOADER_SHOW':True,
+ 'TOOLBAR_SHOW':True,
+ 'FIXED_PANEL':True,
+ 'WELCOME_PANEL_SHOW':False,
+ 'CLEANUP_PLOT':False,
+ 'DEFAULT_PERSPECTIVE':'Fitting'}
+try:
+ CURRENT_STRINGS = {'GUIFRAME_WIDTH':CURRENT.GUIFRAME_WIDTH,
+ 'GUIFRAME_HEIGHT':CURRENT.GUIFRAME_HEIGHT,
+ 'PLOPANEL_WIDTH':CURRENT.PLOPANEL_WIDTH,
+ 'DATAPANEL_WIDTH':CURRENT.DATAPANEL_WIDTH,
+ 'DATALOADER_SHOW':CURRENT.DATALOADER_SHOW,
+ 'TOOLBAR_SHOW':CURRENT.TOOLBAR_SHOW,
+ 'FIXED_PANEL':CURRENT.FIXED_PANEL,
+ 'WELCOME_PANEL_SHOW':CURRENT.WELCOME_PANEL_SHOW,
+ 'CLEANUP_PLOT':CURRENT.CLEANUP_PLOT,
+ 'DEFAULT_PERSPECTIVE':CURRENT.DEFAULT_PERSPECTIVE}
+except:
+ CURRENT_STRINGS = DEFAULT_STRINGS
+
+if sys.platform.count("win32") > 0:
+ PANEL_WIDTH = 265
+ PANEL_HEIGHT = 235
+ FONT_VARIANT = 0
+else:
+ PANEL_WIDTH = 285
+ PANEL_HEIGHT = 255
+ FONT_VARIANT = 1
+
+"""
+Dialog to set Appication startup configuration
+"""
+class StartupConfiguration(wx.Dialog):
+ """
+ Dialog for Startup Configuration
+ """
+ def __init__(self, parent, gui, id=-1, title="Startup Setting"):
+ wx.Dialog.__init__(self, parent, id, title,
+ size=(PANEL_WIDTH, PANEL_HEIGHT))
+ # parent
+ self.parent = parent
+ self.path = parent.path
+ self._gui = gui
+ # font size
+ self.SetWindowVariant(variant=FONT_VARIANT)
+ self.current_string = copy.deepcopy(CURRENT_STRINGS)
+ self.return_string = {}
+ # build layout
+ panel = wx.Panel(self, -1)
+ vbox = wx.BoxSizer(wx.VERTICAL)
+ wx.StaticBox(panel, -1, 'Set View-Configuration', (5, 5),
+ (PANEL_WIDTH*0.94, PANEL_HEIGHT*0.7))
+ default_bt = wx.RadioButton(panel, -1, 'Default View', (15, 30),
+ style=wx.RB_GROUP)
+ default_bt.Bind(wx.EVT_RADIOBUTTON, self.OnDefault)
+ default_bt.SetValue(True)
+ current_bt = wx.RadioButton(panel, -1, 'Current View', (15, 55))
+ current_bt.SetValue(False)
+ current_bt.Bind(wx.EVT_RADIOBUTTON, self.OnCurrent)
+ msg = "\nThis new configuration will take effect after\n"
+ msg += "restarting the SansView application..."
+ note_txt = wx.StaticText(panel, -1, msg, (15, 75))
+ note_txt.SetForegroundColour("black")
+ hbox = wx.BoxSizer(wx.HORIZONTAL)
+ cancelButton = wx.Button(self, -1, 'Cancel', size=(70, 25))
+ hbox.Add(cancelButton, 1, wx.RIGHT, 5)
+ cancelButton.Bind(wx.EVT_BUTTON, self.OnCancel)
+ okButton = wx.Button(self, -1, 'OK', size=(70, 25))
+ hbox.Add(okButton, 1, wx.RIGHT, 5)
+ okButton.Bind(wx.EVT_BUTTON, self.OnClose)
+ vbox.Add(panel)
+
+ vbox.Add(hbox, 1, wx.ALIGN_CENTER | wx.RIGHT | wx.BOTTOM, 5)
+ # set sizer
+ self.SetSizer(vbox)
+ #pos = self.parent.GetPosition()
+ #self.SetPosition(pos)
+
+ def OnDefault(self, event=None):
+ """
+ Set to default
+ """
+ event.Skip()
+ # event object and selection
+ self.return_string = copy.deepcopy(DEFAULT_STRINGS)
+ return self.return_string
+
+ def OnCurrent(self, event=None):
+ """
+ Set to curent setup
+ """
+ event.Skip()
+
+ gui_pw, gui_ph = self.parent.GetSizeTuple()
+ self.current_string['GUIFRAME_WIDTH'] = gui_pw
+ self.current_string['GUIFRAME_HEIGHT'] = gui_ph
+ try:
+ p_size = None
+ for panel in self.parent.plot_panels.values():
+ p_panel = self.parent._mgr.GetPane(panel.window_name)
+ if p_panel.IsShown():
+ if p_size == None or panel.size > p_size:
+ p_size = panel.size
+ if p_size == None:
+ p_size = CURRENT_STRINGS['PLOPANEL_WIDTH']
+ self.current_string['PLOPANEL_WIDTH'] = p_size
+
+ data_pw, _ = self.parent.panels["data_panel"].GetSizeTuple()
+ if data_pw == None:
+ data_pw = CURRENT_STRINGS['DATAPANEL_WIDTH']
+ self.current_string['DATAPANEL_WIDTH'] = data_pw
+
+ #label = self.parent._data_panel_menu.GetText()
+ label = self.parent._mgr.GetPane(\
+ self.parent.panels['data_panel'].window_name).IsShown()
+ if label:# == 'Hide Data Explorer':
+ self.current_string['DATALOADER_SHOW'] = True
+ else:
+ self.current_string['DATALOADER_SHOW'] = False
+
+ if self.parent._toolbar.IsShown():
+ self.current_string['TOOLBAR_SHOW'] = True
+ else:
+ self.current_string['TOOLBAR_SHOW'] = False
+
+ style = self._gui & GUIFRAME.FLOATING_PANEL
+ if style == GUIFRAME.FLOATING_PANEL:
+ self.current_string['FIXED_PANEL'] = False
+ else:
+ self.current_string['FIXED_PANEL'] = True
+
+ if self.parent._mgr.GetPane(self.parent.panels['default'].window_name).IsShown():
+ self.current_string['WELCOME_PANEL_SHOW'] = True
+ else:
+ self.current_string['WELCOME_PANEL_SHOW'] = False
+ self.current_string['CLEANUP_PLOT'] = \
+ self.parent.cleanup_plots
+ perspective = self.parent.get_current_perspective()
+ self.current_string['DEFAULT_PERSPECTIVE'] = str(perspective.sub_menu)
+
+ except:
+ raise
+ # event object and selection
+ self.return_string = self.current_string
+ return self.return_string
+
+ def OnCancel(self, event):
+ """
+ Close event
+ """
+ # clear event
+ event.Skip()
+ self.return_string = {}
+ self.Destroy()
+
+ def OnClose(self, event):
+ """
+ Close event
+ """
+ # clear event
+ event.Skip()
+ fname = os.path.join(self.path, 'custom_config.py')
+ self.write_string(fname, self.return_string)
+
+ self.Destroy()
+
+ def write_string(self, fname, strings):
+ """
+ Write and Save file
+ """
+
+ try:
+ out_f = open(fname,'w')
+ except :
+ raise #RuntimeError, "Error: Can not change the configuration..."
+ out_f.write("#Application appearance custom configuration\n" )
+ for key, item in strings.iteritems():
+ if key == 'DEFAULT_PERSPECTIVE':
+ out_f.write("%s = '%s'\n" % (key,str(item)))
+ else:
+ out_f.write("%s = %s\n" % (key,str(item)))
+
+ out_f.close()
+
Index: test/test_rename_guiframe/state_reader.py
===================================================================
--- test/test_rename_guiframe/state_reader.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/state_reader.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,1609 @@
+
+
+############################################################################
+#This software was developed by the University of Tennessee as part of the
+#Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
+#project funded by the US National Science Foundation.
+#If you use DANSE applications to do scientific research that leads to
+#publication, we ask that you acknowledge the use of the software with the
+#following sentence:
+#This work benefited from DANSE software developed under NSF award DMR-0520547.
+#copyright 2008,2009 University of Tennessee
+#############################################################################
+
+# Known issue: reader not compatible with multiple SASdata entries
+# within a single SASentry. Will raise a runtime error.
+
+#TODO: check that all vectors are written only if they have at
+# least one non-empty value
+#TODO: Writing only allows one SASentry per file.
+# Would be best to allow multiple entries.
+#TODO: Store error list
+#TODO: Allow for additional meta data for each section
+#TODO: Notes need to be implemented. They can be any XML
+# structure in version 1.0
+# Process notes have the same problem.
+#TODO: Unit conversion is not complete (temperature units are missing)
+
+
+import logging
+import numpy
+import os
+import sys
+from sans.guiframe.dataFitting import Data1D
+from sans.guiframe.dataFitting import Data2D
+from DataLoader.data_info import Collimation
+from DataLoader.data_info import Detector
+from DataLoader.data_info import Process
+from DataLoader.data_info import Aperture
+from lxml import etree
+import xml.dom.minidom
+
+has_converter = True
+try:
+ from data_util.nxsunit import Converter
+except:
+ has_converter = False
+
+STATE_NS = "State/1.0"
+
+def write_node(doc, parent, name, value, attr={}):
+ """
+ :param doc: document DOM
+ :param parent: parent node
+ :param name: tag of the element
+ :param value: value of the child text node
+ :param attr: attribute dictionary
+
+ :return: True if something was appended, otherwise False
+ """
+ if value is not None:
+ node = doc.createElement(name)
+ node.appendChild(doc.createTextNode(str(value)))
+ for item in attr:
+ node.setAttribute(item, attr[item])
+ parent.appendChild(node)
+ return True
+ return False
+
+def get_content(location, node):
+ """
+ Get the first instance of the content of a xpath location.
+
+ :param location: xpath location
+ :param node: node to start at
+
+ :return: Element, or None
+ """
+ nodes = node.xpath(location, namespaces={'ns': STATE_NODE})
+
+ if len(nodes)>0:
+ return nodes[0]
+ else:
+ return None
+
+def get_float(location, node):
+ """
+ Get the content of a node as a float
+
+ :param location: xpath location
+ :param node: node to start at
+ """
+ nodes = node.xpath(location, namespaces={'ns': STATE_NODE})
+
+ value = None
+ attr = {}
+ if len(nodes) > 0:
+ try:
+ value = float(nodes[0].text)
+ except:
+ # Could not pass, skip and return None
+ msg = "state_reader.get_float: could not "
+ msg += " convert '%s' to float" % nodes[0].text
+ logging.error(msg)
+ if nodes[0].get('unit') is not None:
+ attr['unit'] = nodes[0].get('unit')
+ return value, attr
+
+
+class Reader1D:
+ """
+ read state of a plugin and available data
+
+ :Dependencies:
+ The CanSas reader requires PyXML 0.8.4 or later.
+ """
+ ## CanSAS version
+ version = '1.0'
+ ## File type
+ type_name = "CanSAS 1D"
+ ## Wildcards
+ type = []
+
+ ## List of allowed extensions
+ ext = []
+
+ def __init__(self):
+ ## List of errors
+ self.errors = []
+
+ def read(self, path):
+ """
+ Load data file
+
+ :param path: file path
+
+ :return: Data1D object if a single SASentry was found,
+ or a list of Data1D objects if multiple entries were found,
+ or None of nothing was found
+
+ :raise RuntimeError: when the file can't be opened
+ :raise ValueError: when the length of the data vectors are inconsistent
+ """
+ output = []
+ if os.path.isfile(path):
+ basename = os.path.basename(path)
+ root, extension = os.path.splitext(basename)
+ if extension.lower() in self.ext:
+
+ tree = etree.parse(path, parser=etree.ETCompatXMLParser())
+ # Check the format version number
+ # Specifying the namespace will take care of the file
+ # format version
+ root = tree.getroot()
+
+ entry_list = root.xpath('/ns:SASroot/ns:SASentry',
+ namespaces={'ns': STATE_NODE})
+
+ for entry in entry_list:
+ self.errors = []
+ sas_entry = self._parse_entry(entry)
+ sas_entry.filename = basename
+
+ # Store loading process information
+ sas_entry.errors = self.errors
+ sas_entry.meta_data['loader'] = self.type_name
+ output.append(sas_entry)
+
+ else:
+ raise RuntimeError, "%s is not a file" % path
+ # Return output consistent with the loader's api
+ if len(output) == 0:
+ #cannot return none when it cannot read
+ #return None
+ raise RuntimeError, "%s cannot be read \n" % path
+ elif len(output) == 1:
+ return output[0]
+ else:
+ return output
+
+ def _parse_entry(self, dom):
+ """
+ Parse a SASentry
+
+ :param node: SASentry node
+
+ :return: Data1D object
+ """
+ x = numpy.zeros(0)
+ y = numpy.zeros(0)
+
+ data_info = Data1D(x, y)
+
+ # Look up title
+ self._store_content('ns:Title', dom, 'title', data_info)
+
+ # Look up run number
+ nodes = dom.xpath('ns:Run', namespaces={'ns': STATE_NODE})
+ for item in nodes:
+ if item.text is not None:
+ value = item.text.strip()
+ if len(value) > 0:
+ data_info.run.append(value)
+ if item.get('name') is not None:
+ data_info.run_name[value] = item.get('name')
+
+ # Look up instrument name
+ self._store_content('ns:SASinstrument/ns:name', dom, 'instrument',
+ data_info)
+
+ # Notes
+ note_list = dom.xpath('ns:SASnote', namespaces={'ns': STATE_NODE})
+ for note in note_list:
+ try:
+ if note.text is not None:
+ note_value = note.text.strip()
+ if len(note_value) > 0:
+ data_info.notes.append(note_value)
+ except:
+ err_mess = "state_reader.read: error processing"
+ err_mess += " entry notes\n %s" % sys.exc_value
+ self.errors.append(err_mess)
+ logging.error(err_mess)
+
+ # Sample info ###################
+ entry = get_content('ns:SASsample', dom)
+ if entry is not None:
+ data_info.sample.name = entry.get('name')
+
+ self._store_content('ns:SASsample/ns:ID',
+ dom, 'ID', data_info.sample)
+ self._store_float('ns:SASsample/ns:thickness',
+ dom, 'thickness', data_info.sample)
+ self._store_float('ns:SASsample/ns:transmission',
+ dom, 'transmission', data_info.sample)
+ self._store_float('ns:SASsample/ns:temperature',
+ dom, 'temperature', data_info.sample)
+
+ nodes = dom.xpath('ns:SASsample/ns:details',
+ namespaces={'ns': STATE_NODE})
+ for item in nodes:
+ try:
+ if item.text is not None:
+ detail_value = item.text.strip()
+ if len(detail_value) > 0:
+ data_info.sample.details.append(detail_value)
+ except:
+ err_mess = "state_reader.read: error processing "
+ err_mess += " sample details\n %s" % sys.exc_value
+ self.errors.append(err_mess)
+ logging.error(err_mess)
+
+ # Position (as a vector)
+ self._store_float('ns:SASsample/ns:position/ns:x',
+ dom, 'position.x', data_info.sample)
+ self._store_float('ns:SASsample/ns:position/ns:y',
+ dom, 'position.y', data_info.sample)
+ self._store_float('ns:SASsample/ns:position/ns:z',
+ dom, 'position.z', data_info.sample)
+
+ # Orientation (as a vector)
+ self._store_float('ns:SASsample/ns:orientation/ns:roll',
+ dom, 'orientation.x', data_info.sample)
+ self._store_float('ns:SASsample/ns:orientation/ns:pitch',
+ dom, 'orientation.y', data_info.sample)
+ self._store_float('ns:SASsample/ns:orientation/ns:yaw',
+ dom, 'orientation.z', data_info.sample)
+
+ # Source info ###################
+ entry = get_content('ns:SASinstrument/ns:SASsource', dom)
+ if entry is not None:
+ data_info.source.name = entry.get('name')
+
+ self._store_content('ns:SASinstrument/ns:SASsource/ns:radiation',
+ dom, 'radiation', data_info.source)
+ self._store_content('ns:SASinstrument/ns:SASsource/ns:beam_shape',
+ dom, 'beam_shape', data_info.source)
+ self._store_float('ns:SASinstrument/ns:SASsource/ns:wavelength',
+ dom, 'wavelength', data_info.source)
+ self._store_float('ns:SASinstrument/ns:SASsource/ns:wavelength_min',
+ dom, 'wavelength_min', data_info.source)
+ self._store_float('ns:SASinstrument/ns:SASsource/ns:wavelength_max',
+ dom, 'wavelength_max', data_info.source)
+ self._store_float('ns:SASinstrument/ns:SASsource/ns:wavelength_spread',
+ dom, 'wavelength_spread', data_info.source)
+
+ # Beam size (as a vector)
+ entry = get_content('ns:SASinstrument/ns:SASsource/ns:beam_size', dom)
+ if entry is not None:
+ data_info.source.beam_size_name = entry.get('name')
+
+ self._store_float('ns:SASinstrument/ns:SASsource/ns:beam_size/ns:x',
+ dom, 'beam_size.x', data_info.source)
+ self._store_float('ns:SASinstrument/ns:SASsource/ns:beam_size/ns:y',
+ dom, 'beam_size.y', data_info.source)
+ self._store_float('ns:SASinstrument/ns:SASsource/ns:beam_size/ns:z',
+ dom, 'beam_size.z', data_info.source)
+
+ # Collimation info ###################
+ nodes = dom.xpath('ns:SASinstrument/ns:SAScollimation',
+ namespaces={'ns': STATE_NODE})
+ for item in nodes:
+ collim = Collimation()
+ if item.get('name') is not None:
+ collim.name = item.get('name')
+ self._store_float('ns:length', item, 'length', collim)
+
+ # Look for apertures
+ apert_list = item.xpath('ns:aperture', namespaces={'ns': STATE_NODE})
+ for apert in apert_list:
+ aperture = Aperture()
+
+ # Get the name and type of the aperture
+ aperture.name = apert.get('name')
+ aperture.type = apert.get('type')
+
+ self._store_float('ns:distance', apert, 'distance', aperture)
+
+ entry = get_content('ns:size', apert)
+ if entry is not None:
+ aperture.size_name = entry.get('name')
+
+ self._store_float('ns:size/ns:x', apert, 'size.x', aperture)
+ self._store_float('ns:size/ns:y', apert, 'size.y', aperture)
+ self._store_float('ns:size/ns:z', apert, 'size.z', aperture)
+
+ collim.aperture.append(aperture)
+
+ data_info.collimation.append(collim)
+
+ # Detector info ######################
+ nodes = dom.xpath('ns:SASinstrument/ns:SASdetector',
+ namespaces={'ns': STATE_NODE})
+ for item in nodes:
+
+ detector = Detector()
+
+ self._store_content('ns:name', item, 'name', detector)
+ self._store_float('ns:SDD', item, 'distance', detector)
+
+ # Detector offset (as a vector)
+ self._store_float('ns:offset/ns:x', item, 'offset.x', detector)
+ self._store_float('ns:offset/ns:y', item, 'offset.y', detector)
+ self._store_float('ns:offset/ns:z', item, 'offset.z', detector)
+
+ # Detector orientation (as a vector)
+ self._store_float('ns:orientation/ns:roll', item, 'orientation.x',
+ detector)
+ self._store_float('ns:orientation/ns:pitch', item, 'orientation.y',
+ detector)
+ self._store_float('ns:orientation/ns:yaw', item, 'orientation.z',
+ detector)
+
+ # Beam center (as a vector)
+ self._store_float('ns:beam_center/ns:x', item, 'beam_center.x',
+ detector)
+ self._store_float('ns:beam_center/ns:y', item, 'beam_center.y',
+ detector)
+ self._store_float('ns:beam_center/ns:z', item, 'beam_center.z',
+ detector)
+
+ # Pixel size (as a vector)
+ self._store_float('ns:pixel_size/ns:x', item, 'pixel_size.x',
+ detector)
+ self._store_float('ns:pixel_size/ns:y', item, 'pixel_size.y',
+ detector)
+ self._store_float('ns:pixel_size/ns:z', item, 'pixel_size.z',
+ detector)
+
+ self._store_float('ns:slit_length', item, 'slit_length', detector)
+
+ data_info.detector.append(detector)
+
+ # Processes info ######################
+ nodes = dom.xpath('ns:SASprocess', namespaces={'ns': STATE_NODE})
+ for item in nodes:
+ process = Process()
+ self._store_content('ns:name', item, 'name', process)
+ self._store_content('ns:date', item, 'date', process)
+ self._store_content('ns:description', item, 'description', process)
+
+ term_list = item.xpath('ns:term', namespaces={'ns': STATE_NODE})
+ for term in term_list:
+ try:
+ term_attr = {}
+ for attr in term.keys():
+ term_attr[attr] = term.get(attr).strip()
+ if term.text is not None:
+ term_attr['value'] = term.text.strip()
+ process.term.append(term_attr)
+ except:
+ err_mess = "state_reader.read: error processing "
+ err_mess += " process term\n %s" % sys.exc_value
+ self.errors.append(err_mess)
+ logging.error(err_mess)
+
+ note_list = item.xpath('ns:SASprocessnote',
+ namespaces={'ns': STATE_NODE})
+ for note in note_list:
+ if note.text is not None:
+ process.notes.append(note.text.strip())
+
+ data_info.process.append(process)
+
+
+ # Data info ######################
+ nodes = dom.xpath('ns:SASdata', namespaces={'ns': STATE_NODE})
+ if len(nodes) > 1:
+ msg = "CanSAS reader is not compatible with multiple"
+ msg += " SASdata entries"
+ raise RuntimeError, msg
+
+ nodes = dom.xpath('ns:SASdata/ns:Idata', namespaces={'ns': STATE_NODE})
+
+ x = numpy.zeros(0)
+ y = numpy.zeros(0)
+ dx = numpy.zeros(0)
+ dy = numpy.zeros(0)
+ dxw = numpy.zeros(0)
+ dxl = numpy.zeros(0)
+
+ for item in nodes:
+ _x, attr = get_float('ns:Q', item)
+ _dx, attr_d = get_float('ns:Qdev', item)
+ _dxl, attr_l = get_float('ns:dQl', item)
+ _dxw, attr_w = get_float('ns:dQw', item)
+ if _dx == None:
+ _dx = 0.0
+ if _dxl == None:
+ _dxl = 0.0
+ if _dxw == None:
+ _dxw = 0.0
+
+ if attr.has_key('unit') and \
+ attr['unit'].lower() != data_info.x_unit.lower():
+ if has_converter==True:
+ try:
+ data_conv_q = Converter(attr['unit'])
+ _x = data_conv_q(_x, units=data_info.x_unit)
+ except:
+ msg = "CanSAS reader: could not convert "
+ msg += "Q unit [%s]; "
+ msg += "expecting [%s]\n %s" % (attr['unit'],
+ data_info.x_unit, sys.exc_value)
+ raise ValueError, msg
+
+ else:
+ msg = "CanSAS reader: unrecognized Q unit [%s]; "
+ msg += "expecting [%s]" % (attr['unit'], data_info.x_unit)
+ raise ValueError, msg
+
+ # Error in Q
+ if attr_d.has_key('unit') and \
+ attr_d['unit'].lower() != data_info.x_unit.lower():
+ if has_converter==True:
+ try:
+ data_conv_q = Converter(attr_d['unit'])
+ _dx = data_conv_q(_dx, units=data_info.x_unit)
+ except:
+ msg = "CanSAS reader: could not convert dQ unit [%s];"
+ msg += " expecting "
+ msg += "[%s]\n %s" % (attr['unit'],
+ data_info.x_unit, sys.exc_value)
+ raise ValueError, msg
+
+ else:
+ msg = "CanSAS reader: unrecognized dQ unit [%s]; "
+ msg += "expecting [%s]" % (attr['unit'], data_info.x_unit)
+ raise ValueError, msg
+
+ # Slit length
+ if attr_l.has_key('unit') and \
+ attr_l['unit'].lower() != data_info.x_unit.lower():
+ if has_converter == True:
+ try:
+ data_conv_q = Converter(attr_l['unit'])
+ _dxl = data_conv_q(_dxl, units=data_info.x_unit)
+ except:
+ msg = "CanSAS reader: could not convert dQl unit [%s];"
+ msg += " expecting [%s]\n %s" % (attr['unit'],
+ data_info.x_unit, sys.exc_value)
+ raise ValueError, msg
+
+ else:
+ msg = "CanSAS reader: unrecognized dQl unit [%s];"
+ msg += " expecting [%s]" % (attr['unit'], data_info.x_unit)
+ raise ValueError, msg
+
+ # Slit width
+ if attr_w.has_key('unit') and \
+ attr_w['unit'].lower() != data_info.x_unit.lower():
+ if has_converter == True:
+ try:
+ data_conv_q = Converter(attr_w['unit'])
+ _dxw = data_conv_q(_dxw, units=data_info.x_unit)
+ except:
+ msg = "CanSAS reader: could not convert dQw unit [%s];"
+ msg += " expecting [%s]\n %s" % (attr['unit'],
+ data_info.x_unit, sys.exc_value)
+ raise ValueError, msg
+
+ else:
+ msg = "CanSAS reader: unrecognized dQw unit [%s];"
+ msg += " expecting [%s]" % (attr['unit'], data_info.x_unit)
+ raise ValueError, msg
+ _y, attr = get_float('ns:I', item)
+ _dy, attr_d = get_float('ns:Idev', item)
+ if _dy == None:
+ _dy = 0.0
+ if attr.has_key('unit') and \
+ attr['unit'].lower() != data_info.y_unit.lower():
+ if has_converter==True:
+ try:
+ data_conv_i = Converter(attr['unit'])
+ _y = data_conv_i(_y, units=data_info.y_unit)
+ except:
+ msg = "CanSAS reader: could not convert I(q) unit [%s];"
+ msg += " expecting [%s]\n %s" % (attr['unit'],
+ data_info.y_unit, sys.exc_value)
+ raise ValueError, msg
+ else:
+ msg = "CanSAS reader: unrecognized I(q) unit [%s];"
+ msg += " expecting [%s]" % (attr['unit'], data_info.y_unit)
+ raise ValueError, msg
+
+ if attr_d.has_key('unit') and \
+ attr_d['unit'].lower() != data_info.y_unit.lower():
+ if has_converter==True:
+ try:
+ data_conv_i = Converter(attr_d['unit'])
+ _dy = data_conv_i(_dy, units=data_info.y_unit)
+ except:
+ msg = "CanSAS reader: could not convert dI(q) unit "
+ msg += "[%s]; expecting [%s]\n %s" % (attr_d['unit'],
+ data_info.y_unit, sys.exc_value)
+ raise ValueError, msg
+ else:
+ msg = "CanSAS reader: unrecognized dI(q) unit [%s]; "
+ msg += "expecting [%s]" % (attr_d['unit'], data_info.y_unit)
+ raise ValueError, msg
+
+ if _x is not None and _y is not None:
+ x = numpy.append(x, _x)
+ y = numpy.append(y, _y)
+ dx = numpy.append(dx, _dx)
+ dy = numpy.append(dy, _dy)
+ dxl = numpy.append(dxl, _dxl)
+ dxw = numpy.append(dxw, _dxw)
+
+ data_info.x = x
+ data_info.y = y
+ data_info.dx = dx
+ data_info.dy = dy
+ data_info.dxl = dxl
+ data_info.dxw = dxw
+
+ data_conv_q = None
+ data_conv_i = None
+
+ if has_converter == True and data_info.x_unit != '1/A':
+ data_conv_q = Converter('1/A')
+ # Test it
+ data_conv_q(1.0, output.Q_unit)
+
+ if has_converter == True and data_info.y_unit != '1/cm':
+ data_conv_i = Converter('1/cm')
+ # Test it
+ data_conv_i(1.0, output.I_unit)
+
+ if data_conv_q is not None:
+ data_info.xaxis("\\rm{Q}", data_info.x_unit)
+ else:
+ data_info.xaxis("\\rm{Q}", 'A^{-1}')
+ if data_conv_i is not None:
+ data_info.yaxis("\\rm{Intensity}", data_info.y_unit)
+ else:
+ data_info.yaxis("\\rm{Intensity}","cm^{-1}")
+
+ return data_info
+
+ def _to_xml_doc(self, datainfo):
+ """
+ Create an XML document to contain the content of a Data1D
+
+ :param datainfo: Data1D object
+ """
+
+ if not issubclass(datainfo.__class__, Data1D):
+ raise RuntimeError, "The cansas writer expects a Data1D instance"
+
+ doc = xml.dom.minidom.Document()
+ main_node = doc.createElement("SASroot")
+ main_node.setAttribute("version", self.version)
+ main_node.setAttribute("xmlns", "cansas1d/%s" % self.version)
+ main_node.setAttribute("xmlns:xsi",
+ "http://www.w3.org/2001/XMLSchema-instance")
+ main_node.setAttribute("xsi:schemaLocation",
+ "cansas1d/%s http://svn.smallangles.net/svn/canSAS/1dwg/trunk/cansas1d.xsd" % self.version)
+
+ doc.appendChild(main_node)
+
+ entry_node = doc.createElement("SASentry")
+ main_node.appendChild(entry_node)
+
+ write_node(doc, entry_node, "Title", datainfo.title)
+ for item in datainfo.run:
+ runname = {}
+ if datainfo.run_name.has_key(item) and \
+ len(str(datainfo.run_name[item]))>1:
+ runname = {'name': datainfo.run_name[item] }
+ write_node(doc, entry_node, "Run", item, runname)
+
+ # Data info
+ node = doc.createElement("SASdata")
+ entry_node.appendChild(node)
+
+ for i in range(len(datainfo.x)):
+ pt = doc.createElement("Idata")
+ node.appendChild(pt)
+ write_node(doc, pt, "Q", datainfo.x[i], {'unit':datainfo.x_unit})
+ if len(datainfo.y)>=i:
+ write_node(doc, pt, "I", datainfo.y[i],
+ {'unit':datainfo.y_unit})
+ if datainfo.dx != None and len(datainfo.dx) >= i:
+ write_node(doc, pt, "Qdev", datainfo.dx[i],
+ {'unit':datainfo.x_unit})
+ if datainfo.dxl != None and len(datainfo.dxl) >= i:
+ write_node(doc, pt, "dQl", datainfo.dxl[i],
+ {'unit':datainfo.x_unit})
+ if datainfo.dxw != None and len(datainfo.dxw) >= i:
+ write_node(doc, pt, "dQw", datainfo.dxw[i],
+ {'unit':datainfo.x_unit})
+ if datainfo.dy != None and len(datainfo.dy) >= i:
+ write_node(doc, pt, "Idev", datainfo.dy[i],
+ {'unit':datainfo.y_unit})
+ #data gui info
+ gui_info = doc.createElement("DataInfoGui")
+
+ write_node(doc, gui_info, "group_id", 'group_id')
+ for item in datainfo.group_id:
+ write_node(doc, gui_info, "group_id", str(item))
+ write_node(doc, gui_info, "name", datainfo.name)
+ write_node(doc, gui_info, "id", datainfo.id)
+ write_node(doc, gui_info, "group_id", datainfo.groud_id)
+ write_node(doc, gui_info, "name", datainfo.name)
+ write_node(doc, gui_info, "is_data", datainfo.is_data)
+ write_node(doc, gui_info, "xtransform", datainfo.xtransform)
+ write_node(doc, gui_info, "scale", datainfo.scale)
+ write_node(doc, gui_info, "ytransform", datainfo.ytransform)
+ write_node(doc, gui_info, "path", datainfo.path)
+ node.appendChild(gui_info)
+ # Sample info
+ sample = doc.createElement("SASsample")
+ if datainfo.sample.name is not None:
+ sample.setAttribute("name", str(datainfo.sample.name))
+ entry_node.appendChild(sample)
+ write_node(doc, sample, "ID", str(datainfo.sample.ID))
+ write_node(doc, sample, "thickness", datainfo.sample.thickness,
+ {"unit":datainfo.sample.thickness_unit})
+ write_node(doc, sample, "transmission", datainfo.sample.transmission)
+ write_node(doc, sample, "temperature", datainfo.sample.temperature,
+ {"unit":datainfo.sample.temperature_unit})
+
+ for item in datainfo.sample.details:
+ write_node(doc, sample, "details", item)
+
+ pos = doc.createElement("position")
+ written = write_node(doc, pos, "x", datainfo.sample.position.x,
+ {"unit":datainfo.sample.position_unit})
+ written = written | write_node(doc, pos, "y",
+ datainfo.sample.position.y,
+ {"unit":datainfo.sample.position_unit})
+ written = written | write_node(doc, pos, "z",
+ datainfo.sample.position.z,
+ {"unit":datainfo.sample.position_unit})
+ if written == True:
+ sample.appendChild(pos)
+
+ ori = doc.createElement("orientation")
+ written = write_node(doc, ori, "roll",
+ datainfo.sample.orientation.x,
+ {"unit":datainfo.sample.orientation_unit})
+ written = written | write_node(doc, ori, "pitch",
+ datainfo.sample.orientation.y,
+ {"unit":datainfo.sample.orientation_unit})
+ written = written | write_node(doc, ori, "yaw",
+ datainfo.sample.orientation.z,
+ {"unit":datainfo.sample.orientation_unit})
+ if written == True:
+ sample.appendChild(ori)
+
+ # Instrument info
+ instr = doc.createElement("SASinstrument")
+ entry_node.appendChild(instr)
+
+ write_node(doc, instr, "name", datainfo.instrument)
+
+ # Source
+ source = doc.createElement("SASsource")
+ if datainfo.source.name is not None:
+ source.setAttribute("name", str(datainfo.source.name))
+ instr.appendChild(source)
+
+ write_node(doc, source, "radiation", datainfo.source.radiation)
+ write_node(doc, source, "beam_shape", datainfo.source.beam_shape)
+ size = doc.createElement("beam_size")
+ if datainfo.source.beam_size_name is not None:
+ size.setAttribute("name", str(datainfo.source.beam_size_name))
+ written = write_node(doc, size, "x", datainfo.source.beam_size.x,
+ {"unit":datainfo.source.beam_size_unit})
+ written = written | write_node(doc, size, "y",
+ datainfo.source.beam_size.y,
+ {"unit":datainfo.source.beam_size_unit})
+ written = written | write_node(doc, size, "z",
+ datainfo.source.beam_size.z,
+ {"unit":datainfo.source.beam_size_unit})
+ if written == True:
+ source.appendChild(size)
+
+ write_node(doc, source, "wavelength",
+ datainfo.source.wavelength,
+ {"unit":datainfo.source.wavelength_unit})
+ write_node(doc, source, "wavelength_min",
+ datainfo.source.wavelength_min,
+ {"unit":datainfo.source.wavelength_min_unit})
+ write_node(doc, source, "wavelength_max",
+ datainfo.source.wavelength_max,
+ {"unit":datainfo.source.wavelength_max_unit})
+ write_node(doc, source, "wavelength_spread",
+ datainfo.source.wavelength_spread,
+ {"unit":datainfo.source.wavelength_spread_unit})
+
+ # Collimation
+ for item in datainfo.collimation:
+ coll = doc.createElement("SAScollimation")
+ if item.name is not None:
+ coll.setAttribute("name", str(item.name))
+ instr.appendChild(coll)
+
+ write_node(doc, coll, "length", item.length,
+ {"unit":item.length_unit})
+
+ for apert in item.aperture:
+ ap = doc.createElement("aperture")
+ if apert.name is not None:
+ ap.setAttribute("name", str(apert.name))
+ if apert.type is not None:
+ ap.setAttribute("type", str(apert.type))
+ coll.appendChild(ap)
+
+ write_node(doc, ap, "distance", apert.distance,
+ {"unit":apert.distance_unit})
+
+ size = doc.createElement("size")
+ if apert.size_name is not None:
+ size.setAttribute("name", str(apert.size_name))
+ written = write_node(doc, size, "x", apert.size.x,
+ {"unit":apert.size_unit})
+ written = written | write_node(doc, size, "y", apert.size.y,
+ {"unit":apert.size_unit})
+ written = written | write_node(doc, size, "z", apert.size.z,
+ {"unit":apert.size_unit})
+ if written == True:
+ ap.appendChild(size)
+
+ # Detectors
+ for item in datainfo.detector:
+ det = doc.createElement("SASdetector")
+ written = write_node(doc, det, "name", item.name)
+ written = written | write_node(doc, det, "SDD", item.distance,
+ {"unit":item.distance_unit})
+ written = written | write_node(doc, det, "slit_length",
+ item.slit_length,
+ {"unit":item.slit_length_unit})
+ if written == True:
+ instr.appendChild(det)
+
+ off = doc.createElement("offset")
+ written = write_node(doc, off, "x", item.offset.x,
+ {"unit":item.offset_unit})
+ written = written | write_node(doc, off, "y", item.offset.y,
+ {"unit":item.offset_unit})
+ written = written | write_node(doc, off, "z", item.offset.z,
+ {"unit":item.offset_unit})
+ if written == True:
+ det.appendChild(off)
+
+ center = doc.createElement("beam_center")
+ written = write_node(doc, center, "x", item.beam_center.x,
+ {"unit":item.beam_center_unit})
+ written = written | write_node(doc, center, "y",
+ item.beam_center.y,
+ {"unit":item.beam_center_unit})
+ written = written | write_node(doc, center, "z",
+ item.beam_center.z,
+ {"unit":item.beam_center_unit})
+ if written == True:
+ det.appendChild(center)
+
+ pix = doc.createElement("pixel_size")
+ written = write_node(doc, pix, "x", item.pixel_size.x,
+ {"unit":item.pixel_size_unit})
+ written = written | write_node(doc, pix, "y", item.pixel_size.y,
+ {"unit":item.pixel_size_unit})
+ written = written | write_node(doc, pix, "z", item.pixel_size.z,
+ {"unit":item.pixel_size_unit})
+ if written == True:
+ det.appendChild(pix)
+
+ ori = doc.createElement("orientation")
+ written = write_node(doc, ori, "roll", item.orientation.x,
+ {"unit":item.orientation_unit})
+ written = written | write_node(doc, ori, "pitch",
+ item.orientation.y,
+ {"unit":item.orientation_unit})
+ written = written | write_node(doc, ori, "yaw",
+ item.orientation.z,
+ {"unit":item.orientation_unit})
+ if written == True:
+ det.appendChild(ori)
+
+
+ # Processes info
+ for item in datainfo.process:
+ node = doc.createElement("SASprocess")
+ entry_node.appendChild(node)
+
+ write_node(doc, node, "name", item.name)
+ write_node(doc, node, "date", item.date)
+ write_node(doc, node, "description", item.description)
+ for term in item.term:
+ value = term['value']
+ del term['value']
+ write_node(doc, node, "term", value, term)
+ for note in item.notes:
+ write_node(doc, node, "SASprocessnote", note)
+
+ # Return the document, and the SASentry node associated with
+ # the data we just wrote
+ return doc, entry_node
+
+ def write(self, filename, datainfo):
+ """
+ Write the content of a Data1D as a CanSAS XML file
+
+ :param filename: name of the file to write
+ :param datainfo: Data1D object
+ """
+ # Create XML document
+ doc, sasentry = self._to_xml_doc(datainfo)
+ # Write the file
+ fd = open(filename, 'w')
+ fd.write(doc.toprettyxml())
+ fd.close()
+
+ def _store_float(self, location, node, variable, storage, optional=True):
+ """
+ Get the content of a xpath location and store
+ the result. Check that the units are compatible
+ with the destination. The value is expected to
+ be a float.
+
+ The xpath location might or might not exist.
+ If it does not exist, nothing is done
+
+ :param location: xpath location to fetch
+ :param node: node to read the data from
+ :param variable: name of the data member to store it in [string]
+ :param storage: data object that has the 'variable' data member
+ :param optional: if True, no exception will be raised
+ if unit conversion can't be done
+
+ :raise ValueError: raised when the units are not recognized
+ """
+ entry = get_content(location, node)
+ try:
+ value = float(entry.text)
+ except:
+ value = None
+
+ if value is not None:
+ # If the entry has units, check to see that they are
+ # compatible with what we currently have in the data object
+ units = entry.get('unit')
+ if units is not None:
+ toks = variable.split('.')
+ exec "local_unit = storage.%s_unit" % toks[0]
+ if units.lower()!=local_unit.lower():
+ if has_converter==True:
+ try:
+ conv = Converter(units)
+ exec "storage.%s = %g" % (variable,
+ conv(value, units=local_unit))
+ except:
+ err_mess = "CanSAS reader: could not convert"
+ err_mess += " %s unit [%s]; expecting [%s]\n %s" \
+ % (variable, units, local_unit, sys.exc_value)
+ self.errors.append(err_mess)
+ if optional:
+ logging.info(err_mess)
+ else:
+ raise ValueError, err_mess
+ else:
+ err_mess = "CanSAS reader: unrecognized %s unit [%s];"
+ err_mess += " expecting [%s]" % (variable,
+ units, local_unit)
+ self.errors.append(err_mess)
+ if optional:
+ logging.info(err_mess)
+ else:
+ raise ValueError, err_mess
+ else:
+ exec "storage.%s = value" % variable
+ else:
+ exec "storage.%s = value" % variable
+
+ def _store_content(self, location, node, variable, storage):
+ """
+ Get the content of a xpath location and store
+ the result. The value is treated as a string.
+
+ The xpath location might or might not exist.
+ If it does not exist, nothing is done
+
+ :param location: xpath location to fetch
+ :param node: node to read the data from
+ :param variable: name of the data member to store it in [string]
+ :param storage: data object that has the 'variable' data member
+
+ :return: return a list of errors
+ """
+ entry = get_content(location, node)
+ if entry is not None and entry.text is not None:
+ exec "storage.%s = entry.text.strip()" % variable
+
+
+
+class Reader2D:
+ """
+ Class to load a basic guiframe state
+ """
+ ## File type
+ type_name = "Fitting"
+
+ ## Wildcards
+ type = ["Fitting files (*.fitv)|*.fitv"
+ "SANSView file (*.svs)|*.svs"]
+ ## List of allowed extensions
+ ext=['.fitv', '.FITV', '.svs', 'SVS']
+
+ def __init__(self):
+ CansasReader.__init__(self)
+ """
+ Initialize the call-back method to be called
+ after we load a file
+
+ :param call_back: call-back method
+ :param cansas: True = files will be written/read in CanSAS format
+ False = write CanSAS format
+
+ """
+ ## Call back method to be executed after a file is read
+ #self.call_back = call_back
+ ## CanSAS format flag
+ self.cansas = cansas
+ self.state = None
+
+ def read(self, path):
+ """
+ Load a new P(r) inversion state from file
+
+ :param path: file path
+
+ """
+ if self.cansas == True:
+ return self._read_cansas(path)
+
+ def _to_xml_doc(self, datainfo):
+ """
+ Create an XML document to contain the content of a Data2D
+
+ :param datainfo: Data2D object
+
+ """
+ if not issubclass(datainfo.__class__, Data2D):
+ raise RuntimeError, "The cansas writer expects a Data2D instance"
+
+ doc = xml.dom.minidom.Document()
+ main_node = doc.createElement("SASroot")
+ main_node.setAttribute("version", self.version)
+ main_node.setAttribute("xmlns", "cansas1d/%s" % self.version)
+ main_node.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance")
+ main_node.setAttribute("xsi:schemaLocation", "cansas1d/%s http://svn.smallangles.net/svn/canSAS/1dwg/trunk/cansas1d.xsd" % self.version)
+
+ doc.appendChild(main_node)
+
+ entry_node = doc.createElement("SASentry")
+ main_node.appendChild(entry_node)
+
+ write_node(doc, entry_node, "Title", datainfo.title)
+ if datainfo is not None:
+ write_node(doc, entry_node, "data_class", datainfo.__class__.__name__)
+ for item in datainfo.run:
+ runname = {}
+ if datainfo.run_name.has_key(item) and len(str(datainfo.run_name[item]))>1:
+ runname = {'name': datainfo.run_name[item] }
+ write_node(doc, entry_node, "Run", item, runname)
+ # Data info
+ new_node = doc.createElement("SASdata")
+ entry_node.appendChild(new_node)
+ for item in list_of_data_2d_attr:
+ element = doc.createElement(item[0])
+ exec "element.setAttribute(item[0], str(datainfo.%s))"%(item[1])
+ new_node.appendChild(element)
+
+ for item in list_of_data2d_values:
+ root_node = doc.createElement(item[0])
+ new_node.appendChild(root_node)
+
+ exec "temp_list = datainfo.%s"%item[1]
+
+ if temp_list is None or len(temp_list)== 0:
+ element = doc.createElement(item[0])
+ exec "element.appendChild(doc.createTextNode(str(%s)))"%temp_list
+ root_node.appendChild(element)
+ else:
+ for value in temp_list:
+ element = doc.createElement(item[0])
+ exec "element.setAttribute(item[0], str(%s))"%value
+ root_node.appendChild(element)
+
+ # Sample info
+ sample = doc.createElement("SASsample")
+ if datainfo.sample.name is not None:
+ sample.setAttribute("name", str(datainfo.sample.name))
+ entry_node.appendChild(sample)
+ write_node(doc, sample, "ID", str(datainfo.sample.ID))
+ write_node(doc, sample, "thickness", datainfo.sample.thickness, {"unit":datainfo.sample.thickness_unit})
+ write_node(doc, sample, "transmission", datainfo.sample.transmission)
+ write_node(doc, sample, "temperature", datainfo.sample.temperature, {"unit":datainfo.sample.temperature_unit})
+
+ for item in datainfo.sample.details:
+ write_node(doc, sample, "details", item)
+
+ pos = doc.createElement("position")
+ written = write_node(doc, pos, "x", datainfo.sample.position.x, {"unit":datainfo.sample.position_unit})
+ written = written | write_node(doc, pos, "y", datainfo.sample.position.y, {"unit":datainfo.sample.position_unit})
+ written = written | write_node(doc, pos, "z", datainfo.sample.position.z, {"unit":datainfo.sample.position_unit})
+ if written == True:
+ sample.appendChild(pos)
+
+ ori = doc.createElement("orientation")
+ written = write_node(doc, ori, "roll", datainfo.sample.orientation.x, {"unit":datainfo.sample.orientation_unit})
+ written = written | write_node(doc, ori, "pitch", datainfo.sample.orientation.y, {"unit":datainfo.sample.orientation_unit})
+ written = written | write_node(doc, ori, "yaw", datainfo.sample.orientation.z, {"unit":datainfo.sample.orientation_unit})
+ if written == True:
+ sample.appendChild(ori)
+
+ # Instrument info
+ instr = doc.createElement("SASinstrument")
+ entry_node.appendChild(instr)
+
+ write_node(doc, instr, "name", datainfo.instrument)
+
+ # Source
+ source = doc.createElement("SASsource")
+ if datainfo.source.name is not None:
+ source.setAttribute("name", str(datainfo.source.name))
+ instr.appendChild(source)
+
+ write_node(doc, source, "radiation", datainfo.source.radiation)
+ write_node(doc, source, "beam_shape", datainfo.source.beam_shape)
+ size = doc.createElement("beam_size")
+ if datainfo.source.beam_size_name is not None:
+ size.setAttribute("name", str(datainfo.source.beam_size_name))
+ written = write_node(doc, size, "x", datainfo.source.beam_size.x, {"unit":datainfo.source.beam_size_unit})
+ written = written | write_node(doc, size, "y", datainfo.source.beam_size.y, {"unit":datainfo.source.beam_size_unit})
+ written = written | write_node(doc, size, "z", datainfo.source.beam_size.z, {"unit":datainfo.source.beam_size_unit})
+ if written == True:
+ source.appendChild(size)
+
+ write_node(doc, source, "wavelength", datainfo.source.wavelength, {"unit":datainfo.source.wavelength_unit})
+ write_node(doc, source, "wavelength_min", datainfo.source.wavelength_min, {"unit":datainfo.source.wavelength_min_unit})
+ write_node(doc, source, "wavelength_max", datainfo.source.wavelength_max, {"unit":datainfo.source.wavelength_max_unit})
+ write_node(doc, source, "wavelength_spread", datainfo.source.wavelength_spread, {"unit":datainfo.source.wavelength_spread_unit})
+
+ # Collimation
+ for item in datainfo.collimation:
+ coll = doc.createElement("SAScollimation")
+ if item.name is not None:
+ coll.setAttribute("name", str(item.name))
+ instr.appendChild(coll)
+
+ write_node(doc, coll, "length", item.length, {"unit":item.length_unit})
+
+ for apert in item.aperture:
+ ap = doc.createElement("aperture")
+ if apert.name is not None:
+ ap.setAttribute("name", str(apert.name))
+ if apert.type is not None:
+ ap.setAttribute("type", str(apert.type))
+ coll.appendChild(ap)
+
+ write_node(doc, ap, "distance", apert.distance, {"unit":apert.distance_unit})
+
+ size = doc.createElement("size")
+ if apert.size_name is not None:
+ size.setAttribute("name", str(apert.size_name))
+ written = write_node(doc, size, "x", apert.size.x, {"unit":apert.size_unit})
+ written = written | write_node(doc, size, "y", apert.size.y, {"unit":apert.size_unit})
+ written = written | write_node(doc, size, "z", apert.size.z, {"unit":apert.size_unit})
+ if written == True:
+ ap.appendChild(size)
+
+ # Detectors
+ for item in datainfo.detector:
+ det = doc.createElement("SASdetector")
+ written = write_node(doc, det, "name", item.name)
+ written = written | write_node(doc, det, "SDD", item.distance, {"unit":item.distance_unit})
+ written = written | write_node(doc, det, "slit_length", item.slit_length, {"unit":item.slit_length_unit})
+ if written == True:
+ instr.appendChild(det)
+
+ off = doc.createElement("offset")
+ written = write_node(doc, off, "x", item.offset.x, {"unit":item.offset_unit})
+ written = written | write_node(doc, off, "y", item.offset.y, {"unit":item.offset_unit})
+ written = written | write_node(doc, off, "z", item.offset.z, {"unit":item.offset_unit})
+ if written == True:
+ det.appendChild(off)
+
+ center = doc.createElement("beam_center")
+ written = write_node(doc, center, "x", item.beam_center.x, {"unit":item.beam_center_unit})
+ written = written | write_node(doc, center, "y", item.beam_center.y, {"unit":item.beam_center_unit})
+ written = written | write_node(doc, center, "z", item.beam_center.z, {"unit":item.beam_center_unit})
+ if written == True:
+ det.appendChild(center)
+
+ pix = doc.createElement("pixel_size")
+ written = write_node(doc, pix, "x", item.pixel_size.x, {"unit":item.pixel_size_unit})
+ written = written | write_node(doc, pix, "y", item.pixel_size.y, {"unit":item.pixel_size_unit})
+ written = written | write_node(doc, pix, "z", item.pixel_size.z, {"unit":item.pixel_size_unit})
+ if written == True:
+ det.appendChild(pix)
+
+ ori = doc.createElement("orientation")
+ written = write_node(doc, ori, "roll", item.orientation.x, {"unit":item.orientation_unit})
+ written = written | write_node(doc, ori, "pitch", item.orientation.y, {"unit":item.orientation_unit})
+ written = written | write_node(doc, ori, "yaw", item.orientation.z, {"unit":item.orientation_unit})
+ if written == True:
+ det.appendChild(ori)
+
+ # Processes info
+ for item in datainfo.process:
+ node = doc.createElement("SASprocess")
+ entry_node.appendChild(node)
+
+ write_node(doc, node, "name", item.name)
+ write_node(doc, node, "date", item.date)
+ write_node(doc, node, "description", item.description)
+ for term in item.term:
+ value = term['value']
+ del term['value']
+ write_node(doc, node, "term", value, term)
+ for note in item.notes:
+ write_node(doc, node, "SASprocessnote", note)
+ # Return the document, and the SASentry node associated with
+ # the data we just wrote
+ return doc, entry_node
+
+ def _parse_state(self, entry, NODE_NAME= 'state'):
+ """
+ Read a fit result from an XML node
+
+ :param entry: XML node to read from
+
+ :return: PageState object
+ """
+ # Create an empty state
+ state = None
+ # Locate the P(r) node
+ try:
+ nodes = entry.xpath('ns:%s' % NODE_NAME, namespaces={'ns': STATE_NODE})
+ if nodes !=[]:
+ # Create an empty state
+ state = PageState()
+ state.fromXML(node=nodes[0])
+ except:
+ logging.info("XML document does not contain fitting information.\n %s" % sys.exc_value)
+
+ return state
+
+
+
+ def _parse_entry(self, dom):
+ """
+ Parse a SASentry
+
+ :param node: SASentry node
+
+ :return: Data1D/Data2D object
+
+ """
+ node = dom.xpath('ns:data_class', namespaces={'ns': STATE_NODE})
+ if not node or node[0].text.lstrip().rstrip() != "Data2D":
+ return CansasReader._parse_entry(self, dom)
+
+ #Parse 2D
+ data_info = Data2D()
+
+ # Look up title
+ self._store_content('ns:Title', dom, 'title', data_info)
+
+ # Look up run number
+ nodes = dom.xpath('ns:Run', namespaces={'ns': STATE_NODE})
+ for item in nodes:
+ if item.text is not None:
+ value = item.text.strip()
+ if len(value) > 0:
+ data_info.run.append(value)
+ if item.get('name') is not None:
+ data_info.run_name[value] = item.get('name')
+
+ # Look up instrument name
+ self._store_content('ns:SASinstrument/ns:name', dom, 'instrument', data_info)
+
+ # Notes
+ note_list = dom.xpath('ns:SASnote', namespaces={'ns': STATE_NODE})
+ for note in note_list:
+ try:
+ if note.text is not None:
+ note_value = note.text.strip()
+ if len(note_value) > 0:
+ data_info.notes.append(note_value)
+ except:
+ err_mess = "state_reader.read: error processing entry notes\n %s" % sys.exc_value
+ self.errors.append(err_mess)
+ logging.error(err_mess)
+
+ # Sample info ###################
+ entry = get_content('ns:SASsample', dom)
+ if entry is not None:
+ data_info.sample.name = entry.get('name')
+
+ self._store_content('ns:SASsample/ns:ID',
+ dom, 'ID', data_info.sample)
+ self._store_float('ns:SASsample/ns:thickness',
+ dom, 'thickness', data_info.sample)
+ self._store_float('ns:SASsample/ns:transmission',
+ dom, 'transmission', data_info.sample)
+ self._store_float('ns:SASsample/ns:temperature',
+ dom, 'temperature', data_info.sample)
+
+ nodes = dom.xpath('ns:SASsample/ns:details', namespaces={'ns': STATE_NODE})
+ for item in nodes:
+ try:
+ if item.text is not None:
+ detail_value = item.text.strip()
+ if len(detail_value) > 0:
+ data_info.sample.details.append(detail_value)
+ except:
+ err_mess = "state_reader.read: error processing sample details\n %s" % sys.exc_value
+ self.errors.append(err_mess)
+ logging.error(err_mess)
+
+ # Position (as a vector)
+ self._store_float('ns:SASsample/ns:position/ns:x',
+ dom, 'position.x', data_info.sample)
+ self._store_float('ns:SASsample/ns:position/ns:y',
+ dom, 'position.y', data_info.sample)
+ self._store_float('ns:SASsample/ns:position/ns:z',
+ dom, 'position.z', data_info.sample)
+
+ # Orientation (as a vector)
+ self._store_float('ns:SASsample/ns:orientation/ns:roll',
+ dom, 'orientation.x', data_info.sample)
+ self._store_float('ns:SASsample/ns:orientation/ns:pitch',
+ dom, 'orientation.y', data_info.sample)
+ self._store_float('ns:SASsample/ns:orientation/ns:yaw',
+ dom, 'orientation.z', data_info.sample)
+
+ # Source info ###################
+ entry = get_content('ns:SASinstrument/ns:SASsource', dom)
+ if entry is not None:
+ data_info.source.name = entry.get('name')
+
+ self._store_content('ns:SASinstrument/ns:SASsource/ns:radiation',
+ dom, 'radiation', data_info.source)
+ self._store_content('ns:SASinstrument/ns:SASsource/ns:beam_shape',
+ dom, 'beam_shape', data_info.source)
+ self._store_float('ns:SASinstrument/ns:SASsource/ns:wavelength',
+ dom, 'wavelength', data_info.source)
+ self._store_float('ns:SASinstrument/ns:SASsource/ns:wavelength_min',
+ dom, 'wavelength_min', data_info.source)
+ self._store_float('ns:SASinstrument/ns:SASsource/ns:wavelength_max',
+ dom, 'wavelength_max', data_info.source)
+ self._store_float('ns:SASinstrument/ns:SASsource/ns:wavelength_spread',
+ dom, 'wavelength_spread', data_info.source)
+
+ # Beam size (as a vector)
+ entry = get_content('ns:SASinstrument/ns:SASsource/ns:beam_size', dom)
+ if entry is not None:
+ data_info.source.beam_size_name = entry.get('name')
+
+ self._store_float('ns:SASinstrument/ns:SASsource/ns:beam_size/ns:x',
+ dom, 'beam_size.x', data_info.source)
+ self._store_float('ns:SASinstrument/ns:SASsource/ns:beam_size/ns:y',
+ dom, 'beam_size.y', data_info.source)
+ self._store_float('ns:SASinstrument/ns:SASsource/ns:beam_size/ns:z',
+ dom, 'beam_size.z', data_info.source)
+
+ # Collimation info ###################
+ nodes = dom.xpath('ns:SASinstrument/ns:SAScollimation', namespaces={'ns': STATE_NODE})
+ for item in nodes:
+ collim = Collimation()
+ if item.get('name') is not None:
+ collim.name = item.get('name')
+ self._store_float('ns:length', item, 'length', collim)
+
+ # Look for apertures
+ apert_list = item.xpath('ns:aperture', namespaces={'ns': STATE_NODE})
+ for apert in apert_list:
+ aperture = Aperture()
+
+ # Get the name and type of the aperture
+ aperture.name = apert.get('name')
+ aperture.type = apert.get('type')
+
+ self._store_float('ns:distance', apert, 'distance', aperture)
+
+ entry = get_content('ns:size', apert)
+ if entry is not None:
+ aperture.size_name = entry.get('name')
+
+ self._store_float('ns:size/ns:x', apert, 'size.x', aperture)
+ self._store_float('ns:size/ns:y', apert, 'size.y', aperture)
+ self._store_float('ns:size/ns:z', apert, 'size.z', aperture)
+
+ collim.aperture.append(aperture)
+
+ data_info.collimation.append(collim)
+
+ # Detector info ######################
+ nodes = dom.xpath('ns:SASinstrument/ns:SASdetector', namespaces={'ns': STATE_NODE})
+ for item in nodes:
+
+ detector = Detector()
+
+ self._store_content('ns:name', item, 'name', detector)
+ self._store_float('ns:SDD', item, 'distance', detector)
+
+ # Detector offset (as a vector)
+ self._store_float('ns:offset/ns:x', item, 'offset.x', detector)
+ self._store_float('ns:offset/ns:y', item, 'offset.y', detector)
+ self._store_float('ns:offset/ns:z', item, 'offset.z', detector)
+
+ # Detector orientation (as a vector)
+ self._store_float('ns:orientation/ns:roll', item, 'orientation.x', detector)
+ self._store_float('ns:orientation/ns:pitch', item, 'orientation.y', detector)
+ self._store_float('ns:orientation/ns:yaw', item, 'orientation.z', detector)
+
+ # Beam center (as a vector)
+ self._store_float('ns:beam_center/ns:x', item, 'beam_center.x', detector)
+ self._store_float('ns:beam_center/ns:y', item, 'beam_center.y', detector)
+ self._store_float('ns:beam_center/ns:z', item, 'beam_center.z', detector)
+
+ # Pixel size (as a vector)
+ self._store_float('ns:pixel_size/ns:x', item, 'pixel_size.x', detector)
+ self._store_float('ns:pixel_size/ns:y', item, 'pixel_size.y', detector)
+ self._store_float('ns:pixel_size/ns:z', item, 'pixel_size.z', detector)
+
+ self._store_float('ns:slit_length', item, 'slit_length', detector)
+
+ data_info.detector.append(detector)
+
+ # Processes info ######################
+ nodes = dom.xpath('ns:SASprocess', namespaces={'ns': STATE_NODE})
+ for item in nodes:
+ process = Process()
+ self._store_content('ns:name', item, 'name', process)
+ self._store_content('ns:date', item, 'date', process)
+ self._store_content('ns:description', item, 'description', process)
+
+ term_list = item.xpath('ns:term', namespaces={'ns': STATE_NODE})
+ for term in term_list:
+ try:
+ term_attr = {}
+ for attr in term.keys():
+ term_attr[attr] = term.get(attr).strip()
+ if term.text is not None:
+ term_attr['value'] = term.text.strip()
+ process.term.append(term_attr)
+ except:
+ err_mess = "state_reader.read: error processing process term\n %s" % sys.exc_value
+ self.errors.append(err_mess)
+ logging.error(err_mess)
+
+ note_list = item.xpath('ns:SASprocessnote', namespaces={'ns': STATE_NODE})
+ for note in note_list:
+ if note.text is not None:
+ process.notes.append(note.text.strip())
+
+ data_info.process.append(process)
+
+
+ # Data info ######################
+ nodes = dom.xpath('ns:SASdata', namespaces={'ns': STATE_NODE})
+ if len(nodes)>1:
+ raise RuntimeError, "CanSAS reader is not compatible with multiple SASdata entries"
+
+ for entry in nodes:
+ for item in list_of_data_2d_attr:
+ #get node
+ node = get_content('ns:%s'%item[0], entry)
+ exec "data_info.%s = parse_entry_helper(node, item)"%(item[1])
+
+ for item in list_of_data2d_values:
+ field = get_content('ns:%s'%item[0], entry)
+ list = []
+ if field is not None:
+ list = [parse_entry_helper(node, item) for node in field]
+ exec "data_info.%s = numpy.array(list)"%item[0]
+
+ return data_info
+
+ def _read_cansas(self, path):
+ """
+ Load data and P(r) information from a CanSAS XML file.
+
+ :param path: file path
+
+ :return: Data1D object if a single SASentry was found,
+ or a list of Data1D objects if multiple entries were found,
+ or None of nothing was found
+
+ :raise RuntimeError: when the file can't be opened
+ :raise ValueError: when the length of the data vectors are inconsistent
+
+ """
+ output = []
+ basename = os.path.basename(path)
+ root, extension = os.path.splitext(basename)
+ ext = extension.lower()
+ try:
+ if os.path.isfile(path):
+
+ #TODO: eventually remove the check for .xml once
+ # the P(r) writer/reader is truly complete.
+ if ext in self.ext or \
+ ext == '.xml':
+
+ tree = etree.parse(path, parser=etree.ETCompatXMLParser())
+ # Check the format version number
+ # Specifying the namespace will take care of the file format version
+ root = tree.getroot()
+ entry_list = root.xpath('ns:SASentry', namespaces={'ns': STATE_NODE})
+ for entry in entry_list:
+ try:
+ sas_entry = self._parse_entry(entry)
+ except:
+ raise
+ fitstate = self._parse_state(entry)
+
+ #state could be None when .svs file is loaded
+ #in this case, skip appending to output
+ if fitstate != None:
+ sas_entry.meta_data['fitstate'] = fitstate
+ sas_entry.filename = fitstate.file
+ output.append(sas_entry)
+ else:
+ self.call_back(format=ext)
+ raise RuntimeError, "%s is not a file" % path
+
+ # Return output consistent with the loader's api
+ if len(output)==0:
+ self.call_back(state=None, datainfo=None,format=ext)
+ return None
+ else:
+ for ind in range(len(output)):
+ # Call back to post the new state
+ state = output[ind].meta_data['fitstate']
+ t = time.localtime(state.timestamp)
+ time_str = time.strftime("%b %d %H:%M", t)
+ # Check that no time stamp is already appended
+ max_char = state.file.find("[")
+ if max_char < 0:
+ max_char = len(state.file)
+ original_fname = state.file[0:max_char]
+ state.file = original_fname +' [' + time_str + ']'
+
+
+ if state is not None and state.is_data is not None:
+ exec 'output[%d].is_data = state.is_data'% ind
+
+ output[ind].filename = state.file
+ state.data = output[ind]
+ state.data.name = output[ind].filename #state.data_name
+ state.data.id = state.data_id
+ if state.is_data is not None:
+ state.data.is_data = state.is_data
+ if output[ind].run_name is not None and\
+ len(output[ind].run_name) != 0 :
+ name = output[ind].run_name
+ else:
+ name=original_fname
+ state.data.group_id = name
+ #store state in fitting
+ self.call_back(state=state, datainfo=output[ind],format=ext)
+ self.state= state
+ return output
+
+ except:
+ #self.call_back(format=ext)
+ self.state= state
+ raise
+
+ def write(self, filename, datainfo=None, fitstate=None):
+ """
+ Write the content of a Data1D as a CanSAS XML file only for standalone
+
+ :param filename: name of the file to write
+ :param datainfo: Data1D object
+ :param fitstate: PageState object
+
+ """
+ # Sanity check
+ if self.cansas == True:
+
+ # Add fitting information to the XML document
+ doc = self.write_toXML(datainfo, fitstate)
+ # Write the XML document
+ fd = open(filename, 'w')
+ fd.write(doc.toprettyxml())
+ fd.close()
+ else:
+ fitstate.toXML(file=filename)
+
+ def write_toXML(self, datainfo=None, state=None):
+ """
+ Write toXML, a helper for write() , could be used by guimanager._on_save()
+
+ : return: xml doc
+ """
+
+ if state.data is None:
+ data = Data2D()
+ else:
+ #make sure title and data run is filled up.
+ if state.data.title == None or state.data.title=='':
+ state.data.title = state.data.name
+ if state.data.run_name == None or state.data.run_name=={}:
+ state.data.run = [str(state.data.name)]
+ state.data.run_name[0] = state.data.name
+ doc, sasentry = self._to_xml_doc(data)
+
+
+ if state is not None:
+ state.toXML(doc=doc, file=data.name, entry_node=sasentry)
+
+ return doc
+
+if __name__ == "__main__":
+ state = PageState(parent=None)
+ #state.toXML()
+ """
+
+ file = open("test_state", "w")
+ pickle.dump(state, file)
+ print pickle.dumps(state)
+ state.data_name = "hello---->"
+ pickle.dump(state, file)
+ file = open("test_state", "r")
+ new_state= pickle.load(file)
+ print "new state", new_state
+ new_state= pickle.load(file)
+ print "new state", new_state
+ #print "state", state
+ """
+ import bsddb
+ import pickle
+ db= bsddb.btopen('file_state.db', 'c')
+ val = (pickle.dumps(state), "hello", "hi")
+ db['state1']= pickle.dumps(val)
+ print pickle.loads(db['state1'])
+ state.data_name = "hello---->22"
+ db['state2']= pickle.dumps(state)
+ state.data_name = "hello---->2"
+ db['state3']= pickle.dumps(state)
+ del db['state3']
+ state.data_name = "hello---->3"
+ db['state4']= pickle.dumps(state)
+ new_state = pickle.loads(db['state1'])
+ #print db.last()
+ db.set_location('state2')
+ state.data_name = "hello---->5"
+ db['aastate5']= pickle.dumps(state)
+ db.keys().sort()
+ print pickle.loads(db['state2'])
+
+ db.close()
+
+ logging.basicConfig(level=logging.ERROR,
+ format='%(asctime)s %(levelname)s %(message)s',
+ filename='state_reader.log',
+ filemode='w')
+ reader = Reader()
+ print reader.read("../test/cansas1d.xml")
+ #print reader.read("../test/latex_smeared.xml")
+
+
+
Index: test/test_rename_guiframe/test/cansas1d.xml
===================================================================
--- test/test_rename_guiframe/test/cansas1d.xml (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/test/cansas1d.xml (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,141 @@
+
+
+
+
+ Test title
+ 1234
+
+
+ 0.02
+ 1000
+ 3
+ 0.01
+
+
+
+
+ 0.03
+ 1001
+ 4
+ 0.02
+
+
+
+
+
+ SI600-new-long
+ 1.03
+ 0.327
+ 0.0000
+
+ 10.00
+ 0.00
+
+
+ 22.5
+ 0.020
+
+
+
+ http://chemtools.chem.soton.ac.uk/projects/blog/blogs.php/bit_id/2720
+
+
+ Some text here
+
+
+
+
+ canSAS instrument
+
+ neutron
+
+ 12.00
+ 13.00
+
+ disc
+ 6.00
+ 0.22
+ 1.00
+
+ 14.3
+
+
+
+ 123.0
+
+
+ 50
+
+ 11.000
+
+
+
+ 1
+
+
+
+
+ fictional hybrid
+
+
+ 4.150
+
+
+ 1.00
+ 0.00
+ 0.00
+
+
+ 1
+ 2
+
+
+ 322.64
+ 327.68
+
+
+ 5.00
+ 5.00
+
+
+
+
+ spol
+ 04-Sep-2007 18:35:02
+ 10.000
+ 180.0
+ 0.0
+ USER:MASK.COM
+
+ AvA1 0.0000E+00 AsA2 1.0000E+00 XvA3 1.0526E+03 XsA4
+ 5.2200E-02 XfA5 0.0000E+00
+
+
+ S... 13597 0 2.26E+02 2A 5mM 0%D2O Sbak 13594 0 1.13E+02
+ H2O Buffer
+
+ V... 13552 3 1.00E+00 H2O5m
+
+
+ NCNR-IGOR
+ 03-SEP-2006 11:42:47
+
+ Circular
+ SEP06064.SA3_AJJ_L205
+ SEP06064.SA3_AJJ_L205
+ SEP06064.SA3_AJJ_L205
+ SEP06064.SA3_AJJ_L205
+ SEP06064.SA3_AJJ_L205
+ 1
+ 1
+ 230.09
+ 1
+
+
+
+
+
Index: test/test_rename_guiframe/test/utest_manipulations.py
===================================================================
--- test/test_rename_guiframe/test/utest_manipulations.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/test/utest_manipulations.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,262 @@
+"""
+ Unit tests for data manipulations
+"""
+#TODO: what happens if you add a Data1D to a Data2D?
+
+import unittest
+import numpy, math
+from DataLoader.loader import Loader
+from sans.guiframe.dataFitting import Theory1D, Data1D, Data2D
+
+import os.path
+
+class data_info_tests(unittest.TestCase):
+
+ def setUp(self):
+ self.data = Loader().load("cansas1d.xml")
+
+ def test_clone1D(self):
+ """
+ Test basic cloning
+ """
+ clone = self.data.clone_without_data()
+
+ for i in range(len(self.data.detector)):
+ self.assertEqual(self.data.detector[i].distance, clone.detector[i].distance)
+
+class theory1d_tests(unittest.TestCase):
+
+ def setUp(self):
+ self.data = Loader().load("cansas1d.xml")
+
+ def test_clone_theory1D(self):
+ """
+ Test basic cloning
+ """
+ theory = Theory1D(x=[], y=[], dy=None)
+ theory.clone_without_data(clone=self.data)
+ theory.copy_from_datainfo(data1d=self.data)
+ for i in range(len(self.data.detector)):
+ self.assertEqual(self.data.detector[i].distance, theory.detector[i].distance)
+
+ for i in range(len(self.data.x)):
+ self.assertEqual(self.data.x[i], theory.x[i])
+ self.assertEqual(self.data.y[i], theory.y[i])
+ self.assertEqual(self.data.dy[i], theory.dy[i])
+
+class manip_tests(unittest.TestCase):
+
+ def setUp(self):
+ # Create two data sets to play with
+ x_0 = numpy.ones(5)
+ for i in range(5):
+ x_0[i] = x_0[i]*(i+1.0)
+
+ y_0 = 2.0*numpy.ones(5)
+ dy_0 = 0.5*numpy.ones(5)
+ self.data = Data1D(x_0, y_0, dy=dy_0)
+
+ x = self.data.x
+ y = numpy.ones(5)
+ dy = numpy.ones(5)
+ self.data2 = Data1D(x, y, dy=dy)
+
+
+ def test_load(self):
+ """
+ Test whether the test file was loaded properly
+ """
+ # There should be 5 entries in the file
+ self.assertEqual(len(self.data.x), 5)
+
+ for i in range(5):
+ # The x values should be from 1 to 5
+ self.assertEqual(self.data.x[i], float(i+1))
+
+ # All y-error values should be 0.5
+ self.assertEqual(self.data.dy[i], 0.5)
+
+ # All y values should be 2.0
+ self.assertEqual(self.data.y[i], 2.0)
+
+ def test_add(self):
+ result = self.data2+self.data
+ for i in range(5):
+ self.assertEqual(result.y[i], 3.0)
+ self.assertEqual(result.dy[i], math.sqrt(0.5**2+1.0))
+
+ def test_sub(self):
+ result = self.data2-self.data
+ for i in range(5):
+ self.assertEqual(result.y[i], -1.0)
+ self.assertEqual(result.dy[i], math.sqrt(0.5**2+1.0))
+
+ def test_mul(self):
+ result = self.data2*self.data
+ for i in range(5):
+ self.assertEqual(result.y[i], 2.0)
+ self.assertEqual(result.dy[i], math.sqrt((0.5*1.0)**2+(1.0*2.0)**2))
+
+ def test_div(self):
+ result = self.data2/self.data
+ for i in range(5):
+ self.assertEqual(result.y[i], 0.5)
+ self.assertEqual(result.dy[i], math.sqrt((1.0/2.0)**2+(0.5*1.0/4.0)**2))
+
+ def test_radd(self):
+ result = self.data+3.0
+ for i in range(5):
+ self.assertEqual(result.y[i], 5.0)
+ self.assertEqual(result.dy[i], 0.5)
+
+ result = 3.0+self.data
+ for i in range(5):
+ self.assertEqual(result.y[i], 5.0)
+ self.assertEqual(result.dy[i], 0.5)
+
+ def test_rsub(self):
+ result = self.data-3.0
+ for i in range(5):
+ self.assertEqual(result.y[i], -1.0)
+ self.assertEqual(result.dy[i], 0.5)
+
+ result = 3.0-self.data
+ for i in range(5):
+ self.assertEqual(result.y[i], 1.0)
+ self.assertEqual(result.dy[i], 0.5)
+
+ def test_rmul(self):
+ result = self.data*3.0
+ for i in range(5):
+ self.assertEqual(result.y[i], 6.0)
+ self.assertEqual(result.dy[i], 1.5)
+
+ result = 3.0*self.data
+ for i in range(5):
+ self.assertEqual(result.y[i], 6.0)
+ self.assertEqual(result.dy[i], 1.5)
+
+ def test_rdiv(self):
+ result = self.data/4.0
+ for i in range(5):
+ self.assertEqual(result.y[i], 0.5)
+ self.assertEqual(result.dy[i], 0.125)
+
+ result = 6.0/self.data
+ for i in range(5):
+ self.assertEqual(result.y[i], 3.0)
+ self.assertEqual(result.dy[i], 6.0*0.5/4.0)
+
+class manip_2D(unittest.TestCase):
+
+ def setUp(self):
+ # Create two data sets to play with
+ x_0 = 2.0*numpy.ones([5,4])
+ dx_0 = 0.5*numpy.ones([5,4])
+ self.data = Data2D(x_0, dx_0)
+
+ y = numpy.ones([5,4])
+ dy = numpy.ones([5,4])
+ self.data2 = Data2D(y, dy)
+
+
+ def test_load(self):
+ """
+ Test whether the test file was loaded properly
+ """
+ # There should be 5 entries in the file
+ self.assertEqual(numpy.size(self.data.data, 0), 5)
+ self.assertEqual(numpy.size(self.data.data, 1), 4)
+
+ for i in range(5):
+ for j in range(4):
+ # All y-error values should be 0.5
+ self.assertEqual(self.data.err_data[i][j], 0.5)
+
+ # All y values should be 2.0
+ self.assertEqual(self.data.data[i][j], 2.0)
+
+ def test_add(self):
+ result = self.data2+self.data
+ for i in range(5):
+ for j in range(4):
+ self.assertEqual(result.data[i][j], 3.0)
+ self.assertEqual(result.err_data[i][j], math.sqrt(0.5**2+1.0))
+
+ def test_sub(self):
+ result = self.data2-self.data
+ for i in range(5):
+ for j in range(4):
+ self.assertEqual(result.data[i][j], -1.0)
+ self.assertEqual(result.err_data[i][j], math.sqrt(0.5**2+1.0))
+
+ def test_mul(self):
+ result = self.data2*self.data
+ for i in range(5):
+ for j in range(4):
+ self.assertEqual(result.data[i][j], 2.0)
+ self.assertEqual(result.err_data[i][j], math.sqrt((0.5*1.0)**2+(1.0*2.0)**2))
+
+ def test_div(self):
+ result = self.data2/self.data
+ for i in range(5):
+ for j in range(4):
+ self.assertEqual(result.data[i][j], 0.5)
+ self.assertEqual(result.err_data[i][j], math.sqrt((1.0/2.0)**2+(0.5*1.0/4.0)**2))
+
+ def test_radd(self):
+ result = self.data+3.0
+ for i in range(5):
+ for j in range(4):
+ self.assertEqual(result.data[i][j], 5.0)
+ self.assertEqual(result.err_data[i][j], 0.5)
+
+ result = 3.0+self.data
+ for i in range(5):
+ for j in range(4):
+ self.assertEqual(result.data[i][j], 5.0)
+ self.assertEqual(result.err_data[i][j], 0.5)
+
+ def test_rsub(self):
+ result = self.data-3.0
+ for i in range(5):
+ for j in range(4):
+ self.assertEqual(result.data[i][j], -1.0)
+ self.assertEqual(result.err_data[i][j], 0.5)
+
+ result = 3.0-self.data
+ for i in range(5):
+ for j in range(4):
+ self.assertEqual(result.data[i][j], 1.0)
+ self.assertEqual(result.err_data[i][j], 0.5)
+
+ def test_rmul(self):
+ result = self.data*3.0
+ for i in range(5):
+ for j in range(4):
+ self.assertEqual(result.data[i][j], 6.0)
+ self.assertEqual(result.err_data[i][j], 1.5)
+
+ result = 3.0*self.data
+ for i in range(5):
+ for j in range(4):
+ self.assertEqual(result.data[i][j], 6.0)
+ self.assertEqual(result.err_data[i][j], 1.5)
+
+ def test_rdiv(self):
+ result = self.data/4.0
+ for i in range(5):
+ for j in range(4):
+ self.assertEqual(result.data[i][j], 0.5)
+ self.assertEqual(result.err_data[i][j], 0.125)
+
+ result = 6.0/self.data
+ for i in range(5):
+ for j in range(4):
+ self.assertEqual(result.data[i][j], 3.0)
+ self.assertEqual(result.err_data[i][j], 6.0*0.5/4.0)
+
+
+if __name__ == '__main__':
+ unittest.main()
+
Index: test/test_rename_guiframe/todo.txt
===================================================================
--- test/test_rename_guiframe/todo.txt (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/todo.txt (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,1 @@
+- Call _check_update in a separate thread
Index: test/test_rename_guiframe/utils.py
===================================================================
--- test/test_rename_guiframe/utils.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/utils.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,124 @@
+"""
+Contains common classes and functions
+"""
+import wx
+import re
+
+def parse_name(name, expression):
+ """
+ remove "_" in front of a name
+ """
+ if re.match(expression, name) is not None:
+ word = re.split(expression, name, 1)
+ for item in word:
+ if item.lstrip().rstrip() != '':
+ return item
+ else:
+ return name
+def format_number(value, high=False):
+ """
+ Return a float in a standardized, human-readable formatted string
+ """
+ try:
+ value = float(value)
+ except:
+ output = "NaN"
+ return output.lstrip().rstrip()
+ if high:
+ output = "%-7.5g" % value
+ else:
+ output = "%-5.3g" % value
+ return output.lstrip().rstrip()
+
+def check_float(item):
+ """
+ :param item: txtcrtl containing a value
+ """
+ flag = True
+ try:
+ mini = float(item.GetValue())
+ item.SetBackgroundColour(wx.WHITE)
+ item.Refresh()
+ except:
+ flag = False
+ item.SetBackgroundColour("pink")
+ item.Refresh()
+ return flag
+
+
+class PanelMenu(wx.Menu):
+ """
+ """
+ plots = None
+ graph = None
+
+ def set_plots(self, plots):
+ """
+ """
+ self.plots = plots
+
+ def set_graph(self, graph):
+ """
+ """
+ self.graph = graph
+
+
+def split_list(separator, mylist, n=0):
+ """
+ returns a list of string without white space of separator
+
+ :param separator: the string to remove
+
+ """
+ list = []
+ for item in mylist:
+ if re.search(separator,item)!= None:
+ if n > 0:
+ word = re.split(separator, item, int(n))
+ else:
+ word = re.split(separator, item)
+ for new_item in word:
+ if new_item.lstrip().rstrip() != '':
+ list.append(new_item.lstrip().rstrip())
+ return list
+
+def split_text(separator, string1, n=0):
+ """
+ return a list of string without white space of separator
+
+ :param separator: the string to remove
+
+ """
+ list = []
+ if re.search(separator, string1) is not None:
+ if n > 0:
+ word = re.split(separator,string1,int(n))
+ else:
+ word = re.split(separator,string1)
+ for item in word:
+ if item.lstrip().rstrip() != '':
+ list.append(item.lstrip().rstrip())
+ return list
+
+def look_for_tag(string1, begin, end=None):
+ """
+ this method remove the begin and end tags given by the user
+ from the string .
+
+ :param begin: the initial tag
+ :param end: the final tag
+ :param string: the string to check
+
+ :return: begin_flag==True if begin was found,
+ end_flag==if end was found else return false, false
+
+ """
+ begin_flag = False
+ end_flag = False
+ if re.search(begin,string1) is not None:
+ begin_flag = True
+ if end is not None:
+ if re.search(end,string1) is not None:
+ end_flag = True
+ return begin_flag, end_flag
+
Index: test/test_rename_guiframe/version.py
===================================================================
--- test/test_rename_guiframe/version.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/version.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,149 @@
+
+################################################################################
+#This software was developed by the University of Tennessee as part of the
+#Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
+#project funded by the US National Science Foundation.
+#
+#See the license text in license.txt
+#
+#copyright 2010, University of Tennessee
+################################################################################
+
+
+import sys
+import time
+import subprocess
+import os
+import getopt
+from threading import Thread
+
+## Maximum number of seconds to wait for an answer from the server
+MAX_WAIT_TIME = 20
+## Local storage file name
+VERSION_FILE = '.current_version'
+
+class VersionChecker(object):
+ """
+ Class of objects used to obtain the current version of an application
+ from the deployment server.
+ A sub process is started to read the URL associated with the version number.
+ The version number is written on file locally before the reading process
+ ends, then read when the version number is requested.
+
+ The reading of the URL is put in a separate process so that it doesn't
+ affect the performance of the application and can be managed and stopped at any time.
+ """
+ ## Process used to obtain the current application version from the server
+ _process = None
+ ## Start time of the process of obtaining a version number
+ _t_0 = None
+
+ def __init__(self, version_url):
+ """
+ Start the sub-process used to read the version URL
+ """
+ self._process = subprocess.Popen([sys.executable, __file__,
+ '-g', '-u%s' % version_url])
+ self._t_0 = time.time()
+
+ def is_complete(self):
+ """
+ Method used to poll the reading process. The process will be killed
+ if the wait time is longer than a predefined maximum.
+ This method should always be called before get_version() to ensure
+ accuracy of the version number that is returned.
+ """
+ if(time.time() - self._t_0 < MAX_WAIT_TIME):
+ if self._process.poll() is not None:
+ return True
+ return False
+ else:
+ return False
+ #self._process.kill()
+ return True
+
+ def get_version(self):
+ """
+ Returns the last version number that was read from the server.
+ """
+ try:
+ f = open(VERSION_FILE, 'r')
+ return f.read()
+ except:
+ return '0.0.0'
+
+class VersionThread(Thread):
+ """
+ Thread used to start the process of reading the current version of an
+ application from the deployment server.
+
+ The VersionChecker is user in a Thread to allow the main application
+ to continue dealing with UI requests from the user. The main application
+ provides a call-back method for when the version number is obtained.
+ """
+ def __init__ (self, url, call_back=None, baggage=None):
+ Thread.__init__(self)
+ self._url = url
+ self._call_back = call_back
+ self._baggage = baggage
+
+ def run(self):
+ """
+ Execute the process of reading the current application version number.
+ """
+ checker = VersionChecker(self._url)
+ while(not checker.is_complete()):
+ time.sleep(1)
+ self._call_back(checker.get_version(), self._baggage)
+
+def write_version(version, filename=VERSION_FILE):
+ """
+ Store the version number
+ This could be put into a DB if the application has one.
+ """
+ f = open(filename, 'w')
+ f.write(version)
+ f.close()
+
+def _get_version_from_server(url):
+ """
+ Method executed in the independent process used to read the
+ current version number from the server.
+
+ :param url: URL to read the version number from
+
+ """
+ import urllib
+ import re
+ try:
+ h = urllib.urlopen(url)
+ for line in h.readlines():
+ version = line.strip()
+ if len(re.findall('\d+\.\d+\.\d+$', version)) > 0:
+ write_version(version)
+ return
+ write_version('0.0.0')
+ except:
+ write_version('0.0.0')
+
+if __name__ == "__main__":
+ _get_version = False
+ _url = 'http://danse.chem.utk.edu/prview_version.php'
+
+ opts, args = getopt.getopt(sys.argv[1:], "gu:", ["get", "url="])
+ for opt, arg in opts:
+ if opt in ("-u", "--url"):
+ _url = arg
+ elif opt in ("-g", "--get"):
+ _get_version = True
+
+ if _get_version:
+ # Get the version number from the URL.
+ _get_version_from_server(_url)
+ else:
+ # Test execution of the reading process
+ def _process(version, baggage=None):
+ print "Received:", version
+ checker = VersionThread(_url, _process)
+ checker.start()
+
Index: test/test_rename_guiframe/widgets/bitmapPopbutton.py
===================================================================
--- test/test_rename_guiframe/widgets/bitmapPopbutton.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
+++ test/test_rename_guiframe/widgets/bitmapPopbutton.py (revision 6b33ffc6beb18353851d29c586bffea43af086ec)
@@ -0,0 +1,200 @@
+
+import wx
+from wx.lib.popupctl import PopButton
+
+class GuiPopButton(PopButton):
+ def __init__(self, parent, *args, **kwrds):
+ PopButton.__init__(self, parent, *args, **kwrds)
+ self.parent = parent
+ self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
+
+ def OnLeftDown(self, event):
+ if not self.IsEnabled():
+ return
+ self.didDown = True
+ self.up = False
+ self.CaptureMouse()
+ self.parent.SetFocus()
+ self.Refresh()
+
+
+
+class BitmapPopUpButton(wx.PyControl):
+ def __init__(self, parent, gui_bitmap=None, gui_size=(-1, -1),*args, **kwrds):
+ if kwrds.has_key('value'):
+ del kwrds['value']
+ style = kwrds.get('style', 0)
+ if (style & wx.BORDER_MASK) == 0:
+ style |= wx.BORDER_NONE
+ kwrds['style'] = wx.BORDER_NONE
+ wx.PyControl.__init__(self, parent, *args, **kwrds)
+ if gui_bitmap is None:
+ gui_bitmap = wx.NullBitmap
+ self._button = wx.BitmapButton(parent=self, id=-1,
+ bitmap=gui_bitmap, size=gui_size)
+ self.bCtrl = GuiPopButton(self, wx.ID_ANY, style=wx.BORDER_NONE)
+ print "hello"
+ sizer = wx.GridBagSizer()
+ self.SetSizer(sizer)
+ sizer.Add(self._button, pos=(0, 0))
+ sizer.Add(self.bCtrl, pos=(0, 1))
+
+ self.pop = None
+ self.content = None
+
+ self.Bind(wx.EVT_SIZE, self.OnSize)
+ self.bCtrl.Bind(wx.EVT_BUTTON, self.OnButton, self.bCtrl)
+ self.Bind(wx.EVT_SET_FOCUS, self.OnFocus)
+
+ self.SetInitialSize(kwrds.get('size', wx.DefaultSize))
+ self.Layout()
+ self.SendSizeEvent()
+
+ def Create(self, parent, id, bitmap, pos, size, style, validator, name):
+ """
+ Acutally create the GUI BitmapButton for 2-phase creation.
+ """
+ raise NotImplemented
+
+ def GetBitmapDisabled(self):
+ """
+ Returns the bitmap for the disabled state
+ """
+ return self._button.GetBitmapDisabled()
+
+ def GetBitmapFocus(self):
+ """
+ Returns the bitmap for the focused state.
+ """
+ return self._button.GetBitmapFocus()
+
+ def GetBitmapHover(self):
+ """
+ Returns the bitmap used when
+ the mouse is over the button, may be invalid.
+ """
+ return self._button.GetBitmapHover()
+
+ def GetBitmapLabel(self):
+ """
+ Returns the label bitmap (the one passed to the constructor).
+ """
+ return self._button.GetBitmapLabel()
+
+ def GetBitmapSelected(self) :
+ """
+ Returns the bitmap for the selected state.
+ """
+ return self._button.GetBitmapSelected()
+
+ def GetMarginX(self):
+ """
+ """
+ return self._button.GetMarginX()
+
+ def GetMarginY(self):
+ """
+ """
+ return self._button.GetMarginY()
+
+ def SetBitmapDisabled(self, bitmap):
+ """
+ Sets the bitmap for the disabled button appearance.
+ """
+ def SetBitmapFocus(self, bitmap):
+ """
+ Sets the bitmap for the button appearance
+ when it has the keyboard focus.
+ """
+ self._button.SetBitmapFocus(bitmap)
+
+ def SetBitmapHover(self, hover):
+ """
+ Sets the bitmap to be shown when the mouse is over the button.
+ """
+ self._button.SetBitmapHover(hover)
+
+ def SetBitmapLabel(self, bitmap):
+ """Sets the bitmap label for the button.
+ """
+ self._button.SetBitmapLabel(bitmap)
+
+ def SetBitmapSelected(self, bitmap):
+ """
+ """
+ self._button.SetBitmapSelected(bitmap)
+
+ def SetMargins(self, x, y):
+ """
+ """
+ self._button.SetMargins(x, y)
+
+ def OnFocus(self,evt):
+ # embedded control should get focus on TAB keypress
+ self._button.SetFocus()
+ evt.Skip()
+
+ def OnSize(self, evt):
+ # layout the child widgets
+ w,h = self.GetClientSize()
+ self._button.SetDimensions(0, 0,
+ w - self.marginWidth - self.buttonWidth, h)
+ self.bCtrl.SetDimensions(w - self.buttonWidth, 0, self.buttonWidth, h)
+
+ def DoGetBestSize(self):
+ # calculate the best size of the combined control based on the
+ # needs of the child widgets.
+ tbs = self._button.GetBestSize()
+ return wx.Size(tbs.width + self.marginWidth + self.buttonWidth,
+ tbs.height)
+ def OnButton(self, evt):
+ if not self.pop:
+ if self.content:
+ self.pop = PopupDialog(self, self.content)
+ del self.content
+ else:
+ print 'No Content to pop'
+ if self.pop:
+ self.pop.Display()
+
+ def Enable(self, flag):
+ wx.PyControl.Enable(self,flag)
+ self._button.Enable(flag)
+ self.bCtrl.Enable(flag)
+
+ def SetPopupContent(self, content):
+ if not self.pop:
+ self.content = content
+ self.content.Show(False)
+ else:
+ self.pop.SetContent(content)
+
+ def FormatContent(self):
+ pass
+
+ def PopDown(self):
+ if self.pop:
+ self.pop.EndModal(1)
+
+ def SetBitmapDisabled(self, bitmap):
+ self._button.SetBitmapDisabled(bitmap)
+
+ def SetMargins(self, x, y):
+ self._button.SetMargins(x, y)
+
+ def SetFont(self, font):
+ self._button.SetFont(font)
+
+ def GetFont(self):
+ return self._button.GetFont()
+
+ def _get_marginWidth(self):
+ if 'wxMac' in wx.PlatformInfo:
+ return 6
+ else:
+ return 3
+ marginWidth = property(_get_marginWidth)
+
+ def _get_buttonWidth(self):
+ return 20
+ buttonWidth = property(_get_buttonWidth)