###############################################################################
# -*- python -*-
#
# Copyright or (C) or Copr. 2010 INRIA - CIRAD - INRA
#
# File author(s): Thomas Cokelaer <Thomas.Cokelaer@sophia.inria.fr>
#
# Distributed under the Cecill-C License.
# See accompanying file LICENSE.txt or copy at
# http://www.cecill.info/licences/Licence_CeCILL-C_V1-en.html
#
# OpenAlea WebSite : http://openalea.gforge.inria.fr
#
###############################################################################
__doc__="""Pylab plotting nodes for VisuAlea"""
__revision__ = " $Revision$ "
__author__ = "$Author$"
__date__ = "$Date$"
from openalea.core import Node
from openalea.core import (Factory, IFileStr, IInt, IBool, IFloat,
ISequence, IEnumStr, IStr, IDirStr, ITuple3, IDict, ITuple)
from openalea.core.external import add_docstring
from openalea.oapylab import tools
[docs]
class Plotting(Node):
"""This class provides common connectors to plotting nodes that are defined in this module.
Classes that inherits from `~openalea.pylab.plotting.Plotting` are ensured to inherits
from `Node` and to have a common API where:
* the first input connector is reserved for connecting a pylab axes
* the first output connector is reserved for connecting a pylab axes
* the last input connector is reseverd to set the pylab.figure number
It also provides several methods that check validity of input axes, update the figure and so on.
"""
ERROR_NOXDATA = 'No data connected to the x connector. Connect a line2D, an array or a list of line2Ds or arrays'
ERROR_FAILURE = 'Failed to generate the image. check your entries.'
def __init__(self, inputs={}):
Node.__init__(self)
self.axe = None
self.fig = None
self.add_input(name="axes")
for input in inputs:
self.add_input(**input)
self.add_input(name="figure", interface=IInt(1,100,1), value=1)
self.add_output(name='axes')
[docs]
def axes(self):
"""manage the pylab axes.
* If no axes is connected to the first input connector, then a new one will be created except if
current node has already generated an axes (was already called). In such case, the node's axes is
cleared.
* If an axes is connected, the current axes is set to this input axes. It is not clear but used to
to plot data generated by the current node on top of this connected axes.
"""
#sometimes, we want to add data to existing axe provided as an input argument. In such case, we do not want to clean
# the axe and create a new one.
if self.get_input('axes') != None:
print('Input axes found. Using it (%s)' % self.get_input('axes'))
axes = self.get_input('axes')
import matplotlib
if not axes.__module__ in [matplotlib.axes._axes.__name__,matplotlib.projections.polar.__name__]:
print('input must be a valid axes from matplotlib.axes %s given for %s' % (type(axes), axes))
self.axe = axes
return
#if an axe already exist, no need to create a new one: we simply clean it
if self.axe:
try:
#matplotlib 1.0.0
from pylab import sca, cla
print('No input axe, but axes already set. Clear it. %s' % self.axe, self.axe.__str__)
self.axe.clear()
self.axe.get_figure().canvas.draw()
sca(self.axe)
except:
#matplotlib 0.99.1
from pylab import Figure
print('No input axe, but axes already set. Clear it. %s' % self.axe, self.axe.__str__)
self.axe.clear()
self.axe.get_figure().canvas.draw()
f = self.axe.get_figure()
Figure.sca(f, self.axe)
#else, we need to create a new axe. Note, the use of label. Indeed, if same position is used, and same default label then
# no new axes is created. See add_axes help. Our label is the number of axes.
else:
print('No input axe and not axes set. Creating a new one.')
label='axe' + str(len(self.fig.get_axes()))
self.axe = self.fig.add_axes([.1,.1,.8,.8], label=label)
[docs]
class PlotxyInterface():
"""A base class common to some plotting functions
The plotting functions that uses this base class are those that plot 2D curves (xy). For instance:
* plot
* loglog
* semilogx, semilogy
* csd, psd, specgram
* stem
* step
* fill
This is used to manage the different possible x and y inputs. See :class:`PyLabPlot` for more explanation.
For more tunable colors and linestyles, use the :class:`Line2D` convertor before passing
the data to a node.
This class provides a method :meth:`call` that manage the inputs data and arguments smoothly.
.. sectionauthor:: Thomas Cokelaer <Thomas.Cokelaer@sophia.inria.fr>
"""
ERROR_NOXDATA = 'No data connected to the x connector. Connect a line2D, an array or a list of line2Ds or arrays'
ERROR_FAILURE = 'Failed to generate the image. check your entries.'
def __init__(self):
pass
[docs]
def call(self, plottype, kwds):
"""Function used to call the plot specified by`plottype`
:param plottype: must be one of plot, loglog, semilogx, semilogy, csd, psd, specgram, step, stem, fill
if several x are provided, different colors will be used for the markers cycling over the available :class:`Colors`
"""
from pylab import Line2D
if plottype=='plot':
from pylab import plot as plot
elif plottype=='loglog':
from pylab import loglog as plot
elif plottype=='semilogx':
from pylab import semilogx as plot
elif plottype=='semilogy':
from pylab import semilogy as plot
elif plottype=='csd':
from pylab import csd as plot
elif plottype=='psd':
from pylab import psd as plot
elif plottype=='specgram':
from pylab import specgram as plot
elif plottype=='stem':
from pylab import stem as plot
elif plottype=='step':
from pylab import step as plot
elif plottype=='fill':
from pylab import fill as plot
elif plottype=='hist':
from pylab import hist as plot
elif plottype=='polar':
from pylab import polar as plot
try:
xinputs = self.get_input("x")
yinputs = self.get_input("y")
except:
xinputs = self.get_input("theta")
yinputs = self.get_input("r")
# convert x and y inputs into lists
if xinputs is None:
raise ValueError(self.ERROR_NOXDATA)
else:
if type(xinputs)!=list:
xinputs = [xinputs]
if type(yinputs)!=list:
yinputs = [yinputs]
output = None
# case of an x input without y input. line2D are all manage in this if statement
if yinputs[0] is None:
#plot(line2D) and plot([line2D, line2D])
if type(xinputs[0])==Line2D:
for x in xinputs:
print(kwds)
line2dkwds = tools.get_kwds_from_line2d(line2d=x, input_kwds=kwds, type=plottype)
#print line2dkwds
#returns the processed data ?
if plottype in ['specgram', 'psd']:
output = plot(x.get_ydata(orig=False), **line2dkwds)
else:
try:
output = plot(x.get_xdata(orig=False), x.get_ydata(orig=False), **line2dkwds)
except:
#print kwds
#print line2dkwds
pass
#plot([x1,None,x2,None, ...) and plot(x1)
else:
c = enumerate(tools.colors)
for x in xinputs:
try:
color = next(c)
kwds['color']=color[1]
except:
print('no more colors')
try:
output = plot(x, **kwds)
except:
raise ValueError("plot failed")
else:
if len(xinputs)==1 and len(yinputs)!=1:
# plot(x,y) and plot(x, [y1,y2])
c = enumerate(tools.colors)
for y in yinputs:
try:
color = next(c)
kwds['color']=color[1]
except:
print('no more colors')
try:
output = plot(xinputs[0], y, **kwds)
except:
raise ValueError("plot failed")
else:
if len(xinputs)!=len(yinputs):
print('warning more x inputs than y inputs. correct the connectors')
for x,y in zip(xinputs, yinputs):
try:
linestyle=kwds.get('linestyle', '-')
if 'linestyle' in kwds:
del kwds['linestyle']
output = plot(x, y, linestyle=linestyle, **kwds)
except:
#print kwds
raise ValueError("plot failed")
return output
[docs]
class PyLabPlot(Plotting, PlotxyInterface):
"""Plot lines. See pylab.plot help for details.
The x connector must be connected. It must be in one of the following format:
* a 1-D array.
* If nothing is connected to `y`, then `x` is used as `y` (similarly to pylab.plot behaviour)
* A 1-D array of same length may be connected to `y`.
* Several 1-D arrays of same length as `x` may be connected to `y`. Therefore,
these arrays have the same `x` data
* a Line2D object (see :ref:`Line2D`). `y` must be empty in such case.
* a list of Line2D objects. `y` must be empty in such case
In order to customize the input data at will, it is necesserary to convert the xy data into a
:class:`PyLabLine2D` object and to pass it to the `x` connector. In such case, the y connector
becomes useless.
.. seealso:: the following dataflow example for illustrations
:param axes: an optional axes where new data will be plotted.
:param x: one or several arrays, or one or several PyLabLine2D objects.
:param y: one or several arrays, or one or several PyLabLine2D objects.
:param str marker: a valid matplotlib marker (e.g., [ '+' | '*']).
:param int markersize: marker size (default is 10)
:param str linestyle: The linestyle of a curve [None | 'solid' | 'dashed' | 'dashdot' | 'dotted' ]
:param str color: a color selected from the list or connected to a :class:`~openalea.color.color`
node to select any color from the wheel color.
:param bool scalex: determine whether x is autoscaled; the default is *True*.
:param bool scaley: determine whether x is autoscaled; the default is *True*.
:param kwargs: a :class:`PyLabLine2D` object to fully tune the lines.
:param int figure: figure id
:return:
* the axes in which the data are plotted.
* the output of plot function (line2d)
:Example:
.. dataflow:: openalea.pylab.test plot
:width: 50%
**The openalea.pylab.test.plot dataflow.** This dataflow illustrates the different usage
of the **PyLabPlot** node.
The 4 independent dataflows that can be seen here generate the four figures here below.
The left upside dataflow has only a x array connected. It is as if you were typing:
.. doctest::
plot(x)
The right upside dataflow as a x and 1 y array connected. It is as if you were typing:
.. code-block:: python
plot(x,y)
The left downside dataflow has 1 x and several y arrays. It is as if you were typing::
plot(x,y1, x, y2)
And finally, the right downside dataflow allows to convert x,y tuple into Line2D to further
customize the line2D. It is as if you were typing::
plot(x1, y1, **kwds1)
plot(x2, y2, **kwds2)
where *kwds* are valid arguments from the **PyLabLine2D** nodes.
.. plot::
:width: 50%
from openalea.core.alea import *
pm = PackageManager()
run_and_display(('openalea.pylab.test', 'plot'),{},pm=pm)
.. seealso:: in VisuAlea, see "plot demos" in openalea.pylab.demo
.. sectionauthor:: Thomas Cokelaer <Thomas.Cokelaer@sophia.inria.fr>
"""
def __init__(self):
PlotxyInterface.__init__(self)
inputs = [
{'name':'x', 'interface':None, 'value':None},
{'name':'y', 'interface':None, 'value':None},
{'name':'marker', 'interface':IEnumStr(list(tools.markers.keys())), 'value':'circle'},
{'name':'markersize', 'interface':IFloat, 'value':10},
{'name':'linestyle', 'interface':IEnumStr(list(tools.linestyles.keys())), 'value':'solid'},
{'name':'color', 'interface':IEnumStr(list(tools.colors.keys())), 'value':'blue'},
{'name':'scalex', 'interface':IBool, 'value':True},
{'name':'scaley', 'interface':IBool, 'value':True},
{'name':'kwargs', 'interface':IDict, 'value':{'label':None}},
]
Plotting.__init__(self, inputs)
self.add_output(name="output")
def __call__(self, inputs):
#todo label must be cast into string
kwds = {}
for key,value in self.get_input('kwargs').items():
kwds[key] = value
kwds['markersize']=self.get_input("markersize")
kwds['marker']=tools.markers[self.get_input("marker")]
kwds['linestyle']=tools.linestyles[self.get_input("linestyle")]
kwds['color']=tools.get_valid_color(self.get_input("color"))
kwds['scaley']=self.get_input("scaley")
kwds['scalex']=self.get_input("scalex")
self.figure()
self.axes()
output = self.call('plot', kwds)
self.update_figure()
return self.axe, output
[docs]
class PyLabLogLog(Plotting, PlotxyInterface):
"""Make a plot with log scaling. See pylab.loglog for details.
:param axes: an optional axes where new data will be plotted.
:param x: one or several arrays, or one or several PyLabLine2D objects.
:param y: one or several arrays, or one or several PyLabLine2D objects.
:param str marker: a valid matplotlib marker (e.g., [ '+' | '*']).
:param int markersize: marker size (default is 10)
:param str linestyle: The linestyle of a curve [None | 'solid' | 'dashed' | 'dashdot' | 'dotted' ]
:param str color: a color selected from the list or connected to a :class:`~openalea.color.color`
node to select any color from the wheel color.
:param kwargs: a :class:`PyLabLine2D` object to fully tune the lines.
:param int figure: figure id
:return:
* the axes in which the data are plotted.
* the output of plot function (line2d)
:Example:
.. dataflow:: openalea.pylab.test loglog
:width: 50%
**The `openalea.pylab.test.loglog` dataflow.** The input data is a normal
distribution (openalea.numpy.randn) passed to the `PyLabLogLog` node, which
calls pylab.loglog.
.. plot::
:width: 50%
from openalea.core.alea import *
pm = PackageManager()
run_and_display(('openalea.pylab.test', 'loglog'),{},pm=pm)
.. seealso:: See :class:`PyLabPlot` for details about the x and y connector.
.. sectionauthor:: Thomas Cokelaer <Thomas.Cokelaer@sophia.inria.fr>
"""
def __init__(self):
self.__doc__ = PyLabPlot.__doc__
PlotxyInterface.__init__(self)
inputs = [
{'name':'x', 'interface':None, 'value':None},
{'name':'y', 'interface':None, 'value':None},
{'name':'marker', 'interface':IEnumStr(list(tools.markers.keys())), 'value':'circle'},
{'name':'markersize', 'interface':IFloat, 'value':10},
{'name':'linestyle', 'interface':IEnumStr(list(tools.linestyles.keys())), 'value':'solid'},
{'name':'color', 'interface':IEnumStr(list(tools.colors.keys())), 'value':'blue'},
]
Plotting.__init__(self, inputs)
self.add_input(name='kwargs', interface=IDict, value={'label':None})
self.add_output(name="output")
def __call__(self, inputs):
kwds = {}
for key,value in self.get_input('kwargs').items():
kwds[key] = value
kwds['markersize']=self.get_input("markersize")
kwds['marker']=tools.markers[self.get_input("marker")]
kwds['linestyle']=tools.linestyles[self.get_input("linestyle")]
kwds['color']=tools.colors[self.get_input("color")]
self.figure()
self.axes()
self.call('loglog', kwds)
self.update_figure()
return self.axe, None
[docs]
class PyLabSemiLogy(Plotting, PlotxyInterface):
"""Make a plot with log scaling on y-axis. See pylab.semilogy for details.
:param axes: an optional axes where new data will be plotted.
:param x: one or several arrays, or one or several PyLabLine2D objects.
:param y: one or several arrays, or one or several PyLabLine2D objects.
:param str marker: a valid matplotlib marker (e.g., [ '+' | '*']).
:param int markersize: marker size (default is 10)
:param str linestyle: The linestyle of a curve [None | 'solid' | 'dashed' | 'dashdot' | 'dotted' ]
:param str color: a color selected from the list or connected to a :class:`~openalea.color.color`
node to select any color from the wheel color.
:param kwargs: a :class:`PyLabLine2D` object to fully tune the lines.
:param int figure: figure id
:return:
* the axes in which the data are plotted.
* the output of plot function (line2d)
:Example:
.. dataflow:: openalea.pylab.test semilogy
:width: 50%
**The openalea.pylab.test.semilogy dataflow.**
.. plot::
:width: 50%
from openalea.core.alea import *
pm = PackageManager()
run_and_display(('openalea.pylab.test', 'semilogy'),{},pm=pm)
.. seealso:: See :class:`PyLabPlot` for details about the x and y connector.
.. sectionauthor:: Thomas Cokelaer <Thomas.Cokelaer@sophia.inria.fr>
"""
def __init__(self):
PlotxyInterface.__init__(self)
inputs = [
{'name':'x', 'interface':None, 'value':None},
{'name':'y', 'interface':None, 'value':None},
{'name':'marker', 'interface':IEnumStr(list(tools.markers.keys())), 'value':'circle'},
{'name':'markersize', 'interface':IFloat, 'value':10},
{'name':'linestyle', 'interface':IEnumStr(list(tools.linestyles.keys())), 'value':'solid'},
{'name':'color', 'interface':IEnumStr(list(tools.colors.keys())), 'value':'blue'},
]
Plotting.__init__(self, inputs)
self.add_input(name='kwargs', interface=IDict, value={'label':None})
self.add_output(name="output")
def __call__(self, inputs):
kwds = {}
for key,value in self.get_input('kwargs').items():
kwds[key] = value
kwds['markersize'] = self.get_input("markersize")
kwds['marker'] = tools.markers[self.get_input("marker")]
kwds['linestyle'] = tools.linestyles[self.get_input("linestyle")]
kwds['color'] = tools.colors[self.get_input("color")]
self.figure()
self.axes()
self.call('semilogy', kwds)
self.update_figure()
return self.axe, None
[docs]
class PyLabSemiLogx(Plotting, PlotxyInterface):
"""Make a plot with log scaling on x-axis. See pylab.semilogx for details.
:param axes: an optional axes where new data will be plotted.
:param x: one or several arrays, or one or several PyLabLine2D objects.
:param y: one or several arrays, or one or several PyLabLine2D objects.
:param str marker: a valid matplotlib marker (e.g., [ '+' | '*']).
:param int markersize: marker size (default is 10)
:param str linestyle: The linestyle of a curve [None | 'solid' | 'dashed' | 'dashdot' | 'dotted' ]
:param str color: a color selected from the list or connected to a :class:`~openalea.color.color`
node to select any color from the wheel color.
:param kwargs: a :class:`PyLabLine2D` object to fully tune the lines.
:param int figure: figure id
:return:
* the axes in which the data are plotted.
* the output of plot function (line2d)
:Example:
.. dataflow:: openalea.pylab.test semilogx
:width: 50%
**The openalea.pylab.test.semilogx dataflow.**
.. plot::
:width: 50%
from openalea.core.alea import *
pm = PackageManager()
run_and_display(('openalea.pylab.test', 'semilogx'),{},pm=pm)
.. seealso:: See :class:`PyLabPlot` for details about the x and y connector.
.. sectionauthor:: Thomas Cokelaer <Thomas.Cokelaer@sophia.inria.fr>
"""
def __init__(self):
self.__doc__ = PyLabPlot.__doc__
PlotxyInterface.__init__(self)
inputs = [
{'name':'x', 'interface':None, 'value':None},
{'name':'y', 'interface':None, 'value':None},
{'name':'marker', 'interface':IEnumStr(list(tools.markers.keys())), 'value':'circle'},
{'name':'markersize', 'interface':IFloat, 'value':10},
{'name':'linestyle', 'interface':IEnumStr(list(tools.linestyles.keys())), 'value':'solid'},
{'name':'color', 'interface':IEnumStr(list(tools.colors.keys())), 'value':'blue'},
]
Plotting.__init__(self, inputs)
self.add_input(name='kwargs', interface=IDict, value={'label':None})
self.add_output(name="output")
def __call__(self, inputs):
kwds = {}
for key,value in self.get_input('kwargs').items():
kwds[key] = value
kwds['markersize']=self.get_input("markersize")
kwds['marker']=tools.markers[self.get_input("marker")]
kwds['linestyle']=tools.linestyles[self.get_input("linestyle")]
kwds['color']=tools.colors[self.get_input("color")]
self.figure()
self.axes()
self.call('semilogx', kwds)
self.update_figure()
return self.axe, None
[docs]
class PyLabHist(Plotting):
"""Compute and draw the histogram of *x*. See pylab.hist for details.
:param axes: an optional axes where new data will be plotted.
:param array x: the input data (1D array)
:param int bins: binning number (default is 10)
:param str facecolor: (default is blue)
:param bool normed: if *True*, the first element of the return tuple will
be the counts normalized to form a probability density (default is False).
:param bool cumulative: draw cumulated histogram (default False)
:param str histtype: The type of histogram to draw [ 'bar' | 'barstacked' | 'step' | 'stepfilled' ]
:param str align: Controls how the histogram is plotted ['left' | 'mid' | 'right' ]
:param str orientation: horizontal or vertical (default vertical)
:param bool log: logarithmic scale (default is False)
:param str label: a text label for the legend
:param kwargs: a :class:`~openalea.pylab_plotting_wralea.py_pylab.PyLabLine2D` object
:param int figure: figure id
:returns:
* The first connector is the current axe.
* The second connector is the output of pylab.hist that is a tuple (lags, c, linecol, b)
.. dataflow:: openalea.pylab.test hist
:width: 50%
**The `openalea.pylab.test.hist` dataflow.**
.. plot::
:width: 50%
from openalea.core.alea import *
pm = PackageManager()
run_and_display(('openalea.pylab.test', 'hist'),{},pm=pm)
.. sectionauthor:: Thomas Cokelaer <Thomas.Cokelaer@sophia.inria.fr>
"""
def __init__(self):
inputs = [
{'name':'x'},
{'name':'bins', 'interface':IInt, 'value':10},
{'name':'facecolor', 'interface':IEnumStr(list(tools.colors.keys())), 'value':'blue'},
{'name':'density', 'interface':IBool, 'value':False},
{'name':'cumulative', 'interface':IBool, 'value':False},
{'name':'histtype', 'interface':IEnumStr(list(tools.histtype.keys())), 'value':'bar'},
{'name':'align', 'interface':IEnumStr(list(tools.align.keys())), 'value':'mid'},
{'name':'orientation', 'interface':IEnumStr(list(tools.orientations.keys())), 'value':'vertical'},
{'name':'log', 'interface':IBool, 'value':False},
{'name':'label', 'interface':IStr, 'value':''}
]
Plotting.__init__(self, inputs)
self.add_input(name="kwargs", interface = IDict, value={'alpha':1., 'animated':False})
self.add_output(name="axes")
self.add_output(name="position")
self.add_output(name="counts")
def __call__(self, inputs):
from pylab import cla, hist, Line2D
self.figure()
self.axes()
#cla()
kwds={}
kwds['bins']=self.get_input("bins")
kwds['density']=self.get_input("density")
kwds['facecolor']=tools.get_valid_color(self.get_input("facecolor"))
kwds['label']=self.get_input("label")
kwds['log']=self.get_input("log")
kwds['orientation']=tools.orientations[self.get_input("orientation")]
#kwds['figure']=self.get_input("figure")
kwds['histtype']=tools.histtype[self.get_input("histtype")]
kwds['align']=tools.align[self.get_input("align")]
kwds['cumulative']=self.get_input("cumulative")
#!! facecolor is alrady in the Hist node, so override it if available in kwargs dict
for key,value in self.get_input('kwargs').items():
kwds[key] = value
xinputs = self.get_input('x')
if type(xinputs)!=list:
xinputs = [xinputs]
try:
for x in xinputs:
if type(x)==Line2D:
line2dkwds = tools.get_kwds_from_line2d(x, kwds, type='hist')
res = self.axe.hist(x.get_ydata(orig=False),**line2dkwds)
else:
res = self.axe.hist(x,**kwds)
except ValueError as e:
res = (None, None)
print(e)
raise ValueError('tttt')
self.update_figure()
return (self.axe,res, res[1],res[0])
[docs]
class PyLabAcorr(Plotting):
r"""Plot the autocorrelation of *x*. See pylab.acorr for details.
:param axes: an optional axes where new data will be plotted.
:param array x: an input array
:param int maxlags: a positive integer detailing the number of lags to show.
(default None means :math:`2 \times \mathrm{len}(x) - 1` lags).
:param bool density: if *True*, draw and return a probability density: each bin
will display the bin's raw count divided by the total number of counts and the bin width.
:param bool usevlines: If *True*, :meth:`~matplotlib.axes.Axes.vlines`
rather than :meth:`~matplotlib.axes.Axes.plot` is used to draw
vertical lines from the origin to the acorr. Otherwise, the
plot style is determined by the kwargs, which are
:class:`~matplotlib.lines.Line2D` properties. (default True)
:param str detrend: apply a linear or mean detrend if not None (default is None)
:param dict kwargs: Connect a :class:`~openalea.pylab_plotting_wralea.py_pylab.PyLabLine2D`
to customize the curve.
:param int figure: figure id
:returns:
- The first connector is the current axe.
- The second connector is the output of pylab.acorr that is a tuple (*lags*, *c*, *linecol*, *b*)
.. seealso:: in VisuAlea, see pylab/test/acorr composite node.
:class:`~~openalea.pylab_plotting_wralea.py_pylab.PyLabXcorr`
:Example:
.. dataflow:: openalea.pylab.test acorr
:width: 50%
**openalea.pylab.test.acorr dataflow** The node **PyLabAcorr** computes the autocorrelation of the input
data (here some data with a gaussian distribution). The **PyLabLine2D** allows to tune the marker color
(red). finally, the **PyLabGrid** node adds a grid to
the final figure.
.. plot::
:width: 50%
from openalea.core.alea import *
pm = PackageManager()
run(('openalea.pylab.test', 'acorr'),{},pm=pm)
.. sectionauthor:: Thomas Cokelaer <Thomas.Cokelaer@sophia.inria.fr>
"""
def __init__(self):
inputs = [
{'name':'x', 'interface':None, 'value':None},
{'name':"maxlags", 'interface':IInt, 'value':10},
{'name':"normed", 'interface':IBool, 'value':True},
{'name':"usevlines", 'interface':IBool, 'value':True},
{'name':'detrend', 'interface':IEnumStr(list(tools.detrends.keys())), 'value':'none'},
{'name':"kwargs(line2d)", 'interface':IDict, 'value':{}}
]
Plotting.__init__(self, inputs)
self.add_output(name='output', interface=ITuple, value=())
def __call__(self, inputs):
from pylab import clf, acorr, Line2D, gca
import pylab
self.figure()
self.axes()
kwds = {}
line2d = self.get_input('kwargs(line2d)')
if type(line2d)==Line2D:
kwds = line2d.properties()
if self.get_input("usevlines") is False:
for x in ['axes', 'children', 'bbox', 'path','xdata', 'ydata', 'data','transform',
'xydata','transformed_clip_path_and_affine', 'picker'
]:
kwds.pop(x, None)
else:
for x in ['axes', 'markerfacecoloralt','marker',
'children', 'bbox', 'markeredgecolor',
'dash_capstyle','solid_joinstyle','markeredgewidth',
'markerfacecolor','markevery','path',
'picker','fillstyle','solid_capstyle',
'xdata','ydata','markersize',
'data','drawstyle','dash_joinstyle',
'xydata','transformed_clip_path_and_affine',
'transform']:
kwds.pop(x, None)
else:
for key,value in self.get_input('kwargs(line2d)').items():
kwds[key] = value
#print kwds
kwds['maxlags'] = self.get_input("maxlags")
kwds['normed'] = self.get_input("normed")
kwds['usevlines'] = self.get_input("usevlines")
kwds['detrend'] = getattr(pylab, 'detrend_'+self.get_input('detrend'))
res = None
xinputs=self.get_input('x')
if type(xinputs)!=list:
xinputs = [xinputs]
#line2dkwds = get_kwds_from_line2d(x, self.get_input('kwargs'), type='linecollection')
#returns the processed data ?
for x in xinputs:
res = acorr(x, **kwds)
self.update_figure()
return self.get_input('axes'), res
[docs]
class PyLabXcorr(Plotting):
r"""Plot the crosscorrelation of *x* with *y*. See pylab.xcorr for details.
x and y inputs must be of same length. If N arrays are connected to x, then
the y connector expects N arrays as well and the xcross function will be called
N times.
:param axes: an optional axes where new data will be plotted.
:param x: the *x* input data
:param y: the *y* input data
:param int maxlags*: a positive integer detailing the number of lags to show.
(default None means :math:`2 \times \mathrm{len}(x) - 1` lags).
:param bool normed: if *True*, normalize the data by the autocorrelation at 0-th lag.
:param usevlines: If *True*, :meth:`~matplotlib.axes.Axes.vlines`
rather than :meth:`~matplotlib.axes.Axes.plot` is used to draw
vertical lines from the origin to the acorr. Otherwise, the
plot style is determined by the kwargs, which are
:class:`~matplotlib.lines.Line2D` properties. (default True)
:param str detrend: apply a linear or mean detrend if not None (default is None)
:param kwargs: Connect a PyLabLine2D to customize the output.
:param int figure: figure id
:returns:
- The first connector is the current axe.
- The second connector is the output of pylab.acorr that is a tuple (*lags*, *c*, *linecol*, *b*)
.. seealso:: in VisuAlea, see pylab/test/acorr composite node.
:class:`~~openalea.pylab_plotting_wralea.py_pylab.PyLabAcorr`
:Example:
.. dataflow:: openalea.pylab.test xcorr
:width: 50%
**The openalea.pylab.test.xcorr dataflow.**
.. plot::
:width: 50%
from openalea.core.alea import *
pm = PackageManager()
run_and_display(('openalea.pylab.test', 'xcorr'),{},pm=pm)
.. sectionauthor:: Thomas Cokelaer <Thomas.Cokelaer@sophia.inria.fr>
"""
def __init__(self):
inputs = [
{'name':'x', 'interface':None, 'value':None},
{'name':'y', 'interface':None, 'value':None},
{'name':"maxlags", 'interface':IInt, 'value':10},
{'name':"normed", 'interface':IBool, 'value':True},
{'name':"usevlines", 'interface':IBool, 'value':True},
{'name':'detrend', 'interface':IEnumStr(list(tools.detrends.keys())), 'value':'none'},
{'name':"kwargs(line2d)", 'interface':IDict, 'value':{}}
]
Plotting.__init__(self, inputs)
self.add_output(name='output', interface=ITuple, value=())
def __call__(self, inputs):
from pylab import clf, xcorr, Line2D, gca
import pylab
self.figure()
self.axes()
kwds = {}
line2d = self.get_input('kwargs(line2d)')
if type(line2d)==Line2D:
kwds = line2d.properties()
if self.get_input("usevlines") is False:
for x in ['axes', 'children', 'bbox', 'path', 'picker', 'xdata', 'ydata', 'data','transform',
'xydata','transformed_clip_path_and_affine',
]:
kwds.pop(x,None)
else:
for x in ['axes', 'markerfacecoloralt','marker',
'children', 'bbox', 'markeredgecolor',
'dash_capstyle','solid_joinstyle','markeredgewidth',
'markerfacecolor','markevery','path',
'fillstyle','solid_capstyle', 'picker',
'xdata','ydata','markersize',
'data','drawstyle','dash_joinstyle',
'xydata','transformed_clip_path_and_affine',
'transform']:
kwds.pop(x, None)
else:
for key,value in self.get_input('kwargs(line2d)').items():
kwds[key] = value
kwds['maxlags'] = self.get_input("maxlags")
kwds['normed'] = self.get_input("normed")
kwds['usevlines'] = self.get_input("usevlines")
kwds['detrend'] = getattr(pylab, 'detrend_'+self.get_input('detrend'))
res = None
xinputs=self.get_input('x')
yinputs=self.get_input('y')
if type(xinputs)!=list:
xinputs = [xinputs]
if type(yinputs)!=list:
yinputs = [yinputs]
#line2dkwds = get_kwds_from_line2d(x, self.get_input('kwargs'), type='linecollection')
#returns the processed data ?
for x, y in zip(xinputs,yinputs):
res = xcorr(x, y, **kwds)
self.update_figure()
return self.get_input('axes'), res
[docs]
class PyLabScatter(Plotting):
"""Make scatter plot of *x* versus *y*. See pylab.scatter for details
:param axes: an optional axes where new data will be plotted.
:param array x: a x-data array
:param array y: a y-data array
:param array size: size in size^2 (default is 20) or an array of the same length as *x* and *y*.
:param str color: can be a single color format string, or a sequence of color
specifications of length *N*, or a sequence of *N* numbers to be mapped to
colors using the *cmap* and *norm* specified via kwargs (see below).
:param str marker: a valid matplotlib marker (e.g., [ '+' | '*']).
:param cmap: a colormap (default jet).
See :class:`~openalea.pylab_decorators_wralea.py_pylab.PyLabColorMap` node.
:param norm: [ None | Normalize ] :class:`matplotlib.colors.Normalize` instance is used to
scale luminance data to 0,1.
:param float vmin: used in conjunction with *norm* to normalize luminance data.
If either *min* or *max* are *None*, the min and max of the color array *C* is used.
:param float vmax: used in conjunction with *norm* to normalize luminance data.
If either *vmin* or *vmax* are *None*, the min and max of the color array *C* is used.
:param float alpha: The alpha blending value. (default is 1.0)
:param float linewidth: width of a line in points (default is 1)
:param int figure: figure id
:returns:
- The first connector is the current axe.
- The second connector is the output of pylab.scatter
.. todo:: allow several x/y inputs.
:Example:
.. dataflow:: openalea.pylab.test scatter
:width: 50%
**The openalea.pylab.test.scatter dataflow.**
.. plot::
:width: 50%
from openalea.core.alea import *
pm = PackageManager()
run_and_display(('openalea.pylab.test', 'scatter'),{},pm=pm)
.. sectionauthor:: Thomas Cokelaer <Thomas.Cokelaer@sophia.inria.fr>
"""
def __init__(self):
inputs = [
{'name':'x', 'value':None},
{'name':'y', 'value':None},
{'name':'sizes', 'value':20},
{'name':"color", 'interface':IEnumStr(list(tools.colors.keys())), 'value':'blue'},
{'name':"marker", 'interface':IEnumStr(list(tools.markers.keys())), 'value' : 'circle'},
{'name':"cmap", 'interface':IEnumStr(list(tools.cmaps.keys())), 'value' : 'jet'},
{'name':"norm", 'interface':IFloat, 'value' : None},
{'name':"vmin", 'interface':IFloat, 'value' : None},
{'name':"vmax", 'interface':IFloat, 'value' : None},
{'name':"alpha", 'interface':IFloat(0,1,0.1), 'value':1.0},
{'name':"faceted", 'interface':IBool, 'value' : True},
{'name':"linewidths", 'interface':None, 'value' : None},
{'name':"verts", 'interface':None, 'value' : None},
{'name':"kwargs", 'interface':IDict, 'value' : {'edgecolors':'none', 'facecolors':'none'}},
]
Plotting.__init__(self, inputs)
self.add_output(name='output')
def __call__(self, inputs):
from pylab import scatter
x = self.get_input("x")
y = self.get_input("y")
sizes = self.get_input("sizes")
try:
color = tools.get_valid_color(self.get_input("color"))
except:
color = self.get_input('color')
marker = tools.markers[self.get_input('marker')]
cmap = tools.cmaps[self.get_input('cmap')]
norm = self.get_input('norm')
vmin = self.get_input('vmin')
vmax = self.get_input('vmax')
if vmin == vmax:
vmin = None
vmax = None
alpha = self.get_input('alpha')
faceted = self.get_input('faceted')
linewidths = self.get_input('linewidths')
verts = self.get_input('verts')
kwds = {}
if self.get_input('kwargs'):
for key, value in self.get_input('kwargs').items():
kwds[key] = value
self.figure()
self.axes()
res = scatter(x,y, s=sizes,c=color,
marker=marker,norm=norm, vmin=vmin,vmax=vmax,
alpha=alpha, cmap=cmap,
linewidths=linewidths, **kwds)
self.update_figure()
return self.axe, res
[docs]
class PyLabBoxPlot(Plotting):
"""Make a box and whisker plot. See pylab.boxplot for details.
:param axes: an optional axes where new data will be plotted.
:param x: data
:param bool notch: 0 (default) makes a rectangular box plot, 1 makes a notched box plot.
:param str marker: a valid matplotlib marker (e.g., [ '+' | '*']).
:param str color: a color selected from the list or connecte to :class:`~openalea.color.color`
node to select any color from the wheel color.
:param bool vert: 1 (default) makes the boxes vertical, 0 makes horizontal boxes.
:param float whis: (default 1.5) defines the length of the whiskers as a function of the
inner quartile range. They extend to the most extreme data point within ( ``whis*(75%-25%)`` )
data range.
:param str sym: (default 'b+') is the default symbol for flier points. Enter an empty string ('')
if you don't want to show fliers.
:param positions: (default 1,2,...,n) sets the horizontal positions of the boxes.
The ticks and limits are automatically set to match the positions
:param float widths: either a scalar or a vector and sets the width of
each box. The default is 0.5, or ``0.15*(distance between extreme
positions)`` if that is smaller.
:param int bootstrap: see pylab.boxplot for details
:param int figure: figure id
.. seealso:: in VisuAlea, see pylab/test/boxplot composite node.
:Example:
.. dataflow:: openalea.pylab.test boxplot
:width: 50%
**The openalea.pylab.test.boxplot dataflow.** Connect several arrays to the x connector; each of the array
will be shown as a single boxplot.
.. plot::
:width: 50%
from openalea.core.alea import *
pm = PackageManager()
run_and_display(('openalea.pylab.test', 'boxplot'),{},pm=pm)
.. sectionauthor:: Thomas Cokelaer <Thomas.Cokelaer@sophia.inria.fr>
"""
def __init__(self):
inputs = [
{'name':"x"},
{'name':"notch", 'interface':IEnumStr({'0':0,'1':1}), 'value':0},
{'name':"marker", 'interface':IEnumStr(list(tools.markers.keys())), 'value':'plus'},
{'name':"color", 'interface':IEnumStr(list(tools.colors.keys())), 'value':'blue'},
{'name':"vert", 'interface':IEnumStr({'0':0,'1':1}), 'value':1},
{'name':"whis", 'interface':IFloat, 'value':1.5},
{'name':"positions",'interface':ISequence, 'value':None},
{'name':"widths", 'interface':IFloat, 'value':None},
{'name':"hold", "interface":IBool, 'value':True},
{'name':"bootstrap", "interface":IInt, 'value':None},
{'name':"patch_artist", 'interface':IBool, 'value':False},
]
Plotting.__init__(self, inputs)
#self.__doc__+=plot.__doc__
self.add_output(name='output')
def __call__(self, inputs):
from pylab import boxplot
self.figure()
self.axes()
x = self.get_input("x")
#hack for matplotlib <1.0
bootstrap =self.get_input('bootstrap')
patch_artist =self.get_input('patch_artist')
#bootstrap not used
res = boxplot(x,
sym=tools.markers[self.get_input("marker")]+tools.colors[self.get_input("color")],
vert=self.get_input("vert"),
notch=self.get_input("notch"),
whis=self.get_input("whis"),
positions=self.get_input('positions'),
widths=self.get_input('widths'),
)
self.update_figure()
return self.get_input('axes'), res
[docs]
class PyLabLine2D(Node):
"""Convert x and y inputs into a pylab.Line2D objects.
:param xdata: a x array
:param ydata: a y array of same length as x
:param linestyle: a valid pylab linestyle
:param color: a valid pylab color
:param str marker: a valid matplotlib marker (e.g., [ '+' | '*']).
:param markersize:
:param markeredgewidth:
:param markercolor:
:param float linewidth: width of a line in points (default is 1)
:param fillstyle:
:param label: a label that will be used when legend() is called
:param float alpha: The alpha blending value.
:param kwargs: all other valid Line2D properties (key/value)
:return: a Line2D object that can be connected to some of the OpenAlea.PyLab nodes.
.. sectionauthor:: Thomas Cokelaer <Thomas.Cokelaer@sophia.inria.fr>
"""
def __init__(self):
Node.__init__(self)
self.add_input(name="xdata", value=[])
self.add_input(name="ydata", value=[])
self.add_input(name="linestyle", interface=IEnumStr(list(tools.linestyles.keys())), value='solid')
self.add_input(name="color", interface=IEnumStr(list(tools.colors.keys())),value='blue')
self.add_input(name="marker", interface=IEnumStr(list(tools.markers.keys())),value='circle')
self.add_input(name="markersize", interface=IInt, value=10)
self.add_input(name="markeredgewidth", interface=IFloat(0.,10,0.1) , value=None)
self.add_input(name="markeredgecolor", interface=IEnumStr(list(tools.colors.keys())), value='None')
self.add_input(name="linewidth", interface=IFloat, value=1.)
self.add_input(name="fillstyle", interface=IEnumStr(tools.fillstyles), value='full')
self.add_input(name="label", interface=IStr, value=None)
self.add_input(name="alpha", interface=IFloat(0.,1., step=0.1), value=1.0)
self.add_input(name="kwargs", interface=IDict, value={})
self.add_output(name="line2d")
def __call__(self, inputs):
from pylab import Line2D
kwds = {}
for key, value in self.get_input('kwargs').items():
kwds[key] = value
xdata=self.get_input('xdata')
ydata=self.get_input('ydata')
#why?
if not any(ydata) or len(ydata)==0:
ydata = xdata
xdata = list(range(0, len(ydata)))
output = Line2D(
xdata=xdata,
ydata=ydata,
linestyle=tools.linestyles[self.get_input('linestyle')],
color=tools.colors[self.get_input('color')],
marker=tools.markers[self.get_input('marker')],
label=self.get_input('label'),
markersize=self.get_input('markersize'),
markeredgecolor=tools.colors[self.get_input('markeredgecolor')],
markeredgewidth=self.get_input('markeredgewidth'),
linewidth=self.get_input('linewidth'),
fillstyle=self.get_input('fillstyle'),
alpha=self.get_input('alpha'),**kwds
)
return (output, )
[docs]
class PyLabPolar(Plotting, PlotxyInterface):
"""Make a polar plot. See pylab.polar for details.
:param axes: an optional axes where new data will be plotted.
:param array theta:
:param array r:
:param dict kwargs: Connect a :class:`~openalea.pylab_plotting_wralea.py_pylab.PyLabLine2D`
to customize the curve
Multiple *theta*, *r* arguments are supported. See
:class:`~openalea.pylab_plotting_wralea.py_pylab.PyLabPlot` for the usage.
:Example:
.. dataflow:: openalea.pylab.test polar
:width: 50%
**The `openalea.pylab.test.polar` dataflow.**
.. plot::
:width: 50%
from openalea.core.alea import *
pm = PackageManager()
run_and_display(('openalea.pylab.test', 'polar'),{},pm=pm )
.. sectionauthor:: Thomas Cokelaer <Thomas.Cokelaer@sophia.inria.fr>
"""
def __init__(self):
PlotxyInterface.__init__(self)
inputs = [
{'name':"theta"},
{'name':"r"},
{'name':"kwargs(line2d)", 'interface':IDict, 'value':{}}
]
Plotting.__init__(self, inputs)
self.add_output(name='output')
def __call__(self, inputs):
from pylab import polar, gca,cla
self.figure()
#do not use that method that is not appropriate to a polar axe
#self.axes()
kwds = {}
for key, value in self.get_input('kwargs(line2d)').items():
kwds[key] = value
try:
del kwds['facecolor']
except:
pass
if self.get_input('axes') is not None:
sca(self.get_input('axes'))
self.axe = gca()
else:
if self.axe != None:
try:
from pylab import sca
sca(self.axe)
cla()
except:
from pylab import Figure
f = self.axe.get_figure()
Figure.sca(f, self.axe)
cla()
output = self.call('polar', kwds)
self.axe = gca()
self.update_figure()
return self.axe, output
[docs]
class PyLabPie(Plotting):
"""Make a pie chart of array *x*. See pylab.pie for details.
The fractional area of each wedge is given by x/sum(x).
If sum(x) <= 1, then the values of x give the fractional area directly
and the array will not be normalized.
:param axes: an optional axes where new data will be plotted.
:param array x: a 1D array
:param array colors: a sequence of matplotlib color for each *x* element
:param array labels: a sequence of labels for each *x* element
:param array explode: sequence of fraction of the radius with which to offset each wedge.
:param array autopct: a string or function used to label the wedges with their numeric value.
the wedge. If it is a format string, the label will be ``fmt%pct``.
:param float pctdistance: ratio between the center of each pie slice and the text generated by *autopct*.
(default is 0.6).
:param float labeldistance: radial distance at which the pie labels are drawn
:param bool shadow: draw a shadow beneath the pie (default is False).
:param int figure: figure id
:Example:
.. dataflow:: openalea.pylab.test pie
:width: 50%
**The openalea.pylab.test.pie dataflow.** The x array contains the numerical values and the y array
contains the labels.
.. plot::
:width: 50%
from openalea.core.alea import *
pm = PackageManager()
run_and_display(('openalea.pylab.test', 'pie'),{},pm=pm )
.. sectionauthor:: Thomas Cokelaer <Thomas.Cokelaer@sophia.inria.fr>
"""
def __init__(self):
inputs = [
{ 'name':'x'},
{'name':'colors', 'interface':IStr, 'value':None},
{'name':'labels', 'interface':ISequence, 'value':None},
{'name':'explode', 'interface':ISequence, 'value':None},
{'name':'pctdistance', 'interface':IFloat, 'value':0.6},
{'name':'labeldistance','interface':IFloat, 'value':1.1},
{'name':'shadow', 'interface':IBool, 'value':False},
{'name':'autopct', 'interface':IStr, 'value':None},
{'name':'hold', 'interface':IBool, 'value':True}
]
Plotting.__init__(self, inputs)
self.add_output(name='output')
def __call__(self, inputs):
from pylab import pie
self.figure()
self.axes()
kwds = {}
kwds['explode'] = self.get_input('explode')
kwds['colors'] = self.get_input('colors')
kwds['labels'] = self.get_input('labels')
kwds['pctdistance'] = self.get_input('pctdistance')
kwds['labeldistance'] = self.get_input('labeldistance')
kwds['shadow'] = self.get_input('shadow')
kwds['autopct'] = self.get_input('autopct')
print(kwds)
res = self.axe.pie(self.get_input('x'), **kwds)
self.update_figure()
return self.axe, res
[docs]
class PyLabBar(Plotting):
"""See pylab.bar for details.
.. todo:: !!!!!!!!!! this node is not yet completed.
.. sectionauthor:: Thomas Cokelaer <Thomas.Cokelaer@sophia.inria.fr>
"""
def __init__(self):
inputs = [
{'name':'left', 'interface':ISequence, 'value':[]},
{'name':'height', 'interface':ISequence, 'value':[]}
]
Plotting.__init__(self, inputs)
def __call__(self, inputs):
from pylab import bar, cla
self.figure()
self.axes()
cla()
left = self.get_input('left')
height = self.get_input('height')
if type(left)!=list:
left = [left]
res = None
if type(left[0])==float:
width = left[1] - left[0]
res = bar(left[1:], height, width=width)
else:
c = enumerate(tools.colors)
for x,y in zip(left, height):
color = next(c)
#width = x[1]-x[0]
width=0.1
res = bar(x[1:],y, width=width, color=color[1], alpha=0.5)
self.update_figure()
return self.axe, res
[docs]
class PyLabCohere(Plotting):
"""Plot the coherence between *x* and *y* (normalized cross spectral density). See pylab.cohere for details.
A function or a vector of length *NFFT*. To create window
vectors see :func:`window_hanning`, :func:`window_none`,
:func:`numpy.blackman`, :func:`numpy.hamming`,
:func:`numpy.bartlett`, :func:`scipy.signal`,
:func:`scipy.signal.get_window`, etc. The default is
:func:`window_hanning`. If a function is passed as the
argument, it must take a data segment as an argument and
return the windowed version of the segment.
:param axes: an optional axes where new data will be plotted.
:param array x: an input array
:param array y: an input array
:param int NFFT: The number of data points used in each block for the FFT. The default is 256.
Must be even; a power 2 is most efficient.
:param float Fs: The sampling frequency (default is 2).
:param float Fc: The center frequency of *x* (default is 0).
:param str detrend: The function applied to each segment before fft-ing,
designed to remove the mean or linear trend (default is 'none')
:param str window: function or a vector of length *NFFT*. default is hanning window
To create other window, use the :class:`~openalea.pylab_text_wralea.py_pylab.PyLabWindow` node.
:param int noverlap: The number of points of overlap between blocks. (default is 0, no overlap).
:param int pad_to: The number of points to which the data segment is padded when
performing the FFT (default is None)
:param str sides: Specifies which sides of the PSD to return (default is 'default').
:param bool scale_by_freq: (default is True)
:param dict kwargs: Connect a :class:`~openalea.pylab_plotting_wralea.py_pylab.PyLabLine2D`
to customize the curve.
:param int figure: figure id
:Example:
.. dataflow:: openalea.pylab.test cohere
:width: 50%
**The openalea.pylab.test.cohere dataflow.** In the simplest case, connect the x/y arrays to the
x connector and y connector respectively. In this example, we want to further tune the curves, so
we use the **PyLabLine2D** node. Therefore, only on edge is connected to the x connector. Nevertheless,
the node **PyLabCohere** will extract the x and y arrays for you.
.. plot::
:width: 50%
from openalea.core.alea import *
pm = PackageManager()
run_and_display(('openalea.pylab.test', 'cohere'),{},pm=pm )
.. todo:: kwargs does not yet accept the node Line2D
.. sectionauthor:: Thomas Cokelaer <Thomas.Cokelaer@sophia.inria.fr>
"""
def __init__(self):
inputs = [
{'name':'x', 'interface':None, 'value':None},
{'name':'y', 'interface':None, 'value':None},
{'name':'NFFT', 'interface':IInt, 'value':256},
{'name':'Fs', 'interface':IFloat, 'value':2.},
{'name':'Fc', 'interface':IFloat, 'value':0},
{'name':'detrend', 'interface':IEnumStr(list(tools.detrends.keys())), 'value':'none'},
{'name':'window', 'interface':IEnumStr(list(tools.windows.keys())), 'value':'hanning'},
{'name':'noverlap', 'interface':IInt, 'value':0},
{'name':'pad_to', 'interface':IInt, 'value':None},
{'name':'sides', 'interface':IEnumStr(tools.sides), 'value':'default'},
{'name':'scale_by_freq','interface':IBool, 'value':True},
{'name':'kwargs(line2d)','interface':IDict, 'value':{}},
]
Plotting.__init__(self, inputs)
self.add_output(name='output')
def __call__(self, inputs):
from pylab import cohere, Line2D
import pylab
self.figure()
self.axes()
kwds = {}
line2d = self.get_input('kwargs(line2d)')
if type(line2d)==Line2D:
kwds = line2d.properties()
else:
for key,value in self.get_input('kwargs(line2d)').items():
kwds[key] = value
for x in ['children', 'path','xydata','transformed_clip_path_and_affine' ]:
try:
del kwds[x]
except:
pass
NFFT = self.get_input('NFFT')
Fs = self.get_input('Fs')
Fc = self.get_input('Fc')
detrend = getattr(pylab, 'detrend_'+self.get_input('detrend'))
try:
window = tools.windows[self.get_input('window')]
except:
window = self.get_input('window')
noverlap = self.get_input('noverlap')
pad_to = self.get_input('pad_to')
sides = self.get_input('sides')
scale_by_freq = self.get_input('scale_by_freq')
cxy = None
freq = None
#scale_by_freq not used due to a wierd behaviour, not understood
try:
cxy, freq = cohere(self.get_input('x'), self.get_input('y'),
NFFT=NFFT, Fs=Fs, Fc=Fc, detrend=detrend,
window=window, noverlap=noverlap, pad_to=pad_to,
sides=sides, **kwds)
except:
xinputs=self.get_input('x')
if type(xinputs)!=list:
xinputs = [xinputs]
if type(xinputs[0])==Line2D:
for x in xinputs:
line2dkwds = tools.get_kwds_from_line2d(x, kwds)
for this in ['facecolor', 'children', 'path','xydata','transformed_clip_path_and_affine' ]:
try:
del line2dkwds[this]
except:
pass
#returns the processed data ?
cxy, freq = cohere(x.get_xdata(orig=False), x.get_ydata(orig=False),
NFFT=NFFT, Fs=Fs, Fc=Fc, detrend=detrend,
window=window, noverlap=noverlap, pad_to=pad_to,
sides=sides, **line2dkwds)
self.update_figure()
return self.get_input('axes'), (cxy, freq)
[docs]
class PyLabHexBin(Plotting):
"""Make a hexagonal binning plot of *x* versus *y*. See pylab.hexbin for details.
:param axes: an optional axes where new data will be plotted.
:param x: a 1D array
:param y: a 1D array
:param C: If *C* is specified, it specifies values at the coordinate (x[i],y[i])
:param int gridsize: the number of hexagons in the x and y directions.
:param bins: [ None | 'log' | integer | sequence ]
* If *None*, no binning is applied; the color of each hexagon directly corresponds to its count value.
* If 'log', use a logarithmic scale for the color map. Internally, :math:`log_{10}(i+1)` is used to
determine the hexagon color.
* If an integer, divide the counts in the specified number of bins, and color the hexagons accordingly.
* If a sequence of values, the values of the lower bound of the bins to be used.
:param str xscale: [ 'linear' | 'log' ] Use a linear or log10 scale on the horizontal axis.
:param str yscale: [ 'linear' | 'log' ] Use a linear or log10 scale on the vertical axis.
:param cmap: a colormap (default jet).
See :class:`~openalea.pylab_decorators_wralea.py_pylab.PyLabColorMap` node.
:param norm: [ None | Normalize ] :class:`matplotlib.colors.Normalize` instance is used to
scale luminance data to 0,1.
:param float vmin: used in conjunction with *norm* to normalize luminance data.
If either *min* or *max* are *None*, the min and max of the color array *C* is used.
:param float vmax: used in conjunction with *norm* to normalize luminance data.
If either *vmin* or *vmax* are *None*, the min and max of the color array *C* is used.
:param float alpha: The alpha blending value. (default is 1.0)
:param float linewidths: width of lines in points (default is None)
:param str edgecolors: a color selected from the list or connected to a :class:`~openalea.color.color`
node to select any color from the wheel color.
:param reduce_C_function: numpy.mean function
:param int mincnt: None | a positive integer, if not None, only display cells with more than *mincnt*
number of points in the cell
:param bool marginals: if marginals is True, plot the marginal density as colormapped rectangles
along the bottom of the x-axis and left of the y-axis
:param float extent: [ None | scalars (left, right, bottom, top) ] The limits of the bins.
The default assigns the limits based on gridsize, x, y, xscale and yscale.
:param dict kwargs: Connect a dictionary to further tune the polygons.
:param int figure: figure id
:Example:
.. dataflow:: openalea.pylab.test hexbin
:width: 50%
**The `openalea.pylab.test.hexbin` dataflow.**
.. plot::
:width: 50%
from openalea.core.alea import *
pm = PackageManager()
run_and_display(('openalea.pylab.test', 'hexbin'),{},pm=pm )
.. sectionauthor:: Thomas Cokelaer <Thomas.Cokelaer@sophia.inria.fr>
"""
def __init__(self):
import numpy as np
inputs = [
{'name':"x"},
{'name':"y"},
{'name':"C", 'interface':None, 'value':None},
{'name':"gridsize", 'interface':IInt, 'value':100},
{'name':"bins", 'interface':IInt, 'value':None},
{'name':"xscale", 'interface':IEnumStr(list(tools.scale.keys())), 'value':'linear'},
{'name':"yscale", 'interface':IEnumStr(list(tools.scale.keys())), 'value':'linear'},
{'name':"cmap", 'interface':IEnumStr(list(tools.cmaps.keys())), 'value':'jet'},
{'name':"norm", 'interface':None, 'value':None},
{'name':"vmin", 'interface':IFloat, 'value':None},
{'name':"vmax", 'interface':IFloat, 'value':None},
{'name':"alpha", 'interface':IFloat(0,1,0.1), 'value':1.0},
{'name':"linewidths", 'interface':IFloat(0,10,1), 'value':None},
{'name':"edgecolors", 'interface':IEnumStr(list(tools.colors.keys())), 'value':'None'},
{'name':"reduce_C_function", 'interface':None, 'value':np.mean},
{'name':"mincnt", 'interface':IInt, 'value':None},
{'name':"marginals", 'interface':IBool, 'value':True},
{'name':"extent", 'interface':None, 'value':None},
{'name':"kwargs(collection)", 'interface':IDict, 'value':{}},
]
Plotting.__init__(self, inputs)
self.add_output(name='output')
def __call__(self, inputs):
from pylab import hexbin
x = self.get_input('x')
y = self.get_input('y')
C = self.get_input('C')
gridsize = self.get_input('gridsize')
bins = self.get_input('bins')
xscale = self.get_input('xscale')
yscale = self.get_input('yscale')
cmap = self.get_input('cmap')
norm = self.get_input('norm')
vmin = self.get_input('vmin')
vmax = self.get_input('vmax')
alpha = self.get_input('alpha')
linewidths = self.get_input('linewidths')
edgecolors = tools.colors[self.get_input('edgecolors')]
reduce_C_function = self.get_input('reduce_C_function')
mincnt = self.get_input('mincnt')
marginals = self.get_input('marginals')
extent = self.get_input('extent')
kwds={}
for key, value in self.get_input('kwargs(collection)'):
kwds[key] = value
self.figure()
self.axes()
output = hexbin(x, y, C=C, gridsize=gridsize, bins=bins,
xscale=xscale, yscale=yscale,
cmap=cmap, norm=norm, vmin=vmin, vmax=vmax,
alpha=alpha, linewidths=linewidths, edgecolors=edgecolors,
reduce_C_function=reduce_C_function,
marginals=marginals, extent=extent,
mincnt=mincnt,
**kwds)
self.update_figure()
return self.axe, output
[docs]
class PyLabCLabel(Node):
"""adds labels to line contours. See pylab.clabel for details.
.. seealso:: :class:`~openalea.pylab_plotting_wralea.py_pylab.PyLabContour`
.. sectionauthor:: Thomas Cokelaer <Thomas.Cokelaer@sophia.inria.fr>
"""
def __init__(self):
Node.__init__(self)
self.add_input(name='axes')
self.add_input(name='CS')
self.add_input(name='v')
self.add_input(name='fontsize', interface=IInt, value=10)
self.add_input(name='colors', interface=IEnumStr(list(tools.colors.keys())), value='None')
self.add_input(name='inline', interface=IBool, value=True)
self.add_input(name='inline_spacing', interface=IInt, value=5)
self.add_input(name='fmt', interface=IStr, value='%1.3f')
self.add_input(name='manual', interface=IBool, value=False)
self.add_input(name='rightside_up', interface=IBool, value=True)
self.add_input(name='use_clabeltext', interface=IBool, value=False)
self.add_output(name='axes')
self.add_output(name='output')
def __call__(self, inputs):
from pylab import clabel
kwds = {}
kwds['fontsize'] = self.get_input('fontsize')
kwds['inline'] = self.get_input('inline')
kwds['rightside_up'] = self.get_input('rightside_up')
kwds['inline_spacing'] = self.get_input('inline_spacing')
kwds['fmt'] = self.get_input('fmt')
kwds['colors'] = tools.colors[self.get_input('colors')]
kwds['manual'] = self.get_input('manual')
kwds['rightside_up'] = self.get_input('rightside_up')
kwds['use_clabeltext'] = self.get_input('use_clabeltext')
CS = self.get_input('CS')
v = self.get_input('v')
if v:
res = clabel(CS, v, **kwds)
else:
res = clabel(CS, **kwds)
from pylab import gca
gca().get_figure().canvas.draw()
return self.get_input('axes'), res
#class PyLabPcolormesh(Plotting, PcolorInterface): is exactly the same as pcolor but the color optio does not exist.
[docs]
class PyLabPcolor(Plotting):
"""Create a pseudocolor plot of a 2-D array. See pylab.pcolor for details.
:param array X: a 2D array
:param array Y: a 2D array
:param array Z: a 2D array
:param cmap: a colormap (default jet).
See :class:`~openalea.pylab_decorators_wralea.py_pylab.PyLabColorMap` node.
:param norm: [ None | Normalize ] A :class:`matplotlib.colors.Normalize` instance for
scaling data values to colors. If *norm* is *None* and *colors* is *None*.
:param float vmin: used in conjunction with *norm* to normalize luminance data.
If either *min* or *max* are *None*, the min and max of the color array *C* is used.
:param float vmax: used in conjunction with *norm* to normalize luminance data.
If either *vmin* or *vmax* are *None*, the min and max of the color array *C* is used.
:param float alpha: The alpha blending value. (default is 1.0)
:param shading: [ 'flat' | 'faceted' ]
* If 'faceted', a black grid is drawn around each rectangle
* If 'flat', edges are not drawn. Default is 'flat', contrary to
:param kwargs: a dictionary to further customize polycollection.
:param int figure: figure id
:Example:
.. dataflow:: openalea.pylab.test pcolor
:width: 50%
**The `openalea.pylab.test.pcolor` dataflow.** The :class:`~openalea.numpy.meshgrid` converts
x and y arrays into apropriate 2D arrays, which are passed to **PyLabPcolor** node with a
2D Z array.
.. plot::
:width: 50%
from openalea.core.alea import *
pm = PackageManager()
run_and_display(('openalea.pylab.test', 'pcolor'),{},pm=pm )
.. note:: pcolormesh is equivalent to pcolor.
.. sectionauthor:: Thomas Cokelaer <Thomas.Cokelaer@sophia.inria.fr>
"""
def __init__(self):
Node.__init__(self)
inputs = [
{'name':"X"},
{'name':"Y"},
{'name':"Z"},
{'name':'cmap', 'interface':IEnumStr(list(tools.cmaps.keys())), 'value':'jet'},
{'name':"norm", 'interface':None, 'value':None},
{'name':"vmin", 'interface':IFloat, 'value' : None},
{'name':"vmax", 'interface':IFloat, 'value' : None},
{'name':"alpha", 'interface':IFloat(0,1,0.1), 'value':1.0},
{'name':"shading", 'interface':IEnumStr(list(tools.shadings.keys())), 'value' : 'auto'},
{'name':"kwargs(polycollection)", 'interface':IDict, 'value' : {}},
]
Plotting.__init__(self, inputs)
self.add_output(name='output')
def __call__(self, inputs):
from pylab import pcolor, cla
self.figure()
self.axes()
kwds = {}
X = self.get_input('X')
Y = self.get_input('Y')
Z = self.get_input('Z')
cmap = self.get_input('cmap')
norm = self.get_input('norm')
vmin = self.get_input('vmin')
vmax = self.get_input('vmax')
alpha = self.get_input('alpha')
shading = self.get_input('shading')
kwds = {}
for key, value in self.get_input('kwargs(polycollection)').items():
kwds[key] = value
if X is not None and Y is not None:
output = pcolor(X, Y, Z, cmap=cmap, norm=norm, vmin=vmin, vmax=vmax, alpha=alpha, shading=shading, **kwds)
elif Z is not None:
output = pcolor(Z, cmap=cmap, norm=norm, vmin=vmin, vmax=vmax, alpha=alpha, shading=shading, **kwds)
else:
raise ValueError('Z is compulsary. If X provided, Y must be provided as well.')
self.update_figure()
return self.axe, output
[docs]
class PyLabContour(Plotting):
"""make a contour plot of an array *Z*. The level values are chosen automatically. See pylab.contour for details.
:param axes: an optional axes where new data will be plotted.
:param array X: a 2D array
:param array y: a 2D array
:param array Z: a 2D array
:param int N: if an int is provided, contour *N* automatically-chosen levels.
If an array is provided, draw contour lines at the values specified in sequence *V*.
:param float linewidth: width of a line in points (default is 1)
:param str linestyle: The linestyle of a curve [None | 'solid' | 'dashed' | 'dashdot' | 'dotted' ]
:param str color: a color selected from the list or connected to :class:`~openalea.color.color`
node to select any color from the wheel color.
:param float alpha: The alpha blending value. (default is 1.0)
:param cmap: a colormap (default jet).
See :class:`~openalea.pylab_decorators_wralea.py_pylab.PyLabColorMap` node.
:param norm: [ None | Normalize ] A :class:`matplotlib.colors.Normalize` instance for
scaling data values to colors. If *norm* is *None* and *colors* is *None*.
:param levels: *levels* [level0, level1, ..., leveln] A list of floating point numbers indicating the level
curves to draw; eg to draw just the zero contour pass ``levels=[0]``
:param origin: [ None | 'upper' | 'lower' | 'image' ] If *None*, the first value of *Z* will correspond to the
lower left corner, location (0,0). If 'image', the rc value for ``image.origin`` will be used.
This keyword is not active if *X* and *Y* are specified in the call to contour.
:param extent: [ None | (x0,x1,y0,y1) ] This keyword is not active if *X* and *Y* are specified.
:param locator: [ None | ticker.Locator subclass ]. The locator is used to determine the contour levels if they
are not given explicitly via the *V* argument.
:param str extend: [ 'neither' | 'both' | 'min' | 'max' ] (default 'neither') If not 'neither',
make pointed end(s) for out-of-range values.
:param xunits: [ None | registered units ]
:param yunits: [ None | registered units ]
:param bool filled:
:param int figure: figure int
:Example:
.. dataflow:: openalea.pylab.test contour
:width: 50%
**The openalea.pylab.test.contour dataflow.** The :class:`~openalea.numpy.meshgrid` converts
x and y arrays into apropriate 2D arrays. The :class:`~openalea.pylab_plotting._wralea.py_pylab.PyLabCLabel`
allows to customize the iso-contour labels.
.. plot::
:width: 50%
from openalea.core.alea import *
pm = PackageManager()
run_and_display(('openalea.pylab.test', 'contour'),{},pm=pm )
.. sectionauthor:: Thomas Cokelaer <Thomas.Cokelaer@sophia.inria.fr>
"""
def __init__(self):
inputs = [
{'name':"X"},
{'name':"Y"},
{'name':"Z"},
{'name':"N or V"},
# specific to contour
{'name':"linewidths", 'interface':IFloat, 'value':None},
{'name':"linestyles", 'interface':IEnumStr(list(tools.linestyles.keys())), 'value':'solid'},
{'name':"colors", 'interface':IEnumStr(list(tools.colors.keys())), 'value':'None'},
{'name':"alpha", 'interface':IFloat(0,1,0.1), 'value':1.0},
{'name':"cmap", 'interface':None, 'value':None},
{'name':"norm", 'interface':None, 'value':None},
{'name':"levels", 'interface':ISequence, 'value':[]},
{'name':"origin", 'interface':IEnumStr(list(tools.origins.keys())), 'value':'None'},
{'name':"extent", 'interface':None, 'value':None},
{'name':"locator", 'interface':None, 'value':None},
{'name':"extend", 'interface':IEnumStr(list(tools.extends.keys())), 'value':'neither'},
{'name':"xunits", 'interface':None, 'value':None},
{'name':"yunits", 'interface':None, 'value':None},
{'name':"filled", 'interface':IBool, 'value':False},
]
Plotting.__init__(self, inputs)
self.add_output(name='output')
def __call__(self, inputs):
from pylab import contour, contourf
kwds={}
X = self.get_input('X')
Y = self.get_input('Y')
Z = self.get_input('Z')
if Z is None:
raise ValueError('Z must be connected to a 2D array at least!')
NV = self.get_input('N or V')
if type(NV)==int and NV<=0:
NV = None
kwds['linewidths']=self.get_input('linewidths')
kwds['alpha']=self.get_input('alpha')
kwds['colors']=tools.colors[self.get_input('colors')]
kwds['xunits']=self.get_input('xunits')
kwds['yunits']=self.get_input('yunits')
kwds['norm']=self.get_input('norm')
kwds['levels']=self.get_input('levels')
kwds['origin']=tools.origins[self.get_input('origin')]
kwds['extent']=self.get_input('extent')
kwds['extend']=tools.extends[self.get_input('extend')]
if self.get_input('linestyles') in [None, 'None']:
kwds['linestyles']='solid'
else:
kwds['linestyles']=tools.linestyles[self.get_input('linestyles')]
if self.get_input('cmap'):
kwds['cmap']=self.get_input('cmap')
self.figure()
self.axes()
if X is None and Y is None:
if NV == None:
if self.get_input('filled')==True:
c = kwds['colors']
kwds['colors'] = None
contourf(Z, **kwds)
kwds['colors'] = c
CS = contour(Z, **kwds)
else:
CS = contour(Z, **kwds)
else:
if self.get_input('filled')==True:
c = kwds['colors']
kwds['colors'] = None
contourf(Z, NV, **kwds)
kwds['colors'] = c
CS = contour(Z, NV, **kwds)
else:
CS = contour(Z, NV, **kwds)
else: #X,Y,Z case
if NV == None:
if self.get_input('filled')==True:
c = kwds['colors']
kwds['colors'] = None
contourf(X, Y, Z, **kwds)
kwds['colors'] = c
CS = contour(X, Y, Z, **kwds)
else:
CS = contour(X, Y, Z, **kwds)
else:
if self.get_input('filled')==True:
c = kwds['colors']
kwds['colors'] = None
contourf(X, Y, Z, NV, **kwds)
kwds['colors'] = c
CS = contour(X, Y, Z, NV, **kwds)
else:
CS = contour(X, Y, Z, NV, **kwds)
from pylab import gca
gca().get_figure().canvas.draw()
self.update_figure()
return self.get_input('axes'), CS
[docs]
class PyLabPsd(Plotting):
"""The power spectral density. See pylab.psd for details.
:param axes: an optional axes where new data will be plotted.
:param array x: input x array
:param NFFT: The number of data points used in each block for
the FFT. The default is 256. Must be even; a power 2 is most efficient.
:param Fs: The sampling frequency. The default is 2.
:param Fc: The center frequency of *x*. Default is 0.
:param str detrend: The function applied to each segment before fft-ing,
designed to remove the mean or linear trend (default is 'none')
:param str window: function or a vector of length *NFFT*. default is hanning window
To create other window, use the :class:`~openalea.pylab_text_wralea.py_pylab.PyLabWindow` node.
:param noverlap: The number of points of overlap between blocks.
The default value is 0.
:param int pad_to: The number of points to which the data segment is padded when
performing the FFT (default is None)
:param str sides: Specifies which sides of the PSD to return (default is 'default').
:param bool scale_by_freq: (default is True)
:param dict kwargs: Connect a :class:`~openalea.pylab_plotting_wralea.py_pylab.PyLabLine2D`
to customize the curve.
:param int figure: figure id
:Example:
.. dataflow:: openalea.pylab.test psd
:width: 50%
**The `openalea.pylab.test.psd` dataflow.** The **PyLabPsd** node compute the power spectral
density between the x array (sin(wt)+ noise). A **PyLabLine2D** further tune the plotted curve.
.. plot::
:width: 50%
from openalea.core.alea import *
pm = PackageManager()
run_and_display(('openalea.pylab.test', 'psd'),{},pm=pm )
.. sectionauthor:: Thomas Cokelaer <Thomas.Cokelaer@sophia.inria.fr>
"""
def __init__(self):
inputs = [
{'name':'x'},
{'name':'NFFT', 'interface':IInt, 'value':256},
{'name':'Fs', 'interface':IFloat, 'value':2.},
{'name':'Fc', 'interface':IFloat, 'value':0},
{'name':'detrend', 'interface':IEnumStr(list(tools.detrends.keys())), 'value':'none'},
{'name':'window', 'interface':IEnumStr(list(tools.windows.keys())), 'value':'hanning'},
{'name':'noverlap', 'interface':IInt, 'value':0},
{'name':'pad_to', 'interface':IInt, 'value':None},
{'name':'sides', 'interface':IEnumStr(tools.sides), 'value':'default'},
{'name':'scale_by_freq','interface':IBool, 'value':None},
{'name':'kwargs(line2d)','interface':IDict, 'value':{}},
]
Plotting.__init__(self, inputs)
self.add_output(name='output')
def __call__(self, inputs):
from pylab import psd, Line2D
self.figure()
self.axes()
kwds = {}
line2d = self.get_input('kwargs(line2d)')
if type(line2d)==Line2D:
kwds = line2d.properties()
else:
for key,value in self.get_input('kwargs(line2d)').items():
kwds[key] = value
for this in ['axes', 'bbox', 'children', 'path', 'picker','data','ydata','xdata',
'xydata','transformed_clip_path_and_affine', 'transform' ]:
kwds.pop(this,None)
x = self.get_input('x')
NFFT = self.get_input('NFFT')
Fs = self.get_input('Fs')
Fc = self.get_input('Fc')
import pylab
detrend = getattr(pylab, 'detrend_'+self.get_input('detrend'))
try:
window = tools.windows[self.get_input('window')]
except:
window = self.get_input('window')
noverlap = self.get_input('noverlap')
pad_to = self.get_input('pad_to')
sides = self.get_input('sides')
scale_by_freq = self.get_input('scale_by_freq')
res = psd(x, NFFT=NFFT, Fs=Fs, Fc=Fc, detrend=detrend,
window=window, noverlap=noverlap, pad_to=pad_to,
sides=sides, scale_by_freq=scale_by_freq, **kwds)
self.update_figure()
return self.axe, res
[docs]
class PyLabCsd(Plotting):
"""The cross spectral density. See pylab.csd for details
:param axes: an optional axes where new data will be plotted.
:param array x: input x array
:param array y: input y array
:param NFFT: The number of data points used in each block for
the FFT. The default is 256. Must be even; a power 2 is most efficient.
:param Fs: The sampling frequency. The default is 2.
:param Fc: The center frequency of *x*. Default is 0.
:param str detrend: The function applied to each segment before fft-ing,
designed to remove the mean or linear trend (default is 'none')
:param str window: function or a vector of length *NFFT*. default is hanning window
To create other window, use the :class:`~openalea.pylab_text_wralea.py_pylab.PyLabWindow` node.
:param noverlap: The number of points of overlap between blocks.
The default value is 0.
:param int pad_to: The number of points to which the data segment is padded when
performing the FFT (default is None)
:param str sides: Specifies which sides of the PSD to return (default is 'default').
:param bool scale_by_freq: (default is True)
:param dict kwargs: Connect a :class:`~openalea.pylab_plotting_wralea.py_pylab.PyLabLine2D`
to customize the curve.
:param int figure: figure id
:Example:
.. dataflow:: openalea.pylab.test csd
:width: 50%
**The `openalea.pylab.test.csd` dataflow.** The **PyLabCsd** node compute the cross spectral
density between the x array (sin(wt)+ noise) and y array (sin(wt)). A **PyLabLine2D** further
tune the plotted curve.
.. plot::
:width: 50%
from openalea.core.alea import *
pm = PackageManager()
run_and_display(('openalea.pylab.test', 'csd'),{},pm=pm )
.. sectionauthor:: Thomas Cokelaer <Thomas.Cokelaer@sophia.inria.fr>
"""
def __init__(self):
inputs = [
{'name':'x'},
{'name':'y'},
{'name':'NFFT', 'interface':IInt, 'value':256},
{'name':'Fs', 'interface':IFloat, 'value':2.},
{'name':'Fc', 'interface':IFloat, 'value':0},
{'name':'detrend', 'interface':IEnumStr(list(tools.detrends.keys())), 'value':'none'},
{'name':'window', 'interface':IEnumStr(list(tools.windows.keys())), 'value':'hanning'},
{'name':'noverlap', 'interface':IInt, 'value':0},
{'name':'pad_to', 'interface':IInt, 'value':None},
{'name':'sides', 'interface':IEnumStr(tools.sides), 'value':'default'},
{'name':'scale_by_freq','interface':IBool, 'value':None},
{'name':'kwargs(line2d)','interface':IDict, 'value':{}},
]
Plotting.__init__(self, inputs)
self.add_output(name='output')
def __call__(self, inputs):
from pylab import csd, Line2D
self.figure()
self.axes()
kwds = {}
line2d = self.get_input('kwargs(line2d)')
if type(line2d)==Line2D:
kwds = line2d.properties()
else:
for key,value in self.get_input('kwargs(line2d)').items():
kwds[key] = value
for this in ['axes', 'bbox', 'children', 'path','picker', 'data','ydata','xdata',
'xydata','transformed_clip_path_and_affine', 'transform' ]:
kwds.pop(this,None)
x = self.get_input('x')
y = self.get_input('y')
NFFT = self.get_input('NFFT')
Fs = self.get_input('Fs')
Fc = self.get_input('Fc')
import pylab
detrend = getattr(pylab, 'detrend_'+self.get_input('detrend'))
try:
window = tools.windows[self.get_input('window')]
except:
window = self.get_input('window')
noverlap = self.get_input('noverlap')
pad_to = self.get_input('pad_to')
sides = self.get_input('sides')
scale_by_freq = self.get_input('scale_by_freq')
res = csd(x, y, NFFT=NFFT, Fs=Fs, Fc=Fc, detrend=detrend,
window=window, noverlap=noverlap, pad_to=pad_to,
sides=sides, scale_by_freq=scale_by_freq, **kwds)
self.update_figure()
return self.axe, res
[docs]
class PyLabSpecgram(Plotting):
"""Compute a spectrogram of data in *x*. See pylab.specgram for details.
:param axes: an optional axes where new data will be plotted.
:param x: the signal to analyse (a 1D- array)
:param NFFT: The number of data points used in each block for
the FFT. The default is 256.
:param Fs: The sampling frequency. The default is 2.
:param Fc: The center frequency of *x*. Default is 0.
:param detrend: The function applied to each segment before fft-ing,
designed to remove the mean or linear trend (default is 'none')
:param window: function or a vector of length *NFFT*. default is hanning window
To create other window, use the :class:`~openalea.pylab_text_wralea.py_pylab.PyLabWindow` node.
:param scale_by_freq: (default is True)
:param noverlap: The number of points of overlap between blocks.
The default value is 128.
:param xextent:
:param cmap: a colormap (default jet).
See :class:`~openalea.pylab_decorators_wralea.py_pylab.PyLabColorMap` node.
:param pad_to: The number of points to which the data segment is padded when
performing the FFT. The default is None.
:param sides: Specifies which sides of the PSD to return. Default is 'default'.
:param scale_by_freq: (default is True)
:param dict kwargs: Connect a :class:`~openalea.pylab_plotting_wralea.py_pylab.PyLabLine2D`
to customize the curve.
:param int figure: figure id
:Example:
.. dataflow:: openalea.pylab.test specgram
:width: 50%
**The openalea.pylab.test.specgram dataflow.** Spectogram of a random noise.
.. plot::
:width: 50%
from openalea.core.alea import *
pm = PackageManager()
run_and_display(('openalea.pylab.test', 'specgram'),{},pm=pm )
.. sectionauthor:: Thomas Cokelaer <Thomas.Cokelaer@sophia.inria.fr>
"""
def __init__(self):
inputs = [
{'name':'x'},
{'name':'NFFT', 'interface':IInt, 'value':256},
{'name':'Fs', 'interface':IFloat, 'value':2.},
{'name':'Fc', 'interface':IFloat, 'value':0},
{'name':'detrend', 'interface':IEnumStr(list(tools.detrends.keys())), 'value':'none'},
{'name':'window', 'interface':IEnumStr(list(tools.windows.keys())), 'value':'hanning'},
{'name':'noverlap', 'interface':IInt, 'value':128},
{'name':'xextent', 'interface':IInt, 'value':None},
{'name':'cmap', 'interface':IEnumStr(list(tools.cmaps.keys())), 'value':'jet'},
{'name':'pad_to', 'interface':IInt, 'value':None},
{'name':'sides', 'interface':IEnumStr(tools.sides), 'value':'default'},
{'name':'scale_by_freq','interface':IBool, 'value':True},
{'name':'kwargs(line2d)','interface':IDict, 'value':{}},
]
Plotting.__init__(self, inputs)
self.add_output(name='output')
# xextent=None,
def __call__(self, inputs):
from pylab import specgram, Line2D
self.figure()
self.axes()
kwds = {}
line2d = self.get_input('kwargs(line2d)')
if type(line2d)==Line2D:
kwds = line2d.properties()
else:
for key,value in self.get_input('kwargs(line2d)').items():
kwds[key] = value
for x in ['children', 'path','data','ydata','xdata','xydata','transformed_clip_path_and_affine' ]:
try:
del kwds[x]
except:
pass
x = self.get_input('x')
NFFT = self.get_input('NFFT')
Fs = self.get_input('Fs')
Fc = self.get_input('Fc')
import pylab
detrend = getattr(pylab, 'detrend_'+self.get_input('detrend'))
try:
window = tools.windows[self.get_input('window')]
except:
window = self.get_input('window')
noverlap = self.get_input('noverlap')
pad_to = self.get_input('pad_to')
sides = self.get_input('sides')
scale_by_freq = self.get_input('scale_by_freq')
cmap = self.get_input('cmap')
res = specgram(x, NFFT=NFFT, Fs=Fs, Fc=Fc, detrend=detrend,
window=window, noverlap=noverlap, pad_to=pad_to,
sides=sides, cmap=cmap,**kwds)
self.update_figure()
return self.axe, res
[docs]
class PyLabStem(Plotting, PlotxyInterface):
"""A stem plot plots vertical lines. See pylab.stem for details.
:param axes: an optional axes where new data will be plotted.
:param x: 1D array
:param y: 1D array
:param marker_color: color of the marker
:param line_color: color of the line
:param base_color: color of the base line
:param str marker_style: a valid matplotlib marker (e.g., [ '+' | '*']).
:param line_style:
:param base_style:
:return:
* the axes in which the data are plotted.
* the output of errorbar
:Example:
.. dataflow:: openalea.pylab.test stem
:width: 50%
**The openalea.pylab.test.stem dataflow.**
.. plot::
:width: 50%
from openalea.core.alea import *
pm = PackageManager()
run_and_display(('openalea.pylab.test', 'stem'),{},pm=pm )
.. sectionauthor:: Thomas Cokelaer <Thomas.Cokelaer@sophia.inria.fr>
"""
def __init__(self):
PlotxyInterface.__init__(self)
inputs = [
{'name': 'x'},
{'name': 'y'},
{'name':'marker_color', 'interface':IEnumStr(list(tools.colors.keys())), 'value':'blue'},
{'name':'line_color', 'interface':IEnumStr(list(tools.colors.keys())), 'value':'blue'},
{'name':'base_color', 'interface':IEnumStr(list(tools.colors.keys())), 'value':'red'},
{'name':'marker_style', 'interface':IEnumStr(list(tools.markers.keys())), 'value':'circle'},
{'name':'line_style', 'interface':IEnumStr(list(tools.linestyles.keys())), 'value':'solid'},
{'name':'base_style', 'interface':IEnumStr(list(tools.linestyles.keys())), 'value':'solid'},
]
Plotting.__init__(self, inputs)
self.add_output(name='output')
def __call__(self, inputs):
self.figure()
self.axes()
kwds = {}
kwds['markerfmt'] = tools.colors[self.get_input('marker_color')]+ tools.markers[self.get_input('marker_style')]
kwds['basefmt'] = tools.colors[self.get_input('base_color')]+ tools.linestyles[self.get_input('base_style')]
kwds['linefmt'] = tools.colors[self.get_input('line_color')]+ tools.linestyles[self.get_input('line_style')]
c = self.call('stem', kwds)
self.update_figure()
return self.axe, c
[docs]
class PyLabStep(Plotting, PlotxyInterface):
"""Make a step plot. See pylab.step for details.
Additional keyword args to :func:`step` are the same
as those for :func:`~matplotlib.pyplot.plot`.
:param axes: an optional axes where new data will be plotted.
:param array x: 1D array
:param array y: 1D array
:param where: [ 'pre' | 'post' | 'mid' ]
* If 'pre', the interval from x[i] to x[i+1] has level y[i+1]
* If 'post', that interval has level y[i]
* If 'mid', the jumps in *y* occur half-way between the *x*-values.
:param str marker: a valid matplotlib marker (e.g., [ '+' | '*']).
:param markersize: (default is 10)
:param str color: a color selected from the list or connected to a :class:`~openalea.color.color`
node to select any color from the wheel color.
:param int figure: figure id
:return: the axes in which the data are plotted.
:Example:
.. dataflow:: openalea.pylab.test step
:width: 50%
**The `openalea.pylab.test.step` dataflow.**
.. plot::
:width: 50%
from openalea.core.alea import *
pm = PackageManager()
run_and_display(('openalea.pylab.test', 'step'),{},pm=pm )
.. sectionauthor:: Thomas Cokelaer <Thomas.Cokelaer@sophia.inria.fr>
"""
def __init__(self):
PlotxyInterface.__init__(self)
inputs = [
{'name':'x', 'interface':None, 'value':None},
{'name':'y', 'interface':None, 'value':None},
{'name':'where', 'interface':IEnumStr(['post','pre','mid']), 'value':'pre'},
{'name':'marker', 'interface':IEnumStr(list(tools.markers.keys())), 'value':'circle'},
{'name':'markersize', 'interface':IFloat, 'value':10},
{'name':'color', 'interface':IEnumStr(list(tools.colors.keys())), 'value':'blue'},
{'name':'kwargs', 'interface':IDict, 'value':{}}
]
Plotting.__init__(self, inputs)
self.add_output(name='output')
def __call__(self, inputs):
from pylab import cla, gcf
self.figure()
self.axes()
kwds = {}
kwds['markersize']=self.get_input("markersize")
kwds['marker']=tools.markers[self.get_input("marker")]
kwds['color']=tools.colors[self.get_input("color")]
kwds['where'] = self.get_input('where')
#todo add kwargs
c = self.call('step', kwds)
#gcf().canvas.draw()
from pylab import gca
gca().get_figure().canvas.draw()
self.update_figure()
return self.axe, c
[docs]
class PyLabQuiver(Plotting):
"""Plot a 2-D field of arrows. See pylab.quiver for details.
:param axes: an optional axes where new data will be plotted.
:param array X: *x* coordinates of the arrow locations (2D)
:param array Y: *y* coordinates of the arrow locations (2D)
:param array U: *x* components of the arrow vectors
:param array V: *y* components of the arrow vectors
:param array C: an optional array used to map colors to the arrows
:param str units: arrow units are in multiples of this unit
* 'width' or 'height': the width or height of the axes
* 'dots' or 'inches': pixels or inches, based on the figure dpi
* 'x', 'y', or 'xy': *X*, *Y*, or sqrt(X^2+Y^2) data units
:param angles:
* 'uv': the arrow aspect ratio is 1, so that if *U*==*V* the angle
of the arrow on the plot is 45 degrees CCW from the *x*-axis
* 'xy': the arrow points from (x,y) to (x+u, y+v).
* array: arbitrary angles may be specified as an array
of values in degrees, CCW from the *x*-axis.
:param float scale: data units per arrow length unit, e.g. m/s per plot width; a smaller
scale parameter makes the arrow longer. If *None*, a simple
autoscaling algorithm is used.
:param float width: shaft width in arrow units
:param float headwidth: head width as multiple of shaft width, default is 3
:param float headlength: head length as multiple of shaft width, default is 5
:param float headaxislength: head length at shaft intersection, default is 4.5
:param float minshaft: length below which arrow scales, in units of head length. Do not
set this to less than 1. Default is 1
:param float minlength: minimum length as a multiple of shaft width; if an arrow length
is less than this, plot a dot (hexagon) of this diameter instead. Default is 1.
:param str pivot: [ 'tail' | 'middle' | 'tip' ] The part of the arrow that is at the grid point.
:param str color: :class:`~matplotlib.collections.PolyCollection` facecolor kwarg. If *C* has been set, *color* has no effect.
:Example:
.. dataflow:: openalea.pylab.test quiver
:width: 50%
**The openalea.pylab.test.quiver dataflow.**
.. plot::
:width: 50%
from openalea.core.alea import *
pm = PackageManager()
run_and_display(('openalea.pylab.test', 'quiver'),{},pm=pm )
.. sectionauthor:: Thomas Cokelaer <Thomas.Cokelaer@sophia.inria.fr>
"""
def __init__(self):
inputs = [
{'name':'X', 'interface':None, 'value':None},
{'name':'Y', 'interface':None, 'value':None},
{'name':'U', 'interface':None, 'value':None},
{'name':'V', 'interface':None, 'value':None},
{'name':'C', 'interface':None, 'value':None},
{'name':'units', 'interface':IEnumStr(tools.units), 'value':'width'},
{'name':'angles', 'interface':IEnumStr(tools.angles), 'value':'uv'},
{'name':'scale', 'interface':IFloat, 'value':None},
{'name':'width', 'interface':IFloat(0.005, 1, 0.005), 'value':None},
{'name':'headwidth', 'interface':IFloat, 'value':3},
{'name':'headlength', 'interface':IFloat, 'value':5},
{'name':'headaxislength','interface':IFloat, 'value':4.5},
{'name':'minshaft', 'interface':IFloat, 'value':1},
{'name':'minlength', 'interface':IFloat, 'value':1},
{'name':'pivot', 'interface':IEnumStr(tools.pivots), 'value':'tail'},
{'name':'color', 'interface':IEnumStr(list(tools.colors.keys())), 'value':'None'},
{'name':'polycollection', 'interface':IDict, 'value':{}},
]
Plotting.__init__(self, inputs)
self.add_output(name='output')
def __call__(self, inputs):
from pylab import quiver, cla
self.figure()
self.axes()
cla()
X = self.get_input('X')
Y = self.get_input('Y')
U = self.get_input('U')
V = self.get_input('V')
C = self.get_input('C')
kwds = {}
for key in ['units', 'angles', 'scale', 'width', 'headwidth', 'headlength', 'headaxislength', 'minshaft', 'minlength']:
kwds[key]=self.get_input(key)
if self.get_input('color')!='None':
kwds['color']=tools.colors[self.get_input('color')]
for key, value in self.get_input('polycollection').items():
kwds[key]=value
if X is None and Y is None and C is None and U is not None and V is not None:
c = quiver(U, V, **kwds)
elif X is None and Y is None and C is not None and U is not None and V is not None:
c = quiver(U, V, C, **kwds)
elif X is not None and Y is not None and C is None and U is not None and V is not None:
c = quiver(X, Y, U, V, **kwds)
elif X is not None and Y is not None and C is not None and U is not None and V is not None:
c = quiver(X, Y, U, V, C, **kwds)
else:
raise SyntaxError('Wrong usage. See documentation. ')
self.update_figure()
return self.axe, c
[docs]
class PyLabFill(Plotting, PlotxyInterface):
"""Plot filled polygons. See pylab.fill for details.
:param axes: an optional axes where new data will be plotted.
:param array x: 1D array
:param array y: 1D array
:param float linewidth: width of a line in points (default is 1)
:param str facecolor: a color selected from the list or connected to a :class:`~openalea.color.color`
node to select any color from the wheel color.
:param dict kwargs: control the Polygon properties by connecting a :class:`~openalea.pylab.pylab_patches_wralea.py_pylab.PyLabPatchDictionary`.
:return: the axes in which the data are plotted.
:return: list of :class:`~matplotlib.patches.Patch` instances that were added.
:Example:
.. dataflow:: openalea.pylab.test fill
:width: 50%
**The `openalea.pylab.test.fill` dataflow.**
.. plot::
:width: 50%
from openalea.core.alea import *
pm = PackageManager()
run_and_display(('openalea.pylab.test', 'fill'),{},pm=pm )
.. sectionauthor:: Thomas Cokelaer <Thomas.Cokelaer@sophia.inria.fr>
"""
def __init__(self):
PlotxyInterface.__init__(self)
inputs = [
{'name':'x'},
{'name':'y'},
{'name':'linewidth', 'interface':IFloat, 'value':1},
{'name':'facecolor', 'interface':IEnumStr(list(tools.colors.keys())), 'value':'blue'},
{'name':'kwargs (Patch)','interface':IDict, 'value':{}},
]
Plotting.__init__(self, inputs)
self.add_output(name='output')
#todo : as many patch as x/y
def __call__(self, inputs):
self.figure()
self.axes()
kwds = self.get_input('kwargs (Patch)')
kwds['facecolor'] = tools.colors[self.get_input('facecolor')]
kwds['linewidth'] = self.get_input('linewidth')
c = self.call('fill', kwds)
self.update_figure()
return self.axe, c
[docs]
class PyLabFillBetween(Plotting, PlotxyInterface):
"""Create a filled regions between 2 functions. See pylab.fillbetween for details.
:param axes: an optional axes where new data will be plotted.
:param array x: 1D array of size N
:param array y1: 1D array of size N
:param array y2: 1D array of size N
:param str where: if None, default to fill between everywhere. If not None, fill region
where ``where==True``. For instance where can be 'y1>y2', 'y1>0'.
:param bool interpolate: if True, interpolate between the two lines to find precise point of intersection.
:param patch: connect a :class:`~openalea.pylab_patches.wralea.py_pylab.Patch`.
:return: the axes in which the data are plotted.
:Example:
.. dataflow:: openalea.pylab.test fill_between
:width: 50%
**The `openalea.pylab.test.fill_between` dataflow.**
.. plot::
:width: 50%
from openalea.core.alea import *
pm = PackageManager()
run_and_display(('openalea.pylab.test', 'fill_between'),{},pm=pm )
.. note:: a more complex example can be found in the openalea.pylab.demo.fill_between composite node.
.. plot::
:width: 50%
from openalea.core.alea import *
pm = PackageManager()
run_and_display(('openalea.pylab.demo', 'fill_between'),{},pm=pm )
.. sectionauthor:: Thomas Cokelaer <Thomas.Cokelaer@sophia.inria.fr>
"""
def __init__(self):
PlotxyInterface.__init__(self)
inputs = [
{'name':'x'},
{'name':'y1'},
{'name':'y2', 'value':0},
{'name':'where', 'interface':IStr, 'value':'None'},
{'name':'interpolate', 'interface':IBool, 'value':False},
{'name':'kwargs (Patch)','interface':IDict, 'value':{}},
]
Plotting.__init__(self, inputs)
self.add_output(name='output')
def __call__(self, inputs):
from pylab import fill_between
self.figure()
self.axes()
kwds = self.get_input('kwargs (Patch)')
kwds.pop('fill', None)
kwds.pop('axes', None)
kwds.pop('figure', None)
x = self.get_input('x')
y1 = self.get_input('y1')
y2 = self.get_input('y2')
where = eval(str(self.get_input('where')))
#hack matplotlib < 1.0.0 interpolate does not exist
interpolate = self.get_input('interpolate')
c = self.axe.fill_between(x, y1, y2, where=where, **kwds)
self.update_figure()
return self.axe, c
[docs]
class PyLabErrorBar(Plotting, PlotxyInterface):
"""Plot *x* versus *y* with error deltas in *yerr* and *xerr*. See pylab.errorbar for details.
Vertical errorbars are plotted if *yerr* is not *None*.
Horizontal errorbars are plotted if *xerr* is not *None*.
:param axes: an optional axes where new data will be plotted.
:param array x: 1D x array
:param array y: 1D y array
:param array xerr: 1D x error array
:param array yerr: 1D y error array (optional)
:param str fmt: The plot format symbol. If *fmt* is *None*, only the errorbars are plotted.
:param str ecolor: a color for the error bars selected from the list or connected to
a :class:`~openalea.color.color` node.
:param float elinewidth: the linewidth of the errorbars in points (default is 1)
:param int capsize: the size of the error bar caps in points (default 3)
:param bool barsabove: if *True*, will plot the errorbars above the plot symbols. Default is below.
:param bool lolims: (default is False)
:param bool uplims: (default is False)
:param bool xuplims: (default is False)
:param bool xlolims: (default is False)
:param dict kwargs: Connect a :class:`~openalea.pylab_plotting_wralea.py_pylab.PyLabLine2D`
to customize the curve.
:return: the axes in which the data are plotted.
:Example:
.. dataflow:: openalea.pylab.test errorbar
:width: 50%
**The openalea.pylab.test.errorbar dataflow.**. In this dataflow, rather complex, we define
a function :math:`y=f(t)=exp(-t)` from scratch plus errorbars in x and y before calling
the **PyLabErrorBar**.
.. plot::
:width: 50%
from openalea.core.alea import *
pm = PackageManager()
run_and_display(('openalea.pylab.test', 'errorbar'),{},pm=pm )
.. sectionauthor:: Thomas Cokelaer <Thomas.Cokelaer@sophia.inria.fr>
"""
def __init__(self):
PlotxyInterface.__init__(self)
inputs = [
{'name':'x'},
{'name':'y'},
{'name':'xerr', 'value':None},
{'name':'yerr', 'value':None},
{'name':'fmt', 'interface':IEnumStr(list(tools.linestyles.keys())), 'value':'solid'},
{'name':'ecolor', 'interface':IEnumStr(list(tools.colors.keys())), 'value':'blue'},
{'name':'elinewidth', 'interface':IFloat, 'value':None},
{'name':'capsize', 'interface':IInt, 'value':3},
{'name':'barsabove', 'interface':IBool, 'value':False},
{'name':'lolims', 'interface':IBool, 'value':False},
{'name':'uplims', 'interface':IBool, 'value':False},
{'name':'xuplims', 'interface':IBool, 'value':False},
{'name':'xlolims', 'interface':IBool, 'value':False},
{'name':'hold', 'interface':IBool, 'value':None},
{'name':'kwargs(line2d)','interface':IDict, 'value':{}},
]
Plotting.__init__(self, inputs)
#todo : as many patch as x/y
self.add_output(name="output")
def __call__(self, inputs):
from pylab import errorbar, Line2D
self.figure()
self.axes()
if type(self.get_input('kwargs(line2d)')) == Line2D:
kwds = tools.line2d2kwds(self.get_input('kwargs(line2d)'))
for this in ['axes', 'bbox', 'children', 'path', 'data', 'xdata', 'ydata',
'xydata','transform', 'transformed_clip_path_and_affine',]:
kwds.pop(this,None)
elif self.get_input('kwargs(line2d)') is None:
kwds = {}
else:
kwds = self.get_input('kwargs(line2d)')
x = self.get_input('x')
y = self.get_input('y')
xerr = self.get_input('xerr')
yerr = self.get_input('yerr')
fmt = tools.linestyles[self.get_input('fmt')]
ecolor = tools.colors[self.get_input('ecolor')]
elinewidth = self.get_input('elinewidth')
capsize = self.get_input('capsize')
barsabove = self.get_input('barsabove')
lolims = self.get_input('lolims')
uplims = self.get_input('uplims')
xlolims = self.get_input('xlolims')
xuplims = self.get_input('xuplims')
c = errorbar(x, y, xerr=xerr, yerr=yerr,
fmt=fmt, ecolor=ecolor,elinewidth=elinewidth,
capsize=capsize, uplims=uplims, lolims=lolims,
xuplims = xuplims, xlolims=xlolims, **kwds)
self.update_figure()
return self.get_input('axes'), c
[docs]
class PyLabImshow(Plotting):
"""Display the image in *X* to current axes. See pylab.imshow for details.
:param axes: an optional axes where new data will be plotted.
:param X: a 2D array
:param cmap: a colormap (default jet).
See :class:`~openalea.pylab_decorators_wralea.py_pylab.PyLabColorMap` node.
:param str interpolation: select interpolation method. If *None* default to rc ``image.interpolation``.
See also the *filternorm* and *filterrad* parameters
:param str aspect:
* If 'auto', changes the image aspect ratio to match that of the axes
* If 'equal', and *extent* is *None*, changes the axes aspect ratio to match that of the image.
* If *extent* is not *None*, the axes aspect ratio is changed to match that of the extent.
* If *None*, default to rc ``image.aspect`` value.
:param float alpha: The alpha blending value. (default is 1.0)
:param float vmin: used in conjunction with *norm* to normalize luminance data.
If either *min* or *max* are *None*, the min and max of the color array *C* is used.
:param float vmax: used in conjunction with *norm* to normalize luminance data.
If either *vmin* or *vmax* are *None*, the min and max of the color array *C* is used.
:param origin: [ None | 'upper' | 'lower' | 'image' ] If *None*, the first value of *Z* will correspond to the
lower left corner, location (0,0). If 'image', the rc value for ``image.origin`` will be used.
This keyword is not active if *X* and *Y* are specified in the call to contour.
:param extent: [ None | scalars (left, right, bottom, top) ] Data limits for the axes.
The default assigns zero-based row, column indices to the *x*, *y* centers of the pixels.
:param shape: [ None | scalars (columns, rows) ] For raw buffer images
:param filternorm: see pylab.imshow for details
:param filterrad: filter radius for filters that have a radius parameter, i.e. when
interpolation is one of: 'sinc', 'lanczos' or 'blackman'
:param arrangment: non-pylab option. See below
:param kwargs: extra arguments if required
:additional argument:
* arrangment a tuple/list of 2 integers: If N images are connected to
the input, the default behaviour is to use pylab.subplot to create a
n x m grid such that n is close to m.
You can overwrite this arbitrary layout by setting yourself the n and m
values using the arrangment but then n x m must be equal to N.
.. note:: if you set vmin or vmax, you cannot get back its original value (None)
To reset them, either you need to reload the whole node, or set them to equal values
like 0 and 0
:returns:
* The first connector is the current axe.
* The second connector is the output of pylab.imshow
:Example:
.. dataflow:: openalea.pylab.test imshow
:width: 50%
**The `openalea.pylab.test.imshow` dataflow.** The input data (test_image.npy)
is read 4 times by the *load* node (openalea.numpy). Thus 4 images data sets
are connected to the `PyLabImshow` node, which arranges the 4 images automatically.
.. plot::
:width: 50%
from openalea.core.alea import *
pm = PackageManager()
run_and_display(('openalea.pylab.test', 'imshow'),{},pm=pm )
.. sectionauthor:: Thomas Cokelaer <Thomas.Cokelaer@sophia.inria.fr>
"""
#@add_docstring(pylab.imshow)
def __init__(self):
inputs = [
{'name':'X', 'interface':None},
{'name':"cmap", 'interface':IEnumStr(list(tools.cmaps.keys())), 'value':'jet'},
{'name':"interpolation", 'interface':IEnumStr(list(tools.interpolations.keys())), 'value':'None'},
{'name':"aspect", 'interface':IEnumStr(list(tools.aspects.keys())), 'value':'None'},
{'name':"alpha", 'interface':IFloat(0., 1., 0.01), 'value':1},
{'name':"vmin", 'interface':IFloat, 'value':None},
{'name':"vmax", 'interface':IFloat, 'value':None},
{'name':"origin", 'interface':None, 'value':None},
{'name':"extent", 'interface':None, 'value':None},
{'name':"shape", 'interface':None, 'value':None},
{'name':"filternorm", 'interface':None, 'value':None},
{'name':"filterrad", 'interface':None, 'value':None},
{'name':'arrangment','interface':ITuple, 'value':(1,1)},
{'name':'kwargs','interface':IDict, 'value':{}},
]
#norm is not implemented: use vmin/vmax instead
Plotting.__init__(self, inputs)
self.add_output(name='output')
def __call__(self, inputs):
from pylab import imshow, subplot, show
self.figure()
#self.axes()
axes = []
kwds = self.get_input('kwargs')
X = self.get_input('X')
if type(X)!=list:
X = [X]
cmap = self.get_input('cmap')
alpha = self.get_input('alpha')
vmin = self.get_input('vmin')
vmax = self.get_input('vmax')
if vmin==vmax:
vmin = None
vmax = None
interpolation = tools.interpolations[self.get_input('interpolation')]
aspect = tools.aspects[self.get_input('aspect')]
#create the proper grid
try:
row = self.get_input('arrangment')[0]
column = self.get_input('arrangment')[1]
if row*column != len(X):
assert False
except:
from pylab import ceil, floor, sqrt
row, column = int(ceil(sqrt(len(X)))), int(floor(sqrt(len(X))))
if row*column < len(X):
row, column = int(ceil(sqrt(len(X)))), int(ceil(sqrt(len(X))))
count = 0
for r in range(1, row+1):
for c in range(1, column+1):
count+=1
if count > len(X):
break
axe = subplot(row,column,count)
axes.append(axe)
im = imshow(X[count-1], cmap=cmap, interpolation=interpolation,
aspect=aspect, vmin=vmin, vmax=vmax,**kwds)
self.update_figure()
return axes, im
"""
*extent*: [ None | scalars (left, right, bottom, top) ]
Data limits for the axes. The default assigns zero-based row,
column indices to the *x*, *y* centers of the pixels.
*shape*: [ None | scalars (columns, rows) ]
For raw buffer images
*filternorm*:
A parameter for the antigrain image resize filter. From the
antigrain documentation, if *filternorm* = 1, the filter normalizes
integer values and corrects the rounding errors. It doesn't do
anything with the source floating point values, it corrects only
integers according to the rule of 1.0 which means that any sum of
pixel weights must be equal to 1.0. So, the filter function must
produce a graph of the proper shape.
*filterrad*:
The filter radius for filters that have a radius
parameter, i.e. when interpolation is one of: 'sinc',
'lanczos' or 'blackman'
"""
[docs]
class PyLabColorBar(Node):
"""See pylab.colorbar for details
:param ax: an optional axes where colorbar will be added
:param cax: an optional axes where colorbar will be added
:param str orientation: vertical or horizontal
:param float fraction: fraction of original axes to use for colorbar (default is 0.15)
:param float pad: fraction of original axes between colorbar and new image axes (default is 0.15)
:param float shrink: fraction by which to shrink the colorbar (default 1)
:param float aspect: ratio of long to short dimensions (default is 20)
:param str extend: [ 'neither' | 'both' | 'min' | 'max' ] (default 'neither') If not 'neither',
make pointed end(s) for out-of-range values.
:param str spacing: [ 'uniform' | 'proportional' ] Uniform spacing gives each discrete color the same
space; proportional makes the space proportional to the data interval.
:param str ticks: [ None | list of ticks | Locator object ] If None, ticks are determined
automatically from the input.
:param str format: format string e.g. '%.3f', that is used.
:param bool drawedges: if True, draw lines at color boundaries
:param cmap: a colormap (default jet).
See :class:`~openalea.pylab_decorators_wralea.py_pylab.PyLabColorMap` node.
:param int figure: figure id
:Example:
.. dataflow:: openalea.pylab.test colorbar
:width: 50%
**The `openalea.pylab.test.colorbar` dataflow.** This test shows how colorbar orientation
can be easily switched from horizontal to vertical orientation.
.. plot::
:width: 50%
from openalea.core.alea import *
pm = PackageManager()
run_and_display(('openalea.pylab.test', 'colorbar'),{},pm=pm )
.. sectionauthor:: Thomas Cokelaer <Thomas.Cokelaer@sophia.inria.fr>
"""
def __init__(self):
Node.__init__(self)
self.add_input(name='ax')
self.add_input(name='cax')
self.add_input(name='orientation', interface=IEnumStr(list(tools.orientations.keys())), value='vertical')
self.add_input(name='fraction', interface=IFloat(0.,1,0.01), value=0.15)
self.add_input(name='pad', interface=IFloat(0.,1,0.01), value=0.05)
self.add_input(name='shrink', interface=IFloat(0.,1,0.01), value=1)
self.add_input(name='aspect', interface=IFloat(1,100,1), value=20)
self.add_input(name='extend', interface=IEnumStr(list(tools.extends.keys())), value='neither')
self.add_input(name='spacing', interface=IEnumStr(list(tools.spacings.keys())), value='uniform')
self.add_input(name='ticks', interface=None, value=None)
self.add_input(name='format', interface=IStr, value=None)
self.add_input(name='drawedges', interface=IBool, value=False)
self.add_input(name='cmap', interface=IEnumStr(list(tools.cmaps.keys())), value='jet')
self.add_input(name='kwargs', interface=IDict, value={})
self.add_output(name='axes')
self.add_output(name='output')
self.colorbar = []
def __call__(self, inputs):
from pylab import colorbar, gcf
# cleanup the colorbars
if len(self.colorbar) != 0:
for this_colorbar in self.colorbar:
f = this_colorbar.ax.get_figure()
f.delaxes(this_colorbar.ax)
self.colorbar = []
ax = self.get_input('ax')
if type(ax) != list:
ax = [ax]
cax = self.get_input('cax')
kwds = {}
kwds['fraction'] = self.get_input('fraction')
kwds['orientation'] = self.get_input('orientation') #no need for dictionary conversion since key==value
kwds['pad'] = self.get_input('pad')
kwds['shrink'] = self.get_input('shrink')
kwds['aspect'] = self.get_input('aspect')
kwds['drawedges'] = self.get_input('drawedges')
#if len(self.get_input('ticks'))>0:
# kwds['ticks'] = self.get_input('ticks')
kwds['format'] = self.get_input('format')
cmap = self.get_input('cmap')
for this_ax in ax:
c = colorbar(ax=this_ax, cax=cax, cmap=cmap,**kwds)
self.colorbar.append(c)
#comment this if you want sphinx to give a proper rendering...
#gcf().canvas.draw()
from pylab import gca
gca().get_figure().canvas.draw()
return ax, self.colorbar