8. Programming with Larch from Python

This chapter describes the use of the larch module from Python. There are plenty of good reasons to want to do this, and it is certainly recommended over using the Larch mini-language for anything fairly complicated.

All the functionality described elsewhere in this documentation is available from the larch Python module - the focus here is on how to work with the larch functions from Python.

To start, you can import larch from Python with

>>> import larch

The toplevel larch module does not do much, so you will probably want to import some of the submodules like xafs or io. A simple Python 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 and documentation on what the larch functions do 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 an interpreter of the larch mini-language 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:

  1. Larch language is missing several constructs: class, lambda, generators, any asynchronous programming constructs.

  2. Larch language doe not use indentation. Leading whitespace is ignored and blocks must be terminated with a matching #endif, #endfor, #enddef, #endwhile, or #endtry.

  3. 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

  1. check indentation and #end* block terminators.

  2. 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.

module name

Description

larch

top-level module, with Interpreter and applications

larch.io

input/output routines

larch.xafs

XAFS analysis and data processingd

larch.xray

X-ray properties (with xraydb)

larch.xrf

X-ray fluorescenece processing and analysis

larch.xrd

X-ray diffraction processing

larch.xrmmap

working with XRF/XRD microprobe maps

larch.fitting

Data fitting (with lmfit)

larch.math

General-purpose mathematical functions

larch.utils

General-purpose utility functions

larch.epics

using with Epics control system (with pyepics)

larch.xmlrpc_server

running a Larch server for other processes

larch.shell

command-line shell

larch.wxlib

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 Interpreter

class to build a Larch Interpreter

class Group

class to build a Larch Group

site_config

a container (module) of site configuration information.

is_from_python

a boolean value indicating whether this larch module has been imported into Python (True) or into a Larch Interpreter (False)

8.5.2. larch.io

The io module contains functions for reading and writing data with known formats.

8.5.3. larch.xafs

The xafs module contains functions for XAFS analysis.

8.5.4. larch.xray

The xray module contains functions for X-ray properties, as imported from xraydb.

8.5.5. larch.xrf

The xrf module contains functions for X-ray fluorescence data.

8.5.6. larch.xrd

8.5.7. larch.xrmmap

8.5.8. larch.fitting

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.

8.5.9. larch.math

8.5.10. larch.utils

8.5.11. larch.epics

8.5.12. larch.xmlrpc_server

8.5.13. larch.shell

8.5.14. larch.wxlib