2011-02-08 00:40:38 +00:00
# -*- coding: utf-8 -*-
2012-12-27 06:52:32 +00:00
"""
PyQtGraph - Scientific Graphics and GUI Library for Python
www . pyqtgraph . org
"""
2021-04-07 01:41:32 +00:00
__version__ = ' 0.12.1 '
2012-06-29 18:39:27 +00:00
2011-02-08 00:40:38 +00:00
### import all the goodies and add some helper functions for easy CLI use
2012-03-02 02:55:32 +00:00
## 'Qt' is a local module; it is intended mainly to cover up the differences
## between PyQt4 and PySide.
2018-02-24 01:34:15 +00:00
from . Qt import QtGui , mkQApp
2012-03-02 02:55:32 +00:00
2012-05-11 22:05:41 +00:00
## not really safe--If we accidentally create another QApplication, the process hangs (and it is very difficult to trace the cause)
2012-03-02 02:55:32 +00:00
#if QtGui.QApplication.instance() is None:
#app = QtGui.QApplication([])
2013-01-12 19:39:23 +00:00
import numpy ## pyqtgraph requires numpy
## (import here to avoid massive error dump later on if numpy is not available)
2012-06-29 18:53:32 +00:00
import os , sys
2012-04-04 18:45:12 +00:00
## check python version
2012-07-12 19:35:58 +00:00
## Allow anything >= 2.7
2012-09-13 14:12:59 +00:00
if sys . version_info [ 0 ] < 2 or ( sys . version_info [ 0 ] == 2 and sys . version_info [ 1 ] < 6 ) :
raise Exception ( " Pyqtgraph requires Python version 2.6 or greater (this is %d . %d ) " % ( sys . version_info [ 0 ] , sys . version_info [ 1 ] ) )
2012-04-04 18:45:12 +00:00
2012-05-11 22:05:41 +00:00
## helpers for 2/3 compatibility
from . import python2_3
2012-05-31 20:22:50 +00:00
## in general openGL is poorly supported with Qt+GraphicsView.
2012-05-11 22:05:41 +00:00
## we only enable it where the performance benefit is critical.
## Note this only applies to 2D graphics; 3D graphics always use OpenGL.
2012-03-27 16:30:51 +00:00
if ' linux ' in sys . platform : ## linux has numerous bugs in opengl implementation
useOpenGL = False
2012-05-31 20:22:50 +00:00
elif ' darwin ' in sys . platform : ## openGL can have a major impact on mac, but also has serious bugs
2012-12-23 02:49:40 +00:00
useOpenGL = False
2012-03-27 16:30:51 +00:00
else :
2012-04-04 13:29:35 +00:00
useOpenGL = False ## on windows there's a more even performance / bugginess tradeoff.
2012-03-27 16:30:51 +00:00
2012-03-02 02:55:32 +00:00
CONFIG_OPTIONS = {
2012-06-29 18:39:27 +00:00
' useOpenGL ' : useOpenGL , ## by default, this is platform-dependent (see widgets/GraphicsView). Set to True or False to explicitly enable/disable opengl.
2012-05-11 22:05:41 +00:00
' leftButtonPan ' : True , ## if false, left button drags a rubber band for zooming in viewbox
2015-07-12 21:43:05 +00:00
# foreground/background take any arguments to the 'mkColor' in /pyqtgraph/functions.py
2013-09-20 07:46:10 +00:00
' foreground ' : ' d ' , ## default foreground color for axes, labels, etc.
' background ' : ' k ' , ## default background for GraphicsWidget
2012-05-11 22:05:41 +00:00
' antialias ' : False ,
2012-06-29 18:39:27 +00:00
' editorCommand ' : None , ## command used to invoke code editor from ConsoleWidgets
2013-03-07 20:29:56 +00:00
' exitCleanup ' : True , ## Attempt to work around some exit crash bugs in PyQt and PySide
2013-03-05 00:43:51 +00:00
' enableExperimental ' : False , ## Enable experimental features (the curious can search for this key in the code)
2014-03-24 19:47:32 +00:00
' crashWarning ' : False , # If True, print warnings about situations that may result in a crash
2020-06-25 05:20:47 +00:00
' mouseRateLimit ' : 100 , # For ignoring frequent mouse events, max number of mouse move events per second, if <= 0, then it is switched off
2016-06-16 15:54:52 +00:00
' imageAxisOrder ' : ' col-major ' , # For 'row-major', image data is expected in the standard (row, col) order.
# For 'col-major', image data is expected in reversed (col, row) order.
# The default is 'col-major' for backward compatibility, but this may
2016-04-28 05:33:51 +00:00
# change in the future.
2021-01-20 05:26:24 +00:00
' useCupy ' : False , # When True, attempt to use cupy ( currently only with ImageItem and related functions )
2012-05-11 22:05:41 +00:00
}
2012-03-02 02:55:32 +00:00
2012-06-29 18:39:27 +00:00
2012-03-02 02:55:32 +00:00
def setConfigOption ( opt , value ) :
2016-08-31 22:15:03 +00:00
if opt not in CONFIG_OPTIONS :
raise KeyError ( ' Unknown configuration option " %s " ' % opt )
if opt == ' imageAxisOrder ' and value not in ( ' row-major ' , ' col-major ' ) :
raise ValueError ( ' imageAxisOrder must be either " row-major " or " col-major " ' )
2012-03-02 02:55:32 +00:00
CONFIG_OPTIONS [ opt ] = value
2012-12-26 03:20:31 +00:00
def setConfigOptions ( * * opts ) :
2016-04-28 05:33:51 +00:00
""" Set global configuration options.
Each keyword argument sets one global option .
"""
2016-08-31 22:15:03 +00:00
for k , v in opts . items ( ) :
setConfigOption ( k , v )
2012-12-25 05:43:31 +00:00
2012-03-02 02:55:32 +00:00
def getConfigOption ( opt ) :
2016-04-28 05:33:51 +00:00
""" Return the value of a single global configuration option.
"""
2012-03-02 02:55:32 +00:00
return CONFIG_OPTIONS [ opt ]
2012-03-11 15:59:45 +00:00
2012-06-29 18:39:27 +00:00
def systemInfo ( ) :
2012-07-09 12:38:30 +00:00
print ( " sys.platform: %s " % sys . platform )
print ( " sys.version: %s " % sys . version )
2012-06-29 18:39:27 +00:00
from . Qt import VERSION_INFO
2012-07-09 12:38:30 +00:00
print ( " qt bindings: %s " % VERSION_INFO )
2012-06-29 18:53:32 +00:00
2012-12-27 06:52:32 +00:00
global __version__
rev = None
if __version__ is None : ## this code was probably checked out from bzr; look up the last-revision file
lastRevFile = os . path . join ( os . path . dirname ( __file__ ) , ' .. ' , ' .bzr ' , ' branch ' , ' last-revision ' )
2012-06-29 18:53:32 +00:00
if os . path . exists ( lastRevFile ) :
2019-11-12 16:45:42 +00:00
with open ( lastRevFile , ' r ' ) as fd :
rev = fd . read ( ) . strip ( )
2012-06-29 18:53:32 +00:00
2012-12-27 06:52:32 +00:00
print ( " pyqtgraph: %s ; %s " % ( __version__ , rev ) )
2012-07-09 12:38:30 +00:00
print ( " config: " )
2012-06-29 18:39:27 +00:00
import pprint
pprint . pprint ( CONFIG_OPTIONS )
2012-03-11 15:59:45 +00:00
## Rename orphaned .pyc files. This is *probably* safe :)
2012-12-27 06:52:32 +00:00
## We only do this if __version__ is None, indicating the code was probably pulled
## from the repository.
2012-03-11 15:59:45 +00:00
def renamePyc ( startDir ) :
### Used to rename orphaned .pyc files
### When a python file changes its location in the repository, usually the .pyc file
### is left behind, possibly causing mysterious and difficult to track bugs.
2012-09-09 23:07:36 +00:00
### Note that this is no longer necessary for python 3.2; from PEP 3147:
### "If the py source file is missing, the pyc file inside __pycache__ will be ignored.
### This eliminates the problem of accidental stale pyc file imports."
2012-03-11 15:59:45 +00:00
printed = False
startDir = os . path . abspath ( startDir )
for path , dirs , files in os . walk ( startDir ) :
2012-05-11 22:05:41 +00:00
if ' __pycache__ ' in path :
continue
2012-03-11 15:59:45 +00:00
for f in files :
fileName = os . path . join ( path , f )
base , ext = os . path . splitext ( fileName )
py = base + " .py "
if ext == ' .pyc ' and not os . path . isfile ( py ) :
if not printed :
2012-05-11 22:05:41 +00:00
print ( " NOTE: Renaming orphaned .pyc files: " )
2012-03-11 15:59:45 +00:00
printed = True
n = 1
while True :
name2 = fileName + " .renamed %d " % n
if not os . path . exists ( name2 ) :
break
n + = 1
2012-05-11 22:05:41 +00:00
print ( " " + fileName + " ==> " )
print ( " " + name2 )
2012-03-11 15:59:45 +00:00
os . rename ( fileName , name2 )
path = os . path . split ( __file__ ) [ 0 ]
2012-12-27 06:52:32 +00:00
if __version__ is None and not hasattr ( sys , ' frozen ' ) and sys . version_info [ 0 ] == 2 : ## If we are frozen, there's a good chance we don't have the original .py files anymore.
2012-10-11 04:57:24 +00:00
renamePyc ( path )
2012-03-11 15:59:45 +00:00
2012-03-02 02:55:32 +00:00
## Import almost everything to make it available from a single namespace
## don't import the more complex systems--canvas, parametertree, flowchart, dockarea
## these must be imported separately.
2013-11-23 00:52:40 +00:00
#from . import frozenSupport
#def importModules(path, globals, locals, excludes=()):
#"""Import all modules residing within *path*, return a dict of name: module pairs.
2012-10-11 04:57:24 +00:00
2013-11-23 00:52:40 +00:00
#Note that *path* MUST be relative to the module doing the import.
#"""
#d = os.path.join(os.path.split(globals['__file__'])[0], path)
#files = set()
#for f in frozenSupport.listdir(d):
#if frozenSupport.isdir(os.path.join(d, f)) and f not in ['__pycache__', 'tests']:
#files.add(f)
#elif f[-3:] == '.py' and f != '__init__.py':
#files.add(f[:-3])
#elif f[-4:] == '.pyc' and f != '__init__.pyc':
#files.add(f[:-4])
2012-03-02 02:55:32 +00:00
2013-11-23 00:52:40 +00:00
#mods = {}
#path = path.replace(os.sep, '.')
#for modName in files:
#if modName in excludes:
#continue
#try:
#if len(path) > 0:
#modName = path + '.' + modName
#print( "from .%s import * " % modName)
#mod = __import__(modName, globals, locals, ['*'], 1)
#mods[modName] = mod
#except:
#import traceback
#traceback.print_stack()
#sys.excepthook(*sys.exc_info())
#print("[Error importing module: %s]" % modName)
2012-10-11 04:57:24 +00:00
2013-11-23 00:52:40 +00:00
#return mods
#def importAll(path, globals, locals, excludes=()):
#"""Given a list of modules, import all names from each module into the global namespace."""
#mods = importModules(path, globals, locals, excludes)
#for mod in mods.values():
#if hasattr(mod, '__all__'):
#names = mod.__all__
#else:
#names = [n for n in dir(mod) if n[0] != '_']
#for k in names:
#if hasattr(mod, k):
#globals[k] = getattr(mod, k)
# Dynamic imports are disabled. This causes too many problems.
#importAll('graphicsItems', globals(), locals())
#importAll('widgets', globals(), locals(),
#excludes=['MatplotlibWidget', 'RawImageWidget', 'RemoteGraphicsView'])
from . graphicsItems . VTickGroup import *
from . graphicsItems . GraphicsWidget import *
from . graphicsItems . ScaleBar import *
from . graphicsItems . PlotDataItem import *
from . graphicsItems . GraphItem import *
from . graphicsItems . TextItem import *
from . graphicsItems . GraphicsLayout import *
from . graphicsItems . UIGraphicsItem import *
from . graphicsItems . GraphicsObject import *
from . graphicsItems . PlotItem import *
from . graphicsItems . ROI import *
from . graphicsItems . InfiniteLine import *
from . graphicsItems . HistogramLUTItem import *
from . graphicsItems . GridItem import *
from . graphicsItems . GradientLegend import *
from . graphicsItems . GraphicsItem import *
from . graphicsItems . BarGraphItem import *
from . graphicsItems . ViewBox import *
from . graphicsItems . ArrowItem import *
from . graphicsItems . ImageItem import *
2020-06-25 20:07:41 +00:00
from . graphicsItems . PColorMeshItem import *
2013-11-23 00:52:40 +00:00
from . graphicsItems . AxisItem import *
Date axis item (#1154)
* Add DateAxisItem
* Change style to camelCase
* Fix missing first tick for negative timestamps
* Add ms precision, auto skipping
Auto skipping allows a zoom level to skip ticks automatically if the
maximum number of ticks/pt is exceeded
* fixes suggested by @goetzc
* workaround for negative argument to utcfromtimestamp on windows
* attachToPlotItem method
* default date axis orientation
* Use new DateAxisItem in Plot Customization example
* attachToPlotItem bugfix
* examples of DateAxisItem
* modified description of customPlot example
* added descriptions to the new examples, reformatted their code, included the first one into utils.py
* typo
* Refactored code for setting axis items into new function
Replaces "DateAxisItem.attachToPlotItem"
* Fix string comparison with ==
* Doc: Slightly more text for DateAxisItem, small improvement for PlotItem
* Make PlotWidget.setAxisItems official
* Fix typo in docstring
* renamed an example
* merge bug fix
* Revert "merge bug fix"
This reverts commit 876b5a7cdb50cd824b4a5218427081b3ce5c2fe4.
* Real bug fix
* support for dates upto -1e13..1e13
* Automatically limit DateAxisItem to a range from -1e12 to 1e12 years
Very large years (|y|>1e13) cause infinite loop, and since nobody
needs time 100 times larger than the age of the universe anyways,
this constrains it to 1e12.
Following suggestion by @axil:
https://github.com/pyqtgraph/pyqtgraph/pull/1154#issuecomment-612662168
* Also catch ValueErrors occuring on Linux before OverfloeErrors
While zooming out, before hitting OverflowErrors, utctimestamp
produces ValueErrors (at least on my Linux machine), so they
are also catched.
* Fix: Timestamp 0 corresponds to year 1970
For large years, x axis labels jump by 1970 years if it is not
accounted for timestamp 0 to be equal to year 1970.
* Fix: When zooming into extreme dates, OSError occurs
This commit catches the OSError like the other observed errors
* Disable stepping below years for dates outside *_REGULAR_TIMESTAMP
2 reasons: First: At least on my Linux machine, zooming into
those dates creates infinite loops. Second: Nobody needs
sub-year-precision for those extreme years anyways.
* Adapt zoom level sizes based on current font size and screen resolution
This is somewhat experimental. With this commit, no longer 60 px are
assumed as width for all zoom levels, but the current font and
display resolution are considered to calculate the width of ticks in
each zoom level. See the new function `updateZoomLevels` for
details.
Before calling this function, overridden functions `paint` and
`generateDrawSpecs` provide information over the current display
and font via `self.fontScaleFactor` and `self.fontMetrics`.
* Meaningful error meassage when adding axis to multiple PlotItems
As @axil noted in the DateAxisItem PR, currently users get a
segmentation fault when one tries to add an axis to multiple
PlotItems. This commit adds a meaningful RuntimeError message
for that case.
* setZoomLevelForDensity: Refactoring and calculating optimal spacing on the fly
* DateTimeAxis Fix: 1970 shows when zooming far out
* Refactoring: Make zoomLevels a customizable dict again
* updated the dateaxisitem example
* Fix: Get screen resolution in a way that also works for Qt 4
This is both a simplification in code and an improvement in backwards compatibility with Qt 4.
* DateAxisItem Fix: Also resolve time below 0.5 seconds
* unix line endings in examples
* DateTimeAxis Fix: For years < 1 and > 9999, stepping broke
Stepping was off by 1970 years for years < 1 and > 9999,
resulting in a gap in ticks visible when zooming out. Fixed by
subtracting the usual 1970 years.
* DateTimeAxis Fix: Zooming out too far causes infinite loop
Fixed by setting default limits to +/- 1e10 years. Should still
be enough.
* improved second dateaxisitem example
* 1..9999 years limit
* DateTimeAxis: Use OrderedDict to stay compatible with Python < 3-6
* DateAxisItem: Use font height to determine spacing for vertical axes
* window title
* added dateaxisitem.rst
* updated index.rst
Co-authored-by: Lukas Heiniger <lukas.heiniger@sed.ethz.ch>
Co-authored-by: Lev Maximov <lev.maximov@gmail.com>
Co-authored-by: 2xB <2xB@users.noreply.github.com>
2020-04-27 18:43:22 +00:00
from . graphicsItems . DateAxisItem import *
2013-11-23 00:52:40 +00:00
from . graphicsItems . LabelItem import *
from . graphicsItems . CurvePoint import *
from . graphicsItems . GraphicsWidgetAnchor import *
from . graphicsItems . PlotCurveItem import *
from . graphicsItems . ButtonItem import *
from . graphicsItems . GradientEditorItem import *
2021-04-06 03:50:52 +00:00
from . graphicsItems . ColorBarItem import *
2013-11-23 00:52:40 +00:00
from . graphicsItems . MultiPlotItem import *
from . graphicsItems . ErrorBarItem import *
from . graphicsItems . IsocurveItem import *
from . graphicsItems . LinearRegionItem import *
from . graphicsItems . FillBetweenItem import *
from . graphicsItems . LegendItem import *
from . graphicsItems . ScatterPlotItem import *
2021-04-11 05:42:44 +00:00
from . graphicsItems . ItemGroup import *
from . graphicsItems . TargetItem import *
2013-11-23 00:52:40 +00:00
from . widgets . MultiPlotWidget import *
from . widgets . ScatterPlotWidget import *
from . widgets . ColorMapWidget import *
from . widgets . FileDialog import *
from . widgets . ValueLabel import *
from . widgets . HistogramLUTWidget import *
from . widgets . CheckTable import *
from . widgets . BusyCursor import *
from . widgets . PlotWidget import *
from . widgets . ComboBox import *
from . widgets . GradientWidget import *
from . widgets . DataFilterWidget import *
from . widgets . SpinBox import *
from . widgets . JoystickButton import *
from . widgets . GraphicsLayoutWidget import *
from . widgets . TreeWidget import *
from . widgets . PathButton import *
from . widgets . VerticalLabel import *
from . widgets . FeedbackButton import *
from . widgets . ColorButton import *
from . widgets . DataTreeWidget import *
2014-09-25 21:26:06 +00:00
from . widgets . DiffTreeWidget import *
2013-11-23 00:52:40 +00:00
from . widgets . GraphicsView import *
from . widgets . LayoutWidget import *
from . widgets . TableWidget import *
from . widgets . ProgressDialog import *
2017-09-03 23:48:08 +00:00
from . widgets . GroupBox import GroupBox
2019-11-19 16:15:27 +00:00
from . widgets . RemoteGraphicsView import RemoteGraphicsView
2012-03-02 02:55:32 +00:00
2012-05-11 22:05:41 +00:00
from . imageview import *
from . WidgetGroup import *
from . Point import Point
2012-05-30 03:18:34 +00:00
from . Vector import Vector
2012-05-31 20:22:50 +00:00
from . SRTTransform import SRTTransform
2012-10-27 01:47:45 +00:00
from . Transform3D import Transform3D
2012-05-31 20:22:50 +00:00
from . SRTTransform3D import SRTTransform3D
2012-05-11 22:05:41 +00:00
from . functions import *
from . graphicsWindows import *
from . SignalProxy import *
2013-02-10 22:45:16 +00:00
from . colormap import *
2012-05-11 22:05:41 +00:00
from . ptime import time
2014-04-15 19:49:17 +00:00
from . Qt import isQObjectAlive
2020-07-08 13:03:32 +00:00
from . ThreadsafeTimer import *
2012-03-02 02:55:32 +00:00
2013-11-23 00:52:40 +00:00
2013-03-07 20:29:56 +00:00
##############################################################
## PyQt and PySide both are prone to crashing on exit.
## There are two general approaches to dealing with this:
## 1. Install atexit handlers that assist in tearing down to avoid crashes.
## This helps, but is never perfect.
## 2. Terminate the process before python starts tearing down
## This is potentially dangerous
2012-03-02 02:55:32 +00:00
2013-03-07 20:29:56 +00:00
## Attempts to work around exit crashes:
2012-06-18 18:01:51 +00:00
import atexit
2014-11-27 02:25:17 +00:00
_cleanupCalled = False
2012-06-18 18:01:51 +00:00
def cleanup ( ) :
2014-11-27 02:25:17 +00:00
global _cleanupCalled
if _cleanupCalled :
return
2013-03-07 20:29:56 +00:00
if not getConfigOption ( ' exitCleanup ' ) :
return
2012-12-05 02:02:05 +00:00
ViewBox . quit ( ) ## tell ViewBox that it doesn't need to deregister views anymore.
## Workaround for Qt exit crash:
## ALL QGraphicsItems must have a scene before they are deleted.
## This is potentially very expensive, but preferred over crashing.
## Note: this appears to be fixed in PySide as of 2012.12, but it should be left in for a while longer..
2016-11-28 14:41:56 +00:00
app = QtGui . QApplication . instance ( )
if app is None or not isinstance ( app , QtGui . QApplication ) :
# app was never constructed is already deleted or is an
# QCoreApplication/QGuiApplication and not a full QApplication
2012-06-18 18:01:51 +00:00
return
import gc
s = QtGui . QGraphicsScene ( )
for o in gc . get_objects ( ) :
try :
2014-03-13 20:38:50 +00:00
if isinstance ( o , QtGui . QGraphicsItem ) and isQObjectAlive ( o ) and o . scene ( ) is None :
2014-03-24 19:47:32 +00:00
if getConfigOption ( ' crashWarning ' ) :
sys . stderr . write ( ' Error: graphics item without scene. '
' Make sure ViewBox.close() and GraphicsView.close() '
' are properly called before app shutdown ( %s ) \n ' % ( o , ) )
2014-03-13 20:38:50 +00:00
2012-06-18 18:01:51 +00:00
s . addItem ( o )
2017-12-18 15:57:31 +00:00
except ( RuntimeError , ReferenceError ) : ## occurs if a python wrapper no longer has its underlying C++ object
2012-06-18 18:01:51 +00:00
continue
2014-11-27 02:25:17 +00:00
_cleanupCalled = True
2012-06-18 18:01:51 +00:00
atexit . register ( cleanup )
2012-03-02 02:55:32 +00:00
2014-11-27 02:25:17 +00:00
# Call cleanup when QApplication quits. This is necessary because sometimes
# the QApplication will quit before the atexit callbacks are invoked.
# Note: cannot connect this function until QApplication has been created, so
# instead we have GraphicsView.__init__ call this for us.
_cleanupConnected = False
def _connectCleanup ( ) :
global _cleanupConnected
if _cleanupConnected :
return
QtGui . QApplication . instance ( ) . aboutToQuit . connect ( cleanup )
_cleanupConnected = True
2012-03-02 02:55:32 +00:00
2013-03-07 20:29:56 +00:00
## Optional function for exiting immediately (with some manual teardown)
def exit ( ) :
"""
Causes python to exit without garbage - collecting any objects , and thus avoids
calling object destructor methods . This is a sledgehammer workaround for
a variety of bugs in PyQt and Pyside that cause crashes on exit .
This function does the following in an attempt to ' safely ' terminate
the process :
* Invoke atexit callbacks
* Close all open file handles
* os . _exit ( )
Note : there is some potential for causing damage with this function if you
are using objects that _require_ their destructors to be called ( for example ,
to properly terminate log files , disconnect from devices , etc ) . Situations
like this are probably quite rare , but use at your own risk .
"""
## first disable our own cleanup function; won't be needing it.
setConfigOptions ( exitCleanup = False )
## invoke atexit callbacks
atexit . _run_exitfuncs ( )
## close file handles
2014-08-07 13:03:26 +00:00
if sys . platform == ' darwin ' :
2015-05-19 13:29:55 +00:00
for fd in range ( 3 , 4096 ) :
2019-06-23 19:14:52 +00:00
if fd in [ 7 ] : # trying to close 7 produces an illegal instruction on the Mac.
continue
try :
2014-08-07 13:03:26 +00:00
os . close ( fd )
2019-06-23 19:14:52 +00:00
except OSError :
pass
2014-08-07 13:03:26 +00:00
else :
os . closerange ( 3 , 4096 ) ## just guessing on the maximum descriptor count..
2013-07-10 04:02:16 +00:00
os . _exit ( 0 )
2013-03-07 20:29:56 +00:00
2012-06-18 18:01:51 +00:00
## Convenience functions for command-line use
2011-02-08 00:40:38 +00:00
plots = [ ]
images = [ ]
QAPP = None
def plot ( * args , * * kargs ) :
2012-03-02 02:55:32 +00:00
"""
2021-02-12 05:55:04 +00:00
Create and return a : class : ` PlotWidget < pyqtgraph . PlotWinPlotWidgetdow > `
2012-04-18 04:02:15 +00:00
Accepts a * title * argument to set the title of the window .
All other arguments are used to plot data . ( see : func : ` PlotItem . plot ( ) < pyqtgraph . PlotItem . plot > ` )
2012-03-02 02:55:32 +00:00
"""
2021-02-14 20:05:22 +00:00
mkQApp ( )
2013-08-24 04:27:09 +00:00
pwArgList = [ ' title ' , ' labels ' , ' name ' , ' left ' , ' right ' , ' top ' , ' bottom ' , ' background ' ]
2012-03-23 07:21:04 +00:00
pwArgs = { }
dataArgs = { }
for k in kargs :
if k in pwArgList :
pwArgs [ k ] = kargs [ k ]
else :
dataArgs [ k ] = kargs [ k ]
2021-02-12 05:55:04 +00:00
windowTitle = pwArgs . pop ( " title " , " PlotWidget " )
w = PlotWidget ( * * pwArgs )
w . setWindowTitle ( windowTitle )
2013-12-19 17:30:00 +00:00
if len ( args ) > 0 or len ( dataArgs ) > 0 :
w . plot ( * args , * * dataArgs )
2011-02-08 00:40:38 +00:00
plots . append ( w )
w . show ( )
return w
Patch/window handling (#468)
* Do not wrap PlotView/ImageView
There is no need to wrap PlotView/ImageView into QMainWindow, since
only purpose of the QMainWindow is some default menu toolbar & menu
handling, that is not used by PyQtGraph anyway.
Moreover, every parent-less Qt widget can become window, so this
change just use PlotView/ImageView as windows, removing extra
complexity, eg. method forwarding, self.win property.
Another benefit of this change, it that these windows get initial
dimensions and titles as they were designed in .ui file.
* Properly cleanup on ImageView.close()
We should not close explicitly child widgets or clear scene, otherwise
Qt will deallocate children views, and cause "wrapped C/C++ object of
type ImageItem has been deleted" error next time we call close()
and/or some other methods.
All children, including self.ui.roiPlot, self.ui.graphicsView will be
closed together with its parent, so there is no need to close them
explicitly.
So the purpose of close it to reclaim the memory, but not to make the existing ImageView object dysfunctional.
* Remove references to plot & image windows after close
PyQtGraph images and plots module list variables are currently holding
references to all plots and image windows returned directly from main
module. This does not seem to be documented however, and causes the Qt
windows to be not released from memory, even if user releases all own
references.
This change removes the references from images/plots list once window
is closed, so when there is no other reference, window and all related
memory is reclaimed.
* Change all UI forms title from Form to PyQtGraph
Co-authored-by: Ogi Moore <ognyan.moore@gmail.com>
2020-06-01 18:23:18 +00:00
2012-03-02 02:55:32 +00:00
def image ( * args , * * kargs ) :
"""
2021-02-12 05:55:04 +00:00
Create and return an : class : ` ImageView < pyqtgraph . ImageView > `
2012-04-18 04:02:15 +00:00
Will show 2 D or 3 D image data .
Accepts a * title * argument to set the title of the window .
All other arguments are used to show data . ( see : func : ` ImageView . setImage ( ) < pyqtgraph . ImageView . setImage > ` )
2012-03-02 02:55:32 +00:00
"""
2011-02-08 00:40:38 +00:00
mkQApp ( )
2021-02-12 05:55:04 +00:00
w = ImageView ( )
windowTitle = kargs . pop ( " title " , " ImageView " )
w . setWindowTitle ( windowTitle )
w . setImage ( * args , * * kargs )
2011-02-08 00:40:38 +00:00
images . append ( w )
w . show ( )
return w
2012-03-02 02:55:32 +00:00
show = image ## for backward compatibility
2012-10-03 01:23:59 +00:00
Patch/window handling (#468)
* Do not wrap PlotView/ImageView
There is no need to wrap PlotView/ImageView into QMainWindow, since
only purpose of the QMainWindow is some default menu toolbar & menu
handling, that is not used by PyQtGraph anyway.
Moreover, every parent-less Qt widget can become window, so this
change just use PlotView/ImageView as windows, removing extra
complexity, eg. method forwarding, self.win property.
Another benefit of this change, it that these windows get initial
dimensions and titles as they were designed in .ui file.
* Properly cleanup on ImageView.close()
We should not close explicitly child widgets or clear scene, otherwise
Qt will deallocate children views, and cause "wrapped C/C++ object of
type ImageItem has been deleted" error next time we call close()
and/or some other methods.
All children, including self.ui.roiPlot, self.ui.graphicsView will be
closed together with its parent, so there is no need to close them
explicitly.
So the purpose of close it to reclaim the memory, but not to make the existing ImageView object dysfunctional.
* Remove references to plot & image windows after close
PyQtGraph images and plots module list variables are currently holding
references to all plots and image windows returned directly from main
module. This does not seem to be documented however, and causes the Qt
windows to be not released from memory, even if user releases all own
references.
This change removes the references from images/plots list once window
is closed, so when there is no other reference, window and all related
memory is reclaimed.
* Change all UI forms title from Form to PyQtGraph
Co-authored-by: Ogi Moore <ognyan.moore@gmail.com>
2020-06-01 18:23:18 +00:00
2013-11-07 04:14:27 +00:00
def dbg ( * args , * * kwds ) :
2012-10-03 01:23:59 +00:00
"""
Create a console window and begin watching for exceptions .
2013-11-07 04:14:27 +00:00
All arguments are passed to : func : ` ConsoleWidget . __init__ ( ) < pyqtgraph . console . ConsoleWidget . __init__ > ` .
2012-10-03 01:23:59 +00:00
"""
mkQApp ( )
2013-09-10 04:31:43 +00:00
from . import console
2013-11-07 04:14:27 +00:00
c = console . ConsoleWidget ( * args , * * kwds )
2012-10-03 01:23:59 +00:00
c . catchAllExceptions ( )
c . show ( )
global consoles
try :
consoles . append ( c )
except NameError :
consoles = [ c ]
2014-02-18 01:02:42 +00:00
return c
2018-01-24 17:06:37 +00:00
def stack ( * args , * * kwds ) :
"""
Create a console window and show the current stack trace .
2012-03-02 02:55:32 +00:00
2018-01-24 17:06:37 +00:00
All arguments are passed to : func : ` ConsoleWidget . __init__ ( ) < pyqtgraph . console . ConsoleWidget . __init__ > ` .
"""
mkQApp ( )
from . import console
c = console . ConsoleWidget ( * args , * * kwds )
c . setStack ( )
c . show ( )
global consoles
try :
consoles . append ( c )
except NameError :
consoles = [ c ]
return c