Skip to content

Commit 25f3609

Browse files
authored
O4b realtime (#58)
Small changes for v1.2.2: scripts to calculate bkg, schema v4.0.0, small bugfixes
1 parent b0f474c commit 25f3609

File tree

10 files changed

+243
-25
lines changed

10 files changed

+243
-25
lines changed

doc/source/conf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
project = 'FastResponseAnalysis'
1717
copyright = '2023, Alex Pizzuto, Jessie Thwaites'
1818
author = 'Alex Pizzuto, Jessie Thwaites'
19-
release = '1.2.1'
19+
release = '1.2.2'
2020

2121
# -- General configuration ---------------------------------------------------
2222
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration

fast_response/FastResponseAnalysis.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1220,7 +1220,12 @@ def unblind_TS(self):
12201220

12211221
def find_coincident_events(self):
12221222
r"""Find "coincident events" for the analysis.
1223-
These are ontime events that have a spatial times energy weight greater than 10
1223+
These are ontime events that satisfy:
1224+
1225+
Spatial weight * energy weight [* temporal weight] > 10
1226+
1227+
(Note that for this box time window, all events in the ontime window
1228+
have the same temporal weight.)
12241229
"""
12251230
spatial_weights = self.llh.llh_model.signal(
12261231
self.ra, self.dec, self.llh._events,
@@ -1294,7 +1299,7 @@ def upper_limit(self, n_per_sig=100, p0=None):
12941299
Returns
12951300
--------
12961301
upperlimit: float
1297-
Value of E^2 dN / dE in units of TeV / cm^2
1302+
Flux upper limit in [TeV cm^2 s]^-1
12981303
"""
12991304
if self.inj is None:
13001305
self.initialize_injector()

fast_response/listeners/gcn_listener.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,8 @@ def process_gcn(payload, root):
105105
print('--skymap={} --time={} --alert_id={}'.format(skymap, str(event_mjd), run_id+':'+event_id))
106106
return
107107

108-
print('Running {}'.format(command))
108+
print('\nRunning {} --skymap={} --time={} --alert_id={} --suffix={}'.format(
109+
command, skymap, str(event_mjd), run_id+':'+event_id, suffix))
109110
subprocess.call([command, '--skymap={}'.format(skymap),
110111
'--time={}'.format(str(event_mjd)),
111112
'--alert_id={}'.format(run_id+':'+event_id),

fast_response/listeners/gw_gcn_listener.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ def process_gcn(payload, root):
191191
webhook = f.readline().rstrip('\n')
192192
bot_name = f.readline().rstrip('\n')
193193

194-
for channel in ['#fra-shifting','#gwnu']:
194+
for channel in ['#fra-shifting','#gwnu-heartbeat']:
195195
bot = slackbot(channel, bot_name, webhook)
196196
bot.send_message(slack_message,'gw')
197197

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
#!/usr/bin/env python
2+
3+
r"""
4+
Run trials for background, with a given prior.
5+
Record TS, best-fit location, and fitted events
6+
around best fit location
7+
8+
"""
9+
import numpy as np
10+
import healpy as hp
11+
import os, argparse
12+
from astropy.time import Time
13+
import pickle
14+
15+
from fast_response.AlertFollowup import AlertFollowup
16+
17+
parser = argparse.ArgumentParser(description='Fast Response Analysis')
18+
parser.add_argument('--deltaT', type=float, default=None,
19+
help='Time Window in seconds')
20+
parser.add_argument('--ntrials', type=int, default = 10000,
21+
help='Trials')
22+
parser.add_argument("--alert_mjd", default=60298.0, type=float,
23+
help="mjd of alert event (default Dec 20, 2023)")
24+
parser.add_argument("--skymap", default=None, type=str,
25+
help='skymap link')
26+
parser.add_argument('--seed', default=1, type=int,
27+
help='Unique seed for running on the cluster')
28+
parser.add_argument('--outdir',type=str, default=None,
29+
help='Output directory to save npz (default = FAST_RESPONSE_OUTPUT env variable or cwd)')
30+
args = parser.parse_args()
31+
32+
if args.outdir == None:
33+
try:
34+
outdir = os.environ.get('FAST_RESPONSE_OUTPUT')
35+
except:
36+
outdir = './'
37+
else:
38+
outdir = args.outdir
39+
if not os.path.exists(outdir+'/trials/'):
40+
os.mkdir(outdir+'/trials/')
41+
outdir=outdir+'/trials/'
42+
43+
start_mjd = args.alert_mjd - (args.deltaT / 86400. /2.)
44+
stop_mjd = start_mjd + (args.deltaT / 86400.)
45+
start_iso = Time(start_mjd, format='mjd').iso
46+
stop_iso = Time(stop_mjd, format='mjd').iso
47+
deltaT = args.deltaT / 86400.
48+
49+
f = AlertFollowup('Precompute_trials_test', args.skymap,
50+
start_iso, stop_iso, save=False)
51+
# f.llh.nbackground=args.bkg*args.deltaT/1000.
52+
inj = f.initialize_injector() #just put this here to initialize f.spatial_prior
53+
# print(f.llh.nbackground)
54+
55+
ntrials = args.ntrials
56+
stop = ntrials * (args.seed+1)
57+
start = stop-ntrials
58+
seed_counter = start
59+
60+
npix = hp.nside2npix(f.nside)
61+
62+
ra, dec, TS_list =[], [], []
63+
ns, seed =[], []
64+
65+
for jj in range(ntrials):
66+
# seed_counter += 1
67+
seed_counter = np.random.randint(0, 1000000)
68+
val = f.llh.scan(0.0, 0.0, scramble=True, seed = seed_counter,
69+
spatial_prior = f.spatial_prior,
70+
time_mask = [deltaT / 2., (start_mjd + stop_mjd) / 2.],
71+
pixel_scan = [f.nside, f._pixel_scan_nsigma], inject = None)
72+
73+
try:
74+
maxLoc = np.argmax(val['TS_spatial_prior_0']) #pick out max of all likelihood ratios at diff pixels
75+
except ValueError:
76+
continue
77+
78+
TS_list.append(val['TS_spatial_prior_0'].max())
79+
ns.append(val['nsignal'][maxLoc])
80+
ra.append(val['ra'][maxLoc])
81+
dec.append(val['dec'][maxLoc])
82+
# gamma.append(val['gamma'][maxLoc]) #fixed gamma in llh
83+
seed.append(seed_counter)
84+
85+
print("DONE")
86+
87+
outfilename = outdir+'seed_delta_t_{:.1e}_{}.npz'.format(args.deltaT, seed_counter)
88+
results={
89+
'TS_List':TS_list,
90+
'ns_fit':ns,
91+
# 'gamma_fit':gamma,
92+
'ra':ra,
93+
'dec':dec,
94+
'seed':seed
95+
}
96+
print('saving everything')
97+
with open(outfilename, 'wb') as f:
98+
pickle.dump(results, f)
99+
100+
print("Saved to {}".format(outfilename))
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
'''
2+
Script to submit a bunch of trials with random seeds
3+
with a given spatial prior
4+
As needed for bkg trials in realtime
5+
'''
6+
7+
import pycondor
8+
import argparse
9+
import pwd, os
10+
import fast_response
11+
12+
parser = argparse.ArgumentParser(
13+
description='Submit script')
14+
parser.add_argument(
15+
'--outdir', type=str, required=True,
16+
help = 'Output directory (will make and output to a subdirectory in this directory called trials/)')
17+
parser.add_argument(
18+
'--skymap', type=str, required=True,
19+
help='Skymap path or link')
20+
parser.add_argument(
21+
'--alert_mjd', type=float, required=True,
22+
help='MJD of alert event')
23+
parser.add_argument(
24+
'--deltaT', type=float, default=172800., #[-0.1, +14]day: 1218240
25+
help='time window to use (in sec)')
26+
parser.add_argument(
27+
'--ntrials', type=int, default=10000,
28+
help='Number of precomputed trials to run, default 30,000')
29+
parser.add_argument(
30+
'--seed_start', type=int,default=0,
31+
help='Seed to start with when running trials')
32+
parser.add_argument(
33+
'--n_per_batch', default=500, type=int,
34+
help='Number of trials to run in each set (default: 500)')
35+
# parser.add_argument(
36+
# '--type', default='alert', type=str,
37+
# help='run alert or GW trials. options are alert (default) or gw')
38+
args = parser.parse_args()
39+
40+
if not os.path.exists(os.path.join(args.outdir, 'trials')):
41+
os.mkdir(os.path.join(args.outdir, 'trials'))
42+
print('Output trials to directory: {}/trials'.format(args.outdir))
43+
44+
fra_dir = os.path.dirname(fast_response.__file__)
45+
script = os.path.join(fra_dir, 'precomputed_background/alert_bkg_trials_withprior.py')
46+
deltaT = args.deltaT
47+
skymap = args.skymap
48+
alert_mjd = args.alert_mjd
49+
50+
username = pwd.getpwuid(os.getuid())[0]
51+
if not os.path.exists(f'/scratch/{username}/'):
52+
os.mkdir(f'/scratch/{username}/')
53+
if not os.path.exists(f'/scratch/{username}/fra/'):
54+
os.mkdir(f'/scratch/{username}/fra/')
55+
if not os.path.exists(f'/scratch/{username}/fra/condor/'):
56+
os.mkdir(f'/scratch/{username}/fra/condor')
57+
58+
error = f'/scratch/{username}/fra/condor/error'
59+
output = f'/scratch/{username}/fra/condor/output'
60+
log = f'/scratch/{username}/fra/condor/log'
61+
submit = f'/scratch/{username}/fra/condor/submit'
62+
63+
### Create Dagman to submit jobs to cluster
64+
job = pycondor.Job(
65+
'alert_precomp_trials',
66+
script,
67+
error=error,
68+
output=output,
69+
log=log,
70+
submit=submit,
71+
getenv=True,
72+
universe='vanilla',
73+
verbose=2,
74+
request_cpus=8,#10,
75+
request_memory=8000,#10000,
76+
extra_lines=[
77+
'should_transfer_files = YES',
78+
'when_to_transfer_output = ON_EXIT']
79+
)
80+
81+
for trial in range(int(args.ntrials / args.n_per_batch)):
82+
job.add_arg(f'--deltaT {deltaT} --ntrials {args.n_per_batch} --outdir {args.outdir} --skymap {skymap} --alert_mjd {alert_mjd}')
83+
84+
dagman = pycondor.Dagman(
85+
'fra_precompbg',
86+
submit=submit, verbose=2)
87+
88+
dagman.add_job(job)
89+
dagman.build_submit()
90+

fast_response/scripts/combine_results_kafka.py

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,7 @@ def format_ontime_events_uml(events, event_mjd):
9393
'localization':{
9494
'ra' : round(np.rad2deg(event['ra']), 2),
9595
'dec' : round(np.rad2deg(event['dec']), 2),
96-
"uncertainty_shape": "circle",
97-
'ra_uncertainty': [round(np.rad2deg(event['sigma']*2.145966),2)],
96+
'ra_dec_error': round(np.rad2deg(event['sigma']*2.145966),2),
9897
"containment_probability": 0.9,
9998
"systematic_included": False
10099
},
@@ -114,8 +113,7 @@ def format_ontime_events_llama(events):
114113
'localization':{
115114
'ra' : round(event['ra'], 2),
116115
'dec' : round(event['dec'], 2),
117-
"uncertainty_shape": "circle",
118-
'ra_uncertainty': [round(np.rad2deg(np.deg2rad(event['sigma'])*2.145966),3)],
116+
'ra_dec_error': round(np.rad2deg(np.deg2rad(event['sigma'])*2.145966),2),
119117
"containment_probability": 0.9,
120118
"systematic_included": False
121119
},
@@ -184,10 +182,10 @@ def parse_notice(record, wait_for_llama=False, heartbeat=False):
184182
if int(params['Significant'])==0:
185183
subthreshold=True
186184
logger.warning('low-significance alert found. ')
187-
if params['Group'] == 'Burst':
185+
if params['Group'] == 'Burst' or params["Pipeline"] =='CWB':
188186
wait_for_llama = False
189187
m = 'Significant' if not subthreshold else 'Subthreshold'
190-
logger.warning('{} burst alert found. '.format(m))
188+
logger.warning('{} burst or CWB alert found. '.format(m))
191189
if len(params['Instruments'].split(','))==1:
192190
#wait_for_llama = False
193191
logger.warning('One detector event found. ')
@@ -198,7 +196,7 @@ def parse_notice(record, wait_for_llama=False, heartbeat=False):
198196
return
199197

200198
collected_results = {}
201-
collected_results["$schema"]= "https://gcn.nasa.gov/schema/v3.0.0/gcn/notices/icecube/lvk_nu_track_search.schema.json"
199+
collected_results["$schema"]= "https://gcn.nasa.gov/schema/v4.0.0/gcn/notices/icecube/lvk_nu_track_search.schema.json"
202200
collected_results["type"]= "IceCube LVK Alert Nu Track Search"
203201

204202
eventtime = record.find('.//ISOTime').text
@@ -304,11 +302,14 @@ def parse_notice(record, wait_for_llama=False, heartbeat=False):
304302
else:
305303
logger.warning('Both analyses not finished after {:.0f} min wait.'.format(max_wait))
306304
logger.warning('Not sending GCN.')
305+
307306
if record.attrib['role']=='observation' and not heartbeat:
308-
err_msg = '--missing_llama=True --missing_uml=True' if not subthreshold else '--missing_llama=True'
307+
err_msg = ['/home/jthwaites/private/make_call.py', '--troubleshoot_gcn=True',
308+
'--missing_llama=True']
309+
if not subthreshold: err_msg.append('--missing_uml=True')
310+
309311
try:
310-
subprocess.call(['/home/jthwaites/private/make_call.py',
311-
'--troubleshoot_gcn=True', err_msg])
312+
subprocess.call(err_msg)
312313
except:
313314
logger.warning('Failed to send alert to shifters: Issue finding both results. ')
314315
return
@@ -482,7 +483,7 @@ def parse_notice(record, wait_for_llama=False, heartbeat=False):
482483
my_key = f.readline()
483484

484485
if not subthreshold:
485-
channels = ['#gwnu-heartbeat', '#gwnu','#alerts']
486+
channels = ['#gwnu-heartbeat', '#alerts']#, '#gwnu']
486487
else:
487488
channels = ['#gwnu-heartbeat']
488489
for channel in channels:
@@ -516,6 +517,23 @@ def parse_notice(record, wait_for_llama=False, heartbeat=False):
516517
logger.info('Sent alert to ROC for p<0.01')
517518
except:
518519
logger.warning('Failed to send email/SMS notification.')
520+
521+
# try:
522+
# if params['Group'] == 'Burst':
523+
# merger_type = 'Burst'
524+
# else:
525+
# k = ['BNS','NSBH','BBH']
526+
# probs = {j: float(params[j]) for j in k}
527+
# merger_type = max(zip(probs.values(), probs.keys()))[1]
528+
# except:
529+
# logger.info('Could not determine type of event')
530+
# merger_type = None
531+
532+
# try:
533+
# subprocess.call(['/home/jthwaites/private/make_call.py', f'--type={merger_type}', '--call_anyway'])
534+
# except Exception as e:
535+
# logger.warning('Call for p<0.01 failed.')
536+
519537
else:
520538
logger.info('p>0.01: no email/sms sent')
521539
else:

fast_response/scripts/run_track_followup.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
Author: Alex Pizzuto
77
May 2020'''
88

9-
import os, argparse
9+
import os, argparse, glob
1010
from astropy.time import Time
1111

1212
from fast_response.AlertFollowup import TrackFollowup
@@ -49,10 +49,14 @@
4949

5050
# look for contour files
5151
base_skymap_path = '/home/followup/output_plots/'
52-
contour_fs = [base_skymap_path \
53-
+ f'run{run_id:08d}.evt{ev_id:012d}.HESE.contour_{containment}.txt' \
54-
for containment in ['50', '90']]
55-
contour_fs = [f for f in contour_fs if os.path.exists(f)]
52+
contour_fs = []
53+
for containment in ['50', '90']:
54+
contour_fs = contour_fs + glob.glob(base_skymap_path +
55+
f'run{run_id:08d}.evt{ev_id:012d}.*.contour_{containment}.txt')
56+
# contour_fs = [base_skymap_path \
57+
# + f'run{run_id:08d}.evt{ev_id:012d}.HESE.contour_{containment}.txt' \
58+
# for containment in ['50', '90']]
59+
# contour_fs = [f for f in contour_fs if os.path.exists(f)]
5660
if len(contour_fs) == 0:
5761
contour_fs = None
5862

fast_response/web_utils.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,7 @@ def updateFastResponsePlots(gw=False):
310310
plt.gca().invert_xaxis()
311311
plt.grid(which = 'both', alpha = 0.2)
312312
plt.xlim(1.1e0,1e-3)
313-
plt.ylim(3e-3, 1e0)
313+
plt.ylim(1e-3, 1e0)
314314
plt.xlabel('p-value', fontsize = 18)
315315
plt.ylabel('Fraction of Analyses', fontsize = 18)
316316
plt.tick_params(labelsize = 18)
@@ -324,7 +324,7 @@ def updateFastResponsePlots(gw=False):
324324
pval_dist_path=f'/home/{username}/public_html/FastResponse/webpage/output/pvalue_distribution_liveupdate.png'
325325
plt.title("{} Fast Response Analyses as of {}".format(len(df), today), fontsize = 20)
326326
#plt.text(7e-3, 5e-2, "IceCube\nPreliminary", fontsize = 20, color = 'r')
327-
plt.ylim(3e-3, 1e0)
327+
# plt.ylim(3e-3, 1e0)
328328

329329
plt.savefig(pval_dist_path, dpi=200, bbox_inches='tight')
330330
#plt.savefig(f'/home/{username}/public_html/FastResponse/webpage/output/pvalue_distribution_liveupdate.png', dpi=200, bbox_inches='tight')
@@ -490,7 +490,7 @@ def createGWEventPage(analysis):
490490
</table>
491491
</table>
492492
'''.format(e, event['event_dt'], event['localization']['ra'], event['localization']['dec'],
493-
event['localization']['ra_uncertainty'][0],
493+
event['localization']['ra_dec_error'],
494494
event['event_pval_generic'], event['event_pval_bayesian'])
495495
e+=1
496496

0 commit comments

Comments
 (0)