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
"""
2012-12-27 16:53:22 +00:00
__version__ = None
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.
2012-06-29 18:39:27 +00:00
from . Qt import QtGui
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([])
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-10-03 01:23:59 +00:00
## install workarounds for numpy bugs
2012-12-05 05:25:45 +00:00
from . import numpy_fix
2012-10-03 01:23:59 +00:00
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
if QtGui . QApplication . instance ( ) is not None :
print ( ' Warning: QApplication was created before pyqtgraph was imported; there may be problems (to avoid bugs, call QApplication.setGraphicsSystem( " raster " ) before the QApplication is created). ' )
QtGui . QApplication . setGraphicsSystem ( ' raster ' ) ## work around a variety of bugs in the native graphics system
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
2012-06-29 18:39:27 +00:00
' foreground ' : ( 150 , 150 , 150 ) , ## default foreground color for axes, labels, etc.
' background ' : ( 0 , 0 , 0 ) , ## 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
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 ) :
CONFIG_OPTIONS [ opt ] = value
2012-12-26 03:20:31 +00:00
def setConfigOptions ( * * opts ) :
2012-12-25 05:43:31 +00:00
CONFIG_OPTIONS . update ( opts )
2012-03-02 02:55:32 +00:00
def getConfigOption ( opt ) :
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 ) :
2012-12-27 06:52:32 +00:00
rev = open ( lastRevFile , ' r ' ) . 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.
2012-12-05 05:25:45 +00:00
from . import frozenSupport
2012-10-11 04:57:24 +00:00
def importModules ( path , globals , locals , excludes = ( ) ) :
""" Import all modules residing within *path*, return a dict of name: module pairs.
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 != ' __pycache__ ' :
files . add ( f )
2012-03-02 02:55:32 +00:00
elif f [ - 3 : ] == ' .py ' and f != ' __init__.py ' :
2012-10-11 04:57:24 +00:00
files . add ( f [ : - 3 ] )
elif f [ - 4 : ] == ' .pyc ' and f != ' __init__.pyc ' :
files . add ( f [ : - 4 ] )
2012-03-02 02:55:32 +00:00
2012-10-11 04:57:24 +00:00
mods = { }
path = path . replace ( os . sep , ' . ' )
2012-03-02 02:55:32 +00:00
for modName in files :
2012-03-24 02:13:41 +00:00
if modName in excludes :
continue
2012-10-11 04:57:24 +00:00
try :
if len ( path ) > 0 :
modName = path + ' . ' + modName
mod = __import__ ( modName , globals , locals , fromlist = [ ' * ' ] )
mods [ modName ] = mod
except :
import traceback
traceback . print_stack ( )
sys . excepthook ( * sys . exc_info ( ) )
print ( " [Error importing module: %s ] " % modName )
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 ( ) :
2012-03-02 02:55:32 +00:00
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 ) :
2012-10-11 04:57:24 +00:00
globals [ k ] = getattr ( mod , k )
2012-03-02 02:55:32 +00:00
2012-10-11 04:57:24 +00:00
importAll ( ' graphicsItems ' , globals ( ) , locals ( ) )
importAll ( ' widgets ' , globals ( ) , locals ( ) , excludes = [ ' MatplotlibWidget ' , ' 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 *
from . ptime import time
2012-03-02 02:55:32 +00:00
2012-06-18 18:01:51 +00:00
import atexit
def cleanup ( ) :
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..
2012-06-18 18:01:51 +00:00
if QtGui . QApplication . instance ( ) is None :
return
import gc
s = QtGui . QGraphicsScene ( )
for o in gc . get_objects ( ) :
try :
if isinstance ( o , QtGui . QGraphicsItem ) and o . scene ( ) is None :
s . addItem ( o )
except RuntimeError : ## occurs if a python wrapper no longer has its underlying C++ object
continue
atexit . register ( cleanup )
2012-03-02 02:55:32 +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
"""
2012-04-18 04:02:15 +00:00
Create and return a : class : ` PlotWindow < pyqtgraph . PlotWindow > `
( this is just a window with : class : ` PlotWidget < pyqtgraph . PlotWidget > ` inside ) , plot data in it .
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
"""
2011-02-08 00:40:38 +00:00
mkQApp ( )
2012-03-23 06:45:11 +00:00
#if 'title' in kargs:
#w = PlotWindow(title=kargs['title'])
#del kargs['title']
#else:
#w = PlotWindow()
#if len(args)+len(kargs) > 0:
#w.plot(*args, **kargs)
2012-03-23 07:21:04 +00:00
2012-08-31 21:18:06 +00:00
pwArgList = [ ' title ' , ' labels ' , ' name ' , ' left ' , ' right ' , ' top ' , ' bottom ' ]
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 ]
w = PlotWindow ( * * pwArgs )
w . plot ( * args , * * dataArgs )
2011-02-08 00:40:38 +00:00
plots . append ( w )
w . show ( )
return w
2012-03-02 02:55:32 +00:00
def image ( * args , * * kargs ) :
"""
2012-04-18 04:02:15 +00:00
Create and return an : class : ` ImageWindow < pyqtgraph . ImageWindow > `
( this is just a window with : class : ` ImageView < pyqtgraph . ImageView > ` widget inside ) , show image data inside .
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 ( )
w = ImageWindow ( * args , * * kargs )
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
def dbg ( ) :
"""
Create a console window and begin watching for exceptions .
"""
mkQApp ( )
import console
c = console . ConsoleWidget ( )
c . catchAllExceptions ( )
c . show ( )
global consoles
try :
consoles . append ( c )
except NameError :
consoles = [ c ]
2012-03-02 02:55:32 +00:00
2011-02-08 00:40:38 +00:00
def mkQApp ( ) :
2012-06-18 18:01:51 +00:00
global QAPP
2012-06-18 23:40:15 +00:00
inst = QtGui . QApplication . instance ( )
if inst is None :
2012-03-11 15:59:45 +00:00
QAPP = QtGui . QApplication ( [ ] )
2012-06-18 23:40:15 +00:00
else :
QAPP = inst
2012-06-18 18:01:51 +00:00
return QAPP
2012-03-11 15:59:45 +00:00