Skip to content

Commit be75223

Browse files
authored
Wrap meca (#516)
* Wrap meca command * Write tests for various meca input formats * Add example to gallery
1 parent 4cfb7a2 commit be75223

11 files changed

+655
-1
lines changed

doc/api/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ Plotting data and laying out the map:
3535
Figure.image
3636
Figure.shift_origin
3737
Figure.text
38+
Figure.meca
3839

3940
Color palette table generation:
4041

examples/gallery/plot/meca.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
"""
2+
Focal mechanisms
3+
----------------
4+
5+
The :meth:`pygmt.Figure.meca` method can plot focal mechanisms, or beachballs.
6+
We can specify the focal mechanism nodal planes or moment tensor components as
7+
a dict using the ``spec`` argument (or they can be specified as a 1d or 2d array,
8+
or within a specified file). The size of plotted beachballs can be specified
9+
using the ``scale`` argument.
10+
"""
11+
12+
import pygmt
13+
14+
fig = pygmt.Figure()
15+
16+
# generate a basemap near Washington state showing coastlines, land, and water
17+
fig.coast(
18+
region=[-125, -122, 47, 49],
19+
projection="M6c",
20+
land="grey",
21+
water="lightblue",
22+
shorelines=True,
23+
resolution="f",
24+
frame="a",
25+
)
26+
27+
# store focal mechanisms parameters in a dict
28+
focal_mechanism = dict(strike=330, dip=30, rake=90, magnitude=3)
29+
30+
# pass the focal mechanism data to meca in addition to the scale and event location
31+
fig.meca(focal_mechanism, scale="1c", longitude=-124.3, latitude=48.1, depth=12.0)
32+
33+
fig.show()

pygmt/base_plotting.py

Lines changed: 382 additions & 1 deletion
Large diffs are not rendered by default.
4.79 KB
Loading
3.13 KB
Loading
5.29 KB
Loading
Loading
Loading
Loading
3.1 KB
Loading

pygmt/tests/test_meca.py

Lines changed: 239 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,239 @@
1+
"""
2+
Tests for meca
3+
"""
4+
import os
5+
import pandas as pd
6+
import numpy as np
7+
import pytest
8+
from pygmt.helpers import GMTTempFile
9+
10+
from .. import Figure
11+
12+
13+
TEST_DATA_DIR = os.path.join(os.path.dirname(__file__), "data")
14+
15+
16+
@pytest.mark.mpl_image_compare
17+
def test_meca_spec_dictionary():
18+
"""
19+
Test supplying a dictionary containing a single focal mechanism to the
20+
`spec` argument.
21+
"""
22+
23+
fig = Figure()
24+
25+
# Right lateral strike slip focal mechanism
26+
fig.meca(
27+
dict(strike=0, dip=90, rake=0, magnitude=5),
28+
longitude=0,
29+
latitude=5,
30+
depth=0,
31+
scale="2.5c",
32+
region=[-1, 1, 4, 6],
33+
projection="M14c",
34+
frame=2,
35+
)
36+
37+
return fig
38+
39+
40+
@pytest.mark.mpl_image_compare
41+
def test_meca_spec_dict_list():
42+
"""
43+
Test supplying a dictionary containing a list of focal mechanism to the
44+
`spec` argument.
45+
"""
46+
47+
fig = Figure()
48+
49+
# supply focal mechanisms as a dict of lists
50+
focal_mechanisms = dict(
51+
strike=[330, 350], dip=[30, 50], rake=[90, 90], magnitude=[3, 2]
52+
)
53+
54+
fig.meca(
55+
focal_mechanisms,
56+
longitude=[-124.3, -124.4],
57+
latitude=[48.1, 48.2],
58+
depth=[12.0, 11.0],
59+
region=[-125, -122, 47, 49],
60+
scale="2c",
61+
projection="M14c",
62+
)
63+
64+
return fig
65+
66+
67+
@pytest.mark.mpl_image_compare
68+
def test_meca_spec_dataframe():
69+
"""
70+
Test supplying a pandas DataFrame containing focal mechanisms and
71+
locations to the `spec` argument.
72+
"""
73+
74+
fig = Figure()
75+
76+
# supply focal mechanisms to meca as a dataframe
77+
focal_mechanisms = dict(
78+
strike=[324, 353],
79+
dip=[20.6, 40],
80+
rake=[83, 90],
81+
magnitude=[3.4, 2.9],
82+
longitude=[-124, -124.4],
83+
latitude=[48.1, 48.2],
84+
depth=[12, 11.0],
85+
)
86+
spec_dataframe = pd.DataFrame(data=focal_mechanisms)
87+
88+
fig.meca(spec_dataframe, region=[-125, -122, 47, 49], scale="2c", projection="M14c")
89+
90+
return fig
91+
92+
93+
@pytest.mark.mpl_image_compare
94+
def test_meca_spec_1d_array():
95+
"""
96+
Test supplying a 1D numpy array containing focal mechanisms and
97+
locations to the `spec` argument.
98+
"""
99+
100+
fig = Figure()
101+
102+
# supply focal mechanisms to meca as a 1D numpy array, here we are using
103+
# the Harvard CMT zero trace convention but the focal mechanism
104+
# parameters may be specified any of the available conventions. Since we
105+
# are not using a dict or dataframe the convention and component should
106+
# be specified.
107+
focal_mechanism = [
108+
-127.40, # longitude
109+
40.87, # latitude
110+
12, # depth
111+
-3.19, # mrr
112+
0.16, # mtt
113+
3.03, # mff
114+
-1.02, # mrt
115+
-3.93, # mrf
116+
-0.02, # mtf
117+
23, # exponent
118+
0, # plot_lon, 0 to plot at event location
119+
0, # plot_lat, 0 to plot at event location
120+
]
121+
focal_mech_array = np.asarray(focal_mechanism)
122+
123+
fig.meca(
124+
focal_mech_array,
125+
convention="mt",
126+
component="full",
127+
region=[-128, -127, 40, 41],
128+
scale="2c",
129+
projection="M14c",
130+
)
131+
132+
return fig
133+
134+
135+
@pytest.mark.mpl_image_compare
136+
def test_meca_spec_2d_array():
137+
"""
138+
Test supplying a 2D numpy array containing focal mechanisms and
139+
locations to the `spec` argument.
140+
"""
141+
142+
fig = Figure()
143+
144+
# supply focal mechanisms to meca as a 2D numpy array, here we are using
145+
# the GCMT convention but the focal mechanism parameters may be
146+
# specified any of the available conventions. Since we are not using a
147+
# dict or dataframe the convention and component should be specified.
148+
focal_mechanisms = [
149+
[
150+
-127.40, # longitude
151+
40.87, # latitude
152+
12, # depth
153+
170, # strike1
154+
20, # dip1
155+
-110, # rake1
156+
11, # strike2
157+
71, # dip2
158+
-83, # rake2
159+
5.1, # mantissa
160+
23, # exponent
161+
0, # plot_lon, 0 means we want to plot at the event location
162+
0, # plot_lat
163+
],
164+
[-127.50, 40.88, 12.0, 168, 40, -115, 20, 54, -70, 4.0, 23, 0, 0],
165+
]
166+
focal_mechs_array = np.asarray(focal_mechanisms)
167+
168+
fig.meca(
169+
focal_mechs_array,
170+
convention="gcmt",
171+
region=[-128, -127, 40, 41],
172+
scale="2c",
173+
projection="M14c",
174+
)
175+
176+
return fig
177+
178+
179+
@pytest.mark.mpl_image_compare
180+
def test_meca_spec_file():
181+
"""
182+
Test supplying a file containing focal mechanisms and locations to the
183+
`spec` argument.
184+
"""
185+
186+
fig = Figure()
187+
188+
focal_mechanism = [-127.43, 40.81, 12, -3.19, 1.16, 3.93, -1.02, -3.93, -1.02, 23]
189+
190+
# writes temp file to pass to gmt
191+
with GMTTempFile() as temp:
192+
with open(temp.name, mode="w") as temp_file:
193+
temp_file.write(" ".join([str(x) for x in focal_mechanism]))
194+
# supply focal mechanisms to meca as a file
195+
fig.meca(
196+
temp.name,
197+
convention="mt",
198+
component="full",
199+
region=[-128, -127, 40, 41],
200+
scale="2c",
201+
projection="M14c",
202+
)
203+
204+
return fig
205+
206+
207+
@pytest.mark.mpl_image_compare
208+
def test_meca_loc_array():
209+
"""
210+
Test supplying lists and np.ndarrays as the event location (longitude,
211+
latitude, and depth).
212+
"""
213+
214+
fig = Figure()
215+
216+
# specify focal mechanisms
217+
focal_mechanisms = dict(
218+
strike=[327, 350], dip=[41, 50], rake=[68, 90], magnitude=[3, 2]
219+
)
220+
221+
# longitude, latitude, and depth may be specified as an int, float,
222+
# list, or 1d numpy array
223+
longitude = np.array([-123.3, -124.4])
224+
latitude = np.array([48.4, 48.2])
225+
depth = [12.0, 11.0] # to test mixed data types as inputs
226+
227+
scale = "2c"
228+
229+
fig.meca(
230+
focal_mechanisms,
231+
scale,
232+
longitude,
233+
latitude,
234+
depth,
235+
region=[-125, -122, 47, 49],
236+
projection="M14c",
237+
)
238+
239+
return fig

0 commit comments

Comments
 (0)