Noise   A
last analyzed

Complexity

Total Complexity 33

Size/Duplication

Total Lines 220
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
dl 0
loc 220
rs 9.76
c 2
b 0
f 0
wmc 33

14 Methods

Rating   Name   Duplication   Size   Complexity  
A dimensions() 0 3 1
A implementation() 0 3 2
A octaves() 0 3 1
A algorithm() 0 3 1
A dimentions() 0 3 1
A lacunarity() 0 3 1
A hurst() 0 3 1
A __setstate__() 0 19 3
A __init__() 0 20 3
A get_point() 0 10 1
B __getstate__() 0 30 5
B sample_ogrid() 0 26 5
A sample_mgrid() 0 28 3
A _setstate_old() 0 17 2
1
"""
2
The :any:`Noise.sample_mgrid` and :any:`Noise.sample_ogrid` methods are
3
multi-threaded operations when the Python runtime supports OpenMP.
4
Even when single threaded these methods will perform much better than
5
multiple calls to :any:`Noise.get_point`.
6
7
Example::
8
9
    import numpy as np
10
    import tcod
11
    import tcod.noise
12
13
    noise = tcod.noise.Noise(
14
        dimensions=2,
15
        algorithm=tcod.NOISE_SIMPLEX,
16
        implementation=tcod.noise.TURBULENCE,
17
        hurst=0.5,
18
        lacunarity=2.0,
19
        octaves=4,
20
        seed=None,
21
        )
22
23
    # Create a 5x5 open multi-dimensional mesh-grid.
24
    ogrid = [np.arange(5, dtype=np.float32),
25
             np.arange(5, dtype=np.float32)]
26
    print(ogrid)
27
28
    # Scale the grid.
29
    ogrid[0] *= 0.25
30
    ogrid[1] *= 0.25
31
32
    # Return the sampled noise from this grid of points.
33
    samples = noise.sample_ogrid(ogrid)
34
    print(samples)
35
"""
36
from __future__ import absolute_import
37
38
import numpy as np
0 ignored issues
show
Configuration introduced by
The import numpy could not be resolved.

This can be caused by one of the following:

1. Missing Dependencies

This error could indicate a configuration issue of Pylint. Make sure that your libraries are available by adding the necessary commands.

# .scrutinizer.yml
before_commands:
    - sudo pip install abc # Python2
    - sudo pip3 install abc # Python3
Tip: We are currently not using virtualenv to run pylint, when installing your modules make sure to use the command for the correct version.

2. Missing __init__.py files

This error could also result from missing __init__.py files in your module folders. Make sure that you place one file in each sub-folder.

Loading history...
39
40
from tcod.libtcod import ffi, lib
41
import tcod.libtcod
42
43
"""Noise implementation constants"""
0 ignored issues
show
Unused Code introduced by
This string statement has no effect and could be removed.
Loading history...
44
SIMPLE = 0
45
FBM = 1
46
TURBULENCE = 2
47
48
class Noise(object):
49
    """
50
51
    The ``hurst`` exponent describes the raggedness of the resultant noise,
52
    with a higher value leading to a smoother noise.
53
    Not used with tcod.noise.SIMPLE.
54
55
    ``lacunarity`` is a multiplier that determines how fast the noise
56
    frequency increases for each successive octave.
57
    Not used with tcod.noise.SIMPLE.
58
59
    Args:
60
        dimensions (int): Must be from 1 to 4.
61
        algorithm (int): Defaults to NOISE_SIMPLEX
62
        implementation (int): Defaults to tcod.noise.SIMPLE
63
        hurst (float): The hurst exponent.  Should be in the 0.0-1.0 range.
64
        lacunarity (float): The noise lacunarity.
65
        octaves (float): The level of detail on fBm and turbulence
66
                         implementations.
67
        seed (Optional[Random]): A Random instance, or None.
68
69
    Attributes:
70
        noise_c (CData): A cffi pointer to a TCOD_noise_t object.
71
    """
72
73
    def __init__(self, dimensions, algorithm=2, implementation=SIMPLE,
74
                 hurst=0.5, lacunarity=2.0, octaves=4, seed=None):
75
        if not 0 < dimensions <= 4:
76
            raise ValueError('dimensions must be in range 0 < n <= 4, got %r' %
77
                             (dimensions,))
78
        self._random = seed
79
        _random_c = seed.random_c if seed else ffi.NULL
80
        self._algorithm = algorithm
81
        self.noise_c = ffi.gc(
82
            ffi.cast(
83
                'perlin_data_t*',
84
                lib.TCOD_noise_new(dimensions, hurst, lacunarity,
85
                                   _random_c),
86
                ),
87
            lib.TCOD_noise_delete)
88
        self._tdl_noise_c = ffi.new('TDLNoise*', (self.noise_c,
89
                                                  dimensions,
90
                                                  0,
91
                                                  octaves))
92
        self.implementation = implementation # sanity check
93
94
    @property
95
    def dimensions(self):
0 ignored issues
show
Coding Style introduced by
This method should have a docstring.

The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods:

class SomeClass:
    def some_method(self):
        """Do x and return foo."""

If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions.

Loading history...
96
        return self._tdl_noise_c.dimensions
97
98
    @property
99
    def dimentions(self): # deprecated
0 ignored issues
show
Coding Style introduced by
This method should have a docstring.

The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods:

class SomeClass:
    def some_method(self):
        """Do x and return foo."""

If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions.

Loading history...
100
        return self.dimensions
101
102
    @property
103
    def algorithm(self):
0 ignored issues
show
Coding Style introduced by
This method should have a docstring.

The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods:

class SomeClass:
    def some_method(self):
        """Do x and return foo."""

If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions.

Loading history...
104
        return self.noise_c.noise_type
105
    @algorithm.setter
106
    def algorithm(self, value):
0 ignored issues
show
Coding Style introduced by
This method should have a docstring.

The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods:

class SomeClass:
    def some_method(self):
        """Do x and return foo."""

If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions.

Loading history...
107
        lib.TCOD_noise_set_type(self.noise_c, value)
108
109
    @property
110
    def implementation(self):
0 ignored issues
show
Coding Style introduced by
This method should have a docstring.

The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods:

class SomeClass:
    def some_method(self):
        """Do x and return foo."""

If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions.

Loading history...
111
        return self._tdl_noise_c.implementation
112
    @implementation.setter
113
    def implementation(self, value):
0 ignored issues
show
Coding Style introduced by
This method should have a docstring.

The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods:

class SomeClass:
    def some_method(self):
        """Do x and return foo."""

If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions.

Loading history...
114
        if not 0 <= value < 3:
115
            raise ValueError('%r is not a valid implementation. ' % (value,))
116
        self._tdl_noise_c.implementation = value
117
118
    @property
119
    def hurst(self):
0 ignored issues
show
Coding Style introduced by
This method should have a docstring.

The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods:

class SomeClass:
    def some_method(self):
        """Do x and return foo."""

If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions.

Loading history...
120
        return self.noise_c.H
121
122
    @property
123
    def lacunarity(self):
0 ignored issues
show
Coding Style introduced by
This method should have a docstring.

The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods:

class SomeClass:
    def some_method(self):
        """Do x and return foo."""

If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions.

Loading history...
124
        return self.noise_c.lacunarity
125
126
    @property
127
    def octaves(self):
0 ignored issues
show
Coding Style introduced by
This method should have a docstring.

The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods:

class SomeClass:
    def some_method(self):
        """Do x and return foo."""

If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions.

Loading history...
128
        return self._tdl_noise_c.octaves
129
    @octaves.setter
130
    def octaves(self, value):
0 ignored issues
show
Coding Style introduced by
This method should have a docstring.

The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods:

class SomeClass:
    def some_method(self):
        """Do x and return foo."""

If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions.

Loading history...
131
        self._tdl_noise_c.octaves = value
132
133
    def get_point(self, x=0, y=0, z=0, w=0):
0 ignored issues
show
Coding Style Naming introduced by
The name x does not conform to the argument naming conventions ([a-z_][a-z0-9_]{2,30}$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
Coding Style Naming introduced by
The name y does not conform to the argument naming conventions ([a-z_][a-z0-9_]{2,30}$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
Coding Style Naming introduced by
The name z does not conform to the argument naming conventions ([a-z_][a-z0-9_]{2,30}$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
Coding Style Naming introduced by
The name w does not conform to the argument naming conventions ([a-z_][a-z0-9_]{2,30}$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
134
        """Return the noise value at the (x, y, z, w) point.
135
136
        Args:
137
            x (float): The position on the 1st axis.
138
            y (float): The position on the 2nd axis.
139
            z (float): The position on the 3rd axis.
140
            w (float): The position on the 4th axis.
141
        """
142
        return lib.NoiseGetSample(self._tdl_noise_c, (x, y, z, w))
143
144
    def sample_mgrid(self, mgrid):
145
        """Sample a mesh-grid array and return the result.
146
147
        The :any:`sample_ogrid` method performs better as there is a lot of
148
        overhead when working with large mesh-grids.
149
150
        Args:
151
            mgrid (numpy.ndarray): A mesh-grid array of points to sample.
152
                A contiguous array of type `numpy.float32` is preferred.
153
154
        Returns:
155
            numpy.ndarray: An array of sampled points.
156
157
                This array has the shape: ``mgrid.shape[:-1]``.
158
                The ``dtype`` is `numpy.float32`.
159
        """
160
        mgrid = np.ascontiguousarray(mgrid, np.float32)
161
        if mgrid.shape[0] != self.dimensions:
162
            raise ValueError('mgrid.shape[0] must equal self.dimensions, '
163
                             '%r[0] != %r' % (mgrid.shape, self.dimensions))
164
        out = np.ndarray(mgrid.shape[1:], np.float32)
165
        if mgrid.shape[1:] != out.shape:
166
            raise ValueError('mgrid.shape[1:] must equal out.shape, '
167
                             '%r[1:] != %r' % (mgrid.shape, out.shape))
168
        lib.NoiseSampleMeshGrid(self._tdl_noise_c, out.size,
169
                                ffi.cast('float*', mgrid.ctypes.data),
170
                                ffi.cast('float*', out.ctypes.data))
171
        return out
172
173
    def sample_ogrid(self, ogrid):
174
        """Sample an open mesh-grid array and return the result.
175
176
        Args
177
            ogrid (Sequence[Sequence[float]]): An open mesh-grid.
178
179
        Returns:
180
            numpy.ndarray: An array of sampled points.
181
182
                The ``shape`` is based on the lengths of the open mesh-grid
183
                arrays.
184
                The ``dtype`` is `numpy.float32`.
185
        """
186
        if len(ogrid) != self.dimensions:
187
            raise ValueError('len(ogrid) must equal self.dimensions, '
188
                             '%r != %r' % (len(ogrid), self.dimensions))
189
        ogrids = [np.ascontiguousarray(array, np.float32) for array in ogrid]
190
        out = np.ndarray([array.size for array in ogrids], np.float32)
191
        lib.NoiseSampleOpenMeshGrid(
192
            self._tdl_noise_c,
193
            len(ogrids),
194
            out.shape,
195
            [ffi.cast('float*', array.ctypes.data) for array in ogrids],
196
            ffi.cast('float*', out.ctypes.data),
197
            )
198
        return out
199
200
    def __getstate__(self):
201
        state = self.__dict__.copy()
202
        if self.dimensions < 4 and self.noise_c.waveletTileData == ffi.NULL:
203
            # Trigger a side effect of wavelet, so that copies will be synced.
204
            saved_algo = self.algorithm
205
            self.algorithm = tcod.libtcod.NOISE_WAVELET
0 ignored issues
show
Bug introduced by
The Module tcod.libtcod does not seem to have a member named NOISE_WAVELET.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
206
            self.get_point()
207
            self.algorithm = saved_algo
208
209
        waveletTileData = None
0 ignored issues
show
Coding Style Naming introduced by
The name waveletTileData does not conform to the variable naming conventions ([a-z_][a-z0-9_]{2,30}$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
210
        if self.noise_c.waveletTileData != ffi.NULL:
211
            waveletTileData = list(self.noise_c.waveletTileData[0:32*32*32])
0 ignored issues
show
Coding Style Naming introduced by
The name waveletTileData does not conform to the variable naming conventions ([a-z_][a-z0-9_]{2,30}$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
212
            state['_waveletTileData'] = waveletTileData
213
214
        state['noise_c'] = {
215
            'ndim': self.noise_c.ndim,
216
            'map': list(self.noise_c.map),
217
            'buffer': [list(sub_buffer) for sub_buffer in self.noise_c.buffer],
218
            'H': self.noise_c.H,
219
            'lacunarity': self.noise_c.lacunarity,
220
            'exponent': list(self.noise_c.exponent),
221
            'waveletTileData': waveletTileData,
222
            'noise_type': self.noise_c.noise_type,
223
            }
224
        state['_tdl_noise_c'] = {
225
            'dimensions': self._tdl_noise_c.dimensions,
226
            'implementation': self._tdl_noise_c.implementation,
227
            'octaves': self._tdl_noise_c.octaves,
228
            }
229
        return state
230
231
    def __setstate__(self, state):
232
        if isinstance(state, tuple): # deprecated format
233
            return self._setstate_old(state)
234
        # unpack wavelet tile data if it exists
235
        if '_waveletTileData' in state:
236
            state['_waveletTileData'] = ffi.new('float[]',
237
                                                state['_waveletTileData'])
238
            state['noise_c']['waveletTileData'] = state['_waveletTileData']
239
        else:
240
            state['noise_c']['waveletTileData'] = ffi.NULL
241
242
        # unpack perlin_data_t and link to Random instance
243
        state['noise_c']['rand'] = state['_random'].random_c
244
        state['noise_c'] = ffi.new('perlin_data_t*', state['noise_c'])
245
246
        # unpack TDLNoise and link to libtcod noise
247
        state['_tdl_noise_c']['noise'] = state['noise_c']
248
        state['_tdl_noise_c'] = ffi.new('TDLNoise*', state['_tdl_noise_c'])
249
        self.__dict__.update(state)
250
251
    def _setstate_old(self, state):
0 ignored issues
show
Coding Style introduced by
This method should have a docstring.

The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods:

class SomeClass:
    def some_method(self):
        """Do x and return foo."""

If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions.

Loading history...
252
        self._random = state[0]
253
        self.noise_c = ffi.new('perlin_data_t*')
254
        self.noise_c.ndim = state[3]
255
        ffi.buffer(self.noise_c.map)[:] = state[4]
256
        ffi.buffer(self.noise_c.buffer)[:] = state[5]
257
        self.noise_c.H = state[6]
258
        self.noise_c.lacunarity = state[7]
259
        ffi.buffer(self.noise_c.exponent)[:] = state[8]
260
        if state[9]:
261
            # high change of this being prematurely garbage collected!
262
            self.__waveletTileData = ffi.new('float[]', 32*32*32)
0 ignored issues
show
Coding Style Naming introduced by
The name __waveletTileData does not conform to the attribute naming conventions ([a-z_][a-z0-9_]{2,30}$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
Coding Style introduced by
The attribute __waveletTileData was defined outside __init__.

It is generally a good practice to initialize all attributes to default values in the __init__ method:

class Foo:
    def __init__(self, x=None):
        self.x = x
Loading history...
263
            ffi.buffer(self.__waveletTileData)[:] = state[9]
264
        self.noise_c.noise_type = state[10]
265
        self._tdl_noise_c = ffi.new('TDLNoise*',
266
                                    (self.noise_c, self.noise_c.ndim,
267
                                     state[1], state[2]))
268