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 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
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)
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
.