gl_space.py 5.67 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
25
import d2o
from d2o import STRATEGIES as DISTRIBUTION_STRATEGIES
csongor's avatar
csongor committed
26

27
from nifty.spaces.space import Space
28
from nifty.config import dependency_injector as gdi
29

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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
    """
        ..                 __
        ..               /  /
        ..     ____ __  /  /
        ..   /   _   / /  /
        ..  /  /_/  / /  /_
        ..  \___   /  \___/  space class
        .. /______/

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

        Parameters
        ----------
        nlat : int
            Number of latitudinal bins, or rings.
        nlon : int, *optional*
            Number of longitudinal bins (default: ``2*nlat - 1``).
        dtype : numpy.dtype, *optional*
            Data type of the field values (default: numpy.float64).

        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.

        Attributes
        ----------
        dtype : numpy.dtype
            Data type of the field values.
    """

71
72
    # ---Overwritten properties and methods---

73
    def __init__(self, nlat, nlon=None, dtype=None):
csongor's avatar
csongor committed
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
        """
            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``).
            dtype : numpy.dtype, *optional*
                Data type of the field values (default: numpy.float64).

            Returns
            -------
            None

            Raises
            ------
            ValueError
93
                If input `nlat` is invalid.
csongor's avatar
csongor committed
94
95

        """
96
97

        super(GLSpace, self).__init__(dtype)
csongor's avatar
csongor committed
98

99
100
        self._nlat = self._parse_nlat(nlat)
        self._nlon = self._parse_nlon(nlon)
csongor's avatar
csongor committed
101

102
    # ---Mandatory properties and methods---
csongor's avatar
csongor committed
103

104
105
106
    @property
    def harmonic(self):
        return False
csongor's avatar
csongor committed
107
108
109

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

112
    @property
113
    def dim(self):
114
        return np.int((self.nlat * self.nlon))
115
116
117
118

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

120
121
122
123
124
    def copy(self):
        return self.__class__(nlat=self.nlat,
                              nlon=self.nlon,
                              dtype=self.dtype)

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

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

        if inplace:
            x *= weight
            result_x = x
csongor's avatar
csongor committed
143
        else:
Jait Dixit's avatar
Jait Dixit committed
144
            result_x = x * weight
csongor's avatar
csongor committed
145

Jait Dixit's avatar
Jait Dixit committed
146
        return result_x
147

148
    def get_distance_array(self, distribution_strategy):
149
150
        raise NotImplementedError \
            ("get_distance_array only works on spaces with a zero point.")
151

152
    def get_fft_smoothing_kernel_function(self, sigma):
153
154
        raise NotImplementedError \
            ("get_fft_smoothing_kernel not supported by this space.")
155

156
157
158
159
160
161
162
163
164
165
166
167
    # ---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)
168
169
170
        if nlat < 1:
            raise ValueError(
                "nlat must be a positive number.")
171
172
173
174
175
176
177
        return nlat

    def _parse_nlon(self, nlon):
        if nlon is None:
            nlon = 2 * self.nlat - 1
        else:
            nlon = int(nlon)
178
179
            if nlon < 1:
                raise ValueError("nlon must be a positive number.")
180
        return nlon
181
182
183
184

    # ---Serialization---

    def _to_hdf5(self, hdf5_group):
Jait Dixit's avatar
Jait Dixit committed
185
186
        hdf5_group['nlat'] = self.nlat
        hdf5_group['nlon'] = self.nlon
187
        hdf5_group.attrs['dtype'] = self.dtype.name
Jait Dixit's avatar
Jait Dixit committed
188

189
190
191
        return None

    @classmethod
Theo Steininger's avatar
Theo Steininger committed
192
    def _from_hdf5(cls, hdf5_group, repository):
193
        result = cls(
Jait Dixit's avatar
Jait Dixit committed
194
195
            nlat=hdf5_group['nlat'][()],
            nlon=hdf5_group['nlon'][()],
196
            dtype=np.dtype(hdf5_group.attrs['dtype'])
Jait Dixit's avatar
Jait Dixit committed
197
198
            )

199
        return result