# Copyright (C) 2017 Christopher M. Biwer
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 3 of the License, or (at your
# option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
# Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
""" This modules contains functions for reading single and coincident triggers
from the command line.
"""
import logging
import h5py
import numpy
from pycbc import conversions, pnutils
from pycbc.events import coinc
import pycbc.detector
logger = logging.getLogger('pycbc.events.triggers')
[docs]
def insert_bank_bins_option_group(parser):
""" Add options to the optparser object for selecting templates in bins.
Parameters
-----------
parser : object
OptionParser instance.
"""
bins_group = parser.add_argument_group(
"Options for selecting templates in bins.")
bins_group.add_argument("--bank-bins", nargs="+", default=None,
help="Ordered list of mass bin upper boundaries. "
"An ordered list of type-boundary pairs, "
"applied sequentially. Must provide a name "
"(can be any unique string for tagging "
"purposes), the parameter to bin "
"on, and the membership condition via "
"'lt' / 'gt' operators. "
"Ex. name1:component:lt2 name2:total:lt15")
bins_group.add_argument("--bank-file", default=None,
help="HDF format template bank file.")
bins_group.add_argument("--f-lower", default=None,
help="Low frequency cutoff in Hz.")
return bins_group
[docs]
def bank_bins_from_cli(opts):
""" Parses the CLI options related to binning templates in the bank.
Parameters
----------
opts : object
Result of parsing the CLI with OptionParser.
Results
-------
bins_idx : dict
A dict with bin names as key and an array of their indices as value.
bank : dict
A dict of the datasets from the bank file.
"""
bank = {}
fp = h5py.File(opts.bank_file)
for key in fp.keys():
bank[key] = fp[key][:]
bank["f_lower"] = float(opts.f_lower) if opts.f_lower else None
if opts.bank_bins:
bins_idx = coinc.background_bin_from_string(opts.bank_bins, bank)
else:
bins_idx = {"all" : numpy.arange(0, len(bank[tuple(fp.keys())[0]]))}
fp.close()
return bins_idx, bank
[docs]
def get_mass_spin(bank, tid):
"""
Helper function
Parameters
----------
bank : h5py File object
Bank parameter file
tid : integer or array of int
Indices of the entries to be returned
Returns
-------
m1, m2, s1z, s2z : tuple of floats or arrays of floats
Parameter values of the bank entries
"""
m1 = bank['mass1'][:][tid]
m2 = bank['mass2'][:][tid]
s1z = bank['spin1z'][:][tid]
s2z = bank['spin2z'][:][tid]
return m1, m2, s1z, s2z
[docs]
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
[docs]
def get_found_param(injfile, bankfile, trigfile, param, ifo, args=None):
"""
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'
args : Namespace object returned from ArgumentParser instance
Calling code command line options, used for f_lower value
Returns
-------
[return value]: NumPy array of floats, array of boolean
The calculated parameter values and a Boolean mask indicating which
injections were found in the given ifo (if supplied)
"""
foundtmp = injfile["found_after_vetoes/template_id"][:]
# will record whether inj was found in the given ifo
found_in_ifo = numpy.ones_like(foundtmp, dtype=bool)
if trigfile is not None:
try: # old 2-ifo behaviour
# 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]]
except IndexError: # multi-ifo
foundtrg = injfile["found_after_vetoes/%s/trigger_id" % ifo]
# multi-ifo pipeline assigns -1 for inj not found in specific ifo
found_in_ifo = foundtrg[:] != -1
if bankfile is not None and param in bankfile.keys():
return bankfile[param][:][foundtmp], found_in_ifo
elif trigfile is not None and param in trigfile[ifo].keys():
return trigfile[ifo][param][:][foundtrg], found_in_ifo
else:
assert bankfile
b = bankfile
return get_param(param, args, b['mass1'][:], b['mass2'][:],
b['spin1z'][:], b['spin2z'][:])[foundtmp],\
found_in_ifo
[docs]
def get_inj_param(injfile, param, ifo, args=None):
"""
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'
args: Namespace object returned from ArgumentParser instance
Calling code command line options, used for f_lower value
Returns
-------
[return value]: NumPy array of floats
The calculated parameter values
"""
det = pycbc.detector.Detector(ifo)
inj = injfile["injections"]
if param in inj.keys():
return inj[param][:]
if param == "end_time_"+ifo[0].lower():
return inj['end_time'][:] + det.time_delay_from_earth_center(
inj['longitude'][:],
inj['latitude'][:],
inj['end_time'][:])
else:
return get_param(param, args, inj['mass1'][:], inj['mass2'][:],
inj['spin1z'][:], inj['spin2z'][:])