AHELP for CIAO 4.12

# ciao_smooth

Context: contrib

## Synopsis

Simple smoothing routines for 2D data

## Syntax

```Load the module:
from ciao_contrib.smooth import *

Routines:
smoothed = gsmooth(image, sigma, nsigma=5)
smoothed = fsmooth(image, filename, norm=True, origin=None)
smoothed = ismooth(image, kernel, norm=True, origin=None)

where image is a 2D numpy array (which can contain NaN values)```

## Description

The ciao_contrib.smooth module provides several routines to smooth (or convolve) 2D data, and is provided as part of the CIAO contributed scripts package.

The module can be loaded into Sherpa or a Python program by saying:

```from ciao_contrib.smooth import *
```

### Gaussian smoothing

The gsmooth() routine smoothes an image with a gaussian with a given sigma (in pixels) and using a box with half-width equal to

`sigma * nsigma`

The default value for nsigma is 5.

### Top-hat smoothing

The tsmooth() routine smoothes an image with a top-hat filter of the given radius. This is a circular kernel which is flat within the radius and zero outside it. The radius is treated as an integer value here.

### Box-car smoothing

The bsmooth() routine smoothes an image with a box-car filter of the given radius. This is a square kernel with a constant value for all pixels. The radius is treated as an integer value here.

### Smothing by an image

The ismooth() routine will smooth an image by a kernel image. The default behavior is to normalize the kernel by its sum before smoothing; to use the input kernel values directly set the norm parameter to True. The kernel is assumed to be centered; to use a different center use the origin argument which accepts a pair (y,x), giving the pixel location of the origin. This location uses 0-indexing, so the center of a nx=5 by ny=3 array would be (1,2). Any non-finite values in the kernel image are replaced by 0.

### Smothing by a file

The fsmooth() routine is similar to the ismooth() routine; the difference being that instead of an image the input is the name of a file containing the image to use as the smoothing kernel.

## Examples

### Example 1

```sherpa> from ciao_contrib.smooth import *
sherpa> img = copy_piximgvals(cr)
sherpa> simg = gsmooth(img, 3)
sherpa> import maplotlib.pyplot as plt
sherpa> plt.imshow(simg, origin='lower')```

Here we smooth the data in img.fits with a gaussian using a sigma of 3 pixels before displaying it using the Matplotlib imshow routine.

### Example 2

```sherpa> cr = read_file("img.fits")
sherpa> img = copy_piximgvals(cr)
sherpa> set_piximgvals(cr, gsmooth(img, 3))```

This is the same as the previous example except that we store the smoothed image back into the Crate.

### Example 3

```sherpa> cr = read_file("img.fits")
sherpa> img = copy_piximgvals(cr)
sherpa> simg = gsmooth(img, 3)
sherpa> set_piximgvals(cr, np.arcsinh(simg))```

Here the smoothed image is scaled using the "arcsinh" function before it is added back to the Crate. See the scale_image_crate routine for more information on this scaling.

### Example 4

```sherpa> cr = read_file("img.fits")
sherpa> img = copy_piximgvals(cr)
sherpa> import matplotlib.pyplot as plt
sherpa> plt.subplot(2, 2, 1)
sherpa> plt.imshow(img, origin='lower')
sherpa> plt.subplot(2, 2, 2)
sherpa> plt.imshow(gsmooth(img, 5), origin='lower')
sherpa> plt.subplot(2, 2, 3)
sherpa> plt.imshow(bsmooth(img, 5), origin='lower')
sherpa> plt.subplot(2, 2, 4)
sherpa> plt.imshow(tsmooth(img, 5), origin='lower')```

Here we compare the original image to gaussian, box-car, and top-hat smoothed versions in a two-by-two plot.

### Example 5

```sherpa> cr1 = read_file("img.fits")
sherpa> img = copy_piximgvals(cr1)
sherpa> kern = copy_piximgvals(cr2)
sherpa> sm = ismooth(img, kern)```

Here we smooth an image ("img.fits") using another image ("psf.fits"). The kernel is assumed to be centered in the image in psf.fits. See the following example for another way of performing this task.

### Example 6

```sherpa> cr1 = read_file("img.fits")
sherpa> img = copy_piximgvals(cr1)
sherpa> sm = fsmooth(img, "psf.fits")```

Here we smooth an image ("img.fits") using another image ("psf.fits"). The kernel is assumed to be centered in the image in psf.fits. See the preceeding example for another way of performing this task.

### Example 7

```sherpa> ivals = np.asarray([0,0,0,0,0,1,1,0,0,1,1,0,0,0,0,0])
sherpa> ivals.resize(4,4)
sherpa> kvals = np.asarray([0,0,0,1,1,1,0,0,0]).reshape(3,3)
sherpa> svals = ismooth(ivals, kvals)```

Here we create two 2D arrays (the "image" with a size of 4 by 4 and the "kernel" with a size of 3 by 3) and smooth ivals by kvals. Although both arrays are square they do not need to be; the kernel should have odd dimensionality and be centered in the array to avoid the possibility of a coordinate shift in the output image.

The input arrays are:

```sherpa> print(ivals)
[[0 0 0 0]
[0 1 1 0]
[0 1 1 0]
[0 0 0 0]]
sherpa> print(kvals)
[[ 0.  0.  0.]
[ 1.  1.  1.]
[ 0.  0.  0.]]
```

and the result is:

```sherpa> print(svals)
[[ 0.          0.          0.          0.        ]
[ 0.33333333  0.66666667  0.66666667  0.33333333]
[ 0.33333333  0.66666667  0.66666667  0.33333333]
[ 0.          0.          0.          0.        ]]
```

### Example 8

```sherpa> ivals = np.asarray([0,0,0,0,0,1,1,0,0,1,1,0,0,0,0,0])
sherpa> ivals.resize(4,4)
sherpa> kvals = np.asarray([0,0,0,1,1,1,0,0,0]).reshape(3,3)
sherpa> svals = ismooth(ivals, kvals, norm=False)```

By setting the norm parameter to False the kernel image is not normalized before smoothing, which creates an output image of:

```sherpa> print(svals)
[[ 0.  0.  0.  0.]
[ 1.  2.  2.  1.]
[ 1.  2.  2.  1.]
[ 0.  0.  0.  0.]]
```

### Example 9

```sherpa> ivals = np.asarray([0,0,0,0,0,1,1,0,0,1,1,0,0,0,0,0])
sherpa> ivals.resize(4,4)
sherpa> kvals = np.asarray([0,0,0,0,0,0,0,1,0]).reshape(3,3)
sherpa> svals1 = ismooth(ivals, kvals)
sherpa> svals2 = ismooth(ivals, kvals, origin=(2,1))```

In this example we show how the origin parameter of the smooth routine is used by creating a kernel where only a single pixel set, but this pixel is off-set from the center of the kernel:

```sherpa> print(kvals)
[[0 0 0]
[0 0 0]
[0 1 0]]
```

When used with the default origin setting, the result is a shifted output (svals1), as shown below:

```sherpa> print(svals1)
[[ 0.  0.  0.  0.]
[ 0.  0.  0.  0.]
[ 0.  1.  1.  0.]
[ 0.  1.  1.  0.]]
```

By changing the origin to the peak position of the kernel, the output is no-longer shifted with respect to the input image.

```sherpa> print(svals2)
[[ 0.  0.  0.  0.]
[ 0.  1.  1.  0.]
[ 0.  1.  1.  0.]
[ 0.  0.  0.  0.]]
```

### Dealing with NaN/Inf values

Since the smoothing is performed using a Fast Fourier Transform (FFT), any pixels with a non-finite value (such as NaN or Inf) are set to 0. On output these pixels are set to NaN values.

### Identity transforms

If the scale parameter (radius or sigma) is set to 0 for gsmooth(), bsmooth() or tsmooth() then the smoothing function is set to a 1 by 1 image - i.e. the identity transform. Since the smoothing is done via a FFT the output image in this case will be very-close, but not identical, to the input image.

## Bugs

See the bugs pages for an up-to-date listing of known bugs.

Refer to the CIAO bug pages for an up-to-date listing of known issues.