# ------------------- The OpenQuake Model Building Toolkit --------------------
# Copyright (C) 2022 GEM Foundation
# _______ _______ __ __ _______ _______ ___ _
# | || | | |_| || _ || || | | |
# | _ || _ | ____ | || |_| ||_ _|| |_| |
# | | | || | | ||____|| || | | | | _|
# | |_| || |_| | | || _ | | | | |_
# | || | | ||_|| || |_| | | | | _ |
# |_______||____||_| |_| |_||_______| |___| |___| |_|
#
# This program is free software: you can redistribute it and/or modify it under
# the terms of the GNU Affero General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
# details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# -----------------------------------------------------------------------------
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# coding: utf-8
import os
import json
import unittest
import configparser
import tempfile
import pathlib
from openquake.utils import are_equal_ignoring_line_endings
import openquake.mbt.tools.fault_modeler.fault_source_modeler as fsm
# -----------------------------------------------------------------------------
BASE_DATA_PATH = os.path.dirname(__file__)
# -----------------------------------------------------------------------------
[docs]
class TestDatabaseIO(unittest.TestCase):
geojson_file = os.path.join(
BASE_DATA_PATH, 'data', 'ne_asia_faults_rates.geojson')
param_map = {'source_id': 'ogc_fid',
'name': 'ns_name',
'average_dip': 'ns_average_dip',
'average_rake': 'ns_average_rake',
'net_slip_rate': 'ns_net_slip_rate',
'vert_slip_rate': 'ns_vert_slip_rate',
'strike_slip_rate': 'ns_strike_slip_rate',
'shortening_rate': 'ns_shortening_rate',
'dip_dir': 'ns_dip_dir',
'dip_slip_rate': 'ns_dip_slip_rate'}
defaults = {'m_min': 6.0}
[docs]
def test_fault_database(self):
# Target and reference files
_, test_file = tempfile.mkstemp()
base_file = os.path.join(BASE_DATA_PATH, 'data',
'fault_database.base.geojson')
# Import the database
fault_db = fsm.FaultDatabase()
fault_db.import_from_geojson(self.geojson_file,
param_map=self.param_map,
select_list=[1, 2],
update_keys=True)
# Adding a key/value to all faults
fault_db.add_property('lower_seismogenic_depth', value=25)
# Adding key/value to given faults
# raise unittest.SkipTest('Marco Pagani: this test is broken!')
fault_db.add_property('m_max', value=7., id=1)
fault_db.add_property('m_max', value=7.5, id=2)
fault_db.remove_property('name')
# Export the augmented database
fault_db.export_to_geojson(test_file)
with open(test_file, 'r') as f:
test_out = json.load(f)
with open(base_file, 'r') as f:
base_out = json.load(f)
for bo, to in zip(base_out['features'], test_out['features']):
self.assertTrue(bo == to)
# @unittest.skip('find better way to compare outputs!')
[docs]
def test_build_model_from_db(self):
# Target and reference files
_, test_file = tempfile.mkstemp()
base_file = os.path.join(BASE_DATA_PATH, 'data',
'fault_model_01.base.xml')
# Import the database
fault_db = fsm.FaultDatabase()
fault_db.import_from_geojson(self.geojson_file,
param_map=self.param_map,
select_list=[1, 2])
# Create and export the model
# this test didn't work because the length_scaling method
# is used to get the lower_seismo_depth, and that doesn't permit
# using the default value (the one being tested against in the base
# output file -> 35 km). length_scaling was being set as the default
# in build_model_from_db (fault_source_modeler line 91). I changed it
# to 'seismo_depth' here but we should discuss the optimal default.
# the mfds did not match because the reference file was created before
# the implementation of m_cli, so the mfds were being computed with
# different ranges of magnitudes, so I added the default m_min (I
# double checked this in a separate notebook that I can share). Lastly,
# the lons and lats and mfds didn't match because of decimal places,
# so I changed the test to read in teh sources and compare attributes
fsm.build_model_from_db(fault_db, xml_output=test_file,
param_map=self.param_map,
project_name='fault_model_01.test',
width_method='seismo_depth',
defaults=self.defaults)
# Compare files
self.assertTrue(are_equal_ignoring_line_endings(base_file, test_file))
[docs]
@unittest.skip('RS to check the output file which has traces reverted')
def test_build_source_model_single_args(self):
# Target and reference files
_, test_file = tempfile.mkstemp()
base_file = os.path.join(BASE_DATA_PATH, 'data',
'fault_model_02.base.xml')
# Create and export the model
# same applies here for m_min and needing to fix the lon/lat coords
# and mfd precision
fsm.build_fault_model(geojson_file=self.geojson_file,
xml_output=test_file,
black_list=[1, 2, 3],
param_map=self.param_map,
m_max=8.2, m_min=6.0,
project_name='fault_model_02.test',
lower_seismogenic_depth=30.)
# Compare files
self.assertTrue(are_equal_ignoring_line_endings(base_file, test_file))
[docs]
@unittest.skip('RS to check the output file which has traces reverted')
def test_build_source_model_dictionary(self):
# Target and reference files
_, test_file = tempfile.mkstemp()
base_file = os.path.join(BASE_DATA_PATH, 'data',
'fault_model_03.base.xml')
# Create and export the model
# here as well with m_min and fault trace
fsm.build_fault_model(geojson_file=self.geojson_file,
xml_output=test_file,
param_map=self.param_map,
project_name='fault_model_03.test',
defaults={'upper_seismogenic_depth': 10.,
'lower_seismogenic_depth': 30.,
'm_min': 6.0})
# Compare files
self.assertTrue(are_equal_ignoring_line_endings(base_file, test_file))
[docs]
def test_build_source_model_config_file(self):
# Configuration, target and reference files
conf_file = os.path.join(BASE_DATA_PATH, 'config.ini')
config = configparser.ConfigParser()
config.read(conf_file)
test_dir = pathlib.Path(tempfile.mkdtemp())
test_file = test_dir / 'fault_model_04.test.xml'
config['config']['xml_output'] = str(test_file)
new_config_fname = test_dir / 'config.ini'
data_path = pathlib.Path(BASE_DATA_PATH)
geojson_original_path = data_path / config['config']['geojson_file']
config['config']['geojson_file'] = str(geojson_original_path)
with open(new_config_fname, 'w') as configfile:
config.write(configfile)
base_file = os.path.join(BASE_DATA_PATH, 'data',
'fault_model_04.base.xml')
# Create and export the model
fsm.build_fault_model(cfg_file=new_config_fname)
# Compare files
self.assertTrue(are_equal_ignoring_line_endings(base_file, test_file))