pygmi 2.2.7__zip

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. pygmi-2.2.7/LICENSE.txt +623 -0
  2. pygmi-2.2.7/MANIFEST.in +7 -0
  3. pygmi-2.2.7/PKG-INFO +47 -0
  4. pygmi-2.2.7/README.md +55 -0
  5. pygmi-2.2.7/README.rst +20 -0
  6. pygmi-2.2.7/log.txt +242 -0
  7. pygmi-2.2.7/pygmi/__init__.py +22 -0
  8. pygmi-2.2.7/pygmi/clust/__init__.py +4 -0
  9. pygmi-2.2.7/pygmi/clust/crisp_clust.py +708 -0
  10. pygmi-2.2.7/pygmi/clust/datatypes.py +65 -0
  11. pygmi-2.2.7/pygmi/clust/fuzzy_clust.py +906 -0
  12. pygmi-2.2.7/pygmi/clust/graphs.py +421 -0
  13. pygmi-2.2.7/pygmi/clust/graphtool.py +667 -0
  14. pygmi-2.2.7/pygmi/clust/menu.py +139 -0
  15. pygmi-2.2.7/pygmi/clust/var_ratio.py +92 -0
  16. pygmi-2.2.7/pygmi/clust/xie_beni.py +93 -0
  17. pygmi-2.2.7/pygmi/helpdocs/linepointer.png +0 -0
  18. pygmi-2.2.7/pygmi/helpdocs/pygmi.main.html +31 -0
  19. pygmi-2.2.7/pygmi/helpdocs/pygmi.pfmod.ddisp.html +15 -0
  20. pygmi-2.2.7/pygmi/helpdocs/pygmi.pfmod.iodefs.exportkmz.html +13 -0
  21. pygmi-2.2.7/pygmi/helpdocs/pygmi.pfmod.iodefs.importpicture.html +16 -0
  22. pygmi-2.2.7/pygmi/helpdocs/pygmi.pfmod.layer.html +17 -0
  23. pygmi-2.2.7/pygmi/helpdocs/pygmi.pfmod.mext.html +44 -0
  24. pygmi-2.2.7/pygmi/helpdocs/pygmi.pfmod.misc.rangedcopy.html +16 -0
  25. pygmi-2.2.7/pygmi/helpdocs/pygmi.pfmod.param.html +37 -0
  26. pygmi-2.2.7/pygmi/helpdocs/pygmi.pfmod.prof.html +32 -0
  27. pygmi-2.2.7/pygmi/helpdocs/pygmi.pfmod.pview.html +26 -0
  28. pygmi-2.2.7/pygmi/helpdocs/pygmi.raster.cooper.gradients.html +14 -0
  29. pygmi-2.2.7/pygmi/helpdocs/pygmi.raster.cooper.tilt.html +14 -0
  30. pygmi-2.2.7/pygmi/helpdocs/pygmi.raster.cooper.visibility.html +14 -0
  31. pygmi-2.2.7/pygmi/helpdocs/pygmi.raster.dataprep.datagrid.html +13 -0
  32. pygmi-2.2.7/pygmi/helpdocs/pygmi.raster.dataprep.datamerge.html +11 -0
  33. pygmi-2.2.7/pygmi/helpdocs/pygmi.raster.dataprep.datareproj.html +11 -0
  34. pygmi-2.2.7/pygmi/helpdocs/pygmi.raster.dataprep.rtp.html +14 -0
  35. pygmi-2.2.7/pygmi/helpdocs/pygmi.raster.ginterp.html +31 -0
  36. pygmi-2.2.7/pygmi/helpdocs/pygmi.raster.igrf.html +20 -0
  37. pygmi-2.2.7/pygmi/helpdocs/pygmi.raster.normalisation.html +14 -0
  38. pygmi-2.2.7/pygmi/helpdocs/pygmi.raster.smooth.html +22 -0
  39. pygmi-2.2.7/pygmi/helpdocs/pygmi.raster.tiltdepth.html +20 -0
  40. pygmi-2.2.7/pygmi/images/Help.png +0 -0
  41. pygmi-2.2.7/pygmi/images/bringtofront.png +0 -0
  42. pygmi-2.2.7/pygmi/images/cgs2.emf +0 -0
  43. pygmi-2.2.7/pygmi/images/delete.png +0 -0
  44. pygmi-2.2.7/pygmi/images/linepointer.png +0 -0
  45. pygmi-2.2.7/pygmi/images/logo256.ico +0 -0
  46. pygmi-2.2.7/pygmi/images/logo256.png +0 -0
  47. pygmi-2.2.7/pygmi/images/pointer.png +0 -0
  48. pygmi-2.2.7/pygmi/images/pygmi.png +0 -0
  49. pygmi-2.2.7/pygmi/images/sendtoback.png +0 -0
  50. pygmi-2.2.7/pygmi/main.py +1037 -0
  51. pygmi-2.2.7/pygmi/menu_default.py +327 -0
  52. pygmi-2.2.7/pygmi/misc.py +147 -0
  53. pygmi-2.2.7/pygmi/pfmod/__init__.py +6 -0
  54. pygmi-2.2.7/pygmi/pfmod/cubes.py +1488 -0
  55. pygmi-2.2.7/pygmi/pfmod/datatypes.py +292 -0
  56. pygmi-2.2.7/pygmi/pfmod/grvmag3d.py +1265 -0
  57. pygmi-2.2.7/pygmi/pfmod/iodefs.py +1001 -0
  58. pygmi-2.2.7/pygmi/pfmod/menu.py +107 -0
  59. pygmi-2.2.7/pygmi/pfmod/misc.py +301 -0
  60. pygmi-2.2.7/pygmi/pfmod/pfmod.py +248 -0
  61. pygmi-2.2.7/pygmi/pfmod/tab_ddisp.py +425 -0
  62. pygmi-2.2.7/pygmi/pfmod/tab_layer.py +490 -0
  63. pygmi-2.2.7/pygmi/pfmod/tab_mext.py +544 -0
  64. pygmi-2.2.7/pygmi/pfmod/tab_param.py +548 -0
  65. pygmi-2.2.7/pygmi/pfmod/tab_prof.py +946 -0
  66. pygmi-2.2.7/pygmi/pfmod/tab_pview.py +740 -0
  67. pygmi-2.2.7/pygmi/raster/IGRF11.COF +1635 -0
  68. pygmi-2.2.7/pygmi/raster/__init__.py +14 -0
  69. pygmi-2.2.7/pygmi/raster/cooper.py +718 -0
  70. pygmi-2.2.7/pygmi/raster/dataprep.py +1640 -0
  71. pygmi-2.2.7/pygmi/raster/datatypes.py +123 -0
  72. pygmi-2.2.7/pygmi/raster/equation_editor.py +256 -0
  73. pygmi-2.2.7/pygmi/raster/ginterp.py +1901 -0
  74. pygmi-2.2.7/pygmi/raster/graphs.py +531 -0
  75. pygmi-2.2.7/pygmi/raster/igrf.py +860 -0
  76. pygmi-2.2.7/pygmi/raster/iodefs.py +813 -0
  77. pygmi-2.2.7/pygmi/raster/menu.py +307 -0
  78. pygmi-2.2.7/pygmi/raster/normalisation.py +187 -0
  79. pygmi-2.2.7/pygmi/raster/show_table.py +245 -0
  80. pygmi-2.2.7/pygmi/raster/smooth.py +406 -0
  81. pygmi-2.2.7/pygmi/raster/tiltdepth.py +590 -0
  82. pygmi-2.2.7/pygmi/seis/__init__.py +0 -0
  83. pygmi-2.2.7/pygmi/seis/beachball.py +751 -0
  84. pygmi-2.2.7/pygmi/seis/datatypes.py +605 -0
  85. pygmi-2.2.7/pygmi/seis/del_rec.py +410 -0
  86. pygmi-2.2.7/pygmi/seis/iodefs.py +1261 -0
  87. pygmi-2.2.7/pygmi/seis/menu.py +136 -0
  88. pygmi-2.2.7/pygmi/seis/scan_imp.py +795 -0
  89. pygmi-2.2.7/pygmi/test/__init__.py +6 -0
  90. pygmi-2.2.7/pygmi/test/pfmod.py +212 -0
  91. pygmi-2.2.7/pygmi/test/tests.py +39 -0
  92. pygmi-2.2.7/pygmi/vector/__init__.py +7 -0
  93. pygmi-2.2.7/pygmi/vector/datatypes.py +74 -0
  94. pygmi-2.2.7/pygmi/vector/graphs.py +443 -0
  95. pygmi-2.2.7/pygmi/vector/iodefs.py +345 -0
  96. pygmi-2.2.7/pygmi/vector/menu.py +127 -0
  97. pygmi-2.2.7/pygmi.egg-info/PKG-INFO +47 -0
  98. pygmi-2.2.7/pygmi.egg-info/SOURCES.txt +105 -0
  99. pygmi-2.2.7/pygmi.egg-info/dependency_links.txt +1 -0
  100. pygmi-2.2.7/pygmi.egg-info/entry_points.txt +3 -0
  101. pygmi-2.2.7/pygmi.egg-info/not-zip-safe +1 -0
  102. pygmi-2.2.7/pygmi.egg-info/requires.txt +7 -0
  103. pygmi-2.2.7/pygmi.egg-info/top_level.txt +1 -0
  104. pygmi-2.2.7/quickstart.py +35 -0
  105. pygmi-2.2.7/setup.cfg +8 -0
  106. pygmi-2.2.7/setup.py +80 -0
@@ -0,0 +1,708 @@
1
+ # -----------------------------------------------------------------------------
2
+ # Name: crisp_clust.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 the main Crisp Clustering set of routines """
26
+
27
+ from PyQt4 import QtGui, QtCore
28
+ import numpy as np
29
+ import copy
30
+ from pygmi.clust.datatypes import Clust
31
+ import pygmi.clust.var_ratio as vr
32
+ import os
33
+ import pdb
34
+
35
+
36
+ class CrispClust(QtGui.QDialog):
37
+ """
38
+ Crisp Cluster Class
39
+
40
+ Attributes
41
+ ----------
42
+ parent : parent
43
+ reference to the parent routine
44
+ indata : dictionary
45
+ dictionary of input datasets
46
+ outdata : dictionary
47
+ dictionary of output datasets
48
+ """
49
+ def __init__(self, parent=None):
50
+ QtGui.QDialog.__init__(self, parent)
51
+
52
+ self.indata = {}
53
+ self.outdata = {}
54
+ self.parent = parent
55
+ self.pbar = parent.pbar
56
+
57
+ self.spinbox_maxclusters = QtGui.QSpinBox()
58
+ self.combobox_alg = QtGui.QComboBox()
59
+ self.doublespinbox_maxerror = QtGui.QDoubleSpinBox()
60
+ self.spinbox_maxiterations = QtGui.QSpinBox()
61
+ self.spinbox_repeatedruns = QtGui.QSpinBox()
62
+ self.spinbox_minclusters = QtGui.QSpinBox()
63
+ self.checkbox_denorm = QtGui.QCheckBox()
64
+ self.groupbox = QtGui.QGroupBox()
65
+ self.label_7 = QtGui.QLabel()
66
+ self.doublespinbox_constraincluster = QtGui.QDoubleSpinBox()
67
+ self.radiobutton_random = QtGui.QRadioButton()
68
+ self.radiobutton_manual = QtGui.QRadioButton()
69
+ self.radiobutton_datadriven = QtGui.QRadioButton()
70
+
71
+ self.setupui()
72
+
73
+ self.name = "Crisp Clustering"
74
+ self.cltype = 'k-means'
75
+ self.min_cluster = 5
76
+ self.max_cluster = 5
77
+ self.max_iter = 100
78
+ self.term_thresh = 0.00001
79
+ self.runs = 1
80
+ self.constrain = 0.0
81
+ self.denorm = False
82
+ self.init_type = 'random'
83
+ self.type = 'crisp'
84
+ self.log = ''
85
+
86
+ self.combobox_alg.addItems(['k-means', 'advanced k-means', 'w-means'])
87
+ self.combobox_alg.currentIndexChanged.connect(self.combo)
88
+ self.combo()
89
+
90
+ self.reportback = self.parent.showprocesslog
91
+
92
+ def setupui(self):
93
+ """ setup UI """
94
+ gridlayout = QtGui.QGridLayout(self)
95
+ verticallayout = QtGui.QVBoxLayout(self.groupbox)
96
+
97
+ buttonbox = QtGui.QDialogButtonBox()
98
+ label = QtGui.QLabel()
99
+ label_2 = QtGui.QLabel()
100
+ label_3 = QtGui.QLabel()
101
+ label_4 = QtGui.QLabel()
102
+ label_5 = QtGui.QLabel()
103
+ label_6 = QtGui.QLabel()
104
+
105
+ self.spinbox_minclusters.setMinimum(1)
106
+ self.spinbox_minclusters.setProperty("value", 5)
107
+ self.spinbox_maxclusters.setMinimum(1)
108
+ self.spinbox_maxclusters.setProperty("value", 5)
109
+ self.spinbox_maxiterations.setMinimum(1)
110
+ self.spinbox_maxiterations.setMaximum(1000)
111
+ self.spinbox_maxiterations.setProperty("value", 100)
112
+ self.doublespinbox_maxerror.setDecimals(5)
113
+ self.doublespinbox_maxerror.setProperty("value", 1e-05)
114
+ self.spinbox_repeatedruns.setMinimum(1)
115
+
116
+ buttonbox.setOrientation(QtCore.Qt.Horizontal)
117
+ buttonbox.setStandardButtons(buttonbox.Cancel | buttonbox.Ok)
118
+ self.radiobutton_random.setChecked(True)
119
+ self.groupbox.hide()
120
+
121
+ self.setWindowTitle("Crisp Clustering")
122
+ label.setText("Cluster Algorithm:")
123
+ label_2.setText("Minimum Clusters:")
124
+ label_3.setText("Maximum Clusters")
125
+ label_4.setText("Maximum Iterations:")
126
+ label_5.setText("Terminate if relative change per iteration is less than:")
127
+ label_6.setText("Repeated Runs:")
128
+ self.label_7.setText("Constrain Cluster Shape (0: unconstrained, 1: spherical)")
129
+ self.checkbox_denorm.setText("De-normalise Results")
130
+ self.groupbox.setTitle("Initial Guess")
131
+ self.radiobutton_random.setText("Random")
132
+ self.radiobutton_manual.setText("Manual")
133
+ self.radiobutton_datadriven.setText("Data Driven")
134
+
135
+ gridlayout.addWidget(label, 0, 2, 1, 1)
136
+ gridlayout.addWidget(self.combobox_alg, 0, 4, 1, 1)
137
+ gridlayout.addWidget(label_2, 1, 2, 1, 1)
138
+ gridlayout.addWidget(self.spinbox_minclusters, 1, 4, 1, 1)
139
+ gridlayout.addWidget(label_3, 2, 2, 1, 1)
140
+ gridlayout.addWidget(self.spinbox_maxclusters, 2, 4, 1, 1)
141
+ gridlayout.addWidget(label_4, 3, 2, 1, 1)
142
+ gridlayout.addWidget(self.spinbox_maxiterations, 3, 4, 1, 1)
143
+ gridlayout.addWidget(label_5, 4, 2, 1, 1)
144
+ gridlayout.addWidget(self.doublespinbox_maxerror, 4, 4, 1, 1)
145
+ gridlayout.addWidget(label_6, 5, 2, 1, 1)
146
+ gridlayout.addWidget(self.spinbox_repeatedruns, 5, 4, 1, 1)
147
+ gridlayout.addWidget(self.label_7, 6, 2, 1, 1)
148
+ gridlayout.addWidget(self.doublespinbox_constraincluster, 6, 4, 1, 1)
149
+ gridlayout.addWidget(self.checkbox_denorm, 7, 2, 1, 1)
150
+ gridlayout.addWidget(self.groupbox, 8, 2, 1, 3)
151
+ gridlayout.addWidget(buttonbox, 9, 4, 1, 1)
152
+
153
+ verticallayout.addWidget(self.radiobutton_random)
154
+ verticallayout.addWidget(self.radiobutton_manual)
155
+ verticallayout.addWidget(self.radiobutton_datadriven)
156
+
157
+ buttonbox.accepted.connect(self.accept)
158
+ buttonbox.rejected.connect(self.reject)
159
+
160
+ def combo(self):
161
+ """ Combo box """
162
+ i = str(self.combobox_alg.currentText())
163
+ if i == 'w-means':
164
+ self.label_7.show()
165
+ self.doublespinbox_constraincluster.show()
166
+ else:
167
+ self.label_7.hide()
168
+ self.doublespinbox_constraincluster.hide()
169
+
170
+ def settings(self):
171
+ """ Settings """
172
+ tst = np.unique([i.data.shape for i in self.indata['Raster']])
173
+ if tst.size > 2:
174
+ pdb.set_trace()
175
+ self.reportback('Error: Your input datasets have different ' +
176
+ 'sizes. Merge the data first')
177
+ return
178
+
179
+ self.update_vars()
180
+ temp = self.exec_()
181
+ if temp == 0:
182
+ return
183
+
184
+ self.parent.process_is_active()
185
+ self.run()
186
+ self.parent.process_is_active(False)
187
+ self.pbar.to_max()
188
+ return True
189
+
190
+ def update_vars(self):
191
+ """ Updates the variables """
192
+ self.cltype = str(self.combobox_alg.currentText())
193
+ self.min_cluster = self.spinbox_minclusters.value()
194
+ self.max_cluster = self.spinbox_maxclusters.value()
195
+ self.max_iter = self.spinbox_maxiterations.value()
196
+ self.term_thresh = self.doublespinbox_maxerror.value()
197
+ self.runs = self.spinbox_repeatedruns.value()
198
+ self.constrain = self.doublespinbox_constraincluster.value()
199
+ self.denorm = self.checkbox_denorm.isChecked()
200
+
201
+ def run(self):
202
+ """ Process data """
203
+ data = copy.copy(self.indata['Raster'])
204
+ self.update_vars()
205
+ # if datachecks.Datachecks(self).multdata(data) == False:
206
+ # return data
207
+ # if datachecks.Datachecks(self).isdata(data) == False:
208
+ # return data
209
+ # if datachecks.Datachecks(self).equalsize(data) == False:
210
+ # return data
211
+ # if datachecks.Datachecks(self).samecoords(data) == False:
212
+ # return data
213
+ # if datachecks.Datachecks(self).iscomplete(data) == False:
214
+ # return data
215
+
216
+ cltype = self.cltype
217
+ cov_constr = self.constrain
218
+ no_runs = self.runs
219
+ max_iter = self.max_iter
220
+ term_thresh = self.term_thresh
221
+ no_clust = np.array([self.min_cluster, self.max_cluster])
222
+ de_norm = self.denorm
223
+
224
+ self.reportback('Crisp Clustering started')
225
+
226
+ # #############################################################################
227
+ # Section to deal with different bands having different null values.
228
+ # Start with the first entry
229
+ masktmp = data[0].data.mask
230
+ # Add the all the masks to this. This promotes False values to True.
231
+ for i in data:
232
+ masktmp += i.data.mask
233
+ for i in range(len(data)): # Apply this to all the bands
234
+ data[i].data.mask = masktmp
235
+ # #############################################################################
236
+
237
+ # dat_in = np.array([i.data.flatten() for i in data]).T
238
+ dat_in = np.array([i.data.compressed() for i in data]).T
239
+
240
+ # dat_in = dat_in[dat_in != None]
241
+
242
+ # dat_in = np.array([[x for x in data[i].data.flatten() if x != None]
243
+ # for i in range(len(data))]).T
244
+
245
+ if self.radiobutton_manual.isChecked() is True:
246
+ ext = \
247
+ "ASCII matrix (*.txt);;" + \
248
+ "ASCII matrix (*.asc);;" + \
249
+ "ASCII matrix (*.dat)"
250
+ filename = QtGui.QFileDialog.getOpenFileName(
251
+ self.parent, 'Read Cluster Centers', '.', ext)
252
+ if filename == '':
253
+ return False
254
+ os.chdir(filename.rpartition('/')[0])
255
+
256
+ ifile = str(filename)
257
+
258
+ dummy_mod = np.ma.array(np.genfromtxt(ifile, unpack=True))
259
+ [ro0, co0] = np.shape(dummy_mod)
260
+ ro1 = np.sum(list(range(no_clust[0], no_clust[1] + 1)))
261
+ if dat_in.shape[1] != co0 or ro0 != ro1:
262
+ QtGui.QMessageBox.warning(self.parent, 'Warning',
263
+ ' Incorrect matrix size!',
264
+ QtGui.QMessageBox.Ok,
265
+ QtGui.QMessageBox.Ok)
266
+ cnt = -1
267
+ for i in range(no_clust[0], no_clust[1] + 1):
268
+ smtmp = np.zeros(i)
269
+ for j in range(i):
270
+ cnt = cnt + 1
271
+ smtmp[j] = dummy_mod[cnt]
272
+ startmdat = {i: smtmp}
273
+ startmfix = {i: []}
274
+
275
+ filename = QtGui.QFileDialog.getOpenFileName(
276
+ self.parent, 'Read Cluster Center Constraints', '.', ext)
277
+ if filename == '':
278
+ QtGui.QMessageBox.warning(
279
+ self.parent, 'Warning',
280
+ 'Running cluster analysis without constraints',
281
+ QtGui.QMessageBox.Ok, QtGui.QMessageBox.Ok)
282
+ else:
283
+ os.chdir(filename.rpartition('/')[0])
284
+ ifile = str(filename)
285
+ dummy_mod = np.ma.array(np.genfromtxt(ifile, unpack=True))
286
+ [ro0, co0] = np.shape(dummy_mod)
287
+ ro1 = np.sum(list(range(no_clust[0], no_clust[1] + 1)))
288
+ if dat_in.shape[1] != co0 or ro0 != ro1:
289
+ QtGui.QMessageBox.warning(self.parent, 'Warning',
290
+ ' Incorrect matrix size!',
291
+ QtGui.QMessageBox.Ok,
292
+ QtGui.QMessageBox.Ok)
293
+ cnt = -1
294
+ for i in range(no_clust[0], no_clust[1] + 1):
295
+ smtmp = np.zeros(i)
296
+ for j in range(i):
297
+ cnt = cnt + 1
298
+ smtmp = dummy_mod[cnt]
299
+ startmfix = {i: smtmp}
300
+
301
+ cnt = -1
302
+ dat_out = [Clust() for i in range(no_clust[0], no_clust[1]+1)]
303
+
304
+ for i in range(no_clust[0], no_clust[1]+1):
305
+ self.reportback('Number of Clusters:'+str(i))
306
+ cnt = cnt + 1
307
+ if self.radiobutton_datadriven.isChecked() is True:
308
+ self.reportback('Initial guess: data driven')
309
+ no_samp = dat_in.shape[0]
310
+ dno_samp = no_samp/i
311
+ # idx=1
312
+ # idx=[[idx,(j-1)*dno_samp] for j in range(2,i+1)]
313
+ idx = np.arange(0, no_samp+dno_samp, dno_samp)
314
+ idx[0] = 1
315
+ # idx=np.array([idx,no_samp])
316
+ startmdat = {i: np.zeros([i, dat_in.shape[1]])}
317
+ dat_in1 = dat_in
318
+ smtmp = np.zeros([i, dat_in.shape[1]])
319
+ for k in range(dat_in.shape[1]):
320
+ for j in range(i):
321
+ smtmp[j, k] = np.median(dat_in1[idx[j]:idx[j+1], k])
322
+ startmdat = {i: smtmp}
323
+ startmfix = {i: []}
324
+ del dat_in1
325
+
326
+ clidx, clcent, clobj_fcn, clvrc = self.crisp_means(
327
+ dat_in, i, startmdat[i], startmfix[i], max_iter,
328
+ term_thresh, cltype, cov_constr)
329
+
330
+ elif self.radiobutton_manual.isChecked() is True:
331
+
332
+ self.reportback('Initial guess: manual')
333
+
334
+ clidx, clcent, clobj_fcn, clvrc = self.crisp_means(
335
+ dat_in, i, startmdat[i], startmfix[i], max_iter,
336
+ term_thresh, cltype, cov_constr)
337
+
338
+ elif self.radiobutton_random.isChecked() is True:
339
+ self.reportback('Initial guess: random')
340
+
341
+ clobj_fcn = np.array([np.inf])
342
+ for j in range(no_runs):
343
+ self.reportback('Run '+str(j)+' of'+str(no_runs))
344
+
345
+ xmins = np.minimum(dat_in, 1)
346
+ xmaxs = np.maximum(dat_in, 1)
347
+ startm1dat = {i: np.random.uniform(
348
+ xmins[np.zeros(i, int), :],
349
+ xmaxs[np.zeros(i, int), :])}
350
+ startmfix = {i: np.array([])}
351
+ clidx1, clcent1, clobj_fcn1, clvrc1 = self.crisp_means(
352
+ dat_in, i, startm1dat[i], startmfix[i], max_iter,
353
+ term_thresh, cltype, cov_constr)
354
+
355
+ if clobj_fcn1[-1] < clobj_fcn[-1]:
356
+ clidx = clidx1
357
+ clcent = clcent1
358
+ clobj_fcn = clobj_fcn1
359
+ clvrc = clvrc1
360
+ startmdat = {i: startm1dat[i]}
361
+
362
+ # zonal = np.zeros(data[0].data.shape)-9999.0
363
+ zonal = np.ma.masked_all(data[0].data.shape)
364
+
365
+ alpha = (data[0].data.mask == 0)
366
+ zonal[alpha == 1] = clidx
367
+
368
+ cent_std = np.array([np.std(dat_in[clidx == k], 0)
369
+ for k in range(i)])
370
+
371
+ den_cent = clcent
372
+ den_cent_std = np.array(cent_std, copy=True)
373
+ den_cent_std1 = np.array(cent_std, copy=True)
374
+ if de_norm is True:
375
+ for k in range(len(data)):
376
+ if np.size(data[k].norm) > 0:
377
+ nnorm = len(data[k].norm)
378
+ for j in range(nnorm, 0, -1):
379
+ if data[k].norm[j-1]['type'] == 'minmax':
380
+ den_cent[:, k] = (
381
+ den_cent[:, k] *
382
+ (data[k].norm[j-1]['transform'][1, 1] -
383
+ data[k].norm[j-1]['transform'][0, 1]) +
384
+ data[k].norm[j-1]['transform'][0, 1])
385
+ den_cent_std[:, k] = (
386
+ den_cent_std[:, k] *
387
+ (data[k].norm[j-1]['transform'][1, 1] -
388
+ data[k].norm[j-1]['transform'][0, 1]) +
389
+ data[k].norm[j-1]['transform'][0, 1])
390
+ den_cent_std1[:, k] = (
391
+ den_cent_std1[:, k] *
392
+ (data[k].norm[j-1]['transform'][1, 1] -
393
+ data[k].norm[j-1]['transform'][0, 1]) +
394
+ data[k].norm[j-1]['transform'][0, 1])
395
+ elif (data[k].norm[j-1]['type'] == 'meanstd' or
396
+ data[k].norm[j-1]['type'] == 'medmad'):
397
+ den_cent[:, k] = (
398
+ den_cent[:, k] *
399
+ data[k].norm[j-1]['transform'][1, 1] +
400
+ data[k].norm[j-1]['transform'][0, 1])
401
+ den_cent_std[:, k] = (
402
+ den_cent_std[:, k] *
403
+ data[k].norm[j-1]['transform'][1, 1] +
404
+ data[k].norm[j-1]['transform'][0, 1])
405
+ den_cent_std1[:, k] = (
406
+ den_cent_std1[:, k] *
407
+ data[k].norm[j-1]['transform'][1, 1] +
408
+ data[k].norm[j-1]['transform'][0, 1])
409
+ elif data[k].norm[j-1]['type'] == 'histeq':
410
+ den_cent[:, k] = np.interp(
411
+ den_cent[:, k],
412
+ data[k].norm[j-1]['transform'][:, 0],
413
+ data[k].norm[j-1]['transform'][:, 1])
414
+ den_cent_std[:, k] = np.interp(
415
+ (den_cent[:, k] + den_cent_std[:, k]),
416
+ data[k].norm[j-1]['transform'][:, 0],
417
+ data[k].norm[j-1]['transform'][:, 1])
418
+ den_cent_std1[:, k] = np.interp(
419
+ (den_cent[:, k] - den_cent_std1[:, k]),
420
+ data[k].norm[j-1]['transform'][:, 0],
421
+ data[k].norm[j-1]['transform'][:, 1])
422
+ else:
423
+ den_cent = np.array([])
424
+ den_cent_std = np.array([])
425
+ den_cent_std1 = np.array([])
426
+
427
+ for k in data:
428
+ dat_out[cnt].input_type.append(k.dataid)
429
+ # dat_out[cnt].proc_history.append(k.proc)
430
+
431
+ dat_out[cnt].data = zonal
432
+ # dat_out[cnt].data.mask = masktmp
433
+ dat_out[cnt].nullvalue = zonal.fill_value
434
+ dat_out[cnt].no_clusters = i
435
+ dat_out[cnt].center = clcent # These are arrays
436
+ dat_out[cnt].center_std = cent_std # These are arrays
437
+ dat_out[cnt].obj_fcn = clobj_fcn
438
+ dat_out[cnt].vrc = clvrc
439
+
440
+ # dat_out[cnt].type = self.type
441
+ # dat_out[cnt].algorithm = cltype
442
+ # dat_out[cnt].initialization = init_type
443
+ # dat_out[cnt].init_mod = startmdat[i]
444
+ # dat_out[cnt].init_constrains = startmfix[i]
445
+ # dat_out[cnt].runs = no_runs
446
+ # dat_out[cnt].max_iterations = max_iter
447
+ # dat_out[cnt].denormalize = de_norm
448
+ # dat_out[cnt].term_threshold = term_thresh
449
+ # dat_out[cnt].shape_constrain = cov_constr
450
+ # dat_out[cnt].zonal = zonal
451
+ # dat_out[cnt].alpha = alpha
452
+ # dat_out[cnt].xxx = data[0].xxx
453
+ # dat_out[cnt].yyy = data[0].yyy
454
+ # dat_out[cnt].denorm_center = den_cent
455
+ # dat_out[cnt].denorm_center_stdup = den_cent_std
456
+ # dat_out[cnt].denorm_center_stdlow = den_cent_std1
457
+ # dat_out[cnt].iterations = clobj_fcn.size
458
+
459
+ self.log = ("Crisp Cluster complete" + ' (' + self.cltype + ' ' +
460
+ self.init_type+')')
461
+
462
+ for i in dat_out:
463
+ i.tlx = data[0].tlx
464
+ i.tly = data[0].tly
465
+ i.xdim = data[0].xdim
466
+ i.ydim = data[0].ydim
467
+ i.nrofbands = 1
468
+ i.dataid = 'Crisp Cluster: '+str(i.no_clusters)
469
+ i.rows = data[0].rows
470
+ i.cols = data[0].cols
471
+ i.nullvalue = data[0].nullvalue
472
+
473
+ self.reportback("Crisp Cluster complete" + ' ('+self.cltype + ' ' +
474
+ self.init_type+')')
475
+
476
+ self.outdata['Cluster'] = dat_out
477
+ return True
478
+
479
+ def crisp_means(self, data, no_clust, cent, centfix, maxit, term_thresh,
480
+ cltype, cov_constr):
481
+ """ Crisp Means """
482
+
483
+ # [idx, cent, obj_fcn] = crisp_means(data, no_clust, cent, maxit, term_thresh,
484
+ # cltype, cov_constr)
485
+
486
+ # script enables the crisp clustering of COMPLETE multi-variate datasets.
487
+ # (no attributes missing!!!!!!!!!)
488
+
489
+ # NOTE: All input arguments must be provided, even if they are empty!!!!
490
+ # DATA: NxP matrix containing the data to be clustered, N is number of
491
+ # samples, P is number of different attributes availabe for each sample
492
+ # NO_CLUST: number of clusters to be used
493
+ # CENT: cluster centre positions, either empty [] --> randomly
494
+ # guess center positions will be used for initialisation or NO_CLUSTxP
495
+ # matrix
496
+ # CENTFIX: Constrains the position of cluster centers, if centfix is empty,
497
+ # cluster centers can freely vary during cluster analysis, otherwise
498
+ # CENTFIX is of equal size to CENT and gives an absolut deviation from
499
+ # initial center positions that should not be exceeded during clustering.
500
+ # Note, CETNFIX applies only if center values are provided by the user
501
+ # MAXIT: number of maximal allowed iterations
502
+ # TERM_THRESH: Termination threshold, either empty [] --> go for the maximum
503
+ # number of iterations MAXIT or
504
+ # a scalar giving the minimum reduction of the size of the objective function
505
+ # for two consecutive iterations in Percent
506
+ # CLTYPE: either 'kmeans' --> kmeans cluster analysis (spherically shaped
507
+ # cluster), 'det' --> uses the determinant criterion of Spath, H.,
508
+ # "Cluster-Formation and Analyse, chapter3" (ellipsoidal clusters, all
509
+ # cluster use the same ellipsoid), or 'vardet' --> Spath, H., chapter 4
510
+ # (each cluster uses its individual ellipsoid) Note: the latter is the
511
+ # crisp version of the Gustafson-Kessel algorithm
512
+ # COV_CONSTR: scalar between [0 1], values >0 trimm the covariance matrix
513
+ # to avoid needle-like ellpsoids for the clusters, applies only for
514
+ # CLTYPE='vardet', but must always be provided
515
+
516
+ # IDX: cluster index number for each sample after the last iteration, column
517
+ # vector
518
+ # CENT: matrix with cluster centre positions after last iteration, one cluster
519
+ # centre per row
520
+ # OBJ_FCN: Vector, size of the objective function after each iteration
521
+ # VRC: Variance Ratio Criterion
522
+ self.reportback(' ')
523
+
524
+ no_samples = data.shape[0]
525
+ if cent.size == 0: # if no center values are provided
526
+ xmins = np.minimum(data, 1)
527
+ xmaxs = np.maximum(data, 1)
528
+ cent = np.random.uniform(xmins[np.zeros(no_clust, int), :],
529
+ xmaxs[np.zeros(no_clust, int), :])
530
+ centfix = np.array([])
531
+
532
+ cent_orig = cent
533
+ centfix = np.abs(centfix)
534
+
535
+ # calculate euclidian distance for initial classification
536
+ onetmp = np.ones([no_samples, 1], int) # trying this for speed?
537
+ edist = np.array([np.sqrt(np.sum(((data-onetmp*cent[j])**2), 1))
538
+ for j in range(no_clust)]) # initial distance -->
539
+ # Euclidian
540
+
541
+ mindist = edist.min(0) # 0 means row wize minimum
542
+ idx = edist.argmin(0)
543
+
544
+ # initial size of objective function
545
+ obj_fcn_initial = np.sum(mindist**2)
546
+ obj_fcn_prev = obj_fcn_initial
547
+ obj_fcn = np.zeros(maxit) # This is new - we must initialize this.
548
+
549
+ for i in self.pbar.iter(range(maxit)): # =1:maxit. loop over all iterations
550
+ cent_prev = cent # store result of last iteration
551
+ idx_prev = idx
552
+ dist_prev = edist
553
+ # calc new cluster centre positions
554
+ cent, idx = self.gcentroids(data, idx, no_clust, mindist)
555
+ # constrain the cluster center positions to keep it in the given interval
556
+ if centfix.size > 0:
557
+ # constrain the center positions within the given limits
558
+ cent_idx = cent > (cent_orig+centfix)
559
+ cent[cent_idx == 1] = (cent_orig(cent_idx == 1) +
560
+ centfix(cent_idx == 1))
561
+ cent_idx = cent < (cent_orig-centfix)
562
+ cent[cent_idx == 1] = (cent_orig(cent_idx == 1) -
563
+ centfix(cent_idx == 1))
564
+
565
+ # calc new cluster centre distances
566
+ edist = self.gdist(data, cent, idx, no_clust, cltype, cov_constr)
567
+ # get new index values for each data point and the distance from each
568
+ # sample to its cluster center
569
+ mindist = edist.min(0)
570
+ idx = edist.argmin(0)
571
+
572
+ # calc new objective function size
573
+ obj_fcn[i] = np.sum(mindist**2)
574
+
575
+ self.reportback('Iteration: ' + str(i) + ' Threshold: ' +
576
+ str(term_thresh) + ' Current: ' +
577
+ '{:.2e}'.format(100 *
578
+ ((obj_fcn_prev-obj_fcn[i]) /
579
+ obj_fcn[i])), True)
580
+ # if no termination threshold provided, ignore this and do all iterations
581
+ if term_thresh > 0:
582
+ # if the improvement between the last two iterations was less
583
+ # than a defined threshold in percent
584
+ if (100*((obj_fcn_prev-obj_fcn[i])/obj_fcn[i]) < term_thresh
585
+ or obj_fcn[i] > obj_fcn_prev):
586
+ # go back to the results of the previous iteration
587
+ idx = idx_prev
588
+ cent = cent_prev
589
+ edist = dist_prev
590
+ if i == 0:
591
+ obj_fcn = obj_fcn_prev
592
+ else:
593
+ # changed from i-1 to i for w-means
594
+ obj_fcn = np.delete(obj_fcn, np.s_[i::])
595
+ # vrc=vr.var_ratio(data, idx, cent, edist)
596
+ break # and stop the clustering right now
597
+ obj_fcn_prev = obj_fcn[i]
598
+ vrc = vr.var_ratio(data, idx, cent, edist)
599
+ return idx, cent, obj_fcn, vrc
600
+
601
+ # -----------------------------------------------------------------------------
602
+ def gdist(self, data, center, index, no_clust, cltype, cov_constr):
603
+ """ Gdist routine """
604
+ no_samples = data.shape[0]
605
+ no_datasets = data.shape[1]
606
+ bigd = np.zeros([no_clust, no_samples])
607
+ ddd = []
608
+ if cltype == 'k-means':
609
+ onetmp = np.ones([no_samples, 1]) # trying this for speed?
610
+ for j in range(no_clust):
611
+ # Euclidian
612
+ bigd[j] = np.sqrt(np.sum(((data-onetmp*center[j])**2), 1))
613
+ # determinant criterion see Spath, Helmuth,
614
+ # "Cluster-Formation and Analyse", chapter 3
615
+ elif cltype == 'advanced k-means':
616
+ for j in range(no_clust):
617
+ # difference between each sample attribute to the corresponding
618
+ # attribute of the j-th cluster
619
+ dcent = data-np.ones([no_samples, 1])*center[j]
620
+ # grab the data belonging to cluster j
621
+ mod_idx = (index == j)*1
622
+ # should I use different transpose?
623
+ # Streuungsmatrix/ covariance of the j-th cluster
624
+ mat_a = np.dot(np.ones([no_datasets, 1])*mod_idx*dcent.T,
625
+ dcent/np.sum(mod_idx))
626
+ # constrain covariance matrix if badly conditioned
627
+ if np.linalg.cond(mat_a) > 1e10:
628
+ # warning([' Badly conditionend covariance matrix \
629
+ # (cond. number > 1e10) of cluster ',num2unicode(j)]);
630
+ ed1, ev1 = np.linalg.eig(mat_a)
631
+ edmax = np.max(ed1)
632
+ ed1[1e10*ed1 < edmax] = edmax/1e10
633
+ mat_a = np.dot(np.dot(ev1, (ed1*np.eye(no_datasets))),
634
+ np.linalg.inv(ev1))
635
+ if j == 0: # sum all covariance matrices for all clusters
636
+ mat_a0 = mat_a
637
+ else:
638
+ mat_a0 = mat_a0 + mat_a
639
+ # calc new distances using the same covariance matrix for all clusters -->
640
+ # ellisoidal clusters, all clusters use equal ellipsoids
641
+ for j in range(no_clust):
642
+ # difference between each sample attribute to the corresponding
643
+ # attribute of the j-th cluster
644
+ dcent = data-np.ones([no_samples, 1])*center[j]
645
+ # does this need to be in this loop?
646
+ mbig = (np.linalg.det(mat_a0)**(1.0/no_datasets) *
647
+ np.linalg.pinv(mat_a0))
648
+ ddd.append(np.sum((np.dot(dcent, mbig)*dcent), 1).T)
649
+ bigd = np.sqrt(ddd)
650
+ # cluster adapted determinant criterion see Spath, Helmuth,
651
+ # "Cluster-Formation and Analyse", chapter 4 --> equivalent to crisp GK
652
+ # algorithm
653
+ elif cltype == 'w-means':
654
+ for j in range(no_clust):
655
+ # difference between each sample attribute to the corresponding
656
+ # attribute of the j-th cluster
657
+ dcent = data-np.ones([no_samples, 1])*center[j]
658
+ mod_idx = (index == j)*1 # grab data belonging to cluster j
659
+ # '*dcent/sum(mod_idx); % Streuungsmatrix/ covariance of the j-th cluster
660
+ mat_a = np.dot(np.ones([no_datasets, 1])*mod_idx*dcent.T,
661
+ dcent/np.sum(mod_idx))
662
+ mat_a0 = np.eye(mat_a.shape[0])
663
+ # if cov_constr>0, this enforces not to elongated ellipsoids -->
664
+ # avoid the needle-like cluster
665
+ mat_a = (1-cov_constr)*mat_a+cov_constr*(mat_a0/no_samples)
666
+ # constrain covariance matrix if badly conditioned and cluster contains
667
+ # more than 1 sample
668
+ if np.linalg.cond(mat_a) > 1e10 and np.sum(mod_idx) > 1:
669
+ # warning([' Badly conditionend covariance matrix '+
670
+ # '(cond. number > 1e10) of cluster ',num2unicode(j)])
671
+ ed1, ev1 = np.linalg.eig(mat_a)
672
+ edmax = np.max(ed1)
673
+ ed1[1e10*ed1 < edmax] = edmax/1e10
674
+ mat_a = np.dot(np.dot(ev1, (ed1*np.eye(no_datasets))),
675
+ np.linalg.inv(ev1))
676
+ # assume spherical shape of clusters with only one sample
677
+ elif np.sum(mod_idx) == 1:
678
+ mat_a = mat_a0
679
+ mbig = (np.linalg.det(mat_a)**(1.0/no_datasets) *
680
+ np.linalg.pinv(mat_a))
681
+ # calc cluster to sample distances using mahalanobis distance for each
682
+ # cluster, ellipsoidal clusters, each cluster has its own individually
683
+ # oriented and shaped ellipsoid
684
+ ddd.append(np.sum((np.dot(dcent, mbig)*dcent), 1).T)
685
+ bigd = np.sqrt(ddd)
686
+ # end
687
+ return bigd
688
+
689
+ # -----------------------------------------------------------------------------
690
+ def gcentroids(self, data, index, no_clust, mindist):
691
+ """Gcentroids"""
692
+ # no_samples=data.shape[0]
693
+ no_datatypes = data.shape[1]
694
+ centroids = np.tile(np.nan, (no_clust, no_datatypes))
695
+ for j in range(no_clust):
696
+ # find all members of the j-th cluster
697
+ members = (index == j).nonzero()[0]
698
+ # if j is an empty cluster, put one sample into this cluster
699
+ if members.size == 0:
700
+ # take the sample that has the greatest distance to its current
701
+ # cluster and make this the center of the j-th cluster
702
+ idx1 = mindist.argmax(0)
703
+ centroids[j] = data[idx1]
704
+ index[idx1] = j
705
+ mindist[idx1] = 0
706
+ else:
707
+ centroids[j] = data[members].mean(0)
708
+ return centroids, index