Arrays wrapping

In scattering, experimental data can be large. Depending on your sample and resolution of your instrument, single High Resolution X-ray diffraction curve measured near one diffraction peak can easily reach 5000 points. When developing library like ESCAPE one has to keep in mind a good enough performance in operating with large datasets, lack of unnecessary data copying to keep memory consumption constant and easy user interface to access and treat the data with other libraries. The escape.core.array module is responsible for that. This module provides an interface between numpy arrays and internal array_t core object which wraps a pointer to data and provides functionality to access this data by the core in an efficient way.

This notebook demonstrates how wrapping of numpy arrays works with the following ESCAPE array types: double_array_obj and mask_array_obj. The latter works with bool arrays and used for data masking. User can create a wrapper which will manage the same memory as a source numpy array or a new object with a full copy of the source.

All ESCAPE objects which require arrays for input and output do the wrapping automatically.

Below we create two double_array_obj objects, one contains a copy of a numpy array, dcopy and a second which wraps the same numpy array, dwrap

Let's set the last value of wrapper dwrap to 5, it shoud also change the original array. And we set dcopy[0] to -5, it doesn't influence original array.

Obviously, wrapping also works in another direction i.e. ESCAPE arrays double_array_obj and mask_array_obj can be wrapped by numpy library. In this case one can apply full functionality of numpy library to that arrays. Below we wrap a dcopy object. We set all its values to 10, which will not affect values of dwrap and darr arrays.

Masked arrays work in the same way as double arrays, except source array should contain boolean values. Below is an example of wrapping of boolean array.

Data

The object of data_obj type is a container class for experimental data. Data object is created with the following command:

esc.data(name="Data name", coordinates, experiment, errors=None, mask=None, 
          copy=False)

The data command expects 'coordinates' and 'experiment' arrays to have numpy.ndarray type. If not, they will be comverted and copied regardless of copy parameter.

All arrays will be copied if 'copy' parameter is True, otherwise data_obj keeps wrappers of arrays if it is possible. If 'errors' parameter is None, the experimental errors will be calculated according to Poisson distribution, i.e. errors=sqrt(experiment). The 'mask' parameter is used if some data points should be hidden, for example, primary beam or cosmic rays.

Data object has a dimensions property which returns number of coordinates in the input array, i.e. data which has dimensionality equal to $2$ correspond to a modeled function $F(x, y)$ and its input coordinates array is expected to have a form of $[x0, y0, x1, y1, x2, y2, ...]$. Two-dimensional arrays of the following form

coordinates=[
    [x0, y0],
    [x1, y1],
    [x2, y2]
]

are also supported.

Below few examples are given about how to create data objects of different dimensionality and how to plot them using show method from escape.utils module. In real life these arrays are read from experimental files of different formats. Currently there is no support of any format. The experimental data which is kept in ASCII text files can be read easily with exisitng numpy methods, like 'numpy.loadtxt', 'numpy.genfromtxt'.

Two-dimensional data

Two-dimensional data is straightforward.

Two-dimensional data with mask

Three-dimensional data

Three-dimensional data has two coordinates $x, y$ and intensity along $z$ - axis. Below is an example of how coordinate and intensity arrays can be created. Show method supports currently only map-like plots for 3d data, which should be specified with plot_type parameter.

Three-dimensional data with mask