source: orange/orange/OrangeWidgets/OWNxHist.py @ 9421:bbfeb42cfe96

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