Module shapes

This module defines a class for drawing shapes that define an area in your image. The drawing is interactive using mouse- and keyboard buttons. For each defined area the module maputils calculates the sum of the intensities, the area and some other properties of the data. The shapes are one of polygon, ellipse, circle, rectangle or spline.

The strength of this module is that it duplicates a shape to other selected images using transformations to world coordinates. This enables one to compare e.g. flux in two images with different WCS systems. It works with spatial maps and maps with mixed axes (e.g. position-velocity maps) and maps with linear axes. The order of the two axes in a map can be swapped.

class kapteyn.shapes.Shapecollection(images, ifigure, wcs=True, inputfilename=None, inputwcs=False, gipsy=False)[source]

Administration class for a collection of shapes. The figure

  • images (A list of objects from class maputils.Annotatedimage) – In each image a shape can be drawn using mouse- and keyboard buttons. This shape is duplicated either in pixel coordinates or world coordinates in the other images of the list with images. These images have two attributes that are relevant for this module. These are fluxfie to define how the flux should be calculated using fixed variables s for the sum of the intensities of the pixels in an area and a which represents the area.
  • ifigure (Matplotlib Figure object) – The Matplotlib figure where the images are.
  • wcs (Boolean) – The default is True which implies that in case of multiple images shapes propagate through world coordinates. If you have images with the same size and WCS, then set wcs=False to duplicate shapes in pixel coordinates which is much faster.
  • inputfilename (String) – Name of file on disk which stores shape information. The objects are read from this file and plotted on all the images in the image list. The coordinates in the file can be either pixel- or world coordinates. You should specify that with parameter inputwcs
  • inputwcs (Boolean) – Set the shape mode for shapes from file to either pixels coordinates (inputwcs=False) or to world coordinates (inputwcs=True).

This shape interactor reacts to the following keyboard and mouse buttons:

mouse - left  :  Drag a polygon point to a new position or
                 change the radius of a circle or
                 change the minor axis of an ellipse or
                 change the major axis and position angle of an ellipse
mouse - middle:  Select an existing object in any frame
key   - a     :  Add a point to a polygon or spline
key   - c     :  Copy current object at mouse cursor
key   - d     :  Delete a point in a polygon or spline
key   - e     :  Erase active object and associated objects in other images
key   - i     :  Insert a point in a polygon or spline
key   - n     :  Start with a new object
key   - u     :  Toggle markers. Usually for a hardcopy
                 one does not want to show the markers of a shape.
key   - w     :  Write object data in current image to file on disk
key   - r     :  Read objects from file for current image
key   - [     :  Next active object in current shape selection
key   - ]     :  Previous active object in current shape selection

Interactive navigation defined by canvas
Amongst others:
key   - f     :  Toggle fullscreen
key   - g     :  Toggle grid

Gui buttons:
'Quit'         :  Abort program
'plot result'  :  Plot calculated flux as function of shape and image
'Save result'  :  Save flux information to disk
                  The file names are generated and contain date
                  and time stamp (e.g flux_24042010_212029.dat)
'Pol.'         :  Select shape polygon. Start with key 'n' for
                  new polygon. Add new points with key 'a'.
'Ell.'         :  Select shape ellipse. Start with key 'n' for
                  new ellipse. With left mouse button Drag major axis to change
                  size and rotation or, using a point near the
                  center, drag entire ellipse to a new position.
'Cir.:'        :  Select shape circle. Start with key 'n' for
                  new circle. The radius can be changed by dragging
                  an arbitrary point on the border to a new position.
'Rec.'         :  Select shape rectangle. Start with key 'n' for
                  new rectangle. Drag any of the four edges to resize
                  the rectangle.
'Spl.'         :  Like the polygon but the points between two knots
                  follow a spline curve.

All shapes are derived from a polygon class. There is one method that generates coordinates for all shapes and kapteyn.maputils.getflux() uses the same routine to calculate whether a pixel in an enclosing box is within or outside the shape. For circles and ellipses the number of polygon points is 360 and this slows down the calculation significantly. Methods which assume a perfect circle or ellipse can handle the inside/outside problem much faster, but note that due to different WCS’s, ellipses and circles don’t keep their shape in other images. So in fact only a polygon is the common shape. A spline is a polygon with an artificially increased number of points.

fig = plt.figure(figsize=(12,10))
frame1 = fig.add_axes([0.07,0.1,0.35, 0.8])
frame2 = fig.add_axes([0.5,0.1,0.43, 0.8])
im1 = f1.Annotatedimage(frame1)
im2 = f2.Annotatedimage(frame2)
im1.Image(); im1.Graticule()
im2.Image(); im2.Graticule()
im1.interact_imagecolors(); im1.interact_toolbarinfo()
im2.interact_imagecolors(); im2.interact_toolbarinfo()
im1.plot(); im2.plot()
im1.fluxfie = lambda s, a: s/a
im2.fluxfie = lambda s, a: s/a
im1.pixelstep = 0.5; im2.pixelstep = 0.5
images = [im1, im2]
shapes = shapes.Shapecollection(images, fig, wcs=True, inputwcs=True)

Utility functions

kapteyn.shapes.ellipsesamples(xc, yc, major, minor, pa, n)[source]

Get sample positions on ellipse Algorithm from ‘Mathematical Elements for Computer Graphics’ by Rogers and Adams, section about ‘Parametric Representation of an Ellipse’ Many methods which calculate sample positions on an ellipse suffer from a reasonable sampling near the positions where the curvature of an ellipse is large. The method we use, finds more sample points near the end points of an ellipse where the curvature is large while the increment between sample points along the sides of the ellipse where the curvature is not large, is small

For an ellipse centered at (0,0), semimajor axis a and semiminor axis b the parametric representation is given by:

x = a * cos(th)
y = b * sin(th)

‘th’ is the parameter and it represents the angle between 0 and 2*pi One can derive a recursive relation:

x_i+1 =       x_i cos(dth) - (a/b) y_i sin(dth)
y_i+1 = (b/a) x_i sin(dth) +       y_i cos(dth)

dth is a step size in the angle th. It is equal to 2*pi/(n-1) n-1 is the required number or unique points on the ellipse and therefore an input parameter. The routine returns a result which is empty when either a or b is zero.

The shift of the origin and the rotation of the ellipse can be combined into one matrix:

         | cos(a)     sin (a)    0 | | 1  0  0 |
T =      |-sin(a)     cos (a)    0 | | 0  1  0 |
         |     0           0     1 | | xc yc 1 |

Finally the result is computed with:

X, Y, dummy = (x, y, 1).T

The result is a polygon which describes the maximum inscribed area for the given ellipse parameters (Smith, L.B., “Drawing Ellipses, Hyperbolas, or Parabolas With a Fixed Number of Points and Maximum Inscribed Area,” Comp. J., Vol. 14, pp. 81-86, 1969

  • xc (float) – Center position of ellipse in x direction
  • yc (float) – Center position of ellipse in y direction
  • major (float) – Semi major axis in pixels
  • minor (float) – Semi minor axis in pixels
  • pa (float) – Position angle in degrees
  • n (int) – Number of sample points

The ‘classical’ method involves the calculation of many cosine and sine functions. This method avoids that by using a method which calculates a new sample based on the information of a previous sample. However, we didn’t find a way to do this properly using NumPy. The classic method is very suitable to do implement in NumPy and is therefore faster than the algorithm here. But the sampling is better and we can do with less samples to get the same result.