Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rename two API endpoints and add field descriptions to the exported json files #10433

Open
wants to merge 16 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 20 additions & 15 deletions doc/api-reference/rest-api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -114,11 +114,11 @@ Response:

A list of error lines extracted from the log. If the calculation was successfull, the list is empty.

**********************************
GET /v1/calc/:calc_id/aggrisk_tags
**********************************
********************************
GET /v1/calc/:calc_id/impact
********************************

Get risk results aggregated by tag, together with the corresponding exposure values.
Get impact results aggregated by tag, together with the corresponding exposure values.

NB: this URL is valid only for risk calculations with an aggregate_by parameter.
Otherwise it returns a BadRequest error with HTTP code 400.
Expand All @@ -127,29 +127,34 @@ Parameters: None

Response:

A JSON object corresponding to a pandas DataFrame. The names of the
columns are "ID_1", "loss_type", "value", "lossmea", "lossq05",
"lossq95".
A JSON object containing:

**********************************
GET /v1/calc/:calc_id/mmi_tags
**********************************
- an 'impact' key containing a pandas DataFrame; the names of the columns are "ID_1", "loss_type",
"value", "lossmea", "lossq05", "lossq95".
- a 'loss_type_description' dictionary containing a description for each loss type.

*****************************************
GET /v1/calc/:calc_id/exposure_by_mmi
*****************************************

Get exposure aggregated by MMI regions and tags.

NB: this URL is valid only for ShakeMap based calculations downloading
the MMI regions from the USGS service/
the MMI regions from the USGS service.

Otherwise it returns a BadRequest error with HTTP code 400.

Parameters: None

Response:

A JSON object corresponding to a pandas DataFrame. The names of the
columns are "ID_1", "number", "contents", "nonstructural", "structural",
"residents", "area", "occupants_day", "occupants_night", "occupants_transit",
"occupants_avg", "mmi".
A JSON object containing:

- an 'exposure_by_mmi' key corresponding to a pandas DataFrame; the names of the
columns are "ID_1", "number", "contents", "nonstructural", "structural",
"residents", "area", "occupants_day", "occupants_night", "occupants_transit",
"occupants_avg", "mmi".
- a 'column_descriptions' dictionary containing a description for each exposure type.

***********************************
GET /v1/calc/:calc_id/extract/:spec
Expand Down
20 changes: 19 additions & 1 deletion openquake/calculators/export/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,14 +82,32 @@
}


FIELD_DESCRIPTION = {
AGGRISK_FIELD_DESCRIPTION = {
'contents': 'Contents loss (USD)',
'nonstructural': 'Nonstructural loss (USD)',
'structural': 'Structural loss (USD)',
'occupants': 'Fatalities',
'area': 'Floor area lost (m2)',
'number': 'Buildings beyond repair',
'residents': 'Rendered homeless',
'injured': 'Number of injured people',
'affectedpop': 'Number of people living in buildings with moderate or higher damage'

}

EXPOSURE_FIELD_DESCRIPTION = {
'number': 'Buildings',
'contents': 'Contents value (USD)',
'nonstructural': 'Nonstructural value (USD)',
'structural': 'Structural value (USD)',
'residents': 'Residents',
'area': 'Floor area (m2)',
'occupants_day': 'Occupants day',
'occupants_night': 'Occupants night',
'occupants_transit': 'Occupants transit hours',
'occupants_avg': 'Average number of occupants',
'mmi': ('Macroseismic intensity (MMI) to which the given group'
' of assets is subjected')
}


Expand Down
4 changes: 4 additions & 0 deletions openquake/calculators/extract.py
Original file line number Diff line number Diff line change
Expand Up @@ -898,6 +898,10 @@ def extract_aggrisk_tags(dstore, what):
for qfield, qvalue in zip(qfields, qvalues):
acc[qfield].append(qvalue)
df = pandas.DataFrame(acc)
total_df = df.groupby('loss_type', as_index=False).sum()
total_df[aggby] = 'total'
df = pandas.concat([df, total_df], ignore_index=True)

return df


Expand Down
2 changes: 1 addition & 1 deletion openquake/engine/tests/impact_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ def test_impact(n):
raise unittest.SkipTest(f'Missing {expo}')
calc = check(cd / f'impact{n}/job.ini', what='aggrisk_tags')
if n == 1:
check_export_job(calc.datastore)
check_export_job(calc.datastore)


def test_impact5():
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@ B,RM,nonstructural,2.50000E+03,9.44013E+01
B,RM,structural,5.00000E+03,3.55602E+02
B,W,nonstructural,5.00000E+02,2.60544E+01
B,W,structural,1.00000E+03,2.52457E+02
total,total,nonstructural,5.50000E+03,1.69074E+02
total,total,structural,1.10000E+04,8.13301E+02
4 changes: 2 additions & 2 deletions openquake/server/templates/engine/get_outputs_impact.html
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,11 @@ <h2>Outputs from calculation {{ calc_id }}: {{ description }}{% if local_timesta
{% if user_level == 2 %}
<div class="my-pngs">
<a href="{{ oq_engine_server_url }}/v1/calc/{{ calc_id }}/extract_html_table/aggrisk_tags" class="btn btn-sm">
Show aggrisk_tags</a>
Show impact table</a>
</div>
<div class="my-pngs">
<a href="{{ oq_engine_server_url }}/v1/calc/{{ calc_id }}/extract_html_table/mmi_tags" class="btn btn-sm">
Show mmi_tags</a>
Show exposure by MMI table</a>
</div>
{% endif %}
</div>
Expand Down
4 changes: 2 additions & 2 deletions openquake/server/v1/calc_urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@
re_path(r'^(\d+)/log/size$', views.calc_log_size),
re_path(r'^(\d+)/log/(\d*):(\d*)$', views.calc_log, name="log"),
re_path(r'^result/(\d+)$', views.calc_result),
re_path(r'^(\d+)/aggrisk_tags$', views.aggrisk_tags),
re_path(r'^(\d+)/mmi_tags$', views.mmi_tags),
re_path(r'^(\d+)/impact$', views.impact_results),
re_path(r'^(\d+)/exposure_by_mmi$', views.exposure_by_mmi),
re_path(r'^(\d+)/result/list$', views.calc_results),
re_path(r'^(\d+)/share$', views.calc_share),
re_path(r'^(\d+)/unshare$', views.calc_unshare),
Expand Down
29 changes: 19 additions & 10 deletions openquake/server/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@
from openquake.commonlib import readinput, oqvalidation, logs, datastore, dbapi
from openquake.calculators import base, views
from openquake.calculators.getters import NotFound
from openquake.calculators.export import export, FIELD_DESCRIPTION
from openquake.calculators.export import (
export, AGGRISK_FIELD_DESCRIPTION, EXPOSURE_FIELD_DESCRIPTION)
from openquake.calculators.extract import extract as _extract
from openquake.calculators.postproc.plots import plot_shakemap, plot_rupture
from openquake.engine import __version__ as oqversion
Expand Down Expand Up @@ -1172,9 +1173,9 @@ def calc_result(request, result_id):

@cross_domain_ajax
@require_http_methods(['GET', 'HEAD'])
def aggrisk_tags(request, calc_id):
def impact_results(request, calc_id):
"""
Return aggrisk_tags, by ``calc_id``, as JSON.
Return impact results (aggrisk_tags), by ``calc_id``, as JSON.

:param request:
`django.http.HttpRequest` object.
Expand All @@ -1197,14 +1198,17 @@ def aggrisk_tags(request, calc_id):
content='%s: %s in %s\n%s' %
(exc.__class__.__name__, exc, 'aggrisk_tags', tb),
content_type='text/plain', status=400)
return HttpResponse(content=df.to_json(), content_type=JSON, status=200)
response_data = {'loss_type_descriptions': AGGRISK_FIELD_DESCRIPTION,
'impact': df.to_dict()}
return JsonResponse(response_data)


@cross_domain_ajax
@require_http_methods(['GET', 'HEAD'])
def mmi_tags(request, calc_id):
def exposure_by_mmi(request, calc_id):
"""
Return mmi_tags, by ``calc_id``, as JSON.
Return exposure aggregated by MMI regions and tags (mmi_tags),
by ``calc_id``, as JSON.

:param request:
`django.http.HttpRequest` object.
Expand All @@ -1227,7 +1231,9 @@ def mmi_tags(request, calc_id):
content='%s: %s in %s\n%s' %
(exc.__class__.__name__, exc, 'mmi_tags', tb),
content_type='text/plain', status=400)
return HttpResponse(content=df.to_json(), content_type=JSON, status=200)
response_data = {'column_descriptions': EXPOSURE_FIELD_DESCRIPTION,
'exposure_by_mmi': df.to_dict()}
return JsonResponse(response_data)


@cross_domain_ajax
Expand Down Expand Up @@ -1508,8 +1514,8 @@ def web_engine_get_outputs_impact(request, calc_id):
weights_precision = None
else:
losses_header = [
f'{field}<br><i>{FIELD_DESCRIPTION[field]}</i>'
if field in FIELD_DESCRIPTION
f'{field}<br><i>{AGGRISK_FIELD_DESCRIPTION[field]}</i>'
if field in AGGRISK_FIELD_DESCRIPTION
else field.capitalize()
for field in losses.dtype.names]
weights_precision = determine_precision(losses['weight'])
Expand Down Expand Up @@ -1592,8 +1598,11 @@ def extract_html_table(request, calc_id, name):
(exc.__class__.__name__, exc, name, tb),
content_type='text/plain', status=400)
table_html = table.to_html(classes="table table-striped", index=False)
display_names = {'aggrisk_tags': 'Impact',
'mmi_tags': 'Exposure by MMI'}
table_name = display_names[name] if name in display_names else name
return render(request, 'engine/show_table.html',
{'table_name': name, 'table_html': table_html})
{'table_name': table_name, 'table_html': table_html})


@csrf_exempt
Expand Down
Loading