Fast and exact spin-s spherical-harmonic transforms
This code is a lightly modified version of the code hosted here by Huffenberger, based on work by Huffenberger and Wandelt.
My 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/