Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Boxplot feature #2562

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open

Add Boxplot feature #2562

wants to merge 7 commits into from

Conversation

noonchen
Copy link
Contributor

Add BoxplotItem and example code.

Closes #2542 .

@pijyoi
Copy link
Contributor

pijyoi commented Dec 26, 2022

I think you left out pyqtgraph/__init__.py
Also please add your example to pyqtgraph/examples/utils.py so that it gets added to ExampleApp and also gets executed by the CI.

From #2561, I found that getting the bounding rectangle right is not so straightforward. Below is a script that demonstrates two issues.

  1. the size of the outlier symbol is not accounted for
  2. when a thick pen is used, QPicture.boundingRect() computes the bounding rectangle wrongly
import numpy as np
import pyqtgraph as pg
from pyqtgraph.Qt import QtCore, QtGui, QtWidgets

class ObjectBounds(QtWidgets.QGraphicsItem):
    def paint(self, painter, *args):
        pen = QtGui.QPen(QtCore.Qt.GlobalColor.red, 0, QtCore.Qt.PenStyle.DashLine)
        rect = self.boundingRect()
        painter.setPen(pen)
        painter.drawRect(rect)
        print(rect)

    def boundingRect(self):
        return self.parentItem().boundingRect()

pg.mkQApp()
pw = pg.PlotWidget()
pw.show()

np.random.seed(8)
n = 5
data = [np.random.normal(500, 30, 1000) for _ in range(n)]

bpi = pg.BoxplotItem()
pen = pg.mkPen('y', width=6)
bpi.setData(data=data, pen=pen, symbol='star', symbolBrush='g')
pw.addItem(bpi)
rect = ObjectBounds(bpi)

pg.exec()

@noonchen
Copy link
Contributor Author

@pijyoi Thanks for pointing out these issues, let me try to fix them.

@noonchen noonchen marked this pull request as draft December 26, 2022 14:20
pyqtgraph/__init__.py Fixed Show resolved Hide resolved
define __all__
@noonchen noonchen marked this pull request as ready for review December 26, 2022 15:49
@noonchen
Copy link
Contributor Author

@pijyoi bounding rect should be correct now.

image

@pijyoi
Copy link
Contributor

pijyoi commented Dec 26, 2022

I am getting the plot below on Windows/PyQt6 and also on WSL2/PySide6. Note that there is no big empty space.
Did you paste an older screenshot?
Screenshot 2022-12-27 071041

@noonchen
Copy link
Contributor Author

noonchen commented Dec 27, 2022

No, it's the screenshot from latest changes. I can't explain why there are still blank spaces surround bounding rect.

I'm running on macos + pyqt5

@pijyoi
Copy link
Contributor

pijyoi commented Dec 27, 2022

Ah, I see that the bounding rectangle is tight but the viewbox is not in your screenshot.
Perhaps this is platform specific.

Could you try out the example in #2561 on both #2561 and #2565 on your macOS system and see if there are any differences?
On {Windows,Linux} x {Qt5,Qt6} they look the same to me, i.e. no empty space.

Or even better, try out the script in #2565 (comment)


p.setPen(symbolPen)
p.setBrush(symbolBrush)
for pos, outliers in self.outlierData.items():
Copy link
Contributor

@pijyoi pijyoi Dec 28, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I made a mistake, deviceTransform should be used instead of mapToScene.
But if we follow ScatterPlotItem's code, we can just use QPainter.transform instead

        tr = p.transform()
        for pos, outliers in self.outlierData.items():
            for o in outliers:
                x, y = (pos, o) if self.opts["locAsX"] else (o, pos)
                p.resetTransform()
                p.translate(*tr.map(x, y))
                p.scale(symbolSize, symbolSize)
                p.drawPath(symbol)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Feature: Boxplot support
2 participants