diff --git a/src/msspec/iodata.py b/src/msspec/iodata.py
index 4b2fb1e..8a4771b 100644
--- a/src/msspec/iodata.py
+++ b/src/msspec/iodata.py
@@ -17,7 +17,7 @@
# along with this msspec. If not, see .
#
# Source file : src/msspec/iodata.py
-# Last modified: Mon, 16 Jun 2025 14:42:03 +0200
+# Last modified: Wed, 18 Jun 2025 11:46:41 +0200
# Committed by : Sylvain Tricot
@@ -84,6 +84,7 @@ from lxml import etree
from matplotlib.backends.backend_agg import FigureCanvasAgg
#from matplotlib.backends.backend_cairo import FigureCanvasCairo as FigureCanvasAgg
from matplotlib.figure import Figure
+from matplotlib import pyplot as plt
from terminaltables import AsciiTable
import msspec
@@ -336,6 +337,15 @@ class DataSet(object):
except:
pass
+ def get_views(self):
+ """Returns all the defined views in the dataset.
+
+ :return: A list of view
+ :rtype: List of :py:class:`iodata._DataSetView`
+ """
+ return self._views
+
+ @property
def views(self):
"""Returns all the defined views in the dataset.
@@ -365,7 +375,13 @@ class DataSet(object):
mydset.add_parameter(name='Spectrometer', group='misc', value='Omicron', unit='')
"""
- self._parameters.append(kwargs)
+ group = kwargs.get('group')
+ name = kwargs.get('name')
+ r = self.get_parameter(group=group, name=name)
+ if r:
+ r.update(**kwargs)
+ else:
+ self._parameters.append(kwargs)
def parameters(self):
"""
@@ -398,30 +414,39 @@ class DataSet(object):
p.append(_)
return p[0] if len(p) == 1 else p
+ def set_cluster(self, cluster):
+ clusbuf = StringIO()
+ cluster.info['absorber'] = cluster.absorber
+ write_xyz(clusbuf, cluster)
+ self.add_parameter(group='Cluster', name='cluster', value=clusbuf.getvalue(), hidden="True")
+
def get_cluster(self):
"""Get all the atoms in the cluster.
:return: The cluster
:rtype: :py:class:`ase.Atoms`
"""
- p = self.get_parameter(group='Cluster', name='cluster')['value']
- s = StringIO()
- s.write(self.get_parameter(group='Cluster', name='cluster')['value'])
- s.seek(0)
- #return ase.io.read(s, format='xyz')
- cluster = list(read_xyz(s))[-1]
- return cluster
+ try:
+ p = self.get_parameter(group='Cluster', name='cluster')['value']
+ s = StringIO()
+ s.write(self.get_parameter(group='Cluster', name='cluster')['value'])
+ s.seek(0)
+ #return ase.io.read(s, format='xyz')
+ cluster = list(read_xyz(s))[-1]
+ return cluster
+ except:
+ return None
def select(self, *args, **kwargs):
condition = kwargs.get('where', 'True')
indices = []
- def export_views(self, folder):
- for view in self.views():
+ def export_views(self, folder, dpi=100):
+ for view in self.get_views():
f = view.get_figure()
fname = os.path.join(folder, view.title) + '.png'
- f.savefig(fname)
+ f.savefig(fname, dpi=dpi)
def export(self, filename="", mode="w"):
@@ -671,6 +696,7 @@ class Data(object):
return
else:
data_grp = fd.create_group('DATA')
+ data_grp.attrs['dset_names'] = titles
meta_grp = fd.create_group('MsSpec viewer metainfo')
data_grp.attrs['title'] = self.title
@@ -681,6 +707,7 @@ class Data(object):
continue
grp = data_grp.create_group(dset.title)
grp.attrs['notes'] = dset.notes
+ grp.attrs['col_names'] = dset.columns()
for col_name in dset.columns():
data = dset[col_name]
grp.create_dataset(col_name, data=data)
@@ -691,7 +718,7 @@ class Data(object):
# xmlize views
for dset in self._datasets:
views_node = etree.SubElement(root, 'views', dataset=dset.title)
- for view in dset.views():
+ for view in dset.get_views():
view_el = etree.fromstring(view.to_xml())
views_node.append(view_el)
@@ -712,7 +739,7 @@ class Data(object):
self._dirty = False
LOGGER.info('Data saved in {}'.format(os.path.abspath(filename)))
- def export(self, folder, overwrite=False):
+ def export(self, folder, overwrite=False, dpi=150):
os.makedirs(folder, exist_ok=overwrite)
for dset in self._datasets:
dset_name = dset.title.replace(' ', '_')
@@ -720,7 +747,7 @@ class Data(object):
os.makedirs(p, exist_ok=overwrite)
fname = os.path.join(p, dset_name) + '.txt'
dset.export(fname)
- dset.export_views(p)
+ dset.export_views(p, dpi=dpi)
@staticmethod
def load(filename):
@@ -737,12 +764,20 @@ class Data(object):
views = {}
output.title = fd['DATA'].attrs['title']
- for dset_name in fd['DATA'] :
+ try:
+ dset_names = fd['DATA'].attrs['dset_names']
+ except:
+ dset_names = [_ for _ in fd['DATA']]
+ for dset_name in dset_names:
parameters[dset_name] = []
views[dset_name] = []
dset = output.add_dset(dset_name)
dset.notes = fd['DATA'][dset_name].attrs['notes']
- for h5dset in fd['DATA'][dset_name]:
+ try:
+ col_names = fd['DATA'][dset_name].attrs['col_names']
+ except:
+ col_names = [_ for _ in fd['DATA'][dset_name]]
+ for h5dset in col_names:
dset.add_columns(**{h5dset: fd['DATA'][dset_name][h5dset][...]})
try:
@@ -870,10 +905,19 @@ class _DataSetView(object):
data.append(values)
return data
- def get_figure(self):
+ def plot(self):
+ f = self.get_figure(backend='plt')
+ return f, f.get_axes()[0]
+
+
+ def get_figure(self, backend=None):
opts = self._plotopts
- figure = Figure(figsize=(3,2))
+ if backend is None:
+ figure = Figure()
+ else:
+ figure = plt.figure(num="[{}][{}]".format(self.dataset.title, self.title))
+
axes = None
proj = opts['projection']
scale = opts['scale']
@@ -1113,7 +1157,7 @@ if has_gui:
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():
+ for view in dset.get_views():
self.create_page(nb, view)
self.create_menu()
@@ -1291,6 +1335,10 @@ if has_gui:
self.Layout()
self.update_statusbar()
self._current_dset = name
+ has_cluster = True if self.data[self._current_dset].get_cluster() is not None else False
+ menu_item = self.GetMenuBar().FindItemById(302)
+ menu_item.Enable(has_cluster)
+
def create_page(self, nb, view):
# Get the matplotlib figure
@@ -1324,95 +1372,6 @@ if has_gui:
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 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:
- 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)
-
- nb.AddPage(p, view.title)
-
-
def update_statusbar(self):
sb = self.GetStatusBar()
menu_id = self.GetMenuBar().FindMenu('Datasets')