Provide a "nogui" target in the installation.

It is possible to install msspec without gui, which
reduces a lot the number of dependencies. It is still possible
to export the results as *.png or to view the cluster with
the ase gui.
This commit is contained in:
Sylvain Tricot 2024-10-22 12:39:54 +02:00
parent 583eb08924
commit 4aec48b4f6
3 changed files with 418 additions and 397 deletions

View File

@ -37,6 +37,11 @@ light: VENV_PATH = ./_venv
light: venv
@$(INSIDE_VENV) pip install src/
nogui: VENV_PATH = ./_venv
nogui: venv
@$(INSIDE_VENV) pip install --no-cache-dir --upgrade -r src/pip.freeze
@$(INSIDE_VENV) pip install -e src/
@+$(INSIDE_VENV) $(MAKE) -C src pybinding
_attrdict:
# Check if virtualenv python version > 3.3.0

View File

@ -17,7 +17,7 @@
# along with this msspec. If not, see <http://www.gnu.org/licenses/>.
#
# Source file : src/msspec/iodata.py
# Last modified: Mon, 11 Mar 2024 09:51:47 +0100
# Last modified: Tue, 22 Oct 2024 12:39:54 +0200
# Committed by : Sylvain Tricot <sylvain.tricot@univ-rennes.fr>
@ -79,19 +79,26 @@ import ase.io
from ase.io.extxyz import read_xyz, write_xyz
import h5py
import numpy as np
import wx.grid
from lxml import etree
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
#from matplotlib.backends.backend_wxagg import FigureCanvasWx as FigureCanvas
from matplotlib.backends.backend_agg import FigureCanvasAgg
from matplotlib.backends.backend_wxagg import NavigationToolbar2WxAgg
#from matplotlib.backends.backend_cairo import FigureCanvasCairo as FigureCanvasAgg
from matplotlib.figure import Figure
from terminaltables import AsciiTable
import msspec
from msspec.msspecgui.msspec.gui.clusterviewer import ClusterViewer
from msspec.misc import LOGGER
try:
import wx.grid
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
from matplotlib.backends.backend_wxagg import NavigationToolbar2WxAgg
from msspec.msspecgui.msspec.gui.clusterviewer import ClusterViewer
has_gui = True
except ImportError:
LOGGER.warning('No modules for GUI')
has_gui = False
def cols2matrix(x, y, z, nx=88*1+1, ny=360*1+1):
# mix the values of existing theta and new theta and return the
@ -796,11 +803,17 @@ class Data(object):
"""Pops up a grphical window to show all the defined views of the Data object.
"""
app = wx.App(False)
app.SetAppName('MsSpec Data Viewer')
frame = _DataWindow(self)
frame.Show(True)
app.MainLoop()
if has_gui:
app = wx.App(False)
app.SetAppName('MsSpec Data Viewer')
frame = _DataWindow(self)
frame.Show(True)
app.MainLoop()
else:
print('**** INFORMATION ****')
print('You can not use the Data.view() method since ther is no')
print('graphical user interface available in this version of MsSpec.')
print("Install WxPython if you need it or use Data.export(...) method instead.")
class _DataSetView(object):
@ -895,7 +908,8 @@ class _DataSetView(object):
axes.set_yticks(R_ticks)
axes.set_yticklabels(theta_ticks)
figure.colorbar(im)
cbar = figure.colorbar(im)
#im.set_clim(0, 0.0275)
elif proj == 'polar':
values[0] = np.radians(values[0])
@ -918,6 +932,7 @@ class _DataSetView(object):
axes.set_ylabel(opts['ylabel'])
axes.set_xlim(*opts['xlim'])
axes.set_ylim(*opts['ylim'])
#axes.set_axis_off()
#axes.set_pickradius(5)
if label:
axes.legend()
@ -1008,425 +1023,426 @@ class _DataSetView(object):
s += '\tconditions : %s\n' % str(self._selection_conditions)
return s
class _GridWindow(wx.Frame):
def __init__(self, dset, parent=None):
title = 'Data: ' + dset.title
wx.Frame.__init__(self, parent, title=title, size=(640, 480))
self.create_grid(dset)
if has_gui:
class _GridWindow(wx.Frame):
def __init__(self, dset, parent=None):
title = 'Data: ' + dset.title
wx.Frame.__init__(self, parent, title=title, size=(640, 480))
self.create_grid(dset)
def create_grid(self, dset):
grid = wx.grid.Grid(self, -1)
grid.CreateGrid(len(dset), len(dset.columns()))
for ic, c in enumerate(dset.columns()):
grid.SetColLabelValue(ic, c)
for iv, v in enumerate(dset[c]):
grid.SetCellValue(iv, ic, str(v))
def create_grid(self, dset):
grid = wx.grid.Grid(self, -1)
grid.CreateGrid(len(dset), len(dset.columns()))
for ic, c in enumerate(dset.columns()):
grid.SetColLabelValue(ic, c)
for iv, v in enumerate(dset[c]):
grid.SetCellValue(iv, ic, str(v))
class _ParametersWindow(wx.Frame):
def __init__(self, dset, parent=None):
title = 'Parameters: ' + dset.title
wx.Frame.__init__(self, parent, title=title, size=(400, 480))
self.create_tree(dset)
class _ParametersWindow(wx.Frame):
def __init__(self, dset, parent=None):
title = 'Parameters: ' + dset.title
wx.Frame.__init__(self, parent, title=title, size=(400, 480))
self.create_tree(dset)
def create_tree(self, dset):
datatree = {}
for p in dset.parameters():
is_hidden = p.get('hidden', "False")
if is_hidden == "True":
continue
group = datatree.get(p['group'], [])
#strval = str(p['value'] * p['unit'] if p['unit'] else p['value'])
#group.append("{:s} = {:s}".format(p['name'], strval))
group.append("{} = {} {}".format(p['name'], p['value'], p['unit']))
datatree[p['group']] = group
def create_tree(self, dset):
datatree = {}
for p in dset.parameters():
is_hidden = p.get('hidden', "False")
if is_hidden == "True":
continue
group = datatree.get(p['group'], [])
#strval = str(p['value'] * p['unit'] if p['unit'] else p['value'])
#group.append("{:s} = {:s}".format(p['name'], strval))
group.append("{} = {} {}".format(p['name'], p['value'], p['unit']))
datatree[p['group']] = group
tree = wx.TreeCtrl(self, -1)
root = tree.AddRoot('Parameters')
tree = wx.TreeCtrl(self, -1)
root = tree.AddRoot('Parameters')
for key in list(datatree.keys()):
item0 = tree.AppendItem(root, key)
for item in datatree[key]:
tree.AppendItem(item0, item)
tree.ExpandAll()
tree.SelectItem(root)
for key in list(datatree.keys()):
item0 = tree.AppendItem(root, key)
for item in datatree[key]:
tree.AppendItem(item0, item)
tree.ExpandAll()
tree.SelectItem(root)
class _DataWindow(wx.Frame):
def __init__(self, data):
assert isinstance(data, (Data, DataSet))
class _DataWindow(wx.Frame):
def __init__(self, data):
assert isinstance(data, (Data, DataSet))
if isinstance(data, DataSet):
dset = data
data = Data()
data.first = dset
self.data = data
self._filename = None
self._current_dset = None
if isinstance(data, DataSet):
dset = data
data = Data()
data.first = dset
self.data = data
self._filename = None
self._current_dset = None
wx.Frame.__init__(self, None, title="", size=(640, 480))
wx.Frame.__init__(self, None, title="", size=(640, 480))
self.Bind(wx.EVT_CLOSE, self.on_close)
self.Bind(wx.EVT_CLOSE, self.on_close)
# Populate the menu bar
self.create_menu()
# Populate the menu bar
self.create_menu()
# Create the status bar
statusbar = wx.StatusBar(self, -1)
statusbar.SetFieldsCount(3)
statusbar.SetStatusWidths([-2, -1, -1])
self.SetStatusBar(statusbar)
# Create the status bar
statusbar = wx.StatusBar(self, -1)
statusbar.SetFieldsCount(3)
statusbar.SetStatusWidths([-2, -1, -1])
self.SetStatusBar(statusbar)
# Add the notebook to hold all graphs
self.notebooks = {}
sizer = wx.BoxSizer(wx.VERTICAL)
#sizer.Add(self.notebook)
self.SetSizer(sizer)
# Add the notebook to hold all graphs
self.notebooks = {}
sizer = wx.BoxSizer(wx.VERTICAL)
#sizer.Add(self.notebook)
self.SetSizer(sizer)
self.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self.on_page_changed)
self.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self.on_page_changed)
self.create_notebooks()
self.update_title()
def create_notebooks(self):
for key in list(self.notebooks.keys()):
nb = self.notebooks.pop(key)
nb.Destroy()
for dset in self.data:
nb = wx.Notebook(self, -1)
self.notebooks[dset.title] = nb
#self.GetSizer().Add(nb, 1, wx.ALL|wx.EXPAND)
self.GetSizer().Add(nb, proportion=1, flag=wx.ALL|wx.EXPAND)
for view in dset.views():
self.create_page(nb, view)
self.create_menu()
self.show_dataset(self.data[0].title)
def create_menu(self):
menubar = wx.MenuBar()
menu1 = wx.Menu()
menu1.Append(110, "Open\tCtrl+O")
menu1.Append(120, "Save\tCtrl+S")
menu1.Append(130, "Save as...")
menu1.Append(140, "Export\tCtrl+E")
menu1.AppendSeparator()
menu1.Append(199, "Close\tCtrl+Q")
menu2 = wx.Menu()
for i, dset in enumerate(self.data):
menu_id = 201 + i
menu2.AppendRadioItem(menu_id, dset.title)
self.Bind(wx.EVT_MENU, self.on_menu_dataset, id=menu_id)
self.Bind(wx.EVT_MENU, self.on_open, id=110)
self.Bind(wx.EVT_MENU, self.on_save, id=120)
self.Bind(wx.EVT_MENU, self.on_saveas, id=130)
self.Bind(wx.EVT_MENU, self.on_export, id=140)
self.Bind(wx.EVT_MENU, self.on_close, id=199)
menu3 = wx.Menu()
menu3.Append(301, "Data")
menu3.Append(302, "Cluster")
menu3.Append(303, "Parameters")
self.Bind(wx.EVT_MENU, self.on_viewdata, id=301)
self.Bind(wx.EVT_MENU, self.on_viewcluster, id=302)
self.Bind(wx.EVT_MENU, self.on_viewparameters, id=303)
menubar.Append(menu1, "&File")
menubar.Append(menu2, "&Datasets")
menubar.Append(menu3, "&View")
self.SetMenuBar(menubar)
def on_open(self, event):
if self.data.is_dirty():
mbx = wx.MessageDialog(self, ('Displayed data is unsaved. Do '
'you wish to save before opening'
'another file ?'),
'Warning: Unsaved data',
wx.YES_NO | wx.ICON_WARNING)
if mbx.ShowModal() == wx.ID_YES:
self.on_saveas(wx.Event())
mbx.Destroy()
wildcard = "HDF5 files (*.hdf5)|*.hdf5"
dlg = wx.FileDialog(
self, message="Open a file...", defaultDir=os.getcwd(),
defaultFile="", wildcard=wildcard, style=wx.FD_OPEN
)
if dlg.ShowModal() == wx.ID_OK:
path = dlg.GetPath()
self._filename = path
self.data = Data.load(path)
self.create_notebooks()
dlg.Destroy()
self.update_title()
def on_save(self, event):
if self._filename:
self.update_title()
def create_notebooks(self):
for key in list(self.notebooks.keys()):
nb = self.notebooks.pop(key)
nb.Destroy()
for dset in self.data:
nb = wx.Notebook(self, -1)
self.notebooks[dset.title] = nb
#self.GetSizer().Add(nb, 1, wx.ALL|wx.EXPAND)
self.GetSizer().Add(nb, proportion=1, flag=wx.ALL|wx.EXPAND)
for view in dset.views():
self.create_page(nb, view)
self.create_menu()
self.show_dataset(self.data[0].title)
def create_menu(self):
menubar = wx.MenuBar()
menu1 = wx.Menu()
menu1.Append(110, "Open\tCtrl+O")
menu1.Append(120, "Save\tCtrl+S")
menu1.Append(130, "Save as...")
menu1.Append(140, "Export\tCtrl+E")
menu1.AppendSeparator()
menu1.Append(199, "Close\tCtrl+Q")
menu2 = wx.Menu()
for i, dset in enumerate(self.data):
menu_id = 201 + i
menu2.AppendRadioItem(menu_id, dset.title)
self.Bind(wx.EVT_MENU, self.on_menu_dataset, id=menu_id)
self.Bind(wx.EVT_MENU, self.on_open, id=110)
self.Bind(wx.EVT_MENU, self.on_save, id=120)
self.Bind(wx.EVT_MENU, self.on_saveas, id=130)
self.Bind(wx.EVT_MENU, self.on_export, id=140)
self.Bind(wx.EVT_MENU, self.on_close, id=199)
menu3 = wx.Menu()
menu3.Append(301, "Data")
menu3.Append(302, "Cluster")
menu3.Append(303, "Parameters")
self.Bind(wx.EVT_MENU, self.on_viewdata, id=301)
self.Bind(wx.EVT_MENU, self.on_viewcluster, id=302)
self.Bind(wx.EVT_MENU, self.on_viewparameters, id=303)
menubar.Append(menu1, "&File")
menubar.Append(menu2, "&Datasets")
menubar.Append(menu3, "&View")
self.SetMenuBar(menubar)
def on_open(self, event):
if self.data.is_dirty():
self.data.save(self._filename)
else:
self.on_saveas(event)
def on_saveas(self, event):
overwrite = True
wildcard = "HDF5 files (*.hdf5)|*.hdf5|All files (*.*)|*.*"
dlg = wx.FileDialog(
self, message="Save file as ...", defaultDir=os.getcwd(),
defaultFile='{}.hdf5'.format(self.data.title.replace(' ','_')),
wildcard=wildcard, style=wx.FD_SAVE)
dlg.SetFilterIndex(0)
if dlg.ShowModal() == wx.ID_OK:
path = dlg.GetPath()
if os.path.exists(path):
mbx = wx.MessageDialog(self, ('This file already exists. '
'Do you wish to overwrite it ?'),
'Warning: File exists',
wx.YES_NO | wx.ICON_WARNING)
if mbx.ShowModal() == wx.ID_NO:
overwrite = False
mbx = wx.MessageDialog(self, ('Displayed data is unsaved. Do '
'you wish to save before opening'
'another file ?'),
'Warning: Unsaved data',
wx.YES_NO | wx.ICON_WARNING)
if mbx.ShowModal() == wx.ID_YES:
self.on_saveas(wx.Event())
mbx.Destroy()
if overwrite:
self.data.save(path)
wildcard = "HDF5 files (*.hdf5)|*.hdf5"
dlg = wx.FileDialog(
self, message="Open a file...", defaultDir=os.getcwd(),
defaultFile="", wildcard=wildcard, style=wx.FD_OPEN
)
if dlg.ShowModal() == wx.ID_OK:
path = dlg.GetPath()
self._filename = path
dlg.Destroy()
self.update_title()
self.data = Data.load(path)
self.create_notebooks()
dlg.Destroy()
self.update_title()
def on_export(self, event):
overwrite = True
dlg = wx.DirDialog(
self, message="Export data...", defaultPath=os.getcwd(),
style=wx.DD_DEFAULT_STYLE)
if dlg.ShowModal() == wx.ID_OK:
path = dlg.GetPath()
if os.listdir(path):
mbx = wx.MessageDialog(self,
('This folder is not empty. '
'Exporting tour data here may '
'overwrite its content. Do you wish '
'to continue ?'),
'Warning: Folder is not empty',
wx.YES_NO | wx.ICON_WARNING)
if mbx.ShowModal() == wx.ID_NO:
overwrite = False
mbx.Destroy()
self.data.export(path, overwrite)
dlg.Destroy()
def on_viewdata(self, event):
dset = self.data[self._current_dset]
frame = _GridWindow(dset, parent=self)
frame.Show()
def on_viewcluster(self, event):
win = wx.Frame(None, size=wx.Size(480, 340))
cluster_viewer = ClusterViewer(win, size=wx.Size(480, 340))
dset = self.data[self._current_dset]
#s = StringIO()
#s.write(dset.get_parameter(group='Cluster', name='cluster')['value'])
#_s = dset.get_parameter(group='Cluster', name='cluster')['value']
#print(_s)
# rewind to the begining of the string
#s.seek(0)
#atoms = ase.io.read(s, format='xyz')
atoms = dset.get_cluster()
cluster_viewer.set_atoms(atoms, rescale=True, center=True)
cluster_viewer.rotate_atoms(0., 180.)
cluster_viewer.rotate_atoms(-45., -45.)
#cluster_viewer.show_emitter(True)
win.Show()
def on_viewparameters(self, event):
dset = self.data[self._current_dset]
frame = _ParametersWindow(dset, parent=self)
frame.Show()
def on_close(self, event):
if self.data.is_dirty():
mbx = wx.MessageDialog(self, ('Displayed data is unsaved. Do you '
'really want to quit ?'),
'Warning: Unsaved data',
wx.YES_NO | wx.ICON_WARNING)
if mbx.ShowModal() == wx.ID_NO:
mbx.Destroy()
return
self.Destroy()
def on_menu_dataset(self, event):
menu_id = event.GetId()
dset_name = self.GetMenuBar().FindItemById(menu_id).GetItemLabelText()
self.show_dataset(dset_name)
def show_dataset(self, name):
for nb in list(self.notebooks.values()):
nb.Hide()
self.notebooks[name].Show()
self.Layout()
self.update_statusbar()
self._current_dset = name
def create_page(self, nb, view):
# Get the matplotlib figure
figure = view.get_figure()
# Create a panel
p = wx.Panel(nb, -1)
# Create a matplotlib canvas for the figure
canvas = FigureCanvas(p, -1, figure)
sizer = wx.BoxSizer(wx.VERTICAL)
toolbar = NavigationToolbar2WxAgg(canvas)
toolbar.Realize()
#sizer.Add(toolbar, 0, wx.ALL|wx.EXPAND)
sizer.Add(toolbar, proportion=0, flag=wx.ALL|wx.EXPAND)
toolbar.update()
#sizer.Add(canvas, 5, wx.ALL|wx.EXPAND)
sizer.Add(canvas, proportion=1, flag=wx.ALL|wx.EXPAND)
p.SetSizer(sizer)
p.Fit()
p.Show()
# MPL events
figure.canvas.mpl_connect('motion_notify_event', self.on_mpl_motion)
figure.canvas.mpl_connect('pick_event', self.on_mpl_pick)
nb.AddPage(p, view.title)
canvas.draw()
def OLDcreate_page(self, nb, view):
opts = view._plotopts
p = wx.Panel(nb, -1)
figure = Figure()
axes = None
proj = opts['projection']
scale = opts['scale']
if proj == 'rectilinear':
axes = figure.add_subplot(111, projection='rectilinear')
elif proj in ('polar', 'ortho', 'stereo'):
axes = figure.add_subplot(111, projection='polar')
canvas = FigureCanvas(p, -1, figure)
sizer = wx.BoxSizer(wx.VERTICAL)
toolbar = NavigationToolbar2WxAgg(canvas)
toolbar.Realize()
sizer.Add(toolbar, 0, wx.ALL|wx.EXPAND)
toolbar.update()
sizer.Add(canvas, 5, wx.ALL|wx.EXPAND)
p.SetSizer(sizer)
p.Fit()
p.Show()
for values, label in zip(view.get_data(), opts['legend']):
# if we have only one column to plot, select a bar graph
if np.shape(values)[0] == 1:
xvalues = list(range(len(values[0])))
axes.bar(xvalues, values[0], label=label,
picker=5)
axes.set_xticks(xvalues)
def on_save(self, event):
if self._filename:
if self.data.is_dirty():
self.data.save(self._filename)
else:
if proj in ('ortho', 'stereo'):
theta, phi, Xsec = cols2matrix(*values)
theta_ticks = np.arange(0, 91, 15)
if proj == 'ortho':
R = np.sin(np.radians(theta))
R_ticks = np.sin(np.radians(theta_ticks))
elif proj == 'stereo':
R = 2 * np.tan(np.radians(theta/2.))
R_ticks = 2 * np.tan(np.radians(theta_ticks/2.))
#R = np.tan(np.radians(theta/2.))
X, Y = np.meshgrid(np.radians(phi), R)
im = axes.pcolormesh(X, Y, Xsec)
axes.set_yticks(R_ticks)
axes.set_yticklabels(theta_ticks)
self.on_saveas(event)
figure.colorbar(im)
def on_saveas(self, event):
overwrite = True
wildcard = "HDF5 files (*.hdf5)|*.hdf5|All files (*.*)|*.*"
dlg = wx.FileDialog(
self, message="Save file as ...", defaultDir=os.getcwd(),
defaultFile='{}.hdf5'.format(self.data.title.replace(' ','_')),
wildcard=wildcard, style=wx.FD_SAVE)
dlg.SetFilterIndex(0)
elif proj == 'polar':
values[0] = np.radians(values[0])
axes.plot(*values, label=label, picker=5,
marker=opts['marker'])
if dlg.ShowModal() == wx.ID_OK:
path = dlg.GetPath()
if os.path.exists(path):
mbx = wx.MessageDialog(self, ('This file already exists. '
'Do you wish to overwrite it ?'),
'Warning: File exists',
wx.YES_NO | wx.ICON_WARNING)
if mbx.ShowModal() == wx.ID_NO:
overwrite = False
mbx.Destroy()
if overwrite:
self.data.save(path)
self._filename = path
dlg.Destroy()
self.update_title()
def on_export(self, event):
overwrite = True
dlg = wx.DirDialog(
self, message="Export data...", defaultPath=os.getcwd(),
style=wx.DD_DEFAULT_STYLE)
if dlg.ShowModal() == wx.ID_OK:
path = dlg.GetPath()
if os.listdir(path):
mbx = wx.MessageDialog(self,
('This folder is not empty. '
'Exporting tour data here may '
'overwrite its content. Do you wish '
'to continue ?'),
'Warning: Folder is not empty',
wx.YES_NO | wx.ICON_WARNING)
if mbx.ShowModal() == wx.ID_NO:
overwrite = False
mbx.Destroy()
self.data.export(path, overwrite)
dlg.Destroy()
def on_viewdata(self, event):
dset = self.data[self._current_dset]
frame = _GridWindow(dset, parent=self)
frame.Show()
def on_viewcluster(self, event):
win = wx.Frame(None, size=wx.Size(480, 340))
cluster_viewer = ClusterViewer(win, size=wx.Size(480, 340))
dset = self.data[self._current_dset]
#s = StringIO()
#s.write(dset.get_parameter(group='Cluster', name='cluster')['value'])
#_s = dset.get_parameter(group='Cluster', name='cluster')['value']
#print(_s)
# rewind to the begining of the string
#s.seek(0)
#atoms = ase.io.read(s, format='xyz')
atoms = dset.get_cluster()
cluster_viewer.set_atoms(atoms, rescale=True, center=True)
cluster_viewer.rotate_atoms(0., 180.)
cluster_viewer.rotate_atoms(-45., -45.)
#cluster_viewer.show_emitter(True)
win.Show()
def on_viewparameters(self, event):
dset = self.data[self._current_dset]
frame = _ParametersWindow(dset, parent=self)
frame.Show()
def on_close(self, event):
if self.data.is_dirty():
mbx = wx.MessageDialog(self, ('Displayed data is unsaved. Do you '
'really want to quit ?'),
'Warning: Unsaved data',
wx.YES_NO | wx.ICON_WARNING)
if mbx.ShowModal() == wx.ID_NO:
mbx.Destroy()
return
self.Destroy()
def on_menu_dataset(self, event):
menu_id = event.GetId()
dset_name = self.GetMenuBar().FindItemById(menu_id).GetItemLabelText()
self.show_dataset(dset_name)
def show_dataset(self, name):
for nb in list(self.notebooks.values()):
nb.Hide()
self.notebooks[name].Show()
self.Layout()
self.update_statusbar()
self._current_dset = name
def create_page(self, nb, view):
# Get the matplotlib figure
figure = view.get_figure()
# Create a panel
p = wx.Panel(nb, -1)
# Create a matplotlib canvas for the figure
canvas = FigureCanvas(p, -1, figure)
sizer = wx.BoxSizer(wx.VERTICAL)
toolbar = NavigationToolbar2WxAgg(canvas)
toolbar.Realize()
#sizer.Add(toolbar, 0, wx.ALL|wx.EXPAND)
sizer.Add(toolbar, proportion=0, flag=wx.ALL|wx.EXPAND)
toolbar.update()
#sizer.Add(canvas, 5, wx.ALL|wx.EXPAND)
sizer.Add(canvas, proportion=1, flag=wx.ALL|wx.EXPAND)
p.SetSizer(sizer)
p.Fit()
p.Show()
# MPL events
figure.canvas.mpl_connect('motion_notify_event', self.on_mpl_motion)
figure.canvas.mpl_connect('pick_event', self.on_mpl_pick)
nb.AddPage(p, view.title)
canvas.draw()
def OLDcreate_page(self, nb, view):
opts = view._plotopts
p = wx.Panel(nb, -1)
figure = Figure()
axes = None
proj = opts['projection']
scale = opts['scale']
if proj == 'rectilinear':
axes = figure.add_subplot(111, projection='rectilinear')
elif proj in ('polar', 'ortho', 'stereo'):
axes = figure.add_subplot(111, projection='polar')
canvas = FigureCanvas(p, -1, figure)
sizer = wx.BoxSizer(wx.VERTICAL)
toolbar = NavigationToolbar2WxAgg(canvas)
toolbar.Realize()
sizer.Add(toolbar, 0, wx.ALL|wx.EXPAND)
toolbar.update()
sizer.Add(canvas, 5, wx.ALL|wx.EXPAND)
p.SetSizer(sizer)
p.Fit()
p.Show()
for values, label in zip(view.get_data(), opts['legend']):
# if we have only one column to plot, select a bar graph
if np.shape(values)[0] == 1:
xvalues = list(range(len(values[0])))
axes.bar(xvalues, values[0], label=label,
picker=5)
axes.set_xticks(xvalues)
else:
if scale == 'semilogx':
pltcmd = axes.semilogx
elif scale == 'semilogy':
pltcmd = axes.semilogy
elif scale == 'log':
pltcmd = axes.loglog
if proj in ('ortho', 'stereo'):
theta, phi, Xsec = cols2matrix(*values)
theta_ticks = np.arange(0, 91, 15)
if proj == 'ortho':
R = np.sin(np.radians(theta))
R_ticks = np.sin(np.radians(theta_ticks))
elif proj == 'stereo':
R = 2 * np.tan(np.radians(theta/2.))
R_ticks = 2 * np.tan(np.radians(theta_ticks/2.))
#R = np.tan(np.radians(theta/2.))
X, Y = np.meshgrid(np.radians(phi), R)
im = axes.pcolormesh(X, Y, Xsec)
axes.set_yticks(R_ticks)
axes.set_yticklabels(theta_ticks)
figure.colorbar(im)
elif proj == 'polar':
values[0] = np.radians(values[0])
axes.plot(*values, label=label, picker=5,
marker=opts['marker'])
else:
pltcmd = axes.plot
pltcmd(*values, label=label, picker=5,
marker=opts['marker'])
axes.grid(opts['grid'])
axes.set_title(opts['title'])
axes.set_xlabel(opts['xlabel'])
axes.set_ylabel(opts['ylabel'])
axes.set_xlim(*opts['xlim'])
axes.set_ylim(*opts['ylim'])
if label:
axes.legend()
axes.autoscale(enable=opts['autoscale'])
if scale == 'semilogx':
pltcmd = axes.semilogx
elif scale == 'semilogy':
pltcmd = axes.semilogy
elif scale == 'log':
pltcmd = axes.loglog
else:
pltcmd = axes.plot
pltcmd(*values, label=label, picker=5,
marker=opts['marker'])
axes.grid(opts['grid'])
axes.set_title(opts['title'])
axes.set_xlabel(opts['xlabel'])
axes.set_ylabel(opts['ylabel'])
axes.set_xlim(*opts['xlim'])
axes.set_ylim(*opts['ylim'])
if label:
axes.legend()
axes.autoscale(enable=opts['autoscale'])
# MPL events
figure.canvas.mpl_connect('motion_notify_event', self.on_mpl_motion)
figure.canvas.mpl_connect('pick_event', self.on_mpl_pick)
# MPL events
figure.canvas.mpl_connect('motion_notify_event', self.on_mpl_motion)
figure.canvas.mpl_connect('pick_event', self.on_mpl_pick)
nb.AddPage(p, view.title)
nb.AddPage(p, view.title)
def update_statusbar(self):
sb = self.GetStatusBar()
menu_id = self.GetMenuBar().FindMenu('Datasets')
menu = self.GetMenuBar().GetMenu(menu_id)
for item in menu.GetMenuItems():
if item.IsChecked():
sb.SetStatusText("%s" % item.GetItemLabelText(), 1)
break
def update_statusbar(self):
sb = self.GetStatusBar()
menu_id = self.GetMenuBar().FindMenu('Datasets')
menu = self.GetMenuBar().GetMenu(menu_id)
for item in menu.GetMenuItems():
if item.IsChecked():
sb.SetStatusText("%s" % item.GetItemLabelText(), 1)
break
def update_title(self):
title = "MsSpec Data Viewer"
if self.data.title:
title += ": " + self.data.title
if self._filename:
title += " [" + os.path.basename(self._filename) + "]"
self.SetTitle(title)
def update_title(self):
title = "MsSpec Data Viewer"
if self.data.title:
title += ": " + self.data.title
if self._filename:
title += " [" + os.path.basename(self._filename) + "]"
self.SetTitle(title)
def on_mpl_motion(self, event):
sb = self.GetStatusBar()
try:
txt = "[{:.3f}, {:.3f}]".format(event.xdata, event.ydata)
sb.SetStatusText(txt, 2)
except Exception:
pass
def on_mpl_motion(self, event):
sb = self.GetStatusBar()
try:
txt = "[{:.3f}, {:.3f}]".format(event.xdata, event.ydata)
sb.SetStatusText(txt, 2)
except Exception:
pass
def on_mpl_pick(self, event):
print(event.artist)
def on_mpl_pick(self, event):
print(event.artist)
def on_page_changed(self, event):
self.update_statusbar()
def on_page_changed(self, event):
self.update_statusbar()

View File

@ -3,7 +3,7 @@ PYMAJ = 3
PYMIN = 5
FC = gfortran
F2PY = f2py3 --f77exec=$(FC) --f90exec=$(FC)
F2PY = f2py --f77exec=$(FC) --f90exec=$(FC)
NO_VENV = 0
DEBUG = 0