Skip to content

Commit

Permalink
Merge pull request #3028 from j9ac9k/more-performance-talk-in-docs
Browse files Browse the repository at this point in the history
Substantially upgrade ImageItem docs
  • Loading branch information
j9ac9k committed May 27, 2024
2 parents ab407d6 + 6d6063d commit 65dc273
Show file tree
Hide file tree
Showing 18 changed files with 6,288 additions and 366 deletions.
1 change: 1 addition & 0 deletions .readthedocs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ build:
python: "3"
apt_packages:
- libopengl0
- graphviz

sphinx:
fail_on_warning: true
Expand Down
27 changes: 19 additions & 8 deletions doc/source/_static/custom.css
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ Nat Methods 8, 441 (2011). https://doi.org/10.1038/nmeth.1618
}

/* Main index page overview cards */

.sd-card {
background: #fff;
border-radius: 0;
Expand Down Expand Up @@ -134,15 +133,14 @@ types are assumed to be normal images.
*/
html[data-theme=dark] img[src*='.svg']:not(.only-dark):not(.dark-light) {
filter: brightness(0.8) invert(0.82) contrast(1.2);
background: unset
background: unset;
}

html[data-theme=dark] .MathJax_SVG * {
fill: var(--pst-color-text-base);
}

/* Main index page overview cards */

html[data-theme=dark] .sd-card {
background-color:var(--pst-color-background);
border: none
Expand All @@ -161,10 +159,23 @@ html[data-theme=dark] .sd-card .sd-card-footer {
background-color:var(--pst-color-background);
}

/*
Hide TypeAlias Classes
*/

/* Hide TypeAlias Classes */
dt#ColorMapSpecifier {
visibility: hidden;
}
}

/* Flip the colours on graphviz graphs on dark mode */
html[data-theme="dark"] div.graphviz > object.inheritance {
filter: brightness(0.8) invert(0.82) contrast(1.2);
color-scheme: normal;
}

/* Make inheritance images have a scroll bar if necessary. */
div.graphviz {
border: 1px solid #7f7f7f00;
max-height: 50em;
overflow: auto;
}
img.graphviz.inheritance {
max-width: none;
}
22 changes: 7 additions & 15 deletions doc/source/api_reference/functions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,12 @@ Color, Pen, and Brush Functions

Qt uses the classes QColor, QPen, and QBrush to determine how to draw lines and fill shapes. These classes are highly capable but somewhat awkward to use. PyQtGraph offers the functions :func:`~pyqtgraph.mkColor`, :func:`~pyqtgraph.mkPen`, and :func:`~pyqtgraph.mkBrush` to simplify the process of creating these classes. In most cases, however, it will be unnecessary to call these functions directly--any function or method that accepts *pen* or *brush* arguments will make use of these functions for you. For example, the following three lines all have the same effect::
.. code-block:: python
pg.plot(xdata, ydata, pen='r')
pg.plot(xdata, ydata, pen=pg.mkPen('r'))
pg.plot(xdata, ydata, pen=QPen(QColor(255, 0, 0)))

.. autofunction:: pyqtgraph.mkColor

.. autofunction:: pyqtgraph.mkPen
Expand All @@ -36,13 +37,11 @@ Qt uses the classes QColor, QPen, and QBrush to determine how to draw lines and

.. autofunction:: pyqtgraph.colorDistance


Data Slicing
------------

.. autofunction:: pyqtgraph.affineSlice


Coordinate Transformation
-------------------------

Expand All @@ -54,8 +53,6 @@ Coordinate Transformation

.. autofunction:: pyqtgraph.solveBilinearTransform



SI Unit Conversion Functions
----------------------------

Expand All @@ -67,20 +64,18 @@ SI Unit Conversion Functions

.. autofunction:: pyqtgraph.siParse


Image Preparation Functions
---------------------------

.. autofunction:: pyqtgraph.makeARGB

.. autofunction:: pyqtgraph.makeQImage
.. autofunction:: pyqtgraph.functions.makeARGB

.. autofunction:: pyqtgraph.applyLookupTable
.. autofunction:: pyqtgraph.functions.makeQImage

.. autofunction:: pyqtgraph.rescaleData
.. autofunction:: pyqtgraph.functions.applyLookupTable

.. autofunction:: pyqtgraph.imageToArray
.. autofunction:: pyqtgraph.functions.rescaleData

.. autofunction:: pyqtgraph.functions.imageToArray

Mesh Generation Functions
-------------------------
Expand All @@ -89,7 +84,6 @@ Mesh Generation Functions

.. autofunction:: pyqtgraph.isosurface


Miscellaneous Functions
-----------------------

Expand All @@ -103,13 +97,11 @@ Miscellaneous Functions

.. autofunction:: pyqtgraph.exit


Legacy Color Helper Functions
-------------------------------

The following helper functions should no longer be used. The functionality that they implement is trivial and it is suggested that the user use the equivalent QColor methods directly.


.. autofunction:: pyqtgraph.colorTuple

.. autofunction:: pyqtgraph.colorStr
Expand Down
135 changes: 98 additions & 37 deletions doc/source/api_reference/graphicsItems/imageitem.rst
Original file line number Diff line number Diff line change
@@ -1,67 +1,128 @@
.. role:: python(code)
:language: python

ImageItem
=========

:class:`~pyqtgraph.ImageItem` displays images inside a :class:`~pyqtgraph.GraphicsView`, or a
:class:`~pyqtgraph.ViewBox`, which may itself be part of a :class:`~pyqtgraph.PlotItem`. It is designed
for rapid updates as needed for a video display. The supplied data is optionally scaled (see
:func:`~pyqtgraph.ImageItem.setLevels`) and/or colored according to a
lookup table (see :func:`~pyqtgraph.ImageItem.setColorMap` and
:func:`~pyqtgraph.ImageItem.setLookupTable`).
Overview
--------

:class:`~pyqtgraph.ImageItem` displays images inside a
:class:`~pyqtgraph.GraphicsView`, or a :class:`~pyqtgraph.ViewBox`, which may itself be
part of a :class:`~pyqtgraph.PlotItem`. It is designed for rapid updates as needed for
a video display. The supplied data is optionally scaled (see
:meth:`ImageItem.setLevels <pyqtgraph.ImageItem.setLevels>`) and/or colored according
to a lookup table (see :meth:`ImageItem.setColorMap <pyqtgraph.ImageItem.setColorMap>`
and :meth:`ImageItem.setLookupTable <pyqtgraph.ImageItem.setLookupTable>`).

Data is provided as a NumPy array with an ordering of either

* `col-major`, where the shape of the array represents (width, height) or
* `row-major`, where the shape of the array represents (height, width).
* `col-major`, where the shape of the array represents (width, height) or
* `row-major`, where the shape of the array represents (height, width).

While `col-major` is the default, `row-major` ordering typically has the best performance. In either ordering,
a third dimension can be added to the array to hold individual
``[R,G,B]`` or ``[R,G,B,A]`` components.
While `col-major` is the default, `row-major` ordering typically has the best
performance. In either ordering, a third dimension can be added to the array to hold
individual :python:`[R,G,B]` or :python:`[R,G,B,A]` channels/components.

Notes
-----

Data ordering can be set for each ImageItem, or in the :ref:`global configuration options <apiref_config>` by ::

pyqtgraph.setConfigOption('imageAxisOrder', 'row-major') # best performance
:class:`~pyqtgraph.ImageItem` is frequently used in conjunction with
:class:`~pyqtgraph.ColorBarItem` to provide a color map display and interactive level
adjustments, or with :class:`~pyqtgraph.HistogramLUTItem` or
:class:`~pyqtgraph.HistogramLUTWidget` for a full GUI to control the levels and lookup
table used to display the image.

An image can be placed into a plot area of a given extent directly through the
:func:`~pyqtgraph.ImageItem.setRect` method or the ``rect`` keyword. This is internally realized through
assigning a ``QtGui.QTransform``. For other translation, scaling or rotations effects that
persist for all later image data, the user can also directly define and assign such a
transform, as shown in the example below.

ImageItem is frequently used in conjunction with :class:`~pyqtgraph.ColorBarItem` to provide
a color map display and interactive level adjustments, or with
:class:`~pyqtgraph.HistogramLUTItem` or :class:`~pyqtgraph.HistogramLUTWidget` for a full GUI
to control the levels and lookup table used to display the image.

If performance is critial, the following points may be worth investigating:

* Use row-major ordering and C-contiguous image data.
* Manually provide ``level`` information to avoid autoLevels sampling of the image.
* Prefer `float32` to `float64` for floating point data, avoid NaN values.
* Use lookup tables with <= 256 entries for false color images.
* Avoid individual level adjustments RGB components.
* Use the latest version of NumPy. Notably, SIMD code added in version 1.20 significantly improved performance on Linux platforms.
* Enable Numba with ``pyqtgraph.setConfigOption('useNumba', True)``, although the JIT compilation will only accelerate repeated image display.
:meth:`ImageItem.setRect <pyqtgraph.ImageItem.setRect>` method or the `rect` keyword.
This is internally realized through assigning a :class:`QTransform`. For other
translation, scaling or rotations effects that persist for all later image data, the
user can also directly define and assign such a transform, as shown in the example
below.

.. _ImageItem_performance:

Performance
-----------

The performance of :class:`~pyqtgraph.ImageItem` can vary *significantly* based on
attributes of the `image`, `levels` and `lut` input arguments. It should not be
assumed that the default parameters are the most performant, as the default values are
largely there to preserve backwards compatibility.

The following guidance should be observed if performance is an important factor

* Instantiate :class:`~pyqtgraph.ImageItem` with :python:`axisOrder='row-major'`

* Alternatively, set the global configuration optionally
:python:`pyqtgraph.setConfigOption('imageAxisOrder', 'row-major')`

* Use C-contiguous image data.
* For 1 or 3 channel data, use `uint8`, `uint16`, `float32`, or `float64` `image`
dtype.
* For 4-channel data, use `uint8` or `uint16` with :python:`levels=None`.
* `levels` should be set to either to ``None`` or to single channel ``[min, max]``

* Not setting `levels` will trigger autoLevels sampling

* If using LUTs (lookup tables), ensure they have a dtype of `uint8` and have 256
points or less. That can be accomplished with calling:

* :func:`ImageItem.setColorMap <pyqtgraph.ImageItem.setColorMap>` or
* :func:`ImageItem.setLookupTable <pyqtgraph.ImageItem.setLookupTable>` with
:python:`ColorMap.getLookupTable(nPts=256)` (default is :python:`nPts=512`)

* For floating point `image` arrays, prefer `float32` dtype to `float64` and avoid
``NaN`` values.
* Enable Numba with :python:`pyqtgraph.setConfigOption('useNumba', True)`

* JIT compilation will only accelerate repeated image display.

Internally, pyqtgraph attempts to directly construct a :class:`QImage` using a
combination of :class:`QImage.Format <QImage.Format>` options and
:meth:`QImage.setColorTable <QImage.setColorTable>` if necessary. This does not work in
all cases that pyqtgraph supports. If pyqtgraph is unable to construct the
:class:`QImage` in such a fashion, it will fall back on
:func:`~pyqtgraph.functions.makeARGB` to manipulate the data in a manner that
:class:`QImage` can read it in. There is a *significant* performance penalty when
having to use :func:`~pyqtgraph.functions.makeARGB`.

For applications that are *very* performance sensitive, every effort should be made so
that the arguments passed to :meth:`ImageItem.setImage <pyqtgraph.ImageItem.setImage>`
do not call :func:`~pyqtgraph.functions.makeARGB`.

.. _ImageItem_examples:

Examples
--------

Scale and Position ImageItem
^^^^^^^^^^^^^^^^^^^^^^^^^^^^

In the following example, it is demonstrated how a user scale and translate a
:class:`~pyqtgraph.ImageItem` within a :class:`~pyqtgraph.ViewBox` to occupy a specific
position and size.

.. literalinclude:: /images/gen_example_imageitem_transform.py
:lines: 19-28
:dedent: 8
:lines: 4-44
:emphasize-lines: 24-33
:language: python

.. thumbnail::
/images/example_imageitem_transform.png
:width: 49%
:alt: Example of transformed image display
:title: Transformed Image Display

Inheritance
-----------

.. inheritance-diagram:: pyqtgraph.graphicsItems.ImageItem.ImageItem
:top-classes: PyQt6.QtCore.QObject, PyQt6.QtWidgets.QGraphicsItem
:parts: 1

API
---

.. autoclass:: pyqtgraph.ImageItem
:members:

.. automethod:: pyqtgraph.ImageItem.__init__

0 comments on commit 65dc273

Please sign in to comment.