gl_space.py 5.79 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, *optional*
            Number of longitudinal bins (default: ``2*nlat - 1``).
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` or `nlon` is invalid.
csongor's avatar
csongor committed
86
87

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

Martin Reinecke's avatar
Martin Reinecke committed
92
        super(GLSpace, self).__init__()
csongor's avatar
csongor committed
93

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

97
    # ---Mandatory properties and methods---
csongor's avatar
csongor committed
98

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

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

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

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

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

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

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

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

Jait Dixit's avatar
Jait Dixit committed
139
        return result_x
140

141
    def get_distance_array(self, distribution_strategy):
142
143
144
145
146
147
148
        """This should not be used, it just raises an error when called.
        
        Raises
        ------
        NotImplementedError
            Always when called.
        """
Theo Steininger's avatar
Theo Steininger committed
149
        raise NotImplementedError
150

151
    def get_fft_smoothing_kernel_function(self, sigma):
152
153
154
155
156
157
158
        """This should not be used, it just raises an error when called.
        
        Raises
        ------
        NotImplementedError
            Always when called.
        """
Theo Steininger's avatar
Theo Steininger committed
159
        raise NotImplementedError
160

161
162
163
164
    # ---Added properties and methods---

    @property
    def nlat(self):
165
166
167
168
169
        """Number of latitudinal bins.
        Returns
        -------
        int : Number of latitudinal bins (or rings) that are used in the pixelization
        """
170
171
172
173
        return self._nlat

    @property
    def nlon(self):
174
175
176
177
178
        """Number of longditudinal bins.
        Returns
        -------
        int : Number of longditudinal bins that are used in the pixelization
        """
179
180
181
182
        return self._nlon

    def _parse_nlat(self, nlat):
        nlat = int(nlat)
183
184
185
        if nlat < 1:
            raise ValueError(
                "nlat must be a positive number.")
186
187
188
189
190
191
192
        return nlat

    def _parse_nlon(self, nlon):
        if nlon is None:
            nlon = 2 * self.nlat - 1
        else:
            nlon = int(nlon)
193
194
            if nlon < 1:
                raise ValueError("nlon must be a positive number.")
195
        return nlon
196
197
198
199

    # ---Serialization---

    def _to_hdf5(self, hdf5_group):
Jait Dixit's avatar
Jait Dixit committed
200
201
202
        hdf5_group['nlat'] = self.nlat
        hdf5_group['nlon'] = self.nlon

203
204
205
        return None

    @classmethod
Theo Steininger's avatar
Theo Steininger committed
206
    def _from_hdf5(cls, hdf5_group, repository):
207
        result = cls(
Jait Dixit's avatar
Jait Dixit committed
208
209
210
211
            nlat=hdf5_group['nlat'][()],
            nlon=hdf5_group['nlon'][()],
            )

212
        return result