astropy:docs

NDData overview

Initializing

An NDData object can be instantiated by passing it an n-dimensional Numpy array:

>>> import numpy as np
>>> from astropy.nddata import NDData
>>> array = np.zeros((12, 12, 12))  # a 3-dimensional array with all zeros
>>> ndd = NDData(array)

Note that the data in ndd is a reference to the original array, so changing the data in ndd will change the corresponding data in array in most circumstances.

An NDData object can also be instantiated by passing it an NDData object:

>>> ndd1 = NDData(array)
>>> ndd2 = NDData(ndd1)

As above, the data in``ndd2`` is a reference to the data in ndd1, so changes to one will affect the other.

This object has a few attributes in common with Numpy:

>>> ndd.ndim
3
>>> ndd.shape
(12, 12, 12)
>>> ndd.dtype
dtype('float64')

The underlying Numpy array can be accessed via the data attribute:

>>> ndd.data
array([[[ 0.,  0.,  0., ...

Mask

Values can be masked using the mask attribute, which should be a boolean Numpy array with the same dimensions as the data, e.g.:

>>> ndd.mask = ndd.data > 0.9

A mask value of True indicates a value that should be ignored, while a mask value of False indicates a valid value.

Flags

Values can be assigned one or more flags. The flags attribute is used to store either a single Numpy array (of any type) with dimensions matching that of the data, or a FlagCollection, which is essentially a dictionary of Numpy arrays (of any type) with the same shape as the data. The following example demonstrates setting a single set of integer flags:

>>> ndd.flags = np.zeros(ndd.shape)
>>> ndd.flags[ndd.data < 0.1] = 1
>>> ndd.flags[ndd.data < 0.01] = 2

but one can also have multiple flag layers with different types:

>>> from astropy.nddata import FlagCollection
>>> ndd.flags = FlagCollection(shape=(12, 12, 12))
>>> ndd.flags['photometry'] = np.zeros(ndd.shape, dtype=str)
>>> ndd.flags['photometry'][ndd.data > 0.9] = 's'
>>> ndd.flags['cosmic_rays'] = np.zeros(ndd.shape, dtype=int)
>>> ndd.flags['cosmic_rays'][ndd.data > 0.99] = 99

and flags can easily be used to set the mask:

>>> ndd.mask = ndd.flags['cosmic_rays'] == 99

Uncertainties

NDData objects have an uncertainty attribute that can be used to set the uncertainty on the data values. This is done by using classes to represent the uncertainties of a given type. For example, to set standard deviation uncertainties on the pixel values, you can do:

>>> from astropy.nddata import StdDevUncertainty
>>> ndd.uncertainty = StdDevUncertainty(np.ones((12, 12, 12)) * 0.1)

Note

For information on creating your own uncertainty classes, see Subclassing NDData and NDUncertainty.

Arithmetic

Provided that the world coordinate system (WCS) and shape match, and that the units are consisten, two NDData instances can be added, subtracted, multiplied or divided from each other, with uncertainty propagation, creating a new NDData object:

ndd3 = ndd1.add(ndd2)
ndd4 = ndd1.subtract(ndd2)
ndd5 = ndd1.multiply(ndd2)
ndd6 = ndd1.divide(ndd2)

The purpose of the add(), subtract(), multiply() and divide() methods is to allow the combination of two data objects that have common WCS and shape and units consistent with the operation performed, with consistent behavior for masks, and with a framework to propagate uncertainties. Currently any flags on the operands are dropped so that the result of the operation always has no flags. These methods are intended for use by sub-classes and functions that deal with more complex combinations.

Entries that are masked in either of the operands are also masked in the result.

Warning

Uncertainty propagation is still experimental, and does not take into account correlated uncertainties.

Meta-data

The NDData class includes a meta attribute that defaults to an empty dictionary, and can be used to set overall meta-data for the dataset:

ndd.meta['exposure_time'] = 340.
ndd.meta['filter'] = 'J'

Elements of the meta-data dictionary can be set to any valid Python object:

ndd.meta['history'] = ['calibrated', 'aligned', 'flat-fielded']

Converting to Numpy arrays

NDData objects can also be easily converted to numpy arrays:

>>> import numpy as np
>>> arr = np.array(ndd)
>>> np.all(arr == mydataarray)  
True

If a mask is defined, this will result in a MaskedArray, so in all cases a useable numpy.ndarray or subclass will result. This allows straightforward plotting of NDData objects with 1- and 2-dimensional datasets using Matplotlib:

>>> from matplotlib import pyplot as plt  
>>> plt.plot(ndd)  

This works because the Matplotlib plotting functions automatically convert their inputs using numpy.array.