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,906 @@
|
|
|
1
|
+
# -----------------------------------------------------------------------------
|
|
2
|
+
# Name: fuzzy_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
|
+
""" Fuzzy clustering """
|
|
26
|
+
|
|
27
|
+
from PyQt4 import QtGui, QtCore
|
|
28
|
+
import numpy as np
|
|
29
|
+
import copy
|
|
30
|
+
from .datatypes import Clust
|
|
31
|
+
from . import var_ratio as vr
|
|
32
|
+
from . import xie_beni as xb
|
|
33
|
+
import os
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class FuzzyClust(QtGui.QDialog):
|
|
37
|
+
"""
|
|
38
|
+
Fuzzy Clust
|
|
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.combobox_alg = QtGui.QComboBox()
|
|
58
|
+
self.doublespinbox_maxerror = QtGui.QDoubleSpinBox()
|
|
59
|
+
self.doublespinbox_fuzzynessexp = QtGui.QDoubleSpinBox()
|
|
60
|
+
self.doublespinbox_constraincluster = QtGui.QDoubleSpinBox()
|
|
61
|
+
self.spinbox_maxclusters = QtGui.QSpinBox()
|
|
62
|
+
self.spinbox_maxiterations = QtGui.QSpinBox()
|
|
63
|
+
self.spinbox_repeatedruns = QtGui.QSpinBox()
|
|
64
|
+
self.spinbox_minclusters = QtGui.QSpinBox()
|
|
65
|
+
self.label_7 = QtGui.QLabel()
|
|
66
|
+
self.checkbox_denorm = QtGui.QCheckBox()
|
|
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 = "Fuzzy Clustering"
|
|
74
|
+
self.cltype = 'fuzzy c-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 = 'fuzzy'
|
|
84
|
+
self.fexp = 1.5
|
|
85
|
+
|
|
86
|
+
self.combobox_alg.addItems(['fuzzy c-means',
|
|
87
|
+
'advanced fuzzy c-means',
|
|
88
|
+
'Gustafson-Kessel'])
|
|
89
|
+
# , 'Gath-Geva'])
|
|
90
|
+
self.combobox_alg.currentIndexChanged.connect(self.combo)
|
|
91
|
+
self.combo()
|
|
92
|
+
|
|
93
|
+
self.reportback = self.parent.showprocesslog
|
|
94
|
+
|
|
95
|
+
def setupui(self):
|
|
96
|
+
""" Setup UI """
|
|
97
|
+
gridlayout = QtGui.QGridLayout(self)
|
|
98
|
+
groupbox = QtGui.QGroupBox(self)
|
|
99
|
+
verticallayout = QtGui.QVBoxLayout(groupbox)
|
|
100
|
+
|
|
101
|
+
buttonbox = QtGui.QDialogButtonBox(self)
|
|
102
|
+
label = QtGui.QLabel()
|
|
103
|
+
label_2 = QtGui.QLabel()
|
|
104
|
+
label_3 = QtGui.QLabel()
|
|
105
|
+
label_4 = QtGui.QLabel()
|
|
106
|
+
label_5 = QtGui.QLabel()
|
|
107
|
+
label_6 = QtGui.QLabel()
|
|
108
|
+
label_8 = QtGui.QLabel()
|
|
109
|
+
|
|
110
|
+
self.spinbox_maxclusters.setMinimum(1)
|
|
111
|
+
self.spinbox_maxclusters.setProperty("value", 5)
|
|
112
|
+
self.spinbox_maxiterations.setMinimum(1)
|
|
113
|
+
self.spinbox_maxiterations.setMaximum(1000)
|
|
114
|
+
self.spinbox_maxiterations.setProperty("value", 100)
|
|
115
|
+
self.spinbox_repeatedruns.setMinimum(1)
|
|
116
|
+
self.spinbox_minclusters.setMinimum(1)
|
|
117
|
+
self.spinbox_minclusters.setProperty("value", 5)
|
|
118
|
+
self.doublespinbox_maxerror.setDecimals(5)
|
|
119
|
+
self.doublespinbox_maxerror.setProperty("value", 1e-05)
|
|
120
|
+
self.doublespinbox_fuzzynessexp.setProperty("value", 1.5)
|
|
121
|
+
self.radiobutton_random.setChecked(True)
|
|
122
|
+
buttonbox.setOrientation(QtCore.Qt.Horizontal)
|
|
123
|
+
buttonbox.setStandardButtons(buttonbox.Cancel | buttonbox.Ok)
|
|
124
|
+
|
|
125
|
+
self.setWindowTitle("Fuzzy Clustering")
|
|
126
|
+
groupbox.setTitle("Initial Guess")
|
|
127
|
+
groupbox.hide()
|
|
128
|
+
label.setText("Cluster Algorithm:")
|
|
129
|
+
label_2.setText("Minimum Clusters:")
|
|
130
|
+
label_3.setText("Maximum Clusters")
|
|
131
|
+
label_4.setText("Maximum Iterations:")
|
|
132
|
+
label_5.setText("Terminate if relative change per iteration is less than:")
|
|
133
|
+
label_6.setText("Repeated Runs:")
|
|
134
|
+
self.label_7.setText("Constrain Cluster Shape (0: unconstrained, 1: spherical)")
|
|
135
|
+
label_8.setText("Fuzzyness Exponent")
|
|
136
|
+
self.checkbox_denorm.setText("De-normalise Results")
|
|
137
|
+
self.radiobutton_random.setText("Random")
|
|
138
|
+
self.radiobutton_manual.setText("Manual")
|
|
139
|
+
self.radiobutton_datadriven.setText("Data Driven")
|
|
140
|
+
|
|
141
|
+
gridlayout.addWidget(label, 0, 2, 1, 1)
|
|
142
|
+
gridlayout.addWidget(label_2, 1, 2, 1, 1)
|
|
143
|
+
gridlayout.addWidget(label_3, 2, 2, 1, 1)
|
|
144
|
+
gridlayout.addWidget(label_4, 3, 2, 1, 1)
|
|
145
|
+
gridlayout.addWidget(label_5, 4, 2, 1, 1)
|
|
146
|
+
gridlayout.addWidget(label_6, 5, 2, 1, 1)
|
|
147
|
+
gridlayout.addWidget(self.label_7, 6, 2, 1, 1)
|
|
148
|
+
gridlayout.addWidget(label_8, 7, 2, 1, 1)
|
|
149
|
+
gridlayout.addWidget(self.checkbox_denorm, 8, 2, 1, 1)
|
|
150
|
+
gridlayout.addWidget(groupbox, 9, 2, 1, 3)
|
|
151
|
+
|
|
152
|
+
gridlayout.addWidget(self.combobox_alg, 0, 4, 1, 1)
|
|
153
|
+
gridlayout.addWidget(self.spinbox_minclusters, 1, 4, 1, 1)
|
|
154
|
+
gridlayout.addWidget(self.spinbox_maxclusters, 2, 4, 1, 1)
|
|
155
|
+
gridlayout.addWidget(self.spinbox_maxiterations, 3, 4, 1, 1)
|
|
156
|
+
gridlayout.addWidget(self.doublespinbox_maxerror, 4, 4, 1, 1)
|
|
157
|
+
gridlayout.addWidget(self.spinbox_repeatedruns, 5, 4, 1, 1)
|
|
158
|
+
gridlayout.addWidget(self.doublespinbox_constraincluster, 6, 4, 1, 1)
|
|
159
|
+
gridlayout.addWidget(self.doublespinbox_fuzzynessexp, 7, 4, 1, 1)
|
|
160
|
+
gridlayout.addWidget(buttonbox, 10, 4, 1, 1)
|
|
161
|
+
|
|
162
|
+
verticallayout.addWidget(self.radiobutton_random)
|
|
163
|
+
verticallayout.addWidget(self.radiobutton_manual)
|
|
164
|
+
verticallayout.addWidget(self.radiobutton_datadriven)
|
|
165
|
+
|
|
166
|
+
buttonbox.accepted.connect(self.accept)
|
|
167
|
+
buttonbox.rejected.connect(self.reject)
|
|
168
|
+
|
|
169
|
+
def combo(self):
|
|
170
|
+
""" Combo box """
|
|
171
|
+
i = str(self.combobox_alg.currentText())
|
|
172
|
+
if i == 'Gath-Geva' or i == 'Gustafson-Kessel':
|
|
173
|
+
self.label_7.show()
|
|
174
|
+
self.doublespinbox_constraincluster.show()
|
|
175
|
+
else:
|
|
176
|
+
self.label_7.hide()
|
|
177
|
+
self.doublespinbox_constraincluster.hide()
|
|
178
|
+
|
|
179
|
+
def settings(self):
|
|
180
|
+
""" Settings """
|
|
181
|
+
tst = np.unique([i.data.shape for i in self.indata['Raster']])
|
|
182
|
+
if tst.size > 2:
|
|
183
|
+
self.reportback('Error: Your input datasets have different ' +
|
|
184
|
+
'sizes. Merge the data first')
|
|
185
|
+
return
|
|
186
|
+
|
|
187
|
+
self.update_vars()
|
|
188
|
+
temp = self.exec_()
|
|
189
|
+
if temp == 0:
|
|
190
|
+
return
|
|
191
|
+
|
|
192
|
+
self.parent.process_is_active()
|
|
193
|
+
self.run()
|
|
194
|
+
self.parent.process_is_active(False)
|
|
195
|
+
|
|
196
|
+
self.pbar.to_max()
|
|
197
|
+
return True
|
|
198
|
+
|
|
199
|
+
def update_vars(self):
|
|
200
|
+
""" Updates the variables """
|
|
201
|
+
self.cltype = str(self.combobox_alg.currentText())
|
|
202
|
+
self.min_cluster = self.spinbox_minclusters.value()
|
|
203
|
+
self.max_cluster = self.spinbox_maxclusters.value()
|
|
204
|
+
self.max_iter = self.spinbox_maxiterations.value()
|
|
205
|
+
self.term_thresh = self.doublespinbox_maxerror.value()
|
|
206
|
+
self.runs = self.spinbox_repeatedruns.value()
|
|
207
|
+
self.constrain = self.doublespinbox_constraincluster.value()
|
|
208
|
+
self.denorm = self.checkbox_denorm.isChecked()
|
|
209
|
+
self.fexp = self.doublespinbox_fuzzynessexp.value()
|
|
210
|
+
|
|
211
|
+
# self.cltype = tmp.cltype_list[tmp.cltype_val]
|
|
212
|
+
# self.cltype_val = tmp.cltype_val
|
|
213
|
+
# self.init_type = tmp.init_type
|
|
214
|
+
|
|
215
|
+
def run(self):
|
|
216
|
+
""" Entrypoint into routine """
|
|
217
|
+
data = copy.copy(self.indata['Raster'])
|
|
218
|
+
self.update_vars()
|
|
219
|
+
|
|
220
|
+
# if datachecks.Datachecks(self).multdata(data) == False:
|
|
221
|
+
# return data
|
|
222
|
+
# if datachecks.Datachecks(self).isdata(data) == False:
|
|
223
|
+
# return data
|
|
224
|
+
# if datachecks.Datachecks(self).equalsize(data) == False:
|
|
225
|
+
# return data
|
|
226
|
+
# if datachecks.Datachecks(self).samecoords(data) == False:
|
|
227
|
+
# return data
|
|
228
|
+
# if datachecks.Datachecks(self).iscomplete(data) == False:
|
|
229
|
+
# return data
|
|
230
|
+
|
|
231
|
+
cltype = self.cltype
|
|
232
|
+
cov_constr = self.constrain
|
|
233
|
+
no_runs = self.runs
|
|
234
|
+
max_iter = self.max_iter
|
|
235
|
+
term_thresh = self.term_thresh
|
|
236
|
+
no_clust = np.array([self.min_cluster, self.max_cluster])
|
|
237
|
+
de_norm = self.denorm
|
|
238
|
+
expo = self.fexp
|
|
239
|
+
|
|
240
|
+
self.reportback('Fuzzy Clustering started')
|
|
241
|
+
|
|
242
|
+
# #############################################################################
|
|
243
|
+
# Section to deal with different bands having different null values.
|
|
244
|
+
masktmp = data[0].data.mask # Start with the first entry
|
|
245
|
+
# Add the masks to this.This promotes False values to True if necessary
|
|
246
|
+
for i in data:
|
|
247
|
+
masktmp += i.data.mask
|
|
248
|
+
for i in range(len(data)): # Apply this to all the bands
|
|
249
|
+
data[i].data.mask = masktmp
|
|
250
|
+
# #############################################################################
|
|
251
|
+
|
|
252
|
+
dat_in = np.array([i.data.compressed() for i in data]).T
|
|
253
|
+
# dat_in = np.array([i.data.flatten() for i in data]).T
|
|
254
|
+
|
|
255
|
+
# dat_in = np.array([[x for x in data[ii].data.flatten() if x != None]\
|
|
256
|
+
# for ii in range(len(data))]).T
|
|
257
|
+
|
|
258
|
+
if self.radiobutton_manual.isChecked() is True:
|
|
259
|
+
ext = \
|
|
260
|
+
"ASCII matrix (*.txt);;" + \
|
|
261
|
+
"ASCII matrix (*.asc);;" + \
|
|
262
|
+
"ASCII matrix (*.dat)"
|
|
263
|
+
filename = QtGui.QFileDialog.getOpenFileName(
|
|
264
|
+
self.parent, 'Read Cluster Centers', '.', ext)
|
|
265
|
+
if filename == '':
|
|
266
|
+
return False
|
|
267
|
+
|
|
268
|
+
os.chdir(filename.rpartition('/')[0])
|
|
269
|
+
ifile = str(filename)
|
|
270
|
+
|
|
271
|
+
dummy_mod = np.ma.array(np.genfromtxt(ifile, unpack=True))
|
|
272
|
+
[row, col] = np.shape(dummy_mod)
|
|
273
|
+
ro1 = np.sum(list(range(no_clust[0], no_clust[1] + 1)))
|
|
274
|
+
|
|
275
|
+
if dat_in.shape[1] != col or row != ro1:
|
|
276
|
+
QtGui.QMessageBox.warning(self.parent, 'Warning',
|
|
277
|
+
' Incorrect matrix size!',
|
|
278
|
+
QtGui.QMessageBox.Ok,
|
|
279
|
+
QtGui.QMessageBox.Ok)
|
|
280
|
+
|
|
281
|
+
cnt = -1
|
|
282
|
+
for i in range(no_clust[0], no_clust[1] + 1):
|
|
283
|
+
smtmp = np.zeros(i)
|
|
284
|
+
for j in range(i):
|
|
285
|
+
cnt = cnt + 1
|
|
286
|
+
smtmp[j] = dummy_mod[cnt]
|
|
287
|
+
startmdat = {i: smtmp}
|
|
288
|
+
startmfix = {i: []}
|
|
289
|
+
|
|
290
|
+
filename = QtGui.QFileDialog.getOpenFileName(
|
|
291
|
+
self.parent, 'Read Cluster Center Constraints', '.', ext)
|
|
292
|
+
if filename == '':
|
|
293
|
+
QtGui.QMessageBox.warning(
|
|
294
|
+
self.parent, 'Warning',
|
|
295
|
+
'Running cluster analysis without constraints',
|
|
296
|
+
QtGui.QMessageBox.Ok, QtGui.QMessageBox.Ok)
|
|
297
|
+
else:
|
|
298
|
+
ifile = str(filename)
|
|
299
|
+
dummy_mod = np.ma.array(np.genfromtxt(ifile, unpack=True))
|
|
300
|
+
[row, col] = np.shape(dummy_mod)
|
|
301
|
+
ro1 = np.sum(list(range(no_clust[0], no_clust[1] + 1)))
|
|
302
|
+
if dat_in.shape[1] != col or row != ro1:
|
|
303
|
+
QtGui.QMessageBox.warning(
|
|
304
|
+
self.parent, 'Warning', ' Incorrect matrix size!',
|
|
305
|
+
QtGui.QMessageBox.Ok, QtGui.QMessageBox.Ok)
|
|
306
|
+
cnt = -1
|
|
307
|
+
for i in range(no_clust[0], no_clust[1] + 1):
|
|
308
|
+
smtmp = np.zeros(i)
|
|
309
|
+
for j in range(i):
|
|
310
|
+
cnt = cnt + 1
|
|
311
|
+
smtmp = dummy_mod[cnt]
|
|
312
|
+
startmfix = {i: smtmp}
|
|
313
|
+
|
|
314
|
+
cnt = -1
|
|
315
|
+
dat_out = [Clust() for i in range(no_clust[0], no_clust[1] + 1)]
|
|
316
|
+
|
|
317
|
+
for i in range(no_clust[0], no_clust[1] + 1):
|
|
318
|
+
self.reportback('Number of Clusters:' + str(i))
|
|
319
|
+
cnt = cnt + 1
|
|
320
|
+
if self.radiobutton_datadriven.isChecked() is True:
|
|
321
|
+
self.reportback('Initial guess: data driven')
|
|
322
|
+
|
|
323
|
+
no_samp = dat_in.shape[0]
|
|
324
|
+
dno_samp = no_samp / i
|
|
325
|
+
# idx=1
|
|
326
|
+
# idx=[[idx,(jj-1)*dno_samp] for jj in range(2,ii+1)]
|
|
327
|
+
idx = np.arange(0, no_samp + dno_samp, dno_samp)
|
|
328
|
+
idx[0] = 1
|
|
329
|
+
# idx=np.array([idx,no_samp])
|
|
330
|
+
startmdat = {i: np.zeros([i, dat_in.shape[1]])}
|
|
331
|
+
dat_in1 = dat_in
|
|
332
|
+
smtmp = np.zeros([i, dat_in.shape[1]])
|
|
333
|
+
for k in range(dat_in.shape[1]):
|
|
334
|
+
# this is same as matlab sortrows
|
|
335
|
+
# dat_in1[dat_in1[:, k].argsort()]
|
|
336
|
+
for j in range(i):
|
|
337
|
+
smtmp[j, k] = np.median(dat_in1[idx[j]:idx[j + 1], k])
|
|
338
|
+
startmdat = {i: smtmp}
|
|
339
|
+
startmfix = {i: np.array([])} # inserted 'np.array'
|
|
340
|
+
del dat_in1
|
|
341
|
+
|
|
342
|
+
clu, clcent, clobj_fcn, clvrc, clnce, clxbi = self.fuzzy_means(
|
|
343
|
+
dat_in, i, startmdat[i], startmfix[i], max_iter,
|
|
344
|
+
term_thresh, expo, cltype, cov_constr)
|
|
345
|
+
|
|
346
|
+
elif self.radiobutton_manual.isChecked() is True:
|
|
347
|
+
self.reportback('Initial guess: manual')
|
|
348
|
+
|
|
349
|
+
clu, clcent, clobj_fcn, clvrc, clnce, clxbi = self.fuzzy_means(
|
|
350
|
+
dat_in, i, startmdat[i], startmfix[i],
|
|
351
|
+
max_iter, term_thresh, expo, cltype, cov_constr)
|
|
352
|
+
|
|
353
|
+
elif self.radiobutton_random.isChecked() is True:
|
|
354
|
+
self.reportback('Initial guess: random')
|
|
355
|
+
|
|
356
|
+
clobj_fcn = np.array([np.Inf])
|
|
357
|
+
for j in range(no_runs):
|
|
358
|
+
self.reportback('Run ' + str(j) + ' of' + str(no_runs))
|
|
359
|
+
|
|
360
|
+
xmins = np.minimum(dat_in, 1)
|
|
361
|
+
xmaxs = np.maximum(dat_in, 1)
|
|
362
|
+
startm1dat = {i: np.random.uniform(
|
|
363
|
+
xmins[np.zeros(i, int), :],
|
|
364
|
+
xmaxs[np.zeros(i, int), :])}
|
|
365
|
+
startmfix = {i: np.array([])}
|
|
366
|
+
clu1, clcent1, clobj_fcn1, clvrc1, clnce1, clxbi1 = \
|
|
367
|
+
self.fuzzy_means(dat_in, i, startm1dat[i],
|
|
368
|
+
startmfix[i], max_iter, term_thresh,
|
|
369
|
+
expo, cltype, cov_constr)
|
|
370
|
+
|
|
371
|
+
if clobj_fcn1[-1] < clobj_fcn[-1]:
|
|
372
|
+
clu = clu1
|
|
373
|
+
clcent = clcent1
|
|
374
|
+
clobj_fcn = clobj_fcn1
|
|
375
|
+
clnce = clnce1
|
|
376
|
+
clxbi = clxbi1
|
|
377
|
+
clvrc = clvrc1
|
|
378
|
+
startmdat = {i: startm1dat[i]}
|
|
379
|
+
|
|
380
|
+
clalp = np.array(clu).max(0) # 0 means row wize max?
|
|
381
|
+
clidx = np.array(clu).argmax(0)
|
|
382
|
+
clalp = clalp - (1.0 / clcent.shape[0])
|
|
383
|
+
clalp = clalp / clalp.max()
|
|
384
|
+
clalp[clalp > 1] = 1
|
|
385
|
+
clalp[clalp < 0] = 0
|
|
386
|
+
zonal = np.ma.zeros(data[0].data.shape)-9999.0
|
|
387
|
+
alpha = np.ma.zeros(data[0].data.shape)-9999.0
|
|
388
|
+
alpha1 = (data[0].data.mask == 0)
|
|
389
|
+
zonal[alpha1 == 1] = clidx
|
|
390
|
+
alpha[alpha1 == 1] = clalp
|
|
391
|
+
zonal.mask = data[0].data.mask
|
|
392
|
+
alpha.mask = data[0].data.mask
|
|
393
|
+
|
|
394
|
+
cent_std = np.array([np.std(dat_in[clidx == k], 0)
|
|
395
|
+
for k in range(i)])
|
|
396
|
+
|
|
397
|
+
den_cent = clcent
|
|
398
|
+
den_cent_std = np.array(cent_std, copy=True)
|
|
399
|
+
den_cent_std1 = np.array(cent_std, copy=True)
|
|
400
|
+
|
|
401
|
+
if de_norm == 1:
|
|
402
|
+
for k in range(len(data)):
|
|
403
|
+
if np.size(data[k].norm) > 0:
|
|
404
|
+
nnorm = len(data[k].norm)
|
|
405
|
+
for j in range(nnorm, 0, -1):
|
|
406
|
+
if data[k].norm[j - 1]['type'] == 'minmax':
|
|
407
|
+
den_cent[:, k] = (
|
|
408
|
+
den_cent[:, k] *
|
|
409
|
+
(data[k].norm[j - 1]['transform'][1, 1] -
|
|
410
|
+
data[k].norm[j - 1]['transform'][0, 1]) +
|
|
411
|
+
data[k].norm[j - 1]['transform'][0, 1])
|
|
412
|
+
den_cent_std[:, k] = (
|
|
413
|
+
den_cent_std[:, k] *
|
|
414
|
+
(data[k].norm[j - 1]['transform'][1, 1] -
|
|
415
|
+
data[k].norm[j - 1]['transform'][0, 1]) +
|
|
416
|
+
data[k].norm[j - 1]['transform'][0, 1])
|
|
417
|
+
den_cent_std1[:, k] = (
|
|
418
|
+
den_cent_std1[:, k] *
|
|
419
|
+
(data[k].norm[j - 1]['transform'][1, 1] -
|
|
420
|
+
data[k].norm[j - 1]['transform'][0, 1]) +
|
|
421
|
+
data[k].norm[j - 1]['transform'][0, 1])
|
|
422
|
+
elif (data[k].norm[j - 1]['type'] == 'meanstd' or
|
|
423
|
+
data[k].norm[j - 1]['type'] == 'medmad'):
|
|
424
|
+
den_cent[:, k] = (
|
|
425
|
+
den_cent[:, k] *
|
|
426
|
+
data[k].norm[j - 1]['transform'][1, 1] +
|
|
427
|
+
data[k].norm[j - 1]['transform'][0, 1])
|
|
428
|
+
den_cent_std[:, k] = (
|
|
429
|
+
den_cent_std[:, k] *
|
|
430
|
+
data[k].norm[j - 1]['transform'][1, 1] +
|
|
431
|
+
data[k].norm[j - 1]['transform'][0, 1])
|
|
432
|
+
den_cent_std1[:, k] = (
|
|
433
|
+
den_cent_std1[:, k] *
|
|
434
|
+
data[k].norm[j - 1]['transform'][1, 1] +
|
|
435
|
+
data[k].norm[j - 1]['transform'][0, 1])
|
|
436
|
+
elif data[k].norm[j - 1]['type'] == 'histeq':
|
|
437
|
+
den_cent[:, k] = np.interp(
|
|
438
|
+
den_cent[:, k],
|
|
439
|
+
data[k].norm[j - 1]['transform'][:, 0],
|
|
440
|
+
data[k].norm[j - 1]['transform'][:, 1])
|
|
441
|
+
den_cent_std[:, k] = np.interp(
|
|
442
|
+
(den_cent[:, k] + den_cent_std[:, k]),
|
|
443
|
+
data[k].norm[j - 1]['transform'][:, 0],
|
|
444
|
+
data[k].norm[j - 1]['transform'][:, 1])
|
|
445
|
+
den_cent_std1[:, k] = np.interp(
|
|
446
|
+
(den_cent[:, k] - den_cent_std1[:, k]),
|
|
447
|
+
data[k].norm[j - 1]['transform'][:, 0],
|
|
448
|
+
data[k].norm[j - 1]['transform'][:, 1])
|
|
449
|
+
else:
|
|
450
|
+
den_cent = np.array([])
|
|
451
|
+
den_cent_std = np.array([])
|
|
452
|
+
den_cent_std1 = np.array([])
|
|
453
|
+
|
|
454
|
+
for k in data:
|
|
455
|
+
dat_out[cnt].input_type.append(k.dataid)
|
|
456
|
+
# dat_out[cnt].proc_history.append(k.proc)
|
|
457
|
+
|
|
458
|
+
dat_out[cnt].data = np.ma.array(zonal)
|
|
459
|
+
dat_out[cnt].no_clusters = i
|
|
460
|
+
dat_out[cnt].center = clcent
|
|
461
|
+
dat_out[cnt].center_std = cent_std
|
|
462
|
+
for k in range(clcent.shape[0]):
|
|
463
|
+
dummy = np.ones(data[0].data.shape) * np.nan
|
|
464
|
+
alpha1 = (data[0].data.mask == 0)
|
|
465
|
+
dummy[alpha1 == 1] = clu[k, :]
|
|
466
|
+
dat_out[cnt].memdat.append(dummy)
|
|
467
|
+
dat_out[cnt].vrc = clvrc
|
|
468
|
+
dat_out[cnt].nce = clnce
|
|
469
|
+
dat_out[cnt].xbi = clxbi
|
|
470
|
+
dat_out[cnt].obj_fcn = clobj_fcn
|
|
471
|
+
|
|
472
|
+
# dat_out[cnt].type = self.type
|
|
473
|
+
# dat_out[cnt].algorithm = cltype
|
|
474
|
+
# dat_out[cnt].initialization = init_type
|
|
475
|
+
# dat_out[cnt].init_mod = startmdat[i]
|
|
476
|
+
# dat_out[cnt].init_constrains = startmfix[i]
|
|
477
|
+
# dat_out[cnt].runs = no_runs
|
|
478
|
+
# dat_out[cnt].max_iterations = max_iter
|
|
479
|
+
# dat_out[cnt].denormalize = de_norm
|
|
480
|
+
# dat_out[cnt].term_threshold = term_thresh
|
|
481
|
+
# dat_out[cnt].shape_constrain = cov_constr
|
|
482
|
+
# dat_out[cnt].zonal = zonal
|
|
483
|
+
# dat_out[cnt].alpha = alpha
|
|
484
|
+
# dat_out[cnt].memdat = np.ma.array(dat_out[cnt].memdat)
|
|
485
|
+
# dat_out[cnt].memdat.mask = dat_out[cnt].alpha.mask
|
|
486
|
+
# dat_out[cnt].xxx = data[0].xxx
|
|
487
|
+
# dat_out[cnt].yyy = data[0].yyy
|
|
488
|
+
# dat_out[cnt].denorm_center = den_cent
|
|
489
|
+
# dat_out[cnt].denorm_center_stdup = den_cent_std
|
|
490
|
+
# dat_out[cnt].denorm_center_stdlow = den_cent_std1
|
|
491
|
+
# dat_out[cnt].iterations = clobj_fcn.size
|
|
492
|
+
# dat_out[cnt].fuzziness_exp = expo
|
|
493
|
+
|
|
494
|
+
# gaugetmp.crisplogtxt.Value += '\n'+logtxt
|
|
495
|
+
|
|
496
|
+
for i in dat_out:
|
|
497
|
+
i.tlx = data[0].tlx
|
|
498
|
+
i.tly = data[0].tly
|
|
499
|
+
i.xdim = data[0].xdim
|
|
500
|
+
i.ydim = data[0].ydim
|
|
501
|
+
i.nrofbands = 1
|
|
502
|
+
i.dataid = 'Fuzzy Cluster: ' + str(i.no_clusters)
|
|
503
|
+
i.rows = data[0].rows
|
|
504
|
+
i.cols = data[0].cols
|
|
505
|
+
i.nullvalue = data[0].nullvalue
|
|
506
|
+
|
|
507
|
+
self.reportback("Fuzzy Cluster complete" + ' (' + self.cltype + ' ' +
|
|
508
|
+
self.init_type + ')')
|
|
509
|
+
|
|
510
|
+
self.outdata['Cluster'] = dat_out
|
|
511
|
+
return True
|
|
512
|
+
|
|
513
|
+
def fuzzy_means(self, data, no_clust, init, centfix, maxit, term_thresh,
|
|
514
|
+
expo, cltype, cov_constr):
|
|
515
|
+
""" Fuzzy Means """
|
|
516
|
+
# Fuzzy clustering, supported algorithms:
|
|
517
|
+
# fuzzy c-means, Gustafson-Kessel, advanced fuzzy c-means
|
|
518
|
+
# ATTENTION: all input parameter are required and must be provided!
|
|
519
|
+
#
|
|
520
|
+
#
|
|
521
|
+
# [CENTER, uuu, OBJ_FCN] = fuzzy_means(DATA, NO_CLUST, INIT, MAXIT,
|
|
522
|
+
# TERM_THRESH, EXPO, CLTYPE, COV_CONSTR)
|
|
523
|
+
# finds NO_CLUST clusters in the data set DATA.
|
|
524
|
+
# DATA is size M-by-N, where M is the number of samples
|
|
525
|
+
# and N is the number of coordinates (attributes) for each sample.
|
|
526
|
+
# INIT may be set to [], in this case the fcm generates random
|
|
527
|
+
# initial center locations to start the algorithm. Alternatively,
|
|
528
|
+
# INIT can be of matrix type, either containing a user-given membership
|
|
529
|
+
# matrix [NO_CLUST M] or a cluster center matrix [NO_CLUST,
|
|
530
|
+
# N].
|
|
531
|
+
# MAXIT give the maximum number of iterations.
|
|
532
|
+
# TERM_THRESH gives the required minimum improvement in per cent per
|
|
533
|
+
# iteration. (termination threshold)
|
|
534
|
+
# EXPO: Fuzzification exponent
|
|
535
|
+
# CLTYPE: either 'FCM' for fuzy c-means (spherically shaped clusters),
|
|
536
|
+
# 'DET' for advanced fuzzy c-means (ellipsoidal clusters, all clusters
|
|
537
|
+
# use the same ellipsoid), or 'GK' for Gustafson-Kessel clustering
|
|
538
|
+
# (ellipsoidal clusters, each cluster uses its own ellipsoid).
|
|
539
|
+
# COV_CONSTR applies only to the GK algorithm. constrians the cluster
|
|
540
|
+
# shape towards spherical clusters to avoid needle-like clusters.
|
|
541
|
+
# COV_CONSTR = 1 make the GK algorithm equal to the FCM algorithm,
|
|
542
|
+
# COV_CONSTR = 0 results in no constraining of the covarince matrices of
|
|
543
|
+
# the clusters.
|
|
544
|
+
#
|
|
545
|
+
#
|
|
546
|
+
# The
|
|
547
|
+
# coordinates for each cluster center are returned in the rows of the
|
|
548
|
+
# matrix CENT. The membership function matrix uuu contains the grade of
|
|
549
|
+
# membership of each data sample to each cluster. At each iteration, an
|
|
550
|
+
# objective function is minimized to find the best location for the
|
|
551
|
+
# clusters and its values are returned in OBJ_FCN.
|
|
552
|
+
self.reportback(' ')
|
|
553
|
+
|
|
554
|
+
if cltype == 'fuzzy c-means':
|
|
555
|
+
cltype = 'fcm'
|
|
556
|
+
if cltype == 'advanced fuzzy c-means':
|
|
557
|
+
cltype = 'det'
|
|
558
|
+
if cltype == 'Gustafson-Kessel':
|
|
559
|
+
cltype = 'gk'
|
|
560
|
+
if cltype == 'Gath-Geva':
|
|
561
|
+
cltype = 'gg'
|
|
562
|
+
|
|
563
|
+
# [no_samples, data_types] = size(data) [no of data points,
|
|
564
|
+
# no of data types]
|
|
565
|
+
no_samples = data.shape[0]
|
|
566
|
+
data_types = data.shape[1]
|
|
567
|
+
|
|
568
|
+
uuu = [] # dummy definition of membership matrix
|
|
569
|
+
|
|
570
|
+
# if neither initial centers nor initial meberships are provided -> random
|
|
571
|
+
# guess
|
|
572
|
+
if init.size == 0:
|
|
573
|
+
xmins = np.minimum(data, 1)
|
|
574
|
+
xmaxs = np.maximum(data, 1)
|
|
575
|
+
# initial guess of centroids
|
|
576
|
+
cent = np.random.uniform(xmins[np.zeros(no_clust, int), :],
|
|
577
|
+
xmaxs[np.zeros(no_clust, int), :])
|
|
578
|
+
# GK and det clustering require center and memberships for distance
|
|
579
|
+
# calculation: here initial guess for uuu assuming spherically shaped
|
|
580
|
+
# clusters
|
|
581
|
+
# if strcmp('DET',cltype) == 1 | strcmp('det',cltype) == 1 | \
|
|
582
|
+
# strcmp('GK',cltype) == 1 | strcmp('gk',cltype) == 1 | \
|
|
583
|
+
# strcmp('GG',cltype) == 1 | strcmp('gg',cltype) == 1
|
|
584
|
+
# calc distances of each data point to each cluster centre assuming
|
|
585
|
+
# spherical clusters
|
|
586
|
+
edist = self.fuzzy_dist(cent, data, [], [], 'fcm', cov_constr)
|
|
587
|
+
tmp = edist ** (-2 / (expo - 1)) # calc new U, suppose expo != 1
|
|
588
|
+
uuu = tmp / (np.ones([no_clust, 1]) * np.sum(tmp, 0))
|
|
589
|
+
m_f = uuu ** expo # m_f matrix after exponential modification
|
|
590
|
+
# if center matrix is provided
|
|
591
|
+
elif init.shape[0] == no_clust and init.shape[1] == data_types:
|
|
592
|
+
cent = init
|
|
593
|
+
# if strcmp('DET',cltype) == 1 | strcmp('det',cltype) == 1 | \
|
|
594
|
+
# strcmp('GK',cltype) == 1 | strcmp('gk',cltype) == 1 | \
|
|
595
|
+
# strcmp('GG',cltype) == 1 | strcmp('gg',cltype) == 1
|
|
596
|
+
# calc distances of each data point to each cluster centre assuming
|
|
597
|
+
# spherical clusters
|
|
598
|
+
edist = self.fuzzy_dist(cent, data, [], [], 'fcm', cov_constr)
|
|
599
|
+
tmp = edist ** (-2.0 / (expo - 1)) # calc new U, suppose expo != 1
|
|
600
|
+
uuu = tmp / (np.ones([no_clust, 1]) * np.sum(tmp, 0))
|
|
601
|
+
m_f = uuu ** expo # MF matrix after exponential modification
|
|
602
|
+
# if membership matrix is provided
|
|
603
|
+
elif init.shape[0] == no_clust and init.shape[1] == no_samples:
|
|
604
|
+
if init[init < 0].size > 0: # check for negative memberships
|
|
605
|
+
self.parent.showprocesslog('No negative memberships allowed!')
|
|
606
|
+
# scale given memberships to a column sum of unity
|
|
607
|
+
uuu = init / (np.ones([no_clust, 1]) * init.sum())
|
|
608
|
+
# MF matrix after exponential modification
|
|
609
|
+
m_f = uuu ** expo
|
|
610
|
+
# new inital center matrix based on the given membership
|
|
611
|
+
cent = m_f * data / ((np.ones([np.size(data, 2), 1]) *
|
|
612
|
+
(m_f.T).sum()).T)
|
|
613
|
+
# calc distances of each data point to each cluster centre assuming
|
|
614
|
+
# spherical clusters
|
|
615
|
+
edist = self.fuzzy_dist(cent, data, [], [], 'fcm', cov_constr)
|
|
616
|
+
|
|
617
|
+
# cent_orig = cent
|
|
618
|
+
centfix = abs(centfix)
|
|
619
|
+
|
|
620
|
+
# only need to sum once in python
|
|
621
|
+
# initial size of objective function
|
|
622
|
+
# obj_fcn_initial = np.sum((edist**2)*m_f)
|
|
623
|
+
# obj_fcn_prev = obj_fcn_initial
|
|
624
|
+
obj_fcn = np.zeros(maxit) # This is new - we must initialize this.
|
|
625
|
+
|
|
626
|
+
# hh = waitbar(0,['No. of clusters: ',
|
|
627
|
+
# num2unicode(info(1)),'/[',num2unicode(info(2)),
|
|
628
|
+
# ' ',num2unicode(info(3)),'] Run: ',num2unicode(info(4)),'/',
|
|
629
|
+
# num2unicode(info(5))])
|
|
630
|
+
for i in self.pbar.iter(range(maxit)): # loop over all iterations
|
|
631
|
+
# waitbar(i/maxit,hh)
|
|
632
|
+
cent_prev = cent # store result of last iteration
|
|
633
|
+
uprev = uuu
|
|
634
|
+
dist_prev = edist
|
|
635
|
+
if i > 0:
|
|
636
|
+
# calc new centers
|
|
637
|
+
cent = np.dot(m_f, data) / ((np.ones([data.shape[1], 1]) *
|
|
638
|
+
np.sum(m_f, 1)).T)
|
|
639
|
+
# calc distances of each data point to each cluster centre
|
|
640
|
+
edist = self.fuzzy_dist(cent, data, uuu, expo, cltype, cov_constr)
|
|
641
|
+
tmp = edist ** (-2 / (expo - 1)) # calc new uuu, suppose expo != 1
|
|
642
|
+
uuu = tmp / np.sum(tmp, 0)
|
|
643
|
+
m_f = uuu ** expo
|
|
644
|
+
obj_fcn[i] = np.sum((edist ** 2) * m_f) # objective function
|
|
645
|
+
if i > 0:
|
|
646
|
+
self.reportback('Iteration: ' + str(i) + ' Threshold: ' +
|
|
647
|
+
str(term_thresh) + ' Current: ' +
|
|
648
|
+
'{:.2e}'.format(100 * ((obj_fcn[i - 1] -
|
|
649
|
+
obj_fcn[i]) /
|
|
650
|
+
obj_fcn[i - 1])), True)
|
|
651
|
+
|
|
652
|
+
# if i > 0:
|
|
653
|
+
# if objective function has increased
|
|
654
|
+
if obj_fcn[i] > obj_fcn[i - 1]:
|
|
655
|
+
uuu = uprev # use memberships and
|
|
656
|
+
cent = cent_prev # centers od the previous iteration
|
|
657
|
+
# eliminate last value for objective function and
|
|
658
|
+
# obj_fcn[i]=[]
|
|
659
|
+
obj_fcn = np.delete(obj_fcn, np.s_[i::])
|
|
660
|
+
edist = dist_prev
|
|
661
|
+
# [max_v,idx]=max(U)
|
|
662
|
+
# vrc=var_ratio(data, idx, cent, edist)
|
|
663
|
+
# nce=(-1*(sum(sum(U.*log10(U)))/length(U(1,:))))/ \
|
|
664
|
+
# log10(length(U(:,1)))
|
|
665
|
+
# xbi=xie_beni(data, expo, uuu, cent, edist)
|
|
666
|
+
break # terminate
|
|
667
|
+
# if improvement less than given termination threshold
|
|
668
|
+
elif (obj_fcn[i-1]-obj_fcn[i])/obj_fcn[i-1] < term_thresh/100:
|
|
669
|
+
# vrc=var_ratio(data, idx, cent, edist)
|
|
670
|
+
# nce=(-1*(sum(sum(U.*log10(U)))/length(U(1,:))))/ \
|
|
671
|
+
# log10(length(U(:,1)))
|
|
672
|
+
# xbi = xie_beni(data, expo, uuu, cent, edist)
|
|
673
|
+
break # terminate
|
|
674
|
+
# obj_fcn_prev = obj_fcn[i]
|
|
675
|
+
|
|
676
|
+
# [max_v,idx] = max(U)
|
|
677
|
+
# max_v = np.max(uuu, 0)
|
|
678
|
+
idx = np.argmax(uuu, 0)
|
|
679
|
+
vrc = vr.var_ratio(data, idx, cent, edist)
|
|
680
|
+
nce = (-1.0 * (np.sum(uuu * np.log10(uuu)) / np.shape(uuu)[1]) /
|
|
681
|
+
np.log10(np.shape(uuu)[0]))
|
|
682
|
+
xbi = xb.xie_beni(data, expo, uuu, cent, edist)
|
|
683
|
+
# close(hh)
|
|
684
|
+
return uuu, cent, obj_fcn, vrc, nce, xbi
|
|
685
|
+
|
|
686
|
+
# -----------------------------------------------------------------------------
|
|
687
|
+
|
|
688
|
+
def fuzzy_dist2(self, cent, data, uuu, expo, cltype, cov_constr):
|
|
689
|
+
""" Fuzzy dist 2 """
|
|
690
|
+
no_datasets = data.shape[1]
|
|
691
|
+
ddd = np.zeros([cent.shape[0], data.shape[0]])
|
|
692
|
+
if cltype == 'FCM' or cltype == 'fcm':
|
|
693
|
+
for j in range(cent.shape[0]):
|
|
694
|
+
ddd[j, :] = np.sqrt(np.sum(((data - np.ones([data.shape[0], 1])
|
|
695
|
+
* cent[j]) ** 2), 1))
|
|
696
|
+
# determinant criterion see Spath, Helmuth,
|
|
697
|
+
# "Cluster-Formation and Analyse",
|
|
698
|
+
# chapter 3
|
|
699
|
+
elif cltype == 'DET' or cltype == 'det':
|
|
700
|
+
m_f = uuu ** expo
|
|
701
|
+
for j in range(cent.shape[0]):
|
|
702
|
+
# difference between each sample attribute to the corresponding
|
|
703
|
+
# attribute of the j-th cluster
|
|
704
|
+
dcent = data - np.ones([data.shape[0], 1]) * cent[j]
|
|
705
|
+
aaa = np.dot(np.ones([cent.shape[1], 1]) * m_f[j] * dcent.T,
|
|
706
|
+
dcent / np.sum(m_f[j], 0)) # Covariance of the
|
|
707
|
+
# j-th cluster
|
|
708
|
+
|
|
709
|
+
# constrain covariance matrix if badly conditioned
|
|
710
|
+
if np.linalg.cond(aaa) > 1e10:
|
|
711
|
+
e_d, e_v = np.linalg.eig(aaa)
|
|
712
|
+
edmax = np.max(e_d)
|
|
713
|
+
e_d[1e10 * e_d < edmax] = edmax / 1e10
|
|
714
|
+
aaa = np.dot(np.dot(e_v, (e_d * np.eye(no_datasets))),
|
|
715
|
+
np.linalg.inv(e_v))
|
|
716
|
+
if j == 0: # sum all covariance matrices for all clusters
|
|
717
|
+
aaa0 = aaa
|
|
718
|
+
else:
|
|
719
|
+
aaa0 = aaa0 + aaa
|
|
720
|
+
mmm = np.linalg.det(aaa0) ** (1.0 / cent.shape[1]) * \
|
|
721
|
+
np.linalg.pinv(aaa0)
|
|
722
|
+
dtmp = []
|
|
723
|
+
# calc new distances using the same covariance matrix for all clusters -->
|
|
724
|
+
# ellisoidal clusters, all clusters use equal ellipsoids
|
|
725
|
+
for j in range(cent.shape[0]):
|
|
726
|
+
# difference between each sample attribute to the
|
|
727
|
+
# corresponding attribute of the j-th cluster
|
|
728
|
+
dcent = data - np.ones([data.shape[0], 1]) * cent[j]
|
|
729
|
+
dtmp.append(np.sum(np.dot(dcent, mmm) * dcent, 1).T)
|
|
730
|
+
ddd = np.sqrt(np.array(dtmp))
|
|
731
|
+
elif cltype == 'GK' or cltype == 'gk':
|
|
732
|
+
m_f = uuu ** expo
|
|
733
|
+
dtmp = []
|
|
734
|
+
for j in range(cent.shape[0]):
|
|
735
|
+
# difference between each sample attribute to the
|
|
736
|
+
# corresponding attribute of the j-th cluster
|
|
737
|
+
dcent = data - np.ones([data.shape[0], 1]) * cent[j]
|
|
738
|
+
aaa = np.dot(np.ones([cent.shape[1], 1]) * m_f[j] * dcent.T,
|
|
739
|
+
dcent / np.sum(m_f[j], 0)) # Covariance of the
|
|
740
|
+
# j-th cluster
|
|
741
|
+
aaa0 = np.eye(aaa.shape[0])
|
|
742
|
+
# if cov_constr>0, this enforces not to elongated ellipsoids --> avoid the
|
|
743
|
+
# needle-like cluster
|
|
744
|
+
aaa = (1.0 - cov_constr) * aaa + cov_constr * (aaa0 /
|
|
745
|
+
data.shape[0])
|
|
746
|
+
# constrain covariance matrix if badly conditioned
|
|
747
|
+
if np.linalg.cond(aaa) > 1e10:
|
|
748
|
+
e_d, e_v = np.linalg.eig(aaa)
|
|
749
|
+
edmax = np.max(e_d)
|
|
750
|
+
e_d[1e10 * e_d < edmax] = edmax / 1e10
|
|
751
|
+
aaa = np.dot(np.dot(e_v, (e_d * np.eye(no_datasets))),
|
|
752
|
+
np.linalg.inv(e_v))
|
|
753
|
+
mmm = (np.linalg.det(aaa) ** (1.0 / cent.shape[1]) *
|
|
754
|
+
np.linalg.pinv(aaa))
|
|
755
|
+
dtmp.append(np.sum(np.dot(dcent, mmm) * dcent, 1).T)
|
|
756
|
+
# d[j,:] = np.sum((dcent*M*dcent),2).T
|
|
757
|
+
ddd = np.sqrt(np.array(dtmp))
|
|
758
|
+
elif cltype == 'GG' or cltype == 'gg':
|
|
759
|
+
m_f = uuu ** expo
|
|
760
|
+
dtmp = []
|
|
761
|
+
for j in range(cent.shape[0]):
|
|
762
|
+
# difference between each sample attribute to the
|
|
763
|
+
# corresponding attribute of the j-th cluster
|
|
764
|
+
dcent = data - np.ones([data.shape[0], 1]) * cent[j]
|
|
765
|
+
aaa = np.dot(np.ones([cent.shape[1], 1]) * m_f[j] * dcent.T,
|
|
766
|
+
dcent / np.sum(m_f[j], 0)) # Covariance of the
|
|
767
|
+
# j-th cluster
|
|
768
|
+
ppp = 1.0 / data.shape[0] * np.sum(m_f[j])
|
|
769
|
+
aaa0 = np.eye(aaa.shape[0])
|
|
770
|
+
# if cov_constr>0, this enforces not to elongated ellipsoids --> avoid the
|
|
771
|
+
# needle-like cluster
|
|
772
|
+
aaa = (1.0 - cov_constr) * aaa + cov_constr * (aaa0 /
|
|
773
|
+
data.shape[0])
|
|
774
|
+
# constrain covariance matrix if badly conditioned
|
|
775
|
+
if np.linalg.cond(aaa) > 1e10:
|
|
776
|
+
e_d, e_v = np.linalg.eig(aaa)
|
|
777
|
+
edmax = np.max(e_d)
|
|
778
|
+
e_d[1e10 * e_d < edmax] = edmax / 1e10
|
|
779
|
+
aaa = np.dot(np.dot(e_v, (e_d * np.eye(no_datasets))),
|
|
780
|
+
np.linalg.inv(e_v))
|
|
781
|
+
dtmp.append(np.sum((np.linalg.det(aaa))**0.5 /
|
|
782
|
+
ppp*np.exp(np.dot(dcent,
|
|
783
|
+
np.linalg.pinv(aaa)) *
|
|
784
|
+
dcent*0.5), 1).T)
|
|
785
|
+
ddd = np.sqrt(np.array(dtmp))
|
|
786
|
+
ddd[ddd == 0] = 1e-10 # avoid, that a data point equals a cluster
|
|
787
|
+
# center
|
|
788
|
+
return ddd
|
|
789
|
+
|
|
790
|
+
def fuzzy_dist(self, cent, data, uuu, expo, cltype, cov_constr):
|
|
791
|
+
""" Fuzzy Dist """
|
|
792
|
+
# maxnumexp = np.log(np.finfo(np.float64).max)
|
|
793
|
+
no_samples = data.shape[0]
|
|
794
|
+
no_datasets = data.shape[1]
|
|
795
|
+
no_cent = cent.shape[0]
|
|
796
|
+
ddd = np.zeros([cent.shape[0], no_samples])
|
|
797
|
+
|
|
798
|
+
# FCM
|
|
799
|
+
if cltype == 'FCM' or cltype == 'fcm':
|
|
800
|
+
for j in range(no_cent):
|
|
801
|
+
ddd[j, :] = np.sqrt(np.sum(((data - np.ones([no_samples, 1]) *
|
|
802
|
+
cent[j])**2), 1))
|
|
803
|
+
# determinant criterion see Spath, Helmuth,
|
|
804
|
+
# "Cluster-Formation and Analyse", chapter 3
|
|
805
|
+
elif cltype == 'DET' or cltype == 'det':
|
|
806
|
+
m_f = uuu ** expo
|
|
807
|
+
for j in range(no_cent):
|
|
808
|
+
# difference between each sample attribute to the corresponding
|
|
809
|
+
# attribute of the j-th cluster
|
|
810
|
+
dcent = data - np.ones([no_samples, 1]) * cent[j]
|
|
811
|
+
aaa = np.dot(np.ones([no_datasets, 1]) * m_f[j] * dcent.T,
|
|
812
|
+
dcent / np.sum(m_f[j], 0)) # Covar of the j-th
|
|
813
|
+
# cluster
|
|
814
|
+
|
|
815
|
+
# constrain covariance matrix if badly conditioned
|
|
816
|
+
if np.linalg.cond(aaa) > 1e10:
|
|
817
|
+
e_d, e_v = np.linalg.eig(aaa)
|
|
818
|
+
edmax = np.max(e_d)
|
|
819
|
+
e_d[1e10 * e_d < edmax] = edmax / 1e10
|
|
820
|
+
aaa = np.dot(np.dot(e_v, (e_d * np.eye(no_datasets))),
|
|
821
|
+
np.linalg.inv(e_v))
|
|
822
|
+
if j == 0: # sum all covariance matrices for all clusters
|
|
823
|
+
aaa0 = aaa
|
|
824
|
+
else:
|
|
825
|
+
aaa0 = aaa0 + aaa
|
|
826
|
+
mmm = np.linalg.det(aaa0)**(1.0/no_datasets)*np.linalg.pinv(aaa0)
|
|
827
|
+
dtmp = []
|
|
828
|
+
# calc new distances using the same covariance matrix for all
|
|
829
|
+
# clusters --> ellisoidal clusters, all clusters use equal
|
|
830
|
+
# ellipsoids
|
|
831
|
+
for j in range(no_cent):
|
|
832
|
+
# difference between each sample attribute to the corresponding
|
|
833
|
+
# attribute of the j-th cluster
|
|
834
|
+
dcent = data - np.ones([no_samples, 1]) * cent[j]
|
|
835
|
+
dtmp.append(np.sum(np.dot(dcent, mmm) * dcent, 1).T)
|
|
836
|
+
ddd = np.sqrt(np.array(dtmp))
|
|
837
|
+
# GK
|
|
838
|
+
elif cltype == 'GK' or cltype == 'gk':
|
|
839
|
+
m_f = uuu ** expo
|
|
840
|
+
dtmp = []
|
|
841
|
+
for j in range(no_cent):
|
|
842
|
+
# difference between each sample attribute to the corresponding
|
|
843
|
+
# attribute of the j-th cluster
|
|
844
|
+
dcent = data - np.ones([no_samples, 1]) * cent[j]
|
|
845
|
+
# Covariance of the j-th cluster
|
|
846
|
+
aaa = np.dot(np.ones([no_datasets, 1]) * m_f[j] * dcent.T,
|
|
847
|
+
dcent / np.sum(m_f[j], 0))
|
|
848
|
+
aaa0 = np.eye(no_datasets)
|
|
849
|
+
# if cov_constr>0, this enforces not to elongated ellipsoids -->
|
|
850
|
+
# avoid the needle-like cluster
|
|
851
|
+
aaa = (1.0-cov_constr)*aaa + cov_constr*(aaa0/no_samples)
|
|
852
|
+
# constrain covariance matrix if badly conditioned
|
|
853
|
+
if np.linalg.cond(aaa) > 1e10:
|
|
854
|
+
e_d, e_v = np.linalg.eig(aaa)
|
|
855
|
+
edmax = np.max(e_d)
|
|
856
|
+
e_d[1e10 * e_d < edmax] = edmax / 1e10
|
|
857
|
+
aaa = np.dot(np.dot(e_v, (e_d * np.eye(no_datasets))),
|
|
858
|
+
np.linalg.inv(e_v))
|
|
859
|
+
# GK Code
|
|
860
|
+
mmm = np.linalg.det(aaa)**(1.0/no_datasets)*np.linalg.pinv(aaa)
|
|
861
|
+
dtmp.append(np.sum(np.dot(dcent, mmm) * dcent, 1).T)
|
|
862
|
+
# d[j,:] = np.sum((dcent*M*dcent),2).T
|
|
863
|
+
ddd = np.sqrt(np.array(dtmp))
|
|
864
|
+
# GG
|
|
865
|
+
elif cltype == 'GG' or cltype == 'gg':
|
|
866
|
+
m_f = uuu ** expo
|
|
867
|
+
dtmp = []
|
|
868
|
+
for j in range(no_cent):
|
|
869
|
+
# difference between each sample attribute to the corresponding
|
|
870
|
+
# attribute of the j-th cluster
|
|
871
|
+
dcent = data - cent[j]
|
|
872
|
+
# Covariance of the j-th cluster
|
|
873
|
+
aaa = np.dot(m_f[j] * dcent.T, dcent / np.sum(m_f[j], 0))
|
|
874
|
+
aaa0 = np.eye(no_datasets)
|
|
875
|
+
# if cov_constr>0, this enforces not to elongated ellipsoids -->
|
|
876
|
+
# avoid the needle-like cluster
|
|
877
|
+
aaa = (1.0-cov_constr)*aaa + cov_constr*(aaa0/no_samples)
|
|
878
|
+
|
|
879
|
+
# constrain covariance matrix if badly conditioned
|
|
880
|
+
if np.linalg.cond(aaa) > 1e10:
|
|
881
|
+
e_d, e_v = np.linalg.eig(aaa)
|
|
882
|
+
edmax = np.max(e_d)
|
|
883
|
+
e_d[1e10 * e_d < edmax] = edmax / 1e10
|
|
884
|
+
aaa = np.dot(np.dot(e_v, (e_d * np.eye(no_datasets))),
|
|
885
|
+
np.linalg.inv(e_v))
|
|
886
|
+
# GG code
|
|
887
|
+
ppp = 1.0 / no_samples * np.sum(m_f[j])
|
|
888
|
+
|
|
889
|
+
t_1 = np.linalg.det(aaa)**0.5/ppp
|
|
890
|
+
t_4 = np.linalg.pinv(aaa)
|
|
891
|
+
t_5 = np.dot(dcent, t_4) * dcent * 0.5
|
|
892
|
+
# t_6[t_6 > maxnumexp] = maxnumexp
|
|
893
|
+
t_7 = np.exp(t_5)
|
|
894
|
+
t_9 = t_1 * t_7
|
|
895
|
+
t_10 = np.sum(t_9, 1).T
|
|
896
|
+
dtmp.append(t_10)
|
|
897
|
+
# dtmp.append(np.sum((np.linalg.det(aaa)) ** 0.5 / ppp *
|
|
898
|
+
# np.exp(np.dot(dcent, np.linalg.pinv(aaa)) *
|
|
899
|
+
# dcent * 0.5), 1).T)
|
|
900
|
+
ddd = np.sqrt(np.array(dtmp))
|
|
901
|
+
ddd[ddd == 0] = 1e-10 # avoid, that a data point equals a cluster
|
|
902
|
+
# center
|
|
903
|
+
if (ddd == np.inf).max() == True:
|
|
904
|
+
ddd[ddd == np.inf] = np.random.normal() * 1e-10 # solve break
|
|
905
|
+
|
|
906
|
+
return ddd
|