# Slicing and Indexing NDData#

## Introduction#

This page only deals with peculiarities that apply to
`NDData`

-like classes. For a tutorial about slicing/indexing see the
python documentation
and numpy documentation.

## Slicing NDDataRef#

Unlike `NDData`

the class `NDDataRef`

implements slicing or indexing. The result will be wrapped inside the same
class as the sliced object.

Getting one element:

```
>>> import numpy as np
>>> from astropy.nddata import NDDataRef
>>> data = np.array([1, 2, 3, 4])
>>> ndd = NDDataRef(data)
>>> ndd[1]
NDDataRef(2)
```

Getting a sliced portion of the original:

```
>>> ndd[1:3] # Get element 1 (inclusive) to 3 (exclusive)
NDDataRef([2, 3])
```

This will return a reference (and as such **not a copy**) of the original
properties, so changing a slice will affect the original:

```
>>> ndd_sliced = ndd[1:3]
>>> ndd_sliced.data[0] = 5
>>> ndd_sliced
NDDataRef([5, 3])
>>> ndd
NDDataRef([1, 5, 3, 4])
```

But only the one element that was indexed is affected (for example,
`ndd_sliced = ndd[1]`

). The element is a scalar and changes will not
propagate to the original.

## Slicing NDDataRef Including Attributes#

In the case that a `mask`

, or `uncertainty`

is present, this
attribute will be sliced too:

```
>>> from astropy.nddata import StdDevUncertainty
>>> data = np.array([1, 2, 3, 4])
>>> mask = data > 2
>>> uncertainty = StdDevUncertainty(np.sqrt(data))
>>> ndd = NDDataRef(data, mask=mask, uncertainty=uncertainty)
>>> ndd_sliced = ndd[1:3]
>>> ndd_sliced.data
array([2, 3])
>>> ndd_sliced.mask
array([False, True]...)
>>> ndd_sliced.uncertainty
StdDevUncertainty([1.41421356, 1.73205081])
```

`unit`

and `meta`

, however, will be unaffected.

If any of the attributes are set but do not implement slicing, an info will be printed and the property will be kept as is:

```
>>> data = np.array([1, 2, 3, 4])
>>> mask = False
>>> uncertainty = StdDevUncertainty(0)
>>> ndd = NDDataRef(data, mask=mask, uncertainty=uncertainty)
>>> ndd_sliced = ndd[1:3]
INFO: uncertainty cannot be sliced. [astropy.nddata.mixins.ndslicing]
INFO: mask cannot be sliced. [astropy.nddata.mixins.ndslicing]
>>> ndd_sliced.mask
False
```

### Slicing NDData with World Coordinates#

If `wcs`

is set, it must be either implement
`BaseLowLevelWCS`

or `BaseHighLevelWCS`

.
This means that only integer or range slices without a step are supported. So
slices like `[::10]`

or array or boolean based slices will not work.

If you want to slice an `NDData`

object called `ndd`

without the WCS you can remove the
WCS from the `NDData`

object by running:

```
>>> ndd.wcs = None
```

### Removing Masked Data#

By convention, the `mask`

attribute indicates if a point is valid or invalid.
So we are able to get all valid data points by slicing with the mask.

#### Examples#

To get all of the valid data points by slicing with the mask:

```
>>> data = np.array([[1,2,3],[4,5,6],[7,8,9]])
>>> mask = np.array([[0,1,0],[1,1,1],[0,0,1]], dtype=bool)
>>> uncertainty = StdDevUncertainty(np.sqrt(data))
>>> ndd = NDDataRef(data, mask=mask, uncertainty=uncertainty)
>>> # don't forget that ~ or you'll get the invalid points
>>> ndd_sliced = ndd[~ndd.mask]
>>> ndd_sliced
NDDataRef([1, 3, 7, 8])
>>> ndd_sliced.mask
array([False, False, False, False]...)
>>> ndd_sliced.uncertainty
StdDevUncertainty([1. , 1.73205081, 2.64575131, 2.82842712])
```

Or all invalid points:

```
>>> ndd_sliced = ndd[ndd.mask] # without the ~ now!
>>> ndd_sliced
NDDataRef([2, 4, 5, 6, 9])
>>> ndd_sliced.mask
array([ True, True, True, True, True]...)
>>> ndd_sliced.uncertainty
StdDevUncertainty([1.41421356, 2. , 2.23606798, 2.44948974, 3. ])
```

Note

The result of this kind of indexing (boolean indexing) will always be one-dimensional!