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: {}\n End 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