Fast and exact spin-s spherical-harmonic transforms
This code is a modified version of the code hosted here by Huffenberger, based on work by Huffenberger and Wandelt.
My (@moble's) modifications mostly deal with the user interface:
- add
multi_map2salm
andmulti_salm2map
for running many similar transformations efficiently; - create python wrappers for the
map2salm
andsalm2map
functions to deal with any (reasonable) type or shape of input data, including multi-dimensional; - add python 3.x compatibility to
python/spinsfast_module.c
; - fix segfaults due to use of
free
instead offftw_free
whenfftw_malloc
was used; - make it easier to install as a python module by trying to detect paths to FFTW;
- fix numerous massive memory leaks in python extension module;
- include an ipython/jupyter notebook in the
example
directory; - add integration with pip and pypi, for easy installation (see below);
- add integration with conda and anaconda.org, for easiest installation (see below).
The original work is licensed under GPL, so that's what I have to
license this under as well. (I usually go for the more liberal MIT
license, but GPL is fine.) See the LICENSE
file in this directory
for more details.
I based my work on Huffenberger and Wandelt's "Revision 104, 13 Apr 2012", which is current as of this writing (August 2015). Whenever I notice updates on their end, I will gladly update this code, so feel free to open an issue to notify me. To see more specifically what I've added, look through the commits; my contributions are just everything since the initial commit.
A convenient ipython/jupyter notebook is found in the example
directory, and can also be viewed directly
online.
It shows some example python code that can be used to run this module,
and explains some of the conventions established by the spinsfast
authors.
In the interests of a very short, explicit example, here is one using
random (ell,m)
modes:
from numpy.random import normal, seed
import spinsfast
# Some boilerplate for setting things up:
s = 1 # spin weight of the field
lmax = 8 # maximum ell value used
Ntheta = 2*lmax+1 # Minimum value for accuracy
Nphi = 2*lmax+1 # Minimum value for accuracy
Nlm = spinsfast.N_lm(lmax); # Total number of complex components of the mode decomposition
# `alm` will hold the mode components as discussed in `example/spinsfast.ipynb`
# Here we just fill it with some random numbers to test it
seed(3124432) # Seed the random-number generator, for reproducibility
alm = normal(size=(Nlm,)) + 1j*normal(size=(Nlm,))
# This is the key line, where spinsfast converts from (ell,m) modes to values in physical space
f = spinsfast.salm2map(alm,s,lmax,Ntheta,Nphi)
# We can also convert in the opposite direction like this:
alm2 = spinsfast.map2salm(f,s,lmax)
Though manual installation is possible, the best way by far to satisfy
these dependencies is to use the
anaconda
distribution. This
distribution can co-exist with your system python with no trouble --
you simply add the path to anaconda before your system executables.
It installs into your home directory, so it doesn't require root
access. It can be uninstalled easily, since it exists entirely inside
its own directory. And updates are trivial.
Once anaconda
is installed, this package may be installed with the
command
conda install --channel conda-forge spinsfast
Note this may also install numpy
and fftw
automatically.
While generally less robust, this package is also available via pip
:
python -m pip install spinsfast
Unfortunately, maintaining binary distributions on pip is very
complicated, so pip
may try to compile the source code for you, in
which case you will need to have FFTW and a compiler installed. But
pip
has no good way of handling these dependencies. See below for
environment variables you may need to set to get compilation working
properly.
It may be helpful to install pyfftw
first. Or, on MacOS, you may
have better luck installing FFTW via homebrew and adding flags like
CFLAGS=" -L/opt/homebrew/lib " python -m pip install spinsfast
.
Manual installation of this package is slightly more delicate. The FFTW package must be installed first. This is usually very simple. But the resulting header and library must be found by the compilation step for this package. You can first simply try to run
python -m pip install .
from the top directory of the spinsfast
code. This attempts to find
the fftw
header or library for you, using some common defaults
checked by code in setup.py
.
If this doesn't work, you can read the error message, but the most
likely problem is that the compiler cannot find the fftw
header, or
the linker cannot find the fftw
library. To solve these problems,
you will need to run something more like this:
export LIBRARY_PATH=/path/to/fftw/lib
export C_INCLUDE_PATH=/path/to/fftw/include
python -m pip install .
Alternatively, you could try to alter setup.py
to point to the right
paths.
Though these are not necessary for installing the python module, the following are the instructions in the original source code for building the C code.
Get the latest version at:
http://www.physics.miami.edu/~huffenbe/research/spinsfast/
-
Edit the file (or make a new file) called build/config.mk so that the proper locations for header and library files are included.
-
Set the environment variable "build" so that it points to that file. I.e., in bash, say
export build=build/config.mk
-
Build the library and example codes with
make
Run the example code following the instructions at
http://www.physics.miami.edu/~huffenbe/research/spinsfast/