# -*- coding: utf-8 -*-
from magic.setup import defaultLevels, defaultCm
import numpy as np
import matplotlib.pyplot as plt
[docs]def default_cmap(field):
"""
This function selects a default colormap for an input field. This allows
to have different colormaps depending on the quantity one wants to plot.
This can make use of cmocean colormaps, whenever installed.
:param field: the name of input field
:type field: str
:returns cm: the name of the matplotlib colormap
:rtype cm: str
"""
if field in ('Bp', 'bp', 'bphi', 'Bphi', 'Bt', 'bt', 'btheta', 'Btheta',
'Br', 'br', 'bpfluct', 'brfluct'):
cm = 'PuOr'
elif field in ('Vr', 'vr', 'Ur', 'ur', 'Vtheta', 'vtheta', 'Utheta',
'utheta', 'vt', 'Vt', 'Ut', 'ut', 'Vphi', 'vphi', 'Uphi',
'uphi', 'up', 'Up', 'Vp', 'vp', 'vpconv', 'vpc', 'vrea',
'vra', 'vpea', 'vpa', 'Us', 'us', 'Vs', 'vs', 'Uz', 'uz',
'vz', 'Vz'):
cm = 'seismic'
elif field in ('entropy', 's', 'S', 'tea', 'temperature', 't', 'T', 'temp'):
try:
import cmocean.cm as cmo
cm = cmo.thermal
except ModuleNotFoundError:
cm = 'magma'
elif field in ('entropyfluct', 'tempfluct', 'tfluct'):
cm = 'coolwarm'
elif field == 'xifluct':
cm = 'PiYG'
elif field == 'prefluct':
cm = 'RdGy'
elif field in ('composition', 'xi', 'Xi', 'Comp', 'comp', 'chem', 'Chem'):
try:
import cmocean.cm as cmo
cm = cmo.haline
except ModuleNotFoundError:
cm = 'viridis'
elif field in ('jphi', 'jr'):
try:
import cmocean.cm as cmo
cm = cmo.delta
except ModuleNotFoundError:
cm = 'BrBG'
elif field in ('phase', 'Phase'):
try:
import cmocean.cm as cmo
cm = cmo.tempo
except ModuleNotFoundError:
cm = 'binary'
elif field in ('vortz', 'vortzfluct'):
try:
import cmocean.cm as cmo
cm = cmo.curl
except ModuleNotFoundError:
cm = 'Spectral_r'
elif field in ('pressure', 'pre', 'Pre', 'Pressure', 'press', 'Press'):
cm = 'plasma'
elif field in ('u2', 'nrj', 'Ekin', 'ek', 'Ek', 'ekin'):
try:
import cmocean.cm as cmo
cm = cmo.rain
except ModuleNotFoundError:
cm = 'Blues'
elif field in ('b2', 'B2', 'Emag', 'em', 'Em', 'emag'):
try:
import cmocean.cm as cmo
cm = cmo.amp
except ModuleNotFoundError:
cm = 'Reds'
elif field == 'ohm':
cm = 'magma_r'
else: # In case nothing is found
cm = defaultCm
return cm
[docs]def diverging_cmap(field):
"""
This function determines whether the data are sequential or diverging (i.e.
centered around zero). In the latter, colormaps will be by default centered.
:param field: the name of input field
:type field: str
:returns diverging: a boolean to say whether the colormap will be centered or not
:rtype cm: bool
"""
if field in ('entropy', 's', 'S', 'u2', 'b2', 'nrj', 'temperature', 't',
'T', 'Ekin', 'ek', 'ekin', 'Ek', 'B2', 'Emag', 'emag', 'tea',
'em', 'Em', 'temp', 'pressure', 'pre', 'Pre', 'Pressure',
'press', 'Press', 'phase', 'Phase', 'composition', 'xi',
'Xi', 'Comp', 'comp', 'chem', 'Chem', 'ohm'):
diverging = False
else:
diverging = True
return diverging
[docs]def hammer2cart(ttheta, pphi, colat=False):
"""
This function is used to define the Hammer projection used when
plotting surface contours in :py:class:`magic.Surf`
>>> # Load Graphic file
>>> gr = MagicGraph()
>>> # Meshgrid
>>> pphi, ttheta = mgrid[-np.pi:np.pi:gr.nphi*1j, np.pi/2.:-np.pi/2.:gr.ntheta*1j]
>>> x,y = hammer2cart(ttheta, pphi)
>>> # Contour plots
>>> contourf(x, y, gr.vphi)
:param ttheta: meshgrid [nphi, ntheta] for the latitudinal direction
:type ttheta: numpy.ndarray
:param pphi: meshgrid [nphi, ntheta] for the azimuthal direction
:param colat: colatitudes (when not specified a regular grid is assumed)
:type colat: numpy.ndarray
:returns: a tuple that contains two [nphi, ntheta] arrays: the x, y meshgrid
used in contour plots
:rtype: (numpy.ndarray, numpy.ndarray)
"""
if not colat: # for lat and phi \in [-pi, pi]
xx = 2.*np.sqrt(2.) * np.cos(ttheta)*np.sin(pphi/2.)\
/np.sqrt(1.+np.cos(ttheta)*np.cos(pphi/2.))
yy = np.sqrt(2.) * np.sin(ttheta)\
/np.sqrt(1.+np.cos(ttheta)*np.cos(pphi/2.))
else: # for colat and phi \in [0, 2pi]
xx = -2.*np.sqrt(2.) * np.sin(ttheta)*np.cos(pphi/2.)\
/np.sqrt(1.+np.sin(ttheta)*np.sin(pphi/2.))
yy = np.sqrt(2.) * np.cos(ttheta)\
/np.sqrt(1.+np.sin(ttheta)*np.sin(pphi/2.))
return xx, yy
[docs]def cut(dat, vmax=None, vmin=None):
"""
This functions truncates the values of an input array that are beyond
vmax or below vmin and replace them by vmax and vmin, respectively.
>>> # Keep only values between -1e3 and 1e3
>>> datNew = cut(dat, vmin=-1e3, vmax=1e3)
:param dat: an input array
:type dat: numpy.ndarray
:param vmax: maximum upper bound
:type vmax: float
:param vmin: minimum lower bound
:type vmin: float
:returns: an array where the values >=vmax have been replaced by vmax
and the values <=vmin have been replaced by vmin
:rtype: numpy.ndarray
"""
if vmax is not None:
mask = np.where(dat>=vmax, 1, 0)
dat = dat*(mask == 0) + vmax*(mask == 1)
normed = False
if vmin is not None:
mask = np.where(dat<=vmin, 1, 0)
dat = dat*(mask == 0) + vmin*(mask == 1)
normed = False
return dat
[docs]def equatContour(data, radius, minc=1, label=None, levels=defaultLevels,
cm=defaultCm, normed=None, vmax=None, vmin=None, cbar=True,
title=True, normRad=False, deminc=True, bounds=True,
lines=False, linewidths=0.5, pcolor=False, rasterized=False):
"""
Plot the equatorial cut of a given field
:param data: the input data (an array of size (nphi,nr))
:type data: numpy.ndarray
:param radius: the input radius
:type radius: numpy.ndarray
:param minc: azimuthal symmetry
:type minc: int
:param label: the name of the input physical quantity you want to
display
:type label: str
:param normRad: when set to True, the contour levels are normalised
radius by radius (default is False)
:type normRad: bool
:param levels: the number of levels in the contour
:type levels: int
:param cm: name of the colormap ('jet', 'seismic', 'RdYlBu_r', etc.)
:type cm: str
:param title: display the title of the figure when set to True
:type title: bool
:param cbar: display the colorbar when set to True
:type cbar: bool
:param vmax: maximum value of the contour levels
:type vmax: float
:param vmin: minimum value of the contour levels
:type vmin: float
:param normed: when set to True, the colormap is centered around zero.
Default is None, it tries to find it by itself.
:type normed: bool
:param deminc: a logical to indicate if one wants do get rid of the
possible azimuthal symmetry
:type deminc: bool
:param bounds: a boolean to determine if one wants to plot the limits
of the domain (True by default)
:type bounds: bool
:param lines: when set to True, over-plot solid lines to highlight
the limits between two adjacent contour levels
:type lines: bool
:param linewidths: the thickness of the solid lines, whenever plotted
:type linewidths: float
:param pcolor: when set to True, use pcolormesh instead of contourf
:type pcolor: bool
:param rasterized: when set to True, the rasterization for vector graphics
is turned on
:type rasterized: bool
"""
nphi, ntheta = data.shape
if deminc:
phi = np.linspace(0., 2.*np.pi, nphi)
else:
phi = np.linspace(0., 2.*np.pi/minc, nphi)
rr, pphi = np.meshgrid(radius, phi)
xx = rr * np.cos(pphi)
yy = rr * np.sin(pphi)
if normRad: # Normalise each radius
maxS = np.sqrt(np.mean(data**2, axis=0))
data[:, maxS!=0.] /= maxS[maxS!=0.]
if title and label is not None:
if cbar:
fig = plt.figure(figsize=(6.5,5.5))
ax = fig.add_axes([0.01, 0.01, 0.76, 0.9])
else:
fig = plt.figure(figsize=(5,5.5))
ax = fig.add_axes([0.01, 0.01, 0.98, 0.9])
ax.set_title(label, fontsize=24)
else:
if cbar:
fig = plt.figure(figsize=(6.5,5))
ax = fig.add_axes([0.01, 0.01, 0.76, 0.98])
else:
fig = plt.figure(figsize=(5, 5))
ax = fig.add_axes([0.01, 0.01, 0.98, 0.98])
if normed is None:
if abs(data.min()) < 1e-8:
normed = False
else:
if data.max() > 0 and data.min() < 0:
normed = True
else:
normed = False
if cm == defaultCm and not normed:
cm = 'viridis'
cmap = plt.get_cmap(cm)
if vmax is not None or vmin is not None:
normed = False
cs = np.linspace(vmin, vmax, levels)
if pcolor:
im = ax.pcolormesh(xx, yy, data, cmap=cmap, antialiased=True,
shading='gouraud', vmax=vmax, vmin=vmin,
rasterized=rasterized)
else:
im = ax.contourf(xx, yy, data, cs, cmap=cmap, extend='both')
if lines:
ax.contour(xx, yy, data, cs, colors=['k'], linewidths=linewidths,
extend='both', linestyles=['-'])
else:
if not normed:
cs = levels
else:
vmax = max(abs(data.max()), abs(data.min()))
vmin = -vmax
cs = np.linspace(vmin, vmax, levels)
if pcolor:
if normed:
im = ax.pcolormesh(xx, yy, data, cmap=cmap, antialiased=True,
shading='gouraud', vmax=vmax, vmin=vmin,
rasterized=rasterized)
else:
im = ax.pcolormesh(xx, yy, data, cmap=cmap, antialiased=True,
shading='gouraud', rasterized=rasterized)
else:
im = ax.contourf(xx, yy, data, cs, cmap=cmap)
if lines:
ax.contour(xx, yy, data, cs, colors=['k'], linewidths=linewidths,
linestyles=['-'])
if bounds:
ax.plot(radius[0]*np.cos(phi), radius[0]*np.sin(phi), 'k-', lw=1.5)
if abs(radius[-1]) > 1e-8:
ax.plot(radius[-1]*np.cos(phi), radius[-1]*np.sin(phi), 'k-', lw=1.5)
if not deminc and minc > 1:
ax.plot(radius, np.zeros_like(radius), 'k-', lw=1.5)
xa = radius[-1]*np.cos(2.*np.pi/minc)
ya = radius[-1]*np.sin(2.*np.pi/minc)
xb = radius[0]*np.cos(2.*np.pi/minc)
x = np.linspace(xa, xb, 32)
y = np.tan(2.*np.pi/minc)*(x-xa)+ya
ax.plot(x, y, 'k-', lw=1.5)
ax.plot(radius, np.zeros_like(radius), 'k-', lw=1.5)
eps = 1e-4
if xx.min() < -eps:
ax.set_xlim(1.01*xx.min(), 1.01*xx.max())
elif abs(xx.min()) < eps :
ax.set_xlim(xx.min()-0.01, 1.01*xx.max())
else:
ax.set_xlim(0.99*xx.min(), 1.01*xx.max())
if yy.min() < -eps:
ax.set_ylim(1.01*yy.min(), 1.01*yy.max())
elif abs(yy.min()) < eps:
ax.set_ylim(yy.min()-0.01, 1.01*yy.max())
else:
ax.set_ylim(0.99*yy.min(), 1.01*yy.max())
ax.axis('off')
# Add the colorbar at the right place
pos = ax.get_position()
l, b, w, h = pos.bounds
if cbar:
if title and label is not None:
cax = fig.add_axes([0.85, 0.46-0.7*h/2., 0.03, 0.7*h])
else:
cax = fig.add_axes([0.85, 0.5-0.7*h/2., 0.03, 0.7*h])
mir = fig.colorbar(im, cax=cax)
#To avoid white lines on pdfs
if not pcolor:
for c in im.collections:
c.set_edgecolor('face')
if rasterized:
c.set_rasterized(True)
return fig, xx, yy
[docs]def merContour(data, radius, label=None, levels=defaultLevels, cm=defaultCm,
normed=None, vmax=None, vmin=None, cbar=True, title=True,
fig=None, ax=None, bounds=True, lines=False, pcolor=False,
linewidths=0.5, rasterized=False):
"""
Plot a meridional cut of a given field
:param data: the input data (an array of size (ntheta,nr))
:type data: numpy.ndarray
:param radius: the input radius
:type radius: numpy.ndarray
:param label: the name of the input physical quantity you want to
display
:type label: str
:param levels: the number of levels in the contour
:type levels: int
:param cm: name of the colormap ('jet', 'seismic', 'RdYlBu_r', etc.)
:type cm: str
:param title: display the title of the figure when set to True
:type title: bool
:param cbar: display the colorbar when set to True
:type cbar: bool
:param vmax: maximum value of the contour levels
:type vmax: float
:param vmin: minimum value of the contour levels
:type vmin: float
:param normed: when set to True, the colormap is centered around zero.
Default is None, it tries to guess by itself.
:type normed: bool
:param bounds: a boolean to determine if one wants to plot the limits
of the domain (True by default)
:type bounds: bool
:param fig: a pre-existing figure (if needed)
:type fig: matplotlib.figure.Figure
:param ax: a pre-existing axis
:type ax: matplotlib.axes._subplots.AxesSubplot
:param lines: when set to True, over-plot solid lines to highlight
the limits between two adjacent contour levels
:type lines: bool
:param linewidths: the thickness of the solid lines, whenever plotted
:type linewidths: float
:param pcolor: when set to True, use pcolormesh instead of contourf
:type pcolor: bool
:param rasterized: when set to True, the rasterization for vector graphics
is turned on
:type rasterized: bool
"""
ntheta, nr = data.shape
th = np.linspace(0, np.pi, ntheta)
rr, tth = np.meshgrid(radius, th)
xx = rr * np.sin(tth)
yy = rr * np.cos(tth)
if title and label is not None:
if cbar:
fsize = (5, 7.5)
bb = [0.01, 0.01, 0.69, 0.91]
else:
fsize = (3.5, 7.5)
bb = [0.01, 0.01, 0.98, 0.91]
else:
if cbar:
fsize = (5, 7)
bb = [0.01, 0.01, 0.69, 0.98]
else:
fsize = (3.5, 7)
bb = [0.01, 0.01, 0.98, 0.98]
if fig is None:
fig = plt.figure(figsize=fsize)
if ax is None:
ax = fig.add_axes(bb)
if title and label is not None:
ax.set_title(label, fontsize=24)
if normed is None:
if abs(data.min()) < 1e-8:
normed = False
else:
if data.max() > 0 and data.min() < 0:
normed = True
else:
normed = False
if cm == defaultCm and not normed:
cm = 'viridis'
cmap = plt.get_cmap(cm)
if vmax is not None and vmin is not None:
normed = False
cs = np.linspace(vmin, vmax, levels)
if pcolor:
im = ax.pcolormesh(xx, yy, data, cmap=cmap, antialiased=True,
shading='gouraud', vmax=vmax, vmin=vmin,
rasterized=rasterized)
else:
im = ax.contourf(xx, yy, data, cs, cmap=cmap, extend='both')
if lines:
ax.contour(xx, yy, data, cs, colors=['k'], linewidths=linewidths,
extend='both', linestyles=['-'])
else:
if not normed:
cs = levels
else:
vmax = max(abs(data.max()), abs(data.min()))
vmin = -vmax
cs = np.linspace(vmin, vmax, levels)
if pcolor:
if normed:
im = ax.pcolormesh(xx, yy, data, cmap=cmap, antialiased=True,
shading='gouraud', vmax=vmax, vmin=vmin,
rasterized=rasterized)
else:
im = ax.pcolormesh(xx, yy, data, cmap=cmap, antialiased=True,
shading='gouraud', rasterized=rasterized)
else:
im = ax.contourf(xx, yy, data, cs, cmap=cmap)
if lines:
ax.contour(xx, yy, data, cs, colors=['k'], linewidths=linewidths,
linestyles=['-'])
# To avoid white lines on pdfs
if not pcolor:
for c in im.collections:
c.set_edgecolor('face')
if rasterized:
c.set_rasterized(True)
if bounds:
ax.plot((radius[0])*np.sin(th), (radius[0])*np.cos(th), 'k-')
if abs(radius[-1]) > 1e-8:
ax.plot((radius[-1])*np.sin(th), (radius[-1])*np.cos(th), 'k-')
ax.plot([0., 0.], [radius[-1], radius[0]], 'k-')
ax.plot([0., 0.], [-radius[-1], -radius[0]], 'k-')
eps = 1e-4
if xx.min() < -eps:
ax.set_xlim(1.01*xx.min(), 1.01*xx.max())
elif abs(xx.min()) < eps :
ax.set_xlim(xx.min()-0.01, 1.01*xx.max())
else:
ax.set_xlim(0.99*xx.min(), 1.01*xx.max())
if yy.min() < -eps:
ax.set_ylim(1.01*yy.min(), 1.01*yy.max())
elif abs(yy.min()) < eps:
ax.set_ylim(yy.min()-0.01, 1.01*yy.max())
else:
ax.set_ylim(0.99*yy.min(), 1.01*yy.max())
ax.axis('off')
# Add the colorbar at the right place
pos = ax.get_position()
l, b, w, h = pos.bounds
if cbar:
if title and label is not None:
cax = fig.add_axes([0.82, 0.46-0.7*h/2., 0.04, 0.7*h])
else:
cax = fig.add_axes([0.82, 0.5-0.7*h/2., 0.04, 0.7*h])
mir = fig.colorbar(im, cax=cax)
return fig, xx, yy, im
[docs]def radialContour(data, rad=0.85, label=None, proj='hammer', lon_0=0., vmax=None,
vmin=None, lat_0=30., levels=defaultLevels, cm=defaultCm,
normed=None, cbar=True, title=True, lines=False, fig=None,
ax=None, linewidths=0.5, pcolor=False, rasterized=False,
gridLineStyle=':', gridColor='k', gridLineWidth=0.7):
"""
Plot the radial cut of a given field
:param data: the input data (an array of size (nphi,ntheta))
:type data: numpy.ndarray
:param rad: the value of the selected radius
:type rad: float
:param label: the name of the input physical quantity you want to
display
:type label: str
:param proj: the type of projection. Default is Hammer, in case
you want to use 'ortho' or 'moll', then Basemap is
required.
:type proj: str
:param levels: the number of levels in the contour
:type levels: int
:param cm: name of the colormap ('jet', 'seismic', 'RdYlBu_r', etc.)
:type cm: str
:param title: display the title of the figure when set to True
:type title: bool
:param cbar: display the colorbar when set to True
:type cbar: bool
:param lines: when set to True, over-plot solid lines to highlight
the limits between two adjacent contour levels
:type lines: bool
:param linewidths: the thickness of the solid lines, whenever plotted
:type linewidths: float
:param vmax: maximum value of the contour levels
:type vmax: float
:param vmin: minimum value of the contour levels
:type vmin: float
:param normed: when set to True, the colormap is centered around zero.
Default is None, it tries to find it by itself.
:type normed: bool
:param fig: a pre-existing figure (if needed)
:type fig: matplotlib.figure.Figure
:param ax: a pre-existing axis
:type ax: matplotlib.axes._subplots.AxesSubplot
:param pcolor: when set to True, use pcolormesh instead of contourf
:type pcolor: bool
:param rasterized: when set to True, the rasterization for vector graphics
is turned on
:type rasterized: bool
:param gridColor: this is used to set the color of the grid
:type gridColor: str
:param gridLineStyle: this allows to set the line style of the grid
(':', '-', '--')
:type gridLineStyle: str
:param gridLineWidth: this is used to tune the thickness of the lines used
in the grid
:type gridLineWidth: float
"""
nphi, ntheta = data.shape
phi = np.linspace(-np.pi, np.pi, nphi)
theta = np.linspace(np.pi/2, -np.pi/2, ntheta)
pphi, ttheta = np.mgrid[-np.pi:np.pi:nphi*1j, np.pi/2.:-np.pi/2.:ntheta*1j]
lon2 = pphi * 180./np.pi
lat2 = ttheta * 180./np.pi
circles = np.r_[-60., -30., 0., 30., 60.]
delon = 60.
meridians = np.arange(-180+delon, 180, delon)
if fig is None and ax is None:
if proj == 'moll' or proj == 'hammer':
if title and label is not None:
if cbar:
fig = plt.figure(figsize=(9.1, 4.5))
ax = fig.add_axes([0.01, 0.01, 0.87, 0.87])
else:
fig = plt.figure(figsize=(8, 4.5))
ax = fig.add_axes([0.01, 0.01, 0.98, 0.87])
ax.set_title('{}: r/ro = {:.3f}'.format(label, rad),
fontsize=24)
else:
if cbar:
fig = plt.figure(figsize=(9.1, 4))
ax = fig.add_axes([0.01, 0.01, 0.87, 0.98])
else:
fig = plt.figure(figsize=(8., 4))
ax = fig.add_axes([0.01, 0.01, 0.98, 0.98])
#tit1 = r'{:.2f} Ro'.format(rad)
#ax.text(0.12, 0.9, tit1, fontsize=16,
#horizontalalignment='right',
#verticalalignment='center',
#transform = ax.transAxes)
else:
if title and label is not None:
if cbar:
fig = plt.figure(figsize=(6,5.5))
ax = fig.add_axes([0.01, 0.01, 0.82, 0.9])
else:
fig = plt.figure(figsize=(5,5.5))
ax = fig.add_axes([0.01, 0.01, 0.98, 0.9])
ax.set_title('{}: r/ro = {:.3f}'.format(label, rad),
fontsize=24)
else:
if cbar:
fig = plt.figure(figsize=(6,5))
ax = fig.add_axes([0.01, 0.01, 0.82, 0.98])
else:
fig = plt.figure(figsize=(5,5))
ax = fig.add_axes([0.01, 0.01, 0.98, 0.98])
tit1 = r'{:.2f} Ro'.format(rad)
ax.text(0.12, 0.9, tit1, fontsize=16,
horizontalalignment='right',
verticalalignment='center',
transform = ax.transAxes)
if proj != 'hammer':
from mpl_toolkits.basemap import Basemap
map = Basemap(projection=proj, lon_0=lon_0, lat_0=lat_0,
resolution='c')
map.drawparallels([0.], dashes=[2, 3], linewidth=gridLineWidth,
color=gridColor)
map.drawparallels(circles, dashes=[2,3], linewidth=gridLineWidth,
color=gridColor)
map.drawmeridians(meridians, dashes=[2,3], linewidth=gridLineWidth,
color=gridColor)
map.drawmeridians([-180], dashes=[20,0], linewidth=gridLineWidth,
color=gridColor)
map.drawmeridians([180], dashes=[20,0], linewidth=gridLineWidth,
color=gridColor)
x, y = list(map(lon2, lat2))
else:
x, y = hammer2cart(ttheta, pphi)
for lat0 in circles:
x0, y0 = hammer2cart(lat0*np.pi/180., phi)
ax.plot(x0, y0, ls=gridLineStyle, color=gridColor,
linewidth=gridLineWidth)
for lon0 in meridians:
x0, y0 = hammer2cart(theta, lon0*np.pi/180.)
ax.plot(x0, y0, ls=gridLineStyle, color=gridColor,
linewidth=gridLineWidth)
xxout, yyout = hammer2cart(theta, -np.pi)#-1e-3)
xxin, yyin = hammer2cart(theta, np.pi)#+1e-3)
ax.plot(xxin, yyin, 'k-')
ax.plot(xxout, yyout, 'k-')
ax.axis('off')
ax.set_ylim(-1.01*np.sqrt(2.), 1.01*np.sqrt(2.))
ax.set_xlim(-2.02*np.sqrt(2.), 2.02*np.sqrt(2.))
if normed is None:
if abs(data.min()) < 1e-8:
normed = False
else:
if data.max() > 0 and data.min() < 0:
normed = True
else:
normed = False
if cm == defaultCm and not normed:
cm = 'viridis'
cmap = plt.get_cmap(cm)
if proj == 'ortho':
lats = np.linspace(-90., 90., ntheta)
dat = map.transform_scalar(data.T, phi*180/np.pi, lats,
nphi, ntheta, masked=True)
im = map.imshow(dat, cmap=cmap)
else:
if vmax is not None or vmin is not None:
normed = False
cs = np.linspace(vmin, vmax, levels)
if pcolor:
im = ax.pcolormesh(x, y, data, cmap=cmap, antialiased=True,
shading='gouraud', vmax=vmax, vmin=vmin,
rasterized=rasterized)
else:
im = ax.contourf(x, y, data, cs, cmap=cmap, extend='both',
rasterized=rasterized)
if lines:
ax.contour(x, y, data, cs, colors=['k'], linewidths=linewidths,
extend='both', linestyles=['-'])
#ax.contour(x, y, data, 1, colors=['k'])
else:
if not normed:
cs = levels
else:
vmax = max(abs(data.max()), abs(data.min()))
vmin = -vmax
cs = np.linspace(vmin, vmax, levels)
if pcolor:
if normed:
im = ax.pcolormesh(x, y, data, cmap=cmap, antialiased=True,
shading='gouraud', vmax=vmax, vmin=vmin,
rasterized=rasterized)
else:
im = ax.pcolormesh(x, y, data, cmap=cmap, antialiased=True,
shading='gouraud', rasterized=rasterized)
else:
im = ax.contourf(x, y, data, cs, cmap=cmap)
if lines:
ax.contour(x, y, data, cs, colors=['k'], linewidths=linewidths,
linestyles=['-'])
# Add the colorbar at the right place
pos = ax.get_position()
l, b, w, h = pos.bounds
if cbar:
if title and label is not None:
cax = fig.add_axes([0.9, 0.46-0.7*h/2., 0.03, 0.7*h])
else:
cax = fig.add_axes([0.9, 0.51-0.7*h/2., 0.03, 0.7*h])
mir = fig.colorbar(im, cax=cax)
# To avoid white lines on pdfs
if not pcolor:
for c in im.collections:
c.set_edgecolor('face')
if rasterized:
c.set_rasterized(True)
return fig, x, y