.. _programming_chapter: ==================================== 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. 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 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 >>> g.x, g.y (1, 2) >>> g.name Traceback (most recent call last): File "", line 1, in 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. 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. 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 a. check indentation and `#end*` block terminators. b. 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. Larch submodules ============================ .. _lmfit: https://lmfit.github.io/lmfit-py/ .. _xraydb: https://xraypy.github.io/XrayDB/ .. _pyepics: https://pyepics.github.io/pyepics/ .. _wxmplot: https://newville.github.io/wxmplot/ 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. .. _pymodules_table: **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. 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 .. attribute:: site_config a container (module) of site configuration information. .. attribute:: is_from_python a boolean value indicating whether this larch module has been imported into Python (True) or into a Larch Interpreter (False) `larch.io` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The `io` module contains functions for reading and writing data with known formats. `larch.xafs` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The `xafs` module contains functions for XAFS analysis. `larch.xray` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The `xray` module contains functions for X-ray properties, as imported from `xraydb`_. `larch.xrf` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The `xrf` module contains functions for X-ray fluorescence data. `larch.xrd` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ `larch.xrmmap` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ `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. `larch.math` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ `larch.utils` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ `larch.epics` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ `larch.xmlrpc_server` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ `larch.shell` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ `larch.wxlib` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~