def setUp(self, *args): self.numtests = 1000 self.precision = 1e-8 self.f_lower = 10. # create some component masses to work with self.m1 = numpy.random.uniform(1., 100., size=self.numtests) self.m2 = numpy.random.uniform(1., 100., size=self.numtests) # create some spins to work with spin_angledist = distributions.UniformSolidAngle() rvals = spin_angledist.rvs(size=self.numtests) self.spin1_polar = rvals['theta'] self.spin1_az = rvals['phi'] self.spin1_amp = numpy.random.uniform(0., 1., size=self.numtests) rvals = spin_angledist.rvs(size=self.numtests) self.spin2_polar = rvals['theta'] self.spin2_az = rvals['phi'] self.spin2_amp = numpy.random.uniform(0., 1., size=self.numtests) # calculate derived parameters from each self.mp = conversions.primary_mass(self.m1, self.m2) self.ms = conversions.secondary_mass(self.m1, self.m2) self.mtotal = conversions.mtotal_from_mass1_mass2(self.m1, self.m2) self.q = conversions.q_from_mass1_mass2(self.m1, self.m2) self.invq = conversions.invq_from_mass1_mass2(self.m1, self.m2) self.mchirp = conversions.mchirp_from_mass1_mass2(self.m1, self.m2) self.eta = conversions.eta_from_mass1_mass2(self.m1, self.m2) self.tau0 = conversions.tau0_from_mtotal_eta(self.mtotal, self.eta, self.f_lower) self.tau3 = conversions.tau3_from_mtotal_eta(self.mtotal, self.eta, self.f_lower) self.spin1x, self.spin1y, self.spin1z = \ coordinates.spherical_to_cartesian(self.spin1_amp, self.spin1_az, self.spin1_polar) self.spin2x, self.spin2y, self.spin2z = \ coordinates.spherical_to_cartesian(self.spin2_amp, self.spin2_az, self.spin2_polar) self.effective_spin = conversions.chi_eff(self.m1, self.m2, self.spin1z, self.spin2z) self.chi_p = conversions.chi_p(self.m1, self.m2, self.spin1x, self.spin1y, self.spin2x, self.spin2y) self.primary_spinx = conversions.primary_spin(self.m1, self.m2, self.spin1x, self.spin2x) self.primary_spiny = conversions.primary_spin(self.m1, self.m2, self.spin1y, self.spin2y) self.primary_spinz = conversions.primary_spin(self.m1, self.m2, self.spin1z, self.spin2z) self.secondary_spinx = conversions.secondary_spin(self.m1, self.m2, self.spin1x, self.spin2x) self.secondary_spiny = conversions.secondary_spin(self.m1, self.m2, self.spin1y, self.spin2y) self.secondary_spinz = conversions.secondary_spin(self.m1, self.m2, self.spin1z, self.spin2z)
def setUp(self, *args): self.numtests = 1000 self.precision = 1e-8 self.f_lower = 10. # create some component masses to work with self.m1 = numpy.random.uniform(1., 100., size=self.numtests) self.m2 = numpy.random.uniform(1., 100., size=self.numtests) # create some spins to work with spin_angledist = distributions.UniformSolidAngle() rvals = spin_angledist.rvs(size=self.numtests) self.spin1_polar = rvals['theta'] self.spin1_az = rvals['phi'] self.spin1_amp = numpy.random.uniform(0., 1., size=self.numtests) rvals = spin_angledist.rvs(size=self.numtests) self.spin2_polar = rvals['theta'] self.spin2_az = rvals['phi'] self.spin2_amp = numpy.random.uniform(0., 1., size=self.numtests) # calculate derived parameters from each self.mp = conversions.primary_mass(self.m1, self.m2) self.ms = conversions.secondary_mass(self.m1, self.m2) self.mtotal = conversions.mtotal_from_mass1_mass2(self.m1, self.m2) self.q = conversions.q_from_mass1_mass2(self.m1, self.m2) self.invq = conversions.invq_from_mass1_mass2(self.m1, self.m2) self.mchirp = conversions.mchirp_from_mass1_mass2(self.m1, self.m2) self.eta = conversions.eta_from_mass1_mass2(self.m1, self.m2) self.tau0 = conversions.tau0_from_mtotal_eta(self.mtotal, self.eta, self.f_lower) self.tau3 = conversions.tau3_from_mtotal_eta(self.mtotal, self.eta, self.f_lower) self.spin1x, self.spin1y, self.spin1z = \ coordinates.spherical_to_cartesian(self.spin1_amp, self.spin1_az, self.spin1_polar) self.spin2x, self.spin2y, self.spin2z = \ coordinates.spherical_to_cartesian(self.spin2_amp, self.spin2_az, self.spin2_polar) self.effective_spin = conversions.chi_eff(self.m1, self.m2, self.spin1z, self.spin2z) self.primary_spinx = conversions.primary_spin(self.m1, self.m2, self.spin1x, self.spin2x) self.primary_spiny = conversions.primary_spin(self.m1, self.m2, self.spin1y, self.spin2y) self.primary_spinz = conversions.primary_spin(self.m1, self.m2, self.spin1z, self.spin2z) self.secondary_spinx = conversions.secondary_spin(self.m1, self.m2, self.spin1x, self.spin2x) self.secondary_spiny = conversions.secondary_spin(self.m1, self.m2, self.spin1y, self.spin2y) self.secondary_spinz = conversions.secondary_spin(self.m1, self.m2, self.spin1z, self.spin2z)
def get_found_param(injfile, bankfile, trigfile, param, ifo): """ Translates some popular trigger parameters into functions that calculate them from an hdf found injection file Parameters ---------- injfile: hdf5 File object Injection file of format known to ANitz (DOCUMENTME) bankfile: hdf5 File object or None Template bank file trigfile: hdf5 File object or None Single-detector trigger file param: string Parameter to be calculated for the recovered triggers ifo: string or None Standard ifo name, ex. 'L1' Returns ------- [return value]: NumPy array of floats The calculated parameter values """ foundtmp = injfile["found_after_vetoes/template_id"][:] if trigfile is not None: # get the name of the ifo in the injection file, eg "detector_1" # and the integer from that name ifolabel = [name for name, val in injfile.attrs.items() if \ "detector" in name and val == ifo][0] foundtrg = injfile["found_after_vetoes/trigger_id" + ifolabel[-1]] if bankfile is not None and param in bankfile.keys(): return bankfile[param][:][foundtmp] elif trigfile is not None and param in trigfile[ifo].keys(): return trigfile[ifo][param][:][foundtrg] else: b = bankfile found_param_dict = { "mtotal" : (b['mass1'][:] + b['mass2'][:])[foundtmp], "mchirp" : conversions.mchirp_from_mass1_mass2(b['mass1'][:], b['mass2'][:])[foundtmp], "eta" : conversions.eta_from_mass1_mass2(b['mass1'][:], b['mass2'][:])[foundtmp], "effective_spin" : conversions.chi_eff(b['mass1'][:], b['mass2'][:], b['spin1z'][:], b['spin2z'][:])[foundtmp] } return found_param_dict[param]
def get_param(par, args, m1, m2, s1z, s2z): """ Helper function Parameters ---------- par : string Name of parameter to calculate args : Namespace object returned from ArgumentParser instance Calling code command line options, used for f_lower value m1 : float or array of floats First binary component mass (etc.) Returns ------- parvals : float or array of floats Calculated parameter values """ if par == 'mchirp': parvals = conversions.mchirp_from_mass1_mass2(m1, m2) elif par == 'mtotal': parvals = m1 + m2 elif par == 'eta': parvals = conversions.eta_from_mass1_mass2(m1, m2) elif par in ['chi_eff', 'effective_spin']: parvals = conversions.chi_eff(m1, m2, s1z, s2z) elif par == 'template_duration': # default to SEOBNRv4 duration function if not hasattr(args, 'approximant') or args.approximant is None: args.approximant = "SEOBNRv4" parvals = pnutils.get_imr_duration(m1, m2, s1z, s2z, args.f_lower, args.approximant) if args.min_duration: parvals += args.min_duration elif par == 'tau0': parvals = conversions.tau0_from_mass1_mass2(m1, m2, args.f_lower) elif par == 'tau3': parvals = conversions.tau3_from_mass1_mass2(m1, m2, args.f_lower) elif par in pnutils.named_frequency_cutoffs.keys(): parvals = pnutils.frequency_cutoff_from_name(par, m1, m2, s1z, s2z) else: # try asking for a LALSimulation frequency function parvals = pnutils.get_freq(par, m1, m2, s1z, s2z) return parvals
def get_param(par, args, m1, m2, s1z, s2z): """ Helper function Parameters ---------- par : string Name of parameter to calculate args : Namespace object returned from ArgumentParser instance Calling code command line options, used for f_lower value m1 : float or array of floats First binary component mass (etc.) Returns ------- parvals : float or array of floats Calculated parameter values """ if par == 'mchirp': parvals, _ = pnutils.mass1_mass2_to_mchirp_eta(m1, m2) elif par == 'mtotal': parvals = m1 + m2 elif par =='eta': parvals = conversions.eta_from_mass1_mass2(m1, m2) elif par in ['chi_eff', 'effective_spin']: parvals = conversions.chi_eff(m1, m2, s1z, s2z) elif par == 'template_duration': # default to SEOBNRv4 duration function parvals = pnutils.get_imr_duration(m1, m2, s1z, s2z, args.f_lower, args.approximant or "SEOBNRv4") if args.min_duration: parvals += args.min_duration elif par == 'tau0': parvals = conversions.tau0_from_mass1_mass2(m1, m2, args.f_lower) elif par == 'tau3': parvals = conversions.tau3_from_mass1_mass2(m1, m2, args.f_lower) elif par in pnutils.named_frequency_cutoffs.keys(): parvals = pnutils.frequency_cutoff_from_name(par, m1, m2, s1z, s2z) else: # try asking for a LALSimulation frequency function parvals = pnutils.get_freq(par, m1, m2, s1z, s2z) return parvals
def get_inj_param(injfile, param, ifo): """ Translates some popular injection parameters into functions that calculate them from an hdf found injection file Parameters ---------- injfile: hdf5 File object Injection file of format known to ANitz (DOCUMENTME) param: string Parameter to be calculated for the injected signals ifo: string Standard detector name, ex. 'L1' Returns ------- [return value]: NumPy array of floats The calculated parameter values """ det = pycbc.detector.Detector(ifo) time_delay = numpy.vectorize(#lambda dec, ra, t : det.time_delay_from_earth_center)#(dec, ra, t)) inj = injfile["injections"] if param in inj.keys(): return inj["injections/"+param] inj_param_dict = { "mtotal" : inj['mass1'][:] + inj['mass2'][:], "mchirp" : conversions.mchirp_from_mass1_mass2(inj['mass1'][:], inj['mass2'][:]), "eta" : conversions.eta_from_mass1_mass2(inj['mass1'][:], inj['mass2'][:]), "effective_spin" : conversions.chi_eff(inj['mass1'][:], inj['mass2'][:], inj['spin1z'][:], inj['spin2z'][:]), "end_time_"+ifo[0].lower() : inj['end_time'][:] + time_delay(inj['longitude'][:], inj['latitude'][:], inj['end_time'][:]), } return inj_param_dict[param]
def transform_masses(mass1, mass2, mchirp_mod, eta_mod): """Modifies masses given a difference in mchirp and eta. Parameters ---------- mass1 : float Mass of the larger object (already modified). mass2 : float Mass of the smaller object (already modified). mchirp_mod : tuple of (float, str) or None Tuple giving the modification value for ``mchirp``, and a string indicating whether the given modification is a fractional difference (``'fdiff'``), an absolute difference (``'absdiff'``), or a replacement (``'replace'``). If ``None``, the chirp mass will not be modified. eta_mod : tuple of (float, str) Same as ``mchirp_mod``, but for ``eta``. Returns ------- mass1 : float Modified mass1. mass2 : float Modified mass2. """ mchirp = conversions.mchirp_from_mass1_mass2(mass1, mass2) eta = conversions.eta_from_mass1_mass2(mass1, mass2) if mchirp_mod is not None: diff, modtype = mchirp_mod mchirp = apply_mod(mchirp, diff, modtype) if eta_mod is not None: diff, modtype = eta_mod eta = apply_mod(eta, diff, modtype) # make sure values are physical if (eta < 0 or eta > 0.25) or mchirp < 0: raise NoWaveformError("unphysical masses") m1 = conversions.mass1_from_mchirp_eta(mchirp, eta) m2 = conversions.mass2_from_mchirp_eta(mchirp, eta) return m1, m2
def eta(self): return conversions.eta_from_mass1_mass2(self.mass1, self.mass2)
def get_random_mass(numPoints, massRangeParams): """ This function will generate a large set of points within the chosen mass and spin space, and with the desired minimum remnant disk mass (this applies to NS-BH systems only). It will also return the corresponding PN spin coefficients for ease of use later (though these may be removed at some future point). Parameters ---------- numPoints : int Number of systems to simulate massRangeParams : massRangeParameters instance Instance holding all the details of mass ranges and spin ranges. Returns -------- mass1 : float Mass of heavier body. mass2 : float Mass of lighter body. spin1z : float Spin of body 1. spin2z : float Spin of body 2. """ # WARNING: We expect mass1 > mass2 ALWAYS # Check if EM contraints are required, i.e. if the systems must produce # a minimum remnant disk mass. If this is not the case, proceed treating # the systems as point particle binaries if massRangeParams.remnant_mass_threshold is None: mass1, mass2, spin1z, spin2z = \ get_random_mass_point_particles(numPoints, massRangeParams) # otherwise, load EOS dependent data, generate the EM constraint # (i.e. compute the minimum symmetric mass ratio needed to # generate a given remnant disk mass as a function of the NS # mass and the BH spin along z) and then proceed by accepting # only systems that can yield (at least) the desired remnant # disk mass and that pass the mass and spin range cuts. else: ns_sequence, max_ns_g_mass = load_ns_sequence(massRangeParams.ns_eos) boundary_mass = massRangeParams.ns_bh_boundary_mass if max_ns_g_mass < boundary_mass: warn_msg = "WARNING: " warn_msg += "Option of ns-bh-boundary-mass is %s " % ( boundary_mass) warn_msg += "which is higher than the maximum NS gravitational " warn_msg += "mass admitted by the EOS that was prescribed " warn_msg += "(%s). " % (max_ns_g_mass) warn_msg += "The code will proceed using the latter value " warn_msg += "as the boundary mass." logging.warn(warn_msg) boundary_mass = max_ns_g_mass # Empty arrays to store points that pass all cuts mass1_out = [] mass2_out = [] spin1z_out = [] spin2z_out = [] # As the EM cut can remove several randomly generated # binaries, track the number of accepted points that pass # all cuts and stop only once enough of them are generated numPointsFound = 0 while numPointsFound < numPoints: # Generate the random points within the required mass # and spin cuts mass1, mass2, spin1z, spin2z = \ get_random_mass_point_particles(numPoints-numPointsFound, massRangeParams) # Now proceed with cutting out EM dim systems # Use a logical mask to track points that do not correspond to # BBHs. The remaining points will be BNSs and NSBHs. # Further down, EM-dim NSBHs will also be removed. mask_not_bbh = numpy.zeros(len(mass1), dtype=bool) # Keep a point if: # 1) the secondary object is a not a BH (mass2 < boundary mass) # [Store masses and spins of non BBH] mask_not_bbh[mass2 < boundary_mass] = True mass1_not_bbh = mass1[mask_not_bbh] mass2_not_bbh = mass2[mask_not_bbh] spin1z_not_bbh = spin1z[mask_not_bbh] spin2z_not_bbh = spin2z[mask_not_bbh] # 2) and if the primary mass is a NS (i.e., it is a BNS), or... mask_nsbh = numpy.zeros(len(mass1_not_bbh), dtype=bool) # [mask_nsbh identifies NSBH systems] mask_nsbh[mass1_not_bbh > boundary_mass] = True # [mask_bns identifies BNS systems] mask_bns = ~mask_nsbh # [Store masses and spins of BNSs] mass1_bns = mass1_not_bbh[mask_bns] mass2_bns = mass2_not_bbh[mask_bns] spin1z_bns = spin1z_not_bbh[mask_bns] spin2z_bns = spin2z_not_bbh[mask_bns] # 3) ...it is an NS-BH with remnant mass greater than the threshold # required to have a counterpart # [Store masses and spins of all NSBHs] mass1_nsbh = mass1_not_bbh[mask_nsbh] mass2_nsbh = mass2_not_bbh[mask_nsbh] spin1z_nsbh = spin1z_not_bbh[mask_nsbh] spin2z_nsbh = spin2z_not_bbh[mask_nsbh] # [Store etas of all NSBHs] eta_nsbh = conversions.eta_from_mass1_mass2(mass1_nsbh, mass2_nsbh) # [mask_bright_nsbh will identify NSBH systems with high enough # threshold mass] mask_bright_nsbh = numpy.zeros(len(mass1_nsbh), dtype=bool) if eta_nsbh.size != 0: remnant = remnant_masses(eta_nsbh, mass2_nsbh, ns_sequence, spin1z_nsbh, 0.) mask_bright_nsbh[ remnant > massRangeParams.remnant_mass_threshold] = True # Keep only points that correspond to binaries that can produce an # EM counterpart (i.e., BNSs and EM-bright NSBHs) and add their # properties to the pile of accpeted points to output mass1_out = numpy.concatenate( (mass1_out, mass1_bns, mass1_nsbh[mask_bright_nsbh])) mass2_out = numpy.concatenate( (mass2_out, mass2_bns, mass2_nsbh[mask_bright_nsbh])) spin1z_out = numpy.concatenate( (spin1z_out, spin1z_bns, spin1z_nsbh[mask_bright_nsbh])) spin2z_out = numpy.concatenate( (spin2z_out, spin2z_bns, spin2z_nsbh[mask_bright_nsbh])) # Number of points that survived all cuts numPointsFound = len(mass1_out) # Ready to go mass1 = mass1_out mass2 = mass2_out spin1z = spin1z_out spin2z = spin2z_out return mass1, mass2, spin1z, spin2z
def mass1_mass2_to_mchirp_eta(mass1, mass2): m_chirp = conversions.mchirp_from_mass1_mass2(mass1, mass2) eta = conversions.eta_from_mass1_mass2(mass1, mass2) return m_chirp,eta
def mass1_mass2_to_mtotal_eta(mass1, mass2): m_total = conversions.mtotal_from_mass1_mass2(mass1, mass2) eta = conversions.eta_from_mass1_mass2(mass1, mass2) return m_total,eta