-
Notifications
You must be signed in to change notification settings - Fork 41
/
sr_util.py
137 lines (114 loc) · 5.26 KB
/
sr_util.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# Ensure compatibility between python 2 and python 3
from __future__ import (absolute_import, division,
print_function, unicode_literals)
from builtins import *
import requests
import platform
import os
import stat
import tempfile
import json
import time
import subprocess
import geopandas as gpd
import shutil
def _download(url, file_name):
# open in binary mode
with open(file_name, "wb") as file:
# get request
response = requests.get(url)
if not response.ok:
raise Exception("Downloading file from {} failed".format(url))
# write to file
file.write(response.content)
_inmap_exe = None
_tmpdir = tempfile.TemporaryDirectory()
def run_sr(emis, model, output_variables, emis_units="tons/year"):
"""
Run the provided emissions through the specified SR matrix, calculating the
specified output properties.
Args:
emis: The emissions to be calculated, Needs to be a geopandas dataframe.
model: The SR matrix to use. Allowed values:
isrm: The InMAP SR matrix
apsca_q0: The APSCA SR matrix, annual average
apsca_q1: The APSCA SR matrix, Jan-Mar season
apsca_q2: The APSCA SR matrix, Apr-Jun season
apsca_q3: The APSCA SR matrix, Jul-Sep season
apsca_q4: The APSCA SR matrix, Oct-Dec season
output_variables: Output variables to be calculated. See
https://inmap.run/docs/results/ for more information.
emis_units: The units that the emissions are in. Allowed values:
'tons/year', 'kg/year', 'ug/s', and 'μg/s'.
"""
global _tmpdir
global _inmap_exe
model_paths = {
"isrm": "/data/isrmv121/isrm_v1.2.1.ncf",
"apsca_q0": "/data/apsca/apsca_sr_Q0_v1.2.1.ncf",
"apsca_q1": "/data/apsca/apsca_sr_Q1_v1.2.1.ncf",
"apsca_q2": "/data/apsca/apsca_sr_Q2_v1.2.1.ncf",
"apsca_q3": "/data/apsca/apsca_sr_Q3_v1.2.1.ncf",
"apsca_q4": "/data/apsca/apsca_sr_Q4_v1.2.1.ncf",
}
if model not in model_paths.keys():
models = ', '.join("{!s}".format(k) for (k) in model_paths.keys())
msg = 'model must be one of \{{!s}\}, but is `{!s}`'.format(models, model)
raise ValueError(msg)
model_path = model_paths[model]
start = time.time()
job_name = "run_aqm_%s"%start
emis_file = os.path.join(_tmpdir.name, "%s.shp"%(job_name))
emis.to_file(emis_file)
arch = platform.machine()
if arch == "x86_64": arch = "amd64"
version = "1.9.0"
if _inmap_exe == None:
ost = platform.system()
print("Downloading InMAP executable for %s "%ost, end='\r')
if ost == "Windows":
_inmap_exe = os.path.join(_tmpdir.name, "inmap_%s.exe"%version)
_download("https://github.com/spatialmodel/inmap/releases/download/v%s/inmap-v%s-windows-%s.exe"%(version, version, arch), _inmap_exe)
elif ost == "Darwin":
_inmap_exe = os.path.join(_tmpdir.name, "inmap_%s"%version)
_download("https://github.com/spatialmodel/inmap/releases/download/v%s/inmap-v%s-darwin-%s"%(version, version, arch), _inmap_exe)
elif ost == "Linux":
_inmap_exe = os.path.join(_tmpdir.name, "inmap_%s"%version)
_download("https://github.com/spatialmodel/inmap/releases/download/v%s/inmap-v%s-linux-%s"%(version, version, arch), _inmap_exe)
else:
raise(OSError("invalid operating system %s"%(ost)))
os.chmod(_inmap_exe, stat.S_IXUSR|stat.S_IRUSR|stat.S_IWUSR)
subprocess.check_output([_inmap_exe, "cloud", "start",
"--cmds=srpredict",
"--version=v%s"%version,
"--job_name=%s"%job_name,
"--memory_gb=3",
"--EmissionUnits=%s"%emis_units,
"--EmissionsShapefiles=%s"%emis_file,
"--OutputVariables=%s"%json.dumps(output_variables),
"--SR.OutputFile=%s"%model_path])
# You can also run the simulation locally by replacing the above command with the below command:
# subprocess.check_output([_inmap_exe, "srpredict",
# "--EmissionUnits=%s"%emis_units,
# "--EmissionsShapefiles=%s"%emis_file,
# "--OutputVariables=%s"%json.dumps(output_variables),
# "--SR.OutputFile=/path/to/isrm/file/you/downloaded.ncf"])
# You can download the ISRM source receptor matrix itself from here: https://zenodo.org/record/3590127#.Yl2SSvPMKWA
while True:
try:
status = subprocess.check_output([_inmap_exe, "cloud", "status", "--job_name=%s"%job_name]).decode("utf-8").strip()
print("simulation %s (%.0f seconds) "%(status, time.time()-start), end='\r')
if status == "Complete":
break
elif status != "Running":
raise ValueError(status)
except subprocess.CalledProcessError as err:
# ignore transient errors when checking status
print(err.output)
time.sleep(5)
subprocess.check_call([_inmap_exe, "cloud", "output", "--job_name=%s"%job_name])
output = gpd.read_file("%s/OutputFile.shp"%job_name)
shutil.rmtree(job_name)
subprocess.check_call([_inmap_exe, "cloud", "delete", "--job_name=%s"%job_name])
print("Finished (%.0f seconds) "%(time.time()-start))
return output