|  | #!/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() |