Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Combined plotifar #5034

Merged
merged 5 commits into from
Feb 10, 2025
Merged
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
168 changes: 168 additions & 0 deletions bin/plotting/pycbc_page_ifar_vs_stat
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
#!/usr/bin/env python
import sys, h5py
import matplotlib
matplotlib.use('agg')
from matplotlib import pyplot as plt
import numpy as np
import argparse, logging
from pycbc import init_logging, add_common_pycbc_options, results
from pycbc.events import significance
from pycbc.conversions import sec_to_year as convert_s_to_y

plt.rcParams.update({
"text.usetex": True,
})

parser = argparse.ArgumentParser(usage='pycbc_page_ifar_vs_stat [--options]',
description='Plots cumulative IFAR vs stat for'
'backgrounds of different event types.')
add_common_pycbc_options(parser)
# get singles fit options
significance.insert_significance_option_group(parser)
parser.add_argument('--trigger-files', nargs='+',
help='Paths to separate-event-type statmap files.')
parser.add_argument('--ifo-combos', nargs='+',
help='Which event types (detector combinations) to plot.')
tdent marked this conversation as resolved.
Show resolved Hide resolved
parser.add_argument('--output-file', required=True,
help='Path to output plot.')
parser.add_argument("--loudest-keep-values",
default='[6:1]',
help="Apply successive multiplicative levels of"
" decimation to coincs with stat value below the"
" given thresholds. Supply as a comma-separated list"
" of threshold:decimation value pairs surrounded by"
" square brackets (no spaces!). Decimation values must"
" be positive integers."
" Ex. [15:5,10:30,5:30,0:30]."
" Default: no decimation")
opts = parser.parse_args()
init_logging(opts.verbose)

sig_dict = significance.digest_significance_options(opts.ifo_combos, opts)

coinc_color_map = {
'H': '#ee0000', # red
'L': '#4ba6ff', # blue
'V': '#9b59b6', # magenta/purple
'HL': '#0000DD',
'LV': '#FFCC33',
'HV': '#990000',
'HLV': np.array([20, 120, 20]) / 255.}
tdent marked this conversation as resolved.
Show resolved Hide resolved

coinc_line_map = {
'H': '--',
'L': '--',
'V': '--',
'HL': '-',
'LV': '-',
'HV': '-',
'HLV':'-'
}

exc_zlag_filenames = []
# Not sure what this step does precisely - select the first matching file ?
tdent marked this conversation as resolved.
Show resolved Hide resolved
for coinc_key in [f'/{k}-' for k in opts.ifo_combos]:
exc_zlag_filenames.append([f for f in opts.trigger_files if coinc_key in f][0])
logging.info('Got files: ', ', '.join(exc_zlag_filenames))

loudest_keep_vals = opts.loudest_keep_values.strip('[]').split(',')
threshes = []
factors = []
for decstr in loudest_keep_vals:
thresh, factor = decstr.split(':')
if float(factor) % 1:
raise RuntimeError("Non-integer decimation is not supported")
if int(factor) < 1:
raise RuntimeError("Negative or zero decimation does not make sense")
if int(factor) == 1:
continue
threshes.append(float(thresh))
factors.append(int(factor))

# Sort the threshes into descending order
# - allows decimation factors to be given in any order
threshorder = np.argsort(threshes)[::-1]
decimation_stat = np.array(threshes)[threshorder]
decimation_fact = np.array(factors)[threshorder]
tdent marked this conversation as resolved.
Show resolved Hide resolved

fig = plt.figure(figsize=(9, 6))
ax = fig.add_subplot(111)

ifar_calc_points = np.linspace(-10, 30, 100)

singles = []
for exc_zlag_filename in exc_zlag_filenames:
logging.info(f"opening file {exc_zlag_filename}")
with h5py.File(exc_zlag_filename,'r') as exc_zlag_f:
event_ifos = exc_zlag_f.attrs['ifos'].split()
coinc_key = ''.join(event_ifos).replace('1', '')
stat_exc = exc_zlag_f['background_exc']['stat'][:]
stat = exc_zlag_f['background']['stat'][:]
dec_fac = exc_zlag_f['background']['decimation_factor'][:]
tdent marked this conversation as resolved.
Show resolved Hide resolved
dec_fac_exc = exc_zlag_f['background_exc']['decimation_factor'][:]
bg_time = convert_s_to_y(exc_zlag_f.attrs['background_time_exc'])
ifar_file = exc_zlag_f['background_exc']['ifar'][:]

logging.info(f"Min {coinc_key} IFAR: {min(ifar_file)}")
logging.info(f"{coinc_key} background time (y): {bg_time}")
if len(event_ifos) == 1:
tdent marked this conversation as resolved.
Show resolved Hide resolved
ifo = event_ifos[0]
singles.append(ifo)
fit_thresh = sig_dict[ifo]['fit_threshold']
_, far, _ = significance.get_far(stat_exc,
ifar_calc_points,
dec_fac_exc,
bg_time,
**sig_dict[ifo])

# Plot n-louder points with a solid line and sngl fits with dashed
ax.plot(ifar_calc_points[ifar_calc_points < fit_thresh],
far[ifar_calc_points < fit_thresh],
'-', c=coinc_color_map[coinc_key], zorder=-5)
ax.plot(ifar_calc_points[ifar_calc_points > fit_thresh],
far[ifar_calc_points > fit_thresh],
coinc_line_map[coinc_key],
c=coinc_color_map[coinc_key], label=coinc_key, zorder=-5)
del ifo, fit_thresh # avoid variables hanging around

else:
_, far = significance.get_far(stat_exc,
ifar_calc_points,
dec_fac_exc,
bg_time,
method='n_louder')

ax.plot(ifar_calc_points, far, '-',
c=coinc_color_map[coinc_key], label=coinc_key, zorder=-5)

del far # avoid variable hanging around

# Plot the thresholds
for ifo in singles:
ax.axvline(sig_dict[ifo]['fit_threshold'], ls='--', zorder=-10,
c=coinc_color_map[ifo.rstrip('1')])

ax.semilogy()
ax.legend(ncol=2, fontsize=12)
ax.grid()
ax.set_xlim([-10, 30])
ax.set_ylim([1e-3, 1e6])
yticks = ax.get_yticks()
ax.set_yticklabels(['$10^{%d}$' % np.log10(t) for t in yticks], fontsize=14)
xticks = ax.get_xticks()
ax.set_xticklabels(['%d' % t for t in xticks], fontsize=14)
ax.set_xlabel('Ranking Statistic', fontsize=16)
ax.set_ylabel('Cumulative Event Rate [y$^{-1}$]', fontsize=16)

# Save
caption = 'Cumulative rates of noise events for separate event types. Solid ' \
'lines represent estimates from counts of louder (zerolag or time ' \
'shifted) events. Dashed lines represent estimates from fit ' \
'extrapolation for single-detector events.'
tdent marked this conversation as resolved.
Show resolved Hide resolved

results.save_fig_with_metadata(fig, opts.output_file,
fig_kwds={'bbox_inches': 'tight'},
title='Cumulative Rate vs. Statistic',
caption=caption,
cmd=' '.join(sys.argv))

Loading