-
Notifications
You must be signed in to change notification settings - Fork 0
/
forecast_ssm.py
89 lines (77 loc) · 3.37 KB
/
forecast_ssm.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
import sys
import time
import datetime
import numpy as np
import pandas as pd
from models.rates import bo_2017_forecast
from models.stresses import bo_2017_stress
from tools.catalogue_tools import filter_attr_str2list
from chaintools.chaintools import tools_configuration as cfg
from chaintools.chaintools import tools_xarray as xf
from chaintools.chaintools import tools_grid as go
def main(config_path):
"""
Create a forecast/hindcast based on the Bayesian calibration of the source model parameters. Store results to file
Parameters
----------
config_path : str
The filepath to the configuration file (example included in the repository)
legacy_format : bool
Temporary flag for saving results in legacy format
"""
# Load the configuration file
module_name = "forecast_ssm"
config = cfg.configure(config_path, module_name)
# To make these files, run ssm_input_parser.py
faults = xf.open("fault_data", config)
pressure = xf.open("pressure_data", config)
compaction_coef = xf.open("compressibility_data", config)
# Load calibration result
calib_group = config["data_sources"]["calibration_data"]["group"]
config["data_sources"]["calibration_data"]["group"] = f"{calib_group}/activity_rate_model"
ar_posterior = xf.open("calibration_data", config)
config["data_sources"]["calibration_data"]["group"] = f"{calib_group}/magnitude_model"
mag_posterior = xf.open("calibration_data", config)
config["data_sources"]["calibration_data"]["group"] = f"{calib_group}/dsm_pmf"
stress_posterior = xf.open("calibration_data", config)
stress = bo_2017_stress(
pressure,
compaction_coef,
faults,
ar_posterior.hs_exp,
ar_posterior.sigma,
ar_posterior.rmax,
)
# Describe for which period we want a rate forecast (no magnitudes) and for which period we want a full forecast
calibration_daterange = pd.to_datetime(
filter_attr_str2list(ar_posterior.attrs["calibration_date_filter"]), format=r"%Y%m%d"
)
rate_bool = stress.time >= calibration_daterange[0]
full_bool = np.logical_and(
stress.time >= pd.to_datetime(min(config["forecast_epochs"]), format=r"%Y"),
stress.time <= pd.to_datetime(max(config["forecast_epochs"]) + 1, format=r"%Y"),
)
mmax = go.make_xarray_based("mmax", [4.0, 4.5, 5.0, 5.5, 6.0, 6.5])
mags = go.make_xarray_based("magnitude", np.linspace(1.45, 6.55, 103))
event_rate_forecast, full_forecast, nr_event_pmf = bo_2017_forecast(
ar_posterior,
mag_posterior,
stress_posterior,
stress,
mags,
mmax,
rate_bool,
full_bool,
)
# Store results
forecast_group = config["data_sinks"]["forecast_data"]["group"]
xf.store(event_rate_forecast, "forecast_data", config, group="event_rate_forecast", mode="a")
xf.store(full_forecast, "forecast_data", config, group="forecast", mode="a")
xf.store(nr_event_pmf, "forecast_data", config, group="nr_event_pmf", mode="a")
if __name__ == "__main__":
time0 = time.time()
# First command-line argument is passed as the path to the configuration file or else default is used
conf_path = sys.argv[1] if sys.argv[1:] else "example_configs/forecast_config.json"
main(conf_path)
time1 = time.time()
print(f"Done in {str(datetime.timedelta(seconds=int(time1-time0)))} (hh:mm:ss)")