2024-02-19 18:30:39 +08:00

4555 lines
178 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# coding=utf-8
# -----------------------------------------------------
# Author: Yaqiang Wang
# Date: 2017-3-25
# Purpose: MeteoInfoLab axes module
# Note: Jython
# -----------------------------------------------------
from org.meteoinfo.chart import Location, ChartWindArrow, ChartText, LegendPosition, \
ChartLegend, ChartColorBar, AspectType
from org.meteoinfo.chart.plot import Plot2D, PolarPlot, PlotOrientation
from org.meteoinfo.chart.graphic import GraphicFactory
from org.meteoinfo.common import XAlign, YAlign
from org.meteoinfo.chart.axis import Axis, LonLatAxis, TimeAxis, LogAxis
#from org.meteoinfo.geo.legend import LegendManage
from org.meteoinfo.geometry.legend import BarBreak, PolygonBreak, PolylineBreak, \
PointBreak, LineStyles, PointStyle, LegendScheme, LegendType, LegendManage, ExtendFraction
from org.meteoinfo.geometry.shape import ShapeTypes
from org.meteoinfo.geometry.graphic import Graphic, GraphicCollection
from org.meteoinfo.geometry.colors import ExtendType
from org.meteoinfo.common import MIMath, Extent
from org.meteoinfo.geo.layer import MapLayer
from java.awt import Font, Color, BasicStroke
from java.awt.image import BufferedImage
from java.util import HashMap
import numbers
import datetime
import math
import mipylib.numeric as np
from mipylib.numeric.core import DimArray, NDArray
from mipylib.geolib.milayer import MILayer, MIXYListData
import plotutil
import colors
import mipylib.miutil as miutil
from .graphic import Line2D
__all__ = ['Axes', 'PolarAxes']
class Axes(object):
"""
Axes with Cartesian coordinate.
"""
def __init__(self, *args, **kwargs):
axes = kwargs.pop('axes', None)
self._set_plot(axes)
figure = kwargs.pop('figure', None)
self.figure = figure
if len(args) > 0:
position = args[0]
else:
position = kwargs.pop('position', None)
outerposition = kwargs.pop('outerposition', None)
if position is None:
position = [0.13, 0.11, 0.775, 0.815]
self.active_outerposition(True)
else:
self.active_outerposition(False)
self.set_position(position)
if not outerposition is None:
self.set_outerposition(outerposition)
self.active_outerposition(True)
units = kwargs.pop('units', None)
if not units is None:
self._axes.setUnits(units)
aspect = kwargs.pop('aspect', 'auto')
axis = kwargs.pop('axis', None)
if axis is None:
axis = kwargs.pop('axison', True)
b_axis = self.get_axis(Location.BOTTOM)
l_axis = self.get_axis(Location.LEFT)
t_axis = self.get_axis(Location.TOP)
r_axis = self.get_axis(Location.RIGHT)
if axis:
bottomaxis = kwargs.pop('bottomaxis', True)
leftaxis = kwargs.pop('leftaxis', True)
topaxis = kwargs.pop('topaxis', True)
rightaxis = kwargs.pop('rightaxis', True)
else:
bottomaxis = False
leftaxis = False
topaxis = False
rightaxis = False
xreverse = kwargs.pop('xreverse', False)
yreverse = kwargs.pop('yreverse', False)
xaxistype = kwargs.pop('xaxistype', None)
bgcobj = kwargs.pop('bgcolor', None)
if aspect == 'equal':
self._axes.setAspectType(AspectType.EQUAL)
else:
if isinstance(aspect, (int, float)):
self._axes.setAspect(aspect)
self._axes.setAspectType(AspectType.RATIO)
if not bottomaxis:
b_axis.setVisible(False)
if not leftaxis:
l_axis.setVisible(False)
if not topaxis:
t_axis.setVisible(False)
if not rightaxis:
r_axis.setVisible(False)
if xreverse:
b_axis.setInverse(True)
t_axis.setInverse(True)
if yreverse:
l_axis.setInverse(True)
r_axis.setInverse(True)
if not xaxistype is None:
self.set_xaxis_type(xaxistype)
bgcolor = plotutil.getcolor(bgcobj)
self._axes.setBackground(bgcolor)
tickline = kwargs.pop('tickline', None)
if not tickline is None:
b_axis.setDrawTickLine(tickline)
t_axis.setDrawTickLine(tickline)
l_axis.setDrawTickLine(tickline)
r_axis.setDrawTickLine(tickline)
tickfontname = kwargs.pop('tickfontname', 'Arial')
tickfontsize = kwargs.pop('tickfontsize', 14)
tickbold = kwargs.pop('tickbold', False)
if tickbold:
font = Font(tickfontname, Font.BOLD, tickfontsize)
else:
font = Font(tickfontname, Font.PLAIN, tickfontsize)
self._axes.setAxisLabelFont(font)
clip = kwargs.pop('clip', None)
if not clip is None:
self._axes.setClip(clip)
def _set_plot(self, plot):
"""
Set plot.
:param plot: (*Plot2D*) Plot.
"""
if plot is None:
self._axes = Plot2D()
else:
self._axes = plot
@property
def axestype(self):
return 'cartesian'
@property
def ndim(self):
"""
Dimension number property
"""
return 2
def get_type(self):
"""
Get axes type
:returns: Axes type
"""
return self._axes.getPlotType()
def get_position(self):
"""
Get axes position
:returns: Axes position [left, bottom, width, height] in normalized (0, 1) units
"""
pos = self._axes.getPosition()
return [pos.x, pos.y, pos.width, pos.height]
def set_position(self, pos):
"""
Set axes position
:param pos: (*list*) Axes position specified by *position=* [left, bottom, width,
height] in normalized (0, 1) units
"""
self._axes.setPosition(pos)
def get_outerposition(self):
"""
Get axes outer position
:returns: Axes outer position [left, bottom, width, height] in normalized (0, 1) units
"""
pos = self._axes.getOuterPosition()
return [pos.x, pos.y, pos.width, pos.height]
def set_outerposition(self, pos):
"""
Set axes outer position
:param pos: (*list*) Axes outer position specified by *outerposition=* [left, bottom, width,
height] in normalized (0, 1) units
"""
self._axes.setOuterPosition(pos)
def active_outerposition(self, active):
"""
Set axes outer position active or not.
:param active: (*boolean*) Active or not
"""
self._axes.setOuterPosActive(active)
def get_axis(self, loc):
"""
Get axis by location.
:param loc: (*Location*) Location enum.
:returns: Axis
"""
return self._axes.getAxis(loc)
def set_aspect(self, aspect):
"""
Set axes aspect
:param aspect: (*string or number*) Axes aspect ['equal' | 'auto'].
"""
if aspect == 'equal':
self._axes.setAspectType(AspectType.EQUAL)
else:
if isinstance(aspect, (int, float)):
self._axes.setAspect(aspect)
self._axes.setAspectType(AspectType.RATIO)
else:
self._axes.setAspectType(AspectType.AUTO)
def set_clip(self, clip):
"""
Set axes clip or not
:param clip: (*bool*) Clip or not
"""
self._axes.setClip(clip)
def get_title(self, loc='center'):
"""
Get title
:param loc: (*string*) Which title to get ['center' | 'left' | 'right'],
default to 'center'.
:returns: The title.
"""
if loc == 'left':
return self.aexs.getLeftTitle()
elif loc == 'right':
return self._axes.getRightTitle()
else:
return self._axes.getTitle()
def set_title(self, label, loc='center', fontname=None, fontsize=14, bold=True, color='black', **kwargs):
"""
Set a title of the current axes.
:param label: (*string*) Title string.
:param loc: (*string') Which title to set ['center' | 'left' | 'right'],
default to 'center'.
:param fontname: (*string*) Font name. Default is ``None``, using ``Arial`` .
:param fontsize: (*int*) Font size. Default is ``14`` .
:param bold: (*boolean*) Is bold font or not. Default is ``True`` .
:param color: (*color*) Title string color. Default is ``black`` .
:param linespace: (*int*) Line space of multiple line title.
"""
exfont = False
if fontname is None:
fontname = 'Arial'
else:
exfont = True
if bold:
font = Font(fontname, Font.BOLD, fontsize)
else:
font = Font(fontname, Font.PLAIN, fontsize)
c = plotutil.getcolor(color)
title = ChartText(label, font)
title.setXAlign(loc)
title.setUseExternalFont(exfont)
title.setColor(c)
linespace = kwargs.pop('linespace', None)
if not linespace is None:
title.setLineSpace(linespace)
if loc == 'left':
self._axes.setLeftTitle(title)
elif loc == 'right':
self._axes.setRightTitle(title)
else:
self._axes.setTitle(title)
return title
def set_xlabel(self, label, **kwargs):
"""
Set the x axis label of the current axes.
:param label: (*string*) Label string.
:param fontname: (*string*) Font name. Default is ``Arial`` .
:param fontsize: (*int*) Font size. Default is ``14`` .
:param bold: (*boolean*) Is bold font or not. Default is ``True`` .
:param color: (*color*) Label string color. Default is ``black`` .
"""
if not kwargs.has_key('xalign'):
kwargs['xalign'] = 'center'
if not kwargs.has_key('yalign'):
kwargs['yalign'] = 'top'
ctext = plotutil.text(0, 0, label, **kwargs)
axis = self._axes.getXAxis()
axis.setLabel(ctext)
axis.setDrawLabel(True)
if self.axestype != '3d':
axis_t = self._axes.getAxis(Location.TOP)
text = ctext.clone()
text.setXAlign('center')
text.setYAlign('bottom')
axis_t.setLabel(text)
def set_ylabel(self, label, **kwargs):
"""
Set the y axis label of the current axes.
:param label: (*string*) Label string.
:param fontname: (*string*) Font name. Default is ``Arial`` .
:param fontsize: (*int*) Font size. Default is ``14`` .
:param bold: (*boolean*) Is bold font or not. Default is ``True`` .
:param color: (*color*) Label string color. Default is ``black`` .
"""
if not kwargs.has_key('xalign'):
kwargs['xalign'] = 'center'
if not kwargs.has_key('yalign'):
kwargs['yalign'] = 'bottom'
if not kwargs.has_key('rotation'):
kwargs['rotation'] = 90
ctext = plotutil.text(0, 0, label, **kwargs)
axis = self._axes.getYAxis()
axis.setLabel(ctext)
axis.setDrawLabel(True)
if self.axestype != '3d':
axis_r = self._axes.getAxis(Location.RIGHT)
text = ctext.clone()
text.setXAlign('left')
text.setYAlign('center')
axis_r.setLabel(text)
def get_xticks(self):
"""
Get x axis tick locations.
"""
axis = self._axes.getXAxis()
axis.updateTickLabels()
return axis.getTickLocations()
def set_xticks(self, locs):
"""
Set x axis tick locations.
"""
axis = self._axes.getXAxis()
if isinstance(locs, (NDArray, DimArray)):
locs = locs.aslist()
axis.setTickLocations(locs)
if self.axestype == '3d':
axis_t = None
else:
axis_t = self._axes.getAxis(Location.TOP)
if not axis_t is None:
axis_t.setTickLocations(locs)
def get_yticks(self):
"""
Get y axis tick locations.
"""
axis = self._axes.getYAxis()
axis.updateTickLabels()
return axis.getTickLocations()
def set_yticks(self, locs):
"""
Set y axis tick locations.
"""
axis = self._axes.getYAxis()
if isinstance(locs, NDArray):
locs = locs.aslist()
axis.setTickLocations(locs)
if self.axestype == '3d':
axis_r = None
else:
axis_r = self._axes.getAxis(Location.RIGHT)
if not axis_r is None:
axis_r.setTickLocations(locs)
def get_xticklabels(self):
"""
Get x axis tick labels.
"""
axis = self._axes.getXAxis()
axis.updateTickLabels()
return axis.getTickLabelText()
def set_xticklabels(self, labels, **kwargs):
"""
Set x axis tick labels.
"""
axis = self._axes.getXAxis()
if self.axestype == '3d':
axis_t = None
else:
axis_t = self._axes.getAxis(Location.TOP)
if not labels is None:
if isinstance(labels, (NDArray, DimArray)):
labels = labels.aslist()
if isinstance(labels[0], (int, long, float)):
axis.setTickLabels_Number(labels)
else:
axis.setTickLabelText(labels)
if not axis_t is None:
if isinstance(labels[0], (int, long, float)):
axis_t.setTickLabels_Number(labels)
else:
axis_t.setTickLabelText(labels)
fontname = kwargs.pop('fontname', axis.getTickLabelFont().getName())
fontsize = kwargs.pop('fontsize', axis.getTickLabelFont().getSize())
bold = kwargs.pop('bold', axis.getTickLabelFont().isBold())
if bold:
font = Font(fontname, Font.BOLD, fontsize)
else:
font = Font(fontname, Font.PLAIN, fontsize)
color = kwargs.pop('color', axis.getTickLabelColor())
c = plotutil.getcolor(color)
angle = kwargs.pop('rotation', 0)
if angle == 'vertical':
angle = 90
axis.setTickLabelFont(font)
axis.setTickLabelColor(c)
axis.setTickLabelAngle(angle)
if not axis_t is None:
axis_t.setTickLabelFont(font)
axis_t.setTickLabelColor(c)
axis_t.setTickLabelAngle(angle)
def get_yticklabels(self):
"""
Get y axis tick labels.
"""
axis = self._axes.getYAxis()
axis.updateTickLabels()
return axis.getTickLabelText()
def set_yticklabels(self, labels, **kwargs):
"""
Set y axis tick labels.
"""
axis = self._axes.getYAxis()
if self.axestype == '3d':
axis_r = None
else:
axis_r = self._axes.getAxis(Location.RIGHT)
if not labels is None:
if isinstance(labels, (NDArray, DimArray)):
labels = labels.aslist()
if isinstance(labels[0], (int, long, float)):
axis.setTickLabels_Number(labels)
else:
axis.setTickLabelText(labels)
if not axis_r is None:
if isinstance(labels[0], (int, long, float)):
axis_r.setTickLabels_Number(labels)
else:
axis_r.setTickLabelText(labels)
fontname = kwargs.pop('fontname', axis.getTickLabelFont().getName())
fontsize = kwargs.pop('fontsize', axis.getTickLabelFont().getSize())
bold = kwargs.pop('bold', axis.getTickLabelFont().isBold())
if bold:
font = Font(fontname, Font.BOLD, fontsize)
else:
font = Font(fontname, Font.PLAIN, fontsize)
color = kwargs.pop('color', axis.getTickLabelColor())
c = plotutil.getcolor(color)
angle = kwargs.pop('rotation', 0)
if angle == 'vertical':
angle = 90
axis.setTickLabelFont(font)
axis.setTickLabelColor(c)
axis.setTickLabelAngle(angle)
if not axis_r is None:
axis_r.setTickLabelFont(font)
axis_r.setTickLabelColor(c)
axis_r.setTickLabelAngle(angle)
def set_xaxis_type(self, axistype, timetickformat=None):
"""
Set x axis type.
:param axistype: (*string*) Axis type ['lon' | 'lat' | 'time' | 'log'].
:param timetickformat: (*string*) Time tick label format.
"""
ax = self._axes
b_axis = ax.getAxis(Location.BOTTOM)
t_axis = ax.getAxis(Location.TOP)
if axistype == 'lon':
if not isinstance(b_axis, LonLatAxis):
b_axis = LonLatAxis(b_axis)
b_axis.setLongitude(True)
ax.setAxis(b_axis, Location.BOTTOM)
if not isinstance(t_axis, LonLatAxis):
t_axis = LonLatAxis(t_axis)
t_axis.setLongitude(True)
ax.setAxis(t_axis, Location.TOP)
elif axistype == 'lat':
if not isinstance(b_axis, LonLatAxis):
b_axis = LonLatAxis(b_axis)
b_axis.setLongitude(False)
ax.setAxis(b_axis, Location.BOTTOM)
if not isinstance(t_axis, LonLatAxis):
t_axis = LonLatAxis(t_axis)
t_axis.setLongitude(False)
ax.setAxis(t_axis, Location.TOP)
elif axistype == 'time':
if not isinstance(b_axis, TimeAxis):
b_axis = TimeAxis(b_axis)
ax.setAxis(b_axis, Location.BOTTOM)
if not isinstance(t_axis, TimeAxis):
t_axis = TimeAxis(t_axis)
ax.setAxis(t_axis, Location.TOP)
if not timetickformat is None:
b_axis.setTimeFormat(timetickformat)
t_axis.setTimeFormat(timetickformat)
elif axistype == 'log':
if not isinstance(b_axis, LogAxis):
b_axis = LogAxis(b_axis)
b_axis.setMinorTickNum(10)
ax.setAxis(b_axis, Location.BOTTOM)
if not isinstance(t_axis, LogAxis):
t_axis = LogAxis(t_axis)
t_axis.setMinorTickNum(10)
ax.setAxis(t_axis, Location.TOP)
ax.setAutoExtent()
else:
b_axis = Axis(ax.getAxis(Location.BOTTOM))
ax.setAxis(b_axis, Location.BOTTOM)
t_axis = Axis(ax.getAxis(Location.TOP))
ax.setAxis(t_axis, Location.TOP)
def set_yaxis_type(self, axistype, timetickformat=None):
"""
Set y axis type.
:param axistype: (*string*) Axis type ['lon' | 'lat' | 'time' | 'log'].
:param timetickformat: (*string*) Time tick label format.
"""
ax = self._axes
if axistype == 'lon':
b_axis = LonLatAxis(ax.getAxis(Location.LEFT))
# b_axis.setLabel('Longitude')
b_axis.setLongitude(True)
ax.setAxis(b_axis, Location.LEFT)
t_axis = LonLatAxis(ax.getAxis(Location.RIGHT))
# t_axis.setLabel('Longitude')
t_axis.setLongitude(True)
ax.setAxis(t_axis, Location.RIGHT)
elif axistype == 'lat':
b_axis = LonLatAxis(ax.getAxis(Location.LEFT))
# b_axis.setLabel('Latitude')
b_axis.setLongitude(False)
ax.setAxis(b_axis, Location.LEFT)
t_axis = LonLatAxis(ax.getAxis(Location.RIGHT))
# t_axis.setLabel('Latitude')
t_axis.setLongitude(False)
ax.setAxis(t_axis, Location.RIGHT)
elif axistype == 'time':
b_axis = TimeAxis(ax.getAxis(Location.LEFT))
ax.setAxis(b_axis, Location.LEFT)
t_axis = TimeAxis(ax.getAxis(Location.RIGHT))
ax.setAxis(t_axis, Location.RIGHT)
if not timetickformat is None:
ax.getAxis(Location.LEFT).setTimeFormat(timetickformat)
ax.getAxis(Location.RIGHT).setTimeFormat(timetickformat)
elif axistype == 'log':
l_axis = LogAxis(ax.getAxis(Location.LEFT))
# l_axis.setLabel('Log')
l_axis.setMinorTickNum(10)
ax.setAxis(l_axis, Location.LEFT)
r_axis = LogAxis(ax.getAxis(Location.RIGHT))
# r_axis.setLabel('Log')
r_axis.setMinorTickNum(10)
ax.setAxis(r_axis, Location.RIGHT)
ax.setAutoExtent()
else:
l_axis = Axis(ax.getAxis(Location.LEFT))
ax.setAxis(l_axis, Location.LEFT)
r_axis = Axis(ax.getAxis(Location.RIGHT))
ax.setAxis(r_axis, Location.RIGHT)
def set_axis_on(self):
"""
Set all axis visible.
"""
self.get_axis(Location.BOTTOM).setVisible(True)
self.get_axis(Location.LEFT).setVisible(True)
self.get_axis(Location.TOP).setVisible(True)
self.get_axis(Location.RIGHT).setVisible(True)
def set_axis_off(self):
"""
Set all axis not visible.
"""
self.get_axis(Location.BOTTOM).setVisible(False)
self.get_axis(Location.LEFT).setVisible(False)
self.get_axis(Location.TOP).setVisible(False)
self.get_axis(Location.RIGHT).setVisible(False)
def axis(self, arg=None, **kwargs):
"""
Convenience method to get or set some axis properties.
Call signatures::
xmin, xmax, ymin, ymax = axis()
xmin, xmax, ymin, ymax = axis([xmin, xmax, ymin, ymax])
xmin, xmax, ymin, ymax = axis(option)
xmin, xmax, ymin, ymax = axis(**kwargs)
Parameters
----------
xmin, xmax, ymin, ymax : float, optional
The axis limits to be set. This can also be achieved using ::
ax.set(xlim=(xmin, xmax), ylim=(ymin, ymax))
option : bool or str
If a bool, turns axis lines and labels on or off. If a string,
possible values are:
======== ==========================================================
Value Description
======== ==========================================================
'on' Turn on axis lines and labels. Same as ``True``.
'off' Turn off axis lines and labels. Same as ``False``.
'equal' Set equal scaling (i.e., make circles circular) by
changing axis limits. This is the same as
``ax.set_aspect('equal', adjustable='datalim')``.
Explicit data limits may not be respected in this case.
'scaled' Set equal scaling (i.e., make circles circular) by
changing dimensions of the plot box. This is the same as
``ax.set_aspect('equal', adjustable='box', anchor='C')``.
Additionally, further autoscaling will be disabled.
'tight' Set limits just large enough to show all data, then
disable further autoscaling.
'auto' Automatic scaling (fill plot box with data).
'image' 'scaled' with axis limits equal to data limits.
'square' Square plot; similar to 'scaled', but initially forcing
``xmax-xmin == ymax-ymin``.
======== ==========================================================
Returns
-------
xmin, xmax, ymin, ymax : float
The axis limits.
"""
if isinstance(arg, (str, bool)):
if arg is True:
arg = 'on'
if arg is False:
arg = 'off'
arg = arg.lower()
if arg == 'on':
self.set_axis_on()
elif arg == 'off':
self.set_axis_off()
elif arg in ['auto', 'equal']:
self.set_aspect(arg)
else:
raise ValueError("Unrecognized string {} to axis; "
"try 'on' or 'off'".format(arg))
else:
if arg is not None:
try:
xmin, xmax, ymin, ymax = arg
except (TypeError, ValueError) as err:
raise TypeError('the first argument to axis() must be an '
'iterable of the form '
'[xmin, xmax, ymin, ymax]')
self.set_xlim(xmin, xmax)
self.set_ylim(ymin, ymax)
return self.get_xlim() + self.get_ylim()
def get_xlim(self):
"""
Get the *x* limits of the current axes.
:returns: (*tuple*) x limits.
"""
extent = self._axes.getDrawExtent()
return extent.minX, extent.maxX
def set_xlim(self, xmin, xmax):
"""
Set the *x* limits of the current axes.
:param xmin: (*float*) Minimum limit of the x axis.
:param xmax: (*float*) Maximum limit of the x axis.
"""
if isinstance(xmin, datetime.datetime):
xmin = miutil.date2num(xmin)
if isinstance(xmax, datetime.datetime):
xmax = miutil.date2num(xmax)
extent = self._axes.getDrawExtent()
extent.minX = xmin
extent.maxX = xmax
self._axes.setDrawExtent(extent)
self._axes.setExtent(extent.clone())
self._axes.setFixDrawExtent(True)
def get_ylim(self):
"""
Get the *y* limits of the current axes.
:returns: (*tuple*) y limits.
"""
extent = self._axes.getDrawExtent()
return extent.minY, extent.maxY
def set_ylim(self, ymin, ymax):
"""
Set the *yt* limits of the current axes.
:param ymin: (*float*) Minimum limit of the y axis.
:param ymax: (*float*) Maximum limit of the y axis.
"""
if isinstance(ymin, datetime.datetime):
ymin = miutil.date2num(ymin)
if isinstance(ymax, datetime.datetime):
ymax = miutil.date2num(ymax)
extent = self._axes.getDrawExtent()
extent.minY = ymin
extent.maxY = ymax
self._axes.setDrawExtent(extent)
self._axes.setExtent(extent.clone())
self._axes.setFixDrawExtent(True)
def twinx(self):
"""
Make a second axes that shares the x-axis. The new axes will overlay *ax*. The ticks
for *ax2* will be placed on the right, and the *ax2* instance is returned.
:returns: The second axes
"""
self._axes.getAxis(Location.RIGHT).setVisible(False)
self._axes.setSameShrink(True)
ax2 = Axes()
ax2._axes.setSameShrink(True)
ax2._axes.setPosition(self.get_position())
ax2._axes.setOuterPosActive(self._axes.isOuterPosActive())
ax2._axes.getAxis(Location.BOTTOM).setVisible(False)
ax2._axes.getAxis(Location.LEFT).setVisible(False)
ax2._axes.getAxis(Location.TOP).setVisible(False)
axis = ax2._axes.getAxis(Location.RIGHT)
axis.setDrawTickLine(True)
axis.setDrawTickLabel(True)
axis.setDrawLabel(True)
return ax2
def twiny(self):
"""
Make a second axes that shares the y-axis. The new axes will overlay *ax*. The ticks
for *ax2* will be placed on the top, and the *ax2* instance is returned.
:returns: The second axes
"""
self._axes.getAxis(Location.TOP).setVisible(False)
self._axes.setSameShrink(True)
ax2 = Axes()
ax2._axes.setSameShrink(True)
ax2._axes.setPosition(self.get_position())
ax2._axes.setOuterPosActive(self._axes.isOuterPosActive())
ax2._axes.getAxis(Location.BOTTOM).setVisible(False)
ax2._axes.getAxis(Location.LEFT).setVisible(False)
ax2._axes.getAxis(Location.RIGHT).setVisible(False)
axis = ax2._axes.getAxis(Location.TOP)
axis.setDrawTickLine(True)
axis.setDrawTickLabel(True)
axis.setDrawLabel(True)
return ax2
def xaxis(self, **kwargs):
"""
Set x-axis of the axes.
:param color: (*Color*) Color of the axis. Default is `black`.
:param position: (*tuple*) Axis position specified by a 2 tuple of (position type, amount).
The position types are ['outerward' | 'axes' | 'data'].
:param shift: (*int) Axis shif along x direction. Units are pixel. Default is 0.
:param visible: (*bool*) Set axis visible or not, Default is `None`.
:param linewidth: (*float*) Line width of the axis.
:param linestyle: (*string*) Line style of the axis.
:param tickline: (*boolean*) Draw tick line or not.
:param tickwidth: (*float*) Tick line width.
:param ticklength: (*float*) Tick line length.
:param ticklabel: (*bool*) Draw tick label or not.
:param minortick: (*bool*) Draw minor tick line or not.
:param minorticknum: (*int*) Minor tick line number between two adjacent major tick lines.
:param tickin: (*bool*) Tick lines are plot inside or outside the axes.
:param axistype: (*string*) Axis type ['normal' | 'lon' | 'lat' | 'time' | 'log'].
:param timetickformat: (*string*) Time tick label format, only valid with time axis.
:param tickfontname: (*string*) Tick label font name.
:param tickfontsize: (*int*) Tick label font size.
:param tickbold: (*bool*) Tick label font is bold or not.
:param tickavoidcoll: (*bool*) Whether avoid collision of tick labels. Default is `True`.
:param location: (*string*) Locations of the axis ['both' | 'top' | 'bottom'].
"""
visible = kwargs.pop('visible', None)
position = kwargs.pop('position', None)
if position == 'center':
position = ['axes', 0.5]
elif position == 'zero':
position = ['data', 0]
shift = kwargs.pop('shift', None)
color = kwargs.pop('color', None)
if not color is None:
color = plotutil.getcolor(color)
tickcolor = kwargs.pop('tickcolor', None)
if not tickcolor is None:
tickcolor = plotutil.getcolor(tickcolor)
linewidth = kwargs.pop('linewidth', None)
linestyle = kwargs.pop('linestyle', None)
tickline = kwargs.pop('tickline', None)
tickline = kwargs.pop('tickvisible', tickline)
tickwidth = kwargs.pop('tickwidth', None)
ticklength = kwargs.pop('ticklength', None)
ticklabel = kwargs.pop('ticklabel', None)
minortick = kwargs.pop('minortick', None)
minorticknum = kwargs.pop('minorticknum', None)
tickin = kwargs.pop('tickin', None)
axistype = kwargs.pop('axistype', None)
timetickformat = kwargs.pop('timetickformat', None)
if not axistype is None:
self.set_xaxis_type(axistype, timetickformat)
self._axes.setAutoExtent()
location = kwargs.pop('location', 'both')
if location == 'top':
locs = [Location.TOP]
elif location == 'bottom':
locs = [Location.BOTTOM]
else:
locs = [Location.BOTTOM, Location.TOP]
axislist = []
if self.axestype == '3d':
axislist.append(self._axes.getXAxis())
else:
for loc in locs:
axislist.append(self._axes.getAxis(loc))
ticklabelcolor = kwargs.pop('ticklabelcolor', None)
if not ticklabelcolor is None:
ticklabelcolor = plotutil.getcolor(ticklabelcolor)
tick_font = axislist[0].getTickLabelFont()
tickfontname = kwargs.pop('tickfontname', tick_font.getFontName())
tickfontsize = kwargs.pop('tickfontsize', tick_font.getSize())
tickbold = kwargs.pop('tickbold', tick_font.isBold())
if tickbold:
font = Font(tickfontname, Font.BOLD, tickfontsize)
else:
font = Font(tickfontname, Font.PLAIN, tickfontsize)
tickavoidcoll = kwargs.pop('tickavoidcoll', None)
for axis in axislist:
if not visible is None:
axis.setVisible(visible)
if not position is None:
axis.setPositionType(position[0])
axis.setPosition(position[1])
else:
if not shift is None:
axis.setPositionType('OUTERWARD')
axis.setPosition(shift)
if not color is None:
axis.setColor_All(color)
if not tickcolor is None:
axis.setTickColor(tickcolor)
if not linewidth is None:
axis.setLineWidth(linewidth)
if not linestyle is None:
axis.setLineStyle(linestyle)
if not tickline is None:
axis.setDrawTickLine(tickline)
if not tickwidth is None:
axis.setTickWidth(tickwidth)
if not ticklength is None:
axis.setTickLength(ticklength)
if not ticklabel is None:
axis.setDrawTickLabel(ticklabel)
if not minortick is None:
axis.setMinorTickVisible(minortick)
if not minorticknum is None:
axis.setMinorTickNum(minorticknum)
if not tickin is None:
axis.setInsideTick(tickin)
if not ticklabelcolor is None:
axis.setTickLabelColor(ticklabelcolor)
if not tickavoidcoll is None:
axis.setTickLabelAvoidCollision(tickavoidcoll)
axis.setTickLabelFont(font)
def yaxis(self, **kwargs):
"""
Set y-axis of the axes.
:param color: (*Color*) Color of the y axis. Default is 'black'.
:param position: (*tuple*) Axis position specified by a 2 tuple of (position type, amount).
The position types are ['outerward' | 'axes' | 'data'].
:param shift: (*int) Y axis shift along x direction. Units are pixel. Default is 0.
:param visible: (*bool*) Set axis visible or not, Default is `None`.
:param linewidth: (*float*) Line width of the axis.
:param linestyle: (*string*) Line style of the axis.
:param tickline: (*bool*) Draw tick line or not.
:param tickwidth: (*float*) Tick line width.
:param ticklength: (*float*) Tick line length.
:param ticklabel: (*bool*) Draw tick label or not.
:param minortick: (*bool*) Draw minor tick line or not.
:param minorticknum: (*int*) Minor tick line number between two adjacent major tick lines.
:param tickin: (*bool*) Tick lines are ploted inside or outside the axes.
:param axistype: (*string*) Axis type ['normal' | 'lon' | 'lat' | 'time' | 'log'].
:param timetickformat: (*string*) Time tick label format, only valid with time axis.
:param tickfontname: (*string*) Tick label font name.
:param tickfontsize: (*int*) Tick label font size.
:param tickbold: (*bool*) Tick label font is bold or not.
:param tickavoidcoll: (*bool*) Whether avoid collision of tick labels. Default is `True`.
:param location: (*string*) Locations of the axis ['both' | 'left' | 'right'].
"""
visible = kwargs.pop('visible', None)
position = kwargs.pop('position', None)
if position == 'center':
position = ['axes', 0.5]
elif position == 'zero':
position = ['data', 0]
shift = kwargs.pop('shift', None)
color = kwargs.pop('color', None)
if not color is None:
color = plotutil.getcolor(color)
tickcolor = kwargs.pop('tickcolor', None)
if not tickcolor is None:
tickcolor = plotutil.getcolor(tickcolor)
linewidth = kwargs.pop('linewidth', None)
linestyle = kwargs.pop('linestyle', None)
tickline = kwargs.pop('tickline', None)
tickline = kwargs.pop('tickvisible', tickline)
tickwidth = kwargs.pop('tickwidth', None)
ticklength = kwargs.pop('ticklength', None)
ticklabel = kwargs.pop('ticklabel', None)
minortick = kwargs.pop('minortick', None)
minorticknum = kwargs.pop('minorticknum', None)
tickin = kwargs.pop('tickin', None)
axistype = kwargs.pop('axistype', None)
timetickformat = kwargs.pop('timetickformat', None)
if not axistype is None:
self.set_yaxis_type(axistype, timetickformat)
self._axes.updateDrawExtent()
location = kwargs.pop('location', 'both')
if location == 'left':
locs = [Location.LEFT]
elif location == 'right':
locs = [Location.RIGHT]
else:
locs = [Location.LEFT, Location.RIGHT]
axislist = []
if self.axestype == '3d':
axislist.append(self._axes.getYAxis())
else:
for loc in locs:
axislist.append(self._axes.getAxis(loc))
ticklabelcolor = kwargs.pop('ticklabelcolor', None)
if not ticklabelcolor is None:
ticklabelcolor = plotutil.getcolor(ticklabelcolor)
tick_font = axislist[0].getTickLabelFont()
tickfontname = kwargs.pop('tickfontname', tick_font.getFontName())
tickfontsize = kwargs.pop('tickfontsize', tick_font.getSize())
tickbold = kwargs.pop('tickbold', tick_font.isBold())
if tickbold:
font = Font(tickfontname, Font.BOLD, tickfontsize)
else:
font = Font(tickfontname, Font.PLAIN, tickfontsize)
tickavoidcoll = kwargs.pop('tickavoidcoll', None)
for axis in axislist:
if not visible is None:
axis.setVisible(visible)
if not position is None:
axis.setPositionType(position[0])
axis.setPosition(position[1])
else:
if not shift is None:
axis.setPositionType('OUTERWARD')
axis.setPosition(shift)
if not color is None:
axis.setColor_All(color)
if not tickcolor is None:
axis.setTickColor(tickcolor)
if not linewidth is None:
axis.setLineWidth(linewidth)
if not linestyle is None:
axis.setLineStyle(linestyle)
if not tickline is None:
axis.setDrawTickLine(tickline)
if not tickwidth is None:
axis.setTickWidth(tickwidth)
if not ticklength is None:
axis.setTickLength(ticklength)
if not ticklabel is None:
axis.setDrawTickLabel(ticklabel)
if not minortick is None:
axis.setMinorTickVisible(minortick)
if not minorticknum is None:
axis.setMinorTickNum(minorticknum)
if not tickin is None:
axis.setInsideTick(tickin)
if not ticklabelcolor is None:
axis.setTickLabelColor(ticklabelcolor)
if not tickavoidcoll is None:
axis.setTickLabelAvoidCollision(tickavoidcoll)
axis.setTickLabelFont(font)
def xreverse(self):
"""
Reverse x axis.
"""
self._axes.getXAxis().setInverse(True)
def yreverse(self):
"""
Reverse y axis.
"""
self._axes.getYAxis().setInverse(True)
def add_patch(self, patch):
"""
Add a patch.
:param patch: (*Graphic or list of graphics*) The patch(s) to be added.
"""
if isinstance(patch, (list, tuple)):
self._axes.addGraphics(patch)
else:
self._axes.addGraphic(patch)
self._axes.setAutoExtent()
def add_graphic(self, graphic, projection=None, zorder=None):
"""
Add a graphic
:param graphic: (*Graphic*) The graphic to be added.
:param projection: (*Projection*) The projection.
:param zorder: (*int*) Z order of the graphic. Default is `None` that the graphic added
to the end.
"""
if not zorder is None:
if zorder > self.num_graphics():
zorder = self.num_graphics()
if projection is None:
if zorder is None:
self._axes.addGraphic(graphic)
else:
self._axes.addGraphic(zorder, graphic)
else:
if zorder is None:
self._axes.addGraphic(graphic, projection)
else:
self._axes.addGraphic(zorder, graphic, projection)
self._axes.setAutoExtent()
def get_graphics(self):
"""
Get graphics
:return: (*list*) The graphics
"""
return self._axes.getGraphics()
def num_graphics(self):
"""
Get the number of graphics
:return: (*int*) The number of graphics
"""
return self._axes.getGraphicNumber()
def remove_graphic(self, graphic):
"""
Remove a graphic
:param graphic: (*int or Graphic*) The graphic
:return:
"""
if isinstance(graphic, int):
if graphic < 0:
graphic = self._axes.getGraphicNumber() + graphic
self._axes.getGraphics().remove(graphic)
def remove(self):
"""
Remove all graphics.
"""
self._axes.getGraphics().clear()
def data2pixel(self, x, y, z=None):
"""
Transform data coordinate to screen coordinate
:param x: (*float*) X coordinate.
:param y: (*float*) Y coordinate.
:param z: (*float*) Z coordinate - only used for 3-D axes.
"""
rect = self._axes.getPositionArea()
r = self._axes.projToScreen(x, y, rect)
sx = r[0] + rect.getX()
sy = r[1] + rect.getY()
sy = self.figure.get_size()[1] - sy
return sx, sy
def grid(self, b=None, **kwargs):
"""
Turn the axes grids on or off.
:param b: If b is *None* and *len(kwargs)==0* , toggle the grid state. If *kwargs*
are supplied, it is assumed that you want a grid and *b* is thus set to *True* .
:param which: *which* can be 'major' (default), 'minor', or 'both' to control
whether major tick grids, minor tick grids, or both are affected.
:param axis: *axis* can be 'both' (default), 'x', or 'y' to control which set of
gridlines are drawn.
:param kwargs: *kwargs* are used to set the grid line properties.
"""
gridline = self._axes.getGridLine()
is_draw = gridline.isDrawXLine()
if b is None:
is_draw = not gridline.isDrawXLine()
elif b == True or b == 'on':
is_draw = True
elif b == False or b == 'on':
is_draw = False
axis = kwargs.pop('axis', 'both')
if axis == 'both':
gridline.setDrawXLine(is_draw)
gridline.setDrawYLine(is_draw)
elif axis == 'x':
gridline.setDrawXLine(is_draw)
elif axis == 'y':
gridline.setDrawYLine(is_draw)
color = kwargs.pop('color', None)
if not color is None:
c = plotutil.getcolor(color)
gridline.setColor(c)
linewidth = kwargs.pop('linewidth', None)
if not linewidth is None:
gridline.setSize(linewidth)
linestyle = kwargs.pop('linestyle', None)
if not linestyle is None:
linestyle = plotutil.getlinestyle(linestyle)
gridline.setStyle(linestyle)
top = kwargs.pop('top', None)
if not top is None:
gridline.setTop(top)
def plot(self, *args, **kwargs):
"""
Plot lines and/or markers to the axes. *args* is a variable length argument, allowing
for multiple *x, y* pairs with an optional format string.
:param x: (*array_like*) Input x data.
:param y: (*array_like*) Input y data.
:param style: (*string*) Line style for plot.
:returns: Legend breaks of the lines.
The following format string characters are accepted to control the line style or marker:
========= ===========
Character Description
========= ===========
'-' solid line style
'--' dashed line style
'-.' dash-dot line style
':' dotted line style
'.' point marker
',' pixel marker
'o' circle marker
'v' triangle_down marker
'^' triangle_up marker
'<' triangle_left marker
'>' triangle_right marker
's' square marker
'p' pentagon marker
'*' star marker
'x' x marker
'D' diamond marker
========= ===========
The following color abbreviations are supported:
========= =====
Character Color
========= =====
'b' blue
'g' green
'r' red
'c' cyan
'm' magenta
'y' yellow
'k' black
========= =====
"""
xdatalist = []
ydatalist = []
styles = []
xaxistype = None
isxylistdata = False
if len(args) == 1:
if isinstance(args[0], MIXYListData):
dataset = args[0].data
snum = args[0].size()
isxylistdata = True
else:
ydata = np.array(args[0])
if isinstance(ydata, DimArray):
xdata = ydata.dimvalue(0)
if ydata.ndim == 2:
xdata = ydata.dimvalue(1)
xx = np.zeros(ydata.shape)
xx[:, :] = xdata
xdata = xx
else:
xdata = np.arange(ydata.shape[-1])
if ydata.ndim == 2:
xx = np.zeros(ydata.shape)
xx[:, :] = xdata
xdata = xx
xdatalist.append(xdata)
ydatalist.append(ydata)
elif len(args) == 2:
if isinstance(args[1], basestring):
ydata = np.array(args[0])
if isinstance(ydata, DimArray):
xdata = ydata.dimvalue(0)
if ydata.ndim == 2:
xdata = ydata.dimvalue(1)
xx = np.zeros(ydata.shape)
xx[:, :] = xdata
xdata = xx
else:
xdata = np.arange(ydata.shape[-1])
if ydata.ndim == 2:
xx = np.zeros(ydata.shape)
xx[:, :] = xdata
xdata = xx
styles.append(args[1])
else:
xdata = args[0]
ydata = args[1]
xdatalist.append(xdata)
ydatalist.append(ydata)
else:
c = 'x'
for arg in args:
if c == 'x':
xdatalist.append(arg)
c = 'y'
elif c == 'y':
ydatalist.append(arg)
c = 's'
elif c == 's':
if isinstance(arg, basestring):
styles.append(arg)
c = 'x'
else:
styles.append(None)
xdatalist.append(arg)
c = 'y'
if len(styles) == 0:
styles = None
else:
while len(styles) < len(xdatalist):
styles.append(None)
# Set plot data styles
zvalues = kwargs.pop('zvalues', None)
cdata = kwargs.pop('cdata', zvalues)
if cdata is None:
lines = []
legend = kwargs.pop('legend', None)
if not legend is None:
if isinstance(legend, list):
lines = legend
else:
lines = legend.getLegendBreaks()
else:
if not styles is None:
colors = plotutil.makecolors(len(styles))
for i in range(0, len(styles)):
label = kwargs.pop('label', 'S_' + str(i + 1))
if styles[i] is None:
line = plotutil.getlegendbreak('line', **kwargs)[0]
line.setCaption(label)
line.setColor(colors[i])
else:
line = plotutil.getplotstyle(styles[i], label, **kwargs)
lines.append(line)
else:
snum = len(xdatalist)
colors = kwargs.pop('colors', None)
if colors is None:
if kwargs.has_key('color'):
color = kwargs['color']
color = plotutil.getcolor(color)
colors = [color] * snum
else:
colors = plotutil.makecolors(snum)
else:
snum = len(colors) if len(colors) > snum else snum
for i in range(0, snum):
label = kwargs.pop('label', 'S_' + str(i + 1))
line = plotutil.getlegendbreak('line', **kwargs)[0]
line.setCaption(label)
if i < len(colors):
line.setColor(plotutil.getcolor(colors[i]))
lines.append(line)
else:
ls = kwargs.pop('symbolspec', None)
if ls is None:
if isinstance(cdata, (list, tuple)):
cdata = np.array(cdata)
levels = kwargs.pop('levs', None)
levels = kwargs.pop('levels', levels)
if levels is None:
cnum = kwargs.pop('cnum', None)
if cnum is None:
ls = plotutil.getlegendscheme([], cdata.min(), cdata.max(), **kwargs)
else:
ls = plotutil.getlegendscheme([cnum], cdata.min(), cdata.max(), **kwargs)
else:
ls = plotutil.getlegendscheme([levels], cdata.min(), cdata.max(), **kwargs)
ls = plotutil.setlegendscheme_line(ls, **kwargs)
if not xaxistype is None:
self.set_xaxis_type(xaxistype)
timetickformat = kwargs.pop('timetickformat', None)
if not timetickformat is None:
if not xaxistype == 'time':
self._axes.setXAxis(TimeAxis('Time', True))
self._axes.getAxis(Location.BOTTOM).setTimeFormat(timetickformat)
self._axes.getAxis(Location.TOP).setTimeFormat(timetickformat)
# Add graphics
zorder = kwargs.pop('zorder', None)
iscurve = kwargs.pop('curve', False)
graphics = []
if isxylistdata:
graphic = GraphicFactory.createLineString(dataset, lines)
self.add_graphic(graphic, zorder=zorder)
graphics.append(graphic)
else:
if cdata is None:
# Add data series
snum = len(xdatalist)
if snum == 1:
#xdata = plotutil.getplotdata(xdatalist[0])
#ydata = plotutil.getplotdata(ydatalist[0])
xdata = np.asarray(xdatalist[0])
ydata = np.asarray(ydatalist[0])
if len(lines) == 1:
colors = kwargs.pop('colors', None)
if not colors is None:
colors = plotutil.getcolors(colors)
cb = lines[0]
lines = []
for cc in colors:
ncb = cb.clone()
ncb.setColor(cc)
lines.append(ncb)
graphic = GraphicFactory.createLineString(xdata._array, ydata._array, lines, iscurve)
else:
#graphic = GraphicFactory.createLineString(xdata, ydata, lines[0], iscurve)
graphic = Line2D(xdata, ydata, legend=lines[0], curve=iscurve)
else: # >1
graphic = GraphicFactory.createLineString(xdata._array, ydata._array, lines, iscurve)
self.add_graphic(graphic, zorder=zorder)
graphics.append(graphic)
else:
for i in range(0, snum):
label = kwargs.pop('label', 'S_' + str(i + 1))
#xdata = plotutil.getplotdata(xdatalist[i])
#ydata = plotutil.getplotdata(ydatalist[i])
xdata = np.asarray(xdatalist[i])
ydata = np.asarray(ydatalist[i])
#graphic = GraphicFactory.createLineString(xdata, ydata, lines[i], iscurve)
graphic = Line2D(xdata, ydata, legend=lines[i], curve=iscurve)
self.add_graphic(graphic)
graphics.append(graphic)
else:
xdata = np.asarray(xdatalist[0])
ydata = np.asarray(ydatalist[0])
cdata = np.asarray(cdata)
#graphic = GraphicFactory.createLineString(xdata, ydata, cdata, ls, iscurve)
graphic = Line2D(xdata, ydata, legend=ls, cdata=cdata, curve=iscurve)
self.add_graphic(graphic, zorder=zorder)
graphics.append(graphic)
self._axes.setAutoExtent()
if len(graphics) > 1:
return graphics
else:
return graphics[0]
def step(self, x, y, *args, **kwargs):
"""
Make a step plot.
:param x: (*array_like*) Input x data.
:param y: (*array_like*) Input y data.
:param style: (*string*) Line style for plot.
:param label: (*string*) Step line label.
:param where: (*string*) ['pre' | 'post' | 'mid']. If 'pre' (the default), 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.
:returns: Step lines
"""
label = kwargs.pop('label', 'S_0')
xdata = plotutil.getplotdata(x)
ydata = plotutil.getplotdata(y)
if len(args) > 0:
fmt = args[0]
fmt = plotutil.getplotstyle(fmt, label, **kwargs)
else:
fmt = plotutil.getlegendbreak('line', **kwargs)[0]
fmt.setCaption(label)
where = kwargs.pop('where', 'pre')
# Create graphics
graphics = GraphicFactory.createStepLineString(xdata, ydata, fmt, where)
zorder = kwargs.pop('zorder', None)
self.add_graphic(graphics, zorder=zorder)
self._axes.setAutoExtent()
return graphics
def scatter(self, *args, **kwargs):
"""
Make a scatter plot of x vs y, where x and y are sequence like objects of the same lengths.
:param x: (*array_like*) Input x data.
:param y: (*array_like*) Input y data.
:param s: (*int*) Size of points.
:param c: (*Color or array*) Color of the points. Or z values.
:param alpha: (*int*) The alpha blending value, between 0 (transparent) and 1 (opaque).
:param marker: (*string*) Marker of the points.
:param label: (*string*) Label of the point series.
:param levs: (*array_like*) Optional. A list of floating point numbers indicating the level
points to draw, in increasing order.
:returns: Points legend break.
"""
n = len(args)
if n == 1:
a = args[0]
y = a.dimvalue(0)
x = a.dimvalue(1)
else:
x = args[0]
y = args[1]
s = kwargs.pop('s', 8)
c = kwargs.pop('c', None)
# Add data series
label = kwargs.pop('label', 'S_0')
xdata = plotutil.getplotdata(x)
ydata = plotutil.getplotdata(y)
# Set plot data styles
pb, isunique = plotutil.getlegendbreak('point', **kwargs)
if c is None:
c = pb.getColor()
if c is None:
c = 'b'
pb.setCaption(label)
# pstyle = plotutil.getpointstyle(marker)
# pb.setStyle(pstyle)
isvalue = False
if isinstance(c, NDArray):
isvalue = True
elif isinstance(c, (list, tuple)):
if len(x) == len(c) and isinstance(c[0], (int, long, float)):
isvalue = True
if isvalue:
ls = kwargs.pop('symbolspec', None)
if ls is None:
if isinstance(c, (list, tuple)):
c = np.array(c)
levels = kwargs.pop('levs', None)
if levels is None:
levels = kwargs.pop('levels', None)
if levels is None:
cnum = kwargs.pop('cnum', None)
if cnum is None:
ls = plotutil.getlegendscheme([], c.min(), c.max(), **kwargs)
else:
ls = plotutil.getlegendscheme([cnum], c.min(), c.max(), **kwargs)
else:
ls = plotutil.getlegendscheme([levels], c.min(), c.max(), **kwargs)
ls = plotutil.setlegendscheme_point(ls, **kwargs)
if isinstance(s, int):
for lb in ls.getLegendBreaks():
lb.setSize(s)
else:
n = len(s)
for i in range(0, n):
ls.getLegendBreaks()[i].setSize(s[i])
# Create graphics
graphics = GraphicFactory.createPoints(xdata, ydata, c.asarray(), ls)
else:
alpha = kwargs.pop('alpha', None)
colors = plotutil.getcolors(c, alpha)
edgecolors = kwargs.pop('edgecolors', pb.getOutlineColor())
if edgecolors is None:
edgecolors = [Color.black]
pbs = []
if isinstance(s, int):
s = [s]
n = max(len(s), len(colors))
if isinstance(edgecolors, Color):
edgecolors = [edgecolors]
if n == 1:
n = len(edgecolors)
if n == 1:
pb.setSize(s[0])
pb.setColor(colors[0])
pb.setOutlineColor(edgecolors[0])
pbs.append(pb)
else:
if len(s) == 1:
s = s * n
if len(colors) == 1:
colors = colors * n
if len(edgecolors) == 1:
edgecolors = edgecolors * n
for i in range(n):
kwargs['size'] = s[i]
kwargs['color'] = colors[i]
kwargs['edgecolor'] = edgecolors[i]
npb = pb.clone()
plotutil.setpointlegendbreak(npb, **kwargs)
pbs.append(npb)
# Create graphics
graphics = GraphicFactory.createPoints(xdata, ydata, pbs)
zorder = kwargs.pop('zorder', None)
self.add_graphic(graphics, zorder=zorder)
self._axes.setAutoExtent()
return graphics
def semilogy(self, *args, **kwargs):
"""
Make a plot with log scaling on the y axis.
:param x: (*array_like*) Input x data.
:param y: (*array_like*) Input y data.
:param style: (*string*) Line style for plot.
:returns: Legend breaks of the lines.
The following format string characters are accepted to control the line style or marker:
========= ===========
Character Description
========= ===========
'-' solid line style
'--' dashed line style
'-.' dash-dot line style
':' dotted line style
'.' point marker
',' pixel marker
'o' circle marker
'v' triangle_down marker
'^' triangle_up marker
'<' triangle_left marker
'>' triangle_right marker
's' square marker
'p' pentagon marker
'*' star marker
'x' x marker
'D' diamond marker
========= ===========
The following color abbreviations are supported:
========= =====
Character Color
========= =====
'b' blue
'g' green
'r' red
'c' cyan
'm' magenta
'y' yellow
'k' black
========= =====
"""
lines = self.plot(*args, **kwargs)
self.set_yaxis_type('log')
self._axes.setAutoExtent()
return lines
def semilogx(self, *args, **kwargs):
"""
Make a plot with log scaling on the x axis.
:param x: (*array_like*) Input x data.
:param y: (*array_like*) Input y data.
:param style: (*string*) Line style for plot.
:returns: Legend breaks of the lines.
The following format string characters are accepted to control the line style or marker:
========= ===========
Character Description
========= ===========
'-' solid line style
'--' dashed line style
'-.' dash-dot line style
':' dotted line style
'.' point marker
',' pixel marker
'o' circle marker
'v' triangle_down marker
'^' triangle_up marker
'<' triangle_left marker
'>' triangle_right marker
's' square marker
'p' pentagon marker
'*' star marker
'x' x marker
'D' diamond marker
========= ===========
The following color abbreviations are supported:
========= =====
Character Color
========= =====
'b' blue
'g' green
'r' red
'c' cyan
'm' magenta
'y' yellow
'k' black
========= =====
"""
lines = self.plot(*args, **kwargs)
self.set_xaxis_type('log')
self._axes.setAutoExtent()
return lines
def loglog(self, *args, **kwargs):
"""
Make a plot with log scaling on both x and y axis.
:param x: (*array_like*) Input x data.
:param y: (*array_like*) Input y data.
:param style: (*string*) Line style for plot.
:returns: Legend breaks of the lines.
The following format string characters are accepted to control the line style or marker:
========= ===========
Character Description
========= ===========
'-' solid line style
'--' dashed line style
'-.' dash-dot line style
':' dotted line style
'.' point marker
',' pixel marker
'o' circle marker
'v' triangle_down marker
'^' triangle_up marker
'<' triangle_left marker
'>' triangle_right marker
's' square marker
'p' pentagon marker
'*' star marker
'x' x marker
'D' diamond marker
========= ===========
The following color abbreviations are supported:
========= =====
Character Color
========= =====
'b' blue
'g' green
'r' red
'c' cyan
'm' magenta
'y' yellow
'k' black
========= =====
"""
lines = self.plot(*args, **kwargs)
self.set_xaxis_type('log')
self.set_yaxis_type('log')
self._axes.setAutoExtent()
return lines
def errorbar(self, x, y, yerr=None, xerr=None, fmt='', ecolor=None, elinewidth=None, capsize=None,
**kwargs):
"""
Plot an errorbar graph.
:param x: (*array_like*) X data.
:param y: (*array_like*) Y data.
:param yerr: (*scalar or array_like*) Y error values.
:param xerr: (*scalar or array_like*) X error values.
:param fmt: (*string*) Plot format string.
:param ecolor: (*color*) Error bar color.
:param elinewidth: (*float*) Error bar line width.
:param capsize: (*float*) The length of the error bar caps.
:returns: Error bar lines.
"""
# Add data series
label = kwargs.pop('label', 'S_0')
xdata = plotutil.getplotdata(x)
ydata = plotutil.getplotdata(y)
if not yerr is None:
if isinstance(yerr, (int, float)):
ye = []
for i in range(xdata.getSize()):
ye.append(yerr)
yerrB = np.array(ye)._array
yerrU = yerrB
else:
if isinstance(yerr, (list, tuple)):
if isinstance(yerr[0], numbers.Number):
yerrB = plotutil.getplotdata(yerr)
yerrU = yerrB
else:
yerrB = plotutil.getplotdata(yerr[0])
yerrU = plotutil.getplotdata(yerr[1])
elif yerr.ndim == 2:
yerrB = yerr[0, :].asarray()
yerrU = yerr[1, :].asarray()
else:
yerrB = plotutil.getplotdata(yerr)
yerrU = yerrB
else:
yerrB = None
yerrU = None
if not xerr is None:
if isinstance(xerr, (int, float)):
ye = []
for i in range(xdata.getSize()):
ye.append(xerr)
xerrL = np.array(ye)._array
xerrR = xerrL
else:
if isinstance(xerr, (list, tuple)):
xerrL = plotutil.getplotdata(xerr[0])
xerrR = plotutil.getplotdata(xerr[1])
elif xerr.ndim == 2:
xerrL = xerr[0, :].asarray()
xerrR = xerr[1, :].asarray()
else:
xerrL = plotutil.getplotdata(xerr)
xerrR = xerrL
else:
xerrL = None
xerrR = None
# Get plot data style
if fmt == '':
line = plotutil.getlegendbreak('line', **kwargs)[0]
line.setCaption(label)
else:
line = plotutil.getplotstyle(fmt, label, **kwargs)
if isinstance(line, PolylineBreak):
eline = line.clone()
else:
eline = PolylineBreak()
eline.setDrawSymbol(False)
eline.setStyle(LineStyles.SOLID)
if not ecolor is None:
ecolor = plotutil.getcolor(ecolor)
eline.setColor(ecolor)
if not elinewidth is None:
eline.setSize(elinewidth)
# Create graphics
if capsize is None:
capsize = 10
graphics = GraphicFactory.createErrorLineString(xdata, ydata, xerrL, xerrR, yerrB, \
yerrU, line, eline, capsize)
zorder = kwargs.pop('zorder', None)
self.add_graphic(graphics, zorder=zorder)
self._axes.setAutoExtent()
return graphics
def bar(self, x, height, width=0.8, bottom=None, align='center', data=None, **kwargs):
"""
Make a bar plot.
The bars are positioned at x with the given alignment. Their dimensions are given by
width and height. The vertical baseline is bottom (default 0).
:param x: (*array_like*) The x coordinates of the bars. See also align for the alignment
of the bars to the coordinates.
:param height: (*array_like*) The height of the bars.
:param width: (*array_like*) Optional, the widths of the bars default: 0.8.
:param bottom: (*array_like*) Optional, the y coordinates of the bars default: None
:param color: (*Color*) Optional, the color of the bar faces.
:param edgecolor: (*Color*) Optional, the color of the bar edge. Default is black color.
Edge line will not be plotted if ``edgecolor`` is ``None``.
:param linewidth: (*int*) Optional, width of bar edge.
:param label: (*string*) Label of the bar series.
:param hatch: (*string*) Hatch string.
:param hatchsize: (*int*) Hatch size. Default is None (8).
:param bgcolor: (*Color*) Background color, only valid with hatch.
:param barswidth: (*float*) Bars width (0 - 1), only used for automatic bar with plot
(only one argument without ``width`` argument). Default is 0.8.
:param ecolor: (*Color*) The line color of the errorbars. Default is black.
:param elinewidth: (*float*) The line width of the errorbars.
:param capsize: (*float*) The length of the error bar caps in pixels. Default is 0.
:param morepoints: (*boolean*) More points in bar rectangle. Default is False.
:returns: Bar legend break.
The following format string characters are accepted to control the hatch style:
========= ===========
Character Description
========= ===========
'-' horizontal hatch style
'|' vertical hatch style
'\\' forward_diagonal hatch style
'/' backward_diagonal hatch style
'+' cross hatch style
'x' diagonal_cross hatch style
'.' dot hatch style
========= ===========
"""
# Add data series
label = kwargs.pop('label', 'S_0')
autowidth = False
isdate = False
if isinstance(x, (list, tuple)):
if isinstance(x[0], datetime.datetime):
isdate = True
x = np.asarray(x)
height = np.asarray(height)
if isdate and width <= 1:
width = (x[1] - x[0]) * width
width = np.asarray(width)
if align == 'center':
x = x - width / 2
yerr = kwargs.pop('yerr', None)
if not yerr is None:
if not isinstance(yerr, (int, float)):
yerr = plotutil.getplotdata(yerr)
if not bottom is None:
bottom = plotutil.getplotdata(bottom)
# Set plot data styles
fcobj = kwargs.pop('color', None)
if fcobj is None:
fcobj = kwargs.pop('facecolor', 'b')
if isinstance(fcobj, (tuple, list)):
colors = plotutil.getcolors(fcobj)
else:
color = plotutil.getcolor(fcobj)
colors = [color]
ecobj = kwargs.pop('edgecolor', 'k')
edgecolor = plotutil.getcolor(ecobj)
linewidth = kwargs.pop('linewidth', 1.0)
hatch = kwargs.pop('hatch', None)
hatch = plotutil.gethatch(hatch)
hatchsize = kwargs.pop('hatchsize', None)
bgcolor = kwargs.pop('bgcolor', None)
bgcolor = plotutil.getcolor(bgcolor)
ecolor = kwargs.pop('ecolor', 'k')
ecolor = plotutil.getcolor(ecolor)
elinewidth = kwargs.pop('elinewidth', None)
capsize = kwargs.pop('capsize', None)
morepoints = kwargs.pop('morepoints', False)
barbreaks = []
for color in colors:
lb = BarBreak()
lb.setCaption(label)
lb.setColor(color)
if edgecolor is None:
lb.setDrawOutline(False)
else:
lb.setOutlineColor(edgecolor)
lb.setOutlineSize(linewidth)
if not hatch is None:
lb.setStyle(hatch)
if not bgcolor is None:
lb.setBackColor(bgcolor)
if not hatchsize is None:
lb.setStyleSize(hatchsize)
lb.setErrorColor(ecolor)
if not elinewidth is None:
lb.setErrorSize(elinewidth)
if not capsize is None:
lb.setCapSize(capsize)
barbreaks.append(lb)
# Create bar graphics
if isinstance(width, NDArray):
width = width.asarray()
if morepoints:
graphics = GraphicFactory.createBars1(x.asarray(), height.asarray(), autowidth, width, not yerr is None,
yerr, \
not bottom is None, bottom, barbreaks)
else:
graphics = GraphicFactory.createBars(x.asarray(), height.asarray(), autowidth, width, not yerr is None,
yerr, \
not bottom is None, bottom, barbreaks)
zorder = kwargs.pop('zorder', None)
self.add_graphic(graphics, zorder=zorder)
self._axes.setAutoExtent()
if autowidth:
barswidth = kwargs.pop('barswidth', 0.8)
self._axes.setBarsWidth(barswidth)
return barbreaks
def barh(self, *args, **kwargs):
"""
Make a horizontal bar plot.
Make a bar plot with rectangles bounded by:
left, left + width, y, y + height
:param y: (*array_like*) The y coordinates of the bars.
:param width: (*array_like*) The widths of the bars.
:param height: (*array_like*) Optional, the height of the bars default: 0.8.
:param left: (*array_like*) Optional, the x coordinates of the bars default: None
:param color: (*Color*) Optional, the color of the bar faces.
:param edgecolor: (*Color*) Optional, the color of the bar edge. Default is black color.
Edge line will not be plotted if ``edgecolor`` is ``None``.
:param linewidth: (*int*) Optional, width of bar edge.
:param label: (*string*) Label of the bar series.
:param hatch: (*string*) Hatch string.
:param hatchsize: (*int*) Hatch size. Default is None (8).
:param bgcolor: (*Color*) Background color, only valid with hatch.
:param barswidth: (*float*) Bars width (0 - 1), only used for automatic bar with plot
(only one argument widthout ``width`` augument). Defaul is 0.8.
:param morepoints: (*boolean*) More points in bar rectangle. Defaul is False.
:returns: Bar legend break.
The following format string characters are accepted to control the hatch style:
========= ===========
Character Description
========= ===========
'-' horizontal hatch style
'|' vertical hatch style
'\\' forward_diagonal hatch style
'/' backward_diagonal hatch style
'+' cross hatch style
'x' diagonal_cross hatch style
'.' dot hatch style
========= ===========
"""
# Add data series
label = kwargs.pop('label', 'S_0')
xdata = None
autoheight = True
height = 0.8
if len(args) == 1:
xdata = args[0]
elif len(args) == 2:
if isinstance(args[1], (int, float)):
xdata = args[0]
height = args[1]
autoheight = False
else:
ydata = args[0]
xdata = args[1]
else:
ydata = args[0]
xdata = args[1]
height = args[2]
autoheight = False
if ydata is None:
ydata = []
for i in range(1, len(args[0]) + 1):
ydata.append(i)
ydata = plotutil.getplotdata(ydata)
xdata = plotutil.getplotdata(xdata)
height = plotutil.getplotdata(height)
xerr = kwargs.pop('xerr', None)
if not xerr is None:
if not isinstance(xerr, (int, float)):
xerr = plotutil.getplotdata(xerr)
left = kwargs.pop('left', None)
if not left is None:
left = plotutil.getplotdata(left)
# Set plot data styles
fcobj = kwargs.pop('color', None)
if fcobj is None:
fcobj = kwargs.pop('facecolor', 'b')
if isinstance(fcobj, (tuple, list)):
colors = plotutil.getcolors(fcobj)
else:
color = plotutil.getcolor(fcobj)
colors = [color]
ecobj = kwargs.pop('edgecolor', 'k')
edgecolor = plotutil.getcolor(ecobj)
linewidth = kwargs.pop('linewidth', 1.0)
hatch = kwargs.pop('hatch', None)
hatch = plotutil.gethatch(hatch)
hatchsize = kwargs.pop('hatchsize', None)
bgcolor = kwargs.pop('bgcolor', None)
bgcolor = plotutil.getcolor(bgcolor)
ecolor = kwargs.pop('ecolor', 'k')
ecolor = plotutil.getcolor(ecolor)
barbreaks = []
for color in colors:
lb = BarBreak()
lb.setCaption(label)
lb.setColor(color)
if edgecolor is None:
lb.setDrawOutline(False)
else:
lb.setOutlineColor(edgecolor)
lb.setOutlineSize(linewidth)
if not hatch is None:
lb.setStyle(hatch)
if not bgcolor is None:
lb.setBackColor(bgcolor)
if not hatchsize is None:
lb.setStyleSize(hatchsize)
lb.setErrorColor(ecolor)
barbreaks.append(lb)
# Create bar graphics
graphics = GraphicFactory.createHBars(ydata, xdata, autoheight, height, not xerr is None, xerr, \
not left is None, left, barbreaks)
zorder = kwargs.pop('zorder', None)
self.add_graphic(graphics, zorder=zorder)
self._axes.setAutoExtent()
if autoheight:
barsheight = kwargs.pop('barsheight', 0.8)
self._axes.setBarsWidth(barsheight)
return barbreaks
def hist(self, x, bins=10, density=False, cumulative=False,
rwidth=None, orientation='vertical', **kwargs):
"""
Plot a histogram.
:param x: (*array_like*) Input values, this takes either a single array or a sequence of arrays
which are not required to be of the same length.
:param bins: (*int*) If an integer is given, bins + 1 bin edges are returned.
:param density: (*bool*) Default is `False`. 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 cumulative: (*bool*) Default is `False`. If `True`, then a histogram is computed
where each bin gives the counts in that bin plus all bins for smaller values. The
last bin gives the total number of datapoints.
:param rwidth: (*float or None*) Default is `None`. The relative width of the bars as a
fraction of the bin width. If None, automatically compute the width.
:param orientation: (*str*) {'vertical', 'horizontal'}, default: 'vertical'. If
'horizontal', barh will be used for bar-type histograms and the bottom kwarg will be
the left edges.
Returns
-------
n : array or list of arrays
The values of the histogram bins. See *density* and *weights* for a
description of the possible semantics. If input *x* is an array,
then this is an array of length *nbins*. If input is a sequence of
arrays ``[data1, data2, ...]``, then this is a list of arrays with
the values of the histograms for each of the arrays in the same
order. The dtype of the array *n* (or of its element arrays) will
always be float even if no weighting or normalization is used.
bins : array
The edges of the bins. Length nbins + 1 (nbins left edges and right
edge of last bin). Always a single array even when multiple data
sets are passed in.
patches : `.BarContainer` or list of a single `.Polygon` or list of such objects
Container of individual artists used to create the histogram
or list of such containers if there are multiple input datasets.
"""
if isinstance(x, NDArray) and x.ndim == 1:
m, bins = np.histogram(x, bins=bins, density=density)
width = np.diff(bins)
if cumulative:
m = np.cumsum(m * width)
if rwidth is not None:
width = width * rwidth
if orientation == 'vertical':
barbreaks = self.bar(bins[:-1], m, width, align='center', **kwargs)
else:
barbreaks = self.barh(bins[:-1], m, width, align='center', **kwargs)
return m, bins, barbreaks
else:
mlist = []
barbreaklist = []
if isinstance(x, (list, tuple)):
n = len(x)
else:
n = x.shape[1]
colors = kwargs.pop('color', None)
if colors is None:
colors = plotutil.makecolors(n)
labels = kwargs.pop('label', None)
for i in range(n):
if isinstance(x, NDArray):
xx = x[:,i]
else:
xx = x[i]
m, bins = np.histogram(xx, bins=bins, density=density)
width = np.diff(bins) / n
if cumulative:
m = np.cumsum(m * width)
mlist.append(m)
if rwidth is not None:
width = width * rwidth
kwargs['color'] = colors[i]
if labels is not None:
kwargs['label'] = labels[i]
if orientation == 'vertical':
barbreaks = self.bar(bins[:-1] + width * i, m, width, align='center', **kwargs)
else:
barbreaks = self.barh(bins[:-1] + width * i, m, width, align='center', **kwargs)
barbreaklist.append(barbreaks)
return mlist, bins, barbreaklist
def hist_back(self, x, bins=10, range=None, density=False, cumulative=False,
bottom=None, histtype='bar', align='mid',
orientation='vertical', rwidth=None, log=False, **kwargs):
"""
Plot a histogram.
:param x: (*array_like*) Input values, this takes either a single array or a sequency of arrays
which are not required to be of the same length.
:param bins: (*int*) If an integer is given, bins + 1 bin edges are returned.
"""
# Add data series
label = kwargs.pop('label', 'S_0')
# Set plot data styles
fcobj = kwargs.pop('color', None)
if fcobj is None:
fcobj = kwargs.pop('facecolor', 'b')
if isinstance(fcobj, (tuple, list)):
colors = plotutil.getcolors(fcobj)
else:
color = plotutil.getcolor(fcobj)
colors = [color]
ecobj = kwargs.pop('edgecolor', 'k')
edgecolor = plotutil.getcolor(ecobj)
linewidth = kwargs.pop('linewidth', 1.0)
hatch = kwargs.pop('hatch', None)
hatch = plotutil.gethatch(hatch)
hatchsize = kwargs.pop('hatchsize', None)
bgcolor = kwargs.pop('bgcolor', None)
bgcolor = plotutil.getcolor(bgcolor)
ecolor = kwargs.pop('ecolor', 'k')
ecolor = plotutil.getcolor(ecolor)
barbreaks = []
for color in colors:
lb = BarBreak()
lb.setCaption(label)
lb.setColor(color)
if edgecolor is None:
lb.setDrawOutline(False)
else:
lb.setOutlineColor(edgecolor)
lb.setOutlineSize(linewidth)
if not hatch is None:
lb.setStyle(hatch)
if not bgcolor is None:
lb.setBackColor(bgcolor)
if not hatchsize is None:
lb.setStyleSize(hatchsize)
lb.setErrorColor(ecolor)
barbreaks.append(lb)
# Create bar graphics
x = plotutil.getplotdata(x)
if not isinstance(bins, numbers.Number):
bins = plotutil.getplotdata(bins)
graphics = GraphicFactory.createHistBars(x, bins, barbreaks)
self.add_graphic(graphics)
self._axes.setAutoExtent()
return lb
def stem(self, *args, **kwargs):
"""
Make a stem plot.
A stem plot plots vertical lines at each x location from the baseline to y, and
places a marker there.
:param x: (*array_like*) The x-positions of the stems.
:param y: (*array_like*) The y-values of the stem heads.
:param bottom: (*array_like*) Optional, The y-position of the baseline.
:param linefmt: (*dict*) Optional, stem line format.
:param markerfmt: (*dict*) Optional, stem marker format.
:param color: (*Color*) Optional, the color of the stem.
:returns: Stem line legend break.
"""
# Add data series
label = kwargs.pop('label', 'S_0')
xdata = None
if len(args) == 1:
ydata = args[0]
else:
xdata = args[0]
ydata = args[1]
if xdata is None:
xdata = []
for i in range(1, len(args[0]) + 1):
xdata.append(i)
xdata = plotutil.getplotdata(xdata)
ydata = plotutil.getplotdata(ydata)
bottom = kwargs.pop('bottom', 0)
# Set plot data styles
color = kwargs.pop('color', None)
if not color is None:
color = plotutil.getcolor(color)
linefmt = kwargs.pop('linefmt', None)
if linefmt is None:
linefmt = PolylineBreak()
linefmt.setColor(color is None and Color.red or color)
else:
linefmt = plotutil.getlegendbreak('line', **linefmt)[0]
linefmt.setCaption(label)
markerfmt = kwargs.pop('markerfmt', None)
if markerfmt is None:
markerfmt = PointBreak()
markerfmt.setOutlineColor(color is None and Color.red or color)
markerfmt.setDrawFill(False)
else:
markerfmt = plotutil.getlegendbreak('point', **markerfmt)[0]
basefmt = kwargs.pop('basefmt', None)
if basefmt is None:
basefmt = PolylineBreak()
basefmt.setColor(color is None and Color.red or color)
else:
basefmt = plotutil.getlegendbreak('line', **basefmt)[0]
# Create stem graphics
graphics = GraphicFactory.createStems(xdata, ydata, linefmt, markerfmt, \
basefmt, bottom)
zorder = kwargs.pop('zorder', None)
self.add_graphic(graphics, zorder=zorder)
self._axes.setAutoExtent()
return linefmt
def contour(self, *args, **kwargs):
"""
Plot contours.
:param x: (*array_like*) Optional. X coordinate array.
:param y: (*array_like*) Optional. Y coordinate array.
:param z: (*array_like*) 2-D z value array.
:param levels: (*array_like*) Optional. A list of floating point numbers indicating the level curves
to draw, in increasing order.
:param cmap: (*string*) Color map string.
:param colors: (*list*) If None (default), the colormap specified by cmap will be used. If a
string, like r or red, all levels will be plotted in this color. If a tuple of matplotlib
color args (string, float, rgb, etc.), different levels will be plotted in different colors in
the order specified.
:param smooth: (*boolean*) Smooth contour lines or not.
:returns: (*contour graphics*) Contour graphics created from array data.
"""
n = len(args)
ls = kwargs.pop('symbolspec', None)
cmap = plotutil.getcolormap(**kwargs)
fill_value = kwargs.pop('fill_value', -9999.0)
xaxistype = None
if n <= 2:
a = args[0]
if isinstance(a, DimArray):
y = a.dimvalue(0)
x = a.dimvalue(1)
else:
x = np.arange(a.shape[1])
y = np.arange(a.shape[0])
args = args[1:]
elif n <= 4:
x = args[0]
y = args[1]
a = args[2]
args = args[3:]
vmin = kwargs.pop('vmin', a.min())
vmax = kwargs.pop('vmax', a.max())
if ls is None:
if len(args) > 0:
level_arg = args[0]
if isinstance(level_arg, int):
cn = level_arg
ls = LegendManage.createLegendScheme(vmin, vmax, cn, cmap)
else:
if isinstance(level_arg, NDArray):
level_arg = level_arg.aslist()
ls = LegendManage.createLegendScheme(vmin, vmax, level_arg, cmap)
else:
ls = LegendManage.createLegendScheme(vmin, vmax, cmap)
ls = ls.convertTo(ShapeTypes.POLYLINE)
plotutil.setlegendscheme(ls, **kwargs)
# norm = kwargs.pop('norm', colors.Normalize(vmin, vmax))
# ls.setNormalize(norm._norm)
# ls.setColorMap(cmap)
smooth = kwargs.pop('smooth', True)
if x.ndim == 2 and y.ndim == 2:
griddata_props = kwargs.pop('griddata_props', dict(method='idw', pointnum=5, convexhull=True))
a, x, y = np.griddata((x, y), a, **griddata_props)
igraphic = GraphicFactory.createContourLines(x.asarray(), y.asarray(), a.asarray(), ls, smooth)
if not xaxistype is None:
self.set_xaxis_type(xaxistype)
self._axes.updateDrawExtent()
zorder = kwargs.pop('zorder', None)
self.add_graphic(igraphic, zorder=zorder)
# self._axes.setAutoExtent()
self._axes.setExtent(igraphic.getExtent())
self._axes.setDrawExtent(igraphic.getExtent())
return igraphic
def clabel(self, layer, **kwargs):
"""
Add contour layer labels.
:param layer: (*MILayer*) The contour layer.
:param fontname, fontsize: The font augments.
:param color: (*color*) The label color. Default is ``None``, the label color will be set as
same as color of the line.
:param dynamic: (*boolean*) Draw labels dynamic or not. Default is ``True``.
:param drawshadow: (*boolean*) Draw shadow under labels or not.
:param fieldname: (*string*) The field name used for label.
:param xoffset: (*int*) X offset of the labels.
:param yoffset: (int*) Y offset of the labels.
:param avoidcoll: (*boolean*) Avoid labels collision or not.
"""
color = kwargs.pop('color', None)
gc = layer
if isinstance(layer, MILayer):
gc = layer._layer
dynamic = kwargs.pop('dynamic', True)
if gc.getShapeType() != ShapeTypes.POLYLINE:
dynamic = False
drawshadow = kwargs.pop('drawshadow', dynamic)
labelset = gc.getLabelSet()
if isinstance(gc, MapLayer):
fieldname = kwargs.pop('fieldname', labelset.getFieldName())
if fieldname is None:
fieldname = gc.getFieldName(0)
labelset.setFieldName(fieldname)
fontdic = kwargs.pop('font', None)
if not fontdic is None:
font = plotutil.getfont(fontdic)
labelset.setLabelFont(font)
else:
font = plotutil.getfont_1(**kwargs)
labelset.setLabelFont(font)
if color is None:
labelset.setColorByLegend(True)
else:
labelset.setColorByLegend(False)
color = plotutil.getcolor(color)
labelset.setLabelColor(color)
labelset.setDrawShadow(drawshadow)
xoffset = kwargs.pop('xoffset', 0)
labelset.setXOffset(xoffset)
yoffset = kwargs.pop('yoffset', 0)
labelset.setYOffset(yoffset)
avoidcoll = kwargs.pop('avoidcoll', True)
labelset.setAvoidCollision(avoidcoll)
decimals = kwargs.pop('decimals', None)
if not decimals is None:
labelset.setAutoDecimal(False)
labelset.setDecimalDigits(decimals)
if dynamic:
gc.addLabelsContourDynamic(gc.getExtent())
else:
gc.addLabels()
def contourf(self, *args, **kwargs):
"""
Plot filled contours.
:param x: (*array_like*) Optional. X coordinate array.
:param y: (*array_like*) Optional. Y coordinate array.
:param z: (*array_like*) 2-D z value array.
:param levels: (*array_like*) Optional. A list of floating point numbers indicating the level curves
to draw, in increasing order.
:param cmap: (*string*) Color map string.
:param colors: (*list*) If None (default), the colormap specified by cmap will be used. If a
string, like r or red, all levels will be plotted in this color. If a tuple of matplotlib
color args (string, float, rgb, etc.), different levels will be plotted in different colors in
the order specified.
:param extend: (*string*) {'neither', 'both', 'min', 'max'}, default: 'neither'. Determines the
contourf-coloring of values that are outside the levels range. If 'neither', values outside
the levels range are not colored. If 'min', 'max' or 'both', color the values below, above
or below and above the levels range.
:param extendfrac: (*string or float*) {None, 'auto', length}, If set to None, both the minimum
and maximum triangular colorbar extensions will have a length of 5% of the interior colorbar
length (this is the default setting). If set to 'auto', makes the triangular colorbar
extensions the same lengths as the interior boxes. If a scalar, indicates the length of both
the minimum and maximum triangular colorbar extensions as a fraction of the interior colorbar
length.
:param smooth: (*boolean*) Smooth contour lines or not.
:returns: (*GraphicCollection*) Contour filled graphics created from array data.
"""
n = len(args)
ls = kwargs.pop('symbolspec', None)
cmap = plotutil.getcolormap(**kwargs)
fill_value = kwargs.pop('fill_value', -9999.0)
xaxistype = None
if n <= 2:
a = args[0]
if isinstance(a, DimArray):
y = a.dimvalue(0)
x = a.dimvalue(1)
else:
x = np.arange(a.shape[1])
y = np.arange(a.shape[0])
args = args[1:]
elif n <= 4:
x = args[0]
y = args[1]
a = args[2]
args = args[3:]
vmin = kwargs.pop('vmin', a.min())
vmax = kwargs.pop('vmax', a.max())
extend = ExtendType.valueOf(kwargs.pop('extend', 'neither').upper())
if ls is None:
if len(args) > 0:
level_arg = args[0]
if isinstance(level_arg, int):
cn = level_arg
ls = LegendManage.createLegendScheme(vmin, vmax, cn, cmap, extend)
else:
if isinstance(level_arg, NDArray):
level_arg = level_arg.aslist()
ls = LegendManage.createLegendScheme(level_arg, cmap, extend)
else:
ls = LegendManage.createLegendScheme(vmin, vmax, cmap, extend)
ls = ls.convertTo(ShapeTypes.POLYGON)
if 'edgecolor' not in kwargs.keys():
kwargs['edgecolor'] = None
plotutil.setlegendscheme(ls, **kwargs)
extendfrac = kwargs.pop('extendfrac', None)
if extendfrac is not None:
if extendfrac == 'auto':
efrac = ExtendFraction.AUTO
else:
efrac = ExtendFraction.LENGTH
efrac.fraction = extendfrac
ls.setExtendFraction(efrac)
# norm = kwargs.pop('norm', colors.Normalize(vmin, vmax))
# ls.setNormalize(norm._norm)
# ls.setColorMap(cmap)
smooth = kwargs.pop('smooth', True)
if x.ndim == 2 and y.ndim == 2:
griddata_props = kwargs.pop('griddata_props', dict(method='idw', pointnum=5, convexhull=True))
a, x, y = np.griddata((x, y), a, **griddata_props)
igraphic = GraphicFactory.createContourPolygons(x.asarray(), y.asarray(), a.asarray(), ls, smooth)
visible = kwargs.pop('visible', True)
if visible:
if xaxistype is not None:
self.set_xaxis_type(xaxistype)
self._axes.updateDrawExtent()
zorder = kwargs.pop('zorder', None)
self.add_graphic(igraphic, zorder=zorder)
# self.setAutoExtent()
self._axes.setExtent(igraphic.getExtent())
self._axes.setDrawExtent(igraphic.getExtent())
return igraphic
def imshow(self, *args, **kwargs):
"""
Display an image on the axes.
:param X: (*array_like*) 2-D or 3-D (RGB or RGBA) image value array or BufferedImage.
:param levels: (*array_like*) Optional. A list of floating point numbers indicating the level curves
to draw, in increasing order.
:param cmap: (*string*) Color map string.
:param colors: (*list*) If None (default), the colormap specified by cmap will be used. If a
string, like r or red, all levels will be plotted in this color. If a tuple of matplotlib
color args (string, float, rgb, etc.), different levels will be plotted in different colors in
the order specified.
:param interpolation: (*string*) Interpolation option [None | bilinear | bicubic].
:returns: (*Image graphic*) Image graphic created from array data.
"""
n = len(args)
cmap = plotutil.getcolormap(**kwargs)
fill_value = kwargs.pop('fill_value', -9999.0)
xaxistype = None
isrgb = False
isimage = False
extent = None
if n >= 3:
xdata = args[0]
ydata = args[1]
extent = [xdata[0], xdata[-1], ydata[0], ydata[-1]]
args = args[2:]
X = args[0]
if isinstance(X, (list, tuple)):
isrgb = True
elif isinstance(X, BufferedImage):
isimage = True
elif X.ndim > 2:
isrgb = True
else:
if n < 3:
if isinstance(X, DimArray):
xdata = X.dimvalue(-1)
ydata = X.dimvalue(-2)
else:
ny, nx = X.shape
xdata = np.arange(nx)
ydata = np.arange(ny)
args = args[1:]
extent = kwargs.pop('extent', extent)
if isrgb:
if isinstance(X, (list, tuple)):
rgbd = []
for d in rgbdata:
rgbd.append(d.asarray())
rgbdata = rgbd
else:
rgbdata = X.asarray()
igraphic = GraphicFactory.createImage(rgbdata, extent)
ls = None
elif isimage:
igraphic = GraphicFactory.createImage(X)
ls = None
else:
ls = kwargs.pop('symbolspec', None)
if ls is None:
vmin = kwargs.pop('vmin', X.min())
vmax = kwargs.pop('vmax', X.max())
if len(args) > 0:
level_arg = args[0]
if isinstance(level_arg, int):
cn = level_arg
ls = LegendManage.createImageLegend(X._array, cn, cmap)
else:
if isinstance(level_arg, NDArray):
level_arg = level_arg.aslist()
ls = LegendManage.createImageLegend(X._array, level_arg, cmap)
else:
ls = plotutil.getlegendscheme(args, vmin, vmax, **kwargs)
norm = kwargs.pop('norm', colors.Normalize(vmin, vmax))
ls.setNormalize(norm._norm)
ls.setColorMap(cmap)
ls = ls.convertTo(ShapeTypes.IMAGE)
plotutil.setlegendscheme(ls, **kwargs)
igraphic = GraphicFactory.createImage(X._array, xdata._array, ydata._array, ls, extent)
interpolation = kwargs.pop('interpolation', None)
if not interpolation is None:
igraphic.getShape().setInterpolation(interpolation)
if not xaxistype is None:
self.set_xaxis_type(xaxistype)
self._axes.updateDrawExtent()
zorder = kwargs.pop('zorder', None)
self.add_graphic(igraphic, zorder=zorder)
self._axes.setAutoExtent()
gridline = self._axes.getGridLine()
gridline.setTop(True)
if ls is None:
return igraphic
else:
return ls
def imshow_bak(self, *args, **kwargs):
"""
Display an image on the axes.
:param X: (*array_like*) 2-D or 3-D (RGB or RGBA) image value array or BufferedImage.
:param levels: (*array_like*) Optional. A list of floating point numbers indicating the level curves
to draw, in increasing order.
:param cmap: (*string*) Color map string.
:param colors: (*list*) If None (default), the colormap specified by cmap will be used. If a
string, like r or red, all levels will be plotted in this color. If a tuple of matplotlib
color args (string, float, rgb, etc.), different levels will be plotted in different colors in
the order specified.
:param interpolation: (*string*) Interpolation option [None | bilinear | bicubic].
:returns: (*Image graphic*) Image graphic created from array data.
"""
n = len(args)
cmap = plotutil.getcolormap(**kwargs)
fill_value = kwargs.pop('fill_value', -9999.0)
xaxistype = None
isrgb = False
isimage = False
extent = None
if n >= 3:
xdata = args[0]
ydata = args[1]
extent = [xdata[0], xdata[-1], ydata[0], ydata[-1]]
args = args[2:]
X = args[0]
if isinstance(X, (list, tuple)):
isrgb = True
elif isinstance(X, BufferedImage):
isimage = True
elif X.ndim > 2:
isrgb = True
else:
if n >= 3:
gdata = np.asgridarray(X, xdata, ydata)
else:
gdata = np.asgridarray(X)
args = args[1:]
extent = kwargs.pop('extent', extent)
if isrgb:
if isinstance(X, (list, tuple)):
rgbd = []
for d in rgbdata:
rgbd.append(d.asarray())
rgbdata = rgbd
else:
rgbdata = X.asarray()
igraphic = GraphicFactory.createImage(rgbdata, extent)
ls = None
elif isimage:
igraphic = GraphicFactory.createImage(X)
ls = None
else:
ls = kwargs.pop('symbolspec', None)
if ls is None:
vmin = kwargs.pop('vmin', gdata.min())
vmax = kwargs.pop('vmax', gdata.max())
if len(args) > 0:
level_arg = args[0]
if isinstance(level_arg, int):
cn = level_arg
ls = LegendManage.createImageLegend(gdata, cn, cmap)
else:
if isinstance(level_arg, NDArray):
level_arg = level_arg.aslist()
ls = LegendManage.createImageLegend(gdata, level_arg, cmap)
else:
ls = plotutil.getlegendscheme(args, vmin, vmax, **kwargs)
norm = kwargs.pop('norm', colors.Normalize(vmin, vmax))
ls.setNormalize(norm._norm)
ls.setColorMap(cmap)
ls = ls.convertTo(ShapeTypes.IMAGE)
plotutil.setlegendscheme(ls, **kwargs)
igraphic = GraphicFactory.createImage(gdata, ls, extent)
interpolation = kwargs.pop('interpolation', None)
if not interpolation is None:
igraphic.getShape().setInterpolation(interpolation)
if not xaxistype is None:
self.set_xaxis_type(xaxistype)
self._axes.updateDrawExtent()
zorder = kwargs.pop('zorder', None)
self.add_graphic(igraphic, zorder=zorder)
self._axes.setAutoExtent()
gridline = self._axes.getGridLine()
gridline.setTop(True)
if ls is None:
return igraphic
else:
return ls
def pcolor(self, *args, **kwargs):
"""
Draw a pseudo color plot.
:param x: (*array_like*) Optional. X coordinate array.
:param y: (*array_like*) Optional. Y coordinate array.
:param z: (*array_like*) 2-D z value array.
:param levs: (*array_like*) Optional. A list of floating point numbers indicating the level curves
to draw, in increasing order.
:param cmap: (*string*) Color map string.
:param colors: (*list*) If None (default), the colormap specified by cmap will be used. If a
string, like r or red, all levels will be plotted in this color. If a tuple of matplotlib
color args (string, float, rgb, etc), different levels will be plotted in different colors in
the order specified.
:returns: (*GraphicCollection*) Polygon graphic collection.
"""
n = len(args)
if n <= 2:
a = args[0]
if isinstance(a, DimArray):
y = a.dimvalue(0)
x = a.dimvalue(1)
else:
ny, nx = a.shape
y = np.arange(ny)
x = np.arange(nx)
args = args[1:]
else:
x = args[0]
y = args[1]
a = args[2]
args = args[3:]
if a.ndim == 2 and x.ndim == 1:
x, y = np.meshgrid(x, y)
ls = plotutil.getlegendscheme(args, a.min(), a.max(), **kwargs)
ls = ls.convertTo(ShapeTypes.POLYGON)
if not kwargs.has_key('edgecolor'):
kwargs['edgecolor'] = None
plotutil.setlegendscheme(ls, **kwargs)
graphics = GraphicFactory.createPColorPolygons(x.asarray(), y.asarray(), a.asarray(), ls)
visible = kwargs.pop('visible', True)
if visible:
zorder = kwargs.pop('zorder', None)
self.add_graphic(graphics, zorder=zorder)
self._axes.setExtent(graphics.getExtent())
self._axes.setDrawExtent(graphics.getExtent())
return graphics
def gridshow(self, *args, **kwargs):
"""
Draw a grid plot.
:param x: (*array_like*) Optional. X coordinate array.
:param y: (*array_like*) Optional. Y coordinate array.
:param z: (*array_like*) 2-D z value array.
:param levs: (*array_like*) Optional. A list of floating point numbers indicating the level curves
to draw, in increasing order.
:param cmap: (*string*) Color map string.
:param colors: (*list*) If None (default), the colormap specified by cmap will be used. If a
string, like r or red, all levels will be plotted in this color. If a tuple of matplotlib
color args (string, float, rgb, etc), different levels will be plotted in different colors in
the order specified.
:param fill_value: (*float*) Fill_value. Default is ``-9999.0``.
:returns: (*GraphicCollection*) Polygon graphic collection.
"""
fill_value = kwargs.pop('fill_value', -9999.0)
n = len(args)
if n <= 2:
a = args[0]
y = a.dimvalue(0)
x = a.dimvalue(1)
args = args[1:]
else:
x = args[0]
y = args[1]
a = args[2]
args = args[3:]
ls = plotutil.getlegendscheme(args, a.min(), a.max(), **kwargs)
ls = ls.convertTo(ShapeTypes.POLYGON)
plotutil.setlegendscheme(ls, **kwargs)
graphics = GraphicFactory.createGridPolygons(x.asarray(), y.asarray(), a.asarray(), ls)
visible = kwargs.pop('visible', True)
if visible:
zorder = kwargs.pop('zorder', None)
self.add_graphic(graphics, zorder=zorder)
self._axes.setExtent(graphics.getExtent())
self._axes.setDrawExtent(graphics.getExtent())
return graphics
def text(self, x, y, s, **kwargs):
"""
Add text to the axes. Add text in string *s* to axis at location *x* , *y* , data
coordinates.
:param x: (*float*) Data x coordinate.
:param y: (*float*) Data y coordinate.
:param s: (*string*) Text.
:param fontname: (*string*) Font name. Default is ``Arial`` .
:param fontsize: (*int*) Font size. Default is ``14`` .
:param bold: (*boolean*) Is bold font or not. Default is ``False`` .
:param color: (*color*) Tick label string color. Default is ``black`` .
:param coordinates=['axes'|'figure'|'data'|'inches']: (*string*) Coordinate system and units for
*X, Y*. 'axes' and 'figure' are normalized coordinate system with 0,0 in the lower left and
1,1 in the upper right, 'data' are the axes data coordinates (Default value); 'inches' is
position in the figure in inches, with 0,0 in the lower left corner.
"""
ctext = plotutil.text(x, y, s, **kwargs)
self._axes.addText(ctext)
return ctext
def arrow(self, x, y, dx, dy, **kwargs):
"""
Add an arrow to the axes.
:param x: (*float*) X coordinate.
:param y: (*float*) Y coordinate.
:param dx: (*float*) The length of arrow along x direction.
:param dy: (*float*) The length of arrow along y direction.
:returns: Arrow graphic.
"""
if not kwargs.has_key('facecolor'):
kwargs['facecolor'] = (51, 204, 255)
apb, isunique = plotutil.getlegendbreak('polygon', **kwargs)
apb = plotutil.polygon2arrow(apb, **kwargs)
graphic = GraphicFactory.createArrow(x, y, dx, dy, apb)
zorder = kwargs.pop('zorder', None)
self.add_graphic(graphic, zorder=zorder)
self._axes.setAutoExtent()
return graphic
def arrowline(self, x, y, dx=0, dy=0, **kwargs):
"""
Add an arrow line to the axes.
:param x: (*float or array_like*) X coordinates.
:param y: (*float or array_like*) Y coordinates.
:param dx: (*float*) The length of arrow along x direction. Only valid when x is float.
:param dy: (*float*) The length of arrow along y direction. Only valid when y is float.
:returns: Arrow line graphic.
"""
if isinstance(x, (list, tuple)):
x = np.array(x)
if isinstance(y, (list, tuple)):
y = np.array(y)
alb, isunique = plotutil.getlegendbreak('line', **kwargs)
alb = plotutil.line2arrow(alb, **kwargs)
if isinstance(x, NDArray):
iscurve = kwargs.pop('iscurve', False)
graphic = GraphicFactory.createArrowLine(x._array, y._array, alb, iscurve)
else:
graphic = GraphicFactory.createArrowLine(x, y, dx, dy, alb)
zorder = kwargs.pop('zorder', None)
self.add_graphic(graphic, zorder=zorder)
self._axes.setAutoExtent()
return graphic
def annotate(self, s, xy, *args, **kwargs):
"""
Annotate the point xy with text s.
:param s: (*string*) The text of the annotation.
:param xy: (*float, float*) The point (x,y) to annotate.
:param xytext: (*float, float*) The position (x,y) to place the text at. If None,
defaults to xy.
:param arrowprops: (*dict*) Arrow properties.
:returns: Annotation.
"""
if len(args) > 0:
xytext = args[0]
else:
xytext = xy
ctext = plotutil.text(xytext[0], xytext[1], s, **kwargs)
self._axes.addText(ctext)
arrowprops = kwargs.pop('arrowprops', dict())
if not arrowprops.has_key('headwidth'):
arrowprops['headwidth'] = 10
if not arrowprops.has_key('shrink'):
arrowprops['shrink'] = 0.05
alb, isunique = plotutil.getlegendbreak('line', **arrowprops)
alb = plotutil.line2arrow(alb, **arrowprops)
x0 = xytext[0]
y0 = xytext[1]
dx = xy[0] - xytext[0]
dy = xy[1] - xytext[1]
shrink = arrowprops['shrink']
if shrink > 0:
sx = dx * shrink
sy = dy * shrink
x0 = xytext[0] + sx
y0 = xytext[1] + sy
dx = dx - sx * 2
dy = dy - sy * 2
graphic = GraphicFactory.createArrowLine(x0, y0, dx, dy, alb)
self.add_graphic(graphic)
self._axes.setAutoExtent()
return ctext, graphic
def axhline(self, y=0, xmin=0, xmax=1, **kwargs):
"""
Add a horizontal line across the axis.
Parameters
----------
y : float, default: 0
y position in data coordinates of the horizontal line.
xmin : float, default: 0
Should be between 0 and 1, 0 being the far left of the plot, 1 the
far right of the plot.
xmax : float, default: 1
Should be between 0 and 1, 0 being the far left of the plot, 1 the
far right of the plot.
Returns
-------
`~matplotlib.lines.Line2D`
"""
pass
def fill(self, x, y, color=None, **kwargs):
"""
Plot filled polygons.
- To plot one region, specify x and y as vectors.
- To plot multiple regions, specify x and y as matrices where each column corresponds to a polygon.
:param x: (*array_like*) X coordinates for each vertex.
:param y: (*array_like*) Y coordinates for each vertex.
:param color: (*Color*) Fill color.
:return: Filled polygons
"""
if color is not None:
kwargs['facecolor'] = color
lbreak, isunique = plotutil.getlegendbreak('polygon', **kwargs)
x = plotutil.getplotdata(x)
y = plotutil.getplotdata(y)
graphics = GraphicFactory.createPolygons(x, y, lbreak)
zorder = kwargs.pop('zorder', None)
self.add_graphic(graphics, zorder=zorder)
self._axes.setAutoExtent()
return graphics
def patch(self, x, y=None, **kwargs):
"""
Create one or more filled polygons.
:param x: (*array_like*) X coordinates for each vertex. X should be PolygonShape if y
is None.
:param y: (*array_like*) Y coordinates for each vertex.
"""
lbreak, isunique = plotutil.getlegendbreak('polygon', **kwargs)
if y is None:
graphics = Graphic(x, lbreak)
else:
x = plotutil.getplotdata(x)
y = plotutil.getplotdata(y)
graphics = GraphicFactory.createPolygons(x, y, lbreak)
zorder = kwargs.pop('zorder', None)
self.add_graphic(graphics, zorder=zorder)
self._axes.setAutoExtent()
return graphics
def rectangle(self, position, curvature=None, **kwargs):
"""
Create one or more filled polygons.
:param position: (*list*) Position of the rectangle [x, y, width, height].
:param curvature: (*list*) Curvature of the rectangle [x, y]. Default is None.
"""
lbreak, isunique = plotutil.getlegendbreak('polygon', **kwargs)
if isinstance(curvature, (int, float)):
curvature = [curvature, curvature]
graphic = GraphicFactory.createRectangle(position, curvature, lbreak)
zorder = kwargs.pop('zorder', None)
self.add_graphic(graphic, zorder=zorder)
self._axes.setAutoExtent()
return graphic
def fill_between(self, x, y1, y2=0, where=None, **kwargs):
"""
Make filled polygons between two curves (y1 and y2) where ``where==True``.
:param x: (*array_like*) An N-length array of the x data.
:param y1: (*array_like*) An N-length array (or scalar) of the y data.
:param y2: (*array_like*) An N-length array (or scalar) of the y data.
:param where: (*array_like*) If None, default to fill between everywhere. If not None, it is an
N-length boolean array and the fill will only happen over the regions where ``where==True``.
"""
# Add data series
label = kwargs.pop('label', 'S_0')
dn = len(x)
xdata = plotutil.getplotdata(x)
if isinstance(y1, (int, long, float)):
yy = []
for i in range(dn):
yy.append(y1)
y1 = np.array(yy)._array
else:
y1 = plotutil.getplotdata(y1)
if isinstance(y2, (int, long, float)):
yy = []
for i in range(dn):
yy.append(y2)
y2 = np.array(yy)._array
else:
y2 = plotutil.getplotdata(y2)
if not where is None:
if isinstance(where, (tuple, list)):
where = np.array(where)
where = where.asarray()
# Set plot data styles
# if not 'fill' in kwargs:
# kwargs['fill'] = True
# if not 'edge' in kwargs:
# kwargs['edge'] = False
pb, isunique = plotutil.getlegendbreak('polygon', **kwargs)
pb.setCaption(label)
# Create graphics
graphics = GraphicFactory.createFillBetweenPolygons(xdata, y1, y2, where, pb)
zorder = kwargs.pop('zorder', None)
self.add_graphic(graphics, zorder=zorder)
self._axes.setAutoExtent()
return pb
def fill_betweenx(self, y, x1, x2=0, where=None, **kwargs):
"""
Make filled polygons between two curves (x1 and x2) where ``where==True``.
:param y: (*array_like*) An N-length array of the y data.
:param x1: (*array_like*) An N-length array (or scalar) of the x data.
:param x2: (*array_like*) An N-length array (or scalar) of the x data.
:param where: (*array_like*) If None, default to fill between everywhere. If not None, it is an
N-length boolean array and the fill will only happen over the regions where ``where==True``.
"""
# Add data series
label = kwargs.pop('label', 'S_0')
dn = len(y)
ydata = plotutil.getplotdata(y)
if isinstance(x1, (int, long, float)):
xx = []
for i in range(dn):
xx.append(x1)
x1 = np.array(xx)._array
else:
x1 = plotutil.getplotdata(x1)
if isinstance(x2, (int, long, float)):
xx = []
for i in range(dn):
xx.append(x2)
x2 = np.array(xx)._array
else:
x2 = plotutil.getplotdata(x2)
if not where is None:
if isinstance(where, (tuple, list)):
where = np.array(where)
where = where.asarray()
# Set plot data styles
# if not 'fill' in kwargs:
# kwargs['fill'] = True
# if not 'edge' in kwargs:
# kwargs['edge'] = False
pb, isunique = plotutil.getlegendbreak('polygon', **kwargs)
pb.setCaption(label)
# Create graphics
graphics = GraphicFactory.createFillBetweenPolygonsX(ydata, x1, x2, where, pb)
zorder = kwargs.pop('zorder', None)
self.add_graphic(graphics, zorder=zorder)
self._axes.setAutoExtent()
return pb
def pie(self, x, explode=None, labels=None, colors=None, autopct=None, pctdistance=0.6, shadow=False,
labeldistance=1.1, startangle=0, radius=None, wedgeprops=None, **kwargs):
"""
Plot a pie chart.
Make a pie chart of array *x*. The fraction 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. The wedges are plotted counterclockwise, by default starting from the x-axis.
:param explode: (*None | len(x)sequence) If not *None*, is a ``len(x)`` array which specifies
the fraction of the radius with which to offset each wedge.
:param labels: (*None | len(x) sequence of colors*] A sequence of strings providing the labels
for each wedge.
:param colors: (*None | color sequence*) A sequence of color args through which the pie chart
will cycle.
:param autopct: (*None | format string | format function) If not *None*, is a string or function
used to label the wedges with their numeric value. The label will be placed inside the wedge.
If it is a format string, the label will be ``fmt%pct``. If it is a function, it will be called.
:param pctdistance: (*float*) The ratio between the center of each pie slice and the start of the
text generated by *autopct*. Ignored if autopct is *None*; default is 0.6.
:param labeldistance: (*float*) The ratial distance at which the pie labels are drawn.
:param shadow: (*boolean*) Draw a shadow beneath the pie.
:param startangle: (*float*) If not *0*, rotates the start of the pie chart by *angle* degrees
counterclockwise from the x-axis.
:param radius: (*float*) The radius of the pie, if *radius* is *None* it will be set to 1.
:param wedgeprops: (*dict*) Dict of arguments passed to the wedge objects making the pie.
:param fontname: (*string*) Font name. Default is ``Arial`` .
:param fontsize: (*int*) Font size. Default is ``14`` .
:returns: (*tuple*) Patches and texts.
"""
n = len(x)
x = plotutil.getplotdata(x)
if colors is None:
cmap = kwargs.pop('cmap', 'matlab_jet')
colors = plotutil.makecolors(n, cmap=cmap)
else:
colors = plotutil.getcolors(colors)
fontname = kwargs.pop('fontname', 'Arial')
fontsize = kwargs.pop('fontsize', 14)
bold = kwargs.pop('bold', False)
fontcolor = kwargs.pop('fontcolor', 'black')
if bold:
font = Font(fontname, Font.BOLD, fontsize)
else:
font = Font(fontname, Font.PLAIN, fontsize)
fontcolor = plotutil.getcolor(fontcolor)
if radius is None:
radius = 1
if wedgeprops is None:
wedgeprops = HashMap()
else:
jmap = HashMap()
for key in wedgeprops.keys():
value = wedgeprops[key]
if key == 'edgecolor':
if value is None:
jmap['drawedge'] = False
else:
value = plotutil.getcolor(value)
jmap[key] = value
else:
jmap[key] = value
wedgeprops = jmap
# Create graphics
graphics = GraphicFactory.createPieArcs(x, colors, labels, startangle, explode, font, fontcolor, \
labeldistance, autopct, pctdistance, radius, wedgeprops)
for graphic in graphics:
self.add_graphic(graphic)
self._axes.setAutoExtent()
self._axes.setAspectType(AspectType.EQUAL)
self._axes.getAxis(Location.BOTTOM).setVisible(False)
self._axes.getAxis(Location.LEFT).setVisible(False)
self._axes.getAxis(Location.TOP).setVisible(False)
self._axes.getAxis(Location.RIGHT).setVisible(False)
self._axes.setClip(False)
return tuple(graphics)
def boxplot(self, x, sym=None, vert=True, positions=None, widths=None, color=None, showcaps=True, showfliers=True,
showmeans=False, \
showmedians=True, meanline=False, medianline=True, boxprops=None, medianprops=None, meanprops=None,
whiskerprops=None, capprops=None, flierprops=None):
"""
Make a box and whisker plot.
Make a box and whisker plot for each column of x or each vector in sequence x. The box extends from lower
to upper quartile values of the data, with a line at the median. The whiskers extend from the box to show
the range of the data. Flier points are those past the end of the whiskers.
:param x: (*Array or a sequence of vectors*) The input data.
:param sym: (*string*) The default symbol for flier points. Enter an empty string ('') if you dont
want to show fliers. If None, then the fliers default to b+ If you want more control use the
flierprops kwarg.
:param vert: (*boolean*) If True, draws vertical boxes (default). If False, draw horizontal boxes.
:param positions: (*array_like*) Sets the positions of the boxes. The ticks and limits are automatically
set to match the positions. Defaults to range(1, N+1) where N is the number of boxes to be drawn.
:param widths: (*scalar or array_like*) Sets the width of each box either with a scalar or a sequence.
The default is 0.5, or 0.15*(distance between extreme positions), if that is smaller.
:param color: (*Color*) Color for all parts of the box plot. Defaul is None.
:param showcaps: (*boolean*) Show the caps on the ends of whiskers. Default is ``True``.
:param showfliers: (*boolean*) Show the outliers beyond the caps. Defaul is ``True``.
:param showmeans: (*boolean*) Default is ``False``. Show the mean or not.
:param showmedians: (*boolean*) Default is ``True``. Show the median or not.
:param meanline: (*boolean*) Default is ``False``. If ``True`` (and showmeans is ``True``), will try to render
the mean as a line spanning. Otherwise, means will be shown as points.
:param medianline: (*boolean*) Default is ``True``. If ``True`` (and showmedians is ``True``), will try to render
the median as a line spanning. Otherwise, medians will be shown as points.
:param boxprops: (*dict*) Specifies the style of the box.
:param medianprops: (*dict*) Specifies the style of the median.
:param meanprops: (*dict*) Specifies the style of the mean.
:param whiskerprops: (*dict*) Specifies the style of the whiskers.
:param capprops: (*dict*) Specifies the style of the caps.
:param flierprops: (*dict*) Specifies the style of the fliers.
"""
if isinstance(x, list):
x1 = []
for a in x:
x1.append(plotutil.getplotdata(a))
x = x1
else:
x = plotutil.getplotdata(x)
x = [x]
if not positions is None:
if isinstance(positions, (NDArray, DimArray)):
positions = positions.tolist()
if not widths is None:
if isinstance(widths, (int, float)):
nwidths = []
for i in range(len(x)):
nwidths.append(widths)
widths = nwidths
elif isinstance(widths, (NDArray, DimArray)):
widths = widths.tolist()
# Get box plot properties
if not color is None:
color = plotutil.getcolor(color)
if not sym is None:
sym = plotutil.getplotstyle(sym, '')
sym.setDrawFill(False)
if not color is None:
sym.setColor(color)
sym.setOutlineColor(color)
if boxprops is None:
boxprops = PolygonBreak()
boxprops.setDrawFill(False)
boxprops.setOutlineColor(color is None and Color.blue or color)
else:
if not boxprops.has_key('facecolor'):
boxprops['facecolor'] = None
boxprops = plotutil.getlegendbreak('polygon', **boxprops)[0]
if medianline:
if medianprops is None:
medianprops = PolylineBreak()
medianprops.setColor(color is None and Color.red or color)
else:
medianprops = plotutil.getlegendbreak('line', **medianprops)[0]
else:
if medianprops is None:
medianprops = PointBreak()
medianprops.setColor(color is None and Color.blue or color)
else:
medianprops = plotutil.getlegendbreak('point', **medianprops)[0]
if whiskerprops is None:
whiskerprops = PolylineBreak()
whiskerprops.setColor(color is None and Color.black or color)
whiskerprops.setStyle(LineStyles.DASH)
else:
whiskerprops = plotutil.getlegendbreak('line', **whiskerprops)[0]
if capprops is None:
capprops = PolylineBreak()
capprops.setColor(color is None and Color.black or color)
else:
capprops = plotutil.getlegendbreak('line', **capprops)[0]
if meanline:
if not meanprops is None:
meanprops = plotutil.getlegendbreak('line', **meanprops)[0]
else:
meanprops = PolylineBreak()
meanprops.setColor(color is None and Color.black or color)
else:
if meanprops is None:
meanprops = PointBreak()
meanprops.setStyle(PointStyle.SQUARE)
meanprops.setColor(color is None and Color.red or color)
meanprops.setOutlineColor(color is None and Color.black or color)
else:
meanprops = plotutil.getlegendbreak('point', **meanprops)[0]
if not flierprops is None:
flierprops = plotutil.getlegendbreak('point', **flierprops)[0]
else:
flierprops = sym
if flierprops is None:
flierprops = PointBreak()
flierprops.setColor(color is None and Color.red or color)
flierprops.setStyle(PointStyle.PLUS)
# Create graphics
if vert:
graphics = GraphicFactory.createBox(x, positions, widths, showcaps, showfliers, showmeans, \
showmedians, boxprops, medianprops, whiskerprops, capprops, meanprops,
flierprops)
else:
graphics = GraphicFactory.createHBox(x, positions, widths, showcaps, showfliers, showmeans, \
showmedians, boxprops, medianprops, whiskerprops, capprops, meanprops,
flierprops)
self.add_graphic(graphics)
self._axes.setAutoExtent()
return graphics
def violinplot(self, dataset, positions=None, widths=0.5, boxwidth=0.01, boxprops=None,
whiskerprops=None, **kwargs):
"""
Make a violin plot.
:param dataset: (*Array or a sequence of vectors*) The input data.
:param positions: (*array_like*) Sets the positions of the violins. The ticks and limits are automatically
set to match the positions. Defaults to range(1, N+1) where N is the number of violins to be drawn.
:param widths: (*scalar or array_like*) Sets the width of each box either with a scalar or a sequence.
The default is 0.5, or 0.15*(distance between extreme positions), if that is smaller.
:param boxwidth: (*float*) box width.
:param boxprops: (*dict*) Specifies the style of the box.
:param whiskerprops: (*dict*) Specifies the style of the whiskers.
:returns: Violin graphics.
"""
if isinstance(dataset, NDArray):
dataset = [dataset]
n = len(dataset)
if positions is None:
positions = np.arange(1, n + 1)
graphics = []
pdfs = []
xx = []
max = 0
for data, position in zip(dataset, positions):
if data.contains_nan():
data = np.delnan(data)
kde = np.stats.GaussianKDE(data)
x = np.linspace(data.min(), data.max(), 100)
pdf = kde.evaluate(x)
pdfs.append(pdf)
xx.append(x)
if pdf.max() > max:
max = pdf.max()
if boxprops is None:
boxprops = dict(color='k', edgecolor=None)
if whiskerprops is None:
whiskerprops = dict(color='k')
if not kwargs.has_key('color'):
kwargs['color'] = 'c'
if not kwargs.has_key('edgecolor'):
kwargs['edgecolor'] = 'b'
ratio = widths / max
for data, position, pdf, x in zip(dataset, positions, pdfs, xx):
pdf = pdf * ratio
self.fill_betweenx(x, position - pdf, position + pdf, **kwargs)
ggs = self.boxplot(data, positions=[position], widths=boxwidth, showfliers=False, \
showcaps=False, medianline=False, boxprops=boxprops, \
whiskerprops=whiskerprops, medianprops=dict(color='w', edgecolor=None))
graphics.extend(ggs)
return graphics
def taylor_diagram(self, stddev, correlation, std_max=1.65, labels=None, ref_std=1., colors=None,
**kwargs):
"""
Create Taylor diagram.
:param stddev: (*array*) Standard deviation.
:param correlation: (*array*) Pattern correlations.
:param ref_std: (*float*) Reference standard deviation. Default value is `1.`.
:param std_max: (*float*) Maximum standard deviation. Default value is `1.651`.
:param labels: (*list of string*) Data labels.
:param colors: (*list of color*) Data points colors.
:param markers: (*list of marker string*) Data points markers.
:param sizes: (*list of int*) Data points sizes.
:param std_max_axis_props: (*dict*) Property of the maximum standard deviation axis line.
:param corr_tick_props: (*dict*) Property of the correlation tick lines.
:param corr_tick_label_props: (*dict*) Property of the correlation tick labels.
:param corr_label_props: (*dict*) Property of the correlation label.
:returns: Axes and Taylor graphic.
"""
# Set axes
self.set_aspect('equal')
self.set_clip(False)
self.xaxis(location='top', visible=False)
self.yaxis(location='right', visible=False)
# plot RMS circle
th = np.linspace(0, np.pi, 200)
xunit = np.cos(th)
yunit = np.sin(th)
tickrms = np.arange(0.25, ref_std + 0.2, 0.25)
radius = np.sqrt(ref_std ** 2 + std_max ** 2 -
2 * ref_std * std_max * xunit)
for iradius in tickrms:
phi = th[np.where(radius >= iradius)]
if len(phi) > 0:
phi = phi[0]
ig = np.where(iradius * np.cos(th) + ref_std <=
std_max * np.cos(phi))
self.plot(xunit[ig] * iradius + ref_std, yunit[ig] * iradius, color='gray')
# plot stddev circle
self.set_xlim(0, std_max)
self.set_ylim(0, std_max)
std_ticks = np.arange(0, std_max, 0.25)
self.set_xticks(std_ticks)
xtick_labels = []
for std_tick in std_ticks:
if std_tick == ref_std:
xtick_labels.append('REF')
else:
xtick_labels.append(str(std_tick))
self.set_xticklabels(xtick_labels)
self.set_yticks(std_ticks)
th = np.linspace(0, np.pi * 0.5, 200)
xunit = np.cos(th)
yunit = np.sin(th)
xticks = self.get_xticks()
for i in xticks:
self.plot(xunit * i, yunit * i, color='gray', linestyle='--')
std_max_axis_props = kwargs.pop('std_max_axis_props', dict(color='k'))
self.plot(xunit * std_max, yunit * std_max, **std_max_axis_props)
# plot correlation lines
values = np.arange(0., 1., 0.1)
values = values.join(np.array([0.95, 0.99, 1.0]), 0)
corr_tick_props = kwargs.pop('corr_tick_props', dict(color='k'))
corr_tick_label_props = kwargs.pop('corr_tick_label_props', dict(yalign='center'))
if not corr_tick_label_props.has_key('yalign'):
corr_tick_label_props['yalign'] = 'center'
corr_label_props = kwargs.pop('corr_label_props', dict(xalign='center', yalign='bottom'))
if not corr_label_props.has_key('xalign'):
corr_label_props['xalign'] = 'center'
if not corr_label_props.has_key('yalign'):
corr_label_props['yalign'] = 'bottom'
for t in values:
theta = np.acos(t)
x = np.cos(theta) * std_max
y = np.sin(theta) * std_max
if 0 < t < 1:
if t == 0.6 or t == 0.9:
self.plot([0, x], [0, y], color='gray', linestyle=':')
self.plot([x * 0.98, x], [y * 0.98, y], **corr_tick_props)
x = x * 1.02
y = y * 1.02
self.text(x, y, str(t), rotation=np.degrees(theta), **corr_tick_label_props)
if t == 0.7:
self.text(x * 1.1, y * 1.1, 'Correlation', rotation=np.degrees(theta) - 90,
**corr_label_props)
values = np.arange(0.05, 0.9, 0.1)
values = values.join(np.array([0.91, 0.92, 0.93, 0.94, 0.96, 0.97, 0.98]), 0)
for t in values:
theta = np.acos(t)
x = np.cos(theta) * std_max
y = np.sin(theta) * std_max
self.plot([x * 0.99, x], [y * 0.99, y], **corr_tick_props)
# plot data
stddev = np.atleast_2d(stddev)
correlation = np.atleast_2d(correlation)
if not labels is None:
labels = np.atleast_2d(labels)
ncase = stddev.shape[0]
if colors is None:
cmap = kwargs.pop('cmap', 'matlab_jet')
colors = plotutil.makecolors(ncase, cmap)
gg = []
markers = kwargs.pop('markers', [None] * ncase)
sizes = kwargs.pop('sizes', [6] * ncase)
for i in range(ncase):
rho = stddev[i]
theta = np.acos(correlation[i])
x = np.cos(theta) * rho
y = np.sin(theta) * rho
gg.append(self.scatter(x, y, edge=False, c=colors[i], s=sizes[i], marker=markers[i]))
if labels is None:
lbs = []
for j in range(len(rho)):
lbs.append(str(j + 1))
else:
lbs = labels[i]
for xx, yy, label in zip(x, y, lbs):
self.text(xx, yy, label, color=colors[i], xalign='center', yalign='bottom', yshift=-sizes[i])
self.set_xlim(0, std_max)
self.set_ylim(0, std_max)
xl = kwargs.pop('xlabel', None)
if not xl is None:
self.set_xlabel(xl)
yl = kwargs.pop('ylabel', 'Standard Deviation (Normalized)')
self.set_ylabel(yl)
tt = kwargs.pop('title', None)
if not tt is None:
self.set_title(tt)
self.set_title(' ', loc='left')
return self, gg
def barbs(self, *args, **kwargs):
"""
Plot a 2-D field of barbs.
:param x: (*array_like*) Optional. X coordinate array.
:param y: (*array_like*) Optional. Y coordinate array.
:param u: (*array_like*) U component of the arrow vectors (wind field) or wind direction.
:param v: (*array_like*) V component of the arrow vectors (wind field) or wind speed.
:param z: (*array_like*) Optional, 2-D z value array.
:param levs: (*array_like*) Optional. A list of floating point numbers indicating the level
barbs to draw, in increasing order.
:param cmap: (*string*) Color map string.
:param fill_value: (*float*) Fill_value. Default is ``-9999.0``.
:param isuv: (*boolean*) Is U/V or direction/speed data array pairs. Default is True.
:param size: (*float*) Base size of the arrows.
:param order: (*int*) Z-order of created layer for display.
:returns: Barbs graphics.
"""
ls = kwargs.pop('symbolspec', None)
cmap = plotutil.getcolormap(**kwargs)
fill_value = kwargs.pop('fill_value', -9999.0)
order = kwargs.pop('order', None)
isuv = kwargs.pop('isuv', True)
n = len(args)
iscolor = False
cdata = None
xaxistype = None
if n <= 3 or (n == 4 and isinstance(args[3], int)):
x = args[0].dimvalue(1)
y = args[0].dimvalue(0)
x, y = np.meshgrid(x, y)
u = args[0]
v = args[1]
if args[0].islondim(1):
xaxistype = 'lon'
elif args[0].islatdim(1):
xaxistype = 'lat'
elif args[0].istimedim(1):
xaxistype = 'time'
args = args[2:]
if len(args) > 0:
cdata = args[0]
iscolor = True
args = args[1:]
elif n <= 6:
x = args[0]
y = args[1]
u = args[2]
v = args[3]
args = args[4:]
if len(args) > 0:
cdata = args[0]
iscolor = True
args = args[1:]
x = plotutil.getplotdata(x)
y = plotutil.getplotdata(y)
u = plotutil.getplotdata(u)
v = plotutil.getplotdata(v)
if ls is None:
if iscolor:
if len(args) > 0:
cn = args[0]
ls = LegendManage.createLegendScheme(cdata.min(), cdata.max(), cn, cmap)
else:
levs = kwargs.pop('levs', None)
if levs is None:
ls = LegendManage.createLegendScheme(cdata.min(), cdata.max(), cmap)
else:
if isinstance(levs, NDArray):
levs = levs.aslist()
ls = LegendManage.createLegendScheme(cdata.min(), cdata.max(), levs, cmap)
else:
if cmap.getColorCount() == 1:
c = cmap.getColor(0)
else:
c = Color.black
ls = LegendManage.createSingleSymbolLegendScheme(ShapeTypes.POINT, c, 10)
ls = plotutil.setlegendscheme_point(ls, **kwargs)
if not cdata is None:
cdata = plotutil.getplotdata(cdata)
igraphic = GraphicFactory.createBarbs(x, y, u, v, cdata, ls, isuv)
if not xaxistype is None:
self.set_xaxis_type(xaxistype)
self._axes.updateDrawExtent()
zorder = kwargs.pop('zorder', None)
self.add_graphic(igraphic, zorder=zorder)
self._axes.setAutoExtent()
return igraphic
def quiver(self, *args, **kwargs):
"""
Plot a 2-D field of arrows.
:param x: (*array_like*) Optional. X coordinate array.
:param y: (*array_like*) Optional. Y coordinate array.
:param u: (*array_like*) U component of the arrow vectors (wind field) or wind direction.
:param v: (*array_like*) V component of the arrow vectors (wind field) or wind speed.
:param z: (*array_like*) Optional, 2-D z value array.
:param levs: (*array_like*) Optional. A list of floating point numbers indicating the level
vectors to draw, in increasing order.
:param cmap: (*string*) Color map string.
:param fill_value: (*float*) Fill_value. Default is ``-9999.0``.
:param isuv: (*boolean*) Is U/V or direction/speed data array pairs. Default is True.
:param size: (*float*) Base size of the arrows.
:param overhang: (*float*) fraction that the arrow is swept back (0 overhang means
triangular shape). Can be negative or greater than one.
:param zorder: (*int*) Z-order of created layer for display.
:returns: Quiver graphics.
"""
ls = kwargs.pop('symbolspec', None)
cmap = plotutil.getcolormap(**kwargs)
fill_value = kwargs.pop('fill_value', -9999.0)
zorder = kwargs.pop('zorder', None)
isuv = kwargs.pop('isuv', True)
n = len(args)
iscolor = False
cdata = None
xaxistype = None
if n < 4 or (n == 4 and isinstance(args[3], int)):
u = args[0]
v = args[1]
if isinstance(u, DimArray):
x = u.dimvalue(1)
y = u.dimvalue(0)
# if args[0].islondim(1):
# xaxistype = 'lon'
# elif args[0].islatdim(1):
# xaxistype = 'lat'
# elif args[0].istimedim(1):
# xaxistype = 'time'
else:
x = np.arange(u.shape[1])
y = np.arange(u.shape[0])
x, y = np.meshgrid(x, y)
args = args[2:]
if len(args) > 0:
cdata = args[0]
iscolor = True
args = args[1:]
elif n <= 6:
x = args[0]
y = args[1]
u = args[2]
v = args[3]
args = args[4:]
if len(args) > 0:
cdata = args[0]
iscolor = True
args = args[1:]
x = plotutil.getplotdata(x)
y = plotutil.getplotdata(y)
u = plotutil.getplotdata(u)
v = plotutil.getplotdata(v)
if ls is None:
if iscolor:
if len(args) > 0:
cn = args[0]
ls = LegendManage.createLegendScheme(cdata.min(), cdata.max(), cn, cmap)
else:
levs = kwargs.pop('levs', None)
if levs is None:
ls = LegendManage.createLegendScheme(cdata.min(), cdata.max(), cmap)
else:
if isinstance(levs, NDArray):
levs = levs.tolist()
ls = LegendManage.createLegendScheme(cdata.min(), cdata.max(), levs, cmap)
else:
if cmap.getColorCount() == 1:
c = cmap.getColor(0)
else:
c = Color.black
ls = LegendManage.createSingleSymbolLegendScheme(ShapeTypes.POINT, c, 10)
ls = plotutil.setlegendscheme_arrow(ls, **kwargs)
if not cdata is None:
cdata = plotutil.getplotdata(cdata)
igraphic = GraphicFactory.createArrows(x, y, u, v, cdata, ls, isuv)
if not xaxistype is None:
self.set_xaxis_type(xaxistype)
self._axes.updateDrawExtent()
zorder = kwargs.pop('zorder', None)
self.add_graphic(igraphic, zorder=zorder)
self._axes.setAutoExtent()
return igraphic
def quiverkey(self, *args, **kwargs):
"""
Add a key to a quiver plot.
:param Q: (*MILayer or GraphicCollection*) The quiver layer instance returned by a call to quiver/quiverm.
:param X: (*float*) The location x of the key.
:param Y: (*float*) The location y of the key.
:param U: (*float*) The length of the key.
:param label: (*string*) A string with the length and units of the key.
:param coordinates=['axes'|'figure'|'data']: (*string*) Default: 'axes'. Coordinate system and units for
*X, Y*. 'axes' and 'figure' are normalized coordinate system with 0,0 in the lower left and
1,1 in the upper right, 'data' are the axes data coordinates (used for the locations of the
vectors in the quiver plot itself).
:param color: (*Color*) Overrides face and edge colors from Q.
:param labelpos=['N'|'S'|'E'|'W']: (*string*) Position the label above, below, to the right, to
the left of the arrow, respectively.
:param labelsep: (*float*) Distance in pixel between the arrow and the label. Default is 5.
:param labelcolor: (*Color*) Label color. Default to default is black.
:param fontname: (*string*) Label font name. Default is ``Arial`` .
:param fontsize: (*int*) Label font size. Default is ``12`` .
:param bold: (*boolean*) Is bold font or not. Default is ``False`` .
:param fontproperties: (*dict*) A dictionary with keyword arguments accepted by the FontProperties
initializer: *family, style, variant, size, weight*.
"""
wa = ChartWindArrow()
Q = args[0]
if isinstance(Q, MILayer):
wa.setLayer(Q._layer)
else:
wa.setLayer(Q)
x = args[1]
y = args[2]
wa.setX(x)
wa.setY(y)
u = args[3]
wa.setLength(u)
if len(args) == 5:
label = args[4]
wa.setLabel(label)
coordinates = kwargs.pop('coordinates', 'axes')
wa.setCoordinates(coordinates)
arrowbreak, isunique = plotutil.getlegendbreak('point', **kwargs)
arrowbreak = plotutil.point2arrow(arrowbreak, **kwargs)
wa.setArrowBreak(arrowbreak)
lcobj = kwargs.pop('labelcolor', 'k')
lcolor = plotutil.getcolor(lcobj)
wa.setLabelColor(lcolor)
fontname = kwargs.pop('fontname', 'Arial')
fontsize = kwargs.pop('fontsize', 12)
bold = kwargs.pop('bold', False)
if bold:
font = Font(fontname, Font.BOLD, fontsize)
else:
font = Font(fontname, Font.PLAIN, fontsize)
wa.setFont(font)
labelsep = kwargs.pop('labelsep', None)
if not labelsep is None:
wa.setLabelSep(labelsep)
bbox = kwargs.pop('bbox', None)
if not bbox is None:
fill = bbox.pop('fill', None)
if not fill is None:
wa.setFill(fill)
facecolor = bbox.pop('facecolor', None)
if not facecolor is None:
facecolor = plotutil.getcolor(facecolor)
wa.setFill(True)
wa.setBackground(facecolor)
edge = bbox.pop('edge', None)
if not edge is None:
wa.setDrawNeatline(edge)
edgecolor = bbox.pop('edgecolor', None)
if not edgecolor is None:
edgecolor = plotutil.getcolor(edgecolor)
wa.setNeatlineColor(edgecolor)
wa.setDrawNeatline(True)
linewidth = bbox.pop('linewidth', None)
if not linewidth is None:
wa.setNeatlineSize(linewidth)
wa.setDrawNeatline(True)
self._axes.setWindArrow(wa)
def streamplot(self, *args, **kwargs):
"""
Plot 2D streamline.
:param x: (*array_like*) Optional. X coordinate array.
:param y: (*array_like*) Optional. Y coordinate array.
:param u: (*array_like*) U component of the arrow vectors (wind field) or wind direction.
:param v: (*array_like*) V component of the arrow vectors (wind field) or wind speed.
:param z: (*array_like*) Optional, 2-D z value array.
:param color: (*Color*) Streamline color.
:param fill_value: (*float*) Fill_value. Default is ``-9999.0``.
:param isuv: (*boolean*) Is U/V or direction/speed data array pairs. Default is True.
:param density: (*int*) Streamline density. Default is 4.
:param zorder: (*int*) Z-order of streamline graphic for display.
:returns: (*graphics*) 2D streamline graphics.
"""
isuv = kwargs.pop('isuv', True)
density = kwargs.pop('density', 4)
n = len(args)
if n < 4:
u = args[0]
v = args[1]
y = u.dimvalue(0)
x = u.dimvalue(1)
else:
x = args[0]
y = args[1]
u = args[2]
v = args[3]
if not kwargs.has_key('headwidth'):
kwargs['headwidth'] = 8
if not kwargs.has_key('overhang'):
kwargs['overhang'] = 0.5
cdata = kwargs.pop('cdata', None)
if cdata is None:
alb, isunique = plotutil.getlegendbreak('line', **kwargs)
alb = plotutil.line2stream(alb, **kwargs)
igraphic = GraphicFactory.createStreamlines(x._array, y._array, u._array, v._array,
density, alb, isuv)
else:
if isinstance(cdata, (list, tuple)):
cdata = np.array(cdata)
levels = kwargs.pop('levels', None)
if levels is None:
cnum = kwargs.pop('cnum', None)
if cnum is None:
ls = plotutil.getlegendscheme([], cdata.min(), cdata.max(), **kwargs)
else:
ls = plotutil.getlegendscheme([cnum], cdata.min(), cdata.max(), **kwargs)
else:
ls = plotutil.getlegendscheme([levels], cdata.min(), cdata.max(), **kwargs)
ls = plotutil.setlegendscheme_line(ls, **kwargs)
for i in range(ls.getBreakNum()):
lb = plotutil.line2stream(ls.getLegendBreak(i), **kwargs)
ls.setLegendBreak(i, lb)
igraphic = GraphicFactory.createStreamlines(x._array, y._array, u._array, v._array,
cdata._array, density, ls, isuv)
zorder = kwargs.pop('zorder', None)
self.add_graphic(igraphic, zorder=zorder)
self._axes.setAutoExtent()
return igraphic
def get_legend(self):
"""
Get legend of the axes.
:return: Legend
"""
return self._axes.getLegendScheme()
def legend(self, *args, **kwargs):
"""
Places a legend on the axes.
:param breaks: (*ColorBreak*) Legend breaks (optional).
:param labels: (*list of string*) Legend labels (optional).
:param orientation: (*string*) Legend orientation: ``vertical`` or ``horizontal``.
:param loc: (*string*) The location of the legend, including: 'upper right', 'upper left',
'lower left', 'lower right', 'right', 'ceter left', 'center right', lower center',
'upper center', 'center' and 'custom'. Default is 'upper right'.
:param x: (*float*) Location x in normalized (0, 1) units when ``loc=custom`` .
:param y: (*float*) Location y in normalized (0, 1) units when ``loc=custom`` .
:param frameon: (*boolean*) Control whether a frame should be drawn around the legend. Default
is True.
:param facecolor: (*None or color*) Control the legends background color. Default is None which
set not draw background.
:param fontname: (*string*) Label font name. Default is ``Arial`` .
:param fontsize: (*int*) Label font size. Default is ``14`` .
:param labelcolor: (*color*) Label string color. Defaul is ``black``.
:param bold: (*boolean*) Is bold font or not. Default is ``False`` .
:param title: (*string*) Title string.
:param titlefontname: (*string*) Title font name.
:param titlefontsize: (*int*) Title font size.
:param titlecolor: (*color*) Title color. Default is ``black`` .
:param breakspace: (*float*) Break space. Default is `3`.
:param titlespace: (*float*) Title space. Default is `5`.
:param markerscale: (*float*) Marker symbol scale.
:param markerwidth: (*float*) Marker symbol width.
:param markerheight: (*float*) Marker symbol height.
:param ncol: (*float*) Column number of the legend.
:param xshift: (*float*) X shift.
:param yshift: (*float*) Y shift.
:returns: (*ChartLegend*) The chart legend.
"""
newlegend = kwargs.pop('newlegend', True)
ols = self._axes.getLegendScheme()
if newlegend:
clegend = ChartLegend(ols)
else:
clegend = self._axes.getLegend()
ls = kwargs.pop('legend', None)
if len(args) > 0:
if isinstance(args[0], MILayer):
ls = args[0].legend()
args = args[1:]
elif isinstance(args[0], LegendScheme):
ls = args[0]
args = args[1:]
elif isinstance(args[0], GraphicCollection):
if not args[0].isSingleLegend():
ls = args[0].getLegendScheme()
args = args[1:]
if ls is None:
if len(args) > 0:
lbs = []
for lb in args[0]:
if isinstance(lb, Graphic):
lbs.append(lb.getLegend().clone())
elif isinstance(lb, MILayer):
lbs.extend(lb.legend().getLegendBreaks())
else:
lbs.append(lb)
if len(args) == 2:
labels = args[1]
for i in range(0, len(lbs)):
lbs[i].setCaption(labels[i])
if isinstance(lbs[0], basestring):
clegend.setTickCaptions(lbs)
else:
ls = LegendScheme()
for lb in lbs:
ls.addLegendBreak(lb)
if len(lbs) == 1:
ls.setLegendType(LegendType.SINGLE_SYMBOL)
elif lbs[0].getStartValue() == lbs[1].getEndValue():
ls.setLegendType(LegendType.UNIQUE_VALUE)
else:
ls.setLegendType(LegendType.GRADUATED_COLOR)
if clegend is None:
clegend = ChartLegend(ls)
self._axes.setLegend(clegend)
else:
clegend.setLegendScheme(ls)
else:
if len(args) > 0:
labels = args[0]
for i in range(len(labels)):
if i < ls.getBreakNum():
ls.getLegendBreak(i).setCaption(labels[i])
if clegend is None:
clegend = ChartLegend(ls)
self._axes.setLegend(clegend)
else:
clegend.setLegendScheme(ls)
loc = kwargs.pop('loc', 'upper right')
lp = LegendPosition.fromString(loc)
clegend.setPosition(lp)
if lp == LegendPosition.CUSTOM:
x = kwargs.pop('x', 0)
y = kwargs.pop('y', 0)
clegend.setX(x)
clegend.setY(y)
orien = 'vertical'
if lp == LegendPosition.UPPER_CENTER_OUTSIDE or lp == LegendPosition.LOWER_CENTER_OUTSIDE:
orien = 'horizontal'
orientation = kwargs.pop('orientation', orien)
if orientation == 'horizontal':
clegend.setPlotOrientation(PlotOrientation.HORIZONTAL)
else:
clegend.setPlotOrientation(PlotOrientation.VERTICAL)
frameon = kwargs.pop('frameon', True)
clegend.setDrawNeatLine(frameon)
bcobj = kwargs.pop('background', None)
bcobj = kwargs.pop('facecolor', bcobj)
if bcobj is None:
clegend.setDrawBackground(False)
else:
clegend.setDrawBackground(True)
background = plotutil.getcolor(bcobj)
clegend.setBackground(background)
labelfontdic = kwargs.pop('labelfont', None)
if labelfontdic is None:
labelfont = plotutil.getfont_1(**kwargs)
else:
labelfont = plotutil.getfont(labelfontdic)
clegend.setTickLabelFont(labelfont)
labelcolor = kwargs.pop('labelcolor', None)
if not labelcolor is None:
labelcolor = plotutil.getcolor(labelcolor)
clegend.setTickLabelColor(labelcolor)
title = kwargs.pop('title', None)
if not title is None:
titlefontdic = kwargs.pop('titlefont', None)
exfont = False
if titlefontdic is None:
fontname = kwargs.pop('titlefontname', None)
exfont = False
if fontname is None:
fontname = 'Arial'
else:
exfont = True
fontsize = kwargs.pop('titlefontsize', 14)
bold = kwargs.pop('titlebold', False)
if bold:
titlefont = Font(fontname, Font.BOLD, fontsize)
else:
titlefont = Font(fontname, Font.PLAIN, fontsize)
else:
titlefont = plotutil.getfont(titlefontdic)
title = ChartText(title, titlefont)
title.setUseExternalFont(exfont)
titlecolor = kwargs.pop('titlecolor', None)
if not titlecolor is None:
titlecolor = plotutil.getcolor(titlecolor)
title.setColor(titlecolor)
title.setXAlign(XAlign.CENTER)
title.setYAlign(YAlign.TOP)
clegend.setLabel(title)
breakspace = kwargs.pop('breakspace', None)
if not breakspace is None:
clegend.setBreakSpace(breakspace)
titlespace = kwargs.pop('titlespace', None)
if titlespace is not None:
clegend.setTitleSpace(titlespace)
markerscale = kwargs.pop('markerscale', None)
if not markerscale is None:
clegend.setSymbolScale(markerscale)
markerwidth = kwargs.pop('markerwidth', None)
markerheight = kwargs.pop('markerheight', None)
if not markerwidth is None:
clegend.setSymbolWidth(markerwidth)
if not markerheight is None:
clegend.setSymbolHeight(markerheight)
ncol = kwargs.pop('ncol', None)
if not ncol is None:
clegend.setColumnNumber(ncol)
clegend.setAutoRowColNum(False)
xshift = kwargs.pop('xshift', None)
if not xshift is None:
clegend.setXShift(xshift)
yshift = kwargs.pop('yshift', None)
if not yshift is None:
clegend.setYShift(yshift)
if newlegend:
self._axes.addLegend(clegend)
return clegend
def colorbar(self, mappable=None, **kwargs):
"""
Add a colorbar to a plot.
:param mappable: (*MapLayer | LegendScheme | List of ColorBreak*) The mappable in plot.
:param cax: (*Plot*) None | axes object into which the colorbar will be drawn.
:param cmap: (*string*) Color map name. Default is None.
:param shrink: (*float*) Fraction by which to shrink the colorbar. Default is 1.0.
:param orientation: (*string*) Colorbar orientation: ``vertical`` or ``horizontal``.
:param aspect: (*int*) Ratio of long to short dimensions.
:param fontname: (*string*) Font name. Default is ``Arial`` .
:param fontsize: (*int*) Font size. Default is ``14`` .
:param bold: (*boolean*) Is bold font or not. Default is ``False`` .
:param label: (*string*) Label. Default is ``None`` .
:param labelloc: (*string*) Label location ['in' | 'out' | 'top' | 'bottom' | 'left' | 'right'].
Default is ``out``.
:param labelshift: (*float*) Label location shift value. Default is None (value is 5).
:param newlegend: (*boolean*) Add a new legend or replace existing one.
:param extend: (*string*) {'neither', 'both', 'min', 'max'} If not 'neither', make pointed end(s)
for out-of- range values. These are set for a given colormap using the colormap set_under and
set_over methods.
:param extendrect: (*boolean*) If ``True`` the minimum and maximum colorbar extensions will be
rectangular. If ``False`` the extensions will be triangular (the default).
:param extendfrac: [None | 'auto' | length] If set to *None*, both the minimum and maximum triangular
colorbar extensions with have a length of 5% of the interior colorbar length (the default). If
set to 'auto', makes the triangular colorbar extensions the same lengths as the interior boxes
. If a scalar, indicates the length of both the minimum and maximum triangle colorbar extensions
as a fraction of the interior colorbar length.
:param ticks: [None | list of ticks] If None, ticks are determined automatically from the input.
:param ticklabels: [None | list of ticklabels] Tick labels.
:param tickin: (*boolean*) Draw tick line inside or outside the colorbar.
:param tickrotation: (*float*) Set tick label rotation angle.
:param xshift: (*float*) X shift of the colorbar with pixel coordinate.
:param yshift: (*float*) Y shift of the colorbar with pixel coordinate.
:param vmintick: (*boolean*) Draw minimum value tick or not.
:param vmaxtick: (*boolean*) Draw maximum value tick or not.
:param minortick: (*boolean*) Draw minor tick line or not.
:param minorticknum: (*int*) Minor tick line number between two adjacent major tick lines.
"""
cmap = kwargs.pop('cmap', None)
shrink = kwargs.pop('shrink', 1)
orientation = kwargs.pop('orientation', 'vertical')
aspect = kwargs.pop('aspect', 20)
tickfontdic = kwargs.pop('tickfont', None)
if tickfontdic is None:
tickfont = plotutil.getfont_1(**kwargs)
else:
tickfont = plotutil.getfont(tickfontdic)
exfont = False
labelfontdic = kwargs.pop('labelfont', None)
if labelfontdic is None:
labfontname = kwargs.pop('labelfontname', tickfont.getName())
if labfontname is None:
labfontname = tickfont.getName()
else:
exfont = True
labfontsize = kwargs.pop('labelfontsize', tickfont.getSize())
labbold = kwargs.pop('labelbold', tickfont.isBold())
if labbold:
labelfont = Font(labfontname, Font.BOLD, labfontsize)
else:
labelfont = Font(labfontname, Font.PLAIN, labfontsize)
else:
labelfont = plotutil.getfont(labelfontdic)
if mappable is None:
ls = self.get_legend()
else:
if isinstance(mappable, MILayer):
ls = mappable.legend()
elif isinstance(mappable, LegendScheme):
ls = mappable
elif isinstance(mappable, GraphicCollection):
ls = mappable.getLegendScheme()
else:
ls = plotutil.makelegend(mappable, **kwargs)
newlegend = kwargs.pop('newlegend', True)
if newlegend:
legend = ChartColorBar(ls)
self._axes.addLegend(legend)
else:
legend = self._axes.getLegend()
if legend is None:
legend = ChartColorBar(ls)
self._axes.setLegend(legend)
else:
legend.setLegendScheme(ls)
legend.setColorbar(True)
legend.setShrink(shrink)
legend.setAspect(aspect)
legend.setTickLabelFont(tickfont)
label = kwargs.pop('label', None)
if not label is None:
label = ChartText(label, labelfont)
label.setUseExternalFont(exfont)
legend.setLabel(label)
labelloc = kwargs.pop('labelloc', None)
if not labelloc is None:
legend.setLabelLocation(labelloc)
labelshift = kwargs.pop('labelshift', None)
if not labelshift is None:
legend.setLabelShift(labelshift)
if orientation == 'horizontal':
legend.setPlotOrientation(PlotOrientation.HORIZONTAL)
legend.setPosition(LegendPosition.LOWER_CENTER_OUTSIDE)
else:
legend.setPlotOrientation(PlotOrientation.VERTICAL)
legend.setPosition(LegendPosition.RIGHT_OUTSIDE)
legend.setDrawNeatLine(False)
extend = kwargs.pop('extend', None)
if extend is not None:
legend.setExtendType(extend)
extendrect = kwargs.pop('extendrect', False)
legend.setExtendRect(extendrect)
extendfrac = kwargs.pop('extendfrac', None)
if extendfrac is not None:
if extendfrac == 'auto':
efrac = ExtendFraction.AUTO
else:
efrac = ExtendFraction.LENGTH
efrac.fraction = extendfrac
legend.setExtendFraction(efrac)
tickvisible = kwargs.pop('tickvisible', None)
if not tickvisible is None:
legend.setTickVisible(tickvisible)
tickin = kwargs.pop('tickin', None)
if not tickin is None:
legend.setInsideTick(tickin)
ticklen = kwargs.pop('ticklen', None)
if not ticklen is None:
legend.setTickLength(ticklen)
if kwargs.has_key('tickwidth'):
tickwidth = kwargs.pop('tickwidth')
legend.setTickWidth(tickwidth)
if kwargs.has_key('tickcolor'):
tickcolor = kwargs.pop('tickcolor')
tickcolor = plotutil.getcolor(tickcolor)
legend.setTickColor(tickcolor)
ticks = kwargs.pop('ticks', None)
if not ticks is None:
if isinstance(ticks, NDArray):
ticks = ticks.aslist()
legend.setTickLocations(ticks)
ticklabels = kwargs.pop('ticklabels', None)
if not ticklabels is None:
if isinstance(ticklabels, (NDArray, DimArray)):
ticklabels = ticklabels.aslist()
if ls.getLegendType() == LegendType.UNIQUE_VALUE:
legend.setTickCaptions(ticklabels)
else:
if isinstance(ticklabels[0], (int, long, float)):
legend.setTickLabels_Number(ticklabels)
else:
legend.setTickLabelText(ticklabels)
tickrotation = kwargs.pop('tickrotation', None)
if not tickrotation is None:
legend.setTickLabelAngle(tickrotation)
xshift = kwargs.pop('xshift', None)
if not xshift is None:
legend.setXShift(xshift)
yshift = kwargs.pop('yshift', None)
if not yshift is None:
legend.setYShift(yshift)
vmintick = kwargs.pop('vmintick', False)
vmaxtick = kwargs.pop('vmaxtick', False)
legend.setDrawMinLabel(vmintick)
legend.setDrawMaxLabel(vmaxtick)
if kwargs.has_key('edgecolor'):
edgecolor = kwargs.pop('edgecolor')
edgecolor = plotutil.getcolor(edgecolor)
legend.setNeatLineColor(edgecolor)
if kwargs.has_key('edgesize'):
edgesize = kwargs.pop('edgesize')
legend.setNeatLineSize(edgesize)
minortick = kwargs.pop('minortick', None)
if not minortick is None:
legend.setDrawMinorTick(minortick)
return legend
###############################################
class PolarAxes(Axes):
"""
Axes with polar coordinate.
"""
def __init__(self, *args, **kwargs):
super(PolarAxes, self).__init__(*args, **kwargs)
bottom = kwargs.pop('bottom', None)
if not bottom is None:
self._axes.setBottom(bottom)
def _set_plot(self, plot):
"""
Set plot.
:param plot: (*PolarPlot*) Plot.
"""
if plot is None:
self._axes = PolarPlot()
else:
self._axes = plot
@property
def axestype(self):
return 'polar'
def set_rmax(self, rmax):
"""
Set radial max circle.
:param rmax: (*float*) Radial max value.
"""
self._axes.setRadius(rmax)
def set_rlabel_position(self, pos):
"""
Updates the theta position of the radial labels.
:param pos: (*float*) The angular position of the radial labels in degrees.
"""
if isinstance(pos, (DimArray, NDArray)):
pos = pos.tolist()
self._axes.setYTickLabelPos(pos)
def set_rticks(self, ticks):
"""
Set radial ticks.
:param ticks: (*string list*) Tick labels.
"""
self._axes.setYTickLabels(ticks)
def set_rtick_format(self, fmt=''):
"""
Set radial tick format.
:param ftm: (*string*) Tick format ['' | '%'].
"""
self._axes.setYTickFormat(fmt)
def set_rtick_locations(self, loc):
"""
Set radial tick locations.
:param loc: (*float list*) Tick locations.
"""
if isinstance(loc, (DimArray, NDArray)):
loc = loc.tolist()
self._axes.setYTickLocations(loc)
def set_xtick_locations(self, loc):
"""
Set angular tick locations.
:param loc: (*float list*) Tick locations.
"""
if isinstance(loc, (DimArray, NDArray)):
loc = loc.tolist()
self._axes.setXTickLocations(loc)
def set_xticks(self, ticks):
"""
Set angular ticks.
:param ticks: (*string list*) Tick labels.
"""
self._axes.setXTickLabels(ticks)
def set_rtick_font(self, name=None, size=None, style=None):
"""
Set radial tick font.
:param name: (*string*) Font name.
:param size: (*int*) Font size.
:param style: (*string*) Font style.
"""
font = self._axes.getYTickFont()
if name is None:
name = font.getName()
if size is None:
size = font.getSize()
if style is None:
style = font.getStyle()
else:
if style.lower() == 'bold':
style = Font.BOLD
elif style.lower() == 'italic':
style = Font.ITALIC
else:
style = Font.PLAIN
font = Font(name, style, size)
self._axes.setYTickFont(font)
def set_rtick_color(self, color):
"""
Set radial tick label color
:param color: (*color*) The color.
"""
color = plotutil.getcolor(color)
self._axes.setYTickColor(color)
def set_xtick_font(self, name=None, size=None, style=None):
"""
Set angular tick font.
:param name: (*string*) Font name.
:param size: (*int*) Font size.
:param style: (*string*) Font style.
"""
font = self._axes.getXTickFont()
if name is None:
name = font.getName()
if size is None:
size = font.getSize()
if style is None:
style = font.getStyle()
else:
if style.lower() == 'bold':
style = Font.BOLD
elif style.lower() == 'italic':
style = Font.ITALIC
else:
style = Font.PLAIN
font = Font(name, style, size)
self._axes.setXTickFont(font)
def set_xtick_color(self, color):
"""
Set angular tick label color
:param color: (*color*) The color.
"""
color = plotutil.getcolor(color)
self._axes.setXTickColor(color)
def data2pixel(self, x, y, z=None):
"""
Transform data coordinate to screen coordinate
:param x: (*float*) X coordinate.
:param y: (*float*) Y coordinate.
:param z: (*float*) Z coordinate - only used for 3-D axes.
"""
r = MIMath.polarToCartesian(x, y)
x = r[0]
y = r[1]
rect = self._axes.getPositionArea()
r = self._axes.projToScreen(x, y, rect)
sx = r[0] + rect.getX()
sy = r[1] + rect.getY()
sy = self.figure.get_size()[1] - sy
return sx, sy
def windrose(self, wd, ws, nwdbins=16, wsbins=None, degree=True, colors=None, cmap='matlab_jet', \
alpha=0.7, rmax=None, rtickloc=None, rticks=None, rlabelpos=60, xticks=None, **kwargs):
"""
Plot windrose chart.
:param wd: (*array_like*) Wind direction.
:param ws: (*array_like*) Wind speed.
:param nwdbins: (*int*) Number of wind direction bins [4 | 8 | 16].
:param wsbins: (*array_like*) Wind speed bins.
:param degree: (*boolean*) The unit of wind direction is degree or radians.
:param colors: (*color list*) The colors.
:param cmap: (*string*) Color map.
:param alpha: (*float*) Color alpha (0 - 1).
:param rmax: (*float*) Radial maximum value.
:param rtickloc: (*list of float*) Radial tick locations.
:param rticks: (*list of string*) Radial ticks.
:param rlabelpos: (*float*) Radial label position in degree.
:param xticks: (*list of string*) X ticks.
:returns: Polar axes and bars
"""
if not nwdbins in [4, 8, 16]:
print('nwdbins must be 4, 8 or 16!')
raise ValueError(nwdbins)
if isinstance(wd, list):
wd = np.array(wd)
if isinstance(ws, list):
ws = np.array(ws)
wdbins = np.linspace(0.0, 2 * np.pi, nwdbins + 1)
if wsbins is None:
wsbins = np.arange(0., ws.max(), 2.).tolist()
wsbins.append(100)
wsbins = np.array(wsbins)
dwdbins = np.degrees(wdbins)
dwdbins = dwdbins - 90
for i in range(len(dwdbins)):
if dwdbins[i] < 0:
dwdbins[i] += 360
for i in range(len(dwdbins)):
d = dwdbins[i]
d = 360 - d
dwdbins[i] = d
rwdbins = np.radians(dwdbins)
N = len(wd)
wdN = nwdbins
wsN = len(wsbins) - 1
if colors is None:
colors = plotutil.makecolors(wsN, cmap=cmap, alpha=alpha)
wd = wd + 360. / wdN / 2
wd[wd > 360] = wd - 360
rwd = np.radians(wd)
width = kwargs.pop('width', 0.5)
if width > 1:
width = 1
if width <= 0:
width = 0.2
theta = rwdbins[:-1]
width = 2. * width * np.pi / wdN
bars = []
hhist = 0
rrmax = 0
for i in range(wsN):
idx = np.where((ws >= wsbins[i]) * (ws < wsbins[i + 1]))
if idx is None:
continue
print(wsbins[i], wsbins[i + 1])
s_wd = rwd[idx]
wdhist = np.histogram(s_wd, wdbins)[0].astype('float')
wdhist = wdhist / N
rrmax = max(rrmax, wdhist.max())
lab = '%s - %s' % (wsbins[i], wsbins[i + 1])
bb = self.bar(theta, wdhist, width, bottom=hhist, color=colors[i], \
edgecolor='gray', label=lab, morepoints=True)[0]
bb.setStartValue(wsbins[i])
bb.setEndValue(wsbins[i + 1])
bars.append(bb)
hhist = hhist + wdhist
if rmax is None:
rmax = math.ceil(rrmax)
self.set_rmax(rmax)
if not rtickloc is None:
self.set_rtick_locations(rtickloc)
if not rticks is None:
self.set_rticks(rticks)
self.set_rtick_format('%')
self.set_rlabel_position(rlabelpos)
self.set_xtick_locations(np.arange(0., 360., 360. / wdN))
step = 16 / nwdbins
if xticks is None:
xticks = ['E', 'ENE', 'NE', 'NNE', 'N', 'NNW', 'NW', 'WNW', 'W', 'WSW', \
'SW', 'SSW', 'S', 'SSE', 'SE', 'ESE']
xticks = xticks[::step]
elif not xticks:
xticks = [''] * nwdbins
self.set_xticks(xticks)
return bars