xraypy / xraylarch

Larch: Applications and Python Library for Data Analysis of X-ray Absorption Spectroscopy (XAS, XANES, XAFS, EXAFS), X-ray Fluorescence (XRF) Spectroscopy and Imaging, and more.
https://xraypy.github.io/xraylarch
Other
132 stars 63 forks source link

Using io.save() in Jupyter Lab #272

Open BGerwe opened 4 years ago

BGerwe commented 4 years ago

I'm not sure if this is truly a bug or my misunderstanding. For what it's worth I'm using larch 0.9.47 in JupyterLab 2.2.5 with Python 3.7.6 on Windows 10, and I have replicated this problem in both a "fresh" conda env and the base env.

When trying to save a Group I get the following error:

~\Anaconda3\lib\site-packages\larch\io\save_restore.py in save(fname, _larch, *args, **kws)
     48     for name, arg in zip(names, args):
     49         buff.append("#=> %s" % name)
---> 50         buff.append(json.dumps(encode4js(arg, grouplist=grouplist)))
     51     buff.append("")
     52     with open(fname, "w") as fh:

~\Anaconda3\lib\site-packages\larch\utils\jsonutils.py in encode4js(obj, grouplist)
     23     if grouplist is not None:
     24         for g in grouplist:
---> 25             _groups[g.__name__] = g
     26 
     27     if isinstance(obj, np.ndarray):

AttributeError: 'tuple' object has no attribute '__name__'

A minimal example based on the Jupyter Notebook example:

import larch
from larch import Interpreter
mylarch = Interpreter()
from larch.io import read_athena
project = read_athena('fe_athena.prj')
fe2o3 = project.fe2o3_rt1_xmu
larch.io.save('test.', fe2o3, _larch=mylarch)

Digging into the error I found that grouplist contains a list of tuples from _larch.symtable._sys.saverestore_groups

[(larch.xrf.roi.ROI, larch.xrf.mca.MCA),
 (larch.xafs.diffkk.diffKKGroup,
  larch.xafs.feffrunner.FeffRunner,
  larch.xafs.feffdat.FeffDatFile,
  larch.xafs.feffdat.FeffPathGroup,
  larch.xafs.feffit.TransformGroup,
  larch.xafs.feffit.FeffitDataSet)]

My ultimate goal is looping through a list of XAFS spectra, using pre_edge and autobk, and then saving the results (either all together or in separate files). Maybe there is a simpler way to accomplish this?

BGerwe commented 4 years ago

I figured out the solution for my use-case by using Athena project Groups. However, I'll keep the issue open unless it is expected behavior.

To show this behavior isn't tied to anything to Athena project Groups, here's another minimal example (loosely based on #58:

import larch
from larch import Group, Interpreter
from larch import io

mylarch = Interpreter()

x = [1, 2, 3, 4]
y = [0.5, 1, 1, 0.1]
z = ['a', 'b', 'c', 'd']
g = Group('mygroup', x=x, y=y, z=z)

io.save('test.lsav', g, _larch=mylarch)
newville commented 4 years ago

@BGerwe Yeah, saving a Project file should be easy with projectfile.save(). And then you have a resulting file that can be easily loaded into Athena or XAS_Viewer - that would definitely be the way to go.

The io.save() was meant to try to replace Ifeffit's save() function, which would basically save the state of the interpreter to be reloadable. This turns out to be much harder with something as complex as Python. So, it's sort of a "known wart". I'm OK with leaving this open a nudge to do something about it - maybe remove save() altogether or maybe "save the simple things that can be saved" (as this is almost always enough).

maurov commented 3 years ago

@newville @BGerwe doing some housekeeping with this issue, as it is relatively simple to solve. I propose to stick with Athena project files only to store/restore the state of a Larch project: