Pixel Filtering Specification

When supplying the name of an input FITS image to a task, a pixel filter specifier may be appended to the file name to modify the pixel values in an image. The pixel filter consists of a mathematical expression that is applied to the pixel values in the input image to create a virtual FITS image (usually in memory) that is then opened by the task. The input file itself remains unchanged.

Any other extension specifiers, or any row, column, binning or image subsection filters in the input file name expression will be evaluated first before the pixel filter is applied, as illustrated in the 'Combined Filtering' section, below.

Pixel Filter Syntax

The pixel filter specifier is enclosed is square brackets and begins with the keyword 'pix', followed by a mathematical expression where the symbol 'X' is used to represent the input pixel value. The expression is evaluated for each pixel in the input image and the result is written to the virtual image. For example,

        file.fits[EXP3][pix sqrt(X)]
means "move to the EXP3 image extension, then construct a virtual image where each pixel is the square root of the value in the corresponding input pixel".

One can also create a text file containing the mathematical expression, and then import it into the pixel filter expression with this syntax:

        file.fits[EXP3][pix @file.txt]
where 'file.txt' is the name of the text file. The mathematical expression may extend over multiple lines in the text file.

By default the created virtual image will have the same data type as the input image. This default data type may be overridden by appending a code letter to the 'pix' keyword as follows:

	b :  8-bit unsigned byte
	i : 16-bit signed integer
	j : 32-bit signed integer
	r : 32-bit floating point
	d : 64-bit double precision
For example,

        image.fits[pixi X * 100]
means create a 16-bit integer virtual image in which the pixel values are equal to the corresponding pixel in the FITS primary array multiplied by 100.

Also by default, any other HDUs in the input FITS file, in addition to the image that is being modified, are copied verbatim to the virtual FITS file. Thus if the pixel filter is applied to the primary array of a FITS file that also has 4 extensions, then all those extensions will be copied to the virtual FITS file. To override this behavior, append the digit '1' to the 'pix' keyword (and following any optional data type character, if present). In the following examples,

        image.fits[EXP3][pix1 X]
	image.fits[EXP3][pixr1 X]
the image that is in the EXP3 extension of the input file is copied into the primary array of the virtual FITS file, and none of the other extensions are copied.

The expression may consist of any sequence of mathematical operations that are to be applied to the input pixel value. Besides the four basic arithmetic operators (+, - , *, and /), most other common mathematical functions are supported, such as ABS, SIN, EXP, SQRT, etc. Refer to the calc_express. help file for a complete list of supported functions and their syntax.

Conditional expressions are supported using the "EXP?A:B" syntax, where EXP is a logical expression. If it evaluates to TRUE, then the A expression is evaluated, else if EXP evaluates to FALSE than the B expression evaluated. For example,

        image.fits[pix X>0?X:0]
will test if the input pixel value is greater than zero, and if so, will copy the pixel value to the virtual image, otherwise it will set the virtual image pixel equal to zero.

Relative Pixel Offsets

In simple cases, the mathematical expression for the value of the virtual pixel is only a function of the corresponding input image pixel, X. It is possible, however, for the expression to depend on the value of other pixels in the image with a specified relative offset from the current pixel that is being evaluated. The pixel offset is given in curly brackets, as in this example:

        image.fits[pix (X{-1} + X + X{+1}) / 3.]
which creates a virtual image where each pixel is equal to the running mean of the preceeding and following pixels in the input image. Note that this effectively treats the input image as a 1 dimensional vector of pixels, regardless of the true dimensionality of the image. In the case of a 2 dimensional image, the offset will 'wrap around' to the following or preceeding line of the image if it extends beyond the width of the image (as given by the NAXIS1 keyword value). If the offset extends completely off the beginning or end of the image, then the pixel will be set to the appropriate FITS null value.

The expression may also be a function of the value of keywords in the image header. In this case the keyword name is preceeded by a '#' pound sign, as shown in this example:

        image.fits[pix X / #EXPOSURE]
which divides the input image pixel values by the value of the EXPOSURE keyword.

This keyword mechanism can be used to specify pixel offsets in higher dimensions. For example, the following rather complex looking expression will create a smoothed virtual image where each pixel is a 3 x 3 boxcar average of the input image pixels:

        image.fits[pix (X + X{-1} + X{+1} 
	           + X{-#NAXIS1} + X{-#NAXIS1 - 1} + X{-#NAXIS1 + 1}
	           + X{#NAXIS1} + X{#NAXIS1 - 1} + X{#NAXIS1 + 1}) / 9.]

Combined Filtering

The pixel filtering specifier can be combined with other CFITSIO filters which will operate on the input FITS file in sequence. For example:
	file.fits[events][pi < 100][bin (X,Y) = 1:500:10][pixr 1 + X / 3]
will first create a virtual table containing only the rows that have a PI column value less than 100, which will be used to create a virtual image by binning the X and Y columns. That image will then have the pixel filter applied.


	[pix (X{-1} + X + X{1}) / 3]
		smooth a 1-d vector

        ftstat a.img[pix X==0 ? #null : X]
		find image statistics (using the ftstat task) ignoring zeros

        [pix1 sqrt(X)]
		create a noise estimate of an image


filenames, colfilter, rowfilter, binfilter, imfilter. calc_express.