Skip to main content
`Ctrl`+`K`

# NDCube

class ndcube.NDCube(

  data,
  wcs=None,
  uncertainty=None,
  mask=None,
  meta=None,
  unit=None,
  copy=False,
  psf=None,
  *,
  extra_coords=None,
  global_coords=None,
  **kwargs,

)

  Bases: `NDCubeBase`

  Class representing N-D data described by a single array and set of WCS transformations.

  Parameters:

    - data (`numpy.ndarray`) – The array holding the actual data in this object.

    - wcs (`astropy.wcs.wcsapi.BaseLowLevelWCS`, `astropy.wcs.wcsapi.BaseHighLevelWCS`, optional) – The WCS object containing the axes’ information, optional only if `data` is an `astropy.nddata.NDData` object.

    - uncertainty (Any, optional) – Uncertainty in the dataset. Should have an attribute uncertainty_type that defines what kind of uncertainty is stored, for example “std” for standard deviation or “var” for variance. A metaclass defining such an interface is NDUncertainty - but isn’t mandatory. If the uncertainty has no such attribute the uncertainty is stored as UnknownUncertainty. Defaults to None.

    - mask (Any, optional) – Mask for the dataset. Masks should follow the numpy convention that valid data points are marked by False and invalid ones with True. Defaults to None.

    - meta (dict-like, optional) – Additional meta information about the dataset. If no meta is provided an empty collections.OrderedDict is created. Default is None.

    - unit (`astropy.units.Unit` or str, optional) – Unit for the dataset. Strings that can be converted to a Unit are allowed. Default is None.

    - extra_coords (iterable of `tuple`, each with three entries) – (`str`, `int`, `astropy.units.Quantity` or array-like) Gives the name, axis of data, and values of coordinates of a data axis not included in the WCS object.

    - copy (bool, optional) – Indicates whether to save the arguments as copy. True copies every attribute before saving it while False tries to save every parameter as reference. Note however that it is not always possible to save the input as reference. Default is False.

  Attributes Summary

  `array_axis_physical_types` | Returns the WCS physical types that vary along each array axis.
  `combined_wcs` | The WCS transform for the NDCube, including the coordinates specified in `.extra_coords`.
  `data` | `ndarray` - like
  `dimensions` |
  `extra_coords` | Coordinates not described by `NDCubeABC.wcs` which vary along one or more axes.
  `global_coords` | Coordinate metadata which applies to the whole cube.
  `mask` | Mask for the dataset, if any.
  `meta` |
  `plotter` | A ~ndcube.visualization.mpl_plotter.MatplotlibPlotter` instance providing visualization methods.
  `psf` | Image representation of the PSF for the dataset.
  `quantity` | Unitful representation of the NDCube data.
  `shape` |
  `uncertainty` | Uncertainty in the dataset, if any.
  `unit` | Unit for the dataset, if any.
  `wcs` | A world coordinate system (WCS) for the dataset, if any.

  Methods Summary

  `axis_world_coords`(*axes[, pixel_corners, wcs]) | Returns objects representing the world coordinates of pixel centers for a desired axes.
  `axis_world_coords_values`(*axes[, ...]) | Returns the world coordinate values of all pixels for desired axes.
  `crop`(*points[, wcs, keepdims]) | Crop using real world coordinates.
  `crop_by_values`(*points[, units, wcs, keepdims]) | Crop using real world coordinates.
  `explode_along_axis`(axis) | Separates slices of NDCubes along a given axis into an NDCubeSequence of (N-1)DCubes.
  `fill_masked`(fill_value[, ...]) | Replaces masked data values with input value.
  `plot`([axes, plot_axes, axes_coordinates, ...]) | Visualize the `NDCube`.
  `rebin`(bin_shape[, operation, ...]) | Downsample array by combining contiguous pixels into bins.
  `reproject_to`(target_wcs[, algorithm, ...]) | Reprojects the instance to the coordinates described by another WCS object.
  `squeeze`([axis]) | Removes all axes with a length of 1.
  `to`(new_unit, **kwargs) | Convert instance to another unit.
  `to_nddata`(*[, data, wcs, uncertainty, mask, ...]) | Constructs a new `NDData` instance from this object.

  Attributes Documentation

  array_axis_physical_types
  combined_wcs
  data
    `ndarray` - like

      The stored dataset.

    Notes

    It is possible to set the `.data` attribute on a `NDCube` with an array-like object of the same shape. However, this is really only intended for replacing the data with a different object representing the same physical data as no other properties of the cube will be changed, such as uncertainty or unit.

  dimensions
  extra_coords
  global_coords
  mask

    Mask for the dataset, if any.

    Masks should follow the `numpy` convention that valid data points are marked by `False` and invalid ones with `True`.

    Type:

      any type

  meta = None
  plotter = None

    A ~ndcube.visualization.mpl_plotter.MatplotlibPlotter` instance providing visualization methods.

    The type of this attribute can be changed to provide custom visualization functionality.

  psf
  quantity

    Unitful representation of the NDCube data.

  shape
  uncertainty

    Uncertainty in the dataset, if any.

    Should have an attribute `uncertainty_type` that defines what kind of uncertainty is stored, such as `'std'` for standard deviation or `'var'` for variance. A metaclass defining such an interface is `NDUncertainty` but isn’t mandatory.

    Type:

      any type

  unit

    Unit for the dataset, if any.

    Type:

      `Unit`

  wcs

    A world coordinate system (WCS) for the dataset, if any.

    Type:

      any type

  Methods Documentation

  axis_world_coords(*axes, pixel_corners=False, wcs=None)

    Returns objects representing the world coordinates of pixel centers for a desired axes.

    Parameters:

      - axes (`int` or `str`, or multiple `int` or `str`, optional) – Axis number in numpy ordering or unique substring of `ndcube.NDCube.wcs.world_axis_physical_types` of axes for which real world coordinates are desired. Not specifying axes inputs causes results for all axes to be returned.

      - pixel_corners (`bool`, optional) – If `True` then instead of returning the coordinates at the centers of the pixels, the coordinates at the pixel corners will be returned. This increases the size of the output by 1 in all dimensions as all corners are returned.

      - wcs (`astropy.wcs.wcsapi.BaseHighLevelWCS`, optional) – The WCS object to used to calculate the world coordinates. Although technically this can be any valid WCS, it will typically be `self.wcs`, `self.extra_coords`, or `self.combined_wcs` combining both the WCS and extra coords. Default=self.wcs

    Returns:

      axes_coords – An iterable of “high level” objects giving the real world coords for the axes requested by user. For example, a tuple of `SkyCoord` objects. The types returned are determined by the WCS object. The dimensionality of these objects should match that of their corresponding array dimensions, unless `pixel_corners=True` in which case the length along each axis will be 1 greater than the number of pixels.

    Return type:

      iterable

    Examples

        >>> NDCube.axis_world_coords('lat', 'lon')
        >>> NDCube.axis_world_coords(2)

  axis_world_coords_values(*axes, pixel_corners=False, wcs=None)

    Returns the world coordinate values of all pixels for desired axes. In contrast to `ndcube.NDCube.axis_world_coords()`, this method returns `Quantity` objects. Which only provide units rather than full coordinate metadata provided by high-level coordinate objects.

    Parameters:

      - axes (`int` or `str`, or multiple `int` or `str`, optional) – Axis number in numpy ordering or unique substring of `ndcube.NDCube.wcs.world_axis_physical_types` of axes for which real world coordinates are desired. axes=None implies all axes will be returned.

      - pixel_corners (`bool`, optional) – If `True` then coordinates at pixel corners will be returned rather than at pixel centers. This increases the size of the output along each dimension by 1 as all corners are returned.

      - wcs (`BaseHighLevelWCS` or `ExtraCoordsABC`, optional) – The WCS object to be used to calculate the world coordinates. Although technically this can be any valid WCS, it will typically be `self.wcs`, `self.extra_coords`, or `self.combined_wcs`, combing both the WCS and extra coords. Defaults to the `.wcs` property.

    Returns:

      axes_coords – An iterable of raw coordinate values for all pixels for the requested axes. The returned units are determined by the WCS object. The dimensionality of these objects should match that of their corresponding array dimensions, unless `pixel_corners=True` in which case the length along each axis will be 1 greater than the number of pixels.

    Return type:

      `tuple` of `Quantity`

    Examples

        >>> NDCube.axis_world_coords_values('lat', 'lon')
        >>> NDCube.axis_world_coords_values(2)

  crop(*points, wcs=None, keepdims=False)

    Crop using real world coordinates. This method crops the NDCube to the smallest bounding box in pixel space that contains all the provided world coordinate points.

    This function takes the points defined as high-level astropy coordinate objects such as `SkyCoord`, `SpectralCoord`, etc.

    Parameters:

      - points (iterable of iterables) –

        Tuples of high level coordinate objects e.g. `SkyCoord`. Each iterable of coordinate objects represents a single location in the data array in real world coordinates.

        The coordinates of the points as they are passed to `world_to_pixel`. Therefore their number and order must be compatible with the API of that method, i.e. they must be passed in world order.

      - wcs (`BaseHighLevelWCS` or `ExtraCoordsABC`) – The WCS to use to calculate the pixel coordinates based on the input. Will default to the `.wcs` property if not given. While any valid WCS could be used it is expected that either the `.wcs` or `.extra_coords` properties will be used.

      - keepdims (`bool`, optional) – If `False` and if cropping results in length-1 dimensions, these are sliced away in output cube. If `True`, length-1 dimensions are kept. Default=False

    Return type:

      `NDCubeABC`

    Examples

        >>> # An example of cropping a region of interest on the Sun from a 3-D image-time cube
        >>> point1 = [SkyCoord(-50*u.deg, -40*u.deg, frame=frames.HeliographicStonyhurst), None]
        >>> point2 = [SkyCoord(0*u.deg, -6*u.deg, frame=frames.HeliographicStonyhurst), None]
        >>> NDCube.crop(point1, point2)

  crop_by_values(*points, units=None, wcs=None, keepdims=False)

    Crop using real world coordinates. This method crops the NDCube to the smallest bounding box in pixel space that contains all the provided world coordinate points.

    This function takes points as iterables of low-level coordinate objects, i.e. `Quantity` objects. This differs from `crop()` which takes high-level coordinate objects requiring all the relevant coordinate information such as coordinate frame etc. Hence this method’s API is more basic but less explicit.

    Parameters:

      - points (iterable) – Tuples of coordinate values, the length of the tuples must be equal to the number of world dimensions. These points are passed to `wcs.world_to_pixel_values` so their units and order must be compatible with that method.

      - units (`str` or `Unit`) – If the inputs are set without units, the user must set the units inside this argument as `str` or `Unit` objects. The length of the iterable must equal the number of world dimensions and must have the same order as the coordinate points.

      - wcs (`BaseHighLevelWCS` or `ExtraCoordsABC`) – The WCS to use to calculate the pixel coordinates based on the input. Will default to the `.wcs` property if not given. While any valid WCS could be used it is expected that either the `.wcs` or `.extra_coords` properties will be used.

      - keepdims (`bool`, optional) – If `False` and if cropping results in length-1 dimensions, these are sliced away in output cube. If `True`, length-1 dimensions are kept. Default=False

    Return type:

      `NDCubeABC`

    Examples

        >>> # An example of cropping a region of interest on the Sun from a 3-D image-time cube
        >>> NDCube.crop_by_values((-600, -600, 0), (0, 0, 0), units=(u.arcsec, u.arcsec, u.s))

  explode_along_axis(axis)

    Separates slices of NDCubes along a given axis into an NDCubeSequence of (N-1)DCubes.

    Parameters:

      axis (`int`) – The array axis along which the data is to be changed.

    Returns:

      result

    Return type:

      `ndcube.NDCubeSequence`

  fill_masked(
    fill_value,
    uncertainty_fill_value=None,
    unmask=False,
    fill_in_place=False,
  )

    Replaces masked data values with input value.

    Returns a new instance or alters values in place.

    Parameters:

      - fill_value (`numbers.Number` or scalar `astropy.units.Quantity`) – The value to replace masked data with.

      - unmask (`bool`, optional) – If True, the newly filled masked values are unmasked. If False, they remain masked Default=False

      - uncertainty_fill_value (`numbers.Number` or scalar `astropy.units.Quantity`, optional) – The value to replace masked uncertainties with.

      - fill_in_place (`bool`, optional) – If `True`, the masked values are filled in place. If `False`, a new instance is returned with masked values filled. Default=False.

  plot(
    axes=None,
    plot_axes=None,
    axes_coordinates=None,
    axes_units=None,
    data_unit=None,
    wcs=None,
    **kwargs,
  )

    Visualize the `NDCube`.

    Parameters:

      - axes (`WCSAxes` or None:, optional) – The axes to plot onto. If None the current axes will be used.

      - plot_axes (`list`, optional) – A list of length equal to the number of pixel dimensions in array axis order. This list selects which cube axes are displayed on which plot axes. For an image plot this list should contain `'x'` and `'y'` for the plot axes and `None` for all the other elements. For a line plot it should only contain `'x'` and `None` for all the other elements.

      - axes_unit (`list`, optional) – A list of length equal to the number of world dimensions specifying the units of each axis, or `None` to use the default unit for that axis.

      - axes_coordinates (`list`, optional) – A list of length equal to the number of pixel dimensions. For each axis the value of the list should either be a string giving the world axis type or `None` to use the default axis from the WCS.

      - data_unit (`astropy.units.Unit`) – The data is changed to the unit given or the `NDCube.unit` if not given.

      - wcs (`astropy.wcs.wcsapi.BaseHighLevelWCS`) – The WCS object to define the coordinates of the plot axes.

      - kwargs – Additional keyword arguments are given to the underlying plotting infrastructure which depends on the dimensionality of the data and whether 1 or 2 plot_axes are defined: - Animations: `mpl_animators.ArrayAnimatorWCS` - Static 2-D images: `matplotlib.pyplot.imshow` - Static 1-D line plots: `matplotlib.pyplot.plot`

  rebin(
    bin_shape,
    operation=<function mean>,
    operation_ignores_mask=False,
    handle_mask=<function all>,
    propagate_uncertainties=False,
    new_unit=None,
    **kwargs,
  )

    Downsample array by combining contiguous pixels into bins.

    Values in bins are determined by applying a function to the pixel values within it. The number of pixels in each bin in each dimension is given by the `bin_shape` input. This must be an integer fraction of the cube’s array size in each dimension. If the NDCube instance has uncertainties attached, they are propagated depending on binning method chosen.

    Parameters:

      - bin_shape (array-like, `astropy.units.Quantity`) – The number of pixels in a bin in each dimension. Must be the same length as number of dimensions in data. Each element must be in int. If they are not they will be rounded to the nearest int. If provided as a `Quantity` the units have to be convertible to pixels. The sentinel value `-1` can be passed for a dimension which sets the bin size equal to the number of pixels along that axis. This results in a pixel size of 1 for this axis in the output (e.g. sum along that axis). Please note the `bin_shape` follows array axis (NumPy) ordering of the axes.

      - operation (function) – Function applied to the data to derive values of the bins. Default is `numpy.mean`

      - operation_ignores_mask (`bool`) – Determines how masked values are handled. If False (default), masked values are excluded when calculating rebinned value. If True, masked values are used in calculating rebinned value.

      - handle_mask (`None` or function) – Function to apply to each bin in the mask to calculate the new mask values. If `None` resultant mask is `None`. Default is `numpy.all`

      - propagate_uncertainties (`bool` or function.) – If False, uncertainties are dropped. If True, default algorithm is used (`propagate_rebin_uncertainties`) Can also be set to a function which performs custom uncertainty propagation. Additional kwargs provided to this method are passed onto this function. See Notes section on how to write a custom `propagate_uncertainties` function.

      - new_unit (`astropy.units.Unit`, optional) – If the rebinning operation alters the data unit, the new unit can be provided here.

      - kwargs – All kwargs are passed to the error propagation function.

    Returns:

      new_cube – The resolution-degraded cube.

    Return type:

      `NDCube`

    Notes

    Rebining Algorithm Rebinning is achieved by reshaping the N-D array to a 2N-D array and applying the function over the odd-numbered axes. To demonstrate, consider the following example. Let’s say you have an array:

        x = np.array([[0, 0, 0, 1, 1, 1],
                      [0, 0, 1, 1, 0, 0],
                      [1, 1, 0, 0, 1, 1],
                      [0, 0, 0, 0, 1, 1],
                      [1, 0, 1, 0, 1, 1],
                      [0, 0, 1, 0, 0, 0]])

    and you want to sum over 2x2 non-overlapping sub-arrays. This summing can be done by reshaping the array:

        y = x.reshape(3,2,3,2)

    and then summing over the 1st and third directions:

        y2 = y.sum(axis=3).sum(axis=1)

    which gives the expected array:

        array([[0, 3, 2],
               [2, 0, 4],
               [1, 2, 2]])

    Defining Custom Error Propagation To perform custom uncertainty propagation, a function must be provided via the propgate_uncertainty kwarg. This function must accept, although doesn’t have to use, the following args:

    uncertainty: `astropy.nddata.NDUncertainty` but not `astropy.nddata.UnknownUncertainty`

      The uncertainties associated with the data.

    data: array-like

      The data associated with the above uncertainties. Must have same shape as uncertainty.

    mask: array-like of `bool` or `None`

      Indicates whether any uncertainty elements should be ignored in propagation. True elements cause corresponding uncertainty elements to be ignored. False elements cause corresponding uncertainty elements to be propagated. Must have same shape as above. If None, no uncertainties are ignored.

    All kwarg inputs to the rebin method are also passed on transparently to the propagation function. Hence additional inputs to the propagation function can be included as kwargs to `ndcube.NDCube.rebin()`.

    The shape of the uncertainty, data and mask inputs are such that the first dimension represents the pixels in a given bin whose data and uncertainties are aggregated by the rebin process. The shape of the remaining dimensions must be the same as the final rebinned data. A silly but informative example of a custom propagation function might be:

        def my_propagate(uncertainty, data, mask, **kwargs):
            # As a silly example, propagate uncertainties by summing those in same bin.
            # Note not all args are used, but function must accept them.
            n_pixels_per_bin = data.shape[0]  # 1st dimension of inputs gives pixels in bin.
            final_shape = data.shape[1:]  # Trailing dims give shape of put rebinned data.
            # Propagate uncerts by adding them.
            new_uncert = numpy.zeros(final_shape)
            for i in range(n_pixels_per_bin):
                new_uncert += uncertainty.array[i]
            # Alternatively: new_uncerts = uncertainty.array.sum(axis=0)
            return type(uncertainty)(new_uncert)  # Convert to original uncert type and return.

  reproject_to(
    target_wcs,
    algorithm='interpolation',
    shape_out=None,
    return_footprint=False,
    **reproject_args,
  )

    Reprojects the instance to the coordinates described by another WCS object.

    Parameters:

      - target_wcs (`astropy.wcs.wcsapi.BaseHighLevelWCS`, `astropy.wcs.wcsapi.BaseLowLevelWCS`,) – or `astropy.io.fits.Header` The WCS object to which the `ndcube.NDCube` is to be reprojected.

      - algorithm (`str`, optional) – The algorithm to use for reprojecting. When set to “interpolation” `reproject_interp` is used. When set to “adaptive” `reproject_adaptive` is used. When set to “exact” `reproject_exact` is used.

      - shape_out (`tuple`, optional) – The shape of the output data array. The ordering of the dimensions must follow NumPy ordering and not the WCS pixel shape. If not specified, `array_shape` attribute (if available) from the low level API of the `target_wcs` is used.

      - return_footprint (`bool`) – If `True` the footprint is returned in addition to the new `NDCube`. Defaults to `False`.

      - **reproject_args – All other arguments are passed through to the reproject function being called. The function being called depends on the `algorithm=` keyword argument, see that for more details.

    Returns:

      - reprojected_cube (`ndcube.NDCube`) – A new resultant NDCube object, the supplied `target_wcs` will be the `.wcs` attribute of the output `NDCube`.

      - footprint (`numpy.ndarray`) – Footprint of the input array in the output array. Values of 0 indicate no coverage or valid values in the input image, while values of 1 indicate valid values.

    See also

    `reproject.reproject_interp`, `reproject.reproject_adaptive`, `reproject.reproject_exact`

    Notes

    This method doesn’t support handling of the `mask`, `extra_coords`, and `uncertainty` attributes yet. However, `meta` and `global_coords` are copied to the output `ndcube.NDCube`.

  squeeze(axis=None)

    Removes all axes with a length of 1.

    Parameters:

      axis (array-like, optional) – Specifies specific axes to be removed. If one of those axes has length larger than 1, an error is thrown. If not specified, all axes of length 1 get removed.

    Returns:

      A new NDCube instance with the removed axes.

    Return type:

      `NDCube`

  to(new_unit, **kwargs)

    Convert instance to another unit.

    Converts the data, uncertainty and unit and returns a new instance with other attributes unchanged.

    Parameters:

      - new_unit (`astropy.units.Unit`) – The unit to convert to.

      - kwargs – Passed to the unit conversion method, self.unit.to.

    Returns:

      A new instance with the new unit and data and uncertainties scales accordingly.

    Return type:

      `NDCube`

  to_nddata(
    *,
    data='copy',
    wcs='copy',
    uncertainty='copy',
    mask='copy',
    unit='copy',
    meta='copy',
    psf='copy',
    nddata_type=<class 'astropy.nddata.nddata.NDData'>,
    **kwargs,
  )

    Constructs a new `NDData` instance from this object.

    By default all known `NDData` attributes are copied (by reference) from this object, values can be altered on the output object by setting a kwarg with the new value, e.g. `data=new_data`. Custom attributes on this class can be passed by setting that keyword to `"copy"`, for example `mycube.to_nddata(spam="copy")` is the equivalent of setting `mycube.to_nddata(spam=mycube.spam)`.

    A motivating use case for this method is in enabling arithmetic operations between `NDCube` instances by removing coordinate-awareness. See the section of the ndcube documentation on Arithmetic Operations.

    Parameters:

      - data (array-like, optional) – Data array of new instance. Default is to use data of this instance.

      - wcs (`astropy.wcs.wcsapi.BaseLowLevelWCS`, `astropy.wcs.wcsapi.BaseHighLevelWCS`, optional) – WCS object of new instance. Default is to use data of this instance.

      - uncertainty (Any, optional) – Uncertainy object of new instance. Default is to use data of this instance.

      - mask (Any, optional) – Mask object of new instance. Default is to use data of this instance.

      - unit (Any, optional) – Unit of new instance. Default is to use data of this instance.

      - meta (dict-like, optional) – Metadata object of new instance. Default is to use data of this instance.

      - psf (Any, optional) – PSF object of new instance. Default is to use data of this instance.

      - nddata_type (Any, optional) – The type of the returned object. Must be a subclass of `NDData` or a class that behaves like one. Default=`~astropy.nddata.NDData`.

      - kwargs – Additional inputs to the `nddata_type` constructor. For example, to set different data values on the returned object, set a kwarg `data=new_data`, where `new_data` is an array of compatible shape and dtype. Other keyword arguments can be specified to copy custom attributes with the value `"copy"`, for example `global_coords="copy"`.

    Returns:

      new_nddata – The new instance of class given by `nddata_type` with the same attribute values as this `NDCube` instance, except for any alterations specified by the kwargs.

    Return type:

      Any

    Examples

    To create an `NDData` instance which is a copy of an `NDCube` (called `cube`) without a WCS, do:

        >>> nddata_without_coords = cube.to_nddata(wcs=None)
        >>> nddata_without_coords
        NDData([[——, ——, ——],
                [13, 14, 15]])

    To create a new `NDCube` instance which is a copy of an `NDCube` (called `cube`) without an uncertainty, but with `global_coords` and `extra_coords` do:

        >>> ndcube_without_uncertainty = cube.to_nddata(
        ...     uncertainty=None,
        ...     global_coords="copy",
        ...     extra_coords="copy",
        ...     nddata_type=NDCube,
        ...     )
        >>> ndcube_without_uncertainty
        <ndcube.ndcube.NDCube object at ...>
        NDCube
        ------
        Shape: (2, 3)
        Physical Types of Axes: [('custom:pos.helioprojective.lat', 'custom:pos.helioprojective.lon'), ('custom:pos.helioprojective.lat', 'custom:pos.helioprojective.lon')]
        Unit: None
        ...

    To create a different type of `NDData` object do:

        >>> from astropy.nddata import NDDataRef
        >>> nddataref = cube.to_nddata(wcs=None, nddata_type=NDDataRef)
        >>> nddataref
        NDDataRef([[——, ——, ——],
                   [13, 14, 15]])

    The value of any input supported by the `nddata_type`’s constructor can be altered by setting a kwarg for that input, e.g.:

        >>> nddata_ones = cube.to_nddata(data=np.ones(cube.data.shape))
        >>> nddata_ones.data
        array([[1., 1., 1.],
               [1., 1., 1.]])