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,1640 @@
|
|
|
1
|
+
# -----------------------------------------------------------------------------
|
|
2
|
+
# Name: dataprep.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 set of Raster Data Preparation routines """
|
|
26
|
+
|
|
27
|
+
from __future__ import print_function
|
|
28
|
+
|
|
29
|
+
from PyQt4 import QtGui, QtCore
|
|
30
|
+
import os
|
|
31
|
+
import numpy as np
|
|
32
|
+
from osgeo import gdal, osr, ogr
|
|
33
|
+
from pygmi.raster.datatypes import Data
|
|
34
|
+
from pygmi.vector.datatypes import PData
|
|
35
|
+
from PIL import Image, ImageDraw
|
|
36
|
+
import copy
|
|
37
|
+
import scipy.ndimage as ndimage
|
|
38
|
+
from collections import Counter
|
|
39
|
+
import pygmi.menu_default as menu_default
|
|
40
|
+
|
|
41
|
+
gdal.PushErrorHandler('CPLQuietErrorHandler')
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class DataCut(object):
|
|
45
|
+
"""
|
|
46
|
+
Cut Data using shapefiles
|
|
47
|
+
|
|
48
|
+
This class cuts raster datasets using a boundary defined by a polygon
|
|
49
|
+
shapefile.
|
|
50
|
+
|
|
51
|
+
Attributes
|
|
52
|
+
----------
|
|
53
|
+
ifile : str
|
|
54
|
+
input file name.
|
|
55
|
+
name : str
|
|
56
|
+
item name
|
|
57
|
+
ext : str
|
|
58
|
+
file name extension.
|
|
59
|
+
pbar : progressbar
|
|
60
|
+
reference to a progress bar.
|
|
61
|
+
parent : parent
|
|
62
|
+
reference to the parent routine
|
|
63
|
+
indata : dictionary
|
|
64
|
+
dictionary of input datasets
|
|
65
|
+
outdata : dictionary
|
|
66
|
+
dictionary of output datasets
|
|
67
|
+
"""
|
|
68
|
+
def __init__(self, parent):
|
|
69
|
+
self.ifile = ""
|
|
70
|
+
self.name = "Cut Data:"
|
|
71
|
+
self.ext = ""
|
|
72
|
+
self.pbar = parent.pbar
|
|
73
|
+
self.parent = parent
|
|
74
|
+
self.indata = {}
|
|
75
|
+
self.outdata = {}
|
|
76
|
+
# self.dirname = ""
|
|
77
|
+
|
|
78
|
+
def settings(self):
|
|
79
|
+
""" Show Info """
|
|
80
|
+
# if 'Cluster' in self.indata:
|
|
81
|
+
# data = self.indata['Cluster']
|
|
82
|
+
if 'Raster' in self.indata:
|
|
83
|
+
data = copy.deepcopy(self.indata['Raster'])
|
|
84
|
+
else:
|
|
85
|
+
self.parent.showprocesslog('No raster data')
|
|
86
|
+
return
|
|
87
|
+
|
|
88
|
+
ext = "Shape file (*.shp)"
|
|
89
|
+
|
|
90
|
+
filename = QtGui.QFileDialog.getOpenFileName(
|
|
91
|
+
self.parent, 'Open Shape File', '.', ext)
|
|
92
|
+
if filename == '':
|
|
93
|
+
return False
|
|
94
|
+
os.chdir(filename.rpartition('/')[0])
|
|
95
|
+
|
|
96
|
+
self.ifile = str(filename)
|
|
97
|
+
self.ext = filename[-3:]
|
|
98
|
+
data = cut_raster(data, self.ifile)
|
|
99
|
+
|
|
100
|
+
if data is None:
|
|
101
|
+
err = ('There was a problem importing the shapefile. Please make '
|
|
102
|
+
'sure you have at all the individual files which make up '
|
|
103
|
+
'the shapefile.')
|
|
104
|
+
QtGui.QMessageBox.warning(self.parent, 'Error', err,
|
|
105
|
+
QtGui.QMessageBox.Ok,
|
|
106
|
+
QtGui.QMessageBox.Ok)
|
|
107
|
+
return False
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
# data = trim_raster(data)
|
|
111
|
+
self.pbar.to_max()
|
|
112
|
+
self.outdata['Raster'] = data
|
|
113
|
+
|
|
114
|
+
return True
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
class DataGrid(QtGui.QDialog):
|
|
118
|
+
"""
|
|
119
|
+
Grid Point Data
|
|
120
|
+
|
|
121
|
+
This class grids point data using a nearest neighbourhood technique.
|
|
122
|
+
|
|
123
|
+
Attributes
|
|
124
|
+
----------
|
|
125
|
+
parent : parent
|
|
126
|
+
reference to the parent routine
|
|
127
|
+
indata : dictionary
|
|
128
|
+
dictionary of input datasets
|
|
129
|
+
outdata : dictionary
|
|
130
|
+
dictionary of output datasets
|
|
131
|
+
"""
|
|
132
|
+
def __init__(self, parent=None):
|
|
133
|
+
QtGui.QDialog.__init__(self, parent)
|
|
134
|
+
|
|
135
|
+
self.indata = {}
|
|
136
|
+
self.outdata = {}
|
|
137
|
+
self.parent = parent
|
|
138
|
+
self.pbar = parent.pbar
|
|
139
|
+
|
|
140
|
+
self.dsb_dxy = QtGui.QDoubleSpinBox()
|
|
141
|
+
self.dataid = QtGui.QComboBox()
|
|
142
|
+
self.label_rows = QtGui.QLabel()
|
|
143
|
+
self.label_cols = QtGui.QLabel()
|
|
144
|
+
|
|
145
|
+
self.setupui()
|
|
146
|
+
|
|
147
|
+
def setupui(self):
|
|
148
|
+
""" Setup UI """
|
|
149
|
+
gridlayout_main = QtGui.QGridLayout(self)
|
|
150
|
+
buttonbox = QtGui.QDialogButtonBox()
|
|
151
|
+
helpdocs = menu_default.HelpButton('pygmi.raster.dataprep.datagrid')
|
|
152
|
+
label_band = QtGui.QLabel()
|
|
153
|
+
label_dxy = QtGui.QLabel()
|
|
154
|
+
|
|
155
|
+
self.dsb_dxy.setMaximum(9999999999.0)
|
|
156
|
+
self.dsb_dxy.setMinimum(0.00001)
|
|
157
|
+
self.dsb_dxy.setDecimals(5)
|
|
158
|
+
buttonbox.setOrientation(QtCore.Qt.Horizontal)
|
|
159
|
+
buttonbox.setCenterButtons(True)
|
|
160
|
+
buttonbox.setStandardButtons(buttonbox.Cancel | buttonbox.Ok)
|
|
161
|
+
|
|
162
|
+
self.setWindowTitle("Dataset Gridding")
|
|
163
|
+
self.label_rows.setText("Rows: 0")
|
|
164
|
+
self.label_cols.setText("Columns: 0")
|
|
165
|
+
label_dxy.setText("Cell Size:")
|
|
166
|
+
label_band.setText("Column to Grid:")
|
|
167
|
+
|
|
168
|
+
gridlayout_main.addWidget(label_dxy, 0, 0, 1, 1)
|
|
169
|
+
gridlayout_main.addWidget(self.dsb_dxy, 0, 1, 1, 1)
|
|
170
|
+
gridlayout_main.addWidget(self.label_rows, 1, 0, 1, 2)
|
|
171
|
+
gridlayout_main.addWidget(self.label_cols, 2, 0, 1, 2)
|
|
172
|
+
gridlayout_main.addWidget(label_band, 3, 0, 1, 1)
|
|
173
|
+
gridlayout_main.addWidget(self.dataid, 3, 1, 1, 1)
|
|
174
|
+
gridlayout_main.addWidget(helpdocs, 4, 0, 1, 1)
|
|
175
|
+
gridlayout_main.addWidget(buttonbox, 4, 1, 1, 3)
|
|
176
|
+
|
|
177
|
+
buttonbox.accepted.connect(self.accept)
|
|
178
|
+
buttonbox.rejected.connect(self.reject)
|
|
179
|
+
self.dsb_dxy.valueChanged.connect(self.dxy_change)
|
|
180
|
+
|
|
181
|
+
def dxy_change(self):
|
|
182
|
+
""" update dxy """
|
|
183
|
+
dxy = self.dsb_dxy.value()
|
|
184
|
+
data = self.indata['Point'][0]
|
|
185
|
+
x = data.xdata
|
|
186
|
+
y = data.ydata
|
|
187
|
+
|
|
188
|
+
cols = int(x.ptp()/dxy)
|
|
189
|
+
rows = int(y.ptp()/dxy)
|
|
190
|
+
|
|
191
|
+
self.label_rows.setText("Rows: "+str(rows))
|
|
192
|
+
self.label_cols.setText("Columns: "+str(cols))
|
|
193
|
+
|
|
194
|
+
def settings(self):
|
|
195
|
+
""" Settings """
|
|
196
|
+
tmp = []
|
|
197
|
+
if 'Point' not in self.indata:
|
|
198
|
+
return False
|
|
199
|
+
|
|
200
|
+
for i in self.indata['Point']:
|
|
201
|
+
tmp.append(i.dataid)
|
|
202
|
+
|
|
203
|
+
self.dataid.addItems(tmp)
|
|
204
|
+
|
|
205
|
+
data = self.indata['Point'][0]
|
|
206
|
+
x = data.xdata
|
|
207
|
+
y = data.ydata
|
|
208
|
+
|
|
209
|
+
dx = x.ptp()/np.sqrt(x.size)
|
|
210
|
+
dy = y.ptp()/np.sqrt(y.size)
|
|
211
|
+
dxy = max(dx, dy)
|
|
212
|
+
|
|
213
|
+
# xy = np.transpose([x, y])
|
|
214
|
+
# xy = xy.tolist()
|
|
215
|
+
# xy = np.array(xy)
|
|
216
|
+
# xy = xy[:-1]-xy[1:]
|
|
217
|
+
# dxy = np.median(np.sqrt(np.sum(xy**2, 1)))/3
|
|
218
|
+
|
|
219
|
+
self.dsb_dxy.setValue(dxy)
|
|
220
|
+
self.dxy_change()
|
|
221
|
+
tmp = self.exec_()
|
|
222
|
+
|
|
223
|
+
if tmp == 1:
|
|
224
|
+
self.acceptall()
|
|
225
|
+
tmp = True
|
|
226
|
+
|
|
227
|
+
return tmp
|
|
228
|
+
|
|
229
|
+
def acceptall(self):
|
|
230
|
+
""" accept """
|
|
231
|
+
dxy = self.dsb_dxy.value()
|
|
232
|
+
data = self.indata['Point'][0]
|
|
233
|
+
|
|
234
|
+
newdat = []
|
|
235
|
+
for data in self.pbar.iter(self.indata['Point']):
|
|
236
|
+
if data.dataid != self.dataid.currentText():
|
|
237
|
+
continue
|
|
238
|
+
x = data.xdata
|
|
239
|
+
y = data.ydata
|
|
240
|
+
z = data.zdata
|
|
241
|
+
|
|
242
|
+
for i in [x, y, z]:
|
|
243
|
+
filt = np.logical_not(np.isnan(i))
|
|
244
|
+
x = x[filt]
|
|
245
|
+
y = y[filt]
|
|
246
|
+
z = z[filt]
|
|
247
|
+
|
|
248
|
+
# self.parent.showprocesslog
|
|
249
|
+
# pdb.set_trace()
|
|
250
|
+
tmp = quickgrid(x, y, z, dxy, showtext=self.parent.showprocesslog)
|
|
251
|
+
# pdb.set_trace()
|
|
252
|
+
mask = tmp.mask
|
|
253
|
+
gdat = tmp.data
|
|
254
|
+
|
|
255
|
+
# Create dataset
|
|
256
|
+
dat = Data()
|
|
257
|
+
dat.data = np.ma.masked_invalid(gdat[::-1])
|
|
258
|
+
dat.data.mask = mask[::-1]
|
|
259
|
+
dat.rows, dat.cols = gdat.shape
|
|
260
|
+
dat.nullvalue = dat.data.fill_value
|
|
261
|
+
dat.dataid = data.dataid
|
|
262
|
+
dat.tlx = x.min()
|
|
263
|
+
dat.tly = y.max()
|
|
264
|
+
dat.xdim = dxy
|
|
265
|
+
dat.ydim = dxy
|
|
266
|
+
newdat.append(dat)
|
|
267
|
+
|
|
268
|
+
self.outdata['Raster'] = newdat
|
|
269
|
+
self.outdata['Point'] = self.indata['Point']
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
class DataMerge(QtGui.QDialog):
|
|
273
|
+
"""
|
|
274
|
+
Data Merge
|
|
275
|
+
|
|
276
|
+
This class merges datasets which have different rows and columns. It
|
|
277
|
+
resamples them so that they have the same rows and columns.
|
|
278
|
+
|
|
279
|
+
Attributes
|
|
280
|
+
----------
|
|
281
|
+
parent : parent
|
|
282
|
+
reference to the parent routine
|
|
283
|
+
indata : dictionary
|
|
284
|
+
dictionary of input datasets
|
|
285
|
+
outdata : dictionary
|
|
286
|
+
dictionary of output datasets
|
|
287
|
+
"""
|
|
288
|
+
def __init__(self, parent=None):
|
|
289
|
+
QtGui.QDialog.__init__(self, parent)
|
|
290
|
+
|
|
291
|
+
self.indata = {}
|
|
292
|
+
self.outdata = {}
|
|
293
|
+
self.parent = parent
|
|
294
|
+
self.pbar = self.parent.pbar
|
|
295
|
+
|
|
296
|
+
self.dsb_dxy = QtGui.QDoubleSpinBox()
|
|
297
|
+
self.label_rows = QtGui.QLabel()
|
|
298
|
+
self.label_cols = QtGui.QLabel()
|
|
299
|
+
|
|
300
|
+
self.setupui()
|
|
301
|
+
|
|
302
|
+
def setupui(self):
|
|
303
|
+
""" Setup UI """
|
|
304
|
+
|
|
305
|
+
gridlayout_main = QtGui.QGridLayout(self)
|
|
306
|
+
buttonbox = QtGui.QDialogButtonBox()
|
|
307
|
+
helpdocs = menu_default.HelpButton('pygmi.raster.dataprep.datamerge')
|
|
308
|
+
label_dxy = QtGui.QLabel()
|
|
309
|
+
|
|
310
|
+
self.dsb_dxy.setMaximum(9999999999.0)
|
|
311
|
+
self.dsb_dxy.setMinimum(0.00001)
|
|
312
|
+
self.dsb_dxy.setDecimals(5)
|
|
313
|
+
buttonbox.setOrientation(QtCore.Qt.Horizontal)
|
|
314
|
+
buttonbox.setCenterButtons(True)
|
|
315
|
+
buttonbox.setStandardButtons(buttonbox.Cancel | buttonbox.Ok)
|
|
316
|
+
|
|
317
|
+
self.setWindowTitle("Dataset Merge and Resample")
|
|
318
|
+
self.label_rows.setText("Rows: 0")
|
|
319
|
+
self.label_cols.setText("Columns: 0")
|
|
320
|
+
label_dxy.setText("Cell Size:")
|
|
321
|
+
|
|
322
|
+
gridlayout_main.addWidget(label_dxy, 0, 0, 1, 1)
|
|
323
|
+
gridlayout_main.addWidget(self.dsb_dxy, 0, 1, 1, 1)
|
|
324
|
+
gridlayout_main.addWidget(self.label_rows, 1, 0, 1, 2)
|
|
325
|
+
gridlayout_main.addWidget(self.label_cols, 2, 0, 1, 2)
|
|
326
|
+
gridlayout_main.addWidget(helpdocs, 3, 0, 1, 1)
|
|
327
|
+
gridlayout_main.addWidget(buttonbox, 3, 1, 1, 1)
|
|
328
|
+
|
|
329
|
+
buttonbox.accepted.connect(self.accept)
|
|
330
|
+
buttonbox.rejected.connect(self.reject)
|
|
331
|
+
self.dsb_dxy.valueChanged.connect(self.dxy_change)
|
|
332
|
+
|
|
333
|
+
def dxy_change(self):
|
|
334
|
+
""" Update dxy - which is the size of a grid cell in the x and y
|
|
335
|
+
directions."""
|
|
336
|
+
data = self.indata['Raster'][0]
|
|
337
|
+
dxy = self.dsb_dxy.value()
|
|
338
|
+
|
|
339
|
+
xmin0 = data.tlx
|
|
340
|
+
xmax0 = data.tlx+data.xdim*data.cols
|
|
341
|
+
ymax0 = data.tly
|
|
342
|
+
ymin0 = data.tly-data.ydim*data.rows
|
|
343
|
+
|
|
344
|
+
for data in self.indata['Raster']:
|
|
345
|
+
xmin = min(data.tlx, xmin0)
|
|
346
|
+
xmax = max(data.tlx+data.xdim*data.cols, xmax0)
|
|
347
|
+
ymax = max(data.tly, ymax0)
|
|
348
|
+
ymin = min(data.tly-data.ydim*data.rows, ymin0)
|
|
349
|
+
|
|
350
|
+
cols = int((xmax - xmin)/dxy)
|
|
351
|
+
rows = int((ymax - ymin)/dxy)
|
|
352
|
+
|
|
353
|
+
self.label_rows.setText("Rows: "+str(rows))
|
|
354
|
+
self.label_cols.setText("Columns: "+str(cols))
|
|
355
|
+
|
|
356
|
+
def settings(self):
|
|
357
|
+
""" Settings """
|
|
358
|
+
data = self.indata['Raster'][0]
|
|
359
|
+
dxy0 = min(data.xdim, data.ydim)
|
|
360
|
+
for data in self.indata['Raster']:
|
|
361
|
+
dxy = min(dxy0, data.xdim, data.ydim)
|
|
362
|
+
|
|
363
|
+
self.dsb_dxy.setValue(dxy)
|
|
364
|
+
tmp = self.exec_()
|
|
365
|
+
|
|
366
|
+
if tmp == 1:
|
|
367
|
+
self.acceptall()
|
|
368
|
+
tmp = True
|
|
369
|
+
|
|
370
|
+
return tmp
|
|
371
|
+
|
|
372
|
+
def acceptall(self):
|
|
373
|
+
"""
|
|
374
|
+
This routine is called by settings() if accept is pressed. It contains
|
|
375
|
+
the main merge routine.
|
|
376
|
+
"""
|
|
377
|
+
dxy = self.dsb_dxy.value()
|
|
378
|
+
data = self.indata['Raster'][0]
|
|
379
|
+
orig_wkt = data.wkt
|
|
380
|
+
|
|
381
|
+
xmin = data.tlx
|
|
382
|
+
xmax = data.tlx+data.xdim*data.cols
|
|
383
|
+
ymax = data.tly
|
|
384
|
+
ymin = data.tly-data.ydim*data.rows
|
|
385
|
+
|
|
386
|
+
for data in self.indata['Raster']:
|
|
387
|
+
xmin = min(data.tlx, xmin)
|
|
388
|
+
xmax = max(data.tlx+data.xdim*data.cols, xmax)
|
|
389
|
+
ymax = max(data.tly, ymax)
|
|
390
|
+
ymin = min(data.tly-data.ydim*data.rows, ymin)
|
|
391
|
+
|
|
392
|
+
cols = int((xmax - xmin)/dxy)
|
|
393
|
+
rows = int((ymax - ymin)/dxy)
|
|
394
|
+
gtr = (xmin, dxy, 0.0, ymax, 0.0, -dxy)
|
|
395
|
+
|
|
396
|
+
if cols == 0 or rows == 0:
|
|
397
|
+
self.parent.showprocesslog("Your rows or cols are zero. " +
|
|
398
|
+
"Your input projection may be wrong")
|
|
399
|
+
return
|
|
400
|
+
|
|
401
|
+
dat = []
|
|
402
|
+
for data in self.pbar.iter(self.indata['Raster']):
|
|
403
|
+
doffset = 0.0
|
|
404
|
+
if data.data.min() <= 0:
|
|
405
|
+
doffset = data.data.min()-1.
|
|
406
|
+
data.data -= doffset
|
|
407
|
+
gtr0 = (data.tlx, data.xdim, 0.0, data.tly, 0.0, -data.ydim)
|
|
408
|
+
src = data_to_gdal_mem(data, gtr0, orig_wkt, data.cols, data.rows)
|
|
409
|
+
dest = data_to_gdal_mem(data, gtr, orig_wkt, cols, rows, True)
|
|
410
|
+
|
|
411
|
+
gdal.ReprojectImage(src, dest, orig_wkt, orig_wkt,
|
|
412
|
+
gdal.GRA_Bilinear)
|
|
413
|
+
|
|
414
|
+
dat.append(gdal_to_dat(dest, data.dataid))
|
|
415
|
+
dat[-1].data += doffset
|
|
416
|
+
|
|
417
|
+
# mask = dat[-1].data.mask
|
|
418
|
+
# for i in dat:
|
|
419
|
+
# mask += i.data.mask
|
|
420
|
+
# mask[mask != 0] = 1
|
|
421
|
+
# for i in dat:
|
|
422
|
+
# i.data.mask = mask
|
|
423
|
+
|
|
424
|
+
self.outdata['Raster'] = dat
|
|
425
|
+
# self.accept()
|
|
426
|
+
|
|
427
|
+
|
|
428
|
+
class DataReproj(QtGui.QDialog):
|
|
429
|
+
"""
|
|
430
|
+
Reprojections
|
|
431
|
+
|
|
432
|
+
This class reprojects datasets using the GDAL routines.
|
|
433
|
+
|
|
434
|
+
Attributes
|
|
435
|
+
----------
|
|
436
|
+
parent : parent
|
|
437
|
+
reference to the parent routine
|
|
438
|
+
indata : dictionary
|
|
439
|
+
dictionary of input datasets
|
|
440
|
+
outdata : dictionary
|
|
441
|
+
dictionary of output datasets
|
|
442
|
+
"""
|
|
443
|
+
def __init__(self, parent=None):
|
|
444
|
+
QtGui.QDialog.__init__(self, parent)
|
|
445
|
+
|
|
446
|
+
self.indata = {}
|
|
447
|
+
self.outdata = {}
|
|
448
|
+
self.parent = parent
|
|
449
|
+
self.pbar = self.parent.pbar
|
|
450
|
+
|
|
451
|
+
self.groupboxb = QtGui.QGroupBox()
|
|
452
|
+
self.combobox_inp_epsg = QtGui.QComboBox()
|
|
453
|
+
self.inp_epsg_info = QtGui.QLabel()
|
|
454
|
+
self.groupbox2b = QtGui.QGroupBox()
|
|
455
|
+
self.combobox_out_epsg = QtGui.QComboBox()
|
|
456
|
+
self.out_epsg_info = QtGui.QLabel()
|
|
457
|
+
self.in_proj = GroupProj('Input Projection')
|
|
458
|
+
self.out_proj = GroupProj('Output Projection')
|
|
459
|
+
|
|
460
|
+
self.setupui()
|
|
461
|
+
|
|
462
|
+
def setupui(self):
|
|
463
|
+
""" Setup UI """
|
|
464
|
+
gridlayout_main = QtGui.QGridLayout(self)
|
|
465
|
+
buttonbox = QtGui.QDialogButtonBox()
|
|
466
|
+
helpdocs = menu_default.HelpButton('pygmi.raster.dataprep.datareproj')
|
|
467
|
+
|
|
468
|
+
buttonbox.setOrientation(QtCore.Qt.Horizontal)
|
|
469
|
+
buttonbox.setCenterButtons(True)
|
|
470
|
+
buttonbox.setStandardButtons(buttonbox.Cancel | buttonbox.Ok)
|
|
471
|
+
|
|
472
|
+
self.setWindowTitle("Dataset Reprojection")
|
|
473
|
+
|
|
474
|
+
gridlayout_main.addWidget(self.in_proj, 0, 0, 1, 1)
|
|
475
|
+
gridlayout_main.addWidget(self.out_proj, 0, 1, 1, 1)
|
|
476
|
+
gridlayout_main.addWidget(helpdocs, 1, 0, 1, 1)
|
|
477
|
+
gridlayout_main.addWidget(buttonbox, 1, 1, 1, 1)
|
|
478
|
+
|
|
479
|
+
buttonbox.accepted.connect(self.accept)
|
|
480
|
+
buttonbox.rejected.connect(self.reject)
|
|
481
|
+
|
|
482
|
+
def acceptall(self):
|
|
483
|
+
"""
|
|
484
|
+
This routine is called by settings() if accept is pressed. It contains
|
|
485
|
+
the main routine.
|
|
486
|
+
"""
|
|
487
|
+
|
|
488
|
+
# Input stuff
|
|
489
|
+
orig_wkt = self.in_proj.wkt
|
|
490
|
+
|
|
491
|
+
orig = osr.SpatialReference()
|
|
492
|
+
orig.ImportFromWkt(orig_wkt)
|
|
493
|
+
|
|
494
|
+
# Output stuff
|
|
495
|
+
targ_wkt = self.out_proj.wkt
|
|
496
|
+
|
|
497
|
+
targ = osr.SpatialReference()
|
|
498
|
+
targ.ImportFromWkt(targ_wkt)
|
|
499
|
+
|
|
500
|
+
# Set transformation
|
|
501
|
+
ctrans = osr.CoordinateTransformation(orig, targ)
|
|
502
|
+
|
|
503
|
+
# Now create virtual dataset
|
|
504
|
+
dat = []
|
|
505
|
+
for data in self.pbar.iter(self.indata['Raster']):
|
|
506
|
+
datamin = data.data.min()
|
|
507
|
+
if datamin <= 0:
|
|
508
|
+
data.data = data.data-(datamin-1)
|
|
509
|
+
|
|
510
|
+
# Work out the boundaries of the new dataset in the target projection
|
|
511
|
+
u_l = ctrans.TransformPoint(data.tlx, data.tly)
|
|
512
|
+
u_r = ctrans.TransformPoint(data.tlx+data.xdim*data.cols, data.tly)
|
|
513
|
+
l_l = ctrans.TransformPoint(data.tlx, data.tly-data.ydim*data.rows)
|
|
514
|
+
l_r = ctrans.TransformPoint(data.tlx+data.xdim*data.cols,
|
|
515
|
+
data.tly - data.ydim*data.rows)
|
|
516
|
+
|
|
517
|
+
lrx = l_r[0]
|
|
518
|
+
llx = l_l[0]
|
|
519
|
+
ulx = u_l[0]
|
|
520
|
+
urx = u_r[0]
|
|
521
|
+
lry = l_r[1]
|
|
522
|
+
lly = l_l[1]
|
|
523
|
+
uly = u_l[1]
|
|
524
|
+
ury = u_r[1]
|
|
525
|
+
|
|
526
|
+
minx = min(llx, ulx, urx, lrx)
|
|
527
|
+
maxx = max(llx, ulx, urx, lrx)
|
|
528
|
+
miny = min(lly, lry, ury, uly)
|
|
529
|
+
maxy = max(lly, lry, ury, uly)
|
|
530
|
+
newdimx = (maxx-minx)/data.cols
|
|
531
|
+
newdimy = (maxy-miny)/data.rows
|
|
532
|
+
newdim = min(newdimx, newdimy)
|
|
533
|
+
cols = round((maxx - minx)/newdim)
|
|
534
|
+
rows = round((maxy - miny)/newdim)
|
|
535
|
+
|
|
536
|
+
if cols == 0 or rows == 0:
|
|
537
|
+
self.parent.showprocesslog("Your rows or cols are zero. " +
|
|
538
|
+
"Your input projection may be " +
|
|
539
|
+
"wrong")
|
|
540
|
+
return
|
|
541
|
+
|
|
542
|
+
# top left x, w-e pixel size, rotation, top left y, rotation, n-s pixel size
|
|
543
|
+
old_geo = (data.tlx, data.xdim, 0, data.tly, 0, -data.ydim)
|
|
544
|
+
src = data_to_gdal_mem(data, old_geo, orig_wkt, data.cols,
|
|
545
|
+
data.rows)
|
|
546
|
+
|
|
547
|
+
new_geo = (minx, newdim, 0, maxy, 0, -newdim)
|
|
548
|
+
dest = data_to_gdal_mem(data, new_geo, targ_wkt, cols, rows, True)
|
|
549
|
+
|
|
550
|
+
gdal.ReprojectImage(src, dest, orig_wkt, targ_wkt,
|
|
551
|
+
gdal.GRA_Bilinear)
|
|
552
|
+
|
|
553
|
+
data2 = gdal_to_dat(dest, data.dataid)
|
|
554
|
+
if datamin <= 0:
|
|
555
|
+
data2.data = data2.data+(datamin-1)
|
|
556
|
+
data.data = data.data+(datamin-1)
|
|
557
|
+
# mask = data2.data.mask
|
|
558
|
+
data2.data = np.ma.masked_equal(data2.data.filled(data.nullvalue),
|
|
559
|
+
data.nullvalue)
|
|
560
|
+
# data2.data.mask = mask
|
|
561
|
+
# data2.data.set_fill_value(data.nullvalue)
|
|
562
|
+
data2.nullvalue = data.nullvalue
|
|
563
|
+
data2.data = np.ma.masked_invalid(data2.data)
|
|
564
|
+
data2.data = np.ma.masked_less(data2.data, data.data.min())
|
|
565
|
+
data2.data = np.ma.masked_greater(data2.data, data.data.max())
|
|
566
|
+
|
|
567
|
+
dat.append(data2)
|
|
568
|
+
|
|
569
|
+
self.outdata['Raster'] = dat
|
|
570
|
+
|
|
571
|
+
def settings(self):
|
|
572
|
+
""" Settings """
|
|
573
|
+
|
|
574
|
+
self.in_proj.set_current(self.indata['Raster'][0].wkt)
|
|
575
|
+
self.out_proj.set_current(self.indata['Raster'][0].wkt)
|
|
576
|
+
|
|
577
|
+
tmp = self.exec_()
|
|
578
|
+
if tmp == 1:
|
|
579
|
+
self.acceptall()
|
|
580
|
+
tmp = True
|
|
581
|
+
|
|
582
|
+
return tmp
|
|
583
|
+
|
|
584
|
+
|
|
585
|
+
class GetProf(object):
|
|
586
|
+
"""
|
|
587
|
+
Get a Profile
|
|
588
|
+
|
|
589
|
+
This class extracts a profile from a raster dataset using a line shapefile.
|
|
590
|
+
|
|
591
|
+
Attributes
|
|
592
|
+
----------
|
|
593
|
+
ifile : str
|
|
594
|
+
input file name.
|
|
595
|
+
name : str
|
|
596
|
+
item name
|
|
597
|
+
ext : str
|
|
598
|
+
file name extension.
|
|
599
|
+
pbar : progressbar
|
|
600
|
+
reference to a progress bar.
|
|
601
|
+
parent : parent
|
|
602
|
+
reference to the parent routine
|
|
603
|
+
indata : dictionary
|
|
604
|
+
dictionary of input datasets
|
|
605
|
+
outdata : dictionary
|
|
606
|
+
dictionary of output datasets
|
|
607
|
+
"""
|
|
608
|
+
def __init__(self, parent):
|
|
609
|
+
self.ifile = ""
|
|
610
|
+
self.name = "Get Profile: "
|
|
611
|
+
self.ext = ""
|
|
612
|
+
self.pbar = parent.pbar
|
|
613
|
+
self.parent = parent
|
|
614
|
+
self.indata = {}
|
|
615
|
+
self.outdata = {}
|
|
616
|
+
# self.dirname = ""
|
|
617
|
+
|
|
618
|
+
def settings(self):
|
|
619
|
+
""" Show Info """
|
|
620
|
+
# if 'Cluster' in self.indata:
|
|
621
|
+
# data = self.indata['Cluster']
|
|
622
|
+
if 'Raster' in self.indata:
|
|
623
|
+
data = copy.deepcopy(self.indata['Raster'])
|
|
624
|
+
else:
|
|
625
|
+
self.parent.showprocesslog('No raster data')
|
|
626
|
+
return
|
|
627
|
+
|
|
628
|
+
ext = "Shape file (*.shp)"
|
|
629
|
+
|
|
630
|
+
filename = QtGui.QFileDialog.getOpenFileName(
|
|
631
|
+
self.parent, 'Open Shape File', '.', ext)
|
|
632
|
+
if filename == '':
|
|
633
|
+
return False
|
|
634
|
+
os.chdir(filename.rpartition('/')[0])
|
|
635
|
+
|
|
636
|
+
self.ifile = str(filename)
|
|
637
|
+
self.ext = filename[-3:]
|
|
638
|
+
|
|
639
|
+
shapef = ogr.Open(self.ifile)
|
|
640
|
+
if shapef is None:
|
|
641
|
+
err = ('There was a problem importing the shapefile. Please make '
|
|
642
|
+
'sure you have at all the individual files which make up '
|
|
643
|
+
'the shapefile.')
|
|
644
|
+
QtGui.QMessageBox.warning(self.parent, 'Error', err,
|
|
645
|
+
QtGui.QMessageBox.Ok,
|
|
646
|
+
QtGui.QMessageBox.Ok)
|
|
647
|
+
return False
|
|
648
|
+
|
|
649
|
+
lyr = shapef.GetLayer()
|
|
650
|
+
line = lyr.GetNextFeature()
|
|
651
|
+
if lyr.GetGeomType() is not ogr.wkbLineString:
|
|
652
|
+
self.parent.showprocesslog('You need lines in that shape file')
|
|
653
|
+
return
|
|
654
|
+
|
|
655
|
+
allpoints = []
|
|
656
|
+
for idata in self.pbar.iter(data):
|
|
657
|
+
tmp = line.GetGeometryRef()
|
|
658
|
+
points = tmp.GetPoints()
|
|
659
|
+
|
|
660
|
+
x_0, y_0 = points[0]
|
|
661
|
+
x_1, y_1 = points[1]
|
|
662
|
+
|
|
663
|
+
bly = idata.tly-idata.ydim*idata.rows
|
|
664
|
+
x_0 = (x_0-idata.tlx)/idata.xdim
|
|
665
|
+
x_1 = (x_1-idata.tlx)/idata.xdim
|
|
666
|
+
y_0 = (y_0-bly)/idata.ydim
|
|
667
|
+
y_1 = (y_1-bly)/idata.ydim
|
|
668
|
+
rcell = int(np.sqrt((x_1-x_0)**2+(y_1-y_0)**2))
|
|
669
|
+
# rdist = np.sqrt((idata.xdim*(x_1-x_0))**2 +
|
|
670
|
+
# (idata.ydim*(y_1-y_0))**2)
|
|
671
|
+
|
|
672
|
+
xxx = np.linspace(x_0, x_1, rcell, False)
|
|
673
|
+
yyy = np.linspace(y_0, y_1, rcell, False)
|
|
674
|
+
|
|
675
|
+
tmpprof = ndimage.map_coordinates(idata.data[::-1], [yyy, xxx],
|
|
676
|
+
order=1, cval=np.nan)
|
|
677
|
+
xxx = xxx[np.logical_not(np.isnan(tmpprof))]
|
|
678
|
+
yyy = yyy[np.logical_not(np.isnan(tmpprof))]
|
|
679
|
+
tmpprof = tmpprof[np.logical_not(np.isnan(tmpprof))]
|
|
680
|
+
xxx = xxx*idata.xdim+idata.tlx
|
|
681
|
+
yyy = yyy*idata.ydim+bly
|
|
682
|
+
# allpoints.append(np.array([xxx, yyy, tmpprof]))
|
|
683
|
+
allpoints.append(PData())
|
|
684
|
+
allpoints[-1].xdata = xxx
|
|
685
|
+
allpoints[-1].ydata = yyy
|
|
686
|
+
allpoints[-1].zdata = tmpprof
|
|
687
|
+
allpoints[-1].dataid = idata.dataid
|
|
688
|
+
|
|
689
|
+
self.outdata['Point'] = allpoints
|
|
690
|
+
|
|
691
|
+
return True
|
|
692
|
+
|
|
693
|
+
|
|
694
|
+
class GroupProj(QtGui.QWidget):
|
|
695
|
+
"""
|
|
696
|
+
Group Proj
|
|
697
|
+
|
|
698
|
+
Custom widget
|
|
699
|
+
"""
|
|
700
|
+
def __init__(self, title='Projection', parent=None):
|
|
701
|
+
QtGui.QWidget.__init__(self, parent)
|
|
702
|
+
|
|
703
|
+
self.wkt = ''
|
|
704
|
+
|
|
705
|
+
self.gridlayout = QtGui.QGridLayout(self)
|
|
706
|
+
self.groupbox = QtGui.QGroupBox()
|
|
707
|
+
self.combobox = QtGui.QComboBox()
|
|
708
|
+
self.label = QtGui.QLabel()
|
|
709
|
+
|
|
710
|
+
self.gridlayout.addWidget(self.groupbox, 1, 0, 1, 2)
|
|
711
|
+
|
|
712
|
+
self.groupbox.setTitle(title)
|
|
713
|
+
gridlayout = QtGui.QGridLayout(self.groupbox)
|
|
714
|
+
gridlayout.addWidget(self.combobox, 0, 0, 1, 1)
|
|
715
|
+
gridlayout.addWidget(self.label, 1, 0, 1, 1)
|
|
716
|
+
|
|
717
|
+
self.epsg_proj = getepsgcodes()
|
|
718
|
+
self.epsg_proj['Current'] = self.wkt
|
|
719
|
+
tmp = list(self.epsg_proj.keys())
|
|
720
|
+
tmp.sort(key=lambda c: c.lower())
|
|
721
|
+
tmp = ['Current']+tmp
|
|
722
|
+
|
|
723
|
+
self.combobox.addItems(tmp)
|
|
724
|
+
self.combobox.currentIndexChanged.connect(self.combo_change)
|
|
725
|
+
|
|
726
|
+
def set_current(self, wkt):
|
|
727
|
+
""" Sets new wkt for current """
|
|
728
|
+
self.wkt = wkt
|
|
729
|
+
self.epsg_proj['Current'] = self.wkt
|
|
730
|
+
self.combo_change()
|
|
731
|
+
|
|
732
|
+
def combo_change(self):
|
|
733
|
+
""" Change Combo """
|
|
734
|
+
indx = self.combobox.currentIndex()
|
|
735
|
+
txt = self.combobox.itemText(indx)
|
|
736
|
+
|
|
737
|
+
self.wkt = self.epsg_proj[txt]
|
|
738
|
+
|
|
739
|
+
srs = osr.SpatialReference()
|
|
740
|
+
srs.ImportFromWkt(self.wkt)
|
|
741
|
+
self.label.setText(srs.ExportToPrettyWkt())
|
|
742
|
+
|
|
743
|
+
|
|
744
|
+
class Metadata(QtGui.QDialog):
|
|
745
|
+
"""
|
|
746
|
+
Edit Metadata
|
|
747
|
+
|
|
748
|
+
This class allows the editing of teh metadata for a raster dataset using a
|
|
749
|
+
GUI.
|
|
750
|
+
|
|
751
|
+
Attributes
|
|
752
|
+
----------
|
|
753
|
+
name : oldtxt
|
|
754
|
+
old text
|
|
755
|
+
banddata : dictionary
|
|
756
|
+
band data
|
|
757
|
+
bandid : dictionary
|
|
758
|
+
dictionary of strings containing band names.
|
|
759
|
+
parent : parent
|
|
760
|
+
reference to the parent routine
|
|
761
|
+
indata : dictionary
|
|
762
|
+
dictionary of input datasets
|
|
763
|
+
outdata : dictionary
|
|
764
|
+
dictionary of output datasets
|
|
765
|
+
"""
|
|
766
|
+
def __init__(self, parent=None):
|
|
767
|
+
QtGui.QDialog.__init__(self, parent)
|
|
768
|
+
|
|
769
|
+
self.indata = {}
|
|
770
|
+
self.outdata = {}
|
|
771
|
+
self.banddata = {}
|
|
772
|
+
self.dataid = {}
|
|
773
|
+
self.oldtxt = ''
|
|
774
|
+
self.parent = parent
|
|
775
|
+
|
|
776
|
+
self.groupbox = QtGui.QGroupBox()
|
|
777
|
+
self.combobox_bandid = QtGui.QComboBox()
|
|
778
|
+
self.pb_rename_id = QtGui.QPushButton()
|
|
779
|
+
self.lbl_rows = QtGui.QLabel()
|
|
780
|
+
self.lbl_cols = QtGui.QLabel()
|
|
781
|
+
self.inp_epsg_info = QtGui.QLabel()
|
|
782
|
+
self.txt_null = QtGui.QLineEdit()
|
|
783
|
+
self.dsb_tlx = QtGui.QLineEdit()
|
|
784
|
+
self.dsb_tly = QtGui.QLineEdit()
|
|
785
|
+
self.dsb_xdim = QtGui.QLineEdit()
|
|
786
|
+
self.dsb_ydim = QtGui.QLineEdit()
|
|
787
|
+
self.led_units = QtGui.QLineEdit()
|
|
788
|
+
self.lbl_min = QtGui.QLabel()
|
|
789
|
+
self.lbl_max = QtGui.QLabel()
|
|
790
|
+
self.lbl_mean = QtGui.QLabel()
|
|
791
|
+
|
|
792
|
+
self.proj = GroupProj('Input Projection')
|
|
793
|
+
|
|
794
|
+
self.setupui()
|
|
795
|
+
|
|
796
|
+
def setupui(self):
|
|
797
|
+
""" Setup UI """
|
|
798
|
+
gridlayout_main = QtGui.QGridLayout(self)
|
|
799
|
+
buttonbox = QtGui.QDialogButtonBox()
|
|
800
|
+
|
|
801
|
+
gridlayout = QtGui.QGridLayout(self.groupbox)
|
|
802
|
+
label_tlx = QtGui.QLabel()
|
|
803
|
+
label_tly = QtGui.QLabel()
|
|
804
|
+
label_xdim = QtGui.QLabel()
|
|
805
|
+
label_ydim = QtGui.QLabel()
|
|
806
|
+
label_null = QtGui.QLabel()
|
|
807
|
+
label_rows = QtGui.QLabel()
|
|
808
|
+
label_cols = QtGui.QLabel()
|
|
809
|
+
label_min = QtGui.QLabel()
|
|
810
|
+
label_max = QtGui.QLabel()
|
|
811
|
+
label_mean = QtGui.QLabel()
|
|
812
|
+
label_units = QtGui.QLabel()
|
|
813
|
+
label_bandid = QtGui.QLabel()
|
|
814
|
+
|
|
815
|
+
sizepolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred,
|
|
816
|
+
QtGui.QSizePolicy.Expanding)
|
|
817
|
+
self.groupbox.setSizePolicy(sizepolicy)
|
|
818
|
+
buttonbox.setOrientation(QtCore.Qt.Horizontal)
|
|
819
|
+
buttonbox.setCenterButtons(True)
|
|
820
|
+
buttonbox.setStandardButtons(buttonbox.Cancel | buttonbox.Ok)
|
|
821
|
+
|
|
822
|
+
self.setWindowTitle("Dataset Metadata")
|
|
823
|
+
self.pb_rename_id.setText("Rename Band Name")
|
|
824
|
+
self.groupbox.setTitle("Dataset")
|
|
825
|
+
label_bandid.setText('Band Name:')
|
|
826
|
+
label_tlx.setText("Top Left X Coordinate:")
|
|
827
|
+
label_tly.setText("Top Left Y Coordinate:")
|
|
828
|
+
label_xdim.setText("X Dimension:")
|
|
829
|
+
label_ydim.setText("Y Dimension:")
|
|
830
|
+
label_null.setText("Null/Nodata value:")
|
|
831
|
+
label_rows.setText("Rows:")
|
|
832
|
+
label_cols.setText("Columns:")
|
|
833
|
+
label_min.setText("Dataset Minimum:")
|
|
834
|
+
label_max.setText("Dataset Maximum:")
|
|
835
|
+
label_mean.setText("Dataset Mean:")
|
|
836
|
+
label_units.setText("Dataset Units:")
|
|
837
|
+
|
|
838
|
+
gridlayout_main.addWidget(label_bandid, 0, 0, 1, 1)
|
|
839
|
+
gridlayout_main.addWidget(self.combobox_bandid, 0, 1, 1, 3)
|
|
840
|
+
gridlayout_main.addWidget(self.pb_rename_id, 1, 1, 1, 3)
|
|
841
|
+
gridlayout_main.addWidget(self.groupbox, 2, 0, 1, 2)
|
|
842
|
+
gridlayout_main.addWidget(self.proj, 2, 2, 1, 2)
|
|
843
|
+
gridlayout_main.addWidget(buttonbox, 4, 0, 1, 4)
|
|
844
|
+
|
|
845
|
+
gridlayout.addWidget(label_tlx, 0, 0, 1, 1)
|
|
846
|
+
gridlayout.addWidget(self.dsb_tlx, 0, 1, 1, 1)
|
|
847
|
+
gridlayout.addWidget(label_tly, 1, 0, 1, 1)
|
|
848
|
+
gridlayout.addWidget(self.dsb_tly, 1, 1, 1, 1)
|
|
849
|
+
gridlayout.addWidget(label_xdim, 2, 0, 1, 1)
|
|
850
|
+
gridlayout.addWidget(self.dsb_xdim, 2, 1, 1, 1)
|
|
851
|
+
gridlayout.addWidget(label_ydim, 3, 0, 1, 1)
|
|
852
|
+
gridlayout.addWidget(self.dsb_ydim, 3, 1, 1, 1)
|
|
853
|
+
gridlayout.addWidget(label_null, 4, 0, 1, 1)
|
|
854
|
+
gridlayout.addWidget(self.txt_null, 4, 1, 1, 1)
|
|
855
|
+
gridlayout.addWidget(label_rows, 5, 0, 1, 1)
|
|
856
|
+
gridlayout.addWidget(self.lbl_rows, 5, 1, 1, 1)
|
|
857
|
+
gridlayout.addWidget(label_cols, 6, 0, 1, 1)
|
|
858
|
+
gridlayout.addWidget(self.lbl_cols, 6, 1, 1, 1)
|
|
859
|
+
gridlayout.addWidget(label_min, 7, 0, 1, 1)
|
|
860
|
+
gridlayout.addWidget(self.lbl_min, 7, 1, 1, 1)
|
|
861
|
+
gridlayout.addWidget(label_max, 8, 0, 1, 1)
|
|
862
|
+
gridlayout.addWidget(self.lbl_max, 8, 1, 1, 1)
|
|
863
|
+
gridlayout.addWidget(label_mean, 9, 0, 1, 1)
|
|
864
|
+
gridlayout.addWidget(self.lbl_mean, 9, 1, 1, 1)
|
|
865
|
+
gridlayout.addWidget(label_units, 10, 0, 1, 1)
|
|
866
|
+
gridlayout.addWidget(self.led_units, 10, 1, 1, 1)
|
|
867
|
+
|
|
868
|
+
buttonbox.accepted.connect(self.accept)
|
|
869
|
+
buttonbox.rejected.connect(self.reject)
|
|
870
|
+
|
|
871
|
+
self.combobox_bandid.currentIndexChanged.connect(self.update_vals)
|
|
872
|
+
self.pb_rename_id.clicked.connect(self.rename_id)
|
|
873
|
+
|
|
874
|
+
def acceptall(self):
|
|
875
|
+
"""
|
|
876
|
+
This routine is called by settings() if accept is pressed. It contains
|
|
877
|
+
the main routine.
|
|
878
|
+
"""
|
|
879
|
+
wkt = self.proj.wkt
|
|
880
|
+
|
|
881
|
+
self.update_vals()
|
|
882
|
+
for tmp in self.indata['Raster']:
|
|
883
|
+
for j in self.dataid.items():
|
|
884
|
+
if j[1] == tmp.dataid:
|
|
885
|
+
i = self.banddata[j[0]]
|
|
886
|
+
tmp.dataid = j[0]
|
|
887
|
+
tmp.tlx = i.tlx
|
|
888
|
+
tmp.tly = i.tly
|
|
889
|
+
tmp.xdim = i.xdim
|
|
890
|
+
tmp.ydim = i.ydim
|
|
891
|
+
tmp.rows = i.rows
|
|
892
|
+
tmp.cols = i.cols
|
|
893
|
+
tmp.nullvalue = i.nullvalue
|
|
894
|
+
tmp.wkt = wkt
|
|
895
|
+
tmp.units = i.units
|
|
896
|
+
if tmp.dataid[-1] == ')':
|
|
897
|
+
tmp.dataid = tmp.dataid[:tmp.dataid.rfind(' (')]
|
|
898
|
+
if i.units != '':
|
|
899
|
+
tmp.dataid += ' ('+i.units+')'
|
|
900
|
+
# tmp.data.data[tmp.data.data == i.nullvalue] = np.nan
|
|
901
|
+
tmp.data.mask = (tmp.data.data == i.nullvalue)
|
|
902
|
+
|
|
903
|
+
def rename_id(self):
|
|
904
|
+
""" Renames the band name """
|
|
905
|
+
ctxt = str(self.combobox_bandid.currentText())
|
|
906
|
+
(skey, isokay) = QtGui.QInputDialog.getText(
|
|
907
|
+
self.parent, 'Rename Band Name',
|
|
908
|
+
'Please type in the new name for the band',
|
|
909
|
+
QtGui.QLineEdit.Normal, ctxt)
|
|
910
|
+
|
|
911
|
+
if isokay:
|
|
912
|
+
self.combobox_bandid.currentIndexChanged.disconnect()
|
|
913
|
+
indx = self.combobox_bandid.currentIndex()
|
|
914
|
+
txt = self.combobox_bandid.itemText(indx)
|
|
915
|
+
self.banddata[skey] = self.banddata.pop(txt)
|
|
916
|
+
self.dataid[skey] = self.dataid.pop(txt)
|
|
917
|
+
self.oldtxt = skey
|
|
918
|
+
self.combobox_bandid.setItemText(indx, skey)
|
|
919
|
+
self.combobox_bandid.currentIndexChanged.connect(self.update_vals)
|
|
920
|
+
|
|
921
|
+
def update_vals(self):
|
|
922
|
+
""" Updates the values on the interface """
|
|
923
|
+
odata = self.banddata[self.oldtxt]
|
|
924
|
+
odata.units = self.led_units.text()
|
|
925
|
+
|
|
926
|
+
try:
|
|
927
|
+
odata.nullvalue = float(self.txt_null.text())
|
|
928
|
+
odata.tlx = float(self.dsb_tlx.text())
|
|
929
|
+
odata.tly = float(self.dsb_tly.text())
|
|
930
|
+
odata.xdim = float(self.dsb_xdim.text())
|
|
931
|
+
odata.ydim = float(self.dsb_ydim.text())
|
|
932
|
+
except ValueError:
|
|
933
|
+
self.parent.showprocesslog('Value error - abandoning changes')
|
|
934
|
+
|
|
935
|
+
indx = self.combobox_bandid.currentIndex()
|
|
936
|
+
txt = self.combobox_bandid.itemText(indx)
|
|
937
|
+
self.oldtxt = txt
|
|
938
|
+
idata = self.banddata[txt]
|
|
939
|
+
|
|
940
|
+
self.lbl_cols.setText(str(idata.cols))
|
|
941
|
+
self.lbl_rows.setText(str(idata.rows))
|
|
942
|
+
self.txt_null.setText(str(idata.nullvalue))
|
|
943
|
+
self.dsb_tlx.setText(str(idata.tlx))
|
|
944
|
+
self.dsb_tly.setText(str(idata.tly))
|
|
945
|
+
self.dsb_xdim.setText(str(idata.xdim))
|
|
946
|
+
self.dsb_ydim.setText(str(idata.ydim))
|
|
947
|
+
self.lbl_min.setText(str(idata.min))
|
|
948
|
+
self.lbl_max.setText(str(idata.max))
|
|
949
|
+
self.lbl_mean.setText(str(idata.mean))
|
|
950
|
+
self.led_units.setText(str(idata.units))
|
|
951
|
+
|
|
952
|
+
def run(self):
|
|
953
|
+
""" Entrypoint to start this routine """
|
|
954
|
+
|
|
955
|
+
bandid = []
|
|
956
|
+
self.proj.set_current(self.indata['Raster'][0].wkt)
|
|
957
|
+
|
|
958
|
+
for i in self.indata['Raster']:
|
|
959
|
+
bandid.append(i.dataid)
|
|
960
|
+
self.banddata[i.dataid] = Data()
|
|
961
|
+
tmp = self.banddata[i.dataid]
|
|
962
|
+
self.dataid[i.dataid] = i.dataid
|
|
963
|
+
tmp.tlx = i.tlx
|
|
964
|
+
tmp.tly = i.tly
|
|
965
|
+
tmp.xdim = i.xdim
|
|
966
|
+
tmp.ydim = i.ydim
|
|
967
|
+
tmp.rows = i.rows
|
|
968
|
+
tmp.cols = i.cols
|
|
969
|
+
tmp.nullvalue = i.nullvalue
|
|
970
|
+
tmp.wkt = i.wkt
|
|
971
|
+
tmp.min = i.data.min()
|
|
972
|
+
tmp.max = i.data.max()
|
|
973
|
+
tmp.mean = i.data.mean()
|
|
974
|
+
try:
|
|
975
|
+
tmp.units = i.units
|
|
976
|
+
except AttributeError:
|
|
977
|
+
tmp.units = ''
|
|
978
|
+
|
|
979
|
+
self.combobox_bandid.currentIndexChanged.disconnect()
|
|
980
|
+
self.combobox_bandid.addItems(bandid)
|
|
981
|
+
indx = self.combobox_bandid.currentIndex()
|
|
982
|
+
self.oldtxt = self.combobox_bandid.itemText(indx)
|
|
983
|
+
self.combobox_bandid.currentIndexChanged.connect(self.update_vals)
|
|
984
|
+
|
|
985
|
+
idata = self.banddata[self.oldtxt]
|
|
986
|
+
self.lbl_cols.setText(str(idata.cols))
|
|
987
|
+
self.lbl_rows.setText(str(idata.rows))
|
|
988
|
+
self.txt_null.setText(str(idata.nullvalue))
|
|
989
|
+
self.dsb_tlx.setText(str(idata.tlx))
|
|
990
|
+
self.dsb_tly.setText(str(idata.tly))
|
|
991
|
+
self.dsb_xdim.setText(str(idata.xdim))
|
|
992
|
+
self.dsb_ydim.setText(str(idata.ydim))
|
|
993
|
+
self.lbl_min.setText(str(idata.min))
|
|
994
|
+
self.lbl_max.setText(str(idata.max))
|
|
995
|
+
self.lbl_mean.setText(str(idata.mean))
|
|
996
|
+
self.led_units.setText(str(idata.units))
|
|
997
|
+
|
|
998
|
+
self.update_vals()
|
|
999
|
+
|
|
1000
|
+
tmp = self.exec_()
|
|
1001
|
+
if tmp == 1:
|
|
1002
|
+
self.acceptall()
|
|
1003
|
+
tmp = True
|
|
1004
|
+
|
|
1005
|
+
return tmp
|
|
1006
|
+
|
|
1007
|
+
|
|
1008
|
+
class RTP(QtGui.QDialog):
|
|
1009
|
+
"""
|
|
1010
|
+
Perform Reduction to the Pole on Magnetic data.
|
|
1011
|
+
|
|
1012
|
+
This class grids point data using a nearest neighbourhood technique.
|
|
1013
|
+
|
|
1014
|
+
Attributes
|
|
1015
|
+
----------
|
|
1016
|
+
parent : parent
|
|
1017
|
+
reference to the parent routine
|
|
1018
|
+
indata : dictionary
|
|
1019
|
+
dictionary of input datasets
|
|
1020
|
+
outdata : dictionary
|
|
1021
|
+
dictionary of output datasets
|
|
1022
|
+
"""
|
|
1023
|
+
def __init__(self, parent=None):
|
|
1024
|
+
QtGui.QDialog.__init__(self, parent)
|
|
1025
|
+
|
|
1026
|
+
self.indata = {}
|
|
1027
|
+
self.outdata = {}
|
|
1028
|
+
self.parent = parent
|
|
1029
|
+
self.pbar = self.parent.pbar
|
|
1030
|
+
|
|
1031
|
+
self.dataid = QtGui.QComboBox()
|
|
1032
|
+
self.dsb_inc = QtGui.QDoubleSpinBox()
|
|
1033
|
+
self.dsb_dec = QtGui.QDoubleSpinBox()
|
|
1034
|
+
|
|
1035
|
+
self.setupui()
|
|
1036
|
+
|
|
1037
|
+
def setupui(self):
|
|
1038
|
+
""" Setup UI """
|
|
1039
|
+
gridlayout_main = QtGui.QGridLayout(self)
|
|
1040
|
+
buttonbox = QtGui.QDialogButtonBox()
|
|
1041
|
+
helpdocs = menu_default.HelpButton('pygmi.raster.dataprep.rtp')
|
|
1042
|
+
label_band = QtGui.QLabel()
|
|
1043
|
+
label_inc = QtGui.QLabel()
|
|
1044
|
+
label_dec = QtGui.QLabel()
|
|
1045
|
+
|
|
1046
|
+
self.dsb_inc.setMaximum(90.0)
|
|
1047
|
+
self.dsb_inc.setMinimum(-90.0)
|
|
1048
|
+
self.dsb_dec.setMaximum(360.0)
|
|
1049
|
+
self.dsb_dec.setMinimum(-360.0)
|
|
1050
|
+
# self.dsb_dxy.setDecimals(5)
|
|
1051
|
+
buttonbox.setOrientation(QtCore.Qt.Horizontal)
|
|
1052
|
+
buttonbox.setCenterButtons(True)
|
|
1053
|
+
buttonbox.setStandardButtons(buttonbox.Cancel | buttonbox.Ok)
|
|
1054
|
+
|
|
1055
|
+
self.setWindowTitle("Reduction to the Pole")
|
|
1056
|
+
label_band.setText("Band to Reduce to the Pole:")
|
|
1057
|
+
label_inc.setText("Inclination of Magnetic Field:")
|
|
1058
|
+
label_dec.setText("Declination of Magnetic Field:")
|
|
1059
|
+
|
|
1060
|
+
gridlayout_main.addWidget(label_band, 0, 0, 1, 1)
|
|
1061
|
+
gridlayout_main.addWidget(self.dataid, 0, 1, 1, 1)
|
|
1062
|
+
|
|
1063
|
+
gridlayout_main.addWidget(label_inc, 1, 0, 1, 1)
|
|
1064
|
+
gridlayout_main.addWidget(self.dsb_inc, 1, 1, 1, 1)
|
|
1065
|
+
gridlayout_main.addWidget(label_dec, 2, 0, 1, 1)
|
|
1066
|
+
gridlayout_main.addWidget(self.dsb_dec, 2, 1, 1, 1)
|
|
1067
|
+
gridlayout_main.addWidget(helpdocs, 3, 0, 1, 1)
|
|
1068
|
+
gridlayout_main.addWidget(buttonbox, 3, 1, 1, 3)
|
|
1069
|
+
|
|
1070
|
+
buttonbox.accepted.connect(self.accept)
|
|
1071
|
+
buttonbox.rejected.connect(self.reject)
|
|
1072
|
+
|
|
1073
|
+
def settings(self):
|
|
1074
|
+
""" Settings """
|
|
1075
|
+
tmp = []
|
|
1076
|
+
if 'Raster' not in self.indata:
|
|
1077
|
+
return False
|
|
1078
|
+
|
|
1079
|
+
for i in self.indata['Raster']:
|
|
1080
|
+
tmp.append(i.dataid)
|
|
1081
|
+
|
|
1082
|
+
self.dataid.addItems(tmp)
|
|
1083
|
+
|
|
1084
|
+
self.dsb_inc.setValue(-62.5)
|
|
1085
|
+
self.dsb_dec.setValue(-16.75)
|
|
1086
|
+
tmp = self.exec_()
|
|
1087
|
+
|
|
1088
|
+
if tmp == 1:
|
|
1089
|
+
self.acceptall()
|
|
1090
|
+
tmp = True
|
|
1091
|
+
|
|
1092
|
+
return tmp
|
|
1093
|
+
|
|
1094
|
+
def acceptall(self):
|
|
1095
|
+
""" accept """
|
|
1096
|
+
I_deg = self.dsb_inc.value()
|
|
1097
|
+
D_deg = self.dsb_dec.value()
|
|
1098
|
+
|
|
1099
|
+
newdat = []
|
|
1100
|
+
for data in self.pbar.iter(self.indata['Raster']):
|
|
1101
|
+
if data.dataid != self.dataid.currentText():
|
|
1102
|
+
continue
|
|
1103
|
+
dat = rtp(data, I_deg, D_deg)
|
|
1104
|
+
newdat.append(dat)
|
|
1105
|
+
|
|
1106
|
+
self.outdata['Raster'] = newdat
|
|
1107
|
+
|
|
1108
|
+
|
|
1109
|
+
def rtp(data, I_deg, D_deg):
|
|
1110
|
+
""" Reduction to the Pole """
|
|
1111
|
+
|
|
1112
|
+
datamedian = np.ma.median(data.data)
|
|
1113
|
+
ndat = data.data - datamedian
|
|
1114
|
+
ndat[ndat.mask] = 0
|
|
1115
|
+
|
|
1116
|
+
fftmod = np.fft.fft2(ndat)
|
|
1117
|
+
|
|
1118
|
+
ny, nx = fftmod.shape
|
|
1119
|
+
nyqx = 1/(2*data.xdim)
|
|
1120
|
+
nyqy = 1/(2*data.ydim)
|
|
1121
|
+
|
|
1122
|
+
kx = np.linspace(-nyqx, nyqx, nx)
|
|
1123
|
+
ky = np.linspace(-nyqy, nyqy, ny)
|
|
1124
|
+
|
|
1125
|
+
KX, KY = np.meshgrid(kx, ky)
|
|
1126
|
+
|
|
1127
|
+
I = np.deg2rad(I_deg)
|
|
1128
|
+
D = np.deg2rad(D_deg)
|
|
1129
|
+
alpha = np.arctan2(KX, KY)
|
|
1130
|
+
filt = 1/(np.sin(I)+1j*np.cos(I)*np.cos(D-alpha))**2
|
|
1131
|
+
|
|
1132
|
+
zrtp = np.fft.ifft2(fftmod*filt)
|
|
1133
|
+
zrtp = np.abs(zrtp) + datamedian
|
|
1134
|
+
|
|
1135
|
+
# Create dataset
|
|
1136
|
+
dat = Data()
|
|
1137
|
+
dat.data = np.ma.masked_invalid(np.abs(zrtp))
|
|
1138
|
+
dat.data.mask = data.data.mask
|
|
1139
|
+
dat.rows, dat.cols = zrtp.shape
|
|
1140
|
+
dat.nullvalue = data.data.fill_value
|
|
1141
|
+
dat.dataid = data.dataid
|
|
1142
|
+
dat.tlx = data.tlx
|
|
1143
|
+
dat.tly = data.tly
|
|
1144
|
+
dat.xdim = data.xdim
|
|
1145
|
+
dat.ydim = data.ydim
|
|
1146
|
+
|
|
1147
|
+
return dat
|
|
1148
|
+
|
|
1149
|
+
|
|
1150
|
+
def check_dataid(out):
|
|
1151
|
+
""" Checks dataid for duplicates and renames where necessary """
|
|
1152
|
+
tmplist = []
|
|
1153
|
+
for i in out:
|
|
1154
|
+
tmplist.append(i.dataid)
|
|
1155
|
+
|
|
1156
|
+
tmpcnt = Counter(tmplist)
|
|
1157
|
+
for elt, count in tmpcnt.items():
|
|
1158
|
+
j = 1
|
|
1159
|
+
for i in out:
|
|
1160
|
+
if elt == i.dataid and count > 1:
|
|
1161
|
+
i.dataid += '('+str(j)+')'
|
|
1162
|
+
j += 1
|
|
1163
|
+
|
|
1164
|
+
return out
|
|
1165
|
+
|
|
1166
|
+
|
|
1167
|
+
def cluster_to_raster(indata):
|
|
1168
|
+
""" Converts cluster datasets to raster datasets
|
|
1169
|
+
|
|
1170
|
+
Some routines will not understand the datasets produced by cluster
|
|
1171
|
+
analysis routines, since they are designated 'Cluster' and not 'Raster'.
|
|
1172
|
+
This provides a work-around for that.
|
|
1173
|
+
|
|
1174
|
+
Parameters
|
|
1175
|
+
----------
|
|
1176
|
+
indata : Data
|
|
1177
|
+
PyGMI raster dataset
|
|
1178
|
+
|
|
1179
|
+
Returns
|
|
1180
|
+
-------
|
|
1181
|
+
Data
|
|
1182
|
+
PyGMI raster dataset
|
|
1183
|
+
|
|
1184
|
+
"""
|
|
1185
|
+
if 'Cluster' not in indata:
|
|
1186
|
+
return indata
|
|
1187
|
+
if 'Raster' not in indata:
|
|
1188
|
+
indata['Raster'] = []
|
|
1189
|
+
|
|
1190
|
+
for i in indata['Cluster']:
|
|
1191
|
+
indata['Raster'].append(i)
|
|
1192
|
+
indata['Raster'][-1].data += 1
|
|
1193
|
+
|
|
1194
|
+
return indata
|
|
1195
|
+
|
|
1196
|
+
|
|
1197
|
+
def cut_raster(data, ifile):
|
|
1198
|
+
"""Cuts a raster dataset
|
|
1199
|
+
|
|
1200
|
+
Cut a raster dataset using a shapefile
|
|
1201
|
+
|
|
1202
|
+
Parameters
|
|
1203
|
+
----------
|
|
1204
|
+
data : Data
|
|
1205
|
+
PyGMI Dataset
|
|
1206
|
+
ifile : str
|
|
1207
|
+
shapefile used to cut data
|
|
1208
|
+
|
|
1209
|
+
Returns
|
|
1210
|
+
-------
|
|
1211
|
+
Data
|
|
1212
|
+
PyGMI Dataset
|
|
1213
|
+
"""
|
|
1214
|
+
shapef = ogr.Open(ifile)
|
|
1215
|
+
if shapef is None:
|
|
1216
|
+
return None
|
|
1217
|
+
lyr = shapef.GetLayer()
|
|
1218
|
+
poly = lyr.GetNextFeature()
|
|
1219
|
+
if lyr.GetGeomType() is not ogr.wkbPolygon or poly is None:
|
|
1220
|
+
# self.parent.showprocesslog('You need polygons in that shape file')
|
|
1221
|
+
return
|
|
1222
|
+
|
|
1223
|
+
for idata in data:
|
|
1224
|
+
# Convert the layer extent to image pixel coordinates
|
|
1225
|
+
minX, maxX, minY, maxY = lyr.GetExtent()
|
|
1226
|
+
ulX = max(0, int((minX - idata.tlx) / idata.xdim))
|
|
1227
|
+
ulY = max(0, int((idata.tly - maxY) / idata.ydim))
|
|
1228
|
+
lrX = int((maxX - idata.tlx) / idata.xdim)
|
|
1229
|
+
lrY = int((idata.tly - minY) / idata.ydim)
|
|
1230
|
+
|
|
1231
|
+
# Map points to pixels for drawing the
|
|
1232
|
+
# boundary on a mas image
|
|
1233
|
+
points = []
|
|
1234
|
+
pixels = []
|
|
1235
|
+
geom = poly.GetGeometryRef()
|
|
1236
|
+
|
|
1237
|
+
ifin = 0
|
|
1238
|
+
imax = 0
|
|
1239
|
+
if geom.GetGeometryName() == 'MULTIPOLYGON':
|
|
1240
|
+
for i in range(geom.GetGeometryCount()):
|
|
1241
|
+
geom.GetGeometryRef(i)
|
|
1242
|
+
itmp = geom.GetGeometryRef(i)
|
|
1243
|
+
itmp = itmp.GetGeometryRef(0).GetPointCount()
|
|
1244
|
+
if itmp > imax:
|
|
1245
|
+
imax = itmp
|
|
1246
|
+
ifin = i
|
|
1247
|
+
geom = geom.GetGeometryRef(ifin)
|
|
1248
|
+
|
|
1249
|
+
pts = geom.GetGeometryRef(0)
|
|
1250
|
+
for p in range(pts.GetPointCount()):
|
|
1251
|
+
points.append((pts.GetX(p), pts.GetY(p)))
|
|
1252
|
+
for p in points:
|
|
1253
|
+
tmpx = int((p[0] - idata.tlx) / idata.xdim)
|
|
1254
|
+
tmpy = int((idata.tly - p[1]) / idata.ydim)
|
|
1255
|
+
pixels.append((tmpx, tmpy))
|
|
1256
|
+
rasterPoly = Image.new("L", (idata.cols, idata.rows), 1)
|
|
1257
|
+
rasterize = ImageDraw.Draw(rasterPoly)
|
|
1258
|
+
rasterize.polygon(pixels, 0)
|
|
1259
|
+
mask = np.array(rasterPoly)
|
|
1260
|
+
|
|
1261
|
+
idata.data.mask = mask
|
|
1262
|
+
idata.data = idata.data[ulY:lrY, ulX:lrX]
|
|
1263
|
+
idata.cols = idata.data.shape[1]
|
|
1264
|
+
idata.rows = idata.data.shape[0]
|
|
1265
|
+
idata.tlx = ulX*idata.xdim + idata.tlx # minX
|
|
1266
|
+
idata.tly = idata.tly - ulY*idata.ydim # maxY
|
|
1267
|
+
data = trim_raster(data)
|
|
1268
|
+
return data
|
|
1269
|
+
|
|
1270
|
+
|
|
1271
|
+
def dat_extent(dat):
|
|
1272
|
+
""" Gets the extend of the dat variable """
|
|
1273
|
+
left = dat.tlx
|
|
1274
|
+
top = dat.tly
|
|
1275
|
+
right = left + dat.cols*dat.xdim
|
|
1276
|
+
bottom = top - dat.rows*dat.ydim
|
|
1277
|
+
return (left, right, bottom, top)
|
|
1278
|
+
|
|
1279
|
+
|
|
1280
|
+
def data_to_gdal_mem(data, gtr, wkt, cols, rows, nodata=False):
|
|
1281
|
+
"""
|
|
1282
|
+
Data to GDAL mem format
|
|
1283
|
+
|
|
1284
|
+
Parameters
|
|
1285
|
+
----------
|
|
1286
|
+
data : PyGMI Data
|
|
1287
|
+
PyGMI Dataset
|
|
1288
|
+
gtr : tuple
|
|
1289
|
+
Geotransform
|
|
1290
|
+
wkt : str
|
|
1291
|
+
Projection in wkt (well known text) format
|
|
1292
|
+
cols : int
|
|
1293
|
+
columns
|
|
1294
|
+
rows : int
|
|
1295
|
+
rows
|
|
1296
|
+
nodata : bool, optional
|
|
1297
|
+
no data
|
|
1298
|
+
|
|
1299
|
+
Returns
|
|
1300
|
+
-------
|
|
1301
|
+
src - GDAL mem format
|
|
1302
|
+
"""
|
|
1303
|
+
data.data = np.ma.array(data.data)
|
|
1304
|
+
dtype = data.data.dtype
|
|
1305
|
+
# Get rid of array() which can break driver.create later
|
|
1306
|
+
cols = int(cols)
|
|
1307
|
+
rows = int(rows)
|
|
1308
|
+
|
|
1309
|
+
if dtype == np.uint8:
|
|
1310
|
+
fmt = gdal.GDT_Byte
|
|
1311
|
+
elif dtype == np.int32:
|
|
1312
|
+
fmt = gdal.GDT_Int32
|
|
1313
|
+
elif dtype == np.float64:
|
|
1314
|
+
fmt = gdal.GDT_Float64
|
|
1315
|
+
else:
|
|
1316
|
+
fmt = gdal.GDT_Float32
|
|
1317
|
+
|
|
1318
|
+
driver = gdal.GetDriverByName('MEM')
|
|
1319
|
+
src = driver.Create('', cols, rows, 1, fmt)
|
|
1320
|
+
|
|
1321
|
+
src.SetGeoTransform(gtr)
|
|
1322
|
+
src.SetProjection(wkt)
|
|
1323
|
+
|
|
1324
|
+
if nodata is False:
|
|
1325
|
+
if data.nullvalue is not None:
|
|
1326
|
+
src.GetRasterBand(1).SetNoDataValue(data.nullvalue)
|
|
1327
|
+
src.GetRasterBand(1).WriteArray(data.data)
|
|
1328
|
+
else:
|
|
1329
|
+
tmp = np.ma.masked_all((rows, cols))
|
|
1330
|
+
src.GetRasterBand(1).SetNoDataValue(0) # Set to this because of Reproj
|
|
1331
|
+
src.GetRasterBand(1).WriteArray(tmp)
|
|
1332
|
+
|
|
1333
|
+
return src
|
|
1334
|
+
|
|
1335
|
+
|
|
1336
|
+
def epsgtowkt(epsg):
|
|
1337
|
+
""" Convenience routine to get a wkt from an epsg code """
|
|
1338
|
+
orig = osr.SpatialReference()
|
|
1339
|
+
err = orig.ImportFromEPSG(int(epsg))
|
|
1340
|
+
if err != 0:
|
|
1341
|
+
return ''
|
|
1342
|
+
out = orig.ExportToWkt()
|
|
1343
|
+
return out
|
|
1344
|
+
|
|
1345
|
+
|
|
1346
|
+
def gdal_to_dat(dest, bandid='Data'):
|
|
1347
|
+
"""
|
|
1348
|
+
GDAL to Data format
|
|
1349
|
+
|
|
1350
|
+
Parameters
|
|
1351
|
+
----------
|
|
1352
|
+
dest - GDAL format
|
|
1353
|
+
GDAL format
|
|
1354
|
+
bandid - str
|
|
1355
|
+
band identity
|
|
1356
|
+
"""
|
|
1357
|
+
dat = Data()
|
|
1358
|
+
gtr = dest.GetGeoTransform()
|
|
1359
|
+
|
|
1360
|
+
rtmp = dest.GetRasterBand(1)
|
|
1361
|
+
dat.data = rtmp.ReadAsArray()
|
|
1362
|
+
nval = rtmp.GetNoDataValue()
|
|
1363
|
+
dat.data = np.ma.masked_equal(dat.data, nval)
|
|
1364
|
+
|
|
1365
|
+
# dtype = dat.data.dtype
|
|
1366
|
+
# nval = np.nan
|
|
1367
|
+
# if dtype == np.float32 or dtype == np.float64:
|
|
1368
|
+
# dat.data[dat.data == 0.] = np.nan
|
|
1369
|
+
# # dat.data[dat.data == rtmp.GetNoDataValue()] = np.nan
|
|
1370
|
+
# dat.data = np.ma.masked_invalid(nval)
|
|
1371
|
+
#
|
|
1372
|
+
# if dtype == np.uint8:
|
|
1373
|
+
# dat.data = np.ma.masked_equal(dat.data, 0)
|
|
1374
|
+
# nval = 0
|
|
1375
|
+
|
|
1376
|
+
# dat.data[dat.data.mask] = rtmp.GetNoDataValue()
|
|
1377
|
+
|
|
1378
|
+
dat.nrofbands = dest.RasterCount
|
|
1379
|
+
dat.tlx = gtr[0]
|
|
1380
|
+
dat.tly = gtr[3]
|
|
1381
|
+
dat.dataid = bandid
|
|
1382
|
+
dat.nullvalue = nval
|
|
1383
|
+
dat.rows = dest.RasterYSize
|
|
1384
|
+
dat.cols = dest.RasterXSize
|
|
1385
|
+
dat.xdim = abs(gtr[1])
|
|
1386
|
+
dat.ydim = abs(gtr[5])
|
|
1387
|
+
dat.wkt = dest.GetProjection()
|
|
1388
|
+
dat.gtr = gtr
|
|
1389
|
+
|
|
1390
|
+
return dat
|
|
1391
|
+
|
|
1392
|
+
|
|
1393
|
+
def getepsgcodes():
|
|
1394
|
+
"""
|
|
1395
|
+
Convenience function used to get a list of EPSG codes
|
|
1396
|
+
"""
|
|
1397
|
+
dfile = open(os.environ['GDAL_DATA']+'\\gcs.csv')
|
|
1398
|
+
dlines = dfile.readlines()
|
|
1399
|
+
dfile.close()
|
|
1400
|
+
|
|
1401
|
+
dlines = dlines[1:]
|
|
1402
|
+
dcodes = {}
|
|
1403
|
+
for i in dlines:
|
|
1404
|
+
tmp = i.split(',')
|
|
1405
|
+
if tmp[1][0] == '"':
|
|
1406
|
+
tmp[1] = tmp[1][1:]
|
|
1407
|
+
if tmp[1][-1] == '"':
|
|
1408
|
+
tmp[1] = tmp[1][:-1]
|
|
1409
|
+
wkttmp = epsgtowkt(tmp[0])
|
|
1410
|
+
if wkttmp != '':
|
|
1411
|
+
dcodes[tmp[1]] = wkttmp
|
|
1412
|
+
|
|
1413
|
+
pfile = open(os.environ['GDAL_DATA']+'\\pcs.csv')
|
|
1414
|
+
plines = pfile.readlines()
|
|
1415
|
+
pfile.close()
|
|
1416
|
+
|
|
1417
|
+
pcodes = {}
|
|
1418
|
+
for i in dcodes.keys():
|
|
1419
|
+
pcodes[i+r' / Geodetic Geographic'] = dcodes[i]
|
|
1420
|
+
|
|
1421
|
+
plines = plines[1:]
|
|
1422
|
+
for i in plines:
|
|
1423
|
+
tmp = i.split(',')
|
|
1424
|
+
if tmp[1][0] == '"':
|
|
1425
|
+
tmp[1] = tmp[1][1:]
|
|
1426
|
+
if tmp[1][-1] == '"':
|
|
1427
|
+
tmp[1] = tmp[1][:-1]
|
|
1428
|
+
wkttmp = epsgtowkt(tmp[0])
|
|
1429
|
+
if wkttmp != '':
|
|
1430
|
+
pcodes[tmp[1]] = wkttmp
|
|
1431
|
+
|
|
1432
|
+
clat = 0.
|
|
1433
|
+
scale = 1.
|
|
1434
|
+
f_e = 0.
|
|
1435
|
+
f_n = 0.
|
|
1436
|
+
orig = osr.SpatialReference()
|
|
1437
|
+
|
|
1438
|
+
for datum in ['Cape', 'Hartebeesthoek94']:
|
|
1439
|
+
orig.ImportFromWkt(dcodes[datum])
|
|
1440
|
+
for clong in range(15, 35, 2):
|
|
1441
|
+
orig.SetTM(clat, clong, scale, f_e, f_n)
|
|
1442
|
+
orig.SetProjCS(datum+r' / TM'+str(clong))
|
|
1443
|
+
pcodes[datum+r' / TM'+str(clong)] = orig.ExportToWkt()
|
|
1444
|
+
|
|
1445
|
+
return pcodes
|
|
1446
|
+
|
|
1447
|
+
|
|
1448
|
+
def merge(dat):
|
|
1449
|
+
""" Merges datasets found in a single PyGMI data object.
|
|
1450
|
+
|
|
1451
|
+
The aim is to ensure that all datasets have the same number of rows and
|
|
1452
|
+
columns.
|
|
1453
|
+
|
|
1454
|
+
Parameters
|
|
1455
|
+
----------
|
|
1456
|
+
dat : Data
|
|
1457
|
+
data object which stores datasets
|
|
1458
|
+
|
|
1459
|
+
Returns
|
|
1460
|
+
-------
|
|
1461
|
+
Data
|
|
1462
|
+
data object which stores datasets
|
|
1463
|
+
"""
|
|
1464
|
+
needsmerge = False
|
|
1465
|
+
for i in dat:
|
|
1466
|
+
if i.rows != dat[0].rows or i.cols != dat[0].cols:
|
|
1467
|
+
needsmerge = True
|
|
1468
|
+
|
|
1469
|
+
if needsmerge is False:
|
|
1470
|
+
dat = check_dataid(dat)
|
|
1471
|
+
return dat
|
|
1472
|
+
|
|
1473
|
+
mrg = DataMerge()
|
|
1474
|
+
mrg.indata['Raster'] = dat
|
|
1475
|
+
data = dat[0]
|
|
1476
|
+
dxy0 = min(data.xdim, data.ydim)
|
|
1477
|
+
for data in dat:
|
|
1478
|
+
dxy = min(dxy0, data.xdim, data.ydim)
|
|
1479
|
+
|
|
1480
|
+
mrg.dsb_dxy.setValue(dxy)
|
|
1481
|
+
mrg.acceptall()
|
|
1482
|
+
out = mrg.outdata['Raster']
|
|
1483
|
+
|
|
1484
|
+
out = check_dataid(out)
|
|
1485
|
+
|
|
1486
|
+
return out
|
|
1487
|
+
|
|
1488
|
+
|
|
1489
|
+
#def taper(data):
|
|
1490
|
+
# nr, nc = data.shape
|
|
1491
|
+
# nmax = np.max([nr, nc])
|
|
1492
|
+
# npts = int(2**cooper.__nextpow2(nmax))
|
|
1493
|
+
# npts *= 2
|
|
1494
|
+
#
|
|
1495
|
+
# cdiff = int(np.floor((npts-nc)/2))
|
|
1496
|
+
# rdiff = int(np.floor((npts-nr)/2))
|
|
1497
|
+
# data1 = cooper.__taper2d(data, npts, nc, nr, cdiff, rdiff)
|
|
1498
|
+
## data1 = np.pad(data-np.median(data), ((rdiff, cdiff), (rdiff,cdiff)), 'edge')
|
|
1499
|
+
|
|
1500
|
+
# return data1
|
|
1501
|
+
|
|
1502
|
+
|
|
1503
|
+
def trim_raster(olddata):
|
|
1504
|
+
""" Function to trim nulls from a raster dataset.
|
|
1505
|
+
|
|
1506
|
+
This function trims entire rows or columns of data which have only nulls,
|
|
1507
|
+
and are on the edges of the dataset.
|
|
1508
|
+
|
|
1509
|
+
Parameters
|
|
1510
|
+
----------
|
|
1511
|
+
olddata : Data
|
|
1512
|
+
PyGMI dataset
|
|
1513
|
+
|
|
1514
|
+
Returns
|
|
1515
|
+
-------
|
|
1516
|
+
Data
|
|
1517
|
+
PyGMI dataset
|
|
1518
|
+
"""
|
|
1519
|
+
|
|
1520
|
+
for data in olddata:
|
|
1521
|
+
mask = data.data.mask
|
|
1522
|
+
data.data[mask] = data.nullvalue
|
|
1523
|
+
|
|
1524
|
+
rowstart = 0
|
|
1525
|
+
for i in range(mask.shape[0]):
|
|
1526
|
+
if bool(mask[i].min()) is False:
|
|
1527
|
+
break
|
|
1528
|
+
rowstart += 1
|
|
1529
|
+
|
|
1530
|
+
rowend = mask.shape[0]
|
|
1531
|
+
for i in range(mask.shape[0]-1, -1, -1):
|
|
1532
|
+
if bool(mask[i].min()) is False:
|
|
1533
|
+
break
|
|
1534
|
+
rowend -= 1
|
|
1535
|
+
|
|
1536
|
+
colstart = 0
|
|
1537
|
+
for i in range(mask.shape[1]):
|
|
1538
|
+
if bool(mask[:, i].min()) is False:
|
|
1539
|
+
break
|
|
1540
|
+
colstart += 1
|
|
1541
|
+
|
|
1542
|
+
colend = mask.shape[1]
|
|
1543
|
+
for i in range(mask.shape[1]-1, -1, -1):
|
|
1544
|
+
if bool(mask[:, i].min()) is False:
|
|
1545
|
+
break
|
|
1546
|
+
colend -= 1
|
|
1547
|
+
|
|
1548
|
+
data.data = data.data[rowstart:rowend, colstart:colend]
|
|
1549
|
+
data.data.mask = (data.data.data == data.nullvalue)
|
|
1550
|
+
# data.data = np.ma.masked_invalid(data.data[rowstart:rowend,
|
|
1551
|
+
# colstart:colend])
|
|
1552
|
+
data.rows, data.cols = data.data.shape
|
|
1553
|
+
data.tlx = data.tlx + colstart*data.xdim
|
|
1554
|
+
data.tly = data.tly - rowstart*data.ydim
|
|
1555
|
+
|
|
1556
|
+
return olddata
|
|
1557
|
+
|
|
1558
|
+
|
|
1559
|
+
def quickgrid(x, y, z, dxy, showtext=None, numits=4):
|
|
1560
|
+
"""
|
|
1561
|
+
Do a quick grid
|
|
1562
|
+
|
|
1563
|
+
Parameters
|
|
1564
|
+
----------
|
|
1565
|
+
x : numpy array
|
|
1566
|
+
array of x coordinates
|
|
1567
|
+
y : numpy array
|
|
1568
|
+
array of y coordinates
|
|
1569
|
+
z : numpy array
|
|
1570
|
+
array of z values - this is the column being gridded
|
|
1571
|
+
dxy : float
|
|
1572
|
+
cell size for the grid, in both the x and y direction.
|
|
1573
|
+
showtext : module, optional
|
|
1574
|
+
showtext provided an alternative to print
|
|
1575
|
+
numits : int
|
|
1576
|
+
number of iterations. By default its 4. If this is negative, a maximum
|
|
1577
|
+
numits will be calculated and used.
|
|
1578
|
+
|
|
1579
|
+
Returns
|
|
1580
|
+
-------
|
|
1581
|
+
newz : numpy array
|
|
1582
|
+
M x N array of z values
|
|
1583
|
+
"""
|
|
1584
|
+
|
|
1585
|
+
if showtext is None:
|
|
1586
|
+
showtext = print
|
|
1587
|
+
|
|
1588
|
+
showtext('Creating Grid')
|
|
1589
|
+
|
|
1590
|
+
xmin = x.min()
|
|
1591
|
+
xmax = x.max()
|
|
1592
|
+
ymin = y.min()
|
|
1593
|
+
ymax = y.max()
|
|
1594
|
+
newmask = np.array([1])
|
|
1595
|
+
j = -1
|
|
1596
|
+
rows = int((ymax-ymin)/dxy)+1
|
|
1597
|
+
cols = int((xmax-xmin)/dxy)+1
|
|
1598
|
+
|
|
1599
|
+
if numits < 1:
|
|
1600
|
+
numits = int(max(np.log2(cols), np.log2(rows)))
|
|
1601
|
+
|
|
1602
|
+
while newmask.max() > 0 and j < (numits-1):
|
|
1603
|
+
j += 1
|
|
1604
|
+
jj = 2**j
|
|
1605
|
+
dxy2 = dxy*jj
|
|
1606
|
+
rows = int((ymax-ymin)/dxy2)+1
|
|
1607
|
+
cols = int((xmax-xmin)/dxy2)+1
|
|
1608
|
+
|
|
1609
|
+
newz = np.zeros([rows, cols])
|
|
1610
|
+
zdiv = np.zeros([rows, cols])
|
|
1611
|
+
|
|
1612
|
+
xindex = ((x-xmin)/dxy2).astype(int)
|
|
1613
|
+
yindex = ((y-ymin)/dxy2).astype(int)
|
|
1614
|
+
|
|
1615
|
+
for i in range(z.size):
|
|
1616
|
+
newz[yindex[i], xindex[i]] += z[i]
|
|
1617
|
+
zdiv[yindex[i], xindex[i]] += 1
|
|
1618
|
+
|
|
1619
|
+
filt = zdiv > 0
|
|
1620
|
+
newz[filt] = newz[filt]/zdiv[filt]
|
|
1621
|
+
|
|
1622
|
+
if j == 0:
|
|
1623
|
+
newmask = np.ones([rows, cols])
|
|
1624
|
+
for i in range(z.size):
|
|
1625
|
+
newmask[yindex[i], xindex[i]] = 0
|
|
1626
|
+
zfin = newz
|
|
1627
|
+
else:
|
|
1628
|
+
xx, yy = np.nonzero(newmask)
|
|
1629
|
+
xx2 = xx//jj
|
|
1630
|
+
yy2 = yy//jj
|
|
1631
|
+
zfin[xx, yy] = newz[xx2, yy2]
|
|
1632
|
+
newmask[xx, yy] = np.logical_not(zdiv[xx2, yy2])
|
|
1633
|
+
|
|
1634
|
+
showtext('Iteration done: '+str(j+1)+' of '+str(numits))
|
|
1635
|
+
|
|
1636
|
+
showtext('Finished!')
|
|
1637
|
+
|
|
1638
|
+
newz = np.ma.array(zfin)
|
|
1639
|
+
newz.mask = newmask
|
|
1640
|
+
return newz
|