gl_space.py 5.14 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# NIFTy
# Copyright (C) 2017  Theo Steininger
#
# Author: Theo Steininger
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

csongor's avatar
csongor committed
19
20
from __future__ import division

Jait Dixit's avatar
Jait Dixit committed
21
import itertools
csongor's avatar
csongor committed
22
23
import numpy as np

24
from nifty.spaces.space import Space
25
from nifty.config import dependency_injector as gdi
26

Theo Steininger's avatar
Theo Steininger committed
27
28
29
pyHealpix = gdi.get('pyHealpix')


Theo Steininger's avatar
Theo Steininger committed
30
class GLSpace(Space):
csongor's avatar
csongor committed
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
    """
        ..                 __
        ..               /  /
        ..     ____ __  /  /
        ..   /   _   / /  /
        ..  /  /_/  / /  /_
        ..  \___   /  \___/  space class
        .. /______/

        NIFTY subclass for Gauss-Legendre pixelizations [#]_ of the two-sphere.

        Parameters
        ----------
        nlat : int
            Number of latitudinal bins, or rings.
46
47
        nlon : int
            Number of longitudinal bins.
csongor's avatar
csongor committed
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64

        See Also
        --------
        hp_space : A class for the HEALPix discretization of the sphere [#]_.
        lm_space : A class for spherical harmonic components.

        References
        ----------
        .. [#] M. Reinecke and D. Sverre Seljebotn, 2013, "Libsharp - spherical
               harmonic transforms revisited";
               `arXiv:1303.4945 <http://www.arxiv.org/abs/1303.4945>`_
        .. [#] K.M. Gorski et al., 2005, "HEALPix: A Framework for
               High-Resolution Discretization and Fast Analysis of Data
               Distributed on the Sphere", *ApJ* 622..759G.

    """

65
66
    # ---Overwritten properties and methods---

Martin Reinecke's avatar
Martin Reinecke committed
67
    def __init__(self, nlat, nlon=None):
csongor's avatar
csongor committed
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
        """
            Sets the attributes for a gl_space class instance.

            Parameters
            ----------
            nlat : int
                Number of latitudinal bins, or rings.
            nlon : int, *optional*
                Number of longitudinal bins (default: ``2*nlat - 1``).

            Returns
            -------
            None

            Raises
            ------
            ValueError
85
                If input `nlat` is invalid.
86
87
            ImportError
                If the pyHealpix module is not available
csongor's avatar
csongor committed
88
89

        """
Theo Steininger's avatar
Theo Steininger committed
90
91
92
        if 'pyHealpix' not in gdi:
            raise ImportError(
                "The module pyHealpix is needed but not available.")
93

Martin Reinecke's avatar
Martin Reinecke committed
94
        super(GLSpace, self).__init__()
csongor's avatar
csongor committed
95

96
97
        self._nlat = self._parse_nlat(nlat)
        self._nlon = self._parse_nlon(nlon)
csongor's avatar
csongor committed
98

99
    # ---Mandatory properties and methods---
csongor's avatar
csongor committed
100

101
102
103
    @property
    def harmonic(self):
        return False
csongor's avatar
csongor committed
104
105
106

    @property
    def shape(self):
107
        return (np.int((self.nlat * self.nlon)),)
csongor's avatar
csongor committed
108

109
    @property
110
    def dim(self):
111
        return np.int((self.nlat * self.nlon))
112
113
114
115

    @property
    def total_volume(self):
        return 4 * np.pi
116

117
118
    def copy(self):
        return self.__class__(nlat=self.nlat,
Martin Reinecke's avatar
Martin Reinecke committed
119
                              nlon=self.nlon)
120

Jait Dixit's avatar
Jait Dixit committed
121
    def weight(self, x, power=1, axes=None, inplace=False):
122
123
        nlon = self.nlon
        nlat = self.nlat
Theo Steininger's avatar
Theo Steininger committed
124
        vol = pyHealpix.GL_weights(nlat, nlon) ** power
125
        weight = np.array(list(itertools.chain.from_iterable(
Theo Steininger's avatar
Theo Steininger committed
126
                          itertools.repeat(x, nlon) for x in vol)))
Jait Dixit's avatar
Jait Dixit committed
127
128
129

        if axes is not None:
            # reshape the weight array to match the input shape
130
            new_shape = np.ones(len(x.shape), dtype=np.int)
131
132
            # we know len(axes) is always 1
            new_shape[axes[0]] = len(weight)
Jait Dixit's avatar
Jait Dixit committed
133
134
135
136
137
            weight = weight.reshape(new_shape)

        if inplace:
            x *= weight
            result_x = x
csongor's avatar
csongor committed
138
        else:
Jait Dixit's avatar
Jait Dixit committed
139
            result_x = x * weight
csongor's avatar
csongor committed
140

Jait Dixit's avatar
Jait Dixit committed
141
        return result_x
142

143
    def get_distance_array(self, distribution_strategy):
Theo Steininger's avatar
Theo Steininger committed
144
        raise NotImplementedError
145

146
    def get_fft_smoothing_kernel_function(self, sigma):
Theo Steininger's avatar
Theo Steininger committed
147
        raise NotImplementedError
148

149
150
151
152
153
154
155
156
157
158
159
160
    # ---Added properties and methods---

    @property
    def nlat(self):
        return self._nlat

    @property
    def nlon(self):
        return self._nlon

    def _parse_nlat(self, nlat):
        nlat = int(nlat)
161
162
163
        if nlat < 1:
            raise ValueError(
                "nlat must be a positive number.")
164
165
166
167
168
169
170
        return nlat

    def _parse_nlon(self, nlon):
        if nlon is None:
            nlon = 2 * self.nlat - 1
        else:
            nlon = int(nlon)
171
172
            if nlon < 1:
                raise ValueError("nlon must be a positive number.")
173
        return nlon
174
175
176
177

    # ---Serialization---

    def _to_hdf5(self, hdf5_group):
Jait Dixit's avatar
Jait Dixit committed
178
179
180
        hdf5_group['nlat'] = self.nlat
        hdf5_group['nlon'] = self.nlon

181
182
183
        return None

    @classmethod
Theo Steininger's avatar
Theo Steininger committed
184
    def _from_hdf5(cls, hdf5_group, repository):
185
        result = cls(
Jait Dixit's avatar
Jait Dixit committed
186
187
188
189
            nlat=hdf5_group['nlat'][()],
            nlon=hdf5_group['nlon'][()],
            )

190
        return result