Skip to content

Commit 2fe87af

Browse files
committed
Added all GMT meca data conventions to pygmt meca
1 parent 28efc2d commit 2fe87af

File tree

1 file changed

+154
-10
lines changed

1 file changed

+154
-10
lines changed

pygmt/base_plotting.py

+154-10
Original file line numberDiff line numberDiff line change
@@ -988,27 +988,171 @@ def text(
988988
@fmt_docstring
989989
@use_alias(R="region", J="projection", B="frame", S="convention")
990990
@kwargs_to_strings(R="sequence",)
991-
def meca(self, focal_mechanism, **kwargs):
991+
def meca(
992+
self,
993+
lon=None,
994+
lat=None,
995+
depth=None,
996+
spec=None,
997+
convention=None,
998+
plot_lon=None, # FIXME: implement -C flag if plot location is specified
999+
plot_lat=None,
1000+
text=None,
1001+
scale=None, # FIXME: implement
1002+
**kwargs,
1003+
):
9921004
"""
9931005
Plot focal mechanisms.
9941006
9951007
Parameters
9961008
----------
997-
focal_mechanism: 1D array, 2D array, or str
998-
Description here.
1009+
lon: int or float
1010+
Longitude of event location.
1011+
lat: int or float
1012+
Latitude of event location.
1013+
depth: int or float
1014+
Depth of event location in kilometers.
1015+
spec: dict, 1D array, 2D array, or str
1016+
Object specifying event parameters that are consistent with the specified convention.
1017+
If a string specifying a filename is assigned to spec, no other parameters are required,
1018+
as those parameters are assumed to exist in the file.
1019+
List of required spec parameters for different conventions:
1020+
a (Aki & Rickards): strike, dip, rake, magnitude
1021+
c (global CMT): strike1, dip1, rake1, strike2, dip2, rake2, mantissa, exponent
1022+
m (seismic moment tensor): mrr, mtt, mff, mrt, mrf, mtf, exponent
1023+
p (partial focal mechanism): strike1, dip1, strike2, fault_type, magnitude
1024+
x (principal axis): t_exponent, t_azimuth, t_plunge, n_exponent, n_azimuth, n_plunge, p_exponent, p_azimuth, p_plunge, exponent
1025+
convention: str
1026+
a (Aki & Richards), c (global CMT), m (seismic moment tensor), p (partial focal mechanism), x (principal axis)
1027+
Optional (auto-detected) if spec is defined as a dict.
1028+
plot_lon: (optional) int or float
1029+
Longitude at which to place beachball
1030+
plot_lat: (optional) int or float
1031+
Latitude at which to place beachball
1032+
text: (optional) str
1033+
Text string to appear near the beachball
1034+
1035+
Examples
1036+
--------
1037+
fig = pygmt.Figure()
1038+
fig.meca(lon=239.384, lat=34.556, depth=12.0,
1039+
spec=dict(strike1=180, dip1=18, rake1=-88, strike2=0,
1040+
dip2=72, rake2=-90, mantissa=5.5, exponent=0),
1041+
region=[239, 240, 34, 35.2], projection='m4c')
1042+
fig.show()
1043+
1044+
fig = pygmt.Figure()
1045+
fig.meca(spec='focal_mechanisms.psmeca')
1046+
fig.show()
9991047
"""
1000-
kind = data_kind(focal_mechanism)
1048+
1049+
# Check the spec and parse the data according to the specified convention
1050+
if type(spec) is dict:
1051+
if (
1052+
(lon is None) or (lat is None) or (depth is None)
1053+
): # if no specified location
1054+
raise Error("Location not fully specified.")
1055+
1056+
# These are constants related to GMT and could be defined elsewhere (top of file?)
1057+
AKI_PARAMS = ["strike", "dip", "rake", "magnitude"]
1058+
GCMT_PARAMS = [
1059+
"strike1",
1060+
"dip1",
1061+
"rake1",
1062+
"strike2",
1063+
"dip2",
1064+
"rake2",
1065+
"mantissa",
1066+
"exponent",
1067+
]
1068+
# FIXME: allow specification of moment instead of mantissa and exponent.
1069+
MT_PARAMS = ["mrr", "mtt", "mff", "mrt", "mrf", "mtf", "exponent"]
1070+
PFM_PARAMS = ["strike1", "dip1", "strike2", "fault_type", "magnitude"]
1071+
PA_PARAMS = [
1072+
"t_exponent",
1073+
"t_azimuth",
1074+
"t_plunge",
1075+
"n_exponent",
1076+
"n_azimuth",
1077+
"n_plunge",
1078+
"p_exponent",
1079+
"p_azimuth",
1080+
"p_plunge",
1081+
"exponent",
1082+
]
1083+
1084+
# Aki and Richards convention: -Sa in GMT
1085+
if set(spec.keys()) == set(AKI_PARAMS):
1086+
if (convention != "a") and (convention is not None):
1087+
print(
1088+
f"Specified convention {convention} is incompatible with data specified in spec dict. Proceeding using Aki and Richards convention."
1089+
)
1090+
convention = "a"
1091+
foc_params = AKI_PARAMS
1092+
1093+
# Global CMT convention: -Sc in GMT
1094+
elif set(spec.keys()) == set(GCMT_PARAMS):
1095+
if (convention != "c") and (convention is not None):
1096+
print(
1097+
f"Specified convention {convention} is incompatible with data specified in spec dict. Proceeding using global CMT convention."
1098+
)
1099+
convention = "c"
1100+
foc_params = GCMT_PARAMS
1101+
1102+
# Seismic moment tensor convention: -Sm in GMT
1103+
elif set(spec.keys()) == set(MT_PARAMS):
1104+
if (convention != "m") and (convention is not None):
1105+
print(
1106+
f"Specified convention {convention} is incompatible with data specified in spec dict. Proceeding using seismic moment tensor convention."
1107+
)
1108+
convention = "m"
1109+
foc_params = MT_PARAMS
1110+
1111+
# Partial focal mechanism convention: -Sp in GMT
1112+
elif set(spec.keys()) == set(PFM_PARAMS):
1113+
if (convention != "p") and (convention is not None):
1114+
print(
1115+
f"Specified convention {convention} is incompatible with data specified in spec dict. Proceeding using partial focal mechanism convention."
1116+
)
1117+
convention = "p"
1118+
foc_params = PFM_PARAMS
1119+
1120+
# Principal axis convention: -Sx in GMT
1121+
elif set(spec.keys()) == set(PFM_PARAMS):
1122+
if (convention != "x") and (convention is not None):
1123+
print(
1124+
f"Specified convention {convention} is incompatible with data specified in spec dict. Proceeding using principal axis convention."
1125+
)
1126+
convention = "x"
1127+
foc_params = PA_PARAMS
1128+
1129+
else:
1130+
raise Error("Parameters in spec dict do not match known conventions.")
1131+
1132+
# Construct the vector (note that order matters here, hence the list comprehension!)
1133+
spec = [lon, lat, depth] + [spec[key] for key in foc_params]
1134+
1135+
# Add in plotting options, if given, otherwise add 0s as required by GMT
1136+
for arg in plot_lon, plot_lat, text:
1137+
if arg is None:
1138+
spec.append(0)
1139+
else:
1140+
spec.append(arg)
1141+
1142+
elif convention is None:
1143+
raise Error("We need a convention to know how to interpret the input!")
1144+
1145+
# if spec is not a dict it is handled here
1146+
kind = data_kind(spec)
10011147
with Session() as lib:
10021148
if kind == "matrix":
10031149
file_context = lib.virtualfile_from_matrix(
1004-
np.atleast_2d(focal_mechanism)
1005-
)
1150+
np.atleast_2d(spec)
1151+
) # np.atleast_2d allows 1D and 2D arrays
10061152
elif kind == "file":
1007-
file_context = dummy_context(focal_mechanism)
1153+
file_context = dummy_context(spec)
10081154
else:
1009-
raise GMTInvalidInput(
1010-
"Unrecognized data type: {}".format(type(focal_mechanism))
1011-
)
1155+
raise GMTInvalidInput("Unrecognized data type: {}".format(type(spec)))
10121156
with file_context as fname:
10131157
arg_str = " ".join([fname, build_arg_string(kwargs)])
10141158
lib.call_module("meca", arg_str)

0 commit comments

Comments
 (0)