Merge branch 'master' into prep-for-release

This commit is contained in:
Kyle Sunden 2021-07-08 00:38:57 -05:00 committed by GitHub
commit 89958dbaab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
65 changed files with 2345 additions and 455 deletions

View File

@ -23,7 +23,7 @@ heavy leverage of numpy for number crunching, Qt's GraphicsView framework for
Requirements
------------
pyqtgraph has adopted [NEP 29](https://numpy.org/neps/nep-0029-deprecation_policy.html).
PyQtGraph has adopted [NEP 29](https://numpy.org/neps/nep-0029-deprecation_policy.html).
This project supports:
@ -36,8 +36,8 @@ Currently this means:
* Python 3.7+
* Qt 5.12-5.15, 6.1
* Required
* PyQt5, PyQt6, PySide2 or PySide6
* `numpy` 1.17+
* [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.17+
* Optional
* `scipy` for image processing
* `pyopengl` for 3D graphics
@ -48,6 +48,32 @@ Currently this means:
* On Windows, CUDA toolkit must be >= 11.1
* [`numba`] used to accelerate repeated image display for ImageItem
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
-----------------------
@ -81,7 +107,7 @@ Installation Methods
* 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
@ -89,7 +115,7 @@ Documentation
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
-------

View File

@ -4,10 +4,12 @@ import re
import sys
import subprocess
from argparse import Namespace
import pyqtgraph as pg
from pyqtgraph.Qt import QtGui, QtCore, QT_LIB
from pyqtgraph.Qt import QtWidgets, QtGui, QtCore, QT_LIB
from collections import OrderedDict
from .utils import examples
from .utils import examples_
from functools import lru_cache
path = os.path.abspath(os.path.dirname(__file__))
sys.path.insert(0, path)
@ -28,7 +30,7 @@ QTextCharFormat = QtGui.QTextCharFormat
QSyntaxHighlighter = QtGui.QSyntaxHighlighter
def format(color, style=''):
def charFormat(color, style='', background=None):
"""
Return a QTextCharFormat with the given attributes.
"""
@ -44,6 +46,8 @@ def format(color, 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
@ -95,28 +99,28 @@ class DarkThemeColors:
LIGHT_STYLES = {
'keyword': format(LightThemeColors.Blue, 'bold'),
'operator': format(LightThemeColors.Red, 'bold'),
'brace': format(LightThemeColors.Purple),
'defclass': format(LightThemeColors.Indigo, 'bold'),
'string': format(LightThemeColors.Amber),
'string2': format(LightThemeColors.DeepPurple),
'comment': format(LightThemeColors.Green, 'italic'),
'self': format(LightThemeColors.Blue, 'bold'),
'numbers': format(LightThemeColors.Teal),
'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': format(DarkThemeColors.Blue, 'bold'),
'operator': format(DarkThemeColors.Red, 'bold'),
'brace': format(DarkThemeColors.Purple),
'defclass': format(DarkThemeColors.Indigo, 'bold'),
'string': format(DarkThemeColors.Amber),
'string2': format(DarkThemeColors.DeepPurple),
'comment': format(DarkThemeColors.Green, 'italic'),
'self': format(DarkThemeColors.Blue, 'bold'),
'numbers': format(DarkThemeColors.Teal),
'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),
}
@ -145,7 +149,7 @@ class PythonHighlighter(QSyntaxHighlighter):
]
def __init__(self, document):
QSyntaxHighlighter.__init__(self, document)
super().__init__(document)
# Multi-line strings (expression, flag, style)
self.tri_single = (QRegularExpression("'''"), 1, 'string2')
@ -185,17 +189,19 @@ class PythonHighlighter(QSyntaxHighlighter):
(r'#[^\n]*', 0, 'comment'),
]
self.rules = rules
self.searchText = None
@property
def styles(self):
app = QtGui.QApplication.instance()
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
for expression, nth, format in self.rules:
rules = self.rules.copy()
for expression, nth, format in rules:
format = self.styles[format]
for n, match in enumerate(re.finditer(expression, text)):
@ -204,6 +210,8 @@ class PythonHighlighter(QSyntaxHighlighter):
start = match.start()
length = match.end() - start
self.setFormat(start, length, format)
self.applySearchHighlight(text)
self.setCurrentBlockState(0)
# Do multi-line strings
@ -249,39 +257,86 @@ class PythonHighlighter(QSyntaxHighlighter):
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)
class ExampleLoader(QtGui.QMainWindow):
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):
QtGui.QMainWindow.__init__(self)
QtWidgets.QMainWindow.__init__(self)
self.ui = ui_template.Ui_Form()
self.cw = QtGui.QWidget()
self.cw = QtWidgets.QWidget()
self.setCentralWidget(self.cw)
self.ui.setupUi(self.cw)
self.setWindowTitle("PyQtGraph Examples")
self.codeBtn = QtGui.QPushButton('Run Edited Code')
self.codeLayout = QtGui.QGridLayout()
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 = QtGui.QApplication.instance()
app = QtWidgets.QApplication.instance()
app.paletteChanged.connect(self.updateTheme)
self.codeLayout.addItem(QtGui.QSpacerItem(100,100,QtGui.QSizePolicy.Policy.Expanding,QtGui.QSizePolicy.Policy.Expanding), 0, 0)
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()
global examples
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.populateTree(self.ui.exampleTree.invisibleRootItem(), examples_)
self.ui.exampleTree.expandAll()
self.resize(1000,500)
@ -290,9 +345,76 @@ class ExampleLoader(QtGui.QMainWindow):
self.ui.loadBtn.clicked.connect(self.loadFile)
self.ui.exampleTree.currentItemChanged.connect(self.showFile)
self.ui.exampleTree.itemDoubleClicked.connect(self.loadFile)
self.ui.codeView.textChanged.connect(self.codeEdited)
# 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
@ -309,7 +431,7 @@ class ExampleLoader(QtGui.QMainWindow):
f.setForeground(QtGui.QColor('white'))
self.ui.codeView.setCurrentCharFormat(f)
# finally, override application automatic detection
app = QtGui.QApplication.instance()
app = QtWidgets.QApplication.instance()
app.setProperty('darkMode', True)
def updateTheme(self):
@ -318,7 +440,7 @@ class ExampleLoader(QtGui.QMainWindow):
def populateTree(self, root, examples):
bold_font = None
for key, val in examples.items():
item = QtGui.QTreeWidgetItem([key])
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.
@ -338,7 +460,6 @@ class ExampleLoader(QtGui.QMainWindow):
def currentFile(self):
item = self.ui.exampleTree.currentItem()
if hasattr(item, 'file'):
global path
return os.path.join(path, item.file)
return None
@ -364,27 +485,62 @@ class ExampleLoader(QtGui.QMainWindow):
def showFile(self):
fn = self.currentFile()
if fn is None:
self.ui.codeView.clear()
return
if os.path.isdir(fn):
fn = os.path.join(fn, '__main__.py')
with open(fn, "r") as currentFile:
text = currentFile.read()
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__':

View File

@ -6,10 +6,10 @@ 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, mkQApp
import pyqtgraph as pg
import pyqtgraph.opengl as gl
app = mkQApp("GLViewWidget Example")
pg.mkQApp("GLViewWidget Example")
w = gl.GLViewWidget()
w.opts['distance'] = 20
w.show()

View File

@ -1,8 +1,7 @@
# -*- coding: utf-8 -*-
"""
This example demonstrates generating ColorMap objects from external data.
It displays the full list of color maps available as local files or by import
from Matplotlib or ColorCET.
This example displays all color maps currently available, either as local data
or imported from Matplotlib of ColorCET.
"""
## Add path to library (just for examples; you do not need this)
import initExample
@ -49,12 +48,14 @@ def add_bar(lw, name, cm):
add_heading(lw, 'local color maps')
list_of_maps = pg.colormap.listMaps()
list_of_maps = sorted( list_of_maps, key=lambda x: x.swapcase() )
for map_name in list_of_maps:
cm = pg.colormap.get(map_name)
add_bar(lw, map_name, cm)
add_heading(lw, 'Matplotlib import')
list_of_maps = pg.colormap.listMaps('matplotlib')
list_of_maps = sorted( list_of_maps, key=lambda x: x.lower() )
for map_name in list_of_maps:
cm = pg.colormap.get(map_name, source='matplotlib', skipCache=True)
if cm is not None:
@ -62,6 +63,7 @@ for map_name in list_of_maps:
add_heading(lw, 'ColorCET import')
list_of_maps = pg.colormap.listMaps('colorcet')
list_of_maps = sorted( list_of_maps, key=lambda x: x.lower() )
for map_name in list_of_maps:
cm = pg.colormap.get(map_name, source='colorcet', skipCache=True)
if cm is not None:

View File

@ -14,26 +14,14 @@
<string>PyQtGraph</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<item row="1" column="0">
<widget class="QSplitter" name="splitter">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<widget class="QWidget" name="">
<widget class="QWidget" name="layoutWidget">
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0" colspan="2">
<widget class="QTreeWidget" name="exampleTree">
<attribute name="headerVisible">
<bool>false</bool>
</attribute>
<column>
<property name="text">
<string notr="true">1</string>
</property>
</column>
</widget>
</item>
<item row="1" column="1">
<item row="4" column="1">
<widget class="QComboBox" name="qtLibCombo">
<item>
<property name="text">
@ -62,23 +50,56 @@
</item>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Qt Library:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<item row="6" column="1">
<widget class="QPushButton" name="loadBtn">
<property name="text">
<string>Run Example</string>
</property>
</widget>
</item>
<item row="3" column="0" colspan="2">
<widget class="QTreeWidget" name="exampleTree">
<attribute name="headerVisible">
<bool>false</bool>
</attribute>
<column>
<property name="text">
<string notr="true">1</string>
</property>
</column>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Qt Library:</string>
</property>
</widget>
</item>
<item row="0" column="0" colspan="2">
<widget class="QLineEdit" name="exampleFilter">
<property name="placeholderText">
<string>Type to filter...</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="QComboBox" name="searchFiles">
<item>
<property name="text">
<string>Title Search</string>
</property>
</item>
<item>
<property name="text">
<string>Content Search</string>
</property>
</item>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="">
<widget class="QWidget" name="layoutWidget">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="loadedFileLabel">

View File

@ -1,10 +1,11 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'exampleLoaderTemplate.ui'
# Form implementation generated from reading ui file 'examples/exampleLoaderTemplate.ui'
#
# Created by: PyQt5 UI code generator 5.12.3
# Created by: PyQt5 UI code generator 5.15.4
#
# WARNING! All changes made in this file will be lost!
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets
@ -19,36 +20,44 @@ class Ui_Form(object):
self.splitter = QtWidgets.QSplitter(Form)
self.splitter.setOrientation(QtCore.Qt.Horizontal)
self.splitter.setObjectName("splitter")
self.widget = QtWidgets.QWidget(self.splitter)
self.widget.setObjectName("widget")
self.gridLayout = QtWidgets.QGridLayout(self.widget)
self.layoutWidget = QtWidgets.QWidget(self.splitter)
self.layoutWidget.setObjectName("layoutWidget")
self.gridLayout = QtWidgets.QGridLayout(self.layoutWidget)
self.gridLayout.setContentsMargins(0, 0, 0, 0)
self.gridLayout.setObjectName("gridLayout")
self.exampleTree = QtWidgets.QTreeWidget(self.widget)
self.exampleTree.setObjectName("exampleTree")
self.exampleTree.headerItem().setText(0, "1")
self.exampleTree.header().setVisible(False)
self.gridLayout.addWidget(self.exampleTree, 0, 0, 1, 2)
self.qtLibCombo = QtWidgets.QComboBox(self.widget)
self.qtLibCombo = QtWidgets.QComboBox(self.layoutWidget)
self.qtLibCombo.setObjectName("qtLibCombo")
self.qtLibCombo.addItem("")
self.qtLibCombo.addItem("")
self.qtLibCombo.addItem("")
self.qtLibCombo.addItem("")
self.qtLibCombo.addItem("")
self.gridLayout.addWidget(self.qtLibCombo, 1, 1, 1, 1)
self.label = QtWidgets.QLabel(self.widget)
self.label.setObjectName("label")
self.gridLayout.addWidget(self.label, 1, 0, 1, 1)
self.loadBtn = QtWidgets.QPushButton(self.widget)
self.gridLayout.addWidget(self.qtLibCombo, 4, 1, 1, 1)
self.loadBtn = QtWidgets.QPushButton(self.layoutWidget)
self.loadBtn.setObjectName("loadBtn")
self.gridLayout.addWidget(self.loadBtn, 3, 1, 1, 1)
self.widget1 = QtWidgets.QWidget(self.splitter)
self.widget1.setObjectName("widget1")
self.verticalLayout = QtWidgets.QVBoxLayout(self.widget1)
self.gridLayout.addWidget(self.loadBtn, 6, 1, 1, 1)
self.exampleTree = QtWidgets.QTreeWidget(self.layoutWidget)
self.exampleTree.setObjectName("exampleTree")
self.exampleTree.headerItem().setText(0, "1")
self.exampleTree.header().setVisible(False)
self.gridLayout.addWidget(self.exampleTree, 3, 0, 1, 2)
self.label = QtWidgets.QLabel(self.layoutWidget)
self.label.setObjectName("label")
self.gridLayout.addWidget(self.label, 4, 0, 1, 1)
self.exampleFilter = QtWidgets.QLineEdit(self.layoutWidget)
self.exampleFilter.setObjectName("exampleFilter")
self.gridLayout.addWidget(self.exampleFilter, 0, 0, 1, 2)
self.searchFiles = QtWidgets.QComboBox(self.layoutWidget)
self.searchFiles.setObjectName("searchFiles")
self.searchFiles.addItem("")
self.searchFiles.addItem("")
self.gridLayout.addWidget(self.searchFiles, 1, 0, 1, 2)
self.layoutWidget1 = QtWidgets.QWidget(self.splitter)
self.layoutWidget1.setObjectName("layoutWidget1")
self.verticalLayout = QtWidgets.QVBoxLayout(self.layoutWidget1)
self.verticalLayout.setContentsMargins(0, 0, 0, 0)
self.verticalLayout.setObjectName("verticalLayout")
self.loadedFileLabel = QtWidgets.QLabel(self.widget1)
self.loadedFileLabel = QtWidgets.QLabel(self.layoutWidget1)
font = QtGui.QFont()
font.setBold(True)
self.loadedFileLabel.setFont(font)
@ -56,13 +65,13 @@ class Ui_Form(object):
self.loadedFileLabel.setAlignment(QtCore.Qt.AlignCenter)
self.loadedFileLabel.setObjectName("loadedFileLabel")
self.verticalLayout.addWidget(self.loadedFileLabel)
self.codeView = QtWidgets.QPlainTextEdit(self.widget1)
self.codeView = QtWidgets.QPlainTextEdit(self.layoutWidget1)
font = QtGui.QFont()
font.setFamily("Courier New")
self.codeView.setFont(font)
self.codeView.setObjectName("codeView")
self.verticalLayout.addWidget(self.codeView)
self.gridLayout_2.addWidget(self.splitter, 0, 0, 1, 1)
self.gridLayout_2.addWidget(self.splitter, 1, 0, 1, 1)
self.retranslateUi(Form)
QtCore.QMetaObject.connectSlotsByName(Form)
@ -75,5 +84,8 @@ class Ui_Form(object):
self.qtLibCombo.setItemText(2, _translate("Form", "PySide2"))
self.qtLibCombo.setItemText(3, _translate("Form", "PySide6"))
self.qtLibCombo.setItemText(4, _translate("Form", "PyQt6"))
self.label.setText(_translate("Form", "Qt Library:"))
self.loadBtn.setText(_translate("Form", "Run Example"))
self.label.setText(_translate("Form", "Qt Library:"))
self.exampleFilter.setPlaceholderText(_translate("Form", "Type to filter..."))
self.searchFiles.setItemText(0, _translate("Form", "Title Search"))
self.searchFiles.setItemText(1, _translate("Form", "Content Search"))

View File

@ -1,6 +1,6 @@
# Form implementation generated from reading ui file 'examples/exampleLoaderTemplate.ui'
#
# Created by: PyQt6 UI code generator 6.1.0
# Created by: PyQt6 UI code generator 6.1.1
#
# WARNING: Any manual changes made to this file will be lost when pyuic6 is
# run again. Do not edit this file unless you know what you are doing.
@ -18,36 +18,44 @@ class Ui_Form(object):
self.splitter = QtWidgets.QSplitter(Form)
self.splitter.setOrientation(QtCore.Qt.Orientation.Horizontal)
self.splitter.setObjectName("splitter")
self.widget = QtWidgets.QWidget(self.splitter)
self.widget.setObjectName("widget")
self.gridLayout = QtWidgets.QGridLayout(self.widget)
self.layoutWidget = QtWidgets.QWidget(self.splitter)
self.layoutWidget.setObjectName("layoutWidget")
self.gridLayout = QtWidgets.QGridLayout(self.layoutWidget)
self.gridLayout.setContentsMargins(0, 0, 0, 0)
self.gridLayout.setObjectName("gridLayout")
self.exampleTree = QtWidgets.QTreeWidget(self.widget)
self.exampleTree.setObjectName("exampleTree")
self.exampleTree.headerItem().setText(0, "1")
self.exampleTree.header().setVisible(False)
self.gridLayout.addWidget(self.exampleTree, 0, 0, 1, 2)
self.qtLibCombo = QtWidgets.QComboBox(self.widget)
self.qtLibCombo = QtWidgets.QComboBox(self.layoutWidget)
self.qtLibCombo.setObjectName("qtLibCombo")
self.qtLibCombo.addItem("")
self.qtLibCombo.addItem("")
self.qtLibCombo.addItem("")
self.qtLibCombo.addItem("")
self.qtLibCombo.addItem("")
self.gridLayout.addWidget(self.qtLibCombo, 1, 1, 1, 1)
self.label = QtWidgets.QLabel(self.widget)
self.label.setObjectName("label")
self.gridLayout.addWidget(self.label, 1, 0, 1, 1)
self.loadBtn = QtWidgets.QPushButton(self.widget)
self.gridLayout.addWidget(self.qtLibCombo, 4, 1, 1, 1)
self.loadBtn = QtWidgets.QPushButton(self.layoutWidget)
self.loadBtn.setObjectName("loadBtn")
self.gridLayout.addWidget(self.loadBtn, 3, 1, 1, 1)
self.widget1 = QtWidgets.QWidget(self.splitter)
self.widget1.setObjectName("widget1")
self.verticalLayout = QtWidgets.QVBoxLayout(self.widget1)
self.gridLayout.addWidget(self.loadBtn, 6, 1, 1, 1)
self.exampleTree = QtWidgets.QTreeWidget(self.layoutWidget)
self.exampleTree.setObjectName("exampleTree")
self.exampleTree.headerItem().setText(0, "1")
self.exampleTree.header().setVisible(False)
self.gridLayout.addWidget(self.exampleTree, 3, 0, 1, 2)
self.label = QtWidgets.QLabel(self.layoutWidget)
self.label.setObjectName("label")
self.gridLayout.addWidget(self.label, 4, 0, 1, 1)
self.exampleFilter = QtWidgets.QLineEdit(self.layoutWidget)
self.exampleFilter.setObjectName("exampleFilter")
self.gridLayout.addWidget(self.exampleFilter, 0, 0, 1, 2)
self.searchFiles = QtWidgets.QComboBox(self.layoutWidget)
self.searchFiles.setObjectName("searchFiles")
self.searchFiles.addItem("")
self.searchFiles.addItem("")
self.gridLayout.addWidget(self.searchFiles, 1, 0, 1, 2)
self.layoutWidget1 = QtWidgets.QWidget(self.splitter)
self.layoutWidget1.setObjectName("layoutWidget1")
self.verticalLayout = QtWidgets.QVBoxLayout(self.layoutWidget1)
self.verticalLayout.setContentsMargins(0, 0, 0, 0)
self.verticalLayout.setObjectName("verticalLayout")
self.loadedFileLabel = QtWidgets.QLabel(self.widget1)
self.loadedFileLabel = QtWidgets.QLabel(self.layoutWidget1)
font = QtGui.QFont()
font.setBold(True)
self.loadedFileLabel.setFont(font)
@ -55,13 +63,13 @@ class Ui_Form(object):
self.loadedFileLabel.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
self.loadedFileLabel.setObjectName("loadedFileLabel")
self.verticalLayout.addWidget(self.loadedFileLabel)
self.codeView = QtWidgets.QPlainTextEdit(self.widget1)
self.codeView = QtWidgets.QPlainTextEdit(self.layoutWidget1)
font = QtGui.QFont()
font.setFamily("Courier New")
self.codeView.setFont(font)
self.codeView.setObjectName("codeView")
self.verticalLayout.addWidget(self.codeView)
self.gridLayout_2.addWidget(self.splitter, 0, 0, 1, 1)
self.gridLayout_2.addWidget(self.splitter, 1, 0, 1, 1)
self.retranslateUi(Form)
QtCore.QMetaObject.connectSlotsByName(Form)
@ -74,5 +82,8 @@ class Ui_Form(object):
self.qtLibCombo.setItemText(2, _translate("Form", "PySide2"))
self.qtLibCombo.setItemText(3, _translate("Form", "PySide6"))
self.qtLibCombo.setItemText(4, _translate("Form", "PyQt6"))
self.label.setText(_translate("Form", "Qt Library:"))
self.loadBtn.setText(_translate("Form", "Run Example"))
self.label.setText(_translate("Form", "Qt Library:"))
self.exampleFilter.setPlaceholderText(_translate("Form", "Type to filter..."))
self.searchFiles.setItemText(0, _translate("Form", "Title Search"))
self.searchFiles.setItemText(1, _translate("Form", "Content Search"))

View File

@ -1,79 +1,120 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'exampleLoaderTemplate.ui',
# licensing of 'exampleLoaderTemplate.ui' applies.
#
# Created: Mon Feb 22 18:33:36 2021
# by: pyside2-uic running on PySide2 5.12.6
#
# WARNING! All changes made in this file will be lost!
################################################################################
## Form generated from reading UI file 'exampleLoaderTemplate.ui'
##
## Created by: Qt User Interface Compiler version 5.15.2
##
## WARNING! All changes made in this file will be lost when recompiling UI file!
################################################################################
from PySide2.QtCore import *
from PySide2.QtGui import *
from PySide2.QtWidgets import *
from PySide2 import QtCore, QtGui, QtWidgets
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName("Form")
if not Form.objectName():
Form.setObjectName(u"Form")
Form.resize(846, 552)
self.gridLayout_2 = QtWidgets.QGridLayout(Form)
self.gridLayout_2.setObjectName("gridLayout_2")
self.splitter = QtWidgets.QSplitter(Form)
self.splitter.setOrientation(QtCore.Qt.Horizontal)
self.splitter.setObjectName("splitter")
self.widget = QtWidgets.QWidget(self.splitter)
self.widget.setObjectName("widget")
self.gridLayout = QtWidgets.QGridLayout(self.widget)
self.gridLayout_2 = QGridLayout(Form)
self.gridLayout_2.setObjectName(u"gridLayout_2")
self.splitter = QSplitter(Form)
self.splitter.setObjectName(u"splitter")
self.splitter.setOrientation(Qt.Horizontal)
self.layoutWidget = QWidget(self.splitter)
self.layoutWidget.setObjectName(u"layoutWidget")
self.gridLayout = QGridLayout(self.layoutWidget)
self.gridLayout.setObjectName(u"gridLayout")
self.gridLayout.setContentsMargins(0, 0, 0, 0)
self.gridLayout.setObjectName("gridLayout")
self.exampleTree = QtWidgets.QTreeWidget(self.widget)
self.exampleTree.setObjectName("exampleTree")
self.exampleTree.headerItem().setText(0, "1")
self.qtLibCombo = QComboBox(self.layoutWidget)
self.qtLibCombo.addItem("")
self.qtLibCombo.addItem("")
self.qtLibCombo.addItem("")
self.qtLibCombo.addItem("")
self.qtLibCombo.addItem("")
self.qtLibCombo.setObjectName(u"qtLibCombo")
self.gridLayout.addWidget(self.qtLibCombo, 4, 1, 1, 1)
self.loadBtn = QPushButton(self.layoutWidget)
self.loadBtn.setObjectName(u"loadBtn")
self.gridLayout.addWidget(self.loadBtn, 6, 1, 1, 1)
self.exampleTree = QTreeWidget(self.layoutWidget)
__qtreewidgetitem = QTreeWidgetItem()
__qtreewidgetitem.setText(0, u"1");
self.exampleTree.setHeaderItem(__qtreewidgetitem)
self.exampleTree.setObjectName(u"exampleTree")
self.exampleTree.header().setVisible(False)
self.gridLayout.addWidget(self.exampleTree, 0, 0, 1, 2)
self.qtLibCombo = QtWidgets.QComboBox(self.widget)
self.qtLibCombo.setObjectName("qtLibCombo")
self.qtLibCombo.addItem("")
self.qtLibCombo.addItem("")
self.qtLibCombo.addItem("")
self.qtLibCombo.addItem("")
self.qtLibCombo.addItem("")
self.gridLayout.addWidget(self.qtLibCombo, 1, 1, 1, 1)
self.label = QtWidgets.QLabel(self.widget)
self.label.setObjectName("label")
self.gridLayout.addWidget(self.label, 1, 0, 1, 1)
self.loadBtn = QtWidgets.QPushButton(self.widget)
self.loadBtn.setObjectName("loadBtn")
self.gridLayout.addWidget(self.loadBtn, 3, 1, 1, 1)
self.widget1 = QtWidgets.QWidget(self.splitter)
self.widget1.setObjectName("widget1")
self.verticalLayout = QtWidgets.QVBoxLayout(self.widget1)
self.gridLayout.addWidget(self.exampleTree, 3, 0, 1, 2)
self.label = QLabel(self.layoutWidget)
self.label.setObjectName(u"label")
self.gridLayout.addWidget(self.label, 4, 0, 1, 1)
self.exampleFilter = QLineEdit(self.layoutWidget)
self.exampleFilter.setObjectName(u"exampleFilter")
self.gridLayout.addWidget(self.exampleFilter, 0, 0, 1, 2)
self.searchFiles = QComboBox(self.layoutWidget)
self.searchFiles.addItem("")
self.searchFiles.addItem("")
self.searchFiles.setObjectName(u"searchFiles")
self.gridLayout.addWidget(self.searchFiles, 1, 0, 1, 2)
self.splitter.addWidget(self.layoutWidget)
self.layoutWidget1 = QWidget(self.splitter)
self.layoutWidget1.setObjectName(u"layoutWidget1")
self.verticalLayout = QVBoxLayout(self.layoutWidget1)
self.verticalLayout.setObjectName(u"verticalLayout")
self.verticalLayout.setContentsMargins(0, 0, 0, 0)
self.verticalLayout.setObjectName("verticalLayout")
self.loadedFileLabel = QtWidgets.QLabel(self.widget1)
font = QtGui.QFont()
self.loadedFileLabel = QLabel(self.layoutWidget1)
self.loadedFileLabel.setObjectName(u"loadedFileLabel")
font = QFont()
font.setBold(True)
self.loadedFileLabel.setFont(font)
self.loadedFileLabel.setText("")
self.loadedFileLabel.setAlignment(QtCore.Qt.AlignCenter)
self.loadedFileLabel.setObjectName("loadedFileLabel")
self.loadedFileLabel.setAlignment(Qt.AlignCenter)
self.verticalLayout.addWidget(self.loadedFileLabel)
self.codeView = QtWidgets.QPlainTextEdit(self.widget1)
font = QtGui.QFont()
font.setFamily("Courier New")
self.codeView.setFont(font)
self.codeView.setObjectName("codeView")
self.codeView = QPlainTextEdit(self.layoutWidget1)
self.codeView.setObjectName(u"codeView")
font1 = QFont()
font1.setFamily(u"Courier New")
self.codeView.setFont(font1)
self.verticalLayout.addWidget(self.codeView)
self.gridLayout_2.addWidget(self.splitter, 0, 0, 1, 1)
self.splitter.addWidget(self.layoutWidget1)
self.gridLayout_2.addWidget(self.splitter, 1, 0, 1, 1)
self.retranslateUi(Form)
QtCore.QMetaObject.connectSlotsByName(Form)
QMetaObject.connectSlotsByName(Form)
# setupUi
def retranslateUi(self, Form):
Form.setWindowTitle(QtWidgets.QApplication.translate("Form", "PyQtGraph", None, -1))
self.qtLibCombo.setItemText(0, QtWidgets.QApplication.translate("Form", "default", None, -1))
self.qtLibCombo.setItemText(1, QtWidgets.QApplication.translate("Form", "PyQt5", None, -1))
self.qtLibCombo.setItemText(2, QtWidgets.QApplication.translate("Form", "PySide2", None, -1))
self.qtLibCombo.setItemText(3, QtWidgets.QApplication.translate("Form", "PySide6", None, -1))
self.qtLibCombo.setItemText(4, QtWidgets.QApplication.translate("Form", "PyQt6", None, -1))
self.label.setText(QtWidgets.QApplication.translate("Form", "Qt Library:", None, -1))
self.loadBtn.setText(QtWidgets.QApplication.translate("Form", "Run Example", None, -1))
Form.setWindowTitle(QCoreApplication.translate("Form", u"PyQtGraph", None))
self.qtLibCombo.setItemText(0, QCoreApplication.translate("Form", u"default", None))
self.qtLibCombo.setItemText(1, QCoreApplication.translate("Form", u"PyQt5", None))
self.qtLibCombo.setItemText(2, QCoreApplication.translate("Form", u"PySide2", None))
self.qtLibCombo.setItemText(3, QCoreApplication.translate("Form", u"PySide6", None))
self.qtLibCombo.setItemText(4, QCoreApplication.translate("Form", u"PyQt6", None))
self.loadBtn.setText(QCoreApplication.translate("Form", u"Run Example", None))
self.label.setText(QCoreApplication.translate("Form", u"Qt Library:", None))
self.exampleFilter.setPlaceholderText(QCoreApplication.translate("Form", u"Type to filter...", None))
self.searchFiles.setItemText(0, QCoreApplication.translate("Form", u"Title Search", None))
self.searchFiles.setItemText(1, QCoreApplication.translate("Form", u"Content Search", None))
self.loadedFileLabel.setText("")
# retranslateUi

View File

@ -3,14 +3,14 @@
################################################################################
## Form generated from reading UI file 'exampleLoaderTemplate.ui'
##
## Created by: Qt User Interface Compiler version 6.1.0
## Created by: Qt User Interface Compiler version 6.1.1
##
## WARNING! All changes made in this file will be lost when recompiling UI file!
################################################################################
from PySide6.QtCore import *
from PySide6.QtGui import *
from PySide6.QtWidgets import *
from PySide6.QtCore import * # type: ignore
from PySide6.QtGui import * # type: ignore
from PySide6.QtWidgets import * # type: ignore
class Ui_Form(object):
@ -23,21 +23,12 @@ class Ui_Form(object):
self.splitter = QSplitter(Form)
self.splitter.setObjectName(u"splitter")
self.splitter.setOrientation(Qt.Horizontal)
self.widget = QWidget(self.splitter)
self.widget.setObjectName(u"widget")
self.gridLayout = QGridLayout(self.widget)
self.layoutWidget = QWidget(self.splitter)
self.layoutWidget.setObjectName(u"layoutWidget")
self.gridLayout = QGridLayout(self.layoutWidget)
self.gridLayout.setObjectName(u"gridLayout")
self.gridLayout.setContentsMargins(0, 0, 0, 0)
self.exampleTree = QTreeWidget(self.widget)
__qtreewidgetitem = QTreeWidgetItem()
__qtreewidgetitem.setText(0, u"1");
self.exampleTree.setHeaderItem(__qtreewidgetitem)
self.exampleTree.setObjectName(u"exampleTree")
self.exampleTree.header().setVisible(False)
self.gridLayout.addWidget(self.exampleTree, 0, 0, 1, 2)
self.qtLibCombo = QComboBox(self.widget)
self.qtLibCombo = QComboBox(self.layoutWidget)
self.qtLibCombo.addItem("")
self.qtLibCombo.addItem("")
self.qtLibCombo.addItem("")
@ -45,25 +36,46 @@ class Ui_Form(object):
self.qtLibCombo.addItem("")
self.qtLibCombo.setObjectName(u"qtLibCombo")
self.gridLayout.addWidget(self.qtLibCombo, 1, 1, 1, 1)
self.gridLayout.addWidget(self.qtLibCombo, 4, 1, 1, 1)
self.label = QLabel(self.widget)
self.label.setObjectName(u"label")
self.gridLayout.addWidget(self.label, 1, 0, 1, 1)
self.loadBtn = QPushButton(self.widget)
self.loadBtn = QPushButton(self.layoutWidget)
self.loadBtn.setObjectName(u"loadBtn")
self.gridLayout.addWidget(self.loadBtn, 3, 1, 1, 1)
self.gridLayout.addWidget(self.loadBtn, 6, 1, 1, 1)
self.splitter.addWidget(self.widget)
self.widget1 = QWidget(self.splitter)
self.widget1.setObjectName(u"widget1")
self.verticalLayout = QVBoxLayout(self.widget1)
self.exampleTree = QTreeWidget(self.layoutWidget)
__qtreewidgetitem = QTreeWidgetItem()
__qtreewidgetitem.setText(0, u"1");
self.exampleTree.setHeaderItem(__qtreewidgetitem)
self.exampleTree.setObjectName(u"exampleTree")
self.exampleTree.header().setVisible(False)
self.gridLayout.addWidget(self.exampleTree, 3, 0, 1, 2)
self.label = QLabel(self.layoutWidget)
self.label.setObjectName(u"label")
self.gridLayout.addWidget(self.label, 4, 0, 1, 1)
self.exampleFilter = QLineEdit(self.layoutWidget)
self.exampleFilter.setObjectName(u"exampleFilter")
self.gridLayout.addWidget(self.exampleFilter, 0, 0, 1, 2)
self.searchFiles = QComboBox(self.layoutWidget)
self.searchFiles.addItem("")
self.searchFiles.addItem("")
self.searchFiles.setObjectName(u"searchFiles")
self.gridLayout.addWidget(self.searchFiles, 1, 0, 1, 2)
self.splitter.addWidget(self.layoutWidget)
self.layoutWidget1 = QWidget(self.splitter)
self.layoutWidget1.setObjectName(u"layoutWidget1")
self.verticalLayout = QVBoxLayout(self.layoutWidget1)
self.verticalLayout.setObjectName(u"verticalLayout")
self.verticalLayout.setContentsMargins(0, 0, 0, 0)
self.loadedFileLabel = QLabel(self.widget1)
self.loadedFileLabel = QLabel(self.layoutWidget1)
self.loadedFileLabel.setObjectName(u"loadedFileLabel")
font = QFont()
font.setBold(True)
@ -72,7 +84,7 @@ class Ui_Form(object):
self.verticalLayout.addWidget(self.loadedFileLabel)
self.codeView = QPlainTextEdit(self.widget1)
self.codeView = QPlainTextEdit(self.layoutWidget1)
self.codeView.setObjectName(u"codeView")
font1 = QFont()
font1.setFamilies([u"Courier New"])
@ -80,9 +92,9 @@ class Ui_Form(object):
self.verticalLayout.addWidget(self.codeView)
self.splitter.addWidget(self.widget1)
self.splitter.addWidget(self.layoutWidget1)
self.gridLayout_2.addWidget(self.splitter, 0, 0, 1, 1)
self.gridLayout_2.addWidget(self.splitter, 1, 0, 1, 1)
self.retranslateUi(Form)
@ -98,8 +110,11 @@ class Ui_Form(object):
self.qtLibCombo.setItemText(3, QCoreApplication.translate("Form", u"PySide6", None))
self.qtLibCombo.setItemText(4, QCoreApplication.translate("Form", u"PyQt6", None))
self.label.setText(QCoreApplication.translate("Form", u"Qt Library:", None))
self.loadBtn.setText(QCoreApplication.translate("Form", u"Run Example", None))
self.label.setText(QCoreApplication.translate("Form", u"Qt Library:", None))
self.exampleFilter.setPlaceholderText(QCoreApplication.translate("Form", u"Type to filter...", None))
self.searchFiles.setItemText(0, QCoreApplication.translate("Form", u"Title Search", None))
self.searchFiles.setItemText(1, QCoreApplication.translate("Form", u"Content Search", None))
self.loadedFileLabel.setText("")
# retranslateUi

View File

@ -32,7 +32,7 @@ def buildFileList(examples, files=None):
path = os.path.abspath(os.path.dirname(__file__))
files = [("Example App", "RunExampleApp.py")]
for ex in [utils.examples, utils.others]:
for ex in [utils.examples_, utils.others]:
files = buildFileList(ex, files)
files = sorted(set(files))
frontends = {

View File

@ -1,8 +1,8 @@
from collections import OrderedDict
from argparse import Namespace
examples = OrderedDict([
# Avoid clash with module name
examples_ = OrderedDict([
('Command-line usage', 'CLIexample.py'),
('Basic Plotting', Namespace(filename='Plotting.py', recommended=True)),
('ImageView', 'ImageView.py'),

View File

View File

View File

View File

@ -12,7 +12,7 @@ This module exists to smooth out some of the differences between PySide and PyQt
import os, sys, re, time, subprocess, warnings
from .python2_3 import asUnicode
from ..python2_3 import asUnicode
PYSIDE = 'PySide'
PYSIDE2 = 'PySide2'
@ -130,10 +130,29 @@ def _loadUiType(uiFile):
return form_class, base_class
# For historical reasons, pyqtgraph maintains a Qt4-ish interface back when
# there wasn't a QtWidgets module. This _was_ done by monkey-patching all of
# QtWidgets into the QtGui module. This monkey-patching modifies QtGui at a
# global level.
# To avoid this, we now maintain a local "mirror" of QtCore, QtGui and QtWidgets.
# Thus, when monkey-patching happens later on in this file, they will only affect
# the local modules and not the global modules.
def _copy_attrs(src, dst):
for o in dir(src):
if not hasattr(dst, o):
setattr(dst, o, getattr(src, o))
from . import QtCore, QtGui, QtWidgets
if QT_LIB == PYQT5:
# We're using PyQt5 which has a different structure so we're going to use a shim to
# recreate the Qt4 structure for Qt5
from PyQt5 import QtGui, QtCore, QtWidgets, sip, uic
import PyQt5.QtCore, PyQt5.QtGui, PyQt5.QtWidgets
_copy_attrs(PyQt5.QtCore, QtCore)
_copy_attrs(PyQt5.QtGui, QtGui)
_copy_attrs(PyQt5.QtWidgets, QtWidgets)
from PyQt5 import sip, uic
try:
from PyQt5 import QtSvg
@ -147,7 +166,12 @@ if QT_LIB == PYQT5:
VERSION_INFO = 'PyQt5 ' + QtCore.PYQT_VERSION_STR + ' Qt ' + QtCore.QT_VERSION_STR
elif QT_LIB == PYQT6:
from PyQt6 import QtGui, QtCore, QtWidgets, sip, uic
import PyQt6.QtCore, PyQt6.QtGui, PyQt6.QtWidgets
_copy_attrs(PyQt6.QtCore, QtCore)
_copy_attrs(PyQt6.QtGui, QtGui)
_copy_attrs(PyQt6.QtWidgets, QtWidgets)
from PyQt6 import sip, uic
try:
from PyQt6 import QtSvg
@ -165,7 +189,10 @@ elif QT_LIB == PYQT6:
VERSION_INFO = 'PyQt6 ' + QtCore.PYQT_VERSION_STR + ' Qt ' + QtCore.QT_VERSION_STR
elif QT_LIB == PYSIDE2:
from PySide2 import QtGui, QtCore, QtWidgets
import PySide2.QtCore, PySide2.QtGui, PySide2.QtWidgets
_copy_attrs(PySide2.QtCore, QtCore)
_copy_attrs(PySide2.QtGui, QtGui)
_copy_attrs(PySide2.QtWidgets, QtWidgets)
try:
from PySide2 import QtSvg
@ -182,7 +209,10 @@ elif QT_LIB == PYSIDE2:
VERSION_INFO = 'PySide2 ' + PySide2.__version__ + ' Qt ' + QtCore.__version__
elif QT_LIB == PYSIDE6:
from PySide6 import QtGui, QtCore, QtWidgets
import PySide6.QtCore, PySide6.QtGui, PySide6.QtWidgets
_copy_attrs(PySide6.QtCore, QtCore)
_copy_attrs(PySide6.QtGui, QtGui)
_copy_attrs(PySide6.QtWidgets, QtWidgets)
try:
from PySide6 import QtSvg

View File

@ -1,6 +1,8 @@
# -*- coding: utf-8 -*-
from .Qt import QtCore, QtGui
__all__ = ['ThreadsafeTimer']
class ThreadsafeTimer(QtCore.QObject):
"""
Thread-safe replacement for QTimer.

View File

@ -10,7 +10,7 @@ __version__ = '0.12.1'
## 'Qt' is a local module; it is intended mainly to cover up the differences
## between PyQt4 and PySide.
from .Qt import QtGui, mkQApp
from .Qt import QtCore, QtGui, mkQApp
from .Qt import exec_ as exec
## not really safe--If we accidentally create another QApplication, the process hangs (and it is very difficult to trace the cause)
@ -280,6 +280,15 @@ from .ptime import time
from .Qt import isQObjectAlive
from .ThreadsafeTimer import *
# indirect imports used within library
from .GraphicsScene import GraphicsScene
from .python2_3 import asUnicode
from .util.cupy_helper import getCupy
# indirect imports known to be used outside of the library
from .metaarray import MetaArray
from .ordereddict import OrderedDict
##############################################################
## PyQt and PySide both are prone to crashing on exit.

View File

@ -5,6 +5,8 @@ from os import path, listdir
from collections.abc import Callable, Sequence
import warnings
__all__ = ['ColorMap']
_mapCache = {}
def listMaps(source=None):
@ -102,7 +104,6 @@ def _getFromFile(name):
else:
csv_mode = False
for line in fh:
name = None
line = line.strip()
if len(line) == 0: continue # empty line
if line[0] == ';': continue # comment
@ -149,7 +150,7 @@ def getFromMatplotlib(name):
col_map = mpl_plt.get_cmap(name)
if hasattr(col_map, '_segmentdata'): # handle LinearSegmentedColormap
data = col_map._segmentdata
if ('red' in data) and isinstance(data['red'], Sequence):
if ('red' in data) and isinstance(data['red'], (Sequence, np.ndarray)):
positions = set() # super-set of handle positions in individual channels
for key in ['red','green','blue']:
for tup in data[key]:
@ -598,32 +599,45 @@ class ColorMap(object):
pen.setCosmetic(True)
return pen
def getColors(self, mode=None):
"""Returns a list of all color stops, converted to the specified mode.
If `mode` is None, no conversion is performed.
def getColors(self, mode=BYTE):
"""
Returns a list of the colors associated with the stops of the color map.
The parameter `mode` can be one of
- `ColorMap.BYTE` or 'byte' to return colors as RGBA tuples in byte format (0 to 255)
- `ColorMap.FLOAT` or 'float' to return colors as RGBA tuples in float format (0.0 to 1.0)
- `ColorMap.QCOLOR` or 'qcolor' to return a list of QColors
The default is byte format.
"""
stops, color = self.getStops(mode=mode)
return color
def getStops(self, mode=BYTE):
"""
Returns a tuple (stops, colors) containing a list of all stops (ranging 0.0 to 1.0)
and a list of the associated colors.
The parameter `mode` can be one of
- `ColorMap.BYTE` or 'byte' to return colors as RGBA tuples in byte format (0 to 255)
- `ColorMap.FLOAT` or 'float' to return colors as RGBA tuples in float format (0.0 to 1.0)
- `ColorMap.QCOLOR` or 'qcolor' to return a list of QColors
The default is byte format.
"""
if isinstance(mode, str):
mode = self.enumMap[mode.lower()]
color = self.color
if mode in [self.BYTE, self.QCOLOR] and color.dtype.kind == 'f':
color = (color * 255).astype(np.ubyte)
elif mode == self.FLOAT and color.dtype.kind != 'f':
color = color.astype(float) / 255.
if mode == self.QCOLOR:
color = [QtGui.QColor(*x) for x in color]
return color
def getStops(self, mode):
## Get fully-expanded set of RGBA stops in either float or byte mode.
if mode not in self.stopsCache:
color = self.color
if mode == self.BYTE and color.dtype.kind == 'f':
color = (color*255).astype(np.ubyte)
elif mode == self.FLOAT and color.dtype.kind != 'f':
color = color.astype(float) / 255.
elif mode == self.QCOLOR:
if color.dtype.kind == 'f':
color = (color*255).astype(np.ubyte)
color = [QtGui.QColor(*x) for x in color]
self.stopsCache[mode] = (self.pos, color)
return self.stopsCache[mode]

View File

@ -0,0 +1,121 @@
Creative Commons Legal Code
CC0 1.0 Universal
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
HEREUNDER.
Statement of Purpose
The laws of most jurisdictions throughout the world automatically confer
exclusive Copyright and Related Rights (defined below) upon the creator
and subsequent owner(s) (each and all, an "owner") of an original work of
authorship and/or a database (each, a "Work").
Certain owners wish to permanently relinquish those rights to a Work for
the purpose of contributing to a commons of creative, cultural and
scientific works ("Commons") that the public can reliably and without fear
of later claims of infringement build upon, modify, incorporate in other
works, reuse and redistribute as freely as possible in any form whatsoever
and for any purposes, including without limitation commercial purposes.
These owners may contribute to the Commons to promote the ideal of a free
culture and the further production of creative, cultural and scientific
works, or to gain reputation or greater distribution for their Work in
part through the use and efforts of others.
For these and/or other purposes and motivations, and without any
expectation of additional consideration or compensation, the person
associating CC0 with a Work (the "Affirmer"), to the extent that he or she
is an owner of Copyright and Related Rights in the Work, voluntarily
elects to apply CC0 to the Work and publicly distribute the Work under its
terms, with knowledge of his or her Copyright and Related Rights in the
Work and the meaning and intended legal effect of CC0 on those rights.
1. Copyright and Related Rights. A Work made available under CC0 may be
protected by copyright and related or neighboring rights ("Copyright and
Related Rights"). Copyright and Related Rights include, but are not
limited to, the following:
i. the right to reproduce, adapt, distribute, perform, display,
communicate, and translate a Work;
ii. moral rights retained by the original author(s) and/or performer(s);
iii. publicity and privacy rights pertaining to a person's image or
likeness depicted in a Work;
iv. rights protecting against unfair competition in regards to a Work,
subject to the limitations in paragraph 4(a), below;
v. rights protecting the extraction, dissemination, use and reuse of data
in a Work;
vi. database rights (such as those arising under Directive 96/9/EC of the
European Parliament and of the Council of 11 March 1996 on the legal
protection of databases, and under any national implementation
thereof, including any amended or successor version of such
directive); and
vii. other similar, equivalent or corresponding rights throughout the
world based on applicable law or treaty, and any national
implementations thereof.
2. Waiver. To the greatest extent permitted by, but not in contravention
of, applicable law, Affirmer hereby overtly, fully, permanently,
irrevocably and unconditionally waives, abandons, and surrenders all of
Affirmer's Copyright and Related Rights and associated claims and causes
of action, whether now known or unknown (including existing as well as
future claims and causes of action), in the Work (i) in all territories
worldwide, (ii) for the maximum duration provided by applicable law or
treaty (including future time extensions), (iii) in any current or future
medium and for any number of copies, and (iv) for any purpose whatsoever,
including without limitation commercial, advertising or promotional
purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
member of the public at large and to the detriment of Affirmer's heirs and
successors, fully intending that such Waiver shall not be subject to
revocation, rescission, cancellation, termination, or any other legal or
equitable action to disrupt the quiet enjoyment of the Work by the public
as contemplated by Affirmer's express Statement of Purpose.
3. Public License Fallback. Should any part of the Waiver for any reason
be judged legally invalid or ineffective under applicable law, then the
Waiver shall be preserved to the maximum extent permitted taking into
account Affirmer's express Statement of Purpose. In addition, to the
extent the Waiver is so judged Affirmer hereby grants to each affected
person a royalty-free, non transferable, non sublicensable, non exclusive,
irrevocable and unconditional license to exercise Affirmer's Copyright and
Related Rights in the Work (i) in all territories worldwide, (ii) for the
maximum duration provided by applicable law or treaty (including future
time extensions), (iii) in any current or future medium and for any number
of copies, and (iv) for any purpose whatsoever, including without
limitation commercial, advertising or promotional purposes (the
"License"). The License shall be deemed effective as of the date CC0 was
applied by Affirmer to the Work. Should any part of the License for any
reason be judged legally invalid or ineffective under applicable law, such
partial invalidity or ineffectiveness shall not invalidate the remainder
of the License, and in such case Affirmer hereby affirms that he or she
will not (i) exercise any of his or her remaining Copyright and Related
Rights in the Work or (ii) assert any associated claims and causes of
action with respect to the Work, in either case contrary to Affirmer's
express Statement of Purpose.
4. Limitations and Disclaimers.
a. No trademark or patent rights held by Affirmer are waived, abandoned,
surrendered, licensed or otherwise affected by this document.
b. Affirmer offers the Work as-is and makes no representations or
warranties of any kind concerning the Work, express, implied,
statutory or otherwise, including without limitation warranties of
title, merchantability, fitness for a particular purpose, non
infringement, or the absence of latent or other defects, accuracy, or
the present or absence of errors, whether or not discoverable, all to
the greatest extent permissible under applicable law.
c. Affirmer disclaims responsibility for clearing rights of other persons
that may apply to the Work or any use thereof, including without
limitation any person's Copyright and Related Rights in the Work.
Further, Affirmer disclaims responsibility for obtaining any necessary
consents, permissions or other rights required for any use of the
Work.
d. Affirmer understands and acknowledges that Creative Commons is not a
party to this document and has no duty or obligation with respect to
this CC0 or use of the Work.

View File

@ -0,0 +1,266 @@
; cividis colormap, optimized with consideration for color vision deficiency
; to enable accurate interpretation of scientific data
;
; Published by Jamie R. Nuñez, Christopher R. Anderton and Ryan S. Renslow
; in PLoS ONE 13(7): e0199239. https://doi.org/10.1371/journal.pone.0199239
; available under Creative Commons CC0 public domain dedication.
;
; You should have received a copy of the CC0 legalcode along with this
; work. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
;
0.000000,0.126200,0.301500
0.000000,0.129200,0.307700
0.000000,0.132100,0.314200
0.000000,0.135000,0.320500
0.000000,0.137900,0.326900
0.000000,0.140800,0.333400
0.000000,0.143700,0.340000
0.000000,0.146500,0.346700
0.000000,0.149200,0.353700
0.000000,0.151900,0.360600
0.000000,0.154600,0.367600
0.000000,0.157400,0.374600
0.000000,0.160100,0.381700
0.000000,0.162900,0.388800
0.000000,0.165700,0.396000
0.000000,0.168500,0.403100
0.000000,0.171400,0.410200
0.000000,0.174300,0.417200
0.000000,0.177300,0.424100
0.000000,0.179800,0.430700
0.000000,0.181700,0.434700
0.000000,0.183400,0.436300
0.000000,0.185200,0.436800
0.000000,0.187200,0.436800
0.000000,0.190100,0.436500
0.000000,0.193000,0.436100
0.000000,0.195800,0.435600
0.000000,0.198700,0.434900
0.000000,0.201500,0.434300
0.000000,0.204400,0.433600
0.000000,0.207300,0.432900
0.005500,0.210100,0.432200
0.023600,0.213000,0.431400
0.041600,0.215800,0.430800
0.057600,0.218700,0.430100
0.071000,0.221500,0.429300
0.082700,0.224400,0.428700
0.093200,0.227200,0.428000
0.103000,0.230000,0.427400
0.112000,0.232900,0.426800
0.120400,0.235700,0.426200
0.128300,0.238500,0.425600
0.135900,0.241400,0.425100
0.143100,0.244200,0.424500
0.150000,0.247000,0.424100
0.156600,0.249800,0.423600
0.163000,0.252600,0.423200
0.169200,0.255500,0.422800
0.175200,0.258300,0.422400
0.181100,0.261100,0.422000
0.186800,0.263900,0.421700
0.192300,0.266700,0.421400
0.197700,0.269500,0.421200
0.203000,0.272300,0.420900
0.208200,0.275100,0.420700
0.213300,0.278000,0.420500
0.218300,0.280800,0.420400
0.223200,0.283600,0.420300
0.228100,0.286400,0.420200
0.232800,0.289200,0.420100
0.237500,0.292000,0.420000
0.242100,0.294800,0.420000
0.246600,0.297600,0.420000
0.251100,0.300400,0.420100
0.255600,0.303200,0.420100
0.259900,0.306000,0.420200
0.264300,0.308800,0.420300
0.268600,0.311600,0.420500
0.272800,0.314400,0.420600
0.277000,0.317200,0.420800
0.281100,0.320000,0.421000
0.285300,0.322800,0.421200
0.289400,0.325600,0.421500
0.293400,0.328400,0.421800
0.297400,0.331200,0.422100
0.301400,0.334000,0.422400
0.305400,0.336800,0.422700
0.309300,0.339600,0.423100
0.313200,0.342400,0.423600
0.317000,0.345300,0.424000
0.320900,0.348100,0.424400
0.324700,0.350900,0.424900
0.328500,0.353700,0.425400
0.332300,0.356500,0.425900
0.336100,0.359300,0.426400
0.339800,0.362200,0.427000
0.343500,0.365000,0.427600
0.347200,0.367800,0.428200
0.350900,0.370600,0.428800
0.354600,0.373400,0.429400
0.358200,0.376300,0.430200
0.361900,0.379100,0.430800
0.365500,0.381900,0.431600
0.369100,0.384800,0.432200
0.372700,0.387600,0.433100
0.376300,0.390400,0.433800
0.379800,0.393300,0.434600
0.383400,0.396100,0.435500
0.386900,0.399000,0.436400
0.390500,0.401800,0.437200
0.394000,0.404700,0.438100
0.397500,0.407500,0.439000
0.401000,0.410400,0.440000
0.404500,0.413200,0.440900
0.408000,0.416100,0.441900
0.411400,0.418900,0.443000
0.414900,0.421800,0.444000
0.418300,0.424700,0.445000
0.421800,0.427500,0.446200
0.425200,0.430400,0.447300
0.428600,0.433300,0.448500
0.432000,0.436200,0.449600
0.435400,0.439000,0.450800
0.438800,0.441900,0.452100
0.442200,0.444800,0.453400
0.445600,0.447700,0.454700
0.448900,0.450600,0.456100
0.452300,0.453500,0.457500
0.455600,0.456400,0.458900
0.458900,0.459300,0.460400
0.462200,0.462200,0.462000
0.465600,0.465100,0.463500
0.468900,0.468000,0.465000
0.472200,0.470900,0.466500
0.475600,0.473800,0.467900
0.479000,0.476700,0.469100
0.482500,0.479700,0.470100
0.486100,0.482600,0.470700
0.489700,0.485600,0.471400
0.493400,0.488600,0.471900
0.497100,0.491500,0.472300
0.500800,0.494500,0.472700
0.504500,0.497500,0.473000
0.508300,0.500500,0.473200
0.512100,0.503500,0.473400
0.515800,0.506500,0.473600
0.519600,0.509500,0.473700
0.523400,0.512500,0.473800
0.527200,0.515500,0.473900
0.531000,0.518600,0.473900
0.534900,0.521600,0.473800
0.538700,0.524600,0.473900
0.542500,0.527700,0.473800
0.546400,0.530700,0.473600
0.550200,0.533800,0.473500
0.554100,0.536800,0.473300
0.557900,0.539900,0.473200
0.561800,0.543000,0.472900
0.565700,0.546100,0.472700
0.569600,0.549100,0.472300
0.573500,0.552200,0.472000
0.577400,0.555300,0.471700
0.581300,0.558400,0.471400
0.585200,0.561500,0.470900
0.589200,0.564600,0.470500
0.593100,0.567800,0.470100
0.597000,0.570900,0.469600
0.601000,0.574000,0.469100
0.605000,0.577200,0.468500
0.608900,0.580300,0.468000
0.612900,0.583500,0.467300
0.616800,0.586600,0.466800
0.620800,0.589800,0.466200
0.624800,0.592900,0.465500
0.628800,0.596100,0.464900
0.632800,0.599300,0.464100
0.636800,0.602500,0.463200
0.640800,0.605700,0.462500
0.644900,0.608900,0.461700
0.648900,0.612100,0.460900
0.652900,0.615300,0.460000
0.657000,0.618500,0.459100
0.661000,0.621700,0.458300
0.665100,0.625000,0.457300
0.669100,0.628200,0.456200
0.673200,0.631500,0.455300
0.677300,0.634700,0.454300
0.681300,0.638000,0.453200
0.685400,0.641200,0.452100
0.689500,0.644500,0.451100
0.693600,0.647800,0.449900
0.697700,0.651100,0.448700
0.701800,0.654400,0.447500
0.706000,0.657700,0.446300
0.710100,0.661000,0.445000
0.714200,0.664300,0.443700
0.718400,0.667600,0.442400
0.722500,0.671000,0.440900
0.726700,0.674300,0.439600
0.730800,0.677600,0.438200
0.735000,0.681000,0.436800
0.739200,0.684400,0.435200
0.743400,0.687700,0.433800
0.747600,0.691100,0.432200
0.751800,0.694500,0.430700
0.756000,0.697900,0.429000
0.760200,0.701300,0.427300
0.764400,0.704700,0.425800
0.768600,0.708100,0.424100
0.772900,0.711500,0.422300
0.777100,0.715000,0.420500
0.781400,0.718400,0.418800
0.785600,0.721800,0.416800
0.789900,0.725300,0.415000
0.794200,0.728800,0.412900
0.798500,0.732200,0.411100
0.802700,0.735700,0.409000
0.807000,0.739200,0.407000
0.811400,0.742700,0.404900
0.815700,0.746200,0.402800
0.820000,0.749700,0.400700
0.824300,0.753200,0.398400
0.828700,0.756800,0.396100
0.833000,0.760300,0.393800
0.837400,0.763900,0.391500
0.841700,0.767400,0.389200
0.846100,0.771000,0.386900
0.850500,0.774500,0.384300
0.854800,0.778100,0.381800
0.859200,0.781700,0.379300
0.863600,0.785300,0.376600
0.868100,0.788900,0.373900
0.872500,0.792600,0.371200
0.876900,0.796200,0.368400
0.881300,0.799800,0.365700
0.885800,0.803500,0.362700
0.890200,0.807100,0.359900
0.894700,0.810800,0.356900
0.899200,0.814500,0.353800
0.903700,0.818200,0.350700
0.908200,0.821900,0.347400
0.912700,0.825600,0.344200
0.917200,0.829300,0.340900
0.921700,0.833000,0.337400
0.926200,0.836700,0.334000
0.930800,0.840500,0.330600
0.935300,0.844200,0.326800
0.939900,0.848000,0.323200
0.944400,0.851800,0.319500
0.949000,0.855600,0.315500
0.953600,0.859300,0.311600
0.958200,0.863200,0.307600
0.962800,0.867000,0.303400
0.967400,0.870800,0.299000
0.972100,0.874600,0.294700
0.976700,0.878500,0.290100
0.981400,0.882300,0.285600
0.986000,0.886200,0.280700
0.990700,0.890100,0.275900
0.995400,0.894000,0.270800
1.000000,0.897900,0.265500
1.000000,0.901800,0.260000
1.000000,0.905700,0.259300
1.000000,0.909400,0.263400
1.000000,0.913100,0.268000
1.000000,0.916900,0.273100
Can't render this file because it has a wrong number of fields in line 11.

View File

@ -0,0 +1,270 @@
; New matplotlib colormaps by Nathaniel J. Smith, Stefan van der Walt,
; and (in the case of viridis) Eric Firing.
;
; This file and the colormaps in it are released under the CC0 license /
; public domain dedication. The creators would appreciate credit if you use or
; redistribute these colormaps, but do not impose any legal restrictions.
;
; To the extent possible under law, the persons who associated CC0 with
; mpl-colormaps have waived all copyright and related or neighboring rights
; to mpl-colormaps.
;
; You should have received a copy of the CC0 legalcode along with this
; work. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
;
0.001462,0.000466,0.013866
0.002267,0.001270,0.018570
0.003299,0.002249,0.024239
0.004547,0.003392,0.030909
0.006006,0.004692,0.038558
0.007676,0.006136,0.046836
0.009561,0.007713,0.055143
0.011663,0.009417,0.063460
0.013995,0.011225,0.071862
0.016561,0.013136,0.080282
0.019373,0.015133,0.088767
0.022447,0.017199,0.097327
0.025793,0.019331,0.105930
0.029432,0.021503,0.114621
0.033385,0.023702,0.123397
0.037668,0.025921,0.132232
0.042253,0.028139,0.141141
0.046915,0.030324,0.150164
0.051644,0.032474,0.159254
0.056449,0.034569,0.168414
0.061340,0.036590,0.177642
0.066331,0.038504,0.186962
0.071429,0.040294,0.196354
0.076637,0.041905,0.205799
0.081962,0.043328,0.215289
0.087411,0.044556,0.224813
0.092990,0.045583,0.234358
0.098702,0.046402,0.243904
0.104551,0.047008,0.253430
0.110536,0.047399,0.262912
0.116656,0.047574,0.272321
0.122908,0.047536,0.281624
0.129285,0.047293,0.290788
0.135778,0.046856,0.299776
0.142378,0.046242,0.308553
0.149073,0.045468,0.317085
0.155850,0.044559,0.325338
0.162689,0.043554,0.333277
0.169575,0.042489,0.340874
0.176493,0.041402,0.348111
0.183429,0.040329,0.354971
0.190367,0.039309,0.361447
0.197297,0.038400,0.367535
0.204209,0.037632,0.373238
0.211095,0.037030,0.378563
0.217949,0.036615,0.383522
0.224763,0.036405,0.388129
0.231538,0.036405,0.392400
0.238273,0.036621,0.396353
0.244967,0.037055,0.400007
0.251620,0.037705,0.403378
0.258234,0.038571,0.406485
0.264810,0.039647,0.409345
0.271347,0.040922,0.411976
0.277850,0.042353,0.414392
0.284321,0.043933,0.416608
0.290763,0.045644,0.418637
0.297178,0.047470,0.420491
0.303568,0.049396,0.422182
0.309935,0.051407,0.423721
0.316282,0.053490,0.425116
0.322610,0.055634,0.426377
0.328921,0.057827,0.427511
0.335217,0.060060,0.428524
0.341500,0.062325,0.429425
0.347771,0.064616,0.430217
0.354032,0.066925,0.430906
0.360284,0.069247,0.431497
0.366529,0.071579,0.431994
0.372768,0.073915,0.432400
0.379001,0.076253,0.432719
0.385228,0.078591,0.432955
0.391453,0.080927,0.433109
0.397674,0.083257,0.433183
0.403894,0.085580,0.433179
0.410113,0.087896,0.433098
0.416331,0.090203,0.432943
0.422549,0.092501,0.432714
0.428768,0.094790,0.432412
0.434987,0.097069,0.432039
0.441207,0.099338,0.431594
0.447428,0.101597,0.431080
0.453651,0.103848,0.430498
0.459875,0.106089,0.429846
0.466100,0.108322,0.429125
0.472328,0.110547,0.428334
0.478558,0.112764,0.427475
0.484789,0.114974,0.426548
0.491022,0.117179,0.425552
0.497257,0.119379,0.424488
0.503493,0.121575,0.423356
0.509730,0.123769,0.422156
0.515967,0.125960,0.420887
0.522206,0.128150,0.419549
0.528444,0.130341,0.418142
0.534683,0.132534,0.416667
0.540920,0.134729,0.415123
0.547157,0.136929,0.413511
0.553392,0.139134,0.411829
0.559624,0.141346,0.410078
0.565854,0.143567,0.408258
0.572081,0.145797,0.406369
0.578304,0.148039,0.404411
0.584521,0.150294,0.402385
0.590734,0.152563,0.400290
0.596940,0.154848,0.398125
0.603139,0.157151,0.395891
0.609330,0.159474,0.393589
0.615513,0.161817,0.391219
0.621685,0.164184,0.388781
0.627847,0.166575,0.386276
0.633998,0.168992,0.383704
0.640135,0.171438,0.381065
0.646260,0.173914,0.378359
0.652369,0.176421,0.375586
0.658463,0.178962,0.372748
0.664540,0.181539,0.369846
0.670599,0.184153,0.366879
0.676638,0.186807,0.363849
0.682656,0.189501,0.360757
0.688653,0.192239,0.357603
0.694627,0.195021,0.354388
0.700576,0.197851,0.351113
0.706500,0.200728,0.347777
0.712396,0.203656,0.344383
0.718264,0.206636,0.340931
0.724103,0.209670,0.337424
0.729909,0.212759,0.333861
0.735683,0.215906,0.330245
0.741423,0.219112,0.326576
0.747127,0.222378,0.322856
0.752794,0.225706,0.319085
0.758422,0.229097,0.315266
0.764010,0.232554,0.311399
0.769556,0.236077,0.307485
0.775059,0.239667,0.303526
0.780517,0.243327,0.299523
0.785929,0.247056,0.295477
0.791293,0.250856,0.291390
0.796607,0.254728,0.287264
0.801871,0.258674,0.283099
0.807082,0.262692,0.278898
0.812239,0.266786,0.274661
0.817341,0.270954,0.270390
0.822386,0.275197,0.266085
0.827372,0.279517,0.261750
0.832299,0.283913,0.257383
0.837165,0.288385,0.252988
0.841969,0.292933,0.248564
0.846709,0.297559,0.244113
0.851384,0.302260,0.239636
0.855992,0.307038,0.235133
0.860533,0.311892,0.230606
0.865006,0.316822,0.226055
0.869409,0.321827,0.221482
0.873741,0.326906,0.216886
0.878001,0.332060,0.212268
0.882188,0.337287,0.207628
0.886302,0.342586,0.202968
0.890341,0.347957,0.198286
0.894305,0.353399,0.193584
0.898192,0.358911,0.188860
0.902003,0.364492,0.184116
0.905735,0.370140,0.179350
0.909390,0.375856,0.174563
0.912966,0.381636,0.169755
0.916462,0.387481,0.164924
0.919879,0.393389,0.160070
0.923215,0.399359,0.155193
0.926470,0.405389,0.150292
0.929644,0.411479,0.145367
0.932737,0.417627,0.140417
0.935747,0.423831,0.135440
0.938675,0.430091,0.130438
0.941521,0.436405,0.125409
0.944285,0.442772,0.120354
0.946965,0.449191,0.115272
0.949562,0.455660,0.110164
0.952075,0.462178,0.105031
0.954506,0.468744,0.099874
0.956852,0.475356,0.094695
0.959114,0.482014,0.089499
0.961293,0.488716,0.084289
0.963387,0.495462,0.079073
0.965397,0.502249,0.073859
0.967322,0.509078,0.068659
0.969163,0.515946,0.063488
0.970919,0.522853,0.058367
0.972590,0.529798,0.053324
0.974176,0.536780,0.048392
0.975677,0.543798,0.043618
0.977092,0.550850,0.039050
0.978422,0.557937,0.034931
0.979666,0.565057,0.031409
0.980824,0.572209,0.028508
0.981895,0.579392,0.026250
0.982881,0.586606,0.024661
0.983779,0.593849,0.023770
0.984591,0.601122,0.023606
0.985315,0.608422,0.024202
0.985952,0.615750,0.025592
0.986502,0.623105,0.027814
0.986964,0.630485,0.030908
0.987337,0.637890,0.034916
0.987622,0.645320,0.039886
0.987819,0.652773,0.045581
0.987926,0.660250,0.051750
0.987945,0.667748,0.058329
0.987874,0.675267,0.065257
0.987714,0.682807,0.072489
0.987464,0.690366,0.079990
0.987124,0.697944,0.087731
0.986694,0.705540,0.095694
0.986175,0.713153,0.103863
0.985566,0.720782,0.112229
0.984865,0.728427,0.120785
0.984075,0.736087,0.129527
0.983196,0.743758,0.138453
0.982228,0.751442,0.147565
0.981173,0.759135,0.156863
0.980032,0.766837,0.166353
0.978806,0.774545,0.176037
0.977497,0.782258,0.185923
0.976108,0.789974,0.196018
0.974638,0.797692,0.206332
0.973088,0.805409,0.216877
0.971468,0.813122,0.227658
0.969783,0.820825,0.238686
0.968041,0.828515,0.249972
0.966243,0.836191,0.261534
0.964394,0.843848,0.273391
0.962517,0.851476,0.285546
0.960626,0.859069,0.298010
0.958720,0.866624,0.310820
0.956834,0.874129,0.323974
0.954997,0.881569,0.337475
0.953215,0.888942,0.351369
0.951546,0.896226,0.365627
0.950018,0.903409,0.380271
0.948683,0.910473,0.395289
0.947594,0.917399,0.410665
0.946809,0.924168,0.426373
0.946392,0.930761,0.442367
0.946403,0.937159,0.458592
0.946903,0.943348,0.474970
0.947937,0.949318,0.491426
0.949545,0.955063,0.507860
0.951740,0.960587,0.524203
0.954529,0.965896,0.540361
0.957896,0.971003,0.556275
0.961812,0.975924,0.571925
0.966249,0.980678,0.587206
0.971162,0.985282,0.602154
0.976511,0.989753,0.616760
0.982257,0.994109,0.631017
0.988362,0.998364,0.644924
Can't render this file because it has a wrong number of fields in line 15.

View File

@ -0,0 +1,270 @@
; New matplotlib colormaps by Nathaniel J. Smith, Stefan van der Walt,
; and (in the case of viridis) Eric Firing.
;
; This file and the colormaps in it are released under the CC0 license /
; public domain dedication. The creators would appreciate credit if you use or
; redistribute these colormaps, but do not impose any legal restrictions.
;
; To the extent possible under law, the persons who associated CC0 with
; mpl-colormaps have waived all copyright and related or neighboring rights
; to mpl-colormaps.
;
; You should have received a copy of the CC0 legalcode along with this
; work. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
;
0.001462,0.000466,0.013866
0.002258,0.001295,0.018331
0.003279,0.002305,0.023708
0.004512,0.003490,0.029965
0.005950,0.004843,0.037130
0.007588,0.006356,0.044973
0.009426,0.008022,0.052844
0.011465,0.009828,0.060750
0.013708,0.011771,0.068667
0.016156,0.013840,0.076603
0.018815,0.016026,0.084584
0.021692,0.018320,0.092610
0.024792,0.020715,0.100676
0.028123,0.023201,0.108787
0.031696,0.025765,0.116965
0.035520,0.028397,0.125209
0.039608,0.031090,0.133515
0.043830,0.033830,0.141886
0.048062,0.036607,0.150327
0.052320,0.039407,0.158841
0.056615,0.042160,0.167446
0.060949,0.044794,0.176129
0.065330,0.047318,0.184892
0.069764,0.049726,0.193735
0.074257,0.052017,0.202660
0.078815,0.054184,0.211667
0.083446,0.056225,0.220755
0.088155,0.058133,0.229922
0.092949,0.059904,0.239164
0.097833,0.061531,0.248477
0.102815,0.063010,0.257854
0.107899,0.064335,0.267289
0.113094,0.065492,0.276784
0.118405,0.066479,0.286321
0.123833,0.067295,0.295879
0.129380,0.067935,0.305443
0.135053,0.068391,0.315000
0.140858,0.068654,0.324538
0.146785,0.068738,0.334011
0.152839,0.068637,0.343404
0.159018,0.068354,0.352688
0.165308,0.067911,0.361816
0.171713,0.067305,0.370771
0.178212,0.066576,0.379497
0.184801,0.065732,0.387973
0.191460,0.064818,0.396152
0.198177,0.063862,0.404009
0.204935,0.062907,0.411514
0.211718,0.061992,0.418647
0.218512,0.061158,0.425392
0.225302,0.060445,0.431742
0.232077,0.059889,0.437695
0.238826,0.059517,0.443256
0.245543,0.059352,0.448436
0.252220,0.059415,0.453248
0.258857,0.059706,0.457710
0.265447,0.060237,0.461840
0.271994,0.060994,0.465660
0.278493,0.061978,0.469190
0.284951,0.063168,0.472451
0.291366,0.064553,0.475462
0.297740,0.066117,0.478243
0.304081,0.067835,0.480812
0.310382,0.069702,0.483186
0.316654,0.071690,0.485380
0.322899,0.073782,0.487408
0.329114,0.075972,0.489287
0.335308,0.078236,0.491024
0.341482,0.080564,0.492631
0.347636,0.082946,0.494121
0.353773,0.085373,0.495501
0.359898,0.087831,0.496778
0.366012,0.090314,0.497960
0.372116,0.092816,0.499053
0.378211,0.095332,0.500067
0.384299,0.097855,0.501002
0.390384,0.100379,0.501864
0.396467,0.102902,0.502658
0.402548,0.105420,0.503386
0.408629,0.107930,0.504052
0.414709,0.110431,0.504662
0.420791,0.112920,0.505215
0.426877,0.115395,0.505714
0.432967,0.117855,0.506160
0.439062,0.120298,0.506555
0.445163,0.122724,0.506901
0.451271,0.125132,0.507198
0.457386,0.127522,0.507448
0.463508,0.129893,0.507652
0.469640,0.132245,0.507809
0.475780,0.134577,0.507921
0.481929,0.136891,0.507989
0.488088,0.139186,0.508011
0.494258,0.141462,0.507988
0.500438,0.143719,0.507920
0.506629,0.145958,0.507806
0.512831,0.148179,0.507648
0.519045,0.150383,0.507443
0.525270,0.152569,0.507192
0.531507,0.154739,0.506895
0.537755,0.156894,0.506551
0.544015,0.159033,0.506159
0.550287,0.161158,0.505719
0.556571,0.163269,0.505230
0.562866,0.165368,0.504692
0.569172,0.167454,0.504105
0.575490,0.169530,0.503466
0.581819,0.171596,0.502777
0.588158,0.173652,0.502035
0.594508,0.175701,0.501241
0.600868,0.177743,0.500394
0.607238,0.179779,0.499492
0.613617,0.181811,0.498536
0.620005,0.183840,0.497524
0.626401,0.185867,0.496456
0.632805,0.187893,0.495332
0.639216,0.189921,0.494150
0.645633,0.191952,0.492910
0.652056,0.193986,0.491611
0.658483,0.196027,0.490253
0.664915,0.198075,0.488836
0.671349,0.200133,0.487358
0.677786,0.202203,0.485819
0.684224,0.204286,0.484219
0.690661,0.206384,0.482558
0.697098,0.208501,0.480835
0.703532,0.210638,0.479049
0.709962,0.212797,0.477201
0.716387,0.214982,0.475290
0.722805,0.217194,0.473316
0.729216,0.219437,0.471279
0.735616,0.221713,0.469180
0.742004,0.224025,0.467018
0.748378,0.226377,0.464794
0.754737,0.228772,0.462509
0.761077,0.231214,0.460162
0.767398,0.233705,0.457755
0.773695,0.236249,0.455289
0.779968,0.238851,0.452765
0.786212,0.241514,0.450184
0.792427,0.244242,0.447543
0.798608,0.247040,0.444848
0.804752,0.249911,0.442102
0.810855,0.252861,0.439305
0.816914,0.255895,0.436461
0.822926,0.259016,0.433573
0.828886,0.262229,0.430644
0.834791,0.265540,0.427671
0.840636,0.268953,0.424666
0.846416,0.272473,0.421631
0.852126,0.276106,0.418573
0.857763,0.279857,0.415496
0.863320,0.283729,0.412403
0.868793,0.287728,0.409303
0.874176,0.291859,0.406205
0.879464,0.296125,0.403118
0.884651,0.300530,0.400047
0.889731,0.305079,0.397002
0.894700,0.309773,0.393995
0.899552,0.314616,0.391037
0.904281,0.319610,0.388137
0.908884,0.324755,0.385308
0.913354,0.330052,0.382563
0.917689,0.335500,0.379915
0.921884,0.341098,0.377376
0.925937,0.346844,0.374959
0.929845,0.352734,0.372677
0.933606,0.358764,0.370541
0.937221,0.364929,0.368567
0.940687,0.371224,0.366762
0.944006,0.377643,0.365136
0.947180,0.384178,0.363701
0.950210,0.390820,0.362468
0.953099,0.397563,0.361438
0.955849,0.404400,0.360619
0.958464,0.411324,0.360014
0.960949,0.418323,0.359630
0.963310,0.425390,0.359469
0.965549,0.432519,0.359529
0.967671,0.439703,0.359810
0.969680,0.446936,0.360311
0.971582,0.454210,0.361030
0.973381,0.461520,0.361965
0.975082,0.468861,0.363111
0.976690,0.476226,0.364466
0.978210,0.483612,0.366025
0.979645,0.491014,0.367783
0.981000,0.498428,0.369734
0.982279,0.505851,0.371874
0.983485,0.513280,0.374198
0.984622,0.520713,0.376698
0.985693,0.528148,0.379371
0.986700,0.535582,0.382210
0.987646,0.543015,0.385210
0.988533,0.550446,0.388365
0.989363,0.557873,0.391671
0.990138,0.565296,0.395122
0.990871,0.572706,0.398714
0.991558,0.580107,0.402441
0.992196,0.587502,0.406299
0.992785,0.594891,0.410283
0.993326,0.602275,0.414390
0.993834,0.609644,0.418613
0.994309,0.616999,0.422950
0.994738,0.624350,0.427397
0.995122,0.631696,0.431951
0.995480,0.639027,0.436607
0.995810,0.646344,0.441361
0.996096,0.653659,0.446213
0.996341,0.660969,0.451160
0.996580,0.668256,0.456192
0.996775,0.675541,0.461314
0.996925,0.682828,0.466526
0.997077,0.690088,0.471811
0.997186,0.697349,0.477182
0.997254,0.704611,0.482635
0.997325,0.711848,0.488154
0.997351,0.719089,0.493755
0.997351,0.726324,0.499428
0.997341,0.733545,0.505167
0.997285,0.740772,0.510983
0.997228,0.747981,0.516859
0.997138,0.755190,0.522806
0.997019,0.762398,0.528821
0.996898,0.769591,0.534892
0.996727,0.776795,0.541039
0.996571,0.783977,0.547233
0.996369,0.791167,0.553499
0.996162,0.798348,0.559820
0.995932,0.805527,0.566202
0.995680,0.812706,0.572645
0.995424,0.819875,0.579140
0.995131,0.827052,0.585701
0.994851,0.834213,0.592307
0.994524,0.841387,0.598983
0.994222,0.848540,0.605696
0.993866,0.855711,0.612482
0.993545,0.862859,0.619299
0.993170,0.870024,0.626189
0.992831,0.877168,0.633109
0.992440,0.884330,0.640099
0.992089,0.891470,0.647116
0.991688,0.898627,0.654202
0.991332,0.905763,0.661309
0.990930,0.912915,0.668481
0.990570,0.920049,0.675675
0.990175,0.927196,0.682926
0.989815,0.934329,0.690198
0.989434,0.941470,0.697519
0.989077,0.948604,0.704863
0.988717,0.955742,0.712242
0.988367,0.962878,0.719649
0.988033,0.970012,0.727077
0.987691,0.977154,0.734536
0.987387,0.984288,0.742002
0.987053,0.991438,0.749504
Can't render this file because it has a wrong number of fields in line 15.

View File

@ -0,0 +1,270 @@
; New matplotlib colormaps by Nathaniel J. Smith, Stefan van der Walt,
; and (in the case of viridis) Eric Firing.
;
; This file and the colormaps in it are released under the CC0 license /
; public domain dedication. The creators would appreciate credit if you use or
; redistribute these colormaps, but do not impose any legal restrictions.
;
; To the extent possible under law, the persons who associated CC0 with
; mpl-colormaps have waived all copyright and related or neighboring rights
; to mpl-colormaps.
;
; You should have received a copy of the CC0 legalcode along with this
; work. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
;
0.050383,0.029803,0.527975
0.063536,0.028426,0.533124
0.075353,0.027206,0.538007
0.086222,0.026125,0.542658
0.096379,0.025165,0.547103
0.105980,0.024309,0.551368
0.115124,0.023556,0.555468
0.123903,0.022878,0.559423
0.132381,0.022258,0.563250
0.140603,0.021687,0.566959
0.148607,0.021154,0.570562
0.156421,0.020651,0.574065
0.164070,0.020171,0.577478
0.171574,0.019706,0.580806
0.178950,0.019252,0.584054
0.186213,0.018803,0.587228
0.193374,0.018354,0.590330
0.200445,0.017902,0.593364
0.207435,0.017442,0.596333
0.214350,0.016973,0.599239
0.221197,0.016497,0.602083
0.227983,0.016007,0.604867
0.234715,0.015502,0.607592
0.241396,0.014979,0.610259
0.248032,0.014439,0.612868
0.254627,0.013882,0.615419
0.261183,0.013308,0.617911
0.267703,0.012716,0.620346
0.274191,0.012109,0.622722
0.280648,0.011488,0.625038
0.287076,0.010855,0.627295
0.293478,0.010213,0.629490
0.299855,0.009561,0.631624
0.306210,0.008902,0.633694
0.312543,0.008239,0.635700
0.318856,0.007576,0.637640
0.325150,0.006915,0.639512
0.331426,0.006261,0.641316
0.337683,0.005618,0.643049
0.343925,0.004991,0.644710
0.350150,0.004382,0.646298
0.356359,0.003798,0.647810
0.362553,0.003243,0.649245
0.368733,0.002724,0.650601
0.374897,0.002245,0.651876
0.381047,0.001814,0.653068
0.387183,0.001434,0.654177
0.393304,0.001114,0.655199
0.399411,0.000859,0.656133
0.405503,0.000678,0.656977
0.411580,0.000577,0.657730
0.417642,0.000564,0.658390
0.423689,0.000646,0.658956
0.429719,0.000831,0.659425
0.435734,0.001127,0.659797
0.441732,0.001540,0.660069
0.447714,0.002080,0.660240
0.453677,0.002755,0.660310
0.459623,0.003574,0.660277
0.465550,0.004545,0.660139
0.471457,0.005678,0.659897
0.477344,0.006980,0.659549
0.483210,0.008460,0.659095
0.489055,0.010127,0.658534
0.494877,0.011990,0.657865
0.500678,0.014055,0.657088
0.506454,0.016333,0.656202
0.512206,0.018833,0.655209
0.517933,0.021563,0.654109
0.523633,0.024532,0.652901
0.529306,0.027747,0.651586
0.534952,0.031217,0.650165
0.540570,0.034950,0.648640
0.546157,0.038954,0.647010
0.551715,0.043136,0.645277
0.557243,0.047331,0.643443
0.562738,0.051545,0.641509
0.568201,0.055778,0.639477
0.573632,0.060028,0.637349
0.579029,0.064296,0.635126
0.584391,0.068579,0.632812
0.589719,0.072878,0.630408
0.595011,0.077190,0.627917
0.600266,0.081516,0.625342
0.605485,0.085854,0.622686
0.610667,0.090204,0.619951
0.615812,0.094564,0.617140
0.620919,0.098934,0.614257
0.625987,0.103312,0.611305
0.631017,0.107699,0.608287
0.636008,0.112092,0.605205
0.640959,0.116492,0.602065
0.645872,0.120898,0.598867
0.650746,0.125309,0.595617
0.655580,0.129725,0.592317
0.660374,0.134144,0.588971
0.665129,0.138566,0.585582
0.669845,0.142992,0.582154
0.674522,0.147419,0.578688
0.679160,0.151848,0.575189
0.683758,0.156278,0.571660
0.688318,0.160709,0.568103
0.692840,0.165141,0.564522
0.697324,0.169573,0.560919
0.701769,0.174005,0.557296
0.706178,0.178437,0.553657
0.710549,0.182868,0.550004
0.714883,0.187299,0.546338
0.719181,0.191729,0.542663
0.723444,0.196158,0.538981
0.727670,0.200586,0.535293
0.731862,0.205013,0.531601
0.736019,0.209439,0.527908
0.740143,0.213864,0.524216
0.744232,0.218288,0.520524
0.748289,0.222711,0.516834
0.752312,0.227133,0.513149
0.756304,0.231555,0.509468
0.760264,0.235976,0.505794
0.764193,0.240396,0.502126
0.768090,0.244817,0.498465
0.771958,0.249237,0.494813
0.775796,0.253658,0.491171
0.779604,0.258078,0.487539
0.783383,0.262500,0.483918
0.787133,0.266922,0.480307
0.790855,0.271345,0.476706
0.794549,0.275770,0.473117
0.798216,0.280197,0.469538
0.801855,0.284626,0.465971
0.805467,0.289057,0.462415
0.809052,0.293491,0.458870
0.812612,0.297928,0.455338
0.816144,0.302368,0.451816
0.819651,0.306812,0.448306
0.823132,0.311261,0.444806
0.826588,0.315714,0.441316
0.830018,0.320172,0.437836
0.833422,0.324635,0.434366
0.836801,0.329105,0.430905
0.840155,0.333580,0.427455
0.843484,0.338062,0.424013
0.846788,0.342551,0.420579
0.850066,0.347048,0.417153
0.853319,0.351553,0.413734
0.856547,0.356066,0.410322
0.859750,0.360588,0.406917
0.862927,0.365119,0.403519
0.866078,0.369660,0.400126
0.869203,0.374212,0.396738
0.872303,0.378774,0.393355
0.875376,0.383347,0.389976
0.878423,0.387932,0.386600
0.881443,0.392529,0.383229
0.884436,0.397139,0.379860
0.887402,0.401762,0.376494
0.890340,0.406398,0.373130
0.893250,0.411048,0.369768
0.896131,0.415712,0.366407
0.898984,0.420392,0.363047
0.901807,0.425087,0.359688
0.904601,0.429797,0.356329
0.907365,0.434524,0.352970
0.910098,0.439268,0.349610
0.912800,0.444029,0.346251
0.915471,0.448807,0.342890
0.918109,0.453603,0.339529
0.920714,0.458417,0.336166
0.923287,0.463251,0.332801
0.925825,0.468103,0.329435
0.928329,0.472975,0.326067
0.930798,0.477867,0.322697
0.933232,0.482780,0.319325
0.935630,0.487712,0.315952
0.937990,0.492667,0.312575
0.940313,0.497642,0.309197
0.942598,0.502639,0.305816
0.944844,0.507658,0.302433
0.947051,0.512699,0.299049
0.949217,0.517763,0.295662
0.951344,0.522850,0.292275
0.953428,0.527960,0.288883
0.955470,0.533093,0.285490
0.957469,0.538250,0.282096
0.959424,0.543431,0.278701
0.961336,0.548636,0.275305
0.963203,0.553865,0.271909
0.965024,0.559118,0.268513
0.966798,0.564396,0.265118
0.968526,0.569700,0.261721
0.970205,0.575028,0.258325
0.971835,0.580382,0.254931
0.973416,0.585761,0.251540
0.974947,0.591165,0.248151
0.976428,0.596595,0.244767
0.977856,0.602051,0.241387
0.979233,0.607532,0.238013
0.980556,0.613039,0.234646
0.981826,0.618572,0.231287
0.983041,0.624131,0.227937
0.984199,0.629718,0.224595
0.985301,0.635330,0.221265
0.986345,0.640969,0.217948
0.987332,0.646633,0.214648
0.988260,0.652325,0.211364
0.989128,0.658043,0.208100
0.989935,0.663787,0.204859
0.990681,0.669558,0.201642
0.991365,0.675355,0.198453
0.991985,0.681179,0.195295
0.992541,0.687030,0.192170
0.993032,0.692907,0.189084
0.993456,0.698810,0.186041
0.993814,0.704741,0.183043
0.994103,0.710698,0.180097
0.994324,0.716681,0.177208
0.994474,0.722691,0.174381
0.994553,0.728728,0.171622
0.994561,0.734791,0.168938
0.994495,0.740880,0.166335
0.994355,0.746995,0.163821
0.994141,0.753137,0.161404
0.993851,0.759304,0.159092
0.993482,0.765499,0.156891
0.993033,0.771720,0.154808
0.992505,0.777967,0.152855
0.991897,0.784239,0.151042
0.991209,0.790537,0.149377
0.990439,0.796859,0.147870
0.989587,0.803205,0.146529
0.988648,0.809579,0.145357
0.987621,0.815978,0.144363
0.986509,0.822401,0.143557
0.985314,0.828846,0.142945
0.984031,0.835315,0.142528
0.982653,0.841812,0.142303
0.981190,0.848329,0.142279
0.979644,0.854866,0.142453
0.977995,0.861432,0.142808
0.976265,0.868016,0.143351
0.974443,0.874622,0.144061
0.972530,0.881250,0.144923
0.970533,0.887896,0.145919
0.968443,0.894564,0.147014
0.966271,0.901249,0.148180
0.964021,0.907950,0.149370
0.961681,0.914672,0.150520
0.959276,0.921407,0.151566
0.956808,0.928152,0.152409
0.954287,0.934908,0.152921
0.951726,0.941671,0.152925
0.949151,0.948435,0.152178
0.946602,0.955190,0.150328
0.944152,0.961916,0.146861
0.941896,0.968590,0.140956
0.940015,0.975158,0.131326
Can't render this file because it has a wrong number of fields in line 15.

View File

@ -0,0 +1,270 @@
; New matplotlib colormaps by Nathaniel J. Smith, Stefan van der Walt,
; and (in the case of viridis) Eric Firing.
;
; This file and the colormaps in it are released under the CC0 license /
; public domain dedication. The creators would appreciate credit if you use or
; redistribute these colormaps, but do not impose any legal restrictions.
;
; To the extent possible under law, the persons who associated CC0 with
; mpl-colormaps have waived all copyright and related or neighboring rights
; to mpl-colormaps.
;
; You should have received a copy of the CC0 legalcode along with this
; work. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
;
0.267004,0.004874,0.329415
0.268510,0.009605,0.335427
0.269944,0.014625,0.341379
0.271305,0.019942,0.347269
0.272594,0.025563,0.353093
0.273809,0.031497,0.358853
0.274952,0.037752,0.364543
0.276022,0.044167,0.370164
0.277018,0.050344,0.375715
0.277941,0.056324,0.381191
0.278791,0.062145,0.386592
0.279566,0.067836,0.391917
0.280267,0.073417,0.397163
0.280894,0.078907,0.402329
0.281446,0.084320,0.407414
0.281924,0.089666,0.412415
0.282327,0.094955,0.417331
0.282656,0.100196,0.422160
0.282910,0.105393,0.426902
0.283091,0.110553,0.431554
0.283197,0.115680,0.436115
0.283229,0.120777,0.440584
0.283187,0.125848,0.444960
0.283072,0.130895,0.449241
0.282884,0.135920,0.453427
0.282623,0.140926,0.457517
0.282290,0.145912,0.461510
0.281887,0.150881,0.465405
0.281412,0.155834,0.469201
0.280868,0.160771,0.472899
0.280255,0.165693,0.476498
0.279574,0.170599,0.479997
0.278826,0.175490,0.483397
0.278012,0.180367,0.486697
0.277134,0.185228,0.489898
0.276194,0.190074,0.493001
0.275191,0.194905,0.496005
0.274128,0.199721,0.498911
0.273006,0.204520,0.501721
0.271828,0.209303,0.504434
0.270595,0.214069,0.507052
0.269308,0.218818,0.509577
0.267968,0.223549,0.512008
0.266580,0.228262,0.514349
0.265145,0.232956,0.516599
0.263663,0.237631,0.518762
0.262138,0.242286,0.520837
0.260571,0.246922,0.522828
0.258965,0.251537,0.524736
0.257322,0.256130,0.526563
0.255645,0.260703,0.528312
0.253935,0.265254,0.529983
0.252194,0.269783,0.531579
0.250425,0.274290,0.533103
0.248629,0.278775,0.534556
0.246811,0.283237,0.535941
0.244972,0.287675,0.537260
0.243113,0.292092,0.538516
0.241237,0.296485,0.539709
0.239346,0.300855,0.540844
0.237441,0.305202,0.541921
0.235526,0.309527,0.542944
0.233603,0.313828,0.543914
0.231674,0.318106,0.544834
0.229739,0.322361,0.545706
0.227802,0.326594,0.546532
0.225863,0.330805,0.547314
0.223925,0.334994,0.548053
0.221989,0.339161,0.548752
0.220057,0.343307,0.549413
0.218130,0.347432,0.550038
0.216210,0.351535,0.550627
0.214298,0.355619,0.551184
0.212395,0.359683,0.551710
0.210503,0.363727,0.552206
0.208623,0.367752,0.552675
0.206756,0.371758,0.553117
0.204903,0.375746,0.553533
0.203063,0.379716,0.553925
0.201239,0.383670,0.554294
0.199430,0.387607,0.554642
0.197636,0.391528,0.554969
0.195860,0.395433,0.555276
0.194100,0.399323,0.555565
0.192357,0.403199,0.555836
0.190631,0.407061,0.556089
0.188923,0.410910,0.556326
0.187231,0.414746,0.556547
0.185556,0.418570,0.556753
0.183898,0.422383,0.556944
0.182256,0.426184,0.557120
0.180629,0.429975,0.557282
0.179019,0.433756,0.557430
0.177423,0.437527,0.557565
0.175841,0.441290,0.557685
0.174274,0.445044,0.557792
0.172719,0.448791,0.557885
0.171176,0.452530,0.557965
0.169646,0.456262,0.558030
0.168126,0.459988,0.558082
0.166617,0.463708,0.558119
0.165117,0.467423,0.558141
0.163625,0.471133,0.558148
0.162142,0.474838,0.558140
0.160665,0.478540,0.558115
0.159194,0.482237,0.558073
0.157729,0.485932,0.558013
0.156270,0.489624,0.557936
0.154815,0.493313,0.557840
0.153364,0.497000,0.557724
0.151918,0.500685,0.557587
0.150476,0.504369,0.557430
0.149039,0.508051,0.557250
0.147607,0.511733,0.557049
0.146180,0.515413,0.556823
0.144759,0.519093,0.556572
0.143343,0.522773,0.556295
0.141935,0.526453,0.555991
0.140536,0.530132,0.555659
0.139147,0.533812,0.555298
0.137770,0.537492,0.554906
0.136408,0.541173,0.554483
0.135066,0.544853,0.554029
0.133743,0.548535,0.553541
0.132444,0.552216,0.553018
0.131172,0.555899,0.552459
0.129933,0.559582,0.551864
0.128729,0.563265,0.551229
0.127568,0.566949,0.550556
0.126453,0.570633,0.549841
0.125394,0.574318,0.549086
0.124395,0.578002,0.548287
0.123463,0.581687,0.547445
0.122606,0.585371,0.546557
0.121831,0.589055,0.545623
0.121148,0.592739,0.544641
0.120565,0.596422,0.543611
0.120092,0.600104,0.542530
0.119738,0.603785,0.541400
0.119512,0.607464,0.540218
0.119423,0.611141,0.538982
0.119483,0.614817,0.537692
0.119699,0.618490,0.536347
0.120081,0.622161,0.534946
0.120638,0.625828,0.533488
0.121380,0.629492,0.531973
0.122312,0.633153,0.530398
0.123444,0.636809,0.528763
0.124780,0.640461,0.527068
0.126326,0.644107,0.525311
0.128087,0.647749,0.523491
0.130067,0.651384,0.521608
0.132268,0.655014,0.519661
0.134692,0.658636,0.517649
0.137339,0.662252,0.515571
0.140210,0.665859,0.513427
0.143303,0.669459,0.511215
0.146616,0.673050,0.508936
0.150148,0.676631,0.506589
0.153894,0.680203,0.504172
0.157851,0.683765,0.501686
0.162016,0.687316,0.499129
0.166383,0.690856,0.496502
0.170948,0.694384,0.493803
0.175707,0.697900,0.491033
0.180653,0.701402,0.488189
0.185783,0.704891,0.485273
0.191090,0.708366,0.482284
0.196571,0.711827,0.479221
0.202219,0.715272,0.476084
0.208030,0.718701,0.472873
0.214000,0.722114,0.469588
0.220124,0.725509,0.466226
0.226397,0.728888,0.462789
0.232815,0.732247,0.459277
0.239374,0.735588,0.455688
0.246070,0.738910,0.452024
0.252899,0.742211,0.448284
0.259857,0.745492,0.444467
0.266941,0.748751,0.440573
0.274149,0.751988,0.436601
0.281477,0.755203,0.432552
0.288921,0.758394,0.428426
0.296479,0.761561,0.424223
0.304148,0.764704,0.419943
0.311925,0.767822,0.415586
0.319809,0.770914,0.411152
0.327796,0.773980,0.406640
0.335885,0.777018,0.402049
0.344074,0.780029,0.397381
0.352360,0.783011,0.392636
0.360741,0.785964,0.387814
0.369214,0.788888,0.382914
0.377779,0.791781,0.377939
0.386433,0.794644,0.372886
0.395174,0.797475,0.367757
0.404001,0.800275,0.362552
0.412913,0.803041,0.357269
0.421908,0.805774,0.351910
0.430983,0.808473,0.346476
0.440137,0.811138,0.340967
0.449368,0.813768,0.335384
0.458674,0.816363,0.329727
0.468053,0.818921,0.323998
0.477504,0.821444,0.318195
0.487026,0.823929,0.312321
0.496615,0.826376,0.306377
0.506271,0.828786,0.300362
0.515992,0.831158,0.294279
0.525776,0.833491,0.288127
0.535621,0.835785,0.281908
0.545524,0.838039,0.275626
0.555484,0.840254,0.269281
0.565498,0.842430,0.262877
0.575563,0.844566,0.256415
0.585678,0.846661,0.249897
0.595839,0.848717,0.243329
0.606045,0.850733,0.236712
0.616293,0.852709,0.230052
0.626579,0.854645,0.223353
0.636902,0.856542,0.216620
0.647257,0.858400,0.209861
0.657642,0.860219,0.203082
0.668054,0.861999,0.196293
0.678489,0.863742,0.189503
0.688944,0.865448,0.182725
0.699415,0.867117,0.175971
0.709898,0.868751,0.169257
0.720391,0.870350,0.162603
0.730889,0.871916,0.156029
0.741388,0.873449,0.149561
0.751884,0.874951,0.143228
0.762373,0.876424,0.137064
0.772852,0.877868,0.131109
0.783315,0.879285,0.125405
0.793760,0.880678,0.120005
0.804182,0.882046,0.114965
0.814576,0.883393,0.110347
0.824940,0.884720,0.106217
0.835270,0.886029,0.102646
0.845561,0.887322,0.099702
0.855810,0.888601,0.097452
0.866013,0.889868,0.095953
0.876168,0.891125,0.095250
0.886271,0.892374,0.095374
0.896320,0.893616,0.096335
0.906311,0.894855,0.098125
0.916242,0.896091,0.100717
0.926106,0.897330,0.104071
0.935904,0.898570,0.108131
0.945636,0.899815,0.112838
0.955300,0.901065,0.118128
0.964894,0.902323,0.123941
0.974417,0.903590,0.130215
0.983868,0.904867,0.136897
0.993248,0.906157,0.143936
Can't render this file because it has a wrong number of fields in line 15.

View File

@ -26,6 +26,31 @@ from .metaarray import MetaArray
from collections import OrderedDict
from .python2_3 import asUnicode, basestring
# in order of appearance in this file.
# add new functions to this list only if they are to reside in pg namespace.
__all__ = [
'siScale', 'siFormat', 'siParse', 'siEval', 'siApply',
'Color', 'mkColor', 'mkBrush', 'mkPen', 'hsvColor',
'CIELabColor', 'colorCIELab', 'colorDistance',
'colorTuple', 'colorStr', 'intColor', 'glColor',
'makeArrowPath', 'eq',
'affineSliceCoords', 'affineSlice',
'interweaveArrays', 'interpolateArray', 'subArray',
'transformToArray', 'transformCoordinates',
'solve3DTransform', 'solveBilinearTransform',
'clip_scalar', 'clip_array', 'rescaleData', 'applyLookupTable',
'makeRGBA', 'makeARGB',
# 'try_fastpath_argb', 'ndarray_to_qimage',
'makeQImage',
# 'qimage_to_ndarray',
'imageToArray', 'colorToAlpha',
'gaussianFilter', 'downsample', 'arrayToQPath',
# 'ndarray_from_qpolygonf', 'create_qpolygonf', 'arrayToQPolygonF',
'isocurve', 'traceImage', 'isosurface',
'invertQTransform',
'pseudoScatter', 'toposort', 'disconnect', 'SignalBlock']
Colors = {
'b': QtGui.QColor(0,0,255,255),
'g': QtGui.QColor(0,255,0,255),

View File

@ -1151,7 +1151,7 @@ class AxisItem(GraphicsWidget):
pen, p1, p2 = axisSpec
p.setPen(pen)
p.drawLine(p1, p2)
p.translate(0.5,0) ## resolves some damn pixel ambiguity
# p.translate(0.5,0) ## resolves some damn pixel ambiguity
## draw ticks
for pen, p1, p2 in tickSpecs:
@ -1184,20 +1184,31 @@ class AxisItem(GraphicsWidget):
else:
self._updateHeight()
def wheelEvent(self, ev):
def wheelEvent(self, event):
lv = self.linkedView()
if lv is None:
return
if self.orientation in ['left', 'right']:
lv.wheelEvent(ev, axis=1)
# Did the event occur inside the linked ViewBox (and not over the axis iteself)?
if lv.sceneBoundingRect().contains(event.scenePos()):
# pass event to linked ViewBox without marking it as single axis zoom
lv.wheelEvent(event)
else:
lv.wheelEvent(ev, axis=0)
ev.accept()
# pass event to linked viewbox with appropriate single axis zoom parameter
if self.orientation in ['left', 'right']:
lv.wheelEvent(event, axis=1)
else:
lv.wheelEvent(event, axis=0)
event.accept()
def mouseDragEvent(self, event):
lv = self.linkedView()
if lv is None:
return
# Did the mouse down event occur inside the linked ViewBox (and not the axis)?
if lv.sceneBoundingRect().contains(event.buttonDownScenePos()):
# pass event to linked ViewBox without marking it as single axis pan
return lv.mouseDragEvent(event)
# otherwise pass event to linked viewbox with appropriate single axis parameter
if self.orientation in ['left', 'right']:
return lv.mouseDragEvent(event, axis=1)
else:

View File

@ -85,7 +85,7 @@ class ColorBarItem(PlotItem):
for key in ['left','right','top','bottom']:
self.showAxis(key)
axis = self.getAxis(key)
axis.setZValue(1)
axis.setZValue(0.5)
# select main axis:
if self.horizontal and key == 'bottom':
self.axis = axis
@ -93,7 +93,8 @@ class ColorBarItem(PlotItem):
self.axis = axis
self.axis.setWidth(45)
else: # show other axes to create frame
axis.setStyle( showValues=False, tickLength=0 )
axis.setTicks( [] )
axis.setStyle( showValues=False )
self.axis.setStyle( showValues=True )
self.axis.unlinkFromView()
self.axis.setRange( self.values[0], self.values[1] )

View File

@ -3,6 +3,8 @@ from .. import functions as fn
from .PlotDataItem import PlotDataItem
from .PlotCurveItem import PlotCurveItem
__all__ = ['FillBetweenItem']
class FillBetweenItem(QtGui.QGraphicsPathItem):
"""
GraphicsItem filling the space between two PlotDataItems.

View File

@ -15,17 +15,25 @@ class GradientLegend(UIGraphicsItem):
self.offset = offset
UIGraphicsItem.__init__(self)
self.setAcceptedMouseButtons(QtCore.Qt.MouseButton.NoButton)
self.brush = QtGui.QBrush(QtGui.QColor(200,0,0))
self.brush = QtGui.QBrush(QtGui.QColor(255,255,255,100)) # background color
self.pen = QtGui.QPen(QtGui.QColor(0,0,0))
self.textPen = QtGui.QPen(QtGui.QColor(0,0,0))
self.labels = {'max': 1, 'min': 0}
self.gradient = QtGui.QLinearGradient()
self.gradient.setColorAt(0, QtGui.QColor(0,0,0))
self.gradient.setColorAt(1, QtGui.QColor(255,0,0))
self.setZValue(100) # draw on top of ordinary plots
def setGradient(self, g):
self.gradient = g
self.update()
def setColorMap(self, colormap):
"""
Set displayed gradient from a :class:`~pyqtgraph.ColorMap` object.
"""
self.gradient = colormap.getGradient()
def setIntColorScale(self, minVal, maxVal, *args, **kargs):
colors = [fn.intColor(i, maxVal-minVal, *args, **kargs) for i in range(minVal, maxVal)]
g = QtGui.QLinearGradient()
@ -45,13 +53,14 @@ class GradientLegend(UIGraphicsItem):
def paint(self, p, opt, widget):
UIGraphicsItem.paint(self, p, opt, widget)
rect = self.boundingRect() ## Boundaries of visible area in scene coords.
unit = self.pixelSize() ## Size of one view pixel in scene coords.
if unit[0] is None:
return
## Have to scale painter so that text and gradients are correct size and not upside down
p.scale(unit[0], -unit[1])
view = self.getViewBox()
if view is None:
return
p.save() # save painter state before we change transformation
trans = view.sceneTransform()
p.setTransform( trans ) # draw in ViewBox pixel coordinates
rect = view.rect()
## determine max width of all labels
labelWidth = 0
@ -63,10 +72,10 @@ class GradientLegend(UIGraphicsItem):
textPadding = 2 # in px
xR = rect.right() / unit[0]
xL = rect.left() / unit[0]
yB = -(rect.top() / unit[1])
yT = -(rect.bottom() / unit[1])
xR = rect.right()
xL = rect.left()
yT = rect.top()
yB = rect.bottom()
# coordinates describe edges of text and bar, additional margins will be added for background
if self.offset[0] < 0:
@ -87,7 +96,7 @@ class GradientLegend(UIGraphicsItem):
## Draw background
p.setPen(self.pen)
p.setBrush(QtGui.QBrush(QtGui.QColor(255,255,255,100)))
p.setBrush(self.brush) # background color
rect = QtCore.QRectF(
QtCore.QPointF(x1 - textPadding, y1-labelHeight/2 - textPadding), # extra left/top padding
QtCore.QPointF(x3 + textPadding, y2+labelHeight/2 + textPadding) # extra bottom/right padding
@ -95,8 +104,8 @@ class GradientLegend(UIGraphicsItem):
p.drawRect(rect)
## Draw color bar
self.gradient.setStart(0, y1)
self.gradient.setFinalStop(0, y2)
self.gradient.setStart(0, y2)
self.gradient.setFinalStop(0, y1)
p.setBrush(self.gradient)
rect = QtCore.QRectF(
QtCore.QPointF(x1, y1),
@ -105,10 +114,12 @@ class GradientLegend(UIGraphicsItem):
p.drawRect(rect)
## draw labels
p.setPen(QtGui.QPen(QtGui.QColor(0,0,0)))
p.setPen(self.textPen)
tx = x2 + 2 * textPadding # margin between bar and text
lh = labelHeight
lw = labelWidth
for k in self.labels:
y = y1 + self.labels[k] * (y2-y1)
y = y2 - self.labels[k] * (y2-y1)
p.drawText(QtCore.QRectF(tx, y - lh/2, lw, lh), QtCore.Qt.AlignmentFlag.AlignLeft | QtCore.Qt.AlignmentFlag.AlignVCenter, str(k))
p.restore() # restore QPainter transform to original state

View File

@ -9,6 +9,7 @@ from .. import functions as fn
import weakref
import operator
__all__ = ['GraphicsItem']
# Recipe from https://docs.python.org/3.8/library/collections.html#collections.OrderedDict
# slightly adapted for Python 3.7 compatibility

View File

@ -13,11 +13,12 @@ class GraphicsLayout(GraphicsWidget):
This is usually created automatically as part of a :class:`GraphicsWindow <pyqtgraph.GraphicsWindow>` or :class:`GraphicsLayoutWidget <pyqtgraph.GraphicsLayoutWidget>`.
"""
def __init__(self, parent=None, border=None):
GraphicsWidget.__init__(self, parent)
if border is True:
border = (100,100,100)
elif border is False:
border = None
self.border = border
self.layout = QtGui.QGraphicsGridLayout()
self.setLayout(self.layout)

View File

@ -1,6 +1,7 @@
from ..Qt import QtGui, QtCore
from ..Point import Point
__all__ = ['GraphicsWidgetAnchor']
class GraphicsWidgetAnchor(object):
"""

View File

@ -12,6 +12,7 @@ from .ViewBox import *
from .GradientEditorItem import *
from .LinearRegionItem import *
from .PlotDataItem import *
from .PlotCurveItem import *
from .AxisItem import *
from .GridItem import *
from ..Point import Point

View File

@ -900,7 +900,7 @@ class ImageItem(GraphicsObject):
step = int(self._xp.ceil((mx - mn) / 500.))
bins = []
if step > 0.0:
bins = self._xp.arange(mn, mx + 1.01 * step, step, dtype=self._xp.int)
bins = self._xp.arange(mn, mx + 1.01 * step, step, dtype=int)
else:
# for float data, let numpy select the bins.
bins = self._xp.linspace(mn, mx, 500)

View File

@ -3,6 +3,7 @@ from .GraphicsObject import *
from .. import functions as fn
from ..Qt import QtGui, QtCore
__all__ = ['IsocurveItem']
class IsocurveItem(GraphicsObject):
"""

View File

@ -6,6 +6,7 @@ from .GraphicsObject import GraphicsObject
from .. import mkBrush, mkPen
from .. import functions as fn
__all__ = ['NonUniformImage']
class NonUniformImage(GraphicsObject):
"""

View File

@ -11,6 +11,7 @@ from .. import functions as fn
from .. import debug as debug
from .. import getConfigOption
__all__ = ['PlotDataItem']
class PlotDataItem(GraphicsObject):
"""

View File

@ -14,9 +14,11 @@ from ..InfiniteLine import InfiniteLine
from ..LabelItem import LabelItem
from ..LegendItem import LegendItem
from ..PlotDataItem import PlotDataItem
from ..PlotCurveItem import PlotCurveItem
from ..ScatterPlotItem import ScatterPlotItem
from ..ViewBox import ViewBox
from ... import functions as fn
from ... import icons, PlotCurveItem, ScatterPlotItem
from ... import icons
from ...Qt import QtGui, QtCore, QT_LIB
from ...WidgetGroup import WidgetGroup
from ...python2_3 import basestring

View File

@ -1 +1,3 @@
from .PlotItem import PlotItem
__all__ = ['PlotItem']

View File

@ -1676,8 +1676,8 @@ class LineROI(ROI):
pos2 = Point(pos2)
d = pos2-pos1
l = d.length()
ra = Point(1, 0).angle(d, units="radians")
c = Point(-width/2. * sin(ra), -width/2. * cos(ra))
ra = d.angle(Point(1, 0), units="radians")
c = Point(width/2. * sin(ra), -width/2. * cos(ra))
pos1 = pos1 + c
ROI.__init__(self, pos1, size=Point(l, width), angle=degrees(ra), **args)

View File

@ -10,6 +10,7 @@ from .ViewBox import ViewBox
import string
import warnings
__all__ = ['TargetItem', 'TargetLabel']
class TargetItem(UIGraphicsItem):
"""Draws a draggable target symbol (circle plus crosshair).

View File

@ -4,6 +4,7 @@ from ..Point import Point
from .. import functions as fn
from .GraphicsObject import GraphicsObject
__all__ = ['TextItem']
class TextItem(GraphicsObject):
"""

View File

@ -1 +1,3 @@
from .ViewBox import ViewBox
__all__ = ['ViewBox']

View File

@ -6,6 +6,8 @@ it is possible to place any widget into its own window by simply calling its
show() method.
"""
__all__ = ['GraphicsWindow', 'TabWindow', 'PlotWindow', 'ImageWindow']
from .Qt import QtCore, QtGui, mkQApp
from .widgets.PlotWidget import *
from .imageview import *

View File

@ -4,3 +4,5 @@ Includes ROI plotting over time and image normalization.
"""
from .ImageView import ImageView
__all__ = ['ImageView']

View File

@ -132,6 +132,10 @@ class MetaArray(object):
def __init__(self, data=None, info=None, dtype=None, file=None, copy=False, **kwargs):
object.__init__(self)
warnings.warn(
'MetaArray is deprecated and will be removed in 0.14.',
DeprecationWarning, stacklevel=2
)
self._isHDF = False
if file is not None:

View File

@ -123,12 +123,23 @@ class Process(RemoteEventHandler):
## set its sys.path properly before unpickling the target
pid = os.getpid() # we must send pid to child because windows does not have getppid
# When running in a venv on Windows platform, since Python >= 3.7.3, the launched
# subprocess is a grandchild instead of a child, leading to self.proc.pid not being
# the pid of the launched subprocess.
# https://bugs.python.org/issue38905
#
# As a workaround, when we detect such a situation, we perform exchange of pids via
# the multiprocessing connection. Technically, only the launched subprocess needs to
# send its pid back. Practically, we hijack the ppid parameter to indicate to the
# subprocess that pid exchange is needed.
xchg_pids = sys.platform == 'win32' and os.getenv('VIRTUAL_ENV') is not None
## Send everything the remote process needs to start correctly
data = dict(
name=name+'_child',
port=port,
authkey=authkey,
ppid=pid,
ppid=pid if not xchg_pids else None,
targetStr=targetStr,
path=sysPath,
qt_lib=QT_LIB,
@ -150,7 +161,14 @@ class Process(RemoteEventHandler):
else:
raise
RemoteEventHandler.__init__(self, conn, name+'_parent', pid=self.proc.pid, debug=self.debug)
child_pid = self.proc.pid
if xchg_pids:
# corresponding code is in:
# remoteproxy.py::RemoteEventHandler.__init__()
conn.send(pid)
child_pid = conn.recv()
RemoteEventHandler.__init__(self, conn, name+'_parent', pid=child_pid, debug=self.debug)
self.debugMsg('Connected to child process.')
atexit.register(self.join)

View File

@ -87,6 +87,13 @@ class RemoteEventHandler(object):
self.processLock = threading.RLock()
self.sendLock = threading.RLock()
# parent sent us None as its pid, wants us to exchange pids
# corresponding code is in:
# processes.py::Process.__init__()
if pid is None:
connection.send(os.getpid())
pid = connection.recv()
RemoteEventHandler.handlers[pid] = self ## register this handler as the one communicating with pid
@classmethod

View File

@ -1,8 +1,7 @@
from OpenGL.GL import *
from OpenGL import GL
from ..Qt import QtGui, QtCore
from ..Qt import QtCore
from .. import Transform3D
from ..python2_3 import basestring
GLOptions = {
@ -42,6 +41,7 @@ class GLGraphicsItem(QtCore.QObject):
self.__children = set()
self.__transform = Transform3D()
self.__visible = True
self.__initialized = False
self.setParentItem(parentItem)
self.setDepthValue(0)
self.__glOpts = {}
@ -91,7 +91,7 @@ class GLGraphicsItem(QtCore.QObject):
"""
if isinstance(opts, basestring):
if isinstance(opts, str):
opts = GLOptions[opts]
self.__glOpts = opts.copy()
self.update()
@ -228,6 +228,12 @@ class GLGraphicsItem(QtCore.QObject):
view, as it may be obscured or outside of the current view area."""
return self.__visible
def initialize(self):
self.initializeGL()
self.__initialized = True
def isInitialized(self):
return self.__initialized
def initializeGL(self):
"""
@ -245,7 +251,7 @@ class GLGraphicsItem(QtCore.QObject):
for k,v in self.__glOpts.items():
if v is None:
continue
if isinstance(k, basestring):
if isinstance(k, str):
func = getattr(GL, k)
func(*v)
else:

View File

@ -1,4 +1,4 @@
from ..Qt import QtCore, QtGui, QtWidgets, QT_LIB
from ..Qt import QtCore, QtGui, QtWidgets
from OpenGL.GL import *
import OpenGL.GL.framebufferobjects as glfbo
import numpy as np
@ -8,7 +8,6 @@ import warnings
from math import cos, sin, tan, radians
##Vector = QtGui.QVector3D
ShareWidget = None
class GLViewWidget(QtWidgets.QOpenGLWidget):
@ -99,10 +98,11 @@ class GLViewWidget(QtWidgets.QOpenGLWidget):
def addItem(self, item):
self.items.append(item)
if hasattr(item, 'initializeGL'):
if self.isValid():
self.makeCurrent()
try:
item.initializeGL()
item.initialize()
except:
self.checkOpenGLVersion('Error while adding item %s to GLViewWidget.' % str(item))
@ -128,7 +128,12 @@ class GLViewWidget(QtWidgets.QOpenGLWidget):
self.update()
def initializeGL(self):
self.resizeGL(self.width(), self.height())
"""
Initialize items that were not initialized during addItem().
"""
for item in self.items:
if not item.isInitialized():
item.initialize()
def setBackgroundColor(self, *args, **kwds):
"""
@ -430,10 +435,11 @@ class GLViewWidget(QtWidgets.QOpenGLWidget):
return xDist / self.width()
def mousePressEvent(self, ev):
self.mousePos = ev.localPos()
lpos = ev.position() if hasattr(ev, 'position') else ev.localPos()
self.mousePos = lpos
def mouseMoveEvent(self, ev):
lpos = ev.localPos()
lpos = ev.position() if hasattr(ev, 'position') else ev.localPos()
diff = lpos - self.mousePos
self.mousePos = lpos
@ -462,13 +468,9 @@ class GLViewWidget(QtWidgets.QOpenGLWidget):
#self.swapBuffers()
def wheelEvent(self, ev):
delta = 0
if QT_LIB in ['PyQt4', 'PySide']:
delta = ev.delta()
else:
delta = ev.angleDelta().x()
if delta == 0:
delta = ev.angleDelta().y()
delta = ev.angleDelta().x()
if delta == 0:
delta = ev.angleDelta().y()
if (ev.modifiers() & QtCore.Qt.KeyboardModifier.ControlModifier):
self.opts['fov'] *= 0.999**delta
else:

View File

@ -54,9 +54,6 @@ class GLLinePlotItem(GLGraphicsItem):
#self.vbo.pop(arg, None)
self.update()
def initializeGL(self):
pass
def paint(self):
if self.pos is None:
return

View File

@ -1,137 +1,12 @@
# Copyright (c) 2009 Raymond Hettinger
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
# (the "Software"), to deal in the Software without restriction,
# including without limitation the rights to use, copy, modify, merge,
# publish, distribute, sublicense, and/or sell copies of the Software,
# and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
# OTHER DEALINGS IN THE SOFTWARE.
import collections
import warnings
warnings.warn(
"OrderedDict is in the standard library for supported versions of Python. Will be removed in 0.13",
DeprecationWarning, stacklevel=2
)
import sys
if sys.version[0] > '2':
from collections import OrderedDict
else:
from UserDict import DictMixin
class OrderedDict(dict, DictMixin):
def __init__(self, *args, **kwds):
if len(args) > 1:
raise TypeError('expected at most 1 arguments, got %d' % len(args))
try:
self.__end
except AttributeError:
self.clear()
self.update(*args, **kwds)
def clear(self):
self.__end = end = []
end += [None, end, end] # sentinel node for doubly linked list
self.__map = {} # key --> [key, prev, next]
dict.clear(self)
def __setitem__(self, key, value):
if key not in self:
end = self.__end
curr = end[1]
curr[2] = end[1] = self.__map[key] = [key, curr, end]
dict.__setitem__(self, key, value)
def __delitem__(self, key):
dict.__delitem__(self, key)
key, prev, next = self.__map.pop(key)
prev[2] = next
next[1] = prev
def __iter__(self):
end = self.__end
curr = end[2]
while curr is not end:
yield curr[0]
curr = curr[2]
def __reversed__(self):
end = self.__end
curr = end[1]
while curr is not end:
yield curr[0]
curr = curr[1]
def popitem(self, last=True):
if not self:
raise KeyError('dictionary is empty')
if last:
key = reversed(self).next()
else:
key = iter(self).next()
value = self.pop(key)
return key, value
def __reduce__(self):
items = [[k, self[k]] for k in self]
tmp = self.__map, self.__end
del self.__map, self.__end
inst_dict = vars(self).copy()
self.__map, self.__end = tmp
if inst_dict:
return (self.__class__, (items,), inst_dict)
return self.__class__, (items,)
def keys(self):
return list(self)
setdefault = DictMixin.setdefault
update = DictMixin.update
pop = DictMixin.pop
values = DictMixin.values
items = DictMixin.items
iterkeys = DictMixin.iterkeys
itervalues = DictMixin.itervalues
iteritems = DictMixin.iteritems
def __repr__(self):
if not self:
return '%s()' % (self.__class__.__name__,)
return '%s(%r)' % (self.__class__.__name__, self.items())
def copy(self):
return self.__class__(self)
@classmethod
def fromkeys(cls, iterable, value=None):
d = cls()
for key in iterable:
d[key] = value
return d
def __eq__(self, other):
if isinstance(other, OrderedDict):
if len(self) != len(other):
return False
for p, q in zip(self.items(), other.items()):
if p != q:
return False
return True
return dict.__eq__(self, other)
def __ne__(self, other):
return not self == other
class OrderedDict(collections.OrderedDict):
def __init__(self, *args, **kwds):
warnings.warn(
"OrderedDict is in the standard library for supported versions of Python. Will be removed in 0.13",
DeprecationWarning,
stacklevel=2,
)
super().__init__(*args, **kwds)

View File

@ -4,6 +4,7 @@ from ..SignalProxy import SignalProxy
from collections import OrderedDict
from ..python2_3 import asUnicode, basestring
__all__ = ['ComboBox']
class ComboBox(QtGui.QComboBox):
"""Extends QComboBox to add extra functionality.

View File

@ -317,13 +317,9 @@ class GraphicsView(QtGui.QGraphicsView):
super().wheelEvent(ev)
if not self.mouseEnabled:
return
delta = 0
if QT_LIB in ['PyQt4', 'PySide']:
delta = ev.delta()
else:
delta = ev.angleDelta().x()
if delta == 0:
delta = ev.angleDelta().y()
delta = ev.angleDelta().x()
if delta == 0:
delta = ev.angleDelta().y()
sc = 1.001 ** delta
#self.scale *= sc

View File

@ -2,6 +2,7 @@ from ..Qt import QtGui, QtCore
from .PathButton import PathButton
from ..python2_3 import basestring
__all__ = ['GroupBox']
class GroupBox(QtGui.QGroupBox):
"""Subclass of QGroupBox that implements collapse handle.

View File

@ -6,6 +6,8 @@ from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as Navigatio
from matplotlib.figure import Figure
__all__ = ['MatplotlibWidget']
class MatplotlibWidget(QtGui.QWidget):
"""
Implements a Matplotlib figure inside a QWidget.

View File

@ -73,7 +73,7 @@ class ProgressDialog(QtGui.QProgressDialog):
else:
self.setMinimumDuration(wait)
self.setWindowModality(QtCore.Qt.WindowType.WindowModality.WindowModal)
self.setWindowModality(QtCore.Qt.WindowModality.WindowModal)
self.setValue(self.minimum())
if noCancel:
self.setCancelButton(None)
@ -206,7 +206,7 @@ class ProgressDialog(QtGui.QProgressDialog):
# Qt docs say this should happen automatically, but that doesn't seem
# to be the case.
if self.windowModality() == QtCore.Qt.WindowType.WindowModality.WindowModal:
if self.windowModality() == QtCore.Qt.WindowModality.WindowModal:
now = ptime.time()
if self._lastProcessEvents is None or (now - self._lastProcessEvents) > 0.2:
QtGui.QApplication.processEvents()

View File

@ -18,6 +18,7 @@ except (ImportError, AttributeError):
# AttributeError upon import
HAVE_OPENGL = False
__all__ = ['RawImageWidget']
class RawImageWidget(QtGui.QWidget):
"""
@ -78,6 +79,7 @@ class RawImageWidget(QtGui.QWidget):
if HAVE_OPENGL:
__all__.append('RawImageGLWidget')
class RawImageGLWidget(QOpenGLWidget):
"""
Similar to RawImageWidget, but uses a GL widget to do all drawing.

View File

@ -2,6 +2,7 @@
CSV export test
"""
from __future__ import division, print_function, absolute_import
import numpy as np
import pyqtgraph as pg
import csv
import tempfile
@ -19,11 +20,11 @@ def test_CSVExporter():
plt.plot(y=y1, name='myPlot')
y2 = [3,4,6,1,2,4,2,3,5,3,5,1,3]
x2 = pg.np.linspace(0, 1.0, len(y2))
x2 = np.linspace(0, 1.0, len(y2))
plt.plot(x=x2, y=y2)
y3 = [1,5,2,3,4,6,1,2,4,2,3,5,3]
x3 = pg.np.linspace(0, 1.0, len(y3)+1)
x3 = np.linspace(0, 1.0, len(y3)+1)
plt.plot(x=x3, y=y3, stepMode="center")
ex = pg.exporters.CSVExporter(plt.plotItem)

View File

@ -7,7 +7,7 @@ pytest.importorskip("matplotlib")
app = pg.mkQApp()
skip_qt6 = pytest.mark.skipif(
pg.QT_LIB in ["PySide6", "PyQt6"],
pg.Qt.QT_LIB in ["PySide6", "PyQt6"],
reason= (
"Matplotlib has no Qt6 support yet, "
"see https://github.com/matplotlib/matplotlib/pull/19255"

View File

@ -229,7 +229,7 @@ def test_setRect():
def test_dividebyzero():
im = pg.image(pg.np.random.normal(size=(100,100)))
im = pg.image(np.random.normal(size=(100,100)))
im.imageItem.setAutoDownsample(True)
im.view.setRange(xRange=[-5+25, 5e+25],yRange=[-5e+25, 5e+25])
app.processEvents()

View File

@ -6,6 +6,7 @@ import platform
from pyqtgraph.Qt import QtCore, QtGui, QtTest
from tests.image_testing import assertImageApproved
from tests.ui_testing import mouseMove, mouseDrag, mouseClick, resizeWindow
import math
app = pg.mkQApp()
pg.setConfigOption("mouseRateLimit", 0)
@ -252,3 +253,21 @@ def test_PolyLineROI():
plt.hide()
@pytest.mark.parametrize("p1,p2", [
((1, 1), (2, 5)),
((0.1, 0.1), (-1, 5)),
((3, -1), (5, -6)),
((-2, 1), (-4, -8)),
])
def test_LineROI_coords(p1, p2):
pw = pg.plot()
lineroi = pg.LineROI(p1, p2, width=0.5, pen="r")
pw.addItem(lineroi)
# first two handles are the scale-rotate handles positioned by pos1, pos2
for expected, (name, scenepos) in zip([p1, p2], lineroi.getSceneHandlePositions()):
got = lineroi.mapSceneToParent(scenepos)
assert math.isclose(got.x(), expected[0])
assert math.isclose(got.y(), expected[1])

75
tests/test_colormap.py Normal file
View File

@ -0,0 +1,75 @@
import pytest
import pyqtgraph as pg
from pyqtgraph.Qt import QtGui
pos = [0.0, 0.5, 1.0]
qcols = [
QtGui.QColor('#FF0000'),
QtGui.QColor('#00FF00'),
QtGui.QColor('#0000FF')
]
float_tuples = [
(1.0, 0.0, 0.0, 1.0),
(0.0, 1.0, 0.0, 1.0),
(0.0, 0.0, 1.0, 1.0)
]
int_tuples = [
(255, 0, 0,255),
( 0,255, 0,255),
( 0, 0,255,255)
]
@pytest.mark.parametrize("color_list", (qcols, int_tuples))
def test_ColorMap_getStops(color_list):
cm = pg.ColorMap(pos, color_list, name='test')
# default is byte format:
stops, colors = cm.getStops()
assert (stops == pos).all()
assert (colors == int_tuples).all()
# manual byte format:
stops, colors = cm.getStops(pg.ColorMap.BYTE)
assert (stops == pos).all()
assert (colors == int_tuples).all()
stops, colors = cm.getStops('bYTe')
assert (stops == pos).all()
assert (colors == int_tuples).all()
# manual float format:
stops, colors = cm.getStops(pg.ColorMap.FLOAT)
assert (stops == pos).all()
assert (colors == float_tuples).all()
stops, colors = cm.getStops('floaT')
assert (stops == pos).all()
assert (colors == float_tuples).all()
# manual QColor format:
stops, colors = cm.getStops(pg.ColorMap.QCOLOR)
assert (stops == pos).all()
for actual, good in zip(colors, qcols):
assert actual.getRgbF() == good.getRgbF()
stops, colors = cm.getStops('qColor')
assert (stops == pos).all()
for actual, good in zip(colors, qcols):
assert actual.getRgbF() == good.getRgbF()
@pytest.mark.parametrize("color_list", (qcols, int_tuples))
def test_ColorMap_getColors(color_list):
cm = pg.ColorMap(pos, color_list, name='from QColors')
colors = cm.getColors()
assert (colors == int_tuples).all()
colors = cm.getColors('byte')
assert (colors == int_tuples).all()
colors = cm.getColors('float')
assert (colors == float_tuples).all()
colors = cm.getColors('qcolor')
for actual, good in zip(colors, qcols):
assert actual.getRgbF() == good.getRgbF()

View File

@ -37,7 +37,7 @@ def test_PlotWidget():
with warnings.catch_warnings():
warnings.simplefilter("ignore")
w = pg.PlotWidget(*args, **kwds)
data = pg.np.array([1,5,2,4,3])
data = np.array([1,5,2,4,3])
c = w.plot(data, name='stuff')
w.addLegend()

View File

@ -0,0 +1,9 @@
# -*- coding: utf-8 -*-
from pyqtgraph import mkQApp, ProgressDialog
mkQApp()
def test_progress_dialog():
with ProgressDialog("test", 0, 1) as dlg:
dlg += 1