Note

This tutorial was generated from a Jupyter notebook that can be downloaded here.

Using gwent to Generate Characteristic Strain Curves

Here we show examples of using the different classes in gwent for various detectors, both loading in from a file and generating with gwent, and binary black holes, both in the frequency and time domain.

First, we load important packages

import numpy as np

import matplotlib as mpl
import matplotlib.pyplot as plt

from cycler import cycler
from scipy.constants import golden_ratio

import astropy.constants as const
import astropy.units as u

import gwent
import gwent.detector as detector
import gwent.binary as binary

#Turn off warnings for tutorial
import warnings
warnings.filterwarnings('ignore')

Setting matplotlib and plotting preferences

def get_fig_size(width=7,scale=1.0):
    #width = 3.36 # 242 pt
    base_size = np.array([1, 1/scale/golden_ratio])
    fig_size = width * base_size
    return(fig_size)
mpl.rcParams['figure.dpi'] = 300
mpl.rcParams['figure.figsize'] = get_fig_size()
mpl.rcParams['text.usetex'] = True
mpl.rc('font',**{'family':'serif','serif':['Times New Roman']})
mpl.rcParams['lines.linewidth'] = 2
mpl.rcParams['axes.labelsize'] = 12
mpl.rcParams['xtick.labelsize'] = 12
mpl.rcParams['ytick.labelsize'] = 12
mpl.rcParams['legend.fontsize'] = 10
color_cycle_wong = ['#000000','#E69F00','#56B4E9','#009E73','#F0E442','#0072B2','#D55E00','#CC79A7','#5a5a5a']
mpl.rcParams['axes.prop_cycle'] = cycler(color=color_cycle_wong)

We need to get the file directories to load in the instrument files.

load_directory = gwent.__path__[0] + '/LoadFiles'

Initialize different instruments

If loading a detector, the file should be frequency in the first column and either strain, effective strain noise spectral density, or amplitude spectral density in the second column.

For generating a detector, one must assign a value to each of the different instrument parameters (see the section on Declaring x and y variables and Sample Rates).

Load ground instruments from files

aLIGO

Ground_T_obs = 4*u.yr
#aLIGO
aLIGO_filedirectory = load_directory + '/InstrumentFiles/aLIGO/'
aLIGO_1_filename = 'aLIGODesign.txt'
aLIGO_2_filename = 'ZERO_DET_high_P.txt'

aLIGO_1_filelocation = aLIGO_filedirectory + aLIGO_1_filename
aLIGO_2_filelocation = aLIGO_filedirectory + aLIGO_2_filename

aLIGO_1 = detector.GroundBased('aLIGO 1',Ground_T_obs,load_location=aLIGO_1_filelocation,I_type='A')
aLIGO_2 = detector.GroundBased('aLIGO 2',Ground_T_obs,load_location=aLIGO_2_filelocation,I_type='A')

Einstein Telescope

#Einstein Telescope
ET_filedirectory = load_directory + '/InstrumentFiles/EinsteinTelescope/'
ET_B_filename = 'ET_B_data.txt'
ET_C_filename = 'ET_C_data.txt'
ET_D_filename = 'ET_D_data.txt'

ET_B_filelocation = ET_filedirectory + ET_B_filename
ET_C_filelocation = ET_filedirectory + ET_C_filename
ET_D_filelocation = ET_filedirectory + ET_D_filename

ET_B = detector.GroundBased('ET',Ground_T_obs,load_location=ET_B_filelocation,I_type='A')
ET_C = detector.GroundBased('ET',Ground_T_obs,load_location=ET_C_filelocation,I_type='A')
ET_D = detector.GroundBased('ET',Ground_T_obs,load_location=ET_D_filelocation,I_type='A')

Plots of Ground Detectors

fig = plt.figure()
plt.loglog(ET_B.fT,ET_B.h_n_f,label='Hild et al., (2008) ET Design B')
plt.loglog(ET_C.fT,ET_C.h_n_f,label='Einstein Telescope Design C')
plt.loglog(ET_D.fT,ET_D.h_n_f,label='Hild et al., (2011) ET Design D')
plt.loglog(aLIGO_1.fT,aLIGO_1.h_n_f,label='Advanced LIGO')
plt.loglog(aLIGO_2.fT,aLIGO_2.h_n_f,label='Advanced LIGO 2')
plt.xlabel(r'Frequency [Hz]')
plt.ylabel(r'Characteristic Strain')
plt.tick_params(axis = 'both',which = 'major')
plt.legend()
plt.show()
_images/strain_plot_tutorial_14_0.png

Load LISA Instruments from File

LISA Example 1

Modelled off of the Science Requirements document from https://lisa.nasa.gov/documentsReference.html.

SpaceBased_T_obs = 4*u.yr
LISA_Other_filedirectory = load_directory + '/InstrumentFiles/LISA_Other/'
LISA_ex1_filename = 'LISA_Allocation_S_h_tot.txt'
LISA_ex1_filelocation = LISA_Other_filedirectory + LISA_ex1_filename

#`I_type` should be Effective Noise Spectral Density
LISA_ex1 = detector.SpaceBased('LISA Example 1',SpaceBased_T_obs,load_location=LISA_ex1_filelocation,I_type='E')

LISA Example 2

Modelled off of Robson,Cornish,and Liu 2018, LISA (https://arxiv.org/abs/1803.01944).

LISA_ex2_filedirectory = load_directory + '/InstrumentFiles/LISA_Other/'
LISA_ex2_filename = 'LISA_sensitivity.txt'
LISA_ex2_filelocation = LISA_ex2_filedirectory + LISA_ex2_filename

#`I_type` should be Effective Noise Spectral Density
LISA_ex2 = detector.SpaceBased('LISA Example 2',SpaceBased_T_obs,load_location=LISA_ex2_filelocation,I_type='E')

LISA Example 3

Generated by http://www.srl.caltech.edu/~shane/sensitivity/

LISA_ex3_filename = 'scg_6981.dat'
LISA_ex3_filelocation = LISA_Other_filedirectory + LISA_ex3_filename

#`I_type` should be Amplitude Spectral Density
LISA_ex3 = detector.SpaceBased('LISA Example 3',SpaceBased_T_obs,load_location=LISA_ex3_filelocation,I_type='A')

Plots of loaded LISA examples.

fig = plt.figure()
plt.loglog(LISA_ex1.fT,LISA_ex1.h_n_f,label=LISA_ex1.name)
plt.loglog(LISA_ex2.fT,LISA_ex2.h_n_f,label=LISA_ex2.name)
plt.loglog(LISA_ex3.fT,LISA_ex3.h_n_f,label=LISA_ex3.name)
plt.xlabel(r'Frequency [Hz]')
plt.ylabel(r'Characteristic Strain')
plt.tick_params(axis = 'both',which = 'major')
plt.legend()
plt.show()
_images/strain_plot_tutorial_23_0.png

Loading PTA Detection Curves and Upper Limits

Simulated NANOGrav Continuous Wave Detection Sensitivity

Samples from Mingarelli, et al. 2017 (https://arxiv.org/abs/1708.03491) of the Simulated NANOGrav Continuous Wave Detection Sensitivity.

NANOGrav_filedirectory = load_directory + '/InstrumentFiles/NANOGrav/StrainFiles/'
#NANOGrav continuous wave sensitivity
NANOGrav_background = 4e-16 # Unsubtracted GWB amplitude: 0,4e-16
NANOGrav_dp = 0.95 #Detection Probablility: 0.95,0.5
NANOGrav_fap = 0.0001 #False Alarm Probability: 0.05,0.003,0.001,0.0001
NANOGrav_Tobs = 15 #Observation years: 15,20,25

NANOGrav_filename = 'cw_simulation_Ared_' + str(NANOGrav_background) + '_dp_' + str(NANOGrav_dp) \
                    + '_fap_' + str(NANOGrav_fap) + '_T_' + str(NANOGrav_Tobs) + '.txt'
NANOGrav_filelocation = NANOGrav_filedirectory + NANOGrav_filename

NANOGrav_cw_GWB = detector.PTA('NANOGrav CW Detection w/ GWB',load_location=NANOGrav_filelocation,I_type='h')
#NANOGrav continuous wave sensitivity
NANOGrav_background_2 = 0 # Unsubtracted GWB amplitude: 0,4e-16
NANOGrav_dp_2 = 0.95 #Detection Probablility: 0.95,0.5
NANOGrav_fap_2 = 0.0001 #False Alarm Probability: 0.05,0.003,0.001,0.0001
NANOGrav_Tobs_2 = 15 #Observation years: 15,20,25

NANOGrav_filename_2 = 'cw_simulation_Ared_' + str(NANOGrav_background_2) + '_dp_' + str(NANOGrav_dp_2) \
                    + '_fap_' + str(NANOGrav_fap_2) + '_T_' + str(NANOGrav_Tobs_2) + '.txt'
NANOGrav_filelocation_2 = NANOGrav_filedirectory + NANOGrav_filename_2

NANOGrav_cw_no_GWB = detector.PTA('NANOGrav CW Detection no GWB',load_location=NANOGrav_filelocation_2,I_type='h')

NANOGrav Continuous Wave 11yr Upper Limit

Sample from Aggarwal, et al. 2019 (https://arxiv.org/abs/1812.11585) of the NANOGrav 11yr continuous wave upper limit.

NANOGrav_cw_ul_file = NANOGrav_filedirectory + 'smoothed_11yr.txt'
NANOGrav_cw_ul = detector.PTA('NANOGrav CW Upper Limit',load_location=NANOGrav_cw_ul_file,I_type='h')

NANOGrav 11yr Characteristic Strain

Using real NANOGrav 11yr data put through hasasia. We need to initialize and fill the values used in the plots (i.e., NANOGrav_11yr_hasasia.T_obs isn’t known until we set the values since we loaded it from a file.

NANOGrav_11yr_hasasia_file = NANOGrav_filedirectory + 'NANOGrav_11yr_S_eff.txt'
NANOGrav_11yr_hasasia = detector.PTA('NANOGrav 11yr',load_location=NANOGrav_11yr_hasasia_file,I_type='E')
NANOGrav_11yr_hasasia.T_obs = 11.4*u.yr

Plots of the loaded PTAs

fig = plt.figure()
plt.loglog(NANOGrav_cw_GWB.fT,NANOGrav_cw_GWB.h_n_f,label = r'Mingarelli et al. (2017), CW Detection Probability w/GWB')
plt.loglog(NANOGrav_cw_no_GWB.fT,NANOGrav_cw_no_GWB.h_n_f, label =r'Mingarelli et al. (2017), CW Detection Probability w/o GWB')
plt.loglog(NANOGrav_cw_ul.fT,NANOGrav_cw_ul.h_n_f, label = r'Aggarwal et al. (2018), CW Upper Limit')
plt.loglog(NANOGrav_11yr_hasasia.fT,np.sqrt(NANOGrav_11yr_hasasia.S_n_f/np.max(np.unique(NANOGrav_11yr_hasasia.T_obs.to('s').value))),
           label = r'NANOGrav: 11yr Data  corresponding to a source strain with SNR of one')

plt.tick_params(axis = 'both',which = 'major')
plt.ylim([2e-15,6e-12])
plt.xlim([4e-10,4e-7])
plt.xlabel(r'Frequency [Hz]')
plt.ylabel('Strain')
plt.legend(loc='upper left',fontsize=8)
plt.show()
_images/strain_plot_tutorial_33_0.png

Generating PTAs with gwent

Generated using the code hasasia (https://hasasia.readthedocs.io/en/latest/) via the methods of Hazboun, Romano, and Smith, 2019 (https://arxiv.org/abs/1907.04341)

SKA-esque Detector

Fiducial parameter estimates from Sesana, Vecchio, and Colacino, 2008 (https://arxiv.org/abs/0804.4476) section 7.1.

sigma_SKA = 10*u.ns.to('s')*u.s #sigma_rms timing residuals in nanoseconds to seconds
T_SKA = 15*u.yr #Observing time in years
N_p_SKA = 20 #Number of pulsars
cadence_SKA = 1/(u.wk.to('yr')*u.yr) #Avg observation cadence of 1 every week in [number/yr]

SKA with White noise only

SKA_WN = detector.PTA('SKA, WN Only',N_p_SKA,T_obs=T_SKA,sigma=sigma_SKA,cadence=cadence_SKA)

SKA with White and Varied Red Noise

SKA_WN_RN = detector.PTA('SKA, WN and RN',N_p_SKA,T_obs=T_SKA,sigma=sigma_SKA,cadence=cadence_SKA,
                         rn_amp=[1e-16,1e-12],rn_alpha=[-1/2,1.25])

SKA with White Noise and a Stochastic Gravitational Wave Background

SKA_WN_GWB = detector.PTA('SKA, WN and GWB',N_p_SKA,T_obs=T_SKA,sigma=sigma_SKA,cadence=cadence_SKA,
                          sb_amp=4e-16,sb_alpha=-2/3)

SKA with Sampled Noise for each pulsar, no GWB

SKA_Sampled_Noise = detector.PTA('SKA, Sampled Noise',N_p_SKA,cadence=[cadence_SKA,cadence_SKA/4.],
                                 sigma=[sigma_SKA,10*sigma_SKA],T_obs=T_SKA,use_11yr=True,use_rn=True)

Plots for Simulated SKA PTAs

fig = plt.figure()
plt.loglog(SKA_WN.fT,SKA_WN.h_n_f,label = SKA_WN.name)
plt.loglog(SKA_WN_GWB.fT,SKA_WN_GWB.h_n_f, linestyle=':',label = SKA_WN_GWB.name)
plt.loglog(SKA_WN_RN.fT,SKA_WN_RN.h_n_f, linestyle='-.',label = SKA_WN_RN.name)
plt.loglog(SKA_Sampled_Noise.fT,SKA_Sampled_Noise.h_n_f,linestyle='--',label=SKA_Sampled_Noise.name)

plt.tick_params(axis = 'both',which = 'major')
plt.ylim([1e-18,2e-11])
plt.xlim([3e-10,1e-6])

plt.xlabel('Frequency [Hz]')
plt.ylabel('Characteristic Strain')
plt.legend(loc='upper left')
plt.show()
_images/strain_plot_tutorial_45_0.png

NANOGrav-esque Detector

Fiducial 11yr parameter estimates from Arzoumanian, et al., 2018 https://arxiv.org/abs/1801.01837

###############################################
#NANOGrav calculation using 11.5yr parameters https://arxiv.org/abs/1801.01837
sigma_nano = 100*u.ns.to('s')*u.s #rms timing residuals in nanoseconds to seconds
T_nano = 11.4*u.yr #Observing time in years
N_p_nano = 34 #Number of pulsars
cadence_nano = 1/(2*u.wk.to('yr')*u.yr) #Avg observation cadence of 1 every 2 weeks in number/year

NANOGrav with White Noise only

NANOGrav_WN = detector.PTA('NANOGrav, WN Only',N_p_nano,T_obs=T_nano,sigma=sigma_nano,cadence=cadence_nano)

NANOGrav with White and Varied Red Noise

NANOGrav_WN_RN = detector.PTA('NANOGrav, WN and RN',N_p_nano,T_obs=T_nano,sigma=sigma_nano,cadence=cadence_nano,
                              rn_amp=[1e-16,1e-12],rn_alpha=[-1/2,1.25])

NANOGrav with White Noise and a Stochastic Gravitational Wave Background

NANOGrav_WN_GWB = detector.PTA('NANOGrav, WN and GWB',N_p_nano,
                               T_obs=T_nano,sigma=sigma_nano,cadence=cadence_nano,sb_amp=4e-16)

NANOGrav with Sampled Noise for each pulsar, no GWB

NANOGrav_Sampled_Noise = detector.PTA('NANOGrav, Sampled Noise',N_p_nano,use_11yr=True,use_rn=True)

Plots for Simulated NANOGrav PTAs

fig = plt.figure()
plt.loglog(NANOGrav_WN.fT,NANOGrav_WN.h_n_f,
           label=NANOGrav_WN.name)
plt.loglog(NANOGrav_WN_GWB.fT,NANOGrav_WN_GWB.h_n_f,
           linestyle=':',label=NANOGrav_WN_GWB.name)
plt.loglog(NANOGrav_WN_RN.fT,NANOGrav_WN_RN.h_n_f,
           linestyle='-.',label=NANOGrav_WN_RN.name)
plt.loglog(NANOGrav_Sampled_Noise.fT,NANOGrav_Sampled_Noise.h_n_f,
           linestyle='--',label=NANOGrav_Sampled_Noise.name)

plt.loglog(NANOGrav_11yr_hasasia.fT,NANOGrav_11yr_hasasia.h_n_f,
           label = r'NANOGrav: 11yr Data')

plt.tick_params(axis = 'both',which = 'major')
plt.ylim([3e-17,2e-11])
plt.xlim([3e-10,5e-7])

plt.xlabel('Frequency [Hz]')
plt.ylabel('Characteristic Strain')
plt.legend(loc='upper left')
plt.show()
_images/strain_plot_tutorial_57_0.png

Generating LISA designs with gwent

First we set a fiducial armlength and observation time-length

L = 2.5*u.Gm  #armlength in Gm
L = L.to('m')
LISA_T_obs = 4*u.yr

LISA Proposal 1

Values taken from the ESA L3 proposal, Amaro-Seaone, et al., 2017 (https://arxiv.org/abs/1702.00786)

f_acc_break_low = .4*u.mHz.to('Hz')*u.Hz
f_acc_break_high = 8.*u.mHz.to('Hz')*u.Hz
f_IMS_break = 2.*u.mHz.to('Hz')*u.Hz
A_acc = 3e-15*u.m/u.s/u.s
A_IMS = 10e-12*u.m

Background = False

LISA_prop1 = detector.SpaceBased('LISA',\
                          LISA_T_obs,L,A_acc,f_acc_break_low,f_acc_break_high,A_IMS,f_IMS_break,\
                          Background=Background)

LISA Proposal 1 with Galactic Binary Background

Values taken from the ESA L3 proposal, Amaro-Seaone, et al., 2017 (https://arxiv.org/abs/1702.00786)

f_acc_break_low = .4*u.mHz.to('Hz')*u.Hz
f_acc_break_high = 8.*u.mHz.to('Hz')*u.Hz
f_IMS_break = 2.*u.mHz.to('Hz')*u.Hz
A_acc = 3e-15*u.m/u.s/u.s
A_IMS = 10e-12*u.m

Background = True

LISA_prop1_w_background = detector.SpaceBased('LISA w/Background',\
                          LISA_T_obs,L,A_acc,f_acc_break_low,f_acc_break_high,A_IMS,f_IMS_break,\
                          Background=Background)

LISA Proposal 2

Values from Robson, Cornish, and Liu 2019 https://arxiv.org/abs/1803.01944 using the Transfer Function Approximation within. (Note the factor of 2 change from summing 2 independent low-frequency data channels assumed in the paper.)

f_acc_break_low = .4*u.mHz.to('Hz')*u.Hz
f_acc_break_high = 8.*u.mHz.to('Hz')*u.Hz
f_IMS_break = 2.*u.mHz.to('Hz')*u.Hz
A_acc = 3e-15*u.m/u.s/u.s
A_IMS = 1.5e-11*u.m
Background = False

LISA_prop2 = detector.SpaceBased('LISA Approximate',
                                 LISA_T_obs,L,A_acc,f_acc_break_low,f_acc_break_high,A_IMS,f_IMS_break,
                                 Background=Background,T_type='A')

Plots of Generated LISA Detectors

fig = plt.figure()
plt.loglog(LISA_prop1.fT,LISA_prop1.h_n_f,label=r'LISA: L3 Proposal, Amaro-Seoane et al., (2017)')
plt.loglog(LISA_prop1_w_background.fT,LISA_prop1_w_background.h_n_f,label=r'LISA: L3 Proposal + Background',
           linestyle='--')
plt.loglog(LISA_prop2.fT,LISA_prop2.h_n_f,label=r'Robson et al., (2019)',zorder=-1)
plt.xlabel(r'Frequency [Hz]')
plt.ylabel(r'Characteristic Strain')
plt.tick_params(axis = 'both',which = 'major')
plt.legend()
plt.show()
_images/strain_plot_tutorial_67_0.png

Generating Ground Based Detector Designs with gwent

First we set a fiducial observation time-length

Ground_T_obs = 4*u.yr

aLIGO

aLIGO_prop1 = detector.GroundBased('aLIGO',Ground_T_obs,f_low=min(aLIGO_1.fT),f_high=max(aLIGO_1.fT))

If one wanted to change the parameters from the fiducial values, you could set up a new noise dictionary, then initialize that instument with the new values. It also works for updating the current instrument values.

noise_dict = {'Infrastructure':
                {'Length':2500},
              'Materials':
                {'Substrate':{'Temp':500}}}
aLIGO_prop2 = detector.GroundBased('aLIGO prop 2',Ground_T_obs,noise_dict=noise_dict)

A+

Aplus_prop1 = detector.GroundBased('Aplus',Ground_T_obs,f_low=min(aLIGO_1.fT),f_high=max(aLIGO_1.fT))

If you want to see what the current instrument parameters are, and what you can vary, you can use the instrument.Get_Noise_Dict(). To access each parameter, you must make a noise dictionary like above that matches the depth of the parameter you wish to change.

Aplus_prop1.Get_Noise_Dict()
Infrastructure Parameters:
     Length : 3995
     Temp : 290
     ResidualGas Subparameters:
          pressure : 4e-07
          mass : 3.35e-27
          polarizability : 7.8e-31
TCS Parameters:
     s_cc : 7.024
     s_cs : 7.321
     s_ss : 7.631
     SRCloss : 0.0
Seismic Parameters:
     Site : LHO
     KneeFrequency : 10
     LowFrequencyLevel : 1e-09
     Gamma : 0.8
     Rho : 1800.0
     Beta : 0.8
     Omicron : 1
     TestMassHeight : 1.5
     RayleighWaveSpeed : 250
Suspension Parameters:
     Type : Quad
     FiberType : Tapered
     BreakStress : 750000000.0
     Temp : 290
     Silica Subparameters:
          Rho : 2200.0
          C : 772
          K : 1.38
          Alpha : 3.9e-07
          dlnEdT : 0.000152
          Phi : 4.1e-10
          Y : 72000000000.0
          Dissdepth : 0.015
     C70Steel Subparameters:
          Rho : 7800
          C : 486
          K : 49
          Alpha : 1.2e-05
          dlnEdT : -0.00025
          Phi : 0.0002
          Y : 212000000000.0
     MaragingSteel Subparameters:
          Rho : 7800
          C : 460
          K : 20
          Alpha : 1.1e-05
          dlnEdT : 0
          Phi : 0.0001
          Y : 187000000000.0
     Silicon Subparameters:
          Rho : 2329
          C : 300
          K : 700
          Alpha : 1e-10
          dlnEdT : -2e-05
          Phi : 2e-09
          Y : 155800000000.0
          Dissdepth : 0.0015
     Stage : array of shape 4
     Ribbon Subparameters:
          Thickness : 0.000115
          Width : 0.00115
     Fiber Subparameters:
          Radius : 0.000205
          EndRadius : 0.0004
          EndLength : 0.045
     VHCoupling Subparameters:
          theta : 0.0006263620827519167
     hForce : array of shape (1000,)
     vForce : array of shape (1000,)
     hForce_singlylossy : array of shape (4, 1000)
     vForce_singlylossy : array of shape (4, 1000)
     hTable : array of shape (1000,)
     vTable : array of shape (1000,)
Materials Parameters:
     MassRadius : 0.17
     MassThickness : 0.2
     Coating Subparameters:
          Yhighn : 124000000000.0
          Sigmahighn : 0.28
          CVhighn : 2100000.0
          Alphahighn : 3.6e-06
          Betahighn : 1.4e-05
          ThermalDiffusivityhighn : 33
          Indexhighn : 2.06539
          Phihighn : 9e-05
          Phihighn_slope : 0.1
          Ylown : 72000000000.0
          Sigmalown : 0.17
          CVlown : 1641200.0
          Alphalown : 5.1e-07
          Betalown : 8e-06
          ThermalDiffusivitylown : 1.38
          Indexlown : 1.45
          Philown : 1.25e-05
          Philown_slope : 0.4
     Substrate Subparameters:
          Temp : 295
          c2 : 7.6e-12
          MechanicalLossExponent : 0.77
          Alphas : 5.2e-12
          MirrorY : 72700000000.0
          MirrorSigma : 0.167
          MassDensity : 2200.0
          MassAlpha : 3.9e-07
          MassCM : 739
          MassKappa : 1.38
          RefractiveIndex : 1.45
     MirrorVolume : 0.01815840553774901
     MirrorMass : 39.948492183047826
Laser Parameters:
     Wavelength : 1.064e-06
     Power : 125
Optics Parameters:
     Type : SignalRecycled
     PhotoDetectorEfficiency : 0.9
     Loss : 3.75e-05
     BSLoss : 0.0005
     coupling : 1.0
     SubstrateAbsorption : 5e-05
     pcrit : 10
     Quadrature Subparameters:
          dc : 1.5707963
     ITM Subparameters:
          Transmittance : 0.014
          CoatingThicknessLown : 0.308
          CoatingThicknessCap : 0.5
          CoatingAbsorption : 5e-07
          Thickness : 0.2
          CoatLayerOpticalThickness : array of shape (16,)
          BeamRadius : 0.05549089680470938
     ETM Subparameters:
          Transmittance : 5e-06
          CoatingThicknessLown : 0.27
          CoatingThicknessCap : 0.5
          CoatLayerOpticalThickness : array of shape (38,)
          BeamRadius : 0.06203311014519086
     PRM Subparameters:
          Transmittance : 0.03
     SRM Subparameters:
          Transmittance : 0.325
          CavityLength : 55
          Tunephase : 0.0
     Curvature Subparameters:
          ITM : 1970
          ETM : 2192
Squeezer Parameters:
     Type : Freq Dependent
     AmplitudedB : 12
     InjectionLoss : 0.05
     SQZAngle : 0
     LOAngleRMS : 0.03
     FilterCavity Subparameters:
          L : 300
          Te : 1e-06
          Lrt : 6e-05
          Rot : 0
          fdetune : -45.78
          Ti : 0.0012
gwinc Parameters:
     PRfixed : True
     pbs : 5351.309810308315
     parm : 750599.8555500002
     finesse : 446.4074818600061
     prfactor : 42.81047848246652
     gITM : -1.0279187817258881
     gETM : -0.822536496350365
     BeamWaist : 0.011750961823848846
     BeamRayleighRange : 407.7134846079674
     BeamWaistToITM : 1881.657523510972
     BeamWaistToETM : 2113.3424764890283
     dhdl_sqr : array of shape (1000,)
     sinc_sqr : array of shape (1000,)

Number of Variables:  150

Voyager

Voyager_prop1 = detector.GroundBased('Voyager',Ground_T_obs)

Cosmic Explorer

CE1_prop1 = detector.GroundBased('CE1',Ground_T_obs)

Plots of Generated Ground Based Detectors

fig = plt.figure()
plt.loglog(aLIGO_prop1.fT,aLIGO_prop1.h_n_f,label='Advanced LIGO Prop 1')
plt.loglog(aLIGO_prop2.fT,aLIGO_prop2.h_n_f,label='Advanced LIGO Prop 2')

plt.loglog(ET_D.fT,ET_D.h_n_f,label='Hild et al., (2011) ET Design D')
plt.loglog(Aplus_prop1.fT,Aplus_prop1.h_n_f,label='LIGO A+',
           linestyle=':')
plt.loglog(Voyager_prop1.fT,Voyager_prop1.h_n_f,label='Voyager',
           linestyle='--')
plt.loglog(CE1_prop1.fT,CE1_prop1.h_n_f,label='Cosmic Explorer Proposal 1')
plt.xlabel(r'Frequency [Hz]')
plt.ylabel(r'Characteristic Strain')
plt.tick_params(axis = 'both',which = 'major')
plt.legend()
plt.show()
_images/strain_plot_tutorial_83_0.png

Generating Binary Black Holes with gwent in the Frequency Domain

We start with BBH parameters that exemplify the range of IMRPhenomD’s waveforms from Khan, et al. 2016 https://arxiv.org/abs/1508.07253 and Husa, et al. 2016 https://arxiv.org/abs/1508.07250

For more information see the tutorial on source strains.

M = [1e6,65.0,1e10]
q = [1.0,18.0,1.0]
x1 = [0.5,0.0,-0.95]
x2 = [0.2,0.0,-0.95]
z = [3.0,0.093,20.0]

Uses the first parameter values and the LISA_prop1 detector model for the observation time with the precessing phenomenological lalsuite waveform IMRPhenomPv3.

lalsuite_kwargs = {"S1x": 0.5, "S1y": 0., "S1z": x1[0],
                   "S2x": -0.2, "S2y": 0.5, "S2z": x2[0],
                   "inclination":np.pi/2}
source_1 = binary.BBHFrequencyDomain(M[0],q[0],z[0],instrument=LISA_prop1,
                                     approximant='IMRPhenomPv3',lalsuite_kwargs=lalsuite_kwargs)

Uses the first parameter values and the aLIGO detector model for the observation time.

source_2 = binary.BBHFrequencyDomain(M[1],q[1],z[1],x1[1],x2[1],instrument=aLIGO_1)

Uses the first parameter values and the SKA_WN detector model for the observation time.

source_3 = binary.BBHFrequencyDomain(M[2],q[2],z[2],x1[2],x2[2],instrument=SKA_WN)

To display the time it takes for each source to evolve, we find several markers in time: 200 years prior to merger, T_obs until merger, and one year until merger. In each call, we assume the time to merger is in the observer frame (i.e., in_frame = 'observer')

t_year = u.yr.to('s')*u.s
t_200_year = 200.*t_year
#Source 1
source_1_t_200_year_f = binary.Get_Source_Freq(source_1,t_200_year,
                                               in_frame='observer',out_frame='observer')
idx1 = np.abs(source_1.f-source_1_t_200_year_f).argmin()
source_1_t_200_year_h = binary.Get_Char_Strain(source_1)[idx1]

source_1_t_year_f = binary.Get_Source_Freq(source_1,t_year,
                                           in_frame='observer',out_frame='observer')
idx2 = np.abs(source_1.f-source_1_t_year_f).argmin()
source_1_t_year_h = binary.Get_Char_Strain(source_1)[idx2]

source_1_t_T_obs_f = binary.Get_Source_Freq(source_1,source_1.instrument.T_obs,
                                            in_frame='observer',out_frame='observer')
idx3 = np.abs(source_1.f-source_1_t_T_obs_f).argmin()
source_1_t_T_obs_h = binary.Get_Char_Strain(source_1)[idx3]
#Source 2
source_2_t_200_year_f = binary.Get_Source_Freq(source_2,t_200_year,
                                               in_frame='observer',out_frame='observer')
idx4 = np.abs(source_2.f-source_2_t_200_year_f).argmin()
source_2_t_200_year_h = binary.Get_Char_Strain(source_2)[idx4]

source_2_t_year_f = binary.Get_Source_Freq(source_2,t_year,
                                           in_frame='observer',out_frame='observer')
idx5 = np.abs(source_2.f-source_2_t_year_f).argmin()
source_2_t_year_h = binary.Get_Char_Strain(source_2)[idx5]

source_2_t_T_obs_f = binary.Get_Source_Freq(source_2,source_2.instrument.T_obs,
                                            in_frame='observer',out_frame='observer')
idx6 = np.abs(source_2.f-source_2_t_T_obs_f).argmin()
source_2_t_T_obs_h = binary.Get_Char_Strain(source_2)[idx6]
#Source 3
source_3_t_200_year_f = binary.Get_Source_Freq(source_3,t_200_year,
                                               in_frame='observer',out_frame='observer')
idx7 = np.abs(source_3.f-source_3_t_200_year_f).argmin()
source_3_t_200_year_h = binary.Get_Char_Strain(source_3)[idx7]

source_3_t_year_f = binary.Get_Source_Freq(source_3,t_year,
                                           in_frame='observer',out_frame='observer')
idx8 = np.abs(source_3.f-source_3_t_year_f).argmin()
source_3_t_year_h = binary.Get_Char_Strain(source_3)[idx8]

source_3_t_T_obs_f = binary.Get_Source_Freq(source_3,np.unique(np.max(source_3.instrument.T_obs)),
                                            in_frame='observer',out_frame='observer')
idx9 = np.abs(source_3.f-source_3_t_T_obs_f).argmin()
source_3_t_T_obs_h = binary.Get_Char_Strain(source_3)[idx9]

Plots of Entire GW Band

Displays only generated detectors: WN only PTAs, ESA L3 proposal LISA, aLIGO, and Einstein Telescope.

Displays three sources’ waveform along with their monochromatic strain if they were observed by the initialized instrument at the detector’s most sensitive frequency throughout its observing run (from left to right: SKA_WN,LISA_prop1,ET).

fig,ax = plt.subplots()
zord = 10.

ax.loglog(SKA_WN.fT,SKA_WN.h_n_f,label = r'IPTA ($\sim$2030s)')
ax.loglog(NANOGrav_11yr_hasasia.fT,NANOGrav_11yr_hasasia.h_n_f,label = 'NANOGrav (2018)')
ax.loglog(LISA_prop1.fT,LISA_prop1.h_n_f,label = 'LISA ($\sim$2030s)')
ax.loglog(aLIGO_1.fT,aLIGO_1.h_n_f,label = 'aLIGO (2016)')
ax.loglog(ET_D.fT,ET_D.h_n_f,label = 'Einstein Telescope ($\sim$2030s)')

ax.loglog(source_3.f,binary.Get_Char_Strain(source_3),
          label = r'$M = 10^{%.0f}$ $\mathrm{M}_{\odot}$, $q = %.1f$, $z = %.1f$, $\chi_{i} = %.2f$' %(np.log10(M[2]),q[2],z[2],x1[2]))

ax.loglog(source_1.f,binary.Get_Char_Strain(source_1),
          label = r'$M = 10^{%.0f}$ $\mathrm{M}_{\odot}$, $q = %.1f$, $z = %.1f$, $\chi_{i} = %.2f$' %(np.log10(M[0]),q[0],z[0],x1[0]))

ax.loglog(source_2.f,binary.Get_Char_Strain(source_2),
          label = r'$M = %.0f$ $\mathrm{M}_{\odot}$, $q = %.1f$, $z = %.1f$, $\chi_{i} = %.1f$' %(M[1],q[1],z[1],x1[1]))

#Source 1
ax.scatter(source_1_t_200_year_f.value,source_1_t_200_year_h,color='C8',zorder=zord,marker='x',
            label=r'$\tau = %.0f$ yrs' %t_200_year.to('yr').value)
ax.scatter(source_1_t_year_f.value,source_1_t_year_h,color='C8',zorder=zord,marker='1',
            label=r'$\tau = %.0f$ yr' %t_year.to('yr').value)
ax.scatter(source_1_t_T_obs_f.value,source_1_t_T_obs_h,color='C8',zorder=zord,marker='+',
            label=r'$\tau = T_{\mathrm{obs}}$')
#Source 2
ax.scatter(source_2_t_200_year_f.value,source_2_t_200_year_h,color='C8',zorder=zord,marker='x')
ax.scatter(source_2_t_year_f.value,source_2_t_year_h,color='C8',zorder=zord,marker='1')
ax.scatter(source_2_t_T_obs_f.value,source_2_t_T_obs_h,color='C8',zorder=zord,marker='+')
#Source 3
ax.scatter(source_3_t_200_year_f.value,source_3_t_200_year_h,color='C8',zorder=zord,marker='x')
ax.scatter(source_3_t_year_f.value,source_3_t_year_h,color='C8',zorder=zord,marker='1')
ax.scatter(source_3_t_T_obs_f.value,source_3_t_T_obs_h,color='C8',zorder=zord,marker='+')

xlabel_min = -10
xlabel_max = 4
xlabels = np.arange(xlabel_min,xlabel_max+1)
#xlabels = xlabels[1::2]

ax.set_xticks(10.**xlabels)
print_xlabels = []
for x in xlabels:
    if abs(x) > 1:
        print_xlabels.append(r'$10^{%i}$' %x)
    elif x == -1:
        print_xlabels.append(r'$%.1f$' %10.**x)
    else:
        print_xlabels.append(r'$%.0f$' %10.**x)
ax.set_xticklabels([label for label in print_xlabels],rotation=30)

ax.set_xlim([3e-10, 1e4])
ax.set_ylim([1e-24, 1e-11])

ax.set_xlabel('Frequency [Hz]')
ax.set_ylabel('Characteristic Strain')
ax.legend(loc='upper right',fontsize=6)
plt.show()
_images/strain_plot_tutorial_98_0.png