eqevents¶
Static event website generator
Description¶
EQEvents is a static website generator for SeisComP XML event parameters. It can run in a spooler mode or process single files. It uses a template engine to create the HTML files. It features an index page and event detail page. More information can be added though Plugins.
EQEvents is meant to run as output service for GDS (gempa dissemination server).
Plugins¶
The different EQEvents features are implemented by various plugins which may be
activated by adding a plugin to the list of
processingPlugins
, e.g.,
browser,gds,gis,leaflet,rss,search,shakemap
.
The following plugins exist:
Name |
Description |
---|---|
Adds a calendar based event browser. |
|
bulletins |
Adds bulletins containing additional information generated by an external source to an event detail page. This plugin is rarely used and requires customization. |
gds |
Updates gempa dissemination server (GDS) database with event processing information. It is recommended to activate this plugin if EQEvents is triggered by GDS. |
Generates a detailed event map using gempa image server (GIS). |
|
Generates a dynamic map showing the events of the current event table on the index page, in the event browser and the event search. |
|
notification |
Notifies connected clients about event and bulletin updates through a socket io interface. This plugin is rarely used and requires customization. |
Adds distance, azimuth, and polar plot to event detail page. |
|
rss |
Creates a RSS feet users may subscribe to. |
search |
Adds an event search. Note: The search function is implemented as a WSGI script and needs additional installation steps, described in Dynamic Content - The Search and Feedback Plugins. |
feedback |
Adds an email feedback form. Note: The feedback function is implemented as a WSGI script and needs additional installation steps, described in Dynamic Content - The Search and Feedback Plugins. |
shakemap |
Generates a shake map using gempa’s autosigma module. |
System dependencies which may be required by the plugins:
python-matplotlib
python-jinja2
Processing¶
Offline¶
To process a single XML file run EQEvents and pass it an XML file:
eqevents -i event.xml --debug
Spooler¶
In contrast to a typical GDS service EQEvents is not monitored by GDS but runs
as a SeisComP module. The $SEISCOMP_ROOT/etc/gds.cfg
only defines a
spool directory but no spooler nor filter command. The same directory needs to
be configured in $SEISCOMP_ROOT/etc/eqevents.cfg
. If an event matches
the GDS dissemination criteria or an operator manually disseminated an event the
GDS will place a *.content
file containing the SeisComP XML and a
*.address
file into the spool directory where they are found by EQEvents.
Processing details:
The file name of the address and content file must match.
Files with the same name but different extension are processed as auxiliary files.
Each file found is deleted either after processing or due to wrong the file name format.
The processing starts when the content file is found.
The content file contains a match information according to the GDS dissemination rules, see
ignoreMatch
.If multiple files for the same event are found then only the newest one is processed and the others are deleted.
The file name format is
<SECONDS.MILLIS>-<GDSID>-<EVENTID>-<SERVICE>[-FILTER].<EXT>
Name
Description
SECONDS.MILLIS
Time of dissemination
GDSID
ID of the dissemination procedure used to report back the dissemination status
EVENTID
Event ID used to skip older files of same event
SERVICE
GDS service name, unused
FILTER
GDS custom filter name, unused
EXT
File name extension
Reprocessing¶
If a template was changed or new plugins have been added all static pages need
to be reprocessed. As a precondition for this the event XML data must be
available, see backupXML
.
To initiate reprocessing stop EQEvents and run it using the reprocess command-line option.
eqevents --reprocess
Templates¶
EQEvents uses templates in a well defined structure. The path to the template
directory can be configured with templateDirectory
. The structure
is as follows:
base.html |
Base template inherited by almost all templates |
feed.rss |
RSS web feed |
index.html |
Index page |
leaflet-map.html |
Leaflet map, used in: index, browser, results |
results.html |
Search result page |
search.html |
Search parameter page |
table.html |
Event list table, used in index, browser, results |
browser/day.html |
Browser day page showing all events of a particular day |
browser/index.html |
Browser index page showing all years |
browser/month.html |
Browser month page showing all days |
browser/year.html |
Browser year page showing all months |
event/arrivals.html |
Event details arrival list |
event/base.html |
Event details base template |
event/overview.html |
Event details overview page |
event/quality.html |
Event details quality plots |
Templates are processed by Python Jinja and follow its documented syntax. Each template receives a context with several variables defined.
- ep¶
The EventParameters structure parsed from XML converted to a Python object. Attributes are accessible following the SeisComP ML schema names. They are mapped directly from the XML tag/attribute names. Below a simple example how to access all picks in the EventParameters object in template syntax:
{% for p in ep.pick %} {{ p.waveformID.networkCode }}.{{ p.waveformID.stationCode }} {{ p.time.value|qmldate|date }} {% endfor %}
The special filter qmldate is a special filter added by EQEvents to convert a date string from SeisComP ML to an Python datetime object. That object can then be further processed with the Jinja date filter.
- event¶
The event object currently processed.
- origin¶
The preferred origin of the currently processed event.
- focalMechanism¶
The preferred focal mechanism of the currently processed event.
- magnitude¶
The preferred magnitude of the currently processed event.
- POOL¶
The POOL that maps a publicID to an object.
{% for arr in origin.arrival %} {% p = POOL[arr.pickID] %} {% if p %} <div>{{ p.time.value|qmldate|data }}</div> {% else %} <div class="error">Referenced pick {{ arr.pickID }} not available</div> {% endif %} {% endfor %}
This makes it easier to access referenced objects. Otherwise the template code must iterate over all pick objects and compare the publicID in combination with a linear search which is quite slow for larger events.
- ID¶
The current event ID after cleaning invalid characters. That ID is used as event folder name and all event ID depending filenames.
- ROOT_URL¶
The relative path to the site index file. This can be different according to the templates rendered. If paths are required this variable should be prepended.
<a href="{{ ROOT_URL }}index.html">Home</a>
- STATIC_URL¶
The path to the static files according to
staticURL
.<link rel="stylesheet" type="text/css" href="{{ STATIC_URL }}css/page.css">
- filename¶
The path and filename of the current XML file being processed.
Webpages¶
The following images show the different generated pages with the default templates.
Web Server Integration¶
EQEvents has been deployed using NGINX or Apache. If unsure which web server to use then select NGINX because this is the most lightweight setup. Since EQEvents by default only consists of static pages the web server integration is straight forward. You may either decide to
generate the pages directly into the web server
html
directory by settingoutputDirectory
to e.g.,/usr/share/nginx/html/eqevents
(NGINX) or/var/www/html/eqevents
(Apache) oryou use a softlink to point from inside the
html
directory to the default EQEvents output directory:
ln -s /home/sysop/seiscomp/var/lib/eqevents/pages /usr/share/nginx/html/eqevents
In case of (1.) make sure that the EQEvents system user, probably sysop
, is
allowed to write to the html
directory. In case of (2.) the x
access
right must be set for the web server group and for all directories on the path.
Also security modules like SELinux
might prevent access of the web server
process to the user directory. If this is the case use following command to
grant those access rights:
chcon -v --type=httpd_sys_content_t /home/sysop/seiscomp/etc/global.cfg
chcon -v --type=httpd_sys_content_t /home/sysop/seiscomp/etc/eqevents.cfg
chcon -v --type=httpd_sys_content_t /home/sysop/seiscomp/etc/defaults/global.cfg
chcon -v --type=httpd_sys_content_t /home/sysop/seiscomp/etc/defaults/eqevents.cfg
chcon -Rv --type=httpd_sys_content_t /home/sysop/seiscomp/var/lib/eqevents/pages
chcon -v --type=httpd_sys_content_t /home/sysop/seiscomp/var/lib/eqevents/eqevents.db
chcon -Rv --type=httpd_sys_content_t /home/sysop/seiscomp/share/eqevents/templates
chcon -v --type=httpd_sys_content_t /home/sysop/seiscomp/share/eqevents/search-wsgi.py
chcon -Rv --type=texrel_shlib_ti /home/sysop/seiscomp/lib
#setsebool -P httpd_read_user_content 1
Dynamic Content - The Search and Feedback Plugins¶
The search and the feedback plugin require a WSGI module to generate dynamic content. The installation depends on the web server you selected and is covered different section
NGINX (Gunicorn)¶
Add the search or feedback plugin to
processingPlugins
.Install
gunicorn
python3 -m pip install --user gunicorn
Copy the relevant parts of the
server
andupstream
directives from$SEISCOMP_ROOT/share/eqevents/examples/nginx-gunicorn.conf
to your/etc/nginx/nginx.conf
or/etc/nginx/sites-available/YOUR-VHOST.conf
in case you are using a virtual host setup
Copy the Gunicorn configuration file to the EQEvents base directory:
cd $SEISCOMP_ROOT/share/eqevents/ cp examples/search-gunicorn.py . #cp examples/feedback-gunicorn.py .
Adjust the configuration, e.g., logging level, path and format if necessary.
Copy the Gunicorn socket and service systemd configuration:
sudo cp $SEISCOMP_ROOT/share/gds/web/examples/gunicorn/gunicorn-eqevents-search.* /etc/systemd/system #sudo cp $SEISCOMP_ROOT/share/gds/web/examples/gunicorn/gunicorn-eqevents-feedback.* /etc/systemd/system
Adjust the
user
,group
, orWorkingDirectory
variables if necessary. Changetype
depending on your Gunicorn version. Then enable and start the service:sudo systemctl enable gunicorn-eqevents-search sudo systemctl start gunicorn-eqevents-search #sudo systemctl enable gunicorn-eqevents-feedback #sudo systemctl start gunicorn-eqevents-feedback
Test the NGINX configuration:
sudo nginx -t
Enable and start NGINX:
sudo systemctl enable nginx sudo systemctl start nginx
Trouble shooting¶
Check if the socket file
/var/run/gunicorn-eqevents-{search,feedback}.sock
was created and ensure that the NGINX user (nginx
orwww-data
) has write access to this fileMake a request directly at the socket:
sudo -u nginx curl --unix-socket /var/run/gunicorn-eqevents-search.sock http
By default Gunicorn logs to
$HOME/.seiscomp/log/eqevents-web/{search,feedback}-{access,error}.log
Reload gunicorn-eqvents-{search,feedback} service after modifications to your
$SEISCOMP_ROOT/share/gds/{search,feedback}-gunicorn.py
Reload systemd configuration after modifications to systemd service and socket files:
sudo systemctl daemon-reload
Reload the NGINX server configuration:
sudo nginx -t && sudo systemctl reload nginx
Apache (WSGI)¶
Add the search or feedback plugin to
processingPlugins
.Install and enable
mod_wsgi
a2enmod wsgi
Configure WSGI handler, e.g., in
/etc/apache2/sites-available/eqevents.conf
WSGIScriptAlias /eqevents/search /home/sysop/seiscomp/share/eqevents/search-wsgi.py #WSGIScriptAlias /eqevents/search /home/sysop/seiscomp/share/eqevents/feedback-wsgi.py WSGIPythonPath /home/sysop/seiscomp/lib/python WSGIDaemonProcess eqevents processes=2 threads=1 python-path=/home/sysop/seiscomp/lib/python WSGIProcessGroup eqevents
Configure access to static content (optional, same file as above)
<Location "/eqevents"> Options -Indexes SetHandler None Require all granted </Location>
Set environment variables
Ubuntu:
/etc/apache2/envvars
export LD_LIBRARY_PATH=/home/sysop/seiscomp/lib:$LD_LIBRARY_PATH export SEISCOMP_ROOT=/home/sysop/seiscomp
RHEL:
/etc/sysconfig/httpd
LD_LIBRARY_PATH=/home/sysop/seiscomp/lib:$LD_LIBRARY_PATH SEISCOMP_ROOT=/home/sysop/seiscomp
Enable site
a2ensite eqevents
Restart Apache
Module Configuration¶
etc/defaults/global.cfg
etc/defaults/eqevents.cfg
etc/global.cfg
etc/eqevents.cfg
~/.seiscomp/global.cfg
~/.seiscomp/eqevents.cfg
eqevents inherits global options.
Note
Modules/plugins may require a license file. The default path to license
files is @DATADIR@/licenses/
which can be overridden by global
configuration of the parameter gempa.licensePath
. Example:
gempa.licensePath = @CONFIGDIR@/licenses
- database¶
Default:
@ROOTDIR@/var/lib/eqevents/eqevents.db
Type: path
Path to the sqlite3 database file.
- templateDirectory¶
Default:
@DATADIR@/eqevents/templates/default
Type: path
Directory to read templates from.
- outputDirectory¶
Default:
@ROOTDIR@/var/lib/eqevents/pages
Type: path
Target directory for generated web pages.
- spoolerDirectory¶
Default:
@ROOTDIR@/var/lib/eqevents/spool
Type: path
Spooler directory to read content files from.
- spoolerInterval¶
Default:
10
Unit: s
Type: int
Polling interval in seconds the spooler will scan the service directory for new files.
- backupXML¶
Default:
false
Type: boolean
Defines whether to backup the input XML in the output HTML directory per event as [id].xml. The XML backup allows easy reprocessing of the Web page in case of template changes, see ‘--reprocess’ command line option.
- staticURL¶
Default:
static/
Type: string
URL prefix for static files used in the templates. Can be used as {{ STATIC_URL }} in templates.
- enableArrivals¶
Default:
true
Type: boolean
Enables arrival output as part of the event detail page.
- numberOfIndexEvents¶
Default:
50
Type: int
Number of events for the index page.
- numberOfIndexDays¶
Type: int
Events of this number of past days for the index page. If this parameter is not configured then numberOfIndexEvents is in effect. If this parameter is configured then it takes precedence over numberOfIndexEvents.
- maxDays¶
Default:
0
Type: int
Maximum number of days to keep events for. Older events are removed. A value of 0 or below means unlimited.
- ignoreType¶
Default:
false
Type: boolean
An event might be marked as fake event using the event type ‘not existing’ or ‘other’. Set this parameter to ‘true’ to process fake events respectively to prevent them from being deleted.
- ignoreMatch¶
Default:
false
Type: boolean
The GDS uses the ‘match’ flag to signal whether an event solution fulfilled the dissemination criteria. E.g. an updated event revision might correct the epicenter to a point outside the area of interest. Set this parameter to ‘true’ to process not matching events respectively to prevent them from being deleted.
- processingPlugins¶
Default:
browser, plots
Type: list:string
List of eqevents processing plugins.
- showAuthor¶
Default:
false
Type: boolean
Include origin author information in generated web pages.
Note
filter.* Parameters which filter the event data processed by the various plugins.
- filter.minArrivalWeight¶
Type: double
Hides arrivals having a weight smaller than the configured threshold. To remove unused phases set a value of >0.
Note
gds.* Configuration parameters of the GDS plugin to generate gds reports. To use that plugin, add ‘gds’ to the list of processing plugins.
- gds.db¶
Type: string
GDS database URL used to report back the processing state, e.g. ‘mysql://user:pass@localhost/gds’.
Note
gis.* Configuration parameters of the GIS plugin to generate map files. To use that plugin, add ‘gis’ to the list of processing plugins.
- gis.url¶
Default:
http://localhost:20001
Type: string
URL of the GIS RESTful API.
- gis.timeout¶
Default:
10
Type: int
Defines the timeout for GIS requests. If the timeout expires and GIS did not return an empty image is generated.
- gis.post¶
Default:
false
Type: boolean
By default the image is requested from the GIS using the HTTP-GET mothod along with key event parameters. If set to ‘true’ the HTTP-POST method is used instead to transfer the whole event XML. This allows the GIS to render an image with even more information, like used stations or moment tensor solutions.
Note
rss.* Configuration parameters of the RSS plugin. To use that plugin, add ‘rss’ to the list of processing plugins.
- rss.days¶
Default:
1
Type: int
Number of (last) days to generate the RSS feed for.
- rss.title¶
Default:
EQ Events RSS Channel - last ${days}
Type: string
Title of the RSS feed. The variable ‘${days}’ is replaced by the string containing the number of days configured in the ‘rss.days’ parameter, e.g. ‘2 days’.
- rss.desc¶
Default:
Real-time earthquake locations
Type: string
Description of RSS feed that is copied to the description tag of the RSS XML.
- rss.link¶
Default:
https://localhost
Type: string
URL prefix for each event detail page. EQEvents just deals with relative paths but to transform an RSS item link into an absolute URL this prefix is required.
Note
notification.* Configuration parameters of the NOTIFICATION plugin to send notifications to a socket.io-server. To use that plugin, add ‘notification’ to the list of processing plugins.
- notification.server¶
Default:
localhost
Type: string
Hostname of the Socket.IO server.
- notification.port¶
Default:
8000
Type: int
Port of the Socket.IO server.
- notification.namespace¶
Default:
/event
Type: string
Socket.IO namespace.
Note
leaflet.* Configuration parameters for the Leaflet map plugin that renders an interactive map on the index page.
Note
leaflet.init.* By default the map view is set to the bounds of the current event list. This configuration group allows to define a fix coordinate and zoom level for the initial map view.
- leaflet.init.lat¶
Unit: degrees
Type: double
Initial latitude to center the map view.
- leaflet.init.lon¶
Unit: degrees
Type: double
Initial longitude to center the map view.
- leaflet.init.zoom¶
Default:
3
Type: int
Initial zoom level for the map view.
Note
leaflet.tile.* Parmeters controlling the map tile layer.
- leaflet.tile.url¶
Default:
http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png
Type: string
Tile URL. See https://leafletjs.com/reference-1.7.1.html#tilelayer for a list of supported placeholders.
- leaflet.tile.attribution¶
Default:
"Map data © <a href="http://openstreetmap.org">OpenStreetMap</a> contributors"
Type: string
Tile attribution string displayed on the bottom right corner.
- leaflet.tile.maxZoom¶
Default:
18
Type: int
Maximum available zoom level.
Note
leaflet.control.* Defines available map controls typically displayed at bottom left map corner.
- leaflet.control.scaleMetric¶
Default:
true
Type: boolean
Adds a scale showing the map resolution in meter or kilometer at the map center.
- leaflet.control.scaleImperial¶
Default:
false
Type: boolean
Adds a scale showing the map resolution in feet or miles at the map center.
- leaflet.control.mousePosition¶
Default:
true
Type: boolean
Adds a control showing the geo location under the mouse cursor.
Note
search.* The search plugin provides a page to configure a search filter.
- search.resultLimit¶
Default:
100
Type: int
The maximum number of search results.
- search.distanceUnit¶
Default:
km
Type: string
The unit used for the radius of the circular region filter. This can either be ‘km’, ‘mi’ or ‘deg’. Conversion constants used: 1 mile = 1.609344 kilometers, 1 degree = 111.195079734632 kilometers.
- search.enableMap¶
Default:
true
Type: boolean
Enables interactive map region selection.
Note
feedback.* The feedback plugin implemets a email feedback form.
- feedback.from¶
Type: string
The email’s ‘From’ address (mandatory).
- feedback.to¶
Type: string
The email’s ‘To’ address (mandatory).
- feedback.subject¶
Default:
EQEvents feedback
Type: string
The email’s ‘Subject’.
- feedback.host¶
Default:
localhost
Type: string
SMTP host.
- feedback.port¶
Default:
25
Type: int
SMTP port.
- feedback.user¶
Type: string
User in case the SMTP server requires authorization.
- feedback.password¶
Type: string
Password in case the SMTP server requires authorization.
- feedback.tls¶
Default:
false
Type: boolean
Use StartTLS.
- feedback.ssl¶
Default:
false
Type: boolean
Use Secure Socket Layer (SSL).
Note
shakemap.* The shakemap plugin adds a shake map image to the event overview page. The image is generated by an external application, e.g. autosigma.
- shakemap.cmd¶
Default:
autosigma --ep
Type: string
Command generating the result file, invoked with the location of the SC3 XML file as last paramter.
- shakemap.minMag¶
Default:
5.0
Type: float
Minimum magnitude to trigger shake map generation.
- shakemap.resultFile¶
Default:
@ROOTDIR@/var/sigma/incidents/grid-mmi.png
Type: string
Expected location of the result file.
Command-Line Options¶
Generic¶
Verbosity¶
EQEvents¶
- -i, --input string¶
Input file to be processed immediately. EQEvents will not change into spooler mode after processing this file.
- --reprocess¶
Reprocess event detail pages and index pages for events found in database. This mode requires backupXML being enabled.
- --reprocess-index¶
Reprocess index pages for events found in database.