@@ -988,27 +988,171 @@ def text(
988
988
@fmt_docstring
989
989
@use_alias (R = "region" , J = "projection" , B = "frame" , S = "convention" )
990
990
@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
+ ):
992
1004
"""
993
1005
Plot focal mechanisms.
994
1006
995
1007
Parameters
996
1008
----------
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()
999
1047
"""
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 )
1001
1147
with Session () as lib :
1002
1148
if kind == "matrix" :
1003
1149
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
1006
1152
elif kind == "file" :
1007
- file_context = dummy_context (focal_mechanism )
1153
+ file_context = dummy_context (spec )
1008
1154
else :
1009
- raise GMTInvalidInput (
1010
- "Unrecognized data type: {}" .format (type (focal_mechanism ))
1011
- )
1155
+ raise GMTInvalidInput ("Unrecognized data type: {}" .format (type (spec )))
1012
1156
with file_context as fname :
1013
1157
arg_str = " " .join ([fname , build_arg_string (kwargs )])
1014
1158
lib .call_module ("meca" , arg_str )
0 commit comments