Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1#!/usr/bin/env python
2# (c) Stefan Countryman 2016-2018, Rainer Corley 2016
3"""
4``FileHandler`` for making a nicely-formatted ascii table of IceCube neutrinos
5including their reconstructed properties and their joint significance when
6combined with a gravitational wave. Can also be used as a stand-alone
7command-line script to generate a human-readable table with neutrinos for this
8event from an input JSON file. Used for GCN circulars.
9"""
11import sys
12import json
13from llama.utils import mjd2gps
14from llama.files.i3.utils import zen_az2ra_dec
15from llama.filehandler import FileHandler
16from llama.files.i3.json import IceCubeNeutrinoList
17from llama.files.skymap_info import SkymapInfo
18from llama.files.coinc_significance import CoincSignificanceI3Lvc
19from llama.files.gwastro import GWAstroReceipt
22@GWAstroReceipt.upload_this()
23@FileHandler.set_class_attributes
24class IceCubeNeutrinoListTxt(FileHandler):
25 """
26 A space-delimited, table-formatted list of neutrinos formatted for human
27 consumption in GCN Circulars.
28 """
30 FILENAME = "icecube_neutrino_list.txt"
31 DEPENDENCIES = (IceCubeNeutrinoList, SkymapInfo,)
33 def _generate(self): # pylint: disable=W0221
34 infilename = IceCubeNeutrinoList(self).fullpath
35 outfilename = self.fullpath
36 gpstime = SkymapInfo(self).event_time_gps
37 convert_json_neutrinos_to_txt(infilename, outfilename, gpstime=gpstime)
40@FileHandler.set_class_attributes
41class IceCubeNeutrinoListCoincTxt(FileHandler):
42 """
43 A space-delimited, table-formatted list of neutrinos meant for human
44 consumption in GCN Circulars. Contains coincidence significance measures in
45 addition to the base neutrino properties.
46 """
48 FILENAME = 'icecube_neutrino_list_coinc.txt'
49 DEPENDENCIES = (IceCubeNeutrinoList, SkymapInfo,
50 CoincSignificanceI3Lvc)
52 def _generate(self): # pylint: disable=W0221
53 infilename = IceCubeNeutrinoList(self).fullpath
54 outfilename = self.fullpath
55 gpstime = SkymapInfo(self).event_time_gps
56 p_values = CoincSignificanceI3Lvc(self).p_values
57 convert_json_neutrinos_to_txt(infilename, outfilename, gpstime=gpstime,
58 p_values=p_values)
61# pylint: disable=invalid-name
62def convert_json_neutrinos_to_txt(infilename, outfilename, gpstime=None,
63 p_values=None):
64 """Take a json-formatted input filename and an output filename (both full
65 paths) as arguments. Convert the neutrino list in the infile into a
66 space-delimited, table-formatted list of neutrinos intended for human
67 readability and saved to the path specified in outfilename. If an optional
68 gpstime is given, then the time column will be given as the time difference
69 in seconds between the neutrino's arrival and the GPS time provided, i.e.
70 the neutrino detection time with t=0 defined as the GPS time."""
71 if gpstime is None:
72 time_title = 'GPS'
73 gpstime = 0
74 else:
75 time_title = 'dt[s]'
76 column_titles = [time_title, 'RA[deg]', 'Dec[deg]', 'E[TeV]', 'Sigma[deg]']
77 with open(infilename, 'r') as infile:
78 data = json.load(infile)
79 # handle current and old neutrino list format
80 if isinstance(data, dict):
81 neutrinos = data['triggers']
82 else:
83 neutrinos = data
84 # if odds_ratios are provided, include a column for them
85 if p_values is not None:
86 column_titles += ["P Value"]
87 with open(outfilename, 'w') as f:
88 # write column titles
89 f.write('#' + (' ' * 5)) # row number
90 for column_title in column_titles:
91 f.write('{0: >12}'.format(column_title))
92 f.write('\n')
93 # write separator between header and data
94 f.write(('-' * (6 + 12 * len(column_titles))) + '\n')
95 # write rows
96 for i, n in enumerate(neutrinos):
97 # line num, 6 spaces long
98 f.write(('{}.' + ' '*4).format(i+1)[:6])
99 f.write(' {:11.2f}'.format(mjd2gps(n['mjd']) - gpstime))
100 ra, dec = zen_az2ra_dec(n['mjd'], n['zenith'], n['azimuth'])
101 f.write(' {:11.1f}'.format(ra))
102 f.write(' {:11.1f}'.format(dec))
103 # GeV->TeV
104 f.write(' {:11.2f}'.format(n['energy'] / 1000.))
105 # rad->deg
106 if isinstance(n['sigma'], float):
107 f.write(' {:11.2f}'.format(n['sigma']))
108 else:
109 # might be undefined, need to print the string
110 f.write(' {:>11}'.format(n['sigma']))
111 if p_values is not None:
112 f.write(' {:11.8f}'.format(p_values[i]))
113 f.write('\n')
116# we want parentheses after python2 print statements to maintain python3
117# compatibility.
118# pylint: disable=superfluous-parens
119def main():
120 """Can also use this module as a command-line script to make this file
121 conversion."""
122 infilename = sys.argv[1]
123 outfilename = sys.argv[2]
124 convert_json_neutrinos_to_txt(infilename, outfilename)
126 if len(sys.argv) == 1 or '-h' in sys.argv:
127 print('USAGE: {} infile.json outfile.txt'.format(sys.argv[0]))
128 print('Take a LLAMA JSON neutrino list as input and save a')
129 print('space-delimited output text file with the following format:')
130 print(' dt RA Dec Energy Sigma')
131 print('Where dt is the time difference between the gravitational wave')
132 print('arrival time and the timestamp for the neutrino, RA is the')
133 print('right ascension, DEC is the declination, Energy is the energy,')
134 print('and Sigma is the directional uncertainty in degrees.')
135 exit(1)
137if __name__ == "__main__":
138 main()