astro py:docs

- Index
- Modules

### Navigation

- next »
- « previous |
- Astropy v1.1.1 »
- N-dimensional datasets (`astropy.nddata`) »
- Subclassing

# Subclassing

There are a couple of choices to be made in subclassing from the nddata package. For the greatest flexibility, subclass from `NDDataBase`, which places (almost) no restrictions on any of its attributes. In many cases, subclassing `NDData` will work instead; it is more straightforward but places some minimal restrictions on how the data can be represented.

## `NDDataBase`

The class `NDDataBase` is a metaclass – when subclassing it, all properties of `NDDataBase` except `uncertainty` must be overriden in the subclass. For an example of how to do this, see the source code for `astropy.nddata.NDData`.

Subclassing from `NDDataBase` gives you complete flexibility in how you implement data storage and the other properties. If your data is stored in a numpy array (or something that behaves like a numpy array), it may be more straightforward to subclass `NDData` instead of `NDDataBase`.

## `NDData`

This class serves as the base for subclasses that use a numpy array (or something that presents a numpy-like interface) as the `data` attribute.

For an example of a class that includes mixins and subclasses `NDData` to add additional functionality, see `NDDataArray`.

## Subclassing `NDUncertainty`

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:

    >>> import numpy as np
    >>> from astropy.nddata import NDData, StdDevUncertainty
    >>> array = np.zeros((12, 12, 12))  # a 3-dimensional array with all zeros
    >>> ndd = NDData(array)
    >>> uncertainty = StdDevUncertainty(np.ones((12, 12, 12)) * 0.1)
    >>> ndd_uncertainty = NDData(ndd, uncertainty=uncertainty)
    INFO: Overwriting NDData's current uncertainty being overwritten with specified uncertainty [astropy.nddata.nddata]

New error classes should sub-class from `NDUncertainty`, and should provide methods with the following API:

    class MyUncertainty(NDUncertainty):

        def propagate_add(self, other_nddata, result_data):
            ...
            result_uncertainty = MyUncertainty(...)
            return result_uncertainty

        def propagate_subtract(self, other_nddata, result_data):
            ...
            result_uncertainty = MyUncertainty(...)
            return result_uncertainty

        def propagate_multiply(self, other_nddata, result_data):
            ...
            result_uncertainty = MyUncertainty(...)
            return result_uncertainty

        def propagate_divide(self, other_nddata, result_data):
            ...
            result_uncertainty = MyUncertainty(...)
            return result_uncertainty

All error sub-classes inherit an attribute `self.parent_nddata` that is automatically set to the parent `NDData` object that they are attached to. The arguments passed to the error propagation methods are `other_nddata`, which is the `NDData` object that is being combined with `self.parent_nddata`, and `result_data`, which is a Numpy array that contains the data array after the arithmetic operation. All these methods should return an error instance `result_uncertainty`, and should not modify `parent_nddata` directly. For subtraction and division, the order of the operations is `parent_nddata - other_nddata` and `parent_nddata / other_nddata`.

To make it easier and clearer to code up the error propagation, you can use variables with more explicit names, e.g:

    class MyUncertainty(NDUncertainty):

        def propogate_add(self, other_nddata, result_data):

            left_uncertainty = self.parent.uncertainty.array
            right_uncertainty = other_nddata.uncertainty.array

            ...

Note that the above example assumes that the errors are stored in an `array` attribute, but this does not have to be the case.

For an example of a complete implementation, see `StdDevUncertainty`.