Compare commits

...

1005 Commits

Author SHA1 Message Date
Kyle Sunden 6fa4a0a3eb
Merge pull request #2012 from j9ac9k/prep-0.12.3-release
Prep for 0.12.3 Release
2021-10-10 22:01:10 -05:00
Kyle Sunden 0f3804e32c
Merge pull request #2013 from ksunden/rel_action
Add python publishing workflow
2021-10-10 22:00:18 -05:00
Ogi Moore af8c766de3 Update changelog 2021-10-09 15:28:28 -07:00
Ogi Moore 58325ee91b
Merge pull request #2014 from j9ac9k/fix-some-imports
Fix Some Import Issues
2021-10-09 15:26:44 -07:00
Ogi Moore 936108ec60 Import Dock class not module 2021-10-09 15:06:51 -07:00
Ogi Moore 9b67e51230 Switch to relative imports for some parameterTypes 2021-10-09 15:06:51 -07:00
Ogi Moore db74522003 Have parameter types imports use non __init__
When using isort, the order of parametertree/__init__.py imports broke many
of the parameter-types imports.  This commit modifies the import statement to
not use the imports from __init__.py but import the respective classes from the
the non-__init__ modules
2021-10-09 15:06:51 -07:00
Kyle Sunden 9ae38e6d21
Update .github/workflows/python-publish.yml 2021-10-09 13:04:01 -05:00
Kyle Sunden 34c6981b0f Update version number in __init__ 2021-10-09 00:37:49 -05:00
Ogi Moore b8ca314597 Update changelog for 0.12.3 2021-10-08 22:27:35 -07:00
Kyle Sunden ae484ba411 Add python publishing workflow 2021-10-09 00:26:29 -05:00
Ogi Moore fd6985565c
Merge pull request #2009 from pijyoi/fix_imageview_roi
unhide ImageView roi curves
2021-10-08 21:05:08 -07:00
KIU Shueng Chuan 2da769d6a5 unhide ImageView roi curves 2021-10-08 22:01:41 +08:00
Ogi Moore fb809e5260
Merge pull request #2007 from pijyoi/skip_missing_scipy
skip tests using scipy if not installed
2021-10-07 21:22:24 -07:00
KIU Shueng Chuan 4aeb0ce1dd skip tests using scipy if not installed 2021-10-08 11:52:52 +08:00
Martin Chase a6bb2c6edd
Allow ThreadTrace to save to a file (#1998)
* allow ThreadTrace to save to a file

* make sure we close our output file

* fix the egregious errors in the file
 - no mutable default args
 - import things before using them
 - variable named obj did not exist, but try/except ignored it

* if it's dumb, and it works, it's not dumb

* linux requires a flush; remove commented code

* always close the file handle, even if its stdout

* it may work for us, but just in case, protect with finally

* turns out: lots of things like to use stdout!

Co-authored-by: Luke Campagnola <lukec@alleninstitute.org>
Co-authored-by: Ogi Moore <ognyan.moore@gmail.com>
2021-10-07 12:25:38 -07:00
Ogi Moore e8b77a11e5
Merge pull request #2006 from j9ac9k/revise-reload-skip-condition
Remove python 3.10 skip condition for test_reload
2021-10-06 23:43:05 -07:00
Ogi Moore e04ecdf554 Remove python 3.10 skip condition for test_reload 2021-10-06 23:01:40 -07:00
Nils Nemitz 0cc3580687
Traditional log10 mode for PlotDataItem (by adding "mapped data" stage) (#1992)
* make PlotDataItem aware of mapped data

* inf suppression, metadata storage and refactor of data structures

* cleanup, test, and documentation pass

* re-added prepareForPaint, added PlotDataset to sphinx index

* strip more print statements

* indicate (internal) PlotDataset documentation as orphaned to avoid sphinx error

* Do not export PlotDataset

* replacement example

* example comments
2021-10-06 22:40:38 -07:00
Ogi Moore bc542ae1c4
Merge pull request #2003 from j9ac9k/fix-py310-drawText-call
Fix Python 3.10 GLGradientLegendItem call to QPainter.drawText
2021-10-06 06:35:12 -07:00
Ogi Moore 5917e5e666 QPainter.drawText needs QPointF not x, y 2021-10-05 20:47:15 -07:00
Ogi Moore 95c302fd0d
Merge pull request #1999 from pijyoi/mpl_qt6
Re-enable Matplotlib Exporter Test for Qt6
2021-09-29 09:54:37 -07:00
KIU Shueng Chuan 4b59734629 enable matplotlib exporter test for qt6 2021-09-24 19:47:20 +08:00
ntjess 8d3e6cbd22
Better parameter tree testing (#1953)
* Allows values to be numpy arrays

* Bugfix: Slider now works when limits didn't change during `optsChanged`

* Improved testing + layout of param tree example

* Also fix numpy-like values in list `setValue`

* use proper hex formatting for  value

* Fix code warnings

* Avoids use of configfile in parametertree

* Avoid shadowing variable names

* Add explanatory comment to `makeAllParamTypes`

* Allow string options to be 'unset' in file, etc. parameters example

* Bugfix: unintunitive option unsetting for file window title

* don't use lambda in signal connect

* Remove unused import
2021-09-23 21:06:00 -07:00
Ogi Moore e9d3b6ddd2
Merge pull request #1995 from Achilles1515/colorbutton-padding
Change hardcoded padding into initialization parameter
2021-09-23 17:19:08 -07:00
Dane Owens 1132c138a4 Change hardcoded padding into initialization parameter 2021-09-17 09:51:26 -04:00
Ogi Moore b075035b0d
Merge pull request #1987 from jkotan/regiontypo
Issue 1986: fix for autoLevel of RGB histograms
2021-09-08 11:22:37 -07:00
Jan Kotanski 4334cd14de fix for autoLevel of RGB histograms 2021-09-08 09:20:12 +02:00
Ogi Moore 126b7e0925
Merge pull request #1985 from pijyoi/workaround_float_lut
delegate float luts to makeARGB()
2021-09-07 21:48:15 -07:00
magnium 6f4b6b1b88
Fix ImageView levelMode (#1974)
* fixes #1769

* Automatically set image to ImageView if imageItem is provided.
Added a test for correct initialization of ImageView with imageItem and levelMode.
2021-09-07 21:27:26 -07:00
ntjess babd037cf7
Adds checklist parameter (#1952)
* Alphabetize parameter registration

* Implements a checklist parameter

* Several checklist updates
- Correct indentation
- Allow dict-like setting + non-string values
- Fix several bugs associated with 'exclusive' behavior

* Add 'checklist' to param tree example

* Add documentation

* Removes unneeded code

* Forgot to rebuilt RST doc

* `exclusive` checklist uses radio buttons

* better checklist change logic

Co-authored-by: Ogi Moore <ognyan.moore@gmail.com>
2021-09-07 21:25:17 -07:00
Petras Jokubauskas 745b04baa5
Fix: updateDecimate should not unhide intentionaly hidden curves (#1973)
* Update PlotItem.py

make update decimate to not unhide curves when items added/removed,
while preserving the Max Traces well behaviour

* Update PlotItem.py

fix typo

* Update PlotItem.py

fix: typo with self as argument

* give better name for the function which handles MaxTraces checkstate change

rename it to _handle_max_traces_toggle

* add doc string to updateDecimation

* add test for PlotItem for external curve visibility control

check if hidden curve would stay hidden when adding or removing other items.

* remove additional empty line between methods
2021-09-07 21:19:22 -07:00
Ogi Moore 2a66460afc
Merge pull request #1954 from ntjess/deprecate-values-opt
Deprecate `values` opt for list parameter
2021-09-07 20:57:27 -07:00
Ogi Moore 446a2c324c
Merge pull request #1721 from j9ac9k/test-pr807
Implement a GLGraphItem according to #807
2021-09-07 20:47:19 -07:00
Ogi Moore d54da71138 Add docs page 2021-09-07 20:28:57 -07:00
Ogi Moore 13ab4de209 Add really basic GLGraphItem example 2021-09-07 20:28:57 -07:00
Ogi Moore c3dba791d1 Make equivalent to #807 2021-09-07 20:28:57 -07:00
KIU Shueng Chuan b5475cad6b warn about usage of non-uint8 LUTs 2021-09-08 09:52:46 +08:00
KIU Shueng Chuan 6763b14fb9 delegate float luts to makeARGB() 2021-09-07 00:04:42 +08:00
Ogi Moore 98d7bcf560
Merge pull request #1969 from pijyoi/fix_clip_nop 2021-08-17 07:29:10 -07:00
KIU Shueng Chuan 6f1ea29fe4 bugfix: result of clip_array() not assigned 2021-08-17 22:14:13 +08:00
Ogi Moore 175f84ecbc
Merge pull request #1968 from pijyoi/imageview_scale 2021-08-14 07:37:51 -07:00
KIU Shueng Chuan 11b4a1bb47 fix: ImageView calling deprecated QGraphicsItem.scale() 2021-08-14 14:05:18 +08:00
Ogi Moore e752336b55
Merge pull request #1965 from pijyoi/qpath_chunks
perform arrayToQPath in chunks
2021-08-13 10:37:14 -07:00
KIU Shueng Chuan 0cd926ff8e merge finiteCheck branches 2021-08-14 00:00:59 +08:00
KIU Shueng Chuan e541c9ba1e hoist duplicate code 2021-08-13 18:53:58 +08:00
KIU Shueng Chuan 44e32f00c7 _fill_nonfinite() -> _compute_backfill_indices()
this allows us to defer the backfilling
2021-08-11 21:55:54 +08:00
KIU Shueng Chuan 679c1002c1 break up arrayToQPath
this restructuring removes inter-dependencies between the various modes.
this makes it easier to reason about and modify the various codepaths.
2021-08-11 06:55:21 +08:00
KIU Shueng Chuan 7e31a5e4ee setup codepath for connect=='all' and all-finite
"all-finite" includes the case where user requests to skip finiteCheck.
2021-08-10 11:57:19 +08:00
KIU Shueng Chuan fa826bd4cb add benchmarks/arrayToQPath.py 2021-08-10 11:57:19 +08:00
Ogi Moore 0d8eba36a6
Merge pull request #1957 from j9ac9k/bump-numpy-per-nep29
Bump minimum numpy up per NEP-29 schedule
2021-08-07 10:13:49 -07:00
Ogi Moore 690a416d5d Bump minimum numpy up per NEP-29 schedule 2021-08-07 09:37:19 -07:00
Ogi Moore a537bc2b23
Merge pull request #1956 from pijyoi/zerocopy_qba
arrayToQPath: use QByteArray as backing store
2021-08-06 22:22:09 -07:00
KIU Shueng Chuan 287ec9fbea arrayToQPath: use QByteArray as backing store
this avoids:
1) allocation and zero-ing of bytearray
2) copy of bytearray to QByteArray
2021-08-07 08:56:11 +08:00
Nathan Jessurun 503507ba50 Don't specify a version for deprecation 2021-08-06 08:04:51 -04:00
Nathan Jessurun 3d15ca1038 Catch remaining 'values' usages 2021-08-06 08:04:51 -04:00
Nathan Jessurun 6f44d27f2d Deprecate `values` opt for list parameter 2021-08-05 15:48:09 -04:00
Ogi Moore f16125c378
Merge pull request #1951 from timgates42/bugfix_typos
docs: Fix a few typos
2021-08-04 22:01:50 -07:00
Tim Gates a2078f8a87
docs: Fix a few typos
There are small typos in:
- doc/source/how_to_use.rst
- doc/source/region_of_interest.rst
- examples/ViewBox.py
- pyqtgraph/flowchart/Node.py
- pyqtgraph/graphicsItems/AxisItem.py
- pyqtgraph/graphicsItems/PColorMeshItem.py
- pyqtgraph/graphicsItems/PlotDataItem.py
- pyqtgraph/graphicsItems/TargetItem.py
- pyqtgraph/graphicsItems/ViewBox/ViewBox.py
- pyqtgraph/widgets/RawImageWidget.py

Fixes:
- Should read `mapped` rather than `maped`.
- Should read `vector` rather than `vetctor`.
- Should read `value` rather than `vaule`.
- Should read `preferable` rather than `preferrable`.
- Should read `output` rather than `ouptut`.
- Should read `information` rather than `inforation`.
- Should read `information` rather than `infomation`.
- Should read `exempt` rather than `excempt`.
- Should read `emphasizing` rather than `emphacizing`.
- Should read `construction` rather than `constrution`.
2021-08-05 06:47:08 +10:00
Ogi Moore 239e15a6f8
Merge pull request #1944 from pijyoi/getset_color_nih
use more of QColor functions / methods
2021-08-03 22:53:53 -07:00
KIU Shueng Chuan 178e693a4d add SVG named color support 2021-08-04 09:19:46 +08:00
KIU Shueng Chuan 371facb17f SVGExporter.py : fix background color
1) blue and green were swapped
2) %f used for integer rgb components
3) %d used for float opacity component
2021-08-04 09:19:46 +08:00
KIU Shueng Chuan 482b92d700 GLGradientLegendItem: remove opengl code
change fontColor to take a mkColor() argument

use hyperlink when referring to other functions
2021-08-04 09:19:46 +08:00
KIU Shueng Chuan efa662415e use QColor methods and functions 2021-08-04 09:19:34 +08:00
ntjess 4bf1866c2a
Organize paramtypes (#1919)
* Registered parameter types go in their own files

* Moves [int, float] item definitions outside `WidgetParameterItem`

* Moves [int, float] parameter definitions outside `WidgetParameterItem`

* Allow registering ParameterItems for easy parameter defs

* Finalizes moving simple parameters to their own files

* removes accidentally committed file

* Provides class qualnames in rst

* Address docstring build issues

* Address recent review comments
- `registerParameterItemType`:
  * added to docs and parametertree.__init__
  * Remove unsed PARAM_TYPES global
  * Hyperlink to `registerParameterType`
- parameter tree rst:
  * Alphabetize entries
  * Rebuild RST without fully qualified class name
  * Add note at file header that it is auto generated

* Remove spurious space during rst doc creation

* Ensure created/modified files end with newline

* Address CodeQL warnings

* toPlainText also returns str

* `QTreeWidgetItem.text` returns str
2021-08-02 10:47:55 -07:00
Ogi Moore fb2e684f45
Merge pull request #1943 from ntjess/rm-py2-codepaths
Remove python 2 code paths
2021-08-02 10:19:29 -07:00
ntjess e18d1fb1f2
arrayToQPath can handle empty paths (#1920)
* Fixes #1888

* Improve test coverage of arrayToQPath

* Use early exit to solve empty path instead of slice manipulation

* address codeql qualms: Unused import, uneven tuple
2021-08-02 10:18:25 -07:00
Ogi Moore d0961cc320
Merge pull request #1942 from ntjess/add-newlines
Adds EOF newline to files missing it
2021-08-02 09:09:27 -07:00
njessurun c0eb3267d2 Remove python 2 code paths 2021-08-02 12:07:25 -04:00
Ogi Moore b0bcec1ff2
Merge pull request #1941 from ntjess/more-rm-py2_3
Remove unnecessary casting of `toPlainText` to str
2021-08-02 09:01:22 -07:00
njessurun ef99d3fbf6 Adds EOF newline to files missing it.
Note: intentionally avoids files moved / already adjusted from #1919
2021-08-02 11:51:28 -04:00
Nathan Jessurun 84b491fb9b toPlainText also returns str
Note: intentionally leaves out instance in parametertypes.py to avoid merge conflict with #1919
2021-08-02 11:23:04 -04:00
Kyle Sunden a472f8c5de
Remove all usage of python2_3.py (#1939)
* Remove all usage of python2_3.py

Technically these functions were exported at the top level of the library, this removes them without warning... If we want to we can bring them back for there, but I honestly don't think its needed, as we are py3 only now and have been for multiple releases.

This may introduce a number of 'useless cast' or similar but those were always happening anyway

This PR brought to you by sed

* Update varname in hdf example to avoid collision with builtin

* Clean up some leftover comments surrounding imports of compat code

* Unnecessary string casts

* Additional unnecessary casts

* syntax error fix

* more unnecessary casts

* Yet more unnecessary casts
2021-08-01 21:43:32 -07:00
Ogi Moore 1ddbfc8321
Merge pull request #1940 from pijyoi/fix_logmode
fix log mode by reverting to previous formulation
2021-07-31 20:50:36 -07:00
KIU Shueng Chuan aebc66dcaa fix log mode by reverting to previous formulation
this formulation is in the documentation for setLogMode()
2021-08-01 11:11:41 +08:00
Kyle Sunden 6a59b7e5b5
Many unused import cleanups (#1935)
* Many unused import cleanups

Ignored some star imports, some vendored code in colorama, only looked within pyqtgraph the library, not e.g. examples

* SpinBox decimal imported with both import and from import
2021-07-31 07:35:23 -07:00
Ogi Moore 2d90e54441
Merge pull request #1936 from pijyoi/empty_qpolygonf
Handle empty QPolygonF
2021-07-31 07:30:20 -07:00
KIU Shueng Chuan 04673ac98b rename: qimage_to_ndarray -> ndarray_from_qimage 2021-07-31 21:10:34 +08:00
KIU Shueng Chuan f64290be9e test that binding provides a write-thru QImage 2021-07-31 21:00:54 +08:00
KIU Shueng Chuan 9355ecf469 support padded QImage 2021-07-31 20:58:51 +08:00
KIU Shueng Chuan 75654b8495 handle zero-sized QPolygonF
depending on the implementation, a zero-sized QPolygonF may not
have any underlying buffer allocated and may return a null pointer when
queried for its "data()"

this null pointer is returned to Python as a "None" which breaks code
not expecting it.
2021-07-31 17:25:03 +08:00
KIU Shueng Chuan 9913f7c1e7 import shiboken{2,6} as shiboken 2021-07-31 15:58:56 +08:00
Ogi Moore 7aa5d0cbf4
Merge pull request #1910 from pijyoi/paramtree_plotspeed
PlotSpeedTest: add param tree control panel
2021-07-30 22:51:36 -07:00
KIU Shueng Chuan 643dd87800 add option to allow useOpenGL toggle 2021-07-31 13:01:40 +08:00
Ogi Moore fe10b5e8dc
Merge pull request #1711 from j9ac9k/test-feature-merge
Add GLGradientLegendItem (Reimplement #663)
2021-07-30 20:37:29 -07:00
Ogi Moore 0cfc9cd440 Add GLGradientLegendItem to pyqtgraph
Huge thank you to @feketeimre for the initial PR for this feature
Thank you to @pijyoi for re-implementing with no changes needed to
GLViewWidget and supporting QOpenGLWidget vs. QGLWidget.
2021-07-30 20:19:27 -07:00
Ogi Moore d3755520d0
Merge pull request #1892 from pijyoi/glpainteritem 2021-07-30 18:23:51 -07:00
KIU Shueng Chuan 0afd8adcd8 add Big Sur conditional examples from utils.py 2021-07-31 08:28:45 +08:00
Martin Schulz 96cccd96ec
make antialiasing optional for paintGL in PlotCurveItem (#1932)
* make antialiasing optional for paintGL in PlotCurveItem

* reversion to standard values if aa is disabled

* remove unnecessary lines
2021-07-30 12:19:02 -07:00
Nils Nemitz 5084d9b537
Reduce ColorMap inefficiencies (#1927)
* Avoid regenerating QColor lists, speed up generation where unavoidable

* whitespace and typo reduction
2021-07-29 20:50:10 -07:00
Martin Chase eb8965c2f4
Restore previous signature on TargetItem.setPos() (#1928)
* Restore previous signature on TargetItem.setPos()

* star means something to sphinx

Co-authored-by: Luke Campagnola <luke.campagnola@gmail.com>
2021-07-27 18:04:24 -07:00
KIU Shueng Chuan 1a34c8857f PlotSpeedTest: add param tree control panel
inspired by ScatterPlotSpeedTest.
2021-07-24 07:41:25 +08:00
Nils Nemitz 7009084e4c
more readable names for color map references in ColorBarItem API (#1908)
* more readable names for color map references

* changed example code

* activated deprecation warnings

* added accessor methods for cmap/colorMap
2021-07-23 14:45:57 -07:00
ntjess 81823768c0
feature More parameter item types (#1844)
* feature More parameter item types

Pen: Pops up a dialouge that allows the user to customize a pen. Setting pen value is not working yet.
Progress bar: For indication things.
Slider: Easier way to set values that dont require precision.
Fonts: Picking font types. Next thing could be a Font dialog.
Calendar: For picking dates or intervals
Open/save file/files/directory: Pops up an open/save file/directory dialog to select a file/directory. Filter string and caption can be defined too.

A PenSelectorDialog widget was created for the pen parameter item too.

Also added these parameter items to the example.

* PyQt/Side6 compatibility fixup

* Revisions from intial PR

Co-authored-by: ChristophRose <42769515+ChristophRose@users.noreply.github.com>

Update pyqtgraph/widgets/PenSelectorDialog.py

Co-authored-by: ChristophRose <42769515+ChristophRose@users.noreply.github.com>

Update pyqtgraph/widgets/PenSelectorDialogbox.py

Co-authored-by: ChristophRose <42769515+ChristophRose@users.noreply.github.com>

Update pyqtgraph/widgets/PenSelectorDialogbox.py

Co-authored-by: ChristophRose <42769515+ChristophRose@users.noreply.github.com>

Update pyqtgraph/widgets/PenSelectorDialogbox.py

Co-authored-by: ChristophRose <42769515+ChristophRose@users.noreply.github.com>

Update pyqtgraph/parametertree/parameterTypes.py

Co-authored-by: ChristophRose <42769515+ChristophRose@users.noreply.github.com>

Update pyqtgraph/parametertree/parameterTypes.py

Co-authored-by: ChristophRose <42769515+ChristophRose@users.noreply.github.com>

Update pyqtgraph/widgets/PenSelectorDialog.py

Co-authored-by: ChristophRose <42769515+ChristophRose@users.noreply.github.com>

Update pyqtgraph/widgets/PenSelectorDialogbox.py

Co-authored-by: ChristophRose <42769515+ChristophRose@users.noreply.github.com>

Update pyqtgraph/widgets/PenSelectorDialogbox.py

Co-authored-by: ChristophRose <42769515+ChristophRose@users.noreply.github.com>

Update pyqtgraph/widgets/PenSelectorDialogbox.py

Co-authored-by: ChristophRose <42769515+ChristophRose@users.noreply.github.com>

Update pyqtgraph/widgets/PenSelectorDialogbox.py

Co-authored-by: ChristophRose <42769515+ChristophRose@users.noreply.github.com>

Apply suggestions from code review

Co-authored-by: ChristophRose <42769515+ChristophRose@users.noreply.github.com>

* Bugfix: module instead of class import on param tree example

* Enrich the slider parameter

* Address pijyoi comments on pen style parameter

* Different file picker for easier porting

* Better organization and formatting, minor refactoring

* PyQt6/PySide6 fixup for file dialog

* Minor adjustment to file picker

* Bugfix: for 'None' sigChanged

'None' is explicitly allowed for a WidgetParameterItem's `sigChanged` value. However, this raises an error on a changed value unless the commit's fix is applied

* Calendar works better as sub item

* Fixes bugs in pen parameter's dialog + makes it resizable

* more bugfixes and recommended changes, lets pen serialize its options

* better pen save state

* Fixes file parameter qualms

* Fixes font parameter qualms

* Fixes calendar parameter qualms

* Fixes multiply-defined slider optsChanged

* Fixes pen parameter qualms

* ptree example minor bugfix

* Pen dialog bugfixes

* File dialog bugfixes / mild improvements

* unto ptree save state regression

* file fixup

* Adds parameter descriptions to docstrings

* Improved parameter documentation

* adds 'relativeTo' option for file parameter

* Less abuse of Qt enums during or-operations

* More uniform handling of relative paths

* More cleanup of enum setting

* better name for window title (matches qt name)

* Favor os.path over pathlib

* Exposes 'directory', 'windowTitle' to file parameter

* Fixup and add comparison to parameter tree state restoration

* Exposes "cosmetic" in pen parameter

* Indicate defaults in parameter documentation

* QtEnumParameter works for enums outside QtCore.Qt

* see if altering pytest report fixes ci bug

* Cleanup unused import and redundant `self.widget` assignments

Co-authored-by: Fekete Imre <feketeimre87@gmail.com>
Co-authored-by: ChristophRose <42769515+ChristophRose@users.noreply.github.com>
2021-07-23 14:40:49 -07:00
Nils Nemitz 8f96c78715
Extend ColorMap with HSL cycles and subset generation (#1911)
* Extend ColorMap with HSL cycles and subset generation

* relaxed color palette data

* added hex to be installed in colors/maps/
2021-07-23 14:38:17 -07:00
Ogi Moore d396d33799
Remove the use of pyqtgraph.ptime (#1914)
* Remove the use of pyqtgraph.ptime

With us supporting python3.7+, we have no more need for the ptime module
and can instead safely use perf_counter for everything.

* Address small issues PR turned up

* Reword comment in ImageView
2021-07-22 20:57:50 -07:00
Martin Chase 1d40d50b89
push bullet lists over 2 spaces to get them to show up as such in the… (#1912)
* push bullet lists over 2 spaces to get them to show up as such in the docs

* separate the literal block from the bullet list
2021-07-21 07:12:35 -07:00
KIU Shueng Chuan 1184e3fcce avoid converting dict to set 2021-07-19 08:31:54 +08:00
KIU Shueng Chuan 394b0dd75c implement set/get for cameraParams 2021-07-19 06:57:07 +08:00
KIU Shueng Chuan 8a6640c419 treat self.opts as private. provide accessors 2021-07-19 04:52:49 +08:00
Ogi Moore 66ec0996f4
Merge pull request #1610 from j9ac9k/boost-plotline-performance
Boost plotline performance
2021-07-18 13:44:01 -07:00
Ogi Moore 699ed578f4
Merge pull request #1913 from ixjlyons/update-sphinx
Bump sphinx and theme versions
2021-07-18 12:46:09 -07:00
Kenneth Lyons 0ae6b753fc Bump sphinx and theme versions 2021-07-18 12:37:29 -07:00
Ogi Moore 4e293dd17d
Merge pull request #1909 from NilsNemitz/None-check_AxisItem_label
None-check AxisItem.label before access
2021-07-18 10:44:48 -07:00
Nils Nemitz 8b4db67ae9 None-check self.label before access 2021-07-18 17:24:55 +09:00
KIU Shueng Chuan d9726dbcc1 implement GLPainterItem 2021-07-18 14:14:13 +08:00
Ogi Moore d5990bf32c Uncomment ViewBox.itemChange
This handles calls for ViewBox.prepareForPaint
2021-07-17 22:30:36 -07:00
Dennis Goeries cdb427ff2f Provide a different plot test 2021-07-17 22:29:06 -07:00
Ogi Moore ed66eef203
Merge pull request #1902 from pijyoi/simpler_mvp
simplify modelview projection computation
2021-07-17 22:03:32 -07:00
Ogi Moore 58aac09387
Merge pull request #1903 from pijyoi/cleanup_glv
Cleanup GLViewWidget
2021-07-17 21:59:40 -07:00
Kenneth Lyons ba7129a719
Add option to limit LinearRegionitem bounds to a secondary item (#1834)
* Added clipItem option to LinearRegionItem

* Added a clipItem option to LinearRegionItem

Handle case when no self.viewBox() is yet available

* Implement LinearRegionItem clipItem

* Undo unnecessary change

* Update clipItem doc

* Fixup docstring formatting

* Cleanup

* Support clearing clipItem via setBounds. Fix initialization bug

* Add tests for LinearRegionItem clipItem

* Better clipItem demo in crosshair example

* Another test to verify claim in docstring

Co-authored-by: Arjun Chennu <arjun.chennu@gmail.com>
Co-authored-by: Ogi Moore <ognyan.moore@gmail.com>
Co-authored-by: Arjun Chennu <achennu@mpi-bremen.de>
2021-07-17 21:02:06 -07:00
KIU Shueng Chuan cbc9b4d310 catch specific KeyError exception 2021-07-18 10:45:58 +08:00
Ogi Moore ddab4180e9
Merge pull request #1907 from pijyoi/fix_glvol_arm64
fix GLVolumeItem example for arm64
2021-07-17 18:16:52 -07:00
KIU Shueng Chuan 6f49ede5c1 glDisable(GL_TEXTURE_3D) -> glDisable(GL_TEXTURE_2D) 2021-07-18 09:09:57 +08:00
Ogi Moore 76f3612245
Merge pull request #1904 from Artturin/tests-h5py-optional
tests/exporters/test_hdf5.py: skip if no h5py
2021-07-17 16:35:30 -07:00
Artturin 2de5cd78da tests/exporters/test_hdf5.py: skip if no h5py 2021-07-18 01:26:22 +03:00
Ogi Moore ddf73c2ecf
Merge pull request #1901 from outofculture/where-will-metaarray-be
put new MetaArray location in deprecation warning
2021-07-17 09:50:16 -07:00
KIU Shueng Chuan fa77dae941 render upright image (was previously transposed image) 2021-07-17 21:19:48 +08:00
KIU Shueng Chuan 5283eeb71b remove override of devicePixelRatio() 2021-07-17 18:55:55 +08:00
KIU Shueng Chuan aca627ac8c GLTextItem: use device independent pixels for viewport 2021-07-17 18:39:59 +08:00
KIU Shueng Chuan 31e10fdc1d raise ValueError instead of ctypes.ArgumentError
ctypes.ArgumentError got imported through PyOpenGL import *
2021-07-17 18:29:42 +08:00
KIU Shueng Chuan f85a1015ad fix GLTextItem to use relative imports 2021-07-17 18:28:09 +08:00
KIU Shueng Chuan e10dbfd9e1 change examples to use setCameraPosition 2021-07-17 18:25:21 +08:00
KIU Shueng Chuan 6ca81fdddb Revert "restore opts['viewport'] after clobbering"
This reverts commit 7a17cda956.
2021-07-17 18:25:21 +08:00
KIU Shueng Chuan 7a17cda956 restore opts['viewport'] after clobbering 2021-07-17 16:14:25 +08:00
KIU Shueng Chuan dfd5b5dc1b fix attribute access in failure branch 2021-07-17 16:06:44 +08:00
KIU Shueng Chuan 5b2674c9d5 change some deviceWidth() to width()
viewport / region use device pixels: deviceWidth()
anywhere else uses device independent pixels : width()
2021-07-17 15:59:14 +08:00
KIU Shueng Chuan f43f795950 don't check opengl version again during paint
we already fail upfront at initializeGL(), so any error that occurs
here won't be due to OpenGL version < 2.0
2021-07-17 15:59:14 +08:00
KIU Shueng Chuan 9bf6c01f58 fix renderToArray() broken for hidpi
define opts['viewport'] to be in device pixels.

note from the removed comments that there was one place assuming
opts['viewport'] was in device pixels and the other assuming that it was
in device independent pixels.
2021-07-17 14:49:47 +08:00
KIU Shueng Chuan bc52a2afe0 return ValueError for wrong argument, not RuntimeError 2021-07-17 13:46:11 +08:00
KIU Shueng Chuan fab505a431 remove unneeded call to makeCurrent()
in any case, context will not be valid until the widget is shown.
2021-07-17 13:32:33 +08:00
KIU Shueng Chuan 1814ff535d fail upfront for OpenGL ES instead of during item add 2021-07-17 13:30:20 +08:00
KIU Shueng Chuan f698ccc06e load background color from configOption 2021-07-17 13:05:40 +08:00
KIU Shueng Chuan ce4c6d95ed fix setCameraPosition not setting ele and azi in euler mode 2021-07-17 11:04:32 +08:00
KIU Shueng Chuan b5fc3d2a7e add comment about definition of viewport 2021-07-17 10:40:27 +08:00
KIU Shueng Chuan 1b00d3448a reimplement readQImage()
tested that call to repaint() is not needed
2021-07-17 10:34:27 +08:00
KIU Shueng Chuan 5d7dd101f2 load matrix instead of multiplying to identity 2021-07-17 10:21:26 +08:00
KIU Shueng Chuan 025ca08574 delete empty resizeGL() 2021-07-17 10:17:31 +08:00
KIU Shueng Chuan ee9b1565bd don't redefine width() and height()
Qt widgets define width() and height() to be in device independent
pixels. Don't change that meaning.
2021-07-17 10:14:53 +08:00
KIU Shueng Chuan e158034c07 remove devicePixelRatio argument. only needed for Qt4 2021-07-17 09:49:51 +08:00
KIU Shueng Chuan 31f9d0024a simplify modelview projection computation
1) no need to get rect(), which is actually defined as
	QRect(0, 0, width(), height())
2) use col-maj data() instead of row-maj copyDataTo()
   - glLoadMatrixf() takes col-maj
2021-07-17 07:56:21 +08:00
Martin Chase bcb629495c put new location in deprecation warning 2021-07-16 15:59:23 -07:00
Ogi Moore d28e1c8075
Merge pull request #1895 from j9ac9k/update-contributing-guide
Update contributing guide ahead of scipy sprints
2021-07-15 21:01:07 -07:00
Ogi Moore b79171dc3a Update contributing guide ahead of scipy sprints 2021-07-15 20:42:32 -07:00
Ogi Moore 910142aa6f
Merge pull request #1897 from pijyoi/fix_win32_plotcurveitem_opengl
PlotCurveItem: setup modelview and projection
2021-07-15 19:48:20 -07:00
KIU Shueng Chuan 7442ab1e52 PlotCurveItem: setup modelview and projection 2021-07-15 23:16:26 +08:00
Ogi Moore b9e079b10c
Merge pull request #1889 from swt2c/gltextitem_py310
Fix GLTextItem with Python 3.10
2021-07-12 09:57:01 -07:00
Scott Talbert db8180d88e Fix GLTextItem with Python 3.10
drawText() expects int arguments and Python 3.10 does not allow for
implicit rounding.
2021-07-11 22:04:00 -04:00
Ogi Moore 1ce9da36d3
Merge pull request #1891 from ixjlyons/readme-redundant-optional-deps 2021-07-11 13:14:59 -07:00
Kenneth Lyons bb94290d8e Clean up redundancy in README 2021-07-11 09:57:09 -07:00
KIU Shueng Chuan e17428b018 fix GLVolumeItem example for arm64 2021-07-09 21:12:58 +08:00
Ogi Moore 6b4385ce0d
Merge pull request #1885 from jennifer-manriquez/issue
Raise TypeError instead of Exception
2021-07-08 14:50:48 -07:00
Jennifer Manriquez 0c074ea005 Raise TypeError instead of Exception 2021-07-08 13:35:22 -05:00
Kyle Sunden fda6071ae5
Merge pull request #1884 from pyqtgraph/ksunden-patch-1
Update version number
2021-07-08 02:33:07 -05:00
Kyle Sunden 53fc415813
Update version number 2021-07-08 01:18:00 -05:00
Kyle Sunden 49a97351e7
Merge pull request #1838 from j9ac9k/prep-for-release
Prep for 0.12.2 release
2021-07-08 01:16:25 -05:00
Ogi Moore 0c38ff2754 Add one more PR to the changelog 2021-07-07 22:47:49 -07:00
Kyle Sunden 89958dbaab
Merge branch 'master' into prep-for-release 2021-07-08 00:38:57 -05:00
Kyle Sunden e12ac50a05
Merge pull request #1870 from edumur/master
Update README
2021-07-08 00:35:56 -05:00
Etienne Dumur 804f6b6649 Clarify markdown 2021-07-05 21:46:40 +02:00
Ogi Moore d82a47b864 First go of a changelog for 0.12.2 2021-07-03 22:04:14 -07:00
Nils Nemitz 523b31e97f
Draw GradientLegend in ViewBox coordinates (#1864)
* draw GradientLegend in ViewBox coordinates

* some cleanup

* do not proceed with dummy values

* correct bar and label order, add some styling options

* remove debugging code
2021-07-03 21:43:39 -07:00
Ogi Moore 4b7dfdef88
Merge pull request #1876 from ixjlyons/fix-lineroi-coords
Fix LineROI handle positions
2021-07-03 08:23:13 -07:00
Ogi Moore e83b91e9af
Merge pull request #1871 from pijyoi/opengl_init
Allow adding items to GLViewWidget before show
2021-07-03 08:10:35 -07:00
ntjess 820c1604dd
Set focus to the example filter + Ctrl+F listener for focus (#1873)
* Set focus to the example filter + Ctrl+F listener for focus

* Early return on detecting "F"
2021-07-03 07:58:51 -07:00
Kenneth Lyons 7ebae20c5d Fix LineROI handle positions 2021-07-03 07:51:23 -07:00
KIU Shueng Chuan e9ee11f010 simplify calls needed to initialize items 2021-07-03 15:53:17 +08:00
Ogi Moore 02909999dc
Merge pull request #1875 from pijyoi/fix_pyqt6_mouse_event
bug: PyQt6 does not have localPos()
2021-07-02 13:26:19 -07:00
KIU Shueng Chuan 6fc02711a8 bug: PyQt6 does not have localPos()
this bug must have existed since the removal of the mouse shims
from Qt.py.
2021-07-02 10:14:19 +08:00
KIU Shueng Chuan e76328ab0e bug: PyQt6 does not have localPos()
this bug must have existed since the removal of the mouse shims
from Qt.py.
2021-07-01 15:11:55 +08:00
KIU Shueng Chuan f9f5d46589 missing import of pg
CI passed because of the way the example gets invoked.
2021-07-01 08:56:47 +08:00
KIU Shueng Chuan 96f7ce1325 remove empty initializeGL() 2021-07-01 08:56:47 +08:00
KIU Shueng Chuan b843214f66 remove Qt4 mouse wheel handling 2021-07-01 08:56:47 +08:00
KIU Shueng Chuan 1a29cf7579 defer init if we do not have an OpenGL context yet 2021-07-01 08:56:33 +08:00
Etienne Dumur f5563501ed Modify optional libraries style 2021-06-30 09:02:24 +02:00
Etienne Dumur da39e8f460 Iterative improvement of the README file
Replace "pyqtgraph" by "PyQtGraph".
Replace the optional libraries list by an "Optional added functionalities" section.
More precise on the role of each optional library.
Add numba in optional library.
2021-06-29 11:26:51 +02:00
Etienne Dumur 08e460ad34 Update README
Add matplotlib as optional library.
Replace hdf5 by h5py.
Add links towards the github page or website of the different linraries.
2021-06-28 09:24:55 +02:00
ntjess 4a921ddf71
Filter examples (#1868)
* Allows filtering of examples

* For some reason, the ui designer ignored the courier font family so I manually inserted it into the .ui file

* Allows filtering by file content, too

* Respects dark mode (maybe?), fixes policy setting on code layout

* Prevents "run edited code" from showing unless the actual content changes

* Looks like black font is always best against highlight background

* Left test code in commit...

* Fix broken highlighting on PyQt6

* Address #133

* Better highlighting for both dark and light mode

* Minor refactoring/cleanup, uses combo box instead of checkbox

* Combo box below text edit to avoid clipping

Co-authored-by: njessurun <ntjessu@gmail.com>
2021-06-26 17:51:34 -07:00
Nils Nemitz e79dacf805
Fix Matplotlib color map import, add CC0 maps locally (#1865)
* accept Matplotlib colormap data as numpy array, add CC0 Matplotlib maps locally

* add cividis, prioritize lower case in example/atlas
2021-06-26 08:41:57 -07:00
Ogi Moore 5e8f200aa0
Merge pull request #1869 from NilsNemitz/colorbaritem_ticks
Disable unused ColorBarItem ticks
2021-06-26 08:06:37 -07:00
Nils Nemitz c07b95812c clear out ticks instead of hiding them 2021-06-26 20:42:11 +09:00
Ogi Moore 93fa8664cb
Merge pull request #1846 from pijyoi/import_hygiene
reduce pollution of pg namespace
2021-06-25 23:26:26 -07:00
KIU Shueng Chuan 5d55f3facf remove imports subdir 2021-06-26 07:54:03 +08:00
Ogi Moore 82da8f122e
Merge pull request #1867 from j9ac9k/fix-numpy-deprecation
Use built-in int as dtype
2021-06-25 09:15:44 -07:00
Ogi Moore 418a181691 Use built-in int as dtype 2021-06-25 08:45:02 -07:00
KIU Shueng Chuan 3a1b74df6f move Qt.py to Qt/__init__.py 2021-06-25 21:33:05 +08:00
KIU Shueng Chuan 11bf824c0a deprecate ordereddict.OrderedDict on instantiation 2021-06-25 21:19:34 +08:00
KIU Shueng Chuan 427128ece1 add imports used by ACQ4 2021-06-25 21:19:34 +08:00
KIU Shueng Chuan 81baa182c5 add __all__ to various files 2021-06-25 21:19:33 +08:00
Ogi Moore 3fbb4f6b02
Merge pull request #1862 from j9ac9k/deprecate-metaarray
Deprecate MetaArray Entirely (for 0.14 release)
2021-06-24 10:46:14 -07:00
Ogi Moore 27ad41a10c Add deprecation warning to MetaArray.__init__ 2021-06-23 21:27:21 -07:00
Martin Chase f764e2d3ff
progress dialog fix (#1861) 2021-06-23 19:34:55 -07:00
Nils Nemitz 775f1d629c
Separate out mouse events stolen by AxisItem (#1845)
* separate out mouse events on main plot area

* work in scenepositions so that detection also works in a layout

* added comments/remove debug statements
2021-06-22 16:17:39 -07:00
Ogi Moore addb92f592
Merge pull request #1853 from NilsNemitz/getColor-getStops
make getColors and getStops behavior more consistent; add tests
2021-06-22 11:50:34 -07:00
Ogi Moore 98e9ea9b79
Merge pull request #1860 from pijyoi/remote_venv
remote: exchange pids if running in Windows venv
2021-06-22 11:28:18 -07:00
KIU Shueng Chuan 30f4af5913 remote: exchange pids if running in Windows venv 2021-06-22 21:59:39 +08:00
Nils Nemitz 362fbaa53a fixed docstring 2021-06-22 03:32:12 +09:00
Nils Nemitz f79d0dfa14 make getColors and getStops behavior more consistent; add tests 2021-06-22 01:19:07 +09:00
Ogi Moore ba517aba0e
Merge pull request #1840 from jennifer-manriquez/master
Allow border=False in GraphicsLayout
2021-06-16 20:17:35 -07:00
Jennifer Manriquez 2899143e84 Allow border=False in GraphicsLayout 2021-06-16 19:35:42 -05:00
Ogi Moore 663bb75da4 add numba optional dependency to README.md 2021-06-15 22:43:53 -07:00
Ogi Moore 30bc13831d
Merge pull request #1837 from pyqtgraph/revert-1835-skip_monkey
Revert "skip pytest monkeypatch"
2021-06-15 20:45:49 -07:00
Ogi Moore ee602ac243
Revert "skip pytest monkeypatch" 2021-06-15 20:28:08 -07:00
Ogi Moore 61dedcb4a5
Merge pull request #1794 from pijyoi/numba_lookup 2021-06-15 16:42:54 -07:00
KIU Shueng Chuan 5dcea9bdac rename private function and its arguments 2021-06-16 06:50:51 +08:00
Ogi Moore c376c6fdcc
Merge pull request #1829 from pijyoi/pixmap_fragments
try using QPainter.drawPixmapFragments
2021-06-15 10:06:50 -07:00
KIU Shueng Chuan f63d1e4206 document PyQt boxing and unboxing 2021-06-15 11:40:27 +08:00
KIU Shueng Chuan 7c6d9fe6d5 cleanup python2 and unused imports 2021-06-15 11:06:37 +08:00
Ogi Moore fff2bc82c8
Merge pull request #1835 from pijyoi/skip_monkey
skip pytest monkeypatch
2021-06-14 19:58:30 -07:00
KIU Shueng Chuan 89f6c7da81 remove codepaths other than pixmap fragments codepath 2021-06-15 09:43:31 +08:00
KIU Shueng Chuan abeae0b7fa init so that pointers are present 2021-06-15 06:50:31 +08:00
KIU Shueng Chuan 6bfb516768 skip pytest monkeypatch 2021-06-14 21:06:19 +08:00
KIU Shueng Chuan a1845cddbc don't truncate floating point target coords 2021-06-14 19:24:39 +08:00
KIU Shueng Chuan 6839ec937a reuse pixmap fragment objects 2021-06-14 06:49:52 +08:00
KIU Shueng Chuan ad3e3a6b8b ScatterPlotSpeedTest: add toggle for drawPixmapFragments 2021-06-13 08:00:45 +08:00
KIU Shueng Chuan 380ec2e0b2 implement usage of QPainter.drawPixmapFragments 2021-06-13 08:00:45 +08:00
Ogi Moore cb4af3ac97
Merge pull request #1833 from pijyoi/fix_pyqt61_scatterplot
fix ScatterPlot render issues on PyQt6 6.1
2021-06-12 08:36:01 -07:00
KIU Shueng Chuan 98a020d1bb ROI.py::renderShapeMask : fix little-endian assumption 2021-06-12 20:25:28 +08:00
KIU Shueng Chuan afe47def28 fix ScatterPlot render issues on PyQt6 6.1 2021-06-12 14:05:47 +08:00
Ogi Moore e2b0a5ffae
Merge pull request #1830 from j9ac9k/Address-missing-enums
Add missing enums
2021-06-11 08:46:20 -07:00
Ogi Moore e892ad37aa Add missing enums 2021-06-10 21:28:19 -07:00
Ogi Moore 7e8d34ecd8
Merge pull request #1824 from pijyoi/less_endian
remove little-endian assumption for image export
2021-06-09 15:02:48 -07:00
Martin Chase 2fb04b754c
Fix BusyCursor to use internal stack provided by setOverrideCursor/restoreOverrideCursor (#1827)
* un-busy as many times as needed

* lint

* add test to prove cursor behavior

* tentative change in the hopes that all supported qt versions behave properly

* remove unnecessary code

* use contextmanager decorator instead of class

* use full path to WaitCursor

* restore docstring; refactor variable for clarity

* fix docstring whitespace

* break up long lines

* use variable to shorten instead
2021-06-09 13:32:24 -07:00
KIU Shueng Chuan 6a2bfa5c84 fix PyQt6 long spelling for enums 2021-06-10 03:33:04 +08:00
KIU Shueng Chuan b3e8f332fb add test for export to qimage 2021-06-10 03:18:12 +08:00
KIU Shueng Chuan 765f9648cd remove little-endian assumption for image export 2021-06-10 03:18:12 +08:00
Ogi Moore 6f0ffcbf8f
Merge pull request #1818 from j9ac9k/convert-enums
Convert Qt Enums to Qt6 Namespace
2021-06-08 21:57:45 -07:00
Ogi Moore d974544053 Split up Execution of examples and tests in CI
There seems to be some unintentional side effect when running examples and the
same time.  This change breaks up the execution into two separate calls to
pytest in an attempt to bypass whatever issue is being created.
2021-06-08 21:23:49 -07:00
Ogi Moore f225724f26 Close instead of clear test_scatterplotitm 2021-06-08 21:23:49 -07:00
Ogi Moore 3c352dd1a9 Fix documentation misalignment 2021-06-08 21:23:49 -07:00
Ogi Moore 2f1f297f39 Fix case of int-conversion for MouseButtons
This has been demonstrated to not work in PyQt6.
2021-06-08 21:23:49 -07:00
Ogi Moore cc081af528 New Template Files for PyQt6 6.1
Update PySide6 templates to Qt 6.1
2021-06-08 21:23:49 -07:00
Ogi Moore 195a1a6fa3 Remove Qt 6.0 support
Simplify some PyQt6 code branches
2021-06-08 21:23:49 -07:00
Ogi Moore d455da9aec Use Qt6 Enum Namespace
This namespace appears to be valid in PySide2/PyQt5 5.12+ so we may as
well migrate to the newer namespace ourselves.
2021-06-08 21:23:49 -07:00
Ogi Moore 29bdf9949e Skip GLTextIem on some conditions on macOS 2021-06-08 21:11:24 -07:00
Nils Nemitz 7d41e8a878
Color map linearization (#1797)
* extended color map functions

* assertion string, documentation pass, comment purge

* fix some documentation links

* simplify assert statement

* removed comments and redundancy, renamed modulated bar

* include modulatedBarData in documentation

* test running matplotlib with dummy backend

* skip color maps example on OSX/PySide6.1.1

* removed skipping of tests

* reverted some accidental whitespace, removed unneeded numpy import

* removed unneded alpha parameter
2021-06-08 20:41:46 -07:00
Nils Nemitz f002d70adc
Expose number of subsamples in ImageItem auto-level determination (#1638)
* exposed number of subsamples in auto-level determination

* Removing print statement at @NilsNemitz's request

* make levelSamples count pixels, not pixels * channels

* minimum number of samples can be 2 if we look at pixels anyway

* adjusted minimum levelSamples to 4: Otherwise a 2x2 image downsamples to a single pixel

* extended docstring for level to make the user aware of auto-level subsampling

* subsample towards square array for auto-leveling

* eliminated duplicated code between level downsampling and samples and QuickMinMax method

Co-authored-by: Ogi Moore <ognyan.moore@gmail.com>
2021-06-08 10:25:47 -07:00
Ogi Moore 823988d51c
Merge pull request #1821 from pijyoi/case_sensitive_exception 2021-06-08 05:39:35 -07:00
KIU Shueng Chuan 1715d5a6fa error on presence of "Exception:" and "Error:" 2021-06-08 15:13:17 +08:00
Nils Nemitz 61f067bf7c
Add axis convenience methods and matrix display example (#1726)
* add axis convenient methods and matrix display example

* wrestled wayward space back into docstring

* color map names are case sensitive on Linux

* docstring fix for PlotItem

* protect AxisItem.linkToView from being obscured by DateAxisItem override

* replaced setOrigin method by promoted setPos and setScale

* made tri-state axes switching explicit

* reverted setRect behavior, documentation pass for ImageItem

* minor text adjustment

* implmented some suggested revisions

* fix input parsing for setRect and add tests so that I don't break it again

* don't try to re-add transform after clearing it

* changed example and doc image generators to pg.exec()

* removed commented-out code

* cleaned up transform eqaulity assertion

* restored devoured comment

* restored devoured comment
2021-06-07 07:44:19 -07:00
Ogi Moore 3a3d05b16f
Merge pull request #1817 from pijyoi/split_finite
implement QPolygonF codepath for connect="finite"
2021-06-06 21:55:51 -07:00
bsobhani d863907163
add function to disable autoscaling (#1819) 2021-06-06 21:19:23 -07:00
shikishima-TasakiLab f13002b251
Add "GLTextItem" (#1776)
* Add GLTextItem

* Fixed DocString.

* Delete unnecessary function.

* Add `from .items.GLTextItem import *`

* Add an example.

* [Combines two `isinstance()` into one.](https://github.com/pyqtgraph/pyqtgraph/pull/1776#discussion_r633046120)

* [Combines two `isinstance()` into one.](https://github.com/pyqtgraph/pyqtgraph/pull/1776#discussion_r633046120)

* [The long code has been broken up into separate lines.](https://github.com/pyqtgraph/pyqtgraph/pull/1776#discussion_r633046234)

* [Moved `pos`, `color`, `text`, and `font` to the `__init__` method.](https://github.com/pyqtgraph/pyqtgraph/pull/1776#discussion_r633047216)

* Add `import initExample` and fix `mkQApp().exec_()` to `pg.exec()` (https://github.com/pyqtgraph/pyqtgraph/pull/1776#discussion_r633046878, https://github.com/pyqtgraph/pyqtgraph/pull/1776#discussion_r633046781)

* Fix `pg.exec()` to `pg.mkQApp().exec()`

* Revert "Fix `pg.exec()` to `pg.mkQApp().exec()`"

This reverts commit 67d397d803.

* Remove type-hints.

* Fix `glColor4d(float(self.color[0]), float(self.color[1]), float(self.color[2]), float(self.color[3]))` to `glColor4d(*self.color)`

* Add `value = fn.glColor(value)`

* Remove debug print.

* Add GLGridItem and GLAxisItem

* Remove if-check for "color" argument

* Draw text without using GLUT.

* Divide the text position by the device pixel ratio

* Fixed bare exceptions to ValueError and TypeError.

* Add 'GLTextItem.py' to utils.py.

* Fixed a bare exception to ArgumentErrror.

* Add `__all__ = ['GLTextItem']`
2021-06-05 08:19:54 -07:00
KIU Shueng Chuan ecc3563f6d special-case all-finite 2021-06-05 20:13:07 +08:00
KIU Shueng Chuan 8997cfa07c test the QPolygonF codepath 2021-06-05 15:09:59 +08:00
KIU Shueng Chuan c8e6920443 use multiple polygons for "finite" 2021-06-05 15:09:59 +08:00
Ogi Moore e206ea5ae9
Merge pull request #1796 from j9ac9k/test-polyline
If arrayToQPath uses connect=all, use a different construction for QPainterPath
2021-06-04 21:33:45 -07:00
Ogi Moore 145ab2e9e3 Merge branch 'master' into test-polyline 2021-06-04 21:06:52 -07:00
Ogi Moore 5c54577c26
Merge pull request #1807 from j9ac9k/merge-test-data
Merge test data + make tests directory which contain tests
2021-06-04 21:06:11 -07:00
Ogi Moore 55e42aabfd make numpy style docstring of arrayToQPath
The function had many comments/explanations, decided to convert to
numpy docstring style, which is the direction pyqtgraph is going in
as it stands
2021-06-03 22:53:09 -07:00
Ogi Moore 649757eb31 Remove use of QPolygonF in non-finite cases
With some experimentation, it was determined that when the QPainterPath
is drawn with a QPen that has a thickness greater than 1, the end result
is quite broken.  Due to us trying to exploit non-advertised behavior
we are removing this optimization step.
2021-06-03 22:53:09 -07:00
Ogi Moore 31b4210f4e
Merge branch 'master' into merge-test-data 2021-06-02 22:15:46 -07:00
Ogi Moore bd11e5e401
Merge pull request #1816 from ntjess/rich-param-cmp
Fix #1814
2021-06-02 09:19:28 -07:00
njessurun c0ebf8a432 Fix #1814 2021-06-02 11:03:22 -04:00
Ogi Moore c0b9f3e26e
Merge pull request #1795 from pijyoi/avoid_writable_qimage
don't rely on QImage-wrapped buffer being writable
2021-06-01 23:05:01 -07:00
Ogi Moore 45cf6fa232 Remove comment about QImage data references
Comment was out of date and no longer relevant, removing at @pijyoi's
suggestion.
2021-06-01 22:50:02 -07:00
Nils Nemitz 39f705fd7f
Sanitize input for plotItem.showGrid (was documentation fix for plotItem.showGrid alpha setting) (#1809)
* documentation fix for plotItem.showGrid alpha setting

* revert to 0-1 scale
2021-06-01 22:43:58 -07:00
Ogi Moore 0da1958ff1
Merge pull request #1768 from pijyoi/rgb32_alpha_chan
Format_RGB32 will always have alpha equal 255
2021-06-01 22:25:08 -07:00
3DAlgoLab 28b1499f09
Force cameraPosition() to return Vector class. (#1799)
* Update GLViewWidget.py

Fix the wrong conversion of QVector3D to numpy array.

* new way to fix the conversion error

* Recover prev. version of pixelSize

Co-authored-by: Jaeyoon Jeong <diem389@gmail.com>
2021-06-01 22:21:50 -07:00
Ogi Moore 4264219144 Add PyQt6 version check for QByteArray creation 2021-06-01 22:01:58 -07:00
Ogi Moore f01f3d473f Have debug.printExc emits RuntimeWarning
Several bugs have snuck through due to being wrapped with printExc,
which would prevent the exception from raising, but printing the trace
to the console.  In pytest, this output is not captured at all, and is
invisible unless the -s parameter is added.

This PR changes the print statement to a runtime warning, which pytest
will capture.
2021-05-31 21:06:16 -07:00
Ogi Moore c7675ca8bb Fix unraisable exception in test_examples
The way we called subprocess.Popen, it looks like we didn't close all
the pipes; this PR addresses the warning that pytest generates when
running the examples.

In addition, we toggle the pytest setting to error on any warning
2021-05-31 21:06:16 -07:00
Ogi Moore d72be799d7 Catch and Address Warnings in test_svg and pytest.ini
On Windows, pyreadline is emitting a deprecation warning we can ignore.
Furthermore, test_svg was using NamedTemporaryFile in a manner that was
causing permission denied errors, so this commit switches to the use of
pytest friendly temporary files
2021-05-31 21:06:16 -07:00
Ogi Moore d859cec95a Replace uses of tempfile.mktemp with tempfile.NamedTemporaryFile
This issue was flagged as a security issue in the static code analyzer
2021-05-31 21:06:16 -07:00
Ogi Moore ceeacf4e5f Remove test_exit_crash.py
This file contains two tests, one of which has been skipped forever,
and the second (test_pg_exit) has been a flakey test that does not test
in general, testing a use-case we likely do not see any more.  So
therefore I am removing this test from the library.
2021-05-31 21:06:16 -07:00
Ogi Moore ab792a73a6 Address in-tree-build deprecation issue in pip 2021-05-31 21:06:16 -07:00
Ogi Moore 4224fe5664 Avoid permissions issues on windows CI 2021-05-31 21:06:16 -07:00
Ogi Moore 1d55fde41a Suppress non-relevant deprecation warning 2021-05-31 21:06:16 -07:00
Ogi Moore d519630d14 Fix check for equality between floats
While this fix prevents an assertion error, the assertion error was
being suppressed; and was only noticeable via pytest -s where the error
was printed to console.  Future work should be done to minimize the use
of bare exceptions so these tests do not fail silently
2021-05-31 21:06:16 -07:00
Ogi Moore 648b8c7df4 Fix issue with int comparson impacting Qt6 2021-05-31 21:06:16 -07:00
Ogi Moore ee951331be Close the example app after it launches 2021-05-31 21:06:16 -07:00
Ogi Moore e7a30b9324 Clean up test files
Remove if __name__ == "__main__" bits, replace some == None to is None
checks

Cleanup variety of static code checker issue

Removed missing imports, restructured some logic to make a little
cleaner, fixed a function in test_dockarea, unfortunately broke the test
so now I tell pytest to expect the Exception.
2021-05-31 21:06:16 -07:00
Ogi Moore 0160de22fb Remove QApplication.instance() deleteLater call
the test_signalproxy.py had a fixture for the QApplication instance,
only problem is at the end of each use of the fixture, it would mark
the application instance for deletion, which is most definitely not what
we want
2021-05-31 21:06:16 -07:00
Ogi Moore a6971c768d Move and Update test-data repo into pyqtgraph repo
To reduce complexity, and make it easier to add more images and tests,
the images in the `test-data` repository should be merged with the main
repository.  Furthermore, we can remove a lot of the subprocess work in
the image_testing.py file, as we no longer need to have it interact with
git.

The images are not the same.  Images were regenerated with Qt6, and now
have proper big and little endian handling thanks to @pijyoi

Second commit is a slightly modified variant of
2e135ab282d6007b34a3854921be54d0e9efb241 authored by @pijyoi
it is to convert qimages to RGBA8888 for testing.  Image
files were regenerated images for the big/little handling

Fixed issue with bogus test from test_NonUniformImage and generated a
new image
2021-05-31 21:05:00 -07:00
KIU Shueng Chuan cabcf6cd29 pairs: allocate and manipulate dest polygon buffer directly 2021-05-27 23:31:05 -07:00
KIU Shueng Chuan 8f4104a9ab use qpolygonf underlying buffer as backstore 2021-05-27 19:07:50 -07:00
Ogi Moore 270fc59cab Insert NaN values for connect='pairs' in Qt6
Since the QPainterPath.addPolygon(QPolygonF) does not filter out the NaN
values, we can insert NaN values to create discontinuities in the Lines,
and thus supporting connect='pairs' functionality
2021-05-27 09:38:23 -07:00
Ogi Moore 78e678c1b9 Support connect=finite for qt6 2021-05-27 09:37:23 -07:00
Luke Campagnola e29f86578f
Revert Point.angle behavior change (#1806)
* Revert behavior change of Point.angle

* Propagate Point.angle revert
2021-05-27 08:51:06 -07:00
Martin Chase 1735effea7
fix click bug on removable ROIs; test (#1804) 2021-05-26 17:14:08 -07:00
Ogi Moore 62165bbe45 Revert "Speed up arrayToQPath when connect='pairs'"
This reverts commit d62d3b182f.

Through testing, this was shown to perform quite poorly.
2021-05-25 23:30:06 -07:00
Ogi Moore c6f1d2df94 Cleanup old code, conform comments to pep8 2021-05-25 22:32:26 -07:00
Ogi Moore 07ba7be2a4 Add basic tests for arrayToQPath 2021-05-25 22:32:26 -07:00
Ogi Moore d62d3b182f Speed up arrayToQPath when connect='pairs'
As discussed earlier, the process of QDataStream >> QPainterPath is
quite slow, so this commit makes an improvement on QPainterPath creation
for the case of connect='pairs' by using a naive method of moving the
path and drawing a line on the path.  This was the fastest method
identified during testing.
2021-05-25 21:58:58 -07:00
Ogi Moore aaae0b9e1c Have MultiPlotSpeedTest use skipFiniteCheck 2021-05-25 21:58:58 -07:00
Ogi Moore 7860d641ab Perform finiteCheck on PlotCurveItem.setData
The check for NaN values in arrayToQPath is expensive, this change
attempts to do the check one time, and if no NaN values are present,
an optional flag is passed along telling arrayToQPath that the check
can be skipped
2021-05-25 21:58:58 -07:00
Ogi Moore f08d239578 Use QPolygonF for connect='all'
Since QDataStream >> QPainterPath is an expensive operation, we can
construct our QPainterPath from an open polygon instead but only if the
connect='all' mode is present.  Future optimizations work can likely
be had with constructing a polygon from each connected segment
2021-05-25 21:58:58 -07:00
KIU Shueng Chuan d220e8a6e9 Restructuring of QPainterPath ByteArray 2021-05-25 21:36:27 -07:00
Ogi Moore 7bc5f215c0
Merge pull request #1802 from fbordignon/cx_freeze_example
update cx_freeze example and add a workaround for templates
2021-05-24 14:13:07 -07:00
Fernando Bordignon a4de137535 update cx_freeze example and add a workaround for templates 2021-05-24 17:50:24 -03:00
Ogi Moore ed1653f3c5
Merge pull request #1800 from wubella/master
Fixing GLMeshItem memory leak in face drawing on 64-bit Linux (#1783)
2021-05-23 21:22:31 -07:00
Wyatt Ubellacker 7e5c90a7a4 Fixing GLMeshItem memory leak in face drawing on 64-bit Linux (#1783) 2021-05-23 18:31:49 -07:00
KIU Shueng Chuan 7499c3b375 clip values can be derived from lut shape
also makes it clear that indices won't be out of range
2021-05-22 11:34:20 +08:00
KIU Shueng Chuan 9426ef0391 don't rely on QImage-wrapped buffer being writable 2021-05-22 09:10:03 +08:00
KIU Shueng Chuan 03ddf92839 implement numba lookup 2021-05-22 08:23:47 +08:00
Martin Chase ac84f45787
callable luts still need to be put onto a substrate (#1791) 2021-05-20 07:22:49 -07:00
Kenneth Lyons bcb6a5d66a
Merge pull request #1779 from manschloemark/master
Use fallback minStep in dec mode SpinBox (Issue 1756)
2021-05-19 18:15:10 -07:00
Martin Chase a91953e93d
Bypass makeARGB in some cases (#1786)
* refactor out _ndarray_to_qimage()

* combine levels back with lut

* make use of Grayscale8, RGB888 and Indexed8 QImage formats

Grayscale8 and RGB888 images are those that are ready for display
without further processing.

* add Grayscale16

* apply the efflut early for uint16 mono/rgb, uint8 rgb

* ndarray indexing is faster than np.take

* handle uint16 rgb(a) with no levels same as levels=[0, 65535]

* add support for Format_RGBA64

* fix: support colormaps of shape (h, 1)

* check ImageItem uint8 and uint16 QImage formats

* uint16 mono with rgb lut -> RGBX8888

* got width and height swapped in array dimensions

* set ImageItem as row-major

* no need to form a 1d 32-bit lut for array indexing

you can index (y, x) into a lookup table of shape (nentry, 3) or
(nentry, 4) and get an output of shape (y, x, 3) or (y, x, 4)

* Revert "no need to form a 1d 32-bit lut for array indexing"

This reverts commit 45cf3100de.

* distinguish between levels_lut and colors_lut

this allows uint16 images with user lut to be rendered as
Format_Indexed8

* uint8 (1-chan) images should always combine to efflut

this efflut will then be used for Indexed8 format color table.

previously, we would be taking a performance hit with doing a numpy
lookup with levels_lut.

* adapt benchmarks/makeARGB.py to renderImageItem.py

* restructure uint8 and uint16 codepaths

* normalize 1-chan images to ndim==2 earlier up

* refactor long code into functions

* bug: qimage may not be assigned

* fix: assign to self.qimage only if not None

* for uint16, do rescale rather than do levels_lut lookup

* cases 2,3 are already handled

i.e. no more using lut to do rescale of uint16 image data.

* rescale rgb images by computation, not by memory lookup

* setImage() does not take an output argument

* try to be cupy compatible

use "xp" instead of numpy module

* add numba to benchmarking

* fix: lut_big is dtype uint8 with more than 256 entries

* bug: applying colors_lut needs C-order

* support float with no nans

* fix: variable could be uninitialized

* add float32 format tests

* avoid explicitly forcing to C-contiguous

* cache effective lut only if combination took place

every one of the four branches now does its own return.
this makes it easier to follow.

* fix cupy benchmark : typo in renderQImage

* remove for loop of 1 iteration

* use float32 for floating point benchmark

* superceded by renderImageItem.py

* lint

* benchmark without lut conversion

* put the lut onto the substrate

* fix editor complaints

* handle lack of cupy

* leading underscores imply privacy

Co-authored-by: KIU Shueng Chuan <nixchuan@gmail.com>
2021-05-19 17:21:12 -07:00
Mark Schloeman 1c1212e5e9 Set minStep in dec stepping SpinBox example 2021-05-16 17:37:33 -04:00
Mark Schloeman c9ea25eed6 SpinBox in dec mode sets minStep to step as fallback 2021-05-16 17:37:33 -04:00
Ogi Moore 9566e2ba36
Merge pull request #1778 from j9ac9k/fix-glvolumeitem-example
Do not attempt to avoid np.log(0), instead ignore the warning in GLVolumeItem Example
2021-05-16 10:38:07 -07:00
Ogi Moore 9624b2a049 Do not attempt to avoid np.log(0), instead ignore the warning
Fixes #1775, also took the opportunity to clean the file a bit.
2021-05-16 10:18:23 -07:00
Ogi Moore d3e0d041de
Merge pull request #1774 from pijyoi/pg_exec
implement pg.exec()
2021-05-15 22:42:59 -07:00
Martin Chase 253055003b
Add a Code of Conduct (#1773)
* Code of Conduct adapted from PuPPy and matplotlib

* improve wording; transparency in moderation; fix link
2021-05-13 15:37:07 -07:00
KIU Shueng Chuan dfddb39ce0 Revert "add QApplication.exec() to Qt5 bindings"
This reverts commit 2dad9862cb.
2021-05-14 06:16:21 +08:00
KIU Shueng Chuan 0fb0209e43 Revert "provide QApplication.exec() for PySide6 6.0"
This reverts commit 3eb69e6d9b.
2021-05-14 06:16:21 +08:00
KIU Shueng Chuan 0754602c3c fix in-library uses of exec_() 2021-05-14 06:16:21 +08:00
KIU Shueng Chuan 21296cd4f3 change all examples to use pg.exec() 2021-05-14 06:16:21 +08:00
KIU Shueng Chuan 61badc88b3 implement pg.exec() 2021-05-14 06:16:21 +08:00
Ogi Moore 1905f83047
Merge pull request #1772 from pijyoi/fix_remote
don't print out expected Exception
2021-05-13 12:22:00 -07:00
KIU Shueng Chuan 381147450d pass through any AttributeError 2021-05-13 14:43:28 +08:00
KIU Shueng Chuan 210203d628 don't print out expected Exception 2021-05-13 13:58:06 +08:00
Ogi Moore eed220e874
Merge pull request #1771 from pijyoi/fix_pyside6.1
some fixes PySide6 6.1.0
2021-05-12 21:51:01 -07:00
KIU Shueng Chuan 3eb69e6d9b provide QApplication.exec() for PySide6 6.0 2021-05-13 09:48:47 +08:00
KIU Shueng Chuan 2dad9862cb add QApplication.exec() to Qt5 bindings 2021-05-13 09:02:42 +08:00
KIU Shueng Chuan 3b32e27083 RemoteGraphicsView.py : fix deprecated mouse positions 2021-05-13 08:57:15 +08:00
KIU Shueng Chuan 70c123a95c fix localPos() deprecated warnings 2021-05-13 08:42:45 +08:00
KIU Shueng Chuan 60661f586f fix: QVector3D has no copy constructor 2021-05-13 08:23:06 +08:00
Ogi Moore 96e83b7d43
Merge pull request #1766 from pijyoi/vst_numba_toggle
VideoSpeedTest.py : Add numba checkbox
2021-05-07 08:40:03 -07:00
KIU Shueng Chuan 0503f96121 Format_RGB32 will always have alpha equal 255
this also fixes the assumption that we are on little-endian.

In [18]: qimg = QtGui.QImage(1, 1, QtGui.QImage.Format.Format_RGB32)

In [19]: qimg.fill(QtCore.Qt.GlobalColor.transparent)

In [20]: np.frombuffer(qimg.bits(), dtype=np.uint8)
Out[20]: array([  0,   0,   0, 255], dtype=uint8)
2021-05-07 18:09:02 +08:00
KIU Shueng Chuan 09ce81655d VideoSpeedTest.py : Add numba checkbox 2021-05-07 15:35:27 +08:00
Nils Nemitz bfc63bb730
Make plotting with gradients more fun (#1742)
* added convenience functions to better handle plotting with gradients

* docstring correction, example name correction

* retrying to get  documentation format right

* another attempt at cleaning up docs

* Don't hardcode timer type (and docs fixing attempt)

* more docstring re-formatting

* linebreaks in docstrings

* more documentation adjustments

* documentation pass

* some corrections to documentation

* more adjustments to documentation

* again?

* removed some whitespace and redundant blank lines, changed some checks '== None' to 'is None'

* fixed mis-spelling QColor as Qcolor
2021-05-06 23:20:21 -07:00
Martin Chase 2fb7cdafbd
more complete test yields more complete behavior (#1765) 2021-05-05 18:07:34 -07:00
Martin Chase fa1be1e5bf
show and hide properly for maxTraces; +test (#1764) 2021-05-05 17:08:04 -07:00
Kenneth Lyons cafe079910
Support horizontal HistogramLUT{Item,Widget} (#1757)
* Improve HistogramLUTItem docs, a few cosmetic changes

* Initial implementation of horizontally-oriented HistogramLUTItem

- Also adds support in HistogramLUTWidget
- Fixes AxisItem orientation bug for vertical orientation
- Make use of GradientEditorItem orientation (fixes another bug for
  vertical orientation)
- Use horizontal orientation in an example for demonstration

* Remove unused HistogramLUTItem option

* A few more minor fixups

* Copy paste bug

* Use f-strings

* Update from review and a couple more minor updates

* Woops

* Add doc for orientation arg

* Add top/bottom orientation to doc. Expand on levelMode doc a bit
2021-05-04 21:25:42 -07:00
Ogi Moore 7dd033c03b
Merge pull request #1759 from alimustafashah/master
#1758 Fixed typo in InfiniteLine (sigclicked vs. sigClicked)
2021-05-03 20:31:51 -07:00
shahmustafa54 e1b1410260 Fixed typo in InfiniteLine (sigclicked vs. sigClicked) 2021-05-04 06:03:17 +05:00
Ogi Moore cf70cf4395
Merge pull request #1754 from j9ac9k/remove-pytest-extensions-from-ci
Remove pytest extensions from ci
2021-05-01 21:28:49 -07:00
Ogi Moore 2fd5337215 Run processEvents twice to make sure plot is redrawn 2021-05-01 18:05:33 -07:00
Ogi Moore cb48ce0548 Remove pytest-cov 2021-05-01 14:23:33 -07:00
Ogi Moore 6163a60198 Remove pytest-xdist 2021-05-01 14:23:28 -07:00
Martin Chase 85e2574230
useCupy option should be settable after ImageItem init (#1749)
* do not cache the cupy so the config option can be set later

* getCupy will always return None if the option is not set

* test of failing behavior

* divorce skip from option; restore option after test
2021-04-30 10:41:11 -07:00
Fernando Bordignon 7dc4823cc6
Update symbols documentation and inverted up and down arrows of scatterplotitem (#1747) 2021-04-29 19:34:19 -07:00
pijyoi 4d6a8e4998
add usage of numba (for rescale) (#1695)
* implement rescale using numba

* workaround to pass test_makeARGB.py

* key on (input, output) manually

* remove minimum version check

* signature needs to be a list of signatures

numba considers it a mistake for single-item non-list but works around
it internally

* add numba test to test_makeARGB.py

* add numba as dependency in CI

* handle properly the case where useNumba was already True

* restore useCupy setting after test

* filter numba nan warning

* don't make changes to test_cupy_makeARGB_...
2021-04-28 22:29:09 -07:00
Nils Nemitz a7bc2b9a63
clean-up of PlotDataItem downsample methods (#1725)
* clean-up of PlotDataItem downsample methods

* high end of range at low end, not zero

Co-authored-by: Ogi Moore <ognyan.moore@gmail.com>
2021-04-28 22:07:24 -07:00
Martin Chase 4ee1fe4388
fix bug when plotting boolean arrays (#1748)
* test and fix for plotting boolean arrays

* smaller is faster

* oh, that bool went away

* tests should keep up with optimizations
2021-04-28 21:35:27 -07:00
Ogi Moore a534132c62
Various performance improvements to pg.Point (#1741)
This change makes use of QPointF methods which perform faster than the python
equivalent methods.  Furthermore, some tests are added.

* Set __slots__ to empty tuple for pg.Point
* Make Point.angle() behave as Vector.angle()
2021-04-28 21:29:47 -07:00
Ogi Moore fe66f3fd12
Merge pull request #1746 from pijyoi/fix_cprint_remote
fix: cprint of remote output needs decode()
2021-04-28 20:46:24 -07:00
KIU Shueng Chuan 306e9c2498 fix: cprint of remote output needs decode() 2021-04-28 16:38:15 +08:00
Ogi Moore 2cbc86bee1
Merge pull request #1743 from j9ac9k/cleanup-some-static-code-checks
Cleanup some static code checks
2021-04-25 22:01:06 -07:00
Ogi Moore 2d8d1d6d32 Add tmp_module fixture for test_reload 2021-04-25 21:36:42 -07:00
Ogi Moore 7c48233bfa Remove unreachable code 2021-04-25 21:36:23 -07:00
Ogi Moore 38dccf8642 Fix indentation bug with flowchart 2021-04-25 20:10:54 -07:00
Ogi Moore 00a0ddb0d4 Do not import value of mutable attribute
This was brought to the attention via the stack type checker, Easy fix so it is being
implemented.
2021-04-25 20:08:47 -07:00
Ogi Moore 4d388ee633 Use open context-manager instead of file.open()
Static code checker identified multiple places where a file is opened
but is not necessarily closed.  This commit addressed that with the
exception of RemoteGraphicsView.py
2021-04-25 17:05:05 -07:00
Ogi Moore cf95964678
Merge pull request #1738 from pijyoi/fix_font
use Format_RGB32 when using QImage as paint device
2021-04-24 09:43:42 -07:00
Ogi Moore d9a3774f6c
Merge pull request #1739 from pijyoi/manual_form
Export dialog: ParameterTree needs 2 columns
2021-04-24 09:41:40 -07:00
Ogi Moore 6a708dc203
Merge pull request #1724 from j9ac9k/use-math-module-for-single-values
Use math module methods for scalars
2021-04-23 23:10:17 -07:00
Ogi Moore 03ea368454 Clean up Errors for CodeQL analyzer
CodeQL identified some errors and warnings, which this commit cleans up.
2021-04-23 22:44:29 -07:00
Ogi Moore 329423f525 Use QTransform.rotateRadians when appropriate
In a few places in the library, we are doing the conversion from radians
to degrees just so we can call QTransform.rotate(), but there is a
QTransform.rotateRadians() method which would be more suitable, thus
making it so we do not have to handle the conversions ourselves
2021-04-23 22:43:57 -07:00
Ogi Moore e1415cb3a8 Use np.pi or math.pi instead of just pi 2021-04-23 22:43:57 -07:00
Ogi Moore 6a386e723b Fix overflow warning in QColor by using np.isfinite 2021-04-23 22:43:57 -07:00
Ogi Moore 3ea92736b8 Do not use list comprehensions with any or all
python any and all are able to break early the moment they come across a
member of the iterable that meets the condition; but having a list
comprehension nested within breaks that ability to exit early, as the
list comprehension has to finish being constructed first before it can
be evaluated
2021-04-23 22:43:57 -07:00
Ogi Moore 314121192a Use math module for isfinite or isnan for scalars
Various places in the library attempt to check if scalars are finite
via numpy methods, which are intended to be used on numpy arrays.  Using
the math module equivalent functions on scalars is significantly faster.

In a few places, I also use numpy methods explicitly (np.all vs. all)
2021-04-23 22:43:57 -07:00
Ogi Moore b0769f4be9 Use math.radians and math.degrees
Many places in the library were doing radian to degree conversion
via the manual calculation.  Doing timeit benchmarks on my system, I
am able to get a 4x speedup by using math.degrees or math.radians
instead
2021-04-23 22:43:51 -07:00
Ogi Moore 1138c67d45 Use math module trig functions for scalars
This commit replaces the use of np.sin/np.cos/np.tan uses throughout
the library with math.sin/math.cos/math.tan for scalar values
2021-04-23 22:42:46 -07:00
KIU Shueng Chuan e3372fddc5 specify that ParameterTree needs 2 columns in .ui 2021-04-24 11:21:12 +08:00
Ogi Moore c4a1cf11a1 Use clip_array or clip_scalar instead of np.clip
Significant performance issues have been identified with np.clip
and thus clip_array was created to speed up the operation.  In addition
clip_scalar was created to clip a scalar value between two other values
this commit replaces many uses of np.clip from operating on scalars to
using clip_scalar instead
2021-04-23 11:53:00 -07:00
Ogi Moore 85c726e49a Replace uses of np.log on scalers with math.log 2021-04-23 11:53:00 -07:00
Ogi Moore b01e0e0895 Remove unused function and change line calc
Using @pijyoi's suggestion regarding line calculation broadcasting
2021-04-23 11:53:00 -07:00
Ogi Moore f60fa3b534 Use clip_array instead of np.clip in GLVolumeItem 2021-04-23 11:53:00 -07:00
Ogi Moore f8cefa6284 Use hypot method to avoid over/underflow errors
Use hypot instead of manual calculation
2021-04-23 11:53:00 -07:00
Ogi Moore b0a3849960 Use math module methods for singular values
Using numpy methods that are intended for vectorized operations is
substantially slower than using the math module, so when feasible the
math module methods should be used.
2021-04-23 11:53:00 -07:00
KIU Shueng Chuan fbc86cd2c5 use Format_RGB32 when using QImage as paint device
this allows sub-pixel font antialiasing to take place.
2021-04-23 18:54:21 +08:00
Ogi Moore a9161e0794
Merge pull request #1735 from pijyoi/fix_dpr
unify _dpiRatio() and devicePixelRatio()
2021-04-22 09:52:09 -07:00
Ogi Moore 9a77c223f0
Merge pull request #1736 from pijyoi/remote_dpr
be hidpi-aware for remote rendering
2021-04-22 09:51:19 -07:00
KIU Shueng Chuan 51871cd01e be hidpi-aware for remote rendering 2021-04-22 17:26:46 +08:00
KIU Shueng Chuan f4ed46773f unify _dpiRatio() and devicePixelRatio() 2021-04-22 11:51:10 +08:00
Ogi Moore ec4d613037
Merge pull request #1730 from pijyoi/fix_powershell 2021-04-21 07:02:28 -07:00
Martin Chase d531a808e1
allow gradient position to be configured on a histogram (#1729)
* NEW features for HistgramLUTItem

* gradientPosition=('left', 'right')
* only paint if item is visible (is faster)
* link hisogram to other histograms

* fixes to be able to merge

 * drop linkHistogram (rgba needs to be better integrated)
 * make sure defaults to same as current behavior
 * draw connecting lines correctly on each side
 * add example use
2021-04-20 19:57:15 -07:00
KIU Shueng Chuan 0781f9392b use Popen instead of os.spawnle 2021-04-21 07:31:03 +08:00
Nils Nemitz a6f9a2be12
ColorMap: keep RGBA values as uint8, clean up docstrings (#1722)
* keep RGBA values as uint8, clean up docstrings

* ColorMap docstring correction

* enum mapping fix 2
2021-04-19 23:03:44 -07:00
Ogi Moore c62e51f4d8
Merge pull request #1723 from NilsNemitz/fixed_data_ordering_for_colorbaritem
Set fixed data ordering for ColorBarItem
2021-04-17 08:00:56 -07:00
Nils Nemitz 515ae5f6e3 add axisOrder='col-major' 2021-04-17 18:18:14 +09:00
Ogi Moore 2b2b8d34c2
Merge pull request #1716 from j9ac9k/cleanup-pytest-opts
Update pytest and tox configs, fix misc warnings
2021-04-16 22:52:27 -07:00
Ogi Moore 1326ebe2f4 Update numpy version used in CI from 1.19 to 1.20 2021-04-16 22:33:59 -07:00
Ogi Moore 41eadd678b Remove build docs CI job
Now that readthedocs supports building docs on pull requests, we no
longer need to build the docs ourselves as part of the CI pipeline.
2021-04-16 22:32:14 -07:00
Ogi Moore 7740de4a26 Update README table show not-supported configs 2021-04-16 22:18:11 -07:00
Ogi Moore a231c9ffb0 Update tox.ini config 2021-04-16 22:18:11 -07:00
Ogi Moore 342fbb053f Avoid implicit int conversion for mouse buttons 2021-04-15 22:50:50 -07:00
Ogi Moore 52de9554bb Emit warning about pyside2 bug preventing loading 2021-04-15 22:50:16 -07:00
Ogi Moore e735d2d9b8 Block pyopenGL tests on more macOS platforms
When running on macOS Big Sur, pyopenGL is unable to find the bindings

Previously this was assumed that it would be fixed in later versions
of Python 3.8, but that has not happened.
2021-04-15 22:08:50 -07:00
Ogi Moore 435c54d20b Adjust pytest.ini warning suppressions
Show standard library Deprecation and PendingDeprecation warnings
Remove warning filters used for older Qt bindings no longer supported
2021-04-15 21:09:11 -07:00
Ogi Moore 5c67f03b0e skip test without generating warning 2021-04-15 21:02:49 -07:00
Ogi Moore 314e4eb480 Unescaped sequence and fix typo 2021-04-15 21:02:29 -07:00
Martin Chase 6fed6d42b3
Protect makeARGB with tests and benchmarks (#1697)
* update to working

* cupy tests, too

* doubling up and down

* add more realism to the benchmarks

* name to reflect scale

* use different numbers to mean different numbers

(that sure does sound tautological)

* more sensible: order, error

* thorough check of lots of makeARGB arg combos

* docstring for tool usage

* no print needed

* better error messages

* test makeARGB using cupy, too

* skip without cupy available

* switch from conda to venv

* skip cupy runs when not available

* use endian-proof makeARGB shim in tests

* generate the asv conf to suit the system

* document running asv

* comments for future matrix goals

* put all makeARGB tests together; name for clarity

* subprocess.check_output is standard for all supported pythons

* better handle lack of git version

* use makeARGB shim

* small fixes and improvements
2021-04-15 15:51:21 -07:00
Martin Chase a465f93d9b
small TargetItem fixes (#1715)
* angle is just an int, not a method

* more TargetItem use in the example

* offset is needed before super sometimes

* use setLabel, too
2021-04-14 10:44:03 -07:00
Ogi Moore dfa225f56f
Merge pull request #1714 from j9ac9k/merge-519-in-master
Expose the `clickable` property of `PlotDataItem`. (#519)
2021-04-13 23:20:11 -07:00
Christopher Mullins 10c1e83cd7 Expose the `clickable` property of `PlotDataItem`. (#519)
* Fix the `clickable` property of `PlotDataItem`.

Currently if you attempt to set the `clickable` property of a PlotDataItem,
this property is silently ignored. The expected behavior is to set the
`clickable` property of the underlying PlotCurveItem.

* Use setCurvesClickable and curvesClickable instead

* curve is singular
2021-04-13 22:31:26 -07:00
Ogi Moore 6f74d56266
Merge pull request #1710 from pijyoi/reorder_tests
run pyqtgraph tests before examples
2021-04-11 08:10:53 -07:00
Ogi Moore d2e1f99b5e
Merge pull request #1708 from j9ac9k/remove-infiniteline-from-others-example
Remove infiniteline from others in examples
2021-04-11 08:08:25 -07:00
KIU Shueng Chuan 8cb53d321b run pyqtgraph tests before examples 2021-04-11 21:51:44 +08:00
Ogi Moore fe6ad52262 Remove infiniteline from others in examples 2021-04-10 23:10:12 -07:00
Ogi Moore 5a08650853
Improve target item - incorporate bits from PR 313 (#1318)
Overhaul TargetItem based on @lesauxvi 's PR #313
2021-04-10 22:42:44 -07:00
Ogi Moore bb90ef1ec9
Merge pull request #1707 from pijyoi/pyqt61_compat
add PyQt6 6.1 forwards compatibility
2021-04-10 20:27:04 -07:00
Ogi Moore a3443571f2
Merge pull request #1706 from ntjess/update-mkPen
promote use of '#' in mkPen
2021-04-10 20:21:53 -07:00
KIU Shueng Chuan 2aed5c36d5 no need to reconstruct PyQt6 enums
PyQt6 can serialize / deserialize enums and flags w/o us manually
casting them to int.

In PyQt6 6.0, it was okay to pass the already deserialized flag
back to the class constructor.
In PyQt6 6.1, the flags MouseButtons and KeyboardModifiers have
been renamed to MouseButton and KeyboardModifier respectively.

skipping the reconstruction allows it to work on both PyQt6 6.0 and 6.1.
note that this was already done in deserialize_mouse_event()
2021-04-11 09:53:49 +08:00
KIU Shueng Chuan 64702981d4 temporarily let PyQt6 6.1 run on PyQt6 6.0 ui files 2021-04-11 09:02:58 +08:00
KIU Shueng Chuan 4699bbad6b fix keyboard modifiers default value 2021-04-11 09:00:52 +08:00
Nathan Jessurun e890d832e0 promote use of '#' in mkPen 2021-04-10 17:52:51 -04:00
Ogi Moore 10d924818c
Merge pull request #1701 from pijyoi/fix_overflow_warning
avoid numpy scalar overflow
2021-04-08 21:54:23 -07:00
KIU Shueng Chuan 3be8cafff4 avoid numpy scalar overflow
the "offset" argument passed into rescaleData() is typically an element
of an ndarray, i.e. it comes from the lower bound value of the "levels"
ndarray. as such, arithmetic operations on it can overflow.

this triggers a runtime warning in the test suite.

the workaround is to convert it to a Python (integer) scalar.
2021-04-09 10:14:23 +08:00
Martin Chase 0f94c17d86
Fix roi get array region (#1700)
* ROI.py, getArrayRegion: Fix return mapped coordinates

The *getArrayRegion* method is defined as returning a tuple of the points
in the selected region and the mapped coordinates if the
*returnMappedCoords* keyword argument is set to True in the parent class
*ROI*.

In the *EllipseROI* class, *getArrayRegion* was overriden, however it
ignores the *returnMappedCoords* keyword argument, leading to unintended
bugs because of the change in interface between the parent class and
the subclass.

This patch fixes the above bug.
If *returnMappedCoords* is set to False, then only *arr* containing the
array region is returned. If *returnMappedCoords* is set to True, a
tuple of the array region and the mapped coordinates is returned.

NB: At the time of this commit, the same bug is present in several classes
extending *ROI*. This commit only fixes the issue for the *EllipseROI* class.

* ROI.py, PolyLineROI.getArrayRegion: Fix return mapped coordinats

The *getArrayRegion* method is defined as returning a tuple of the
points in the selected region and the mapped coordinates if the
*returnMappedCoords* keyword argument is set to True in the parent class
*ROI*.

In the *PolyLineROI* class, *getArrayRegion* was overriden, however it
ignores the *returnMappedCoords* keyword argument, leading to unintended
bugs because of the change in interface between the parent class and the
subclass.

This patch fixes the above bug.  If *returnMappedCoords* is set to
False, then only *arr* containing the array region is returned. If
*returnMappedCoords* is set to True, a tuple of the array region and the
mapped coordinates is returned.

* remove merge conflict cruft

* lint

Co-authored-by: Malik Olivier Boussejra <malik@boussejra.com>
2021-04-08 13:43:30 -07:00
Kyle Sunden 711ad8afaa
Merge pull request #1696 from j9ac9k/0.12.1-changelog
Add changelog for 0.12.1
2021-04-06 20:52:46 -05:00
Kyle Sunden 03b7aa7860
Update version number for release 2021-04-06 20:41:32 -05:00
Ogi Moore 4bbbb189db Add changelog for 0.12.1 2021-04-06 13:08:49 -07:00
Ogi Moore 3ed206fa70
Merge pull request #1690 from ntjess/master
revert to old behavior: default created from value if not present
2021-04-06 13:07:10 -07:00
Ogi Moore d4c5025289 Implement suggested changes from ixjlyons 2021-04-06 11:51:10 -07:00
pijyoi aa57c7a685
implement rescaleData as a blocked iterator using np.nditer (#1648)
* implement rescaleData_blocked

clip limits should be int if data is int

* add test for rescaleData_blocked

* dispatch to different versions depending on numpy or cupy

* make rescaleData() the only entry-point
2021-04-05 23:02:52 -07:00
Nils Nemitz 758c038411
Add ColorBarItem for simplified image level adjustment (#1596)
* Initial implementation of ColorBarItem

* initial commit

* fixed missing indent

* docstring extension and corrections

* Converted example to match others / run as part of tests

* load local color maps instead of importing from colorcet

* clean up window creation code

* horizontal color bar and clean-up

* switched to mkQApp initialization

* cleaned up some comments
2021-04-05 20:50:52 -07:00
Nils Nemitz 929f3bda0d
make sure dynamic range limiter runs even when there isn't previous data (#1691) 2021-04-05 15:46:28 -07:00
Dennis Göries b8cf3dded4
DateAxisItem: Account for daylight saving time (#1694)
* DateAxisItem: Account for daylight saving time

* Use  logic more visible in utcoffset

* Rename getOffsetFromUtc function
2021-04-05 15:45:08 -07:00
Nathan Jessurun 58d126dcf3 fixes tests 2021-04-03 20:31:04 -04:00
Nathan Jessurun 4b002c06ba revert to old behavior: default created from value if not present 2021-04-03 17:07:02 -04:00
Ogi Moore 07a99cb443
Merge pull request #1680 from pijyoi/rgba_endian
Fix CI tests for big-endian architectures
2021-04-01 20:37:06 -07:00
KIU Shueng Chuan 02a48afc60 test_makeARGB() : normalize to B,G,R,A 2021-04-01 08:38:10 +08:00
KIU Shueng Chuan 17e2f0f5f2 fix makeARGB() endian ordering 2021-04-01 08:38:08 +08:00
KIU Shueng Chuan 179b27ad8c image_testing.py: swap red and blue channels 2021-04-01 08:32:31 +08:00
Nils Nemitz 30071699d7
Include colormaps in installer (#1660)
* renamed mathods and moved color map example

* added colors/maps/ data to setup.py
2021-03-27 00:15:19 -07:00
Ogi Moore 4dc76ed90e
Merge pull request #1617 from pijyoi/fastpath_argb
Optimize makeARGB for ubyte images
2021-03-26 14:22:56 -07:00
Ogi Moore 1a597b80b7
Merge pull request #1662 from NilsNemitz/cast-to-int_in_ImageView_QSplitter.setSizes
added cast to int so that QSplitter.setSizes works on Python 3.10
2021-03-26 12:39:38 -07:00
Nils Nemitz 028f9d12a2 cast splitter settings to int in Canvas.py 2021-03-27 04:30:51 +09:00
Ogi Moore 21605faa44
Merge pull request #1666 from NilsNemitz/revert_styleUpdate_reduction
revert style change reduction in PlotDataItem
2021-03-26 12:12:41 -07:00
Ogi Moore 75abcb634e
Merge pull request #1665 from lidstrom83/bugfix-legend
Don't pass brush to fn.mkPen
2021-03-26 11:54:29 -07:00
Nils Nemitz d8d5d49f04 revert style change reduction in PlotDataItem 2021-03-27 03:51:44 +09:00
Daniel Lidstrom fb3a8b62bd Don't pass brush to fn.mkPen 2021-03-26 11:36:30 -07:00
Nils Nemitz 2b1e24bf11 added cast to int 2021-03-26 18:47:38 +09:00
KIU Shueng Chuan b3dc090373 implement fastpath for makeARGB 2021-03-26 04:07:19 +08:00
KIU Shueng Chuan de85a23ae0 switch to row-major order 2021-03-26 04:07:19 +08:00
KIU Shueng Chuan fda8731dab reduce memory usage during data generation
random.normal() generates as float64 and gets converted to a smaller
dtype. generating all the needed data in a single call thus uses a lot
more memory than is necessary.

this changes it such that smaller chunks are generated.
data clipping is also changed to be in-place.

the gaussian filtering which gave the video a washed-out look is also
removed. this also contributed to data generation time.
2021-03-26 04:07:19 +08:00
KIU Shueng Chuan cbafc773f5 fix: max value of uint16 is 65535 2021-03-26 04:07:19 +08:00
Ogi Moore 0234a27816
Merge pull request #1656 from ksunden/postrel0.12
Post release 0.12.0
2021-03-25 12:39:49 -07:00
Kyle Sunden 43532aa802 Post release 0.12.0 2021-03-25 14:25:30 -05:00
Ogi Moore 8552c500d5
Merge pull request #1655 from ksunden/prep0.12
Update version to 0.12.0
2021-03-25 12:07:03 -07:00
Kyle Sunden d2a1bcf920 Update version to 0.12.0 2021-03-25 14:04:14 -05:00
Kyle Sunden bf450c29a7
Merge pull request #1643 from j9ac9k/0.12-changelog
Initial draft of changelog for 0.12.0
2021-03-25 13:56:51 -05:00
Ogi Moore e3f8c091c3 Update changelog 2021-03-23 12:56:56 -07:00
Ogi Moore a86f588816 Incorporate suggested changes from NilsNemitz 2021-03-23 12:44:02 -07:00
Ogi Moore 3b620836c4
Merge pull request #1651 from j9ac9k/Use_collections.abc
collections.abc not just collections
2021-03-23 11:56:02 -07:00
Nils Nemitz 954c7342dd
Fix to accidentally disabled style updates in PlotDataItem (#1653)
* allowed style updates to once again update the style of curve and scatter plot, added tests

* tests interleave assign and assert to guard against delayed assignment

* > > > now 100% more camels < < <
2021-03-23 11:54:15 -07:00
Ogi Moore bb5a179647
Add Deprecation Warning to Hex Strings That Do Not Start With "#" in mkColor (#1644)
* Add deprecation warning

* Incorporate changes to docs/warning

* correct input for no warnings

* Update docs examples in LabelItem
2021-03-23 11:35:06 -07:00
Ogi Moore bc7ca1beef Move Color Map Example To Main Section 2021-03-23 11:12:36 -07:00
Ogi Moore 5b278855d6 Switch to camelCase functions 2021-03-23 11:07:19 -07:00
Ogi Moore 675516e0b1 collections.abc not just collections 2021-03-22 22:17:28 -07:00
Ogi Moore 4951bd743e
Replace main stanza with PyQt6 compatable variant (#1645)
* Replace main stanza with PyQt6 compatable variant

* Use fn.mkQApp instead

* remove needless comments
2021-03-22 11:17:12 -07:00
Ogi Moore 69be66699a
Merge pull request #1650 from NilsNemitz/add_clip_scalar_function
Do not use clip_array on scalars (use clip_scalar instead)
2021-03-22 11:16:50 -07:00
Ogi Moore 517d243166
Remove unhelpful warnings (#1646)
* Remove warning about existing QApplication

* Remove reference to weave which we do not use

* Do away with opengl warning

* Remove weaveDebug config option
2021-03-22 11:12:01 -07:00
Nils Nemitz 2c82a84f68 Do not use clip_array on scalars (use clip_scalar instead) 2021-03-23 01:08:31 +09:00
Nils Nemitz a1eca4e2dd
handle empty adjanceny array (#1647) 2021-03-21 21:14:19 -07:00
pijyoi d74bbe3bf6
Fix functions.clip_array() (#1649)
* fix clip_array()

return error for invalid inputs.
use minmax for win32, umath.clip for other platforms

the previous code was penalizing Linux

* force output to be an array
2021-03-21 18:44:26 -07:00
Nils Nemitz d0f5a6686f
PlotDataItem: Fix view range <-> dynamic range limit pathology and switch to np.umath.clip (#1637)
* 'no offscreen clip' optimization and switch to np.umath.clip

* swapped out clipping code for new functions.array_clip
2021-03-20 22:16:15 -07:00
Ogi Moore 170da9746c Initial draft of changelog for 0.12.0 2021-03-20 17:02:43 -07:00
Nils Nemitz 574c2d24f2
Stop PlotDataItem from always sending full style information to PlotCurveItem / ScatterPlotItem (#1619)
* skip unneded style updates in PlotDataItem

* removed unwanted file

* obliviated stray debug statement
2021-03-19 22:54:53 -07:00
Nils Nemitz 5fa3901c00
Fix transformations in GradientLegend (#1639)
* rebuilt transformations

* restored drawing order to bg > bar > labels (and removed some print statements)
2021-03-19 22:06:18 -07:00
Ogi Moore 8e32eeb1a5
Merge pull request #1641 from pijyoi/clip_refactor
refactor code to replace np.clip
2021-03-19 21:58:05 -07:00
KIU Shueng Chuan 8d74dfe11b refactor code to replace np.clip 2021-03-20 08:09:29 +08:00
Nils Nemitz 12aee3e47d
remove pyqtgraph-core from documentation (#1636)
* removed pyqtgraph-core from documentation

* reread --> minor revisions
2021-03-19 08:46:30 -07:00
Ogi Moore 3f9e56f62e
Merge pull request #1630 from pijyoi/lut_combine
combine levels and lut only if both are present
2021-03-14 08:58:19 -07:00
Ogi Moore 63c19800d2
Merge pull request #1632 from pijyoi/clip_regression
rescaleData : workaround np.clip regression since numpy 1.17
2021-03-14 08:52:31 -07:00
Jeffrey Gill 20a3435a4d
Add missing project URL for neurotic to README, add ephyviewer (#1633)
* Add missing project URL for neurotic to README

* Add ephyviewer to project list in README
2021-03-14 08:49:52 -07:00
KIU Shueng Chuan 56b54344e2 workaround np.clip regression since numpy 1.17 2021-03-14 16:01:29 +08:00
KIU Shueng Chuan 5df14aec1d combine levels and lut only if both are present
previously, if levels was present but lut was not, levels would be
converted into lut.
2021-03-13 16:27:20 +08:00
Ogi Moore eb7a60fcf8
Fix environment variable typo for highdpi scaling (#1627) 2021-03-08 09:36:40 -08:00
Ogi Moore 93b708e2e6
Add used by in readme (#1626)
* Add projects with links that use pyqtgraph

* Add existing projects to README.md
2021-03-08 09:22:13 -08:00
Ogi Moore c5a1174f04
Merge pull request #1605 from pijyoi/clean_shutdown
let examples have a chance to exit normally
2021-03-06 20:18:50 -08:00
Ogi Moore 829f07b24a
Merge pull request #1618 from pijyoi/pyqt6_abort
PyQt6 install sys.excepthook
2021-03-02 22:22:18 -08:00
KIU Shueng Chuan df64be371a remove PySide from _loadUiType()
bug:
- QT_LIB == "PYSIDE" should have been QT_LIB == PYSIDE
2021-03-03 10:44:23 +08:00
KIU Shueng Chuan 30a64d5f81 Qt.py : remove Qt4 2021-03-03 10:44:23 +08:00
KIU Shueng Chuan d82f28d390 install sys excepthook for PyQt6 2021-03-03 09:42:16 +08:00
Ogi Moore fb6ae0ff2c
Merge pull request #1613 from chrismullins/parameter-unpacking
Add keys() method to Parameter class
2021-03-02 11:05:47 -08:00
KIU Shueng Chuan c49e471192 don't skip test_ExampleApp.py 2021-03-02 05:57:17 +08:00
KIU Shueng Chuan 85e894dd73 convert uses of QTimer.singleShot to QTimer instances
On macOS and Linux with PyQt bindings, QTimer.singleShot continues
to fire on python interpreter shutdown.
2021-03-02 05:57:17 +08:00
Kiu Shueng Chuan 1ad7d49908 de-duplicate Big Sur opengl skip testing 2021-03-02 05:57:17 +08:00
Kiu Shueng Chuan 5f6be29f66 connect paletteChanged to standalone function 2021-03-02 05:57:17 +08:00
KIU Shueng Chuan de11e6315c let examples have a chance to exit normally
cleanup imported module

1) instantiate MainWindow class if present
2) delete attributes from imported module when done
2021-03-01 21:24:43 +08:00
Chris Mullins 9ed51cd1e2 Add keys() method to Parameter class
This returns the names attribute, allowing **unpacking of Parameter subclasses.
2021-02-28 03:00:19 +00:00
Martin Chase 2318f49bc4
include more color in the ImageView example (#1611)
* work taken from #312 (thanks, @ptweir !)
* turn on an ROI by default
2021-02-25 16:14:34 -08:00
Ogi Moore cd73aeed0e
Merge pull request #1598 from outofculture/selfless-lambdas
Remove references to self from lambdas
2021-02-23 09:40:57 -08:00
Ogi Moore c1900aa71a
Merge pull request #1599 from pijyoi/choose_binding
fix Example App launch of VideoSpeedTest
2021-02-22 13:31:50 -08:00
KIU Shueng Chuan d8e826e379 disable opengl vsync for benchmarking 2021-02-22 21:15:57 +08:00
KIU Shueng Chuan fbd1e89950 regenerate templates 2021-02-22 19:17:53 +08:00
KIU Shueng Chuan a657dea084 remove graphics system combobox 2021-02-22 19:17:53 +08:00
KIU Shueng Chuan 61616ffad9 remove calls to setGraphicsSystem
in fact all are no-ops
2021-02-22 19:17:53 +08:00
KIU Shueng Chuan e09a397ebc modify environment to choose binding
the Example App allows the user to choose a binding and a graphics
system to use to execute an example.

issue 1: setGraphicsSystem is obsolete and the method no longer exists.
thus selecting a graphics system causes an error.

issue 2: the choice of binding to use is passed as an extra command
line argument to be parsed by initExample. this is problematic for
examples that use argparse, such as VideoSpeedTest.py

issue 3: if the user has set PYQTGRAPH_QT_LIB, that takes precedence
over the choice made in the Example App.

this patch fixes the above 3 issues by setting PYQTGRAPH_QT_LIB in
the child process' environment and removing the old parsing of the
command line arguments
2021-02-22 18:13:49 +08:00
Martin af82858bc8 make these tiny methods with little excuse to exist private 2021-02-21 22:31:13 -08:00
Martin 68fa95686b fix typo 2021-02-21 07:05:24 -08:00
Martin 7f4f677ce1 lambdas which reference self prevent GC 2021-02-21 06:49:07 -08:00
Ogi Moore 5b1ac7acaa
Merge pull request #1597 from pijyoi/fix_dim2
RawImageWidget: transpose did not handle luminance only images
2021-02-20 09:24:18 -08:00
KIU Shueng Chuan 0dc17ef546 RawImageGLWidget follow same style as RawImageWidget
i.e. row-major convention is used internally and user inputs are
converted at the point of entry.
2021-02-20 18:58:26 +08:00
KIU Shueng Chuan 5a29373572 fix: make transpose work for either ndim 2 or 3
at the same time, increase performance by using
makeQImage(copy=False, transpose=False)
2021-02-20 18:42:13 +08:00
Ogi Moore 3eda637652
Merge pull request #1595 from outofculture/cupy-bug-workaround
Workaround for cupy indexing bug
2021-02-19 21:58:14 -08:00
Martin 09fd7a81b9 account for cupy inconsistency in slicing with a boolean array
See https://github.com/cupy/cupy/issues/4693
2021-02-19 20:51:35 -08:00
Ogi Moore 6fc0389f33
Merge pull request #1594 from outofculture/plotitem-regression
Fix Plotitem regression
2021-02-19 12:21:16 -08:00
Martin b7e560a7ea fix imports
* metaarray is not used
* PlotCurveItem and ScatterPlotItem needed to be imported
* sort
2021-02-19 11:33:06 -08:00
Martin b9086f1023 no "i" variable anymore 2021-02-19 11:11:38 -08:00
Ogi Moore d9eb8e1afb
Merge pull request #1575 from pijyoi/reduce_shim
Reduce number of shims for PyQt6
2021-02-19 09:40:06 -08:00
Ogi Moore d0d10ca512
Merge pull request #1587 from irgolic/darkmode-example-property
app.dark_mode => app.property('darkMode')
2021-02-18 19:33:16 -08:00
Rafael Irgolic 6da60ccec8 Qt: Remove some Qt4 shims 2021-02-18 19:12:32 +00:00
Rafael Irgolic ae54e27ff6 app.dark_mode => app.property('darkMode') 2021-02-18 19:02:18 +00:00
Ogi Moore 1a2728a671
Merge pull request #1586 from j9ac9k/investigate-rawImage-imageaxisorder
Investigate raw image imageaxisorder
2021-02-16 22:48:22 -08:00
Ogi Moore 765032fc0b Do not upload texture every paintGL call 2021-02-16 22:19:38 -08:00
Ogi Moore 0b26ef3644 RawImageWidget uses imageAxisOrder config option 2021-02-16 22:19:13 -08:00
Ogi Moore acd172eb13
Merge pull request #1583 from pijyoi/port_qopenglwidget
RawImageWidget.py : fix port to QOpenGLWidget
2021-02-15 21:02:34 -08:00
Ogi Moore c13da2c6da
Merge pull request #1582 from pyqtgraph/rtd 2021-02-15 18:40:40 -08:00
KIU Shueng Chuan 2719922584 RawImageWidget.py : fix port to QOpenGLWidget
Qt5 docs specify differences between QGLWidget and QOpenGLWidget:
"...when invoking paintGL().
 QOpenGLWidget sets up the viewport via glViewport().
 It does not perform any clearing."
2021-02-16 09:15:37 +08:00
Kenneth Lyons 87f6c2778b Pin sphinx version to avoid buggy sphinx.ext.viewcode 2021-02-15 16:24:49 -08:00
lidstrom83 6519734932
Deprecate unused/unnecessary modules (#1576)
* Deprecate ordereddict module

* Import OrderedDict from collections module instead of pgcollections

* Deprecate pgcollections module

* Deprecate lru_cache module

A simpler recipe exists from the standard library using OrderedDict.

* Deprecate pil_fix module

* Python 3.7 compatibility fix

* Avoid or suppress deprecation warnings in tests
2021-02-15 09:52:06 -08:00
Martin Chase 5210c55e67
Equilateral Triangle ROI (#1581)
* feature TriangleROI

Added equilateral  TriangleROI.
getArrayRegion is not working yet

* show off (and implicitly test) our new TriangleROI

* the PolyLineROI.getArrayRegion can be used by TriangleROI

refactor the actual logic to live on ROI

* refactors for readability

* variable names
* lint
* docstring type and purpose

Co-authored-by: Fekete Imre <feketeimre87@gmail.com>
2021-02-15 06:06:55 -08:00
Kyle Sunden a5a41cf8eb
Merge pull request #1577 from j9ac9k/cleanup-1573
Remove duplicate import and remove whitespace
2021-02-14 21:36:31 -06:00
Ogi Moore 825286066a only cast to float32 when safe to do so 2021-02-14 17:43:32 -08:00
Ogi Moore 4ac8e39aea Remove duplicate import and remove whitespace 2021-02-14 12:05:22 -08:00
Ogi Moore 5bfe8d5a46
Merge pull request #1572 from outofculture/arbitrary-scale-center
Arbitrary scale center ROI
2021-02-14 08:49:03 -08:00
KIU Shueng Chuan a1f9100ef1 shim only the keys we actually use 2021-02-14 07:56:05 +08:00
KIU Shueng Chuan 6ad1d752fe use QKeySequence to detect platform dependent copy keys 2021-02-14 07:46:20 +08:00
KIU Shueng Chuan 968286a1cf remove drag and drop shims
used only in one place in the codebase
2021-02-14 07:44:00 +08:00
KIU Shueng Chuan f4d685f7bd remove QDialog.exec_ shim
only used by PrinterExport.py which is currently disabled
2021-02-14 07:36:41 +08:00
Ogi Moore a04ff546e0
Merge pull request #1573 from j9ac9k/add-deprecation-warnings
Add deprecation warnings, Use non-deprecated upstream methods
2021-02-13 14:59:17 -08:00
Ogi Moore 6c5c0b590f Skip test_reload on python 3.10+ 2021-02-13 10:57:38 -08:00
Ogi Moore dce2288a18 Fix most errors... 2021-02-13 10:57:38 -08:00
Ogi Moore 3bfe2d81ba Do not use numpy deprecated type aliases 2021-02-13 10:57:38 -08:00
Ogi Moore 955f1c37a6 Use QPointF instead of QPoint for float input 2021-02-13 10:57:38 -08:00
Ogi Moore f853d8b520 Replace float type to QTimer.start() with int 2021-02-13 09:07:54 -08:00
Ogi Moore fc550aab86 keep testing deprecated objects, catch warnings 2021-02-12 13:08:00 -08:00
Ogi Moore 36d89fa3a5 Have test_PlotCurveItem use GraphicsLayoutWidget and not the deprecated GraphicsWindow 2021-02-12 13:08:00 -08:00
Ogi Moore d14a90112c Have test_svg use GraphicsLayoutWidget not the Deprecated GraphicsWindow 2021-02-12 13:08:00 -08:00
Ogi Moore 4fcea2762f Have NonUniformImage test use GraphicsLayoutWidget not deprecated GraphicsWindow 2021-02-12 13:08:00 -08:00
Ogi Moore 45329aac51 Remove unneeded pytest.skipif decorator 2021-02-12 13:08:00 -08:00
Ogi Moore b45386ebc5 Have __init__.plot() use PlotWidget, not deprecated PlotWindow 2021-02-12 13:08:00 -08:00
Ogi Moore ff71b6be6b Add actual deprecation warnings 2021-02-11 21:34:02 -08:00
Ogi Moore bd548e00c9 Restore shimmed Qt4 methods, with deprecation warnings 2021-02-11 20:06:38 -08:00
lidstrom83 d7668f91b3
Fix ScatterPlotItem performance regression (#1569)
* Fix ScatterPlotItem performance regression

* Add hover benchmark to ScatterPlotSpeedTest.py

* Removed a performance regression from GraphicsView

* Removed some tests failing due to the last commit
2021-02-11 08:36:52 -08:00
Ogi Moore 344348441a
Merge pull request #1568 from pijyoi/pyqt_qimage
Change image tests to not rely on non-const QImage
2021-02-10 19:57:22 -08:00
KIU Shueng Chuan 659392d4bb don't rely on QImage being non-const
the previous formulation creates an ndarray and then creates an QImage
over it w/o copying. this relies on the QImage thus created being
non-const.

if the QImage was (unintentionally) created as const, the subsequent
QPainter render on the const QImage would trigger a COW. i.e. the
original underlying ndarray wouldn't be updated.

this is only an issue for PyQt bindings where const QImages can be
created.
2021-02-11 10:38:19 +08:00
KIU Shueng Chuan 6c8e07c377 use 64-bits qimage size for PyQt5 5.15
PyQt5 5.15 has both methods sizeInBytes() (64-bits) and byteCount()
(32-bits)
the previous formulation would use 32-bits qimage size for PyQt5 5.15.
2021-02-11 10:38:19 +08:00
Ogi Moore 87b03b5a2a
Merge pull request #1567 from ksunden/inf_line_0d
Handle case of 0-d array in infinite line setPos
2021-02-10 12:29:28 -08:00
Kyle Sunden 17b1b82ae9 Handle case of 0-d array in infinite line setPos 2021-02-10 13:59:37 -06:00
lidstrom83 389dff4250
Add more options to ScatterPlotSpeedTest (#1566)
* Add more options to ScatterPlotSpeedTest

* Fixed poor choice of variable names

* Add simulated pan/zoom

* Multilingual support
2021-02-10 09:25:31 -08:00
Ogi Moore 28e7d4d12c
Fix Small Heights in ErrorBarItem (#1558)
* Add arrayToQPath bit

* No more moveTo or lineTo

* Use better names than 'partial'

* Implement feedback from reviewer
2021-02-09 20:42:39 -08:00
Nils Nemitz 33365fb730
Reduce reallocation in dynamic range limiter (#1556)
* change imports in cupy module to be local

* reduced re-allocation in dynamic range limiter, part 1

* minor cleanup
2021-02-09 20:36:31 -08:00
lidstrom83 aed2382e38
Correct id-based keying of scatter plot pixmap cache (#1564)
* Correct id-based keying of scatter plot pixmap cache

Note: naively using the id function results in non-unique keys.

Alternatively, we could serialize the Qt objects and use these in the key. This would provide protection from the user mutating these later, but at a cost to performance.

* Make id attribute private

* Access class variable instead of instance
2021-02-09 13:58:15 -08:00
Ogi Moore 44454358f6
Merge pull request #1561 from pijyoi/no_deletelater
remove app.deleteLater() from tests
2021-02-09 08:27:00 -08:00
Ogi Moore ca1ce7aa90
Merge pull request #1563 from RubendeBruin/fix_flowchart_docs
Flowchart documentation fix
2021-02-09 08:21:22 -08:00
Ruben de Bruin 77db5a868b
Flowchart documentation fix
the widget() method should be used to display the flowchart in a window rather than the ctrlWidget().
2021-02-09 15:20:14 +01:00
KIU Shueng Chuan c9dcc0c0ed remove app.deleteLater() from tests
Multiple tests are executed by pytest with the same Python process.
The QApplication instance is a global object that will be used by
subsequent tests.

The Qt documentation says that the object will only be deleted while
running in an event loop. In addition, the Qt docs also specifically
say that processEvents() does not process DeferredDelete events.

i.e. calling processEvents() in a loop is not equivalent to calling
QApplication.instance().exec_()
2021-02-09 16:37:19 +08:00
Ogi Moore ade6a844e7
Merge pull request #1559 from pijyoi/pyqt6_evbug
restrict PyQt6 QEvent.type() monkey patching to 6.0.0
2021-02-08 22:44:50 -08:00
Ogi Moore 2e1514d711
Cache scatter-plot items by hashable properties (#1560)
* Cache scatter-plot items by hashable properties

* use qpainterpath boundingRect+elementCount for key
2021-02-08 10:59:51 -08:00
KIU Shueng Chuan 665988dc4f remove spinbox return key workaround
the code being removed was committed in 2012.
the reason for the workaround no longer exists.

the reason this code is under scrutiny is because while porting to
PyQt6, calling ev.type() triggered a bug in PyQt6 6.0
2021-02-08 22:10:33 +08:00
KIU Shueng Chuan d5e516ad52 restrict PyQt6 QEvent.type() monkey patching to 6.0.0
The bug that this workaround was for has been fixed in PyQt6 6.0.1.

However our feature test for the bug was faulty and triggers positive
for PyQt6 6.0.1. In other words, we would be needlessly monkey patching
where it wasn't needed.
2021-02-08 08:22:19 +08:00
Ogi Moore 6d3de52773
Merge pull request #1555 from pijyoi/pyqt6_remote_mouse
PyQt6 6.0.1 QEvent.Type needs to be explicitly deserialized
2021-02-06 21:43:06 -08:00
Ogi Moore d1bcbf8ec0
Merge pull request #1554 from ixjlyons/glscatterplotitem-nodata
Disable paint in GLScatterPlotItem if it has no data
2021-02-06 16:30:24 -08:00
KIU Shueng Chuan 030c49e659 PyQt6 6.0.1 QEvent.Type needs to be explicitly deserialized
in PyQt6 6.0.0, QEvent.Type was automatically pickled / unpickled.

in PyQt6 6.0.1, QEvent.Type is now pickled to be an int, so needs to be
recreated back explicitly (like the other bindings)

this change is backwards compatible with PyQt6 6.0.0
2021-02-07 07:47:50 +08:00
Ogi Moore 4274e33486
Merge pull request #1553 from pijyoi/pyqt6_qimage_api_change 2021-02-06 15:36:04 -08:00
Kenneth Lyons a1064345d3 Disable paint in GLScatterPlotItem if it has no data 2021-02-06 15:31:54 -08:00
KIU Shueng Chuan 54d7c591b5 PyQt6 6.0.1 changes QImage constructor api 2021-02-07 07:14:24 +08:00
Ogi Moore feaa8fe5fb
Merge pull request #1547 from pijyoi/cleanup_ci
remove ProgressDialog from CI test
2021-02-06 12:05:03 -08:00
Nils Nemitz 194941dfb2
change imports in cupy module to be local (#1548) 2021-02-06 09:21:24 -08:00
Kenneth Lyons f1cfdc302d
Merge pull request #1549 from ixjlyons/pr1437-rmprint
Remove leftover print calls from PR 1437
2021-02-06 08:07:53 -08:00
Kenneth Lyons 8332f2cda0 Remove leftover print calls from PR 1437 2021-02-06 08:04:11 -08:00
KIU Shueng Chuan 310afebe56 fix svg.setResolution(int) deprecation warning
triggered only for PyQt binding, Python 3.8, 3.9

there is a mismatch in API:
- QScreen.logicalDotsPerInchX() -> float
- QSvgGenerator.setResolution(int)
2021-02-06 17:43:12 +08:00
KIU Shueng Chuan 321b5e627a remove ProgressDialog from CI testing 2021-02-06 17:08:32 +08:00
KIU Shueng Chuan c85c62deda getargspec -> getfullargspec
former is deprecated since Python 3.0
2021-02-06 17:08:32 +08:00
Drew e7ceebd867
LegendItem: fix docs & minor bugs (#1437)
* LegendItem: fix spelling mistake

* LegendItem: remove unused curRow variable

* LegendItem: correct calculation of rowCount

Previously, rowCount would never be updated unless setColumnCount()
was called. This fixes that issue.
It also fixes that setColumnCount() rounded down (floored) the
number of rows, instead of providing an accurate number:
e.g. 4 items in 3 columns would yield rowCount=1, when it should be 2

* LegendItem: remove rowCount argument (not implemented)

Logic to actually use the rowCount argument was not implemented.
Users might expect rowCount to limit the number of rows to e.g. 1,
but that is not what the current code does (it only works with limiting
the number of columns).
Thus, we were exposing an unused/misleading parameter to users.

This can and should be reverted if the logic for limiting the number
of rows is added.

* LegendItem: add colCount docs

* test (LegendItem): remove unused curRow variable

* test (LegendItem): check increasing rowCount as add items

* Fixed logic in placement of items in legend with multiple columns

* Actual row count here should be 2, not 3

Co-authored-by: Ogi Moore <ognyan.moore@gmail.com>
2021-02-05 23:00:34 -08:00
Dennis Göries bac2ff5b4b
GraphIcons: Extend and deprecate previous pixmaps (#1534)
* GraphPixmaps: deprecate pixmaps

* Deprecation print

* More doc strings and deprecation warning
2021-02-05 21:09:59 -08:00
Ogi Moore c2daa00714
Merge pull request #1546 from ixjlyons/imageview-init-keyevents
Guard against key events when there's no time axis in ImageView
2021-02-05 20:57:45 -08:00
Kenneth Lyons f1999d9a2c Guard against key events when there's no time axis in ImageView 2021-02-05 20:23:15 -08:00
pijyoi cd914495ec
get test_ref_cycles to pass (#1539)
* get test_ref_cycles to pass

let objects die without gc.collect()
if you don't have cyclic references, there should be no need to call
gc.collect()

the usage of gc.collect() was causing pytest running with coverage to
crash on Python 3.7 / PySide2 5.12 / {Linux, Windows}.

* remove imports used only by the removed code
2021-02-04 20:18:53 -08:00
Ogi Moore f336ac2d91
Merge pull request #1541 from pijyoi/remove_qt4_qtest_shim
use qWaitForWindowExposed instead of qWaitForWindowShown
2021-02-04 16:15:39 -08:00
KIU Shueng Chuan 62ded33222 remove qtest shim for Qt5 too
not considered public API of pyqtgraph
2021-02-05 07:30:33 +08:00
Ogi Moore 601e19745b
Merge pull request #1542 from bilderbuchi/patch-1
Fix typo
2021-02-03 23:15:57 -08:00
Christoph Buchner 6974b25a5f
Fix typo 2021-02-04 08:07:01 +01:00
Ogi Moore 6123e16f54
Merge pull request #1540 from ixjlyons/siprefix-without-suffix
Support siPrefix with no suffix in SpinBox
2021-02-03 22:16:26 -08:00
KIU Shueng Chuan 711dcd4d5a use qWaitForWindowExposed instead of qWaitForWindowShown
qWaitForWindowShown has been obsolete since Qt 5.6
2021-02-04 11:35:19 +08:00
Kenneth Lyons 15bdd89293 Add a few minor notes to docs on suffix/siPrefix 2021-02-03 17:27:41 -08:00
Kenneth Lyons 0e90e70e2a Update SpinBox tests for siPrefix without suffix 2021-02-03 17:18:13 -08:00
Kenneth Lyons 498f2e512b Add siParse to API docs 2021-02-03 17:14:06 -08:00
Kenneth Lyons cd10719837 Support siPrefix with no suffix in SpinBox 2021-02-03 17:14:06 -08:00
Kenneth Lyons 66c77118dc
Support suffix for int parameters (#1528)
* Support suffix for int parameters

* Fix spinbox test for new int formatting

* Tune up SpinBox tests a bit
2021-02-03 12:30:05 -08:00
Ogi Moore 7abf7d36d0
Merge pull request #1462 from Ryytikki/patch-1
Added option to use "None" for adj in setData
2021-01-31 23:03:44 -08:00
Ogi Moore 89d20119fe Update docstring and error message 2021-01-31 22:36:59 -08:00
Ogi Moore 983a3769e7 Check for None first 2021-01-31 22:32:56 -08:00
Ogi Moore f5a823bf38
Merge pull request #1533 from pijyoi/kill_qt4_shim
Remove scale rotate translate Qt4 shims
2021-01-31 22:12:11 -08:00
Ogi Moore 9da7b8f7c1
Merge pull request #1469 from lidstrom83/ptree
Various improvements to parametertree
2021-01-31 22:11:33 -08:00
Ogi Moore e02fc10a40 handle text flags like axisitem 2021-01-31 21:52:51 -08:00
Ogi Moore d70a009c29 Address more PyQt6 enum type shenanigans 2021-01-31 21:17:44 -08:00
Ogi Moore 0495f1dcce Replace deprecated method with suggested one 2021-01-31 20:39:07 -08:00
KIU Shueng Chuan ac4eaa6860 remove redundant shims 2021-02-01 09:12:42 +08:00
KIU Shueng Chuan 185f9c7dad remove scale, rotate and translate shims 2021-02-01 09:06:23 +08:00
Ogi Moore 7b3fdda1e4 Merge branch 'master' into ptree 2021-01-31 13:36:53 -08:00
KIU Shueng Chuan 7192df7032 remove setMargin and setResizeMode shims 2021-01-31 22:21:32 +08:00
KIU Shueng Chuan 97f5459573 regenerate plotConfigTemplate.ui for Qt5
the old ones were using obsoleted method "setMargin"
2021-01-31 22:12:55 +08:00
KIU Shueng Chuan 327581983f delete some more Qt4 generated templates 2021-01-31 22:11:49 +08:00
pijyoi 9d89d10bcf
some optimizations for rescaleData (#1518)
1) use float32 instead of float64 for low precision inputs
2) use in-place operations to avoid unnecessary copies
2021-01-30 14:38:34 -08:00
Ogi Moore 56ee690d58
Merge pull request #1527 from ixjlyons/improve-parameter-docs
Improve parametertree documentation coverage
2021-01-30 11:01:08 -08:00
Kenneth Lyons c24d25bce3 Improve parametertree documentation
- Increase cross-referencing
- Give all built-in parameter and parameter items at least minimal
  docstring
- Start improving coverage of the special options available for some
  parameters
- Organize the built in parameters reference for easier navigation
2021-01-30 10:06:49 -08:00
pijyoi ce8c3262f8
switch to use of QOpenGLWidget in GraphicsView.py (#1525)
* switch to use of QOpenGLWidget in GraphicsView.py

experimental plotting in PlotCurveItem gets broken by this. so we allow
Qt5 users to opt back to using QGLWidget with the enableExperimental
option.

* allow Qt6 users to turn on enableExperimental

to more easily allow users to see the broken-ness.

* drop QGLWidget, use only QOpenGLWidget
2021-01-30 08:59:29 -08:00
Ogi Moore e9eb8d50b6
Merge pull request #1523 from pijyoi/lose_six 2021-01-29 05:11:42 -08:00
KIU Shueng Chuan 6b7afbf75c remove six module 2021-01-29 16:13:27 +08:00
Ogi Moore 961cdac51c
Infiniteline emits clicked signal event (#1522) 2021-01-28 22:02:51 -08:00
Dennis Göries 5bb3800adc
ItemSample: Allow toggle of visibility via mouse click in LegendItem (#1497)
* Legend toggle directly on ItemSample

* Add invisible Eye icon

* Include package data and remove username from svg

* Allow svg and png in the setup.py and cleanup sg
2021-01-28 21:14:41 -08:00
Sérgio Peixoto 3f02b30140
Bugfix/wrong translate implementation (#1520)
* Removes all translate call on the parameter name and moves them into the title instead allowing to decouple visualization from code logic

* Removes all translate calls from the Exporter class property Name and moves the translation logic when setting the QListWidgetItems for the formatList

* Adds missing call to translation function for the export action on GraphicsScene
2021-01-28 08:42:18 -08:00
Ogi Moore b094945dbc
Merge pull request #1517 from pijyoi/shm_close
fix RemoteSpeedTest shutdown errors
2021-01-27 15:49:04 -08:00
KIU Shueng Chuan 2f4ceee1ce fix RemoteSpeedTest shutdown errors
fix BufferError: cannot close exported pointers exist
for some reason, even though the ctypes object falls out of function
scope, it causes a lingering reference.
in any case, the use of ctypes is no longer necessary.

Don't change temporary files mid-way for Darwin
This fixes the CI issues on Darwin.

close the remote process on app shutdown.
2021-01-28 07:19:54 +08:00
Ogi Moore b54aa3914d
Attempt i18n localization (#1513)
* Trying translate on exporter strings

* Try translate on other misc context menu strings

* First f-string and I screw it up...

* add more translation calls
2021-01-27 11:34:32 -08:00
Ogi Moore 309195ceea
Fix windows hidpi (#1516)
* set environment variables before starting QApp

* fix-422

* Better support of hidpi

* Fix Typo in App-Name

* Remove fontScaleFactor bits

* Add documenation for hidpi displays

* Fix pg not defined
2021-01-27 10:59:07 -08:00
Ogi Moore 85773e4530
Revert "have mkQApp configure QApplication such that it handles HIDPI displays on Windows (#1509)" (#1515)
This reverts commit 98f6b2f1a5.
2021-01-27 10:42:38 -08:00
Martin 219f79947e maintain non-scaling behavior for parallel sides
make sure aspectLocked still gets checked
add example
2021-01-27 10:39:08 -08:00
Ogi Moore 98f6b2f1a5
have mkQApp configure QApplication such that it handles HIDPI displays on Windows (#1509)
* set environment variables before starting QApp

* fix-422

* Better support of hidpi

* Fix Typo in App-Name

* Remove fontScaleFactor bits

* Add documenation for hidpi displays
2021-01-27 10:05:56 -08:00
Valentin Valls 9456d07ae8 Fix scale-rotate ROI handler to allow to use a random scale axis and not only x/y
The code relative to scaleSnap is maybe broken
2021-01-27 09:52:50 -08:00
pijyoi 1044a7b6c4
Add almost all examples to ExampleApp (#1511)
* fix: delete generated designerExample_*.py files

designerExample.py loads designerExample.ui directly

* remove unused examples/utils.py

* add almost all examples in folder

* use mkQApp and don't set style nor palette

not needed for an example and also avoids a PyQt6 6.0 refcount bug in
app.setStyle()

* bold interesting examples

* test_examples.py needs to know about Namespace too

* Revert "remove unused examples/utils.py"

This reverts commit 2eddead459.

* categorize examples lists in utils.py
2021-01-26 13:45:53 -08:00
Ogi Moore 74bcd3ba87
Merge pull request #1510 from pijyoi/update_exapp 2021-01-23 08:43:25 -08:00
KIU Shueng Chuan d96ec314be RemoteGraphicsView.py : fix mouse interactions for Qt 5.12
mouse interactions had previously only been tested on Qt 5.15 and
Qt 6.0, and found to be not working on Qt 5.12.
differences in Qt 5.12 and Qt 5.15 are documented in the comments.

an addition bug found (and fixed) was that right-click was drawing
the pop-up menu away from the mouse position.
2021-01-23 19:28:11 +08:00
KIU Shueng Chuan 5186cbd80b remove Qt4 generated template files 2021-01-23 12:12:20 +08:00
KIU Shueng Chuan 59fd72a3d1 exampleLoaderTemplate.ui : add Qt6 and remove Qt4 2021-01-23 11:43:34 +08:00
Ogi Moore 8670407779
Merge pull request #1502 from pijyoi/pyqt6_compat
Pyqt6 compat
2021-01-22 17:42:36 -08:00
KIU Shueng Chuan 6c760f3de1 add PyQt6 to CI
skip tests that don't work for Qt6

add Qt6 and remove Qt4 from test_examples.py

update README.md

switch mouse tests to use QPointF

this eliminates all the special casing for different bindings
2021-01-23 08:31:00 +08:00
KIU Shueng Chuan eec411a3c6 fixup Flowchart for PyQt6 2021-01-23 08:31:00 +08:00
KIU Shueng Chuan d0c062d7e5 Revert "workaround missing setStops binding"
This reverts commit c4addbeaea.
2021-01-23 08:30:59 +08:00
KIU Shueng Chuan 2e688cf672 PySide6 : shim missing binding QGradient.setStops 2021-01-23 08:30:59 +08:00
KIU Shueng Chuan 3a9e81cc49 update RemoteGraphicsView.py for Qt6 2021-01-23 08:30:59 +08:00
KIU Shueng Chuan c0336acc11 bug: style() should have been styleHint()
Style is enum for { StyleNormal, StyleItalic, StyleOblique }
2021-01-23 08:29:52 +08:00
KIU Shueng Chuan 6dbda78231 Container.py : fix RecursionError 2021-01-23 08:29:52 +08:00
KIU Shueng Chuan 8a091859f1 GradientWidget.py : workaround or-ing of enum flag values 2021-01-23 08:29:52 +08:00
KIU Shueng Chuan 0957735255 AxisItem.py : workaround or-ing of text flags 2021-01-23 08:29:52 +08:00
KIU Shueng Chuan 04e0a5e5af WidgetGroup.py : PyQt6 was taking PyQt4 codepath
we drop PyQt4 codepath
2021-01-23 08:29:51 +08:00
KIU Shueng Chuan edea696bc3 ROI.py : pyqt6 has no KeyboardModifier class
the correct type to use is actually KeyboardModifiers
2021-01-23 08:29:51 +08:00
KIU Shueng Chuan 13d652c794 convert to QPointF mouse event position
DockDrop.py : use QPointF mouse coords
2021-01-23 08:29:45 +08:00
KIU Shueng Chuan 607db15949 call super() on virtual QWidget methods 2021-01-23 08:29:44 +08:00
KIU Shueng Chuan 0fa4557ad6 don't cast buttons, enums and flags to int 2021-01-23 08:29:44 +08:00
KIU Shueng Chuan 3ce7f58384 import sip from Qt.py 2021-01-23 08:29:43 +08:00
KIU Shueng Chuan dcbddb0abf add PyQt6 support to Qt.py and functions.py 2021-01-23 08:29:43 +08:00
KIU Shueng Chuan ab41c03358 generate _pyqt6.py files
VideoTemplate_pyside6.py : regenerate for cuda feature
2021-01-23 08:29:39 +08:00
Ogi Moore 157ea91b23
Merge pull request #1507 from j9ac9k/run-apt-update-first
Run apt update first
2021-01-21 14:23:35 -08:00
Ogi Moore 94e5bcff02 Run apt update first 2021-01-21 14:14:17 -08:00
Ogi Moore 122f3077d3
Merge pull request #1506 from j9ac9k/fix-typo-in-glviewwidget
Fixed typo in GLViewWidget
2021-01-21 09:06:57 -08:00
Ogi Moore 4e070f40bc Fixed typo 2021-01-21 08:48:54 -08:00
Ogi Moore a142bd6217
Merge pull request #1504 from j9ac9k/use-getenv-correctly
Use os.getenv, not os.environ
2021-01-19 23:35:58 -08:00
Ogi Moore b3a0051a99 Use os.getenv, not os.environ 2021-01-19 23:23:24 -08:00
Martin Chase 1654cb62ac
Small ImageItem-related improvements (#1501)
* Initial asv configuration

* makeARGB benchmarks are working

* Fix array type checking and allow making QImage in greyscale mode

* Performance improvements

* benchmark minor update

* Add CLI args to video speed test for easier / automated benchmarking

* udpate asv conf

* use a buffer-qimage so we can avoid allocing so much

this should improve performance under windows

* Add CLI args to video speed test for easier / automated benchmarking

* use a buffer-qimage so we can avoid allocing so much

this should improve performance under windows

* playing with numba

* oh, mins/maxes in the other order

* maybe put the cupy in here and see what happens

* pre-alloc for gpu and cpu

* handle possibility of not having cupy

* no numba in this branch

* organize imports

* name them after their use, not their expected device

* cupy.take does not support clip mode, so do it explicitly

* add CUDA option to the VideoSpeedTest

* rename private attr xp to _xp

* handle resizes at the last moment

* cupy is less accepting of lists as args

* or somehow range isn't allowed? what histogram is this?

* construct the array with python objects

* get the python value right away

* put LUT into cupy if needed

* docstring about cuda toolkit version

* better handling and display of missing cuda lib

* lint

* import need

* handle switching between cupy and numpy in a single ImageItem

* only use xp when necessary

we can now depend on numpy >= 1.17, which means __array_function__-implementing cupy can
seamlessly pass into numpy functions. the remaining uses of xp are for our functions which
need to allocate new data structures, an operation that has to be substrate-specific.

remove empty_cupy; just check if the import succeeded, instead.

* use an option to control use of cupy

* convert cupy.ceil array to int for easier mathing

* RawImageWidget gets to use the getCupy function now, too

* raise error to calm linters; rename for clarity

* Add Generated Template Files

* document things better

* cruft removal

* warnings to communicate when cupy is expected but somehow broken

* Merge branch 'cupy-rebase' into 'l/imageitem-performance'

Abundant conflicts; accept theirs in nearly every case.

* playing with settings to suss out timeout

* playing with more stuff to suss out timeout

* replace with empty list

* skip test_ExampleApp on linux+pyside2 only

* clean out some bits that no longer make sense; linty

* ignore airspeed velocity dir

* lint

* tidy up for merge

* lint

* lint, avoid shadowing

* specific import; run-as-script setup

Co-authored-by: Luke Campagnola <luke.campagnola@gmail.com>
Co-authored-by: Ogi Moore <ognyan.moore@gmail.com>
2021-01-19 23:19:03 -08:00
Torsten Sommer 510626c15f
Add NonUniformImage, example and tests. (#509)
* Add NonUniformImage, example and tests.

* Use updated test-data tag

* Fix line ending, remove lut.setLevels keyword arguments call

Co-authored-by: Ogi <ognyan.moore@gmail.com>
2021-01-19 21:43:58 -08:00
Martin Chase f2b4a15b2d
Performance enhancement: use CUDA in ImageItem (#1466)
* Add CLI args to video speed test for easier / automated benchmarking

* use a buffer-qimage so we can avoid allocing so much

this should improve performance under windows

* playing with numba

* oh, mins/maxes in the other order

* maybe put the cupy in here and see what happens

* pre-alloc for gpu and cpu

* handle possibility of not having cupy

* no numba in this branch

* organize imports

* name them after their use, not their expected device

* cupy.take does not support clip mode, so do it explicitly

* add CUDA option to the VideoSpeedTest

* rename private attr xp to _xp

* handle resizes at the last moment

* cupy is less accepting of lists as args

* or somehow range isn't allowed? what histogram is this?

* construct the array with python objects

* get the python value right away

* put LUT into cupy if needed

* docstring about cuda toolkit version

* better handling and display of missing cuda lib

* lint

* import need

* handle switching between cupy and numpy in a single ImageItem

* only use xp when necessary

we can now depend on numpy >= 1.17, which means __array_function__-implementing cupy can
seamlessly pass into numpy functions. the remaining uses of xp are for our functions which
need to allocate new data structures, an operation that has to be substrate-specific.

remove empty_cupy; just check if the import succeeded, instead.

* use an option to control use of cupy

* convert cupy.ceil array to int for easier mathing

* RawImageWidget gets to use the getCupy function now, too

* raise error to calm linters; rename for clarity

* Add Generated Template Files

* document things better

* cruft removal

* warnings to communicate when cupy is expected but somehow broken

* playing with settings to suss out timeout

* playing with more stuff to suss out timeout

* replace with empty list

* skip test_ExampleApp on linux+pyside2 only

Co-authored-by: Luke Campagnola <luke.campagnola@gmail.com>
Co-authored-by: Ogi Moore <ognyan.moore@gmail.com>
2021-01-19 21:26:24 -08:00
Ogi Moore 78bc0fd3ca
Merge pull request #1495 from pijyoi/future_compat
some fixes for PySide6 future compatibility
2021-01-19 21:05:50 -08:00
Ogi Moore dc17e2ef1c
Merge pull request #1503 from j9ac9k/fix-git-head-reference-in-ci
Fix git head reference in ci
2021-01-19 21:05:14 -08:00
KIU Shueng Chuan 54d25ffbcf README.md : update support matrix 2021-01-20 12:41:29 +08:00
Ogi Moore 0bf6cccd57 Up the faulthandler_timeout parameter to 30 2021-01-19 20:36:54 -08:00
Ogi Moore ee623c0fa9 Get testdata using checkout action 2021-01-19 20:20:19 -08:00
Ogi Moore c62838079b
Merge pull request #1500 from pijyoi/bug_aligncenter
bug: AlignCenter should have been AlignHCenter
2021-01-18 20:44:09 -08:00
KIU Shueng Chuan b6e713c306 bug: AlignCenter should have been AlignHCenter
from the Qt documentation,
- "AlignCenter = AlignVCenter | AlignHCenter"
- "You can use at most one horizontal and one vertical flag at a time.
  Qt::AlignCenter counts as both horizontal and vertical"
- "Conflicting combinations of flags have undefined meanings"

for AxisItem.py, from the code structure, it would appear that the
intent was to use AlignHCenter.

for ROI.py, AlignCenter == AlignCenter | AlignVCenter
2021-01-19 09:45:56 +08:00
KIU Shueng Chuan 9f54baed0c test_reload.py: skip for PySide6 and Python 3.9 2021-01-16 14:37:21 +08:00
KIU Shueng Chuan d0a7ceea2d relax image tolerance for PySide6 2021-01-16 14:37:21 +08:00
KIU Shueng Chuan 28c0ea4b33 test_ref_cycles.py : change skip criteria
test_ImageView()
- PySide6 fails the same as PySide2

test_PlotWidget() and test_GraphicsWindow()
- PySide6 succeeds.
- PySide2 also succeeds. (at least on Linux and on version 5.15.2)
2021-01-16 14:37:21 +08:00
Ogi Moore 901f772b5f Skip matplotlib qt6 tests 2021-01-16 14:37:21 +08:00
Ogi Moore 21c5627282 Adding PySide6 to CI
Install package for libopengl.so
Mandate the use of ubuntu 20.04
2021-01-16 14:36:38 +08:00
KIU Shueng Chuan e03d4be767 fix: QComboBox::AdjustToMinimumContentsLength is no longer available
documentation for Qt 4.8 and Qt 5.12 have advised to "Use
AdjustToContents or AdjustToContentsOnFirstShow instead"

documentation in Qt 5.15 no longer shows AdjustToMinimumContentsLength.
2021-01-16 14:33:47 +08:00
KIU Shueng Chuan f21dfd9d95 fix get_resolution.py to use QScreen
QDesktopWidget is deprecated in Qt5 and removed in Qt6
2021-01-16 14:33:47 +08:00
KIU Shueng Chuan 4b1a8fe6b4 call GraphicsView.enterEvent() with QEnterEvent
Qt5 prototype is QWidget::enterEvent(QEvent*)
Qt6 prototype is QWidget::enterEvent(QEnterEvent*)
where QEnterEvent inherits from QEvent

RemoteGraphicsView.enterEvent() is actually already called with a
QEnterEvent instance, so all we need to do is to be able to reconstruct
it in Renderer.enterEvent()
2021-01-16 00:16:28 +08:00
KIU Shueng Chuan 74683be68b GraphicsScene.py : check for C++ item live-ness
this gets triggered in PySide6 but not in PyQt5, PySide2.
2021-01-15 13:12:36 +08:00
KIU Shueng Chuan 10530568f0 ScatterPlotItem.py: use non _USE_QRECT codepath for PySide6
verified by using ScatterPlotSpeedTest.py that PySide6 benefits from this.
2021-01-15 12:47:13 +08:00
KIU Shueng Chuan 6c9b910c5c RemoteGraphicsView.py : include PySide6 in PySide family
this is only sufficient to make remote rendering work.

various errors still get triggered under PySide6 when we try remote plotting.
2021-01-15 10:25:24 +08:00
KIU Shueng Chuan 4f619bbb4c update glinfo.py to use QOpenGLWidget 2021-01-15 08:25:09 +08:00
KIU Shueng Chuan 9145d7f24d switch to usage of QOpenGLWidget
this drops support for Qt4
2021-01-15 08:25:09 +08:00
KIU Shueng Chuan dc46812e5a Qt.py : provide QOpenGLWidget (Qt5,6) instead of QGLWidget (Qt4,5) 2021-01-15 08:25:08 +08:00
KIU Shueng Chuan 44da583511 bootstrap.py: use importlib to generically support all bindings 2021-01-15 08:25:08 +08:00
KIU Shueng Chuan 71e1ea34fd MatplotlibWidget.py: drop Qt4 support
PR for adding Qt6 support to matplotlib indicates that both Qt5 and Qt6
will use backend_qt5agg
2021-01-15 08:25:08 +08:00
KIU Shueng Chuan cc2b811ed1 drop usage of QDesktopWidget
this drops support for Qt4
2021-01-15 08:25:08 +08:00
KIU Shueng Chuan 283e9eb563 drop lack of palette compatibility with Qt4 2021-01-15 08:25:08 +08:00
KIU Shueng Chuan 966ae7a3df import template files using importlib
this lets us support the various bindings w/o having to add binding
specific code.

it breaks PyQt4 support since PyQt4 template files are suffixed as
"_pyqt" rather than "_pyqt4"
2021-01-15 08:25:08 +08:00
KIU Shueng Chuan 5732ca8213 initExample.py: add PySide6 and PyQt6
drop PyQt4 and PySide
2021-01-15 08:25:07 +08:00
KIU Shueng Chuan 359f441973 ExampleApp.py : remove Qt4 paletteChanged signal compatibility 2021-01-15 08:25:07 +08:00
KIU Shueng Chuan ca9f3f2d92 fix: glViewPort() takes integral arguments 2021-01-15 08:25:07 +08:00
KIU Shueng Chuan 3584736155 generate template files for pyside6 2021-01-15 08:25:07 +08:00
KIU Shueng Chuan aa1f4e7547 add PySide6 and PyQt6 to rebuildUi.py 2021-01-15 08:25:07 +08:00
KIU Shueng Chuan 1a6918a241 replace QDesktopWidget() with QGuiApplication.primaryScreen()
the "try, except" could be dropped if we drop Qt4 support.

however, primaryScreen() may not be the right screen.
2021-01-15 08:25:07 +08:00
KIU Shueng Chuan 92016d3d5a add imports of _pyside6 files 2021-01-15 08:25:06 +08:00
KIU Shueng Chuan 6e2a28260a add QImage support for PySide6
also update for PySide2.QImage to take in ndarray directly.
2021-01-15 08:25:06 +08:00
KIU Shueng Chuan 6dc6cda0fc add PySide6 to Qt.py 2021-01-15 08:25:06 +08:00
KIU Shueng Chuan da0a94643c change QPalette.Background to QPalette.Window
the former is obsolete in 5.15 and is removed in 6.0
2021-01-15 08:25:06 +08:00
KIU Shueng Chuan c4addbeaea workaround missing setStops binding 2021-01-15 08:25:05 +08:00
KIU Shueng Chuan b0f7dda102 QFont.setWeight(75) is redundant
QFont.setBold(True) calls QFont.setWeight(QFont.Weight.Bold)

in Qt 5, QFont.Weight.Bold == 75
in Qt 6, QFont.Weight.Bold == 700

in PySide6, QFont.setWeight() no longer accepts an integer value.
2021-01-15 08:25:05 +08:00
KIU Shueng Chuan f863390409 change MidButton to MiddleButton
the former is no longer present in Qt 6 as an alias
2021-01-15 08:25:05 +08:00
KIU Shueng Chuan 119c5fa3d0 convert QTreeWidget.setFirstItemColumnSpanned
convert QTreeWidget.setFirstItemColumnSpanned(item, True) to
item.setFirstColumnSpanned(True)

the former is deprecated since Qt 5.15.2 and removed in Qt 6.
2021-01-15 08:25:05 +08:00
Ogi Moore 4abbc2d5cd
Merge pull request #1498 from jjuod/scrollingplotfix
PlotDataItem now signals on setPos (fix #1494)
2021-01-13 13:16:31 -08:00
jjuod 3cb1128bc2 PlotDataItem now signals on setPos (fix #1494) 2021-01-13 21:57:40 +13:00
Ogi Moore 45e0464163
Merge pull request #1493 from pijyoi/fastinv
invert QTransform using adjoint() and determinant()
2021-01-12 21:05:46 -08:00
KIU Shueng Chuan 3a342b50e2 Revert "Add cache for mapRectFromView"
This reverts commit 55e1f2c520.
2021-01-13 12:43:51 +08:00
Dennis Göries 2affe322ec
PlotItem: Fix enableMenu setting when passing a viewbox (#1496)
* PlotItem: enableMenu setting when passing a viewbox
2021-01-12 20:34:14 -08:00
KIU Shueng Chuan fd85076bb6 invert QTransform using adjoint() and determinant() 2021-01-10 13:58:31 +08:00
Julius Juodakis 386dcf8180
setSpan broke LinearRegionItem (#1488) (#1491) 2021-01-06 14:54:33 -08:00
Nils Nemitz 85719fd8df
Colormap extension (#1424)
* extend ColorMap functionality for palette management

* manual merge with changes in master branch

* extend ColorMap functionality for palette management

* manual merge with changes in master branch

* light mode / dark mode swapping demo

* color map updates

* added ColorCET and Matplotlib import for color maps

* minor cleanup

* restored lost indent

* Code cleanup

* Add colorcet as optional dependency

Co-authored-by: Ogi Moore <ognyan.moore@gmail.com>
2021-01-04 22:01:30 -08:00
Dennis Göries b622e22877
LegendItem: Make ItemSample customizable (#1404)
* LegendItem: Introduce itemStyles and provide ToggleItem

Show example

* Minor cleanup of the legend item and test

* Make ItemSample customizable

* Remove example modifications

* Changes for sampleType according to review
2021-01-04 21:02:08 -08:00
Hanwant e209be20e5
Use log modulus transform for y axis log scaling (#1476)
* Use log modulus transform for y axis log scaling

* Update log modulus to use eps and retain behaviour around -1 < x < 1

* Update setLogMode Dosctring

* Update setLogMode docString

Co-authored-by: Hanwant <admin@madigan.tech>
2021-01-04 19:27:03 -08:00
Martin Chase 1a71bb53c4
add unicode units (#1471)
* adds unicode units

* keep "u" and "Ohm" for compatibility
* add c, d, da and h
* lint

* py2 compatible u"" strings
2021-01-03 14:28:56 -08:00
Lee Tirrell 64e04e3120
Fix #798 (#1487) 2021-01-03 14:28:40 -08:00
Ogi Moore e94f53ac20
minor adjustment on when test runs (#1479)
* minor adjustment on when test runs

* Remove pytest publish results, add sphinx nitpicky

* Deal with nit-picky mode later

* why bother w/ those artifacts...
2021-01-03 12:31:53 -08:00
Yoonyoung (Jamie) Cho d8e4911fcd
Fixed GLViewWidget Gimbal Lock with Quaternion Parametrization (#909)
* Fixed GLViewWidget Gimbal Lock with Quaternion Parametrization

* fixed rotation name

* fixes extraneous pos argument and restore compatibility

* remove redundant getAxisAngle() in rotation (for Qt4 compatibility)

* GLViewWidget takes rotationMethod parameter

* Avoid merge conflict

* Fix docstring

Co-authored-by: Ogi Moore <ognyan.moore@gmail.com>
2020-12-24 21:45:02 -08:00
Ogi Moore 0356a358b3
Remove linting check, add pytest test publishing (#1477) 2020-12-23 23:04:30 -08:00
Daniel Lidstrom daafb1d801 Revert previous commit 2020-12-23 00:05:36 -08:00
Kyle Sunden d3049e41d7
Merge pull request #1474 from j9ac9k/migrate-to-github-actions
Migrate To Github Actions
2020-12-23 00:32:55 -06:00
Ogi Moore 5d33ccff8d Cleanup ExamplesApp 2020-12-22 22:10:59 -08:00
Ogi Moore e5f123deb2 Add more badges 2020-12-22 22:08:31 -08:00
Ogi Moore cc6a4d200c Add analyze segment - thanks to @ksunden 2020-12-22 21:18:13 -08:00
Ogi Moore fcb387c86e Go to one yml file 2020-12-22 12:32:35 -08:00
Ogi Moore c31cba5e06 Update README 2020-12-22 12:16:05 -08:00
Ogi Moore bae760e598 Update pip first 2020-12-22 12:15:59 -08:00
Ogi Moore b98216a2ea Use matplotlib qt5agg backend for pyside2 2020-12-22 10:27:15 -08:00
Ogi Moore 11db50dee5 Remove azure-pipelines configs 2020-12-22 10:27:12 -08:00
Ogi Moore 1c1187a10f swallow xvfb config option warnings 2020-12-22 10:26:20 -08:00
Ogi Moore 6eace48663 Skip openGL tests on some macOS configs 2020-12-22 10:26:19 -08:00
Ogi Moore 2689cdb5f6 Fix regex warning 2020-12-22 10:26:19 -08:00
Ogi Moore e7f64a8fc1 add pytest-xdist 2020-12-22 10:26:19 -08:00
Ogi Moore a7d9034f83 Update mesa3d drivers 2020-12-22 10:26:19 -08:00
Ogi Moore 181b6ee005 Re-introduce xvfb debug steps 2020-12-22 10:26:19 -08:00
Ogi Moore f4df660363 Skip test_ExampleApp 2020-12-22 10:26:19 -08:00
Ogi Moore 3cd9f9ff63 skip test_reload 2020-12-22 10:26:19 -08:00
Ogi Moore d0b26112bc add quotes around string with astricks 2020-12-22 10:26:19 -08:00
Ogi Moore 34e9ee7c91 Add pre-build stage 2020-12-22 10:26:19 -08:00
Kyle Sunden 3b1e55af1e
MAINT: Post 0.11.1 release, drop py2, qt4 (#1473)
* MAINT: Post 0.11.1 release, drop py2, qt4

This focuses on distribution, tests, and docs. This may not be comprehensive, but covers the cases I found by looking and a few greps

Noteably, this does not change any actual internal code yet, to avoid merge conflicts with pending PRs.

* NEP 29 language/versions
2020-12-22 10:25:06 -08:00
Daniel Lidstrom c2f0de0471 Attempt at passing Qt 4 CI pipelines 2020-12-21 23:15:57 -08:00
Daniel Lidstrom 8105385230 Add not enabled example 2020-12-21 23:10:44 -08:00
Daniel Lidstrom 6a8f7779dc Add tool tip support to action and group parameters 2020-12-21 23:09:19 -08:00
Daniel Lidstrom 2260030845 Focus change bug fix 2020-12-21 22:34:12 -08:00
Daniel Lidstrom acca19a1b3 Clearing selection on wheelEvent is buggy, so don't 2020-12-21 22:22:12 -08:00
Daniel Lidstrom b164e54e15 Get parameter's item in a nicer way 2020-12-21 20:48:15 -08:00
Daniel Lidstrom 4618c705e2 Fixed bug where enabled opt is not respected 2020-12-21 20:40:34 -08:00
Daniel Lidstrom 4e8a609375 Fixed bugs with setting expanded and setExpanded 2020-12-21 17:34:43 -08:00
Daniel Lidstrom fab7b20094 ColorButton sizeHint override unnecessary 2020-12-21 17:18:34 -08:00
Daniel Lidstrom 944b75ffcd Don't miss any widgets when updating readonly 2020-12-21 17:11:22 -08:00
Daniel Lidstrom 4561b18377 Consistently emit values with Parameter.sigValueChanging 2020-12-21 12:30:08 -08:00
Daniel Lidstrom d737d80c52 Improved data race test 2020-12-20 23:08:38 -08:00
Daniel Lidstrom bea0fc1135 No interaction with WidgetParameterItem.subItem 2020-12-20 22:41:47 -08:00
Daniel Lidstrom 8519efdd8d Changed my mind 2020-12-20 19:12:11 -08:00
Daniel Lidstrom 0703e3db9b Ensure synchronization of parameter and widget's values 2020-12-20 18:43:11 -08:00
Kyle Sunden cd40562121
Merge pull request #1472 from ksunden/changelog
Update Changelog for release 0.11.1
2020-12-19 20:39:52 -06:00
Ogi Moore 195f609b31 Update __version__ 2020-12-19 09:17:23 -08:00
Ogi Moore ab478d1231 Page 1 2020-12-19 08:54:27 -08:00
Ogi Moore cf64e75de3 Page 2 2020-12-19 08:31:22 -08:00
Kyle Sunden 625469af74 page 3 2020-12-19 01:08:33 -06:00
Kyle Sunden fa444a1d94 page 4 2020-12-18 23:49:50 -06:00
Ogi Moore b2c9b98bae Add Page5 2020-12-18 21:11:17 -08:00
Kyle Sunden 35167df2e6 Update Changelog for release 0.11.1 2020-12-18 21:35:15 -06:00
miranis c5c41b9090
zero-step in np.arange (#1468) 2020-12-17 22:48:55 -08:00
Daniel Lidstrom 6313bb8ae3 Avoid deprecation warnings 2020-12-17 19:00:22 -08:00
Daniel Lidstrom 5a48b68795 Bugfix 2020-12-17 18:17:06 -08:00
Daniel Lidstrom d9c6a2764a Removed pointless subclass method 2020-12-17 18:09:51 -08:00
Daniel Lidstrom ba304faa05 Provide size hints for nicer looking trees that don't need to be manually sized 2020-12-17 17:45:04 -08:00
Daniel Lidstrom db43c9447c Allow default button for text and colormap parameters 2020-12-17 09:53:39 -08:00
Daniel Lidstrom edf42114f8 Show colormap as sub item 2020-12-17 01:08:46 -08:00
Daniel Lidstrom 02079aec8a Handle text with WidgetParameterItem and SimpleParameter 2020-12-17 01:07:49 -08:00
lidstrom83 3af23725ca
Scatter Plot Improvements (#1420)
* Added hovering demo to ScatterPlot example

* Use Qt's serialization for SymbolAtlas.symbolMap keys

Yields significant performance improvements when updating the scatter plot's options. See e.g. the plot hover example.

* Further optimized scatter plot picking

* Fix ScatterPlot example tool tip

* Clean up while I'm here

* Compatibility

* Some simple optimizations for ScatterPlotItem

Speedups for ScatterPlotSpeedTest.py:
~50% without pxMode
~ 0% pxMode with useCache
~30% pxMode without useCache

* ~3x speedup in scatter plot speed test with pxMode

* More optimization low-hanging fruit for the scatter plot

* Removed hover example to lazily pass tests

* Avoid segfault

* Re-add hover example to ScatterPlot.py

* Switch to id-based keying for scatter plot symbol atlas

- Use cases exist where serialization-based keying is a significant bottleneck, e.g. updating without atlas invalidation when a large variety pens or brushes are present.
- To avoid a performance hit, the onus is on the user to carefully reuse pen and brush objects.

* Optimized caching in scatter plot hovering example

* Fixed and optimized scatter plot hovering example

* Minor scatter plot optimization

* Cleanup

* Store hovered points in a set for the hovering example

* Keep a limited number symbol atlas entries around for future reuse

* Added a docstring note to remind the user to reuse QPen and QBrush objects for better performance

* Tidied up hovering example

* Typo

* Avoid unnecessary atlas rebuilds

* Refactored SymbolAtlas

* Efficient appending to SymbolAtlas

* SymbolAtlas rewrite

* Cleanup and profiling

* Add randomized brushes to speed test

* Add loc indexer to ScatterPlotItem

* Profile ScatterPlotItem.paint to identify bottlenecks

* Reuse targetRect to improve paint performance

* Readability improvements (opinionated)

* Only need to set x and y of targetRect

- w and h can stay set to 0 (not entirely sure why)
- this is a bit faster than setting all of x, y, w, h

* Minor renaming

* Strip off API changes and leave to another PR

* Renaming

* Compatibility

* Use drawPixmap(x, y, pm, sx, sy, sw, sh) signature to avoid needing to update QRectFs

* Use different drawing approaches for each Qt binding for performance reasons

* Fix a bug introduced two commits ago

Incidentally, I think there is a similar bug in the main branch currently.

* Minor performance and readability improvements

* Strip out source and target QRectF stuff

* Bring source and target QRectF stuff back in a less coupled way

* Leave deprecating getSpotOpts for another PR

* Compatibility fix

* Added docstrings and use SymbolAtlas__len__ where possible

* Fix export issue

* Add missing import

* Add deprecation warnings

* Avoid using deprecated methods

* Fix and cleanup max spot size measurements

* Make creation of style opts entries explicit

* Add hovering API to ScatterPlotItem

* Compatibility

* Marshal pen and brush lists in setPen and setBrush

* Fixed platform dependent bug
2020-12-16 11:07:39 -08:00
Marko Toplak 1847bfcf97
Remove ViewBox.childGroup ItemClipsChildrenToShape flag (#1458)
The flag was set on ItemClipsChildrenToShape to solve the issue of #316
"A GraphicsItem object overlaps the ViewBox border line" at Luke Campagnola's
suggestion to solve further issues that @espdev had. Luke wisely
commented that this approach needs extensive testing.

We tested it. It broke PDF export in Orange. :)

A solution to #316 was merged in PR #321, which was refined from the discussion
in #316. I am not sure that, given rest of #321, the ItemClipsChildrenToShape
was really needed. Even without modifications to ChildGroup I did not
see any border problems (but I could replicate them in pre-#321 pyqtgraph).

Removing this flag fixes (and unneeded supporting code) fixes PDF export
regression in Orange while borders still seem a-OK.
2020-12-09 22:45:21 -08:00
Ogi Moore a99bda0bb7
Use conda-forge on pyside2+linux (#1464) 2020-12-09 22:43:21 -08:00
Tom Mudway ca7b4580fa
Added option to use "None" for adj in setData
This allows you to easily create code to toggle lines on or off by setting to the appropriate array if on, or None if off. Currently you have to have 2 seperate setData calls, one with adj and one without
2020-12-07 17:55:51 -05:00
Marko Toplak 00fd63e859
arrayToPath: revert to old meaning of connect=ndarray parameter (#1461)
The i-th position of that array used to define if points (i) and (i+1)
were connected, but in master it defines whether points (i-1) and (i) are connected.
This commit reverts to (i) and (i+1) interpretation.
2020-11-27 07:57:26 -08:00
2xB 433b061e81
Fix TickSliderItem: Avoid ghost ticks | Improved customPlot.py code (#1459)
* Fix TickSliderItem: Avoid ghost ticks | Improved customPlot.py code

If `TickSliderItem.setTickValue` was called when a full repaint of the `TickSliderItem` was
not already scheduled, the tick was visible at the old and the new position. This could e.g. be seen
when using the autoscale button in the `customPlot.py` example.

Further, code from `customPlot.py` is improved to make use of `Tick.setVisible` instead of adding and
removing ticks based on their visibility.

* customPlot.py: Explain bool conversion

Co-authored-by: 2xB <2xB@users.noreply.github.com>
2020-11-26 22:28:03 -08:00
Ogi Moore d2255228ba
resolve ordering of issues presented in #1322 (#1456) 2020-11-23 12:12:14 -08:00
Luke Campagnola 6c7bd87592
Fill in non-finite plot values for Qt versions >= 5.12.3 (#1287)
* Fill in non-finite plot values for Qt versions >= 5.12.3

* handle the case of all nan entries

Co-authored-by: Ogi Moore <ognyan.moore@gmail.com>
2020-11-22 20:27:24 -08:00
Matt Liberty a3fbd18239
Clipped AxisItem tick value labels to prevent drawing artifacts #732 (#1447) 2020-11-21 00:46:31 -08:00
Ogi Moore 71a92a6fd2
Fix autosize not taking to correct range with TextItem in view (#1435)
* Removing first call to updateMatrix in resizeEvent
2020-11-21 00:02:32 -08:00
Julius Juodakis 0e816f1dbe
InfiniteLine caching calls merged (fixes #1450) (#1452) 2020-11-20 21:27:55 -08:00
2xB 5adb1b9a5b
Fixes for examples\customPlot.py (#1448)
* Fix examples\customPlot.py: Not object-oriented

Copy-paste error: I referenced a specific object instead of self. Fixed.

* Fix examples\customPlot.py: Allow calling setTicks more than once

This fixes a bug where TickSliderItem is expected to return ticks.keys() but while it returns ticks.items().
Also: Minor code correction.

* Fix examples\customPlot.py: Avoid scaling differences

Consider padding of TickSliderItem for link between ViewBox and ticks

Co-authored-by: 2xB <2xB@users.noreply.github.com>
2020-11-19 10:19:32 -08:00
Nils Nemitz 6c14204682
Fix set empty (#1446)
* changes to setData and dataRect to handle setting empty data

* simplified named argument check

* tests for clearing PlotDataItem by setData() and setData([],[]), commented out vestigal xClean/yClean

* removed last remains of xClean/yClean
2020-11-18 09:31:28 -08:00
2xB 020b7077cb
TickSliderItem: allowRemove property added (#1442)
* TickSliderItem: allowRemove property added

Following #744, this PR suggests the addition of a property
`allowRemove` to `TickSliderItem` and therefore also to
`GradientEditorItem`. It sets the default of whether ticks can
be removed by the user and therefore contemplates `allowAdd`.

I would be interested in other opinions on this design decision,
as #744 suggests to reuse `allowAdd` for the prohibition of
tick removal.
I personally suggest this solution, since it does not change
the effect of the current API.

Fix #744

* customPlot.py: Added markers to example using TickSliderItem

* examples\GradientWidget.py: Demonstrate use of allowRemove

Co-authored-by: 2xB <2xB@users.noreply.github.com>
2020-11-16 16:18:26 -08:00
2xB c359d5fad9
Fix ViewBox axis zoom in RectMode and examples/customPlot.py (#1443)
* Fix examples/customPlot.py: mouseDragEvent misses axis argument

Fixes #1277

* customPlot.py: Update methodolgy to disable menu

If there's an argument for this, we should use it

* customPlot.py: Show how to disable axis interaction

* Fix ViewBox: Moving axis in RectMode not implemented => use normal move mode

Grabbing an axis in RectMode leads to the zoom rectangle being displayed
in unreasonable positions. In this case, fall back to normal mode.

* customPlot.py: Only disable right-click zoom for demonstration

In cases where continuous zooming is not wished (e.g. in case of
complicated rebinning after zooming), this might come in handy
and there is no reason not to show it.

Co-authored-by: 2xB <2xB@users.noreply.github.com>
2020-11-16 14:27:40 -08:00
2xB 75048c473b
TickSliderItem: Use Tick.removeAllowed (#1441)
* Fix: TickSliderItem ignores Tick.removeAllowed

This prohibits removing ticks from a `TickSliderItem` if they were set to `tick.removeAllowed=False`.

Test code:
```python3
import pyqtgraph as pg
from pyqtgraph.Qt import QtCore
import numpy as np

app = pg.mkQApp()

class CustomWidget(pg.GraphicsView):
    def __init__(self, parent=None, *args, **kargs):
        pg.GraphicsView.__init__(self, parent, useOpenGL=False, background=None)
        self.item = pg.TickSliderItem(*args, **kargs)

        for pos in (0, 0.5, 1):
            tick = self.item.addTick(pos)
            tick.removeAllowed = False # Possibility 1

        # Possibility 2
        for tick, value in self.item.listTicks():
            tick.removeAllowed = False

        self.setCentralItem(self.item)
        self.setFixedHeight(31)

w = CustomWidget()
w.show()

app.exec_()
```

* Make 'removeAllowed' regular property of 'Tick'

Co-authored-by: 2xB <2xB@users.noreply.github.com>
2020-11-16 11:54:46 -08:00
2xB 01aee93a16
Fix: TickSliderItem method uses function from subclass GradientEditorItem (#1439)
* Fix: TickSliderItem method uses function from subclass GradientEditorItem

* Improved code layout

Previously, creating a `GradientEditorItem` lead to 34 executions
of `updateGradient`, with these improvements, only 2 are needed.
Further, removed duplicate code and used signals whenever possible.

Co-authored-by: 2xB <2xB@users.noreply.github.com>
2020-11-16 10:56:58 -08:00
Stephanie Seeman b21967d20d
default colors for enum ColorMap type (#1428)
* default colors for enum ColorMap type

* Update ColorMapWidget.py

if to elif

Co-authored-by: ALLENINST\stephanies <stephanies@alleninstitute.org>
2020-11-11 09:03:50 -08:00
Charles Brunet 4575decf6f
Prevent item duplication in Node context menu (#1361)
* Prevent item duplication in Node context menu

* Prevent duplicated items on Terminal context menu

* try better solution to prevent item duplication
2020-11-11 09:02:46 -08:00
2xB 100c793174
Fix ExampleApp: Use pg module from directory when run without installation (#1432)
Co-authored-by: 2xB <2xB@users.noreply.github.com>
2020-11-09 14:57:01 -08:00
Carlos Pascual 3aa3e9b991
Emit signal when GraphicScene.addItem() is used (#1388)
* Emit signal when GraphicScene.addItem() is used

Emit a signal (sigItemAdded) just after adding an item to a scene.
The item object is emited as the only signal argument.
This signal is useful for code that may want to react to newly added
items of a plot.

* Emit signal when GraphicScene.removeItem() is used

Emit a signal (sigItemRemoved) just after removing an item from a scene.
The item object is emited as the only signal argument.
This signal is useful for code that may want to react to removed
items in a plot.
2020-11-06 14:06:53 -08:00
ernierock 98c01a3667
Update GridItem.py (#1423)
Bug in GridItem.setTextPen() : on line 49 **kargs should be **kwargs. setTextPen does not work (until this simple fix is applied)
2020-11-06 14:04:34 -08:00
Gabriele Buondonno cae1c66c78
Fix width, height and background in SVG exporter (#1401)
* [SVGExporter] Fix width and height

* [SVGExporter] Fix background color

* [SVGExporter] Remove f-strings

* [Exporter] Fix for QtGui.QGraphicsScene

* Revert "[Exporter] Fix for QtGui.QGraphicsScene"

This reverts commit 5bdd25ea40.

* [test_svg] Fix unit test
2020-10-27 21:27:31 -07:00
lidstrom83 0a7a54c3f6
Permit entry of non-finite values into float SpinBox (#1422)
* Permit nan, inf, and -inf for float SpinBox

Bounds are enforced against inf and -inf inputs, but not for nan.

* Ensure SpinBox text is updated when out-of-bounds value is entered

* Make inf and nan entry in SpinBox case-insensitive

* Make SpinBox example behave as advertised

* Make non-finite SpinBox values optionally allowed

* Python 2 compatibility
2020-10-27 21:26:05 -07:00
Toussaic ae4522109e
User-defined keywords of getArrayRegion (#1416)
The three parameters "shape, vectors, origin" can't be passed as parameters because they are computed, which raise an error when kwds is passed to affineSlice.
2020-10-26 22:04:38 -07:00
Luke Campagnola 7d2fbe7596
Fix name/title handling (#1356)
- Parameters now respond to title change in setOpts
- Add Parameter.title()
- Action parameter uses default name/title handling in addition to setting button text (fixes #1320)
2020-10-26 21:56:26 -07:00
iam-git 451075b448
DataTreeWidget: sorting crashfix (#1419) 2020-10-24 16:58:51 -07:00
lidstrom83 0dacc57e02
Emit event with mouse clicks for some items (#1414)
Harmonizes behavior with PlotCurveItem.
2020-10-22 11:17:59 -07:00
Ogi Moore 27ca1747f1
Call GraphicsItem.viewTransformChanged() (#1413)
* Call GraphicsItem.viewTransformChanged()

* Needed to apply to labels too
2020-10-22 11:17:33 -07:00
lidstrom83 cff19f3271
Hide WidgetParameterItem.defaultBtn if param has no default (#1411)
Co-authored-by: Daniel Lidstrom <dlidstrom@russelltech.com>
2020-10-22 08:28:03 -07:00
Ogi Moore 1b89c47cc2
Add fontSize kwarg (taken from PR #129) (#1410) 2020-10-21 22:18:36 -07:00
lidstrom83 b44dcc135f
Fixed mouse interaction issues with DockLabel (#1408)
Co-authored-by: Daniel Lidstrom <dlidstrom@russelltech.com>
2020-10-21 20:52:44 -07:00
Ogi Moore 0b52c8453e
prepend conda-forge channel prior to env creation (#1409) 2020-10-21 20:48:19 -07:00
Dennis Göries 55a9e19e43
ScatterItem: Fix name setting (#1405) 2020-10-20 20:02:53 -07:00
Ogi Moore 7e57e07068
example app now works with Qt4 and Python2 again (#1302)
* example app now workw with Qt4 and Python2 again

* Example App is now part of the test suite

* Add initExample

* No scary warning when launching examples

* Fix scary examples.__main__ warning

* Use courier new font as its on all platforms

* Remove commented out code

* Add newline

* Updated docs, example app now tested

* Non-relative import for example app

* Proper importing now
2020-10-19 11:51:12 -07:00
Nils Nemitz 65e90faec5
dynamic range limiting in PlotDataItem (#1140)
* dynamic range limiting in PlotDataItem

* revised version of cynamic range limiting

* replaced == with is operator

* removed unicode +- character, converted to ascii

* code/docstring cleanup

* clean state with changes

* silenced numpy all-NaN warnings

* reverted PlotWidget.py to original

* reverted PlotWidget.py to original

* reverted PlotWidget.py to original

* rewrapped/reformated setDynamicRangeLimits docstring

Co-authored-by: Ogi Moore <ognyan.moore@gmail.com>
2020-10-18 22:34:41 -07:00
Julius Juodakis 39f9c6a6aa
caching for viewRect of LinearRegionItem to reduce CPU load (#1391)
* caching for boundaryRect of LinearRegionItem

* caching viewRect at GraphicsItem
2020-10-18 16:42:40 -07:00
Ogi Moore 2c02d58134
Do not apply transparent background in Qt4 (#1403)
* Do not apply transparent background in Qt4

* Tests need to reflect this change too
2020-10-17 23:01:16 -07:00
Ogi Moore 9f86eef2b9
handle case of version string having no '+' (#1402) 2020-10-17 22:22:29 -07:00
Dennis Göries b5de577c28
LegendItem: Enable customization of label text size and tests (#1397)
* LegendItem: Enable customization of label text size and tests

* One more CI

* Remove deleteLater of QAPP in legend item test

* Remove assert statement in setLabelTextSize

* Modify legend test without assertion
2020-10-15 10:56:34 -07:00
Ogi Moore 5eb671217c
Docs should have no warnings on pcolormeshitem (#1400) 2020-10-15 10:12:36 -07:00
Kenneth Lyons 1f76ac0e2c
Add a docs build job to CI (#1328)
* Add a docs build job to CI

* Add sphinxopts to fail on warning

* Test sphinx warning

* Redid ci stage conditionals

* update conf.py to remove deprecation warning

* introduce 3rd stage for proper conditionals

* Attempt to fix malformed table

Co-authored-by: Ogi Moore <ognyan.moore@gmail.com>
2020-10-15 08:43:23 -07:00
Dennis Göries 3b6eb02520
AxisItem: Account for empty strings in the visibility of text and units (#1367)
* Rebase

* make the tests work

* add test and rather more cleanup

* Cleanup for axisitem visibility test

* Another cleanup in test axis item
2020-10-14 20:40:54 -07:00
Mitchel Paulin e7b11cb39a
Fixed bug where removeTempArea would be called on home even if it was not defined (#1349)
* Fixed bug where removeTempArea would be called on home even if it was not defined

* Made the check for whether or not home is defined more explicit
2020-10-14 10:07:12 -07:00
Ogi Moore 9413dc8005
Disable mouse rate limiting (#1399) 2020-10-13 22:33:00 -07:00
Allard Hendriksen 9d99a3e7b0
Fix incorrect rendering of overlapping object in renderToArray() (#1306)
This commit adds a depth buffer in renderToArray().

This fixes the issue that overlapping objects are rendered incorrectly
when using renderToArray() on a GLViewWidget.

This might be related to issue #743.
2020-10-13 19:47:49 -07:00
Dennis Göries 287d564d7d
GraphicsView: Add basic tests ... (#1396) 2020-10-13 09:06:34 -07:00
Carlos Pascual 23a46b5fb9
Add "left" and "right" step Modes (#1360)
* Add "lstep" and "rstep" step Modes

stepMode is currently either True or False. If it is True,
it requires the user to make len(x) = len(y)+1. This is
inconvenient because it makes it difficult to change the
stepMode on a given curve (just as one would change, e.g.,
its color).

This commit extends the current situation by introducing
two more step modes: "lstep" and "rstep", which do not require
passing an extra x value. In turn, this modes associate each
y value to either the left or the right boundary of the step.

For example, the "rstep" mode is handy when plotting "life"
digital signals in which x,y data pairs are appended as they
are read.

This commit does not modify the behaviour in case of stepMode=True

* Replace step mode names: lstep,rstep -> left,right

* Improve docs for stepMode

Reword docstring and add it to PlotDataItem class too

* Document left and right stepModes as added in v 0.12.0

TODO: confirm the exact version number to use here

* Add comments stress the need for "is True"

Some conditional statements in the code regarding stepMode are
done with "is True". This is actually required since other
possible values such as "left" also evaluate as true but should
not be caught.

* Deprecate boolean API for stepMode

Introduce stepMode="mid" as a replacement of stepMode=True,
but keeping full backwards compatibility with the old API.
Adapt docs, examples and tests accordingly.

* Raise ValueError on unsupported stepMode values

* Rename "mid" step mode to "center"

* Remove "added in 0.12.0" note

See https://github.com/pyqtgraph/pyqtgraph/pull/1360#discussion_r502746919

* Add deprecation warning when stepMode=True

Issue a DeprecationWarning if stepMode=True is being passed to the
constructor or setData() of PlotDataItem or PlotCurveItem.

Note: warnings module is imported locally so that it is esier to
remove once this check is no longer needed.

* Fix wrong syntax in last commit

Fix usage of "default" kwarg in dict.get()
2020-10-13 08:52:07 -07:00
Dennis Göries 325a15a6ef
SignalProxy: Correct initialization without slot argument and tests (#1392)
* SignalProxy: Correct initialization without slot argument and provide tests

* Add missing slot is None case on disconnect

* Start new tests

* Exception block

* Test no module

* Different signal

* Debugging the signal connect

* Re initialize proxy after disconnect

* Add more test cases for blockSignal

* Change test case for signal count

* Give up for python 2 and pyside

* Exclude for Python 2.7 and PySide

* Convert float to integers in timer start period
2020-10-13 08:50:22 -07:00
Ogi Moore 4946a57987
Merge pull request #1382 from dgoeries/code-quality-legend
LegendItem: A bit auto flake8
2020-10-12 22:28:00 -07:00
Ogi Moore 539394e20c
Merge pull request #1362 from bruchar1/make-terminal-sortable
DataTreeWidget exception with multivalue Terminal (flowchart)
2020-10-12 21:46:28 -07:00
Ogi Moore 2955b26fb2
Merge pull request #1383 from dgoeries/transparent-palette
GraphicsView: Set a transparent background palette
2020-10-12 19:44:53 -07:00
Ogi Moore 3f7a9bb642
Merge pull request #1273 from edumur/develop
Implemented pColorMeshItem
2020-10-12 09:24:10 -07:00
Etienne Dumur 5ab0cef017 Solve artifacts issues
Add a parameter "antialiasing".
Remove profiler
Add pyqtgraph mkPen
2020-10-12 12:45:13 +02:00
Ogi Moore ea08dda62d
Merge pull request #1387 from irgolic/patch-1
ScatterPlotItem: Make + and x symbols thicker
2020-10-10 13:10:57 -07:00
rafael fbf1a2fe18
ScatterPlotItem: Make + and x symbols thicker
This is something we're overriding in Orange3 (biolab/orange3#5007), as we change the symbols' alpha_value to show selected symbols. The default + and x symbols are too thin to show a noticeable change in alpha_value.

But I thought you might agree that the symbols look nicer this way.
2020-10-01 12:57:04 +02:00
Kyle Sunden 0a8ad6b1aa
Merge pull request #1386 from ixjlyons/dev-to-master
Remove a few remaining mentions of the develop branch
2020-09-30 23:30:47 -05:00
Kenneth Lyons 8b9ac0557b Remove a few remaining mentions of the develop branch 2020-09-30 21:04:09 -07:00
Ogi Moore b0a7c44357
Merge pull request #1384 from k-dominik/patch-1
fix typo in documentation
2020-09-29 10:00:46 -07:00
Dominik Kutra 5842f42632
fix typo in documentation
found a tiny typo when reading the docs...

thank you guys for this awesome library 🚀
2020-09-29 17:29:52 +02:00
Dennis Goeries 9a51fc3662 GraphicsView: Set a trnasparent background palette 2020-09-26 14:36:43 +02:00
Dennis Goeries 6dc0b2c16d LegendItem: A bit auf auto flake8 2020-09-26 14:09:21 +02:00
Etienne Dumur bd51fa7c87 Clean code, improve boundingRect 2020-09-23 09:27:23 +02:00
Kenneth Lyons a90c443b7a
Fix PlotItem.setAxisItems (#1376)
* Fix PlotItem.setAxisItems

- Use extend so visibleAxes remains a flat list.
- More robust logic for detecting adding an AxisItem instance to
  mulitple plots and suggest a workaround in the error message.

* Simplify membership check

* Add test for PlotItem setAxisitem logic
2020-09-22 20:25:02 -07:00
Ogi Moore e2dc21e2ca
Merge pull request #1377 from ixjlyons/issue-1353-imageitem-autodownsample
Consolidate and fix downsample factor computation in ImageItem
2020-09-22 20:18:03 -07:00
Kenneth Lyons e78e9c256d Consolidate and fix downsample factor computation in ImageItem 2020-09-20 22:06:00 -07:00
Ogi Moore 043b6b47ea
Merge pull request #1375 from ixjlyons/test-vector
Add targeted Vector test coverage
2020-09-20 14:54:47 -07:00
Kenneth Lyons 3ea32ff447
Merge pull request #1374 from ixjlyons/test-warnings-cleanup
Test warnings cleanup
2020-09-20 14:52:49 -07:00
Kenneth Lyons 16ea8ada0c Use raw strings to get rid of DeprecationWarning
DeprecationWarning is for invalid escape sequence ('\'). Decided to use
raw strings rather than double-backslashes because the text processing
is using raw strings anwyay.
2020-09-20 13:59:44 -07:00
Kenneth Lyons fc957bbc4b Add targeted Vector test coverage 2020-09-20 09:19:39 -07:00
Kenneth Lyons f1d0ea99b6
Merge pull request #1364 from meganbkratz/logScaleBugFix
fix for log scaling being broken
2020-09-16 22:27:04 -07:00
Kenneth Lyons 9e76f22750
Merge pull request #1368 from bruchar1/wrong-disconnect-receiver
Fix disconnect() in Flowchart with wrong receiver slot
2020-09-16 22:04:17 -07:00
Kenneth Lyons fa77c65199
Merge pull request #1370 from jenshnielsen/fix_timer_deprecation_warning
Fix deprecation warning in multiprocess module
2020-09-16 21:40:28 -07:00
Jens Hedegaard Nielsen 1d10561974 fix deprecation warning
the argument to qtimer.start should be an int not a float

the current code raises a deprecation warning with python 3.8
2020-09-16 10:48:37 +02:00
Charles Brunet b2ceb8d053 Fix disconnect() in Flowchart with wrong receiver slot 2020-09-14 13:42:16 -04:00
Megan Kratz 46f8f1633f fix for log scaling being broken -- log was being taken twice, resulting in nan. Now it's only being taken once 2020-09-10 19:20:12 -04:00
Charles Brunet a8417b6478 fix exception in DataTreeWidget when clicking on a node with multivalue Terminal connected 2020-09-10 08:59:17 -04:00
Kenneth Lyons 9fdaffaf7d
Merge pull request #1336 from ales-erjavec/fixes/arrow-item-parent-arg
Fix an error in ArrowItem constructor when passed a parent=... argument
2020-08-17 21:07:18 -07:00
Ales Erjavec 3d391d46e3 Add `parent` to ArrowItem's constructor signature 2020-08-17 09:27:23 +02:00
Ales Erjavec 52717fa8b7 Rename test 2020-08-17 09:25:37 +02:00
Kenneth Lyons 11b76a1a6f
Merge pull request #1339 from outofculture/vector-init-qt5
Vector init in qt5
2020-08-16 08:40:06 -07:00
Martin 7bf4e597d9 improve docstring formatting and wording 2020-08-15 22:15:58 -07:00
Kenneth Lyons c8757b2c07 Fix Azure Pipelines badge in README 2020-08-15 13:18:08 -07:00
Kenneth Lyons ab13cd450e
Merge pull request #1331 from LocutusOfBorg/new-sip
sip: switch to new PyQt5 api import, with fallback to the old impleme…
2020-08-15 12:45:05 -07:00
Martin 75899f0c4e conform to docstring format 2020-08-11 12:34:53 -07:00
Martin 817753bd82 right, we're camels here 2020-08-11 12:34:53 -07:00
Martin 9f996d041c Vector.__init__ improvements
* added docstring
* fixed handling of QVector3D args (cannot list() them)
* refactor to no longer need return statements
2020-08-11 12:34:53 -07:00
Kenneth Lyons c8fc221e81
Merge pull request #1334 from termim/PlotCurveItem
More data validity checks in PlotCurveItem
2020-08-03 15:14:07 -07:00
Kenneth Lyons 7504f2ba27
Merge pull request #1326 from ixjlyons/doc-multiplotitem
Improve docs for MultiPlotWidget and MultiPlotItem
2020-08-01 17:19:18 -07:00
Ales Erjavec a9049f1d4d Pop the 'parent' arg from ArrowItem opts parameter dict
If not, then an `KeyError: 'Invalid arrow style option "parent"'`
 is raised in setStyle.
2020-07-28 10:01:15 +02:00
Mikhail Terekhov 471d7415ee PlotCurveItem.dataBounds: more checks for empty range 2020-07-27 15:50:34 -04:00
Mikhail Terekhov 1ad3eacb78 PlotCurveItem.boundingRect: check for None returned from self.dataBounds 2020-07-27 15:50:26 -04:00
Gianfranco Costamagna 32a79f18a4 sip: switch to new PyQt5 api import, with fallback to the old implementation if not found.
Also calls to setapi are not needed anymore, so use them only with the old implementation.

See: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=966045
for reference
2020-07-27 14:52:07 +02:00
Etienne Dumur 16ae3fb510 Allow numpy style docstring with sphinx 2020-07-27 08:19:25 +02:00
Luke Campagnola abfac52c34
Merge pull request #1321 from campagnola/revert-plotcurveitem-changes
Revert plotcurveitem changes from 18999c
2020-07-21 06:43:06 -07:00
Etienne Dumur 85378004ef Correct Pyside bug 2020-07-20 09:36:14 +02:00
Kenneth Lyons c0da4c545e Improve docs for MultiPlotWidget and MultiPlotItem 2020-07-19 14:28:58 -07:00
Kenneth Lyons fe1a4d90f1
Merge pull request #1324 from angulartist/feat/multiplotitem-plot-pen
Pass MultiPlotItem.plot kwargs through to child PlotDataItems
2020-07-19 13:59:24 -07:00
angulartist 5765b0d4c2 Enhancement: [Issue/812]: remove unused import 2020-07-19 19:16:58 +02:00
angulartist 58aa9306df Enhancement: [Issue/812]: just pass plotArgs keyword arguments 2020-07-19 19:16:07 +02:00
angulartist ae4483bfaa Enhancement: [Issue/812]: MultiPlotItem handles pen (QPen) as a keyword argument 2020-07-19 15:58:13 +02:00
Luke Campagnola b031a0a235 Revert changes from 18999c - these incorrectly change the API.
Also tidy up a little
2020-07-18 23:41:35 -07:00
Ogi Moore 5e20d20246
Merge pull request #1319 from campagnola/acq4-merge
Acq4 merge
2020-07-17 11:57:08 -07:00
Luke Campagnola 6fe23887b8 update reload unit test 2020-07-17 10:00:32 +03:00
Luke Campagnola 57f2f876d3 clean up exceptions on windows (don't show syntax error from eval attempt) 2020-07-17 09:55:46 +03:00
Luke Campagnola 7eb2bf6306 reload fix - don't reload files with no pyc 2020-07-17 09:54:51 +03:00
Luke Campagnola 31b0ddcee6 ptime fix - return precision clock time on py3 2020-07-17 09:53:19 +03:00
Etienne Dumur 72c03ea096 Rename PColorMesh example 2020-07-17 08:18:52 +02:00
Ogi Moore 3c6dad376a
Merge pull request #1317 from Dennis-van-Gils/master
Fix line width not being set
2020-07-16 14:20:26 -07:00
Dennis van Gils 603e1b98bc Fix line width not being set 2020-07-16 21:13:33 +02:00
Etienne Dumur 2822790087 Correct Python 2 compatibilities and improve comments 2020-07-15 10:32:29 +02:00
Etienne Dumur f8aee11190 Add PColorMeshItem example to the app 2020-07-15 10:30:41 +02:00
Kenneth Lyons d70e870a44
Merge pull request #1309 from ibrewster/polylineroifix
Properly retain and use hoverPen argument in _PolyLineSegment
2020-07-13 21:28:06 -07:00
Kenneth Lyons b058d032d1 Fix some warnings 2020-07-13 21:09:31 -07:00
Luke Campagnola d3ed45574e
Merge pull request #1312 from campagnola/acq4-merge
TargetItem fix + performance improvements
2020-07-13 17:33:07 -07:00
Luke Campagnola 4562c06576
Merge pull request #1311 from campagnola/acq4-merge
performance fix for histogramlutitem
2020-07-13 16:59:05 -07:00
Luke Campagnola f015f0879e TargetItem fix + performance improvements
- avoid extra work when setLabelAngle would have no effect
- fix errors from bad parent transform (usually the displaying widget has not been given a size yet)
2020-07-13 16:37:29 -07:00
Luke Campagnola cb48ec94b7 performance fix for histogramlutitem
setImageItem is now able to detect trival color gradients like gradientChanged has previously.
2020-07-13 16:25:43 -07:00
Luke Campagnola dce9a5bf0c
Merge pull request #1310 from campagnola/acq4-merge
Acq4 merge
2020-07-13 16:13:38 -07:00
Luke Campagnola 51bb8b9bb8
Merge pull request #1307 from campagnola/acq4-merge
Fix reload to use mod.__cache__ to get name of pyc files
2020-07-13 15:47:15 -07:00
Luke Campagnola 268ba38543 docstring update 2020-07-13 15:31:47 -07:00
Luke Campagnola 5723853308 revert behavior: reload modules with no pyc
Should fix unit test. Also: return a structure from reloadAll describing reasons for failure of each module to reload.
2020-07-13 15:29:00 -07:00
Luke Campagnola 605b0b2144 code cleanup 2020-07-13 13:45:31 -07:00
Luke Campagnola 0df7cbcd06 Fix Vector.__init__ for Qt5 + cleanup 2020-07-13 13:10:58 -07:00
Israel Brewster 3878ab6946 Properly retain and use hoverPen argument in PolyLineSegment function of PolyLineROI 2020-07-13 12:10:49 -08:00
Luke Campagnola 78702eea8b code cleanup 2020-07-13 13:06:27 -07:00
Luke Campagnola eb4dd5626f SimpleParameter.setValue: coerce value for int parameters 2020-07-13 13:05:56 -07:00
Luke Campagnola f9327ea910 Rate-limit event processing inside ProgressDialog 2020-07-13 12:55:12 -07:00
Luke Campagnola ab5a2c5d11 BusyCursor: only restore cursor after all nested levels have exited 2020-07-13 12:53:59 -07:00
Luke Campagnola 6214ff6de8 Add Pa to units 2020-07-13 12:53:06 -07:00
Luke Campagnola e2669f074b Add test for functions.subArray 2020-07-13 12:52:55 -07:00
Luke Campagnola 421b7bdc78 add SignalProxy.block for temporarily disabling signal forwarding 2020-07-13 12:52:25 -07:00
Luke Campagnola 993871b1ae InfinifteLine.setPos add support for array arg 2020-07-13 12:51:03 -07:00
Luke Campagnola 893c85053f debug.ThreadTrace add support for thread names 2020-07-13 12:50:24 -07:00
Luke Campagnola c51a84ae4e Fix console exception filtering for py3 2020-07-13 12:49:57 -07:00
Luke Campagnola 0bc186fe7d Fix reload to use mod.__cache__ to get name of pyc files 2020-07-13 12:43:11 -07:00
Ogi Moore 7a154f74fa
Merge pull request #1304 from berr/patch-1
Import ThreadSafeTimer in __init__
2020-07-08 10:10:32 -07:00
Felipe Silveira 9a83b72e9d
Import ThreadSafeTimer in __init__
This fixes issue #1303
2020-07-08 10:03:32 -03:00
Ogi Moore c03018005a
Merge pull request #1291 from ixjlyons/roi-axisorder
Get ImageView ROI working with both row and col major data
2020-07-07 10:54:26 -07:00
Luke Campagnola 49dd944d10
Merge pull request #1297 from campagnola/acq4-merge2
ArrowItem performance
2020-07-06 03:59:41 -07:00
Luke Campagnola 41f0623014
Merge pull request #1296 from campagnola/acq4-merge
update h5py deps in metaarray
2020-07-06 02:34:23 -07:00
Luke Campagnola 6a5e7cfee5 ArrowItem performance
- Avoid updates that would have no effect
- Raise exception on invalid arguments to setStyle
2020-07-06 01:27:43 -07:00
Luke Campagnola 5e971b646f update h5py deps in metaarray
- update h5py usage to support latest version
- bugfix in __getitem__ for fancy indexing
- code cleanup
2020-07-06 01:08:01 -07:00
Luke Campagnola 46dafe4803
Merge pull request #1295 from campagnola/acq4-merge
TextItem performance
2020-07-06 01:00:04 -07:00
Luke Campagnola 268d25c125 TextItem performance
Avoid expensive work if textitem is not visible, or when setPlainText / setHtml would have no effect.
2020-07-06 00:24:13 -07:00
Luke Campagnola fc31b5c50d
Merge pull request #1294 from campagnola/acq4-merge
console fixes
2020-07-06 00:19:13 -07:00
Luke Campagnola f9d149fe32
Merge pull request #1293 from campagnola/py3-fixes
some lingering py3 fixes
2020-07-05 23:20:52 -07:00
Luke Campagnola 6f69b11c26 console fixes
- add fileno method since console occludes sys.stdout
- fix editor spawning
- don't store sys.stdout, since this is not guaranteed to be the real stdout
2020-07-05 23:06:05 -07:00
Luke Campagnola ac417a6567 py3 fixes 2020-07-05 22:52:15 -07:00
Ogi Moore da15f09479
Merge pull request #1289 from ksunden/dai_si_prefix
Disable autoSIPrefix for DateAxisItem by default
2020-07-05 10:50:54 -07:00
Kenneth Lyons 6052ba7668 Get ImageView ROI working with both row and col major data 2020-07-04 23:14:08 -07:00
Kyle Sunden a4dbcfb1e1 Disable autoSIPrefix for DateAxisItem by default
When adding a label, it adds the offset for the epoch seconds, (1e09), which is not helpful for date axes
2020-07-03 17:02:58 -05:00
Luke Campagnola b79c979663
Merge pull request #1283 from zhujun98/fix_array_to_qpath
Fix arrayToPath
2020-06-29 16:35:27 -07:00
zhujun98 b61c7c1e39 Fix the cases with connect being 'pairs' and 'finite' 2020-06-29 23:20:29 +02:00
Etienne Dumur eb6a93d26e Modify syntax to pass error 2020-06-29 18:28:52 +02:00
Etienne Dumur 52c607de64 Revert "Modify syntax to pass error"
This reverts commit 09a0311fa8.
2020-06-29 18:27:37 +02:00
Etienne Dumur 09a0311fa8 Modify syntax to pass error 2020-06-29 18:21:15 +02:00
Kenneth Lyons 3cf2845743
Improve control over ROI/handle pens (#1285)
* Exposed ability to set pens for handles and hovering for ROIs

* Consistent color format for pen creation

* Exposed ability to set pens for handles and hovering for ROIs

* Consistent color format for pen creation

* Add handleHoverPen arg to ROI and rename Handle arg to hoverPen

Co-authored-by: nmearl <nchlsearl@gmail.com>
2020-06-28 22:44:13 -07:00
Ogi Moore 3947d34ae4
Merge pull request #1284 from ixjlyons/roi-getarrayregion-api
Update doc strings to clarify getArrayRegion API for ROI subclasses
2020-06-28 21:58:08 -07:00
Kenneth Lyons 8a3d4bab2f Update doc strings to clarify getArrayRegion API for ROI subclasses 2020-06-28 14:39:12 -07:00
zhujun98 7016d1c6c3 Fix arrayToPath
Use the correct format for streaming QByteArray to QPainterPath.
2020-06-28 21:23:06 +02:00
Etienne Dumur 667c41d22b PColorMeshItem know require only one 2d array
Allow PColorMeshItem to work with only one 2d array, a regular grid is then assume for the polygons vertices.
Improvement of comments.
2020-06-28 20:32:22 +02:00
Kenneth Lyons 4110b3e539
Handle axis SI prefix scaling in MatplotlibExporter (#1282)
* Handle axis SI prefix scaling in MatplotlibExporter

* Added some MatplotlibExporter tests and added matplotlib to CI deps

* Install mpl with pip instead of conda

* Cleanup
2020-06-28 08:51:34 -07:00
Etienne Dumur 98c6c56358 Make clearer the non-grid meshing of the Item 2020-06-28 15:05:29 +02:00
Etienne Dumur 919ee54b59 Add edgecolor parameter
Allow user to set the polygons edge color.
2020-06-28 14:50:44 +02:00
Etienne Dumur d32d61a1e2 Various improvements
Make an example displaying more clearly the Item capability.
Correct few bugs in the Item class.
Improve overall comments.
2020-06-28 14:49:20 +02:00
Kenneth Lyons 96d1ef986f
Merge pull request #330 from lidstrom83/Parameter.defaultBtn_autoDefault
Set parameter's default button autoDefault value to False
2020-06-27 15:12:03 -07:00
Ogi Moore a719a06b8b
Merge pull request #467 from meganbkratz/derivativePlots_cleanup
Add dy/dx and y vs. y` plot modes to context menus from plots.
2020-06-27 12:50:44 -07:00
Ogi Moore 264d63e90e Update PyQt5, PySide2, PySide1 Templates, apply else statement 2020-06-26 23:51:09 -07:00
Etienne Dumur 3cbe65d46d Correct PColorMeshItem names 2020-06-26 18:12:17 +02:00
Ogi Moore 677ef5132c
Merge pull request #1276 from j9ac9k/implement-pr-307
fix problems with high freequency game mouse
2020-06-25 20:52:10 -07:00
Etienne Dumur 4e7b8dce17 Update PColorMeshItem.py 2020-06-25 22:41:30 +02:00
Etienne Dumur cbbd8287ad Remove matplotlib dependencies 2020-06-25 22:07:41 +02:00
Ogi Moore ce6da3e93f First pass at implementing the diff from PR307 2020-06-24 23:34:17 -07:00
Kenneth Lyons b41c4a71e5
Fix Parameter.hasDefault (#1275)
When a default value is not set, hasDefault returns False. If
default=None is passed, hasDefault still returns False.
2020-06-24 21:35:05 -07:00
Ogi Moore 302d66dd67
Add tickAlpha to AxisItem Style Options (#1274)
* Add tickAlpha setting to AxisItem style

* reworking setTickAlpha docs, redo logic based on types

Co-authored-by: demonchild2112 <denverlovesyou@gmail.com>
2020-06-24 17:42:28 -07:00
Ogi Moore 43328eb053
Merge pull request #1270 from j9ac9k/implement-pr-403
Implement pr 403
2020-06-24 15:56:59 -07:00
Ogi Moore b8abd5d02e Don't let axis item reduce space 2020-06-24 15:40:01 -07:00
Ogi Moore 14d5085636
Merge branch 'develop' into derivativePlots_cleanup 2020-06-23 23:03:56 -07:00
Ogi Moore fd0bbeb9db
Merge pull request #1272 from maxkl/develop
LegendItem: fix clear() not closing widgets
2020-06-23 21:04:35 -07:00
Etienne Dumur 426a70ae60 Implemented pColorMeshItem 2020-06-23 19:59:04 +02:00
Max Klein 78d11f8a71
LegendItem: fix clear() not closing widgets 2020-06-23 17:01:02 +02:00
Ogi Moore a192707654 Implement PR403-diff 2020-06-22 23:02:48 -07:00
Ogi Moore 55e89bccef
Merge pull request #117 from onlyjus/feature-resizeFlowchartNode
Feature: Flow chart nodes resize based on inputs/outputs
2020-06-22 22:49:15 -07:00
Karl Georg Bedrich 1666407a89
ImageView.Timeline better visibility and fixed (#400)
* make imageView-timeline unmovable

* imageview.timeline now visible over white background

* activate splitter when roi visible

* Re-add roiCurves

Co-authored-by: Ogi Moore <ognyan.moore@gmail.com>
2020-06-22 22:48:54 -07:00
Ogi Moore 91ee83ab36
Merge pull request #402 from vladimir-kraus/develop
added method clear() to GLViewWidget
2020-06-22 20:58:04 -07:00
Ogi Moore c190cb4186
Merge pull request #816 from fake-name/develop
Avoid constructing shadow pens when no shadow pen is set
2020-06-22 20:54:44 -07:00
Ogi Moore 1fe3731ec2
Merge branch 'master' into develop 2020-06-22 20:37:55 -07:00
Ogi Moore 6643d73903
Merge pull request #1268 from ixjlyons/dock-container-none
Check for container before setting dock orientation
2020-06-22 19:58:59 -07:00
jeremysee2 f81768ac59
Issue #1260: Added exception to checkOpenGLVersion to highlight OpenGL ES incompatibility on Raspberry Pi (#1264)
* checkOpenGLVersion exception for OpenGL ES

* checkOpenGLVersion exception

* checkOpenGLVersion exception

* python 2/3 compatibility

* Refactoring checkOpenGLVersion

Since the original goal of `checkOpenGLVersion` is to re-throw an exception or notify the user about a wrong OpenGL version in another exception, this commit unifies the two exception messages from `checkOpenGLVersion`.
Further, it corrects ">" to ">=" in the error message (originally my fault).
And it corrects verNumber to be an integer and not a boolean (there was a " < 2" too much at the end of the line).
Finally, since the opportunity was there, the method is further refactored, comments and a docstring are added.

Co-authored-by: 2xB <2xb@users.noreply.github.com>
2020-06-21 13:59:44 -07:00
Kenneth Lyons 0b98140893 Check for container before setting dock orientation 2020-06-20 12:27:29 -07:00
Ogi Moore e5a1327041
Merge pull request #1267 from ixjlyons/fix-plotcurveitem-sigclicked
Add mouse event to PlotCurveItem sigClicked signature
2020-06-20 08:19:51 -07:00
Kenneth Lyons 352a8a425a Add mouse event to PlotCurveItem sigClicked signature 2020-06-19 23:00:02 -07:00
Ogi Moore f5b8a150c0
Merge pull request #1265 from lamby/963124-python-pyqtgraph-please-make-the-build-reproducible
Make the documentation reproducible
2020-06-19 22:21:19 -07:00
Chris Lamb e6c8046320 Make the documentation reproducible
Whilst working on the Reproducible Builds effort [0] we noticed that pyqtgraph
could not be built reproducibly. This is because it generates copyright years
from the current build date and therefore will vary on when you build it.

This commit uses SOURCE_DATE_EPOCH [1] for the "current" build date.

This was originally filed in Debian as #963124 [2].

 [0] https://reproducible-builds.org/
 [1] https://reproducible-builds.org/specs/source-date-epoch/
 [2] https://bugs.debian.org/963124
2020-06-19 12:56:14 +01:00
Ogi Moore 0c08adc411
Merge pull request #1257 from VesnaT/tickFont_painter
AxisItem: Make painter (tick) font dependent
2020-06-15 07:54:25 -07:00
Vesna Tanko ad4f796e32 AxisItem: Make painter tick font dependent 2020-06-15 11:03:50 +02:00
Ogi Moore 362dc93a9d
Merge pull request #1256 from j9ac9k/Implement-PR-317
Implement diff from PR 317
2020-06-13 21:49:33 -07:00
Ogi 8b557af23f Implement diff from PR 317 2020-06-13 21:21:29 -07:00
Ogi Moore ecd0642ca9
Merge pull request #977 from campagnola/pseudoscatter-performance
Add a faster method for computing pseudoscatter
2020-06-13 21:08:33 -07:00
Ogi Moore 1744bb09a9
Merge pull request #1251 from dearkarm/patch-1
DateAxisItem: Parameterize utcOffset during construction
2020-06-12 22:53:20 -07:00
Ogi Moore 5f5803264b
Merge pull request #1252 from j9ac9k/implement-pr-336
fix-incorrect-tick-text-boundaries-calculation
2020-06-12 22:52:46 -07:00
Karl Georg Bedrich 3a758cac96
NEW options for LegendItem (#395)
* NEW options for LegendItem

* * changed 'drawFrame' into 'frame'
* added **kwargs to plotItem.addLegend
* added (frame=False, colCount=2) in legend example
* more elegant solution for legend.getLabel

* repaired getLabel
ItemSample.item == plotitem

Co-authored-by: Ogi Moore <ognyan.moore@gmail.com>
2020-06-12 22:40:20 -07:00
Ogi Moore cee27b6268 fix-incorrect-tick-text-boundaries-calculation 2020-06-12 22:28:26 -07:00
Ogi Moore e1f6c08365
Merge pull request #551 from bensondaled/develop
added fps class variable to ImageView to enable consistent playback f…
2020-06-12 21:55:46 -07:00
carmazine 8da7c166c8
Parameterize utcOffset during construction
Allows for control over timezone offset in a simple, optional manner
2020-06-12 22:46:09 +02:00
Ogi Moore 158efcf65c
Merge pull request #1249 from j9ac9k/Implement-160
Implement PR160 - clear current SpotItems
2020-06-11 23:18:39 -07:00
Ogi 001d91c2f2 Implement PR160 - clear current SpotItems 2020-06-11 22:56:20 -07:00
Ogi Moore 4b484ae46d
Merge pull request #150 from lidstrom83/ViewBox_panning_fix
Speed up ViewBox panning
2020-06-11 22:33:49 -07:00
Ogi Moore b9a0fac815
devicePixelRatio is only accessible in __init__ 2020-06-11 21:32:12 -07:00
Ogi Moore d6f16a7d56
Merge pull request #1247 from j9ac9k/fix-1246
Restore the now-deprecated PlotWindow and ImageWindow classes
2020-06-11 21:20:20 -07:00
Ogi Moore 308bb8d1ff
Merge branch 'master' into develop 2020-06-11 21:11:51 -07:00
Ogi 4dc0865bae Restore the now-deprecated PlotWindow and ImageWindow classes 2020-06-11 20:55:28 -07:00
Ogi Moore 12a7c449f1
Give ability to hide/show individual spots (#1245)
Co-authored-by: dlidstrom <lidstrom83@gmail.com>
2020-06-10 23:31:39 -07:00
Ogi Moore dbdd5d9a39
Peque scatter symbols (#1244)
* Added arrow symbols for the ScatterPlotItem

* Fixed arrows rotation in scatter plots

* Added new symbols to example

Co-authored-by: Miguel Sánchez de León Peque <msdeleonpeque@gmail.com>
2020-06-10 23:03:43 -07:00
Ogi Moore f762f489dc
Merge pull request #1243 from j9ac9k/implement-PR-143-with-changes
Implement suggested changes in PR 143
2020-06-10 21:07:08 -07:00
Ogi 05f8921555 Implement suggested changes in PR 143 2020-06-10 20:50:04 -07:00
Ogi Moore 79ce0c46b5
Merge pull request #1242 from j9ac9k/implement-PR-142-with-changes
Emit the event with sigClicked in PlotCurveItem
2020-06-10 20:34:43 -07:00
Ogi 2e8dce2fc2 Emit the event with sigClicked in PlotCurveItem 2020-06-10 20:08:34 -07:00
Ogi Moore 1f00578cf1
Merge pull request #157 from lidstrom83/GradientWidget_widgetGroupInterface
Provide widgetGroupInterface to GradientWidget
2020-06-10 20:02:38 -07:00
Maurice van der Pot e18af48b8d
Implement headWidth parameter for arrows (#385)
Although the documentation used to say that specifying tipAngle would
override headWidth, headWidth was never used. The new behaviour is that
tipAngle will be used, with a default value of 25, unless headWidth is
specified.

Co-authored-by: Ogi Moore <ognyan.moore@gmail.com>
2020-06-09 22:04:29 -07:00
Ogi Moore dcef886a44
Merge pull request #800 from ReehcQ/develop
add legend for bar graph and update the examples
2020-06-09 21:35:44 -07:00
Ogi Moore 517adc87c0
Merge branch 'master' into develop 2020-06-09 20:56:51 -07:00
Ogi Moore 26d54e7cc0
Merge pull request #503 from kiwi0fruit/patch-1
Fix bug in RawImageWidget.py
2020-06-09 20:50:58 -07:00
Ogi Moore 4d01023e77
Merge pull request #1241 from j9ac9k/update-xvfb-config-for-ci
Use older pytest-xvfb for py2 configs
2020-06-09 20:49:27 -07:00
Ogi 258da19886 Use older pytest-xvfb for py2 configs 2020-06-09 20:27:22 -07:00
Ogi Moore f7127c0bc7
Merge branch 'master' into patch-1 2020-06-09 20:21:46 -07:00
Ogi Moore b52809d879
Merge pull request #1240 from pyqtgraph/develop
Reset self._needsUpdate in GLImageItem after updating
2020-06-09 20:12:43 -07:00
Karl Georg Bedrich 2848d451f6
draw connector lines between gradient and region with anti-aliasing (#496)
Co-authored-by: serkgb <serkgb@J873GY1-2.stf.nus.edu.sg>
Co-authored-by: Ogi Moore <ognyan.moore@gmail.com>
2020-06-08 23:33:12 -07:00
Ogi Moore b12f9174bc
Merge pull request #389 from ales-erjavec/scroll-phase-fix
Revert "ignore wheel events in GraphicsView if mouse disabled"
2020-06-08 23:22:04 -07:00
alfon_news fc7921100e
Fix siScale imprecision errors (#508)
* Fix siScale imprecision errors

* Implement 2xB suggested change

Co-authored-by: Alberto Fontán Correa <afontan@com.uvigo.es>
Co-authored-by: Ogi Moore <ognyan.moore@gmail.com>
2020-06-08 22:51:14 -07:00
Ogi Moore 0dcd79bbc6
Merge pull request #1239 from j9ac9k/PR-343-update
PlotItem doesn't add item if already there
2020-06-08 22:18:15 -07:00
Ogi 66d8943317 PlotItem doesn't add item if already there 2020-06-08 21:50:29 -07:00
Ogi Moore 8fce6c6ad8
Merge pull request #345 from fschill/develop
performance improvement of GLImageItem
2020-06-08 21:40:28 -07:00
Luke Campagnola dc9aa84ce3 Add a faster method for computing pseudoscatter 2019-07-01 18:30:00 -07:00
fake-name 8fa6410382 Moar dumb typos. I managed to totally bugger up the rebase. 2019-06-24 14:14:04 -07:00
fake-name 14925b7fe3 Gah, forgot to add this. 2019-06-24 14:11:54 -07:00
fake-name 3f71276ac3 Fix more mkPen invocations that got added for some reason. 2019-06-24 14:02:19 -07:00
fake-name 18999c2ca1 Consolidate to simpler get is not none check. 2019-06-24 14:01:53 -07:00
Connor Wolf 17e90af36c Avoid constructing shadow pens when no shadow pen is set
Basically, profiling has pointed me to the fact that a fair bit of code time is spent in `setShadowPen()` (actually, it's in `mkPen()`, which `setShadowPen()` calls), even when no shadow pen is specified.

In my application, I'm calling `pyqtgraph.PlotDataItem.setdata()`, which calls through PlotDataItem->setData, PlotDataItem->updateItems. At some point in the call stack, the default value for `shadowPen` is being inserted into the kwargs, which then causes the specious calling of setShadowPen.

Anyways, if we check if shadowPen is a value other then none, this doesn't happen.
2019-06-24 14:01:17 -07:00
MingZZZZZZZZ b773b020a5
Update LegendItem.py 2019-03-25 18:02:04 -04:00
MingZZZZZZZZ 3f93e30b31
Update Legend.py
add legend examples for line plot, bar graph and scatter plot.
2018-12-21 01:47:23 -05:00
MingZZZZZZZZ 7e09022e67
add legend for bar graph items 2018-12-21 01:45:00 -05:00
Ben Deverett 3fc6eff76f added fps class variable to ImageView to enable consistent playback frame rate 2017-09-06 23:30:55 -04:00
vladimir-kraus 668973bd44 raising AttributeError in __getattr__ instead of NameError is the correct way of handling non-existent attributes; otherwise for example hasattr(obj, attribute) would raise NameError instead of returning False if the attribute does not exist 2017-08-04 11:32:21 +02:00
kiwi0fruit 54ddb79e89 Bug-fix and small changes in RawImageWidget.py
1. Bug was in the `def paintGL(self)` method (at least with PySide1): image was mirrored upside down.
2. Added support for `setConfigOptions(imageAxisOrder='row-major')`
3. Small cosmetic changes
2017-06-27 20:53:08 +07:00
kiwi0fruit 8a40c22848 Bug in RawImageWidget.py
For example: it prevents integration of this widget to Enaml.
2017-06-22 16:00:54 +07:00
Megan Kratz 4cd53ddb1b updated PyQt4 template file; still need to update template files for PyQt5 and PySide (but it's not working for me in this moment) 2017-03-31 10:41:39 -04:00
Megan Kratz 8307e96cfe changed dV/dt labels to dy/dx, to be more general 2017-03-31 10:40:24 -04:00
Paul manis b93facb10a Added dv/Dt and V vs V' phasemap Plots to context tool in PlotDataItem
(cherry picked from commit 9d88041a0b3b165439d4e0e45923c83afaefb1ad)
2017-03-31 10:14:11 -04:00
vladimir-kraus 30864df76d added method reset() to GLViewWidget to initialize or reset the current state 2016-11-18 15:03:19 +01:00
vladimir-kraus 051dfe0d31 added method clear() to GLViewWidget 2016-11-18 14:55:39 +01:00
Ales Erjavec 0bc711b31f Revert "ignore wheel events in GraphicsView if mouse disabled"
This reverts commit f49c179275.

On Qt 5.7 ignoring the initial `wheelEvent` when `phase() ==
Qt.ScrollBegin` suppresses all intermediate events (`Qt.ScrollUpdate`)
from being delivered to the view. This makes ViewBox zooming
unresponsive.
2016-11-10 11:22:52 +01:00
Felix Schill 0a25fb0874 clearing _needUpdate flag in GLImageItem to prevent redundant re-upload of textures 2016-05-21 17:50:05 +02:00
lidstrom83 edce25b3ce Set parameter default button's autoDefault value to False.
Makes dialogs containing parameter trees behave more intuitively.
2016-05-03 17:13:46 -06:00
dlidstrom 96e06f212a Provide widgetGroupInterface to GradientWidget 2015-03-16 14:03:58 -06:00
dlidstrom 0908d98d65 Speed up ViewBox panning. Noticeable when a large number of items are present. 2015-03-14 22:06:05 -06:00
Justin Weber 3479dbeb8a Feature: Flow chart nodes resize based on inputs/outputs 2014-11-01 18:11:41 -07:00
632 changed files with 45005 additions and 12561 deletions

46
.flake8
View File

@ -3,47 +3,5 @@ exclude = .git,.tox,__pycache__,doc,old,build,dist
show_source = True
statistics = True
verbose = 2
select =
E101,
E112,
E122,
E125,
E133,
E223,
E224,
E242,
E273,
E274,
E901,
E902,
W191,
W601,
W602,
W603,
W604,
E124,
E231,
E211,
E261,
E271,
E272,
E304,
F401,
F402,
F403,
F404,
E501,
E502,
E702,
E703,
E711,
E712,
E721,
F811,
F812,
F821,
F822,
F823,
F831,
F841,
W292
max-line-length = 88
extend-ignore = E203, W503

55
.github/workflows/codeql-analysis.yml vendored Normal file
View File

@ -0,0 +1,55 @@
name: codeql
on: [push, pull_request]
jobs:
analyze:
name: analyze
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v2
with:
# We must fetch at least the immediate parents so that if this is
# a pull request then we can checkout the head.
fetch-depth: 2
- name: Setup Python
uses: actions/setup-python@v2
with:
python-version: '3.9'
- name: Install Dependencies
run: |
python -m pip install --upgrade pip
pip install PyQt5 numpy scipy
echo "CODEQL_PYTHON=$(which python)" >> $GITHUB_ENV
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: 'python'
# Supported options are ['csharp', 'cpp', 'go', 'java', 'javascript', 'python']
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
queries: +security-and-quality
setup-python-dependencies: false
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1

128
.github/workflows/main.yml vendored Normal file
View File

@ -0,0 +1,128 @@
name: main
on: [push, pull_request]
jobs:
test:
runs-on: ${{ matrix.os }}
timeout-minutes: 30
strategy:
fail-fast: false
matrix:
os: [ubuntu-20.04 , windows-latest, macos-latest]
qt-lib: [pyqt, pyside]
python-version: [3.7, 3.8, 3.9]
include:
- python-version: "3.7"
qt-lib: "pyqt"
qt-version: "PyQt5~=5.12.0"
numpy-version: "~=1.18.0"
- python-version: "3.7"
qt-lib: "pyside"
qt-version: "PySide2~=5.12.0"
numpy-version: "~=1.18.0"
- python-version: "3.8"
qt-lib: "pyqt"
qt-version: "PyQt5~=5.15.0"
numpy-version: "~=1.21.0"
- python-version: "3.8"
qt-lib: "pyside"
qt-version: "PySide2~=5.15.0"
numpy-version: "~=1.21.0"
- python-version: "3.9"
qt-lib: "pyqt"
qt-version: "PyQt6"
numpy-version: "~=1.21.0"
- python-version: "3.9"
qt-lib: "pyside"
qt-version: "PySide6"
numpy-version: "~=1.21.0"
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Setup Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
# Semantic version range syntax or exact version of a Python version
python-version: ${{ matrix.python-version }}
- name: "Install Windows-Mesa OpenGL DLL"
if: runner.os == 'Windows'
run: |
curl -LJO https://github.com/pal1000/mesa-dist-win/releases/download/19.2.7/mesa3d-19.2.7-release-msvc.7z
7z x mesa3d-19.2.7-release-msvc.7z
cd x64
xcopy opengl32.dll C:\windows\system32\mesadrv.dll*
xcopy opengl32.dll C:\windows\syswow64\mesadrv.dll*
REG ADD "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\OpenGLDrivers\MSOGL" /v DLL /t REG_SZ /d "mesadrv.dll" /f
REG ADD "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\OpenGLDrivers\MSOGL" /v DriverVersion /t REG_DWORD /d 1 /f
REG ADD "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\OpenGLDrivers\MSOGL" /v Flags /t REG_DWORD /d 1 /f
REG ADD "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\OpenGLDrivers\MSOGL" /v Version /t REG_DWORD /d 2 /f
REG ADD "HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\OpenGLDrivers\MSOGL" /v DLL /t REG_SZ /d "mesadrv.dll" /f
REG ADD "HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\OpenGLDrivers\MSOGL" /v DriverVersion /t REG_DWORD /d 1 /f
REG ADD "HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\OpenGLDrivers\MSOGL" /v Flags /t REG_DWORD /d 1 /f
REG ADD "HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\OpenGLDrivers\MSOGL" /v Version /t REG_DWORD /d 2 /f
shell: cmd
- name: Install Dependencies
run: |
python -m pip install --upgrade pip setuptools wheel
python -m pip install ${{ matrix.qt-version }} numpy${{ matrix.numpy-version }} scipy pyopengl h5py matplotlib numba
python -m pip install --use-feature=in-tree-build .
python -m pip install pytest
- name: "Install Linux VirtualDisplay"
if: runner.os == 'Linux'
run: |
sudo apt-get update -y
sudo apt-get install -y libxkbcommon-x11-0 x11-utils
sudo apt-get install --no-install-recommends -y libyaml-dev libegl1-mesa libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-randr0 libxcb-render-util0 libxcb-xinerama0
sudo apt-get install -y libopengl0
python -m pip install pytest-xvfb
- name: 'Debug Info'
run: |
echo python location: `which python`
echo python version: `python --version`
echo pytest location: `which pytest`
echo installed packages
python -m pip list
echo pyqtgraph system info
python -c "import pyqtgraph as pg; pg.systemInfo()"
shell: bash
env:
QT_DEBUG_PLUGINS: 1
- name: 'XVFB Display Info'
run: |
xvfb-run --server-args="-screen 0, 1920x1200x24 -ac +extension GLX +render -noreset" python -c "from pyqtgraph.opengl.glInfo import GLTest"
xvfb-run --server-args="-screen 0, 1920x1200x24 -ac +extension GLX +render -noreset" python -m pyqtgraph.util.get_resolution
if: runner.os == 'Linux'
- name: 'Display Info'
run: |
python -c "from pyqtgraph.opengl.glInfo import GLTest"
python -m pyqtgraph.util.get_resolution
if: runner.os != 'Linux'
- name: Run Tests
run: |
mkdir $SCREENSHOT_DIR
pytest tests -v
pytest examples -v
shell: bash
- name: Upload Screenshots
uses: actions/upload-artifact@v2
with:
name: Screenshots (Python ${{ matrix.python-version }} - Qt-Bindings ${{ matrix.qt-lib }} - OS ${{ matrix.os }})
path: $SCREENSHOT_DIR
if-no-files-found: ignore
env:
SCREENSHOT_DIR: ./screenshots
build-wheel:
name: build wheel
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup Python 3.9
uses: actions/setup-python@v2
with:
python-version: '3.9'
- name: Build Wheel
run: |
python -m pip install setuptools wheel
python setup.py bdist_wheel

33
.github/workflows/python-publish.yml vendored Normal file
View File

@ -0,0 +1,33 @@
# This workflows will upload a Python Package using setup.py/twine when a release is created
# For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries
name: Upload Python Package
on:
release:
types: [created]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: '3.x'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install wheel twine setuptools
- name: Build and publish
env:
TWINE_USERNAME: __token__
# The PYPI_PASSWORD must be a pypi token with the "pypi-" prefix with sufficient permissions to upload this package
# https://pypi.org/help/#apitoken
TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }}
run: |
python setup.py sdist bdist_wheel
twine upload dist/*

2
.gitignore vendored
View File

@ -107,3 +107,5 @@ rtr.cvs
# ctags
.tags*
.asv/
asv.conf.json

398
CHANGELOG
View File

@ -1,3 +1,401 @@
pyqtgraph-0.12.3
Highlights:
- PlotCurveItem render speed is now substantially faster
- #1868/#1873 Example app now has filter text input
- #1910 PlotSpeedTest now has parameter tree control panel
New Features:
- #1844 More parameter item types (File, Calendar, ProgressBar, Font, Pen, Slider)
- #1865 Matplotlib colormaps viridis, plasma, magma and inferno are now included in pyqtgraph
- #1911 Extend Colormap with HSL cycles and subset generation
- #1932 Make anti-aliasing optional for paintGL in PlotCurveItem
- #1944 Expand use of QColor functions/methods, including setNamedColor
- #1952 Add checklist parameter item
- #1998 ThreadTrace can now save to a file
Performance Enhancement:
- #1927 Reduce ColorMap inefficiencies
- #1956 use QByteArray as backing store in arrayToQPath
- #1965 perform arrayToQPath in chunks
Bug Fixes:
- #1845 Fix zoom behavior with showGrid by separating mouse events stolen by AxisItem
- #1860 RemoteGraphicsView and RemoteSpeedTest now work under windows venv environments
- #1865 Fixed matplotlib colormap importer code
- #1869 Fix ColorBarItem tick position on export
- #1871 Allow adding items to GLViewWidget before showing plot
- #1875 Fix calls in mouse methods in GLViewWidgets due to missing event.localPos() in PyQt6
- #1876 Fix for improper placement of ROI handle positions in some cases
- #1889/#2003 Fix call to drawText in GLTextItem and GLGradientLegendItem on Python 3.10
- #1897/#1902 Re-enable "experimental" feature with fix for PlotCurveItem with OpenGL on Windows
- #1907 Fix GLVolumeItem example for arm64 platforms
- #1909 Check if AxisItem.label is None before and exit early in resizeEvent
- #1920 arrayToQPath can handle empty paths
- #1936 QPolygonF creation can now handle empty arrays
- #1968 Fix output of clip_array in colormap.modulatedBarData not being assigned
- #1973 Fix PlotItem.updateDecimate unhiding intentionally hidden curves
- #1974 Fix ImageView levelMode with levelMode == 'rgba'
- #1987 Fix HistogramLUTItem itemChanged with use of autoLevel
- #2009 Fix ROI curves hidding in ImageView
API/Behavior Changes:
- #1992 Reverted to traditional log10 mode for PlotDataItem
- #1840 Allow border=False in GraphicsLayout
- #1846 Reduced pollution to pg.namespace
- #1853 ColorMap.getColors and getStops behavior changes
- #1864 Draw GradientLegend in ViewBox coordinates
- #1885 Raise TypeError instead of general Exception if functions.eq is unable to determine equality
- #1903 Cleanup GLViewWidget
- #1908 More readable parameters for ColorBarItem
- #1914 Emit deprecation warning for use of pyqtgraph.ptime
- #1928 Restore previous signature of TargetItem.setPos
- #1940 fix log mode by reverting to previous formulation
- #1954 Deprecate use of values opt for list parameter type
- #1995 ColorButton now takes optional padding argument instead of hardcoded value of 6
Other:
- #1862/#1901 MetaArray now under deprecation warning, to be removed in a future version
- #1892 Add GLPainterItem Example
- #1844 Debugged elusive intermitted CI segfault
- #1870/#1891 Updated README.md
- #1895 Update CONTRIBUTING.md
- #1913 Bump sphinx and theme versions
- #1919 Re-organize paramtypes
- #1935 Remove some unused imports
- #1939 Remove usage of python2_3.py
- #1941 Remove str casting of QTextEdit.toPlainText output
- #1942 Add EOF newline to files missing it
- #1943 Remove python2 code paths
- #1951 Fix typos in docs
- #1957 Bump minimum numpy version to 1.18
- #1968 Fix ImageView calling deprecated QGraphicsItem.scale()
- #1985 delegate float LUTs to makeARGB with warning
- #2014 Replace couple absolute imports with relative imports
pyqtgraph-0.12.2
Highlights
- Qt6 6.0 support has been removed in favor of Qt6 6.1+
- More numba utilization, specifically for makeARGB
- Substantial ImageItem performance improvements have been made thanks to @pijyoi and @outofculture
- Significant performance improvements made to ScatterPlotItem and LinePlots
- More ColorMap features/support (more are coming!)
New Features
- #1318 Added TargetItem
- #1707 Added Qt 6.1 support
- #1729 Allow gradient position to be configured on a histogram
- #1742 Better support for plotting with gradients
- #1776 Add GLTextItem
- #1797 Add ColorMap linearization (using CIELab calculations), colorDistance functionality
- #1865 Include viridis, magma, plasma, inferno, and cividis colormaps
- #1868/#1873 Example app now has a filter text box to search for relevant examples
Performance enhancement:
- #1738, #1695, 1786, #1768, 1794 - ImageItem/makeARGB performance improvements
- #1724 Use math module for scalar values math instead of numpy functions
- #1796 Greatly speed up line plots with use-case of connect='all'
- #1817 Speed up some cases of connect='finite' (few discontinuities)
- #1829 Use QPainter.drawPixmapFragments for ScatterPlotItem
Bug Fixes:
- #1700 Fixed ROI getArrayRegion
- #1748 Fixed bug when plotting boolean arrays in PlotDataItem
- #1791 Callable LUTs being used on the ImageItem substrates
- #1783 Fix memory leak in GLMeshItem
- #1802 Updated cx_freeze example and added workaround for template files
- #1804 Fix mouseClick handling for Qt6 on ROIs
- #1799 Force cameraPosition() to return a Vector in GLViewWidget
- #1809 Sanitize ShowGrid Alpha Input PlotItem
- #1816 Fix bug with Parameter value failing with numpy array-like values
- #1827 Fix BusyCursor to use internal stack provided by setOverrideCursor/restoreOverrideCursor
- #1833 Fix ScatterPlot render issues for PyQt6 6.1.0
- #1843 Fix zoom only applied to y-axis with show grid
- #1860 Fix pyqtgraph multiprocessing on Windows inside a venv environment
- #1869 Fix color bar ticks not being drawn correctly during export
- #1865 Fix matplotlib colormap import code
- #1876 Fix LineROI handle positions being way off-base in some circumstances
- #1871 Allow adding items to GLViewWidget before calling GLViewWidget.show()
- #1864 Draw GradientLegend in ViewBox coordinate system with correct orientation
- #1875 Fixed mouse events in GLViewWidget for PyQt6 bindings
API/Behavior Changes:
- #519 Expose clickable property in PlotDataItem
- #1772 Keep ColorMap values for RGBA as uint8
- #1736 RemoteGraphicsView is now hidpi aware
- #1779 Have SpinBox use fallback minStep in dec mode
- #1706 Colors defined with hex string values must start with a #
- #1819 Added method to disable autoscaling for HistogramLUTItem
- #1638 Expose number of subsamples in ImageItem auto-level determination
- #1824 Remove little-endian assumption for image export
Other
- #1807 Merge pyqtgraph/test-data repo into main repo, move test files to tests directory
- #1862 Scheduled deprecation for MetaArray module
- #1846 Cleaned up pg namespace
pyqtgraph-0.12.1
New Features
- #1596 - Add ColorBarItem for simplified image level adjustment
Performance enhancement:
- #1650 Don't use clip_array on scalers in DynamicPlotRange
- #1617 Optimize makeARGB for ubyte images
- #1648 Implement blocked variant of rescaleData
API/Behavior Change:
- #1690 Parameter Item default created from value if not present
Bug Fixes:
- #1665 Don't pass brush to mkPen in LegendItem.paint()
- #1660 Include colormaps in the python wheel
- #1653 Fix accidental disabling of style updates in PlotDataItem
- #1647 Handle empty adjacency array for GraphItem
- #1680 Fix test suite for big-endian architectures
- #1694 DateAxisItem now accounts for Daylight Savings Time
- #1691 Make sure dynamic range limiter runs on PlotDataItem
pyqtgraph-0.12.0
Deprecations:
- Qt < 5.12, Python < 3.7, and NumPy < 1.17 are no longer supported
New Features:
- Qt6 Compatibility (thank you so much @pijyoi !)
- #1466 CuPy/CUDA support for ImageItem! (thanks you so much @outofculture !)
- #1520/#1518 i18n Localization support for dialogs
- #1497 Allow toggling visibility via mouse click on LegendItem
- #1527 Expand parameter tree documentation
- #1563 Fixes to FlowChart documentation
- #1534 Extend pixmaps for GraphIcons
- #1566 Toggle-able options for ScatterPlotSpeedTest.py
- #1572 Arbitrary scale center ROI
- #1581 Equilateral Triangle ROI
Performance enhancement:
- #1493 significant speedup to invertQTransform()
- #1501 various ImageItem performance improvements
- #1509 mkQApp will now have settings for better HiDPI settings
- #1518 Small Optimizations for functions.rescaleData()
- #1556 Reduce reallocation in PlotDataItem dynamic range limiter
- #1560 Cache scatter-plot items by hashable properties
- #1564 Correct id-based keyring of scatter plot pixmap cache
- #1569 Fix ScatterPlotItem performance regression
- #1619 Stop PlotDataItem from always sending full style information to PlotCurveItem/ScatterPlotItem
- #1630 Combine levels and lut only if both are present
- #1632/#1641/#1649 workaround for np.clip regression since numpy 1.17
- #1641 Introduce functions.clip_array as faster replacement for currently slow np.clip
- #1637 PlotDataItem Fix viewRange <-> dynamic range limit
- #1650 Introduce functions.clip_scalar to clip scalar values
API/Behavior Change:
- #1476 Use log modulus transform for y-axis log scaling
- #1522 InfiniteLine emits clicked signal event
- #1525 Use QOpenGLWidget instead of QGLWidget
- #1540 Support siPrefix with no suffix in SpinBox
- #1541 Use qWaitForWindowExposed instead of qWaitForWindowShown
- #1554 Disable paint in GLScatterPlotItem if it has no data
- #1573/1576 Add deprecation warnings to portions of library
- #1587 qApp.property('darkMode') is now a dynamic property
- #1613 Added keys() method to Parameter class
- #1646 Removed unhelpful warnings
- #1645 Make main stanza PyQt6 compatible
- #1644 Deprecate use of hex strings that do not start with "#" in mkColor
Bug Fixes:
- #1487 Fix InfiniteLabel object has no attribute 'updateText'
- #1491 LinearRegionItem would break with setSpan
- #1496 enableMenu setting now preserved when passing ViewBox to PlotItem
- #1498 PlotDataItem now signals on setPos()
- #1500 AlignCenter should have been AlignHCenter
- #1506 Fix "camerPosition" typo in GLViewWidget
- #1510 Fix RemoteGraphicsView mouse interactions on Qt 5.12
- #1517 Fix RemoteSpeedTest Shutdown Errors
- #1528 Support suffix for int parameters in SpinBox
- #1546 ImageView guards against key events when there is no time axis
- #1558 Fix Small Heights in ErrorBarItem
- #1567 Handle 0-d arrays in InfiniteLine.setPos()
- #1583 RawImageWidget fix port to QOpenGLWidget
- #1594 PlotItem removeItem regression fixed
- #1595 Workaround for CuPy Indexing Bug
- #1597 Fix RawImageWidget transpose did not handle luminance only images
- #1598 Remove references to self from lambdas for Signals
- #1618 Install sys.excepthook for PyQt6
- #1639 Fix transformations in GradientLegend
- #1647 Have GraphItem handle empty adjacency array
- #1653 Fix accidentally styled updates in PlotDataItem
- #1651 Use collections.abc for collections metaclasses in colormap.py
pyqtgraph-0.11.1
New Features:
- #800 Legend for bar graphs
- #1244 Arrow scatter symbols
- #161 Allow hiding individual points in scatter plot
- #395 LegendItem display options
- #1310 Added `Pa` to Units
- #1310 `debug.ThreadTrace` add support for thread names
- #117 Flow Chart Nodes now resized based on number of inputs/outputs
- #1154 `DateAxisItem`
- #1285 Improve control over ROI/handle pens
- #1273 `PColorMeshItem`
- #1397 `LegendItem` enable customization of label text size
- #1422 Permit entry of non-finite values into float `SpinBox`
- #1442 `TickSliderItem.allowRemote` property added
- #1441 `Tick.removeAllowed` is now a regular property and used with `TickSliderItem`
- #1388 Emit a signal when `GraphicsScene` `addItem` or `removeItem` methods called
Performance enhancement:
- #1240/#345 GLImageItem clear need update flag
- #977 Faster computation option for pseudoscatter
- #1297 Improve ArrowItem performance
- #1296 Update `h5py` deps in metaarray
- #1295 Improve TextItem performance
- #1283 Performance improvements to arrayToQPath
- #816 Avoid constructing shadow pens when no shadow pen is set
- #1311 HistogramLUTItem detect trivial gradients
- #1312 avoid extra work when setLabelAngle would have no effect
- #1391 cache viewRect of `GraphicsItem` to reduce CPU load
- #150 Slight speedup to ViewBox panning
- #1420 Many ScatterPlot Improvements
API/Behavior Change:
- #496 Always antialias lines between gradient and region in HistogramLUTItem
- #385 Add headWidth parameter to arrows
- #551 fps variable on ImageView
- #1251 Allow explicit utcOffset timezone in DateAxisItem
- #1310 Add `SignalProxy.block` for temporary disabling of signal forwarding
- #1310 `InfiniteLine.setPos` add support for array argument
- #1310 Rate-limit Qt event processing in ProgressDialog if it is modal
- #1289 Disable autoSIPrefix for DateAxisItem by default
- #1274 Add tickAlpha to AxisItem Style Options
- #402 Added `clear()` method to `GLViewWidget`
- #1264 Added exception to checkOpenGLVersion to highlight OpenGL ES incompatibility
- #1257 Make painter tick font dependent for AxisItem
- #1256 Added `setState`, `setState` and `saveState` to `ROI`
- #1324 Pass through kwargs from MultiPlotItem.plot to PlotItem.plot
- #1387 ScatterPlotItem: Make + and x symbols thicker
- #1362 Make flowchart.Terminal sortable
- #1360 Add "left" and "right" step Modes to PlotCurveItem and PlotDataItem
- #1414 Emit event with mouse clicks for some items
- #1413 `InfiniteLine.viewTransformChanged` now calls superclass-method
- #1411 Hide `WidgetParameterItem.defaultBtn` if param has no default
- #1410 add fontSize kwarg to `Dock`
- #159 Add wrapping option to `SpinBox`
- #330 Set parameter default button `autoDefault` value to `False`
- #157 Provide `WidgetGroupInterface` to `GradientWidget`
- #151 Optional provide custom `PlotItem` to `PlotWidget`
- #1140 Dynamic range limiting in `PlotDataItem`
- #1383 GraphicsView set a transparent background palette
- #1428 Add default color for `ColorMap` type in `ColorMapWidget`
Bug Fixes:
- #1239 Avoid adding PlotItem twice
- #508 siScale precision
- #503 Fix butg in RawImageWidget which resulted in mirrored image
- #1242,#1267 Add the mouse event to the sigClicked signal in PlotCurveItem
- #1247 Restore the now-deprecated PlotWindow and ImageWindow classes
- #1249 Remove ScatterPlotItem's SpotItems during addItem call
- #1252 Fix incorrect tick text boundaries calculation on axis by setting the font
- #1310 Fixed `Vector.__init__` when used with `QVector3D` argument
- #1310 Fix console exception filtering for python3
- #1310 BusyCursor only restore cursor after all nested levels have exited
- #1310 `SimpleParameter.setValue` coerces argument to int if parameter type is int
- #1307 Fixed `reload` methods for python3
- #1294 Various console fixes
- #1293 Various Python3 code fixes
- #1282 Handle Axis SI prefix scaling in MatplotlibExporter
- #1276 Fix problems with high frequency gaming mice
- #1270 Various fixes with AxisItem space being taken
- #1272 `LegendItem.clear()` fixed
- #1268 Check for container before setting dock orientation
- #1312 Avoid divide by 0 condition in TargetItem
- #1309 Properly retain and use hoverPen argument in _PolyLineSegment
- #1371 Explicitly set line width in PlotCurveItem when using OpenGL
- #1319 don't automatically reload modules without pyc
- #1319 make ptime.time on py3 return precision wall-clock time
- #1334 Edge case detection in PlotCurveItem
- #1339 fix handling of QVector3D args in Vector.__init__
- #1336 Make `parent` an explicit kwarg of ArrowItem.__init__, avoid passing into setStyle
- #1368 Disconnect from correct slots in Flowchart
- #1364 fix log scaling
- #963 Allow last image in stack to be selected by slider in ImageView
- #1045 Raise AttributeError in __getattr__ in TabWindow
- #960 Work around PySide setOverrideCursor bug in BusyCursor
- #309 Encode QPropertyAnimation property name if not passed as bytes
- #1072 Fix storing of ragged curves in HDF5Exporter
- #1275 Fix Parameter.hasDefault
- #1291 Get ImageView ROI working with both row and col major data
- #1377 Consolidate and fix downsample factor computation in ImageItem
- #1376 Fix PlotItem.setAxisItems
- #1392 SignalProxy: Correct initialization without slot argument
- #1306 Fix incorrect rendering of overlapping object in renderToArray()
- #1349 Avoid calling method on undefined attribute
- #1367 AxisItem: Account for empty strings in the visibility of text and units
- #1356 Fix `ParameterTree` tree name and title handling
- #1419 Fix `DataTreeWidget` dict sorting crash
- #1408 Fix mouse interaction issues with `DockLabel`
- #329 Fix bug where `int` and `float` parameter limits are not always set
- #158 Make `DockArea` compatible with Qt Designer
- #1405 Fix name setting in `ScatterPlotItem` options
- #1403 Do not apply transparent background to Qt4
- #1468 Allow zero step in `ImageItem`
- #1464 Remove `ViewBox.childGroup`'s `ItemClipsChildrenToShape` flag
- #1461 arrayToQPath revert to old behavior of `connect=ndarray` parameter
- #1459 Fix `TickSliderItem` to avoid ghost ticks
- #1456 Resolve issue with `PlotCurveItem` with merging PRs in an incorrect order
- #1287 Fill in non-finite plot values for Qt versions >= 5.12.3
- #1447 Clipped AxisItem tick value labels to prevent drawing artifacts
- #1435 Fix autosize not taking to the correct range with `TextItem` in view
- #1452 merge `InfiniteLine` caching calls
- #1446 Fix `PlotDataItem.setData([], [])`
- #1443 Fix Viewbox axis zoom in RectMode
- #1439 Fix `TickSliderItem.setTickValue` when it references a `GradientEditorItem` method
- #1361 Prevent item duplication in `Node` context menu
- #1423 Fix typo in `kwargs` for `GridItem.setTextPen`
- #1401 Fix width, height and background in SVG exporter
- #1416 Handle case in `ROI` when `shape`, `vectors`, or `origin` keywords are passed in
Maintenance:
- #389 Revert workaround for upstream QT bug regarding mouse events
- #1243 Ensure setPos in ROI is initialized correctly
- #1241 Pin pytest-xvfb version on py2
- #1310 Added tests for `functions.subArray`
- #1307 Add `ThreadSafeTimer` to `__init__.py`
- #467 derivatePlots cleanup
- #400 `ImageView.Timeline` better visibility
- #1265 Make the documentation reproducible
- #1319 clean up exception messages in console
- #356 Fix some NumPy warnings
- #1326 Improve docs for MultiPlotWidget and MultiPlotItem
- #1331 Migrate imports of PyQt5's sip module to new namespace
- #1370 Fix deprecation warning in multiprocess module
- #308 Fix opt name for SpinBox: range -> bounds in UnsharpMaskNode example
- #887 Update collections.abc imports
- #1142 Miscellaneous doc fixups
- #1169 Avoid using mutable default argument value
- #1073 Python3 fixes
- #1284 Update doc strings to clarify getArrayRegion API for ROI subclasses
- #1042 Close windows at the end of test functions
- #1374 Test warnings cleanup
- #1375 Add targeted Vector test coverage
- #1384 GLViewWidget.pan docstring typo
- #1382 Autoformat LegendItem
- #1396 Add tests for GraphicsView
- #1399 Disable mouse rate limiting on test_ROI
- #1409 Prepend conda-forge channel prior to env creation in CI
- #1302 Fix Example app now works with Qt4/Python2
- #1402 Handle case of version string having no `+`
- #1400 Fix sphinx warnings on `PColorMeshItem`
- #1328 Add docs build job to CI
- #1464 Use `conda-forge` on pyside2+linux
- #1448 Fixes for `examples/CustomPlot.py`
- #1432 ExampleApp fix to use `pg` module from directory
pyqtgraph-0.11.0
NOTICE: This is the _last_ feature release to support Python 2 and Qt 4 (PyQt4 or pyside 1)

135
CODE_OF_CONDUCT.md Normal file
View File

@ -0,0 +1,135 @@
# Code of Conduct
Diversity is one of our huge strengths, but it can also lead to communication issues. To support a welcoming environment
for all, regardless of individual differences, we have a few ground rules that we ask people to adhere to when they
participate in this community. These rules apply equally to founders, organizers, contributors, users and affiliates —
in short, to all participants.
This isnt an exhaustive list of things that you must do, or cant do. Rather, take it in the spirit in which its
intended. Its a guide to make it easier to enrich all of us and the technical communities in which we participate, and
which we represent.
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for
everyone, regardless of background or identity. This includes, but is not limited to, members of any race, ethnicity,
culture, national origin, color, immigration status, social and economic class, educational level, sex, sexual
orientation, gender identity and expression, age, size, family status, political belief, religion, level of experience,
and mental or physical ability.
We pledge to be respectful. Not all of us will agree all the time, but disagreement is no excuse for poor behavior and
poor manners. We might all experience some frustration now and then, but we cannot allow that frustration to turn into a
personal attack. Its important to remember that a community where people feel uncomfortable or threatened is not a
productive one. Members of the PyQtGraph community should be respectful when dealing with each other as well as with
people outside the community.
We pledge to be welcoming, supportive, kind and professional. We pledge to act and interact in ways that contribute to
an open, diverse, inclusive, and healthy community. We pledge not insult or put down other participants, individually or
as a group. Harassment and other exclusionary behavior arent acceptable.
## Examples
Examples of behavior that contributes to a positive environment for our community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience
* Focusing on what is best not just for us as individuals, but for the overall community
Examples of unacceptable behavior include:
* Violent threats or language directed against another person.
* Discriminatory jokes and language.
* Posting sexually explicit or violent material.
* Posting (or threatening to post) other peoples personally identifying information ("doxing").
* Personal insults, especially those using racist or sexist terms.
* Unwelcome sexual attention.
* Repeated harassment of others. In general, if someone asks you to stop, then stop.
* Advocating for, or encouraging, any of the above behavior.
## Where does this code of conduct apply
This Code of Conduct applies within all online community spaces, official organized meetups, and when an individual is
officially representing the community in public spaces, online or offline.
## What to do in case of violations
If you believe someone is violating the code of conduct, we ask that you report it by contacting any of the following
individuals, being sure to include mention of your message being about a "PyQtGraph conduct violation":
* Ognyan Moore @j9ac9k <ognyan.moore@gmail.com>
* Martin Chase @outofculture <outofculture@gmail.com>
* Nathan Jessurun @ntjess <ntjessu@gmail.com>
All complaints will be reviewed and investigated promptly and fairly. All reports will be kept confidential. In some
cases, we may determine that a public statement will need to be made. If thats the case, the identities of all victims
and reporters will remain confidential unless those individuals instruct us otherwise.
If you believe anyone is in physical danger, please notify appropriate law enforcement first. If you are unsure which
law enforcement agency is appropriate, please include this in your report and we will attempt to notify them.
### What to include in the report
* Your contact information (so we can get in touch with you if we need to follow up)
* Names of any individuals involved (real names, nicknames, or pseudonyms). If there were other witnesses besides you,
please try to include them as well.
* When and where the incident occurred. Please be as specific as possible.
* Your account of what occurred. If there is a publicly available record (e.g., a mailing list archive or a public chat
logger) please include a link. Our Slack is currently on a free plan that does not retain more than 10,000 messages of
history, if an incident occurred on Slack please take a screenshot so it is not lost.
* Any extra context you believe existed for the incident.
* Whether you believe this incident is ongoing.
* Any other information you believe we should have.
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take
appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits,
issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for
moderation decisions when appropriate. This removal should be as transparent as possible, with information available in
the same scope of context as the original moderated content, linking to an incident report, the acting moderators,
and/or this document as appropriate.
All community leaders are obligated to respect the privacy and security of the reporter of any incident.
Upon receiving a report of misconduct, the staff must review the incident and determine the following:
* What happened.
* Whether this event constitutes a code of conduct violation.
* Who the bad actor(s) was.
* Whether this is an ongoing situation.
* If any previous disiplinary measures are relevent and in effect.
* If there is a threat to anyones physical safety.
* What impact this has had on the community.
After the conduct committee has a complete account of the events they need to make a decision as to how to resolve the
case. Resolutions might include:
* Nothing (if we determine no violation occurred).
* A private reprimand from the staff to the individual(s) involved, providing clarity around the nature of the
violation, and an explanation of why the behavior was inappropriate.
* A request for a public or private apology.
* A public reprimand.
* An imposed vacation (for example, asking someone to "take a week off" from Slack).
* A permanent or temporary ban from some or all PyQtGraph spaces (Slack, github, mailing list or events) or from
communicating, in public or in private, with some are all of the members of our community.
* Contacting law enforcement.
A response must be sent within one week to the person who filed the report with either a resolution or an explanation of
why the situation is not yet resolved.
A Code of Conduct transparency report will then be published
to [the PyQtGraph users' list](https://groups.google.com/g/pyqtgraph) with anonymized information about any violations
that might have occurred. This report should be handled with care not to divulge personally identifying information
about victims, reporters, and violators, and should serve as a means to ensure that members will be comfortable
reporting violations and that our community will be kept accountable for supporting and encouraging safe spaces.
## Attribution
This Code of Conduct is adapted from
the [Contributor Covenant, version 2.0](https://www.contributor-covenant.org/version/2/0/code_of_conduct.html) and
the [PuPPy Code of Conduct](https://www.pspython.com/pages/code-of-conduct/).

View File

@ -1,72 +1,92 @@
# Contributing to PyQtGraph
Contributions to pyqtgraph are welcome!
Contributions to pyqtgraph are welcome! Be kind and respectful! See [our Code of Conduct](CODE_OF_CONDUCT.md) for details.
Please use the following guidelines when preparing changes:
## Submitting Code Changes
## Development Environment Creation
* The preferred method for submitting changes is by github pull request against the "develop" branch.
* Pull requests should include only a focused and related set of changes. Mixed features and unrelated changes may be rejected.
* For major changes, it is recommended to discuss your plans on the mailing list or in a github issue before putting in too much effort.
* The following deprecations are being considered by the maintainers
* `pyqtgraph.opengl` may be deprecated and replaced with `VisPy` functionality
* After v0.11, pyqtgraph will adopt [NEP-29](https://numpy.org/neps/nep-0029-deprecation_policy.html) which will effectively mean that python2 support will be deprecated
* Qt4 will be deprecated shortly, as well as Qt5<5.9 (and potentially <5.12)
First thing to do is fork the repository, and clone your own fork to your local computer.
```bash
git clone https://github.com/<username>/pyqtgraph.git
cd pyqtgraph
```
While there is nothing preventing users from using `conda` environments, as a general principle, we recommend using the `venv` module for creating an otherwise empty virtual environment. Furthermore, at this time, WSL is not supported (it can likely be made to work, but you're on your own if you go down this route).
```bash
python3.9 -m venv .venv
source .venv/bin/activate
# on windows this would be .venv/Scripts/activate
python -m pip install --upgrade wheel setuptools pip
python -m pip install numpy scipy pyside6 -e .
```
Before making changes to the code-base, create a different branch with a name that should be unique (this makes it easier for maintainers to examine the proposed changes locally).
```bash
git switch -c my-new-feature
```
When you're ready to submit the pull request, do so via the github, and the target of the pull request should be the `master` branch in the pyqtgraph repo.
Pull requests should include only a focused and related set of changes. Mixed features and unrelated changes may be rejected.
For major changes, it is recommended to discuss your plans on the mailing list or in a github issue/discussion before putting in too much effort.
PyQtGraph has adopted [NEP-29](https://numpy.org/neps/nep-0029-deprecation_policy.html) which governs the timeline for phasing out support for numpy and python versions.
## Documentation
* Writing proper documentation and unit tests is highly encouraged. PyQtGraph uses pytest style testing, so tests should usually be included in a tests/ directory adjacent to the relevant code.
* Documentation is generated with sphinx; please check that docstring changes compile correctly
* Writing proper documentation and unit tests is highly encouraged. PyQtGraph uses [`pytest`](https://docs.pytest.org/) for testing.
* Documentation is generated with sphinx, and usage of [numpy-docstyle](https://numpydoc.readthedocs.io/en/latest/format.html) is encouraged (many places in the library do not use this docstring style at present, it's a gradual process to migrate).
* The docs built for this PR can be previewed by clicking on the "Details" link for the read-the-docs entry in the checks section of the PR conversation page.
## Style guidelines
### Rules
### Formatting ~~Rules~~ Suggestions
* PyQtGraph prefers PEP8 for most style issues, but this is not enforced rigorously as long as the code is clean and readable.
* Use `python setup.py style` to see whether your code follows the mandatory style guidelines checked by flake8.
* Exception 1: All variable names should use camelCase rather than underscore_separation. This is done for consistency with Qt
* Exception 2: Function docstrings use ReStructuredText tables for describing arguments:
```text
============== ========================================================
**Arguments:**
argName1 (type) Description of argument
argName2 (type) Description of argument. Longer descriptions must
be wrapped within the column guidelines defined by the
"====" header and footer.
============== ========================================================
```
QObject subclasses that implement new signals should also describe
these in a similar table.
* Variable and Function/Methods that are intended to be part of the public API should be camelCase.
* "Private" methods/variables should have a leading underscore (`_`) before the name.
### Pre-Commit
PyQtGraph developers are highly encouraged to (but not required) to use [`pre-commit`](https://pre-commit.com/). `pre-commit` does a number of checks when attempting to commit the code to ensure it conforms to various standards, such as `flake8`, utf-8 encoding pragma, line-ending fixers, and so on. If any of the checks fail, the commit will be rejected, and you will have the opportunity to make the necessary fixes before adding and committing a file again. This ensures that every commit made conforms to (most) of the styling standards that the library enforces; and you will most likely pass the code style checks by the CI.
PyQtGraph developers are highly encouraged to (but not required) to use [`pre-commit`](https://pre-commit.com/). `pre-commit` does a number of checks when attempting to commit the code to being committed, such as ensuring no large files are accidentally added, address mixed-line-endings types and so on. Check the [pre-commit documentation](https://pre-commit.com) on how to setup.
To make use of `pre-commit`, have it available in your `$PATH` and run `pre-commit install` from the root directory of PyQtGraph.
## Testing
## Testing Setting up a test environment
### Dependencies
### Basic Setup
* tox
* tox-conda
* pytest
* pytest-cov
* pytest-xdist
* Optional: pytest-xvfb
* Optional: pytest-xvfb (used on linux with headless displays)
If you have `pytest<5` (used in python2), you may also want to install `pytest-faulthandler==1.6` plugin to output extra debugging information in case of test failures. This isn't necessary with `pytest>=5`
To run the test suite, after installing the above dependencies run
```bash
python -m pytest examples tests
```
### Tox
As PyQtGraph supports a wide array of Qt-bindings, and python versions, we make use of `tox` to test against most of the configurations in our test matrix. As some of the qt-bindings are only installable via `conda`, `conda` needs to be in your `PATH`, and we utilize the `tox-conda` plugin.
As PyQtGraph supports a wide array of Qt-bindings, and python versions, we make use of `tox` to test against as many supported configurations as feasible. With tox installed, simply run `tox` and it will run through all the configurations. This should be done if there is uncertainty regarding changes working on specific combinations of PyQt bindings and/or python versions.
* Tests for a module should ideally cover all code in that module, i.e., statement coverage should be at 100%.
* To measure the test coverage, un `pytest --cov -n 4` to run the test suite with coverage on 4 cores.
### Continuous Integration
### Continous Integration
For our Continuous Integration, we utilize Github Actions. Tested configurations are visible on [README](README.md).
For our Continuous Integration, we utilize Azure Pipelines. Tested configurations are visible on [README](README.md). More information on coverage and test failures can be found on the respective tabs of the [build results page](https://dev.azure.com/pyqtgraph/pyqtgraph/_build?definitionId=1)
### Benchmarks
( *Still under development* ) To ensure this library is performant, we use [Air Speed Velocity (asv)](https://asv.readthedocs.io/en/stable/) to run benchmarks. For developing on core functions and classes, be aware of any impact your changes have on their speed. To configure and run asv:
```bash
pip install asv
python setup.py asv_config
asv run
```
( TODO publish results )

112
README.md
View File

@ -1,11 +1,15 @@
[![Build Status](https://pyqtgraph.visualstudio.com/pyqtgraph/_apis/build/status/pyqtgraph.pyqtgraph?branchName=develop)](https://pyqtgraph.visualstudio.com/pyqtgraph/_build/latest?definitionId=17&branchName=develop)
[![Documentation Status](https://readthedocs.org/projects/pyqtgraph/badge/?version=latest)](https://pyqtgraph.readthedocs.io/en/latest/?badge=latest)
PyQtGraph
=========
A pure-Python graphics library for PyQt/PySide/PyQt5/PySide2
[![PyPi](https://img.shields.io/pypi/v/pyqtgraph.svg)](https://pypi.org/project/pyqtgraph/)
[![conda-forge](https://img.shields.io/conda/vn/conda-forge/pyqtgraph.svg)](https://anaconda.org/conda-forge/pyqtgraph)
[![Build Status](https://github.com/pyqtgraph/pyqtgraph/workflows/main/badge.svg)](https://github.com/pyqtgraph/pyqtgraph/actions/?query=workflow%3Amain)
[![CodeQL Status](https://github.com/pyqtgraph/pyqtgraph/workflows/codeql/badge.svg)](https://github.com/pyqtgraph/pyqtgraph/actions/?query=workflow%3Acodeql)
[![Documentation Status](https://readthedocs.org/projects/pyqtgraph/badge/?version=latest)](https://pyqtgraph.readthedocs.io/en/latest/?badge=latest)
[![Total alerts](https://img.shields.io/lgtm/alerts/g/pyqtgraph/pyqtgraph.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/pyqtgraph/pyqtgraph/alerts/)
[![Language grade: Python](https://img.shields.io/lgtm/grade/python/g/pyqtgraph/pyqtgraph.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/pyqtgraph/pyqtgraph/context:python)
A pure-Python graphics library for PyQt5/PyQt6/PySide2/PySide6
Copyright 2020 Luke Campagnola, University of North Carolina at Chapel Hill
@ -19,54 +23,104 @@ heavy leverage of numpy for number crunching, Qt's GraphicsView framework for
Requirements
------------
* Python 2.7, or 3.x
* Required
* PyQt 4.8+, PySide, PyQt5, or PySide2
* `numpy`
* Optional
* `scipy` for image processing
* `pyopengl` for 3D graphics
* `hdf5` for large hdf5 binary format support
PyQtGraph has adopted [NEP 29](https://numpy.org/neps/nep-0029-deprecation_policy.html).
This project supports:
* All minor versions of Python released 42 months prior to the project, and at minimum the two latest minor versions.
* All minor versions of numpy released in the 24 months prior to the project, and at minimum the last three minor versions.
* All Qt5 versions from 5.12-5.15, and Qt6 6.1
Currently this means:
* Python 3.7+
* Qt 5.12-5.15, 6.1
* [PyQt5](https://www.riverbankcomputing.com/software/pyqt/),
[PyQt6](https://www.riverbankcomputing.com/software/pyqt/),
[PySide2](https://wiki.qt.io/Qt_for_Python), or
[PySide6](https://wiki.qt.io/Qt_for_Python)
* [`numpy`](https://github.com/numpy/numpy) 1.18+
### Optional added functionalities
Through 3rd part libraries, additional functionality may be added to PyQtGraph, see the table below for a summary.
| Library | Added functionality |
|----------------|-|
| [`scipy`] | <ul><li> Image processing through [`ndimage`]</li><li> Data array filtering through [`signal`] </li><ul> |
| [`pyopengl`] | <ul><li> 3D graphics </li><li> Faster image processing </li><li>Note: on macOS Big Sur only works with python 3.9.1+</li></ul> |
| [`h5py`] | <ul><li> Export in hdf5 format </li></ul> |
| [`colorcet`] | <ul><li> Add a collection of perceptually uniform colormaps </li></ul> |
| [`matplotlib`] | <ul><li> Export of PlotItem in matplotlib figure </li><li> Add matplotlib collection of colormaps </li></ul> |
| [`cupy`] | <ul><li> CUDA-enhanced image processing </li><li> Note: On Windows, CUDA toolkit must be >= 11.1 </li></ul> |
| [`numba`] | <ul><li> Faster image processing </li></ul> |
[`scipy`]: https://github.com/scipy/scipy
[`ndimage`]: https://docs.scipy.org/doc/scipy/reference/ndimage.html
[`signal`]: https://docs.scipy.org/doc/scipy/reference/signal.html
[`pyopengl`]: https://github.com/mcfletch/pyopengl
[`h5py`]: https://github.com/h5py/h5py
[`colorcet`]: https://github.com/holoviz/colorcet
[`matplotlib`]: https://github.com/matplotlib/matplotlib
[`numba`]: https://github.com/numba/numba
[`cupy`]: https://docs.cupy.dev/en/stable/install.html
Qt Bindings Test Matrix
-----------------------
The following table represents the python environments we test in our CI system. Our CI system uses Ubuntu 18.04, Windows Server 2019, and macOS 10.15 base images.
The following table represents the python environments we test in our CI system. Our CI system uses Ubuntu 20.04, Windows Server 2019, and macOS 10.15 base images.
| Qt-Bindings | Python 2.7 | Python 3.6 | Python 3.7 | Python 3.8 |
| :------------- | :----------------: | :----------------: | :----------------: | :----------------: |
| PyQt-4 | :white_check_mark: | :x: | :x: | :x: |
| PySide1 | :white_check_mark: | :x: | :x: | :x: |
| PyQt5-5.9 | :x: | :white_check_mark: | :x: | :x: |
| PySide2-5.13 | :x: | :x: | :white_check_mark: | :x: |
| PyQt5-Latest | :x: | :x: | :x: | :white_check_mark: |
| PySide2-Latest | :x: | :x: | :x: | :white_check_mark: |
| Qt-Bindings | Python 3.7 | Python 3.8 | Python 3.9 |
| :------------- | :----------------: | :----------------: | :----------------: |
| PySide2-5.12 | :white_check_mark: | :x: | :x: |
| PyQt5-5.12 | :white_check_mark: | | :x: |
| PySide2-5.15 | | :white_check_mark: | |
| PyQt5-5.15 | | :white_check_mark: | |
| PySide6-6.1 | | | :white_check_mark: |
| PyQt6-6.1 | | | :white_check_mark: |
* pyqtgraph has had some incompatibilities with PySide2 versions 5.6-5.11, and we recommend you avoid those versions if possible
* on macOS with Python 2.7 and Qt4 bindings (PyQt4 or PySide) the openGL related visualizations do not work reliably
* :x: - Not compatible
* :white_check_mark: - Tested
Support
-------
* Report issues on the [GitHub issue tracker](https://github.com/pyqtgraph/pyqtgraph/issues)
* Post questions to the [mailing list / forum](https://groups.google.com/forum/?fromgroups#!forum/pyqtgraph) or [StackOverflow](https://stackoverflow.com/questions/tagged/pyqtgraph)
Installation Methods
--------------------
* From PyPI:
* From PyPI:
* Last released version: `pip install pyqtgraph`
* Latest development version: `pip install git+https://github.com/pyqtgraph/pyqtgraph@master`
* From conda
* Last released version: `conda install -c conda-forge pyqtgraph`
* To install system-wide from source distribution: `python setup.py install`
* Many linux package repositories have release versions.
* To use with a specific project, simply copy the pyqtgraph subdirectory
* To use with a specific project, simply copy the PyQtGraph subdirectory
anywhere that is importable from your project.
Documentation
-------------
The official documentation lives at https://pyqtgraph.readthedocs.io
The official documentation lives at [pyqtgraph.readthedocs.io](https://pyqtgraph.readthedocs.io)
The easiest way to learn pyqtgraph is to browse through the examples; run `python -m pyqtgraph.examples` to launch the examples application.
The easiest way to learn PyQtGraph is to browse through the examples; run `python -m pyqtgraph.examples` to launch the examples application.
Used By
-------
Here is a partial listing of some of the applications that make use of PyQtGraph!
* [ACQ4](https://github.com/acq4/acq4)
* [Orange3](https://orangedatamining.com/)
* [neurotic](https://neurotic.readthedocs.io)
* [ephyviewer](https://ephyviewer.readthedocs.io)
* [Joulescope](https://www.joulescope.com/)
* [rapidtide](https://rapidtide.readthedocs.io/en/latest/)
* [argos](https://github.com/titusjan/argos)
* [PySpectra](http://hasyweb.desy.de/services/computing/Spock/node138.html)
* [Semi-Supervised Semantic Annotator](https://gitlab.com/ficsresearch/s3ah)
Do you use PyQtGraph in your own project, and want to add it to the list? Submit a pull request to update this listing!

View File

@ -1,99 +0,0 @@
trigger:
branches:
include:
- '*' # Build for all branches if they have a azure-pipelines.yml file.
tags:
include:
- 'v*' # Ensure that we are building for tags starting with 'v' (Official Versions)
# Build only for PRs for master branch
pr:
autoCancel: true
branches:
include:
- master
- develop
variables:
OFFICIAL_REPO: 'pyqtgraph/pyqtgraph'
DEFAULT_MERGE_BRANCH: 'develop'
disable.coverage.autogenerate: 'true'
stages:
- stage: "pre_test"
jobs:
- job: check_diff_size
pool:
vmImage: 'Ubuntu 18.04'
steps:
- bash: |
git config --global advice.detachedHead false
mkdir ~/repo-clone && cd ~/repo-clone
git init
git remote add -t $(Build.SourceBranchName) origin $(Build.Repository.Uri)
git remote add -t ${DEFAULT_MERGE_BRANCH} upstream https://github.com/${OFFICIAL_REPO}.git
git fetch origin $(Build.SourceBranchName)
git fetch upstream ${DEFAULT_MERGE_BRANCH}
git checkout $(Build.SourceBranchName)
MERGE_SIZE=`du -s . | sed -e "s/\t.*//"`
echo -e "Merge Size ${MERGE_SIZE}"
git checkout ${DEFAULT_MERGE_BRANCH}
TARGET_SIZE=`du -s . | sed -e "s/\t.*//"`
echo -e "Target Size ${TARGET_SIZE}"
if [ "${MERGE_SIZE}" != "${TARGET_SIZE}" ]; then
SIZE_DIFF=`expr \( ${MERGE_SIZE} - ${TARGET_SIZE} \)`;
else
SIZE_DIFF=0;
fi;
echo -e "Estimated content size difference = ${SIZE_DIFF} kB" &&
test ${SIZE_DIFF} -lt 100;
displayName: 'Diff Size Check'
continueOnError: true
- job: "style_check"
pool:
vmImage: "Ubuntu 18.04"
steps:
- task: UsePythonVersion@0
inputs:
versionSpec: 3.7
- bash: |
pip install flake8
python setup.py style
displayName: 'flake8 check'
continueOnError: true
- job: "build_wheel"
pool:
vmImage: 'Ubuntu 18.04'
steps:
- task: UsePythonVersion@0
inputs:
versionSpec: 3.8
- script: |
python -m pip install setuptools wheel
python setup.py bdist_wheel --universal
displayName: "Build Python Wheel"
continueOnError: false
- publish: dist
artifact: wheel
- stage: "test"
jobs:
- template: azure-test-template.yml
parameters:
name: linux
vmImage: 'Ubuntu 18.04'
- template: azure-test-template.yml
parameters:
name: windows
vmImage: 'windows-2019'
- template: azure-test-template.yml
parameters:
name: macOS
vmImage: 'macOS-10.15'

View File

@ -1,203 +0,0 @@
# Azure Pipelines CI job template for PyDM Tests
# https://docs.microsoft.com/en-us/azure/devops/pipelines/languages/anaconda?view=azure-devops
parameters:
name: ''
vmImage: ''
jobs:
- job: ${{ parameters.name }}
pool:
vmImage: ${{ parameters.vmImage }}
strategy:
matrix:
Python27-PyQt4-4.8:
python.version: '2.7'
qt.bindings: "pyqt=4"
install.method: "conda"
Python27-PySide-4.8:
python.version: '2.7'
qt.bindings: "pyside"
install.method: "conda"
Python36-PyQt5-5.9:
python.version: "3.6"
qt.bindings: "pyqt"
install.method: "conda"
Python37-PySide2-5.13:
python.version: "3.7"
qt.bindings: "pyside2"
install.method: "conda"
Python38-PyQt5-Latest:
python.version: '3.8'
qt.bindings: "PyQt5"
install.method: "pip"
Python38-PySide2-Latest:
python.version: '3.8'
qt.bindings: "PySide2"
install.method: "pip"
steps:
- task: DownloadPipelineArtifact@2
inputs:
source: 'current'
artifact: wheel
path: 'dist'
- task: ScreenResolutionUtility@1
inputs:
displaySettings: 'specific'
width: '1920'
height: '1080'
condition: eq(variables['agent.os'], 'Windows_NT' )
- task: UsePythonVersion@0
inputs:
versionSpec: $(python.version)
condition: eq(variables['install.method'], 'pip')
- script: |
curl -LJO https://github.com/pal1000/mesa-dist-win/releases/download/19.1.0/mesa3d-19.1.0-release-msvc.exe
7z x mesa3d-19.1.0-release-msvc.exe
cd x64
xcopy opengl32.dll C:\windows\system32\mesadrv.dll*
xcopy opengl32.dll C:\windows\syswow64\mesadrv.dll*
REG ADD "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\OpenGLDrivers\MSOGL" /v DLL /t REG_SZ /d "mesadrv.dll" /f
REG ADD "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\OpenGLDrivers\MSOGL" /v DriverVersion /t REG_DWORD /d 1 /f
REG ADD "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\OpenGLDrivers\MSOGL" /v Flags /t REG_DWORD /d 1 /f
REG ADD "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\OpenGLDrivers\MSOGL" /v Version /t REG_DWORD /d 2 /f
REG ADD "HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\OpenGLDrivers\MSOGL" /v DLL /t REG_SZ /d "mesadrv.dll" /f
REG ADD "HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\OpenGLDrivers\MSOGL" /v DriverVersion /t REG_DWORD /d 1 /f
REG ADD "HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\OpenGLDrivers\MSOGL" /v Flags /t REG_DWORD /d 1 /f
REG ADD "HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\OpenGLDrivers\MSOGL" /v Version /t REG_DWORD /d 2 /f
displayName: "Install Windows-Mesa OpenGL DLL"
condition: eq(variables['agent.os'], 'Windows_NT')
- bash: |
if [ $(agent.os) == 'Linux' ]
then
echo "##vso[task.prependpath]$CONDA/bin"
elif [ $(agent.os) == 'Darwin' ]
then
sudo chown -R $USER $CONDA
echo "##vso[task.prependpath]$CONDA/bin"
elif [ $(agent.os) == 'Windows_NT' ]
then
echo "##vso[task.prependpath]$CONDA/Scripts"
else
echo 'Just what OS are you using?'
fi
displayName: 'Add Conda To $PATH'
condition: eq(variables['install.method'], 'conda' )
continueOnError: false
- bash: |
if [ $(install.method) == "conda" ]
then
conda update --all --yes --quiet
conda create --name test-environment-$(python.version) python=$(python.version) --yes --quiet
source activate test-environment-$(python.version)
conda config --env --set always_yes true
if [ $(python.version) == '2.7' ]
then
conda config --set restore_free_channel true
fi
if [ $(qt.bindings) == "pyside2" ] || ([ $(qt.bindings) == 'pyside' ] && [ $(agent.os) == 'Darwin' ])
then
conda config --prepend channels conda-forge
fi
conda info
conda install $(qt.bindings) numpy scipy pyopengl h5py six --yes --quiet
else
pip install $(qt.bindings) numpy scipy pyopengl h5py six
fi
pip install pytest pytest-cov coverage pytest-xdist
if [ $(python.version) == "2.7" ]
then
pip install pytest-faulthandler==1.6.0
export PYTEST_ADDOPTS="--faulthandler-timeout=15"
else
pip install pytest pytest-cov coverage
fi
displayName: "Install Dependencies"
- bash: |
if [ $(install.method) == "conda" ]
then
source activate test-environment-$(python.version)
fi
python -m pip install --no-index --find-links=dist pyqtgraph
displayName: 'Install Wheel'
- bash: |
sudo apt-get install -y libxkbcommon-x11-dev
# workaround for QTBUG-84489
sudo apt-get install -y libxcb-xfixes0 libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-randr0 libxcb-render-util0 libxcb-xinerama0
if [ $(install.method) == "conda" ]
then
source activate test-environment-$(python.version)
fi
pip install PyVirtualDisplay==0.2.5 pytest-xvfb
displayName: "Virtual Display Setup"
condition: eq(variables['agent.os'], 'Linux' )
- bash: |
export QT_DEBUG_PLUGINS=1
if [ $(install.method) == "conda" ]
then
source activate test-environment-$(python.version)
fi
echo python location: `which python`
echo python version: `python --version`
echo pytest location: `which pytest`
echo installed packages
pip list
echo pyqtgraph system info
python -c "import pyqtgraph as pg; pg.systemInfo()"
echo display information
if [ $(agent.os) == 'Linux' ]
then
export DISPLAY=:99.0
Xvfb :99 -screen 0 1920x1200x24 -ac +extension GLX +render -noreset &
sleep 3
fi
python -m pyqtgraph.util.get_resolution
echo openGL information
python -c "from pyqtgraph.opengl.glInfo import GLTest"
displayName: 'Debug Info'
continueOnError: false
- bash: |
if [ $(install.method) == "conda" ]
then
source activate test-environment-$(python.version)
fi
mkdir -p "$SCREENSHOT_DIR"
# echo "If Screenshots are generated, they may be downloaded from:"
# echo "https://dev.azure.com/pyqtgraph/pyqtgraph/_apis/build/builds/$(Build.BuildId)/artifacts?artifactName=Screenshots&api-version=5.0"
pytest . -v \
-n 1 \
--junitxml=junit/test-results.xml \
--cov pyqtgraph --cov-report=xml --cov-report=html
displayName: 'Unit tests'
env:
AZURE: 1
SCREENSHOT_DIR: $(Build.ArtifactStagingDirectory)/screenshots
- task: PublishBuildArtifacts@1
displayName: 'Publish Screenshots'
condition: failed()
inputs:
pathtoPublish: $(Build.ArtifactStagingDirectory)/screenshots
artifactName: Screenshots
- task: PublishTestResults@2
condition: succeededOrFailed()
inputs:
testResultsFiles: '**/test-*.xml'
testRunTitle: 'Test Results for $(agent.os) - $(python.version) - $(qt.bindings) - $(install.method)'
publishRunAttachments: true
- task: PublishCodeCoverageResults@1
inputs:
codeCoverageTool: Cobertura
summaryFileLocation: '$(System.DefaultWorkingDirectory)/**/coverage.xml'
reportDirectory: '$(System.DefaultWorkingDirectory)/**/htmlcov'

1
benchmarks/__init__.py Normal file
View File

@ -0,0 +1 @@

View File

@ -0,0 +1,30 @@
import numpy as np
import pyqtgraph as pg
rng = np.random.default_rng(12345)
class _TimeSuite:
params = ([10_000, 100_000, 1_000_000], ['all', 'finite', 'pairs', 'array'])
def setup(self, nelems, connect):
self.xdata = np.arange(nelems, dtype=np.float64)
self.ydata = rng.standard_normal(nelems, dtype=np.float64)
if connect == 'array':
self.connect_array = np.ones(nelems, dtype=bool)
if self.have_nonfinite:
self.ydata[::5000] = np.nan
def time_test(self, nelems, connect):
if connect == 'array':
connect = self.connect_array
pg.arrayToQPath(self.xdata, self.ydata, connect=connect)
class TimeSuiteAllFinite(_TimeSuite):
def __init__(self):
super().__init__()
self.have_nonfinite = False
class TimeSuiteWithNonFinite(_TimeSuite):
def __init__(self):
super().__init__()
self.have_nonfinite = True

View File

@ -0,0 +1,139 @@
# -*- coding: utf-8 -*-
import numpy as np
import pyqtgraph as pg
try:
import cupy as cp
pg.setConfigOption("useCupy", True)
except ImportError:
cp = None
try:
import numba
except ImportError:
numba = None
def renderQImage(*args, **kwargs):
imgitem = pg.ImageItem(axisOrder='row-major')
if 'autoLevels' not in kwargs:
kwargs['autoLevels'] = False
imgitem.setImage(*args, **kwargs)
imgitem.render()
def prime_numba():
shape = (64, 64)
lut_small = np.random.randint(256, size=(256, 3), dtype=np.uint8)
lut_big = np.random.randint(256, size=(512, 3), dtype=np.uint8)
for lut in [lut_small, lut_big]:
renderQImage(np.zeros(shape, dtype=np.uint8), levels=(20, 220), lut=lut)
renderQImage(np.zeros(shape, dtype=np.uint16), levels=(250, 3000), lut=lut)
renderQImage(np.zeros(shape, dtype=np.float32), levels=(-4.0, 4.0), lut=lut)
class _TimeSuite(object):
def __init__(self):
super(_TimeSuite, self).__init__()
self.size = None
self.float_data = None
self.uint8_data = None
self.uint8_lut = None
self.uint16_data = None
self.uint16_lut = None
self.cupy_uint16_lut = None
self.cupy_uint8_lut = None
def setup(self):
size = (self.size, self.size)
self.float_data, self.uint16_data, self.uint8_data, self.uint16_lut, self.uint8_lut = self._create_data(
size, np
)
if numba is not None:
# ensure JIT compilation
pg.setConfigOption("useNumba", True)
prime_numba()
pg.setConfigOption("useNumba", False)
if cp:
_d1, _d2, _d3, self.cupy_uint16_lut, self.cupy_uint8_lut = self._create_data(size, cp)
renderQImage(cp.asarray(self.uint16_data["data"])) # prime the gpu
@property
def numba_uint16_lut(self):
return self.uint16_lut
@property
def numba_uint8_lut(self):
return self.uint8_lut
@property
def numpy_uint16_lut(self):
return self.uint16_lut
@property
def numpy_uint8_lut(self):
return self.uint8_lut
@staticmethod
def _create_data(size, xp):
float_data = {
"data": xp.random.normal(size=size).astype("float32"),
"levels": [-4.0, 4.0],
}
uint16_data = {
"data": xp.random.randint(100, 4500, size=size).astype("uint16"),
"levels": [250, 3000],
}
uint8_data = {
"data": xp.random.randint(0, 255, size=size).astype("ubyte"),
"levels": [20, 220],
}
c_map = xp.array([[-500.0, 255.0], [-255.0, 255.0], [0.0, 500.0]])
uint8_lut = xp.zeros((256, 4), dtype="ubyte")
for i in range(3):
uint8_lut[:, i] = xp.clip(xp.linspace(c_map[i][0], c_map[i][1], 256), 0, 255)
uint8_lut[:, 3] = 255
uint16_lut = xp.zeros((2 ** 16, 4), dtype="ubyte")
for i in range(3):
uint16_lut[:, i] = xp.clip(xp.linspace(c_map[i][0], c_map[i][1], 2 ** 16), 0, 255)
uint16_lut[:, 3] = 255
return float_data, uint16_data, uint8_data, uint16_lut, uint8_lut
def make_test(dtype, kind, use_levels, lut_name, func_name):
def time_test(self):
data = getattr(self, dtype + "_data")
levels = data["levels"] if use_levels else None
lut = getattr(self, f"{kind}_{lut_name}_lut", None) if lut_name is not None else None
pg.setConfigOption("useNumba", kind == "numba")
img_data = data["data"]
if kind == "cupy":
img_data = cp.asarray(img_data)
renderQImage(img_data, lut=lut, levels=levels)
time_test.__name__ = func_name
return time_test
for option in ["cupy", "numba", "numpy"]:
if option == "cupy" and cp is None:
continue
if option == "numba" and numba is None:
continue
for data_type in ["float", "uint16", "uint8"]:
for lvls in [True, False]:
if data_type == "float" and not lvls:
continue
for lutname in [None, "uint8", "uint16"]:
name = (
f'time_1x_renderImageItem_{option}_{data_type}_{"" if lvls else "no"}levels_{lutname or "no"}lut'
)
setattr(_TimeSuite, name, make_test(data_type, option, lvls, lutname, name))
class Time4096Suite(_TimeSuite):
def __init__(self):
super(Time4096Suite, self).__init__()
self.size = 4096

View File

@ -1,5 +1,5 @@
pyside2
numpy
pyopengl
sphinx
sphinx_rtd_theme
sphinx==4.1.1
sphinx_rtd_theme==0.5.2

View File

@ -0,0 +1,7 @@
GLGraphItem
===========
.. autoclass:: pyqtgraph.opengl.GLGraphItem
:members:
.. automethod:: pyqtgraph.opengl.GLGraphItem.__init__

View File

@ -19,6 +19,7 @@ Contents:
glviewwidget
glgriditem
glgraphitem
glsurfaceplotitem
glvolumeitem
glimageitem

View File

@ -12,7 +12,7 @@ Contents:
widgets/index
3dgraphics/index
colormap
parametertree/index
parametertree/apiref
dockarea
graphicsscene/index
flowchart/index

View File

@ -1,8 +1,84 @@
ColorMap
========
Color Maps
==========
A color map defines a relationship between scalar data values and a range of colors. Color maps are
commonly used to generate false color images, color scatter-plot points, and illustrate the height
of surface plots.
PyQtGraph's :class:`~pyqtgraph.ColorMap` can conveniently be applied to images and interactively
adjusted by using :class:`~pyqtgraph.ColorBarItem`.
To provide interactively user-defined color mappings, see
:class:`~pyqtgraph.GradientEditorItem` and :class:`~pyqtgraph.GradientWidget`, which wraps it.
:class:`~pyqtgraph.GradientEditorItem` combines the editing with a histogram and controls for
interactively adjusting image levels.
ColorMap can also be used a convenient source of colors from a consistent palette or to generate
QPen and QBrush objects used to draw lines and fills that are colored according to their values
along the horizontal or vertical axis.
Sources for color maps
----------------------
Color maps can be user defined by assigning a number of *stops* over the range of 0 to 1. A color
is given for each stop, and the in-between values are generated by interpolation.
When map colors directly represent values, an improperly designed map can obscure detail over
certain ranges of values, while creating false detail in others. PyQtGraph includes the
perceptually uniform color maps provided by the
`Colorcet project <https://colorcet.holoviz.org/>`_. Color maps can also be imported from the
``colorcet`` library or from ``matplotlib``, if either of these is installed.
To see all available color maps, please run the `ColorMap` demonstration available in the suite of
:ref:`examples`.
Examples
--------
False color display of a 2D data set. Display levels are controlled by
a :class:`ColorBarItem <pyqtgraph.ColorBarItem>`:
.. literalinclude:: images/gen_example_false_color_image.py
:lines: 18-28
:dedent: 8
Using QtGui.QPen and QtGui.QBrush to color plots according to the plotted value:
.. literalinclude:: images/gen_example_gradient_plot.py
:lines: 16-33
:dedent: 8
.. image::
images/example_false_color_image.png
:width: 49%
:alt: Example of a false color image
.. image::
images/example_gradient_plot.png
:width: 49%
:alt: Example of drawing and filling plots with gradients
The use of color maps is also demonstrated in the `ImageView`, `Color Gradient Plots` and `ColorBarItem`
:ref:`examples`.
API Reference
-------------
.. autofunction:: pyqtgraph.colormap.listMaps
.. autofunction:: pyqtgraph.colormap.get
.. autofunction:: pyqtgraph.colormap.getFromMatplotlib
.. autofunction:: pyqtgraph.colormap.getFromColorcet
.. autofunction:: pyqtgraph.colormap.modulatedBarData
.. autoclass:: pyqtgraph.ColorMap
:members:
.. automethod:: pyqtgraph.ColorMap.__init__

View File

@ -11,6 +11,7 @@
# All configuration values have a default; values that are commented out
# serve to show the default.
import time
import sys
import os
from datetime import datetime
@ -30,7 +31,7 @@ import pyqtgraph
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.viewcode']
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.viewcode', 'sphinx.ext.napoleon']
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
@ -46,7 +47,10 @@ master_doc = 'index'
# General information about the project.
project = 'pyqtgraph'
copyright = '2011 - {}, Luke Campagnola'.format(datetime.now().year)
now = datetime.utcfromtimestamp(
int(os.environ.get('SOURCE_DATE_EPOCH', time.time()))
)
copyright = '2011 - {}, Luke Campagnola'.format(now.year)
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
@ -135,7 +139,7 @@ html_static_path = ['_static']
# add the theme customizations
def setup(app):
app.add_stylesheet("custom.css")
app.add_css_file("custom.css")
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.

View File

@ -26,10 +26,9 @@ imageAxisOrder str 'col-major' For 'row-major', image
change in the future.
editorCommand str or None None Command used to invoke code editor from ConsoleWidget.
exitCleanup bool True Attempt to work around some exit crash bugs in PyQt and PySide.
useWeave bool False Use weave to speed up some operations, if it is available.
weaveDebug bool False Print full error message if weave compile fails.
useOpenGL bool False Enable OpenGL in GraphicsView. This can have unpredictable effects on stability
and performance.
useOpenGL bool False Enable OpenGL in GraphicsView.
useCupy bool False Use cupy to perform calculations on the GPU. Only currently applies to
ImageItem and its associated functions.
enableExperimental bool False Enable experimental features (the curious can search for this key in the code).
crashWarning bool False If True, print warnings about situations that may result in a crash.
================== =================== ================== ================================================================================

View File

@ -41,23 +41,33 @@ Export Formats
Exporting from the API
----------------------
To export a file programatically, follow this example::
To export a file programatically, follow this example:
import pyqtgraph as pg
import pyqtgraph.exporters
.. code-block:: python
import pyqtgraph as pg
import pyqtgraph.exporters
# generate something to export
plt = pg.plot([1,5,2,4,3])
# generate something to export
plt = pg.plot([1,5,2,4,3])
# create an exporter instance, as an argument give it
# the item you wish to export
exporter = pg.exporters.ImageExporter(plt.plotItem)
# create an exporter instance, as an argument give it
# the item you wish to export
exporter = pg.exporters.ImageExporter(plt.plotItem)
# set export parameters if needed
exporter.parameters()['width'] = 100 # (note this also affects height parameter)
# set export parameters if needed
exporter.parameters()['width'] = 100 # (note this also affects height parameter)
# save to file
exporter.export('fileName.png')
# save to file
exporter.export('fileName.png')
To export the overall layout of a GraphicsLayoutWidget `grl`, the exporter initialization is
.. code-block:: python
exporter = pg.exporters.ImageExporter( grl.scene() )
instead.
Exporting 3D Graphics
@ -69,5 +79,3 @@ generate an image from a GLViewWidget by using QGLWidget.grabFrameBuffer or QGLW
glview.grabFrameBuffer().save('fileName.png')
See the Qt documentation for more information.

View File

@ -40,7 +40,7 @@ In the example above, each terminal is defined by a dictionary of options which
Once the flowchart is created, add its control widget to your application::
ctrl = fc.ctrlWidget()
ctrl = fc.widget()
myLayout.addWidget(ctrl) ## read Qt docs on QWidget and layouts for more information
The control widget provides several features:

View File

@ -30,11 +30,11 @@ Qt uses the classes QColor, QPen, and QBrush to determine how to draw lines and
.. autofunction:: pyqtgraph.intColor
.. autofunction:: pyqtgraph.colorTuple
.. autofunction:: pyqtgraph.CIELabColor
.. autofunction:: pyqtgraph.colorStr
.. autofunction:: pyqtgraph.colorCIELab
.. autofunction:: pyqtgraph.glColor
.. autofunction:: pyqtgraph.colorDistance
Data Slicing
@ -65,6 +65,8 @@ SI Unit Conversion Functions
.. autofunction:: pyqtgraph.siEval
.. autofunction:: pyqtgraph.siParse
Image Preparation Functions
---------------------------
@ -102,3 +104,14 @@ 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
.. autofunction:: pyqtgraph.glColor

View File

@ -0,0 +1,7 @@
ColorBarItem
============
.. autoclass:: pyqtgraph.ColorBarItem
:members:
.. automethod:: pyqtgraph.ColorBarItem.__init__

View File

@ -1,8 +1,66 @@
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.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).
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.
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
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.
.. _ImageItem_examples:
Examples
--------
.. literalinclude:: ../images/gen_example_imageitem_transform.py
:lines: 19-28
:dedent: 8
.. image::
../images/example_imageitem_transform.png
:width: 49%
:alt: Example of transformed image display
.. autoclass:: pyqtgraph.ImageItem
:members:
.. automethod:: pyqtgraph.ImageItem.__init__

View File

@ -12,12 +12,15 @@ Contents:
plotdataitem
plotitem
imageitem
colorbaritem
pcolormeshitem
graphitem
viewbox
linearregionitem
infiniteline
roi
graphicslayout
multiplotitem
plotcurveitem
scatterplotitem
isocurveitem
@ -44,3 +47,4 @@ Contents:
uigraphicsitem
graphicswidgetanchor
dateaxisitem
targetitem

View File

@ -11,6 +11,7 @@ GraphicsWidget
GridItem
HistogramLUTItem
ImageItem
PColorMeshItem
InfiniteLine
LabelItem
LinearRegionItem

View File

@ -0,0 +1,5 @@
MultiPlotItem
=============
.. autoclass:: pyqtgraph.MultiPlotItem
:members:

View File

@ -0,0 +1,8 @@
PColorMeshItem
==============
.. autoclass:: pyqtgraph.PColorMeshItem
:members:
.. automethod:: pyqtgraph.PColorMeshItem.__init__

View File

@ -0,0 +1,17 @@
TargetItem
==========
.. autoclass:: pyqtgraph.TargetItem
:members:
.. automethod:: pyqtgraph.TargetItem.__init__
TargetLabel
==================
.. autoclass:: pyqtgraph.TargetLabel
:members:
.. automethod:: pyqtgraph.TargetLabel.__init__

View File

@ -51,7 +51,29 @@ For the serious application developer, all of the functionality in pyqtgraph is
#. Under "Header file", enter "pyqtgraph".
#. Click "Add", then click "Promote".
See the designer documentation for more information on promoting widgets. The "VideoSpeedTest" and "ScatterPlotSpeedTest" examples both demonstrate the use of .ui files that are compiled to .py modules using pyuic4 or pyside-uic. The "designerExample" example demonstrates dynamically generating python classes from .ui files (no pyuic4 / pyside-uic needed).
See the designer documentation for more information on promoting widgets. The "VideoSpeedTest" and "ScatterPlotSpeedTest" examples both demonstrate the use of .ui files that are compiled to .py modules using pyuic5 or pyside-uic. The "designerExample" example demonstrates dynamically generating python classes from .ui files (no pyuic5 / pyside-uic needed).
HiDPI Displays
--------------
PyQtGraph has a method :func:`mkQApp <pyqtgraph.Qt.mkQApp>` that by default sets what we have tested to be the best combination of options to support hidpi displays, when in combination with non-hidpi secondary displays. For your application, you may have instantiated ``QApplication`` yourself, in which case we advise setting these options *before* runing ``QApplication.exec_()``.
For Qt6 bindings, this functionally "just works" without having to set any attributes.
On Versions of Qt >= 5.14 and < 6; you can get ideal behavior with the following lines::
os.environ["QT_ENABLE_HIGHDPI_SCALING"] = "1"
QApplication.setHighDpiScaleFactorRoundingPolicy(QtCore.Qt.HighDpiScaleFactorRoundingPolicy.PassThrough)
If you are on Qt >= 5.6 and < 5.14; you can get near ideal behavior with the following lines::
QApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling)
QApplication.setAttribute(QtCore.Qt.AA_UseHighDpiPixmaps)
With the later, ideal behavior was not achieved.
.. autofunction:: pyqtgraph.Qt.mkQApp
PyQt and PySide
@ -61,15 +83,16 @@ PyQtGraph supports two popular python wrappers for the Qt library: PyQt and PySi
APIs and functionality, but for various reasons (discussed elsewhere) you may prefer to use one package or the other. When
pyqtgraph is first imported, it automatically determines which library to use by making the fillowing checks:
#. If PyQt4 is already imported, use that
#. Else, if PySide is already imported, use that
#. Else, attempt to import PyQt4
#. If that import fails, attempt to import PySide.
#. If PyQt5 is already imported, use that
#. Else, if PySide2 is already imported, use that
#. Else, if PySide6 is already imported, use that
#. Else, if PyQt6 is already imported, use that
#. Else, attempt to import PyQt5, PySide2, PySide6, PyQt6, in that order.
If you have both libraries installed on your system and you wish to force pyqtgraph to use one or the other, simply
make sure it is imported before pyqtgraph::
import PySide ## this will force pyqtgraph to use PySide instead of PyQt4
import PySide2 ## this will force pyqtgraph to use PySide2 instead of PyQt5
import pyqtgraph as pg
@ -78,11 +101,11 @@ Embedding PyQtGraph as a sub-package of a larger project
When writing applications or python packages that make use of pyqtgraph, it is most common to install pyqtgraph system-wide (or within a virtualenv) and simply call `import pyqtgraph` from within your application. The main benefit to this is that pyqtgraph is configured independently of your application and thus you (or your users) are free to install newer versions of pyqtgraph without changing anything in your application. This is standard practice when developing with python.
However, it is also often the case, especially for scientific applications, that software is written for a very specific purpose and then archived. If we want to ensure that the software will still work ten years later, then it is preferrable to tie the application to a very specific version of pyqtgraph and *avoid* importing the system-installed version of pyqtgraph, which may be much newer (and potentially incompatible). This is especially the case when the application requires site-specific modifications to the pyqtgraph package which may not be present in the main releases.
Occasionally, a specific program needs to be kept in working order for an extended amount of time after development has been completed. This is often the case for single-purpose scientific applications. If we want to ensure that the software will still work ten years later, then it is preferable to tie it to a very specific version of pyqtgraph and *avoid* importing the system-installed version, which may be much newer and potentially incompatible. This is especially true when the application requires site-specific modifications to the pyqtgraph package.
PyQtGraph facilitates this usage through two mechanisms. First, all internal import statements in pyqtgraph are relative, which allows the package to be renamed or used as a sub-package without any naming conflicts with other versions of pyqtgraph on the system (that is, pyqtgraph never refers to itself internally as 'pyqtgraph'). Second, a git subtree repository is available at https://github.com/pyqtgraph/pyqtgraph-core.git that contains only the 'pyqtgraph/' subtree, allowing the code to be cloned directly as a subtree of the application which uses it.
To support such a separate local installation, all internal import statements in pyqtgraph are relative. That means that pyqtgraph never refers to itself internally as 'pyqtgraph'. This allows the package to be renamed or used as a sub-package without any naming conflicts with other versions of pyqtgraph on the system.
The basic approach is to clone the repository into the appropriate location in your package. When you import pyqtgraph from within your package, be sure to use the full name to avoid importing any system-installed pyqtgraph packages. For example, imagine a simple project has the following structure::
The basic approach is to clone the repository into the appropriate location in your project. When you import pyqtgraph, be sure to use the full name to avoid importing any system-installed pyqtgraph packages. For example, imagine a simple project has the following structure::
my_project/
__init__.py
@ -92,32 +115,32 @@ The basic approach is to clone the repository into the appropriate location in y
def my_plot_function(*data):
pg.plot(*data)
To embed a specific version of pyqtgraph, we would clone the pyqtgraph-core repository inside the project::
To embed a specific version of pyqtgraph, we would clone the pyqtgraph repository inside the project, with a directory name that distinguishes it from a system-wide installation::
my_project$ git clone https://github.com/pyqtgraph/pyqtgraph-core.git
my_project$ git clone https://github.com/pyqtgraph/pyqtgraph.git local_pyqtgraph
Then adjust the import statements accordingly::
my_project/
__init__.py
pyqtgraph/
local_pyqtgraph/
plotting.py
"""Plotting functions used by this package"""
import my_project.pyqtgraph as pg # be sure to use the local subpackage
# rather than any globally-installed
# versions.
import local_pyqtgraph.pyqtgraph as pg # be sure to use the local subpackage
# rather than any globally-installed
# version.
def my_plot_function(*data):
pg.plot(*data)
Use ``git checkout pyqtgraph-core-x.x.x`` to select a specific version of the repository, or use ``git pull`` to pull pyqtgraph updates from upstream (see the git documentation for more information).
Use ``git checkout pyqtgraph-x.x.x`` to select a specific library version from the repository, or use ``git pull`` to pull pyqtgraph updates from upstream (see the git documentation for more information). If you do not plan to make use of git's versioning features, adding the option ``--depth 1`` to the ``git clone`` command retrieves only the latest version.
For projects that already use git for code control, it is also possible to include pyqtgraph as a git subtree within your own repository. The major advantage to this approach is that, in addition to being able to pull pyqtgraph updates from the upstream repository, it is also possible to commit your local pyqtgraph changes into the project repository and push those changes upstream::
my_project$ git remote add pyqtgraph-core https://github.com/pyqtgraph/pyqtgraph-core.git
my_project$ git fetch pyqtgraph-core
my_project$ git merge -s ours --no-commit pyqtgraph-core/core
my_project$ mkdir pyqtgraph
my_project$ git read-tree -u --prefix=pyqtgraph/ pyqtgraph-core/core
my_project$ git remote add pyqtgraph https://github.com/pyqtgraph/pyqtgraph.git
my_project$ git fetch pyqtgraph
my_project$ git merge -s ours --allow-unrelated-histories --no-commit pyqtgraph/master
my_project$ mkdir local_pyqtgraph
my_project$ git read-tree -u --prefix=local_pyqtgraph/ pyqtgraph/master
my_project$ git commit -m "Added pyqtgraph to project repository"
See the ``git subtree`` documentation for more information.

View File

@ -21,6 +21,6 @@ There are a few other methods for displaying images as well:
* Instances of :class:`~pyqtgraph.ImageItem` can be used inside a :class:`ViewBox <pyqtgraph.ViewBox>` or :class:`GraphicsView <pyqtgraph.GraphicsView>`.
* For higher performance, use :class:`~pyqtgraph.RawImageWidget`.
Any of these classes are acceptable for displaying video by calling setImage() to display a new frame. To increase performance, the image processing system uses scipy.weave to produce compiled libraries. If your computer has a compiler available, weave will automatically attempt to build the libraries it needs on demand. If this fails, then the slower pure-python methods will be used instead.
Any of these classes are acceptable for displaying video by calling setImage() to display a new frame.
For more information, see the classes listed above and the 'VideoSpeedTest', 'ImageItem', 'ImageView', and 'HistogramLUT' :ref:`examples`.

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@ -0,0 +1,45 @@
"""
generates 'example_false_color_image.png'
"""
import numpy as np
import pyqtgraph as pg
import pyqtgraph.exporters as exp
from pyqtgraph.Qt import QtCore, QtGui, QtWidgets, mkQApp
class MainWindow(pg.GraphicsLayoutWidget):
""" example application main window """
def __init__(self):
super().__init__()
self.resize(420,400)
self.show()
plot = self.addPlot() # title="non-interactive")
# prepare demonstration data:
data = np.fromfunction(lambda i, j: (1+0.3*np.sin(i)) * (i)**2 + (j)**2, (100, 100))
noisy_data = data * (1 + 0.2 * np.random.random(data.shape) )
# Example: False color image with interactive level adjustment
img = pg.ImageItem(image=noisy_data) # create monochrome image from demonstration data
plot.addItem( img ) # add to PlotItem 'plot'
cm = pg.colormap.get('CET-L9') # prepare a linear color map
bar = pg.ColorBarItem( values= (0, 20_000), cmap=cm ) # prepare interactive color bar
# Have ColorBarItem control colors of img and appear in 'plot':
bar.setImageItem( img, insert_in=plot )
self.timer = pg.QtCore.QTimer( singleShot=True )
self.timer.timeout.connect(self.export)
self.timer.start(100)
def export(self):
print('exporting')
exporter = exp.ImageExporter(self.scene())
exporter.parameters()['width'] = 420
exporter.export('example_false_color_image.png')
mkQApp("False color image example")
main_window = MainWindow()
## Start Qt event loop
if __name__ == '__main__':
pg.exec()

View File

@ -0,0 +1,55 @@
"""
generates 'example_gradient_plot.png'
"""
import numpy as np
import pyqtgraph as pg
import pyqtgraph.exporters as exp
from pyqtgraph.Qt import QtCore, QtGui, QtWidgets, mkQApp
class MainWindow(pg.GraphicsLayoutWidget):
""" example application main window """
def __init__(self):
super().__init__()
self.resize(420,400)
self.show()
# Prepare demonstration data
raw = np.linspace(0.0, 2.0, 400)
y_data1 = ( (raw+0.1)%1 ) ** 4
y_data2 = ( (raw+0.1)%1 ) ** 4 - ( (raw+0.6)%1 ) ** 4
# Example 1: Gradient pen
cm = pg.colormap.get('CET-L17') # prepare a linear color map
cm.reverse() # reverse it to put light colors at the top
pen = cm.getPen( span=(0.0,1.0), width=5 ) # gradient from blue (y=0) to white (y=1)
# plot a curve drawn with a pen colored according to y value:
curve1 = pg.PlotDataItem( y=y_data1, pen=pen )
# Example 2: Gradient brush
cm = pg.colormap.get('CET-D1') # prepare a diverging color map
cm.setMappingMode('diverging') # set mapping mode
brush = cm.getBrush( span=(-1., 1.) ) # gradient from blue at -1 to red at +1
# plot a curve that is filled to zero with the gradient brush:
curve2 = pg.PlotDataItem( y=y_data2, pen='w', brush=brush, fillLevel=0.0 )
for idx, curve in enumerate( (curve1, curve2) ):
plot = self.addPlot(row=idx, col=0)
plot.getAxis('left').setWidth(25)
plot.addItem( curve )
self.timer = pg.QtCore.QTimer( singleShot=True )
self.timer.timeout.connect(self.export)
self.timer.start(100)
def export(self):
print('exporting')
exporter = exp.ImageExporter(self.scene())
exporter.parameters()['width'] = 420
exporter.export('example_gradient_plot.png')
mkQApp("Gradient plotting example")
main_window = MainWindow()
## Start Qt event loop
if __name__ == '__main__':
pg.exec()

View File

@ -0,0 +1,45 @@
"""
generates 'example_false_color_image.png'
"""
import numpy as np
import pyqtgraph as pg
import pyqtgraph.exporters as exp
from pyqtgraph.Qt import QtGui, mkQApp
class MainWindow(pg.GraphicsLayoutWidget):
""" example application main window """
def __init__(self):
super().__init__()
self.resize(420,400)
self.show()
plot = self.addPlot()
# Example: Transformed display of ImageItem
tr = QtGui.QTransform() # prepare ImageItem transformation:
tr.scale(6.0, 3.0) # scale horizontal and vertical axes
tr.translate(-1.5, -1.5) # move 3x3 image to locate center at axis origin
img = pg.ImageItem( image=np.eye(3), levels=(0,1) ) # create example image
img.setTransform(tr) # assign transform
plot.addItem( img ) # add ImageItem to PlotItem
plot.showAxes(True) # frame it with a full set of axes
plot.invertY(True) # vertical axis counts top to bottom
self.timer = pg.QtCore.QTimer( singleShot=True )
self.timer.timeout.connect(self.export)
self.timer.start(100)
def export(self):
print('exporting')
exporter = exp.ImageExporter(self.scene())
exporter.parameters()['width'] = 420
exporter.export('example_imageitem_transform.png')
mkQApp("ImageItem transform example")
main_window = MainWindow()
## Start Qt event loop
if __name__ == '__main__':
pg.exec()

View File

@ -3,8 +3,8 @@ Installation
PyQtGraph depends on:
* Python 2.7 or Python 3.x
* A Qt library such as PyQt4, PyQt5, PySide, or PySide2
* Python 3.7+
* A Qt library such as PyQt5, or PySide2
* numpy
The easiest way to meet these dependencies is with ``pip`` or with a scientific
@ -49,9 +49,9 @@ To get access to the very latest features and bugfixes you have three choices:
2. Directly install from GitHub repo::
$ pip install git+git://github.com/pyqtgraph/pyqtgraph.git@develop
$ pip install git+git://github.com/pyqtgraph/pyqtgraph.git@master
You can change ``develop`` of the above command to the branch name or the
You can change ``master`` of the above command to the branch name or the
commit you prefer.
3. You can simply place the pyqtgraph folder someplace importable, such as

View File

@ -45,12 +45,13 @@ Examples
--------
PyQtGraph includes an extensive set of examples that can be accessed by
running::
running either ``python -m pyqtgraph.examples`` [#editableInstall]_ or ::
import pyqtgraph.examples
pyqtgraph.examples.run()
Or by running ``python examples/`` from the source root.
Or, if the project repository is local, you can run``python examples/`` from
the source root.
This will start a launcher with a list of available examples. Select an item
from the list to view its source code and double-click an item to run the
@ -84,3 +85,8 @@ How does it compare to...
(My experience with these libraries is somewhat outdated; please correct me if
I am wrong here)
.. rubric:: Footnotes
.. [#editableInstall] This method does not work when pyqtgraph is installed in editable mode.

View File

@ -3,17 +3,22 @@
Parameter Trees
===============
.. currentmodule:: pyqtgraph.parametertree
Parameter trees are a system for handling hierarchies of parameters while automatically generating one or more GUIs to display and interact with the parameters.
This feature is commonly seen, for example, in user interface design applications which display a list of editable properties for each widget.
Parameters generally have a name, a data type (int, float, string, color, etc), and a value matching the data type. Parameters may be grouped and nested
to form hierarchies and may be subclassed to provide custom behavior and display widgets.
Parameters generally have a name, a data type (int, float, string, color, etc), and a value matching the data type. Parameters may be grouped and nested to form hierarchies and may be subclassed to provide custom behavior and display widgets.
PyQtGraph's parameter tree system works similarly to the model-view architecture used by some components of Qt: Parameters are purely data-handling classes
that exist independent of any graphical interface. A ParameterTree is a widget that automatically generates a graphical interface which represents
the state of a haierarchy of Parameter objects and allows the user to edit the values within that hierarchy. This separation of data (model) and graphical
interface (view) allows the same data to be represented multiple times and in a variety of different ways.
PyQtGraph's parameter tree system works similarly to the model-view architecture used by some components of Qt:
For more information, see the 'parametertree' example included with pyqtgraph and the API reference
- A :class:`Parameter` is a purely data-handling class that exists independent of any graphical interface.
- A :class:`ParameterItem` is an interactive graphical representation of a :class:`Parameter`.
- A :class:`ParameterTree` is a widget that automatically generates a graphical interface which represents the state of a hierarchy of Parameter objects and allows the user to edit the values within that hierarchy.
This separation of data (model) and graphical interface (view) allows the same data to be represented multiple times and in a variety of different ways.
For example, a floating point number parameter could be represented by a slider or a spinbox, or both.
For more information, see the 'parametertree' example included with pyqtgraph and the API reference:
.. toctree::
:maxdepth: 2

View File

@ -1,8 +1,11 @@
Parameter
=========
.. autofunction:: pyqtgraph.parametertree.registerParameterType
.. autofunction:: pyqtgraph.parametertree.registerParameterItemType
.. autoclass:: pyqtgraph.parametertree.Parameter
:members:
.. automethod:: pyqtgraph.parametertree.Parameter.__init__

View File

@ -1,6 +1,104 @@
..
This file is auto-generated from pyqtgraph/tools/rebuildPtreeRst.py. Do not modify by hand! Instead, rerun the
generation script with `python pyqtgraph/tools/rebuildPtreeRst.py`.
Built-in Parameter Types
========================
.. automodule:: pyqtgraph.parametertree.parameterTypes
:members:
.. currentmodule:: pyqtgraph.parametertree.parameterTypes
Parameters
----------
.. autoclass:: ActionParameter
:members:
.. autoclass:: CalendarParameter
:members:
.. autoclass:: ChecklistParameter
:members:
.. autoclass:: ColorMapParameter
:members:
.. autoclass:: ColorParameter
:members:
.. autoclass:: FileParameter
:members:
.. autoclass:: FontParameter
:members:
.. autoclass:: GroupParameter
:members:
.. autoclass:: ListParameter
:members:
.. autoclass:: PenParameter
:members:
.. autoclass:: ProgressBarParameter
:members:
.. autoclass:: SimpleParameter
:members:
.. autoclass:: SliderParameter
:members:
.. autoclass:: TextParameter
:members:
ParameterItems
--------------
.. autoclass:: ActionParameterItem
:members:
.. autoclass:: BoolParameterItem
:members:
.. autoclass:: CalendarParameterItem
:members:
.. autoclass:: ChecklistParameterItem
:members:
.. autoclass:: ColorMapParameterItem
:members:
.. autoclass:: ColorParameterItem
:members:
.. autoclass:: FileParameterItem
:members:
.. autoclass:: FontParameterItem
:members:
.. autoclass:: GroupParameterItem
:members:
.. autoclass:: ListParameterItem
:members:
.. autoclass:: NumericParameterItem
:members:
.. autoclass:: PenParameterItem
:members:
.. autoclass:: ProgressBarParameterItem
:members:
.. autoclass:: SliderParameterItem
:members:
.. autoclass:: StrParameterItem
:members:
.. autoclass:: TextParameterItem
:members:

View File

@ -17,7 +17,7 @@ PyQtGraph fits into this scheme by providing its own QWidget subclasses to be in
Example::
from PyQt4 import QtGui # (the example applies equally well to PySide)
from PyQt5 import QtGui # (the example applies equally well to PySide2)
import pyqtgraph as pg
## Always start by initializing Qt (only once per application)
@ -99,4 +99,3 @@ QTimer, Multi-Threading
Multi-threading vs Multi-processing in Qt
-----------------------------------------

View File

@ -16,7 +16,7 @@ To select a 2D region from an image, pyqtgraph uses the :class:`ROI <pyqtgraph.R
To automatically extract a region of image data using an ROI and an ImageItem, use :func:`ROI.getArrayRegion <pyqtgraph.ROI.getArrayRegion>`. ROI classes use the :func:`affineSlice <pyqtgraph.affineSlice>` function to perform this extraction.
ROI can also be used as a control for moving/rotating/scaling items in a scene similar to most vetctor graphics editing applications.
ROI can also be used as a control for moving/rotating/scaling items in a scene similar to most vector graphics editing applications.
See the ROITypes example for more information.

View File

@ -15,7 +15,7 @@ from pyqtgraph.Qt import QtGui, QtCore
import pyqtgraph as pg
app = QtGui.QApplication([])
app = pg.mkQApp("Arrow Example")
w = QtGui.QMainWindow()
cw = pg.GraphicsLayoutWidget()
@ -30,7 +30,7 @@ p2 = cw.addPlot(row=1, col=0)
## variety of arrow shapes
a1 = pg.ArrowItem(angle=-160, tipAngle=60, headLen=40, tailLen=40, tailWidth=20, pen={'color': 'w', 'width': 3})
a2 = pg.ArrowItem(angle=-120, tipAngle=30, baseAngle=20, headLen=40, tailLen=40, tailWidth=8, pen=None, brush='y')
a3 = pg.ArrowItem(angle=-60, tipAngle=30, baseAngle=20, headLen=40, tailLen=None, brush=None)
a3 = pg.ArrowItem(angle=-60, baseAngle=20, headLen=40, headWidth=20, tailLen=None, brush=None)
a4 = pg.ArrowItem(angle=-20, tipAngle=30, baseAngle=-30, headLen=40, tailLen=None)
a2.setPos(10,0)
a3.setPos(20,0)
@ -50,8 +50,5 @@ p2.addItem(a)
anim = a.makeAnimation(loop=-1)
anim.start()
## Start Qt event loop unless running in interactive mode or using pyside.
if __name__ == '__main__':
import sys
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
QtGui.QApplication.instance().exec_()
pg.exec()

View File

@ -34,8 +34,5 @@ class BarGraph(pg.BarGraphItem):
bg = BarGraph(x=x, y=y1*0.3+2, height=0.4+y1*0.2, width=0.8)
win.addItem(bg)
## Start Qt event loop unless running in interactive mode or using pyside.
if __name__ == '__main__':
import sys
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
QtGui.QApplication.instance().exec_()
pg.exec()

View File

@ -18,9 +18,5 @@ pg.plot(data, title="Simplest possible plotting example")
data = np.random.normal(size=(500,500))
pg.image(data, title="Simplest possible image example")
## Start Qt event loop unless running in interactive mode or using pyside.
if __name__ == '__main__':
import sys
if sys.flags.interactive != 1 or not hasattr(QtCore, 'PYQT_VERSION'):
pg.QtGui.QApplication.exec_()
pg.exec()

100
examples/ColorBarItem.py Normal file
View File

@ -0,0 +1,100 @@
# -*- coding: utf-8 -*-
"""
This example demonstrates the use of ColorBarItem, which displays a simple interactive color bar.
"""
## Add path to library (just for examples; you do not need this)
import initExample
import numpy as np
from pyqtgraph.Qt import QtWidgets, mkQApp
import pyqtgraph as pg
class MainWindow(QtWidgets.QMainWindow):
""" example application main window """
def __init__(self, *args, **kwargs):
super(MainWindow, self).__init__(*args, **kwargs)
gr_wid = pg.GraphicsLayoutWidget(show=True)
self.setCentralWidget(gr_wid)
self.setWindowTitle('pyqtgraph example: Interactive color bar')
self.resize(800,700)
self.show()
## Create image items
data = np.fromfunction(lambda i, j: (1+0.3*np.sin(i)) * (i)**2 + (j)**2, (100, 100))
noisy_data = data * (1 + 0.2 * np.random.random(data.shape) )
noisy_transposed = noisy_data.transpose()
#--- add non-interactive image with integrated color -----------------
i1 = pg.ImageItem(image=data)
p1 = gr_wid.addPlot(title="non-interactive")
p1.addItem( i1 )
p1.setMouseEnabled( x=False, y=False)
p1.disableAutoRange()
p1.hideButtons()
p1.setRange(xRange=(0,100), yRange=(0,100), padding=0)
for key in ['left','right','top','bottom']:
p1.showAxis(key)
axis = p1.getAxis(key)
axis.setZValue(1)
if key in ['top', 'right']:
p1.getAxis(key).setStyle( showValues=False )
cmap = pg.colormap.get('CET-L9')
bar = pg.ColorBarItem(
interactive=False, values= (0, 30_000), colorMap=cmap,
label='vertical fixed color bar'
)
bar.setImageItem( i1, insert_in=p1 )
#--- add interactive image with integrated horizontal color bar --------------
i2 = pg.ImageItem(image=noisy_data)
p2 = gr_wid.addPlot(1,0, 1,1, title="interactive")
p2.addItem( i2, title='' )
# inserted color bar also works with labels on the right.
p2.showAxis('right')
p2.getAxis('left').setStyle( showValues=False )
p2.getAxis('bottom').setLabel('bottom axis label')
p2.getAxis('right').setLabel('right axis label')
cmap = pg.colormap.get('CET-L4')
bar = pg.ColorBarItem(
values = (0, 30_000),
colorMap=cmap,
label='horizontal color bar',
limits = (0, None),
rounding=1000,
orientation = 'h',
pen='#8888FF', hoverPen='#EEEEFF', hoverBrush='#EEEEFF80'
)
bar.setImageItem( i2, insert_in=p2 )
#--- multiple images adjusted by a separate color bar ------------------------
i3 = pg.ImageItem(image=noisy_data)
p3 = gr_wid.addPlot(0,1, 1,1, title="shared 1")
p3.addItem( i3 )
i4 = pg.ImageItem(image=noisy_transposed)
p4 = gr_wid.addPlot(1,1, 1,1, title="shared 2")
p4.addItem( i4 )
cmap = pg.colormap.get('CET-L8')
bar = pg.ColorBarItem(
# values = (-15_000, 15_000),
limits = (-30_000, 30_000), # start with full range...
rounding=1000,
width = 10,
colorMap=cmap )
bar.setImageItem( [i3, i4] )
bar.setLevels( low=-5_000, high=15_000) # ... then adjust to retro sunset.
# manually adjust reserved space at top and bottom to align with plot
bar.getAxis('bottom').setHeight(21)
bar.getAxis('top').setHeight(31)
gr_wid.addItem(bar, 0,2, 2,1) # large bar spanning both rows
mkQApp("ColorBarItem Example")
main_window = MainWindow()
## Start Qt event loop
if __name__ == '__main__':
pg.exec()

View File

@ -11,7 +11,7 @@ import pyqtgraph as pg
from pyqtgraph.Qt import QtCore, QtGui
import numpy as np
app = QtGui.QApplication([])
app = pg.mkQApp("ColorButton Example")
win = QtGui.QMainWindow()
btn = pg.ColorButton()
win.setCentralWidget(btn)
@ -26,8 +26,5 @@ def done(btn):
btn.sigColorChanging.connect(change)
btn.sigColorChanged.connect(done)
## Start Qt event loop unless running in interactive mode or using pyside.
if __name__ == '__main__':
import sys
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
QtGui.QApplication.instance().exec_()
pg.exec()

View File

@ -0,0 +1,147 @@
# -*- coding: utf-8 -*-
"""
This example demonstrates plotting with color gradients.
It also shows multiple plots with timed rolling updates
"""
# Add path to library (just for examples; you do not need this)
import initExample
import numpy as np
import time
from pyqtgraph.Qt import QtCore, QtGui, QtWidgets, mkQApp
import pyqtgraph as pg
class DataSource(object):
""" source of buffered demonstration data """
def __init__(self, sample_rate=200., signal_period=0.55, negative_period=None, max_length=300):
""" prepare, but don't start yet """
self.rate = sample_rate
self.period = signal_period
self.neg_period = negative_period
self.start_time = 0.
self.sample_idx = 0 # number of next sample to be taken
def start(self, timestamp):
""" start acquiring simulated data """
self.start_time = timestamp
self.sample_idx = 0
def get_data(self, timestamp, max_length=6000):
""" return all data acquired since last get_data call """
next_idx = int( (timestamp - self.start_time) * self.rate )
if next_idx - self.sample_idx > max_length:
self.sample_idx = next_idx - max_length # catch up if needed
# create some mildly intersting data:
sample_phases = np.arange( self.sample_idx, next_idx, dtype=np.float64 )
self.sample_idx = next_idx
sample_phase_pos = sample_phases / (self.period*self.rate)
sample_phase_pos %= 1.0
if self.neg_period is None:
return sample_phase_pos**4
sample_phase_neg = sample_phases / (self.neg_period*self.rate)
sample_phase_neg %= 1.0
return sample_phase_pos**4 - sample_phase_neg**4
class MainWindow(pg.GraphicsLayoutWidget):
""" example application main window """
def __init__(self):
super().__init__()
self.setWindowTitle('pyqtgraph example: gradient plots')
self.resize(800,800)
self.show()
layout = self # we are using a GraphicsLayoutWidget as main window for convenience
cm = pg.colormap.get('CET-L17')
cm.reverse()
pen0 = cm.getPen( span=(0.0,1.0), width=5 )
curve0 = pg.PlotDataItem(pen=pen0 )
comment0 = 'Clipped color map applied to vertical axis'
cm = pg.colormap.get('CET-D1')
cm.setMappingMode('diverging')
brush = cm.getBrush( span=(-1., 1.), orientation='vertical' )
curve1 = pg.PlotDataItem(pen='w', brush=brush, fillLevel=0.0 )
comment1 = 'Diverging vertical color map used as brush'
cm = pg.colormap.get('CET-L17')
cm.setMappingMode('mirror')
pen2 = cm.getPen( span=(400.0,600.0), width=5, orientation='horizontal' )
curve2 = pg.PlotDataItem(pen=pen2 )
comment2 = 'Mirrored color map applied to horizontal axis'
cm = pg.colormap.get('CET-C2')
cm.setMappingMode('repeat')
pen3 = cm.getPen( span=(100, 200), width=5, orientation='horizontal' )
curve3 = pg.PlotDataItem(pen=pen3 ) # vertical diverging fill
comment3 = 'Repeated color map applied to horizontal axis'
curves = (curve0, curve1, curve2, curve3)
comments = (comment0, comment1, comment2, comment3)
length = int( 3.0 * 200. ) # length of display in samples
self.top_plot = None
for idx, (curve, comment) in enumerate( zip(curves,comments) ):
plot = layout.addPlot(row=idx+1, col=0)
text = pg.TextItem( comment, anchor=(0,1) )
text.setPos(0.,1.)
if self.top_plot is None:
self.top_plot = plot
else:
plot.setXLink( self.top_plot )
plot.addItem( curve )
plot.addItem( text )
plot.setXRange( 0, length )
if idx != 1: plot.setYRange( 0. , 1.1 )
else : plot.setYRange( -1. , 1.2 ) # last plot include positive/negative data
self.traces = (
{'crv': curve0, 'buf': np.zeros( length ), 'ptr':0, 'ds': DataSource( signal_period=0.55 ) },
{'crv': curve1, 'buf': np.zeros( length ), 'ptr':0, 'ds': DataSource( signal_period=0.61, negative_period=0.55 ) },
{'crv': curve2, 'buf': np.zeros( length ), 'ptr':0, 'ds': DataSource( signal_period=0.65 ) },
{'crv': curve3, 'buf': np.zeros( length ), 'ptr':0, 'ds': DataSource( signal_period=0.52 ) },
)
self.timer = QtCore.QTimer(timerType=QtCore.Qt.TimerType.PreciseTimer)
self.timer.timeout.connect(self.update)
timestamp = time.perf_counter()
for dic in self.traces:
dic['ds'].start( timestamp )
self.last_update = time.perf_counter()
self.mean_dt = None
self.timer.start(33)
def update(self):
""" called by timer at 30 Hz """
timestamp = time.perf_counter()
# measure actual update rate:
dt = timestamp - self.last_update
if self.mean_dt is None:
self.mean_dt = dt
else:
self.mean_dt = 0.95 * self.mean_dt + 0.05 * dt # average over fluctuating measurements
self.top_plot.setTitle(
'refresh: {:0.1f}ms -> {:0.1f} fps'.format( 1000*self.mean_dt, 1/self.mean_dt )
)
# handle rolling buffer:
self.last_update = timestamp
for dic in self.traces:
new_data = dic['ds'].get_data( timestamp )
idx_a = dic['ptr']
idx_b = idx_a + len( new_data )
len_buffer = dic['buf'].shape[0]
if idx_b < len_buffer: # data does not cross buffer boundary
dic['buf'][idx_a:idx_b] = new_data
else: # part of the new data needs to roll over to beginning of buffer
len_1 = len_buffer - idx_a # this many elements still fit
dic['buf'][idx_a:idx_a+len_1] = new_data[:len_1] # first part of data at end
idx_b = len(new_data) - len_1
dic['buf'][0:idx_b] = new_data[len_1:] # second part of data at re-start
dic['ptr'] = idx_b
dic['crv'].setData( dic['buf'] )
mkQApp("Gradient plotting example")
main_window = MainWindow()
## Start Qt event loop
if __name__ == '__main__':
pg.exec()

View File

@ -29,8 +29,5 @@ c = pyqtgraph.console.ConsoleWidget(namespace=namespace, text=text)
c.show()
c.setWindowTitle('pyqtgraph example: ConsoleWidget')
## Start Qt event loop unless running in interactive mode or using pyside.
if __name__ == '__main__':
import sys
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
QtGui.QApplication.instance().exec_()
pg.exec()

View File

@ -51,7 +51,7 @@ class Graph(pg.GraphItem):
def mouseDragEvent(self, ev):
if ev.button() != QtCore.Qt.LeftButton:
if ev.button() != QtCore.Qt.MouseButton.LeftButton:
ev.ignore()
return
@ -129,8 +129,5 @@ g.setData(pos=pos, adj=adj, pen=lines, size=1, symbol=symbols, pxMode=False, tex
## Start Qt event loop unless running in interactive mode or using pyside.
if __name__ == '__main__':
import sys
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
QtGui.QApplication.instance().exec_()
pg.exec()

View File

@ -14,7 +14,7 @@ import numpy as np
from pyqtgraph.Qt import QtCore, QtGui
import pyqtgraph as pg
app = QtGui.QApplication([])
app = pg.mkQApp("Data Slicing Example")
## Create window with two ImageView widgets
win = QtGui.QMainWindow()
@ -57,8 +57,5 @@ imv1.setLevels(-0.003, 0.003)
update()
## Start Qt event loop unless running in interactive mode.
if __name__ == '__main__':
import sys
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
QtGui.QApplication.instance().exec_()
pg.exec()

View File

@ -22,7 +22,7 @@ def some_func2():
return sys.exc_info()[2]
app = QtGui.QApplication([])
app = pg.mkQApp("DataTreeWidget Example")
d = {
'a list': [1,2,3,4,5,6, {'nested1': 'aaaaa', 'nested2': 'bbbbb'}, "seven"],
'a dict': {
@ -42,8 +42,5 @@ tree.setWindowTitle('pyqtgraph example: DataTreeWidget')
tree.resize(600,600)
## Start Qt event loop unless running in interactive mode or using pyside.
if __name__ == '__main__':
import sys
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
QtGui.QApplication.instance().exec_()
pg.exec()

View File

@ -12,7 +12,7 @@ import numpy as np
import pyqtgraph as pg
from pyqtgraph.Qt import QtGui
app = QtGui.QApplication([])
app = pg.mkQApp("DateAxisItem Example")
# Create a plot with a date-time axis
w = pg.PlotWidget(axisItems = {'bottom': pg.DateAxisItem()})
@ -26,8 +26,5 @@ w.plot(now-(2*np.pi/x)**2*100*np.pi*1e7, np.sin(x), symbol='o')
w.setWindowTitle('pyqtgraph example: DateAxisItem')
w.show()
## Start Qt event loop unless running in interactive mode or using pyside.
if __name__ == '__main__':
import sys
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
app.exec_()
pg.exec()

View File

@ -9,17 +9,20 @@ import initExample ## Add path to library (just for examples; you do not need th
import sys
import time
import os
import numpy as np
from PyQt5 import QtWidgets, QtCore, uic
import pyqtgraph as pg
from pyqtgraph.Qt import QtWidgets, QtCore, loadUiType
pg.setConfigOption('background', 'w')
pg.setConfigOption('foreground', 'k')
BLUE = pg.mkPen('#1f77b4')
Design, _ = uic.loadUiType('DateAxisItem_QtDesigner.ui')
path = os.path.dirname(os.path.abspath(__file__))
uiFile = os.path.join(path, 'DateAxisItem_QtDesigner.ui')
Design, _ = loadUiType(uiFile)
class ExampleApp(QtWidgets.QMainWindow, Design):
def __init__(self):
@ -34,15 +37,10 @@ class ExampleApp(QtWidgets.QMainWindow, Design):
self.plotWidget.setAxisItems({'bottom': pg.DateAxisItem()})
self.plotWidget.showGrid(x=True, y=True)
app = QtWidgets.QApplication(sys.argv)
app.setStyle(QtWidgets.QStyleFactory.create('Fusion'))
app.setPalette(QtWidgets.QApplication.style().standardPalette())
app = pg.mkQApp("DateAxisItem_QtDesigner Example")
window = ExampleApp()
window.setWindowTitle('pyqtgraph example: DateAxisItem_QtDesigner')
window.show()
## Start Qt event loop unless running in interactive mode or using pyside.
if __name__ == '__main__':
import sys
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
app.exec_()
pg.exec()

View File

@ -12,7 +12,7 @@ from pyqtgraph.Qt import QtCore, QtGui
import numpy as np
app = QtGui.QApplication([])
app = pg.mkQApp("DiffTreeWidget Example")
A = {
'a list': [1,2,2,4,5,6, {'nested1': 'aaaa', 'nested2': 'bbbbb'}, "seven"],
'a dict': {
@ -45,8 +45,5 @@ tree.setWindowTitle('pyqtgraph example: DiffTreeWidget')
tree.resize(1000, 800)
## Start Qt event loop unless running in interactive mode or using pyside.
if __name__ == '__main__':
import sys
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
QtGui.QApplication.instance().exec_()
pg.exec()

View File

@ -12,7 +12,7 @@ from pyqtgraph.Qt import QtCore, QtGui
import numpy as np
import pyqtgraph as pg
app = QtGui.QApplication([])
app = pg.mkQApp("Draw Example")
## Create window with GraphicsView widget
w = pg.GraphicsView()
@ -42,8 +42,5 @@ kern = np.array([
img.setDrawKernel(kern, mask=kern, center=(1,1), mode='add')
img.setLevels([0, 10])
## Start Qt event loop unless running in interactive mode or using pyside.
if __name__ == '__main__':
import sys
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
QtGui.QApplication.instance().exec_()
pg.exec()

View File

@ -26,8 +26,5 @@ err = pg.ErrorBarItem(x=x, y=y, top=top, bottom=bottom, beam=0.5)
plt.addItem(err)
plt.plot(x, y, symbol='o', pen={'color': 0.8, 'width': 2})
## Start Qt event loop unless running in interactive mode or using pyside.
if __name__ == '__main__':
import sys
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
QtGui.QApplication.instance().exec_()
pg.exec()

547
examples/ExampleApp.py Normal file
View File

@ -0,0 +1,547 @@
import keyword
import os
import re
import sys
import subprocess
from argparse import Namespace
import pyqtgraph as pg
from pyqtgraph.Qt import QtWidgets, QtGui, QtCore, QT_LIB
from collections import OrderedDict
from .utils import examples_
from functools import lru_cache
path = os.path.abspath(os.path.dirname(__file__))
sys.path.insert(0, path)
app = pg.mkQApp()
import importlib
ui_template = importlib.import_module(
f'exampleLoaderTemplate_{QT_LIB.lower()}')
# based on https://github.com/art1415926535/PyQt5-syntax-highlighting
QRegularExpression = QtCore.QRegularExpression
QFont = QtGui.QFont
QColor = QtGui.QColor
QTextCharFormat = QtGui.QTextCharFormat
QSyntaxHighlighter = QtGui.QSyntaxHighlighter
def charFormat(color, style='', background=None):
"""
Return a QTextCharFormat with the given attributes.
"""
_color = QColor()
if type(color) is not str:
_color.setRgb(color[0], color[1], color[2])
else:
_color.setNamedColor(color)
_format = QTextCharFormat()
_format.setForeground(_color)
if 'bold' in style:
_format.setFontWeight(QFont.Weight.Bold)
if 'italic' in style:
_format.setFontItalic(True)
if background is not None:
_format.setBackground(pg.mkColor(background))
return _format
class LightThemeColors:
Red = "#B71C1C"
Pink = "#FCE4EC"
Purple = "#4A148C"
DeepPurple = "#311B92"
Indigo = "#1A237E"
Blue = "#0D47A1"
LightBlue = "#01579B"
Cyan = "#006064"
Teal = "#004D40"
Green = "#1B5E20"
LightGreen = "#33691E"
Lime = "#827717"
Yellow = "#F57F17"
Amber = "#FF6F00"
Orange = "#E65100"
DeepOrange = "#BF360C"
Brown = "#3E2723"
Grey = "#212121"
BlueGrey = "#263238"
class DarkThemeColors:
Red = "#F44336"
Pink = "#F48FB1"
Purple = "#CE93D8"
DeepPurple = "#B39DDB"
Indigo = "#9FA8DA"
Blue = "#90CAF9"
LightBlue = "#81D4FA"
Cyan = "#80DEEA"
Teal = "#80CBC4"
Green = "#A5D6A7"
LightGreen = "#C5E1A5"
Lime = "#E6EE9C"
Yellow = "#FFF59D"
Amber = "#FFE082"
Orange = "#FFCC80"
DeepOrange = "#FFAB91"
Brown = "#BCAAA4"
Grey = "#EEEEEE"
BlueGrey = "#B0BEC5"
LIGHT_STYLES = {
'keyword': charFormat(LightThemeColors.Blue, 'bold'),
'operator': charFormat(LightThemeColors.Red, 'bold'),
'brace': charFormat(LightThemeColors.Purple),
'defclass': charFormat(LightThemeColors.Indigo, 'bold'),
'string': charFormat(LightThemeColors.Amber),
'string2': charFormat(LightThemeColors.DeepPurple),
'comment': charFormat(LightThemeColors.Green, 'italic'),
'self': charFormat(LightThemeColors.Blue, 'bold'),
'numbers': charFormat(LightThemeColors.Teal),
}
DARK_STYLES = {
'keyword': charFormat(DarkThemeColors.Blue, 'bold'),
'operator': charFormat(DarkThemeColors.Red, 'bold'),
'brace': charFormat(DarkThemeColors.Purple),
'defclass': charFormat(DarkThemeColors.Indigo, 'bold'),
'string': charFormat(DarkThemeColors.Amber),
'string2': charFormat(DarkThemeColors.DeepPurple),
'comment': charFormat(DarkThemeColors.Green, 'italic'),
'self': charFormat(DarkThemeColors.Blue, 'bold'),
'numbers': charFormat(DarkThemeColors.Teal),
}
class PythonHighlighter(QSyntaxHighlighter):
"""Syntax highlighter for the Python language.
"""
# Python keywords
keywords = keyword.kwlist
# Python operators
operators = [
r'=',
# Comparison
r'==', r'!=', r'<', r'<=', r'>', r'>=',
# Arithmetic
r'\+', r"-", r'\*', r'/', r'//', r'%', r'\*\*',
# In-place
r'\+=', r'-=', r'\*=', r'/=', r'\%=',
# Bitwise
r'\^', r'\|', r'&', r'~', r'>>', r'<<',
]
# Python braces
braces = [
r'\{', r'\}', r'\(', r'\)', r'\[', r'\]',
]
def __init__(self, document):
super().__init__(document)
# Multi-line strings (expression, flag, style)
self.tri_single = (QRegularExpression("'''"), 1, 'string2')
self.tri_double = (QRegularExpression('"""'), 2, 'string2')
rules = []
# Keyword, operator, and brace rules
rules += [(r'\b%s\b' % w, 0, 'keyword')
for w in PythonHighlighter.keywords]
rules += [(o, 0, 'operator')
for o in PythonHighlighter.operators]
rules += [(b, 0, 'brace')
for b in PythonHighlighter.braces]
# All other rules
rules += [
# 'self'
(r'\bself\b', 0, 'self'),
# 'def' followed by an identifier
(r'\bdef\b\s*(\w+)', 1, 'defclass'),
# 'class' followed by an identifier
(r'\bclass\b\s*(\w+)', 1, 'defclass'),
# Numeric literals
(r'\b[+-]?[0-9]+[lL]?\b', 0, 'numbers'),
(r'\b[+-]?0[xX][0-9A-Fa-f]+[lL]?\b', 0, 'numbers'),
(r'\b[+-]?[0-9]+(?:\.[0-9]+)?(?:[eE][+-]?[0-9]+)?\b', 0, 'numbers'),
# Double-quoted string, possibly containing escape sequences
(r'"[^"\\]*(\\.[^"\\]*)*"', 0, 'string'),
# Single-quoted string, possibly containing escape sequences
(r"'[^'\\]*(\\.[^'\\]*)*'", 0, 'string'),
# From '#' until a newline
(r'#[^\n]*', 0, 'comment'),
]
self.rules = rules
self.searchText = None
@property
def styles(self):
app = QtWidgets.QApplication.instance()
return DARK_STYLES if app.property('darkMode') else LIGHT_STYLES
def highlightBlock(self, text):
"""Apply syntax highlighting to the given block of text.
"""
# Do other syntax formatting
rules = self.rules.copy()
for expression, nth, format in rules:
format = self.styles[format]
for n, match in enumerate(re.finditer(expression, text)):
if n < nth:
continue
start = match.start()
length = match.end() - start
self.setFormat(start, length, format)
self.applySearchHighlight(text)
self.setCurrentBlockState(0)
# Do multi-line strings
in_multiline = self.match_multiline(text, *self.tri_single)
if not in_multiline:
in_multiline = self.match_multiline(text, *self.tri_double)
def match_multiline(self, text, delimiter, in_state, style):
"""Do highlighting of multi-line strings.
=========== ==========================================================
delimiter (QRegularExpression) for triple-single-quotes or
triple-double-quotes
in_state (int) to represent the corresponding state changes when
inside those strings. Returns True if we're still inside a
multi-line string when this function is finished.
style (str) representation of the kind of style to use
=========== ==========================================================
"""
# If inside triple-single quotes, start at 0
if self.previousBlockState() == in_state:
start = 0
add = 0
# Otherwise, look for the delimiter on this line
else:
match = delimiter.match(text)
start = match.capturedStart()
# Move past this match
add = match.capturedLength()
# As long as there's a delimiter match on this line...
while start >= 0:
# Look for the ending delimiter
match = delimiter.match(text, start + add)
end = match.capturedEnd()
# Ending delimiter on this line?
if end >= add:
length = end - start + add + match.capturedLength()
self.setCurrentBlockState(0)
# No; multi-line string
else:
self.setCurrentBlockState(in_state)
length = len(text) - start + add
# Apply formatting
self.setFormat(start, length, self.styles[style])
# Highlighting sits on top of this formatting
# Look for the next match
match = delimiter.match(text, start + length)
start = match.capturedStart()
self.applySearchHighlight(text)
# Return True if still inside a multi-line string, False otherwise
if self.currentBlockState() == in_state:
return True
else:
return False
def applySearchHighlight(self, text):
if not self.searchText:
return
expr = f'(?i){self.searchText}'
palette: QtGui.QPalette = app.palette()
color = palette.highlight().color()
fgndColor = palette.color(palette.ColorGroup.Current,
palette.ColorRole.Text).name()
style = charFormat(fgndColor, background=color.name())
for match in re.finditer(expr, text):
start = match.start()
length = match.end() - start
self.setFormat(start, length, style)
def unnestedDict(exDict):
"""Converts a dict-of-dicts to a singly nested dict for non-recursive parsing"""
out = {}
for kk, vv in exDict.items():
if isinstance(vv, dict):
out.update(unnestedDict(vv))
else:
out[kk] = vv
return out
class ExampleLoader(QtWidgets.QMainWindow):
def __init__(self):
QtWidgets.QMainWindow.__init__(self)
self.ui = ui_template.Ui_Form()
self.cw = QtWidgets.QWidget()
self.setCentralWidget(self.cw)
self.ui.setupUi(self.cw)
self.setWindowTitle("PyQtGraph Examples")
self.codeBtn = QtWidgets.QPushButton('Run Edited Code')
self.codeLayout = QtWidgets.QGridLayout()
self.ui.codeView.setLayout(self.codeLayout)
self.hl = PythonHighlighter(self.ui.codeView.document())
app = QtWidgets.QApplication.instance()
app.paletteChanged.connect(self.updateTheme)
policy = QtWidgets.QSizePolicy.Policy.Expanding
self.codeLayout.addItem(QtWidgets.QSpacerItem(100,100, policy, policy), 0, 0)
self.codeLayout.addWidget(self.codeBtn, 1, 1)
self.codeBtn.hide()
textFil = self.ui.exampleFilter
self.curListener = None
self.ui.exampleFilter.setFocus()
def onComboChanged(searchType):
if self.curListener is not None:
self.curListener.disconnect()
self.curListener = textFil.textChanged
if searchType == 'Content Search':
self.curListener.connect(self.filterByContent)
else:
self.hl.searchText = None
self.curListener.connect(self.filterByTitle)
# Fire on current text, too
self.curListener.emit(textFil.text())
self.ui.searchFiles.currentTextChanged.connect(onComboChanged)
onComboChanged(self.ui.searchFiles.currentText())
self.itemCache = []
self.populateTree(self.ui.exampleTree.invisibleRootItem(), examples_)
self.ui.exampleTree.expandAll()
self.resize(1000,500)
self.show()
self.ui.splitter.setSizes([250,750])
self.ui.loadBtn.clicked.connect(self.loadFile)
self.ui.exampleTree.currentItemChanged.connect(self.showFile)
self.ui.exampleTree.itemDoubleClicked.connect(self.loadFile)
# textChanged fires when the highlighter is reassigned the same document. Prevent this
# from showing "run edited code" by checking for actual content change
oldText = self.ui.codeView.toPlainText()
def onTextChange():
nonlocal oldText
newText = self.ui.codeView.toPlainText()
if newText != oldText:
oldText = newText
self.codeEdited()
self.ui.codeView.textChanged.connect(onTextChange)
self.codeBtn.clicked.connect(self.runEditedCode)
def filterByTitle(self, text):
self.showExamplesByTitle(self.getMatchingTitles(text))
self.hl.setDocument(self.ui.codeView.document())
def filterByContent(self, text=None):
# Don't filter very short strings
checkDict = unnestedDict(examples_)
self.hl.searchText = text
# Need to reapply to current document
self.hl.setDocument(self.ui.codeView.document())
titles = []
text = text.lower()
for kk, vv in checkDict.items():
if isinstance(vv, Namespace):
vv = vv.filename
filename = os.path.join(path, vv)
contents = self.getExampleContent(filename).lower()
if text in contents:
titles.append(kk)
self.showExamplesByTitle(titles)
def getMatchingTitles(self, text, exDict=None, acceptAll=False):
if exDict is None:
exDict = examples_
text = text.lower()
titles = []
for kk, vv in exDict.items():
matched = acceptAll or text in kk.lower()
if isinstance(vv, dict):
titles.extend(self.getMatchingTitles(text, vv, acceptAll=matched))
elif matched:
titles.append(kk)
return titles
def showExamplesByTitle(self, titles):
QTWI = QtWidgets.QTreeWidgetItemIterator
flag = QTWI.IteratorFlag.NoChildren
treeIter = QTWI(self.ui.exampleTree, flag)
item = treeIter.value()
while item is not None:
parent = item.parent()
show = (item.childCount() or item.text(0) in titles)
item.setHidden(not show)
# If all children of a parent are gone, hide it
if parent:
hideParent = True
for ii in range(parent.childCount()):
if not parent.child(ii).isHidden():
hideParent = False
break
parent.setHidden(hideParent)
treeIter += 1
item = treeIter.value()
def simulate_black_mode(self):
"""
used to simulate MacOS "black mode" on other platforms
intended for debug only, as it manage only the QPlainTextEdit
"""
# first, a dark background
c = QtGui.QColor('#171717')
p = self.ui.codeView.palette()
p.setColor(QtGui.QPalette.ColorGroup.Active, QtGui.QPalette.ColorRole.Base, c)
p.setColor(QtGui.QPalette.ColorGroup.Inactive, QtGui.QPalette.ColorRole.Base, c)
self.ui.codeView.setPalette(p)
# then, a light font
f = QtGui.QTextCharFormat()
f.setForeground(QtGui.QColor('white'))
self.ui.codeView.setCurrentCharFormat(f)
# finally, override application automatic detection
app = QtWidgets.QApplication.instance()
app.setProperty('darkMode', True)
def updateTheme(self):
self.hl = PythonHighlighter(self.ui.codeView.document())
def populateTree(self, root, examples):
bold_font = None
for key, val in examples.items():
item = QtWidgets.QTreeWidgetItem([key])
self.itemCache.append(item) # PyQt 4.9.6 no longer keeps references to these wrappers,
# so we need to make an explicit reference or else the .file
# attribute will disappear.
if isinstance(val, OrderedDict):
self.populateTree(item, val)
elif isinstance(val, Namespace):
item.file = val.filename
if 'recommended' in val:
if bold_font is None:
bold_font = item.font(0)
bold_font.setBold(True)
item.setFont(0, bold_font)
else:
item.file = val
root.addChild(item)
def currentFile(self):
item = self.ui.exampleTree.currentItem()
if hasattr(item, 'file'):
return os.path.join(path, item.file)
return None
def loadFile(self, edited=False):
qtLib = str(self.ui.qtLibCombo.currentText())
env = None
if qtLib != 'default':
env = dict(os.environ, PYQTGRAPH_QT_LIB=qtLib)
if edited:
path = os.path.abspath(os.path.dirname(__file__))
proc = subprocess.Popen([sys.executable, '-'], stdin=subprocess.PIPE, cwd=path, env=env)
code = str(self.ui.codeView.toPlainText()).encode('UTF-8')
proc.stdin.write(code)
proc.stdin.close()
else:
fn = self.currentFile()
if fn is None:
return
subprocess.Popen([sys.executable, fn], env=env)
def showFile(self):
fn = self.currentFile()
text = self.getExampleContent(fn)
self.ui.codeView.setPlainText(text)
self.ui.loadedFileLabel.setText(fn)
self.codeBtn.hide()
@lru_cache(100)
def getExampleContent(self, filename):
if filename is None:
self.ui.codeView.clear()
return
if os.path.isdir(filename):
filename = os.path.join(filename, '__main__.py')
with open(filename, "r") as currentFile:
text = currentFile.read()
return text
def codeEdited(self):
self.codeBtn.show()
def runEditedCode(self):
self.loadFile(edited=True)
def keyPressEvent(self, event):
ret = super().keyPressEvent(event)
if not QtCore.Qt.KeyboardModifier.ControlModifier & event.modifiers():
return ret
key = event.key()
Key = QtCore.Qt.Key
# Allow quick navigate to search
if key == Key.Key_F:
self.ui.exampleFilter.setFocus()
event.accept()
return
if key not in [Key.Key_Plus, Key.Key_Minus, Key.Key_Underscore, Key.Key_Equal, Key.Key_0]:
return ret
font = self.ui.codeView.font()
oldSize = font.pointSize()
if key == Key.Key_Plus or key == Key.Key_Equal:
font.setPointSize(oldSize + max(oldSize*.15, 1))
elif key == Key.Key_Minus or key == Key.Key_Underscore:
newSize = oldSize - max(oldSize*.15, 1)
font.setPointSize(max(newSize, 1))
elif key == Key.Key_0:
# Reset to original size
font.setPointSize(10)
self.ui.codeView.setFont(font)
event.accept()
def main():
app = pg.mkQApp()
loader = ExampleLoader()
loader.ui.exampleTree.setCurrentIndex(
loader.ui.exampleTree.model().index(0,0)
)
pg.exec()
if __name__ == '__main__':
main()

View File

@ -45,8 +45,5 @@ timer.timeout.connect(update)
timer.start(30)
## Start Qt event loop unless running in interactive mode or using pyside.
if __name__ == '__main__':
import sys
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
QtGui.QApplication.instance().exec_()
pg.exec()

View File

@ -19,7 +19,7 @@ import pyqtgraph as pg
import numpy as np
import pyqtgraph.metaarray as metaarray
app = QtGui.QApplication([])
app = pg.mkQApp("Flowchart Example")
## Create main window with grid layout
win = QtGui.QMainWindow()
@ -75,10 +75,5 @@ fc.connectTerminals(fc['dataIn'], pw1Node['In'])
fc.connectTerminals(fNode['Out'], pw2Node['In'])
fc.connectTerminals(fNode['Out'], fc['dataOut'])
## Start Qt event loop unless running in interactive mode or using pyside.
if __name__ == '__main__':
import sys
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
QtGui.QApplication.instance().exec_()
pg.exec()

View File

@ -13,7 +13,7 @@ from pyqtgraph.Qt import QtGui, QtCore
import pyqtgraph as pg
import numpy as np
app = QtGui.QApplication([])
app = pg.mkQApp("Flowchart Custom Node Example")
## Create main window with a grid layout inside
win = QtGui.QMainWindow()
@ -150,10 +150,5 @@ fc.connectTerminals(fc['dataIn'], v1Node['data'])
fc.connectTerminals(fNode['dataOut'], v2Node['data'])
fc.connectTerminals(fNode['dataOut'], fc['dataOut'])
## Start Qt event loop unless running in interactive mode or using pyside.
if __name__ == '__main__':
import sys
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
QtGui.QApplication.instance().exec_()
pg.exec()

View File

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
"""
Demonstrate use of GLLinePlotItem to draw cross-sections of a surface.
This example demonstrates the use of GLBarGraphItem.
"""
## Add path to library (just for examples; you do not need this)
@ -11,11 +11,11 @@ import pyqtgraph.opengl as gl
import pyqtgraph as pg
import numpy as np
app = QtGui.QApplication([])
app = pg.mkQApp("GLBarGraphItem Example")
w = gl.GLViewWidget()
w.opts['distance'] = 40
w.show()
w.setWindowTitle('pyqtgraph example: GLBarGraphItem')
w.setCameraPosition(distance=40)
gx = gl.GLGridItem()
gx.rotate(90, 0, 1, 0)
@ -39,9 +39,5 @@ size[...,2] = np.random.normal(size=(10,10))
bg = gl.GLBarGraphItem(pos, size)
w.addItem(bg)
## Start Qt event loop unless running in interactive mode.
if __name__ == '__main__':
import sys
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
QtGui.QApplication.instance().exec_()
pg.exec()

View File

@ -0,0 +1,43 @@
import initExample
import pyqtgraph as pg
import pyqtgraph.opengl as gl
import numpy
app = pg.mkQApp()
w = gl.GLViewWidget()
w.show()
w.setWindowTitle("pyqtgraph example: GLGradientLegendItem")
w.setCameraPosition(distance=60)
gx = gl.GLGridItem()
gx.rotate(90, 0, 1, 0)
w.addItem(gx)
md = gl.MeshData.cylinder(rows=10, cols=20, radius=[5.0, 5], length=20.0)
md._vertexes[:, 2] = md._vertexes[:, 2] - 10
# set color based on z coordinates
color_map = pg.colormap.get("CET-L10")
h = md.vertexes()[:, 2]
# remember these
h_max, h_min = h.max(), h.min()
h = (h - h_min) / (h_max - h_min)
colors = color_map.map(h, mode="float")
md.setFaceColors(colors)
m = gl.GLMeshItem(meshdata=md, smooth=True)
w.addItem(m)
legendLabels = numpy.linspace(h_max, h_min, 5)
legendPos = numpy.linspace(1, 0, 5)
legend = dict(zip(map(str, legendLabels), legendPos))
gll = gl.GLGradientLegendItem(
pos=(10, 10), size=(50, 300), gradient=color_map, labels=legend
)
w.addItem(gll)
## Start Qt event loop unless running in interactive mode.
if __name__ == "__main__":
pg.exec()

47
examples/GLGraphItem.py Normal file
View File

@ -0,0 +1,47 @@
"""
Demonstrates use of GLGraphItem
"""
## Add path to library (just for examples; you do not need this)
import initExample
import pyqtgraph as pg
import pyqtgraph.opengl as gl
import numpy as np
app = pg.mkQApp("GLGraphItem Example")
w = gl.GLViewWidget()
w.setCameraPosition(distance=20)
w.show()
edges = np.array([
[0, 2],
[0, 3],
[1, 2],
[1, 3],
[2, 3]
])
nodes = np.array(
[
[0, 0, 0],
[1, 0, 0],
[0, 1, 0],
[1, 1, 1]
]
)
edgeColor=pg.glColor("w")
gi = gl.GLGraphItem(
edges=edges,
nodePositions=nodes,
edgeWidth=1.,
nodeSize=10.
)
w.addItem(gi)
if __name__ == "__main__":
pg.exec()

View File

@ -13,11 +13,11 @@ import pyqtgraph.opengl as gl
import pyqtgraph as pg
import numpy as np
app = QtGui.QApplication([])
app = pg.mkQApp("GLImageItem Example")
w = gl.GLViewWidget()
w.opts['distance'] = 200
w.show()
w.setWindowTitle('pyqtgraph example: GLImageItem')
w.setCameraPosition(distance=200)
## create volume data set to slice three images from
shape = (100,100,70)
@ -50,8 +50,5 @@ w.addItem(v3)
ax = gl.GLAxisItem()
w.addItem(ax)
## Start Qt event loop unless running in interactive mode.
if __name__ == '__main__':
import sys
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
QtGui.QApplication.instance().exec_()
pg.exec()

View File

@ -7,11 +7,11 @@ This example uses the isosurface function to convert a scalar field
## Add path to library (just for examples; you do not need this)
import initExample
from pyqtgraph.Qt import QtCore, QtGui
import numpy as np
import pyqtgraph as pg
import pyqtgraph.opengl as gl
app = QtGui.QApplication([])
app = pg.mkQApp("GLIsosurface Example")
w = gl.GLViewWidget()
w.show()
w.setWindowTitle('pyqtgraph example: GLIsosurface')
@ -22,23 +22,16 @@ g = gl.GLGridItem()
g.scale(2,2,1)
w.addItem(g)
import numpy as np
## Define a scalar field from which we will generate an isosurface
def psi(i, j, k, offset=(25, 25, 50)):
x = i-offset[0]
y = j-offset[1]
z = k-offset[2]
th = np.arctan2(z, (x**2+y**2)**0.5)
phi = np.arctan2(y, x)
r = (x**2 + y**2 + z **2)**0.5
th = np.arctan2(z, np.hypot(x, y))
r = np.sqrt(x**2 + y**2 + z **2)
a0 = 1
#ps = (1./81.) * (2./np.pi)**0.5 * (1./a0)**(3/2) * (6 - r/a0) * (r/a0) * np.exp(-r/(3*a0)) * np.cos(th)
ps = (1./81.) * 1./(6.*np.pi)**0.5 * (1./a0)**(3/2) * (r/a0)**2 * np.exp(-r/(3*a0)) * (3 * np.cos(th)**2 - 1)
return ps
#return ((1./81.) * (1./np.pi)**0.5 * (1./a0)**(3/2) * (r/a0)**2 * (r/a0) * np.exp(-r/(3*a0)) * np.sin(th) * np.cos(th) * np.exp(2 * 1j * phi))**2
print("Generating scalar field..")
@ -66,10 +59,5 @@ m2.setGLOptions('additive')
w.addItem(m2)
m2.translate(-25, -25, -50)
## Start Qt event loop unless running in interactive mode.
if __name__ == '__main__':
import sys
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
QtGui.QApplication.instance().exec_()
pg.exec()

View File

@ -6,16 +6,15 @@ Demonstrate use of GLLinePlotItem to draw cross-sections of a surface.
## Add path to library (just for examples; you do not need this)
import initExample
from pyqtgraph.Qt import QtCore, QtGui
import pyqtgraph.opengl as gl
import pyqtgraph as pg
import numpy as np
app = QtGui.QApplication([])
app = pg.mkQApp("GLLinePlotItem Example")
w = gl.GLViewWidget()
w.opts['distance'] = 40
w.show()
w.setWindowTitle('pyqtgraph example: GLLinePlotItem')
w.setCameraPosition(distance=40)
gx = gl.GLGridItem()
gx.rotate(90, 0, 1, 0)
@ -29,24 +28,16 @@ gz = gl.GLGridItem()
gz.translate(0, 0, -10)
w.addItem(gz)
def fn(x, y):
return np.cos((x**2 + y**2)**0.5)
n = 51
y = np.linspace(-10,10,n)
x = np.linspace(-10,10,100)
for i in range(n):
yi = np.array([y[i]]*100)
d = (x**2 + yi**2)**0.5
yi = y[i]
d = np.hypot(x, yi)
z = 10 * np.cos(d) / (d+1)
pts = np.vstack([x,yi,z]).transpose()
plt = gl.GLLinePlotItem(pos=pts, color=pg.glColor((i,n*1.3)), width=(i+1)/10., antialias=True)
pts = np.column_stack([x, np.full_like(x, yi), z])
plt = gl.GLLinePlotItem(pos=pts, color=pg.mkColor((i,n*1.3)), width=(i+1)/10., antialias=True)
w.addItem(plt)
## Start Qt event loop unless running in interactive mode.
if __name__ == '__main__':
import sys
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
QtGui.QApplication.instance().exec_()
pg.exec()

View File

@ -11,7 +11,7 @@ from pyqtgraph.Qt import QtCore, QtGui
import pyqtgraph as pg
import pyqtgraph.opengl as gl
app = QtGui.QApplication([])
app = pg.mkQApp("GLMeshItem Example")
w = gl.GLViewWidget()
w.show()
w.setWindowTitle('pyqtgraph example: GLMeshItem')
@ -117,13 +117,5 @@ m6.rotate(0., 0, 1, 1)
w.addItem(m5)
w.addItem(m6)
## Start Qt event loop unless running in interactive mode.
if __name__ == '__main__':
import sys
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
QtGui.QApplication.instance().exec_()
pg.exec()

94
examples/GLPainterItem.py Normal file
View File

@ -0,0 +1,94 @@
"""
Demonstrate using QPainter on a subclass of GLGraphicsItem.
"""
## Add path to library (just for examples; you do not need this)
import initExample
import pyqtgraph as pg
import pyqtgraph.opengl
from pyqtgraph.Qt import QtCore, QtGui
import OpenGL.GL as GL
SIZE = 32
class GLPainterItem(pg.opengl.GLGraphicsItem.GLGraphicsItem):
def __init__(self, **kwds):
super().__init__()
glopts = kwds.pop('glOptions', 'additive')
self.setGLOptions(glopts)
def compute_projection(self):
modelview = GL.glGetDoublev(GL.GL_MODELVIEW_MATRIX)
projection = GL.glGetDoublev(GL.GL_PROJECTION_MATRIX)
mvp = projection.T @ modelview.T
mvp = QtGui.QMatrix4x4(mvp.ravel().tolist())
# note that QRectF.bottom() != QRect.bottom()
rect = QtCore.QRectF(self.view().rect())
ndc_to_viewport = QtGui.QMatrix4x4()
ndc_to_viewport.viewport(rect.left(), rect.bottom(), rect.width(), -rect.height())
return ndc_to_viewport * mvp
def paint(self):
self.setupGLState()
painter = QtGui.QPainter(self.view())
self.draw(painter)
painter.end()
def draw(self, painter):
painter.setPen(QtCore.Qt.GlobalColor.white)
painter.setRenderHints(QtGui.QPainter.RenderHint.Antialiasing | QtGui.QPainter.RenderHint.TextAntialiasing)
rect = self.view().rect()
af = QtCore.Qt.AlignmentFlag
painter.drawText(rect, af.AlignTop | af.AlignRight, 'TR')
painter.drawText(rect, af.AlignBottom | af.AlignLeft, 'BL')
painter.drawText(rect, af.AlignBottom | af.AlignRight, 'BR')
opts = self.view().cameraParams()
lines = []
center = opts['center']
lines.append(f"center : ({center.x():.1f}, {center.y():.1f}, {center.z():.1f})")
for key in ['distance', 'fov', 'elevation', 'azimuth']:
lines.append(f"{key} : {opts[key]:.1f}")
xyz = self.view().cameraPosition()
lines.append(f"xyz : ({xyz.x():.1f}, {xyz.y():.1f}, {xyz.z():.1f})")
info = "\n".join(lines)
painter.drawText(rect, af.AlignTop | af.AlignLeft, info)
project = self.compute_projection()
hsize = SIZE // 2
for xi in range(-hsize, hsize+1):
for yi in range(-hsize, hsize+1):
if xi == -hsize and yi == -hsize:
# skip one corner for visual orientation
continue
vec3 = QtGui.QVector3D(xi, yi, 0)
pos = project.map(vec3).toPointF()
painter.drawEllipse(pos, 1, 1)
pg.mkQApp("GLPainterItem Example")
glv = pg.opengl.GLViewWidget()
glv.show()
glv.setWindowTitle('pyqtgraph example: GLPainterItem')
glv.setCameraPosition(distance=50, elevation=90, azimuth=0)
griditem = pg.opengl.GLGridItem()
griditem.setSize(SIZE, SIZE)
griditem.setSpacing(1, 1)
glv.addItem(griditem)
axisitem = pg.opengl.GLAxisItem()
axisitem.setSize(SIZE/2, SIZE/2, 1)
glv.addItem(axisitem)
paintitem = GLPainterItem()
glv.addItem(paintitem)
if __name__ == '__main__':
pg.exec()

View File

@ -7,15 +7,17 @@ Demonstrates use of GLScatterPlotItem with rapidly-updating plots.
## Add path to library (just for examples; you do not need this)
import initExample
import pyqtgraph as pg
from pyqtgraph import functions as fn
from pyqtgraph.Qt import QtCore, QtGui
import pyqtgraph.opengl as gl
import numpy as np
app = QtGui.QApplication([])
app = pg.mkQApp("GLScatterPlotItem Example")
w = gl.GLViewWidget()
w.opts['distance'] = 20
w.show()
w.setWindowTitle('pyqtgraph example: GLScatterPlotItem')
w.setCameraPosition(distance=20)
g = gl.GLGridItem()
w.addItem(g)
@ -83,10 +85,10 @@ def update():
global phase, sp2, d2
s = -np.cos(d2*2+phase)
color = np.empty((len(d2),4), dtype=np.float32)
color[:,3] = np.clip(s * 0.1, 0, 1)
color[:,0] = np.clip(s * 3.0, 0, 1)
color[:,1] = np.clip(s * 1.0, 0, 1)
color[:,2] = np.clip(s ** 3, 0, 1)
color[:,3] = fn.clip_array(s * 0.1, 0., 1.)
color[:,0] = fn.clip_array(s * 3.0, 0., 1.)
color[:,1] = fn.clip_array(s * 1.0, 0., 1.)
color[:,2] = fn.clip_array(s ** 3, 0., 1.)
sp2.setData(color=color)
phase -= 0.1
@ -105,9 +107,5 @@ t = QtCore.QTimer()
t.timeout.connect(update)
t.start(50)
## Start Qt event loop unless running in interactive mode.
if __name__ == '__main__':
import sys
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
QtGui.QApplication.instance().exec_()
pg.exec()

View File

@ -13,7 +13,7 @@ import pyqtgraph.opengl as gl
import numpy as np
## Create a GL View widget to display data
app = QtGui.QApplication([])
app = pg.mkQApp("GLSurfacePlot Example")
w = gl.GLViewWidget()
w.show()
w.setWindowTitle('pyqtgraph example: GLSurfacePlot')
@ -92,8 +92,5 @@ timer = QtCore.QTimer()
timer.timeout.connect(update)
timer.start(30)
## Start Qt event loop unless running in interactive mode.
if __name__ == '__main__':
import sys
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
QtGui.QApplication.instance().exec_()
pg.exec()

35
examples/GLTextItem.py Normal file
View File

@ -0,0 +1,35 @@
# -*- coding: utf-8 -*-
"""
Simple examples demonstrating the use of GLTextItem.
"""
import initExample
import pyqtgraph as pg
from pyqtgraph.Qt import QtCore, QtGui, mkQApp
import pyqtgraph.opengl as gl
app = mkQApp("GLTextItem Example")
gvw = gl.GLViewWidget()
gvw.show()
gvw.setWindowTitle('pyqtgraph example: GLTextItem')
griditem = gl.GLGridItem()
griditem.setSize(10, 10)
griditem.setSpacing(1, 1)
gvw.addItem(griditem)
axisitem = gl.GLAxisItem()
gvw.addItem(axisitem)
txtitem1 = gl.GLTextItem(pos=(0.0, 0.0, 0.0), text='text1')
gvw.addItem(txtitem1)
txtitem2 = gl.GLTextItem()
txtitem2.setData(pos=(1.0, -1.0, 2.0), color=(127, 255, 127, 255), text='text2')
gvw.addItem(txtitem2)
if __name__ == '__main__':
pg.exec()

View File

@ -6,14 +6,14 @@ Very basic 3D graphics example; create a view widget and add a few items.
## Add path to library (just for examples; you do not need this)
import initExample
from pyqtgraph.Qt import QtCore, QtGui
import pyqtgraph as pg
import pyqtgraph.opengl as gl
app = QtGui.QApplication([])
pg.mkQApp("GLViewWidget Example")
w = gl.GLViewWidget()
w.opts['distance'] = 20
w.show()
w.setWindowTitle('pyqtgraph example: GLViewWidget')
w.setCameraPosition(distance=20)
ax = gl.GLAxisItem()
ax.setSize(5,5,5)
@ -27,8 +27,5 @@ ax2.setParentItem(b)
b.translate(1,1,1)
## Start Qt event loop unless running in interactive mode.
if __name__ == '__main__':
import sys
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
QtGui.QApplication.instance().exec_()
pg.exec()

View File

@ -7,46 +7,66 @@ Demonstrates GLVolumeItem for displaying volumetric data.
## Add path to library (just for examples; you do not need this)
import initExample
from pyqtgraph.Qt import QtCore, QtGui
import numpy as np
import pyqtgraph as pg
import pyqtgraph.opengl as gl
from pyqtgraph import functions as fn
app = QtGui.QApplication([])
app = pg.mkQApp("GLVolumeItem Example")
w = gl.GLViewWidget()
w.opts['distance'] = 200
w.show()
w.setWindowTitle('pyqtgraph example: GLVolumeItem')
w.setCameraPosition(distance=200)
#b = gl.GLBoxItem()
#w.addItem(b)
g = gl.GLGridItem()
g.scale(10, 10, 1)
w.addItem(g)
import numpy as np
## Hydrogen electron probability density
def psi(i, j, k, offset=(50,50,100)):
x = i-offset[0]
y = j-offset[1]
z = k-offset[2]
th = np.arctan2(z, (x**2+y**2)**0.5)
phi = np.arctan2(y, x)
r = (x**2 + y**2 + z **2)**0.5
th = np.arctan2(z, np.hypot(x, y))
r = np.sqrt(x**2 + y**2 + z **2)
a0 = 2
#ps = (1./81.) * (2./np.pi)**0.5 * (1./a0)**(3/2) * (6 - r/a0) * (r/a0) * np.exp(-r/(3*a0)) * np.cos(th)
ps = (1./81.) * 1./(6.*np.pi)**0.5 * (1./a0)**(3/2) * (r/a0)**2 * np.exp(-r/(3*a0)) * (3 * np.cos(th)**2 - 1)
return ps
#return ((1./81.) * (1./np.pi)**0.5 * (1./a0)**(3/2) * (r/a0)**2 * (r/a0) * np.exp(-r/(3*a0)) * np.sin(th) * np.cos(th) * np.exp(2 * 1j * phi))**2
return (
(1.0 / 81.0)
* 1.0 / (6.0 * np.pi) ** 0.5
* (1.0 / a0) ** (3 / 2)
* (r / a0) ** 2
* np.exp(-r / (3 * a0))
* (3 * np.cos(th) ** 2 - 1)
)
data = np.fromfunction(psi, (100,100,200))
positive = np.log(np.clip(data, 0, data.max())**2)
negative = np.log(np.clip(-data, 0, -data.min())**2)
with np.errstate(divide = 'ignore'):
positive = np.log(fn.clip_array(data, 0, data.max())**2)
negative = np.log(fn.clip_array(-data, 0, -data.min())**2)
d2 = np.empty(data.shape + (4,), dtype=np.ubyte)
d2[..., 0] = positive * (255./positive.max())
d2[..., 1] = negative * (255./negative.max())
# Original Code
# d2[..., 0] = positive * (255./positive.max())
# d2[..., 1] = negative * (255./negative.max())
# Reformulated Code
# Both positive.max() and negative.max() are negative-valued.
# Thus the next 2 lines are _not_ bounded to [0, 255]
positive = positive * (255./positive.max())
negative = negative * (255./negative.max())
# When casting to ubyte, the original code relied on +Inf to be
# converted to 0. On arm64, it gets converted to 255.
# Thus the next 2 lines change +Inf explicitly to 0 instead.
positive[np.isinf(positive)] = 0
negative[np.isinf(negative)] = 0
# When casting to ubyte, the original code relied on the conversion
# to do modulo 256. The next 2 lines do it explicitly instead as
# documentation.
d2[..., 0] = positive.astype(int) % 256
d2[..., 1] = negative.astype(int) % 256
d2[..., 2] = d2[...,1]
d2[..., 3] = d2[..., 0]*0.3 + d2[..., 1]*0.3
d2[..., 3] = (d2[..., 3].astype(float) / 255.) **2 * 255
@ -62,8 +82,5 @@ w.addItem(v)
ax = gl.GLAxisItem()
w.addItem(ax)
## Start Qt event loop unless running in interactive mode.
if __name__ == '__main__':
import sys
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
QtGui.QApplication.instance().exec_()
pg.exec()

View File

@ -9,11 +9,12 @@ used to affect the appearance of a surface.
## Add path to library (just for examples; you do not need this)
import initExample
import numpy as np
from pyqtgraph.Qt import QtCore, QtGui
import pyqtgraph as pg
import pyqtgraph.opengl as gl
app = QtGui.QApplication([])
app = pg.mkQApp("GLShaders Example")
w = gl.GLViewWidget()
w.show()
w.setWindowTitle('pyqtgraph example: GL Shaders')
@ -23,9 +24,6 @@ g = gl.GLGridItem()
g.scale(2,2,1)
w.addItem(g)
import numpy as np
md = gl.MeshData.sphere(rows=10, cols=20)
x = np.linspace(-8, 8, 6)
@ -101,10 +99,5 @@ w.addItem(m6)
#w.addItem(m2)
#m2.translate(-25, -25, -50)
## Start Qt event loop unless running in interactive mode.
if __name__ == '__main__':
import sys
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
QtGui.QApplication.instance().exec_()
pg.exec()

View File

@ -7,7 +7,7 @@ from pyqtgraph.Qt import QtGui, QtCore
import pyqtgraph as pg
app = QtGui.QApplication([])
app = pg.mkQApp("Gradiant Editor Example")
mw = pg.GraphicsView()
mw.resize(800,800)
mw.show()
@ -20,9 +20,5 @@ mw.show()
ge = pg.GradientEditorItem()
mw.setCentralItem(ge)
## Start Qt event loop unless running in interactive mode.
if __name__ == '__main__':
import sys
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
QtGui.QApplication.instance().exec_()
pg.exec()

View File

@ -12,7 +12,7 @@ import numpy as np
app = QtGui.QApplication([])
app = pg.mkQApp("Gradiant Widget Example")
w = QtGui.QMainWindow()
w.show()
w.setWindowTitle('pyqtgraph example: GradientWidget')
@ -27,15 +27,18 @@ cw.setLayout(l)
w1 = pg.GradientWidget(orientation='top')
w2 = pg.GradientWidget(orientation='right', allowAdd=False)
#w2.setTickColor(1, QtGui.QColor(255,255,255))
w3 = pg.GradientWidget(orientation='bottom')
w3 = pg.GradientWidget(orientation='bottom', allowAdd=False, allowRemove=False)
w4 = pg.GradientWidget(orientation='left')
w4.loadPreset('spectrum')
label = QtGui.QLabel("""
- Click a triangle to change its color
- Drag triangles to move
- Right-click a gradient to load triangle presets
- Click in an empty area to add a new color
(adding is disabled for the right-side widget)
(adding is disabled for the bottom-side and right-side widgets)
- Right click a triangle to remove
(only possible if more than two triangles are visible)
(removing is disabled for the bottom-side widget)
""")
l.addWidget(w1, 0, 1)
@ -44,12 +47,8 @@ l.addWidget(w3, 2, 1)
l.addWidget(w4, 1, 0)
l.addWidget(label, 1, 1)
## Start Qt event loop unless running in interactive mode or using pyside.
if __name__ == '__main__':
import sys
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
QtGui.QApplication.instance().exec_()
pg.exec()

View File

@ -57,11 +57,5 @@ lines = np.array([
## Update the graph
g.setData(pos=pos, adj=adj, pen=lines, size=1, symbol=symbols, pxMode=False)
## Start Qt event loop unless running in interactive mode or using pyside.
if __name__ == '__main__':
import sys
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
QtGui.QApplication.instance().exec_()
pg.exec()

View File

@ -12,7 +12,7 @@ from pyqtgraph.Qt import QtGui, QtCore
import pyqtgraph as pg
import numpy as np
app = QtGui.QApplication([])
app = pg.mkQApp("Gradiant Layout Example")
view = pg.GraphicsView()
l = pg.GraphicsLayout(border=(100,100,100))
view.setCentralItem(l)
@ -78,10 +78,5 @@ p2.plot([1,3,2,4,3,5])
p4.plot([1,3,2,4,3,5])
p5.plot([1,3,2,4,3,5])
## Start Qt event loop unless running in interactive mode.
if __name__ == '__main__':
import sys
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
QtGui.QApplication.instance().exec_()
pg.exec()

View File

@ -6,7 +6,7 @@ from pyqtgraph.Qt import QtCore, QtGui
import pyqtgraph as pg
from pyqtgraph.GraphicsScene import GraphicsScene
app = QtGui.QApplication([])
app = pg.mkQApp("GraphicsScene Example")
win = pg.GraphicsView()
win.show()
@ -58,9 +58,5 @@ vb.addItem(prox)
g = pg.GridItem()
vb.addItem(g)
## Start Qt event loop unless running in interactive mode.
if __name__ == '__main__':
import sys
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
QtGui.QApplication.instance().exec_()
pg.exec()

View File

@ -3,45 +3,49 @@
Use a HistogramLUTWidget to control the contrast / coloration of an image.
"""
## Add path to library (just for examples; you do not need this)
# Add path to library (just for examples; you do not need this)
import initExample
import numpy as np
from pyqtgraph.Qt import QtGui, QtCore
import pyqtgraph as pg
from pyqtgraph.Qt import QtGui
app = QtGui.QApplication([])
app = pg.mkQApp("Histogram Lookup Table Example")
win = QtGui.QMainWindow()
win.resize(800,600)
win.resize(880, 600)
win.show()
win.setWindowTitle('pyqtgraph example: Histogram LUT')
cw = QtGui.QWidget()
win.setCentralWidget(cw)
l = QtGui.QGridLayout()
cw.setLayout(l)
l.setSpacing(0)
layout = QtGui.QGridLayout()
cw.setLayout(layout)
layout.setSpacing(0)
v = pg.GraphicsView()
view = pg.GraphicsView()
vb = pg.ViewBox()
vb.setAspectLocked()
v.setCentralItem(vb)
l.addWidget(v, 0, 0, 3, 1)
view.setCentralItem(vb)
layout.addWidget(view, 0, 1, 3, 1)
hist = pg.HistogramLUTWidget(gradientPosition="left")
layout.addWidget(hist, 0, 2)
w = pg.HistogramLUTWidget()
l.addWidget(w, 0, 1)
monoRadio = QtGui.QRadioButton('mono')
rgbaRadio = QtGui.QRadioButton('rgba')
l.addWidget(monoRadio, 1, 1)
l.addWidget(rgbaRadio, 2, 1)
layout.addWidget(monoRadio, 1, 2)
layout.addWidget(rgbaRadio, 2, 2)
monoRadio.setChecked(True)
def setLevelMode():
mode = 'mono' if monoRadio.isChecked() else 'rgba'
w.setLevelMode(mode)
hist.setLevelMode(mode)
monoRadio.toggled.connect(setLevelMode)
data = pg.gaussianFilter(np.random.normal(size=(256, 256, 3)), (20, 20, 0))
@ -52,11 +56,7 @@ img = pg.ImageItem(data)
vb.addItem(img)
vb.autoRange()
w.setImageItem(img)
hist.setImageItem(img)
## Start Qt event loop unless running in interactive mode.
if __name__ == '__main__':
import sys
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
QtGui.QApplication.instance().exec_()
pg.exec()

View File

@ -9,9 +9,9 @@ import initExample
from pyqtgraph.Qt import QtCore, QtGui
import numpy as np
import pyqtgraph as pg
import pyqtgraph.ptime as ptime
from time import perf_counter
app = QtGui.QApplication([])
app = pg.mkQApp("ImageItem Example")
## Create window with GraphicsView widget
win = pg.GraphicsLayoutWidget()
@ -33,29 +33,30 @@ view.setRange(QtCore.QRectF(0, 0, 600, 600))
data = np.random.normal(size=(15, 600, 600), loc=1024, scale=64).astype(np.uint16)
i = 0
updateTime = ptime.time()
fps = 0
updateTime = perf_counter()
elapsed = 0
timer = QtCore.QTimer()
timer.setSingleShot(True)
# not using QTimer.singleShot() because of persistence on PyQt. see PR #1605
def updateData():
global img, data, i, updateTime, fps
global img, data, i, updateTime, elapsed
## Display the data
img.setImage(data[i])
i = (i+1) % data.shape[0]
QtCore.QTimer.singleShot(1, updateData)
now = ptime.time()
fps2 = 1.0 / (now-updateTime)
timer.start(1)
now = perf_counter()
elapsed_now = now - updateTime
updateTime = now
fps = fps * 0.9 + fps2 * 0.1
#print "%0.1f fps" % fps
elapsed = elapsed * 0.9 + elapsed_now * 0.1
# print(f"{1 / elapsed:.1f} fps")
timer.timeout.connect(updateData)
updateData()
## Start Qt event loop unless running in interactive mode.
if __name__ == '__main__':
import sys
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
QtGui.QApplication.instance().exec_()
pg.exec()

View File

@ -1,7 +1,8 @@
# -*- coding: utf-8 -*-
"""
This example demonstrates the use of ImageView, which is a high-level widget for
displaying and analyzing 2D and 3D data. ImageView provides:
This example demonstrates the use of ImageView with 3-color image stacks.
ImageView is a high-level widget for displaying and analyzing 2D and 3D data.
ImageView provides:
1. A zoomable region (ViewBox) for displaying the image
2. A combination histogram and gradient editor (HistogramLUTItem) for
@ -20,7 +21,7 @@ import pyqtgraph as pg
# Interpret image data as row-major instead of col-major
pg.setConfigOptions(imageAxisOrder='row-major')
app = QtGui.QApplication([])
app = pg.mkQApp("ImageView Example")
## Create window with ImageView widget
win = QtGui.QMainWindow()
@ -30,22 +31,17 @@ win.setCentralWidget(imv)
win.show()
win.setWindowTitle('pyqtgraph example: ImageView')
## Create random 3D data set with noisy signals
img = pg.gaussianFilter(np.random.normal(size=(200, 200)), (5, 5)) * 20 + 100
img = img[np.newaxis,:,:]
decay = np.exp(-np.linspace(0,0.3,100))[:,np.newaxis,np.newaxis]
data = np.random.normal(size=(100, 200, 200))
data += img * decay
data += 2
## Create random 3D data set with time varying signals
dataRed = np.ones((100, 200, 200)) * np.linspace(90, 150, 100)[:, np.newaxis, np.newaxis]
dataRed += pg.gaussianFilter(np.random.normal(size=(200, 200)), (5, 5)) * 100
dataGrn = np.ones((100, 200, 200)) * np.linspace(90, 180, 100)[:, np.newaxis, np.newaxis]
dataGrn += pg.gaussianFilter(np.random.normal(size=(200, 200)), (5, 5)) * 100
dataBlu = np.ones((100, 200, 200)) * np.linspace(180, 90, 100)[:, np.newaxis, np.newaxis]
dataBlu += pg.gaussianFilter(np.random.normal(size=(200, 200)), (5, 5)) * 100
## Add time-varying signal
sig = np.zeros(data.shape[0])
sig[30:] += np.exp(-np.linspace(1,10, 70))
sig[40:] += np.exp(-np.linspace(1,10, 60))
sig[70:] += np.exp(-np.linspace(1,10, 30))
sig = sig[:,np.newaxis,np.newaxis] * 3
data[:,50:60,30:40] += sig
data = np.concatenate(
(dataRed[:, :, :, np.newaxis], dataGrn[:, :, :, np.newaxis], dataBlu[:, :, :, np.newaxis]), axis=3
)
## Display the data and assign each frame a time value from 1.0 to 3.0
@ -63,8 +59,9 @@ colors = [
cmap = pg.ColorMap(pos=np.linspace(0.0, 1.0, 6), color=colors)
imv.setColorMap(cmap)
## Start Qt event loop unless running in interactive mode.
# Start up with an ROI
imv.ui.roiBtn.setChecked(True)
imv.roiClicked()
if __name__ == '__main__':
import sys
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
QtGui.QApplication.instance().exec_()
pg.exec()

View File

@ -9,7 +9,7 @@ import numpy as np
import pyqtgraph as pg
app = QtGui.QApplication([])
app = pg.mkQApp("InfiniteLine Example")
win = pg.GraphicsLayoutWidget(show=True, title="Plotting items examples")
win.resize(1000,600)
@ -32,14 +32,54 @@ p1.addItem(inf1)
p1.addItem(inf2)
p1.addItem(inf3)
targetItem1 = pg.TargetItem()
targetItem2 = pg.TargetItem(
pos=(30, 5),
size=20,
symbol="star",
pen="#F4511E",
label="vert={1:0.2f}",
labelOpts={
"offset": QtCore.QPoint(15, 15)
}
)
targetItem2.label().setAngle(45)
targetItem3 = pg.TargetItem(
pos=(10, 10),
size=10,
symbol="x",
pen="#00ACC1",
)
targetItem3.setLabel(
"Third Label",
{
"anchor": QtCore.QPointF(0.5, 0.5),
"offset": QtCore.QPointF(30, 0),
"color": "#558B2F",
"rotateAxis": (0, 1)
}
)
def callableFunction(x, y):
return f"Square Values: ({x**2:.4f}, {y**2:.4f})"
targetItem4 = pg.TargetItem(
pos=(10, -10),
label=callableFunction
)
p1.addItem(targetItem1)
p1.addItem(targetItem2)
p1.addItem(targetItem3)
p1.addItem(targetItem4)
# Add a linear region with a label
lr = pg.LinearRegionItem(values=[70, 80])
p1.addItem(lr)
label = pg.InfLineLabel(lr.lines[1], "region 1", position=0.95, rotateAxis=(1,0), anchor=(1, 1))
## Start Qt event loop unless running in interactive mode or using pyside.
if __name__ == '__main__':
import sys
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
QtGui.QApplication.instance().exec_()
pg.exec()

View File

@ -12,7 +12,7 @@ from pyqtgraph.Qt import QtGui, QtCore
import pyqtgraph as pg
app = QtGui.QApplication([])
app = pg.mkQApp("Joystick Button Example")
mw = QtGui.QMainWindow()
mw.resize(300,50)
mw.setWindowTitle('pyqtgraph example: JoystickButton')
@ -46,11 +46,5 @@ timer = QtCore.QTimer()
timer.timeout.connect(update)
timer.start(30)
## Start Qt event loop unless running in interactive mode or using pyside.
if __name__ == '__main__':
import sys
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
QtGui.QApplication.instance().exec_()
pg.exec()

View File

@ -7,21 +7,37 @@ import initExample ## Add path to library (just for examples; you do not need th
import pyqtgraph as pg
from pyqtgraph.Qt import QtCore, QtGui
import numpy as np
plt = pg.plot()
plt.setWindowTitle('pyqtgraph example: Legend')
plt.addLegend()
#l = pg.LegendItem((100,60), offset=(70,30)) # args are (size, offset)
#l.setParentItem(plt.graphicsItem()) # Note we do NOT call plt.addItem in this case
win = pg.plot()
win.setWindowTitle('pyqtgraph example: BarGraphItem')
c1 = plt.plot([1,3,2,4], pen='r', symbol='o', symbolPen='r', symbolBrush=0.5, name='red plot')
c2 = plt.plot([2,1,4,3], pen='g', fillLevel=0, fillBrush=(255,255,255,30), name='green plot')
#l.addItem(c1, 'red plot')
#l.addItem(c2, 'green plot')
# # option1: only for .plot(), following c1,c2 for example-----------------------
# win.addLegend(frame=False, colCount=2)
# bar graph
x = np.arange(10)
y = np.sin(x+2) * 3
bg1 = pg.BarGraphItem(x=x, height=y, width=0.3, brush='b', pen='w', name='bar')
win.addItem(bg1)
# curve
c1 = win.plot([np.random.randint(0,8) for i in range(10)], pen='r', symbol='t', symbolPen='r', symbolBrush='g', name='curve1')
c2 = win.plot([2,1,4,3,1,3,2,4,3,2], pen='g', fillLevel=0, fillBrush=(255,255,255,30), name='curve2')
# scatter plot
s1 = pg.ScatterPlotItem(size=10, pen=pg.mkPen(None), brush=pg.mkBrush(255, 255, 255, 120), name='scatter')
spots = [{'pos': [i, np.random.randint(-3, 3)], 'data': 1} for i in range(10)]
s1.addPoints(spots)
win.addItem(s1)
# # option2: generic method------------------------------------------------
legend = pg.LegendItem((80,60), offset=(70,20))
legend.setParentItem(win.graphicsItem())
legend.addItem(bg1, 'bar')
legend.addItem(c1, 'curve1')
legend.addItem(c2, 'curve2')
legend.addItem(s1, 'scatter')
## Start Qt event loop unless running in interactive mode or using pyside.
if __name__ == '__main__':
import sys
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
QtGui.QApplication.instance().exec_()
pg.exec()

View File

@ -10,7 +10,7 @@ from pyqtgraph.Qt import QtGui, QtCore
import numpy as np
import pyqtgraph as pg
app = QtGui.QApplication([])
app = pg.mkQApp("Log Plot Example")
win = pg.GraphicsLayoutWidget(show=True, title="Basic plotting examples")
win.resize(1000,600)
@ -30,8 +30,5 @@ p5.setLabel('bottom', "Y Axis", units='s')
p5.setLogMode(x=True, y=False)
## Start Qt event loop unless running in interactive mode or using pyside.
if __name__ == '__main__':
import sys
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
QtGui.QApplication.instance().exec_()
pg.exec()

View File

@ -0,0 +1,62 @@
# -*- coding: utf-8 -*-
"""
This example demonstrates ViewBox and AxisItem configuration to plot a correlation matrix.
"""
## Add path to library (just for examples; you do not need this)
import initExample
import numpy as np
import pyqtgraph as pg
from pyqtgraph.Qt import QtWidgets, mkQApp, QtGui
class MainWindow(QtWidgets.QMainWindow):
""" example application main window """
def __init__(self, *args, **kwargs):
super(MainWindow, self).__init__(*args, **kwargs)
gr_wid = pg.GraphicsLayoutWidget(show=True)
self.setCentralWidget(gr_wid)
self.setWindowTitle('pyqtgraph example: Correlation matrix display')
self.resize(600,500)
self.show()
corrMatrix = np.array([
[ 1. , 0.5184571 , -0.70188642],
[ 0.5184571 , 1. , -0.86094096],
[-0.70188642, -0.86094096, 1. ]
])
columns = ["A", "B", "C"]
pg.setConfigOption('imageAxisOrder', 'row-major') # Switch default order to Row-major
correlogram = pg.ImageItem()
# create transform to center the corner element on the origin, for any assigned image:
tr = QtGui.QTransform().translate(-0.5, -0.5)
correlogram.setTransform(tr)
correlogram.setImage(corrMatrix)
plotItem = gr_wid.addPlot() # add PlotItem to the main GraphicsLayoutWidget
plotItem.invertY(True) # orient y axis to run top-to-bottom
plotItem.setDefaultPadding(0.0) # plot without padding data range
plotItem.addItem(correlogram) # display correlogram
# show full frame, label tick marks at top and left sides, with some extra space for labels:
plotItem.showAxes( True, showValues=(True, True, False, False), size=20 )
# define major tick marks and labels:
ticks = [ (idx, label) for idx, label in enumerate( columns ) ]
for side in ('left','top','right','bottom'):
plotItem.getAxis(side).setTicks( (ticks, []) ) # add list of major ticks; no minor ticks
plotItem.getAxis('bottom').setHeight(10) # include some additional space at bottom of figure
colorMap = pg.colormap.get("CET-D1") # choose perceptually uniform, diverging color map
# generate an adjustabled color bar, initially spanning -1 to 1:
bar = pg.ColorBarItem( values=(-1,1), cmap=colorMap)
# link color bar and color map to correlogram, and show it in plotItem:
bar.setImageItem(correlogram, insert_in=plotItem)
mkQApp("Correlation matrix display")
main_window = MainWindow()
## Start Qt event loop
if __name__ == '__main__':
pg.exec()

View File

@ -30,8 +30,5 @@ for c in curves:
win.addItem(c)
c.sigClicked.connect(plotClicked)
## Start Qt event loop unless running in interactive mode or using pyside.
if __name__ == '__main__':
import sys
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
QtGui.QApplication.instance().exec_()
pg.exec()

View File

@ -11,8 +11,10 @@ import initExample
from pyqtgraph.Qt import QtGui, QtCore
import numpy as np
import pyqtgraph as pg
from pyqtgraph.ptime import time
app = QtGui.QApplication([])
from time import perf_counter
# pg.setConfigOptions(useOpenGL=True)
app = pg.mkQApp("MultiPlot Speed Test")
plot = pg.plot()
plot.setWindowTitle('pyqtgraph example: MultiPlotSpeedTest')
@ -22,7 +24,7 @@ nPlots = 100
nSamples = 500
curves = []
for idx in range(nPlots):
curve = pg.PlotCurveItem(pen=(idx,nPlots*1.3))
curve = pg.PlotCurveItem(pen=({'color': (idx, nPlots*1.3), 'width': 1}), skipFiniteCheck=True)
plot.addItem(curve)
curve.setPos(0,idx*6)
curves.append(curve)
@ -37,7 +39,7 @@ plot.addItem(rgn)
data = np.random.normal(size=(nPlots*23,nSamples))
ptr = 0
lastTime = time()
lastTime = perf_counter()
fps = None
count = 0
def update():
@ -48,7 +50,7 @@ def update():
curves[i].setData(data[(ptr+i)%data.shape[0]])
ptr += nPlots
now = time()
now = perf_counter()
dt = now - lastTime
lastTime = now
if fps is None:
@ -62,8 +64,5 @@ timer = QtCore.QTimer()
timer.timeout.connect(update)
timer.start(0)
## Start Qt event loop unless running in interactive mode.
if __name__ == '__main__':
import sys
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
QtGui.QApplication.instance().exec_()
pg.exec()

View File

@ -14,7 +14,7 @@ except:
print("MultiPlot is only used with MetaArray for now (and you do not have the metaarray package)")
exit()
app = QtGui.QApplication([])
app = pg.mkQApp("MultiPlot Widget Example")
mw = QtGui.QMainWindow()
mw.resize(800,800)
pw = MultiPlotWidget()
@ -30,11 +30,8 @@ ma = MetaArray(data, info=[
]},
{'name': 'Time', 'values': linspace(0., 1., 1000), 'units': 's'}
])
pw.plot(ma)
pw.plot(ma, pen='y')
## Start Qt event loop unless running in interactive mode.
if __name__ == '__main__':
import sys
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
QtGui.QApplication.instance().exec_()
pg.exec()

View File

@ -60,8 +60,5 @@ p1.plot([1,2,4,8,16,32])
p2.addItem(pg.PlotCurveItem([10,20,40,80,40,20], pen='b'))
p3.addItem(pg.PlotCurveItem([3200,1600,800,400,200,100], pen='r'))
## Start Qt event loop unless running in interactive mode or using pyside.
if __name__ == '__main__':
import sys
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
QtGui.QApplication.instance().exec_()
pg.exec()

View File

@ -0,0 +1,83 @@
# -*- coding: utf-8 -*-
"""
Display a non-uniform image.
This example displays 2-d data as an image with non-uniformly
distributed sample points.
"""
import initExample ## Add path to library (just for examples; you do not need this)
from pyqtgraph.Qt import QtGui, QtCore
import pyqtgraph as pg
import numpy as np
from pyqtgraph.graphicsItems.GradientEditorItem import Gradients
from pyqtgraph.graphicsItems.NonUniformImage import NonUniformImage
RPM2RADS = 2 * np.pi / 60
RADS2RPM = 1 / RPM2RADS
kfric = 1 # [Ws/rad] angular damping coefficient [0;100]
kfric3 = 1.5e-6 # [Ws3/rad3] angular damping coefficient (3rd order) [0;10-3]
psi = 0.2 # [Vs] flux linkage [0.001;10]
res = 5e-3 # [Ohm] resistance [0;100]
v_ref = 200 # [V] reference DC voltage [0;1000]
k_v = 5 # linear voltage coefficient [-100;100]
# create the (non-uniform) scales
tau = np.array([0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 120, 140, 160, 180, 200, 220], dtype=np.float32)
w = np.array([0, 250, 500, 750, 1000, 1500, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000, 10000], dtype=np.float32) * RPM2RADS
v = 380
# calculate the power losses
TAU, W = np.meshgrid(tau, w, indexing='ij')
V = np.ones_like(TAU) * v
P_loss = kfric * W + kfric3 * W ** 3 + (res * (TAU / psi) ** 2) + k_v * (V - v_ref)
P_mech = TAU * W
P_loss[P_mech > 1.5e5] = np.NaN
# green - orange - red
Gradients['gor'] = {'ticks': [(0.0, (74, 158, 71)), (0.5, (255, 230, 0)), (1, (191, 79, 76))], 'mode': 'rgb'}
app = pg.mkQApp("NonUniform Image Example")
win = QtGui.QMainWindow()
cw = pg.GraphicsLayoutWidget()
win.show()
win.resize(600, 400)
win.setCentralWidget(cw)
win.setWindowTitle('pyqtgraph example: Non-uniform Image')
p = cw.addPlot(title="Power Losses [W]", row=0, col=0)
lut = pg.HistogramLUTItem(orientation="horizontal")
p.setMouseEnabled(x=False, y=False)
cw.nextRow()
cw.addItem(lut)
# load the gradient
lut.gradient.loadPreset('gor')
image = NonUniformImage(w * RADS2RPM, tau, P_loss.T)
image.setLookupTable(lut, autoLevel=True)
image.setZValue(-1)
p.addItem(image)
h = image.getHistogram()
lut.plot.setData(*h)
p.showGrid(x=True, y=True)
p.setLabel(axis='bottom', text='Speed [rpm]')
p.setLabel(axis='left', text='Torque [Nm]')
# elevate the grid lines
p.axes['bottom']['item'].setZValue(1000)
p.axes['left']['item'].setZValue(1000)
if __name__ == '__main__':
pg.exec()

View File

@ -0,0 +1,86 @@
# -*- coding: utf-8 -*-
"""
Demonstrates very basic use of PColorMeshItem
"""
## Add path to library (just for examples; you do not need this)
import initExample
from pyqtgraph.Qt import QtCore
import numpy as np
import pyqtgraph as pg
app = pg.mkQApp("PColorMesh Example")
## Create window with GraphicsView widget
win = pg.GraphicsLayoutWidget()
win.show() ## show widget alone in its own window
win.setWindowTitle('pyqtgraph example: pColorMeshItem')
view = win.addViewBox()
## Create data
# To enhance the non-grid meshing, we randomize the polygon vertices per and
# certain amount
randomness = 5
# x and y being the vertices of the polygons, they share the same shape
# However the shape can be different in both dimension
xn = 50 # nb points along x
yn = 40 # nb points along y
x = np.repeat(np.arange(1, xn+1), yn).reshape(xn, yn)\
+ np.random.random((xn, yn))*randomness
y = np.tile(np.arange(1, yn+1), xn).reshape(xn, yn)\
+ np.random.random((xn, yn))*randomness
x.sort(axis=0)
y.sort(axis=0)
# z being the color of the polygons its shape must be decreased by one in each dimension
z = np.exp(-(x*xn)**2/1000)[:-1,:-1]
## Create image item
edgecolors = None
antialiasing = False
# edgecolors = {'color':'w', 'width':2} # May be uncommened to see edgecolor effect
# antialiasing = True # May be uncommened to see antialiasing effect
pcmi = pg.PColorMeshItem(edgecolors=edgecolors, antialiasing=antialiasing)
view.addItem(pcmi)
## Set the animation
fps = 25 # Frame per second of the animation
# Wave parameters
wave_amplitude = 3
wave_speed = 0.3
wave_length = 10
color_speed = 0.3
timer = QtCore.QTimer()
timer.setSingleShot(True)
# not using QTimer.singleShot() because of persistence on PyQt. see PR #1605
i=0
def updateData():
global i
## Display the new data set
new_x = x
new_y = y+wave_amplitude*np.cos(x/wave_length+i)
new_z = np.exp(-(x-np.cos(i*color_speed)*xn)**2/1000)[:-1,:-1]
pcmi.setData(new_x,
new_y,
new_z)
i += wave_speed
timer.start(1000//fps)
timer.timeout.connect(updateData)
updateData()
if __name__ == '__main__':
pg.exec()

View File

@ -30,8 +30,5 @@ timer = QtCore.QTimer()
timer.timeout.connect(update)
timer.start(50)
## Start Qt event loop unless running in interactive mode or using pyside.
if __name__ == '__main__':
import sys
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
QtGui.QApplication.instance().exec_()
pg.exec()

View File

@ -11,8 +11,7 @@ from pyqtgraph.Qt import QtGui, QtCore
import numpy as np
import pyqtgraph as pg
#QtGui.QApplication.setGraphicsSystem('raster')
app = QtGui.QApplication([])
app = pg.mkQApp("Plot Auto Range Example")
#mw = QtGui.QMainWindow()
#mw.resize(800,800)
@ -41,10 +40,5 @@ timer = QtCore.QTimer()
timer.timeout.connect(update)
timer.start(50)
## Start Qt event loop unless running in interactive mode or using pyside.
if __name__ == '__main__':
import sys
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
QtGui.QApplication.instance().exec_()
pg.exec()

Some files were not shown because too many files have changed in this diff Show More