In [ ]:
from __future__ import division, print_function

# Std lib
import sys
path = "/Users/adrian/projects/biff/build/lib.macosx-10.5-x86_64-2.7/"
if path not in sys.path:
    sys.path.append(path)

# Third-party
import astropy.units as u
from astropy.constants import G as _G
import h5py
import matplotlib as mpl
import matplotlib.pyplot as pl
import numpy as np
%matplotlib inline
fromgala.units import galactic
importgala.potential as gp

import biff
G = _G.decompose(galactic).value

In [ ]:
def _isochrone_density(x, y, z, args):
    """
    .. warning::

        THIS IS AN INTERNAL FUNCTION -- USE ``plummer_density()`` INSTEAD.

    """
    M,r_s = args
    r2 = x*x + y*y + z*z
    a = np.sqrt(r_s**2 + r2)
    return M*(3*(r_s + a)*a**2 - r2*(r_s+3*a))/(4*np.pi*(r_s+a)**3*a**3)

def isochrone_density(xyz, M, r_s):
    """
    Compute the density from a Plummer sphere.

    Parameters
    ----------
    """
    x,y,z = np.atleast_2d(xyz).T
    return _isochrone_density(x,y,z,args=(M,r_s))

_density = _isochrone_density

In [ ]:
true_M = 1/G
true_r_s = 1.

x = np.logspace(-2,1,512)
xyz = np.zeros((len(x),3))
xyz[:,0] = x
true_dens = isochrone_density(xyz, true_M, true_r_s)
true_pot = gp.IsochronePotential(m=true_M, b=true_r_s, units=galactic).value(xyz)
true_grad = gp.IsochronePotential(m=true_M, b=true_r_s, units=galactic).gradient(xyz)

In [ ]:
nmax = 16
lmax = 0

Snlm = np.zeros((nmax+1,lmax+1,lmax+1))
Serr = np.zeros((nmax+1,lmax+1,lmax+1))
Tnlm = np.zeros((nmax+1,lmax+1,lmax+1))
Terr = np.zeros((nmax+1,lmax+1,lmax+1))

nlms = []
for n in range(nmax+1):
    for l in range(lmax+1):
        for m in range(l+1):
            nlms.append([n,l,m])
       
for nlm in nlms:
    n,l,m = nlm
    print(n,l,m)
    (S,S_err),(T,T_err) = biff.compute_coeffs(_density, nlm=nlm, 
                                              M=true_M, r_s=true_r_s, args=(true_M,true_r_s),
                                              epsrel=1E-9)
    Snlm[n,l,m] = S
    Serr[n,l,m] = S_err
    Tnlm[n,l,m] = T
    Terr[n,l,m] = T_err
        
# OR: load from file..
# with h5py.File("/Users/adrian/projects/ophiuchus/data/Anlm_plummer.h5") as f:
#     nmax = f['nlm'].attrs['nmax']
#     lmax = f['nlm'].attrs['lmax']
#     nlm = np.array(f['nlm'])
#     _Anlm = np.array(f['Anlm'])
#     Anlm_err = np.array(f['Anlm_err'])
    
#     ix = np.abs(_Anlm) > np.abs(Anlm_err)
#     nlm = nlm[ix]
#     _Anlm = _Anlm[ix]

# Anlm = np.zeros((nmax+1, lmax+1, lmax+1))
# for (n,l,m),A in zip(nlm, _Anlm):
#     Anlm[n,l,m] = A

In [ ]:
pl.semilogy(np.array(nlms), np.abs(Snlm.flat/Snlm[0,0,0]))
pl.xlim(0,10)
pl.ylim(1E-6, 1)

In [ ]:
bfe_dens = biff.density(xyz, true_M, true_r_s, Snlm, Tnlm, nmax, lmax)
bfe_pot = biff.potential(xyz, G, true_M, true_r_s, Snlm, Tnlm, nmax, lmax)
bfe_grad = biff.gradient(xyz, G, true_M, true_r_s, Snlm, Tnlm, nmax, lmax)

In [ ]:
fig,axes = pl.subplots(3, 1, figsize=(8,10), sharex=True)

axes[0].set_ylabel(r'$\rho$')
axes[0].loglog(x, true_dens, marker=None)
axes[0].loglog(x, bfe_dens, marker=None)

axes[1].set_ylabel(r'$\Phi$')
axes[1].semilogx(x, true_pot, marker=None)
axes[1].semilogx(x, bfe_pot, marker=None)

axes[2].set_ylabel(r'${\rm d}\Phi/{\rm d}x$')
axes[2].semilogx(x, true_grad[:,0], marker=None)
axes[2].semilogx(x, bfe_grad[:,0], marker=None)

fig.tight_layout()

In [ ]:
fig,axes = pl.subplots(3, 1, figsize=(8,10), sharey=True)

axes[0].set_ylabel(r'$\rho$')
axes[0].loglog(x, np.abs((true_dens-bfe_dens)/true_dens), marker=None)

axes[1].set_ylabel(r'$\Phi$')
axes[1].loglog(x, np.abs((true_pot-bfe_pot)/true_pot), marker=None)

axes[2].set_ylabel(r'${\rm d}\Phi/{\rm d}x$')
axes[2].loglog(x, np.abs((true_grad[:,0]-bfe_grad[:,0])/true_grad[:,0]), marker=None)

axes[0].set_ylim(1E-12, 1E0)
fig.tight_layout()

In [ ]: