Skip to content

Commit 23c8753

Browse files
authored
New skymap handling (#61)
* skip check for events if before 2020 * load rates in sections if ext fra longer than 45 days * correct ex time * deal with timezones, if needed * minor typos * bump version to 4.1.0 * use start time not event time to find results file * correct link to wp posted to slack * Move old skymap stuff to new class and add bool to clarify type of skymap * if option given print nearby events to screen * new option for deltallh map, default prob map * new option to print nearby events if desired * minor version increment for new release * increase default no of trials run * change name of arg to make it clear this is for the circular num, not notice
1 parent 065d1c0 commit 23c8753

File tree

12 files changed

+67
-35
lines changed

12 files changed

+67
-35
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ In order to run this analysis, you should find the alert event time (sent in the
128128
Once you have these details, you can run the analysis with
129129

130130
```console
131-
python run_track_followup.py --skymap=/home/followup/output_plots/run{RUNID}.evt{EVENTID}.HESE.skymap_nside_512.fits.gz --time={ALERT_MJD} --gcn_notice_num={GCN_CIRCULAR_NUMBER} --alert_id={RUNID}:{EVENTID}
131+
python run_track_followup.py --skymap=/home/followup/output_plots/run{RUNID}.evt{EVENTID}.neutrino_8_64_512_1024.skymap_nside_1024.fits.gz --time={ALERT_MJD} --alert_circ={GCN_CIRCULAR_NUMBER} --alert_id={RUNID}:{EVENTID}
132132
```
133133

134134
This will run two analyses, one with a time window of 1000 seconds and one with a time window of 2 days, both centered on the alert time. It will also remove the alert event from the sample, and it will assume a spectral index of -2.5, which is different than the -2 used for the `run_external_followup.py` script.
@@ -141,7 +141,7 @@ To run the analysis to follow up a graviational wave event, you will need to nav
141141

142142
As an example, there is a sample map included here: `fast_response/sample_skymaps/S191216ap_update.xml`. To run this event, the input would look like:
143143
```console
144-
python run_gw_followup.py --name="S191216ap Update" --time=58833.893 --skymap="https://gracedb.ligo.org/api/superevents/S191216ap/files/LALInference.fits.gz,0"
144+
python run_gw_followup.py --name="S191216ap Update" --time=58833.89836 --skymap="https://gracedb.ligo.org/api/superevents/S191216ap/files/LALInference.fits.gz,0"
145145
```
146146
Additionally, you can choose to pass the argument `--allow_neg_ts` (bool) if you want to use the convention where a negative TS is allowed. The default is to use the convention TS>=0.
147147

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.2'
19+
release = '1.3.0'
2020

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

fast_response/AlertFollowup.py

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ class AlertFollowup(PriorFollowup):
2525
_fix_index = True
2626
_float_index = not _fix_index
2727
_index = 2.5
28+
_llh_map = False
2829

2930
def run_background_trials(self, ntrials = 1000):
3031
r"""For alert events with specific time windows,
@@ -257,7 +258,22 @@ class TrackFollowup(AlertFollowup):
257258
"""
258259
Class for followup of track alert events
259260
By default, uses a fixed index of 2.5 in LLH.
260-
By default, converts milipede LLH map to a PDF.
261+
Assumes a probability skymap for the follow-up.
262+
Built on AlertFollowup and PriorFollowup base classes
263+
264+
"""
265+
_smear = False
266+
_dataset = "GFUOnline_v001p02"
267+
_fix_index = True
268+
_float_index = not _fix_index
269+
_index = 2.5
270+
_llh_map = False
271+
272+
class TrackFollowupLLH(AlertFollowup):
273+
"""
274+
[Old] Class for followup of track alert events
275+
By default, uses a fixed index of 2.5 in LLH
276+
and converts milipede LLH map to a PDF.
261277
Built on AlertFollowup and PriorFollowup base classes
262278
263279
"""
@@ -266,6 +282,7 @@ class TrackFollowup(AlertFollowup):
266282
_fix_index = True
267283
_float_index = not _fix_index
268284
_index = 2.5
285+
_llh_map = True
269286

270287
def format_skymap(self, skymap):
271288
"""
@@ -370,4 +387,5 @@ class CascadeFollowup(AlertFollowup):
370387
_dataset = "GFUOnline_v001p02"
371388
_fix_index = True
372389
_float_index = not _fix_index
373-
_index = 2.5
390+
_index = 2.5
391+
_llh_map = False

fast_response/FastResponseAnalysis.py

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,8 @@ def __init__(self, name, tstart, tstop, skipped=None, seed=None,
6262
outdir=None, save=True, extension=None):
6363
self.name = name
6464

65-
if seed is not None:
66-
self.llh_seed(seed)
65+
# if seed is not None:
66+
# self.llh_seed(seed)
6767
if outdir is None:
6868
outdir = os.environ.get('FAST_RESPONSE_OUTPUT')
6969
if outdir is None:
@@ -581,8 +581,9 @@ def plot_skymap_zoom(self, with_contour=False, contour_files=None):
581581
cont = np.loadtxt(c_file, skiprows=1)
582582
cont_ra = cont.T[0]
583583
cont_dec = cont.T[1]
584-
label = 'Millipede 50\%, 90\% (160427A syst.)' \
585-
if contour_counter == 0 else ''
584+
cont_label = 'Millipede 50\%, 90\% (160427A syst.)' if self._llh_map else 'Skymap 50\%, 90\%'
585+
label = cont_label if contour_counter == 0 else ''
586+
586587
hp.projplot(np.pi/2. - cont_dec, cont_ra, linewidth=3.,
587588
color='k', linestyle=cont_ls[contour_counter], coord='C',
588589
label=label)
@@ -872,7 +873,7 @@ def run_background_trials(self, ntrials=1000):
872873
self.tsd = tsd
873874
self.save_items['tsd'] = tsd
874875

875-
def find_coincident_events(self):
876+
def find_coincident_events(self, print_events=False):
876877
r"""Find coincident events for a skymap
877878
based analysis. These are ontime events that are also in the
878879
90% contour of the skymap
@@ -885,13 +886,16 @@ def find_coincident_events(self):
885886
overlap = np.isin(exp_pix, self.ipix_90)
886887
events = events[overlap]
887888

888-
# print nearby events, as a check (if needed)
889-
# msk1 = (self.llh.exp[t_mask]['ra'] < (self.skymap_fit_ra+np.radians(5)))*(self.llh.exp[t_mask]['ra'] > (self.skymap_fit_ra-np.radians(5)))
890-
# msk2 = (self.llh.exp[t_mask]['dec'] < (self.skymap_fit_dec+np.radians(5)))*((self.llh.exp[t_mask]['dec'] > self.skymap_fit_dec-np.radians(5)))
891-
# msk3 = msk1*msk2
892-
# print('Nearby events:')
893-
# print("[run, event, ra, dec, sigma, logE, time]")
894-
# for e in self.llh.exp[t_mask][msk3]: print([e[k] for k in ['run', 'event', 'ra', 'dec', 'sigma', 'logE', 'time']])
889+
if print_events:
890+
# print nearby events, as a check (if needed)
891+
msk1 = (self.llh.exp[t_mask]['ra'] < (self.skymap_fit_ra+np.radians(5)))*(self.llh.exp[t_mask]['ra'] > (self.skymap_fit_ra-np.radians(5)))
892+
msk2 = (self.llh.exp[t_mask]['dec'] < (self.skymap_fit_dec+np.radians(5)))*((self.llh.exp[t_mask]['dec'] > self.skymap_fit_dec-np.radians(5)))
893+
msk3 = msk1*msk2
894+
if np.count_nonzero(msk3) > 0:
895+
print('Events within 5 deg of best-fit:')
896+
print("[run, event, ra, dec, sigma, logE, time]")
897+
for e in self.llh.exp[t_mask][msk3]:
898+
print([e[k] for k in ['run', 'event', 'ra', 'dec', 'sigma', 'logE', 'time']])
895899

896900
if len(events) == 0:
897901
coincident_events = []

fast_response/listeners/gw_gcn_listener.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,14 +177,17 @@ def process_gcn(payload, root):
177177
#'--allow_neg_ts=True']
178178
)
179179

180-
output = os.path.join(os.environ.get('FAST_RESPONSE_OUTPUT'),eventtime[0:10].replace('-','_')+'_'+name)
180+
analysis_start = Time(event_mjd - 500./86400., format='mjd').iso
181+
output = os.path.join(os.environ.get('FAST_RESPONSE_OUTPUT'),
182+
analysis_start[0:10].replace('-','_')+'_'+name)
181183
#update webpages
182184
webpage_update = os.path.join(analysis_path,'document.py')
183185
if not mock and root.attrib['role'] == 'observation':
184186
try:
185187
subprocess.call([webpage_update, '--gw', f'--path={output}'])
186188

187-
wp_link = 'https://user-web.icecube.wisc.edu/~jthwaites/FastResponse/gw-webpage/output/{}.html'.format(eventtime[0:10].replace('-','_')+'_'+name)
189+
wp_link = 'https://user-web.icecube.wisc.edu/~jthwaites/FastResponse/gw-webpage/output/'+\
190+
'{}.html'.format(analysis_start[0:10].replace('-','_')+'_'+name)
188191
slack_message = "UML GW analysis finished running for event {}: <{}|link>.".format(name, wp_link)
189192
with open('../slack_posters/internal_alert_slackbot.txt') as f:
190193
chan = f.readline().rstrip('\n')

fast_response/make_ontime_plots.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,6 @@ def make_rate_plots(time_window, run_table, query_events, dirname, season='neutr
174174
format='mjd').iso #first 35 days
175175
rates1 = icecube.realtime_tools.live.get_rates(run_table[0]['start'], midpt)
176176
rates2 = icecube.realtime_tools.live.get_rates(midpt, run_table[-1]['stop'])
177-
#avoid double counting last entry
178177
rates = np.concatenate([rates1, rates2])
179178
else:
180179
rates = icecube.realtime_tools.live.get_rates(run_table[0]['start'], run_table[-1]['stop'])

fast_response/reports/ReportGenerator.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,8 @@ def ontime_table(query_dict):
203203
newevent = event['value']['data']
204204
for key,val in list(newevent['reco']['splinempe'].items()):
205205
newevent['splinempe_'+key]=val
206+
if '+' in newevent['eventtime']:
207+
newevent['eventtime'] = newevent['eventtime'].split('+')[0]
206208
if Time(newevent['eventtime'],scale='utc',format='iso') >= Time("2018-07-10 17:52:03.34", format='iso',scale='utc'):
207209
newevent['muex'] = newevent['reco']['energy']['mpe_muex']
208210
del newevent['reco']

fast_response/scripts/combine_results_kafka.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ def parse_notice(record, wait_for_llama=False, heartbeat=False):
196196
return
197197

198198
collected_results = {}
199-
collected_results["$schema"]= "https://gcn.nasa.gov/schema/v4.0.0/gcn/notices/icecube/lvk_nu_track_search.schema.json"
199+
collected_results["$schema"]= "https://gcn.nasa.gov/schema/v4.1.0/gcn/notices/icecube/lvk_nu_track_search.schema.json"
200200
collected_results["type"]= "IceCube LVK Alert Nu Track Search"
201201

202202
eventtime = record.find('.//ISOTime').text
@@ -235,7 +235,8 @@ def parse_notice(record, wait_for_llama=False, heartbeat=False):
235235
)
236236

237237
while results_done == False:
238-
start_date = Time(dateutil.parser.parse(eventtime)).datetime
238+
start_time = Time(Time(eventtime, format='isot').mjd - 500./86400., format='mjd').isot
239+
start_date = Time(dateutil.parser.parse(start_time)).datetime
239240
start_str = f'{start_date.year:02d}_{start_date.month:02d}_{start_date.day:02d}'
240241

241242
uml_results_path = os.path.join(fra_results_location, start_str + '_' + name.replace(' ', '_') \

fast_response/scripts/run_external_followup.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,9 @@ def run_analysis(args):
8080
type= lambda z:[ tuple(int(y) for y in x.split(':')) for x in z.split(',')],
8181
help="Event to exclude from the analyses, eg."
8282
"Example --skip-events=127853:67093193")
83-
parser.add_argument('--ntrials', default=100, type=int,
83+
parser.add_argument('--ntrials', default=200, type=int,
8484
help="Number of background trials to perform")
85-
parser.add_argument('--n_per_sig', default=100, type=int,
85+
parser.add_argument('--n_per_sig', default=200, type=int,
8686
help="Number of signal trials per injected ns to perform")
8787
parser.add_argument('--document', default=False, action='store_true')
8888
args = parser.parse_args()

fast_response/scripts/run_track_followup.py

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,15 @@
99
import os, argparse, glob
1010
from astropy.time import Time
1111

12-
from fast_response.AlertFollowup import TrackFollowup
12+
from fast_response.AlertFollowup import TrackFollowup, TrackFollowupLLH
1313
import fast_response.web_utils as web_utils
1414

1515
parser = argparse.ArgumentParser(description='Fast Response Analysis')
1616
parser.add_argument('--skymap', type=str, default=None,
1717
help='path to skymap')
1818
parser.add_argument('--time', type=float, default=None,
1919
help='Time of the alert event (mjd)')
20-
parser.add_argument('--gcn_notice_num', default=0, type=int,
20+
parser.add_argument('--alert_circ', default=0, type=int,
2121
help="GCN Circular NUMBER for updated circular (not Bacodine/Notice)")
2222
parser.add_argument('--alert_id', default=None,
2323
type= lambda z:[ tuple(int(y) for y in x.split(':')) for x in z.split(',')],
@@ -27,6 +27,10 @@
2727
parser.add_argument('--suffix', type=str, default='A',
2828
help="letter to differentiate multiple alerts on the same day (default = A)."
2929
"Event name given by IceCube-yymmdd + suffix.")
30+
parser.add_argument('--print_nearby', action='store_true', default=False,
31+
help='Option to print events within 5 degrees of best-fit to the screen (default False)')
32+
parser.add_argument('--deltallh_skymap', action='store_true', default=False,
33+
help='Option MUST be raised if using deltaLLH map (default: False, assumes probability map)')
3034
args = parser.parse_args()
3135

3236
track_time = Time(args.time, format='mjd')
@@ -53,27 +57,28 @@
5357
for containment in ['50', '90']:
5458
contour_fs = contour_fs + glob.glob(base_skymap_path +
5559
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)]
6060
if len(contour_fs) == 0:
6161
contour_fs = None
6262

63-
f = TrackFollowup(name, args.skymap, start, stop, skipped=args.alert_id)
63+
if args.deltallh_skymap:
64+
print('Initializing Track follow up with deltaLLH map')
65+
f = TrackFollowupLLH(name, args.skymap, start, stop, skipped=args.alert_id)
66+
else:
67+
print('Initializing Track follow up with probability skymap')
68+
f = TrackFollowup(name, args.skymap, start, stop, skipped=args.alert_id)
6469

6570
f.unblind_TS()
6671
f.plot_ontime(contour_files=contour_fs)
6772
f.calc_pvalue()
6873
f.make_dNdE()
6974
f.plot_tsd()
7075
f.upper_limit()
71-
f.find_coincident_events()
76+
f.find_coincident_events(print_events=args.print_nearby)
7277
results = f.save_results()
7378
f.generate_report()
7479
all_results[delta_t] = results
7580

76-
all_results[1000.]['gcn_num'] = args.gcn_notice_num
81+
all_results[1000.]['gcn_num'] = args.alert_circ
7782

7883
# Write circular to the output directory of the 2 day analysis
7984
f.write_circular(all_results)

0 commit comments

Comments
 (0)