18 Plotting tools, mostly for inspiral searches.
21 __author__ =
"Leo Singer <leo.singer@ligo.org>"
22 __organization__ = [
"LIGO",
"California Institute of Technology"]
23 __copyright__ =
"Copyright 2010, Leo Singer"
26 import gstlal.pipeutil
29 """Dictionary of strings for useful units."""
35 """Dictionary of strings for useful plot labels. Keys are generallly named the
36 same as a matching ligolw column."""
38 'mtotal':
r"total mass, $M$ (%s)" % units[
'msun'],
39 'mchirp':
r"chirp mass, $\mathcal{M}$ (%s)" % units[
'msun'],
40 'mass1':
r"component mass 1, $M_1$ (%s)" % units[
'msun'],
41 'mass2':
r"component mass 2, $M_2$ (%s)" % units[
'msun'],
43 'eff_snr':
r"effective SNR $\rho_\mathrm{eff}$",
44 'combined_snr':
r"combined SNR, $\sqrt{\sum\rho^2}$",
45 'combined_eff_snr':
r"combined effective SNR, $\sqrt{\sum\rho_\mathrm{eff}^2}$",
47 'tau0':
r"chirp time $\tau0$",
48 'tau3':
r"chirp time $\tau3$",
52 def plotbank(in_filename, out_filename=None, column1='mchirp', column2='mtotal'):
53 """Plot template bank parameters from a file generated by lalapps_tmpltbank."""
54 from glue.ligolw
import ligolw, utils, lsctables
55 class LIGOLWContentHandler(ligolw.LIGOLWContentHandler):
57 lsctables.use_in(LIGOLWContentHandler)
58 table = lsctables.SnglInspiralTable.get_table(
59 utils.load_filename(in_filename, contenthandler = LIGOLWContentHandler)
62 pylab.title(
'%s: placement of %d templates' % (in_filename, len(table)))
63 pylab.plot(table.get_column(column1), table.get_column(column2),
',')
64 pylab.xlabel(labels[column1])
65 pylab.ylabel(labels[column2])
67 if out_filename
is None:
70 pylab.savefig(out_filename)
74 def plotsvd(in_filename, out_filename=None):
75 """Plot heatmap of orthogonal template components."""
76 from gstlal.gstlal_svd_bank
import read_bank
77 bank = read_bank(in_filename)
79 for bf
in bank.bank_fragments:
80 next_ntemplates = ntemplates + bf.orthogonal_template_bank.shape[0]
82 pylab.log10(abs(bf.orthogonal_template_bank[::-1,:])),
83 extent = (bf.end, bf.start, ntemplates, next_ntemplates),
84 hold=
True, aspect=
'auto'
86 pylab.text(bf.end + bank.filter_length / 30, ntemplates + 0.5 * bf.orthogonal_template_bank.shape[0],
'%d Hz' % bf.rate, size=
'x-small')
87 ntemplates = next_ntemplates
89 pylab.xlim(0, 1.15*bank.filter_length)
90 pylab.ylim(0, 1.05*ntemplates)
91 pylab.colorbar().set_label(
'$\mathrm{log}_{10} |u_{i}(t)|$')
92 pylab.xlabel(
r"Time $t$ until coalescence (seconds)")
93 pylab.ylabel(
r"Basis index $i$")
94 pylab.title(
r"Orthonormal basis templates $u_{i}(t)$")
95 if out_filename
is None:
98 pylab.savefig(out_filename)
102 def plotskymap(fig, theta, phi, logp, gpstime, arrival_times=None, inj_lon_lat=None):
103 """Draw a skymap as produced by the lal_skymap element.
104 arrival_times should be a dictionary with keys being IFO names
105 (e.g. 'H1', 'L1', 'V1', ...) and values being double precision GPS arrival
108 If inj_lon_at is set to a celestial Dec/RA tuple in radians, then the
109 injection point of origin will be marked with a cross.
111 Currently, lal_skymap generates a grid of 450x900 points, and this code
112 relies on that. It could be generalized to handle any rectangular grid,
113 but the pcolormesh method that is used here is really only finally tuned for
114 quadrilateral meshes.
120 from math
import atan2, acos, asin, degrees, sqrt, pi
121 from mpl_toolkits.basemap
import Basemap, shiftgrid
125 from glue.iterutils
import choices
130 def location_for_site(prefix):
131 """Get the Cartesian (WGS84) coordinates of a site, given its prefix
132 (H1 for Hanford, L1 for Livingston...)."""
133 return lalsimulation.DetectorPrefixToLALDetector(prefix).location
135 def cart2spherical(cart):
136 """Convert a Cartesian vector to spherical polar azimuth (phi) and elevation (theta) in radians."""
137 return atan2(cart[1], cart[0]), acos(cart[2] / sqrt(np.dot(cart, cart)))
140 def spherical2latlon(spherical):
141 """Converts spherical polar coordinates in radians to latitude, longitude in degrees."""
142 return degrees(spherical[0]), 90 - degrees(spherical[1])
149 m = Basemap(projection=
'moll', lon_0=0, lat_0=0, ax=ax)
150 m.drawparallels(np.arange(-45,46,45), linewidth=0.5, labels=[1, 0, 0, 0], labelstyle=
"+/-")
151 m.drawmeridians(np.arange(-180,180,90), linewidth=0.5)
155 sidereal_time = np.mod(lal.GreenwichMeanSiderealTime(lal.LIGOTimeGPS(gpstime)) / lal.PI_180, 360)
156 lons_grid = sidereal_time + phi.reshape(450, 900) / lal.PI_180
157 lats_grid = 90 - theta.reshape(450, 900) / lal.PI_180
158 logp_grid = logp.reshape(450, 900)
163 gridshift = round(sidereal_time / 360) * 360 + 180
164 lats_grid, dummy = shiftgrid(gridshift, lats_grid, lons_grid[0,:], start=
False)
165 logp_grid, dummy = shiftgrid(gridshift, logp_grid, lons_grid[0,:], start=
False)
166 lons_grid, dummy = shiftgrid(gridshift, lons_grid, lons_grid[0,:], start=
False)
169 x, y = m(lons_grid, lats_grid)
172 pc = m.pcolormesh(x, y, logp_grid, vmin=logp[np.isfinite(logp)].min())
173 cb = fig.colorbar(pc, shrink=0.5)
174 cb.set_label(
'log relative probability')
175 cb.cmap.set_under(
'1.0', alpha=1.0)
176 cb.cmap.set_bad(
'1.0', alpha=1.0)
179 maxidx = logp_grid.flatten().argmax()
180 m.plot(x.flatten()[maxidx], y.flatten()[maxidx],
'*', markerfacecolor=
'white', markersize=10)
183 if arrival_times
is not None:
184 for sites
in choices(arrival_times.keys(), 2):
185 site0_location = location_for_site(sites[0])
186 site1_location = location_for_site(sites[1])
187 site_separation = site0_location - site1_location
188 site_distance_seconds = sqrt(np.dot(site_separation, site_separation)) / lal.C_SI
189 lon, lat = spherical2latlon(cart2spherical(site_separation))
190 site0_toa = arrival_times[sites[0]]
191 site1_toa = arrival_times[sites[1]]
192 radius = acos((site1_toa - site0_toa) / site_distance_seconds) * 180 / pi
196 poly = m.tissot(lon + sidereal_time, lat, radius, 1000, facecolor=
'none')
202 if inj_lon_lat
is not None:
203 inj_x, inj_y = m(degrees(inj_lon_lat[0]), degrees(inj_lon_lat[1]))
204 m.plot(inj_x, inj_y,
'+k', markersize=20, markeredgewidth=1)
207 ax.set_title(
'Candidate log probability distribution')
208 ax.set_xlabel(
'RA/dec, J2000. White star marks the mode of the PDF.\nBlack lines represent time delay solution loci for each pair of detectors.', fontsize=10)