merge with inp
This commit is contained in:
commit
008ca76d53
@ -39,19 +39,19 @@ class AxisItem(GraphicsWidget):
|
|||||||
if orientation not in ['left', 'right', 'top', 'bottom']:
|
if orientation not in ['left', 'right', 'top', 'bottom']:
|
||||||
raise Exception("Orientation argument must be one of 'left', 'right', 'top', or 'bottom'.")
|
raise Exception("Orientation argument must be one of 'left', 'right', 'top', or 'bottom'.")
|
||||||
if orientation in ['left', 'right']:
|
if orientation in ['left', 'right']:
|
||||||
#self.setMinimumWidth(25)
|
|
||||||
#self.setSizePolicy(QtGui.QSizePolicy(
|
|
||||||
#QtGui.QSizePolicy.Minimum,
|
|
||||||
#QtGui.QSizePolicy.Expanding
|
|
||||||
#))
|
|
||||||
self.label.rotate(-90)
|
self.label.rotate(-90)
|
||||||
#else:
|
|
||||||
#self.setMinimumHeight(50)
|
self.style = {
|
||||||
#self.setSizePolicy(QtGui.QSizePolicy(
|
'tickTextOffset': 3, ## spacing between text and axis
|
||||||
#QtGui.QSizePolicy.Expanding,
|
'tickTextWidth': 30, ## space reserved for tick text
|
||||||
#QtGui.QSizePolicy.Minimum
|
'tickTextHeight': 18,
|
||||||
#))
|
'autoExpandTextSpace': True, ## automatically expand text space if needed
|
||||||
#self.drawLabel = False
|
'tickFont': None,
|
||||||
|
'stopAxisAtTick': (False, False), ## whether axis is drawn to edge of box or to last tick
|
||||||
|
}
|
||||||
|
|
||||||
|
self.textWidth = 30 ## Keeps track of maximum width / height of tick text
|
||||||
|
self.textHeight = 18
|
||||||
|
|
||||||
self.labelText = ''
|
self.labelText = ''
|
||||||
self.labelUnits = ''
|
self.labelUnits = ''
|
||||||
@ -60,7 +60,6 @@ class AxisItem(GraphicsWidget):
|
|||||||
self.logMode = False
|
self.logMode = False
|
||||||
self.tickFont = None
|
self.tickFont = None
|
||||||
|
|
||||||
self.textHeight = 18
|
|
||||||
self.tickLength = maxTickLength
|
self.tickLength = maxTickLength
|
||||||
self._tickLevels = None ## used to override the automatic ticking system with explicit ticks
|
self._tickLevels = None ## used to override the automatic ticking system with explicit ticks
|
||||||
self.scale = 1.0
|
self.scale = 1.0
|
||||||
@ -184,7 +183,7 @@ class AxisItem(GraphicsWidget):
|
|||||||
if len(args) > 0:
|
if len(args) > 0:
|
||||||
self.labelStyle = args
|
self.labelStyle = args
|
||||||
self.label.setHtml(self.labelString())
|
self.label.setHtml(self.labelString())
|
||||||
self.resizeEvent()
|
self._adjustSize()
|
||||||
self.picture = None
|
self.picture = None
|
||||||
self.update()
|
self.update()
|
||||||
|
|
||||||
@ -204,13 +203,42 @@ class AxisItem(GraphicsWidget):
|
|||||||
|
|
||||||
return asUnicode("<span style='%s'>%s</span>") % (style, s)
|
return asUnicode("<span style='%s'>%s</span>") % (style, s)
|
||||||
|
|
||||||
|
def _updateMaxTextSize(self, x):
|
||||||
|
## Informs that the maximum tick size orthogonal to the axis has
|
||||||
|
## changed; we use this to decide whether the item needs to be resized
|
||||||
|
## to accomodate.
|
||||||
|
if self.orientation in ['left', 'right']:
|
||||||
|
mx = max(self.textWidth, x)
|
||||||
|
if mx > self.textWidth:
|
||||||
|
self.textWidth = mx
|
||||||
|
if self.style['autoExpandTextSpace'] is True:
|
||||||
|
self.setWidth()
|
||||||
|
#return True ## size has changed
|
||||||
|
else:
|
||||||
|
mx = max(self.textHeight, x)
|
||||||
|
if mx > self.textHeight:
|
||||||
|
self.textHeight = mx
|
||||||
|
if self.style['autoExpandTextSpace'] is True:
|
||||||
|
self.setHeight()
|
||||||
|
#return True ## size has changed
|
||||||
|
|
||||||
|
def _adjustSize(self):
|
||||||
|
if self.orientation in ['left', 'right']:
|
||||||
|
self.setWidth()
|
||||||
|
else:
|
||||||
|
self.setHeight()
|
||||||
|
|
||||||
def setHeight(self, h=None):
|
def setHeight(self, h=None):
|
||||||
"""Set the height of this axis reserved for ticks and tick labels.
|
"""Set the height of this axis reserved for ticks and tick labels.
|
||||||
The height of the axis label is automatically added."""
|
The height of the axis label is automatically added."""
|
||||||
if h is None:
|
if h is None:
|
||||||
h = self.textHeight + max(0, self.tickLength)
|
if self.style['autoExpandTextSpace'] is True:
|
||||||
|
h = self.textHeight
|
||||||
|
else:
|
||||||
|
h = self.style['tickTextHeight']
|
||||||
|
h += max(0, self.tickLength) + self.style['tickTextOffset']
|
||||||
if self.label.isVisible():
|
if self.label.isVisible():
|
||||||
h += self.textHeight
|
h += self.label.boundingRect().height() * 0.8
|
||||||
self.setMaximumHeight(h)
|
self.setMaximumHeight(h)
|
||||||
self.setMinimumHeight(h)
|
self.setMinimumHeight(h)
|
||||||
self.picture = None
|
self.picture = None
|
||||||
@ -220,11 +248,16 @@ class AxisItem(GraphicsWidget):
|
|||||||
"""Set the width of this axis reserved for ticks and tick labels.
|
"""Set the width of this axis reserved for ticks and tick labels.
|
||||||
The width of the axis label is automatically added."""
|
The width of the axis label is automatically added."""
|
||||||
if w is None:
|
if w is None:
|
||||||
w = max(0, self.tickLength) + 40
|
if self.style['autoExpandTextSpace'] is True:
|
||||||
|
w = self.textWidth
|
||||||
|
else:
|
||||||
|
w = self.style['tickTextWidth']
|
||||||
|
w += max(0, self.tickLength) + self.style['tickTextOffset']
|
||||||
if self.label.isVisible():
|
if self.label.isVisible():
|
||||||
w += self.textHeight
|
w += self.label.boundingRect().height() * 0.8 ## bounding rect is usually an overestimate
|
||||||
self.setMaximumWidth(w)
|
self.setMaximumWidth(w)
|
||||||
self.setMinimumWidth(w)
|
self.setMinimumWidth(w)
|
||||||
|
self.picture = None
|
||||||
|
|
||||||
def pen(self):
|
def pen(self):
|
||||||
if self._pen is None:
|
if self._pen is None:
|
||||||
@ -346,12 +379,15 @@ class AxisItem(GraphicsWidget):
|
|||||||
|
|
||||||
def paint(self, p, opt, widget):
|
def paint(self, p, opt, widget):
|
||||||
if self.picture is None:
|
if self.picture is None:
|
||||||
self.picture = QtGui.QPicture()
|
|
||||||
painter = QtGui.QPainter(self.picture)
|
|
||||||
try:
|
try:
|
||||||
self.drawPicture(painter)
|
picture = QtGui.QPicture()
|
||||||
|
painter = QtGui.QPainter(picture)
|
||||||
|
specs = self.generateDrawSpecs(painter)
|
||||||
|
if specs is not None:
|
||||||
|
self.drawPicture(painter, *specs)
|
||||||
finally:
|
finally:
|
||||||
painter.end()
|
painter.end()
|
||||||
|
self.picture = picture
|
||||||
#p.setRenderHint(p.Antialiasing, False) ## Sometimes we get a segfault here ???
|
#p.setRenderHint(p.Antialiasing, False) ## Sometimes we get a segfault here ???
|
||||||
#p.setRenderHint(p.TextAntialiasing, True)
|
#p.setRenderHint(p.TextAntialiasing, True)
|
||||||
self.picture.play(p)
|
self.picture.play(p)
|
||||||
@ -540,12 +576,13 @@ class AxisItem(GraphicsWidget):
|
|||||||
def logTickStrings(self, values, scale, spacing):
|
def logTickStrings(self, values, scale, spacing):
|
||||||
return ["%0.1g"%x for x in 10 ** np.array(values).astype(float)]
|
return ["%0.1g"%x for x in 10 ** np.array(values).astype(float)]
|
||||||
|
|
||||||
def drawPicture(self, p):
|
def generateDrawSpecs(self, p):
|
||||||
|
"""
|
||||||
p.setRenderHint(p.Antialiasing, False)
|
Calls tickValues() and tickStrings to determine where and how ticks should
|
||||||
p.setRenderHint(p.TextAntialiasing, True)
|
be drawn, then generates from this a set of drawing commands to be
|
||||||
|
interpreted by drawPicture().
|
||||||
prof = debug.Profiler("AxisItem.paint", disabled=True)
|
"""
|
||||||
|
prof = debug.Profiler("AxisItem.generateDrawSpecs", disabled=True)
|
||||||
|
|
||||||
#bounds = self.boundingRect()
|
#bounds = self.boundingRect()
|
||||||
bounds = self.mapRectFromParent(self.geometry())
|
bounds = self.mapRectFromParent(self.geometry())
|
||||||
@ -582,11 +619,6 @@ class AxisItem(GraphicsWidget):
|
|||||||
axis = 1
|
axis = 1
|
||||||
#print tickStart, tickStop, span
|
#print tickStart, tickStop, span
|
||||||
|
|
||||||
## draw long line along axis
|
|
||||||
p.setPen(self.pen())
|
|
||||||
p.drawLine(*span)
|
|
||||||
p.translate(0.5,0) ## resolves some damn pixel ambiguity
|
|
||||||
|
|
||||||
## determine size of this item in pixels
|
## determine size of this item in pixels
|
||||||
points = list(map(self.mapToDevice, span))
|
points = list(map(self.mapToDevice, span))
|
||||||
if None in points:
|
if None in points:
|
||||||
@ -615,6 +647,10 @@ class AxisItem(GraphicsWidget):
|
|||||||
|
|
||||||
## determine mapping between tick values and local coordinates
|
## determine mapping between tick values and local coordinates
|
||||||
dif = self.range[1] - self.range[0]
|
dif = self.range[1] - self.range[0]
|
||||||
|
if dif == 0:
|
||||||
|
xscale = 1
|
||||||
|
offset = 0
|
||||||
|
else:
|
||||||
if axis == 0:
|
if axis == 0:
|
||||||
xScale = -bounds.height() / dif
|
xScale = -bounds.height() / dif
|
||||||
offset = self.range[0] * xScale - bounds.height()
|
offset = self.range[0] * xScale - bounds.height()
|
||||||
@ -633,7 +669,7 @@ class AxisItem(GraphicsWidget):
|
|||||||
## draw ticks
|
## draw ticks
|
||||||
## (to improve performance, we do not interleave line and text drawing, since this causes unnecessary pipeline switching)
|
## (to improve performance, we do not interleave line and text drawing, since this causes unnecessary pipeline switching)
|
||||||
## draw three different intervals, long ticks first
|
## draw three different intervals, long ticks first
|
||||||
|
tickSpecs = []
|
||||||
for i in range(len(tickLevels)):
|
for i in range(len(tickLevels)):
|
||||||
tickPositions.append([])
|
tickPositions.append([])
|
||||||
ticks = tickLevels[i][1]
|
ticks = tickLevels[i][1]
|
||||||
@ -663,15 +699,38 @@ class AxisItem(GraphicsWidget):
|
|||||||
color = tickPen.color()
|
color = tickPen.color()
|
||||||
color.setAlpha(lineAlpha)
|
color.setAlpha(lineAlpha)
|
||||||
tickPen.setColor(color)
|
tickPen.setColor(color)
|
||||||
p.setPen(tickPen)
|
tickSpecs.append((tickPen, Point(p1), Point(p2)))
|
||||||
p.drawLine(Point(p1), Point(p2))
|
prof.mark('compute ticks')
|
||||||
prof.mark('draw ticks')
|
|
||||||
|
## This is where the long axis line should be drawn
|
||||||
|
|
||||||
|
if self.style['stopAxisAtTick'][0] is True:
|
||||||
|
stop = max(span[0].y(), min(map(min, tickPositions)))
|
||||||
|
if axis == 0:
|
||||||
|
span[0].setY(stop)
|
||||||
|
else:
|
||||||
|
span[0].setX(stop)
|
||||||
|
if self.style['stopAxisAtTick'][1] is True:
|
||||||
|
stop = min(span[1].y(), max(map(max, tickPositions)))
|
||||||
|
if axis == 0:
|
||||||
|
span[1].setY(stop)
|
||||||
|
else:
|
||||||
|
span[1].setX(stop)
|
||||||
|
axisSpec = (self.pen(), span[0], span[1])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
textOffset = self.style['tickTextOffset'] ## spacing between axis and text
|
||||||
|
#if self.style['autoExpandTextSpace'] is True:
|
||||||
|
#textWidth = self.textWidth
|
||||||
|
#textHeight = self.textHeight
|
||||||
|
#else:
|
||||||
|
#textWidth = self.style['tickTextWidth'] ## space allocated for horizontal text
|
||||||
|
#textHeight = self.style['tickTextHeight'] ## space allocated for horizontal text
|
||||||
|
|
||||||
## Draw text until there is no more room (or no more text)
|
|
||||||
if self.tickFont is not None:
|
|
||||||
p.setFont(self.tickFont)
|
|
||||||
|
|
||||||
textRects = []
|
textRects = []
|
||||||
|
textSpecs = [] ## list of draw
|
||||||
for i in range(len(tickLevels)):
|
for i in range(len(tickLevels)):
|
||||||
## Get the list of strings to display for this level
|
## Get the list of strings to display for this level
|
||||||
if tickStrings is None:
|
if tickStrings is None:
|
||||||
@ -688,18 +747,34 @@ class AxisItem(GraphicsWidget):
|
|||||||
if tickPositions[i][j] is None:
|
if tickPositions[i][j] is None:
|
||||||
strings[j] = None
|
strings[j] = None
|
||||||
|
|
||||||
textRects.extend([p.boundingRect(QtCore.QRectF(0, 0, 100, 100), QtCore.Qt.AlignCenter, str(s)) for s in strings if s is not None])
|
## Measure density of text; decide whether to draw this level
|
||||||
|
rects = []
|
||||||
|
for s in strings:
|
||||||
|
if s is None:
|
||||||
|
rects.append(None)
|
||||||
|
else:
|
||||||
|
br = p.boundingRect(QtCore.QRectF(0, 0, 100, 100), QtCore.Qt.AlignCenter, str(s))
|
||||||
|
## boundingRect is usually just a bit too large
|
||||||
|
## (but this probably depends on per-font metrics?)
|
||||||
|
br.setHeight(br.height() * 0.8)
|
||||||
|
|
||||||
|
rects.append(br)
|
||||||
|
textRects.append(rects[-1])
|
||||||
|
|
||||||
if i > 0: ## always draw top level
|
if i > 0: ## always draw top level
|
||||||
## measure all text, make sure there's enough room
|
## measure all text, make sure there's enough room
|
||||||
if axis == 0:
|
if axis == 0:
|
||||||
textSize = np.sum([r.height() for r in textRects])
|
textSize = np.sum([r.height() for r in textRects])
|
||||||
|
textSize2 = np.max([r.width() for r in textRects])
|
||||||
else:
|
else:
|
||||||
textSize = np.sum([r.width() for r in textRects])
|
textSize = np.sum([r.width() for r in textRects])
|
||||||
|
textSize2 = np.max([r.height() for r in textRects])
|
||||||
|
|
||||||
## If the strings are too crowded, stop drawing text now
|
## If the strings are too crowded, stop drawing text now
|
||||||
textFillRatio = float(textSize) / lengthInPixels
|
textFillRatio = float(textSize) / lengthInPixels
|
||||||
if textFillRatio > 0.7:
|
if textFillRatio > 0.7:
|
||||||
break
|
break
|
||||||
|
|
||||||
#spacing, values = tickLevels[best]
|
#spacing, values = tickLevels[best]
|
||||||
#strings = self.tickStrings(values, self.scale, spacing)
|
#strings = self.tickStrings(values, self.scale, spacing)
|
||||||
for j in range(len(strings)):
|
for j in range(len(strings)):
|
||||||
@ -708,24 +783,61 @@ class AxisItem(GraphicsWidget):
|
|||||||
continue
|
continue
|
||||||
vstr = str(vstr)
|
vstr = str(vstr)
|
||||||
x = tickPositions[i][j]
|
x = tickPositions[i][j]
|
||||||
textRect = p.boundingRect(QtCore.QRectF(0, 0, 100, 100), QtCore.Qt.AlignCenter, vstr)
|
#textRect = p.boundingRect(QtCore.QRectF(0, 0, 100, 100), QtCore.Qt.AlignCenter, vstr)
|
||||||
|
textRect = rects[j]
|
||||||
height = textRect.height()
|
height = textRect.height()
|
||||||
self.textHeight = height
|
width = textRect.width()
|
||||||
|
#self.textHeight = height
|
||||||
|
offset = max(0,self.tickLength) + textOffset
|
||||||
if self.orientation == 'left':
|
if self.orientation == 'left':
|
||||||
textFlags = QtCore.Qt.AlignRight|QtCore.Qt.AlignVCenter
|
textFlags = QtCore.Qt.TextDontClip|QtCore.Qt.AlignRight|QtCore.Qt.AlignVCenter
|
||||||
rect = QtCore.QRectF(tickStop-100, x-(height/2), 99-max(0,self.tickLength), height)
|
rect = QtCore.QRectF(tickStop-offset-width, x-(height/2), width, height)
|
||||||
elif self.orientation == 'right':
|
elif self.orientation == 'right':
|
||||||
textFlags = QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter
|
textFlags = QtCore.Qt.TextDontClip|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter
|
||||||
rect = QtCore.QRectF(tickStop+max(0,self.tickLength)+1, x-(height/2), 100-max(0,self.tickLength), height)
|
rect = QtCore.QRectF(tickStop+offset, x-(height/2), width, height)
|
||||||
elif self.orientation == 'top':
|
elif self.orientation == 'top':
|
||||||
textFlags = QtCore.Qt.AlignCenter|QtCore.Qt.AlignBottom
|
textFlags = QtCore.Qt.TextDontClip|QtCore.Qt.AlignCenter|QtCore.Qt.AlignBottom
|
||||||
rect = QtCore.QRectF(x-100, tickStop-max(0,self.tickLength)-height, 200, height)
|
rect = QtCore.QRectF(x-width/2., tickStop-offset-height, width, height)
|
||||||
elif self.orientation == 'bottom':
|
elif self.orientation == 'bottom':
|
||||||
textFlags = QtCore.Qt.AlignCenter|QtCore.Qt.AlignTop
|
textFlags = QtCore.Qt.TextDontClip|QtCore.Qt.AlignCenter|QtCore.Qt.AlignTop
|
||||||
rect = QtCore.QRectF(x-100, tickStop+max(0,self.tickLength), 200, height)
|
rect = QtCore.QRectF(x-width/2., tickStop+offset, width, height)
|
||||||
|
|
||||||
|
#p.setPen(self.pen())
|
||||||
|
#p.drawText(rect, textFlags, vstr)
|
||||||
|
textSpecs.append((rect, textFlags, vstr))
|
||||||
|
prof.mark('compute text')
|
||||||
|
|
||||||
|
## update max text size if needed.
|
||||||
|
self._updateMaxTextSize(textSize2)
|
||||||
|
|
||||||
|
return (axisSpec, tickSpecs, textSpecs)
|
||||||
|
|
||||||
|
def drawPicture(self, p, axisSpec, tickSpecs, textSpecs):
|
||||||
|
prof = debug.Profiler("AxisItem.drawPicture", disabled=True)
|
||||||
|
|
||||||
|
p.setRenderHint(p.Antialiasing, False)
|
||||||
|
p.setRenderHint(p.TextAntialiasing, True)
|
||||||
|
|
||||||
|
## draw long line along axis
|
||||||
|
pen, p1, p2 = axisSpec
|
||||||
|
p.setPen(pen)
|
||||||
|
p.drawLine(p1, p2)
|
||||||
|
p.translate(0.5,0) ## resolves some damn pixel ambiguity
|
||||||
|
|
||||||
|
## draw ticks
|
||||||
|
for pen, p1, p2 in tickSpecs:
|
||||||
|
p.setPen(pen)
|
||||||
|
p.drawLine(p1, p2)
|
||||||
|
prof.mark('draw ticks')
|
||||||
|
|
||||||
|
## Draw all text
|
||||||
|
if self.tickFont is not None:
|
||||||
|
p.setFont(self.tickFont)
|
||||||
p.setPen(self.pen())
|
p.setPen(self.pen())
|
||||||
p.drawText(rect, textFlags, vstr)
|
for rect, flags, text in textSpecs:
|
||||||
|
p.drawText(rect, flags, text)
|
||||||
|
#p.drawRect(rect)
|
||||||
|
|
||||||
prof.mark('draw text')
|
prof.mark('draw text')
|
||||||
prof.finish()
|
prof.finish()
|
||||||
|
|
||||||
|
@ -403,6 +403,7 @@ class PlotCurveItem(GraphicsObject):
|
|||||||
|
|
||||||
p.setRenderHint(p.Antialiasing, aa)
|
p.setRenderHint(p.Antialiasing, aa)
|
||||||
|
|
||||||
|
|
||||||
if self.opts['brush'] is not None and self.opts['fillLevel'] is not None:
|
if self.opts['brush'] is not None and self.opts['fillLevel'] is not None:
|
||||||
if self.fillPath is None:
|
if self.fillPath is None:
|
||||||
if x is None:
|
if x is None:
|
||||||
|
@ -1079,6 +1079,7 @@ class PlotItem(GraphicsWidget):
|
|||||||
============= =================================================================
|
============= =================================================================
|
||||||
"""
|
"""
|
||||||
self.getAxis(axis).setLabel(text=text, units=units, **args)
|
self.getAxis(axis).setLabel(text=text, units=units, **args)
|
||||||
|
self.showAxis(axis)
|
||||||
|
|
||||||
def setLabels(self, **kwds):
|
def setLabels(self, **kwds):
|
||||||
"""
|
"""
|
||||||
|
Loading…
Reference in New Issue
Block a user