Create a linear 2D transformation for the axes of an image
tr = imextent(img, xlo, xhi, ylo, yhi, limits='center') The limits argument can be either 'center' or 'edge'. from crates_contrib.images import imextent
The imextent routine creates a 2D linear transform object - offset and scale changes only - that can be used to convert between logical and physical coordinate systems (the SimpleCoordTransform class in the crates_contrib.utils module may also be of use for this).
It is similar to the extent argument of Matplotlib's imshow function, in that it defines the physical extent of an image, but returns a transform object that can be used to calculate coordinates.
The imextent routine has 5 required arguments - img, xlo, xhi, ylo, yhi - and one optional argument, limits. The img argument should be the image being transformed, as a NumPy array (the shape field is used to find the number of pixels in both axes), whereas the *lo/hi arguments give the minimum and maximum coordinate values for the image along the two axes. The limits argument determines how these limits are used, as described below.
Here we create a transform for a 30 (x) by 20 (y) pixel image with an X axis going from 0 to 1.5 and Y axis from 0 to 1:
>>> img = np.ones((20, 30)) >>> tr1 = imextent(img, 0, 1.5, 0, 1) >>> tr2 = imextent(img, 0, 1.5, 0, 1, limits='edge')
How the limits are calculated
The default setting of limits='center' means that the *lo/hi values refer to the center of the first and last pixel along each axis. So, for the tr1 transform, the bottom-left pixel of the image is centered at (0, 0) and the top-right pixel is centered at (1.5, 1). Since in this example the pixels are square with a width of 0.05, the bottom-left corner of the image is at (-0.05, -0.05) and the top-right corner is at (1.525, 1.025).
When limits='edge', the *lo/hi values refer to the start and end edges of the pixels. So for the tr2 transform, the bottom-left corner of the image is at (0,0) and the top-right corner is at (1.5, 1). This means that the center of the first (bottom left) pixel is at (0.025, 0.025) and the center of the last (top right) pixel is (1.475, 0.975).
>>> yi, xi = np.mgrid[10:20:20j, 40:60:40j] >>> zi = 100.0 / np.sqrt((xi-45.62)**2 + (yi- 14.7)**2) >>> tr = imextent(zi, 40, 60, 10, 20)
Here we create an image - zi - which has it's peak at x=45.62 and y=14.7 - and is evaluated on a grid that has 40 points along x=40 to 60 and 20 along y=10 to 20 (see the NumPy documentation for mgrid for more information).
Here we use the transform object returned by imextent to convert between physical and logical (i.e. pixel) coordinates. First we convert the pixel coordinates (1,1) and (40,20) to physical coordinates via the apply() method; by construction we would expect these to map to (40,10) and (60,20) given the arguments to the imextent call. Note that here we use the FITS definition for the logical coordinate system: (1,1) refers to the center of the bottom-left pixel.
>>> print(tr.apply([[1,1], [40,20]])) [[40 10] [60 20]]
We can also use the transform object to convert from physical to pixel coortinates by using the invert() method; here we use it to find the pixel location of the peak of the image, which has physical coordinates of (45.62,14.7).
>>> pix = tr.invert([[45.62, 14.7]]) >>> print(pix) [ 11.959 9.93 ]
Lists of lists
Note that the transform object expects a list of lists as input, and returns the same, hence the use of "[[45.62, 14.7]]" and pix/pix above.
Changes in the June 2012 Release
The imextent routine is new in this release.
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.