Commit 36f7b144 authored by eric pellegrini's avatar eric pellegrini
Browse files

Docstringed MDANSE.Core.Preferences module

Reintroduced and refactored several analysis
parent c33398f0
...@@ -5,7 +5,7 @@ import wx.aui as wxaui ...@@ -5,7 +5,7 @@ import wx.aui as wxaui
import wx.py as wxpy import wx.py as wxpy
from MDANSE.App.GUI.JobControllerPanel import JobControllerPanel from MDANSE.App.GUI.JobControllerPanel import JobControllerPanel
from MDANSE.App.GUI.Icons import ICONS, scaled_bitmap from MDANSE.App.GUI.Icons import ICONS
class ControllerPanel(wx.Panel): class ControllerPanel(wx.Panel):
...@@ -33,9 +33,9 @@ class ControllerPanel(wx.Panel): ...@@ -33,9 +33,9 @@ class ControllerPanel(wx.Panel):
#wxpython 2.9 compatibility #wxpython 2.9 compatibility
if wx.VERSION[:2] > (2,8): if wx.VERSION[:2] > (2,8):
il = wx.ImageList(16, 16) il = wx.ImageList(16, 16)
il.Add(scaled_bitmap(ICONS["log"], 16,16)) il.Add(ICONS["log",16,16])
il.Add(scaled_bitmap(ICONS["shell"], 16,16)) il.Add(ICONS["shell",16,16])
il.Add(scaled_bitmap(ICONS["hourglass"], 16,16)) il.Add(ICONS["hourglass",16,16])
self._notebook.AssignImageList(il) self._notebook.AssignImageList(il)
self._notebook.AddPage(self._pages["logger"], 'Logger') self._notebook.AddPage(self._pages["logger"], 'Logger')
...@@ -47,9 +47,9 @@ class ControllerPanel(wx.Panel): ...@@ -47,9 +47,9 @@ class ControllerPanel(wx.Panel):
self._notebook.SetPageImage(2, 2) self._notebook.SetPageImage(2, 2)
else: else:
self._notebook.AddPage(self._pages["logger"], 'Logger', bitmap=scaled_bitmap(ICONS["log"], 16,16)) self._notebook.AddPage(self._pages["logger"], 'Logger', bitmap=ICONS["log",16,16])
self._notebook.AddPage(self._pages["console"], 'Console', bitmap=scaled_bitmap(ICONS["shell"], 16,16)) self._notebook.AddPage(self._pages["console"], 'Console', bitmap=ICONS["shell",16,16])
self._notebook.AddPage(self._pages["jobs"], 'Jobs', bitmap=scaled_bitmap(ICONS["hourglass"], 16,16)) self._notebook.AddPage(self._pages["jobs"], 'Jobs', bitmap=ICONS["hourglass",16,16])
def build_layout(self): def build_layout(self):
......
...@@ -48,7 +48,7 @@ from MDANSE.Framework.Jobs.JobStatus import JobState ...@@ -48,7 +48,7 @@ from MDANSE.Framework.Jobs.JobStatus import JobState
from MDANSE.Externals.pubsub import pub from MDANSE.Externals.pubsub import pub
from MDANSE.Logging.Logger import LOGGER from MDANSE.Logging.Logger import LOGGER
from MDANSE.App.GUI.Icons import ICONS, scaled_bitmap from MDANSE.App.GUI.Icons import ICONS
from MDANSE.App.GUI.Events.JobControllerEvent import EVT_JOB_CONTROLLER, JobControllerEvent from MDANSE.App.GUI.Events.JobControllerEvent import EVT_JOB_CONTROLLER, JobControllerEvent
class JobController(threading.Thread): class JobController(threading.Thread):
...@@ -196,7 +196,7 @@ class JobControllerPanel(wx.ScrolledWindow): ...@@ -196,7 +196,7 @@ class JobControllerPanel(wx.ScrolledWindow):
state = wx.TextCtrl(self, wx.ID_ANY, style=wx.TE_READONLY|wx.ALIGN_CENTER_HORIZONTAL) state = wx.TextCtrl(self, wx.ID_ANY, style=wx.TE_READONLY|wx.ALIGN_CENTER_HORIZONTAL)
progress = wx.Gauge(self, wx.ID_ANY,range=100) progress = wx.Gauge(self, wx.ID_ANY,range=100)
eta = wx.TextCtrl(self, wx.ID_ANY, style=wx.TE_READONLY|wx.ALIGN_CENTER_HORIZONTAL) eta = wx.TextCtrl(self, wx.ID_ANY, style=wx.TE_READONLY|wx.ALIGN_CENTER_HORIZONTAL)
kill = wx.BitmapButton(self, wx.ID_ANY, scaled_bitmap(ICONS["stop"], 24, 24)) kill = wx.BitmapButton(self, wx.ID_ANY, ICONS["stop",24,24])
self._gbSizer.Add(name ,pos=(r,0),flag=wx.EXPAND|wx.ALIGN_CENTER_HORIZONTAL) self._gbSizer.Add(name ,pos=(r,0),flag=wx.EXPAND|wx.ALIGN_CENTER_HORIZONTAL)
self._gbSizer.Add(pid ,pos=(r,1),flag=wx.EXPAND|wx.ALIGN_CENTER_HORIZONTAL) self._gbSizer.Add(pid ,pos=(r,1),flag=wx.EXPAND|wx.ALIGN_CENTER_HORIZONTAL)
......
...@@ -9,7 +9,7 @@ from MDANSE import LOGGER, REGISTRY ...@@ -9,7 +9,7 @@ from MDANSE import LOGGER, REGISTRY
from MDANSE.App.GUI import DATA_CONTROLLER from MDANSE.App.GUI import DATA_CONTROLLER
from MDANSE.App.GUI.ControllerPanel import ControllerPanel from MDANSE.App.GUI.ControllerPanel import ControllerPanel
from MDANSE.App.GUI.DataTreePanel import DataTreePanel from MDANSE.App.GUI.DataTreePanel import DataTreePanel
from MDANSE.App.GUI.Icons import ICONS, scaled_bitmap from MDANSE.App.GUI.Icons import ICONS
from MDANSE.App.GUI.PluginsTreePanel import PluginsTreePanel from MDANSE.App.GUI.PluginsTreePanel import PluginsTreePanel
from MDANSE.App.GUI.WorkingPanel import WorkingPanel from MDANSE.App.GUI.WorkingPanel import WorkingPanel
...@@ -34,7 +34,7 @@ class MainFrame(wx.Frame): ...@@ -34,7 +34,7 @@ class MainFrame(wx.Frame):
self.build_toolbar() self.build_toolbar()
icon = wx.EmptyIcon() icon = wx.EmptyIcon()
icon.CopyFromBitmap(scaled_bitmap(ICONS["nmoldyn"], 32, 32)) icon.CopyFromBitmap(ICONS["nmoldyn",32,32])
self.SetIcon(icon) self.SetIcon(icon)
# The main aui manager. # The main aui manager.
...@@ -98,18 +98,18 @@ class MainFrame(wx.Frame): ...@@ -98,18 +98,18 @@ class MainFrame(wx.Frame):
self._toolbar = self.CreateToolBar() self._toolbar = self.CreateToolBar()
loadDataButton = self._toolbar.AddSimpleTool(wx.ID_ANY, scaled_bitmap(ICONS["load"], 32, 32), 'Load a trajectory') loadDataButton = self._toolbar.AddSimpleTool(wx.ID_ANY, ICONS["load",32,32], 'Load a trajectory')
emptyDataButton = self._toolbar.AddSimpleTool(wx.ID_ANY, scaled_bitmap(ICONS["empty_data"], 32, 32), 'Open an empty data (converters ...)') emptyDataButton = self._toolbar.AddSimpleTool(wx.ID_ANY, ICONS["empty_data",32,32], 'Open an empty data (converters ...)')
databaseButton = self._toolbar.AddSimpleTool(wx.ID_ANY, scaled_bitmap(ICONS["periodic_table"], 32, 32), 'Edit the nMolDyn elements database') databaseButton = self._toolbar.AddSimpleTool(wx.ID_ANY, ICONS["periodic_table",32,32], 'Edit the MDANSE elements database')
plotButton = self._toolbar.AddSimpleTool(wx.ID_ANY,scaled_bitmap(ICONS["plot"], 32, 32), 'Open nMolDyn plotter') plotButton = self._toolbar.AddSimpleTool(wx.ID_ANY,ICONS["plot",32,32], 'Open MDANSE plotter')
userButton = self._toolbar.AddSimpleTool(wx.ID_ANY,scaled_bitmap(ICONS["user"], 32, 32), 'Edit the user definitions') userButton = self._toolbar.AddSimpleTool(wx.ID_ANY,ICONS["user",32,32], 'Edit the user definitions')
preferencesButton = self._toolbar.AddSimpleTool(wx.ID_ANY, scaled_bitmap(ICONS["preferences"], 32, 32), 'Edit the preferences') preferencesButton = self._toolbar.AddSimpleTool(wx.ID_ANY, ICONS["preferences",32,32], 'Edit the preferences')
logfileButton = self._toolbar.AddSimpleTool(wx.ID_ANY, scaled_bitmap(ICONS["logfile"], 32, 32), 'Display nMOLDYN log file') logfileButton = self._toolbar.AddSimpleTool(wx.ID_ANY, ICONS["logfile",32,32], 'Display nMOLDYN log file')
helpButton = self._toolbar.AddSimpleTool(wx.ID_ANY, scaled_bitmap(ICONS["help"], 32, 32), 'Help') helpButton = self._toolbar.AddSimpleTool(wx.ID_ANY, ICONS["help",32,32], 'Help')
websiteButton = self._toolbar.AddSimpleTool(wx.ID_ANY, scaled_bitmap(ICONS["web"], 32, 32), 'Open nMoldyn website') websiteButton = self._toolbar.AddSimpleTool(wx.ID_ANY, ICONS["web",32,32], 'Open MDANSE website')
aboutButton = self._toolbar.AddSimpleTool(wx.ID_ANY, scaled_bitmap(ICONS["about"], 32, 32), 'About nMolDyn') aboutButton = self._toolbar.AddSimpleTool(wx.ID_ANY, ICONS["about",32,32], 'About MDANSE')
bugButton = self._toolbar.AddSimpleTool(wx.ID_ANY, scaled_bitmap(ICONS["bug"], 32, 32), 'Bug report') bugButton = self._toolbar.AddSimpleTool(wx.ID_ANY, ICONS["bug",32,32], 'Bug report')
quitButton = self._toolbar.AddSimpleTool(wx.ID_ANY, scaled_bitmap(ICONS["quit"], 32, 32), 'Quit nMoldyn') quitButton = self._toolbar.AddSimpleTool(wx.ID_ANY, ICONS["quit",32,32], 'Quit MDANSE')
self._toolbar.Realize() self._toolbar.Realize()
......
...@@ -7,27 +7,9 @@ if platform.dist()[0].lower() == "ubuntu": ...@@ -7,27 +7,9 @@ if platform.dist()[0].lower() == "ubuntu":
from MDANSE.App.GUI.DataController import DATA_CONTROLLER from MDANSE.App.GUI.DataController import DATA_CONTROLLER
import glob from MDANSE import REGISTRY
import sys
directories = sorted([x[0] for x in os.walk(os.path.dirname(__file__))][1:]) directories = sorted([x[0] for x in os.walk(os.path.dirname(__file__))][1:])
for d in directories: for d in directories:
REGISTRY.update_registry(d)
for module in glob.glob(os.path.join(d,'*.py')):
moduleDir, moduleFile = os.path.split(module)
if moduleFile == '__init__.py':
continue
moduleName, moduleExt = os.path.splitext(moduleFile)
if moduleDir not in sys.path:
sys.path.append(moduleDir)
# Any error that may occur here has to be caught. In such case the module is skipped.
try:
__import__(moduleName, locals(), globals())
except:
continue
\ No newline at end of file
...@@ -31,8 +31,10 @@ Created on Mar 30, 2015 ...@@ -31,8 +31,10 @@ Created on Mar 30, 2015
''' '''
import abc import abc
import glob
import inspect import inspect
import os import os
import sys
class _Meta(type): class _Meta(type):
''' '''
...@@ -99,12 +101,45 @@ class ClassRegistry(abc.ABCMeta): ...@@ -99,12 +101,45 @@ class ClassRegistry(abc.ABCMeta):
ClassRegistry._registry[interface.type][typ] = self ClassRegistry._registry[interface.type][typ] = self
break break
@classmethod
def update_registry(cls,packageDir):
'''
Update the classes registry by importing all the modules contained in a given package.
Only the classes that are metaclassed by ClassRegistry will be registered.
:param cls: the ClassRegistry instance
:type: ClassRegistry
:param packageDir: the package for which all modules should be imported
:type packageDir: str
'''
for module in glob.glob(os.path.join(packageDir,'*.py')):
moduleDir, moduleFile = os.path.split(module)
if moduleFile == '__init__.py':
continue
moduleName, moduleExt = os.path.splitext(moduleFile)
print moduleName
if moduleDir not in sys.path:
sys.path.append(moduleDir)
# Any error that may occur here has to be caught. In such case the module is skipped.
try:
__import__(moduleName, locals(), globals())
except:
continue
@classmethod @classmethod
def info(cls, interface): def info(cls, interface):
''' '''
Returns informations about the subclasses of a given base class stored in the registry. Returns informations about the subclasses of a given base class stored in the registry.
:param cls: the ClassRegsitry instance :param cls: the ClassRegistry instance
:type cls: ClassRegistry :type cls: ClassRegistry
:param interface: the name of base class of whom information about its subclasses is requested :param interface: the name of base class of whom information about its subclasses is requested
:type interface: str :type interface: str
......
#MDANSE : Molecular Dynamics Analysis for Neutron Scattering Experiments
#------------------------------------------------------------------------------------------
#Copyright (C)
#2015- Eric C. Pellegrini Institut Laue-Langevin
#BP 156
#6, rue Jules Horowitz
#38042 Grenoble Cedex 9
#France
#pellegrini[at]ill.fr
#goret[at]ill.fr
#aoun[at]ill.fr
#
#This library is free software; you can redistribute it and/or
#modify it under the terms of the GNU Lesser General Public
#License as published by the Free Software Foundation; either
#version 2.1 of the License, or (at your option) any later version.
#
#This library is distributed in the hope that it will be useful,
#but WITHOUT ANY WARRANTY; without even the implied warranty of
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
#Lesser General Public License for more details.
#
#You should have received a copy of the GNU Lesser General Public
#License along with this library; if not, write to the Free Software
#Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
'''
Created on Mar 30, 2015
@author: pellegrini
'''
import abc
import collections
import ConfigParser
import os
from MDANSE.Core.Platform import PLATFORM, PlatformError
from MDANSE.Core.Error import Error
from MDANSE.Core.Singleton import Singleton
class PreferencesError(Error):
'''
This class handles the errors that occurs in Preferences.
'''
pass
class PreferencesItem(object):
'''
This is the base class for defining a preferences item.
A preferences item implements is a light object used to check preferences before setting them
but also classify preferences according to their section for a further use in MDANSE GUI.
'''
__metaclass__ = abc.ABCMeta
def __init__(self, name, section, default, *args, **kwargs):
'''
Constructor a new prferences item.
:param name: the name of the preference item
:type name: str
:param section: the section of the preferences item
:type section: str
:param default: the default value for the preferences item
:type default: str
'''
self._name = name
self._section = section
self._default = default
self._value = self._default
@property
def default(self):
'''
Returns the default value of the preferences item.
:return: the default value of the preferences item
:rtype: str
'''
return self._default
def get_default(self):
'''
Returns the default value of the preferences item.
:return: the default value of the preferences item
:rtype: str
'''
return self._default
@property
def name(self):
'''
Returns the name of the preferences item.
:return: the name of the preferences item
:rtype: str
'''
return self._name
def get_name(self):
'''
Returns the name of the preferences item.
:return: the name of the preferences item
:rtype: str
'''
return self._name
@property
def section(self):
'''
Returns the section of the preferences item.
:return: the section of the preferences item
:rtype: str
'''
return self._section
def get_section(self):
'''
Returns the section of the preferences item.
:return: the section of the preferences item
:rtype: str
'''
return self._section
def reset(self):
'''
Reset the preferences item to its default value
'''
self._value = self._default
@property
def value(self):
'''
Returns the value of the preferences item.
:return: the value of the preferences item
:rtype: str
'''
return self._value
def get_value(self):
'''
Returns the value of the preferences item.
:return: the value of the preferences item
:rtype: str
'''
return self._value
@abc.abstractmethod
def set_value(self,value):
'''
Set the value of the preferences item.
:param value: the value of the preferences item
:type value: str
'''
pass
class InputDirectory(PreferencesItem):
'''
This class implements a preferences item that handles an input directory.
When set to a given input directory, if this one does not exists, it will be be created.
'''
type = "input_directory"
def set_value(self, value):
'''
Set the value of the input directory preferences item.
:param value: the input directory
:type value: str
'''
value = PLATFORM.get_path(value)
try:
PLATFORM.create_directory(value)
except PlatformError:
raise PreferencesError('Error when setting input directory %r' % value)
self._value = value
class Preferences(collections.OrderedDict):
'''
This class implements the MDANSE preferences.
Preferences are defined using the ConfigParser python module that allows to read and write
preferences stored in a formatted INI file (RFC822).
'''
__metaclass__ = Singleton
def __init__(self):
'''
Constructs the preferences
'''
self["working_directory"] = InputDirectory("working_directory", "paths", PLATFORM.home_directory())
self["macros_directory"] = InputDirectory("macros_directory", "paths", os.path.join(PLATFORM.home_directory(), "mdanse_macros"))
self._parser = ConfigParser.ConfigParser()
for s in self._items.values():
try:
self._parser.add_section(s.section)
except ConfigParser.DuplicateSectionError:
pass
# Overwrite the default preferences with the user defined loaded ones.
try:
self.load()
except PreferencesError:
pass
@property
def parser(self):
'''
Returns the configuration parser object used to serialize the preferences.
:return: the configuration parser bound to the preferences
:rtype: ConfigParser.ConfigParser
'''
return self._parser
def __getitem__(self, item):
'''
Get the value of a selected preferences item.
:param item: the preferences item
:type item: str
:return: the values of the preferences item.
:rtype: str
'''
try:
value = self[item].value
except KeyError:
raise PreferencesError("The preferences item %r is not valid" % item)
else:
return value
def __setitem__(self, item, value):
'''
Set the value of a preferences item.
:param item: the preferences item
:type item: str
:param value: the value to set for the preferences item.
:type value: any
'''
if not self._items.has_key(item):
return
try:
self._items[item].value = value
except KeyError:
raise PreferencesError("The preferences item %r is not valid" % item)
def load(self):
'''
Load the preferences from a preferences file.
'''
path = PLATFORM.preferences_file()
if not isinstance(path,basestring):
raise PreferencesError("Invalid type for preferences filename: %s" % path)
if not os.path.exists(path):
raise PreferencesError("The preferences files %s does not exists. nMolDyn will use the default preferences." % path)
try:
# Read the preferences and overwrites the nmoldyn default preferences.
self._parser.read(path)
except ConfigParser.ParsingError as e:
raise PreferencesError(e)
for s in self._parser.sections():
for k, v in self._parser.items(s):
self[k] = v
def save(self):
'''
Save the preferences to a file.
'''
path = PLATFORM.preferences_file()
try:
f = open(path, "w")
except (IOError,TypeError) as e:
raise PreferencesError(e)
for v in self._items.values():
self._parser.set(v.section,v.name,v.value)
# Write the preferences.
self._parser.write(f)
# Closes the preferences file.
f.close()
PREFERENCES = Preferences()
\ No newline at end of file
#MDANSE : Molecular Dynamics Analysis for Neutron Scattering Experiments
#------------------------------------------------------------------------------------------
#Copyright (C)
#2015- Eric C. Pellegrini Institut Laue-Langevin
#BP 156
#6, rue Jules Horowitz
#38042 Grenoble Cedex 9
#France
#pellegrini[at]ill.fr
#goret[at]ill.fr
#aoun[at]ill.fr
#
#This library is free software; you can redistribute it and/or
#modify it under the terms of the GNU Lesser General Public
#License as published by the Free Software Foundation; either
#version 2.1 of the License, or (at your option) any later version.
#
#This library is distributed in the hope that it will be useful,
#but WITHOUT ANY WARRANTY; without even the implied warranty of
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
#Lesser General Public License for more details.
#
#You should have received a copy of the GNU Lesser General Public
#License along with this library; if not, write to the Free Software
#Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
'''
Created on Apr 10, 2015
@author: pellegrini
'''