Skip to content

Instantly share code, notes, and snippets.

@thespacedoctor
Last active May 5, 2021 16:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save thespacedoctor/a5a86fe797016b9e3070b4cb896934ba to your computer and use it in GitHub Desktop.
Save thespacedoctor/a5a86fe797016b9e3070b4cb896934ba to your computer and use it in GitHub Desktop.
[Listen to LVC GCN Notices and Download Localisation Maps] #ligo_virgo #map #gcn

LVC GCN Listener & Map Downloader

This script will continuously listen to the GCN notice stream, filtering only notices originating from Ligo-Virgo. If an event is detected, and a skymap is referenced in the VOEvent packet, the script will immediately download a local copy of the HealPix localisation map.

Python 2.* only at the minute.

Here are the only dependencies you should need to install:

pip install fundamentals requests pygcn

Within the script itself you can set the download path for the maps:

# VARIABLES
downloadPath = "/tmp/ligo_virgo_events"

A folder for each event will be created under this path to contain its associated localisation maps.

To run in production mode:

python lvc_gcn_listener.py

or to run in test mode and download maps from the GCN test stream use the -t flag:

python lvc_gcn_listener.py -t

The LVC GCN test stream usually reports one test event / hour.

Note real event IDs start with S (superevent) and test event IDs begin with MS (mock-superevent).

Logging

To control the level of logging and where the script writes log files to, use the template settings.yaml file provided in this gist. There are some comments in the settings file to help you taylor it to your needs.

To run the script with settings:

python lvc_gcn_listener.py /path/to/settings.yaml
#!/usr/local/bin/python
# encoding: utf-8
"""
*Listen to LVC GCN notice stream and download event skymaps*
:Author:
David Young
:Date Created:
March 4, 2019
Usage:
lvc_gcn_listener [-t] [<pathToSettingsFile>]
Options:
<pathToSettingsFile> path to the settings file containing logger settings
-t, --test listen to real *and* test notices (~1 event/hr)
-h, --help show this help message
"""
################# GLOBAL IMPORTS ####################
import sys
import os
from fundamentals import tools
import requests
import gcn
# VARIABLES
downloadPath = "/tmp/ligo_virgo_events"
def main(arguments=None):
"""
*The main function used when ``lvc_gcn_listener.py`` is run as a single script from the cl*
"""
# SETUP THE COMMAND-LINE UTIL SETTINGS
su = tools(
arguments=arguments,
docString=__doc__,
logLevel="WARNING",
options_first=False,
projectName=False
)
arguments, settings, log, dbConn = su.setup()
# UNPACK REMAINING CL ARGUMENTS USING `EXEC` TO SETUP THE VARIABLE NAMES
# AUTOMATICALLY
for arg, val in arguments.iteritems():
if arg[0] == "-":
varname = arg.replace("-", "") + "Flag"
else:
varname = arg.replace("<", "").replace(">", "")
if isinstance(val, str) or isinstance(val, unicode):
exec(varname + " = '%s'" % (val,))
else:
exec(varname + " = %s" % (val,))
if arg == "--dbConn":
dbConn = val
log.debug('%s = %s' % (varname, val,))
listener = gcnListener(
log=log,
settings=settings,
test=testFlag
)
listener.listen()
return
class gcnListener():
"""
*The GCN listener object*
**Key Arguments:**
- ``log`` -- logger
- ``settings`` -- the settings dictionary
- ``test`` -- use test settings for development purposes
"""
def __init__(
self,
log,
settings=False,
test=False
):
self.log = log
log.debug("instansiating a new 'gcnListener' object")
self.settings = settings
self.test = test
return None
def listen(self):
"""*listen to the GCN notice stream*
"""
self.log.debug('starting the ``listen`` method')
# FILTER THE GCN NOTICES TO ONLY LVC NOTICES
@gcn.handlers.include_notice_types(
gcn.notice_types.LVC_PRELIMINARY,
gcn.notice_types.LVC_INITIAL,
gcn.notice_types.LVC_UPDATE,
gcn.notice_types.LVC_RETRACTION)
def process_gcn(payload, root):
# DECIDE HOW TO RESPOND TO REAL/TEST EVENTS
if root.attrib['role'] == 'observation':
pass
if root.attrib['role'] == 'test':
if not self.test:
return
# READ ALL OF THE VOEVENT PARAMETERS FROM THE "WHAT" SECTION.
params = {elem.attrib['name']:
elem.attrib['value']
for elem in root.iterfind('.//Param')}
# PRINT ALL PARAMETERS.
for key, value in params.items():
print key, ':', value
# DOWNLOAD THE FITS MAP
if 'skymap_fits' in params:
local_filename = params['skymap_fits'].split('/')[-1]
r = requests.get(params['skymap_fits'], allow_redirects=True)
mapDownloadPath = downloadPath + "/" + params["GraceID"]
# RECURSIVELY CREATE MISSING DIRECTORIES
if not os.path.exists(mapDownloadPath):
os.makedirs(mapDownloadPath)
open(mapDownloadPath + "/" +
local_filename, 'wb').write(r.content)
# START THE LISTENER - WILL RECONNECT AUTOMATICALLY IF CONNECTION DROPS
gcn.listen(handler=process_gcn)
self.log.debug('completed the ``listen`` method')
return None
if __name__ == '__main__':
main()
version: 1
## LOGGING LEVELS ARE CRITICAL, ERROR, WARNING, INFO, DEBUG
logging settings:
formatters:
file_style:
format: '* %(asctime)s - %(name)s - %(levelname)s (%(pathname)s > %(funcName)s > %(lineno)d) - %(message)s '
datefmt: '%Y/%m/%d %H:%M:%S'
console_style:
format: '* %(asctime)s - %(levelname)s: %(pathname)s:%(funcName)s:%(lineno)d > %(message)s'
datefmt: '%H:%M:%S'
html_style:
format: '<div id="row" class="%(levelname)s"><span class="date">%(asctime)s</span> <span class="label">file:</span><span class="filename">%(filename)s</span> <span class="label">method:</span><span class="funcName">%(funcName)s</span> <span class="label">line#:</span><span class="lineno">%(lineno)d</span> <span class="pathname">%(pathname)s</span> <div class="right"><span class="message">%(message)s</span><span class="levelname">%(levelname)s</span></div></div>'
datefmt: '%Y-%m-%d <span class= "time">%H:%M <span class= "seconds">%Ss</span></span>'
handlers:
console:
class: logging.StreamHandler
level: DEBUG
formatter: console_style
stream: ext://sys.stdout
file:
class: logging.handlers.GroupWriteRotatingFileHandler
level: DEBUG
formatter: file_style
## FILENAME CAN BE AN ABSOLUTE PATH TO WHERE YOU WANT TO SAVE YOUR LOGS
filename: gcn_listener.log
mode: w+
maxBytes: 102400
backupCount: 1
root:
level: DEBUG
handlers: [file,console]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment