~ubuntu-branches/ubuntu/oneiric/guiqwt/oneiric

« back to all changes in this revision

Viewing changes to guiqwt/builder.py

  • Committer: Bazaar Package Importer
  • Author(s): Picca Frédéric-Emmanuel
  • Date: 2010-11-13 11:26:05 UTC
  • Revision ID: james.westby@ubuntu.com-20101113112605-k2ffx4p80rict966
Tags: upstream-2.0.8.1
Import upstream version 2.0.8.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# -*- coding: utf-8 -*-
 
2
#
 
3
# Copyright © 2009-2010 CEA
 
4
# Pierre Raybaut <pierre.raybaut@cea.fr>
 
5
# Licensed under the terms of the CECILL License
 
6
# (see guiqwt/__init__.py for details)
 
7
 
 
8
"""
 
9
guiqwt.builder
 
10
--------------
 
11
 
 
12
The `builder` module provides a builder singleton class 
 
13
used to simplify the creation of plot items.
 
14
 
 
15
Example
 
16
~~~~~~~
 
17
 
 
18
Before creating any widget, a `QApplication` must be instantiated 
 
19
(that is a `Qt` internal requirement):
 
20
          
 
21
>>> import guidata
 
22
>>> app = guidata.qapplication()
 
23
 
 
24
that is mostly equivalent to the following (the only difference is that 
 
25
the `guidata` helper function also installs the `Qt` translation 
 
26
corresponding to the system locale):
 
27
          
 
28
>>> from PyQt4.QtGui import QApplication
 
29
>>> app = QApplication([])
 
30
 
 
31
now that a `QApplication` object exists, we may create the plotting widget:
 
32
 
 
33
>>> from guiqwt.plot import ImageWidget
 
34
>>> widget = ImageWidget()
 
35
 
 
36
create curves, images, histograms, etc. and attach them to the plot:
 
37
 
 
38
>>> from guiqwt.builder import make
 
39
>>> curve = make.mcure(x, y, 'r+')
 
40
>>> image = make.image(data)
 
41
>>> hist = make.histogram(data, 100)
 
42
>>> for item in (curve, image, hist):
 
43
...     widget.plot.add_item()
 
44
 
 
45
and then show the widget to screen:
 
46
 
 
47
>>> widget.show()
 
48
>>> app.exec_()
 
49
 
 
50
Reference
 
51
~~~~~~~~~
 
52
 
 
53
.. autoclass:: PlotItemBuilder
 
54
   :members:
 
55
"""
 
56
 
 
57
from numpy import arange, array, zeros, meshgrid, ndarray
 
58
 
 
59
from PyQt4.Qwt5 import QwtPlot
 
60
 
 
61
# Local imports
 
62
from guiqwt.config import _, CONF, make_title
 
63
from guiqwt.curve import CurveItem, ErrorBarCurveItem, GridItem
 
64
from guiqwt.histogram import HistogramItem
 
65
from guiqwt.image import (ImageItem, QuadGridItem, TrImageItem, XYImageItem,
 
66
                          Histogram2DItem)
 
67
from guiqwt.shapes import (XRangeSelection, RectangleShape, EllipseShape,
 
68
                           SegmentShape)
 
69
from guiqwt.annotations import (AnnotatedRectangle, AnnotatedEllipse,
 
70
                                AnnotatedSegment)
 
71
from guiqwt.styles import (update_style_attr, CurveParam, ErrorBarParam,
 
72
                           style_generator, LabelParam, LegendParam, ImageParam,
 
73
                           TrImageParam, HistogramParam, Histogram2DParam,
 
74
                           ImageFilterParam, MARKERS, COLORS, GridParam,
 
75
                           LineStyleParam, AnnotationParam,
 
76
                           LabelParamWithContents)
 
77
from guiqwt.label import (LabelItem, LegendBoxItem, RangeComputation,
 
78
                          RangeComputation2d, DataInfoLabel,
 
79
                          SelectedLegendBoxItem)
 
80
from guiqwt.io import imagefile_to_array
 
81
import os.path as osp
 
82
 
 
83
# default offset positions for anchors
 
84
ANCHOR_OFFSETS = {
 
85
                  "TL" : ( 5,  5),
 
86
                  "TR" : (-5,  5),
 
87
                  "BL" : ( 5, -5),
 
88
                  "BR" : (-5, -5),
 
89
                  "L"  : ( 5,  0),
 
90
                  "R"  : (-5,  0),
 
91
                  "T"  : ( 0,  5),
 
92
                  "B"  : ( 0, -5),
 
93
                  }
 
94
 
 
95
CURVE_COUNT = 0
 
96
HISTOGRAM_COUNT = 0
 
97
IMAGE_COUNT = 0
 
98
LABEL_COUNT = 0
 
99
HISTOGRAM2D_COUNT = 0
 
100
 
 
101
class PlotItemBuilder(object):
 
102
    """
 
103
    This is just a bare class used to regroup
 
104
    a set of factory functions in a single object
 
105
    """
 
106
    AXES = {
 
107
            'bottom': QwtPlot.xBottom,
 
108
            'left'  : QwtPlot.yLeft,
 
109
            'top'   : QwtPlot.xTop,
 
110
            'right' : QwtPlot.yRight,
 
111
            }
 
112
    
 
113
    def __init__(self):
 
114
        self.style = style_generator()
 
115
        
 
116
    def gridparam(self, background=None,
 
117
                  major_enabled=None, minor_enabled=None,
 
118
                  major_style=None, minor_style=None):
 
119
        """
 
120
        Make `guiqwt.styles.GridParam` instance
 
121
           * background = canvas background color
 
122
           * major_enabled = tuple (major_xenabled, major_yenabled)
 
123
           * minor_enabled = tuple (minor_xenabled, minor_yenabled)
 
124
           * major_style = tuple (major_xstyle, major_ystyle)
 
125
           * minor_style = tuple (minor_xstyle, minor_ystyle)
 
126
           
 
127
        Style: tuple (style, color, width)
 
128
        """
 
129
        gridparam = GridParam(title=_("Grid"), icon="lin_lin.png")
 
130
        gridparam.read_config(CONF, "plot", "grid")
 
131
        if background is not None:
 
132
            gridparam.background = background
 
133
        if major_enabled is not None:
 
134
            gridparam.maj_xenabled, gridparam.maj_yenabled = major_enabled
 
135
        if minor_enabled is not None:
 
136
            gridparam.min_xenabled, gridparam.min_yenabled = minor_enabled
 
137
        if major_style is not None:
 
138
            style = LineStyleParam()
 
139
            linestyle, color, style.width = major_style
 
140
            style.set_style_from_matlab(linestyle)
 
141
            style.color = COLORS.get(color, color) # MATLAB-style
 
142
        if minor_style is not None:
 
143
            style = LineStyleParam()
 
144
            linestyle, color, style.width = minor_style
 
145
            style.set_style_from_matlab(linestyle)
 
146
            style.color = COLORS.get(color, color) # MATLAB-style
 
147
        return gridparam
 
148
    
 
149
    def grid(self, background=None, major_enabled=None, minor_enabled=None,
 
150
             major_style=None, minor_style=None):
 
151
        """
 
152
        Make a grid `plot item` (`guiqwt.curve.GridItem` object)
 
153
           * background = canvas background color
 
154
           * major_enabled = tuple (major_xenabled, major_yenabled)
 
155
           * minor_enabled = tuple (minor_xenabled, minor_yenabled)
 
156
           * major_style = tuple (major_xstyle, major_ystyle)
 
157
           * minor_style = tuple (minor_xstyle, minor_ystyle)
 
158
           
 
159
        Style: tuple (style, color, width)
 
160
        """
 
161
        gridparam = self.gridparam(background, major_enabled, minor_enabled,
 
162
                                   major_style, minor_style)
 
163
        return GridItem(gridparam)
 
164
    
 
165
    def __set_axes(self, curve, xaxis, yaxis):
 
166
        """Set curve axes"""
 
167
        for axis in (xaxis, yaxis):
 
168
            if axis not in self.AXES:
 
169
                raise RuntimeError("Unknown axis %s" % axis)
 
170
        curve.setXAxis(self.AXES[xaxis])
 
171
        curve.setYAxis(self.AXES[yaxis])
 
172
 
 
173
    def __set_param(self, param, title, color, linestyle, linewidth,
 
174
                    marker, markersize, markerfacecolor, markeredgecolor,
 
175
                    shade, fitted, curvestyle, curvetype, baseline):
 
176
        """Apply parameters to a `guiqwt.styles.CurveParam` instance"""
 
177
        if title:
 
178
            param.label = title
 
179
        if color is not None:
 
180
            color = COLORS.get(color, color) # MATLAB-style
 
181
            param.line.color = color
 
182
        if linestyle is not None:
 
183
            param.line.set_style_from_matlab(linestyle)
 
184
        if linewidth is not None:
 
185
            param.line.width = linewidth
 
186
        if marker is not None:
 
187
            if marker in MARKERS:
 
188
                param.symbol.update_param(MARKERS[marker]) # MATLAB-style
 
189
            else:
 
190
                param.symbol.marker = marker
 
191
        if markersize is not None:
 
192
            param.symbol.size = markersize
 
193
        if markerfacecolor is not None:
 
194
            markerfacecolor = COLORS.get(markerfacecolor,
 
195
                                         markerfacecolor) # MATLAB-style
 
196
            param.symbol.facecolor = markerfacecolor
 
197
        if markeredgecolor is not None:
 
198
            markeredgecolor = COLORS.get(markeredgecolor,
 
199
                                         markeredgecolor) # MATLAB-style
 
200
            param.symbol.edgecolor = markeredgecolor
 
201
        if shade is not None:
 
202
            param.shade = shade
 
203
        if fitted is not None:
 
204
            param.fitted = fitted
 
205
        if curvestyle is not None:
 
206
            param.curvestyle = curvestyle
 
207
        if curvetype is not None:
 
208
            param.curvetype = curvetype
 
209
        if baseline is not None:
 
210
            param.baseline = baseline
 
211
            
 
212
    def __get_arg_triple_plot(self, args):
 
213
        """Convert MATLAB-like arguments into x, y, style"""
 
214
        def get_x_y_from_data(data):
 
215
            if len(data.shape) == 1 or data.shape[0] == 1 or data.shape[1] == 1:
 
216
                x = arange(data.size)
 
217
                y = data
 
218
            else:
 
219
                x = arange(len(data[:, 0]))
 
220
                y = [data[:, i] for i in range(len(data[0, :]))]
 
221
            return x, y
 
222
            
 
223
        if len(args)==1:
 
224
            if isinstance(args[0], basestring):
 
225
                x = array((), float)
 
226
                y = array((), float)
 
227
                style = args[0]
 
228
            else:
 
229
                x, y = get_x_y_from_data(args[0])
 
230
                if isinstance(y, ndarray):
 
231
                    style = self.style.next()
 
232
                else:
 
233
                    style = [self.style.next() for yi in y]
 
234
        elif len(args)==2:
 
235
            a1, a2 = args
 
236
            if isinstance(a2, basestring):
 
237
                x, y = get_x_y_from_data(a1)
 
238
                style = a2
 
239
            else:
 
240
                x = a1
 
241
                y = a2
 
242
                style = self.style.next()
 
243
        elif len(args)==3:
 
244
            x, y, style = args
 
245
        else:
 
246
            raise TypeError("Wrong number of arguments")
 
247
        return x, y, style
 
248
        
 
249
    def __get_arg_triple_errorbar(self, args):
 
250
        """Convert MATLAB-like arguments into x, y, style"""
 
251
        if len(args)==2:
 
252
            y, dy = args
 
253
            x = arange(len(y))
 
254
            dx = zeros(len(y))
 
255
            style = self.style.next()
 
256
        elif len(args)==3:
 
257
            a1, a2, a3 = args
 
258
            if isinstance(a3, basestring):
 
259
                y, dy = a1, a2
 
260
                x = arange(len(y))
 
261
                dx = zeros(len(y))
 
262
                style = a3
 
263
            else:
 
264
                x, y, dy = args
 
265
                dx = zeros(len(y))
 
266
                style = self.style.next()
 
267
        elif len(args)==4:
 
268
            a1, a2, a3, a4 = args
 
269
            if isinstance(a4, basestring):
 
270
                x, y, dy = a1, a2, a3
 
271
                dx = zeros(len(y))
 
272
                style = a4
 
273
            else:
 
274
                x, y, dx, dy = args
 
275
                style = self.style.next()
 
276
        elif len(args)==5:
 
277
            x, y, dx, dy, style = args
 
278
        else:
 
279
            raise TypeError("Wrong number of arguments")
 
280
        return x, y, dx, dy, style
 
281
    
 
282
    def mcurve(self, *args, **kwargs):
 
283
        """
 
284
        Make a curve `plot item` based on MATLAB-like syntax
 
285
        (may returns a list of curves if data contains more than one signal)
 
286
        (:py:class:`guiqwt.curve.CurveItem` object)
 
287
        
 
288
        Example: mcurve(x, y, 'r+')
 
289
        """
 
290
        x, y, style = self.__get_arg_triple_plot(args)
 
291
        if isinstance(y, ndarray):
 
292
            y = [y]
 
293
        if not isinstance(style, list):
 
294
            style = [style]
 
295
        if len(y) > len(style):
 
296
            style = [style[0]]*len(y)
 
297
        basename = _("Curve")
 
298
        curves = []
 
299
        for yi, stylei in zip(y, style):
 
300
            param = CurveParam(title=basename, icon='curve.png')
 
301
            if "label" in kwargs:
 
302
                param.label = kwargs.pop("label")
 
303
            else:
 
304
                global CURVE_COUNT
 
305
                CURVE_COUNT += 1
 
306
                param.label = make_title(basename, CURVE_COUNT)
 
307
            update_style_attr(stylei, param)
 
308
            curves.append(self.pcurve(x, yi, param, **kwargs))
 
309
        if len(curves) == 1:
 
310
            return curves[0]
 
311
        else:
 
312
            return curves
 
313
                
 
314
    def pcurve(self, x, y, param, xaxis="bottom", yaxis="left"):
 
315
        """
 
316
        Make a curve `plot item` 
 
317
        based on a `guiqwt.styles.CurveParam` instance
 
318
        (:py:class:`guiqwt.curve.CurveItem` object)
 
319
        
 
320
        Usage: pcurve(x, y, param)
 
321
        """
 
322
        curve = CurveItem(param)
 
323
        curve.set_data(x, y)
 
324
        curve.update_params()
 
325
        self.__set_axes(curve, xaxis, yaxis)
 
326
        return curve
 
327
 
 
328
    def curve(self, x, y, title=u"",
 
329
              color=None, linestyle=None, linewidth=None,
 
330
              marker=None, markersize=None, markerfacecolor=None,
 
331
              markeredgecolor=None, shade=None, fitted=None,
 
332
              curvestyle=None, curvetype=None, baseline=None,
 
333
              xaxis="bottom", yaxis="left"):
 
334
        """
 
335
        Make a curve `plot item` from x, y, data
 
336
        (:py:class:`guiqwt.curve.CurveItem` object)
 
337
            * x: 1D NumPy array
 
338
            * y: 1D NumPy array
 
339
            * color: curve color name
 
340
            * linestyle: curve line style (MATLAB-like string or attribute name 
 
341
              from the :py:class:`PyQt4.QtCore.Qt.PenStyle` enum
 
342
              (i.e. "SolidLine" "DashLine", "DotLine", "DashDotLine", 
 
343
              "DashDotDotLine" or "NoPen")
 
344
            * linewidth: line width (pixels)
 
345
            * marker: marker shape (MATLAB-like string or attribute name from 
 
346
              the :py:class:`PyQt4.Qwt5.QwtSymbol.Style` enum (i.e. "Cross",
 
347
              "Ellipse", "Star1", "XCross", "Rect", "Diamond", "UTriangle", 
 
348
              "DTriangle", "RTriangle", "LTriangle", "Star2" or "NoSymbol")
 
349
            * markersize: marker size (pixels)
 
350
            * markerfacecolor: marker face color name
 
351
            * markeredgecolor: marker edge color name
 
352
            * shade: 0 <= float <= 1 (curve shade)
 
353
            * fitted: boolean (fit curve to data)
 
354
            * curvestyle: attribute name from the 
 
355
              :py:class:`PyQt4.Qwt5.QwtPlotCurve.CurveStyle` enum
 
356
              (i.e. "Lines", "Sticks", "Steps", "Dots" or "NoCurve")
 
357
            * curvetype: attribute name from the 
 
358
              :py:class:`PyQt4.Qwt5.QwtPlotCurve.CurveType` enum
 
359
              (i.e. "Yfx" or "Xfy")
 
360
            * baseline (float: default=0.0): the baseline is needed for filling 
 
361
              the curve with a brush or the Sticks drawing style. 
 
362
              The interpretation of the baseline depends on the curve type 
 
363
              (horizontal line for "Yfx", vertical line for "Xfy")
 
364
            * xaxis, yaxis: X/Y axes bound to curve
 
365
        
 
366
        Examples:
 
367
        curve(x, y, marker='Ellipse', markerfacecolor='#ffffff')
 
368
        which is equivalent to (MATLAB-style support):
 
369
        curve(x, y, marker='o', markerfacecolor='w')
 
370
        """
 
371
        basename = _("Curve")
 
372
        param = CurveParam(title=basename, icon='curve.png')
 
373
        if not title:
 
374
            global CURVE_COUNT
 
375
            CURVE_COUNT += 1
 
376
            title = make_title(basename, CURVE_COUNT)
 
377
        self.__set_param(param, title, color, linestyle, linewidth, marker,
 
378
                         markersize, markerfacecolor, markeredgecolor,
 
379
                         shade, fitted, curvestyle, curvetype, baseline)
 
380
        return self.pcurve(x, y, param, xaxis, yaxis)
 
381
 
 
382
    def merror(self, *args, **kwargs):
 
383
        """
 
384
        Make an errorbar curve `plot item` based on MATLAB-like syntax
 
385
        (:py:class:`guiqwt.curve.ErrorBarCurveItem` object)
 
386
        
 
387
        Example: mcurve(x, y, 'r+')
 
388
        """
 
389
        x, y, dx, dy, style = self.__get_arg_triple_errorbar(args)
 
390
        basename = _("Curve")
 
391
        curveparam = CurveParam(title=basename, icon='curve.png')
 
392
        errorbarparam = ErrorBarParam(title=_("Error bars"),
 
393
                                      icon='errorbar.png')
 
394
        if "label" in kwargs:
 
395
            curveparam.label = kwargs["label"]
 
396
        else:
 
397
            global CURVE_COUNT
 
398
            CURVE_COUNT += 1
 
399
            curveparam.label = make_title(basename, CURVE_COUNT)
 
400
        update_style_attr(style, curveparam)
 
401
        errorbarparam.color = curveparam.line.color
 
402
        return self.perror(x, y, dx, dy, curveparam, errorbarparam)
 
403
 
 
404
    def perror(self, x, y, dx, dy, curveparam, errorbarparam,
 
405
               xaxis="bottom", yaxis="left"):
 
406
        """
 
407
        Make an errorbar curve `plot item` 
 
408
        based on a `guiqwt.styles.ErrorBarParam` instance
 
409
        (:py:class:`guiqwt.curve.ErrorBarCurveItem` object)
 
410
            * x: 1D NumPy array
 
411
            * y: 1D NumPy array
 
412
            * dx: None, or scalar, or 1D NumPy array
 
413
            * dy: None, or scalar, or 1D NumPy array
 
414
            * curveparam: `guiqwt.styles.CurveParam` object
 
415
            * errorbarparam: `guiqwt.styles.ErrorBarParam` object
 
416
            * xaxis, yaxis: X/Y axes bound to curve
 
417
        
 
418
        Usage: perror(x, y, dx, dy, curveparam, errorbarparam)
 
419
        """
 
420
        curve = ErrorBarCurveItem(curveparam, errorbarparam)
 
421
        curve.set_data(x, y, dx, dy)
 
422
        curve.update_params()
 
423
        self.__set_axes(curve, xaxis, yaxis)
 
424
        return curve
 
425
        
 
426
    def error(self, x, y, dx, dy, title=u"",
 
427
              color=None, linestyle=None, linewidth=None, marker=None,
 
428
              markersize=None, markerfacecolor=None, markeredgecolor=None,
 
429
              shade=None, fitted=None, curvestyle=None, curvetype=None,
 
430
              baseline=None, xaxis="bottom", yaxis="left"):
 
431
        """
 
432
        Make an errorbar curve `plot item` 
 
433
        (:py:class:`guiqwt.curve.ErrorBarCurveItem` object)
 
434
            * x: 1D NumPy array
 
435
            * y: 1D NumPy array
 
436
            * dx: None, or scalar, or 1D NumPy array
 
437
            * dy: None, or scalar, or 1D NumPy array
 
438
            * color: curve color name
 
439
            * linestyle: curve line style (MATLAB-like string or attribute name 
 
440
              from the :py:class:`PyQt4.QtCore.Qt.PenStyle` enum
 
441
              (i.e. "SolidLine" "DashLine", "DotLine", "DashDotLine", 
 
442
              "DashDotDotLine" or "NoPen")
 
443
            * linewidth: line width (pixels)
 
444
            * marker: marker shape (MATLAB-like string or attribute name from 
 
445
              the :py:class:`PyQt4.Qwt5.QwtSymbol.Style` enum (i.e. "Cross",
 
446
              "Ellipse", "Star1", "XCross", "Rect", "Diamond", "UTriangle", 
 
447
              "DTriangle", "RTriangle", "LTriangle", "Star2" or "NoSymbol")
 
448
            * markersize: marker size (pixels)
 
449
            * markerfacecolor: marker face color name
 
450
            * markeredgecolor: marker edge color name
 
451
            * shade: 0 <= float <= 1 (curve shade)
 
452
            * fitted: boolean (fit curve to data)
 
453
            * curvestyle: attribute name from the 
 
454
              :py:class:`PyQt4.Qwt5.QwtPlotCurve.CurveStyle` enum
 
455
              (i.e. "Lines", "Sticks", "Steps", "Dots" or "NoCurve")
 
456
            * curvetype: attribute name from the 
 
457
              :py:class:`PyQt4.Qwt5.QwtPlotCurve.CurveType` enum
 
458
              (i.e. "Yfx" or "Xfy")
 
459
            * baseline (float: default=0.0): the baseline is needed for filling 
 
460
              the curve with a brush or the Sticks drawing style. 
 
461
              The interpretation of the baseline depends on the curve type 
 
462
              (horizontal line for "Yfx", vertical line for "Xfy")
 
463
            * xaxis, yaxis: X/Y axes bound to curve
 
464
        
 
465
        Examples::
 
466
            error(x, y, None, dy, marker='Ellipse', markerfacecolor='#ffffff')
 
467
            which is equivalent to (MATLAB-style support):
 
468
            error(x, y, None, dy, marker='o', markerfacecolor='w')
 
469
        """
 
470
        basename = _("Curve")
 
471
        curveparam = CurveParam(title=basename, icon='curve.png')
 
472
        errorbarparam = ErrorBarParam(title=_("Error bars"),
 
473
                                      icon='errorbar.png')
 
474
        if not title:
 
475
            global CURVE_COUNT
 
476
            CURVE_COUNT += 1
 
477
            curveparam.label = make_title(basename, CURVE_COUNT)
 
478
        self.__set_param(curveparam, title, color, linestyle, linewidth, marker,
 
479
                         markersize, markerfacecolor, markeredgecolor,
 
480
                         shade, fitted, curvestyle, curvetype, baseline)
 
481
        errorbarparam.color = curveparam.line.color
 
482
        return self.perror(x, y, dx, dy, curveparam, errorbarparam,
 
483
                           xaxis, yaxis)
 
484
    
 
485
    def histogram(self, data, bins=None, logscale=None, remove_first_bin=None,
 
486
                  title=u"", color=None, xaxis="bottom", yaxis="left"):
 
487
        """
 
488
        Make 1D Histogram `plot item` 
 
489
        (:py:class:`guiqwt.histogram.HistogramItem` object)
 
490
            * data (1D NumPy array)
 
491
            * bins: number of bins (int)
 
492
            * logscale: Y-axis scale (bool)
 
493
        """
 
494
        basename = _("Histogram")
 
495
        histparam = HistogramParam(title=basename, icon='histogram.png')
 
496
        curveparam = CurveParam(_("Curve"), icon='curve.png')
 
497
        curveparam.read_config(CONF, "histogram", "curve")
 
498
        if not title:
 
499
            global HISTOGRAM_COUNT
 
500
            HISTOGRAM_COUNT += 1
 
501
            title = make_title(basename, HISTOGRAM_COUNT)
 
502
        curveparam.label = title
 
503
        if color is not None:
 
504
            curveparam.line.color = color
 
505
        if bins is not None:
 
506
            histparam.n_bins = bins
 
507
        if logscale is not None:
 
508
            histparam.logscale = logscale
 
509
        if remove_first_bin is not None:
 
510
            histparam.remove_first_bin = remove_first_bin
 
511
        return self.phistogram(data, curveparam, histparam, xaxis, yaxis)
 
512
        
 
513
    def phistogram(self, data, curveparam, histparam,
 
514
                   xaxis="bottom", yaxis="left"):
 
515
        """
 
516
        Make 1D histogram `plot item` 
 
517
        (:py:class:`guiqwt.histogram.HistogramItem` object) 
 
518
        based on a `guiqwt.styles.CurveParam` and 
 
519
        `guiqwt.styles.HistogramParam` instances
 
520
        
 
521
        Usage: phistogram(data, curveparam, histparam)
 
522
        """
 
523
        hist = HistogramItem(curveparam, histparam)
 
524
        hist.update_params()
 
525
        hist.set_hist_data(data)
 
526
        self.__set_axes(hist, xaxis, yaxis)
 
527
        return hist
 
528
 
 
529
    def __set_image_param(self, param, title, background_color,
 
530
                          alpha_mask, alpha, colormap, **kwargs):
 
531
        if title:
 
532
            param.label = title
 
533
        else:
 
534
            global IMAGE_COUNT
 
535
            IMAGE_COUNT += 1
 
536
            param.label = make_title(_("Image"), IMAGE_COUNT)
 
537
        if background_color is not None:
 
538
            param.background = background_color
 
539
        if alpha_mask is not None:
 
540
            param.alpha_mask = alpha_mask
 
541
        if alpha is not None:
 
542
            param.alpha = alpha
 
543
        if colormap is not None:
 
544
            param.colormap = colormap
 
545
        for key, val in kwargs.items():
 
546
            setattr(param, key, val)
 
547
 
 
548
    def _get_image_data(self, data, filename, title, cmap):
 
549
        if data is None:
 
550
            assert filename is not None
 
551
            data = imagefile_to_array(filename)
 
552
        if title is None and filename is not None:
 
553
            title = osp.basename(filename)
 
554
        return data, filename, title, cmap
 
555
 
 
556
    def image(self, data=None, filename=None, title=None, background_color=None,
 
557
              alpha_mask=None, alpha=None, colormap=None,
 
558
              xaxis="bottom", yaxis="left", zaxis="right"):
 
559
        """
 
560
        Make an image `plot item` from data
 
561
        (:py:class:`guiqwt.image.ImageItem` object)
 
562
        """
 
563
        param = ImageParam(title=_("Image"), icon='image.png')
 
564
        params = self._get_image_data(data, filename, title, colormap)
 
565
        data, filename, title, colormap = params
 
566
        self.__set_image_param(param, title, background_color,
 
567
                               alpha_mask, alpha, colormap)
 
568
        image = ImageItem(data, param)
 
569
        image.set_filename(filename)
 
570
        return image
 
571
        
 
572
    def quadgrid(self, X, Y, Z, filename=None, title=None,
 
573
                 background_color=None, alpha_mask=None, alpha=None,
 
574
                 colormap=None, xaxis="bottom", yaxis="left", zaxis="right"):
 
575
        """
 
576
        Make a pseudocolor `plot item` of a 2D array
 
577
        (:py:class:`guiqwt.image.QuadGridItem` object)
 
578
        """
 
579
        param = ImageParam(title=_("Image"), icon='image.png')
 
580
        self.__set_image_param(param, title, background_color,
 
581
                               alpha_mask, alpha, colormap)
 
582
        image = QuadGridItem(X, Y, Z, param)
 
583
        return image
 
584
 
 
585
    def pcolor(self, *args, **kwargs):
 
586
        """
 
587
        Make a pseudocolor `plot item` of a 2D array 
 
588
        based on MATLAB-like syntax
 
589
        (:py:class:`guiqwt.image.QuadGridItem` object)
 
590
        
 
591
        Examples:
 
592
            pcolor(C)
 
593
            pcolor(X, Y, C)
 
594
        """
 
595
        if len(args) == 1:
 
596
            Z, = args
 
597
            M, N = Z.shape
 
598
            X, Y = meshgrid(arange(N, dtype=Z.dtype), arange(M, dtype=Z.dtype))
 
599
        elif len(args) == 3:
 
600
            X, Y, Z = args
 
601
        else:
 
602
            raise RuntimeError("1 or 3 non-keyword arguments expected")
 
603
        return self.quadgrid(X, Y, Z, **kwargs)
 
604
 
 
605
    def trimage(self, data=None, filename=None, title=None,
 
606
                background_color=None, alpha_mask=None, alpha=None,
 
607
                colormap=None, xaxis="bottom", yaxis="left", zaxis="right",
 
608
                x0=0.0, y0=0.0, angle=0.0, dx=1.0, dy=1.0,
 
609
                interpolation='linear'):
 
610
        """
 
611
        Make a transformable image `plot item` (image with an arbitrary 
 
612
        affine transform)
 
613
        (:py:class:`guiqwt.image.TrImageItem` object)
 
614
            * data: 2D NumPy array (image pixel data)
 
615
            * filename: image filename (if data is not specified)
 
616
            * title: image title (optional)
 
617
            * x0, y0: position
 
618
            * angle: angle (radians)
 
619
            * dx, dy: pixel size along X and Y axes
 
620
            * interpolation: 'nearest', 'linear' (default), 'antialiasing' (5x5)
 
621
        """
 
622
        param = TrImageParam(title=_("Image"), icon='image.png')
 
623
        params = self._get_image_data(data, filename, title, colormap)
 
624
        data, filename, title, colormap = params
 
625
        self.__set_image_param(param, title, background_color,
 
626
                               alpha_mask, alpha, colormap,
 
627
                               x0=x0, y0=y0, angle=angle, dx=dx, dy=dy)
 
628
        interp_methods = {'nearest': 0, 'linear': 1, 'antialiasing': 5}
 
629
        param.interpolation = interp_methods[interpolation]
 
630
        image = TrImageItem(data, param)
 
631
        image.set_filename(filename)
 
632
        return image
 
633
 
 
634
    def xyimage(self, x, y, data, title=None, background_color=None,
 
635
                alpha_mask=None, alpha=None, colormap=None,
 
636
                xaxis="bottom", yaxis="left", zaxis="right"):
 
637
        """
 
638
        Make an xyimage `plot item` (image with non-linear X/Y axes) from data
 
639
        (:py:class:`guiqwt.image.XYImageItem` object)
 
640
            * x: 1D NumPy array
 
641
            * y: 1D NumPy array
 
642
            * data: 2D NumPy array (image pixel data)
 
643
            * title: image title (optional)
 
644
        """
 
645
        param = ImageParam(title=_("Image"), icon='image.png')
 
646
        self.__set_image_param(param, title, background_color,
 
647
                               alpha_mask, alpha, colormap)
 
648
        return XYImageItem(x, y, data, param)
 
649
    
 
650
    def imagefilter(self, xmin, xmax, ymin, ymax,
 
651
                    imageitem, filter, title=None):
 
652
        """
 
653
        Make a rectangular area image filter `plot item`
 
654
        (:py:class:`guiqwt.image.ImageFilterItem` object)
 
655
            * xmin, xmax, ymin, ymax: filter area bounds
 
656
            * imageitem: An imageitem instance
 
657
            * filter: function (x, y, data) --> data
 
658
        """
 
659
        param = ImageFilterParam(_("Filter"), icon="funct.png")
 
660
        param.xmin, param.xmax, param.ymin, param.ymax = xmin, xmax, ymin, ymax
 
661
        if title is not None:
 
662
            param.label = title
 
663
        filt = imageitem.get_filter(filter, param)
 
664
        _m, _M = imageitem.get_lut_range()
 
665
        filt.set_lut_range([_m, _M])
 
666
        return filt
 
667
    
 
668
    def histogram2D(self, X, Y, NX=None, NY=None, logscale=None,
 
669
                    title=None, transparent=None):
 
670
        """
 
671
        Make a 2D Histogram `plot item` 
 
672
        (:py:class:`guiqwt.image.Histogram2DItem` object)
 
673
            * X: data (1D array)
 
674
            * Y: data (1D array)
 
675
            * NX: Number of bins along x-axis (int)
 
676
            * NY: Number of bins along y-axis (int)
 
677
            * logscale: Z-axis scale (bool)
 
678
            * title: item title (string)
 
679
            * transparent: enable transparency (bool)
 
680
        """
 
681
        basename = _("2D Histogram")
 
682
        param = Histogram2DParam(title=basename, icon='histogram2d.png')
 
683
        if NX is not None:
 
684
            param.nx_bins = NX
 
685
        if NY is not None:
 
686
            param.ny_bins = NY
 
687
        if logscale is not None:
 
688
            param.logscale = int(logscale)
 
689
        if title is not None:
 
690
            param.label = title
 
691
        else:
 
692
            global HISTOGRAM2D_COUNT
 
693
            HISTOGRAM2D_COUNT += 1
 
694
            param.label = make_title(basename, HISTOGRAM2D_COUNT)
 
695
        if transparent is not None:
 
696
            param.transparent = transparent
 
697
        return Histogram2DItem(X, Y, param)
 
698
 
 
699
    def label(self, text, g, c, anchor, title=""):
 
700
        """
 
701
        Make a label `plot item` 
 
702
        (:py:class:`guiqwt.label.LabelItem` object)
 
703
            * text: label text (string)
 
704
            * g: position in plot coordinates (tuple) 
 
705
              or relative position (string)
 
706
            * c: position in canvas coordinates (tuple)
 
707
            * anchor: anchor position in relative position (string)
 
708
            * title: label name (optional)
 
709
        
 
710
        Examples::
 
711
            make.label("Relative position", (x[0], y[0]), (10, 10), "BR")
 
712
            make.label("Absolute position", "R", (0,0), "R")
 
713
        """
 
714
        basename = _("Label")
 
715
        param = LabelParamWithContents(basename, icon='label.png')
 
716
        param.read_config(CONF, "plot", "label")
 
717
        if title:
 
718
            param.label = title
 
719
        else:
 
720
            global LABEL_COUNT
 
721
            LABEL_COUNT += 1
 
722
            param.label = make_title(basename, LABEL_COUNT)
 
723
        if isinstance(g, tuple):
 
724
            param.abspos = False
 
725
            param.xg, param.yg = g
 
726
        else:
 
727
            param.abspos = True
 
728
            param.absg = g
 
729
        if c is None:
 
730
            c = ANCHOR_OFFSETS[anchor]
 
731
        param.xc, param.yc = c
 
732
        param.anchor = anchor
 
733
        return LabelItem(text, param)
 
734
 
 
735
    def legend(self, anchor='TR', c=None, restrict_items=None):
 
736
        """
 
737
        Make a legend `plot item` 
 
738
        (:py:class:`guiqwt.label.LegendBoxItem` or 
 
739
        :py:class:`guiqwt.label.SelectedLegendBoxItem` object)
 
740
            * anchor: legend position in relative position (string)
 
741
            * c (optional): position in canvas coordinates (tuple)
 
742
            * restrict_items (optional):
 
743
                - None: all items are shown in legend box
 
744
                - []: no item shown
 
745
                - [item1, item2]: item1, item2 are shown in legend box
 
746
        """
 
747
        param = LegendParam(_("Legend"), icon='legend.png')
 
748
        param.read_config(CONF, "plot", "legend")
 
749
        param.abspos = True
 
750
        param.absg = anchor
 
751
        param.anchor = anchor
 
752
        if c is None:
 
753
            c = ANCHOR_OFFSETS[anchor]
 
754
        param.xc, param.yc = c
 
755
        if restrict_items is None:
 
756
            return LegendBoxItem(param)
 
757
        else:
 
758
            return SelectedLegendBoxItem(param, restrict_items)
 
759
 
 
760
    def range(self, xmin, xmax):
 
761
        return XRangeSelection(xmin, xmax)
 
762
        
 
763
    def __shape(self, shapeclass, x0, y0, x1, y1, title=None):
 
764
        shape = shapeclass(x0, y0, x1, y1)
 
765
        shape.set_style("plot", "shape/drag")
 
766
        if title is not None:
 
767
            shape.setTitle(title)
 
768
        return shape
 
769
 
 
770
    def rectangle(self, x0, y0, x1, y1, title=None):
 
771
        """
 
772
        Make a rectangle shape `plot item` 
 
773
        (:py:class:`guiqwt.shapes.RectangleShape` object)
 
774
            * x0, y0, x1, y1: rectangle coordinates
 
775
            * title: label name (optional)
 
776
        """
 
777
        return self.__shape(RectangleShape, x0, y0, x1, y1, title)
 
778
 
 
779
    def ellipse(self, x0, y0, x1, y1, ratio, title=None):
 
780
        """
 
781
        Make an ellipse shape `plot item` 
 
782
        (:py:class:`guiqwt.shapes.EllipseShape` object)
 
783
            * x0, y0, x1, y1: ellipse x-axis coordinates
 
784
            * ratio: ratio between y-axis and x-axis lengths
 
785
            * title: label name (optional)
 
786
        """
 
787
        shape = EllipseShape(x0, y0, x1, y1, ratio)
 
788
        shape.set_style("plot", "shape/drag")
 
789
        if title is not None:
 
790
            shape.setTitle(title)
 
791
        return shape
 
792
        
 
793
    def circle(self, x0, y0, x1, y1, title=None):
 
794
        """
 
795
        Make a circle shape `plot item` 
 
796
        (:py:class:`guiqwt.shapes.EllipseShape` object)
 
797
            * x0, y0, x1, y1: circle diameter coordinates
 
798
            * title: label name (optional)
 
799
        """
 
800
        return self.ellipse(x0, y0, x1, y1, 1., title=title)
 
801
 
 
802
    def segment(self, x0, y0, x1, y1, title=None):
 
803
        """
 
804
        Make a segment shape `plot item` 
 
805
        (:py:class:`guiqwt.shapes.SegmentShape` object)
 
806
            * x0, y0, x1, y1: segment coordinates
 
807
            * title: label name (optional)
 
808
        """
 
809
        return self.__shape(SegmentShape, x0, y0, x1, y1, title)
 
810
        
 
811
    def __get_annotationparam(self, title, subtitle):
 
812
        param = AnnotationParam(_("Annotation"), icon="annotation.png")
 
813
        if title is not None:
 
814
            param.title = title
 
815
        if subtitle is not None:
 
816
            param.subtitle = subtitle
 
817
        return param
 
818
        
 
819
    def __annotated_shape(self, shapeclass, x0, y0, x1, y1, title, subtitle):
 
820
        param = self.__get_annotationparam(title, subtitle)
 
821
        shape = shapeclass(x0, y0, x1, y1, param)
 
822
        shape.set_style("plot", "shape/drag")
 
823
        return shape
 
824
        
 
825
    def annotated_rectangle(self, x0, y0, x1, y1, title=None, subtitle=None):
 
826
        """
 
827
        Make an annotated rectangle `plot item` 
 
828
        (:py:class:`guiqwt.annotations.AnnotatedRectangle` object)
 
829
            * x0, y0, x1, y1: rectangle coordinates
 
830
            * title, subtitle: strings
 
831
        """
 
832
        return self.__annotated_shape(AnnotatedRectangle,
 
833
                                      x0, y0, x1, y1, title, subtitle)
 
834
        
 
835
    def annotated_ellipse(self, x0, y0, x1, y1, ratio,
 
836
                          title=None, subtitle=None):
 
837
        """
 
838
        Make an annotated ellipse `plot item`
 
839
        (:py:class:`guiqwt.annotations.AnnotatedEllipse` object)
 
840
            * x0, y0, x1, y1: ellipse rectangle coordinates
 
841
            * ratio: ratio between y-axis and x-axis lengths
 
842
            * title, subtitle: strings
 
843
        """
 
844
        param = self.__get_annotationparam(title, subtitle)
 
845
        shape = AnnotatedEllipse(x0, y0, x1, y1, ratio, param)
 
846
        shape.set_style("plot", "shape/drag")
 
847
        return shape
 
848
                                      
 
849
    def annotated_circle(self, x0, y0, x1, y1, ratio,
 
850
                         title=None, subtitle=None):
 
851
        """
 
852
        Make an annotated circle `plot item`
 
853
        (:py:class:`guiqwt.annotations.AnnotatedCircle` object)
 
854
            * x0, y0, x1, y1: circle diameter coordinates
 
855
            * title, subtitle: strings
 
856
        """
 
857
        return self.annotated_ellipse(x0, y0, x1, y1, 1., title, subtitle)
 
858
        
 
859
    def annotated_segment(self, x0, y0, x1, y1, title=None, subtitle=None):
 
860
        """
 
861
        Make an annotated segment `plot item`
 
862
        (:py:class:`guiqwt.annotations.AnnotatedSegment` object)
 
863
            * x0, y0, x1, y1: segment coordinates
 
864
            * title, subtitle: strings
 
865
        """
 
866
        return self.__annotated_shape(AnnotatedSegment,
 
867
                                      x0, y0, x1, y1, title, subtitle)
 
868
 
 
869
    def info_label(self, anchor, comps, title=""):
 
870
        """
 
871
        Make an info label `plot item` 
 
872
        (:py:class:`guiqwt.label.DataInfoLabel` object)
 
873
        """
 
874
        basename = _("Computation")
 
875
        param = LabelParam(basename, icon='label.png')
 
876
        param.read_config(CONF, "plot", "info_label")
 
877
        if title:
 
878
            param.label = title
 
879
        else:
 
880
            global LABEL_COUNT
 
881
            LABEL_COUNT += 1
 
882
            param.label = make_title(basename, LABEL_COUNT)
 
883
        param.abspos = True
 
884
        param.absg = anchor
 
885
        param.anchor = anchor
 
886
        c = ANCHOR_OFFSETS[anchor]
 
887
        param.xc, param.yc = c
 
888
        return DataInfoLabel(param, comps)
 
889
 
 
890
    def computation(self, range, anchor, label, curve, function):
 
891
        """
 
892
        Make a computation label `plot item` 
 
893
        (:py:class:`guiqwt.label.DataInfoLabel` object)
 
894
        (see example: :py:mod:`guiqwt.tests.computations`)
 
895
        """
 
896
        return self.computations(range, anchor, [ (curve, label, function) ])
 
897
 
 
898
    def computations(self, range, anchor, specs):
 
899
        """
 
900
        Make computation labels  `plot item` 
 
901
        (:py:class:`guiqwt.label.DataInfoLabel` object)
 
902
        (see example: :py:mod:`guiqwt.tests.computations`)
 
903
        """
 
904
        comps = []
 
905
        for curve, label, function in specs:
 
906
            comp = RangeComputation(label, curve, range, function)
 
907
            comps.append(comp)
 
908
        return self.info_label(anchor, comps)
 
909
 
 
910
    def computation2d(self, rect, anchor, label, image, function):
 
911
        """
 
912
        Make a 2D computation label `plot item` 
 
913
        (:py:class:`guiqwt.label.RangeComputation2d` object)
 
914
        (see example: :py:mod:`guiqwt.tests.computations`)
 
915
        """
 
916
        return self.computations2d(rect, anchor, [ (image, label, function) ])
 
917
 
 
918
    def computations2d(self, rect, anchor, specs):
 
919
        """
 
920
        Make 2D computation labels `plot item` 
 
921
        (:py:class:`guiqwt.label.RangeComputation2d` object)
 
922
        (see example: :py:mod:`guiqwt.tests.computations`)
 
923
        """
 
924
        comps = []
 
925
        for image, label, function in specs:
 
926
            comp = RangeComputation2d(label, image, rect, function)
 
927
            comps.append(comp)
 
928
        return self.info_label(anchor, comps)
 
929
 
 
930
make = PlotItemBuilder()
 
 
b'\\ No newline at end of file'