@seismo/core
Version:
This is the package for the core library of Seismo, a JavaScript library for seismic data processing and visualization. It provides utilities for handling seismic data, including FDSN web services, waveform processing, and event handling. The library is d
890 lines (889 loc) • 28.2 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.EventQuery = exports.USGS_HOST = exports.SERVICE_NAME = exports.SERVICE_VERSION = void 0;
/*
* Philip Crotwell
* University of South Carolina, 2019
* https://www.seis.sc.edu
*/
const common_1 = require("./common");
const quakeml_1 = require("../events/quakeml");
Object.defineProperty(exports, "USGS_HOST", { enumerable: true, get: function () { return quakeml_1.USGS_HOST; } });
const utils_1 = require("../utils");
/**
* Major version of the FDSN spec supported here.
* Currently is 1.
*/
exports.SERVICE_VERSION = 1;
/**
* Service name as used in the FDSN DataCenters registry,
* https://www.fdsn.org/datacenters
*/
exports.SERVICE_NAME = `fdsnws-event-${exports.SERVICE_VERSION}`;
/**
* Query to a FDSN Event web service.
*
* @see https://www.fdsn.org/webservices/
* @param host optional host to connect to, defaults to USGS
*/
class EventQuery extends common_1.FDSNCommon {
/** @private */
_eventId;
/** @private */
_startTime;
/** @private */
_endTime;
/** @private */
_updatedAfter;
/** @private */
_minMag;
/** @private */
_maxMag;
/** @private */
_magnitudeType;
/** @private */
_minDepth;
/** @private */
_maxDepth;
/** @private */
_minLat;
/** @private */
_maxLat;
/** @private */
_minLon;
/** @private */
_maxLon;
/** @private */
_latitude;
/** @private */
_longitude;
/** @private */
_minRadius;
/** @private */
_maxRadius;
/** @private */
_includeArrivals;
/** @private */
_includeAllOrigins;
/** @private */
_includeAllMagnitudes;
/** @private */
_limit;
/** @private */
_offset;
/** @private */
_orderBy;
/** @private */
_contributor;
/** @private */
_catalog;
/** @private */
_format;
constructor(host) {
if (!(0, utils_1.isNonEmptyStringArg)(host)) {
host = quakeml_1.USGS_HOST;
}
super(host);
}
/**
* Gets/Sets the version of the fdsnws spec, 1 is currently the only value.
* Setting this is probably a bad idea as the code may not be compatible with
* the web service.
*
* @param value optional new value if setting
* @returns new value if getting, this if setting
*/
specVersion(value) {
(0, utils_1.doStringGetterSetter)(this, "specVersion", value);
return this;
}
getSpecVersion() {
return this._specVersion;
}
/**
* Gets/Sets the protocol, http or https. This should match the protocol
* of the page loaded, but is autocalculated and generally need not be set.
*
* @param value optional new value if setting
* @returns new value if getting, this if setting
*/
protocol(value) {
(0, utils_1.doStringGetterSetter)(this, "protocol", value);
return this;
}
getProtocol() {
return this._protocol;
}
/**
* Gets/Sets the remote host to connect to.
*
* @param value optional new value if setting
* @returns new value if getting, this if setting
*/
host(value) {
(0, utils_1.doStringGetterSetter)(this, "host", value);
return this;
}
getHost() {
return this._host;
}
/**
* Gets/Sets the remote port to connect to.
*
* @param value optional new value if setting
* @returns new value if getting, this if setting
*/
port(value) {
(0, utils_1.doIntGetterSetter)(this, "port", value);
return this;
}
getPort() {
return this._port;
}
/**
* Gets/Sets the nodata parameter, usually 404 or 204 (default), controlling
* the status code when no matching data is found by the service.
*
* @param value optional new value if setting
* @returns new value if getting, this if setting
*/
nodata(value) {
(0, utils_1.doIntGetterSetter)(this, "nodata", value);
return this;
}
getNodata() {
return this._nodata;
}
/**
* Get/Set the timeout in seconds for the request. Default is 30.
*
* @param value optional new value if setting
* @returns new value if getting, this if setting
*/
timeout(value) {
(0, utils_1.doFloatGetterSetter)(this, "timeoutSec", value);
return this;
}
getTimeout() {
return this._timeoutSec;
}
/**
* Get/Set the eventid query parameter.
*
* @param value optional new value if setting
* @returns new value if getting, this if setting
*/
eventId(value) {
(0, utils_1.doStringGetterSetter)(this, "eventId", value);
return this;
}
getEventId() {
return this._eventId;
}
/**
* Get/Set the starttime query parameter.
*
* @param value optional new value if setting
* @returns new value if getting, this if setting
*/
startTime(value) {
(0, utils_1.doMomentGetterSetter)(this, "startTime", value);
return this;
}
getStartTime() {
return this._startTime;
}
/**
* Get/Set the endtime query parameter.
*
* @param value optional new value if setting
* @returns new value if getting, this if setting
*/
endTime(value) {
(0, utils_1.doMomentGetterSetter)(this, "endTime", value);
return this;
}
getEndTime() {
return this._endTime;
}
/**
* Sets startTime and endTime using the given time window
*
* @param se time window
* @returns this
*/
timeRange(se) {
this.startTime((0, utils_1.validStartTime)(se));
this.endTime((0, utils_1.validEndTime)(se));
return this;
}
/**
* Get/Set the updatedafter query parameter.
*
* @param value optional new value if setting
* @returns new value if getting, this if setting
*/
updatedAfter(value) {
(0, utils_1.doMomentGetterSetter)(this, "updatedAfter", value);
return this;
}
getUpdatedAfter() {
return this._updatedAfter;
}
/**
* Get/Set the minmag query parameter.
*
* @param value optional new value if setting
* @returns new value if getting, this if setting
*/
minMag(value) {
(0, utils_1.doFloatGetterSetter)(this, "minMag", value);
return this;
}
getMinMag() {
return this._minMag;
}
/**
* Get/Set the maxmag query parameter.
*
* @param value optional new value if setting
* @returns new value if getting, this if setting
*/
maxMag(value) {
(0, utils_1.doFloatGetterSetter)(this, "maxMag", value);
return this;
}
getMaxMag() {
return this._maxMag;
}
/**
* Get/Set the magnitudetype query parameter.
*
* @param value optional new value if setting
* @returns new value if getting, this if setting
*/
magnitudeType(value) {
(0, utils_1.doStringGetterSetter)(this, "magnitudeType", value);
return this;
}
getMagnitudeType() {
return this._magnitudeType;
}
/**
* Get/Set the mindepth query parameter.
*
* @param value optional new value if setting
* @returns new value if getting, this if setting
*/
minDepth(value) {
(0, utils_1.doFloatGetterSetter)(this, "minDepth", value);
return this;
}
getMinDepth() {
return this._minDepth;
}
/**
* Get/Set the maxdepth query parameter.
*
* @param value optional new value if setting
* @returns new value if getting, this if setting
*/
maxDepth(value) {
(0, utils_1.doFloatGetterSetter)(this, "maxDepth", value);
return this;
}
getMaxDepth() {
return this._maxDepth;
}
/**
* Get/Set the minlat query parameter.
*
* @param value optional new value if setting
* @returns new value if getting, this if setting
*/
minLat(value) {
(0, utils_1.doFloatGetterSetter)(this, "minLat", value);
return this;
}
getMinLat() {
return this._minLat;
}
/**
* Get/Set the maxlat query parameter.
*
* @param value optional new value if setting
* @returns new value if getting, this if setting
*/
maxLat(value) {
(0, utils_1.doFloatGetterSetter)(this, "maxLat", value);
return this;
}
getMaxLat() {
return this._maxLat;
}
/**
* Get/Set the minlon query parameter.
*
* @param value optional new value if setting
* @returns new value if getting, this if setting
*/
minLon(value) {
(0, utils_1.doFloatGetterSetter)(this, "minLon", value);
return this;
}
getMinLon() {
return this._minLon;
}
/**
* Get/Set the maxlon query parameter.
*
* @param value optional new value if setting
* @returns new value if getting, this if setting
*/
maxLon(value) {
(0, utils_1.doFloatGetterSetter)(this, "maxLon", value);
return this;
}
getMaxLon() {
return this._maxLon;
}
/**
* Get/Set the latitude query parameter.
*
* @param value optional new value if setting
* @returns new value if getting, this if setting
*/
latitude(value) {
(0, utils_1.doFloatGetterSetter)(this, "latitude", value);
return this;
}
getLatitude() {
return this._latitude;
}
/**
* Get/Set the longitude query parameter.
*
* @param value optional new value if setting
* @returns new value if getting, this if setting
*/
longitude(value) {
(0, utils_1.doFloatGetterSetter)(this, "longitude", value);
return this;
}
getLongitude() {
return this._longitude;
}
/**
* Get/Set the minradius query parameter.
*
* @param value optional new value if setting
* @returns new value if getting, this if setting
*/
minRadius(value) {
(0, utils_1.doFloatGetterSetter)(this, "minRadius", value);
return this;
}
getMinRadius() {
return this._minRadius;
}
/**
* Get/Set the maxradius query parameter.
*
* @param value optional new value if setting
* @returns new value if getting, this if setting
*/
maxRadius(value) {
(0, utils_1.doFloatGetterSetter)(this, "maxRadius", value);
return this;
}
getMaxRadius() {
return this._maxRadius;
}
/**
* Get/Set the includearrivals query parameter.
*
* @param value optional new value if setting
* @returns new value if getting, this if setting
*/
includeArrivals(value) {
(0, utils_1.doBoolGetterSetter)(this, "includeArrivals", value);
return this;
}
getIncludeArrivals() {
return this._includeArrivals;
}
/**
* Get/Set the includeallorigins query parameter.
*
* @param value optional new value if setting
* @returns new value if getting, this if setting
*/
includeAllOrigins(value) {
(0, utils_1.doBoolGetterSetter)(this, "includeAllOrigins", value);
return this;
}
getIncludeAllOrigins() {
return this._includeAllOrigins;
}
/**
* Get/Set the includeallmagnitudes query parameter.
*
* @param value optional new value if setting
* @returns new value if getting, this if setting
*/
includeAllMagnitudes(value) {
(0, utils_1.doBoolGetterSetter)(this, "includeAllMagnitudes", value);
return this;
}
getIncludeAllMagnitudes() {
return this._includeAllMagnitudes;
}
/**
* Get/Set the format query parameter.
*
* @param value optional new value if setting
* @returns new value if getting, this if setting
*/
format(value) {
(0, utils_1.doStringGetterSetter)(this, "format", value);
return this;
}
getFormat() {
return this._format;
}
/**
* Get/Set the limit query parameter.
*
* @param value optional new value if setting
* @returns new value if getting, this if setting
*/
limit(value) {
(0, utils_1.doIntGetterSetter)(this, "limit", value);
return this;
}
getLimit() {
return this._limit;
}
/**
* Get/Set the offset query parameter.
*
* @param value optional new value if setting
* @returns new value if getting, this if setting
*/
offset(value) {
(0, utils_1.doIntGetterSetter)(this, "offset", value);
return this;
}
getOffset() {
return this._offset;
}
/**
* Get/Set the orderby query parameter.
*
* @param value optional new value if setting
* @returns new value if getting, this if setting
*/
orderBy(value) {
(0, utils_1.doStringGetterSetter)(this, "orderBy", value);
return this;
}
getOrderBy() {
return this._orderBy;
}
/**
* Get/Set the catalog query parameter.
*
* @param value optional new value if setting
* @returns new value if getting, this if setting
*/
catalog(value) {
(0, utils_1.doStringGetterSetter)(this, "catalog", value);
return this;
}
getCatalog() {
return this._catalog;
}
/**
* Get/Set the contributor query parameter.
*
* @param value optional new value if setting
* @returns new value if getting, this if setting
*/
contributor(value) {
(0, utils_1.doStringGetterSetter)(this, "contributor", value);
return this;
}
getContributor() {
return this._contributor;
}
latLonRegion(value) {
if (value instanceof common_1.LatLonBox) {
this._minLat = value.south;
this._maxLat = value.north;
this._minLon = value.west;
this._maxLon = value.east;
// unset
this._latitude = undefined;
this._longitude = undefined;
this._minRadius = undefined;
this._maxRadius = undefined;
}
else if (value instanceof common_1.LatLonRadius) {
this._latitude = value.latitude;
this._longitude = value.longitude;
this._minRadius = value.minRadius;
this._maxRadius = value.maxRadius;
// unset
this._minLat = undefined;
this._maxLat = undefined;
this._minLon = undefined;
this._maxLon = undefined;
}
else if (!(0, utils_1.isDef)(value)) {
// unset
this._latitude = undefined;
this._longitude = undefined;
this._minRadius = undefined;
this._maxRadius = undefined;
this._minLat = undefined;
this._maxLat = undefined;
this._minLon = undefined;
this._maxLon = undefined;
}
else {
throw new Error(`value argument is optional or LatLonRegion, but was type ${typeof value}, '${(0, utils_1.stringify)(value)}' `);
}
return this;
}
/**
* Checks to see if any parameter that would limit the data
* returned is set. This is a crude, coarse check to make sure
* the client doesn't ask for EVERYTHING the server has.
*
* @returns true is some parameter is set
*/
isSomeParameterSet() {
return ((0, utils_1.isDef)(this._eventId) ||
(0, utils_1.isDef)(this._startTime) ||
(0, utils_1.isDef)(this._endTime) ||
(0, utils_1.isDef)(this._minLat) ||
(0, utils_1.isDef)(this._maxLat) ||
(0, utils_1.isDef)(this._minLon) ||
(0, utils_1.isDef)(this._maxLon) ||
(0, utils_1.isDef)(this._latitude) ||
(0, utils_1.isDef)(this._longitude) ||
(0, utils_1.isDef)(this._minRadius) ||
(0, utils_1.isDef)(this._maxRadius) ||
(0, utils_1.isDef)(this._minDepth) ||
(0, utils_1.isDef)(this._maxDepth) ||
(0, utils_1.isDef)(this._limit) ||
(0, utils_1.isDef)(this._minMag) ||
(0, utils_1.isDef)(this._maxMag) ||
(0, utils_1.isDef)(this._updatedAfter) ||
(0, utils_1.isDef)(this._catalog) ||
(0, utils_1.isDef)(this._contributor));
}
/**
* Queries the remote service and parses the returned xml.
*
* @returns Promise to an Array of Quake objects.
*/
query() {
return this.queryEventParameters().then((eventParameters) => {
return eventParameters.eventList;
});
}
queryEventParameters() {
return this.queryRawXml().then((rawXml) => {
return (0, quakeml_1.parseQuakeML)(rawXml, this._host);
});
}
/**
* Queries the remote server, to get QuakeML xml.
*
* @returns xml Document
*/
queryRawXml() {
if (!this.isSomeParameterSet()) {
throw new Error("Must set some parameter to avoid asking for everything.");
}
const url = this.formURL();
const fetchInit = (0, utils_1.defaultFetchInitObj)(utils_1.XML_MIME);
return (0, utils_1.doFetchWithTimeout)(url, fetchInit, this._timeoutSec * 1000)
.then((response) => {
if (response.status === 200) {
return response.text();
}
else if (response.status === 204 ||
((0, utils_1.isDef)(this._nodata) && response.status === this._nodata)) {
// 204 is nodata, so successful but empty
return quakeml_1.FAKE_EMPTY_XML;
}
else {
throw new Error(`Status not successful: ${response.status}`);
}
})
.then(function (rawXmlText) {
return new DOMParser().parseFromString(rawXmlText, utils_1.XML_MIME);
});
}
/**
* Forms the basic URL to contact the web service, without any query paramters
*
* @returns the url
*/
formBaseURL() {
let colon = ":";
if (!this._host || this._host === quakeml_1.USGS_HOST) {
this._host = quakeml_1.USGS_HOST;
// usgs does 301 moved permanently to https
this._protocol = "https:";
}
if (this._protocol.endsWith(colon)) {
colon = "";
}
return (this._protocol +
colon +
"//" +
this._host +
(this._port === 80 ? "" : ":" + (0, utils_1.stringify)(this._port)) +
"/fdsnws/event/" +
this._specVersion);
}
/**
* Forms the URL to get catalogs from the web service, without any query paramters
*
* @returns the url
*/
formCatalogsURL() {
return this.formBaseURL() + "/catalogs";
}
/**
* Queries the remote web service to get known catalogs
*
* @returns Promise to Array of catalog names
*/
queryCatalogs() {
const url = this.formCatalogsURL();
const fetchInit = (0, utils_1.defaultFetchInitObj)(utils_1.XML_MIME);
return (0, utils_1.doFetchWithTimeout)(url, fetchInit, this._timeoutSec * 1000)
.then((response) => {
if (response.status === 200) {
return response.text();
}
else {
throw new Error(`Status not 200: ${response.status}`);
}
})
.then((rawXmlText) => {
return new DOMParser().parseFromString(rawXmlText, utils_1.XML_MIME);
})
.then((rawXml) => {
if (!rawXml) {
throw new Error("raw xml from DOMParser is null.");
}
const top = rawXml.documentElement;
if (!top) {
throw new Error("documentElement in xml from DOMParser is null.");
}
const catalogArray = top.getElementsByTagName("Catalog");
const out = [];
if (catalogArray) {
for (let i = 0; i < catalogArray.length; i++) {
const item = catalogArray.item(i);
if (item && (0, utils_1.isDef)(item.textContent)) {
out.push(item.textContent);
}
}
}
return out;
});
}
/**
* Forms the URL to get contributors from the web service, without any query paramters
*
* @returns the url
*/
formContributorsURL() {
return this.formBaseURL() + "/contributors";
}
/**
* Queries the remote web service to get known contributors
*
* @returns Promise to Array of contributor names
*/
queryContributors() {
const url = this.formContributorsURL();
const fetchInit = (0, utils_1.defaultFetchInitObj)(utils_1.XML_MIME);
return (0, utils_1.doFetchWithTimeout)(url, fetchInit, this._timeoutSec * 1000)
.then((response) => {
if (response.status === 200) {
return response.text();
}
else {
throw new Error(`Status not 200: ${response.status}`);
}
})
.then(function (rawXmlText) {
return new DOMParser().parseFromString(rawXmlText, utils_1.XML_MIME);
})
.then(function (rawXml) {
const top = rawXml.documentElement;
if (!top) {
throw new Error("documentElement in xml from DOMParser is null.");
}
const contributorArray = top.getElementsByTagName("Contributor");
const out = [];
if (contributorArray) {
for (let i = 0; i < contributorArray.length; i++) {
const item = contributorArray.item(i);
if (item && (0, utils_1.isDef)(item.textContent)) {
out.push(item.textContent);
}
}
}
return out;
});
}
/**
* Forms the URL to get version from the web service, without any query paramters
*
* @returns the url
*/
formVersionURL() {
return this.formBaseURL() + "/version";
}
/**
* Queries the remote web service to get its version
*
* @returns Promise to version string
*/
queryVersion() {
const url = this.formVersionURL();
const fetchInit = (0, utils_1.defaultFetchInitObj)(utils_1.TEXT_MIME);
return (0, utils_1.doFetchWithTimeout)(url, fetchInit, this._timeoutSec * 1000).then((response) => {
if (response.status === 200) {
return response.text();
}
else {
throw new Error(`Status not 200: ${response.status}`);
}
});
}
/**
* Form URL to query the remote web service, encoding the query parameters.
*
* @returns url
*/
formURL() {
let colon = ":";
if (this._protocol.endsWith(colon)) {
colon = "";
}
let url = this.formBaseURL() + "/query?";
if (this._eventId) {
url = url + (0, utils_1.makeParam)("eventid", this._eventId);
}
if (this._startTime) {
url = url + (0, utils_1.makeParam)("starttime", (0, utils_1.toIsoWoZ)(this._startTime));
}
if (this._endTime) {
url = url + (0, utils_1.makeParam)("endtime", (0, utils_1.toIsoWoZ)(this._endTime));
}
if ((0, utils_1.isNumArg)(this._minMag)) {
url = url + (0, utils_1.makeParam)("minmag", this._minMag);
}
if ((0, utils_1.isNumArg)(this._maxMag)) {
url = url + (0, utils_1.makeParam)("maxmag", this._maxMag);
}
if ((0, utils_1.isStringArg)(this._magnitudeType)) {
url = url + (0, utils_1.makeParam)("magnitudetype", this._magnitudeType);
}
if ((0, utils_1.isNumArg)(this._minDepth)) {
url = url + (0, utils_1.makeParam)("mindepth", this._minDepth);
}
if ((0, utils_1.isNumArg)(this._maxDepth)) {
url = url + (0, utils_1.makeParam)("maxdepth", this._maxDepth);
}
if ((0, utils_1.isNumArg)(this._minLat)) {
url = url + (0, utils_1.makeParam)("minlat", this._minLat);
}
if ((0, utils_1.isNumArg)(this._maxLat)) {
url = url + (0, utils_1.makeParam)("maxlat", this._maxLat);
}
if ((0, utils_1.isNumArg)(this._minLon)) {
url = url + (0, utils_1.makeParam)("minlon", this._minLon);
}
if ((0, utils_1.isNumArg)(this._maxLon)) {
url = url + (0, utils_1.makeParam)("maxlon", this._maxLon);
}
if ((0, utils_1.isNumArg)(this._minRadius) || (0, utils_1.isNumArg)(this._maxRadius)) {
if ((0, utils_1.isNumArg)(this._latitude) && (0, utils_1.isNumArg)(this._longitude)) {
url =
url +
(0, utils_1.makeParam)("latitude", this._latitude) +
(0, utils_1.makeParam)("longitude", this._longitude);
if ((0, utils_1.isNumArg)(this._minRadius)) {
url = url + (0, utils_1.makeParam)("minradius", this._minRadius);
}
if ((0, utils_1.isNumArg)(this._maxRadius)) {
url = url + (0, utils_1.makeParam)("maxradius", this._maxRadius);
}
}
else {
throw new Error(`Cannot use minRadius or maxRadius without latitude and longitude: lat=` +
`${this._latitude} lon= ${this._longitude}`);
}
}
if (this._includeArrivals) {
if (this._host !== quakeml_1.USGS_HOST) {
url = url + "includearrivals=true&";
}
else {
// USGS does not support includearrivals, but does actually
// include the arrivals for an eventid= style query
if (this._eventId) {
// ok, works without the param
}
else {
throw new Error("USGS host, earthquake.usgs.gov, does not support includearrivals parameter.");
}
}
}
if ((0, utils_1.isObject)(this._updatedAfter)) {
url = url + (0, utils_1.makeParam)("updatedafter", this._updatedAfter);
}
if ((0, utils_1.isDef)(this._includeAllOrigins)) {
url = url + (0, utils_1.makeParam)("includeallorigins", this._includeAllOrigins);
}
if ((0, utils_1.isDef)(this._includeAllMagnitudes)) {
url = url + (0, utils_1.makeParam)("includeallmagnitudes", this._includeAllMagnitudes);
}
if ((0, utils_1.isStringArg)(this._format)) {
url = url + (0, utils_1.makeParam)("format", this._format);
}
if ((0, utils_1.isNumArg)(this._limit)) {
url = url + (0, utils_1.makeParam)("limit", this._limit);
}
if ((0, utils_1.isNumArg)(this._offset)) {
url = url + (0, utils_1.makeParam)("offset", this._offset);
}
if ((0, utils_1.isStringArg)(this._orderBy)) {
url = url + (0, utils_1.makeParam)("orderby", this._orderBy);
}
if ((0, utils_1.isStringArg)(this._catalog)) {
url = url + (0, utils_1.makeParam)("catalog", this._catalog);
}
if ((0, utils_1.isStringArg)(this._contributor)) {
url = url + (0, utils_1.makeParam)("contributor", this._contributor);
}
if ((0, utils_1.isDef)(this._nodata)) {
url = url + (0, utils_1.makeParam)("nodata", this._nodata);
}
if (url.endsWith("&") || url.endsWith("?")) {
url = url.substr(0, url.length - 1); // zap last & or ?
}
return url;
}
}
exports.EventQuery = EventQuery;