Commit 10c38dc7 authored by eric pellegrini's avatar eric pellegrini
Browse files

All the analysis are now reintroduced in MDANSE

Splitted the Plotter plugin in several modules
parent 36f7b144
#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: Gael Goret, Eric C. Pellegrini
'''
from MDANSE.App.GUI.Plugins.IPlugin import IPlugin
class ComponentPlugin(IPlugin):
type = None
@property
def datakey(self):
return self.parent.datakey
@property
def dataproxy(self):
return self.parent.dataproxy
#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: Gael Goret, Eric C. Pellegrini
'''
import wx
import wx.aui as wxaui
from MDANSE import REGISTRY
from MDANSE.Externals.pubsub import pub
from MDANSE.App.GUI import DATA_CONTROLLER
from MDANSE.App.GUI.Plugins.IPlugin import IPlugin, plugin_parent
class DataPlugin(IPlugin):
type = 'data'
ancestor = None
def __init__(self, parent, datakey):
IPlugin.__init__(self, parent, wx.ID_ANY)
self._datakey = datakey
self._dataProxy = DATA_CONTROLLER[self._datakey]
self._mgr.Bind(wx.EVT_CHILD_FOCUS, self.on_changing_pane)
self._currentWindow = self
def build_panel(self):
pass
def plug(self, standalone=False):
pass
@property
def currentWindow(self):
return self._currentWindow
@property
def datakey(self):
return self._datakey
@datakey.setter
def datakey(self, key):
self._datakey = key
@property
def dataproxy(self):
return self._dataProxy
def drop(self, pluginName):
# If no plugin match the name of the dropped plugin, do nothing.
plugin = REGISTRY["plugin"].get(pluginName,None)
if plugin is None:
return
if not issubclass(self.__class__,REGISTRY['plugin'][plugin.ancestor]):
return
plugin = plugin(self)
self._mgr.AddPane(plugin, wxaui.AuiPaneInfo().Caption(getattr(plugin, "label", pluginName)))
self._mgr.Update()
plugin.plug()
plugin.SetFocus()
def has_parent(self, window):
return False
def on_changing_pane(self, event):
window = plugin_parent(event.GetWindow())
if window is None:
return
self._currentWindow = window
pub.sendMessage(('set_plugins_tree'), message= window)
#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: Gael Goret, Eric C. Pellegrini
'''
import abc
import cPickle
import wx
import wx.aui as aui
from MDANSE import REGISTRY
def plugin_parent(window):
if window == window.TopLevelParent:
return None
if isinstance(window,IPlugin):
return window
else:
return plugin_parent(window.Parent)
class PluginDropTarget(wx.DropTarget):
def __init__(self, targetPanel):
wx.DropTarget.__init__(self)
self._targetPanel = targetPanel
self._data = wx.CustomDataObject("Plugin")
self.SetDataObject(self._data)
@property
def target_panel(self):
return self._targetPanel
def OnDrop(self, x, y):
return True
def OnDragOver(self, x, y, d):
return wx.DragCopy
def OnData(self, x, y, d):
if self.GetData():
pluginName = cPickle.loads(self._data.GetData())
self._targetPanel.drop(pluginName)
return d
class IPlugin(wx.Panel):
__metaclass__ = REGISTRY
type = "plugin"
ancestor = None
def __init__(self, parent, *args, **kwargs):
wx.Panel.__init__(self, parent, *args, **kwargs)
self._parent = parent
self.SetDropTarget(PluginDropTarget(self))
self.build_dialog()
self._mgr.Bind(aui.EVT_AUI_PANE_CLOSE, self.on_close_pane)
@abc.abstractmethod
def build_panel(self):
pass
@abc.abstractmethod
def plug(self, standalone=False):
pass
@property
def mgr(self):
return self._mgr
@property
def parent(self):
return self._parent
def close_children(self):
childrenPlugins = [p.window for p in self._mgr.GetAllPanes()]
for plugin in childrenPlugins:
try:
plugin.close_children()
except AttributeError:
continue
self.close()
def close(self):
pass
def on_close_pane(self, event):
plugin = event.GetPane().window
try:
plugin.close_children()
except AttributeError:
plugin.Close()
def build_dialog(self):
self.Freeze()
self._mgr = aui.AuiManager(self)
self.build_panel()
self._mgr.Update()
self.Thaw()
def drop(self, pluginName):
# If no plugin match the name of the dropped plugin, do nothing.
plugin = REGISTRY["plugin"].get(pluginName,None)
if plugin is None:
return
if not issubclass(self.__class__,REGISTRY['plugin'][plugin.ancestor]):
self.parent.drop(pluginName)
return
plugin = plugin(self)
self._mgr.AddPane(plugin, aui.AuiPaneInfo().Caption(getattr(plugin, "label", pluginName)))
self._mgr.Update()
plugin.plug()
plugin.SetFocus()
\ 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: Gael Goret, Eric C. Pellegrini
'''
import collections
import wx
import wx.aui as wxaui
from Scientific.IO.NetCDF import NetCDFFile
from MDANSE.Core.Error import Error
from MDANSE.App.GUI.Framework.Plugins import ComponentPlugin
from MDANSE.App.GUI.Icons import ICONS
class PlotterError(Error):
pass
class PlotterPanel(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent, wx.ID_ANY)
self.parent = parent
self._mgr = wxaui.AuiManager(self)
self.build_panel()
self.build_layout()
@property
def dataproxy(self):
return self.parent._data
@property
def active_plot(self):
try :
page = self.plot_notebook.GetPage(self.plot_notebook.GetSelection())
return page
except:
return None
def build_panel(self):
self.plot_notebook = wxaui.AuiNotebook(self)
def build_layout(self):
self._mgr.AddPane(self.plot_notebook, wxaui.AuiPaneInfo().Center().Dock().CloseButton(False).Caption("Multiple Plot Window"))
self._mgr.Update()
class MultiViewPanel(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent, wx.ID_ANY)
self.parent = parent
self.type = 'image'
self.unique_slicer = None
self.related_slicer_checkbox=None
self._mgr = wxaui.AuiManager(self)
self.Layout()
@property
def dataproxy(self):
return self.parent.dataproxy
def AddPane(self, *args, **kwds):
self._mgr.AddPane(*args, **kwds)
def Update(self):
self._mgr.Update()
class DataPanel(wx.Panel):
def __init__(self, parent, *args,**kwds):
wx.Panel.__init__(self, parent, *args, **kwds)
self.parent = parent
self._mgr = wxaui.AuiManager(self)
self.selectedVar = None
self.activePlot = None
self.selectedPlot = None
self.unique_slicer = None
self.related_slicer_checkbox=None
self.build_panel()
def build_panel(self):
self.setup = wx.Panel(self)
sizer0 = wx.BoxSizer(wx.VERTICAL)
if self.standalone:
self.datasetlist = wx.ListCtrl(self.setup, wx.ID_ANY,style = wx.LC_REPORT|wx.LC_SINGLE_SEL)
self.datasetlist.InsertColumn(0, 'key', width=100)
self.datasetlist.InsertColumn(1, 'filename', width=100)
self.datasetlist.InsertColumn(2, 'path', width=500)
sizer0.Add(self.datasetlist, 1, wx.ALL|wx.EXPAND, 2)
sizer3 = wx.BoxSizer(wx.HORIZONTAL)
self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.on_select_dataset, self.datasetlist)
self.Bind(wx.EVT_LIST_KEY_DOWN, self.delete_dataset, self.datasetlist)
self.datalist = wx.ListCtrl(self.setup, wx.ID_ANY,style = wx.LC_REPORT|wx.LC_SINGLE_SEL)
self.datalist.InsertColumn(0, 'Variable', width=100)
self.datalist.InsertColumn(1, 'Unit', width=65)
self.datalist.InsertColumn(2, 'Axis', width=50)
self.datalist.InsertColumn(3, 'Dimension')
sizer1 = wx.BoxSizer(wx.HORIZONTAL)
self.plot_type_label = wx.StaticText(self.setup, label="Select Plotter")
self.plotter_list = {'Line':1, 'Image':2, 'Elevation':2,'Iso-Surface':3,'Scalar-Field':3}
self.plot_type = wx.ComboBox(self.setup, style=wx.CB_READONLY)
sizer1.Add(self.plot_type_label, 0, wx.ALIGN_CENTER_VERTICAL)
sizer1.Add(self.plot_type, 1, wx.ALIGN_CENTER_VERTICAL)
sizer2 = wx.BoxSizer(wx.HORIZONTAL)
self.plot_button = wx.Button(self.setup, wx.ID_ANY, label="Plot in new window")
self.replot_button = wx.Button(self.setup, wx.ID_ANY, label="Plot in current figure")
sizer2.Add(self.plot_button, 1, wx.ALIGN_CENTER_VERTICAL|wx.EXPAND)
sizer2.Add(self.replot_button, 1, wx.ALIGN_CENTER_VERTICAL|wx.EXPAND)
sizer0.Add(self.datalist, 2, wx.ALL|wx.EXPAND, 2)
sizer0.Add(sizer1, 0, wx.ALL|wx.EXPAND, 2)
sizer0.Add(sizer2, 0, wx.ALL|wx.EXPAND, 2)
self.setup.SetSizer(sizer0)
sizer0.Fit(self.setup)
self.setup.Layout()
qviewPanel = wx.Panel(self)
sb_sizer2 = wx.BoxSizer(wx.VERTICAL)
self.QV_Figure = Figure(figsize=(1,1))
self.QV_Canvas = FigureCanvasWxAgg(qviewPanel, wx.ID_ANY, self.QV_Figure)
self.QV_Plot = self.QV_Figure.add_axes([0.01,0.01,0.98,0.98])
sb_sizer2.Add(self.QV_Canvas, 1, wx.ALL|wx.EXPAND, 2)
qviewPanel.SetSizer(sb_sizer2)
sb_sizer2.Fit(qviewPanel)
qviewPanel.Layout()
self._mgr.AddPane(qviewPanel,wxaui.AuiPaneInfo().Dock().Bottom().Floatable(False).CloseButton(False).Caption("Quick View").MinSize((300,300)))
self._mgr.AddPane(self.setup,wxaui.AuiPaneInfo().Dock().Center().Floatable(False).CloseButton(False).Caption("Data"))
self._mgr.Update()
self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.on_select_variables, self.datalist)
self.Bind(wx.EVT_BUTTON, self.on_plot, self.plot_button)
self.Bind(wx.EVT_BUTTON, self.on_replot, self.replot_button)
@property
def dataDict(self):
if self.standalone:
return self.parent._dataDict
else:
return None
@property
def standalone(self):
return self.parent.standalone
@property
def dataproxy(self):
return self.parent._data
@property
def plotterPanel(self):
return self.parent._plotterPanel
@property
def plotterNotebook(self):
return self.parent._plotterPanel.plot_notebook
def delete_dataset(self, event):
keycode = event.GetKeyCode()
if keycode == wx.WXK_DELETE:
dataset = self.datasetlist.GetItemText(self.datasetlist.GetFocusedItem())
self.dataDict.pop(dataset)
self.datasetlist.DeleteItem(self.datasetlist.GetFocusedItem())
self.datalist.DeleteAllItems()
self.datasetlist.Select(0,1)
def on_select_dataset(self, event):
if event is None:
return
currentItem = event.m_itemIndex
var = self.datasetlist.GetItemText(currentItem)
self.parent._data = self.dataDict[var]['data']
self.show_data()
def show_dataset(self):
self.datasetlist.DeleteAllItems()
for i, k in enumerate(self.dataDict.keys()):
self.datasetlist.InsertStringItem(i, k)
self.datasetlist.SetStringItem(i, 1,self.dataDict[k]['basename'])
self.datasetlist.SetStringItem(i, 2,self.dataDict[k]['path'])
self.datasetlist.Select(0, True)
def show_data(self):
self.datalist.DeleteAllItems()
for i, var in enumerate(sorted(self.dataproxy.keys())):
self.datalist.InsertStringItem(i, var)
self.datalist.SetStringItem(i, 1,self.dataproxy[var]['units'])
axis = ','.join(self.dataproxy[var]['axis'])
if not axis :
axis = 'None'
self.datalist.SetStringItem(i, 2,axis)
self.datalist.SetStringItem(i, 3,str(self.dataproxy[var]['data'].ndim))
self.datalist.Select(0, True)
def on_select_variables(self, event = None):
if event is None:
return
currentItem = event.m_itemIndex
var = self.datalist.GetItemText(currentItem)
data = self.dataproxy[var]['data']
ndim = data.ndim
self.plot_type.Clear()
types = []
for _type, req_dim in self.plotter_list.items():
if ndim == req_dim:
types += [_type]
self<