Skip to content

Commit 72a7046

Browse files
committed
Updated docstrings for documentation purposes
Added load_catalog method to catalogs Updated __init__.py in main module for safe importing Updated installing.rst instructions for default user installation
1 parent 0839a3a commit 72a7046

18 files changed

+514
-372
lines changed

bin/query_comcat_catalog.py

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#! /usr/bin/env python
22

3-
## This script requires that COMCAT_REPO env_var is set and points to a writeable directory.
3+
## This script checks for COMCAT_REPO env_var is set and points to a writeable directory.
44
## For example, you can set this script up to a cronjob to recovery the ComCat catalog daily.
55

66
import datetime
@@ -38,7 +38,10 @@
3838
print("Min Magnitude: {}\n".format(comcat.min_magnitude))
3939

4040
# file paths
41-
base_dir = os.environ['COMCAT_REPO']
41+
try:
42+
base_dir = os.environ['COMCAT_REPO']
43+
except:
44+
base_dir = '.'
4245
fname = os.path.join(base_dir, now.strftime('%Y-%m-%d-comcat.json'))
4346
repo = FileSystem(url=fname)
4447

csep/__init__.py

+32-252
Original file line numberDiff line numberDiff line change
@@ -1,252 +1,32 @@
1-
import os
2-
import time
3-
from csep.core.forecasts import GriddedForecast, CatalogForecast
4-
from csep.core.catalogs import UCERF3Catalog, ZMAPCatalog, ComcatCatalog, CSEPCatalog
5-
from csep.models import EvaluationResult
6-
from csep.core.repositories import FileSystem
7-
from csep.utils.file import get_file_extension
8-
from csep.utils.time_utils import strptime_to_utc_datetime
9-
10-
def load_stochastic_event_sets(filename, type='ascii', format='native', **kwargs):
11-
""" General function to load stochastic event sets
12-
13-
This function returns a generator to iterate through a collection of catalogs.
14-
To load a forecast and include metadata use :func:`csep.load_catalog_forecast`.
15-
16-
Args:
17-
filename (str): name of file or directory where stochastic event sets live.
18-
type (str): either 'ucerf3' or 'csep' depending on the type of observed_catalog to load
19-
format (str): ('csep' or 'native') if native catalogs are not converted to csep format.
20-
**kwargs: see the documentation of that class corresponding to the type you selected
21-
22-
Returns:
23-
(generator): :class:`~csep.core.catalogs.AbstractBaseCatalog`
24-
25-
"""
26-
if type not in ('ucerf3', 'ascii'):
27-
raise ValueError("type must be one of the following: (ucerf3)")
28-
29-
# use mapping to dispatch to correct function
30-
# in general, stochastic event sets are loaded with classmethods and single catalogs use the
31-
# constructor
32-
mapping = {'ucerf3': UCERF3Catalog.load_catalogs,
33-
'ascii': CSEPCatalog.load_ascii_catalogs}
34-
35-
# dispatch to proper loading function
36-
result = mapping[type](filename, **kwargs)
37-
38-
# factory function to load catalogs from different classes
39-
while True:
40-
try:
41-
catalog = next(result)
42-
except StopIteration:
43-
return
44-
except Exception:
45-
raise
46-
if format == 'native':
47-
yield catalog
48-
elif format == 'csep':
49-
yield catalog.get_csep_format()
50-
else:
51-
raise ValueError('format must be either "native" or "csep!')
52-
53-
54-
def load_catalog(filename, type=None, format='native', **kwargs):
55-
""" General function to load single catalog
56-
57-
See corresponding class documentation for additional parameters.
58-
59-
Args:
60-
type (str): either 'ucerf3' or 'comcat'
61-
format (str): ('csep' or 'native'), and determines whether the observed_catalog should be converted into the csep
62-
formatted observed_catalog or kept as native.
63-
64-
Returns (:class:`~csep.core.catalogs.AbstractBaseCatalog`)
65-
"""
66-
if type not in ('ucerf3', 'comcat', 'csep'):
67-
raise ValueError("type must be one of the following: ('ucerf3', 'comcat', 'csep')")
68-
69-
# add entry point to load observed_catalog here.
70-
mapping = {'ucerf3': UCERF3Catalog,
71-
'csep': ZMAPCatalog,
72-
'comcat': ComcatCatalog}
73-
74-
# treat json files using the from_dict() member instead of constructor
75-
if get_file_extension(filename) == 'json':
76-
catalog = mapping[type](filename=None, **kwargs)
77-
repo = FileSystem(url=filename)
78-
catalog = repo.load(catalog)
79-
else:
80-
catalog = mapping[type](filename=filename, **kwargs)
81-
82-
# convert to csep format if needed
83-
if format == 'native':
84-
return_val = catalog
85-
elif format == 'csep':
86-
return_val = catalog.get_csep_format()
87-
else:
88-
raise ValueError('format must be either "native" or "csep"')
89-
return return_val
90-
91-
def query_comcat(start_time, end_time, min_magnitude=2.50,
92-
min_latitude=31.50, max_latitude=43.00,
93-
min_longitude=-125.40, max_longitude=-113.10, region=None, verbose=True):
94-
"""
95-
Access Comcat catalog through web service
96-
97-
Args:
98-
start_time: datetime object of start of catalog
99-
end_time: datetime object for end of catalog
100-
min_magnitude: minimum magnitude to query
101-
min_latitude: maximum magnitude to query
102-
max_latitude: max latitude of bounding box
103-
min_longitude: min latitude of bounding box
104-
max_longitude: max longitude of bounding box
105-
region: :class:`csep.core.
106-
verbose:
107-
108-
Returns:
109-
110-
"""
111-
112-
# Todo: check if datetime has utc timezone and if not set it, and issue a warning to the user.
113-
114-
t0 = time.time()
115-
comcat = ComcatCatalog(start_time=start_time, end_time=end_time,
116-
name='Comcat', min_magnitude=min_magnitude,
117-
min_latitude=min_latitude, max_latitude=max_latitude,
118-
min_longitude=min_longitude, max_longitude=max_longitude, region=region, query=True)
119-
t1 = time.time()
120-
print("Fetched Comcat observed_catalog in {} seconds.\n".format(t1 - t0))
121-
if verbose:
122-
print("Downloaded observed_catalog from ComCat with following parameters")
123-
print("Start Date: {}\nEnd Date: {}".format(str(comcat.start_time), str(comcat.end_time)))
124-
print("Min Latitude: {} and Max Latitude: {}".format(comcat.min_latitude, comcat.max_latitude))
125-
print("Min Longitude: {} and Max Longitude: {}".format(comcat.min_longitude, comcat.max_longitude))
126-
print("Min Magnitude: {}".format(comcat.min_magnitude))
127-
print(f"Found {comcat.get_number_of_events()} events in the Comcat observed_catalog.")
128-
print(f'Processing Catalogs.')
129-
return comcat
130-
131-
def load_evaluation_result(fname):
132-
""" Load evaluation result stored as json file.
133-
134-
Returns:
135-
:class:`csep.core.evaluations.EvaluationResult`
136-
137-
"""
138-
repo = FileSystem(url=fname)
139-
result = repo.load(EvaluationResult())
140-
return result
141-
142-
def write_json(object, fname):
143-
""" Easily write object to json file that implements the to_dict() method
144-
145-
Args:
146-
object (class): must implement a method called to_dict()
147-
fname (str): path of the file to write evaluation results
148-
149-
Returns:
150-
NoneType
151-
"""
152-
repo = FileSystem(url=fname)
153-
repo.save(object.to_dict())
154-
155-
def load_gridded_forecast(fname, loader=None, **kwargs):
156-
""" Loads grid based forecast from hard-disk.
157-
158-
The function loads the forecast provided with at the filepath defined by fname. The function attempts to understand
159-
the file format based on the extension of the filepath. Optionally, if loader function is provided, that function
160-
will be used to load the forecast. The loader function should return a :class:`csep.core.forecasts.GriddedForecast`
161-
class with the region and magnitude members correctly assigned.
162-
163-
File extensions:
164-
.dat -> CSEP ascii format
165-
.xml -> CSEP xml format (not yet implemented)
166-
.h5 -> CSEP hdf5 format (not yet implemented)
167-
.bin -> CSEP binary format (not yet implemented)
168-
169-
Args:
170-
fname (str): path of grid based forecast
171-
loader (func): function to load forecast in bespoke format needs to return :class:`csep.core.forecasts.GriddedForecast`
172-
and first argument should be required and the filename of the forecast to load
173-
called as loader(func, **kwargs).
174-
175-
**kwargs: passed into loader function
176-
177-
Throws:
178-
FileNotFoundError: when the file extension is not known and a loader is not provided.
179-
AttributeError: if loader is provided and is not callable.
180-
181-
Returns:
182-
:class:`csep.core.forecasts.GriddedForecast`
183-
"""
184-
# mapping from file extension to loader function, new formats by default they need to be added here
185-
forecast_loader_mapping = {
186-
'dat': GriddedForecast.from_csep1_ascii,
187-
'xml': None,
188-
'h5': None,
189-
'bin': None
190-
}
191-
# sanity checks
192-
if not os.path.exists(fname):
193-
raise FileNotFoundError(f"Could not locate file {fname}. Unable to load forecast.")
194-
# sanity checks
195-
if loader is not None and not callable(loader):
196-
raise AttributeError("Loader must be callable. Unable to load forecast.")
197-
extension = get_file_extension(fname)
198-
if extension not in forecast_loader_mapping.keys() and loader is None:
199-
raise AttributeError("File extension should be in ('dat','xml','h5','bin') if loader not provided.")
200-
# assign default loader
201-
if loader is None:
202-
loader = forecast_loader_mapping[extension]
203-
forecast = loader(fname, **kwargs)
204-
# final sanity check
205-
if not isinstance(forecast, GriddedForecast):
206-
raise ValueError("Forecast not instance of GriddedForecast")
207-
return forecast
208-
209-
def load_catalog_forecast(fname, catalog_loader=None, format='native', type='ascii', **kwargs):
210-
""" General function to handle loading catalog forecasts.
211-
212-
Currently, just a simple wrapper, but can contain more complex logic in the future.
213-
214-
Args:
215-
fname (str): pathname to the forecast file or directory containing the forecast files
216-
catalog_loader (func): callable that can load catalogs, see load_stochastic_event_sets above.
217-
format (str): either 'native' or 'csep'. if 'csep', will attempt to be returned into csep observed_catalog format. used to convert between
218-
observed_catalog type.
219-
type (str): either 'ucerf3' or 'csep', determines the observed_catalog format of the forecast. if loader is provided, then
220-
this parameter is ignored.
221-
**kwargs: other keyword arguments passed to the :class:`csep.core.forecasts.CatalogForecast`.
222-
223-
Returns:
224-
:class:`csep.core.forecasts.CatalogForecast`
225-
"""
226-
# sanity checks
227-
if not os.path.exists(fname):
228-
raise FileNotFoundError(f"Could not locate file {fname}. Unable to load forecast.")
229-
# sanity checks
230-
if catalog_loader is not None and not callable(catalog_loader):
231-
raise AttributeError("Loader must be callable. Unable to load forecast.")
232-
# factory methods for loading different types of catalogs
233-
catalog_loader_mapping = {
234-
'ascii': CSEPCatalog.load_ascii_catalogs,
235-
'ucerf3': UCERF3Catalog.load_catalogs
236-
}
237-
if catalog_loader is None:
238-
catalog_loader = catalog_loader_mapping[type]
239-
# try and parse information from filename and send to forecast constructor
240-
if format == 'native' and type=='ascii':
241-
# this works for unix how windows?
242-
basename = str(os.path.basename(fname.rstrip('/')).split('.')[0])
243-
split_fname = basename.split('_')
244-
name = split_fname[0]
245-
start_time = strptime_to_utc_datetime(split_fname[1], format="%Y-%m-%dT%H-%M-%S-%f")
246-
# update kwargs
247-
_ = kwargs.setdefault('name', name)
248-
_ = kwargs.setdefault('start_time', start_time)
249-
# create observed_catalog forecast
250-
return CatalogForecast(filename=fname, loader=catalog_loader, catalog_format=format, catalog_type=type, **kwargs)
251-
252-
1+
from csep.core import forecasts
2+
from csep.core import catalogs
3+
from csep.core import poisson_evaluations
4+
from csep.core import catalog_evaluations
5+
from csep.core.repositories import (
6+
load_json,
7+
write_json
8+
)
9+
from csep.io import (
10+
load_stochastic_event_sets,
11+
load_catalog,
12+
query_comcat,
13+
load_evaluation_result,
14+
load_gridded_forecast,
15+
load_catalog_forecast
16+
)
17+
18+
# this defines what is imported on a `from csep import *`
19+
__all__ = [
20+
'load_json',
21+
'write_json',
22+
'catalogs',
23+
'poisson_evaluations',
24+
'catalog_evaluations',
25+
'forecasts',
26+
'load_stochastic_event_sets',
27+
'load_catalog',
28+
'query_comcat',
29+
'load_evaluation_result',
30+
'load_gridded_forecast',
31+
'load_catalog_forecast'
32+
]

0 commit comments

Comments
 (0)