# -*- coding: utf-8 -*-
from magic import MagicGraph, MagicSetup, MagicRadial
from magic.setup import labTex, defaultLevels
from .libmagic import *
from .plotlib import equatContour, merContour, radialContour, default_cmap, \
diverging_cmap
import matplotlib.pyplot as plt
import os
import numpy as np
try:
from scipy.integrate import trapz
except:
from scipy.integrate import trapezoid as trapz
[docs]class Surf:
"""
This class allows to display the content of a graphic file
(:ref:`G_#.TAG <secGraphFile>` or G_ave.TAG). It allows to plot
radial, azimuthal and equatorial cuts as well as phi-averages.
>>> # To read G_1.test
>>> s = Surf(ivar=1, ave=False, tag='test')
>>> # To read the latest G file in the working directory (double precision)
>>> s = Surf(precision=np.float64)
>>> # Possible plots
>>> s.equat(field='vr')
>>> s.avg(field='vp')
>>> s.surf(field='entropy', r=0.8)
>>> s.slice(field='Br', lon_0=[0, 30])
"""
[docs] def __init__(self, ivar=None, datadir='.', vort=False, ave=False, tag=None,
precision=np.float32):
"""
:param ivar: index of the graphic file
:type ivar: int
:param ave: when set to True, it tries to read a time-averaged graphic file
:type ave: bool
:param tag: TAG suffix extension of the graphic file
:type tag: str
:param vort: a boolean to specify whether one wants to compute the 3-D
vorticiy components (take care of the memory imprint)
:type vort: bool
:param datadir: the working directory
:type datadir: str
:param precision: the storage precision of the graphic file (single or
double precision). Default is np.float32 (single)
:type precision: str
"""
self.precision = precision
self.datadir = datadir
self.gr = MagicGraph(ivar=ivar, datadir=self.datadir, ave=ave, tag=tag,
precision=self.precision)
if vort:
thlin = self.gr.colatitude
th3D = np.zeros_like(self.gr.vphi)
rr3D = np.zeros_like(th3D)
for i in range(self.gr.ntheta):
th3D[:, i, :] = thlin[i]
for i in range(self.gr.nr):
rr3D[:, :, i] = self.gr.radius[i]
s3D = rr3D * np.sin(th3D)
dtheta = thetaderavg(self.gr.vphi*s3D)
dr = rderavg(self.gr.vphi*s3D, self.gr.radius, exclude=False)
ds = np.sin(th3D)*dr + np.cos(th3D)/rr3D*dtheta
vs = self.gr.vr * np.sin(th3D) + self.gr.vtheta * np.cos(th3D)
self.vortz = -1./s3D*phideravg(vs, self.gr.minc)+ds/s3D
del dr, dtheta, ds, rr3D, th3D, s3D
[docs] def surf(self, field='Bphi', proj='hammer', lon_0=0., r=0.85, vmax=None,
vmin=None, lat_0=30., levels=defaultLevels, cm=None, ic=False,
lon_shift=0, normed=None, cbar=True, title=True, lines=False,
pcolor=False):
"""
Plot the surface distribution of an input field at a given
input radius (normalised by the outer boundary radius).
>>> s = Surf()
>>> # Radial flow component at ``r=0.95 r_o``, 65 contour levels
>>> s.surf(field='vr', r=0.95, levels=65, cm='seismic')
>>> # Minimal plot (no cbar, not title)
>>> s.surf(field='entropyfluct', r=0.6, title=False, cbar=False)
>>> # Control the limit of the colormap from -1e3 to 1e3
>>> s.surf(field='vp', r=1., vmin=-1e3, vmax=1e3, levels=33)
>>> # If basemap is installed, additional projections are available
>>> s.surf(field='Br', r=0.95, proj='ortho', lat_0=45, lon_0=45)
:param field: the name of the field you want to display
:type field: 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 r: the radius at which you want to display the input
data (in normalised units with the radius of the outer boundary)
:type r: float
: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 lon_shift: translate map in azimuth (in degrees)
:type lon_shift: int
:param lon_0: central azimuth (only used with Basemap)
:type lon_0: float
:param lat_0: central latitude (only used with Basemap)
:type lat_0: float
:param title: display the title of the figure when set to True
: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 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 True, except for entropy/temperature plots.
:type normed: bool
:param lines: when set to True, over-plot solid lines to highlight
the limits between two adjacent contour levels
:type lines: bool
:param pcolor: when set to True, use pcolormesh instead of contourf
:type pcolor: bool
"""
if proj != 'ortho':
lon_0 = 0.
if field in ('Vs', 'vs'):
vr = self.gr.vr
vt = self.gr.vtheta
thlin = np.linspace(0., np.pi, self.gr.ntheta)
th3D = np.zeros_like(self.gr.vr)
for i in range(self.gr.ntheta):
th3D[:, i, :] = thlin[i]
data = vr * np.sin(th3D) + vt * np.cos(th3D)
data_ic = None
if labTex:
label = r'$v_s$'
else:
label = r'vs'
elif field in ('Vz', 'vz'):
vr = self.gr.vr
vt = self.gr.vtheta
thlin = np.linspace(0., np.pi, self.gr.ntheta)
th3D = np.zeros_like(self.gr.vr)
for i in range(self.gr.ntheta):
th3D[:, i, :] = thlin[i]
data = vr * np.cos(th3D) - vt * np.sin(th3D)
data_ic = None
if labTex:
label = r'$v_z$'
else:
label = r'vz'
elif field == 'thu':
data = self.gr.vr*(self.gr.entropy-self.gr.entropy.mean(axis=0))
data_ic = None
label = 'thu'
elif field == 'flux':
data = rderavg(self.gr.entropy, self.gr.radius)
data_ic = None
label = 'flux'
elif field == 'mag_pres_force_r':
data = -rderavg(self.gr.Br**2+self.gr.Btheta**2+self.gr.Bphi**2,
self.gr.radius)/2.0
data_ic = None
label = 'Rad. mag. pres. force'
elif field == 'mag_pres_force_t':
rr3D = np.zeros_like(self.gr.Bphi)
for i in range(self.gr.nr):
rr3D[:, :, i] = self.gr.radius[i]
data = -thetaderavg(self.gr.Br**2+self.gr.Btheta**2+self.gr.Bphi**2,
order=2)/rr3D/2.0
data_ic = None
label = 'Lati. mag. pres. force'
elif field == 'mag_pres_force_p':
th3D = np.zeros_like(self.gr.Bphi)
rr3D = np.zeros_like(th3D)
for i in range(self.gr.nr):
rr3D[:, :, i] = self.gr.radius[i]
for i in range(self.gr.ntheta):
th3D[:, i, :] = self.gr.colatitude[i]
data = -phideravg(self.gr.Br**2+self.gr.Btheta**2+self.gr.Bphi**2,
self.gr.minc)/(rr3D*np.sin(th3D))/2.0
data_ic = None
label = 'Longi. mag. pres. force'
elif field == 'mag_tens_force_r':
th3D = np.zeros_like(self.gr.Bphi)
rr3D = np.zeros_like(th3D)
for i in range(self.gr.nr):
rr3D[:, :, i] = self.gr.radius[i]
for i in range(self.gr.ntheta):
th3D[:, i, :] = self.gr.colatitude[i]
data = self.gr.Br * rderavg(self.gr.Br, self.gr.radius) + \
self.gr.Btheta * thetaderavg(self.gr.Br, order=2) / rr3D + \
self.gr.Bphi * phideravg(self.gr.Br, self.gr.minc) / \
np.sin(th3D) / rr3D - (self.gr.Btheta**2 + self.gr.Bphi**2) / rr3D
data_ic = None
label = 'Rad. tens. force'
elif field == 'mag_tens_force_t':
th3D = np.zeros_like(self.gr.Bphi)
rr3D = np.zeros_like(th3D)
for i in range(self.gr.nr):
rr3D[:, :, i] = self.gr.radius[i]
for i in range(self.gr.ntheta):
th3D[:, i, :] = self.gr.colatitude[i]
data = self.gr.Br * rderavg(self.gr.Btheta, self.gr.radius) + \
self.gr.Btheta * thetaderavg(self.gr.Btheta, order=2) / rr3D + \
self.gr.Bphi * phideravg(self.gr.Btheta, self.gr.minc) / \
np.sin(th3D) / rr3D + self.gr.Btheta * self.gr.Br / rr3D - \
self.gr.Bphi**2 * np.arctan(th3D) / rr3D
data_ic = None
label = 'Lati. tens. force'
elif field == 'mag_tens_force_p':
th3D = np.zeros_like(self.gr.Bphi)
rr3D = np.zeros_like(th3D)
for i in range(self.gr.nr):
rr3D[:, :, i] = self.gr.radius[i]
for i in range(self.gr.ntheta):
th3D[:, i, :] = self.gr.colatitude[i]
data = self.gr.Br * rderavg(self.gr.Bphi, self.gr.radius) + \
self.gr.Btheta * thetaderavg(self.gr.Bphi, order=2) / rr3D + \
self.gr.Bphi * phideravg(self.gr.Bphi, self.gr.minc) / \
np.sin(th3D) / rr3D + self.gr.Bphi * self.gr.Br / rr3D + \
self.gr.Bphi * self.gr.Btheta * np.arctan(th3D) / rr3D
data_ic = None
label = 'Longi. tens. force'
elif field == 'Lorentz_r':
th3D = np.zeros_like(self.gr.Bphi)
rr3D = np.zeros_like(th3D)
for i in range(self.gr.nr):
rr3D[:, :, i] = self.gr.radius[i]
for i in range(self.gr.ntheta):
th3D[:, i, :] = self.gr.colatitude[i]
data = -rderavg(self.gr.Br**2+self.gr.Btheta**2+self.gr.Bphi**2,
self.gr.radius)/2.0 + \
self.gr.Br * rderavg(self.gr.Br, self.gr.radius) + \
self.gr.Btheta * thetaderavg(self.gr.Br, order=2) / rr3D + \
self.gr.Bphi * phideravg(self.gr.Br, self.gr.minc) / \
np.sin(th3D) / rr3D - (self.gr.Btheta**2 + self.gr.Bphi**2) / rr3D
data_ic = None
label = 'Radial Lorentz force'
elif field == 'Lorentz_t':
th3D = np.zeros_like(self.gr.Bphi)
rr3D = np.zeros_like(th3D)
for i in range(self.gr.nr):
rr3D[:, :, i] = self.gr.radius[i]
for i in range(self.gr.ntheta):
th3D[:, i, :] = self.gr.colatitude[i]
data = -thetaderavg(self.gr.Br**2+self.gr.Btheta**2+self.gr.Bphi**2,
order=2)/rr3D/2.0 + \
self.gr.Br * rderavg(self.gr.Btheta, self.gr.radius) + \
self.gr.Btheta * thetaderavg(self.gr.Btheta, order=2) / rr3D + \
self.gr.Bphi * phideravg(self.gr.Btheta, self.gr.minc) / \
np.sin(th3D) / rr3D + self.gr.Btheta * self.gr.Br / rr3D - \
self.gr.Bphi**2 * np.arctan(th3D) / rr3D
data_ic = None
label = 'Lati. Lorentz force'
elif field == 'Lorentz_p':
th3D = np.zeros_like(self.gr.Bphi)
rr3D = np.zeros_like(th3D)
for i in range(self.gr.nr):
rr3D[:, :, i] = self.gr.radius[i]
for i in range(self.gr.ntheta):
th3D[:, i, :] = self.gr.colatitude[i]
data = -phideravg(self.gr.Br**2+self.gr.Btheta**2+self.gr.Bphi**2,
self.gr.minc)/(rr3D*np.sin(th3D))/2.0 + \
self.gr.Br * rderavg(self.gr.Bphi, self.gr.radius) + \
self.gr.Btheta * thetaderavg(self.gr.Bphi, order=2) / rr3D + \
self.gr.Bphi * phideravg(self.gr.Bphi, self.gr.minc) / \
np.sin(th3D) / rr3D + self.gr.Bphi * self.gr.Br / rr3D + \
self.gr.Bphi * self.gr.Btheta * np.arctan(th3D) / rr3D
data_ic = None
label = 'Longi. Lorentz force'
elif field == 'ohm':
label = 'Ohmic dissipation'
th3D = np.zeros_like(self.gr.Bphi)
rr3D = np.zeros_like(th3D)
for i in range(self.gr.ntheta):
th3D[:, i, :] = self.gr.colatitude[i]
for i in range(self.gr.nr):
rr3D[:, :, i] = self.gr.radius[i]
s3D = rr3D * np.sin(th3D)
Op = 1./self.gr.radius * (rderavg(self.gr.radius*self.gr.Btheta,
self.gr.radius) - \
thetaderavg(self.gr.Br))
Ot = 1./s3D * phideravg(self.gr.Br, self.gr.minc) - \
1./self.gr.radius * rderavg(self.gr.radius*self.gr.Bphi,
self.gr.radius)
Or = 1./s3D * (thetaderavg(np.sin(th3D)*self.gr.Bphi) - \
phideravg(self.gr.Btheta, self.gr.minc))
data = Op**2+Ot**2+Or**2
data_ic = None
elif field == 'vortzfluct':
th3D = np.zeros_like(self.gr.vphi)
rr3D = np.zeros_like(th3D)
for i in range(self.gr.ntheta):
th3D[:, i, :] = self.gr.colatitude[i]
for i in range(self.gr.nr):
rr3D[:, :, i] = self.gr.radius[i]
s3D = rr3D*np.sin(th3D)
dth = thetaderavg((self.gr.vphi-self.gr.vphi.mean(axis=0))*rr3D*\
np.sin(th3D))
dr = rderavg((self.gr.vphi-self.gr.vphi.mean(axis=0))*rr3D*np.sin(th3D), \
self.gr.radius)
ds = np.sin(th3D)*dr + np.cos(th3D)/rr3D*dth
data = -1./(rr3D*np.sin(th3D)) * \
phideravg(self.gr.vr*np.sin(th3D)+self.gr.vtheta*np.cos(th3D),
self.gr.minc)+ds/(rr3D*np.sin(th3D))
del dr, dth, ds, rr3D, th3D
data_ic = None
if labTex:
label = r"$\omega_z'$"
else:
label = 'vortzfluct'
elif field == 'vortz':
th3D = np.zeros_like(self.gr.vphi)
rr3D = np.zeros_like(th3D)
for i in range(self.gr.ntheta):
th3D[:, i, :] = self.gr.colatitude[i]
for i in range(self.gr.nr):
rr3D[:, :, i] = self.gr.radius[i]
s3D = rr3D*np.sin(th3D)
dth = thetaderavg(self.gr.vphi*rr3D*np.sin(th3D))
dr = rderavg(self.gr.vphi*rr3D*np.sin(th3D), self.gr.radius)
ds = np.sin(th3D)*dr + np.cos(th3D)/rr3D*dth
data = -1./(rr3D*np.sin(th3D)) * \
phideravg(self.gr.vr*np.sin(th3D)+self.gr.vtheta*np.cos(th3D),
self.gr.minc)+ds/(rr3D*np.sin(th3D))
del dr, dth, ds, rr3D, th3D
data_ic = None
if labTex:
label = r'$\omega_z$'
else:
label = 'vortz'
else:
data, data_ic, label = selectField(self.gr, field, labTex, ic=ic)
if normed is None:
normed = diverging_cmap(field)
if cm is None:
cm = default_cmap(field)
# Determine the radius
r /= (1-self.gr.radratio) # as we give a normalised radius
ri = self.gr.radratio/(1.-self.gr.radratio)
if r < ri and data_ic is not None:
ind = np.nonzero(np.where(abs(self.gr.radius_ic-r)
== min(abs(self.gr.radius_ic-r)), 1, 0))
indPlot = ind[0][0]
rad = self.gr.radius_ic[indPlot]*(1.-self.gr.radratio)
rprof = data_ic[..., indPlot]
else:
ind = np.nonzero(np.where(abs(self.gr.radius-r)
== min(abs(self.gr.radius-r)), 1, 0))
indPlot = ind[0][0]
rad = self.gr.radius[indPlot] * (1.-self.gr.radratio)
rprof = data[..., indPlot]
# Shifting the azimuth data by lon_shift
lon_shift = int(lon_shift*self.gr.nphi/360)
rprof = np.roll(rprof, lon_shift,axis=0)
rprof = symmetrize(rprof, self.gr.minc)
radialContour(rprof, rad, label, proj, lon_0, vmax, vmin,
lat_0, levels, cm, normed, cbar, title, lines,
pcolor=pcolor)
[docs] def equat(self, field='vr', levels=defaultLevels, cm=None,
normed=None, vmax=None, vmin=None, cbar=True, title=True,
avg=False, normRad=False, ic=False, pcolor=False):
"""
Plot the equatorial cut of a given field
>>> s = Surf()
>>> # Equatorial cut of the z-vorticity, 65 contour levels
>>> s.equat(field='vortz', levels=65, cm='seismic')
>>> # Minimal plot (no cbar, not title)
>>> s.equat(field='bphi', title=False, cbar=False)
>>> # Control the limit of the colormap from -1e3 to 1e3
>>> s.equat(field='vr', vmin=-1e3, vmax=1e3, levels=33)
>>> # Normalise the contour levels radius by radius
>>> s.equat(field='jphi', normRad=True)
:param field: the name of the input physical quantity you want to
display
:type field: str
:param avg: when set to True, an additional figure which shows
the radial profile of the input physical quantity
(azimuthal average) is also displayed
:type avg: bool
: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 True, except for entropy/temperature plots.
:type normed: bool
:param ic: when set to True, also display the contour levels in
the inner core
:type ic: bool
:param pcolor: when set to True, use pcolormesh instead of contourf
:type pcolor: bool
"""
phi = np.linspace(0., 2.*np.pi, self.gr.nphi)
rr, pphi = np.meshgrid(self.gr.radius, phi)
xx = rr * np.cos(pphi)
yy = rr * np.sin(pphi)
if field in ('vortzfluct', 'wzfluct'):
philoc = np.linspace(0., 2.*np.pi/self.gr.minc, self.gr.npI)
rrloc, pphiloc = np.meshgrid(self.gr.radius, philoc)
vpfluct = self.gr.vphi-self.gr.vphi.mean(axis=0)
vrfluct = self.gr.vr-self.gr.vr.mean(axis=0)
dr = rderavg(rrloc*vpfluct[:,self.gr.ntheta//2,:], self.gr.radius,
exclude=True)
equator = 1./rrloc*(dr-phideravg(vrfluct[:,self.gr.ntheta//2,:],
self.gr.minc))
if labTex:
label = r"$\omega_z'$"
else:
label = 'wz fluct'
elif field in ('vortz', 'wz'):
philoc = np.linspace(0., 2.*np.pi/self.gr.minc, self.gr.npI)
rrloc, pphiloc = np.meshgrid(self.gr.radius, philoc)
dr = rderavg(rrloc*self.gr.vphi[:,self.gr.ntheta//2,:],
self.gr.radius, exclude=True)
equator = 1./rrloc*(dr - phideravg(self.gr.vr[:,self.gr.ntheta//2,:],
self.gr.minc))
if labTex:
label = r'$\omega_z$'
else:
label = 'vortz'
elif field == 'jz':
philoc = np.linspace(0., 2.*np.pi/self.gr.minc, self.gr.npI)
rrloc, pphiloc = np.meshgrid(self.gr.radius, philoc)
dr = rderavg(rrloc*self.gr.Bphi[:,self.gr.ntheta//2,:],
self.gr.radius, exclude=True)
equator = 1./rrloc*(dr - phideravg(self.gr.Br[:,self.gr.ntheta//2,:],
self.gr.minc))
if labTex:
label = r'$j_z$'
else:
label = 'jz'
elif field == 'vopot':
philoc = np.linspace(0., 2.*np.pi/self.gr.minc, self.gr.npI)
rrloc, pphiloc = np.meshgrid(self.gr.radius, philoc)
dr = rderavg(rrloc*self.gr.vphi[:,self.gr.ntheta//2,:],
self.gr.radius, exclude=True)
wz = 1./rrloc*(dr - phideravg(self.gr.vr[:,self.gr.ntheta//2,:],
self.gr.minc))
temp0, rho0, beta = anelprof(self.gr.radius, self.gr.strat,
self.gr.polind, self.gr.g0, self.gr.g1,
self.gr.g2)
#equator = (wz + 2./(self.gr.ek))/(rho0)
height = 2. * np.sqrt( self.gr.radius.max()**2-self.gr.radius**2 )
equator = (wz + 2./(self.gr.ek))/(rho0*height)
#equator = wz - 2./(self.gr.ek)*np.log(height)
label = r'PV'
fig1 = plt.figure()
ax1 = fig1.add_subplot(111)
ax1.plot(self.gr.radius, equator.mean(axis=0))
ax1.plot(self.gr.radius, 2./(self.gr.ek)/(rho0*height))
elif field == 'rey':
temp0, rho0, beta = anelprof(self.gr.radius, self.gr.strat,
self.gr.polind, self.gr.g0, self.gr.g1,
self.gr.g2)
vp = self.gr.vphi.copy()
vp = self.gr.vphi- self.gr.vphi.mean(axis=0) # convective vp
data = rho0 * self.gr.vr * vp
if labTex:
label = r'$\rho v_s v_\phi$'
else:
label = r'rho vs vp'
elif field == 'mr':
temp0, rho0, beta = anelprof(self.gr.radius, self.gr.strat,
self.gr.polind, self.gr.g0, self.gr.g1,
self.gr.g2)
data = rho0 * self.gr.vr
if labTex:
label = r'$\rho v_r$'
else:
label = r'rho vr'
else:
data, data_ic, label = selectField(self.gr, field, labTex, ic)
if field not in ('vortz', 'vopot', 'jz', 'vortzfluct'):
equator = data[:, self.gr.ntheta//2, :]
if ic and data_ic is not None:
equator_ic = data_ic[:, self.gr.ntheta//2, :]
equator = symmetrize(equator, self.gr.minc)
if ic and data_ic is not None:
equator_ic = symmetrize(equator_ic, self.gr.minc)
if normed is None:
normed = diverging_cmap(field)
if cm is None:
cm = default_cmap(field)
fig, xx, yy = equatContour(equator, self.gr.radius, self.gr.minc,
label, levels, cm, normed, vmax, vmin,
cbar, title, normRad, pcolor=pcolor)
ax = fig.get_axes()[0]
if ic and data_ic is not None:
phi = np.linspace(0., 2.*np.pi, self.gr.nphi)
rr, pphi = np.meshgrid(self.gr.radius_ic, phi)
xx_ic = rr * np.cos(pphi)
yy_ic = rr * np.sin(pphi)
if vmax is not None and vmin is not None:
cs = np.linspace(vmin, vmax, levels)
else:
if not normed:
cs = levels
else:
vmax = max(abs(equator.max()), abs(equator.min()))
vmin = -vmax
cs = np.linspace(vmin, vmax, levels)
if pcolor:
if normed:
ax.pcolormesh(xx_ic, yy_ic, equator_ic, cmap=cm, antialiased=True,
shading='gouraud', vmax=vmax, vmin=vmin)
else:
ax.pcolormesh(xx_ic, yy_ic, equator_ic, cmap=cm, antialiased=True,
shading='gouraud')
else:
ax.contourf(xx_ic, yy_ic, equator_ic, cs, cmap=cm, extend='both')
# Variable conductivity: add a dashed line
if hasattr(self.gr, 'nVarCond'):
if self.gr.nVarCond == 2:
radi = self.gr.con_RadRatio * self.gr.radius[0]
ax.plot(radi*np.cos(phi), radi*np.sin(phi), 'k--', lw=1.5)
# If avg is requested, then display an additional figure
# with azimutal average
if avg:
fig1 = plt.figure()
ax1 = fig1.add_subplot(111)
ax1.plot(self.gr.radius, equator.mean(axis=0))
ax1.set_xlabel('Radius')
ax1.set_ylabel(label)
ax1.set_xlim(self.gr.radius.min(), self.gr.radius.max())
[docs] def avg(self, field='vphi', levels=defaultLevels, cm=None,
normed=None, vmax=None, vmin=None, cbar=True, title=True,
pol=False, tor=False, mer=False, merLevels=16, polLevels=16,
ic=False, lines=False, pcolor=False):
"""
Plot the azimutal average of a given field.
>>> s = Surf()
>>> # Axisymmetric zonal flows, 65 contour levels
>>> s.avg(field='vp', levels=65, cm='seismic')
>>> # Minimal plot (no cbar, not title)
>>> s.avg(field='Br', title=False, cbar=False)
>>> # Axisymmetric Bphi + poloidal field lines
>>> s.avg(field='Bp', pol=True, polLevels=8)
>>> # Omega-effect, contours truncated from -1e3 to 1e3
>>> s.avg(field='omeffect', vmax=1e3, vmin=-1e3)
:param field: the field you want to display
:type field: str
:param levels: the number of levels in the contourf plot
: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 True, except for entropy/temperature plots.
:type normed: bool
:param pol: diplay the poloidal field lines contours when set to True
:type pol: bool
:param tor: diplay the toroidal axisymmetric field contours when
set to True
:type tor: bool
:param mer: display the meridional circulation contours when
set to True
:type mer: bool
:param merLevels: number of contour levels to display meridional
circulation
:type merLevels: int
:param polLevels: number of contour levels to display poloidal
field lines
:type polLevels: int
:param ic: when set to True, also display the contour levels in
the inner core
:type ic: bool
:param lines: when set to True, over-plot solid lines to highlight
the limits between two adjacent contour levels
:type lines: bool
:param pcolor: when set to True, use pcolormesh instead of contourf
:type pcolor: bool
"""
if pol:
if ic:
rr2D = np.zeros((self.gr.ntheta, self.gr.nr+len(self.gr.radius_ic)-1),
dtype=self.precision)
th2D = np.zeros_like(rr2D)
data = np.zeros_like(rr2D)
brm = self.gr.Br.mean(axis=0)
brm_ic = self.gr.Br_ic.mean(axis=0)
brm = np.concatenate((brm, brm_ic[:, 1:]), axis=-1)
for i in range(self.gr.ntheta):
th2D[i, :] = self.gr.colatitude[i]+np.pi/2.
for i in range(self.gr.nr):
rr2D[:, i] = self.gr.radius[i]
for i in range(len(self.gr.radius_ic)-1):
rr2D[:, i+self.gr.nr] = self.gr.radius_ic[i+1]
s2D = rr2D * np.abs(np.cos(th2D))
data[0, :] = -0.5*s2D[0, :]*brm[0, :]*self.gr.colatitude[0]
for i in range(1, self.gr.ntheta):
data[i, :] = data[i-1, :] \
- (s2D[i, :]*brm[i, :]+s2D[i-1, :]*brm[i-1, :]) *\
(th2D[i, :]-th2D[i-1, :])
dataerr = data[-1, :]-0.5*(s2D[-1, :]*brm[-1, :]) *\
(np.pi-self.gr.colatitude[-1])
for i in range(self.gr.ntheta):
data[i, :] = data[i, :] - \
dataerr*self.gr.colatitude[i]/np.pi
poloLines = 0.5*data/np.cos(th2D)
else:
rr2D = np.zeros((self.gr.ntheta, self.gr.nr),
dtype=self.precision)
th2D = np.zeros_like(rr2D)
data = np.zeros_like(rr2D)
brm = self.gr.Br.mean(axis=0)
for i in range(self.gr.ntheta):
rr2D[i, :] = self.gr.radius
th2D[i, :] = self.gr.colatitude[i]+np.pi/2.
s2D = rr2D * np.abs(np.cos(th2D))
data[0, :] = -0.5*s2D[0, :]*brm[0, :]*self.gr.colatitude[0]
for i in range(1, self.gr.ntheta):
data[i, :] = data[i-1, :] \
- (s2D[i, :]*brm[i, :]+s2D[i-1, :]*brm[i-1, :]) *\
(th2D[i, :]-th2D[i-1, :])
dataerr = data[-1, :]-0.5*(s2D[-1, :]*brm[-1, :]) *\
(np.pi-self.gr.colatitude[-1])
for i in range(self.gr.ntheta):
data[i, :] = data[i, :] - \
dataerr*self.gr.colatitude[i]/np.pi
poloLines = 0.5*data/np.cos(th2D)
if mer:
rr2D = np.zeros((self.gr.ntheta, self.gr.nr), dtype=self.precision)
th2D = np.zeros_like(rr2D)
data = np.zeros_like(rr2D)
if hasattr(self.gr, 'strat'):
if (self.gr.strat != 0.):
temp, rho, beta = anelprof(self.gr.radius, self.gr.strat,
self.gr.polind, g0=self.gr.g0,
g1=self.gr.g1, g2=self.gr.g2)
else:
rho = 1.
else:
rho = 1.
vrm = self.gr.vr.mean(axis=0)*rho
for i in range(self.gr.ntheta):
rr2D[i, :] = self.gr.radius
th2D[i, :] = self.gr.colatitude[i]+np.pi/2.
s2D = rr2D * np.abs(np.cos(th2D))
data[0, :] = -0.5*s2D[0, :]*vrm[0, :]*self.gr.colatitude[0]
for i in range(1, self.gr.ntheta):
data[i, :] = data[i-1, :] \
- (s2D[i, :]*vrm[i, :]+s2D[i-1, :]*vrm[i-1, :]) *\
(th2D[i, :]-th2D[i-1, :])
dataerr = data[-1, :]-0.5*(s2D[-1, :]*vrm[-1, :]) *\
(np.pi-self.gr.colatitude[-1])
for i in range(self.gr.ntheta):
data[i, :] = data[i, :] - dataerr*self.gr.colatitude[i]/np.pi
meriLines = 0.5*data/np.cos(th2D)
if field in ('Vs', 'vs', 'us', 'Us'):
vr = self.gr.vr
vt = self.gr.vtheta
thlin = np.linspace(0., np.pi, self.gr.ntheta)
th3D = np.zeros_like(self.gr.vr)
for i in range(self.gr.ntheta):
th3D[:, i, :] = thlin[i]
data = vr * np.sin(th3D) + vt * np.cos(th3D)
label = 'Vs'
elif field == 'entropyreduced':
tt = self.gr.entropy.mean(axis=0).mean(axis=0)
data = self.gr.entropy-tt
label = 'tt'
elif field in ('Vz', 'vz', 'uz', 'Uz'):
vr = self.gr.vr
vt = self.gr.vtheta
thlin = np.linspace(0., np.pi, self.gr.ntheta)
th3D = np.zeros_like(self.gr.vr)
for i in range(self.gr.ntheta):
th3D[:, i, :] = thlin[i]
data = vr * np.cos(th3D) - vt * np.sin(th3D)
label = 'Vz'
elif field == 'Omega':
if labTex:
label = r'$\Omega$'
else:
label = 'omega'
th2D = np.zeros((self.gr.ntheta, self.gr.nr), dtype=self.precision)
rr2D = np.zeros_like(th2D)
for i in range(self.gr.ntheta):
th2D[i, :] = self.gr.colatitude[i]
rr2D[i, :] = self.gr.radius
s2D = rr2D * np.sin(th2D)
data = self.gr.vphi/s2D + 1./self.gr.ek
elif field == 'jphi':
if labTex:
label = r'$j_\phi$'
else:
label = 'jphi'
th2D = np.zeros((self.gr.ntheta, self.gr.nr), dtype=self.precision)
rr2D = np.zeros_like(th2D)
for i in range(self.gr.ntheta):
th2D[i, :] = self.gr.colatitude[i]
rr2D[i, :] = self.gr.radius
Brm = self.gr.Br.mean(axis=0)
Btm = self.gr.Btheta.mean(axis=0)
data = 1./rr2D*(rderavg(rr2D*Btm, self.gr.radius) - thetaderavg(Brm))
elif field == 'ohm':
if labTex:
label = r'$\lambda\,j^2$'
else:
label = 'Ohmic dissipation'
th3D = np.zeros_like(self.gr.Bphi)
rr3D = np.zeros_like(th3D)
for i in range(self.gr.ntheta):
th3D[:, i, :] = self.gr.colatitude[i]
for i in range(self.gr.nr):
rr3D[:, :, i] = self.gr.radius[i]
s3D = rr3D * np.sin(th3D)
Op = 1./self.gr.radius * (rderavg(self.gr.radius*self.gr.Btheta,
self.gr.radius) - \
thetaderavg(self.gr.Br))
Ot = 1./s3D * phideravg(self.gr.Br, self.gr.minc) - \
1./self.gr.radius * rderavg(self.gr.radius*self.gr.Bphi,
self.gr.radius)
Or = 1./s3D * (thetaderavg(np.sin(th3D)*self.gr.Bphi) - \
phideravg(self.gr.Btheta, self.gr.minc))
data = Op**2+Ot**2+Or**2
if hasattr(self.gr, 'nVarCond') and self.gr.nVarCond == 2:
rad = MagicRadial(field='varCond', iplot=False)
data *= rad.lmbda[::-1] # it starts from ri in MagicRadial
elif field == 'omeffect':
if labTex:
label = r'$\Omega$-effect'
else:
label = r'omega-effect'
rr2D = np.zeros((self.gr.ntheta, self.gr.nr), dtype=self.precision)
th2D = np.zeros_like(rr2D)
for i in range(self.gr.ntheta):
th2D[i, :] = self.gr.colatitude[i]
rr2D[i, :] = self.gr.radius
brm = self.gr.Br.mean(axis=0)
btm = self.gr.Btheta.mean(axis=0)
bpm = self.gr.Bphi.mean(axis=0)
vrm = self.gr.vr.mean(axis=0)
vtm = self.gr.vtheta.mean(axis=0)
vpm = self.gr.vphi.mean(axis=0)
dvpdr = rderavg(vpm, self.gr.radius)
dvpdt = thetaderavg(vpm)
# B. Brown
# Phi component of <B> dot grad <u>
#data = brm*dvpdr+btm/rr2D*dvpdt+vrm*bpm/rr2D+\
#vtm*bpm*np.cos(th2D)/(np.sin(th2D)*rr2D)
# M. Schrinner and U. Christensen
# Phi component of curl <Vphi> x <B>
data = brm*dvpdr+btm/rr2D*dvpdt-vpm*brm/rr2D-\
vpm*btm*np.cos(th2D)/(np.sin(th2D)*rr2D)
elif field in ('flux'):
label = 'flux'
temp0, rho0, beta0 = anelprof(self.gr.radius, self.gr.strat,
self.gr.polind, self.gr.g0, self.gr.g1,
self.gr.g2)
ssm = self.gr.entropy.mean(axis=0)
data = rderavg(ssm, self.gr.radius)
elif field == 'alphaeffect':
if labTex:
label = r'$-\alpha \langle B_\phi\rangle$'
else:
label = 'alpha*Bphi'
th3D = np.zeros_like(self.gr.vphi)
rr3D = np.zeros_like(th3D)
for i in range(self.gr.ntheta):
th3D[:, i, :] = self.gr.colatitude[i]
for i in range(self.gr.nr):
rr3D[:, :, i] = self.gr.radius[i]
s3D = rr3D * np.sin(th3D)
vp = self.gr.vphi-self.gr.vphi.mean(axis=0)
vt = self.gr.vtheta - self.gr.vtheta.mean(axis=0)
vr = self.gr.vr-self.gr.vr.mean(axis=0)
wp = 1./self.gr.radius * (rderavg(self.gr.radius*self.gr.vtheta,
self.gr.radius) - \
thetaderavg(self.gr.vr))
wt = 1./s3D * phideravg(self.gr.vr, self.gr.minc) - \
1./self.gr.radius * rderavg(self.gr.radius*self.gr.vphi,
self.gr.radius)
wr = 1./s3D * (thetaderavg(np.sin(th3D)*self.gr.vphi) - \
phideravg(self.gr.vtheta, self.gr.minc))
data = -self.gr.Bphi.mean(axis=0)*(vr*wr+vt*wt+vp*wp)
elif field == 'emf':
if labTex:
label = r"$\langle u'\times B'\rangle_\phi$"
else:
label = 'emf'
vrp = self.gr.vr-self.gr.vr.mean(axis=0)
vtp = self.gr.vtheta-self.gr.vtheta.mean(axis=0)
brp = self.gr.Br-self.gr.Br.mean(axis=0)
btp = self.gr.Btheta-self.gr.Btheta.mean(axis=0)
data = vrp*btp-vtp*brp
elif field in ('hz', 'Hz'):
if labTex:
label = r'$H_z$'
else:
label = 'Hz'
th3D = np.zeros_like(self.gr.vr)
rr3D = np.zeros_like(self.gr.vr)
for i in range(self.gr.ntheta):
th3D[:, i, :] = self.gr.colatitude[i]
for i in range(self.gr.nr):
rr3D[:, :, i] = self.gr.radius[i]
s3D = rr3D * np.sin(th3D)
vs = self.gr.vr * np.sin(th3D) + self.gr.vtheta * np.cos(th3D)
vz = self.gr.vr * np.cos(th3D) - self.gr.vtheta * np.sin(th3D)
vortz = 1./s3D*(-phideravg(vs, self.gr.minc) +
sderavg(s3D*self.gr.vphi, self.gr.radius))
data = vortz * vz
denom = np.sqrt(np.mean(vz**2, axis=0)*np.mean(vortz**2, axis=0))
elif field == 'enstrophy':
label = 'Enstrophy'
normed = False
data = self.vortz**2
elif field in ('helicity', 'hel', 'Hel', 'Helicity'):
label = 'Helicity'
th3D = np.zeros_like(self.gr.vphi)
rr3D = np.zeros_like(th3D)
for i in range(self.gr.ntheta):
th3D[:, i, :] = self.gr.colatitude[i]
if self.gr.radratio != 0:
for i in range(self.gr.nr):
rr3D[:, :, i] = self.gr.radius[i]
else:
for i in range(self.gr.nr-1):
rr3D[:, :, i] = self.gr.radius[i]
rr3D[:, :, -1] = 1e-9 # dummy small value in case of full sphere
s3D = rr3D * np.sin(th3D)
wp = 1./self.gr.radius * (rderavg(self.gr.radius*self.gr.vtheta,
self.gr.radius) - \
thetaderavg(self.gr.vr))
wt = 1./s3D * phideravg(self.gr.vr, self.gr.minc) - \
1./self.gr.radius * rderavg(self.gr.radius*self.gr.vphi, self.gr.radius)
wr = 1./s3D * (thetaderavg(np.sin(th3D)*self.gr.vphi) - \
phideravg(self.gr.vtheta, self.gr.minc))
data = self.gr.vr*wr+self.gr.vtheta*wt+self.gr.vphi*wp
self.hel = data.mean(axis=0)
elif field == 'poloidal':
label = 'poloidal field lines'
rr2D = np.zeros((self.gr.ntheta, self.gr.nr), dtype=self.precision)
th2D = np.zeros_like(rr2D)
data = np.zeros_like(rr2D)
brm = self.gr.Br.mean(axis=0)
for i in range(self.gr.ntheta):
rr2D[i, :] = self.gr.radius
th2D[i, :] = self.gr.colatitude[i]+np.pi/2.
s2D = rr2D * np.abs(np.cos(th2D))
data[0, :] = -0.5*s2D[0, :]*brm[0, :]*self.gr.colatitude[0]
for i in range(1, self.gr.ntheta):
data[i, :] = data[i-1, :] \
-(s2D[i, :]*brm[i, :]+s2D[i-1,:]*brm[i-1,:])* \
(th2D[i,:]-th2D[i-1,:])
dataerr = data[-1, :]-0.5*(s2D[-1,:]*brm[-1,:])*\
(np.pi-self.gr.colatitude[-1])
for i in range(self.gr.ntheta):
data[i, :] = data[i, :] - dataerr*self.gr.colatitude[i]/np.pi
data = 0.5*data/np.cos(th2D)
elif field == 'meridional':
label = "meridional circulation"
rr2D = np.zeros((self.gr.ntheta, self.gr.nr), dtype=self.precision)
th2D = np.zeros_like(rr2D)
data = np.zeros_like(rr2D)
temp, rho, beta = anelprof(self.gr.radius, self.gr.strat,
self.gr.polind,
g0=self.gr.g0, g1=self.gr.g1, g2=self.gr.g2)
vrm = self.gr.vr.mean(axis=0)*rho
for i in range(self.gr.ntheta):
rr2D[i, :] = self.gr.radius
th2D[i, :] = self.gr.colatitude[i]+np.pi/2.
s2D = rr2D * np.abs(np.cos(th2D))
data[0, :] = -0.5*s2D[0, :]*vrm[0, :]*self.gr.colatitude[0]
for i in range(1, self.gr.ntheta):
data[i, :] = data[i-1, :] \
-(s2D[i, :]*vrm[i, :]+s2D[i-1,:]*vrm[i-1,:])* \
(th2D[i,:]-th2D[i-1,:])
dataerr = data[-1, :]-0.5*(s2D[-1,:]*vrm[-1,:])*\
(np.pi-self.gr.colatitude[-1])
for i in range(self.gr.ntheta):
data[i, :] = data[i, :] - dataerr*self.gr.colatitude[i]/np.pi
data = 0.5*data/np.cos(th2D)
elif field in ('ra', 'ratio'):
label = 'Ratio'
data = self.gr.vphi**2#/(self.gr.vphi**2+\
#self.gr.vtheta**2+self.gr.vr**2)
denom = np.mean(self.gr.vphi**2+ self.gr.vtheta**2+self.gr.vr**2,
axis=0)
#denom = 1.
elif field == 'beta':
if labTex:
label = r'$\beta$'
else:
label = r'd ln rho/dr'
temp0, rho0, beta = anelprof(self.gr.radius, self.gr.strat,
self.gr.polind, self.gr.g0, self.gr.g1,
self.gr.g2)
data = beta * np.ones_like(self.gr.vr)#* self.gr.vr
elif field in ('angular', 'AM'):
label = 'Angular momentum'
th2D = np.zeros((self.gr.ntheta, self.gr.nr), dtype=self.precision)
rr2D = np.zeros_like(th2D)
rho2D = np.zeros_like(th2D)
if hasattr(self.gr, 'strat'):
temp0, rho0, beta = anelprof(self.gr.radius, self.gr.strat,
self.gr.polind, self.gr.g0, self.gr.g1,
self.gr.g2)
else:
rho0 = 1.
for i in range(self.gr.ntheta):
rho2D[i, :] = rho0
rr2D[i, :] = self.gr.radius
th2D[i, :] = self.gr.colatitude[i]
s2D = rr2D * np.sin(th2D)
if self.gr.ek > 0: # Outer boundary rotating
norm = self.gr.radius[0]**2/self.gr.ek
data = (self.gr.vphi*s2D+1./self.gr.ek*s2D**2)/norm
else: # Outer boundary non-rotating, ek = -1
norm = self.gr.omega_ic1*self.gr.radius[-1]**2
data = (self.gr.vphi*s2D)/norm
elif field in ('Cr', 'cr'):
if hasattr(self.gr, 'strat'):
temp0, rho0, beta = anelprof(self.gr.radius, self.gr.strat,
self.gr.polind, self.gr.g0,
self.gr.g1, self.gr.g2)
else:
rho0 = 1.
vr = self.gr.vr
vt = self.gr.vtheta
vp = self.gr.vphi.copy()
vp = self.gr.vphi - self.gr.vphi.mean(axis=0) # convective vp
thlin = np.linspace(0., np.pi, self.gr.ntheta)
th3D = np.zeros_like(self.gr.vr)
for i in range(self.gr.ntheta):
th3D[:, i, :] = thlin[i]
vs = vr * np.sin(th3D) + vt * np.cos(th3D)
data = vs * vp
denom = np.sqrt(np.mean(vs**2, axis=0) * np.mean(vp**2, axis=0))
if labTex:
label = r'$\langle v_s v_\phi\rangle$'
else:
label = 'vs vphi'
elif field == 'vortz':
data = self.vortz
label = 'vortz'
elif field == 'vopot':
temp0, rho0, beta = anelprof(self.gr.radius, self.gr.strat,
self.gr.polind, self.gr.g0, self.gr.g1,
self.gr.g2)
height = 2. * np.sqrt( self.gr.radius.max()**2-self.gr.radius**2 )
data = (self.vortz+2./self.gr.ek)/(rho0*height)
label = 'Pot. vort.'
elif field == 'rhocr':
temp0, rho0, beta = anelprof(self.gr.radius, self.gr.strat,
self.gr.polind, self.gr.g0, self.gr.g1,
self.gr.g2)
vr = self.gr.vr
vt = self.gr.vtheta
vp = self.gr.vphi.copy()
vp = self.gr.vphi - self.gr.vphi.mean(axis=0) # convective vp
thlin = np.linspace(0., np.pi, self.gr.ntheta)
th3D = np.zeros_like(self.gr.vr)
for i in range(self.gr.ntheta):
th3D[:, i, :] = thlin[i]
vs = vr * np.sin(th3D) + vt * np.cos(th3D)
data = rho0 * vs * vp
denom = np.sqrt(np.mean(rho0*vs**2, axis=0) *
np.mean(rho0*vp**2, axis=0))
if labTex:
label = r'$C_{s\phi}$'
else:
label = 'Csp'
elif field in ('Cz', 'cz'):
vr = self.gr.vr
vt = self.gr.vtheta
vp = self.gr.vphi.copy()
vp = self.gr.vphi - self.gr.vphi.mean(axis=0) # convective vp
thlin = np.linspace(0., np.pi, self.gr.ntheta)
th3D = np.zeros_like(self.gr.vr)
for i in range(self.gr.ntheta):
th3D[:, i, :] = thlin[i]
vz = vr * np.cos(th3D) - vt * np.sin(th3D)
data = vz * vp
denom = np.sqrt(np.mean(vz**2, axis=0) * np.mean(vp**2, axis=0))
if labTex:
label = r'$\langle v_z v_\phi\rangle$'
else:
label = 'vz vphi'
elif field == 'dvzdz':
if labTex:
label = r'$\partial u_z/\partial z$'
else:
label = 'dvz/dz'
vr = self.gr.vr
vt = self.gr.vtheta
thlin = np.linspace(0., np.pi, self.gr.ntheta)
th3D = np.zeros_like(self.gr.vr)
for i in range(self.gr.ntheta):
th3D[:, i, :] = thlin[i]
data = (vr * np.cos(th3D) - vt * np.sin(th3D))
else:
data, data_ic, label = selectField(self.gr, field, labTex,
ic=ic)
if field not in ('Cr', 'cr', 'ra', 'ratio', 'Cz', 'cz', 'hz', 'jphi',
'rhocr', 'omeffect', 'poloidal', 'flux',
'meridional'):
phiavg = data.mean(axis=0)
if ic and data_ic is not None:
phiavg_ic = data_ic.mean(axis=0)
elif field == 'balance':
phiavg = zderavg(data.mean(axis=0), self.gr.radius, exclude=True)
phiavg = phiavg + data1.mean(axis=0)
elif field == 'dvzdz':
phiavg = zderavg(data.mean(axis=0), self.gr.radius, exclude=True)
elif field in ('omeffect', 'poloidal', 'flux', 'meridional', 'jphi'):
phiavg = data
else:
ro = self.gr.radius[0]
ri = self.gr.radius[-1]
fac = 2./(np.pi*(ro**2-ri**2))
facOTC = ro**2.*(np.pi-2.*np.arcsin(self.gr.radratio))/2. \
-ri**2*np.sqrt(1.-self.gr.radratio**2)/self.gr.radratio
facOTC = 1./facOTC
facITC = ri**2*np.sqrt(1.-self.gr.radratio**2)/self.gr.radratio \
+(ro**2-ri**2)* np.arcsin(self.gr.radratio) \
-ri**2/2.*(np.pi - 2.*np.arcsin(self.gr.radratio))
facITC = 1./facITC
#mask = np.where(denom == 0, 1, 0)
phiavg = data.mean(axis=0)
TC = np.array([], dtype=self.precision)
outTC = np.array([], dtype=self.precision)
inTC = np.array([], dtype=self.precision)
denomTC = np.array([], dtype=self.precision)
denomoutTC = np.array([], dtype=self.precision)
denominTC = np.array([], dtype=self.precision)
integ = np.array([], dtype=self.precision)
for k, th in enumerate(self.gr.colatitude):
rr = self.gr.radius[::-1]
dat = phiavg[k, ::-1] * rr
dat2 = denom[k, ::-1] * rr
corr = intcheb(dat, self.gr.nr-1, ri, ro)
TC = np.append(TC, corr)
corr2 = intcheb(dat2, self.gr.nr-1, ri, ro)
denomTC = np.append(denomTC, corr2)
if th >= np.arcsin(self.gr.radratio) and \
th <= np.pi - np.arcsin(self.gr.radratio):
# Outside tangent cylinder
val = trapz(dat[rr >= ri/np.sin(th)], rr[rr >= ri/np.sin(th)])
outTC = np.append(outTC, val)
integ = np.append(integ, th)
val2 = trapz(dat2[rr >= ri/np.sin(th)], rr[rr >= ri/np.sin(th)])
denomoutTC = np.append(denomoutTC, val2)
# Inside tangent cylinder
val = trapz(dat[rr < ri/np.sin(th)], rr[rr < ri/np.sin(th)])
inTC = np.append(inTC, val)
val2 = trapz(dat2[rr < ri/np.sin(th)], rr[rr < ri/np.sin(th)])
denominTC = np.append(denominTC, val2)
else:
val= intcheb(dat, self.gr.nr-1, ri, ro)
inTC = np.append(inTC, val)
val2= intcheb(dat2, self.gr.nr-1, ri, ro)
denominTC = np.append(denominTC, val2)
num = fac*trapz(TC, self.gr.colatitude)
den = fac*trapz(denomTC, self.gr.colatitude)
print('Correlation', num/den)
num = facOTC*trapz(outTC, integ)
den = facOTC*trapz(denomoutTC, integ)
print('Correlation out TC', num/den)
num = facITC*trapz(inTC, self.gr.colatitude)
den = facITC*trapz(denominTC, self.gr.colatitude)
print('Correlation in TC', num/den)
mask = np.where(denom == 0, 1, 0)
phiavg /= (denom + mask)
# phiavg /= den
if normed is None:
normed = diverging_cmap(field)
if cm is None:
cm = default_cmap(field)
fig, xx, yy, im = merContour(phiavg, self.gr.radius, label, levels, cm,
normed, vmax, vmin, cbar, title, lines=lines,
pcolor=pcolor)
ax = fig.get_axes()[0]
if ic:
th = np.linspace(0., np.pi, phiavg.shape[0])
ri = self.gr.radratio/(1.-self.gr.radratio)
rr, tth = np.meshgrid(self.gr.radius_ic, th)
xx_ic = rr * np.sin(tth)
yy_ic = rr * np.cos(tth)
if data_ic is not None:
if vmax is not None and vmin is not None:
cs = np.linspace(vmin, vmax, levels)
else:
if not normed:
cs = levels
else:
vmax = max(abs(phiavg.max()), abs(phiavg.min()))
vmin = -vmax
cs = np.linspace(vmin, vmax, levels)
if pcolor:
if normed:
ax.pcolormesh(xx_ic, yy_ic, phiavg_ic, cmap=cm,
antialiased=True, shading='gouraud',
vmax=vmax, vmin=vmin)
else:
ax.pcolormesh(xx_ic, yy_ic, phiavg_ic, cmap=cm,
antialiased=True, shading='gouraud')
else:
ax.contourf(xx_ic, yy_ic, phiavg_ic, cs, cmap=cm,
extend='both')
ax.plot([0, 0], [-ri, ri], 'k-')
if pol:
if ic:
xx_big = np.concatenate((xx, xx_ic[:, 1:]), axis=-1)
yy_big = np.concatenate((yy, yy_ic[:, 1:]), axis=-1)
ax.contour(xx_big, yy_big, poloLines, polLevels, colors=['k'],
linewidths=[0.8, 0.8])
else:
ax.contour(xx, yy, poloLines, polLevels, colors=['k'],
linewidths=[0.8, 0.8])
elif tor:
toroLines = self.gr.Bphi.mean(axis=0)
ax.contour(xx, yy, toroLines, polLevels, colors=['k'],
linewidths=[0.8])
elif mer:
maxMeri = abs(meriLines).max()
minMeri = -maxMeri
lev = np.linspace(minMeri, maxMeri, merLevels)
ax.contour(xx, yy, meriLines, lev, colors=['k'],
linewidths=[0.8])
# Variable conductivity: add a dashed line
if hasattr(self.gr, 'nVarCond') and self.gr.nVarCond == 2:
radi = self.gr.con_RadRatio * self.gr.radius[0]
th = np.linspace(0, np.pi, self.gr.ntheta)
ax.plot(radi*np.sin(th), radi*np.cos(th), 'k--')
[docs] def slice(self, field='Bphi', lon_0=0., levels=defaultLevels, cm=None,
normed=None, vmin=None, vmax=None, cbar=True, title=True,
grid=False, nGridLevs=16, normRad=False, ic=False):
"""
Plot an azimuthal slice of a given field.
>>> s = Surf()
>>> # vphi at 0, 30, 60 degrees in longitude
>>> s.slice(field='vp', lon_0=[0, 30, 60], levels=65, cm='seismic')
>>> # Minimal plot (no cbar, not title)
>>> s.avg(field='vp', lon_0=32, title=False, cbar=False)
>>> # Axisymmetric Bphi + poloidal field lines
>>> s.avg(field='Bp', pol=True, polLevels=8)
>>> # Omega-effect, contours truncated from -1e3 to 1e3
>>> s.avg(field='omeffect', vmax=1e3, vmin=-1e3)
:param field: the field you want to display
:type field: str
:param lon_0: the longitude of the slice in degrees, or a list of longitudes
:type lon_0: float or list
:param levels: the number of levels in the contourf plot
: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 grid: display or hide the grid
:type grid: bool
:param nGridLevs: number of grid levels
:type nGridLevs: int
:param normRad: when set to True, the contour levels are normalised
radius by radius (default is False)
:type normRad: bool
:param ic: when set to True, also display the contour levels in
the inner core
:type ic: bool
"""
if field in ('Vs', 'vs', 'us', 'Us'):
if labTex:
label = r'$v_s$'
else:
label = 'vs'
vr = self.gr.vr
vt = self.gr.vtheta
thlin = np.linspace(0., np.pi, self.gr.ntheta)
th3D = np.zeros_like(self.gr.vr)
for i in range(self.gr.ntheta):
th3D[:, i, :] = thlin[i]
data = vr * np.sin(th3D) + vt * np.cos(th3D)
elif field in ('Vz', 'vz', 'Uz', 'uz'):
if labTex:
label = r'$v_z$'
else:
label = 'vz'
vr = self.gr.vr
vt = self.gr.vtheta
thlin = np.linspace(0., np.pi, self.gr.ntheta)
th3D = np.zeros_like(self.gr.vr)
for i in range(self.gr.ntheta):
th3D[:, i, :] = thlin[i]
data = vr * np.cos(th3D) - vt * np.sin(th3D)
elif field == 'anel':
if labTex:
label = r'$\beta v_r$'
else:
label = r'beta vr'
temp0, rho0, beta = anelprof(self.gr.radius, self.gr.strat,
self.gr.polind, self.gr.g0, self.gr.g1,
self.gr.g2)
data = beta * self.gr.vr
elif field == 'dvzdz':
if labTex:
label = r'$\partial v_z / \partial z$'
else:
label = 'dvz/dz'
vr = self.gr.vr
vt = self.gr.vtheta
thlin = np.linspace(0., np.pi, self.gr.ntheta)
th3D = np.zeros_like(self.gr.vr)
for i in range(self.gr.ntheta):
th3D[:, i, :] = thlin[i]
data = vr * np.cos(th3D) - vt * np.sin(th3D)
elif field == 'ohm':
label = 'Ohmic dissipation'
th3D = np.zeros_like(self.gr.Bphi)
rr3D = np.zeros_like(th3D)
for i in range(self.gr.ntheta):
th3D[:, i, :] = self.gr.colatitude[i]
for i in range(self.gr.nr):
rr3D[:, :, i] = self.gr.radius[i]
s3D = rr3D * np.sin(th3D)
Op = 1./self.gr.radius * (rderavg(self.gr.radius*self.gr.Btheta,
self.gr.radius) - \
thetaderavg(self.gr.Br))
Ot = 1./s3D * phideravg(self.gr.Br, self.gr.minc) - \
1./self.gr.radius * rderavg(self.gr.radius*self.gr.Bphi,
self.gr.radius)
Or = 1./s3D * (thetaderavg(np.sin(th3D)*self.gr.Bphi) - \
phideravg(self.gr.Btheta, self.gr.minc))
data = Op**2+Ot**2+Or**2
elif field == 'flux':
data = rderavg(self.gr.entropy, self.gr.radius)
label = 'flux'
elif field == 'mag_pres_force_r':
data = -rderavg(self.gr.Br**2+self.gr.Btheta**2+self.gr.Bphi**2,
self.gr.radius)/2.0
label = 'Rad. mag. pres. force'
elif field == 'mag_pres_force_t':
rr3D = np.zeros_like(self.gr.Bphi)
for i in range(self.gr.nr):
rr3D[:, :, i] = self.gr.radius[i]
data = -thetaderavg(self.gr.Br**2+self.gr.Btheta**2+self.gr.Bphi**2,
order=2)/rr3D/2.0
label = 'Lati. mag. pres. force'
elif field == 'mag_pres_force_p':
th3D = np.zeros_like(self.gr.Bphi)
rr3D = np.zeros_like(th3D)
for i in range(self.gr.nr):
rr3D[:, :, i] = self.gr.radius[i]
for i in range(self.gr.ntheta):
th3D[:, i, :] = self.gr.colatitude[i]
data = -phideravg(self.gr.Br**2+self.gr.Btheta**2+self.gr.Bphi**2,
self.gr.minc)/(rr3D*np.sin(th3D))/2.0
label = 'Longi. mag. pres. force'
elif field == 'mag_tens_force_r':
th3D = np.zeros_like(self.gr.Bphi)
rr3D = np.zeros_like(th3D)
for i in range(self.gr.nr):
rr3D[:, :, i] = self.gr.radius[i]
for i in range(self.gr.ntheta):
th3D[:, i, :] = self.gr.colatitude[i]
data = self.gr.Br * rderavg(self.gr.Br, self.gr.radius) + \
self.gr.Btheta * thetaderavg(self.gr.Br, order=2) / rr3D + \
self.gr.Bphi * phideravg(self.gr.Br, self.gr.minc) / \
np.sin(th3D) / rr3D - (self.gr.Btheta**2 + self.gr.Bphi**2) / rr3D
label = 'Rad. tens. force'
elif field == 'mag_tens_force_t':
th3D = np.zeros_like(self.gr.Bphi)
rr3D = np.zeros_like(th3D)
for i in range(self.gr.nr):
rr3D[:, :, i] = self.gr.radius[i]
for i in range(self.gr.ntheta):
th3D[:, i, :] = self.gr.colatitude[i]
data = self.gr.Br * rderavg(self.gr.Btheta, self.gr.radius) + \
self.gr.Btheta * thetaderavg(self.gr.Btheta, order=2) / rr3D + \
self.gr.Bphi * phideravg(self.gr.Btheta, self.gr.minc) / \
np.sin(th3D) / rr3D + self.gr.Btheta * self.gr.Br / rr3D - \
self.gr.Bphi**2 * np.arctan(th3D) / rr3D
label = 'Lati. tens. force'
elif field == 'mag_tens_force_p':
th3D = np.zeros_like(self.gr.Bphi)
rr3D = np.zeros_like(th3D)
for i in range(self.gr.nr):
rr3D[:, :, i] = self.gr.radius[i]
for i in range(self.gr.ntheta):
th3D[:, i, :] = self.gr.colatitude[i]
data = self.gr.Br * rderavg(self.gr.Bphi, self.gr.radius) + \
self.gr.Btheta * thetaderavg(self.gr.Bphi, order=2) / rr3D + \
self.gr.Bphi * phideravg(self.gr.Bphi, self.gr.minc) / \
np.sin(th3D) / rr3D + self.gr.Bphi * self.gr.Br / rr3D + \
self.gr.Bphi * self.gr.Btheta * np.arctan(th3D) / rr3D
label = 'Longi. tens. force'
elif field == 'Lorentz_r':
th3D = np.zeros_like(self.gr.Bphi)
rr3D = np.zeros_like(th3D)
for i in range(self.gr.nr):
rr3D[:, :, i] = self.gr.radius[i]
for i in range(self.gr.ntheta):
th3D[:, i, :] = self.gr.colatitude[i]
data = -rderavg(self.gr.Br**2+self.gr.Btheta**2+self.gr.Bphi**2,
self.gr.radius)/2.0 + \
self.gr.Br * rderavg(self.gr.Br, self.gr.radius) + \
self.gr.Btheta * thetaderavg(self.gr.Br, order=2) / rr3D + \
self.gr.Bphi * phideravg(self.gr.Br, self.gr.minc) / \
np.sin(th3D) / rr3D - (self.gr.Btheta**2 + self.gr.Bphi**2) / rr3D
label = 'Radial Lorentz force'
elif field == 'Lorentz_t':
th3D = np.zeros_like(self.gr.Bphi)
rr3D = np.zeros_like(th3D)
for i in range(self.gr.nr):
rr3D[:, :, i] = self.gr.radius[i]
for i in range(self.gr.ntheta):
th3D[:, i, :] = self.gr.colatitude[i]
data = -thetaderavg(self.gr.Br**2+self.gr.Btheta**2+self.gr.Bphi**2,
order=2)/rr3D/2.0 + \
self.gr.Br * rderavg(self.gr.Btheta, self.gr.radius) + \
self.gr.Btheta * thetaderavg(self.gr.Btheta, order=2) / rr3D + \
self.gr.Bphi * phideravg(self.gr.Btheta, self.gr.minc) / \
np.sin(th3D) / rr3D + self.gr.Btheta * self.gr.Br / rr3D - \
self.gr.Bphi**2 * np.arctan(th3D) / rr3D
label = 'Lati. Lorentz force'
elif field == 'Lorentz_p':
th3D = np.zeros_like(self.gr.Bphi)
rr3D = np.zeros_like(th3D)
for i in range(self.gr.nr):
rr3D[:, :, i] = self.gr.radius[i]
for i in range(self.gr.ntheta):
th3D[:, i, :] = self.gr.colatitude[i]
data = -phideravg(self.gr.Br**2+self.gr.Btheta**2+self.gr.Bphi**2,
self.gr.minc)/(rr3D*np.sin(th3D))/2.0 + \
self.gr.Br * rderavg(self.gr.Bphi, self.gr.radius) + \
self.gr.Btheta * thetaderavg(self.gr.Bphi, order=2) / rr3D + \
self.gr.Bphi * phideravg(self.gr.Bphi, self.gr.minc) / \
np.sin(th3D) / rr3D + self.gr.Bphi * self.gr.Br / rr3D + \
self.gr.Bphi * self.gr.Btheta * np.arctan(th3D) / rr3D
label = 'Longi. Lorentz force'
else:
data, data_ic, label = selectField(self.gr, field, labTex, ic)
th = np.linspace(np.pi/2, -np.pi/2, self.gr.ntheta)
rr, tth = np.meshgrid(self.gr.radius, th)
xx = rr * np.cos(tth)
yy = rr * np.sin(tth)
phi = np.linspace(0., 360, self.gr.nphi)
if ic:
ri = self.gr.radratio/(1.-self.gr.radratio)
rr_ic, tth_ic = np.meshgrid(self.gr.radius_ic, th)
xx_ic = rr_ic * np.cos(tth_ic)
yy_ic = rr_ic * np.sin(tth_ic)
lon_0 = np.asarray(lon_0)
if normed is None:
normed = diverging_cmap(field)
if cm is None:
cm = default_cmap(field)
cmap = plt.get_cmap(cm)
if len(lon_0) > 1:
if self.gr.minc > 1:
data = symmetrize(data, self.gr.minc)
if ic and data_ic is not None:
data_ic = symmetrize(data_ic, self.gr.minc)
fig = plt.figure(figsize=(2.5*len(lon_0), 5.1))
fig.subplots_adjust(top=0.99, bottom=0.01, right=0.99, left=0.01,
wspace=0.01)
for k, lon in enumerate(lon_0):
ind = np.nonzero(np.where(abs(phi-lon)
== min(abs(phi-lon)), 1, 0))
indPlot = ind[0][0]
phislice = data[indPlot, ...]
if ic and data_ic is not None:
phislice_ic = data_ic[indPlot, ...]
if field == 'dvzdz':
phislice = zderavg(phislice, self.gr.radius, exclude=True)
elif field == 'balance':
phislice = zderavg(phislice, self.gr.radius, exclude=True)
phislice1 = data1[indPlot, ...]
phislice = phislice + phislice1
if normRad: # Normalise each radius
maxS = np.sqrt(np.mean(phislice**2, axis=0))
phislice[:, maxS != 0.] /= maxS[maxS != 0.]
ax = fig.add_subplot(1, len(lon_0), k+1, frameon=False)
if vmax is not None or vmin is not None:
normed = False
cs = np.linspace(vmin, vmax, levels)
im = ax.contourf(xx, yy, phislice, cs, cmap=cmap,
extend='both')
else:
if not normed:
cs = levels
else:
vmax = max(abs(phislice.max()), abs(phislice.min()))
vmin = -vmax
cs = np.linspace(vmin, vmax, levels)
im = ax.contourf(xx, yy, phislice, cs, cmap=cmap)
ax.plot(self.gr.radius[0]*np.cos(th),
self.gr.radius[0]*np.sin(th), 'k-')
ax.plot(self.gr.radius[-1]*np.cos(th),
self.gr.radius[-1]*np.sin(th), 'k-')
ax.plot([0., 0], [self.gr.radius[-1], self.gr.radius[0]], 'k-')
ax.plot([0., 0], [-self.gr.radius[-1], -self.gr.radius[0]],
'k-')
if ic and data_ic is not None:
im_ic = ax.contourf(xx_ic, yy_ic, phislice_ic, cs,
cmap=cmap, extend='both')
ax.plot([0, 0], [-ri, ri], 'k-')
ax.axis('off')
tit1 = r'${}^\circ$'.format(lon)
ax.text(0.9, 0.9, tit1, fontsize=18, horizontalalignment='right',
verticalalignment='center', transform = ax.transAxes)
# To avoid white lines on pdfs
for c in im.collections:
c.set_edgecolor("face")
else:
ind = np.nonzero(np.where(abs(phi-lon_0[0])
== min(abs(phi-lon_0[0])), 1, 0))
indPlot = ind[0][0]
phislice = data[indPlot, ...]
if ic and data_ic is not None:
phislice_ic = data_ic[indPlot, ...]
if field == 'dvzdz':
phislice = zderavg(phislice, self.gr.radius, exclude=True)
elif field == 'balance':
phislice = zderavg(phislice, self.gr.radius, exclude=True)
phislice1 = data1[indPlot, ...]
phislice = phislice + phislice1
if title:
if cbar:
fig = plt.figure(figsize=(5, 7.5))
ax = fig.add_axes([0.01, 0.01, 0.69, 0.91])
else:
fig = plt.figure(figsize=(3.5, 7.5))
ax = fig.add_axes([0.01, 0.01, 0.98, 0.91])
ax.set_title(label, fontsize=24)
else:
if cbar:
fig = plt.figure(figsize=(5, 7))
ax = fig.add_axes([0.01, 0.01, 0.69, 0.98])
else:
fig = plt.figure(figsize=(3.5, 7))
ax = fig.add_axes([0.01, 0.01, 0.98, 0.98])
if vmax is not None or vmin is not None:
normed = False
cs = np.linspace(vmin, vmax, levels)
im = ax.contourf(xx, yy, phislice, cs, cmap=cmap,
extend='both')
else:
if not normed:
cs = levels
else:
vmax = max(abs(phislice.max()), abs(phislice.min()))
vmin = -vmax
cs = np.linspace(vmin, vmax, levels)
im = ax.contourf(xx, yy, phislice, cs, cmap=cmap)
ax.plot(self.gr.radius[0]*np.cos(th), self.gr.radius[0]*np.sin(th),
'k-', lw=1.5)
ax.plot(self.gr.radius[-1]*np.cos(th),
self.gr.radius[-1]*np.sin(th), 'k-', lw=1.5)
ax.plot([0., 0], [self.gr.radius[-1], self.gr.radius[0]], 'k-',
lw=1.5)
ax.plot([0., 0], [-self.gr.radius[-1], -self.gr.radius[0]], 'k-',
lw=1.5)
if ic and data_ic is not None:
im_ic = ax.contourf(xx_ic, yy_ic, phislice_ic, cs,
cmap=cmap, extend='both')
ax.plot([0, 0], [-ri, ri], 'k-')
if hasattr(self.gr, 'epsS'):
if self.gr.epsS != 0:
rad = MagicRadial(field='anel', iplot=False)
idx = np.nonzero(np.where(abs(rad.dsdr) ==
abs(rad.dsdr).min(), 1, 0))[0][0]
ax.plot(self.gr.radius[idx]*np.cos(th),
self.gr.radius[idx]*np.sin(th), 'k--', lw=2)
if grid:
ax.contour(xx, yy, tth, nGridLevs, colors='k', linestyles='--',
linewidths=0.5)
ax.axis('off')
# Add the colorbar at the right place
pos = ax.get_position()
l, b, w, h = pos.bounds
if cbar:
if title:
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)
# To avoid white lines on pdfs
for c in im.collections:
c.set_edgecolor("face")
def report(nvar=1, levels=defaultLevels, lclean=True):
"""
This subroutine prepares a pdf document that gather some important diagnostics
:param lclean: clean or not the LaTeX files
:type lclean: bool
:param levels: number of contour levels
:param levels: int
:param nvar: number of graphic files
:param nvar: int
"""
file = open('report.tex', 'w')
file.write("\\documentclass[a4paper,10pt]{article}\n")
file.write("\\usepackage[utf8]{inputenc}\n")
file.write("\\usepackage{amsmath,amsfonts,amssymb}\n")
file.write("\\usepackage[francais]{babel}\n")
file.write("\\usepackage[T1]{fontenc}\n")
file.write("\\usepackage[dvips]{graphicx}\n")
file.write("\\usepackage{geometry}\n")
file.write("\\usepackage[pdftex]{xcolor}\n")
file.write("\\geometry{hmargin=1cm,vmargin=2cm}\n")
file.write("\\begin{document}\n")
s = Surf(ivar=nvar)
st = "Ek = {:.2e}, Ra = {:.2e}, Pr = {:.1f}, $N_{\\rho}$={:.2f}, $\\eta$={.1f}".format(
s.gr.ek, s.gr.ra, s.gr.pr, s.gr.strat, s.gr.radratio)
file.write("\\begin{center}\\begin{large}\n")
file.write(" "+st+"\n")
file.write("\\end{large}\\end{center}\n")
r1 = 0.98
r3 = 1.03 * s.gr.radratio
r2 = (r1+r3)/2.
s.avg(field='vp', levels=levels, cm='RdYlBu_r', normed=True)
plt.savefig('vp.png')
plt.close()
s.avg(field='entropy', levels=levels, cm='RdYlBu_r', normed=True)
plt.savefig('entropy.png')
plt.close()
s.equat(field='entropy', levels=levels, cm='RdYlBu_r', normed=False)
plt.savefig('equ_s.png')
plt.close()
s.equat(field='vr', levels=levels, cm='RdYlBu_r', normed=False)
plt.savefig('equ_vr.png')
plt.close()
s.surf(field='vp', cm='RdYlBu_r', levels=levels, r=r1, proj='moll',
normed=False)
plt.savefig('surf_vp.png')
plt.close()
s.surf(field='vp', cm='RdYlBu', levels=levels, r=r2, proj='moll',
normed=False)
plt.savefig('surf_vp_08.png')
plt.close()
s.surf(field='vp', cm='RdYlBu', levels=levels, r=r3, proj='moll',
normed=False)
plt.savefig('surf_vp_06.png')
plt.close()
s.surf(field='vr', cm='RdYlBu', levels=levels, r=r1, proj='moll',
normed=False)
plt.savefig('surf_vr.png')
plt.close()
s.surf(field='vr', cm='RdYlBu', levels=levels, r=r2, proj='moll',
normed=False)
plt.savefig('surf_vr_08.png')
plt.close()
s.surf(field='vr', cm='RdYlBu', levels=levels, r=r3, proj='moll',
normed=False)
plt.savefig('surf_vr_06.png')
plt.close()
file.write("\\begin{figure}[htbp]\n")
file.write(" \\centering\n")
file.write(" \\includegraphics[width=9cm]{equ_s}\n")
file.write(" \\includegraphics[width=9cm]{equ_vr}\n")
file.write(" \\includegraphics[height=9cm]{entropy}\n")
file.write(" \\includegraphics[height=9cm]{vp}\n")
file.write("\\end{figure}\n")
file.write("\\newpage\n")
file.write("\\begin{figure}\n")
file.write(" \\centering\n")
file.write(" \\includegraphics[width=18cm]{surf_vr_06}\n")
file.write(" \\includegraphics[width=18cm]{surf_vr_08}\n")
file.write(" \\includegraphics[width=18cm]{surf_vr}\n")
file.write("\\end{figure}\n")
file.write("\\newpage\n")
file.write("\\begin{figure}\n")
file.write(" \\includegraphics[width=18cm]{surf_vp_06}\n")
file.write(" \\includegraphics[width=18cm]{surf_vp_08}\n")
file.write(" \\includegraphics[width=18cm]{surf_vp}\n")
file.write("\\end{figure}\n")
file.write("\\end{document}")
file.close()
os.system("pdflatex report.tex")
if lclean:
os.system("rm vp.png entropy.png equ_s.png equ_vr.png surf_vp.png \
surf_vr.png surf_vr_06.png surf_vr_08.png surf_vp_06.png\
surf_vp_08.png")
os.system("rm report.log report.aux report.tex")