          Provides a Python interface to the CXC region library

The CXC region library is used by the CXC datamodel to perform 2D filtering using various geometric shapes (circle, box, polygon, ellipse, etc.). It also provides information about the area and extent of regions which may be combined together using logical AND and OR operators, ie region Union and Intersection.

The region module is imported in the following ways

from region import * import region

The CXCRegion object is used to represent a region. A typical example may be to load a region from a ds9 region file:

&pr; from region import * &pr; my_region = CXCRegion("region(ds9.reg)")

The argument to the CXCRegion constructor can be any valid region string

&pr; my_region = CXCRegion("circle(4096,4096,100)") &pr; my_region = CXCRegion("circle(4096,4096,100)-box(4096,4096,10)") &pr; my_region = CXCRegion("region(ds9.reg)") &pr; my_region = CXCRegion("bounds(region(ds9.reg))")

Since using region files is so common, users can also omit the "region()" and just use the region file name directly

&pr; my_region = CXCRegion("ds9.reg")

Users can also create an empty region (no shapes)

&pr; my_region = CXCRegion()

There are two additional special construction methods. The CXC Datamodel stores any spatial filter which were used in the output file's data subspace. This information is available using dmlist

unix% dmlist img.fits subspace ... --- Component 1 --- 1 sky Real8 Polygon(3532.07,3282.84,3574.06,3282.75,4517.64, 3668.84,4517.71,3668.9,4517.7,3711.97,4131.65,4655.62, 4131.56,4655.62,4089.8,4655.62,3146.11,4269.78,3146.08, 4269.63,3146.08,4226.56,3531.94,3282.93,3532.07,3282.84) 1 sky Real8 Field area = 1.88513e+06 Region area = 1.1546e+06 ...

but can be difficult to parse, especially for complex filters. The CXCRegion object can obtain the region directly from the file's subspace using the file name and the column name such as

>>> my_subspace=CXCRegion("img.fits","sky") >>> print(my_subspace) polygon(3532.07,3282.84,3574.06,3282.75,4517.64,3668.84,4517.71,3668.9, 4517.7,3711.97,4131.65,4655.62,4131.56,4655.62,4089.8,4655.62,3146.11, 4269.78,3146.08,4269.63,3146.08,4226.56,3531.94,3282.93,3532.07,3282.84)

Users can also use individual Shape objects which is discussed later in this document.

Users can also create CXCRegion objects using the following convenience functions

&pr; myreg = annulus(x,y,inner,outer) &pr; myreg = box(x,y,xlen,ylen) &pr; myreg = box(x,y,xlen,ylen,rotang) &pr; myreg = circle(x,y,r) &pr; myreg = ellipse(x,y,r1,r2) &pr; myreg = ellipse(x,y,r1,r2,rotang) &pr; myreg = field() &pr; myreg = pie(x,y,inner,outer,start,stop) &pr; myreg = point(x,y) &pr; myreg = polygon(x1,y1,x2,y2,x3,y3,...) &pr; myreg = polygon(x_array,y_array) &pr; myreg = rectangle(llx,lly,urx,ury) &pr; myreg = rotbox(x,y,xlen,ylen,rotang) &pr; myreg = sector(x,y,start,stop)

where (x,y) are the center of the shape, rotang & start & stop are all angles measured in degrees from the +X axis.

Note that the region module does not have any intrinsic knowledge of WCS coordinates, so cannot be directly used to match pointed Chandra observations to specific regions. The dmcoords tool can be useful when converting between different Chandra coordinate systems.

Each CXCRegion object has the following methods: area, edit, extent, is_inside, and write.

Computes the area of the region. If the region is simple, then it will compute the analytic area. However, if the region is complex, then it will pixelate the region and compute the area that way.

&pr; a = circle(10,10,100) &pr; a.area() 31415.926535897932 &pr; a.area(pixel=True) 31417.0 &pr; a.area(pixel=True,bin=0.1) 31415.45

The extent of the region is given by the lower left corner location (x0,y0) and the upper right corner location (x1,y1)

&pr; a.extent() {'y1': 110.0, 'y0': -90.0, 'x0': -90.0, 'x1': 110.0}

The is_inside routine checks to see if the x,y pair is located within the region

&pr; a.is_inside( 1,1) True &pr; a.is_inside( -100,-100) False

The edit method allows the user to shift all the x,y locations (dx and dy parameters), scale all the radii (stretch parameter), pad all the radii (pad parameter), and rotate (rotate parameter) the shapes in the region. A single shape within the region can be edited using the index parameter.

Note: edit does not modify the current region. It returns a new CXCRegion object with the modified shape parameters.

&pr; a.edit( dx=-10 ) circle(0,10,100) &pr; a.edit( dy=-10 ) circle(10,0,100) &pr; a.edit( pad=-30) circle(10,10,70) &pr; a.edit( stretch=1.5) circle(10,10,150) &pr; a.edit(rotate=45) circle(10,10,100) &pr; a.edit(index=0,stretch=2) circle(10,10,200)

A CXCRegion can be written to either an ASCII region file or to a FITS region file.

&pr; a.write("ciao.reg") &pr; a.write("ciao.fits", fits=True) &pr; a.write("ciao.reg", clobber=True)

&pr; b=a.edit( dx=-10, dy=-10 ) &pr; c=b-a &pr; c.write("ds9.reg", newline=True)

The CXCRegion objects can be manipulated using mathematical (ie logical) operators: * and & (intersection), + and | (union), ~ (negation), - (same as *~), and ^ (xor). Regions can also be tested for equality using ==.

&pr; a=circle(10,10,20) &pr; b=box(10,10,30,30) &pr; c1 = a+b &pr; c2 = a*b &pr; c3 = b-a &pr; print(c3) box(10,10,30,30)*!circle(10,10,20) &pr; c4 = a^b &pr; print(c4) circle(10,10,20)*!box(10,10,30,30)+box(10,10,30,30)*!circle(10,10,20) &pr; c5 = a|b &pr; c6 = a&b &pr; c1 == c5 True &pr; c1 is c5 False

CXCRegion objects also behave like lists. They support list indexing, and testing for membership. Note that slicing a CXCRegion object creates a new CXCRegion object. Remember, even a region with only 1 shape is still a region.

&pr; new_a = c1[0] &pr; a in c1 True &pr; c1.index(a) [0] &pr; new_a == a True &pr; c4[2:] box(10,10,30,30)+circle(10,10,20)

Note that when a slice contains multiple shapes, they are always "included" and they are always or'ed ("+") together.

Users can access the individual shapes and their properties using the via the CXCRegion().shapes property. This returns a python list of Shape objects which provides access to each shape in the region.

&pr; a=circle(10,10,20) &pr; b=box(10,10,30,30) &pr; c = a+b &pr; z = c[0] &pr; type(z) <class 'region.cxcregion.CXCRegion'> &pr; c.shapes [<region.shape.Circle object at 0x7f21b726ff50>, <region.shape.Box object at 0x7f21b726ffd0>]

With access to the individual shapes, users then have access to its properties: name, xpoints, ypoints, radii, angles, component number, include flag, and logic operator.

&pr; q = c.shapes[0] &pr; print(q) circle(10,10,20) &pr; q.xpoints array([ 10.]) &pr; q.ypoints array([ 10.]) &pr; q.radii array([ 20.]) &pr; q.angles &pr; q.component 1L &pr; q.include ShapeInclusion(val=1, str='') &pr; q.logic ShapeOperation(val=1, str='')

The component value and logic operation are related. All shapes with the same component value are intersected, and different components are unioned.

The Shape object properties are immutable. However, users can create a new CXCRegion object using an existing Shape object which can then be modified using the edit() method.

&pr; new_q = CXCRegion( q ) &pr; new_q = new_q.edit(dx=10,dy=20,stretch=0.5) &pr; new_q circle(20,30,10)

See the bugs page for the region library on the CIAO website for an up-to-date listing of known bugs.

February 2018