Coverage for /usr/local/lib/python3.11/dist-packages/pyrocko/dataset/active_faults.py: 82%
80 statements
« prev ^ index » next coverage.py v6.5.0, created at 2023-10-04 09:52 +0000
« prev ^ index » next coverage.py v6.5.0, created at 2023-10-04 09:52 +0000
1# http://pyrocko.org - GPLv3
2#
3# The Pyrocko Developers, 21st Century
4# ---|P------/S----------~Lg----------
6'''
7GEM Global Active Faults Database
8(`GEM GAF-DB <https://github.com/GEMScienceTools/gem-global-active-faults>`_).
10If the database is not already available, it will be downloaded
11automatically on first use.
13.. note::
15 If you use this dataset, please cite:
17 Styron, Richard, and Marco Pagani. “The GEM Global Active Faults Database.”
18 Earthquake Spectra, vol. 36, no. 1_suppl, Oct. 2020, pp. 160–180,
19 doi:10.1177/8755293020944182.
20'''
22import re
23import logging
24import numpy as num
25from os import path as op
26from collections import OrderedDict
27import json
29from pyrocko import config, util
32def parse_3tup(s):
33 m = re.match(r'^\(?([^,]+),([^,]*),([^,]*)\)$', s)
34 if m:
35 return [float(m.group(1)) if m.group(1) else None for i in range(3)]
36 else:
37 return [None, None, None]
40logger = logging.getLogger('ActiveFaults')
43class ActiveFault(object):
44 '''
45 Representation of a single active fault.
46 '''
47 __fields__ = OrderedDict([
49 ('lat', list),
50 ('lon', list),
51 ('average_dip', float),
52 ('average_rake', float),
53 ('lower_seis_depth', float),
54 ('upper_seis_depth', float),
55 ('slip_type', str),
56 ])
58 __slots__ = list(__fields__.keys())
60 def get_property(self, fault_obj, attr):
61 try:
62 values = float(fault_obj['properties'][attr][1:3])
63 except KeyError:
64 if attr == 'lower_seis_depth' or attr == 'upper_seis_depth':
65 values = 0
66 else:
67 values = -999
68 return values
70 def __init__(self, f):
71 nodes = f['geometry']['coordinates']
72 props = f['properties']
73 lons = [p[0] for p in nodes]
74 lats = [p[1] for p in nodes]
75 self.lon = lons
76 self.lat = lats
77 self.slip_type = props.get('slip_type', 'Unknown')
79 for attr, attr_type in self.__fields__.items():
80 if attr in props:
81 if props[attr] is None or props[attr] == '':
82 continue
84 if isinstance(props[attr], attr_type):
85 v = props[attr]
87 elif attr_type is float:
88 try:
89 v = parse_3tup(props[attr])[0]
90 except TypeError:
91 v = float(props[attr])
93 elif attr_type is int:
94 v = int(props[attr])
96 else:
97 v = None
99 setattr(self, attr, v)
101 def get_surface_line(self):
102 arr = num.empty((len(self.lat), 2))
103 for i in range(len(self.lat)):
104 arr[i, 0] = self.lat[i]
105 arr[i, 1] = self.lon[i]
107 return arr
109 def __str__(self):
110 d = {attr: getattr(self, attr) for attr in self.__fields__.keys()}
111 return '\n'.join(['%s: %s' % (attr, val) for attr, val in d.items()])
114class ActiveFaults(object):
115 '''
116 GEM Global Active Faults Database (`GEM GAF-DB
117 <https://github.com/GEMScienceTools/gem-global-active-faults>`_).
119 :ivar active_faults:
120 Fault parameters.
121 :vartype active_faults:
122 :py:class:`list` of :py:class:`ActiveFault`
123 '''
124 URL_GEM_ACTIVE_FAULTS = 'https://raw.githubusercontent.com/cossatot/gem-global-active-faults/master/geojson/gem_active_faults.geojson' # noqa
126 def __init__(self):
127 self.fname_active_faults = op.join(
128 config.config().fault_lines_dir, 'gem_active_faults.geojson')
130 if not op.exists(self.fname_active_faults):
131 self.download()
133 self.active_faults = []
134 self._load_faults(self.fname_active_faults)
136 def _load_faults(self, fname):
137 with open(fname, 'r') as f:
138 gj = json.load(f)
139 faults = gj['features']
140 for f in faults:
141 fault = ActiveFault(f)
142 self.active_faults.append(fault)
143 logger.debug('loaded %d fault', self.nactive_faults)
145 def download(self):
146 logger.info('Downloading GEM active faults database...')
147 util.download_file(self.URL_GEM_ACTIVE_FAULTS,
148 self.fname_active_faults)
150 @property
151 def nactive_faults(self):
152 return len(self.active_faults)
154 def nactive_faults_nodes(self):
155 return int(sum(len(f.lat) for f in self.active_faults))
157 def get_coords(self):
158 return num.array([f['coordinates'] for f in self.active_faults])
161if __name__ == '__main__':
162 logging.basicConfig(level=logging.DEBUG)
163 activefaults = ActiveFaults()