1from astropy.coordinates
import Angle, SkyCoord
2from astropy.time
import Time
3from astropy
import units
as u
4from typing
import Dict, NamedTuple, Union
5from gwpy.timeseries
import TimeSeries
6from gwpy.frequencyseries
import FrequencySeries
8import lalsimulation
as lalsim
13 hp: Union[TimeSeries, FrequencySeries]
14 hc: Union[TimeSeries, FrequencySeries]
16 GravitationalWavePolarizations class that takes hp,hc GwPy Time/FrequencySeries objects
as inputs. Provides method to compute
17 zero noise strain given a detector, sky-position, polarization
and time of arrival values.
20 hp, hc : GwPy `TimeSeries`
or `FrequencySeries` objects
23 if isinstance(self.hp, TimeSeries)
and isinstance(self.hc, TimeSeries):
25 elif isinstance(self.hp, FrequencySeries)
and isinstance(self.hc, FrequencySeries):
30 def strain(self, det, ra, dec, psi, tgps):
32 Compute the detector strain in zero-noise
37 Name of the detector,
for eg:
'H1' or 'L1'
38 ra : `~astropy.units.Quantity`
39 Right-ascension of the binary
in units of rad
40 dec : `~astropy.units.Quantity`
41 Declination of the binary
in units of rad
42 psi : `~astropy.units.Quantity`
43 Polarization
in units of rad
44 tgps : `float`, `~astropy.units.Quantity`
45 GPS Time of time-of-arrival of signal. Either
as float
or in units of s
49 h : `TimeSeries`
or `FrequencySeries` object
50 Waveform recomposed
with detector response (Fp*hp + Fc*hc)
54 warnings.warn(
"This code is currently UNREVIEWED, use with caution!!")
55 pos = SkyCoord(ra = ra, dec = dec)
57 t = Time(tgps, format=
'gps', scale=
'utc')
59 if isinstance(det, str):
60 det = lalsim.DetectorPrefixToLALDetector(det)
62 if self.
domain() ==
'time':
67 h = lalsim.SimDetectorStrainREAL8TimeSeries(hp, hc, pos.ra.rad, pos.dec.rad, psi.rad, det)
68 h = TimeSeries.from_lal(h)
71 elif self.
domain() ==
'frequency':
74 epoch = lal.LIGOTimeGPS(t.gps)
75 dt = lal.TimeDelayFromEarthCenter(det.location, pos.ra.rad, pos.dec.rad, epoch)
76 fp, fc = lal.ComputeDetAMResponse(det.response, pos.ra.rad, pos.dec.rad, psi.rad, lal.GreenwichMeanSiderealTime(epoch))
81 h = (fp * self.hp + fc * self.hc)
82 h.epoch = Time(t.gps + dt, format=
'gps', scale=
'utc')
85 return ValueError(
'hp and hc must both be either TimeSeries or FrequencySeries')
87 def add_strain(self, data, det, ra, dec, psi, tgps, response=None):
89 Add strain to some LAL strain as required
92 data : LAL TimeSeries data
93 Data
in which to add detector response strain
95 Name of the detector,
for eg:
'H1' or 'L1'
96 ra : `~astropy.units.Quantity`
97 Right-ascension of the binary
in units of rad
98 dec : `~astropy.units.Quantity`
99 Declination of the binary
in units of rad
100 psi : `~astropy.units.Quantity`
101 Polarization
in units of rad
102 tgps : `float`, `~astropy.units.Quantity`
103 GPS Time of time-of-arrival of signal. Either
as float
or in units of s
104 response : `COMPLEX16FrequencySeries`
105 Response function passed to lalsimulation.SimAddInjectionREAL8TimeSeries,
106 transforming strain to detector output units. Use
None for unit response.
110 data : `TimeSeries` object
111 Detector response injected
in strain data
113 warnings.warn("This code is currently UNREVIEWED, use with caution!")
114 h = self.
strain(det, ra, dec, psi, tgps)
116 if isinstance(h, FrequencySeries):
120 lalsim.SimAddInjectionREAL8TimeSeries(data, h, response)
121 data = TimeSeries.from_lal(data)
127 Returns a named tuple given the l,m values
135 Class to return spin `s` weighted spherical harmonic given ModePair
139 new = super().
__new__(cls, l, m)
141 raise ValueError(
'Require l >= |s|')
142 if abs(new.m) > new.l:
143 raise ValueError(
'Require |m| <= l')
148 theta = Angle(theta, u.rad)
149 phi = Angle(phi, u.rad)
150 return lal.SpinWeightedSphericalHarmonic(theta.rad, phi.rad, self.s, self.l, self.m)
155 Class to return spin `-2` weighted spherical harmonic given ModePair
158 return super().
__new__(cls, -2, l, m)
163 Class for gravitational wave modes which returns the waveform recomposed
with -2 spin weighted spherical harmonics
164 given a (theta, phi) value
168 Return plus and cross polarizations
from the gravitational wave modes.
172 theta : `~astropy.units.Quantity`
173 Theta angle (inclination, theta_jn)
in units of rad.
174 phi : `~astropy.units.Quantity`
175 Phi angle (inclination, theta_jn)
in units of rad.
177 if isinstance(theta, float)
and isinstance(phi, float):
178 raise TypeError(
"Theta and phi should be in units of astropy.units.rad, not float")
179 elif theta.unit.is_equivalent(u.rad)
and phi.unit.is_equivalent(u.rad):
182 raise TypeError(
"Theta and phi should be in units of astropy.units.rad")
188 for key, hlm
in self.items():
189 if isinstance(key, str):
191 elif isinstance(hlm, TimeSeries):
193 hpc += mode(theta, phi) * hlm
197 elif isinstance(hlm, FrequencySeries):
200 l, m = int(key[0]), int(key[1])
202 ylm = mode(theta, phi)
203 hp += 0.5*( ylm * hlm + np.conj(ylm) * np.conj(hlm)[::-1])
204 hc += 1j*0.5*( ylm * hlm - np.conj(ylm)* np.conj(hlm)[::-1])
Class for gravitational wave modes which returns the waveform recomposed with -2 spin weighted spheri...
def __call__(self, theta, phi)
Return plus and cross polarizations from the gravitational wave modes.
def strain(self, det, ra, dec, psi, tgps)
Compute the detector strain in zero-noise.
def add_strain(self, data, det, ra, dec, psi, tgps, response=None)
Add strain to some LAL strain as required.
Returns a named tuple given the l,m values.
Class to return spin s weighted spherical harmonic given ModePair.
def __call__(self, theta, phi)
def __new__(cls, s, l, m)
Class to return spin -2 weighted spherical harmonic given ModePair.