pygmi 2.2.7__zip

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. pygmi-2.2.7/LICENSE.txt +623 -0
  2. pygmi-2.2.7/MANIFEST.in +7 -0
  3. pygmi-2.2.7/PKG-INFO +47 -0
  4. pygmi-2.2.7/README.md +55 -0
  5. pygmi-2.2.7/README.rst +20 -0
  6. pygmi-2.2.7/log.txt +242 -0
  7. pygmi-2.2.7/pygmi/__init__.py +22 -0
  8. pygmi-2.2.7/pygmi/clust/__init__.py +4 -0
  9. pygmi-2.2.7/pygmi/clust/crisp_clust.py +708 -0
  10. pygmi-2.2.7/pygmi/clust/datatypes.py +65 -0
  11. pygmi-2.2.7/pygmi/clust/fuzzy_clust.py +906 -0
  12. pygmi-2.2.7/pygmi/clust/graphs.py +421 -0
  13. pygmi-2.2.7/pygmi/clust/graphtool.py +667 -0
  14. pygmi-2.2.7/pygmi/clust/menu.py +139 -0
  15. pygmi-2.2.7/pygmi/clust/var_ratio.py +92 -0
  16. pygmi-2.2.7/pygmi/clust/xie_beni.py +93 -0
  17. pygmi-2.2.7/pygmi/helpdocs/linepointer.png +0 -0
  18. pygmi-2.2.7/pygmi/helpdocs/pygmi.main.html +31 -0
  19. pygmi-2.2.7/pygmi/helpdocs/pygmi.pfmod.ddisp.html +15 -0
  20. pygmi-2.2.7/pygmi/helpdocs/pygmi.pfmod.iodefs.exportkmz.html +13 -0
  21. pygmi-2.2.7/pygmi/helpdocs/pygmi.pfmod.iodefs.importpicture.html +16 -0
  22. pygmi-2.2.7/pygmi/helpdocs/pygmi.pfmod.layer.html +17 -0
  23. pygmi-2.2.7/pygmi/helpdocs/pygmi.pfmod.mext.html +44 -0
  24. pygmi-2.2.7/pygmi/helpdocs/pygmi.pfmod.misc.rangedcopy.html +16 -0
  25. pygmi-2.2.7/pygmi/helpdocs/pygmi.pfmod.param.html +37 -0
  26. pygmi-2.2.7/pygmi/helpdocs/pygmi.pfmod.prof.html +32 -0
  27. pygmi-2.2.7/pygmi/helpdocs/pygmi.pfmod.pview.html +26 -0
  28. pygmi-2.2.7/pygmi/helpdocs/pygmi.raster.cooper.gradients.html +14 -0
  29. pygmi-2.2.7/pygmi/helpdocs/pygmi.raster.cooper.tilt.html +14 -0
  30. pygmi-2.2.7/pygmi/helpdocs/pygmi.raster.cooper.visibility.html +14 -0
  31. pygmi-2.2.7/pygmi/helpdocs/pygmi.raster.dataprep.datagrid.html +13 -0
  32. pygmi-2.2.7/pygmi/helpdocs/pygmi.raster.dataprep.datamerge.html +11 -0
  33. pygmi-2.2.7/pygmi/helpdocs/pygmi.raster.dataprep.datareproj.html +11 -0
  34. pygmi-2.2.7/pygmi/helpdocs/pygmi.raster.dataprep.rtp.html +14 -0
  35. pygmi-2.2.7/pygmi/helpdocs/pygmi.raster.ginterp.html +31 -0
  36. pygmi-2.2.7/pygmi/helpdocs/pygmi.raster.igrf.html +20 -0
  37. pygmi-2.2.7/pygmi/helpdocs/pygmi.raster.normalisation.html +14 -0
  38. pygmi-2.2.7/pygmi/helpdocs/pygmi.raster.smooth.html +22 -0
  39. pygmi-2.2.7/pygmi/helpdocs/pygmi.raster.tiltdepth.html +20 -0
  40. pygmi-2.2.7/pygmi/images/Help.png +0 -0
  41. pygmi-2.2.7/pygmi/images/bringtofront.png +0 -0
  42. pygmi-2.2.7/pygmi/images/cgs2.emf +0 -0
  43. pygmi-2.2.7/pygmi/images/delete.png +0 -0
  44. pygmi-2.2.7/pygmi/images/linepointer.png +0 -0
  45. pygmi-2.2.7/pygmi/images/logo256.ico +0 -0
  46. pygmi-2.2.7/pygmi/images/logo256.png +0 -0
  47. pygmi-2.2.7/pygmi/images/pointer.png +0 -0
  48. pygmi-2.2.7/pygmi/images/pygmi.png +0 -0
  49. pygmi-2.2.7/pygmi/images/sendtoback.png +0 -0
  50. pygmi-2.2.7/pygmi/main.py +1037 -0
  51. pygmi-2.2.7/pygmi/menu_default.py +327 -0
  52. pygmi-2.2.7/pygmi/misc.py +147 -0
  53. pygmi-2.2.7/pygmi/pfmod/__init__.py +6 -0
  54. pygmi-2.2.7/pygmi/pfmod/cubes.py +1488 -0
  55. pygmi-2.2.7/pygmi/pfmod/datatypes.py +292 -0
  56. pygmi-2.2.7/pygmi/pfmod/grvmag3d.py +1265 -0
  57. pygmi-2.2.7/pygmi/pfmod/iodefs.py +1001 -0
  58. pygmi-2.2.7/pygmi/pfmod/menu.py +107 -0
  59. pygmi-2.2.7/pygmi/pfmod/misc.py +301 -0
  60. pygmi-2.2.7/pygmi/pfmod/pfmod.py +248 -0
  61. pygmi-2.2.7/pygmi/pfmod/tab_ddisp.py +425 -0
  62. pygmi-2.2.7/pygmi/pfmod/tab_layer.py +490 -0
  63. pygmi-2.2.7/pygmi/pfmod/tab_mext.py +544 -0
  64. pygmi-2.2.7/pygmi/pfmod/tab_param.py +548 -0
  65. pygmi-2.2.7/pygmi/pfmod/tab_prof.py +946 -0
  66. pygmi-2.2.7/pygmi/pfmod/tab_pview.py +740 -0
  67. pygmi-2.2.7/pygmi/raster/IGRF11.COF +1635 -0
  68. pygmi-2.2.7/pygmi/raster/__init__.py +14 -0
  69. pygmi-2.2.7/pygmi/raster/cooper.py +718 -0
  70. pygmi-2.2.7/pygmi/raster/dataprep.py +1640 -0
  71. pygmi-2.2.7/pygmi/raster/datatypes.py +123 -0
  72. pygmi-2.2.7/pygmi/raster/equation_editor.py +256 -0
  73. pygmi-2.2.7/pygmi/raster/ginterp.py +1901 -0
  74. pygmi-2.2.7/pygmi/raster/graphs.py +531 -0
  75. pygmi-2.2.7/pygmi/raster/igrf.py +860 -0
  76. pygmi-2.2.7/pygmi/raster/iodefs.py +813 -0
  77. pygmi-2.2.7/pygmi/raster/menu.py +307 -0
  78. pygmi-2.2.7/pygmi/raster/normalisation.py +187 -0
  79. pygmi-2.2.7/pygmi/raster/show_table.py +245 -0
  80. pygmi-2.2.7/pygmi/raster/smooth.py +406 -0
  81. pygmi-2.2.7/pygmi/raster/tiltdepth.py +590 -0
  82. pygmi-2.2.7/pygmi/seis/__init__.py +0 -0
  83. pygmi-2.2.7/pygmi/seis/beachball.py +751 -0
  84. pygmi-2.2.7/pygmi/seis/datatypes.py +605 -0
  85. pygmi-2.2.7/pygmi/seis/del_rec.py +410 -0
  86. pygmi-2.2.7/pygmi/seis/iodefs.py +1261 -0
  87. pygmi-2.2.7/pygmi/seis/menu.py +136 -0
  88. pygmi-2.2.7/pygmi/seis/scan_imp.py +795 -0
  89. pygmi-2.2.7/pygmi/test/__init__.py +6 -0
  90. pygmi-2.2.7/pygmi/test/pfmod.py +212 -0
  91. pygmi-2.2.7/pygmi/test/tests.py +39 -0
  92. pygmi-2.2.7/pygmi/vector/__init__.py +7 -0
  93. pygmi-2.2.7/pygmi/vector/datatypes.py +74 -0
  94. pygmi-2.2.7/pygmi/vector/graphs.py +443 -0
  95. pygmi-2.2.7/pygmi/vector/iodefs.py +345 -0
  96. pygmi-2.2.7/pygmi/vector/menu.py +127 -0
  97. pygmi-2.2.7/pygmi.egg-info/PKG-INFO +47 -0
  98. pygmi-2.2.7/pygmi.egg-info/SOURCES.txt +105 -0
  99. pygmi-2.2.7/pygmi.egg-info/dependency_links.txt +1 -0
  100. pygmi-2.2.7/pygmi.egg-info/entry_points.txt +3 -0
  101. pygmi-2.2.7/pygmi.egg-info/not-zip-safe +1 -0
  102. pygmi-2.2.7/pygmi.egg-info/requires.txt +7 -0
  103. pygmi-2.2.7/pygmi.egg-info/top_level.txt +1 -0
  104. pygmi-2.2.7/quickstart.py +35 -0
  105. pygmi-2.2.7/setup.cfg +8 -0
  106. pygmi-2.2.7/setup.py +80 -0
@@ -0,0 +1,751 @@
1
+ # -----------------------------------------------------------------------------
2
+ # Name: beachball.py (part of PyGMI)
3
+ #
4
+ # Author: Patrick Cole
5
+ # E-Mail: pcole@geoscience.org.za
6
+ #
7
+ # Copyright: (c) 2013 Council for Geoscience
8
+ # Licence: GPL-3.0
9
+ #
10
+ # This file is part of PyGMI
11
+ #
12
+ # PyGMI is free software: you can redistribute it and/or modify
13
+ # it under the terms of the GNU General Public License as published by
14
+ # the Free Software Foundation, either version 3 of the License, or
15
+ # (at your option) any later version.
16
+ #
17
+ # PyGMI is distributed in the hope that it will be useful,
18
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
19
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20
+ # GNU General Public License for more details.
21
+ #
22
+ # You should have received a copy of the GNU General Public License
23
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
24
+ # -----------------------------------------------------------------------------
25
+ # Licence for original ModestImage code (modified version below)
26
+ # ModestImage
27
+ # Copyright (c) 2013 Chris Beaumont
28
+ #
29
+ # Permission is hereby granted, free of charge, to any person obtaining a
30
+ # copy of this software and associated documentation files (the "Software"),
31
+ # to deal in the Software without restriction, including without limitation
32
+ # the rights to use, copy, modify, merge, publish, distribute, sublicense,
33
+ # and/or sell copies of the Software, and to permit persons to whom the
34
+ # Software is furnished to do so, subject to the following conditions:
35
+ #
36
+ # The above copyright notice and this permission notice shall be included in
37
+ # all copies or substantial portions of the Software.
38
+ #
39
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
40
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
41
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
42
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
43
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
44
+ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
45
+ # DEALINGS IN THE SOFTWARE.
46
+ # -----------------------------------------------------------------------------
47
+ """ Plot fault plane solutions.
48
+ The code below is translated from bb.m written by Andy Michael and Oliver Boyd
49
+ at http://www.ceri.memphis.edu/people/olboyd/Software/Software.html"""
50
+
51
+ import numpy as np
52
+ import numexpr as ne
53
+ from PyQt4 import QtGui
54
+ import matplotlib.cm as cm
55
+ import matplotlib.pyplot as plt
56
+ from matplotlib.backends.backend_qt4agg import FigureCanvas
57
+ from matplotlib.backends.backend_qt4agg import NavigationToolbar2QT as \
58
+ NavigationToolbar
59
+ import os
60
+ from matplotlib import patches
61
+ import osgeo.ogr as ogr
62
+ import osgeo.osr as osr
63
+ import scipy.spatial.distance as sdist
64
+
65
+
66
+ class MyMplCanvas(FigureCanvas):
67
+ """Canvas for the actual plot"""
68
+ def __init__(self, parent):
69
+ fig = plt.figure()
70
+ super(MyMplCanvas, self).__init__(fig)
71
+
72
+ # figure stuff
73
+ self.htype = 'Linear'
74
+ self.cbar = cm.jet
75
+ self.data = []
76
+ self.gmode = None
77
+ self.argb = [None, None, None]
78
+ self.hhist = [None, None, None]
79
+ self.hband = [None, None, None]
80
+ self.htxt = [None, None, None]
81
+ self.patches = []
82
+ self.lines = []
83
+ self.image = None
84
+ self.cnt = None
85
+ self.cntf = None
86
+ self.background = None
87
+ self.pwidth = 0.001
88
+
89
+ self.axes = fig.add_subplot(111)
90
+ self.axes.xaxis.set_visible(False)
91
+ self.axes.yaxis.set_visible(False)
92
+
93
+ self.setParent(parent)
94
+
95
+ FigureCanvas.setSizePolicy(self,
96
+ QtGui.QSizePolicy.Expanding,
97
+ QtGui.QSizePolicy.Expanding)
98
+ FigureCanvas.updateGeometry(self)
99
+
100
+ def init_graph(self):
101
+ """ Initialize the graph """
102
+
103
+ self.axes.clear()
104
+ self.axes.set_aspect("equal")
105
+
106
+ maxdiam = self.pwidth*self.data[:, -1].max()
107
+ xmin = self.data[:, 0].min()-maxdiam
108
+ xmax = self.data[:, 0].max()+maxdiam
109
+ ymin = self.data[:, 1].min()-maxdiam
110
+ ymax = self.data[:, 1].max()+maxdiam
111
+
112
+ self.axes.set_xlim((xmin, xmax))
113
+ self.axes.set_ylim((ymin, ymax))
114
+
115
+ self.figure.canvas.draw()
116
+ QtGui.QApplication.processEvents()
117
+
118
+ for idat in self.data:
119
+ pxy = idat[:2]
120
+ np1 = idat[2:-1]
121
+ pwidth = self.pwidth*idat[-1]
122
+ xxx, yyy, xxx2, yyy2 = beachball(np1, pxy[0], pxy[1], pwidth)
123
+
124
+ pvert1 = np.transpose([yyy, xxx])
125
+ pvert0 = np.transpose([xxx2, yyy2])
126
+
127
+ self.axes.add_patch(patches.Polygon(pvert1))
128
+ self.axes.add_patch(patches.Polygon(pvert0, facecolor='none'))
129
+
130
+ self.figure.canvas.draw()
131
+
132
+
133
+ class BeachBall(QtGui.QDialog):
134
+ """ Create shapefiles with beachballs """
135
+ def __init__(self, parent=None):
136
+ super(BeachBall, self).__init__(parent)
137
+
138
+ self.ifile = ""
139
+ self.name = "Beachball: "
140
+ self.ext = ""
141
+ self.pbar = None
142
+ self.parent = parent
143
+ self.indata = {}
144
+ self.outdata = {}
145
+ self.algorithm = 'FPFIT'
146
+ self.nofps = False
147
+
148
+ self.mmc = MyMplCanvas(self)
149
+ self.btn_saveshp = QtGui.QPushButton()
150
+ self.cbox_alg = QtGui.QComboBox()
151
+ self.dsb_dist = QtGui.QDoubleSpinBox()
152
+
153
+ self.setupui()
154
+
155
+ def data_init(self):
156
+ """ data init - entry point into routine """
157
+ if 'Seis' not in self.indata:
158
+ return
159
+
160
+ data = self.indata['Seis']
161
+
162
+ alist = []
163
+ for i in data:
164
+ alist += list(i['F'].keys())
165
+ alist = sorted(set(alist))
166
+
167
+ if len(alist) == 0:
168
+ self.parent.showprocesslog('Error: no Fault Plane Solutions')
169
+ self.nofps = True
170
+ return False
171
+ else:
172
+ self.nofps = False
173
+
174
+ try:
175
+ self.cbox_alg.currentIndexChanged.disconnect()
176
+ except TypeError:
177
+ pass
178
+
179
+ self.cbox_alg.clear()
180
+ self.cbox_alg.addItems(alist)
181
+ self.algorithm = alist[0]
182
+
183
+ self.cbox_alg.currentIndexChanged.connect(self.change_alg)
184
+
185
+ pwidth = 1.
186
+
187
+ for j in alist:
188
+ tmpxy = []
189
+ tmpmag = []
190
+ for i in data:
191
+ if i['F'].get(j) is not None:
192
+ tmp = [i['1'].longitude,
193
+ i['1'].latitude,
194
+ i['1'].magnitude_1]
195
+ tmpxy.append([tmp[0], tmp[1]])
196
+ tmpmag.append(tmp[2])
197
+
198
+ if len(tmpmag) > 1:
199
+ pwidth = min(sdist.pdist(tmpxy).min()/(2*max(tmpmag)), pwidth)
200
+
201
+ self.dsb_dist.setValue(pwidth)
202
+
203
+ self.change_alg()
204
+
205
+ def setupui(self):
206
+ """ Setup UI """
207
+ hbl_all = QtGui.QHBoxLayout(self)
208
+ mpl_toolbar = NavigationToolbar(self.mmc, self)
209
+ vbl_raster = QtGui.QVBoxLayout()
210
+ label2 = QtGui.QLabel()
211
+ label3 = QtGui.QLabel()
212
+
213
+ self.dsb_dist.setDecimals(4)
214
+ self.dsb_dist.setMinimum(0.0001)
215
+ self.dsb_dist.setSingleStep(0.0001)
216
+ self.dsb_dist.setProperty("value", 0.001)
217
+
218
+ spacer = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum,
219
+ QtGui.QSizePolicy.Expanding)
220
+
221
+ self.setWindowTitle("Fault Plane Solution (FPS)")
222
+ label2.setText('FPS Algorithm:')
223
+ label3.setText('Width Scale Factor:')
224
+ self.btn_saveshp.setText('Save Shapefile')
225
+
226
+ vbl_raster.addWidget(label2)
227
+ vbl_raster.addWidget(self.cbox_alg)
228
+ vbl_raster.addWidget(label3)
229
+ vbl_raster.addWidget(self.dsb_dist)
230
+ vbl_raster.addItem(spacer)
231
+ vbl_raster.addWidget(self.btn_saveshp)
232
+ vbl_right = QtGui.QVBoxLayout()
233
+ vbl_right.addWidget(self.mmc)
234
+ vbl_right.addWidget(mpl_toolbar)
235
+ hbl_all.addLayout(vbl_raster)
236
+ hbl_all.addLayout(vbl_right)
237
+
238
+ self.btn_saveshp.clicked.connect(self.save_shp)
239
+ self.dsb_dist.valueChanged.connect(self.change_alg)
240
+
241
+ def save_shp(self):
242
+ """Save Beachballs """
243
+ # data = self.indata['Seis']
244
+
245
+ ext = "Shape file (*.shp)"
246
+
247
+ filename = QtGui.QFileDialog.getSaveFileName(
248
+ self.parent, 'Save Shape File', '.', ext)
249
+
250
+ if filename == '':
251
+ return False
252
+ os.chdir(filename.rpartition('/')[0])
253
+
254
+ self.ifile = str(filename)
255
+ self.ext = filename[-3:]
256
+
257
+ indata = self.mmc.data
258
+
259
+ ifile_bnd = self.ifile[:-4]+'_bnd.shp'
260
+ if os.path.isfile(self.ifile):
261
+ tmp = self.ifile[:-4]
262
+ os.remove(tmp+'.shp')
263
+ os.remove(tmp+'.shx')
264
+ os.remove(tmp+'.prj')
265
+ os.remove(tmp+'.dbf')
266
+ if os.path.isfile(ifile_bnd):
267
+ tmp = ifile_bnd[:-4]
268
+ os.remove(tmp+'.shp')
269
+ os.remove(tmp+'.shx')
270
+ os.remove(tmp+'.prj')
271
+ os.remove(tmp+'.dbf')
272
+
273
+ driver = ogr.GetDriverByName("ESRI Shapefile")
274
+ data_source = driver.CreateDataSource(self.ifile)
275
+ data_source2 = driver.CreateDataSource(ifile_bnd)
276
+
277
+ # create the spatial reference, WGS84
278
+ srs = osr.SpatialReference()
279
+ srs.ImportFromEPSG(4326)
280
+
281
+ # create the layer
282
+ layer = data_source.CreateLayer("Fault Plane Solution", srs,
283
+ ogr.wkbPolygon)
284
+ layer.CreateField(ogr.FieldDefn("Strike", ogr.OFTReal))
285
+ layer.CreateField(ogr.FieldDefn("Dip", ogr.OFTReal))
286
+ layer.CreateField(ogr.FieldDefn("Rake", ogr.OFTReal))
287
+ layer.CreateField(ogr.FieldDefn("Magnitude", ogr.OFTReal))
288
+
289
+ layer2 = data_source2.CreateLayer("Fault Plane Solution Boundaries",
290
+ srs, ogr.wkbPolygon)
291
+
292
+ # Calculate BeachBall
293
+ for idat in indata:
294
+ pxy = idat[:2]
295
+ np1 = idat[2:-1]
296
+ pwidth = self.mmc.pwidth*idat[-1]
297
+ xxx, yyy, xxx2, yyy2 = beachball(np1, pxy[0], pxy[1], pwidth)
298
+
299
+ pvert1 = np.transpose([yyy, xxx])
300
+ pvert0 = np.transpose([xxx2, yyy2])
301
+
302
+ # Create Geometry
303
+ outring = ogr.Geometry(ogr.wkbLinearRing)
304
+ for i in pvert1:
305
+ outring.AddPoint(i[0], i[1])
306
+
307
+ innerring = ogr.Geometry(ogr.wkbLinearRing)
308
+ for i in pvert0:
309
+ innerring.AddPoint(i[0], i[1])
310
+
311
+ poly = ogr.Geometry(ogr.wkbPolygon)
312
+ poly.AddGeometry(outring)
313
+
314
+ poly1 = ogr.Geometry(ogr.wkbPolygon)
315
+ poly1.AddGeometry(innerring)
316
+
317
+ feature = ogr.Feature(layer.GetLayerDefn())
318
+
319
+ feature.SetField("Strike", np1[0])
320
+ feature.SetField("Dip", np1[1])
321
+ feature.SetField("Rake", np1[2])
322
+ feature.SetField("Magnitude", idat[-1])
323
+
324
+ feature.SetGeometry(poly)
325
+ # Create the feature in the layer (shapefile)
326
+ layer.CreateFeature(feature)
327
+ # Destroy the feature to free resources
328
+ feature.Destroy()
329
+
330
+ feature = ogr.Feature(layer2.GetLayerDefn())
331
+ feature.SetGeometry(poly1)
332
+ # Create the feature in the layer (shapefile)
333
+ layer2.CreateFeature(feature)
334
+ # Destroy the feature to free resources
335
+ feature.Destroy()
336
+
337
+ data_source.Destroy()
338
+ data_source2.Destroy()
339
+
340
+ def change_alg(self):
341
+ """ Change algorithm """
342
+ txt = str(self.cbox_alg.currentText())
343
+ self.algorithm = txt
344
+ data = self.indata['Seis']
345
+
346
+ indata = []
347
+ for i in data:
348
+ if i['F'].get(self.algorithm) is not None:
349
+ tmp = [i['1'].longitude, i['1'].latitude,
350
+ i['F'][self.algorithm].strike,
351
+ i['F'][self.algorithm].dip,
352
+ i['F'][self.algorithm].rake,
353
+ i['1'].magnitude_1]
354
+ indata.append(tmp)
355
+
356
+ self.mmc.data = np.array(indata)
357
+ self.mmc.pwidth = self.dsb_dist.value()
358
+ self.mmc.init_graph()
359
+
360
+ def settings(self):
361
+ """ run """
362
+ if self.nofps:
363
+ self.parent.showprocesslog('Error: no Fault Plane Solutions')
364
+ return False
365
+
366
+ self.show()
367
+ QtGui.QApplication.processEvents()
368
+
369
+ self.mmc.init_graph()
370
+
371
+
372
+ def beachball(fm, centerx, centery, diam):
373
+ """
374
+ function bb(fm, centerx, centery, diam, ta, color)
375
+ Draws beachball diagram of earthquake double-couple focal mechanism(s).
376
+ S1, D1, and R1, the strike, dip and rake of one of the focal planes, can
377
+ be vectors of multiple focal mechanisms.
378
+
379
+ Parameters
380
+ ----------
381
+ fm : numpy array
382
+ focal mechanism that is either number of mechnisms (NM) by 3
383
+ (strike, dip, and rake) or NM x 6 (mxx, myy, mzz, mxy, mxz, myz -
384
+ the six independent components of the moment tensor). The strike is
385
+ of the first plane, clockwise relative to north. The dip is of the
386
+ first plane, defined clockwise and perpedicular to strike, relative
387
+ to horizontal such that 0 is horizontal and 90 is vertical. The rake is
388
+ of the first focal plane solution. 90 moves the hanging wall up-dip
389
+ (thrust), 0 moves it in the strike direction (left-lateral), -90 moves
390
+ it down-dip (normal), and 180 moves it opposite to strike
391
+ (right-lateral).
392
+ centerx : float
393
+ place beachball(s) at position centerx
394
+ centery : float
395
+ place beachball(s) at position centery
396
+ diam : float
397
+ draw beachball with this diameter.
398
+
399
+ Returns
400
+ -------
401
+ X : numpy array
402
+ array of x coordinates for vertices
403
+ Y : numpy array
404
+ array of y coordinates for vertices
405
+ xx : numpy array
406
+ array of x coordinates for vertices
407
+ yy : numpy array
408
+ array of y coordinates for vertices
409
+ """
410
+
411
+ fm = np.array(fm)
412
+ diam = np.array([diam])
413
+ centerx = np.array([centerx])
414
+ centery = np.array([centery])
415
+
416
+ if fm.ndim == 1:
417
+ ne1 = 1
418
+ n = fm.size
419
+ fm = np.array([fm])
420
+ else:
421
+ ne1, n = fm.shape
422
+ if n == 6:
423
+ s1 = np.zeros(ne)
424
+ d1 = np.zeros(ne)
425
+ r1 = np.zeros(ne)
426
+ for j in range(ne):
427
+ s1[j], d1[j], r1[j] = mij2sdr(fm[j, 0], fm[j, 1], fm[j, 2],
428
+ fm[j, 3], fm[j, 4], fm[j, 5])
429
+ else:
430
+ s1 = fm[:, 0]
431
+ d1 = fm[:, 1]
432
+ r1 = fm[:, 2]
433
+
434
+ # r2d = 180/np.pi
435
+ d2r = np.pi/180
436
+ ampy = np.cos(np.mean(centery)*d2r)
437
+
438
+ if ne1 > 1:
439
+ [_, i] = np.sort(diam, 1, 'descend')
440
+ diam = diam[i]
441
+ s1 = s1[i]
442
+ d1 = d1[i]
443
+ r1 = r1[i]
444
+ centerx = centerx[i]
445
+ centery = centery[i]
446
+
447
+ mech = np.zeros([ne1, 1])
448
+ j = np.nonzero(r1 > 180)
449
+ r1[j] = r1[j] - 180
450
+ mech[j] = 1
451
+ j = np.nonzero(r1 < 0)
452
+ r1[j] = r1[j] + 180
453
+ mech[j] = 1
454
+
455
+ # Get azimuth and dip of second plane
456
+ s2, d2, r2 = auxplane(s1, d1, r1)
457
+
458
+ for ev in range(ne1):
459
+ S1 = s1[ev]
460
+ D1 = d1[ev]
461
+ S2 = s2[ev]
462
+ D2 = d2[ev]
463
+ P = r1[ev]
464
+ CX = centerx[ev]
465
+ CY = centery[ev]
466
+ D = diam[ev]
467
+ M = mech[ev]
468
+
469
+ if M > 0:
470
+ P = 2
471
+ else:
472
+ P = 1
473
+
474
+ if D1 >= 90:
475
+ D1 = 89.9999
476
+ if D2 >= 90:
477
+ D2 = 89.9999
478
+
479
+ phi = np.arange(0, np.pi, .01)
480
+ d = 90 - D1
481
+ m = 90
482
+ l1 = np.sqrt(d**2/(np.sin(phi)**2 + np.cos(phi)**2 * d**2/m**2))
483
+
484
+ d = 90 - D2
485
+ m = 90
486
+ l2 = np.sqrt(d**2/(np.sin(phi)**2 + np.cos(phi)**2 * d**2/m**2))
487
+
488
+ if D == 0:
489
+ print('Enter a diameter for the beachballs!')
490
+ return
491
+
492
+ inc = 1
493
+ X1, Y1 = pol2cart(phi+S1*d2r, l1)
494
+ if P == 1:
495
+ lo = S1 - 180
496
+ hi = S2
497
+ if lo > hi:
498
+ inc = -inc
499
+ th1 = np.arange(S1-180, S2, inc)
500
+ Xs1, Ys1 = pol2cart(th1*d2r, 90*np.ones_like(th1))
501
+ X2, Y2 = pol2cart(phi+S2*d2r, l2)
502
+ th2 = np.arange(S2+180, S1, -inc)
503
+ else:
504
+ hi = S1 - 180
505
+ lo = S2 - 180
506
+ if lo > hi:
507
+ inc = -inc
508
+ th1 = np.arange(hi, lo, -inc)
509
+ Xs1, Ys1 = pol2cart(th1*d2r, 90*np.ones_like(th1))
510
+ X2, Y2 = pol2cart(phi+S2*d2r, l2)
511
+ X2 = X2[::-1]
512
+ Y2 = Y2[::-1]
513
+ th2 = np.arange(S2, S1, inc)
514
+
515
+ Xs2, Ys2 = pol2cart(th2*d2r, 90*np.ones_like(th2))
516
+
517
+ X = np.concatenate((X1, Xs1, X2, Xs2), 1)
518
+ Y = np.concatenate((Y1, Ys1, Y2, Ys2), 1)
519
+
520
+ if D > 0:
521
+ X = ampy*X * D/90 + CY
522
+ Y = Y * D/90 + CX
523
+ phid = np.arange(0, 2*np.pi, 0.01)
524
+ x, y = pol2cart(phid, 90)
525
+ xx = x*D/90 + CX
526
+ yy = ampy*y*D/90 + CY
527
+
528
+ return X, Y, xx, yy
529
+
530
+
531
+ def pol2cart(phi, rho):
532
+ """ Polar to cartesian coordinates """
533
+ xxx = rho*np.cos(phi)
534
+ yyy = rho*np.sin(phi)
535
+ return xxx, yyy
536
+
537
+
538
+ def auxplane(s1, d1, r1):
539
+ """
540
+ function [strike, dip, rake] = auxplane(s1,d1,r1)
541
+ Get Strike and dip of second plane, adapted from Andy Michael bothplanes.c
542
+ """
543
+ r2d = 180/np.pi
544
+
545
+ z = (s1+90)/r2d
546
+ z2 = d1/r2d
547
+ z3 = r1/r2d
548
+ # /* slick vector in plane 1 */
549
+ sl1 = -np.cos(z3)*np.cos(z)-np.sin(z3)*np.sin(z)*np.cos(z2)
550
+ sl2 = np.cos(z3)*np.sin(z)-np.sin(z3)*np.cos(z)*np.cos(z2)
551
+ sl3 = np.sin(z3)*np.sin(z2)
552
+ strike, dip = strikedip(sl2, sl1, sl3)
553
+
554
+ n1 = np.sin(z)*np.sin(z2) # /* normal vector to plane 1 */
555
+ n2 = np.cos(z)*np.sin(z2)
556
+ # n3 = np.cos(z2)
557
+ h1 = -sl2 # /* strike vector of plane 2 */
558
+ h2 = sl1
559
+ # /* note h3=0 always so we leave it out */
560
+
561
+ z = h1*n1 + h2*n2
562
+ z = z/np.sqrt(h1*h1 + h2*h2)
563
+ z = np.arccos(z)
564
+
565
+ rake = np.zeros_like(strike)
566
+ j = np.nonzero(sl3 > 0)
567
+ rake[j] = z[j]*r2d
568
+ j = np.nonzero(sl3 <= 0)
569
+ rake[j] = -z[j]*r2d
570
+
571
+ return strike, dip, rake
572
+
573
+
574
+ def strikedip(n, e, u):
575
+ """
576
+ function [strike, dip] = strikedip(n, e, u)
577
+ Finds strike and dip of plane given normal vector having components n,
578
+ e, and u
579
+ Adapted from Andy Michaels stridip.c
580
+ """
581
+ r2d = 180/np.pi
582
+
583
+ j = np.nonzero(u < 0)
584
+ n[j] = -n[j]
585
+ e[j] = -e[j]
586
+ u[j] = -u[j]
587
+
588
+ strike = np.arctan2(e, n)*r2d
589
+ strike = strike - 90
590
+ while strike >= 360:
591
+ strike = strike - 360
592
+ while strike < 0:
593
+ strike = strike + 360
594
+
595
+ x = np.sqrt(n**2 + e**2)
596
+ dip = np.arctan2(x, u)*r2d
597
+ return strike, dip
598
+
599
+
600
+ def mij2sdr(mxx, myy, mzz, mxy, mxz, myz):
601
+ """
602
+ function [str,dip,rake] = mij2sdr(mxx,myy,mzz,mxy,mxz,myz)
603
+ Adapted from code, mij2d.f, created by Chen Ji
604
+
605
+ Parameters
606
+ ----------
607
+ mxx - float
608
+ independent component of the moment tensor
609
+ myy - float
610
+ independent component of the moment tensor
611
+ mzz - float
612
+ independent component of the moment tensor
613
+ mxy - float
614
+ independent component of the moment tensor
615
+ mxz - float
616
+ independent component of the moment tensor
617
+ myz - float
618
+ independent component of the moment tensor
619
+
620
+ Returns
621
+ -------
622
+ strike : float
623
+ strike of first focal plane (degrees)
624
+ dip : float
625
+ dip of first focal plane (degrees)
626
+ rake : float
627
+ rake of first focal plane (degrees)
628
+ """
629
+
630
+ a = np.array([[mxx, mxy, mxz],
631
+ [mxy, myy, myz],
632
+ [mxz, myz, mzz]])
633
+ d, V = np.linalg.eig(a)
634
+
635
+ D = np.array([d[1], d[0], d[2]])
636
+
637
+ V = np.array([[-V[1, 1], V[1, 0], V[1, 2]],
638
+ [-V[2, 1], V[2, 0], V[2, 2]],
639
+ [V[0, 1], -V[0, 0], -V[0, 2]]])
640
+
641
+ IMAX = np.nonzero(D == D.max())
642
+ IMIN = np.nonzero(D == D.min())
643
+ AE = (V[:, IMAX]+V[:, IMIN])/np.sqrt(2.0)
644
+ AN = (V[:, IMAX]-V[:, IMIN])/np.sqrt(2.0)
645
+ AER = np.sqrt(AE[0]**2+AE[1]**2+AE[2]**2)
646
+ ANR = np.sqrt(AN[0]**2+AN[1]**2+AN[2]**2)
647
+ AE = AE/AER
648
+ AN = AN/ANR
649
+ if AN[2] <= 0.:
650
+ AN1 = AN
651
+ AE1 = AE
652
+ else:
653
+ AN1 = -AN
654
+ AE1 = -AE
655
+ ft, fd, fl = TDL(AN1, AE1)
656
+ strike = 360 - ft
657
+ dip = fd
658
+ rake = 180 - fl
659
+ return strike, dip, rake
660
+
661
+
662
+ def TDL(AN, BN):
663
+ """
664
+ TDL
665
+
666
+ Parameters
667
+ ----------
668
+ AN : numpy array
669
+ array comprising XN, YN, ZN
670
+ BN : numpy array
671
+ array comprising XE, YE, ZE
672
+
673
+ Returns
674
+ -------
675
+ FT : float
676
+ relates to strike (360 - ft)
677
+ FD : float
678
+ dip
679
+ FL : float
680
+ relates to rake (180 - fl)
681
+ """
682
+ XN, YN, ZN = AN.flatten()
683
+ XE, YE, ZE = BN.flatten()
684
+ AAA = 1.0E-06
685
+ CON = 57.2957795
686
+ if abs(ZN) < AAA:
687
+ FD = 90.
688
+ AXN = abs(XN)
689
+ if AXN > 1.0:
690
+ AXN = 1.0
691
+ FT = np.arcsin(AXN)*CON
692
+ ST = -XN
693
+ CT = YN
694
+ if ST >= 0. and CT < 0:
695
+ FT = 180.-FT
696
+ if ST < 0. and CT <= 0:
697
+ FT = 180.+FT
698
+ if ST < 0. and CT > 0:
699
+ FT = 360.-FT
700
+ FL = np.arcsin(abs(ZE))*CON
701
+ SL = -ZE
702
+ if abs(XN) < AAA:
703
+ CL = XE/YN
704
+ else:
705
+ CL = -YE/XN
706
+ if SL >= 0. and CL < 0:
707
+ FL = 180.-FL
708
+ if SL < 0. and CL <= 0:
709
+ FL = FL-180.
710
+ if SL < 0. and CL > 0:
711
+ FL = -FL
712
+ else:
713
+ if -ZN > 1.0:
714
+ ZN = -1.0
715
+ FDH = np.arccos(-ZN)
716
+ FD = FDH*CON
717
+ SD = np.sin(FDH)
718
+ if SD == 0:
719
+ return
720
+ ST = -XN/SD
721
+ CT = YN/SD
722
+ SX = abs(ST)
723
+ if SX > 1.0:
724
+ SX = 1.0
725
+ FT = np.arcsin(SX)*CON
726
+ if ST >= 0. and CT < 0:
727
+ FT = 180.-FT
728
+ if ST < 0. and CT <= 0:
729
+ FT = 180.+FT
730
+ if ST < 0. and CT > 0:
731
+ FT = 360.-FT
732
+ SL = -ZE/SD
733
+ SX = np.abs(SL)
734
+ if SX > 1.0:
735
+ SX = 1.0
736
+ FL = np.arcsin(SX)*CON
737
+ if ST == 0:
738
+ CL = XE/CT
739
+ else:
740
+ xxx = YN*ZN*ZE/SD/SD+YE
741
+ CL = -SD*xxx/XN
742
+ if CT == 0:
743
+ CL = YE/ST
744
+ if SL >= 0. and CL < 0:
745
+ FL = 180.-FL
746
+ if SL < 0. and CL <= 0:
747
+ FL = FL-180.
748
+ if SL < 0. and CL > 0:
749
+ FL = -FL
750
+
751
+ return FT, FD, FL