8. Programming with Larch from Python¶
This chapter describes the use of the larch module from Python. All the functionality described elsewhere in this documentation is available from the larch Python module and is available from:
>>> import larch
A simple session might look like this:
>>> from larch.xafs import autobk >>> from larch.io import read_xdi >>> from wxmplot.interactive import plot >>> dat = read_xdi('examples/xafsdata/fe3c_rt.xdi') >>> dat.mu = dat.mutrans >>> autobk(dat, rbkg=1.0, kweight=2) >>> plot(dat.k, dat.k*dat.chi, xlabel='k 1/A', ylabel='chi*k') >>> from larch.xray import xray_line >>> print(xray_line('Cu', 'Ka1')) >>> (8046.3, 0.577108, u'K', u'L3')
More elaborate examples are given throughout this documentation.
8.1. creating and using a larch interpreter in Python¶
The example above shows the larch functionality being accessed directly from Python. In addition, from Python you can create an instance of a larch Interpreter and communicate with it the Larch macro language with:
>>> from larch import Interpreter >>> session = Interpreter() >>> session(""" >>> dat = read_xdi('examples/xafsdata/fe3c_rt.xdi') >>> dat.mu = dat.mutrans >>> autobk(dat, rbkg=1.0, kweight=2) >>> """)
and so forth (and note that the tolerance against whitespace in the larch macro language might seem not so silly after all!). If you’re running pre-defined scripts or starting from the larch code generated by one of the GUIs, this can be a useful way to use Larch from python - combine that with some string formatting and you can readily have a program that wraps analysis procedures. Indeed this is how XAS_Viewer works.
The larch session instance will have a symtable attribute that is the top-level of the data namespace in the larch session - the _main group - that you can access directly from Python. For example, following the above session, you could do:
>>> dat = session.symtable.dat >>> print(dat.filename, dat.e0, len(dat.energy), len(dat.chi)) fe3c_rt.xdi 7122.5 348 299
8.2. The Larch Group¶
As described throughout the rest of the documentation, Larch organizes data using Group objects. For example, the dat value extracted from the larch session in the example above will be a Group. Many of the container objects created and used in Larch will be larch Groups.
For the Python user, these Groups are very similar to instances of an empty class or argparse.Namespace objects:
class GroupLite(object): pass
That is, it is a containrer object with data accessed using Python’s thing.attribute syntax. A larch Group has no public attributes or methods, but does have a few private ones. The most important of these is __name__, which you can assign at initialization with the name argument and will be shown in the “representation” string:
>>> from larch import Group >>> g = Group(name='my group', x=1, y=2) >>> g <Group my group> >>> g.x, g.y (1, 2) >>> g.name Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'Group' object has no attribute 'name' >>> g.__name__ 'foo' >>> g.name = 'Bob' >>> g.x, g.y, g.name (1, 2, 'Bob')
As you can see, you can create and use Groups from Python and set them into the namespace of a larch session and then access that data from the session:
>>> from larch import Group >>> import numpy as np >>> mygroup = Group(a = 1, message='hello', x=np.linspace(-10, 10, 201)) >>> session.symtable.frompy = mygroup >>> session("print(frompy.message, len(frompy.x))") hello 201
This can make it very easy to embed a larch session (or more than one) into a Python program and use it as a calculation engine.
8.3. The optional _larch argument¶
In earlier versions of larch, many functions in the Python interface required or strongly recommended making a larch interpreter and passing this around as a “session instance” to many of the larch functions. That is, you might see:
>>> from larch import Interreter >>> from larch.io import read_xdi >>> _larch = Interpreter() >>> dat = read_xdi('examples/xafsdata/fe3c_rt.xdi', _larch=_larch) # not needed!
With version 0.9.49, this is no longer needed. For backward compatibility, many functions still have an optional _larch argument. You may see this usage in some existing code, but at this point, this is no longer needed or recommended.
8.4. Converting “Larch code” into Python¶
As discussed in more detail in the next section, the Larch macro language is essentially a dialect of Python so that converting code from the macro language into Python is nearly trivial. The main differences between Python and the larch macro language are described here. Briefly, the differences are:
Larch language is missing several constructs: class, lambda, generators, any asynchronous programming constructs.
Larch language doe not use indentation. Leading whitespace is ignored and blocks must be terminated with a matching #endif, #endfor, #enddef, #endwhile, or #endtry.
import statements are not required for all of the built-in larch functionality, including large parts of numpy and scipy. As is appropropriate for a domain-specific language, many functions are readily available, though they are organized in a namespace with look-up rules. From a Larch session, you can import and use Python modules.
Other than these changes, code in the Larch language is Python code (it is parsed and evaluated using Python’s language tools) and all Larch objects are really Python objects. That means that converting Larch code into Python code can be very easy, with the main steps being
check indentation and #end* block terminators.
make sure the import statements are correctly provided.
Note that if the code is properly indented and also uses #end* block terminators that code can be both valid Python and Larch. The examples in the current document use this convention and have import statements commented out at the top so that they can be easily run in Python or from the Larch interpreter.
8.5. Larch submodules¶
The larch module is broken up into a number of submodules, as described in the table and sections below. To be clear, this list is incomplete and subject to change. The rest of this document should be used for details of the functionality of the various modules and functions.
Table of the Larch Python Modules This is an incomplete list of all the Python modules available from larch, but should cover those that are most useful to Python programmers.
top-level module, with Interpreter and applications
XAFS analysis and data processingd
X-ray properties (with xraydb)
X-ray fluorescenece processing and analysis
X-ray diffraction processing
working with XRF/XRD microprobe maps
Data fitting (with lmfit)
General-purpose mathematical functions
General-purpose utility functions
using with Epics control system (with pyepics)
running a Larch server for other processes
Wx-python utilities (including wxmplot plotting)
Note that several of these modules (xray, fitting, epics, the plotting functionality in wxlib) are fairly thin wrappers around other python libraries that are generally well-documented and do not need to be used only from with larch. If you find yourself using these submodules, it might be easier to just use the more general-purpose library.
8.5.1. Top-level larch¶
The top-level larch module contains several modules and a few important classes and methods. An incomplete list, but the most important objects in the top-level module are:
class to build a Larch Interpreter
class to build a Larch Group
a container (module) of site configuration information.
a boolean value indicating whether this larch module has been imported into Python (True) or into a Larch Interpreter (False)
The io module contains functions for reading and writing data with known formats.
The xafs module contains functions for XAFS analysis.
The xray module contains functions for X-ray properties, as imported from xraydb.
The xrf module contains functions for X-ray fluorescence data.
The fitting module contains functions for fitting data, including to known lineshapes. Much of this is taken directly from lmfit or modified slightly for Larch. If you’re writing programs for fitting data, we do recommend using lmfit directly.