Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
G
geomag-algorithms
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Container Registry
Model registry
Operate
Environments
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
ghsc
National Geomagnetism Program
geomag-algorithms
Commits
6a976561
Commit
6a976561
authored
5 years ago
by
Travis Rivers
Committed by
Jeremy M Fee
5 years ago
Browse files
Options
Downloads
Patches
Plain Diff
add error handling
parent
e639a2c7
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
geomagio/webservice/data.py
+204
-93
204 additions, 93 deletions
geomagio/webservice/data.py
with
204 additions
and
93 deletions
geomagio/webservice/data.py
+
204
−
93
View file @
6a976561
from
datetime
import
datetime
import
os
from
flask
import
Blueprint
,
Flask
,
jsonify
,
render_template
,
request
,
Response
from
obspy
import
UTCDateTime
from
collections
import
OrderedDict
from
json
import
dumps
from
geomagio.edge
import
EdgeFactory
from
geomagio.iaga2002
import
IAGA2002Writer
from
geomagio.imfjson
import
IMFJSONWriter
blueprint
=
Blueprint
(
'
data
'
,
__name__
)
DEFAULT_DATA_TYPE
=
"
variation
"
DEFAULT_ELEMENTS
=
(
"
X
"
,
"
Y
"
,
"
Z
"
,
"
F
"
)
DEFAULT_OUTPUT_FORMAT
=
"
iaga2002
"
DEFAULT_SAMPLING_PERIOD
=
"
60
"
ERROR_CODE_MESSAGES
=
{
204
:
"
No Data
"
,
400
:
"
Bad Request
"
,
404
:
"
Not Found
"
,
409
:
"
Conflict
"
,
500
:
"
Internal Server Error
"
,
501
:
"
Not Implemented
"
,
503
:
"
Service Unavailable
"
,
}
VALID_DATA_TYPES
=
[
"
variation
"
,
"
adjusted
"
,
"
quasi-definitive
"
,
"
definitive
"
]
VALID_OUTPUT_FORMATS
=
[
"
iaga2002
"
,
"
json
"
]
VALID_SAMPLING_PERIODS
=
[
"
1
"
,
"
60
"
]
blueprint
=
Blueprint
(
"
data
"
,
__name__
)
factory
=
EdgeFactory
(
host
=
'
cwbpub.cr.usgs.gov
'
,
port
=
2060
,
write_port
=
7981
)
def
init_app
(
app
:
Flask
):
global
blueprint
global
factory
app
.
register_blueprint
(
blueprint
)
@blueprint.route
(
'
/data
'
,
methods
=
[
'
GET
'
])
class
WebServiceQuery
(
object
):
"""
Query parameters for a web service request.
Parameters
----------
observatory_id : str
observatory
starttime : obspy.core.UTCDateTime
time of first requested sample
endtime : obspy.core.UTCDateTime
time of last requested sample
elements : array_like
list of requested elements
sampling_period : int
period between samples in seconds
default 60.
data_type : {
'
variation
'
,
'
adjusted
'
,
'
quasi-definitive
'
,
'
definitive
'
}
data type
default
'
variation
'
.
output_format : {
'
iaga2002
'
,
'
json
'
}
output format.
default
'
iaga2002
'
.
"""
def
__init__
(
self
,
observatory_id
=
None
,
starttime
=
None
,
endtime
=
None
,
elements
=
None
,
sampling_period
=
60
,
data_type
=
"
variation
"
,
output_format
=
"
iaga2002
"
,
):
self
.
observatory_id
=
observatory_id
self
.
starttime
=
starttime
self
.
endtime
=
endtime
self
.
elements
=
elements
self
.
sampling_period
=
sampling_period
self
.
data_type
=
data_type
self
.
output_format
=
output_format
def
_verify_parameters
(
self
):
"""
Verify that parameters are valid.
Raises
------
WebServiceException
if any parameters are not supported.
"""
if
len
(
self
.
elements
)
>
4
and
self
.
output_format
==
"
iaga2002
"
:
raise
WebServiceException
(
"
No more than four elements allowed for iaga2002 format.
"
)
if
self
.
starttime
>
self
.
endtime
:
raise
WebServiceException
(
"
Starttime must be before endtime.
"
)
if
self
.
data_type
not
in
VALID_DATA_TYPES
:
raise
WebServiceException
(
'
Bad type value
"
%s
"
.
'
"
Valid values are: %s
"
%
(
self
.
data_type
,
VALID_DATA_TYPES
)
)
if
self
.
sampling_period
not
in
VALID_SAMPLING_PERIODS
:
raise
WebServiceException
(
'
Bad sampling_period value
"
%s
"
.
'
"
Valid values are: %s
"
%
(
self
.
sampling_period
,
VALID_SAMPLING_PERIODS
)
)
if
self
.
output_format
not
in
VALID_OUTPUT_FORMATS
:
raise
WebServiceException
(
'
Bad format value
"
%s
"
.
'
"
Valid values are: %s
"
%
(
self
.
output_format
,
VALID_OUTPUT_FORMATS
)
)
@blueprint.route
(
"
/data
"
,
methods
=
[
"
GET
"
])
def
get_data
():
query_params
=
request
.
args
url
=
request
.
url
if
not
query_params
:
return
render_template
(
"
usage.html
"
)
parsed_query
=
parse_query
(
query_params
)
return
render_template
(
'
usage.html
'
)
try
:
parsed_query
.
_verify_parameters
()
except
Exception
as
e
:
message
=
str
(
e
)
error_body
=
error
(
400
,
message
,
parsed_query
,
url
)
return
error_body
query
=
parse_query
(
query_params
)
timeseries
=
get_timeseries
(
parse
d
_query
)
timeseries
=
get_
timeseries
(
query
)
return
format_
timeseries
(
timeseries
,
parsed_
query
)
return
format_timeseries
(
timeseries
,
query
)
def
error
(
code
,
message
,
query
,
url
):
error_body
=
http_error
(
code
,
message
,
query
,
url
)
status
=
str
(
code
)
+
'
'
+
ERROR_CODE_MESSAGES
[
code
]
Response
(
error_body
,
mimetype
=
"
text/plain
"
)
return
error_body
def
http_error
(
code
,
message
,
query
,
url
):
if
query
.
output_format
==
'
json
'
:
http_error_body
=
json_error
(
code
,
message
,
url
)
return
http_error_body
else
:
http_error_body
=
iaga2002_error
(
code
,
message
)
return
http_error_body
def
json_error
(
code
,
message
,
url
):
error_dict
=
OrderedDict
()
error_dict
[
'
type
'
]
=
"
Error
"
error_dict
[
'
metadata
'
]
=
OrderedDict
()
error_dict
[
'
metadata
'
][
'
status
'
]
=
400
date
=
datetime
.
utcnow
().
strftime
(
"
%Y-%m-%dT%H:%M:%S.%fZ
"
)
error_dict
[
'
metadata
'
][
'
generated
'
]
=
date
error_dict
[
'
metadata
'
][
'
url
'
]
=
url
status_message
=
ERROR_CODE_MESSAGES
[
code
]
error_dict
[
'
metadata
'
][
'
title
'
]
=
status_message
error_dict
[
'
metadata
'
][
'
error
'
]
=
message
error_body
=
dumps
(
error_dict
,
ensure_ascii
=
True
).
encode
(
'
utf8
'
)
return
error_body
def
iaga2002_error
(
code
,
message
,
url
):
status_message
=
ERROR_CODE_MESSAGES
[
code
]
error_body
=
'
Error
'
+
str
(
code
)
+
'
:
'
+
status_message
+
\
'
\n\n
'
+
message
+
'
\n\n
'
+
\
'
Usage details are available from
'
+
\
'
http://geomag.usgs.gov/ws/edge/
\n\n
'
+
\
'
Request:
\n
'
+
\
url
+
'
\n\n
'
+
\
'
Request Submitted:
\n
'
+
\
datetime
.
utcnow
().
strftime
(
"
%Y-%m-%dT%H:%M:%SZ
"
)
+
'
\n\n
'
return
error_body
def
parse_query
(
query
):
"""
Parse request arguments into a set of parameters
...
...
@@ -42,121 +189,85 @@ def parse_query(query):
Returns
-------
params: dictiona
ry
query parameters dictionary
WebServiceQue
ry
parsed query object
Raises
------
WebServiceException
if any parameters are not supported.
"""
params
=
{}
# Get
end time
if
not
query
.
get
(
'
endtime
'
):
# Get
values
if
not
query
.
get
(
"
endtime
"
):
now
=
datetime
.
now
()
today
=
UTCDateTime
(
now
.
year
,
now
.
month
,
now
.
day
,
0
)
today
=
UTCDateTime
(
now
.
year
,
now
.
month
,
now
.
day
,
0
)
end_time
=
today
params
[
'
End Time
'
]
=
end_time
else
:
params
[
'
End T
ime
'
]
=
UTCDateTime
(
query
.
get
(
'
endtime
'
))
end_t
ime
=
UTCDateTime
(
query
.
get
(
"
endtime
"
))
# Get start time
if
not
query
.
get
(
'
starttime
'
):
start_time
=
UTCDateTime
(
params
[
'
End Time
'
])
-
(
24
*
60
*
60
-
1
)
params
[
'
Start Time
'
]
=
UTCDateTime
(
start_time
)
if
not
query
.
get
(
"
starttime
"
):
start_time
=
UTCDateTime
(
query
.
get
(
"
endtime
"
))
-
(
24
*
60
*
60
-
1
)
else
:
params
[
'
S
tart
T
ime
'
]
=
UTCDateTime
(
query
.
get
(
'
starttime
'
))
s
tart
_t
ime
=
UTCDateTime
(
query
.
get
(
"
starttime
"
))
# Get sampling period
params
[
'
Sampling Period
'
]
=
query
.
get
(
'
sampling_period
'
)
if
not
query
.
get
(
"
sampling_period
"
):
sampling_period
=
DEFAULT_SAMPLING_PERIOD
else
:
sampling_period
=
query
.
get
(
"
sampling_period
"
)
if
params
[
'
Sampling Period
'
]
==
'
1
'
:
params
[
'
Sampling Period
'
]
=
'
second
'
if
not
query
.
get
(
"
format
"
):
format
=
DEFAULT_OUTPUT_FORMAT
else
:
format
=
query
.
get
(
"
format
"
)
if
params
[
'
Sampling Period
'
]
==
'
60
'
:
params
[
'
Sampling Period
'
]
=
'
minute
'
observatory
=
query
.
get
(
"
observatory
"
)
# Get format
if
query
.
get
(
'
format
'
):
params
[
'
Format
'
]
=
query
.
get
(
'
format
'
)
if
not
query
.
get
(
"
channels
"
):
channels
=
DEFAULT_ELEMENTS
else
:
params
[
'
Format
'
]
=
'
iaga2002
'
# Get observatory
params
[
'
Observatory
'
]
=
query
.
get
(
'
observatory
'
)
channels
=
query
.
get
(
"
channels
"
).
split
(
"
,
"
)
# Get channels
channels
=
query
.
get
(
'
channels
'
).
split
(
'
,
'
)
params
[
'
Channels
'
]
=
channels
type
=
query
.
get
(
"
type
"
)
# Get data type
params
[
'
Type
'
]
=
query
.
get
(
'
type
'
)
params
=
WebServiceQuery
()
validate_parameters
(
params
)
params
.
observatory_id
=
observatory
params
.
starttime
=
start_time
params
.
endtime
=
end_time
params
.
elements
=
channels
params
.
sampling_period
=
sampling_period
params
.
data_type
=
type
params
.
output_format
=
format
return
params
def
validate_parameters
(
params
):
"""
Verify that parameters are valid.
Parameters
----------
params: dict
dictionary of parsed query parameters
Raises
------
WebServiceException
if any parameters are not supported.
"""
valid_data_types
=
[
'
variation
'
,
'
adjusted
'
,
'
quasi-definitive
'
,
'
definitive
'
]
valid_formats
=
[
'
iaga2002
'
,
'
json
'
]
valid_sampling_periods
=
[
'
second
'
,
'
minute
'
]
if
len
(
params
[
'
Channels
'
])
>
4
and
params
[
'
Format
'
]
==
'
iaga2002
'
:
raise
WebServiceException
(
'
No more than four elements allowed for Iaga2002 format.
'
)
if
params
[
'
Start Time
'
]
>
params
[
'
End Time
'
]:
raise
WebServiceException
(
'
Start time must be before end time.
'
)
if
params
[
'
Type
'
]
not
in
valid_data_types
:
raise
WebServiceException
(
'
Bad data type:
'
+
params
[
'
Type
'
]
+
'
. Valid values are:
'
+
'
,
'
.
join
(
valid_data_types
)
+
'
.
'
)
if
params
[
'
Sampling Period
'
]
not
in
valid_sampling_periods
:
raise
WebServiceException
(
'
Bad sampling_period value:
'
+
params
[
'
Sampling Period
'
]
+
'
. Valid values are: 1, 60.
'
)
if
params
[
'
Format
'
]
not
in
valid_formats
:
raise
WebServiceException
(
'
Bad format value:
'
+
params
[
'
Format
'
]
+
'
. Valid values are:
'
+
'
,
'
.
join
(
valid_formats
))
def
get_timeseries
(
query
):
"""
Parameters
----------
query: dict
dictionary of
parsed query
parameters
WebServiceQuery
parsed query
object
Returns
-------
obspy.core.Stream
timeseries object with requested data
"""
factory
=
EdgeFactory
()
if
query
.
sampling_period
==
"
1
"
:
query
.
sampling_period
=
"
second
"
if
query
.
sampling_period
==
"
60
"
:
query
.
sampling_period
=
"
minute
"
timeseries
=
factory
.
get_timeseries
(
query
[
'
Start Time
'
],
query
[
'
End Time
'
],
query
[
'
Observatory
'
],
query
[
'
Channels
'
],
query
[
'
Type
'
],
query
[
'
Sampling Period
'
])
query
.
starttime
,
query
.
endtime
,
query
.
observatory_id
,
query
.
elements
,
query
.
data_type
,
query
.
sampling_period
)
return
timeseries
...
...
@@ -169,23 +280,23 @@ def format_timeseries(timeseries, query):
obspy.core.Stream
timeseries object with requested data
query: dict
dictionary of
parsed query
parameters
WebServiceQuery
parsed query
object
Returns
-------
unicode
IAGA2002 or JSON formatted string.
"""
if
query
[
'
Format
'
]
==
'
json
'
:
json_output
=
IMFJSONWriter
.
format
(
timeseries
,
query
[
'
Channels
'
])
if
query
.
output_format
==
"
json
"
:
json_output
=
IMFJSONWriter
.
format
(
timeseries
,
query
.
elements
)
json_output
=
Response
(
json_output
,
mimetype
=
"
application/json
"
)
return
json_output
else
:
iaga_output
=
IAGA2002Writer
.
format
(
timeseries
,
query
[
'
Channels
'
])
iaga_output
=
Response
(
iaga_output
,
mimetype
=
"
text / plain
"
)
iaga_output
=
IAGA2002Writer
.
format
(
timeseries
,
query
.
elements
)
iaga_output
=
Response
(
iaga_output
,
mimetype
=
"
text/plain
"
)
return
iaga_output
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment