How to visualize the BFE bases used to make your coefficients
This is easy with pyEXP. Each of the three main basis types supported
by pyEXP, SphericalSL
, Cylindrical
, and FlatDisk
provides
a getBasis
member function that returns the basis functions in
their native geometry.
Let’s work a few simple examples to give you all you need to look at
your bases. A Jupyter notebook implementing these examples,
viewing_a_basis.ipynb
, is available in the pyEXP examples repository in the
Tutorials/Basis directory.
A spherical basis
Start with a simple configuration file for spherical basis and instantiate the basis:
# Make the halo basis config
halo_config="""
---
id: sphereSL
parameters :
numr: 2000 # number of radial grid points
rmin: 0.0001 # smallest radial grid point
rmax: 1.95 # largest radial grid point
Lmax: 4 # maximum spherical harmonic degree
nmax: 10 # maximum radial order
rmapping: 0.0667 # radius for coordinate mapping
modelname: SLGridSph.model # model file name
...
"""
#
halo_basis = pyEXP.basis.Basis.factory(halo_config)
The getBasis
member for each basis returns a vector of arrays for
the basis functions on the grid you have defined. For the spherical
or flat disk case, the basis functions are one-dimensional functions.
We provide a beginning and ending radius in logarithmic units along
with a grid size:
# Get the basis grid
#
lrmin = -3.0
lrmax = 0.5
rnum = 200
halo_grid = halo_basis.getBasis(lrmin, lrmax, rnum)
Now that we have the basis function grids, we can plot them. For example:
# Make a logarithmically spaced grid in radius
#
r = np.linspace(lrmin, lrmax, rnum)
r = np.power(10.0, r)
for l in range(3):
for n in range(5):
plt.semilogx(r, halo_grid[l][n], '-', label="n={}".format(n))
plt.xlabel('r')
plt.ylabel('potential')
plt.title('l={}'.format(l))
plt.legend()
plt.show()
The resulting images are:



Cylindrical basis
Now let’s do the same for a cylindrical basis. The main difference here is that the basis functions are two-dimensional meriodinal planes.
As before let’s begin by configuring and instantiating our basis:
# Make the disk basis config
#
disk_config = """
---
id: cylinder
parameters:
acyl: 0.01 # exponential disk scale length
hcyl: 0.001 # exponential disk scale height
nmaxfid: 32 # maximum radial order for spherical basis
lmaxfid: 32 # maximum harmonic order for spherical basis
mmax: 6 # maximum azimuthal order of cylindrical basis
nmax: 8 # maximum radial order of cylindrical basis
ncylodd: 3 # vertically anti-symmetric basis functions
ncylnx: 256 # grid points in radial direction
ncylny: 128 # grid points in vertical direction
rnum: 200 # radial quadrature knots for Gram matrix
pnum: 0 # azimuthal quadrature knots for Gram matrix
tnum: 80 # latitudinal quadrature knots for Gram matrix
ashift: 0.5 # # basis shift for variance generation
vflag: 0 # verbose output flag
logr: false # # logarithmically spaced radial grid
density: false # generate density basis functions
eof_file: .eof.cache.run0 # EOF cache file name
...
"""
The ncylodd parameters sets the number of vertically anti-symmetric basis functions. The first nmax-ncylodd basis functions are symmetric and the last ncylodd are vertically anti-symmetric. You can adjust these parameters to provide the desired number of basis functions, anticipating the degree of vertical symmetry.
We provide a beginning and ending cylindrical radius and a beginning and ending vertical extent, this time in linear units (matching the logr parameter given in the config):
# Get the two-dimensional basis grid
#
Rmin = 0.0
Rmax = 0.1
Rnum = 100
Zmin = -0.03
Zmax = 0.03
Znum = 40
disk_grid = disk_basis.getBasis(Rmin, Rmax, Rnum, Zmin, Zmax, Znum)
We’ll use Pyplot’s contourf to visualize the meridional-plane basis functions:
R = np.linspace(Rmin, Rmax, Rnum)
Z = np.linspace(Zmin, Zmax, Znum)
#
xv, yv = np.meshgrid(R, Z)
#
for m in range(3):
for n in range(5):
# Tranpose for contourf
cx = plt.contourf(xv, yv, disk_grid[m][n].transpose())
plt.xlabel('R')
plt.ylabel('Z')
plt.title('m, n={}, {}'.format(m, n))
plt.colorbar(cx)
plt.show()
The first three of the resulting images are:



The code above can be easily tweaked to produce only the vertically antisymmetric basis functions. Recall that the first nmax-ncylodd are symmetric and the last ncylodd are vertically anti-symmetric. In this case, nmax=8 and ncylodd=3, so indices 5, 6, and 7 are the vertically antisymmetric basis functions.
R = np.linspace(Rmin, Rmax, Rnum)
Z = np.linspace(Zmin, Zmax, Znum)
#
xv, yv = np.meshgrid(R, Z)
#
for m in range(3):
for n in range(5, 8):
# Tranpose for contourf
cx = plt.contourf(xv, yv, disk_grid[m][n].transpose())
plt.xlabel('R')
plt.ylabel('Z')
plt.title('m, n={}, {}'.format(m, n))
plt.colorbar(cx)
plt.show()
The first three anti-symmetric basis functions are:



We can visualize the basis for FlatDisk
using the same steps as
SphericalSL
.