A data object contains your entire n-dimensional dataset, including axes, units, channels, and relevant metadata. Once you have a data object, all of the other capabilities of WrightTools are immediately open to you, including processing, fitting, and plotting tools.


WrightTools aims to provide user-friendly ways of creating data directly from common spectroscopy file formats. Here are the formats currently supported.

name description API
BrunoldrRaman Files from Brunold lab resonance raman measurements from_BrunoldrRaman()
Cary Files from Varian’s Cary® Spectrometers from_Cary()
COLORS Files from Control Lots Of Research in Spectroscopy from_COLORS()
JASCO Files from JASCO optical spectrometers. from_JASCO()
KENT Files from “ps control” by Kent Meyer from_KENT()
PyCMDS Files from PyCMDS. from_PyCMDS()
Ocean Optics .scope files from ocean optics spectrometers from_ocean_optics()
Shimadzu Files from Shimadzu UV-VIS spectrophotometers. from_shimadzu()
SPCM Files from Becker & Hickl spcm software from_spcm()
Tensor 27 Files from Bruker Tensor 27 FT-IR from_Tensor27()

Is your favorite format missing? It’s easy to add—promise! Check out Contributing.

Got bare numpy arrays and dreaming of data? It is possible to create data objects directly in special circumstances, as shown below.

# import
import numpy as np
import WrightTools as wt
# generate arrays for example
def my_resonance(xi, yi, intensity=1, FWHM=500, x0=7000):
    def single(arr, intensity=intensity, FWHM=FWHM, x0=x0):
        return intensity*(0.5*FWHM)**2/((xi-x0)**2+(0.5*FWHM)**2)
    return single(xi) * single(yi)
xi = np.linspace(6000, 8000, 75)[:, None]
yi = np.linspace(6000, 8000, 75)[None, :]
zi = my_resonance(xi, yi)
# package into data object
data = wt.Data(name='example')
data.create_variable(name='w1', units='wn', values=xi)
data.create_variable(name='w2', units='wn', values=yi)
data.create_channel(name='signal', values=zi)
data.transform('w1', 'w2')

Structure & properties

So what is a data object anyway? To put it simply, Data is a collection of Axis and Channel objects. Axis objects are composed of Variable objects.

attribute tuple of…
data.axes objects
data.constants objects
data.channels objects
data.variables objects

See also Data.axis_expressions, Data.constant_expressions, Data.channel_names and Data.variable_names.


Axes are the coordinates of the dataset. They have the following key attributes:

attribute description
axis.label LaTeX-formatted label, appropriate for plotting
axis.min() coordinates minimum, in current units
axis.max() coordinates maximum, in current units
axis.natural_name axis name
axis.units current axis units (change with axis.convert)
axis.variables component variables
axis.expression expression


Constants are a special subclass of Axis objects, which is expected to be a single value. Constant adds the value to to the label attribute, suitable for titles of plots to identify static values associated with the plot. Note that there is nothing enforcing that the value is actually static: constants still have shapes and can be indexed to get the underlying numpy array. In addition to the above attributes, constants add:

attribute description
constant.value The mean (ignoring NaNs) of the evaluated expression.
constant.std The standard deviation of the points used to compute the value.


Channels contain the n-dimensional data itself. They have the following key attributes:

attribute description
channel.label LaTeX-formatted label, appropriate for plotting
channel.mag() channel magnitude (furthest deviation from null)
channel.max() channel maximum
channel.min() channel minimum channel name
channel.null channel null (value of zero signal)
channel.signed flag to indicate if channel is signed


As mentioned above, the axes and channels within data can be accessed within the data.axes and data.channels lists. Data also supports natural naming, so axis and channel objects can be accessed directly according to their name. The natural syntax is recommended, as it tends to result in more readable code.

>>> data.axis_expressions
('w1', 'w2')
>>> data.w2 == data.axes[1]
>>> data.channel_names
('signal', 'pyro1', 'pyro2', 'pyro3')
>>> data.pyro2 == data.channels[2]

The order of axes and channels is arbitrary. However many methods within WrightTools operate on the zero-indexed channel by default. For this reason, you can bring your favorite channel to zero-index using bring_to_front().

Units aware & interpolation ready

Experiments are taken over all kinds of dynamic range, with all kinds of units. You might wish to take the difference between a UV-VIS scan taken from 400 to 800 nm, 1 nm steps and a different scan taken from 1.75 to 2.00 eV, 1 meV steps. This can be a huge pain! Even if you converted them to the same unit system, you would still have to deal with the different absolute positions of the two coordinate arrays. map_variable() allows you to easily obtain a data object mapped onto a different set of coordinates.

WrightTools data objects know all about units, and they are able to use interpolation to map between different absolute coordinates. Here we list some of the capabilities that are enabled by this behavior.

method description
heal() use interpolation to guess the value of NaNs within a channel
join() join together multiple data objects, accounting for dimensionality and overlap
map_variable() re-map data coordinates
offset() offset one axis based on another

Dimensionality without the cursing

Working with multidimensional data can be intimidating. What axis am I looking at again? Where am I in the other axis? Is this slice unusual, or do they all look like that?

WrightTools tries to make multi-dimensional data easy to work with. The following methods deal directly with dimensionality manipulation.

method description
chop() chop data into a list of lower dimensional data
collapse() destroy one dimension of data using a mathematical strategy
split() split data at a series of coordinates, without reducing dimensionality

WrightTools seamlessly handles dimensionality throughout. Artists is one such place where dimensionality is addressed explicitly.

Processing without the pain

There are many common data processing operations in spectroscopy. WrightTools endeavors to make these operations easy. A selection of important methods follows.

method description
clip() clip values outside of a given range
gradient() take the derivative along an axis
join() join multiple data objects into one
level() level the edge of data along a certain axis
smooth() smooth a channel via convolution with a n-dimensional Kaiser window
zoom() zoom a channel using spline interpolation