source: orange/Orange/OrangeWidgets/OWNxHist.py @ 10860:44fb1a39ded6

Revision 10860:44fb1a39ded6, 12.6 KB checked in by mstajdohar, 2 years ago (diff)

Fixed some errors.

Line 
1#
2# OWHist.py
3#
4# the base for network histograms
5
6import math
7import numpy
8
9import Orange
10import OWGUI
11
12from OWWidget import *
13from OWGraph import *
14from OWHist import *
15
16class OWNxHist():
17
18    def __init__(self, parent=None, type=0):
19        self.parent = parent
20
21    def addHistogramControls(self, parent=None):
22        # set default settings
23        self.spinLowerThreshold = 0
24        self.spinLowerChecked = False
25        self.spinUpperThreshold = 0
26        self.spinUpperChecked = False
27        self.netOption = 0
28        self.dstWeight = 0
29        self.kNN = 0
30        self.andor = 0
31        self.matrix = None
32        self.excludeLimit = 2
33        self.percentil = 0
34
35        self.graph = None
36        self.graph_matrix = None
37
38        if parent is None:
39            parent = self.controlArea
40
41        boxGeneral = OWGUI.widgetBox(parent, box="Distance boundaries")
42
43        ribg = OWGUI.widgetBox(boxGeneral, None, orientation="horizontal", addSpace=False)
44        OWGUI.lineEdit(ribg, self, "spinLowerThreshold", "Lower", orientation='horizontal', callback=self.changeLowerSpin, valueType=float, enterPlaceholder=True, controlWidth=100)
45        OWGUI.lineEdit(ribg, self, "spinUpperThreshold", "Upper    ", orientation='horizontal', callback=self.changeUpperSpin, valueType=float, enterPlaceholder=True, controlWidth=100)
46        ribg.layout().addStretch(1)
47        #ribg = OWGUI.radioButtonsInBox(boxGeneral, self, "andor", [], orientation='horizontal', callback = self.generateGraph)
48        #OWGUI.appendRadioButton(ribg, self, "andor", "OR", callback = self.generateGraph)
49        #b = OWGUI.appendRadioButton(ribg, self, "andor", "AND", callback = self.generateGraph)
50        #b.setEnabled(False)
51        #ribg.hide(False)
52
53        ribg = OWGUI.widgetBox(boxGeneral, None, orientation="horizontal", addSpace=False)
54        OWGUI.spin(ribg, self, "kNN", 0, 1000, 1, label="kNN   ", orientation='horizontal', callback=self.generateGraph, callbackOnReturn=1, controlWidth=100)
55        OWGUI.doubleSpin(ribg, self, "percentil", 0, 100, 0.1, label="Percentile", orientation='horizontal', callback=self.setPercentil, callbackOnReturn=1, controlWidth=100)
56        ribg.layout().addStretch(1)
57        # Options
58        self.attrColor = ""
59        ribg = OWGUI.radioButtonsInBox(parent, self, "netOption", [], "Options", callback=self.generateGraph)
60        OWGUI.appendRadioButton(ribg, self, "netOption", "All vertices", callback=self.generateGraph)
61        hb = OWGUI.widgetBox(ribg, None, orientation="horizontal", addSpace=False)
62        OWGUI.appendRadioButton(ribg, self, "netOption", "Large components only. Min nodes:", insertInto=hb, callback=self.generateGraph)
63        OWGUI.spin(hb, self, "excludeLimit", 2, 100, 1, callback=(lambda h=True: self.generateGraph(h)))
64        OWGUI.appendRadioButton(ribg, self, "netOption", "Largest connected component only", callback=self.generateGraph)
65        OWGUI.appendRadioButton(ribg, self, "netOption", "Connected component with vertex")
66        self.attribute = None
67        self.attributeCombo = OWGUI.comboBox(parent, self, "attribute", box="Filter attribute", orientation='horizontal')#, callback=self.setVertexColor)
68
69        ribg = OWGUI.radioButtonsInBox(parent, self, "dstWeight", [], "Distance -> Weight", callback=self.generateGraph)
70        hb = OWGUI.widgetBox(ribg, None, orientation="horizontal", addSpace=False)
71        OWGUI.appendRadioButton(ribg, self, "dstWeight", "Weight := distance", insertInto=hb, callback=self.generateGraph)
72        OWGUI.appendRadioButton(ribg, self, "dstWeight", "Weight := 1 - distance", insertInto=hb, callback=self.generateGraph)
73
74        self.label = ''
75        self.searchString = OWGUI.lineEdit(self.attributeCombo.box, self, "label", callback=self.setSearchStringTimer, callbackOnType=True)
76        self.searchStringTimer = QTimer(self)
77        self.connect(self.searchStringTimer, SIGNAL("timeout()"), self.generateGraph)
78
79        if str(self.netOption) != '3':
80            self.attributeCombo.box.setEnabled(False)
81
82    def setPercentil(self):
83        if self.matrix is None or self.percentil <= 0:
84            return
85
86        self.spinLowerThreshold = self.histogram.minValue
87        # flatten matrix, sort values and remove identities (self.matrix[i][i])
88        vals = sorted(sum(self.matrix, ()))[self.matrix.dim:]
89        ind = int(len(vals) * self.percentil / 100)
90        self.spinUpperThreshold = vals[ind]
91        self.generateGraph()
92
93    def enableAttributeSelection(self):
94        self.attributeCombo.box.setEnabled(True)
95
96    def setSearchStringTimer(self):
97        self.searchStringTimer.stop()
98        self.searchStringTimer.start(750)
99
100    def setMatrix(self, data):
101        if data == None: return
102
103        if not hasattr(data, "items") or data.items is None:
104            setattr(data, "items", [i for i in range(data.dim)])
105
106        self.matrix = data
107        # draw histogram
108        data.matrixType = orange.SymMatrix.Symmetric
109        values = data.getValues()
110        #print "values:",values
111        self.histogram.setValues(values)
112
113        low = min(values)
114        upp = max(values)
115        self.spinLowerThreshold = self.spinUpperThreshold = math.floor(low - (0.03 * (upp - low)))
116
117        self.attributeCombo.clear()
118        vars = []
119        if (self.matrix != None):
120            if hasattr(self.matrix, "items"):
121
122                if isinstance(self.matrix.items, orange.ExampleTable):
123                    vars = list(self.matrix.items.domain.variables)
124
125                    metas = self.matrix.items.domain.getmetas(0)
126                    for i, var in metas.iteritems():
127                        vars.append(var)
128
129        self.icons = self.createAttributeIconDict()
130
131        for var in vars:
132            try:
133                if var.varType != 7: # if not Orange.feature.Python
134                    self.attributeCombo.addItem(self.icons[var.varType], unicode(var.name))
135            except:
136                print "Error adding", var, "to the attribute combo."
137
138        self.setPercentil()
139        self.generateGraph()
140
141    def changeLowerSpin(self):
142        self.percentil = 0
143
144        if self.spinLowerThreshold < self.histogram.minValue:
145            self.spinLowerThreshold = self.histogram.minValue
146        elif self.spinLowerThreshold > self.histogram.maxValue:
147            self.spinLowerThreshold = self.histogram.maxValue
148
149        if self.spinLowerThreshold >= self.spinUpperThreshold:
150            self.spinUpperThreshold = self.spinLowerThreshold
151
152        self.generateGraph()
153
154    def changeUpperSpin(self):
155        self.percentil = 0
156
157        if self.spinUpperThreshold < self.histogram.minValue:
158            self.spinUpperThreshold = self.histogram.minValue
159        elif self.spinUpperThreshold > self.histogram.maxValue:
160            self.spinUpperThreshold = self.histogram.maxValue
161
162        if self.spinUpperThreshold <= self.spinLowerThreshold:
163            self.spinLowerThreshold = self.spinUpperThreshold
164
165        self.generateGraph()
166
167    def generateGraph(self, N_changed=False):
168        self.searchStringTimer.stop()
169        self.attributeCombo.box.setEnabled(False)
170        self.error()
171        matrix = None
172        self.warning('')
173
174        if N_changed:
175            self.netOption = 1
176
177        if self.matrix == None:
178            self.infoa.setText("No data loaded.")
179            self.infob.setText("")
180            return
181
182        #print len(self.histogram.yData), len(self.histogram.xData)
183        nEdgesEstimate = 2 * sum([self.histogram.yData[i] for i, e in enumerate(self.histogram.xData) if self.spinLowerThreshold <= e <= self.spinUpperThreshold])
184
185        if nEdgesEstimate > 200000:
186            self.graph = None
187            nedges = 0
188            n = 0
189            self.error('Estimated number of edges is too high (%d).' % nEdgesEstimate)
190        else:
191            graph = Orange.network.Graph()
192            graph.add_nodes_from(range(self.matrix.dim))
193            matrix = self.matrix
194
195            if hasattr(self.matrix, "items") and self.matrix.items is not None:
196                if type(self.matrix.items) == Orange.data.Table:
197                    graph.set_items(self.matrix.items)
198                else:
199                    data = [[str(x)] for x in self.matrix.items]
200                    items = Orange.data.Table(Orange.data.Domain(Orange.feature.String('label'), 0), data)
201                    graph.set_items(items)
202
203            # set the threshold
204            # set edges where distance is lower than threshold
205            self.warning(0)
206            if self.kNN >= self.matrix.dim:
207                self.warning(0, "kNN larger then supplied distance matrix dimension. Using k = %i" % (self.matrix.dim - 1))
208            #nedges = graph.fromDistanceMatrix(self.matrix, self.spinLowerThreshold, self.spinUpperThreshold, min(self.kNN, self.matrix.dim - 1), self.andor)
209            edge_list = Orange.network.GraphLayout().edges_from_distance_matrix(self.matrix, self.spinLowerThreshold, self.spinUpperThreshold, min(self.kNN, self.matrix.dim - 1))
210            if self.dstWeight == 1:
211                graph.add_edges_from(((u, v, {'weight':1 - d}) for u, v, d in edge_list))
212            else:
213                graph.add_edges_from(((u, v, {'weight':d}) for u, v, d in edge_list))
214
215            # exclude unconnected
216            if str(self.netOption) == '1':
217                components = [x for x in Orange.network.nx.algorithms.components.connected_components(graph) if len(x) >= self.excludeLimit]
218                if len(components) > 0:
219                    include = reduce(lambda x, y: x + y, components)
220                    if len(include) > 1:
221                        self.graph = graph.subgraph(include)
222                        matrix = self.matrix.getitems(include)
223                    else:
224                        self.graph = None
225                        matrix = None
226                else:
227                    self.graph = None
228                    matrix = None
229            # largest connected component only
230            elif str(self.netOption) == '2':
231                component = Orange.network.nx.algorithms.components.connected_components(graph)[0]
232                if len(component) > 1:
233                    self.graph = graph.subgraph(component)
234                    matrix = self.matrix.getitems(component)
235                else:
236                    self.graph = None
237                    matrix = None
238            # connected component with vertex by label
239            elif str(self.netOption) == '3':
240                self.attributeCombo.box.setEnabled(True)
241                self.graph = None
242                matrix = None
243                #print self.attributeCombo.currentText()
244                if self.attributeCombo.currentText() != '' and self.label != '':
245                    components = Orange.network.nx.algorithms.components.connected_components(graph)
246
247                    txt = self.label.lower()
248                    #print 'txt:',txt
249                    nodes = [i for i, values in enumerate(self.matrix.items) if txt in str(values[str(self.attributeCombo.currentText())]).lower()]
250                    #print "nodes:",nodes
251                    if len(nodes) > 0:
252                        vertices = []
253                        for component in components:
254                            for node in nodes:
255                                if node in component:
256                                    if len(component) > 0:
257                                        vertices.extend(component)
258
259                        if len(vertices) > 0:
260                            #print "n vertices:", len(vertices), "n set vertices:", len(set(vertices))
261                            vertices = list(set(vertices))
262                            self.graph = graph.subgraph(include)
263                            matrix = self.matrix.getitems(vertices)
264            else:
265                self.graph = graph
266
267        if matrix != None:
268            matrix.items = self.graph.items()
269        self.graph_matrix = matrix
270
271        if self.graph is None:
272            self.pconnected = 0
273            self.nedges = 0
274        else:
275            self.pconnected = self.graph.number_of_nodes()
276            self.nedges = self.graph.number_of_edges()
277        if hasattr(self, "infoa"):
278            self.infoa.setText("Matrix size: %d" % self.matrix.dim)
279        if hasattr(self, "infob"):
280            self.infob.setText("Graph nodes: %d (%3.1f%%)" % (self.pconnected,
281                self.pconnected / float(self.matrix.dim) * 100))
282        if hasattr(self, "infoc"):
283            self.infoc.setText("Graph edges: %d (%.2f edges/node)" % (
284                self.nedges, self.nedges / float(self.pconnected)
285                if self.pconnected else 0))
286
287        #print 'self.graph:',self.graph+
288        if hasattr(self, "sendSignals"):
289            self.sendSignals()
290
291        self.histogram.setBoundary(self.spinLowerThreshold, self.spinUpperThreshold)
292
Note: See TracBrowser for help on using the repository browser.