source: orange/orange/OrangeWidgets/OWHist.py @ 8042:ffcb93bc9028

Revision 8042:ffcb93bc9028, 8.2 KB checked in by markotoplak, 3 years ago (diff)

Hierarchical clustering: also catch RuntimeError when importing matplotlib (or the documentation could not be built on server).

Line 
1#
2# OWHist.py
3#
4# the base for all histograms
5
6import OWGUI
7from OWWidget import *
8from OWGraph import *
9
10import numpy, math
11
12class OWHist(OWGraph):
13    def __init__(self, parent=None, type=0):
14        OWGraph.__init__(self, parent, "Histogram")
15        self.parent = parent
16        self.type = type
17       
18        self.enableXaxis(1)
19        self.enableYLaxis(1)
20       
21        self.xData = []
22        self.yData = []
23       
24        self.minValue = 0
25        self.maxValue = 0
26        self.lowerBoundary = 0
27        self.upperBoundary = 0
28        self.lowerBoundaryKey = None
29        self.upperBoundaryKey = None
30       
31        self.enableGridXB(False)
32        self.enableGridYL(False)
33
34        self.buttonCurrentlyPressed = None
35        self.updatingState = False, None
36
37    def setValues(self, values):
38        nBins = 100
39        if len(values) < 100:
40            nBins = len(values)
41
42        self.yData, self.xData = numpy.histogram(values, bins=100)
43        #if numpy version greater than 1.3
44        if len(self.xData) == len(self.yData) + 1:
45            self.xData = [(self.xData[i] + self.xData[i+1]) / 2. for i in range(len(self.xData) - 1)]
46       
47        self.minx = min(self.xData) 
48        self.maxx = max(self.xData)
49        self.miny = min(self.yData)
50        self.maxy = max(self.yData)
51       
52        self.minValue = min(values)
53        self.maxValue = max(values)
54       
55        self.updateData()
56        self.replot()
57       
58    def setBoundary(self, lower, upper):
59        if len(self.xData) == 0 and len(self.yData) == 0:
60            return
61       
62        self.lowerBoundary = lower
63        self.upperBoundary = upper
64        maxy = max(self.yData)
65       
66        self.lowerBoundaryKey.setData([float(self.lowerBoundary), float(self.lowerBoundary)], [0., float(maxy)])
67        self.upperBoundaryKey.setData([float(self.upperBoundary), float(self.upperBoundary)], [0., float(maxy)])
68#        self.updateData()
69        self.replot()
70           
71    def updateData(self):
72        self.removeDrawingCurves(removeLegendItems = 0, removeMarkers=1)
73                   
74        self.key = self.addCurve("histogramCurve", Qt.blue, Qt.blue, 6, symbol = QwtSymbol.NoSymbol, style = QwtPlotCurve.Steps, xData = self.xData, yData = self.yData)
75       
76        maxy = self.maxy
77        self.lowerBoundaryKey = self.addCurve("lowerBoundaryCurve", Qt.red, Qt.red, 6, symbol = QwtSymbol.NoSymbol, style = QwtPlotCurve.Lines, xData = [float(self.lowerBoundary), float(self.lowerBoundary)], yData = [0., float(maxy)])
78        self.upperBoundaryKey = self.addCurve("upperBoundaryCurve", Qt.red, Qt.red, 6, symbol = QwtSymbol.NoSymbol, style = QwtPlotCurve.Lines, xData = [float(self.upperBoundary), float(self.upperBoundary)], yData = [0., float(maxy)])
79
80        minx = self.minx
81        maxx = self.maxx
82        miny = self.miny
83
84        self.setAxisScale(QwtPlot.xBottom, minx - (0.05 * (maxx - minx)), maxx + (0.05 * (maxx - minx)))
85        self.setAxisScale(QwtPlot.yLeft, miny - (0.05 * (maxy - miny)), maxy + (0.05 * (maxy - miny)))
86
87class OWInteractiveHist(OWHist):
88    shadeTypes = ["lowTail", "hiTail", "twoTail", "middle"]
89    def updateData(self):
90        OWHist.updateData(self)
91        self.upperTailShadeKey = self.addCurve("upperTailShade", Qt.blue, Qt.blue, 6, symbol = QwtSymbol.NoSymbol, style = QwtPlotCurve.Steps)
92        self.lowerTailShadeKey = self.addCurve("lowerTailShade", Qt.blue, Qt.blue, 6, symbol = QwtSymbol.NoSymbol, style = QwtPlotCurve.Steps)
93        self.middleShadeKey = self.addCurve("middleShade", Qt.blue, Qt.blue, 6, symbol = QwtSymbol.NoSymbol, style = QwtPlotCurve.Steps)
94
95        self.upperTailShadeKey.setBrush(QBrush(Qt.blue))
96        self.lowerTailShadeKey.setBrush(QBrush(Qt.blue))
97        self.middleShadeKey.setBrush(QBrush(Qt.blue))
98##        self.setCurveBrush(self.upperTailShadeKey, QBrush(Qt.red))
99##        self.setCurveBrush(self.lowerTailShadeKey, QBrush(Qt.red))
100##        self.setCurveBrush(self.middleShadeKey, QBrush(Qt.red))
101
102    def shadeTails(self):
103        if len(self.xData) == 0 and len(self.yData) == 0:
104            return
105       
106        if self.type in ["hiTail", "twoTail"]:
107            index = max(min(int(math.ceil(100*(self.upperBoundary-self.minx)/(self.maxx-self.minx))), 100), 0)
108            x = [self.upperBoundary] + list(self.xData[index:])
109            y = [self.yData[min(index, 99)]] + list(self.yData[index:])
110            x = [float(a) for a  in x]
111            y = [float(a) for a  in y]
112            self.upperTailShadeKey.setData(x, y)
113        if self.type in ["lowTail", "twoTail"]:
114            index = max(min(int(math.ceil(100*(self.lowerBoundary-self.minx)/(self.maxx-self.minx))),100), 0)
115            x = list(self.xData[:index]) + [self.lowerBoundary]
116            y = list(self.yData[:index]) + [self.yData[min(index,99)]]
117            x = [float(a) for a  in x]
118            y = [float(a) for a  in y]
119            self.lowerTailShadeKey.setData(x, y)
120        if self.type in ["middle"]:
121            indexLow = max(min(int(100*(self.lowerBoundary-self.minx)/(self.maxx-self.minx)),99), 0)
122            indexHi = max(min(int(100*(self.upperBoundary-self.minx)/(self.maxx-self.minx)), 100)-1, 0)
123            x = [self.lowerBoundary] + list(self.xData[indexLow: indexHi]) +[self.upperBoundary]
124            y = [self.yData[max(index,0)]] + list(self.yData[indexLow: indexHi]) +[self.yData[max(indexHi, 99)]]
125            x = [float(a) for a  in x]
126            y = [float(a) for a  in y]
127            self.middleShadeKey.setData(x, y)
128        if self.type in ["hiTail", "middle"]:
129            self.lowerTailShadeKey.setData([], [])
130        if self.type in ["lowTail", "middle"]:
131            self.upperTailShadeKey.setData([], [])
132        if self.type in ["lowTail", "hiTail", "twoTail"]:
133            self.middleShadeKey.setData([], [])
134       
135    def setBoundary(self, low, hi):
136        OWHist.setBoundary(self, low, hi)
137        self.shadeTails()
138#        self.updateData()
139        self.replot()
140   
141    def _setBoundary(self, boundary, cut):
142        if self.type in ["twoTail", "middle"]:
143            if boundary == "lower":
144                low, hi = cut, self.upperBoundary
145            else:
146                low, hi = self.lowerBoundary, cut
147            if low > hi:
148                low, hi = hi, low
149            self.setBoundary(low, hi)
150        else:
151            self.setBoundary(cut, cut)
152       
153    def mousePressEvent(self, e):
154        if self.state == SELECT and self.getBoundaryAt(e.pos()) and e.button() == Qt.LeftButton:
155            boundary = self.getBoundaryAt(e.pos())
156            cut = self.invTransform(QwtPlot.xBottom, self.canvas().mapFrom(self, e.pos()).x())
157##            self.mouseCurrentlyPressed = 1
158##            self.buttonCurrentlyPressed = e.button()
159            self.updatingState = True, boundary
160            self._setBoundary(boundary, cut)
161        else:
162            return OWHist.mousePressEvent(self, e)
163       
164    def mouseMoveEvent(self, e):
165        if self.state == SELECT:
166            updating, boundary = self.updatingState
167            if updating:
168                cut = self.invTransform(QwtPlot.xBottom, self.canvas().mapFrom(self, e.pos()).x())
169                self._setBoundary(boundary, cut)
170            else:
171                if self.getBoundaryAt(e.pos()):
172                    self.canvas().setCursor(Qt.SizeHorCursor)
173                else:
174                    self.canvas().setCursor(self._cursor)
175        else:
176            return OWHist.mouseMoveEvent(self ,e)       
177
178    def mouseReleaseEvent(self, e):
179        updating, boundary = self.updatingState
180        if self.state == SELECT and updating:
181            cut = self.invTransform(QwtPlot.xBottom, self.canvas().mapFrom(self, e.pos()).x())
182            self._setBoundary(boundary, cut)
183            self.updatingState = False, None
184        else:
185            return OWHist.mouseReleaseEvent(self, e)
186
187    def getBoundaryAt(self, pos):
188        x = self.canvas().mapFrom(self, pos).x()
189        def check (boundary):
190            return abs(self.transform(QwtPlot.xBottom, boundary) - x) <= 3
191        if self.type in ["hiTail", "twoTail", "middleTail"] and check(self.upperBoundary):
192            return "upper"
193        elif self.type in ["lowTail", "twoTail", "middleTail"] and check(self.lowerBoundary):
194            return "lower"
195        else:
196            return None
197           
Note: See TracBrowser for help on using the repository browser.