-
Notifications
You must be signed in to change notification settings - Fork 243
Expand file tree
/
Copy pathfocal_mechanisms.py
More file actions
325 lines (271 loc) · 9.57 KB
/
focal_mechanisms.py
File metadata and controls
325 lines (271 loc) · 9.57 KB
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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
"""
Plotting focal mechanisms
=========================
Focal mechanisms can be plotted as beachballs with the :meth:`pygmt.Figure.meca` method.
The focal mechanism data or parameters can be provided as various input types: ASCII
file, :class:`numpy.array`, dictionary, or :class:`pandas.Dataframe`. Different
conventions to define the focal mechanism are supported: Aki and Richards (``"aki"``),
global CMT (``"gcmt"``), moment tensor (``"mt"``), partial focal mechanism
(``"partial"``), and, principal axis (``"principal_axis"``). Please refer to the table
in the documentation of :meth:`pygmt.Figure.meca` regarding how to set up the input data
in respect to the chosen input type and convention (i.e., the expected column order,
keys, or column names). In this tutorial we focus on how to adjust the display of the
beachballs.
"""
# %%
import pandas as pd
import pygmt
from pygmt.params import Pattern
# Set up arguments for basemap
region = [-5, 5, -5, 5]
projection = "X10c/4c"
frame = ["af", "+ggray90"]
# %%
# Setting up the focal mechanism data
# -----------------------------------
#
# We store focal mechanism parameters for two single events in dictionaries using the
# moment tensor and Aki and Richards conventions:
# moment tensor convention
mt_single = {
"mrr": 4.71,
"mtt": 0.0381,
"mff": -4.74,
"mrt": 0.399,
"mrf": -0.805,
"mtf": -1.23,
"exponent": 24,
}
# Aki and Richards convention
aki_single = {"strike": 318, "dip": 89, "rake": -179, "magnitude": 7.75}
# %%
# Plotting a single beachball
# ---------------------------
#
# Required parameters are ``spec`` and ``scale`` as well as ``longitude``, ``latitude``
# (event location), and depth (if these values are not included in the argument passed
# to ``spec``). Additionally, the ``convention`` parameter is required if ``spec`` is
# an 1-D or 2-D numpy array; for the input types dictionary and ``pandas.Dataframe``,
# the focal mechanism convention is automatically determined from dictionary keys or
# :class:`pandas.DataFrame` column names. The ``scale`` parameter controls the radius
# of the beachball. By default, the value defines the size for a magnitude of 5 (i.e.,
# a scalar seismic moment of :math:`M_0 = 4.0 \times 10^{23}` dyn cm) and the beachball
# size is proportional to the magnitude. Append ``"+l"`` to force the radius to be
# proportional to the seismic moment.
fig = pygmt.Figure()
fig.basemap(region=region, projection=projection, frame=frame)
fig.meca(spec=mt_single, scale="1c", longitude=0, latitude=0, depth=0)
fig.show()
# %%
# Plotting the components of a seismic moment tensor
# --------------------------------------------------
#
# A moment tensor can be decomposed into isotropic and deviatoric parts. The deviatoric
# part can be further decomposed into multiple parts (e.g., a double couple (DC) and a
# compensated linear vector dipole (CLVD)). Use the ``component`` parameter to specify
# the component you want to plot.
fig = pygmt.Figure()
fig.basemap(region=region, projection=projection, frame=frame)
for component, longitude in zip(["full", "dc", "deviatoric"], [-2, 0, 2], strict=True):
fig.meca(
spec=mt_single,
scale="1c",
longitude=longitude,
latitude=0,
depth=0,
component=component,
)
fig.show()
# %%
# Filling the quadrants
# ---------------------
#
# Use the parameters ``compressionfill`` and ``extensionfill`` to fill the quadrants
# with different colors or :class:`patterns <pygmt.params.Pattern>`.
fig = pygmt.Figure()
fig.basemap(region=region, projection=projection, frame=frame)
fig.meca(
spec=mt_single,
scale="1c",
longitude=-2,
latitude=0,
depth=0,
compressionfill="darkorange",
extensionfill="cornsilk",
)
fig.meca(
spec=mt_single,
scale="1c",
longitude=2,
latitude=0,
depth=0,
compressionfill=Pattern(8),
extensionfill=Pattern(31),
outline=True,
)
fig.show()
# %%
# Adjusting the outlines
# ----------------------
#
# Use the parameters ``pen`` and ``outline`` for adjusting the circumference of the
# beachball or all lines (i.e, circumference and both nodal planes).
fig = pygmt.Figure()
fig.basemap(region=region, projection=projection, frame=frame)
fig.meca(
spec=aki_single,
scale="1c",
longitude=-2,
latitude=0,
depth=0,
# Use a 1-point thick, darkorange and solid line
pen="1p,darkorange",
)
fig.meca(
spec=aki_single,
scale="1c",
longitude=2,
latitude=0,
depth=0,
outline="1p,darkorange",
)
fig.show()
# %%
# Highlighting the nodal planes
# -----------------------------
#
# Use the parameter ``nodal`` to highlight specific nodal planes. ``"0"`` refers to
# both, ``"1"`` to the first, and ``"2"`` to the second nodal plane(s). Only the
# circumference and the specified nodal plane(s) are plotted, i.e. the quadrants
# remain unfilled (transparent). We can make use of the stacking concept of (Py)GMT,
# and use ``nodal`` in combination with the ``outline``, ``compressionfill`` /
# ``extensionfill`` and ``pen`` parameters.
fig = pygmt.Figure()
fig.basemap(region=region, projection=projection, frame=frame)
fig.meca(
spec=aki_single,
scale="1c",
longitude=-2,
latitude=0,
depth=0,
nodal="0/1p,black",
)
# Plot the same beachball three times with different settings:
# (i) Fill the compressive quadrants
# (ii) Plot the first nodal plane and the circumference in darkorange
# (iii) Plot the circumfence in black on top; use "-" to not fill the quadrants
for kwargs in [
{"compressionfill": "lightorange"},
{"nodal": "1/1p,darkorange"},
{"compressionfill": "-", "extensionfill": "-", "pen": "1p,gray30"},
]:
fig.meca(
spec=aki_single,
scale="1c",
longitude=0,
latitude=0,
depth=0,
**kwargs,
)
fig.show()
# %%
# Adding offset from event location
# ---------------------------------
#
# Specify the optional parameters ``plot_longitude`` and ``plot_latitude``. If ``spec``
# is an ASCII file with columns for ``plot_longitude`` and ``plot_latitude``, the
# ``offset`` parameter has to be set to ``True``. Besides just drawing a line between
# the beachball and the event location, a small circle can be plotted at the event
# location by appending **+s** and the descired circle diameter. The connecting line as
# well as the outline of the circle are plotted with the setting of pen, or can be
# adjusted separately. The fill of the small circle corresponds to the fill of the
# compressive quadrantes.
fig = pygmt.Figure()
fig.basemap(region=region, projection=projection, frame=frame)
fig.meca(
spec=aki_single,
scale="1c",
longitude=-1,
latitude=0,
depth=0,
plot_longitude=-3,
plot_latitude=2,
)
fig.meca(
spec=aki_single,
scale="1c",
longitude=3,
latitude=0,
depth=0,
plot_longitude=1,
plot_latitude=2,
offset="+p1p,darkorange+s0.25c",
compressionfill="lightorange",
)
fig.show()
# %%
# Plotting multiple beachballs
# ----------------------------
#
# Now we want to plot multiple beachballs with one call of :meth:`pygmt.Figure.meca`. We
# use data of four earthquakes taken from USGS. For each focal mechanism parameter a
# list with a length corresponding to the number of events has to be given.
# Set up a pandas.DataFrame with multiple focal mechanism parameters.
aki_multiple = pd.DataFrame(
{
"strike": [255, 173, 295, 318],
"dip": [70, 68, 79, 89],
"rake": [20, 83, -177, -179],
"magnitude": [7.0, 5.8, 6.0, 7.8],
"longitude": [-72.53, -79.61, 69.46, 37.01],
"latitude": [18.44, 0.90, 33.02, 37.23],
"depth": [13, 19, 4, 10],
"plot_longitude": [-70, -110, 100, 0],
"plot_latitude": [40, 10, 50, 55],
"event_name": [
"Haiti - 2010/01/12",
"Esmeraldas - 2022/03/27",
"Afghanistan - 2022/06/21",
"Syria/Turkey - 2023/02/06",
],
}
)
# %%
# Adding a label
# --------------
#
# Use the optional parameter ``event_name`` to add a label near the beachball, e.g.,
# event name or event date and time. Change the font of the label text by appending
# **+f** and the desired font (size,name,color) to the argument passed to the ``scale``
# parameter. Additionally, the location of the label relative to the beachball [Default
# is ``"TC"``, i.e., Top Center] can be changed by appending **+j** and an offset can
# be applied by appending **+o** with values for *dx*\ /*dy*. Add a colored [Default is
# white] box behind the label via the label ``labelbox``. Force a fixed size of the
# beachball by appending **+m** to the argument passed to the ``scale`` parameter.
fig = pygmt.Figure()
fig.coast(region="d", projection="N10c", land="lightgray", frame=True)
fig.meca(spec=aki_multiple, scale="0.4c+m+f5p", labelbox="white@30", offset="+s0.1c")
fig.show()
# %%
# Using size-coding and color-coding
# ----------------------------------
#
# The beachball can be sized and colored by the quantities given as ``magnitude`` and
# ``depth``, e.g., by moment magnitude or hypocentral depth, respectively. Use the
# parameter ``cmap`` to pass the descired colormap. Now, the fills of the small circles
# indicating the event locations are given by the colormap.
fig = pygmt.Figure()
fig.coast(region="d", projection="N10c", land="lightgray", frame=True)
# Set up colormap and colorbar for hypocentral depth
pygmt.makecpt(cmap="lajolla", series=[0, 20])
fig.colorbar(frame=["x+lhypocentral depth", "y+lkm"])
fig.meca(
spec=aki_multiple,
scale="0.4c+f5p",
offset="0.2p,gray30+s0.1c",
labelbox="white@30",
cmap=True,
outline="0.2p,gray30",
)
fig.show()
# sphinx_gallery_thumbnail_number = 8