2import lalsimulation
as lalsim
4from astropy
import units
as u
5from gwpy.timeseries
import TimeSeries
6from gwpy.frequencyseries
import FrequencySeries
8from .
import utils
as ut
9from .
import parameter_conventions
as pc
11from .
import waveform_conditioning
as wave_cond
12from .
import errors
as err
19 This is the Parent
class for all gravitational wave generator classes.
20 This
class implements the basic generate modes and polarizations definitions which can then be used by the
21 consequent children classes.
26 Initialize the class and set base
domain to time.
31 No parameters required
for initialization.
36 Generate time domain modes given kwargs. The child classes will provide these routines.
41 kwargs required for generation of waveform modes
46 Waveform modes
as implemented
in the child
class
49 raise NotImplementedError
53 Generate frequency domain modes given kwargs. The child classes will provide these routines.
58 kwargs required for generation of waveform modes
63 Waveform modes
as implemented
in the child
class
66 raise NotImplementedError
70 Generate time domain polarizations given kwargs. The child classes will provide these routines.
75 kwargs required for generation of waveform polarizations
80 Waveform polarizations implemented
in the child
class
83 raise NotImplementedError
87 Generate frequency domain polarizations given kwargs. The child classes will provide these routines.
92 kwargs required for generation of waveform polarizations
97 Waveform polarizations
as implemented
in the child
class
100 raise NotImplementedError
106 def _update_domains(self):
108 Update the generation or implementation domain
for a given generator /
if needed.
116 Updated domain tags
for polarization generation
and waveform implementation.
128 "polarizations":
None,
129 "implemented_domain":
None,
130 "generation_domain":
None,
131 "approximant" :
None,
132 "implementation" :
'',
133 "conditioning_routines" :
''
139 This is the parent generator
class for compact binary coalescence waveforms (
BBH, BNS, NSBH etc.).
141 The main intended functionality of this
class is to check the different parameters passed in the kwargs
142 and to populate the parameter dictionaries
with all the other parameters
from the lalsuite parameter checks.
152 No parameters required
for initilazation.
155 super(CompactBinaryCoalescenceGenerator, self).__init__()
158 def parameter_check(self, units_sys='S.I.', extra_parameters=dict(), **parameters):
160 Perform checks on the various parameters and populate the different parameters
not passed
161 in the kwargs required
for generating waveforms.
166 Python dictionary of parameters required
for waveform generation
167 of the form specified
in `parameter_conventions.py`.
172 Populate self.
waveform_dict with python dictionary
and self.
lal_dict with LALSuite dictionary structure.
174 default_dict = pc.default_dict.copy()
176 ExternalPythonParameters=[
'object',
'module']
178 for key, value
in parameters.items():
179 if key
in ExternalPythonParameters:
182 default_dict[key] = value
184 if not 'deltaF' in default_dict:
185 default_dict[
'deltaF'] = 1./16.*u.Hz
186 if not 'deltaT' in default_dict:
187 default_dict[
'deltaT'] = 1./512.*u.s
188 if not 'f_max' in default_dict:
189 default_dict[
'f_max'] = (0.5/default_dict[
'deltaT'].value)*u.Hz
192 if units_sys
is not None:
193 self.
waveform_dict = ut.add_params_units(default_dict, units_sys, generic_param_dict=extra_parameters)
195 ut.check_dict_parameters(default_dict, generic_param_dict=extra_parameters)
207 Generator class for all CBC waveforms as implemented in LALSimulation.
210 def __init__(self, approximant, **kwargs):
212 Initialize class. Parent
class is the
"CompactBinaryCoalescenceGenerator" class
216 approximant : type
'str'
217 Name of the LAL approximant of which waveform to be generated
221 generator : Python GW generator
class
222 Generator
class for LALSimulation waveforms required to generate time and frequency
domain polarizations and modes
225 super(LALCompactBinaryCoalescenceGenerator, self).__init__()
226 warnings.warn("This code is currently UNREVIEWED, use with caution!")
235 "type":
'cbc_lalsimulation',
238 "polarizations":
True,
242 "implementation" :
"LALSimulation",
243 "conditioning_routines" :
'lalsimulation'
247 def _update_domains(self):
249 Update the implemented domain of the LAL generator based on LALSimulations ImplementedTD/FDApproximant flag
253 td_flag = lalsim.SimInspiralImplementedTDApproximants(self.
_approx)
254 fd_flag = lalsim.SimInspiralImplementedFDApproximants(self.
_approx)
255 check_array = [td_flag, fd_flag]
257 if check_array==[1,0]:
259 elif check_array==[0,1]:
261 elif check_array==[1,1]:
264 def _get_approximant(self, approx):
265 """Populate the approximant name and approximant int (as used by lalsimulation) from waveform dictionary.
275 Populate self.
_approx_name (str)
and self.
_approx (int) to be used by lalsimulation ChooseWaveformGenerator
280 ValueError
if approximant
is not included
in LALSimulation
283 if type(approx)
is str:
285 self.
_approx = lalsim.SimInspiralGetApproximantFromString(approx)
286 elif type(approx)
is int:
288 self.
_approx_name = lalsim.GetStringFromApproximant(approx)
290 raise ValueError(
'approximant not of recognized type')
295 Perform parameter check, choose lalsimulation generator based on domain and conditioning subroutines.
299 parameter_dict : dictionary
300 Dictionary of waveform parameters of the form specified
301 in `parameter_conventions.py`.
305 hp, hc : LAL Time Series
306 Plus
and cross polarizations of a gravitational waveform (hp,hc)
as LAL Data objects.
310 ValueError
if domain (
'time' or 'freq')
for approximant
is not specified
322 raise ValueError(
"Generator requires conditioning to be turned on to generate time domain waveform")
327 def gen_pol_func(lal_dict, lal_generator):
336 Perform parameter check, choose lalsimulation generator based on domain and conditioning subroutines.
340 parameter_dict : dictionary
341 Dictionary of waveform parameters of the form specified
342 in `parameter_conventions.py`.
346 hp, hc : LAL Frequency Series
347 Plus
and cross polarizations of a gravitational waveform (hp,hc)
as LAL Data objects.
351 ValueError
if domain (
'time' or 'freq')
for approximant
is not specified
361 raise ValueError(
"Generator requires conditioning to be turned on to generate frequency domain waveform")
369 def gen_pol_func(lal_dict, lal_generator):
379 Perform parameter check, choose lalsimulation generator based on domain and attempt to generate
384 parameter_dict : dictionary
385 Dictionary of waveform parameters of the form specified
386 in `parameter_conventions.py`.
390 hlm : Python dictionary of modes
391 Modes of a gravitational waveform
as python dictionary where each mode
is LAL Time series
402 raise ValueError(
'Approximant does not have time domain mode generator')
404 raise ValueError(
'Approximant domain unspecified')
410 def gen_modes(lal_dict, gen):
422 mode_22 = lalsim.SphHarmTimeSeriesGetMode(hlm, 2, 2)
424 times = np.float64(mode_22.epoch) + np.arange(0, len(mode_22.data.data))*dt
426 hlm_dict[
'time_array'] = np.array(times)
430 for l
in np.arange(2, lmax+1):
431 for m
in np.arange(-l, l+1):
432 hlm_dict[l,m] = lalsim.SphHarmTimeSeriesGetMode(hlm, int(l), int(m))
440 Perform parameter check, choose lalsimulation generator based on domain and attempt to generate
445 parameter_dict : dictionary
446 Dictionary of waveform parameters of the form specified
447 in `parameter_conventions.py`.
451 hlm : Python dictionary of modes
452 Modes of a gravitational waveform
as python dictionary where each mode
is LAL Frequency series
461 raise ValueError(
'Approximant does not have frequency domain mode generator')
465 raise ValueError(
'approximant domain unspecified')
470 def gen_modes(lal_dict, gen):
480 hlm_dict[
'frequency_array'] = hlm.fdata.data
484 for l
in np.arange(2, lmax+1):
485 for m
in np.arange(-l, l+1):
486 hlm_dict[l,m] = lalsim.SphHarmFrequencySeriesGetMode(hlm, int(l), int(m))
494 Given a generator with contioning
as 1,
return function that generates conditioned waveforms
498 generator : `GravitationalWaveGenerator`
499 GravitationalWaveGenerator object
503 Conditioning function
for the generator
506 if generator._implemented_domain==
'time' and generator._generation_domain==
'time':
507 generator_func = wave_cond.generate_conditioned_td_waveform_from_td
509 elif generator._implemented_domain==
'time' and generator._generation_domain==
'freq':
510 generator_func = wave_cond.generate_conditioned_fd_waveform_from_td
512 elif generator._implemented_domain==
'freq' and generator._generation_domain==
'freq':
513 generator_func = wave_cond.generate_conditioned_fd_waveform_from_fd
515 elif generator._implemented_domain==
'freq' and generator._generation_domain==
'time':
516 generator_func = wave_cond.generate_conditioned_td_waveform_from_fd
518 return generator_func
527 Function to convert a lal series to a gwpy series.
531 h : lal time or frequency series
532 'lal.REAL8TimeSeries' or 'lal.COMPLEX16FrequencySeries'
534 f0 : Starting frequency passed to gwpy.FrequencySeries
539 h : GWpy Time/Freq series
540 Time/Freq domain waveform
543 if isinstance(h, lal.REAL8TimeSeries)
or isinstance(h, lal.COMPLEX16TimeSeries):
544 return TimeSeries(h.data.data, dt = h.deltaT, t0 = h.epoch, **kwargs)
546 elif isinstance(h, lal.COMPLEX16FrequencySeries):
547 return FrequencySeries(h.data.data, df = h.deltaF, f0=f0, **kwargs)
549 elif isinstance(h, TimeSeries) :
550 return TimeSeries(h, **kwargs)
552 elif isinstance(h, FrequencySeries):
553 return FrequencySeries(h, **kwargs)
556 print(
'Input type not recognized')
560 Function to convert a mode dictionary of lal series to a dictionary of
565 mode_dict : python dictionary
566 entries of the form {(l, m): lal-series} and {`time/frequency_array` : }
570 new_dict : python dictionary
571 entries of the form {(l, m): gwpy-series}
and {`time/frequency_array` : }
576 for k, v
in mode_dict.items():
577 if k ==
'time_array':
578 new_dict.update({k: v})
579 elif k ==
'frequency_array':
580 new_dict.update({k: v})
585 new_dict.update({k:
to_gwpy_Series(v, f0, name=
'h_%i_%i'%(k[0], k[1]),**kwargs)})
596 Function to generate time domain gravitational wave polarizations.
600 parameter_dict : dictionary
601 Dictionary of intrinsic / extrinsic gravitational wave parameters
602 generator : Python GW generator class
603 Generator
class for the waveform
approximant (either LAL or external)
607 `GravitationalWavePolarizations` object: allows to extract the zero noise strain
608 given a detector, sky-position, polarization
and time of arrival values.
611 generator._generation_domain = 'time'
612 generator._update_domains()
614 conditioning = parameter_dict[
'condition']
615 conditioning_routines = generator.metadata[
'conditioning_routines']
619 if not conditioning
and generator._generation_domain!=generator._implemented_domain:
620 raise ValueError(
"Generator does not provide a method to generate time-domain waveforms. \n Please turn on conditioning to generate time-domain waveform")
622 if conditioning
and conditioning_routines==
'gwsignal':
623 warnings.warn(
"This code is currently UNREVIEWED, use with caution!")
625 hp, hc = generator_func(parameter_dict, generator)
627 hp, hc = generator.generate_td_waveform(**parameter_dict)
633 Function to generate frequency domain gravitational wave polarizations.
637 parameter_dict : dictionary
638 Dictionary of intrinsic / extrinsic gravitational wave parameters
639 generator : Python GW generator class
640 Generator
class for the waveform
approximant (either LAL or external)
644 `GravitationalWavePolarizations` object: allows to extract the zero noise strain
645 given a detector, sky-position, polarization
and time of arrival values.
648 generator._generation_domain = 'freq'
649 generator._update_domains()
651 conditioning = parameter_dict[
'condition']
652 conditioning_routines = generator.metadata[
'conditioning_routines']
656 if not conditioning
and generator._generation_domain!=generator._implemented_domain:
657 raise ValueError(
"Generator does not provide a method to generate frequency-domain waveforms. \n Please turn on conditioning to generate time-domain waveform")
659 if conditioning
and conditioning_routines==
'gwsignal':
660 warnings.warn(
"This code is currently UNREVIEWED, use with caution!")
662 hp, hc = generator_func(parameter_dict, generator)
664 hp, hc = generator.generate_fd_waveform(**parameter_dict)
670 Function to generate time domain gravitational wave modes.
674 parameter_dict : dictionary
675 Dictionary of intrinsic / extrinsic gravitational wave parameters
676 generator : Python GW generator class
677 Generator
class for the waveform
approximant (either LAL or external)
681 hlm : Python dictionary
682 Time domain modes returned
as a dictionary where each mode
is a GWpy Time series object
685 generator._generation_domain = 'time'
686 generator._update_domains()
688 hlm = generator.generate_td_modes(**parameter_dict)
696 Function to generate frequency domain gravitational wave modes.
700 parameter_dict : dictionary
701 Dictionary of intrinsic / extrinsic gravitational wave parameters
702 generator : Python GW generator class
703 Generator
class for the waveform
approximant (either LAL or external)
707 hlm : Python dictionary
708 Frequency domain modes returned
as a dictionary where each mode
is a GWpy Frequency series object
711 generator._generation_domain = 'freq'
712 generator._update_domains()
714 hlm = generator.generate_fd_modes(**parameter_dict)
Class for gravitational wave modes which returns the waveform recomposed with -2 spin weighted spheri...