seisobs-webapp/scripts/mkGeolocationTable.py

156 lines
6.5 KiB
Python
Raw Normal View History

2021-10-16 15:51:38 +02:00
#! /usr/bin/env python3
2014-05-06 13:26:47 +02:00
# -*- coding: utf-8 -*-
'''
2014-06-01 15:56:56 +02:00
Script to lookup city names of events with Nominatim service
2014-05-06 13:26:47 +02:00
2014-06-01 15:56:56 +02:00
The input should be an valid quakeML file passed to stdin.
The output will will be a javascript structure to be included in the
SeisObs map service.
2014-05-06 13:26:47 +02:00
2021-10-16 15:51:38 +02:00
The script should be updated regularly keep the total number of all
2014-06-01 15:56:56 +02:00
AJAX calls to the Nominatim service small, e. g. :
2021-10-16 15:51:38 +02:00
curl -s "https://fdsnws.geophysik.ruhr-uni-bochum.de/fdsnws/event/1/query?minlat=50&maxlat=54&minlon=3&maxlon=10&minmag=1" | mkGeolocationTable.py > geolocationTable.js
2014-06-01 15:56:56 +02:00
License
2020-07-14 21:13:15 +02:00
Copyright 2020 Kasper D. Fischer <kasper.fischer@rub.de>
2014-06-01 15:56:56 +02:00
This program is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the Free
Software Foundation, either version 3 of the License, or (at your option)
any later version.
2014-06-01 15:56:56 +02:00
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
2014-06-01 15:56:56 +02:00
You should have received a copy of the GNU General Public License along
with this program. If not, see http://www.gnu.org/licenses/.
2014-06-01 15:56:56 +02:00
$Id$
2014-05-06 13:26:47 +02:00
'''
2014-06-01 15:56:56 +02:00
def mkGeolocationTable(file=''):
# imports
try:
import xml.etree.cElementTree as ET
except ImportError:
import xml.etree.ElementTree as ET
from sys import stdin
import warnings
from time import sleep
from geopy.geocoders import Photon
2014-06-01 15:56:56 +02:00
import urllib2 as URL
import json as JSON
2014-06-01 15:56:56 +02:00
# constants
namespaces = {'sc3': 'http://geofon.gfz-potsdam.de/ns/seiscomp3-schema/0.7',
'qml': 'http://quakeml.org/xmlns/bed/1.2'}
def simple_warning(message, category, filename, lineno, file=None, line=None):
return 'Warning: %s\n' % (message)
warnings.formatwarning = simple_warning
# try loading the file
geolocationTable = {}
2014-06-01 15:56:56 +02:00
if file :
try:
jsonfile = open(file)
jsonfileContent = jsonfile.read().split('=')[1].replace(';', '')
geolocationTable = JSON.loads(jsonfileContent)
except:
geolocationTable = {}
warnings.warn('Could not parse file %s' %file)
# parse event.xml
DOM = ET.parse(stdin).getroot()
geolocator = Photon()
2014-06-01 15:56:56 +02:00
# iterate over all events
for event in DOM.iterfind('qml:eventParameters/qml:event', namespaces):
publicID = event.attrib['publicID'].split('/')[2]
lat = event.find('./qml:origin/qml:latitude/qml:value', namespaces).text
lng = event.find('./qml:origin/qml:longitude/qml:value', namespaces).text
evaluationMode = event.find('./qml:origin/qml:evaluationMode', namespaces).text
if publicID in geolocationTable:
warnings.warn('Skipping cached event %s' %(publicID))
elif evaluationMode == 'automatic':
warnings.warn('Skipping automatic event %s' %(publicID))
else:
try:
location = geolocator.reverse("{lat}, {lng}".format(lat=lat, lng=lng))
except:
warnings.warn('Reverse Geolocation failed. Skipping event.')
continue
place = []
try:
place = location.raw['properties']['city']
except KeyError:
try:
place = location.raw['properties']['town']
except KeyError:
try:
place = location.raw['properties']['village']
except KeyError:
try:
place = location.raw['properties']['county']
except KeyError:
warnings.warn('Could not extract city for event {0} at {1} N / {2} E (URL: {3})'.format(publicID, lat, lng, url))
geolocationTable[publicID] = place
sleep(1.1)
'''
2014-06-01 15:56:56 +02:00
#warnings.warn('Processing event %s' %publicID)
# send and evaluate nominatim request
url = 'https://open.mapquestapi.com/nominatim/v1/reverse.php?key=oE512xGQxeH1n2cueacJ6xzRv7qFlCib&lat={0}&lon={1}&zoom=10&format=json'.format(lat, lng)
2014-06-01 15:56:56 +02:00
response = URL.urlopen(url)
if ( response.msg == 'OK' ):
data = JSON.loads(response.read())
city = []
2014-06-01 15:56:56 +02:00
try:
try:
city = data['address']['city']
except:
warnings.warn('Request {3} for event {0} at {1} N / {2} E did not provide city attribute\n\t(Response: {4})'.format(publicID, lat, lng, url, data))
try:
city = data['address']['town']
warnings.warn('Using attribute town ({1}) for event {0}'.format(publicID, city))
except:
try:
city = data['address']['county']
warnings.warn('Using attribute county ({1}) for event {0}'.format(publicID, city))
except:
warnings.warn('Skipping event')
continue
2014-06-01 15:56:56 +02:00
countryCode = data['address']['country_code'].upper()
if ( countryCode == 'DE' ):
geolocationTable[publicID] = city.encode('utf-8')
else:
geolocationTable[publicID] = '{0} ({1})'.format(city.encode('utf-8'), countryCode)
except:
warnings.warn('Could not extract city for event {0} at {1} N / {2} E (URL: {3})'.format(publicID, lat, lng, url))
else:
warnings.warn('Request {0} failed'.format(url))
'''
2014-06-01 15:56:56 +02:00
# dump json
2021-10-16 15:51:38 +02:00
print('var geolocationTable = {0};'.format(JSON.dumps(geolocationTable, sort_keys=True)))
2014-06-01 15:56:56 +02:00
# __main__
if __name__ == "__main__":
# parse arguments
import argparse
versionText = '$Revision$ ($Date$, $Author$)'.replace('$', '').replace(':','')
parser = argparse.ArgumentParser(
2021-10-16 15:51:38 +02:00
description='Reverse geocoding lookup of events in xml format (stdin).',
2014-06-01 15:56:56 +02:00
epilog=versionText)
parser.add_argument('-v', '-V', '--version', action='version',
version=versionText)
parser.add_argument('-f', '--file', action='store', dest='file',
help='read in JSON file containing old output.')
cla = parser.parse_args()
# call mkGeolocationTable(...)
mkGeolocationTable(file=cla.file)