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.
- pygmi-2.2.7/LICENSE.txt +623 -0
- pygmi-2.2.7/MANIFEST.in +7 -0
- pygmi-2.2.7/PKG-INFO +47 -0
- pygmi-2.2.7/README.md +55 -0
- pygmi-2.2.7/README.rst +20 -0
- pygmi-2.2.7/log.txt +242 -0
- pygmi-2.2.7/pygmi/__init__.py +22 -0
- pygmi-2.2.7/pygmi/clust/__init__.py +4 -0
- pygmi-2.2.7/pygmi/clust/crisp_clust.py +708 -0
- pygmi-2.2.7/pygmi/clust/datatypes.py +65 -0
- pygmi-2.2.7/pygmi/clust/fuzzy_clust.py +906 -0
- pygmi-2.2.7/pygmi/clust/graphs.py +421 -0
- pygmi-2.2.7/pygmi/clust/graphtool.py +667 -0
- pygmi-2.2.7/pygmi/clust/menu.py +139 -0
- pygmi-2.2.7/pygmi/clust/var_ratio.py +92 -0
- pygmi-2.2.7/pygmi/clust/xie_beni.py +93 -0
- pygmi-2.2.7/pygmi/helpdocs/linepointer.png +0 -0
- pygmi-2.2.7/pygmi/helpdocs/pygmi.main.html +31 -0
- pygmi-2.2.7/pygmi/helpdocs/pygmi.pfmod.ddisp.html +15 -0
- pygmi-2.2.7/pygmi/helpdocs/pygmi.pfmod.iodefs.exportkmz.html +13 -0
- pygmi-2.2.7/pygmi/helpdocs/pygmi.pfmod.iodefs.importpicture.html +16 -0
- pygmi-2.2.7/pygmi/helpdocs/pygmi.pfmod.layer.html +17 -0
- pygmi-2.2.7/pygmi/helpdocs/pygmi.pfmod.mext.html +44 -0
- pygmi-2.2.7/pygmi/helpdocs/pygmi.pfmod.misc.rangedcopy.html +16 -0
- pygmi-2.2.7/pygmi/helpdocs/pygmi.pfmod.param.html +37 -0
- pygmi-2.2.7/pygmi/helpdocs/pygmi.pfmod.prof.html +32 -0
- pygmi-2.2.7/pygmi/helpdocs/pygmi.pfmod.pview.html +26 -0
- pygmi-2.2.7/pygmi/helpdocs/pygmi.raster.cooper.gradients.html +14 -0
- pygmi-2.2.7/pygmi/helpdocs/pygmi.raster.cooper.tilt.html +14 -0
- pygmi-2.2.7/pygmi/helpdocs/pygmi.raster.cooper.visibility.html +14 -0
- pygmi-2.2.7/pygmi/helpdocs/pygmi.raster.dataprep.datagrid.html +13 -0
- pygmi-2.2.7/pygmi/helpdocs/pygmi.raster.dataprep.datamerge.html +11 -0
- pygmi-2.2.7/pygmi/helpdocs/pygmi.raster.dataprep.datareproj.html +11 -0
- pygmi-2.2.7/pygmi/helpdocs/pygmi.raster.dataprep.rtp.html +14 -0
- pygmi-2.2.7/pygmi/helpdocs/pygmi.raster.ginterp.html +31 -0
- pygmi-2.2.7/pygmi/helpdocs/pygmi.raster.igrf.html +20 -0
- pygmi-2.2.7/pygmi/helpdocs/pygmi.raster.normalisation.html +14 -0
- pygmi-2.2.7/pygmi/helpdocs/pygmi.raster.smooth.html +22 -0
- pygmi-2.2.7/pygmi/helpdocs/pygmi.raster.tiltdepth.html +20 -0
- pygmi-2.2.7/pygmi/images/Help.png +0 -0
- pygmi-2.2.7/pygmi/images/bringtofront.png +0 -0
- pygmi-2.2.7/pygmi/images/cgs2.emf +0 -0
- pygmi-2.2.7/pygmi/images/delete.png +0 -0
- pygmi-2.2.7/pygmi/images/linepointer.png +0 -0
- pygmi-2.2.7/pygmi/images/logo256.ico +0 -0
- pygmi-2.2.7/pygmi/images/logo256.png +0 -0
- pygmi-2.2.7/pygmi/images/pointer.png +0 -0
- pygmi-2.2.7/pygmi/images/pygmi.png +0 -0
- pygmi-2.2.7/pygmi/images/sendtoback.png +0 -0
- pygmi-2.2.7/pygmi/main.py +1037 -0
- pygmi-2.2.7/pygmi/menu_default.py +327 -0
- pygmi-2.2.7/pygmi/misc.py +147 -0
- pygmi-2.2.7/pygmi/pfmod/__init__.py +6 -0
- pygmi-2.2.7/pygmi/pfmod/cubes.py +1488 -0
- pygmi-2.2.7/pygmi/pfmod/datatypes.py +292 -0
- pygmi-2.2.7/pygmi/pfmod/grvmag3d.py +1265 -0
- pygmi-2.2.7/pygmi/pfmod/iodefs.py +1001 -0
- pygmi-2.2.7/pygmi/pfmod/menu.py +107 -0
- pygmi-2.2.7/pygmi/pfmod/misc.py +301 -0
- pygmi-2.2.7/pygmi/pfmod/pfmod.py +248 -0
- pygmi-2.2.7/pygmi/pfmod/tab_ddisp.py +425 -0
- pygmi-2.2.7/pygmi/pfmod/tab_layer.py +490 -0
- pygmi-2.2.7/pygmi/pfmod/tab_mext.py +544 -0
- pygmi-2.2.7/pygmi/pfmod/tab_param.py +548 -0
- pygmi-2.2.7/pygmi/pfmod/tab_prof.py +946 -0
- pygmi-2.2.7/pygmi/pfmod/tab_pview.py +740 -0
- pygmi-2.2.7/pygmi/raster/IGRF11.COF +1635 -0
- pygmi-2.2.7/pygmi/raster/__init__.py +14 -0
- pygmi-2.2.7/pygmi/raster/cooper.py +718 -0
- pygmi-2.2.7/pygmi/raster/dataprep.py +1640 -0
- pygmi-2.2.7/pygmi/raster/datatypes.py +123 -0
- pygmi-2.2.7/pygmi/raster/equation_editor.py +256 -0
- pygmi-2.2.7/pygmi/raster/ginterp.py +1901 -0
- pygmi-2.2.7/pygmi/raster/graphs.py +531 -0
- pygmi-2.2.7/pygmi/raster/igrf.py +860 -0
- pygmi-2.2.7/pygmi/raster/iodefs.py +813 -0
- pygmi-2.2.7/pygmi/raster/menu.py +307 -0
- pygmi-2.2.7/pygmi/raster/normalisation.py +187 -0
- pygmi-2.2.7/pygmi/raster/show_table.py +245 -0
- pygmi-2.2.7/pygmi/raster/smooth.py +406 -0
- pygmi-2.2.7/pygmi/raster/tiltdepth.py +590 -0
- pygmi-2.2.7/pygmi/seis/__init__.py +0 -0
- pygmi-2.2.7/pygmi/seis/beachball.py +751 -0
- pygmi-2.2.7/pygmi/seis/datatypes.py +605 -0
- pygmi-2.2.7/pygmi/seis/del_rec.py +410 -0
- pygmi-2.2.7/pygmi/seis/iodefs.py +1261 -0
- pygmi-2.2.7/pygmi/seis/menu.py +136 -0
- pygmi-2.2.7/pygmi/seis/scan_imp.py +795 -0
- pygmi-2.2.7/pygmi/test/__init__.py +6 -0
- pygmi-2.2.7/pygmi/test/pfmod.py +212 -0
- pygmi-2.2.7/pygmi/test/tests.py +39 -0
- pygmi-2.2.7/pygmi/vector/__init__.py +7 -0
- pygmi-2.2.7/pygmi/vector/datatypes.py +74 -0
- pygmi-2.2.7/pygmi/vector/graphs.py +443 -0
- pygmi-2.2.7/pygmi/vector/iodefs.py +345 -0
- pygmi-2.2.7/pygmi/vector/menu.py +127 -0
- pygmi-2.2.7/pygmi.egg-info/PKG-INFO +47 -0
- pygmi-2.2.7/pygmi.egg-info/SOURCES.txt +105 -0
- pygmi-2.2.7/pygmi.egg-info/dependency_links.txt +1 -0
- pygmi-2.2.7/pygmi.egg-info/entry_points.txt +3 -0
- pygmi-2.2.7/pygmi.egg-info/not-zip-safe +1 -0
- pygmi-2.2.7/pygmi.egg-info/requires.txt +7 -0
- pygmi-2.2.7/pygmi.egg-info/top_level.txt +1 -0
- pygmi-2.2.7/quickstart.py +35 -0
- pygmi-2.2.7/setup.cfg +8 -0
- pygmi-2.2.7/setup.py +80 -0
|
@@ -0,0 +1,718 @@
|
|
|
1
|
+
# -----------------------------------------------------------------------------
|
|
2
|
+
# Name: cooper.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
|
+
""" This is a collection of routines by Gordon Cooper
|
|
26
|
+
|
|
27
|
+
| School of Geosciences, University of the Witwatersrand
|
|
28
|
+
| Johannesburg, South Africa
|
|
29
|
+
| cooperg@geosciences.wits.ac.za
|
|
30
|
+
| http://www.wits.ac.za/science/geophysics/gc.htm
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
from PyQt4 import QtGui, QtCore
|
|
34
|
+
import numpy as np
|
|
35
|
+
import scipy.signal as si
|
|
36
|
+
import copy
|
|
37
|
+
import pygmi.menu_default as menu_default
|
|
38
|
+
from numba import jit
|
|
39
|
+
|
|
40
|
+
# data = np.array([ [1, 2, 3, 4, 5, 6, 7, 8, 9],
|
|
41
|
+
# [1, 2, 3, 4, 5, 7, 6, 8, 9],
|
|
42
|
+
# [1, 2, 3, 4, 5, 7, 6, 8, 9],
|
|
43
|
+
# [4, 3, 2, 1, 0, 1, 2, 9, 0],
|
|
44
|
+
# [4, 3, 1, 1, 0, 1, 2, 3, 4],
|
|
45
|
+
# [4, 3, 1, 1, 0, 1, 1, 1, 2],
|
|
46
|
+
# [4, 3, 1, 1, 0, 1, 2, 3, 4],
|
|
47
|
+
# [4, 3, 1, 1, 0, 1, 1, 1, 2],
|
|
48
|
+
# [4, 3, 1, 1, 0, 1, 1, 2, 2]])
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class Gradients(QtGui.QDialog):
|
|
52
|
+
"""
|
|
53
|
+
Class used to gather information via a GUI, for function gradients
|
|
54
|
+
|
|
55
|
+
Attributes
|
|
56
|
+
----------
|
|
57
|
+
parent : parent
|
|
58
|
+
indata : dictionary
|
|
59
|
+
PyGMI input data in a dictionary
|
|
60
|
+
outdata :
|
|
61
|
+
PyGMI input data in a dictionary
|
|
62
|
+
azi : float
|
|
63
|
+
Azimuth/filter direction (degrees)
|
|
64
|
+
elev : float
|
|
65
|
+
Elevation (for sunshading, degrees from horizontal)
|
|
66
|
+
order : int
|
|
67
|
+
Order of DR filter - see paper. Try 1 first.
|
|
68
|
+
"""
|
|
69
|
+
def __init__(self, parent):
|
|
70
|
+
QtGui.QDialog.__init__(self, parent)
|
|
71
|
+
|
|
72
|
+
self.parent = parent
|
|
73
|
+
self.indata = {}
|
|
74
|
+
self.outdata = {}
|
|
75
|
+
self.azi = 45.
|
|
76
|
+
self.elev = 45.
|
|
77
|
+
self.order = 1
|
|
78
|
+
self.pbar = self.parent.pbar
|
|
79
|
+
|
|
80
|
+
self.sb_order = QtGui.QSpinBox()
|
|
81
|
+
self.sb_azi = QtGui.QSpinBox()
|
|
82
|
+
|
|
83
|
+
self.setupui()
|
|
84
|
+
|
|
85
|
+
self.sb_azi.setValue(self.azi)
|
|
86
|
+
self.sb_order.setValue(self.order)
|
|
87
|
+
|
|
88
|
+
def setupui(self):
|
|
89
|
+
""" Setup UI """
|
|
90
|
+
# self.resize(289, 166)
|
|
91
|
+
gridlayout = QtGui.QGridLayout(self)
|
|
92
|
+
label_az = QtGui.QLabel()
|
|
93
|
+
label_or = QtGui.QLabel()
|
|
94
|
+
buttonbox = QtGui.QDialogButtonBox()
|
|
95
|
+
helpdocs = menu_default.HelpButton('pygmi.raster.cooper.gradients')
|
|
96
|
+
|
|
97
|
+
self.sb_order.setMinimum(1)
|
|
98
|
+
self.sb_azi.setPrefix("")
|
|
99
|
+
self.sb_azi.setMinimum(-360)
|
|
100
|
+
self.sb_azi.setMaximum(360)
|
|
101
|
+
buttonbox.setOrientation(QtCore.Qt.Horizontal)
|
|
102
|
+
buttonbox.setStandardButtons(buttonbox.Cancel | buttonbox.Ok)
|
|
103
|
+
|
|
104
|
+
self.setWindowTitle("Gradient Calculation")
|
|
105
|
+
label_az.setText("Azimuth")
|
|
106
|
+
label_or.setText("Order")
|
|
107
|
+
|
|
108
|
+
gridlayout.addWidget(label_az, 0, 0, 1, 1)
|
|
109
|
+
gridlayout.addWidget(self.sb_azi, 0, 1, 1, 1)
|
|
110
|
+
gridlayout.addWidget(label_or, 3, 0, 1, 1)
|
|
111
|
+
gridlayout.addWidget(self.sb_order, 3, 1, 1, 1)
|
|
112
|
+
gridlayout.addWidget(helpdocs, 4, 0, 1, 1)
|
|
113
|
+
gridlayout.addWidget(buttonbox, 4, 1, 1, 1)
|
|
114
|
+
|
|
115
|
+
buttonbox.accepted.connect(self.accept)
|
|
116
|
+
buttonbox.rejected.connect(self.reject)
|
|
117
|
+
|
|
118
|
+
def settings(self):
|
|
119
|
+
""" Settings """
|
|
120
|
+
temp = self.exec_()
|
|
121
|
+
if temp == 0:
|
|
122
|
+
return
|
|
123
|
+
|
|
124
|
+
self.azi = self.sb_azi.value()
|
|
125
|
+
self.order = self.sb_order.value()
|
|
126
|
+
|
|
127
|
+
data = copy.deepcopy(self.indata['Raster'])
|
|
128
|
+
|
|
129
|
+
for i in self.pbar.iter(range(len(data))):
|
|
130
|
+
data[i].data = gradients(data[i].data, self.azi, 0., self.order)
|
|
131
|
+
|
|
132
|
+
self.outdata['Raster'] = data
|
|
133
|
+
|
|
134
|
+
return True
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def gradients(data, azi, elev, order):
|
|
138
|
+
"""
|
|
139
|
+
Compute different gradients of image data
|
|
140
|
+
|
|
141
|
+
Compute different horizontal gradients of image data. Based on code by
|
|
142
|
+
Gordon Cooper.
|
|
143
|
+
|
|
144
|
+
Parameters
|
|
145
|
+
----------
|
|
146
|
+
data : numpy array
|
|
147
|
+
input numy data array
|
|
148
|
+
azi : float
|
|
149
|
+
Filter direction (degrees)
|
|
150
|
+
elev : float
|
|
151
|
+
Elevation (for sunshading, degrees from horizontal)
|
|
152
|
+
order : int
|
|
153
|
+
Order of DR filter - see paper. Try 1 first.
|
|
154
|
+
|
|
155
|
+
Returns
|
|
156
|
+
-------
|
|
157
|
+
dr : float
|
|
158
|
+
returns derivative ratio
|
|
159
|
+
"""
|
|
160
|
+
# Directional derivative
|
|
161
|
+
|
|
162
|
+
azi = azi*np.pi/180
|
|
163
|
+
elev = elev*np.pi/180
|
|
164
|
+
dx, dy = np.gradient(data)
|
|
165
|
+
dt1 = -dy*np.sin(azi)-dx*np.cos(azi)
|
|
166
|
+
|
|
167
|
+
# Sunshading
|
|
168
|
+
|
|
169
|
+
# cAzi = np.cos(azi)
|
|
170
|
+
# sAzi = np.sin(azi)
|
|
171
|
+
# tElev = np.tan(elev)
|
|
172
|
+
# top = (1.0-dx*cAzi*tElev-dy*sAzi*tElev)
|
|
173
|
+
# bottom = np.sqrt(1.0+dx*dx+dy*dy)+np.sqrt(1.0+tElev*tElev)
|
|
174
|
+
# sun = top/bottom
|
|
175
|
+
|
|
176
|
+
# Derivative ratio
|
|
177
|
+
|
|
178
|
+
dt2 = -dy*np.sin(azi+np.pi/2)-dx*np.cos(azi+np.pi/2)
|
|
179
|
+
dr = np.arctan2(dt1, abs(dt2)**order)
|
|
180
|
+
|
|
181
|
+
return dr
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
class Visibility2d(QtGui.QDialog):
|
|
185
|
+
"""
|
|
186
|
+
Class used to gather information via a GUI, for function visibility2d
|
|
187
|
+
|
|
188
|
+
Attributes
|
|
189
|
+
----------
|
|
190
|
+
parent : parent
|
|
191
|
+
indata : dictionary
|
|
192
|
+
PyGMI input data in a dictionary
|
|
193
|
+
outdata :
|
|
194
|
+
PyGMI input data in a dictionary
|
|
195
|
+
wsize : int
|
|
196
|
+
window size, must be odd
|
|
197
|
+
dh : float
|
|
198
|
+
height of observer above surface
|
|
199
|
+
"""
|
|
200
|
+
def __init__(self, parent):
|
|
201
|
+
QtGui.QDialog.__init__(self, parent)
|
|
202
|
+
|
|
203
|
+
self.parent = parent
|
|
204
|
+
self.indata = {}
|
|
205
|
+
self.outdata = {}
|
|
206
|
+
self.wsize = 11
|
|
207
|
+
self.dh = 10
|
|
208
|
+
self.pbar = self.parent.pbar
|
|
209
|
+
|
|
210
|
+
self.sb_dh = QtGui.QSpinBox()
|
|
211
|
+
self.sb_wsize = QtGui.QSpinBox()
|
|
212
|
+
|
|
213
|
+
self.setupui()
|
|
214
|
+
|
|
215
|
+
self.sb_wsize.setValue(self.wsize)
|
|
216
|
+
self.sb_dh.setValue(self.dh)
|
|
217
|
+
|
|
218
|
+
def setupui(self):
|
|
219
|
+
""" Setup UI """
|
|
220
|
+
gridlayout = QtGui.QGridLayout(self)
|
|
221
|
+
buttonbox = QtGui.QDialogButtonBox()
|
|
222
|
+
helpdocs = menu_default.HelpButton('pygmi.raster.cooper.visibility')
|
|
223
|
+
label = QtGui.QLabel()
|
|
224
|
+
label_2 = QtGui.QLabel()
|
|
225
|
+
|
|
226
|
+
self.sb_dh.setMinimum(1)
|
|
227
|
+
self.sb_dh.setMaximum(10000)
|
|
228
|
+
self.sb_wsize.setPrefix("")
|
|
229
|
+
self.sb_wsize.setMinimum(3)
|
|
230
|
+
self.sb_wsize.setMaximum(100000)
|
|
231
|
+
self.sb_wsize.setSingleStep(2)
|
|
232
|
+
buttonbox.setOrientation(QtCore.Qt.Horizontal)
|
|
233
|
+
buttonbox.setStandardButtons(buttonbox.Cancel | buttonbox.Ok)
|
|
234
|
+
|
|
235
|
+
self.setWindowTitle("Visibility")
|
|
236
|
+
label.setText("Viewing Height (% std dev)")
|
|
237
|
+
label_2.setText("Window Size (Odd)")
|
|
238
|
+
|
|
239
|
+
gridlayout.addWidget(label_2, 0, 0, 1, 1)
|
|
240
|
+
gridlayout.addWidget(self.sb_wsize, 0, 1, 1, 1)
|
|
241
|
+
gridlayout.addWidget(label, 1, 0, 1, 1)
|
|
242
|
+
gridlayout.addWidget(self.sb_dh, 1, 1, 1, 1)
|
|
243
|
+
gridlayout.addWidget(helpdocs, 2, 0, 1, 1)
|
|
244
|
+
gridlayout.addWidget(buttonbox, 2, 1, 1, 1)
|
|
245
|
+
|
|
246
|
+
buttonbox.accepted.connect(self.accept)
|
|
247
|
+
buttonbox.rejected.connect(self.reject)
|
|
248
|
+
|
|
249
|
+
def settings(self):
|
|
250
|
+
""" Settings """
|
|
251
|
+
temp = self.exec_()
|
|
252
|
+
if temp == 0:
|
|
253
|
+
return
|
|
254
|
+
|
|
255
|
+
self.wsize = self.sb_wsize.value()
|
|
256
|
+
self.dh = self.sb_dh.value()
|
|
257
|
+
|
|
258
|
+
data = copy.deepcopy(self.indata['Raster'])
|
|
259
|
+
data2 = []
|
|
260
|
+
|
|
261
|
+
for i in range(len(data)):
|
|
262
|
+
self.parent.showprocesslog(data[i].dataid+':')
|
|
263
|
+
|
|
264
|
+
vtot, vstd, vsum = visibility2d(data[i].data, self.wsize,
|
|
265
|
+
self.dh*data[i].data.std()/100.,
|
|
266
|
+
self.pbar.iter)
|
|
267
|
+
# data[i].data = vtot
|
|
268
|
+
data2.append(copy.deepcopy(data[i]))
|
|
269
|
+
data2.append(copy.deepcopy(data[i]))
|
|
270
|
+
data2.append(copy.deepcopy(data[i]))
|
|
271
|
+
data2[-3].data = vtot
|
|
272
|
+
data2[-2].data = vstd
|
|
273
|
+
data2[-1].data = vsum
|
|
274
|
+
data2[-3].dataid += ' Total Visibility'
|
|
275
|
+
data2[-2].dataid += ' Visibility Variation'
|
|
276
|
+
data2[-1].dataid += ' Visibility Vector Resultant'
|
|
277
|
+
|
|
278
|
+
self.outdata['Raster'] = data2
|
|
279
|
+
self.parent.showprocesslog('Finished!')
|
|
280
|
+
|
|
281
|
+
return True
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
def visibility2d(data, wsize, dh, piter=iter):
|
|
285
|
+
"""
|
|
286
|
+
Compute visibility as a textural measure
|
|
287
|
+
|
|
288
|
+
Compute vertical derivatives by calculating the visibility at different
|
|
289
|
+
heights above the surface (see paper)
|
|
290
|
+
|
|
291
|
+
Parameters
|
|
292
|
+
----------
|
|
293
|
+
data : numpy array
|
|
294
|
+
input dataset - numpy MxN array
|
|
295
|
+
wsize : int
|
|
296
|
+
window size, must be odd
|
|
297
|
+
dh : float
|
|
298
|
+
height of observer above surface
|
|
299
|
+
|
|
300
|
+
Returns
|
|
301
|
+
-------
|
|
302
|
+
vtot : numpy array
|
|
303
|
+
vstd : numpy array
|
|
304
|
+
vsum : numpy array
|
|
305
|
+
"""
|
|
306
|
+
|
|
307
|
+
nr, nc = np.shape(data)
|
|
308
|
+
wsize = abs(np.real(wsize))
|
|
309
|
+
w2 = int(np.floor(wsize/2))
|
|
310
|
+
vn = np.zeros([nr, nc])
|
|
311
|
+
vs = np.zeros([nr, nc])
|
|
312
|
+
ve = np.zeros([nr, nc])
|
|
313
|
+
vw = np.zeros([nr, nc])
|
|
314
|
+
vd1 = np.zeros([nr, nc])
|
|
315
|
+
vd2 = np.zeros([nr, nc])
|
|
316
|
+
vd3 = np.zeros([nr, nc])
|
|
317
|
+
vd4 = np.zeros([nr, nc])
|
|
318
|
+
vstd = np.zeros([nr, nc])
|
|
319
|
+
mask = data.mask
|
|
320
|
+
mean = data.mean()
|
|
321
|
+
data = data.data
|
|
322
|
+
data[mask] = mean
|
|
323
|
+
|
|
324
|
+
# self.parent.showprocesslog('NS')
|
|
325
|
+
for j in piter(range(nc)): # Columns
|
|
326
|
+
for i in range(w2, nr-w2):
|
|
327
|
+
dtmp = data[i-w2:i+w2+1, j]
|
|
328
|
+
vn[i, j] = __visible1(dtmp, wsize, w2+1, dh)
|
|
329
|
+
vs[i, j] = __visible2(dtmp, wsize, w2+1, dh)
|
|
330
|
+
|
|
331
|
+
# self.parent.showprocesslog('EW')
|
|
332
|
+
for j in piter(range(w2, nc-w2)): # Rows
|
|
333
|
+
for i in range(nr):
|
|
334
|
+
dtmp = data[i, j-w2:j+w2+1]
|
|
335
|
+
ve[i, j] = __visible1(dtmp, wsize, w2+1, dh)
|
|
336
|
+
vw[i, j] = __visible2(dtmp, wsize, w2+1, dh)
|
|
337
|
+
|
|
338
|
+
# self.parent.showprocesslog('Diag')
|
|
339
|
+
for j in piter(range(w2, nc-w2)):
|
|
340
|
+
for i in range(w2, nr-w2):
|
|
341
|
+
dtmp = np.zeros(wsize)
|
|
342
|
+
for k in range(wsize):
|
|
343
|
+
dtmp[k] = data[i-w2+k, j-w2+k]
|
|
344
|
+
vd1[i, j] = __visible1(dtmp, wsize, w2+1, dh)
|
|
345
|
+
vd2[i, j] = __visible2(dtmp, wsize, w2+1, dh)
|
|
346
|
+
dtmp = np.zeros(wsize)
|
|
347
|
+
for k in range(wsize):
|
|
348
|
+
dtmp[k] = data[i+w2-k, j-w2+k]
|
|
349
|
+
vd3[i, j] = __visible1(dtmp, wsize, w2+1, dh)
|
|
350
|
+
vd4[i, j] = __visible2(dtmp, wsize, w2+1, dh)
|
|
351
|
+
|
|
352
|
+
# self.parent.showprocesslog('Computing std of visibility')
|
|
353
|
+
vtot = vn+vs+ve+vw+vd1+vd2+vd3+vd4
|
|
354
|
+
vtot = vtot[w2:nr-w2, w2:nc-w2]
|
|
355
|
+
|
|
356
|
+
for j in piter(range(nc)):
|
|
357
|
+
for i in range(nr):
|
|
358
|
+
vstd[i, j] = np.std([vn[i, j], vs[i, j], ve[i, j], vw[i, j],
|
|
359
|
+
vd1[i, j], vd2[i, j], vd3[i, j],
|
|
360
|
+
vd4[i, j]], ddof=1)
|
|
361
|
+
|
|
362
|
+
vstd = vstd[w2:nr-w2, w2:nc-w2]
|
|
363
|
+
|
|
364
|
+
dtr = np.pi/180
|
|
365
|
+
c45 = np.cos(45*dtr)
|
|
366
|
+
s45 = np.sin(45*dtr)
|
|
367
|
+
vsumx = ve-vw+vd1*c45-vd2*c45+vd3*c45-vd4*c45
|
|
368
|
+
vsumy = vn-vs+vd1*s45-vd2*s45-vd3*s45+vd4*s45
|
|
369
|
+
vsum = np.sqrt(vsumx*vsumx+vsumy*vsumy)
|
|
370
|
+
vsum = vsum[w2:nr-w2, w2:nc-w2]
|
|
371
|
+
|
|
372
|
+
vtot = np.ma.array(vtot)
|
|
373
|
+
vstd = np.ma.array(vstd)
|
|
374
|
+
vsum = np.ma.array(vsum)
|
|
375
|
+
vtot.mask = mask[w2:-w2, w2:-w2]
|
|
376
|
+
vstd.mask = mask[w2:-w2, w2:-w2]
|
|
377
|
+
vsum.mask = mask[w2:-w2, w2:-w2]
|
|
378
|
+
|
|
379
|
+
return vtot, vstd, vsum
|
|
380
|
+
|
|
381
|
+
|
|
382
|
+
def __visible1(dat, nr, cp, dh):
|
|
383
|
+
""" Visible 1 """
|
|
384
|
+
num = 1
|
|
385
|
+
# d = d[d.nonzero()].tolist()
|
|
386
|
+
|
|
387
|
+
if cp < nr-1 and len(dat) > 0:
|
|
388
|
+
num = 2
|
|
389
|
+
cpn = cp-1
|
|
390
|
+
thetamax = float(dat[cpn+1]-dat[cpn]-dh)
|
|
391
|
+
for i in range(cpn+2, nr):
|
|
392
|
+
theta = ((dat[i]-dat[cpn]-dh)/float(i-cpn))
|
|
393
|
+
if theta >= thetamax:
|
|
394
|
+
num = num + 1
|
|
395
|
+
thetamax = theta
|
|
396
|
+
|
|
397
|
+
return num
|
|
398
|
+
|
|
399
|
+
|
|
400
|
+
def __visible2(dat, nr, cp, dh):
|
|
401
|
+
""" Visible 2 """
|
|
402
|
+
num = 0
|
|
403
|
+
# d = d[d.nonzero()].tolist()
|
|
404
|
+
|
|
405
|
+
if cp > 2 and len(dat) > 0:
|
|
406
|
+
num = 1
|
|
407
|
+
cpn = cp-1
|
|
408
|
+
thetamax = (dat[cpn-1]-dat[cpn]-dh)
|
|
409
|
+
for i in range(cpn-2, -1, -1):
|
|
410
|
+
theta = ((dat[i]-dat[cpn]-dh)/(cpn-i))
|
|
411
|
+
if theta >= thetamax:
|
|
412
|
+
num = num + 1
|
|
413
|
+
thetamax = theta
|
|
414
|
+
return num
|
|
415
|
+
|
|
416
|
+
|
|
417
|
+
class Tilt1(QtGui.QDialog):
|
|
418
|
+
"""
|
|
419
|
+
Class used to gather information via a GUI, for function tilt1
|
|
420
|
+
|
|
421
|
+
Attributes
|
|
422
|
+
----------
|
|
423
|
+
parent : parent
|
|
424
|
+
indata : dictionary
|
|
425
|
+
PyGMI input data in a dictionary
|
|
426
|
+
outdata :
|
|
427
|
+
PyGMI input data in a dictionary
|
|
428
|
+
azi : float
|
|
429
|
+
directional filter azimuth in degrees from East
|
|
430
|
+
smooth : int
|
|
431
|
+
size of smoothing matrix to use - must be odd input 0 for no smoothing
|
|
432
|
+
"""
|
|
433
|
+
def __init__(self, parent):
|
|
434
|
+
QtGui.QDialog.__init__(self, parent)
|
|
435
|
+
|
|
436
|
+
self.parent = parent
|
|
437
|
+
self.indata = {}
|
|
438
|
+
self.outdata = {}
|
|
439
|
+
self.azi = 75
|
|
440
|
+
self.smooth = 0
|
|
441
|
+
self.pbar = self.parent.pbar
|
|
442
|
+
|
|
443
|
+
self.sb_azi = QtGui.QSpinBox()
|
|
444
|
+
self.sb_s = QtGui.QSpinBox()
|
|
445
|
+
|
|
446
|
+
self.setupui()
|
|
447
|
+
|
|
448
|
+
self.sb_s.setValue(self.smooth)
|
|
449
|
+
self.sb_azi.setValue(self.azi)
|
|
450
|
+
|
|
451
|
+
def setupui(self):
|
|
452
|
+
""" Setup UI """
|
|
453
|
+
gridlayout = QtGui.QGridLayout(self)
|
|
454
|
+
buttonbox = QtGui.QDialogButtonBox()
|
|
455
|
+
helpdocs = menu_default.HelpButton('pygmi.raster.cooper.tilt')
|
|
456
|
+
label = QtGui.QLabel()
|
|
457
|
+
label_2 = QtGui.QLabel()
|
|
458
|
+
|
|
459
|
+
buttonbox.setOrientation(QtCore.Qt.Horizontal)
|
|
460
|
+
buttonbox.setStandardButtons(buttonbox.Cancel | buttonbox.Ok)
|
|
461
|
+
self.sb_azi.setMinimum(-360)
|
|
462
|
+
self.sb_azi.setMaximum(360)
|
|
463
|
+
self.sb_azi.setProperty("value", 0)
|
|
464
|
+
self.sb_s.setPrefix("")
|
|
465
|
+
self.sb_s.setMinimum(0)
|
|
466
|
+
self.sb_s.setMaximum(100000)
|
|
467
|
+
self.sb_s.setSingleStep(1)
|
|
468
|
+
|
|
469
|
+
self.setWindowTitle("Tilt Angle")
|
|
470
|
+
label.setText("Azimuth (degrees from east)")
|
|
471
|
+
label_2.setText("Smoothing Matrix Size (Odd, 0 for None)")
|
|
472
|
+
|
|
473
|
+
gridlayout.addWidget(label_2, 0, 0, 1, 1)
|
|
474
|
+
gridlayout.addWidget(self.sb_s, 0, 1, 1, 1)
|
|
475
|
+
gridlayout.addWidget(label, 1, 0, 1, 1)
|
|
476
|
+
gridlayout.addWidget(self.sb_azi, 1, 1, 1, 1)
|
|
477
|
+
gridlayout.addWidget(helpdocs, 2, 0, 1, 1)
|
|
478
|
+
gridlayout.addWidget(buttonbox, 2, 1, 1, 1)
|
|
479
|
+
|
|
480
|
+
buttonbox.accepted.connect(self.accept)
|
|
481
|
+
buttonbox.rejected.connect(self.reject)
|
|
482
|
+
|
|
483
|
+
def settings(self):
|
|
484
|
+
""" Settings """
|
|
485
|
+
temp = self.exec_()
|
|
486
|
+
if temp == 0:
|
|
487
|
+
return
|
|
488
|
+
|
|
489
|
+
self.smooth = self.sb_s.value()
|
|
490
|
+
self.azi = self.sb_azi.value()
|
|
491
|
+
|
|
492
|
+
data = copy.deepcopy(self.indata['Raster'])
|
|
493
|
+
data2 = []
|
|
494
|
+
|
|
495
|
+
for i in self.pbar.iter(range(len(data))):
|
|
496
|
+
t1, th, t2, ta, tdx = tilt1(data[i].data, self.azi, self.smooth)
|
|
497
|
+
data2.append(copy.deepcopy(data[i]))
|
|
498
|
+
data2.append(copy.deepcopy(data[i]))
|
|
499
|
+
data2.append(copy.deepcopy(data[i]))
|
|
500
|
+
data2.append(copy.deepcopy(data[i]))
|
|
501
|
+
data2.append(copy.deepcopy(data[i]))
|
|
502
|
+
data2[-5].data = t1
|
|
503
|
+
data2[-4].data = th
|
|
504
|
+
data2[-3].data = t2
|
|
505
|
+
data2[-2].data = ta
|
|
506
|
+
data2[-1].data = tdx
|
|
507
|
+
data2[-5].dataid += ' Standard Tilt Angle'
|
|
508
|
+
data2[-4].dataid += ' Hyperbolic Tilt Angle'
|
|
509
|
+
data2[-3].dataid += ' 2nd Order Tilt Angle'
|
|
510
|
+
data2[-2].dataid += ' Tilt Based Directional Derivative'
|
|
511
|
+
data2[-1].dataid += ' Total Derivative'
|
|
512
|
+
|
|
513
|
+
for i in data2:
|
|
514
|
+
i.data.data[i.data.mask] = i.nullvalue
|
|
515
|
+
|
|
516
|
+
self.outdata['Raster'] = data2
|
|
517
|
+
return True
|
|
518
|
+
|
|
519
|
+
|
|
520
|
+
def tilt1(data, azi, s):
|
|
521
|
+
"""
|
|
522
|
+
Tilt angle calculations
|
|
523
|
+
|
|
524
|
+
Parameters
|
|
525
|
+
----------
|
|
526
|
+
data : numpy array
|
|
527
|
+
matrix of double to be filtered
|
|
528
|
+
azi : float
|
|
529
|
+
directional filter azimuth in degrees from East
|
|
530
|
+
s : int
|
|
531
|
+
size of smoothing matrix to use - must be odd input 0 for no smoothing
|
|
532
|
+
|
|
533
|
+
Returns
|
|
534
|
+
-------
|
|
535
|
+
t1 : numpy masked array
|
|
536
|
+
Standard tilt angle
|
|
537
|
+
th : numpy masked array
|
|
538
|
+
Hyperbolic tilt angle
|
|
539
|
+
t2 : numpy masked array
|
|
540
|
+
2nd order tilt angle
|
|
541
|
+
ta : numpy masked array
|
|
542
|
+
Tilt Based Directional Derivative
|
|
543
|
+
tdx : numpy masked array
|
|
544
|
+
Total Derivative
|
|
545
|
+
"""
|
|
546
|
+
|
|
547
|
+
dmin = data.min()
|
|
548
|
+
dmax = data.max()
|
|
549
|
+
dm = 0.5*(dmin+dmax)
|
|
550
|
+
data.data[data.mask] = dm
|
|
551
|
+
data[np.isnan(data)] = dm
|
|
552
|
+
data[np.isinf(data)] = dm
|
|
553
|
+
# import pdb
|
|
554
|
+
# pdb.set_trace()
|
|
555
|
+
if s > 0:
|
|
556
|
+
se = np.ones((s, s))/(s*s)
|
|
557
|
+
data2 = si.convolve2d(data, se, 'valid') # smooth
|
|
558
|
+
mask = si.convolve2d(data.mask, se, 'valid')
|
|
559
|
+
data = np.ma.array(data2, mask=mask)
|
|
560
|
+
|
|
561
|
+
nr, nc = data.shape
|
|
562
|
+
dtr = np.pi/180.0
|
|
563
|
+
azi = azi*dtr
|
|
564
|
+
# thresh = thresh*dtr
|
|
565
|
+
|
|
566
|
+
dy, dx = np.gradient(data)
|
|
567
|
+
dxtot = np.sqrt(dx*dx+dy*dy)
|
|
568
|
+
nmax = np.max([nr, nc])
|
|
569
|
+
npts = int(2**__nextpow2(nmax))
|
|
570
|
+
dz = vertical(data, npts, 1)
|
|
571
|
+
t1 = np.ma.arctan(dz/dxtot)
|
|
572
|
+
th = np.real(np.arctanh(np.nan_to_num(dz/dxtot)+(0+0j)))
|
|
573
|
+
tdx = np.real(np.ma.arctan(dxtot/abs(dz)))
|
|
574
|
+
|
|
575
|
+
dx1 = dx*np.cos(azi)+dy*np.sin(azi) # Standard directional derivative
|
|
576
|
+
dx2 = dx*np.cos(azi+np.pi/2)+dy*np.sin(azi+np.pi/2)
|
|
577
|
+
dxz = np.ma.sqrt(dx2*dx2+dz*dz)
|
|
578
|
+
ta = np.ma.arctan(dx1/dxz) # Tilt directional derivative
|
|
579
|
+
|
|
580
|
+
# 2nd order Tilt angle
|
|
581
|
+
|
|
582
|
+
ts = t1
|
|
583
|
+
if s < 3:
|
|
584
|
+
s = 3
|
|
585
|
+
se = np.ones([s, s])/(s*s)
|
|
586
|
+
# s2 = np.floor(s/2)
|
|
587
|
+
ts = si.convolve2d(t1, se, 'same')
|
|
588
|
+
[dxs, dys] = np.gradient(ts)
|
|
589
|
+
dzs = vertical(ts, npts, 1)
|
|
590
|
+
dxtots = np.ma.sqrt(dxs*dxs+dys*dys)
|
|
591
|
+
t2 = np.ma.arctan(dzs/dxtots)
|
|
592
|
+
|
|
593
|
+
# Standard tilt angle, hyperbolic tilt angle, 2nd order tilt angle,
|
|
594
|
+
# Tilt Based Directional Derivative, Total Derivative
|
|
595
|
+
t1 = np.ma.array(t1)
|
|
596
|
+
th = np.ma.array(th)
|
|
597
|
+
th.mask = t1.mask
|
|
598
|
+
t2 = np.ma.array(t2)
|
|
599
|
+
t2.mask = t1.mask
|
|
600
|
+
ta = np.ma.array(ta)
|
|
601
|
+
tdx = np.ma.array(tdx)
|
|
602
|
+
|
|
603
|
+
return t1, th, t2, ta, tdx
|
|
604
|
+
|
|
605
|
+
|
|
606
|
+
def __nextpow2(n):
|
|
607
|
+
""" nextpow2 """
|
|
608
|
+
m_i = np.ceil(np.log2(n))
|
|
609
|
+
return m_i
|
|
610
|
+
|
|
611
|
+
|
|
612
|
+
@jit
|
|
613
|
+
def vertical(data, npts=None, xint=1):
|
|
614
|
+
""" Vertical """
|
|
615
|
+
|
|
616
|
+
nr, nc = data.shape
|
|
617
|
+
|
|
618
|
+
if npts is None:
|
|
619
|
+
nmax = np.max([nr, nc])
|
|
620
|
+
npts = int(2**__nextpow2(nmax))
|
|
621
|
+
|
|
622
|
+
cdiff = int(np.floor((npts-nc)/2))
|
|
623
|
+
rdiff = int(np.floor((npts-nr)/2))
|
|
624
|
+
data1 = __taper2d(data, npts, nc, nr, cdiff, rdiff)
|
|
625
|
+
# data1 = np.pad(data, ((rdiff, cdiff), (rdiff,cdiff)), 'edge')
|
|
626
|
+
|
|
627
|
+
f = np.fft.fft2(data1)
|
|
628
|
+
fz = f
|
|
629
|
+
wn = 2.0*np.pi/(xint*(npts-1))
|
|
630
|
+
f = np.fft.fftshift(f)
|
|
631
|
+
cx = npts/2+1
|
|
632
|
+
cy = cx
|
|
633
|
+
for i in range(npts):
|
|
634
|
+
freqx = (i+1-cx)*wn
|
|
635
|
+
for j in range(npts):
|
|
636
|
+
freqy = (j+1-cy)*wn
|
|
637
|
+
freq = np.sqrt(freqx*freqx+freqy*freqy)
|
|
638
|
+
fz[i, j] = f[i, j]*freq
|
|
639
|
+
fz = np.fft.fftshift(fz)
|
|
640
|
+
fzinv = np.fft.ifft2(fz)
|
|
641
|
+
dz = np.real(fzinv[rdiff:nr+rdiff, cdiff:nc+cdiff])
|
|
642
|
+
return dz
|
|
643
|
+
|
|
644
|
+
|
|
645
|
+
def __taper2d(g, npts, n, m, ndiff, mdiff):
|
|
646
|
+
""" Taper 2D """
|
|
647
|
+
|
|
648
|
+
# n is cols, m is rows
|
|
649
|
+
|
|
650
|
+
npts2 = npts-1
|
|
651
|
+
gm = g.mean()
|
|
652
|
+
gf = np.zeros([npts, npts])+np.median(g-gm)
|
|
653
|
+
gf[mdiff:mdiff+m, ndiff:ndiff+n] = g-gm
|
|
654
|
+
|
|
655
|
+
# gf = np.pad(g-gm, ((mdiff, mdiff), (ndiff, ndiff)), 'median')
|
|
656
|
+
|
|
657
|
+
for j in range(mdiff, mdiff+m):
|
|
658
|
+
for i in range(ndiff):
|
|
659
|
+
gf[i, j] = gf[i, j]*((1+np.sin(-np.pi/2+i*np.pi/ndiff))*0.5)
|
|
660
|
+
gf[npts2-i, j] = gf[npts2-i, j]*((1+np.sin(-np.pi/2 +
|
|
661
|
+
i*np.pi/ndiff))*0.5)
|
|
662
|
+
|
|
663
|
+
for j in range(mdiff):
|
|
664
|
+
tmp = ((1+np.sin(-np.pi/2+j*np.pi/(mdiff)))*0.5)
|
|
665
|
+
for i in range(ndiff, ndiff+n):
|
|
666
|
+
gf[i, j] = gf[i, j]*tmp
|
|
667
|
+
gf[i, npts2-j-1] = gf[i, npts2-j-1]*tmp
|
|
668
|
+
|
|
669
|
+
for i in range(ndiff):
|
|
670
|
+
tmp = ((1+np.sin(-np.pi/2+i*np.pi/(ndiff)))*0.5)
|
|
671
|
+
for j in range(mdiff):
|
|
672
|
+
gf[i, j] = gf[i, j]*tmp
|
|
673
|
+
gf[npts2-i, j] = gf[npts2-i, j]*tmp
|
|
674
|
+
|
|
675
|
+
for i in range(ndiff):
|
|
676
|
+
tmp = ((1+np.sin(-np.pi/2+i*np.pi/(ndiff)))*0.5)
|
|
677
|
+
for j in range(mdiff+m-1, npts):
|
|
678
|
+
gf[i, j] = gf[i, j]*tmp
|
|
679
|
+
gf[npts2-i, j] = gf[npts2-i, j]*tmp
|
|
680
|
+
|
|
681
|
+
for j in range(mdiff+m-1, npts): # Corners
|
|
682
|
+
for i in range(ndiff+n-1, npts):
|
|
683
|
+
if ndiff == 0 or mdiff == 0:
|
|
684
|
+
gf[i, j] = np.nan
|
|
685
|
+
else:
|
|
686
|
+
gf[i, j] = (gf[i, j] *
|
|
687
|
+
np.cos((i+1-ndiff-n)*np.pi/(2*ndiff)) *
|
|
688
|
+
np.cos((j+1-ndiff-m)*np.pi/(2*mdiff)))
|
|
689
|
+
|
|
690
|
+
for j in range(mdiff):
|
|
691
|
+
for i in range(ndiff):
|
|
692
|
+
if ndiff == 0 or mdiff == 0:
|
|
693
|
+
gf[i, j] = np.nan
|
|
694
|
+
else:
|
|
695
|
+
gf[i, j] = (gf[i, j] *
|
|
696
|
+
np.cos((i+1-ndiff)*np.pi/(2*ndiff)) *
|
|
697
|
+
np.cos((j+1-ndiff)*np.pi/(2*mdiff)))
|
|
698
|
+
|
|
699
|
+
for j in range(mdiff):
|
|
700
|
+
for i in range(ndiff+n-1, npts):
|
|
701
|
+
if ndiff == 0 or mdiff == 0:
|
|
702
|
+
gf[i, j] = np.nan
|
|
703
|
+
else:
|
|
704
|
+
gf[i, j] = (gf[i, j] *
|
|
705
|
+
np.cos((i+1-ndiff-n)*np.pi/(2*ndiff)) *
|
|
706
|
+
np.cos((j+1-ndiff)*np.pi/(2*mdiff)))
|
|
707
|
+
|
|
708
|
+
for j in range(mdiff+m, npts):
|
|
709
|
+
for i in range(ndiff):
|
|
710
|
+
if ndiff == 0 or mdiff == 0:
|
|
711
|
+
gf[i, j] = np.nan
|
|
712
|
+
else:
|
|
713
|
+
gf[i, j] = (gf[i, j] *
|
|
714
|
+
np.cos((i+1-ndiff)*np.pi/(2*ndiff)) *
|
|
715
|
+
np.cos((j+1-ndiff-m)*np.pi/(2*mdiff)))
|
|
716
|
+
|
|
717
|
+
|
|
718
|
+
return gf
|