About Chandra Archive Proposer Instruments & Calibration Newsletters Data Analysis HelpDesk Calibration Database NASA Archives & Centers Chandra Science Links

Skip the navigation links
Last modified: 10 December 2007

URL: http://cxc.harvard.edu/chips4.0/gallery/intro.py.html
Hardcopy (PDF): A4 | Letter

Gallery: Introductory examples (Python)

Examples


Plot two columns from a file

In this example we show how to quickly plot two columns from a file, change the properties of the resulting curve and plot, and create a postscript version of the figure.

[ChIPS output]
Postscript version
make_figure("bcg.txt[cols z,mk]",["line.style","noline"])
set_curve(["symbol.style","square","symbol.size",2.0])

log_scale(X_AXIS)

set_plot_ylabel("m_k")

print_window("plot")

The make_figure routine creates a plot of the two columns - selected by the Data Model filter - and labels the axes and title. The line.style setting is set to noline to stop lines being drawn connecting the points.

The set_curve routine modifies the existing curve; in this case it changes the symbol to a square of size 2. There are 9 symbol styles to chose from.

The log_scale routine is used to change the scaling of the X axis. The make_figure call uses the column names as axis labels. Here we change the Y-axis label to m_k, where the underscore is used to indicate a subscript. Labels, including axis labels and plot titles, support LaTeX-like syntax for formatting the text.

Finally the print_window routine is used to create a postscript version of the visualization called plot.ps.


A radial profile drawn as a histogram

In this example we show how to draw a histogram, change the X-axis range, and create both postscript and PNG versions of the plot.

[ChIPS output]
Postscript version
make_figure("rprof.fits[cols r,sur_bri]","histogram")

log_scale(XY_AXIS)
limits(X_AXIS,1.0,AUTO)

print_window("rprof")
print_window("rprof",["format","png"])

The make_figure routine can be used to draw a histogram, by adding the optional second argument "histogram". If given two columns then it uses them as x and y values. In this case the first column, r, is a two-dimensinal array, so it is used to indicate the low and high values of each bin. The file was created by dmextract, and the columns are:

unix% dmlist "rprof.fits[cols r,sur_bri]" cols
 
--------------------------------------------------------------------------------
Columns for Table Block HISTOGRAM
--------------------------------------------------------------------------------
 
ColNo  Name                 Unit        Type             Range
   1   R[2]                 pixel        Real8(2)       -Inf:+Inf            Radius
   2   SUR_BRI              count/pixel**2 Real8          -Inf:+Inf            Net Counts per square pixel

Since the data covers a large range, we change the scale from linear to logarithmic for both axes using log_scale, and then use limits to set the minimum X value to 1 (the first bin starts at r=0).

We create postscript and PNG versions of the plot - called rprof.ps and rprof.png respectively - using print_window.


Contour an image using the WCS axes

In this example we show how to contour an image, adjust the axes to use sexagesimal notation for the labels, and create a postscript version that is US-letter sized.

[ChIPS output]
Postscript version
make_figure("a2142_smoothed.fits")

reverse_axes(X_AXIS)
set_xaxis(["tickformat","ra"])
set_yaxis(["tickformat","dec"])

set_plot(["leftmargin",0.2])

print_window("contour",["pagesize","letter","fittopage","1"])

If sent an image then make_figure will contour it. As we do not supply any levels, ChIPS uses equally-spaced values that cover the image range. The axis limits are chosen to enclose the outer contour values, not the input image. Unlike when plotting curves and histograms, make_figure does not add any axis labels for contours.

Since the image contains WCS information - as shown below by dmlist - the axes are drawn using this coordinate system. The sky coordinate contour example shows how to use a different coordinate system for the axes.

We reverse the X axis and change the tick labels to use sexagesimal notation. The left margin of the plot is shifted to make space for the declination values.

unix% dmlist a2142_smoothed.fits cols
 
--------------------------------------------------------------------------------
Columns for Image Block CONVOLVE
--------------------------------------------------------------------------------
 
ColNo  Name                 Unit        Type             Range
   1   CONVOLVE[366,366]                 Real4(366x366) -Inf:+Inf            
 
--------------------------------------------------------------------------------
Physical Axis Transforms for Image Block CONVOLVE
--------------------------------------------------------------------------------
 
Group# Axis# 
   1   1,2    sky(x) = (+3109.50) +(+4.0)* ((#1)-(+0.50))
                 (y)   (+2939.50)  (+4.0)  ((#2) (+0.50))
 
--------------------------------------------------------------------------------
World Coordinate Axis Transforms for Image Block CONVOLVE
--------------------------------------------------------------------------------
 
Group# Axis# 
   1   1,2    EQPOS(RA ) = (+239.5378)[deg] +TAN[(-0.000136667)* (sky(x)-(+4096.50))]
                   (DEC)   (+27.2755 )           (+0.000136667)  (   (y) (+4096.50)) 

The print_window routine is used to create a US-letter sized postscript plot called contour.ps, and the figure is expanded so that it fits this page size.


Two curves in a plot

In this example we show how to overlay multiple curves within a single plot and how to use the ChipsCurve object to change - or set - the appearance of a curve.

[ChIPS output]
Postscript version
make_figure("flare.fits[cols time_bin,count_rate]",["symbol.style","none"])

add_curve("flare.fits[count_rate>5][cols time_bin,count_rate]")
crv = ChipsCurve()
crv.line.style = "noline"
crv.symbol.style = "circle"
crv.symbol.size = 2.0
crv.symbol.color = "red"
set_curve(crv)

log_scale(Y_AXIS)

add_hline(5.0,["style","longdash"])

set_plot_xlabel("Time bin")
set_plot_ylabel("Count rate (s^{-1})")
set_plot_title("Background light curve")

add_label(22.0,12.0,"Cut off at 5 count s^{-1}")

In this example we use make_figure to plot the initial data - the solid line - and then add to the plot using add_curve. This is because make_figure always erases any existing plots, whereas add_curve will add the curve to an existing plot.

In this example we use the ChipsCurve object to change a number of the second curve's attributes in one call to set_curve. We could have also used the crv variable in the add_curve call by saying

add_curve("flare.fits[count_rate>5][cols time_bin,count_rate]",crv)

The add_hline() routine is used to add a horizontal line - in this case drawn with long dashes - that always extends across the whole plot, no matter what range is selected for the X axis.


Multiple histograms within a plot

In this example we show how to draw multiple histograms within a single plot and how to add annotations using lines and labels.

[ChIPS output]
Postscript version
make_figure("rprof.fits[cols r,sur_bri]","histogram")
add_histogram("rprof.n.fits[cols r,sur_bri]",["line.color","red"])
add_histogram("rprof.s.fits[cols r,sur_bri]",["line.color","green"])

log_scale(Y_AXIS)

set_plot_xlabel("Radius (pixel)")
set_plot_ylabel("Surface brightness (count pixel^{-2})")

add_line(200.0,3.0,250.0,3.0)
add_label(260.0,3.0,"All data",["valign",0.5])

add_line(200.0,2.5,250.0,2.5,["color","red"])
add_label(260.0,2.5,"Northern sector",["valign",0.5,"color","red"])

add_line(200.0,2.0,250.0,2.0,["color","green"])
add_label(260.0,2.0,"Southern sector",["valign",0.5,"color","green"])

Three datasets are plotted in this figure. The first is created using make_figure while the remaining are created using add_histogram, since make_figure() will erase any existing plots when called.

The axis labels are changed from the values created by make_figure(), and include LaTeX-like commands for formatting the text. Finally labels and lines are used to annotate the plot. The valign attribute of the labels is set to 0.5 so that they are centered vertically on the lines. Regions can also be used to help annotate plots, as shown in the Two sets of contours example.


Use the sky coordinate system to contour an image

In this example we show how to contour an image - selecting the SKY coordinate system rather than the default celestial one - and how to add a filled region, ensuring that it does not obscure the contours.

[ChIPS output]
Postscript version
make_figure("a2142_smoothed.fits",["wcs","sky"])

set_plot_xlabel("X (pixel)")
set_plot_ylabel("Y (pixel)")

xr = [3840.0,3970.0,3764.0,3647.0]
yr = [3970.0,3850.0,3641.0,3798.0]
add_region(xr,yr,["fill.visible",1,"edge.color","red","edge.style","dot","depth",50])

By setting the wcs parameter to "sky", the contour is drawn using the SKY coordinate system (the value "physical" produces the same plot).

A region is added to the plot by specifying the four corners; for general polygons the add_region routine takes two one-dimensional arrays containing the x- and y- coordinates of the vertexes respectively. Since the polygon is convex we can fill it; we also change the edge color and style to highlight the region. The depth attribute is set to 50 for the region so that it is drawn behind the contours, since they are drawn at the default depth opf 100. The plot within a plot example shows another way of changing the order objects are drawn, and the Depth Control concept document provides more information on this topic.


Placing one plot within another plot

In this example we show how to create multiple plots by placing one plot within another, find out the data range covered by a curve, switch between plots, and create a filled region.

[ChIPS output]
Postscript version
set_preference("curve.symbol.style","none")
make_figure("flare.fits[cols time,count_rate]")

set_xaxis(["majortick.mode","interval","majortick.interval",10000.0])

add_plot(0.3,0.45,0.7,0.8,["style","open"])
add_curve("flare.fits[time<1.45986e8][cols time,count_rate]")

set_xaxis(["majortick.mode","interval","majortick.interval",10000.0])

xr = get_curve_xrange()
yr = get_curve_yrange()

current_plot("plot1")

x = [xr[0], xr[1], xr[1], xr[0]]
y = [yr[0], yr[0], yr[1], yr[1]]
add_region(x,y,["fill.visible",1,"edge.style","none","fill.color","red"])

shuffle_region(chips_back)

Since we know we do not want symbols to be drawn for curves, we set the curve.symbol.style preference to none here, rather than changing the symbol.style attribute for every curve we create.

Since the time values are large, we change the tick mode of the X axis so that a major tick mark is drawn every 10^4 seconds.

To highlight the behavior in the low-count region a second plot is added within the first one. We use the add_plot routine to place the plot roughly in the center of the existing plot, and change the plot.style attribute to open to hide the display of the top and right axes. The add_curve call adds the curve to this new plot rather than the original plot, since it is the one that is current. The file name includes a Data Model filter on the time column to restrict the data being plotted.

We add a region to the first plot showing the range covered by the second plot. This is done by first finding out the data range of the second curve using the get_curve_xrange and get_curve_yrange calls. The currency is then changed back to the first plot using current_plot, and then the region is drawn using the coordinates obtained from the second plot. The region is moved so that it is drawn behind the curve by the shuffle_region call. The contour using sky coordinates example shows an alternative way of changing the order objects are drawn.

An altrnative way to create this plot would have been to read the data into Python - as in the strip chart example - and plot the array values, instead of reading the data from a file both times. In this case the calls would have looked something like:

flare = read_table("flare.fits")
t = get_colvals(flare,"TIME")
crate = get_colvals(flare,"COUNT_RATE")
add_curve(t, crate)

and

idx = numpy.where(t<1.45986e8)
add_curve(t[idx],crate[idx])

Plotting related values in a strip chart

In this example we show how to create multiple plots, read in data from a file, and place labels outside the plots.

[ChIPS output]
Postscript version
tbl = read_file("asol1.fits")
t = get_colvals(tbl,"time")
ra = get_colvals(tbl,"ra")
dec = get_colvals(tbl,"dec")
roll = get_colvals(tbl,"roll")

dt = (t - t[0])/1e3
dra = ra - get_keyval(tbl,"RA_NOM")
ddec = dec - get_keyval(tbl,"DEC_NOM")
droll = roll - get_keyval(tbl,"ROLL_NOM")

pref = ChipsPreferences()
pref.curve.symbol.style = "none"
pref.label.size = 14.0
pref.label.halign = 0.5
pref.label.angle = 270.0
set_preferences(pref)

strip_chart(3)
add_curve(dt,dra)

set_plot_title("RA, Dec, and roll variation")

cid = ChipsId()
cid.coord_sys = PLOT_NORM
add_label(cid,1.05,0.5,r"\Delta \alpha (deg)")

current_plot("plot2")
add_curve(dt,ddec)

cid = ChipsId()
cid.coord_sys = PLOT_NORM
add_label(cid,1.05,0.5,r"\Delta \delta (deg)")

current_plot("plot3")
add_curve(dt,droll)

set_plot_xlabel(r"\Delta t (ks)")
cid = ChipsId()
cid.coord_sys = PLOT_NORM
add_label(cid,1.05,0.5,r"\Delta roll (deg)")

limits(X_AXIS,10.0,20.0)
limits(Y_AXIS,AUTO,-3.5e-3)

Since the time values will be used in all three plots we read the file in once - using the read_file routine - and plot the arrays each time. The get_colvals routine gets the array data for the given column from the return value of read_file (here the variable tbl). Having read in the arrays means that we can perform some simple scaling so as to simplify the range of each plots; the time value is converted to an offset from the first value and changed from seconds to kiloseconds, and the other values are turned into offsets from the *_NOM header keyword values.

The ChipsPreference object and set_preferences call are used to set up several attribute preferences, such as no symbols for curves.

The drawing begins with the strip_chart call, which creates three vertical plots. The top plot - called "plot1" - is the current plot, so is where the dt,dra values will be drawn. A label indicating the Y axis is added to the right-hand side of the plot usng add_label. Since we want the label to appear outside the plot we use the plot normalized coordinate system to place the label to the right of the plot (x=1.05), and mid-way up it (y=0.5). The earlier preference settings ensure that the label is centered on this position (label.halign=0.5) and rotated (label.angle=270). Since the label text contains \ characters, it is preceeded by the r symbol to ensure it is interpreted correctly.

The remaining commands move to the second and third plots (plot2 and plot3 respectively), using the current_plot routine, and add data - a curve and a label - to each of them. Finally the limits of the third plot are changed to zoom in on the 10 - 20 kilosecond range, and to stop the Y axis from displaying values larger than -3.5e-3. Since the X axes of all the plots are bound together (by the strip_chart call), the change to the X axis is also reflected in the first two plots.

The make_figure call was not used in this example for two reasons:

  1. It would have created axis and plot labels that we did not want. These could have been deleted, or hidden, but it was less work to use add_curve instead.

  2. Since make_figure deletes the existing plot, the X axes would no longer have been bound together, so the change to the X axis range made in the last plot would have had to been replicated in the other plots by saying

    current_plot("all")
    limits(X_AXIS,10,20)
    current_plot("plot3")
    

    or by replacing the bound axes with the bind_axes call:

    bind_axes("plot1","ax1","plot2","ax1")
    bind_axes("plot1","ax1","plot3","ax1")
    limits(X_AXIS,10,20)
    

Using a filled region to show the error bounds

In this example we use a region to represent the error bounds of a set of points.

[ChIPS output]
Postscript version
rprof = read_file("profile.fits[cols r,cel_bri,cel_bri_err]")
r = get_colvals(rprof,"R")
y = get_colvals(rprof,"CEL_BRI")
dy = get_colvals(rprof,"CEL_BRI_ERR")

x = 0.492 * 0.5*(r[:,0] + r[:,1])
ym = 1.03 * (1 + (x/16.1)**2)**-1.43
add_curve(x,ym,["symbol.style","none"])

xr = numpy.append(x, x[::-1])
yr = numpy.append(y+dy, (y-dy)[::-1])
add_region(xr,yr,["fill.visible",1,"fill.color","olive","depth",90])

log_scale(XY_AXIS)
limits(Y_AXIS,8.0e-3,3.0)

bx = [0.1, 1000, 1000, 0.1]
by = [0.009, 0.009, 0.015, 0.015]
add_region(bx,by,["fill.visible",1,"fill.color","red","edge.style","none","depth",80])

set_plot_xlabel("r (arcsec)")
set_plot_ylabel("Surface brightness (count arcsec^{-2})")
set_plot_title(r"\chi^2_r = 1.04")
set_plot(["title.size",20.0])

The input file used here (profile.fits) contains a radial profile created by dmextract. The columns we are interested in are R - which gives the minimum and maximum radius of each annulus in pixels - and the surface brightness columns CEL_BRI and CEL_BRI_ERR, which are in counts per square arcsecond. We have to explicitly include the names of these two columns in the read_file call since they are stored as virtual columns, as shown in the dmlist output below:

unix% dmlist "profile.fits[cols r,sur_bri,sur_bri_err]" cols

--------------------------------------------------------------------------------
Columns for Table Block HISTOGRAM
--------------------------------------------------------------------------------
 
ColNo  Name             Unit           Type          Range
   1   R[2]             pixel          Real8(2)   -Inf:+Inf        Radius
   2   SUR_BRI          count/pixel**2 Real8      -Inf:+Inf        Net Counts per square pixel
   3   SUR_BRI_ERR      count/pixel**2 Real8      -Inf:+Inf        Error on net counts per square pixel
 
--------------------------------------------------------------------------------
World Coord Transforms for Columns in Table Block HISTOGRAM
--------------------------------------------------------------------------------
 
ColNo    Name
2:    CEL_BRI          = +0 [count/arcsec**2] +4.1311 * (SUR_BRI  -0)
3:    CEL_BRI_ERR      = +0 [count/arcsec**2] +4.1311 * (SUR_BRI_ERR  -0)

The bin center is calculated from the R values and converted to arcseconds, using the default ACIS pixel scale of 0.492 arcseconds per pixel. The model fit (a one-dimensional beta profile) is calculated using the bin center values and drawn as a curve.

To draw the data values we create a polygon by appending the (x,y-dy) values - in reverse order - onto the (x,y+dy) values to form the xr and yr arrays, and then use these to create a filled region. The depth attribute is set to 90 so that the region is drawn behind the other plot elements (which are drawn at the default depth of 100). This ensures that the curve is visible in the hardcopy outputs - created by print_window - since the opacity attribute is only used with the on-screen version of the visualization for CIAO 4.0.

The region was added to the plot after the curve to make sure that there was a data coordinate system to use. Unlike curves, histograms, and contours, creating a region will not create a pair of axes if one does not already exist.

Hardcopy (PDF): A4 | Letter
Last modified: 10 December 2007


The Chandra X-Ray Center (CXC) is operated for NASA by the Smithsonian Astrophysical Observatory.
60 Garden Street, Cambridge, MA 02138 USA.    Email: cxcweb@head.cfa.harvard.edu
Smithsonian Institution, Copyright © 1998-2004. All rights reserved.