Skip to content

Commit 5b37b2b

Browse files
committed
refactor flatfile columns
1 parent 843a4ef commit 5b37b2b

File tree

15 files changed

+193
-242
lines changed

15 files changed

+193
-242
lines changed

egsim/api/forms/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
from egsim.api import models
1515
from egsim.smtk import (validate_inputs, harmonize_input_gsims, harmonize_input_imts)
16-
from egsim.smtk.flatfile import FlatfileMetadata
16+
from egsim.smtk.flatfile import column_help
1717
from egsim.smtk.registry import gsim_info
1818
from egsim.smtk.validation import IncompatibleModelImtError, ImtError, ModelError
1919

@@ -452,7 +452,7 @@ def output(self) -> dict:
452452
for gmm_name, gmm in self.cleaned_data['gsim'].items():
453453
doc, imts, gm_props, sa_limits = gsim_info(gmm)
454454
# ground motion properties:
455-
gm_props = {p: FlatfileMetadata.get_help(p) for p in gm_props}
455+
gm_props = {p: column_help(p) for p in gm_props}
456456
# remove unnecessary flatfile-related info (everything after 1st paragraph)
457457
# and also jsonify the string (replace " with ''):
458458
gm_props = {

egsim/api/forms/flatfile.py

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@
1010

1111
from egsim.smtk import (ground_motion_properties_required_by,
1212
intensity_measures_defined_for, get_sa_limits)
13-
from egsim.smtk.flatfile import (read_flatfile, get_dtype_of, FlatfileMetadata,
13+
from egsim.smtk.flatfile import (read_flatfile, get_dtype_of, column_exists, column_type,
14+
column_categorical_dtype, column_aliases,
15+
column_dtype, column_help,
1416
query as flatfile_query, EVENT_ID_COLUMN_NAME,
1517
FlatfileError, FlatfileQueryError,
16-
IncompatibleColumnError)
18+
IncompatibleColumnError, column_names)
1719
from egsim.api import models
1820
from egsim.api.forms import EgsimBaseForm, APIForm, GsimForm, split_pars
1921

@@ -169,7 +171,7 @@ class FlatfileMetadataInfoForm(GsimForm, APIForm):
169171

170172
def clean(self):
171173
cleaned_data = super().clean()
172-
unique_imts = FlatfileMetadata.get_intensity_measures()
174+
unique_imts = column_names(type='intensity')
173175

174176
for m_name, model in cleaned_data['gsim'].items():
175177
imts = intensity_measures_defined_for(model)
@@ -210,7 +212,7 @@ def output(self) -> dict:
210212

211213
required_columns = (ground_motion_properties_required_by(*gsims) |
212214
{EVENT_ID_COLUMN_NAME}) # <- event id always required
213-
ff_columns = {FlatfileMetadata.get_aliases(c)[0] for c in required_columns}
215+
ff_columns = {column_aliases(c)[0] for c in required_columns}
214216

215217
imts = cleaned_data['imt']
216218

@@ -244,16 +246,16 @@ def get_hr_flatfile_column_meta(name: str, values: Optional[pd.Series] = None) -
244246
c_dtype = None
245247
c_categories = []
246248

247-
if FlatfileMetadata.has(name):
248-
c_dtype = FlatfileMetadata.get_dtype(name)
249-
cat_dtype = FlatfileMetadata.get_categorical_dtype(name)
249+
if column_exists(name):
250+
c_dtype = column_dtype(name)
251+
cat_dtype = column_categorical_dtype(name)
250252
if cat_dtype is not None:
251253
# c_categories is a pandas CategoricalStype. So:
252254
c_dtype = get_dtype_of(cat_dtype.categories)
253255
c_categories = cat_dtype.categories.tolist()
254-
c_type = getattr(FlatfileMetadata.get_type(name), 'value', "")
255-
c_help = FlatfileMetadata.get_help(name) or ""
256-
c_aliases = FlatfileMetadata.get_aliases(name)
256+
c_type = getattr(column_type(name), 'value', "")
257+
c_help = column_help(name) or ""
258+
c_aliases = column_aliases(name)
257259
if len(c_aliases) > 1:
258260
c_aliases = [n for n in c_aliases if n != name]
259261
c_aliases = (f"Alternative valid name{'s' if len(c_aliases) != 1 else ''}: "

egsim/api/forms/scenarios.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from django.forms.fields import BooleanField, FloatField, ChoiceField, Field
1111

1212
from egsim.api.forms import APIForm, GsimImtForm
13-
from egsim.smtk import get_scenarios_predictions
13+
from egsim.smtk import get_ground_motion_from_scenarios
1414
from egsim.smtk.scenarios import RuptureProperties, SiteProperties, Clabel
1515

1616

@@ -216,13 +216,13 @@ def output(self) -> pd.DataFrame:
216216
self.site_fieldnames
217217
if p in cleaned_data})
218218
header_sep = None if cleaned_data.get('multi_header') else Clabel.sep
219-
return get_scenarios_predictions(cleaned_data['gsim'],
220-
cleaned_data['imt'],
221-
cleaned_data['magnitude'],
222-
cleaned_data['distance'],
223-
rupture_properties=rup,
224-
site_properties=site,
225-
header_sep=header_sep)
219+
return get_ground_motion_from_scenarios(cleaned_data['gsim'],
220+
cleaned_data['imt'],
221+
cleaned_data['magnitude'],
222+
cleaned_data['distance'],
223+
rupture_properties=rup,
224+
site_properties=site,
225+
header_sep=header_sep)
226226

227227

228228
PredictionsForm.rupture_fieldnames = tuple(sorted(

egsim/api/management/commands/egsim-init.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from django.core.management import BaseCommand, CommandError
99
from egsim.smtk import (registered_gsims, gsim, intensity_measures_defined_for,
1010
ground_motion_properties_required_by, get_sa_limits)
11-
from egsim.smtk.flatfile import FlatfileMetadata
11+
from egsim.smtk.flatfile import column_exists
1212
from ... import models
1313
from django.conf import settings
1414

@@ -108,7 +108,7 @@ def write_model(self, name, cls):
108108
self.stdout.write(f" {prefix} {name}. No ground motion property "
109109
f"defined")
110110
return False
111-
invalid = sorted(c for c in gmp if not FlatfileMetadata.has(c))
111+
invalid = sorted(c for c in gmp if not column_exists(c))
112112
if invalid:
113113
self.stdout.write(f" {prefix} {name}. Unregistered "
114114
f"ground motion properties: {invalid}")

egsim/api/views.py

Lines changed: 14 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -40,24 +40,8 @@ class MimeType: # noqa
4040

4141
class EgsimView(View):
4242
"""Base View class for serving eGSIM HttpResponse. All views should inherits from
43-
this class, implementing the abstract-like method `response`
44-
45-
Example
46-
=======
47-
48-
1. Implementation (note: any exception will be caught and returned as 500
49-
HttpResponse, see `handle_exception`)
50-
```
51-
class MyEgsimView(EgsimView):
52-
53-
def response(self, request: HttpRequest, data: dict, files: Optional[dict] = None) -> HttpResponseBase:
54-
content = ... # bytes or string sequence (serialized from a Python object)
55-
return HttpResponse(content, content_type=MimeType.csv, ...)
56-
# or, if content is a JSON dict:
57-
return JsonResponse(content)
58-
```
59-
60-
2. URL mapping: given an endpoint (URL string or regex pattern), in `urls.py`:
43+
this class, implementing the abstract-like method `response` (**see docstring therein
44+
for details**). After that, you can map this view to a given URL as usual (in `urls.py`):
6145
```
6246
urlpatterns = [
6347
...
@@ -107,7 +91,10 @@ def response(self,
10791
need to be returned in try except clauses, as usual:
10892
```
10993
try:
110-
... return response, e.g. JsonResponse, HttpResponse
94+
content = ... # bytes or string sequence (serialized from a Python object)
95+
return HttpResponse(content, content_type=MimeType.csv, ...)
96+
# or, if content is a JSON dict:
97+
return JsonResponse(content)
11198
except ValueError as exc:
11299
return self.error_response(exc, status=400)
113100
```
@@ -184,17 +171,17 @@ def response(self,
184171

185172
class APIFormView(EgsimView):
186173
""":class:`EgsimView` subclass serving :class:`ApiForm.output()` objects and
187-
expecting a 'format' request parameter (default if missing: 'json', see `MimeType`
188-
class attributes) dictating the response type. Form validation errors will be
189-
returned as 400 HttpResponse with the form error string as reponse message.
174+
expecting a 'format' request parameter (any attribute of :class:`MimeType`)
175+
dictating the response type. Form validation errors will be
176+
returned as 400 HttpResponse, any uncaught exception as 500 HttpResponse.
190177
191178
Usage
192179
=====
193180
194181
Given an `APiForm` subclass named `MyApiForm`:
195182
196183
1. If this view is supposed to return JSON data only, then `MyApiForm.output()`
197-
must also return a JSON serializable dict. After that, you only need to
184+
must also return a JSON serializable dict. If this is the casse, you only need to
198185
implement a new endpoint in `urls.py`:
199186
200187
```
@@ -205,10 +192,11 @@ class attributes) dictating the response type. Form validation errors will be
205192
]
206193
```
207194
208-
2. If this view is suppoosed to return several data formats, then
195+
2. If this view is supposed to return several data formats, then
209196
`MyApiForm.output()` can be any Python object, but you must serialize it here
210-
depending on the requested format. For instance, if you want to support users
211-
request format to be 'hdf', this class expets the relative method `response_hdf`:
197+
depending on the requested format (including overriding the existing reponse_json,
198+
if needed). For instance, if you want to serve HDF data, you must implement
199+
the method `response_hdf`:
212200
213201
```
214202
class MyApiFormView(APIFormView):

egsim/smtk/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
"""Root module for the strong motion modeller toolkit (smtk) package of eGSIM"""
2-
from .scenarios import get_scenarios_predictions
2+
from .scenarios import get_ground_motion_from_scenarios
33
from .residuals import get_residuals
44
from .ranking import get_measures_of_fit
55
from .flatfile import read_flatfile, FlatfileError

0 commit comments

Comments
 (0)