Coverage for /usr/local/lib/python3.11/dist-packages/pyrocko/model/geometry.py: 71%
85 statements
« prev ^ index » next coverage.py v6.5.0, created at 2023-10-06 06:59 +0000
« prev ^ index » next coverage.py v6.5.0, created at 2023-10-06 06:59 +0000
1# https://pyrocko.org - GPLv3
2#
3# The Pyrocko Developers, 21st Century
4# ---|P------/S----------~Lg----------
6'''
7Representation of geometrical objects built from vertices, faces, outlines,
8etc.
9'''
11import numpy as num
13from pyrocko.guts import Object, List
14from pyrocko.guts_array import Array
15from pyrocko.table import Table, LocationRecipe
17from .event import Event
19from logging import getLogger
22logger = getLogger('model.geometry')
25def reduce_array_dims(array):
26 '''
27 Support function to reduce output array ndims from table
28 '''
30 if array.shape[0] == 1 and array.ndim > 1:
31 return num.squeeze(array, axis=0)
32 else:
33 return array
36class Geometry(Object):
37 '''
38 Spatial (and temporal) distributed properties of an event
40 The Geometry object allows to store properties of an event in a spatial
41 (and temporal) distributed manner. For a set of planes ("faces"),
42 characterized by their corner points ("vertices"), properties are stored.
43 Also information on the outline of the source are stored.
44 '''
46 properties = Table.T(
47 default=Table.D(),
48 help='Properties that should be displayable on the surface of the'
49 ' geometry. If 2d time dependency in column directions.',
50 optional=True)
52 vertices = Table.T(
53 default=Table.D(),
54 help='Vertices of the mesh of the geometry. '
55 'Expected to be (lat,lon,north,east,depth) for each vertex.',
56 optional=True)
58 faces = Table.T(
59 default=Table.D(),
60 help='Face integer indexes to the respective vertices. '
61 'Indexes belonging to one polygon have to be given row-wise.',
62 optional=True)
64 outlines = List.T(
65 Table.T(),
66 default=[],
67 help='List of vertices of the mesh of the outlines of the geometry. '
68 'Expected to be (lat,lon,north,east,depth) for each vertex'
69 '(outline).',
70 optional=True)
72 event = Event.T(default=Event.D())
74 times = Array.T(
75 shape=(None,),
76 dtype='float64',
77 help='1d vector of times [s] wrt. event time for which '
78 'properties have value. Must have constant delta t',
79 optional=True)
81 def __init__(self, **kwargs):
82 Object.__init__(self, **kwargs)
83 self._ntimes = None
85 @property
86 def deltat(self):
87 '''
88 Sampling rate of properties (time difference) [s]
89 '''
91 if self.times.size > 2:
92 return self.times[1] - self.times[0]
93 else:
94 return 1.
96 @property
97 def ntimes(self):
98 if self._ntimes is None:
99 if self.times is not None:
100 self._ntimes = len(self.times)
101 else:
102 return 0
104 return self._ntimes
106 def time2idx(self, time):
107 if self.times.size > 2:
108 idx = int(round((time - self.times.min() - (
109 self.deltat / 2.)) / self.deltat))
111 if idx < 0:
112 return 0
113 elif idx > self.ntimes:
114 return self.ntimes
115 else:
116 return idx
117 else:
118 return 0
120 def set_vertices(self, vertices):
121 self.vertices.add_recipe(LocationRecipe())
122 self.vertices.add_col((
123 'c5', '',
124 ('ref_lat', 'ref_lon', 'north_shift', 'east_shift', 'depth')),
125 vertices)
127 def get_vertices(self, col='c5'):
128 if self.vertices:
129 return reduce_array_dims(self.vertices.get_col(col))
131 def set_faces(self, faces):
132 ncorners = faces.shape[1]
133 sub_headers = tuple(['f{}'.format(i) for i in range(ncorners)])
134 self.faces.add_col(('faces', '', sub_headers), faces)
136 def get_faces(self, col='faces'):
137 if self.faces:
138 return reduce_array_dims(self.faces.get_col(col))
140 def no_faces(self):
141 return self.faces.get_nrows()
143 def setup(self, vertices, faces, outlines=None):
144 self.set_vertices(vertices)
145 self.set_faces(faces)
147 if outlines is not None:
148 self.set_outlines(outlines)
150 def set_outlines(self, outlines):
151 if outlines is not None:
152 self.outlines = []
153 for outline in outlines:
154 outl = Table()
155 outl.add_recipe(LocationRecipe())
156 outl.add_col((
157 'c5', '',
158 ('ref_lat', 'ref_lon', 'north_shift', 'east_shift',
159 'depth')),
160 outline)
161 self.outlines.append(outl)
163 def get_outlines(self):
164 if self.outlines:
165 return self.outlines
166 else:
167 logger.warning('No outlines set!')
169 def add_property(self, name, values):
170 if values.ndim == 1 or values.shape[1] == 1:
171 self.properties.add_col(name, values.reshape(-1,))
172 elif (values.ndim == 2) and (self.times is not None):
173 assert values.shape[1] == self.times.shape[0]
174 self.properties.add_col(name, values)
175 else:
176 raise AttributeError(
177 'Please give either 1D array or the associated times first.')
179 def get_property(self, name):
180 return reduce_array_dims(self.properties.get_col(name))
182 def has_property(self, name):
183 return self.properties.has_col(name)