Advanced Server Configuration¶
Certain advanced functionality requires a more extensive server configuration. This is a bit more work but you can tweak that functionality to best suite your own needs.
You can find a complete example implementation here.
It works by implementing up to three callback functions to:
resolve station coordinates from network and station codes
resolve event parameters from event ids
calculate theoretical travel times
You can choose to implement any number of these - appropriate error messages will be raised if the server requires a callback function this is not available. The rest will keep on working just fine.
Note
Please raise a ValueError
within in the callback functions if something
does not go as expected. That will be caught by Instaseis; other exceptions
will result in a return code 500 (internal server error).
Contents of this Page
Finite Source Size Setting¶
Per default the \finite_source
route (POST /finite_source) allows
at most 1000 point sources for a single finite source. This limit can be
changed with the max_size_of_finite_sources
parameter passed to the server
launching script either on the command line or in the script.
Station Coordinates Callback¶
This callback function is used for the /coordinates
route, as well as
network
and station
based queries in the /seismograms
route. It
resolves network and station code searches to actual coordinates. How the
coordinates are resolved is up to the users but make sure it is fast. Also make
sure the coordinates are geocentric. Instaseis has a helper function to aid
with that: instaseis.helpers.elliptic_to_geocentric_latitude()
Affected routes:
Function Signature:
def get_station_coordinates(networks, stations):
...
return [...]
Parameters:
networks
: [list of strings], list of case-insensitive network ids. Wildcards*
and?
are allowed.stations
: [list of strings], list of case-insensitive station ids. Wildcards*
and?
are allowed.
Return Values:
A list with one dictionary per found station if successful. Each dictionary has the following keys:
"network"
,"station"
,"latitude"
,"longitude"
.An empty list if no station matching the query has been found.
Raise a
ValueError
for other cases.
Examples:
>>> get_station_coordinates(networks=["IU"], stations["ANMO"])
[{"latitude": 34.94591,
"longitude": -106.4572,
"network": "IU",
"station": "ANMO"}]
>>> get_station_coordinates(networks=["IU", "B*"], stations["ANT*", "ANM?"])
[{"latitude": 39.868,
"longitude": 32.7934,
"network": "IU",
"station": "ANTO"
}, {
"latitude": 34.94591,
"longitude": -106.4572,
"network": "IU",
"station": "ANMO"}]
>>> get_station_coordinates(networks=["AA", "BB"], stations["CC", "DD"])
[]
Event Parameters Callback¶
This callback function has a single purpose: resolve an event identifier to
event parameters. Users could choose to call an external web service within
that function or query a local database. It is used for the /event
route as
well as event identifier based queries in the /seismograms
route. Make sure
the coordinates are geocentric. Instaseis has a helper function to aid with
that: instaseis.helpers.elliptic_to_geocentric_latitude()
Affected routes:
Function Signature:
def get_event(event_id):
...
return {...}
Parameters:
event_id
: [str], event identifier
Return Values:
A dictionary with the event parameters and the following keys:
"m_rr"
,"m_tt"
,"m_pp"
,"m_rt"
,"m_rp"
,"m_tp"
,"latitude"
,"longitude"
,"depth_in_m"
,"origin_time"
. The tensor components have to be in Nm.A
ValueError
will be always be interpreted as a not found event.
Examples:
>>> get_event("B071791B")
{"m_rr": -58000000000000000,
"m_tt": 78100000000000000,
"m_pp": -20100000000000000,
"m_rt": -56500000000000000,
"m_rp": 108100000000000000,
"m_tp": 315300000000000000,
"latitude": -3.8,
"longitude": -104.21,
"depth_in_m": 0,
"origin_time": "1991-07-17T16:41:33.100000Z"}
>>> get_event("random_things")
ValueError: Event not found.
Travel Time Callback¶
This callback function is used for the /ttimes
route and for the phase
relative start and end times in the /seismograms
route. It receives source
and receiver coordinates as well as a phase name and is supposed to return the
travel time from source to receiver for that particular phase in seconds. The
coordinates can be assumed to be geocentric and the calculations should happen
in a spherical planet. Make sure to perform the calculations in the same model
that has been used to calculate the databases. Please note that this callback
function also receives the info
attribute dictionary of the database.
Affected routes:
Function Signature:
def get_travel_time(sourcelatitude, sourcelongitude, sourcedepthinmeters,
receiverlatitude, receiverlongitude,
receiverdepthinmeters, phase_name, db_info):
...
return ttime
Parameters:
sourcelatitude
: [float], geocentric source latitudesourcelongitude
: [float], source longitudesourcedepthinmeters
: [float], source depth in metersreceiverlatitude
: [float], geocentric receiver latitudereceiverlongitude
: [float], receiver longitudereceiverdepthinmeters
: [float], receiver depth in metersphase_name
: [str], case-sensitive phase namedb_info
: Theinfo
attribute dictionary of the used database. Useful to calculate travel times for different models depending on the database.
Return Values:
Travel time in seconds if successful.
None
if phase has no arrival for the given source-receiver geometry.Raise a
ValueError
for other cases, e.g. unknown phase name, invalid source-receiver geometry, …
Examples:
>>> get_travel_time(0.0, 50.0, 300000, 0.0, 0.0, 0.0, "P", {})
504.357
>>> get_travel_time(0.0, 50.0, 300000, 0.0, 0.0, 0.0, "Pdiff", {})
None
>>> get_travel_time(0.0, 50.0, 300000, 0.0, 0.0, 0.0, "bogus", {})
ValueError: Invalid phase name.
Hooking it up to the Instaseis Server¶
Best have a look at the full example implementation here.
You will have to create a new file and pass the three callback functions to the
launch_io_loop()
function. The following code snippet will give you a
similar command line interface to the default Instaseis server:
import argparse
import os
from instaseis.server.app import launch_io_loop
if __name__ == "__main__":
parser = argparse.ArgumentParser(
prog="python -m instaseis.server",
description='Launch an Instaseis server offering seismograms with a '
'REST API.')
parser.add_argument('--port', type=int, required=True,
help='Server port.')
parser.add_argument('--buffer_size_in_mb', type=int,
default=0, help='Size of the buffer in MB')
parser.add_argument('--max_size_of_finite_sources', type=int,
default=1000,
help='The maximum allowed number of point sources in '
'a single finite source for the /finite_source '
'route.')
parser.add_argument('db_path', type=str,
help='Database path')
parser.add_argument(
'--quiet', action='store_true',
help="Don't print any output. Overwrites the 'log_level` setting.")
parser.add_argument(
'--log-level', type=str, default='INFO',
choices=['CRITICAL', 'ERROR', 'WARNING', 'INFO', 'DEBUG', 'NOTSET'],
help='The log level for all Tornado loggers.')
args = parser.parse_args()
db_path = os.path.abspath(args.db_path)
launch_io_loop(db_path=db_path, port=args.port,
buffer_size_in_mb=args.buffer_size_in_mb,
quiet=args.quiet, log_level=args.log_level,
max_size_of_finite_sources=args.max_size_of_finite_sources,
station_coordinates_callback=get_station_coordinates,
event_info_callback=get_event,
travel_time_callback=get_travel_time)