From bb4b79c0b62a2dfb2ffbb2888d821b315ef3194f Mon Sep 17 00:00:00 2001
From: Martin Reinecke <martin@mpa-garching.mpg.de>
Date: Thu, 20 Apr 2017 14:43:27 +0200
Subject: [PATCH] switch to pyHealpix and adjust dependencies accordingly

---
 .gitlab-ci.yml                                |  25 +--
 Dockerfile                                    |  10 +-
 README.md                                     | 154 ++++--------------
 ci/install_h5py.sh                            |  13 --
 ci/install_libsharp.sh                        |  12 --
 ci/install_pyfftw.sh                          |   7 -
 ci/requirements.txt                           |  10 +-
 ci/requirements_base.txt                      |   5 +-
 nifty/config/nifty_config.py                  |  35 ++--
 .../transformations/gllmtransformation.py     |  33 +---
 .../transformations/hplmtransformation.py     |  27 +--
 .../transformations/lmgltransformation.py     |  34 +---
 .../transformations/lmhptransformation.py     |  31 +---
 nifty/spaces/gl_space/gl_space.py             |  58 +------
 nifty/spaces/hp_space/hp_space.py             |  69 ++------
 nifty/spaces/lm_space/lm_space.py             |  45 +----
 test/common.py                                |  13 +-
 test/test_spaces/test_gl_space.py             |  23 +--
 test/test_spaces/test_hp_space.py             |  49 +++---
 test/test_spaces/test_interface.py            |  24 +--
 test/test_spaces/test_lm_space.py             |  65 +++-----
 21 files changed, 182 insertions(+), 560 deletions(-)
 delete mode 100644 ci/install_h5py.sh
 delete mode 100644 ci/install_libsharp.sh
 delete mode 100644 ci/install_pyfftw.sh

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index aa651ae92..5726b040d 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -12,8 +12,8 @@ variables:
 before_script:
   - apt-get update
   - >
-    apt-get install -y build-essential python python-pip python-dev git 
-    gfortran autoconf gsl-bin libgsl-dev wget
+    apt-get install -y build-essential python python-pip python-dev git
+    autoconf gsl-bin libgsl-dev wget python-numpy cython
   - pip install -r ci/requirements_base.txt
   - chmod +x ci/*.sh
 
@@ -26,10 +26,8 @@ test_min:
 test_mpi:
   stage: test
   script:
-    - apt-get install -y openmpi-bin libopenmpi-dev
-    - pip install astropy healpy mpi4py
-    - pip install git+https://github.com/mrbell/gfft
-    - ci/install_libsharp.sh
+    - apt-get install -y openmpi-bin libopenmpi-dev python-mpi4py
+    - ci/install_pyHealpix.sh
     - python setup.py build_ext --inplace
     - nosetests -vv
 
@@ -40,11 +38,8 @@ test_mpi_fftw:
     - >
       apt-get install -y libatlas-base-dev libfftw3-bin libfftw3-dev
       libfftw3-double3 libfftw3-long3 libfftw3-mpi-dev libfftw3-mpi3
-      libfftw3-quad3 libfftw3-single3
-    - pip install astropy healpy mpi4py
-    - pip install git+https://github.com/mrbell/gfft
-    - ci/install_libsharp.sh
-    - ci/install_pyfftw.sh
+      libfftw3-quad3 libfftw3-single3 python-mpi4py python-pyfftw
+    - ci/install_pyHealpix.sh
     - python setup.py build_ext --inplace
     - nosetests -vv
 
@@ -58,12 +53,8 @@ test_mpi_fftw_hdf5:
       libfftw3-quad3 libfftw3-single3
     - >
       apt-get install -y libhdf5-10 libhdf5-dev libhdf5-openmpi-10
-      libhdf5-openmpi-dev hdf5-tools
-    - pip install astropy healpy mpi4py
-    - pip install git+https://github.com/mrbell/gfft
-    - ci/install_h5py.sh
-    - ci/install_libsharp.sh
-    - ci/install_pyfftw.sh
+      libhdf5-openmpi-dev hdf5-tools python-mpi4py python-pyfftw python-h5py
+    - ci/install_pyHealpix.sh
     - python setup.py build_ext --inplace
     - nosetests -vv --with-coverage --cover-package=nifty --cover-branches
     - >
diff --git a/Dockerfile b/Dockerfile
index 37bf8dbb5..c9e98457f 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -8,17 +8,15 @@ RUN \
     libopenmpi-dev libatlas-base-dev libfftw3-bin libfftw3-dev \
     libfftw3-double3 libfftw3-long3 libfftw3-mpi-dev libfftw3-mpi3 \
     libfftw3-quad3 libfftw3-single3 libhdf5-10 libhdf5-dev \
-    libhdf5-openmpi-10 libhdf5-openmpi-dev hdf5-tools python-h5py
+    libhdf5-openmpi-10 libhdf5-openmpi-dev hdf5-tools python-h5py python-pyfftw
 
 # python dependencies
 ADD ci/requirements.txt /tmp/requirements.txt
 RUN pip install -r /tmp/requirements.txt
 
-# install libsharp and pyfftw
-ADD ci/install_libsharp.sh /tmp/install_libsharp.sh
-ADD ci/install_pyfftw.sh /tmp/install_pyfftw.sh
-RUN cd /tmp && chmod +x install_libsharp.sh && ./install_libsharp.sh
-RUN cd /tmp && chmod +x install_pyfftw.sh && ./install_pyfftw.sh
+# install pyHealpix
+ADD ci/install_pyHealpix.sh /tmp/install_pyHealpix.sh
+RUN cd /tmp && chmod +x install_pyHealpix.sh && ./install_pyHealpix.sh
 
 # copy sources and install nifty
 COPY . /tmp/NIFTy
diff --git a/README.md b/README.md
index 2ba6d425c..702f55d17 100644
--- a/README.md
+++ b/README.md
@@ -38,36 +38,26 @@ certain grids, **fields** that are defined on spaces, and **operators**
 that apply to fields.
 
 -   [Spaces](http://www.mpa-garching.mpg.de/ift/nifty/space.html)
-    -   `point_space` - unstructured list of points
     -   `rg_space` - *n*-dimensional regular Euclidean grid
     -   `lm_space` - spherical harmonics
     -   `gl_space` - Gauss-Legendre grid on the 2-sphere
     -   `hp_space` - [HEALPix](http://sourceforge.net/projects/healpix/)
         grid on the 2-sphere
-    -   `nested_space` - arbitrary product of grids
 -   [Fields](http://www.mpa-garching.mpg.de/ift/nifty/field.html)
     -   `field` - generic class for (discretized) fields
 
 <!-- -->
 
-    field.cast_domain   field.hat           field.power        field.smooth
-    field.conjugate     field.inverse_hat   field.pseudo_dot   field.tensor_dot
-    field.dim           field.norm          field.set_target   field.transform
-    field.dot           field.plot          field.set_val      field.weight
+    field.conjugate     field.dim          field.norm
+    field.dot           field.set_val      field.weight
 
 -   [Operators](http://www.mpa-garching.mpg.de/ift/nifty/operator.html)
     -   `diagonal_operator` - purely diagonal matrices in a specified
         basis
     -   `projection_operator` - projections onto subsets of a specified
         basis
-    -   `vecvec_operator` - matrices derived from the outer product of a
-        vector
-    -   `response_operator` - exemplary responses that include a
-        convolution, masking and projection
     -   `propagator_operator` - information propagator in Wiener filter
         theory
-    -   `explicit_operator` - linear operators with an explicit matrix
-        representation
     -   (and more)
 -   (and more)
 
@@ -81,19 +71,7 @@ Installation
 
 -   [Python](http://www.python.org/) (v2.7.x)
     -   [NumPy](http://www.numpy.org/)
-    -   [SciPy](http://www.scipy.org/)
     -   [Cython](http://cython.org/)
-    -   [matplotlib](http://matplotlib.org/)
--   [GFFT](https://github.com/mrbell/gfft) (v0.1.0) - Generalized Fast
-    Fourier Transformations for Python - **optional**
--   [HEALPy](https://github.com/healpy/healpy) (v1.8.1 without openmp) -
-    A Python wrapper for
-    [HEALPix](http://sourceforge.net/projects/healpix/) -**optional,
-    only needed for spherical spaces**
--   [libsharp-wrapper](https://github.com/mselig/libsharp-wrapper)
-    (v0.1.2 without openmp) - A Python wrapper for the
-    [libsharp](http://sourceforge.net/projects/libsharp/) library
-    -**optional, only needed for spherical spaces**
 
 ### Download
 
@@ -112,57 +90,35 @@ Starting with a fresh Ubuntu installation move to a folder like
 
 -   Install basic packages like python, python-dev, gsl and others:
 
-        sudo apt-get install curl git autoconf 
-        sudo apt-get install python-dev python-pip gsl-bin libgsl0-dev libfreetype6-dev libpng-dev  libatlas-base-dev gfortran 
+        sudo apt-get install curl git autoconf
+        sudo apt-get install python-dev python-pip gsl-bin libgsl0-dev libfreetype6-dev libpng-dev libatlas-base-dev
 
--   Install matplotlib:
+-   Using pip install numpy etc...:
 
-        sudo apt-get install python-matplotlib
+        sudo pip install numpy cython
 
--   Using pip install numpy, scipy, etc...:
+-   Install pyHealpix:
 
-        sudo pip install numpy scipy cython pyfits healpy
-
--   Now install the 'non-standard' dependencies. First of all gfft:
-
-        curl -LOk https://github.com/mrbell/gfft/tarball/master 
-        tar -xzf master 
-        cd mrbell-gfft* 
-        sudo python setup.py install 
-        cd ..
-
--   Libsharp:
-
-        git clone http://git.code.sf.net/p/libsharp/code libsharp-code 
-        cd libsharp-code 
-        sudo autoconf 
-        ./configure --enable-pic --disable-openmp 
-        sudo make 
-        cd ..
-
--   Libsharpwrapper:
-
-        git clone http://github.com/mselig/libsharp-wrapper.git libsharp-wrapper 
-        cd libsharp-wrapper 
-        sudo python setup.py build_ext 
-        sudo python setup.py install 
+        git clone https://gitlab.mpcdf.mpg.de/mtr/pyHealpix.git
+        cd pyHealpix
+        autoreconf -i && ./configure && sudo make install
         cd ..
 
 -   Finally, NIFTy:
 
         git clone https://gitlab.mpcdf.mpg.de/ift/NIFTy.git
         cd nifty
-        sudo python setup.py install 
-        cd .. 
+        sudo python setup.py install
+        cd ..
 
-### Installation on a linux cluster
+### Installation on a Linux cluster
 
 This is for you if you want to install NIFTy on a HPC machine or cluster
 that is hosted by your university or institute. Most of the dependencies
 will most likely already be there, but you won't have superuser
-priviledges. In this case, instead:
+privileges. In this case, instead of:
 
-    sudo python setup.py install 
+    sudo python setup.py install
 
 use:
 
@@ -175,82 +131,40 @@ or:
 in the instruction above. This will install the python packages into
 your local user directory.
 
+For pyHealpix, use:
+
+    git clone https://gitlab.mpcdf.mpg.de/mtr/pyHealpix.git
+    cd pyHealpix
+    autoreconf -i && ./configure --prefix=$HOME/.local && make install
+    cd ..
+
 ### Installation on OS X 10.11
 
-We advice to install the following packages in the order as they appear
+We advise to install the following packages in the order as they appear
 below. We strongly recommend to install all needed packages via
 MacPorts. Please be aware that not all packages are available on
 MacPorts, missing ones need to be installed manually. It may also be
 mentioned that one should only use one package manager, as multiple ones
 may cause trouble.
 
--   Install basic packages python, scipy, matplotlib and cython:
+-   Install basic packages numpy and cython:
 
         sudo port install py27-numpy
-        sudo port install py27-scipy
-        sudo port install py27-matplotlib
         sudo port install py27-cython
 
--   Install gfft. **Depending where you installed GSL you may need to
-    change the path in setup.py!**:
-
-        sudo port install gsl
-        git clone https://github.com/mrbell/gfft.git}{https://github.com/mrbell/gfft.git
-        sudo python setup.py install
-
--   Install healpy:
+-   Install pyHealpix:
 
-        sudo port install py27-pyfits
-        git clone https://github.com/healpy/healpy.git
-        cd healpy 
-        sudo python setup.py install
-        cd ..
-
--   Install libsharp and therefore autoconf, automake and libtool.
-    Installations instructions for libsharp may be found here:
-    <https://sourceforge.net/p/libsharp/code/ci/master/tree/>:
-
-        curl -OL http://ftpmirror.gnu.org/autoconf/autoconf-2.69.tar.gz
-        tar -xzf autoconf-2.69.tar.gz 
-        cd autoconf-2.69
-        ./configure && make && sudo make install
-        cd ..
-
-        curl -OL http://ftpmirror.gnu.org/automake/automake-1.14.tar.gz
-        tar -xzf automake-1.14.tar.gz
-        cd automake-1.14
-        ./configure && make && sudo make install
-        cd ..
-
-        curl -OL http://ftpmirror.gnu.org/libtool/libtool-2.4.2.tar.gz
-        tar -xzf libtool-2.4.2.tar.gz
-        cd libtool-2.4.2
-        ./configure && make && sudo make install
-        cd ..
-
-        git clone http://git.code.sf.net/p/libsharp/code libsharp-code 
-        cd libsharp-code 
-        sudo autoconf 
-        ./configure --enable-pic --disable-openmp 
-        sudo make 
-        cd ..
-
--   Install libsharp-wrapper. **Adopt the path of the libsharp
-    installation in setup.py** :
-
-        sudo port install gcc
-        sudo port select gcc  mp-gcc5
-        git clone https://github.com/mselig/libsharp-wrapper.git
-        cd libsharp-wrapper
-        sudo python setup.py install
+        git clone https://gitlab.mpcdf.mpg.de/mtr/pyHealpix.git
+        cd pyHealpix
+        autoreconf -i && ./configure && sudo make install
         cd ..
 
 -   Install NIFTy:
 
         git clone https://gitlab.mpcdf.mpg.de/ift/NIFTy.git
         cd nifty
-        sudo python setup.py install 
-        cd .. 
+        sudo python setup.py install
+        cd ..
 
 ### Installation using pypi
 
@@ -269,10 +183,10 @@ In oder to run the tests one needs two additional packages:
 
     pip install nose
     pip install parameterized
-    
-Afterwards the tests (including a coverage report) are run using the following 
+
+Afterwards the tests (including a coverage report) are run using the following
 command in the repository root:
-    
+
     nosetests --exe --cover-html
 
 
@@ -282,7 +196,7 @@ For a quickstart, you can browse through the [informal
 introduction](http://www.mpa-garching.mpg.de/ift/nifty/start.html) or
 dive into NIFTY by running one of the demonstrations, e.g.:
 
-    >>> run -m nifty.demos.demo_wf1
+    python demos/wiener_filter.py
 
 Acknowledgement
 ---------------
diff --git a/ci/install_h5py.sh b/ci/install_h5py.sh
deleted file mode 100644
index 0f008f3f3..000000000
--- a/ci/install_h5py.sh
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/bin/bash
-
-wget https://api.github.com/repos/h5py/h5py/tags -O - | grep tarball_url | grep -v rc | head -n 1 | cut -d '"' -f 4 | wget -i - -O h5py.tar.gz
-tar xzf h5py.tar.gz
-cd h5py-h5py*
-export CC=mpicc
-export HDF5_DIR=/usr/lib/x86_64-linux-gnu/hdf5/openmpi
-python setup.py configure --mpi
-python setup.py build
-python setup.py install
-cd ..
-rm -r h5py-h5py*
-rm h5py.tar.gz
diff --git a/ci/install_libsharp.sh b/ci/install_libsharp.sh
deleted file mode 100644
index 456e79d12..000000000
--- a/ci/install_libsharp.sh
+++ /dev/null
@@ -1,12 +0,0 @@
-#!/bin/bash
-
-git clone http://git.code.sf.net/p/libsharp/code libsharp-code
-cd libsharp-code
-autoconf && ./configure --enable-pic --disable-openmp && make
-cd ..
-git clone https://github.com/mselig/libsharp-wrapper libsharp-wrapper
-cd libsharp-wrapper
-python setup.py build_ext install
-cd ..
-rm -r libsharp-code
-rm -r libsharp-wrapper
diff --git a/ci/install_pyfftw.sh b/ci/install_pyfftw.sh
deleted file mode 100644
index c9995f7c4..000000000
--- a/ci/install_pyfftw.sh
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/bin/bash
-
-git clone -b mpi https://github.com/fredRos/pyFFTW.git
-cd pyFFTW/
-CC=mpicc python setup.py build_ext install
-cd ..
-rm -r pyFFTW
diff --git a/ci/requirements.txt b/ci/requirements.txt
index a7bace6ff..f50515781 100644
--- a/ci/requirements.txt
+++ b/ci/requirements.txt
@@ -1,12 +1,6 @@
-numpy
-scipy
-cython
-astropy
-healpy
-mpi4py
-ipython==5.3.0
 nose
-nose-parameterized
+parameterized
+coverage
 git+https://gitlab.mpcdf.mpg.de/ift/mpi_dummy.git
 git+https://gitlab.mpcdf.mpg.de/ift/keepers.git
 git+https://gitlab.mpcdf.mpg.de/ift/D2O.git
diff --git a/ci/requirements_base.txt b/ci/requirements_base.txt
index 120f9fd28..f50515781 100644
--- a/ci/requirements_base.txt
+++ b/ci/requirements_base.txt
@@ -1,8 +1,5 @@
-numpy
-scipy
-cython
 nose
-nose-parameterized
+parameterized
 coverage
 git+https://gitlab.mpcdf.mpg.de/ift/mpi_dummy.git
 git+https://gitlab.mpcdf.mpg.de/ift/keepers.git
diff --git a/nifty/config/nifty_config.py b/nifty/config/nifty_config.py
index 4211e8bc0..5baa4aa9e 100644
--- a/nifty/config/nifty_config.py
+++ b/nifty/config/nifty_config.py
@@ -25,12 +25,10 @@ import keepers
 # Setup the dependency injector
 dependency_injector = keepers.DependencyInjector(
                                    [('mpi4py.MPI', 'MPI'),
-                                    'healpy',
-                                    'libsharp_wrapper_gl'])
+                                    'pyHealpix'])
 
 dependency_injector.register('pyfftw', lambda z: hasattr(z, 'FFTW_MPI'))
 
-
 # Initialize the variables
 variable_fft_module = keepers.Variable(
                                'fft_module',
@@ -38,35 +36,23 @@ variable_fft_module = keepers.Variable(
                                lambda z: (('pyfftw' in dependency_injector)
                                           if z == 'fftw' else True))
 
-
-def _healpy_validator(use_healpy):
-    if not isinstance(use_healpy, bool):
+def _pyHealpix_validator(use_pyHealpix):
+    if not isinstance(use_pyHealpix, bool):
         return False
-    if not use_healpy:
+    if not use_pyHealpix:
         return True
-    if 'healpy' not in dependency_injector:
-        return False
-    healpy = dependency_injector['healpy']
-    if lv(healpy.__version__) < lv('1.8.1'):
+    if 'pyHealpix' not in dependency_injector:
         return False
+    pyHealpix = dependency_injector['pyHealpix']
     return True
 
 
-variable_use_healpy = keepers.Variable(
-                          'use_healpy',
+variable_use_pyHealpix = keepers.Variable(
+                          'use_pyHealpix',
                           [True, False],
-                          _healpy_validator,
+                          _pyHealpix_validator,
                           genus='boolean')
 
-variable_use_libsharp = keepers.Variable(
-                         'use_libsharp',
-                         [True, False],
-                         lambda z: (('libsharp_wrapper_gl' in
-                                     dependency_injector)
-                                    if z else True) and isinstance(z, bool),
-                         genus='boolean')
-
-
 def _dtype_validator(dtype):
     try:
         np.dtype(dtype)
@@ -91,8 +77,7 @@ variable_default_distribution_strategy = keepers.Variable(
 nifty_configuration = keepers.get_Configuration(
                  name='NIFTy',
                  variables=[variable_fft_module,
-                            variable_use_healpy,
-                            variable_use_libsharp,
+                            variable_use_pyHealpix,
                             variable_default_field_dtype,
                             variable_default_distribution_strategy],
                  file_name='NIFTy.conf',
diff --git a/nifty/operators/fft_operator/transformations/gllmtransformation.py b/nifty/operators/fft_operator/transformations/gllmtransformation.py
index 677495e9e..a2532b6a2 100644
--- a/nifty/operators/fft_operator/transformations/gllmtransformation.py
+++ b/nifty/operators/fft_operator/transformations/gllmtransformation.py
@@ -23,7 +23,7 @@ from nifty import GLSpace, LMSpace
 from slicing_transformation import SlicingTransformation
 import lm_transformation_factory as ltf
 
-libsharp = gdi.get('libsharp_wrapper_gl')
+pyHealpix = gdi.get('pyHealpix')
 
 
 class GLLMTransformation(SlicingTransformation):
@@ -31,9 +31,9 @@ class GLLMTransformation(SlicingTransformation):
     # ---Overwritten properties and methods---
 
     def __init__(self, domain, codomain=None, module=None):
-        if 'libsharp_wrapper_gl' not in gdi:
+        if 'pyHealpix' not in gdi:
             raise ImportError(
-                "The module libsharp is needed but not available.")
+                "The module pyHealpix is needed but not available.")
 
         super(GLLMTransformation, self).__init__(domain, codomain,
                                                  module=module)
@@ -108,14 +108,12 @@ class GLLMTransformation(SlicingTransformation):
         lmax = self.codomain.lmax
         mmax = self.codomain.mmax
 
+        sjob=pyHealpix.sharpjob_d()
+        sjob.set_Gauss_geometry(nlat,nlot)
+        sjob.set_triangular_alm_info(lmax,mmax)
         if issubclass(inp.dtype.type, np.complexfloating):
 
-            [resultReal, resultImag] = [self.libsharpMap2Alm(x,
-                                                             nlat=nlat,
-                                                             nlon=nlon,
-                                                             lmax=lmax,
-                                                             mmax=mmax,
-                                                             **kwargs)
+            [resultReal, resultImag] = [sjob.map2alm(x)
                                         for x in (inp.real, inp.imag)]
 
             [resultReal, resultImag] = [ltf.buildIdx(x, lmax=lmax)
@@ -123,22 +121,7 @@ class GLLMTransformation(SlicingTransformation):
 
             result = self._combine_complex_result(resultReal, resultImag)
         else:
-            result = self.libsharpMap2Alm(inp, nlat=nlat, nlon=nlon, lmax=lmax,
-                                          mmax=mmax)
+            result = sjob.map2alm(inp)
             result = ltf.buildIdx(result, lmax=lmax)
 
         return result
-
-    # ---Added properties and methods---
-
-    def libsharpMap2Alm(self, inp, **kwargs):
-        if inp.dtype == np.dtype('float32'):
-            return libsharp.map2alm_f(inp, **kwargs)
-        elif inp.dtype == np.dtype('float64'):
-            return libsharp.map2alm(inp, **kwargs)
-        else:
-            self.logger.debug("performing dtype conversion for libsharp "
-                              "compatibility.")
-            casted_inp = inp.astype(np.dtype('float64'), copy=False)
-            result = libsharp.map2alm(casted_inp, **kwargs)
-            return result
diff --git a/nifty/operators/fft_operator/transformations/hplmtransformation.py b/nifty/operators/fft_operator/transformations/hplmtransformation.py
index b9ab811ef..1ac176401 100644
--- a/nifty/operators/fft_operator/transformations/hplmtransformation.py
+++ b/nifty/operators/fft_operator/transformations/hplmtransformation.py
@@ -24,7 +24,7 @@ from slicing_transformation import SlicingTransformation
 
 import lm_transformation_factory as ltf
 
-hp = gdi.get('healpy')
+pyHealpix = gdi.get('pyHealpix')
 
 
 class HPLMTransformation(SlicingTransformation):
@@ -32,9 +32,9 @@ class HPLMTransformation(SlicingTransformation):
     # ---Overwritten properties and methods---
 
     def __init__(self, domain, codomain=None, module=None):
-        if 'healpy' not in gdi:
+        if 'pyHealpix' not in gdi:
             raise ImportError(
-                "The module healpy is needed but not available")
+                "The module pyHealpix is needed but not available")
 
         super(HPLMTransformation, self).__init__(domain, codomain,
                                                  module=module)
@@ -62,7 +62,7 @@ class HPLMTransformation(SlicingTransformation):
             raise TypeError(
                 "domain needs to be a HPSpace")
 
-        lmax = 3 * domain.nside - 1
+        lmax = 2 * domain.nside
 
         result = LMSpace(lmax=lmax, dtype=np.dtype('float64'))
         cls.check_codomain(domain, result)
@@ -81,24 +81,17 @@ class HPLMTransformation(SlicingTransformation):
         nside = domain.nside
         lmax = codomain.lmax
 
-        if 3 * nside - 1 != lmax:
-            raise ValueError(
-                'ERROR: codomain has 3*nside-1 != lmax.')
-
         return None
 
     def _transformation_of_slice(self, inp, **kwargs):
         lmax = self.codomain.lmax
         mmax = lmax
 
+        sjob=pyHealpix.sharpjob_d()
+        sjob.set_Healpix_geometry(nside)
+        sjob.set_triangular_alm_info(lmax,mmax)
         if issubclass(inp.dtype.type, np.complexfloating):
-            [resultReal, resultImag] = [hp.map2alm(x.astype(np.float64,
-                                                            copy=False),
-                                                   lmax=lmax,
-                                                   mmax=mmax,
-                                                   pol=True,
-                                                   use_weights=False,
-                                                   **kwargs)
+            [resultReal, resultImag] = [sjob.map2alm(x)
                                         for x in (inp.real, inp.imag)]
 
             [resultReal, resultImag] = [ltf.buildIdx(x, lmax=lmax)
@@ -107,9 +100,7 @@ class HPLMTransformation(SlicingTransformation):
             result = self._combine_complex_result(resultReal, resultImag)
 
         else:
-            result = hp.map2alm(inp.astype(np.float64, copy=False),
-                                lmax=lmax, mmax=mmax, pol=True,
-                                use_weights=False)
+            result = sjob.map2alm(inp)
             result = ltf.buildIdx(result, lmax=lmax)
 
         return result
diff --git a/nifty/operators/fft_operator/transformations/lmgltransformation.py b/nifty/operators/fft_operator/transformations/lmgltransformation.py
index b1e6f1921..0d07b34e8 100644
--- a/nifty/operators/fft_operator/transformations/lmgltransformation.py
+++ b/nifty/operators/fft_operator/transformations/lmgltransformation.py
@@ -23,7 +23,7 @@ from nifty import GLSpace, LMSpace
 from slicing_transformation import SlicingTransformation
 import lm_transformation_factory as ltf
 
-libsharp = gdi.get('libsharp_wrapper_gl')
+pyHealpix = gdi.get('pyHealpix')
 
 
 class LMGLTransformation(SlicingTransformation):
@@ -31,9 +31,9 @@ class LMGLTransformation(SlicingTransformation):
     # ---Overwritten properties and methods---
 
     def __init__(self, domain, codomain=None, module=None):
-        if 'libsharp_wrapper_gl' not in gdi:
+        if 'pyHealpix' not in gdi:
             raise ImportError(
-                "The module libsharp is needed but not available.")
+                "The module pyHealpix is needed but not available.")
 
         super(LMGLTransformation, self).__init__(domain, codomain,
                                                  module=module)
@@ -114,38 +114,20 @@ class LMGLTransformation(SlicingTransformation):
         lmax = self.domain.lmax
         mmax = self.domain.mmax
 
+        sjob=pyHealpix.sharpjob_d()
+        sjob.set_Gauss_geometry(nlat,nlot)
+        sjob.set_triangular_alm_info(lmax,mmax)
         if issubclass(inp.dtype.type, np.complexfloating):
             [resultReal, resultImag] = [ltf.buildLm(x, lmax=lmax)
                                         for x in (inp.real, inp.imag)]
 
-            [resultReal, resultImag] = [self.libsharpAlm2Map(x,
-                                                             nlat=nlat,
-                                                             nlon=nlon,
-                                                             lmax=lmax,
-                                                             mmax=mmax,
-                                                             cl=False,
-                                                             **kwargs)
+            [resultReal, resultImag] = [sjob.alm2map(x)
                                         for x in [resultReal, resultImag]]
 
             result = self._combine_complex_result(resultReal, resultImag)
 
         else:
             result = ltf.buildLm(inp, lmax=lmax)
-            result = self.libsharpAlm2Map(result, nlat=nlat, nlon=nlon,
-                                          lmax=lmax, mmax=mmax, cl=False)
+            result = sjob.alm2map(result)
 
         return result
-
-    # ---Added properties and methods---
-
-    def libsharpAlm2Map(self, inp, **kwargs):
-        if inp.dtype == np.dtype('complex64'):
-            return libsharp.alm2map_f(inp, **kwargs)
-        elif inp.dtype == np.dtype('complex128'):
-            return libsharp.alm2map(inp, **kwargs)
-        else:
-            self.logger.debug("Performing dtype conversion for libsharp "
-                              "compatibility.")
-            casted_inp = inp.astype(np.dtype('complex128'), copy=False)
-            result = libsharp.alm2map(casted_inp, **kwargs)
-            return result
diff --git a/nifty/operators/fft_operator/transformations/lmhptransformation.py b/nifty/operators/fft_operator/transformations/lmhptransformation.py
index 77cdb0978..3e32c7c01 100644
--- a/nifty/operators/fft_operator/transformations/lmhptransformation.py
+++ b/nifty/operators/fft_operator/transformations/lmhptransformation.py
@@ -22,7 +22,7 @@ from nifty import HPSpace, LMSpace
 from slicing_transformation import SlicingTransformation
 import lm_transformation_factory as ltf
 
-hp = gdi.get('healpy')
+pyHealpix = gdi.get('pyHealpix')
 
 
 class LMHPTransformation(SlicingTransformation):
@@ -30,9 +30,9 @@ class LMHPTransformation(SlicingTransformation):
     # ---Overwritten properties and methods---
 
     def __init__(self, domain, codomain=None, module=None):
-        if gdi.get('healpy') is None:
+        if gdi.get('pyHealpix') is None:
             raise ImportError(
-                "The module libsharp is needed but not available.")
+                "The module pyHealpix is needed but not available.")
 
         super(LMHPTransformation, self).__init__(domain, codomain,
                                                  module=module)
@@ -65,7 +65,7 @@ class LMHPTransformation(SlicingTransformation):
             raise TypeError(
                 'ERROR: domain needs to be a LMSpace')
 
-        nside = (domain.lmax + 1) // 3
+        nside = np.max(domain.lmax // 2,1)
         result = HPSpace(nside=nside)
         cls.check_codomain(domain, result)
         return result
@@ -83,10 +83,6 @@ class LMHPTransformation(SlicingTransformation):
         nside = codomain.nside
         lmax = domain.lmax
 
-        if 3*nside - 1 != lmax:
-            raise ValueError(
-                'ERROR: codomain has 3*nside -1 != lmax.')
-
         return None
 
     def _transformation_of_slice(self, inp, **kwargs):
@@ -94,29 +90,20 @@ class LMHPTransformation(SlicingTransformation):
         lmax = self.domain.lmax
         mmax = lmax
 
+        sjob=pyHealpix.sharpjob_d()
+        sjob.set_Healpix_geometry(nside)
+        sjob.set_triangular_alm_info(lmax,mmax)
         if issubclass(inp.dtype.type, np.complexfloating):
             [resultReal, resultImag] = [ltf.buildLm(x, lmax=lmax)
                                         for x in (inp.real, inp.imag)]
 
-            [resultReal, resultImag] = [hp.alm2map(x.astype(np.complex128,
-                                                            copy=False),
-                                                   nside,
-                                                   lmax=lmax,
-                                                   mmax=mmax,
-                                                   pixwin=False,
-                                                   fwhm=0.0,
-                                                   sigma=None,
-                                                   pol=True,
-                                                   inplace=False,
-                                                   **kwargs)
+            [resultReal, resultImag] = [sjob.alm2map(x)
                                         for x in [resultReal, resultImag]]
 
             result = self._combine_complex_result(resultReal, resultImag)
 
         else:
             result = ltf.buildLm(inp, lmax=lmax)
-            result = hp.alm2map(result.astype(np.complex128, copy=False),
-                                nside, lmax=lmax, mmax=mmax, pixwin=False,
-                                fwhm=0.0, sigma=None, pol=True, inplace=False)
+            result = sjob.alm2map(result)
 
         return result
diff --git a/nifty/spaces/gl_space/gl_space.py b/nifty/spaces/gl_space/gl_space.py
index e5c1ba497..8ae7e958a 100644
--- a/nifty/spaces/gl_space/gl_space.py
+++ b/nifty/spaces/gl_space/gl_space.py
@@ -25,13 +25,7 @@ import d2o
 from d2o import STRATEGIES as DISTRIBUTION_STRATEGIES
 
 from nifty.spaces.space import Space
-from nifty.config import nifty_configuration as gc,\
-                         dependency_injector as gdi
-
-gl = gdi.get('libsharp_wrapper_gl')
-
-GL_DISTRIBUTION_STRATEGIES = DISTRIBUTION_STRATEGIES['global']
-
+from nifty.config import dependency_injector as gdi
 
 class GLSpace(Space):
     """
@@ -59,11 +53,6 @@ class GLSpace(Space):
         hp_space : A class for the HEALPix discretization of the sphere [#]_.
         lm_space : A class for spherical harmonic components.
 
-        Notes
-        -----
-        Only real-valued fields on the two-sphere are supported, i.e.
-        `dtype` has to be either numpy.float64 or numpy.float32.
-
         References
         ----------
         .. [#] M. Reinecke and D. Sverre Seljebotn, 2013, "Libsharp - spherical
@@ -75,20 +64,13 @@ class GLSpace(Space):
 
         Attributes
         ----------
-        para : numpy.ndarray
-            One-dimensional array containing the two numbers `nlat` and `nlon`.
         dtype : numpy.dtype
             Data type of the field values.
-        discrete : bool
-            Whether or not the underlying space is discrete, always ``False``
-            for spherical spaces.
-        vol : numpy.ndarray
-            An array containing the pixel sizes.
     """
 
     # ---Overwritten properties and methods---
 
-    def __init__(self, nlat=2, nlon=None, dtype=None):
+    def __init__(self, nlat, nlon=None, dtype=None):
         """
             Sets the attributes for a gl_space class instance.
 
@@ -107,16 +89,10 @@ class GLSpace(Space):
 
             Raises
             ------
-            ImportError
-                If the libsharp_wrapper_gl module is not available.
             ValueError
-                If input `nlat` is invaild.
+                If input `nlat` is invalid.
 
         """
-        # check imports
-        if not gc['use_libsharp']:
-            raise ImportError(
-                "libsharp_wrapper_gl not available or not loaded.")
 
         super(GLSpace, self).__init__(dtype)
 
@@ -147,9 +123,10 @@ class GLSpace(Space):
                               dtype=self.dtype)
 
     def weight(self, x, power=1, axes=None, inplace=False):
+        pyHealpix = gdi.get('pyHealpix')
         nlon = self.nlon
         nlat = self.nlat
-        vol = gl.vol(nlat) ** power
+        vol = pyHealpix.GL_weights(nlat,nlon) ** power
         weight = np.array(list(itertools.chain.from_iterable(
                           itertools.repeat(x, nlon) for x in vol)))
 
@@ -169,29 +146,12 @@ class GLSpace(Space):
         return result_x
 
     def get_distance_array(self, distribution_strategy):
-        dists = d2o.arange(start=0, stop=self.shape[0],
-                           distribution_strategy=distribution_strategy)
-
-        dists = dists.apply_scalar_function(
-            lambda x: self._distance_array_helper(divmod(x, self.nlon)),
-            dtype=np.float)
-
-        return dists
-
-    def _distance_array_helper(self, qr_tuple):
-        lat = qr_tuple[0]*(np.pi/(self.nlat-1))
-        lon = qr_tuple[1]*(2*np.pi/(self.nlon-1))
-        numerator = np.sqrt(np.sin(lon)**2 +
-                            (np.sin(lat) * np.cos(lon))**2)
-        denominator = np.cos(lat) * np.cos(lon)
-
-        return np.arctan(numerator / denominator)
+        raise NotImplementedError \
+            ("get_distance_array only works on spaces with a zero point.")
 
     def get_fft_smoothing_kernel_function(self, sigma):
-        if sigma is None:
-            sigma = np.sqrt(2) * np.pi
-
-        return lambda x: np.exp((-0.5 * x**2) / sigma**2)
+        raise NotImplementedError \
+            ("get_fft_smoothing_kernel not supported by this space.")
 
     # ---Added properties and methods---
 
diff --git a/nifty/spaces/hp_space/hp_space.py b/nifty/spaces/hp_space/hp_space.py
index 210ec4586..d21c3b0bb 100644
--- a/nifty/spaces/hp_space/hp_space.py
+++ b/nifty/spaces/hp_space/hp_space.py
@@ -21,11 +21,6 @@ import numpy as np
 import d2o
 
 from nifty.spaces.space import Space
-from nifty.config import nifty_configuration as gc, \
-                         dependency_injector as gdi
-
-hp = gdi.get('healpy')
-
 
 class HPSpace(Space):
     """
@@ -41,9 +36,9 @@ class HPSpace(Space):
 
         Parameters
         ----------
-        nside : int
+        nside :
             Resolution parameter for the HEALPix discretization, resulting in
-            ``12*nside**2`` pixels.
+            ``12*nside**2`` pixels. Must be positive.
 
         See Also
         --------
@@ -51,10 +46,6 @@ class HPSpace(Space):
             sphere [#]_.
         lm_space : A class for spherical harmonic components.
 
-        Notes
-        -----
-        Only powers of two are allowed for `nside`.
-
         References
         ----------
         .. [#] K.M. Gorski et al., 2005, "HEALPix: A Framework for
@@ -66,20 +57,13 @@ class HPSpace(Space):
 
         Attributes
         ----------
-        para : numpy.ndarray
-            Array containing the number `nside`.
         dtype : numpy.dtype
             Data type of the field values, which is always numpy.float64.
-        discrete : bool
-            Whether or not the underlying space is discrete, always ``False``
-            for spherical spaces.
-        vol : numpy.ndarray
-            An array with one element containing the pixel size.
     """
 
     # ---Overwritten properties and methods---
 
-    def __init__(self, nside=2, dtype=None):
+    def __init__(self, nside, dtype=None):
         """
             Sets the attributes for a hp_space class instance.
 
@@ -87,7 +71,7 @@ class HPSpace(Space):
             ----------
             nside : int
                 Resolution parameter for the HEALPix discretization, resulting
-                in ``12*nside**2`` pixels.
+                in ``12*nside**2`` pixels. Must be positive.
 
             Returns
             -------
@@ -95,15 +79,10 @@ class HPSpace(Space):
 
             Raises
             ------
-            ImportError
-                If the healpy module is not available.
             ValueError
-                If input `nside` is invaild.
+                If input `nside` is invalid.
 
         """
-        # check imports
-        if not gc['use_healpy']:
-            raise ImportError("healpy not available or not loaded.")
 
         super(HPSpace, self).__init__(dtype)
 
@@ -143,36 +122,12 @@ class HPSpace(Space):
         return result_x
 
     def get_distance_array(self, distribution_strategy):
-        """
-        Calculates distance from center to all the points on the sphere
-
-        Parameters
-        ----------
-        distribution_strategy: Result d2o's distribution strategy
-
-        Returns
-        -------
-        dists: distributed_data_object
-        """
-        dists = d2o.arange(
-            start=0, stop=self.shape[0],
-            distribution_strategy=distribution_strategy
-        )
-
-        # translate distances to 3D unit vectors on a sphere,
-        # extract the first entry (simulates the scalar product with (1,0,0))
-        # and apply arccos
-        dists = dists.apply_scalar_function(
-                    lambda z: np.arccos(hp.pix2vec(self.nside, z)[0]),
-                    dtype=np.float)
-
-        return dists
+        raise NotImplementedError \
+            ("get_distance_array only works on spaces with a zero point.")
 
     def get_fft_smoothing_kernel_function(self, sigma):
-        if sigma is None:
-            sigma = np.sqrt(2) * np.pi
-
-        return lambda x: np.exp((-0.5 * x**2) / sigma**2)
+        raise NotImplementedError \
+            ("get_fft_smoothing_kernel not supported by this space.")
 
     # ---Added properties and methods---
 
@@ -182,10 +137,8 @@ class HPSpace(Space):
 
     def _parse_nside(self, nside):
         nside = int(nside)
-        if nside < 2:
-            raise ValueError("nside must be greater than 2.")
-        elif nside % 2 != 0:
-            raise ValueError("nside must be a multiple of 2.")
+        if nside < 1:
+            raise ValueError("nside must be >=1.")
         return nside
 
     # ---Serialization---
diff --git a/nifty/spaces/lm_space/lm_space.py b/nifty/spaces/lm_space/lm_space.py
index c8c098fca..e91675b3a 100644
--- a/nifty/spaces/lm_space/lm_space.py
+++ b/nifty/spaces/lm_space/lm_space.py
@@ -22,14 +22,8 @@ import numpy as np
 
 from nifty.spaces.space import Space
 
-from nifty.config import nifty_configuration as gc,\
-                         dependency_injector as gdi
-
 from d2o import arange
 
-gl = gdi.get('libsharp_wrapper_gl')
-hp = gdi.get('healpy')
-
 def _distance_array_helper(index_array, lmax):
     u=2*lmax+1
     index_half=(index_array+np.minimum(lmax,index_array)+1)//2
@@ -55,9 +49,6 @@ class LMSpace(Space):
         lmax : int
             Maximum :math:`\ell`-value up to which the spherical harmonics
             coefficients are to be used.
-        mmax : int, *optional*
-            Maximum :math:`m`-value up to which the spherical harmonics
-            coefficients are to be used (default: `lmax`).
         dtype : numpy.dtype, *optional*
             Data type of the field values (default: numpy.complex128).
 
@@ -85,16 +76,8 @@ class LMSpace(Space):
 
         Attributes
         ----------
-        para : numpy.ndarray
-            One-dimensional array containing the two numbers `lmax` and
-            `mmax`.
         dtype : numpy.dtype
             Data type of the field values.
-        discrete : bool
-            Parameter captioning the fact that an :py:class:`lm_space` is
-            always discrete.
-        vol : numpy.ndarray
-            Pixel volume of the :py:class:`lm_space`, which is always 1.
     """
 
     def __init__(self, lmax, dtype=None):
@@ -106,9 +89,6 @@ class LMSpace(Space):
             lmax : int
                 Maximum :math:`\ell`-value up to which the spherical harmonics
                 coefficients are to be used.
-            mmax : int, *optional*
-                Maximum :math:`m`-value up to which the spherical harmonics
-                coefficients are to be used (default: `lmax`).
             dtype : numpy.dtype, *optional*
                 Data type of the field values (default: numpy.complex128).
 
@@ -116,21 +96,8 @@ class LMSpace(Space):
             -------
             None.
 
-            Raises
-            ------
-            ImportError
-                If neither the libsharp_wrapper_gl nor the healpy module are
-                available.
-            ValueError
-                If input `nside` is invaild.
-
         """
 
-        # check imports
-        if not gc['use_libsharp'] and not gc['use_healpy']:
-            raise ImportError(
-                "neither libsharp_wrapper_gl nor healpy activated.")
-
         super(LMSpace, self).__init__(dtype)
         self._lmax = self._parse_lmax(lmax)
 
@@ -155,7 +122,7 @@ class LMSpace(Space):
     @property
     def dim(self):
         l = self.lmax
-        # the LMSpace consist of the full triangle (including -m's!),
+        # the LMSpace consists of the full triangle (including -m's!),
         # minus two little triangles if mmax < lmax
         # dim = (((2*(l+1)-1)+1)**2/4 - 2 * (l-m)(l-m+1)/2
         # dim = np.int((l+1)**2 - (l-m)*(l-m+1.))
@@ -188,9 +155,6 @@ class LMSpace(Space):
         return dists
 
     def get_fft_smoothing_kernel_function(self, sigma):
-        if sigma is None:
-            sigma = np.sqrt(2) * np.pi / (self.lmax + 1)
-
         return lambda x: np.exp(-0.5 * x * (x + 1) * sigma**2)
 
     # ---Added properties and methods---
@@ -205,11 +169,8 @@ class LMSpace(Space):
 
     def _parse_lmax(self, lmax):
         lmax = np.int(lmax)
-        if lmax < 1:
-            raise ValueError("lmax must be non-zero and positive.")
-        # exception lmax == 2 (nside == 1)
-        if (lmax % 2 == 0) and (lmax > 2):
-            self.logger.warn("Unrecommended parameter (lmax <> 2*n+1).")
+        if lmax < 0:
+            raise ValueError("lmax must be >=0.")
         return lmax
 
     # ---Serialization---
diff --git a/test/common.py b/test/common.py
index 0dadff479..fad4d1ca5 100644
--- a/test/common.py
+++ b/test/common.py
@@ -66,13 +66,12 @@ def expand(*args, **kwargs):
 
 
 def generate_spaces():
-    spaces = [RGSpace(4), PowerSpace(RGSpace((4, 4), harmonic=True))]
+    spaces = [RGSpace(4), PowerSpace(RGSpace((4, 4), harmonic=True)),
+              LMSpace(5), HPSpace(4), GLSpace(4)]
 
-    if 'healpy' in di:
-        spaces.append(HPSpace(4))
-    if 'libsharp_wrapper_gl' in di:
-        spaces.append(GLSpace(4))
-    if 'healpy' in di or 'libsharp_wrapper_gl' in di:
-        spaces.append(LMSpace(5))
+    return spaces
+
+def generate_harmonic_spaces():
+    spaces = [RGSpace(4),LMSpace(5)]
 
     return spaces
diff --git a/test/test_spaces/test_gl_space.py b/test/test_spaces/test_gl_space.py
index 8ad315f6f..d8b0616e2 100644
--- a/test/test_spaces/test_gl_space.py
+++ b/test/test_spaces/test_gl_space.py
@@ -69,31 +69,24 @@ class GLSpaceInterfaceTests(unittest.TestCase):
     @expand([['nlat', int],
             ['nlon', int]])
     def test_property_ret_type(self, attribute, expected_type):
-        try:
-            g = GLSpace()
-        except ImportError:
-            raise SkipTest
+        g = GLSpace(2)
         assert_(isinstance(getattr(g, attribute), expected_type))
 
 
 class GLSpaceFunctionalityTests(unittest.TestCase):
     @expand(CONSTRUCTOR_CONFIGS)
     def test_constructor(self, nlat, nlon, dtype, expected):
-        if 'libsharp_wrapper_gl' not in di:
-            raise SkipTest
+        if 'error' in expected:
+            with assert_raises(expected['error']):
+                GLSpace(nlat, nlon, dtype)
         else:
-            if 'error' in expected:
-                with assert_raises(expected['error']):
-                    GLSpace(nlat, nlon, dtype)
-            else:
-                g = GLSpace(nlat, nlon, dtype)
-                for key, value in expected.iteritems():
-                    assert_equal(getattr(g, key), value)
+            g = GLSpace(nlat, nlon, dtype)
+            for key, value in expected.iteritems():
+                assert_equal(getattr(g, key), value)
 
     @expand(get_weight_configs())
-    @unittest.expectedFailure
     def test_weight(self, x, power, axes, inplace, expected):
-        if 'libsharp_wrapper_gl' not in di:
+        if 'pyHealpix' not in di:
             raise SkipTest
         else:
             g = GLSpace(2)
diff --git a/test/test_spaces/test_hp_space.py b/test/test_spaces/test_hp_space.py
index 507886a58..6a9e1b503 100644
--- a/test/test_spaces/test_hp_space.py
+++ b/test/test_spaces/test_hp_space.py
@@ -21,7 +21,6 @@ import numpy as np
 
 from numpy.testing import assert_, assert_equal, assert_raises,\
                           assert_almost_equal
-from nose.plugins.skip import SkipTest
 from nifty import HPSpace
 from nifty.config import dependency_injector as di
 from test.common import expand
@@ -37,9 +36,22 @@ CONSTRUCTOR_CONFIGS = [
             'dtype': np.dtype('float64')
             }],
         [5, None, {
-            'error': ValueError
+            'nside': 5,
+            'harmonic': False,
+            'shape': (300,),
+            'dim': 300,
+            'total_volume': 4 * np.pi,
+            'dtype': np.dtype('float64')
             }],
         [1, None, {
+            'nside': 1,
+            'harmonic': False,
+            'shape': (12,),
+            'dim': 12,
+            'total_volume': 4 * np.pi,
+            'dtype': np.dtype('float64')
+            }],
+        [0, None, {
             'error': ValueError
             }]
     ]
@@ -62,34 +74,25 @@ def get_weight_configs():
 class HPSpaceInterfaceTests(unittest.TestCase):
     @expand([['nside', int]])
     def test_property_ret_type(self, attribute, expected_type):
-        try:
-            x = HPSpace()
-        except ImportError:
-            raise SkipTest
+        x = HPSpace(2)
         assert_(isinstance(getattr(x, attribute), expected_type))
 
 
 class HPSpaceFunctionalityTests(unittest.TestCase):
     @expand(CONSTRUCTOR_CONFIGS)
     def test_constructor(self, nside, dtype, expected):
-        if 'healpy' not in di:
-            raise SkipTest
+        if 'error' in expected:
+            with assert_raises(expected['error']):
+                HPSpace(nside, dtype)
         else:
-            if 'error' in expected:
-                with assert_raises(expected['error']):
-                    HPSpace(nside, dtype)
-            else:
-                h = HPSpace(nside, dtype)
-                for key, value in expected.iteritems():
-                    assert_equal(getattr(h, key), value)
+            h = HPSpace(nside, dtype)
+            for key, value in expected.iteritems():
+                assert_equal(getattr(h, key), value)
 
     @expand(get_weight_configs())
     def test_weight(self, x, power, axes, inplace, expected):
-        if 'healpy' not in di:
-            raise SkipTest
-        else:
-            h = HPSpace(2)
-            res = h.weight(x, power, axes, inplace)
-            assert_almost_equal(res, expected)
-            if inplace:
-                assert_(x is res)
+        h = HPSpace(2)
+        res = h.weight(x, power, axes, inplace)
+        assert_almost_equal(res, expected)
+        if inplace:
+            assert_(x is res)
diff --git a/test/test_spaces/test_interface.py b/test/test_spaces/test_interface.py
index c77b07dee..e05dcfbeb 100644
--- a/test/test_spaces/test_interface.py
+++ b/test/test_spaces/test_interface.py
@@ -22,24 +22,12 @@ import numpy as np
 from itertools import product
 from types import LambdaType
 from numpy.testing import assert_, assert_raises, assert_equal
-from nose.plugins.skip import SkipTest
 from nifty import LMSpace, GLSpace, HPSpace
 from nifty.config import dependency_injector as di
-from test.common import expand, generate_spaces
+from test.common import expand, generate_spaces, generate_harmonic_spaces
 
 
 class SpaceInterfaceTests(unittest.TestCase):
-    def test_dependency_handling(self):
-        if 'healpy' not in di and 'libsharp_wrapper_gl' not in di:
-            with assert_raises(ImportError):
-                LMSpace(5)
-        elif 'healpy' not in di:
-            with assert_raises(ImportError):
-                HPSpace(4)
-        elif 'libsharp_wrapper_gl' not in di:
-            with assert_raises(ImportError):
-                GLSpace(4)
-
     @expand(product(generate_spaces(), [['dtype', np.dtype],
                     ['harmonic', bool],
                     ['shape', tuple],
@@ -53,17 +41,13 @@ class SpaceInterfaceTests(unittest.TestCase):
             ), attr_expected_type[1])
         )
 
-    @expand(product(generate_spaces(), [
+    @expand(product(generate_harmonic_spaces(), [
         ['get_fft_smoothing_kernel_function', None, LambdaType],
         ['get_fft_smoothing_kernel_function', 2.0, LambdaType],
         ]))
     def test_method_ret_type(self, space, method_expected_type):
-        # handle exceptions here
-        try:
-            getattr(
-                space, method_expected_type[0])(*method_expected_type[1:-1])
-        except NotImplementedError:
-            raise SkipTest
+        getattr(
+            space, method_expected_type[0])(*method_expected_type[1:-1])
 
         assert_equal(
             type(getattr(
diff --git a/test/test_spaces/test_lm_space.py b/test/test_spaces/test_lm_space.py
index ce4bf0e40..5e27dbe84 100644
--- a/test/test_spaces/test_lm_space.py
+++ b/test/test_spaces/test_lm_space.py
@@ -21,10 +21,8 @@ import numpy as np
 
 from numpy.testing import assert_, assert_equal, assert_raises,\
         assert_almost_equal
-from nose.plugins.skip import SkipTest
 from d2o import distributed_data_object
 from nifty import LMSpace
-from nifty.config import dependency_injector as di
 from test.common import expand
 
 # [lmax, dtype, expected]
@@ -52,7 +50,6 @@ CONSTRUCTOR_CONFIGS = [
             }]
     ]
 
-
 def _distance_array_helper(index_arr, lmax):
     if index_arr <= lmax:
         index_half = index_arr
@@ -69,7 +66,6 @@ def _distance_array_helper(index_arr, lmax):
 
     return index_half - m * (2 * lmax + 1 - m) // 2
 
-
 def get_distance_array_configs():
     da_0 = [_distance_array_helper(idx, 5) for idx in np.arange(36)]
     return [[5, None, da_0]]
@@ -83,7 +79,6 @@ def get_weight_configs():
         [w_0_x.copy(), 1, None,  True, w_0_x]
         ]
 
-
 def get_hermitian_configs():
     np.random.seed(42)
     h_0_res_real = np.random.rand(32, 16, 6).astype(np.complex128)
@@ -93,61 +88,45 @@ def get_hermitian_configs():
         [h_0_x, h_0_res_real, h_0_res_imag]
     ]
 
-
-class LMSpaceIntefaceTests(unittest.TestCase):
+class LMSpaceInterfaceTests(unittest.TestCase):
     @expand([['lmax', int],
             ['mmax', int],
             ['dim', int]])
     def test_property_ret_type(self, attribute, expected_type):
-        try:
-            l = LMSpace(7)
-        except ImportError:
-            raise SkipTest
+        l = LMSpace(7)
         assert_(isinstance(getattr(l, attribute), expected_type))
 
 
 class LMSpaceFunctionalityTests(unittest.TestCase):
     @expand(CONSTRUCTOR_CONFIGS)
     def test_constructor(self, lmax, dtype, expected):
-        if 'libsharp_wrapper_gl' not in di or 'healpy' not in di:
-            raise SkipTest
+        if 'error' in expected:
+            with assert_raises(expected['error']):
+                LMSpace(lmax, dtype)
         else:
-            if 'error' in expected:
-                with assert_raises(expected['error']):
-                    LMSpace(lmax, dtype)
-            else:
-                l = LMSpace(lmax, dtype)
-                for key, value in expected.iteritems():
-                    assert_equal(getattr(l, key), value)
+            l = LMSpace(lmax, dtype)
+            for key, value in expected.iteritems():
+                assert_equal(getattr(l, key), value)
 
     @expand(get_hermitian_configs())
     def test_hermitian_decomposition(self, x, real, imag):
-        if 'libsharp_wrapper_gl' not in di or 'healpy' not in di:
-            raise SkipTest
-        else:
-            l = LMSpace(5)
-            assert_almost_equal(
-                l.hermitian_decomposition(distributed_data_object(x))[0],
-                real)
-            assert_almost_equal(
-                l.hermitian_decomposition(distributed_data_object(x))[1],
-                imag)
+        l = LMSpace(5)
+        assert_almost_equal(
+            l.hermitian_decomposition(distributed_data_object(x))[0],
+            real)
+        assert_almost_equal(
+            l.hermitian_decomposition(distributed_data_object(x))[1],
+            imag)
 
     @expand(get_weight_configs())
     def test_weight(self, x, power, axes, inplace, expected):
-        if 'libsharp_wrapper_gl' not in di or 'healpy' not in di:
-            raise SkipTest
-        else:
-            l = LMSpace(5)
-            res = l.weight(x, power, axes, inplace)
-            assert_almost_equal(res, expected)
-            if inplace:
-                assert_(x is res)
+        l = LMSpace(5)
+        res = l.weight(x, power, axes, inplace)
+        assert_almost_equal(res, expected)
+        if inplace:
+            assert_(x is res)
 
     @expand(get_distance_array_configs())
     def test_distance_array(self, lmax, dtype, expected):
-        if 'libsharp_wrapper_gl' not in di or 'healpy' not in di:
-            raise SkipTest
-        else:
-            l = LMSpace(lmax, dtype)
-            assert_almost_equal(l.get_distance_array('not').data, expected)
+        l = LMSpace(lmax, dtype)
+        assert_almost_equal(l.get_distance_array('not').data, expected)
-- 
GitLab