Examples
The test launcher
A lot of examples are available in the guiqwt test module
from guiqwt import tests
tests.run()
The two lines above execute the guiqwt test launcher:
Curve plotting
Basic curve plotting
from guidata.qt.QtGui import QFont
from guiqwt.plot import CurveDialog
from guiqwt.builder import make
def plot(*items):
win = CurveDialog(edit=False, toolbar=True, wintitle="CurveDialog test",
options=dict(title="Title", xlabel="xlabel",
ylabel="ylabel"))
plot = win.get_plot()
for item in items:
plot.add_item(item)
plot.set_axis_font("left", QFont("Courier"))
win.get_itemlist_panel().show()
plot.set_items_readonly(False)
win.show()
win.exec_()
def test():
"""Test"""
# -- Create QApplication
import guidata
_app = guidata.qapplication()
# --
from numpy import linspace, sin
x = linspace(-10, 10, 200)
dy = x/100.
y = sin(sin(sin(x)))
x2 = linspace(-10, 10, 20)
y2 = sin(sin(sin(x2)))
plot(make.curve(x, y, color="b"),
make.curve(x2, y2, color="g", curvestyle="Sticks"),
make.curve(x, sin(2*y), color="r"),
make.merror(x, y/2, dy),
make.label("Relative position <b>outside</b>",
(x[0], y[0]), (-10, -10), "BR"),
make.label("Relative position <i>inside</i>",
(x[0], y[0]), (10, 10), "TL"),
make.label("Absolute position", "R", (0,0), "R"),
make.legend("TR"),
make.marker(position=(5., .8), label_cb=lambda x, y: u"A = %.2f" % x,
markerstyle="|", movable=False)
)
if __name__ == "__main__":
test()
Computations on curves
from guiqwt.plot import CurveDialog
from guiqwt.builder import make
def plot( *items ):
win = CurveDialog(edit=False, toolbar=True)
plot = win.get_plot()
for item in items:
plot.add_item(item)
win.show()
win.exec_()
def test():
"""Test"""
# -- Create QApplication
import guidata
_app = guidata.qapplication()
# --
from numpy import linspace, sin, trapz
x = linspace(-10, 10, 1000)
y = sin(sin(sin(x)))
curve = make.curve(x, y, "ab", "b")
range = make.range(-2, 2)
disp0 = make.range_info_label(range, 'BR', u"x = %.1f ± %.1f cm",
title="Range infos")
disp1 = make.computation(range, "BL", "trapz=%g",
curve, lambda x,y: trapz(y,x))
disp2 = make.computations(range, "TL",
[(curve, "min=%.5f", lambda x,y: y.min()),
(curve, "max=%.5f", lambda x,y: y.max()),
(curve, "avg=%.5f", lambda x,y: y.mean())])
legend = make.legend("TR")
plot( curve, range, disp0, disp1, disp2, legend)
if __name__ == "__main__":
test()
Curve fitting
import numpy as np
from guiqwt.widgets.fit import FitParam, guifit
def test():
x = np.linspace(-10, 10, 1000)
y = np.cos(1.5*x)+np.random.rand(x.shape[0])*.2
def fit(x, params):
a, b = params
return np.cos(b*x)+a
a = FitParam("Offset", 1., 0., 2.)
b = FitParam("Frequency", 2., 1., 10., logscale=True)
params = [a, b]
values = guifit(x, y, fit, params, xlabel="Time (s)", ylabel="Power (a.u.)")
print values
print [param.value for param in params]
if __name__ == "__main__":
test()
Image visualization
Image contrast adjustment
import os.path as osp
from guiqwt.plot import ImageDialog
from guiqwt.builder import make
def test():
"""Test"""
# -- Create QApplication
import guidata
_app = guidata.qapplication()
# --
filename = osp.join(osp.dirname(__file__), "brain.png")
image = make.image(filename=filename, title="Original", colormap='gray')
win = ImageDialog(edit=False, toolbar=True, wintitle="Contrast test",
options=dict(show_contrast=True))
plot = win.get_plot()
plot.add_item(image)
win.resize(600, 600)
win.show()
try:
plot.save_widget('contrast.png')
except IOError:
# Skipping this part of the test
# because user has no write permission on current directory
pass
win.exec_()
if __name__ == "__main__":
test()
Image cross-sections
import os.path as osp, numpy as np
from guiqwt.plot import ImageDialog
from guiqwt.builder import make
def create_window():
win = ImageDialog(edit=False, toolbar=True, wintitle="Cross sections test",
options=dict(show_xsection=True, show_ysection=True))
win.resize(600, 600)
return win
def test():
"""Test"""
# -- Create QApplication
import guidata
_app = guidata.qapplication()
# --
filename = osp.join(osp.dirname(__file__), "brain.png")
win = create_window()
image = make.image(filename=filename, colormap="bone")
data2 = np.array(image.data.T[200:], copy=True)
image2 = make.image(data2, title="Modified", alpha_mask=True)
plot = win.get_plot()
plot.add_item(image)
plot.add_item(image2, z=1)
win.exec_()
if __name__ == "__main__":
test()
Transformable images
Affine transforms example on 3000x3000 images (real-time transforms):
from guidata.qt.QtCore import QRectF
from guidata.qt.QtGui import QImage
import numpy as np
from guiqwt.image import assemble_imageitems
from guiqwt.plot import ImageDialog
from guiqwt.builder import make
from guiqwt import io
DEFAULT_CHARS = "".join([chr(c) for c in range(32,256)])
def get_font_array(sz, chars=DEFAULT_CHARS):
from guidata.qt.QtGui import QFont, QPainter, QColor
font = QFont()
font.setFixedPitch(True)
font.setPixelSize(sz)
font.setStyleStrategy(QFont.NoAntialias)
dummy = QImage(10, 10, QImage.Format_ARGB32)
pnt = QPainter(dummy)
pnt.setFont(font)
metric = pnt.fontMetrics()
rct = metric.boundingRect(chars)
pnt.end()
h = rct.height()
w = rct.width()
img = QImage(w, h, QImage.Format_ARGB32)
paint = QPainter()
paint.begin(img)
paint.setFont(font)
paint.setBrush( QColor(255, 255, 255) )
paint.setPen( QColor(255, 255, 255) )
paint.drawRect(0, 0, w+1, h+1)
paint.setPen( QColor(0, 0, 0))
paint.setBrush( QColor(0, 0, 0) )
paint.drawText(0, paint.fontMetrics().ascent(), chars)
paint.end()
data = img.bits().asstring(img.numBytes())
npy = np.frombuffer(data, np.uint8)
npy.shape = img.height(), img.bytesPerLine()/4, 4
return npy[:, :, 0]
def txtwrite(data, x, y, sz, txt, range=None):
arr = get_font_array(sz, txt)
if range is None:
m, M = data.min(),data.max()
else:
m, M = range
z = (float(M)-float(m))*np.array(arr, float)/255.+m
arr = np.array(z, data.dtype)
dy, dx = arr.shape
data[y:y+dy, x:x+dx] = arr
def imshow(items, title=""):
gridparam = make.gridparam(background="black", minor_enabled=(False, False),
major_style=(".", "gray", 1))
win = ImageDialog(edit=False, toolbar=True, wintitle=title,
options=dict(gridparam=gridparam))
nc = int(np.sqrt(len(items))+1.0)
maxy = 0
y = 0
x = 0
w = None
plot = win.get_plot()
print "-"*80
for i, item in enumerate(items):
h = item.boundingRect().height()
if i%nc==0:
x = 0
y += maxy
maxy = h
else:
x += w
maxy = max(maxy,h)
w = item.boundingRect().width()
item.set_transform(x, y, 0.0)
print "Adding item #%d..." % i,
plot.add_item(item)
print "Done"
win.show()
win.exec_()
def compute_image(NX, NY):
BX, BY = 40, 40
img = np.random.normal(0,100,size=(BX, BY))
timg = np.fft.fftshift(np.fft.fft2(img))
print timg.shape
cx = NX/2
cy = NY/2
bx2 = BX/2
by2 = BY/2
z=np.zeros( (NX, NY), np.complex64)
z[cx-bx2:cx-bx2+BX, cy-by2:cy-by2+BY] = timg
z = np.fft.ifftshift(z)
rev = np.fft.ifft2(z)
return np.abs(rev)
def get_bbox(items):
r = QRectF()
for it in items:
r = r.united(it.boundingRect())
return r
def save_image(name, data):
io.imwrite(name+".u16.tif", data, dtype=np.uint16, max_range=True)
io.imwrite(name+".u8.png", data, dtype=np.uint8, max_range=True)
def build_image(items):
r = get_bbox(items)
x,y,w,h = r.getRect()
print "Assemble test1:", w,"x", h
dest = assemble_imageitems(items, r, w, h, align=4)
print "saving..."
save_image("test1.png", dest)
print "Assemble test2:", w/4,"x", h/4
dest = assemble_imageitems(items, r, w/4, h/4, align=4)
save_image("test2.png", dest)
def test():
"""Test"""
N = 500
data = compute_image(N, N)
m = data.min()
M = data.max()
items = [make.trimage(data, alpha_mask=True, colormap="jet")]
for type in (np.uint8, np.uint16, np.int8, np.int16):
info = np.iinfo(type().dtype)
s = float((info.max-info.min))
a1 = s*(data-m)/(M-m)
img = np.array(a1+info.min, type)
txtwrite(img, 0, 0, N/15., str(type))
items.append(make.trimage(img, colormap="jet"))
imshow(items, title=u"Transform test (%dx%d images)" % (N, N))
return items
if __name__ == "__main__":
# -- Create QApplication
import guidata
_app = guidata.qapplication()
# --
items = test()
build_image(items)
Image rectangular filter
from scipy.ndimage import gaussian_filter
from guiqwt.plot import ImageDialog
from guiqwt.builder import make
def imshow(x, y, data, filter_area, yreverse=True):
win = ImageDialog(edit=False, toolbar=True, wintitle="Image filter demo",
options=dict(xlabel="x (cm)", ylabel="y (cm)",
yreverse=yreverse))
image = make.xyimage(x, y, data)
plot = win.get_plot()
plot.add_item(image)
xmin, xmax, ymin, ymax = filter_area
flt = make.imagefilter(xmin, xmax, ymin, ymax, image,
filter=lambda x, y, data: gaussian_filter(data, 5))
plot.add_item(flt, z=1)
plot.replot()
win.show()
win.exec_()
def test():
"""Test"""
# -- Create QApplication
import guidata
_app = guidata.qapplication()
# --
from guiqwt.tests.imagexy import compute_image
x, y, data = compute_image()
imshow(x, y, data, filter_area=(-3., -1., 0., 2.), yreverse=False)
# --
import os.path as osp, numpy as np
from guiqwt import io
filename = osp.join(osp.dirname(__file__), "brain.png")
data = io.imread(filename, to_grayscale=True)
x = np.linspace(0, 30., data.shape[1])
y = np.linspace(0, 30., data.shape[0])
imshow(x, y, data, filter_area=(10, 20, 5, 15))
if __name__ == "__main__":
test()
Histograms
2-D histogram
from numpy import random, array, dot, concatenate
from guiqwt.plot import ImageDialog
from guiqwt.builder import make
from guiqwt.config import _
def hist2d(X, Y):
win = ImageDialog(edit=True, toolbar=True,
wintitle="2-D Histogram X0=(0,1), X1=(-1,-1)")
hist2d = make.histogram2D(X, Y, 200, 200)
curve = make.curve(X[::50], Y[::50],
linestyle='', marker='+', title=_("Markers"))
plot = win.get_plot()
plot.set_aspect_ratio(lock=False)
plot.set_antialiasing(False)
plot.add_item(hist2d)
plot.add_item(curve)
plot.set_item_visible(curve, False)
win.show()
win.exec_()
if __name__ == "__main__":
import guidata
_app = guidata.qapplication()
N = 150000
m = array([[ 1., .2], [-.2, 3.]])
X1 = random.normal(0, .3, size=(N, 2))
X2 = random.normal(0, .3, size=(N, 2))
X = concatenate((X1+[0, 1.], dot(X2, m)+[-1, -1.]))
hist2d(X[:, 0], X[:, 1])
Other examples
Image plot tools
import os.path as osp
from guiqwt.plot import ImageDialog
from guiqwt.tools import (RectangleTool, EllipseTool, HRangeTool, PlaceAxesTool,
MultiLineTool, FreeFormTool, SegmentTool, CircleTool,
AnnotatedRectangleTool, AnnotatedEllipseTool,
AnnotatedSegmentTool, AnnotatedCircleTool, LabelTool,
AnnotatedPointTool,
VCursorTool, HCursorTool, XCursorTool,
ObliqueRectangleTool, AnnotatedObliqueRectangleTool)
from guiqwt.builder import make
def create_window():
win = ImageDialog(edit=False, toolbar=True,
wintitle="All image and plot tools test")
for toolklass in (LabelTool, HRangeTool,
VCursorTool, HCursorTool, XCursorTool,
SegmentTool, RectangleTool, ObliqueRectangleTool,
CircleTool, EllipseTool,
MultiLineTool, FreeFormTool, PlaceAxesTool,
AnnotatedRectangleTool, AnnotatedObliqueRectangleTool,
AnnotatedCircleTool, AnnotatedEllipseTool,
AnnotatedSegmentTool, AnnotatedPointTool):
win.add_tool(toolklass)
return win
def test():
"""Test"""
# -- Create QApplication
import guidata
_app = guidata.qapplication()
# --
filename = osp.join(osp.dirname(__file__), "brain.png")
win = create_window()
image = make.image(filename=filename, colormap="bone")
plot = win.get_plot()
plot.add_item(image)
win.exec_()
if __name__ == "__main__":
test()
Real-time Mandelbrot plotting
import numpy as np
from guidata.qt.QtCore import QRectF, QPointF
from guiqwt.config import _
from guiqwt.plot import ImageDialog
from guiqwt.image import RawImageItem
from guiqwt.tools import ToggleTool
from guiqwt._mandel import mandel
mandelbrot = mandel.mandelbrot
class FullScale(ToggleTool):
def __init__(self, parent, image):
super(FullScale, self).__init__(parent, _(u"MAX resolution"), None)
self.image = image
self.minprec = image.IMAX
self.maxprec = 5*image.IMAX
def activate_command(self, plot, checked):
if self.image.IMAX == self.minprec:
self.image.IMAX = self.maxprec
else:
self.image.IMAX = self.minprec
self.image.set_lut_range([0, self.image.IMAX])
plot.replot()
def update_status(self, plot):
self.action.setChecked(self.image.IMAX == self.maxprec)
class MandelItem(RawImageItem):
def __init__(self, xmin, xmax, ymin, ymax):
super(MandelItem, self).__init__(np.zeros((1, 1), np.int16, order='F'))
self.bounds = QRectF(QPointF(xmin, ymin),
QPointF(xmax, ymax))
self.update_border()
self.IMAX = 80
self.set_lut_range([0, self.IMAX])
#---- QwtPlotItem API ------------------------------------------------------
def draw_image(self, painter, canvasRect, srcRect, dstRect, xMap, yMap):
x1, y1 = canvasRect.left(), canvasRect.top()
x2, y2 = canvasRect.right(), canvasRect.bottom()
i1, j1, i2, j2 = srcRect
NX = x2-x1
NY = y2-y1
if self.data.shape != (NX, NY):
self.data = np.zeros((NX, NY), np.int16, order='F')
orig = complex(i1, j1)
dx = (i2-i1)/(NX-1)
dy = 1j*(j2-j1)/(NY-1)
NMAX = self.IMAX
mandelbrot(orig, dx, dy, self.data, NMAX)
self.data = self.data.T
srcRect = (0, 0, NX, NY)
x1, y1, x2, y2 = canvasRect.getCoords()
RawImageItem.draw_image(self, painter, canvasRect,
srcRect, (x1, y1, x2, y2), xMap, yMap)
def mandel():
win = ImageDialog(edit=True, toolbar=True, wintitle="Mandelbrot",
options=dict(yreverse=False))
mandel = MandelItem(-1.5, .5, -1., 1.)
win.add_tool(FullScale, mandel)
plot = win.get_plot()
plot.set_aspect_ratio(lock=False)
plot.add_item(mandel)
plot.set_full_scale(mandel)
win.show()
win.exec_()
if __name__ == "__main__":
import guidata
_app = guidata.qapplication()
mandel()
Simple application
from guidata.qt.QtGui import QMainWindow, QMessageBox, QSplitter, QListWidget
from guidata.qt.QtCore import (QSize, QT_VERSION_STR, PYQT_VERSION_STR, Qt,
SIGNAL)
from guidata.qt.compat import getopenfilename
import sys, platform
import numpy as np
from guidata.dataset.datatypes import DataSet, GetAttrProp
from guidata.dataset.dataitems import (IntItem, FloatArrayItem, StringItem,
ChoiceItem)
from guidata.dataset.qtwidgets import DataSetEditGroupBox
from guidata.configtools import get_icon
from guidata.qthelpers import create_action, add_actions, get_std_icon
from guidata.utils import update_dataset
from guiqwt.config import _
from guiqwt.plot import ImageWidget
from guiqwt.builder import make
from guiqwt.signals import SIG_LUT_CHANGED
from guiqwt import io
APP_NAME = _("Application example")
VERSION = '1.0.0'
class ImageParam(DataSet):
_hide_data = False
_hide_size = True
title = StringItem(_("Title"), default=_("Untitled"))
data = FloatArrayItem(_("Data")).set_prop("display",
hide=GetAttrProp("_hide_data"))
width = IntItem(_("Width"), help=_("Image width (pixels)"), min=1,
default=100).set_prop("display",
hide=GetAttrProp("_hide_size"))
height = IntItem(_("Height"), help=_("Image height (pixels)"), min=1,
default=100).set_prop("display",
hide=GetAttrProp("_hide_size"))
class ImageParamNew(ImageParam):
_hide_data = True
_hide_size = False
type = ChoiceItem(_("Type"),
(("rand", _("random")), ("zeros", _("zeros"))))
class ImageListWithProperties(QSplitter):
def __init__(self, parent):
QSplitter.__init__(self, parent)
self.imagelist = QListWidget(self)
self.addWidget(self.imagelist)
self.properties = DataSetEditGroupBox(_("Properties"), ImageParam)
self.properties.setEnabled(False)
self.addWidget(self.properties)
class CentralWidget(QSplitter):
def __init__(self, parent, toolbar):
QSplitter.__init__(self, parent)
self.setContentsMargins(10, 10, 10, 10)
self.setOrientation(Qt.Vertical)
imagelistwithproperties = ImageListWithProperties(self)
self.addWidget(imagelistwithproperties)
self.imagelist = imagelistwithproperties.imagelist
self.connect(self.imagelist, SIGNAL("currentRowChanged(int)"),
self.current_item_changed)
self.connect(self.imagelist, SIGNAL("itemSelectionChanged()"),
self.selection_changed)
self.properties = imagelistwithproperties.properties
self.connect(self.properties, SIGNAL("apply_button_clicked()"),
self.properties_changed)
self.imagewidget = ImageWidget(self)
self.connect(self.imagewidget.plot, SIG_LUT_CHANGED,
self.lut_range_changed)
self.item = None # image item
self.imagewidget.add_toolbar(toolbar, "default")
self.imagewidget.register_all_image_tools()
self.addWidget(self.imagewidget)
self.images = [] # List of ImageParam instances
self.lut_ranges = [] # List of LUT ranges
self.setStretchFactor(0, 0)
self.setStretchFactor(1, 1)
self.setHandleWidth(10)
self.setSizes([1, 2])
def refresh_list(self):
self.imagelist.clear()
self.imagelist.addItems([image.title for image in self.images])
def selection_changed(self):
"""Image list: selection changed"""
row = self.imagelist.currentRow()
self.properties.setDisabled(row == -1)
def current_item_changed(self, row):
"""Image list: current image changed"""
image, lut_range = self.images[row], self.lut_ranges[row]
self.show_data(image.data, lut_range)
update_dataset(self.properties.dataset, image)
self.properties.get()
def lut_range_changed(self):
row = self.imagelist.currentRow()
self.lut_ranges[row] = self.item.get_lut_range()
def show_data(self, data, lut_range=None):
plot = self.imagewidget.plot
if self.item is not None:
self.item.set_data(data)
if lut_range is None:
lut_range = self.item.get_lut_range()
self.imagewidget.set_contrast_range(*lut_range)
self.imagewidget.update_cross_sections()
else:
self.item = make.image(data)
plot.add_item(self.item, z=0)
plot.replot()
def properties_changed(self):
"""The properties 'Apply' button was clicked: updating image"""
row = self.imagelist.currentRow()
image = self.images[row]
update_dataset(image, self.properties.dataset)
self.refresh_list()
self.show_data(image.data)
def add_image(self, image):
self.images.append(image)
self.lut_ranges.append(None)
self.refresh_list()
self.imagelist.setCurrentRow(len(self.images)-1)
plot = self.imagewidget.plot
plot.do_autoscale()
def add_image_from_file(self, filename):
image = ImageParam()
image.title = unicode(filename)
image.data = io.imread(filename, to_grayscale=True)
image.height, image.width = image.data.shape
self.add_image(image)
class MainWindow(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.setup()
def setup(self):
"""Setup window parameters"""
self.setWindowIcon(get_icon('python.png'))
self.setWindowTitle(APP_NAME)
self.resize(QSize(600, 800))
# Welcome message in statusbar:
status = self.statusBar()
status.showMessage(_("Welcome to guiqwt application example!"), 5000)
# File menu
file_menu = self.menuBar().addMenu(_("File"))
new_action = create_action(self, _("New..."),
shortcut="Ctrl+N",
icon=get_icon('filenew.png'),
tip=_("Create a new image"),
triggered=self.new_image)
open_action = create_action(self, _("Open..."),
shortcut="Ctrl+O",
icon=get_icon('fileopen.png'),
tip=_("Open an image"),
triggered=self.open_image)
quit_action = create_action(self, _("Quit"),
shortcut="Ctrl+Q",
icon=get_std_icon("DialogCloseButton"),
tip=_("Quit application"),
triggered=self.close)
add_actions(file_menu, (new_action, open_action, None, quit_action))
# Help menu
help_menu = self.menuBar().addMenu("?")
about_action = create_action(self, _("About..."),
icon=get_std_icon('MessageBoxInformation'),
triggered=self.about)
add_actions(help_menu, (about_action,))
main_toolbar = self.addToolBar("Main")
add_actions(main_toolbar, (new_action, open_action, ))
# Set central widget:
toolbar = self.addToolBar("Image")
self.mainwidget = CentralWidget(self, toolbar)
self.setCentralWidget(self.mainwidget)
#------?
def about(self):
QMessageBox.about( self, _("About ")+APP_NAME,
"""<b>%s</b> v%s<p>%s Pierre Raybaut
<br>Copyright © 2009-2010 CEA
<p>Python %s, Qt %s, PyQt %s %s %s""" % \
(APP_NAME, VERSION, _("Developped by"), platform.python_version(),
QT_VERSION_STR, PYQT_VERSION_STR, _("on"), platform.system()) )
#------I/O
def new_image(self):
"""Create a new image"""
imagenew = ImageParamNew(title=_("Create a new image"))
if not imagenew.edit(self):
return
image = ImageParam()
image.title = imagenew.title
if imagenew.type == 'zeros':
image.data = np.zeros((imagenew.width, imagenew.height))
elif imagenew.type == 'rand':
image.data = np.random.randn(imagenew.width, imagenew.height)
self.mainwidget.add_image(image)
def open_image(self):
"""Open image file"""
saved_in, saved_out, saved_err = sys.stdin, sys.stdout, sys.stderr
sys.stdout = None
filename, _filter = getopenfilename(self, _("Open"), "",
io.iohandler.get_filters('load'))
sys.stdin, sys.stdout, sys.stderr = saved_in, saved_out, saved_err
if filename:
self.mainwidget.add_image_from_file(filename)
if __name__ == '__main__':
from guidata import qapplication
app = qapplication()
window = MainWindow()
window.show()
app.exec_()