field.py 16.3 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
# 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/>.
Theo Steininger's avatar
Theo Steininger committed
13
14
15
16
17
#
# Copyright(C) 2013-2017 Max-Planck-Society
#
# NIFTy is being developed at the Max-Planck-Institut fuer Astrophysik
# and financially supported by the Studienstiftung des deutschen Volkes.
18

Martin Reinecke's avatar
Martin Reinecke committed
19
from __future__ import division
Martin Reinecke's avatar
Martin Reinecke committed
20
from builtins import range
csongor's avatar
csongor committed
21
import numpy as np
Martin Reinecke's avatar
Martin Reinecke committed
22
from . import nifty_utilities as utilities
Martin Reinecke's avatar
Martin Reinecke committed
23
from .domain_tuple import DomainTuple
Martin Reinecke's avatar
Martin Reinecke committed
24
from functools import reduce
25
from . import dobj
26

27

Martin Reinecke's avatar
Martin Reinecke committed
28
class Field(object):
Theo Steininger's avatar
Theo Steininger committed
29
30
31
    """ The discrete representation of a continuous field over multiple spaces.

    In NIFTY, Fields are used to store data arrays and carry all the needed
32
    metainformation (i.e. the domain) for operators to be able to work on them.
Martin Reinecke's avatar
updates    
Martin Reinecke committed
33
    In addition, Field has methods to work with power spectra.
Theo Steininger's avatar
Theo Steininger committed
34

35
36
37
38
    Parameters
    ----------
    domain : DomainObject
        One of the space types NIFTY supports. RGSpace, GLSpace, HPSpace,
Theo Steininger's avatar
Theo Steininger committed
39
        LMSpace or PowerSpace. It might also be a FieldArray, which is
40
        an unstructured domain.
Theo Steininger's avatar
Theo Steininger committed
41

Martin Reinecke's avatar
stage1    
Martin Reinecke committed
42
    val : scalar, numpy.ndarray, Field
43
44
45
        The values the array should contain after init. A scalar input will
        fill the whole array with this scalar. If an array is provided the
        array's dimensions must match the domain's.
Theo Steininger's avatar
Theo Steininger committed
46

47
    dtype : type
Martin Reinecke's avatar
updates    
Martin Reinecke committed
48
        A numpy.type. Most common are float and complex.
Theo Steininger's avatar
Theo Steininger committed
49

50
51
52
53
    copy: boolean

    Attributes
    ----------
Martin Reinecke's avatar
stage1    
Martin Reinecke committed
54
    val : numpy.ndarray
Theo Steininger's avatar
Theo Steininger committed
55

Martin Reinecke's avatar
Martin Reinecke committed
56
    domain : DomainTuple
57
58
59
        See Parameters.
    dtype : type
        Contains the datatype stored in the Field.
Theo Steininger's avatar
Theo Steininger committed
60

61
62
63
64
65
66
67
    Raise
    -----
    TypeError
        Raised if
            *the given domain contains something that is not a DomainObject
             instance
            *val is an array that has a different dimension than the domain
Theo Steininger's avatar
Theo Steininger committed
68

69
    """
70

Theo Steininger's avatar
Theo Steininger committed
71
    # ---Initialization methods---
72

Martin Reinecke's avatar
stage1    
Martin Reinecke committed
73
    def __init__(self, domain=None, val=None, dtype=None, copy=False):
74
        self.domain = self._parse_domain(domain=domain, val=val)
75

Martin Reinecke's avatar
Martin Reinecke committed
76
        dtype = self._infer_dtype(dtype=dtype, val=val)
Martin Reinecke's avatar
cleanup    
Martin Reinecke committed
77
        if isinstance(val, Field):
Martin Reinecke's avatar
PEP8    
Martin Reinecke committed
78
            if self.domain != val.domain:
Martin Reinecke's avatar
cleanup    
Martin Reinecke committed
79
                raise ValueError("Domain mismatch")
80
            self._val = dobj.from_object(val.val, dtype=dtype, copy=copy)
Martin Reinecke's avatar
cleanup    
Martin Reinecke committed
81
        elif (np.isscalar(val)):
82
83
            self._val = dobj.full(self.domain.shape, dtype=dtype,
                                  fill_value=val)
84
        elif isinstance(val, dobj.data_object):
Martin Reinecke's avatar
Martin Reinecke committed
85
            if self.domain.shape == val.shape:
86
                self._val = dobj.from_object(val, dtype=dtype, copy=copy)
Martin Reinecke's avatar
cleanup    
Martin Reinecke committed
87
88
89
            else:
                raise ValueError("Shape mismatch")
        elif val is None:
90
            self._val = dobj.empty(self.domain.shape, dtype=dtype)
Martin Reinecke's avatar
cleanup    
Martin Reinecke committed
91
92
        else:
            raise TypeError("unknown source type")
csongor's avatar
csongor committed
93

94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
    @staticmethod
    def full(domain, val, dtype=None):
        if not np.isscalar(val):
            raise TypeError("val must be a scalar")
        return Field(DomainTuple.make(domain), val, dtype)

    @staticmethod
    def ones(domain, dtype=None):
        return Field(DomainTuple.make(domain), 1., dtype)

    @staticmethod
    def zeros(domain, dtype=None):
        return Field(DomainTuple.make(domain), 0., dtype)

    @staticmethod
    def empty(domain, dtype=None):
        return Field(DomainTuple.make(domain), None, dtype)

    @staticmethod
    def full_like(field, val, dtype=None):
        if not isinstance(field, Field):
            raise TypeError("field must be of Field type")
        return Field.full(field.domain, val, dtype)

    @staticmethod
    def zeros_like(field, dtype=None):
        if not isinstance(field, Field):
            raise TypeError("field must be of Field type")
        if dtype is None:
            dtype = field.dtype
        return Field.zeros(field.domain, dtype)

    @staticmethod
    def ones_like(field, dtype=None):
        if not isinstance(field, Field):
            raise TypeError("field must be of Field type")
        if dtype is None:
            dtype = field.dtype
        return Field.ones(field.domain, dtype)

    @staticmethod
    def empty_like(field, dtype=None):
        if not isinstance(field, Field):
            raise TypeError("field must be of Field type")
        if dtype is None:
            dtype = field.dtype
        return Field.empty(field.domain, dtype)

Martin Reinecke's avatar
Martin Reinecke committed
142
143
    @staticmethod
    def _parse_domain(domain, val=None):
144
        if domain is None:
145
            if isinstance(val, Field):
Martin Reinecke's avatar
tweaks    
Martin Reinecke committed
146
147
                return val.domain
            if np.isscalar(val):
148
                return DomainTuple.make(())  # empty domain tuple
Martin Reinecke's avatar
tweaks    
Martin Reinecke committed
149
            raise TypeError("could not infer domain from value")
Martin Reinecke's avatar
Martin Reinecke committed
150
        return DomainTuple.make(domain)
151

Martin Reinecke's avatar
Martin Reinecke committed
152
    # MR: this needs some rethinking ... do we need to have at least float64?
Martin Reinecke's avatar
Martin Reinecke committed
153
154
    @staticmethod
    def _infer_dtype(dtype, val):
Martin Reinecke's avatar
Martin Reinecke committed
155
156
157
158
159
        if val is None or dtype is not None:
            return np.result_type(dtype, np.float64)
        if isinstance(val, Field):
            return val.dtype
        return np.result_type(val, np.float64)
160

Martin Reinecke's avatar
Martin Reinecke committed
161
162
    @staticmethod
    def from_random(random_type, domain, dtype=np.float64, **kwargs):
163
164
165
166
167
168
169
        """ Draws a random field with the given parameters.

        Parameters
        ----------
        random_type : String
            'pm1', 'normal', 'uniform' are the supported arguments for this
            method.
Theo Steininger's avatar
Theo Steininger committed
170

171
172
        domain : DomainObject
            The domain of the output random field
Theo Steininger's avatar
Theo Steininger committed
173

174
175
        dtype : type
            The datatype of the output random field
Theo Steininger's avatar
Theo Steininger committed
176

177
178
179
180
181
        Returns
        -------
        out : Field
            The output object.
        """
Theo Steininger's avatar
Theo Steininger committed
182

Martin Reinecke's avatar
Martin Reinecke committed
183
        domain = DomainTuple.make(domain)
Martin Reinecke's avatar
Martin Reinecke committed
184
185
186
        return Field(domain=domain,
                     val=dobj.from_random(random_type, dtype=dtype,
                                          shape=domain.shape, **kwargs))
187

Martin Reinecke's avatar
Martin Reinecke committed
188
189
190
    def fill(self, fill_value):
        self._val.fill(fill_value)

Theo Steininger's avatar
Theo Steininger committed
191
    # ---Properties---
192

Theo Steininger's avatar
Theo Steininger committed
193
194
    @property
    def val(self):
Martin Reinecke's avatar
stage1    
Martin Reinecke committed
195
        """ Returns the data object associated with this Field.
Martin Reinecke's avatar
PEP8    
Martin Reinecke committed
196
        No copy is made.
Theo Steininger's avatar
Theo Steininger committed
197

198
199
        Returns
        -------
Martin Reinecke's avatar
stage1    
Martin Reinecke committed
200
        out : numpy.ndarray
201
        """
Martin Reinecke's avatar
Martin Reinecke committed
202
        return self._val
csongor's avatar
csongor committed
203

Martin Reinecke's avatar
Martin Reinecke committed
204
205
206
207
    @property
    def dtype(self):
        return self._val.dtype

208
209
    @property
    def shape(self):
Theo Steininger's avatar
Theo Steininger committed
210
        """ Returns the total shape of the Field's data array.
Theo Steininger's avatar
Theo Steininger committed
211

212
213
214
        Returns
        -------
        out : tuple
Martin Reinecke's avatar
Martin Reinecke committed
215
            The output object. The tuple contains the dimensions of the spaces
216
            in domain.
Martin Reinecke's avatar
PEP8    
Martin Reinecke committed
217
       """
Martin Reinecke's avatar
Martin Reinecke committed
218
        return self.domain.shape
csongor's avatar
csongor committed
219

220
221
    @property
    def dim(self):
Theo Steininger's avatar
Theo Steininger committed
222
        """ Returns the total number of pixel-dimensions the field has.
Theo Steininger's avatar
Theo Steininger committed
223

Theo Steininger's avatar
Theo Steininger committed
224
        Effectively, all values from shape are multiplied.
Theo Steininger's avatar
Theo Steininger committed
225

226
227
228
229
230
        Returns
        -------
        out : int
            The dimension of the Field.
        """
Martin Reinecke's avatar
Martin Reinecke committed
231
        return self.domain.dim
csongor's avatar
csongor committed
232

Theo Steininger's avatar
Theo Steininger committed
233
234
235
236
    @property
    def real(self):
        """ The real part of the field (data is not copied).
        """
Martin Reinecke's avatar
PEP8    
Martin Reinecke committed
237
        return Field(self.domain, self.val.real)
Theo Steininger's avatar
Theo Steininger committed
238
239
240
241
242

    @property
    def imag(self):
        """ The imaginary part of the field (data is not copied).
        """
Martin Reinecke's avatar
PEP8    
Martin Reinecke committed
243
        return Field(self.domain, self.val.imag)
Theo Steininger's avatar
Theo Steininger committed
244

Theo Steininger's avatar
Theo Steininger committed
245
    # ---Special unary/binary operations---
246

Martin Reinecke's avatar
Martin Reinecke committed
247
    def copy(self):
248
        """ Returns a full copy of the Field.
Theo Steininger's avatar
Theo Steininger committed
249

Martin Reinecke's avatar
Martin Reinecke committed
250
        The returned object will be an identical copy of the original Field.
Theo Steininger's avatar
Theo Steininger committed
251

252
253
254
255
256
        Returns
        -------
        out : Field
            The output object. An identical copy of 'self'.
        """
Martin Reinecke's avatar
Martin Reinecke committed
257
        return Field(val=self, copy=True)
csongor's avatar
csongor committed
258

259
260
    def scalar_weight(self, spaces=None):
        if np.isscalar(spaces):
261
            return self.domain[spaces].scalar_dvol()
262
263
264

        if spaces is None:
            spaces = range(len(self.domain))
Martin Reinecke's avatar
Martin Reinecke committed
265
        res = 1.
266
        for i in spaces:
267
            tmp = self.domain[i].scalar_dvol()
268
269
270
271
272
            if tmp is None:
                return None
            res *= tmp
        return res

273
    def weight(self, power=1, spaces=None, out=None):
Theo Steininger's avatar
Theo Steininger committed
274
        """ Weights the pixels of `self` with their invidual pixel-volume.
275
276
277
278

        Parameters
        ----------
        power : number
Theo Steininger's avatar
Theo Steininger committed
279
            The pixels get weighted with the volume-factor**power.
Theo Steininger's avatar
Theo Steininger committed
280

Theo Steininger's avatar
Theo Steininger committed
281
282
        spaces : tuple of ints
            Determines on which subspace the operation takes place.
Theo Steininger's avatar
Theo Steininger committed
283

284
285
286
287
288
        out : Field or None
            if not None, the result is returned in a new Field
            otherwise the contents of "out" are overwritten with the result.
            "out" may be identical to "self"!

289
290
291
        Returns
        -------
        out : Field
Theo Steininger's avatar
Theo Steininger committed
292
            The weighted field.
293
294

        """
295
296
297
298
299
        if out is None:
            out = self.copy()
        else:
            if out is not self:
                out.copy_content_from(self)
csongor's avatar
csongor committed
300

csongor's avatar
csongor committed
301
        if spaces is None:
Martin Reinecke's avatar
Martin Reinecke committed
302
            spaces = range(len(self.domain))
Martin Reinecke's avatar
Martin Reinecke committed
303
304
        else:
            spaces = utilities.cast_iseq_to_tuple(spaces)
csongor's avatar
csongor committed
305

306
307
        fct = 1.
        for ind in spaces:
308
            wgt = self.domain[ind].dvol()
309
310
311
            if np.isscalar(wgt):
                fct *= wgt
            else:
Martin Reinecke's avatar
Martin Reinecke committed
312
                new_shape = np.ones(len(self.shape), dtype=np.int)
Martin Reinecke's avatar
Martin Reinecke committed
313
314
                new_shape[self.domain.axes[ind][0]:
                          self.domain.axes[ind][-1]+1] = wgt.shape
315
                wgt = wgt.reshape(new_shape)
Martin Reinecke's avatar
Martin Reinecke committed
316
                if dobj.distaxis(self._val) >= 0 and ind == 0:  # we need to distribute the weights along axis 0
Martin Reinecke's avatar
fixes    
Martin Reinecke committed
317
                    wgt = dobj.local_data(dobj.from_global_data(wgt))
318
                out *= wgt**power
319
        fct = fct**power
Martin Reinecke's avatar
Martin Reinecke committed
320
        if fct != 1.:
321
            out *= fct
322

323
        return out
csongor's avatar
csongor committed
324

Martin Reinecke's avatar
Martin Reinecke committed
325
    def vdot(self, x=None, spaces=None):
Theo Steininger's avatar
Theo Steininger committed
326
        """ Computes the volume-factor-aware dot product of 'self' with x.
Theo Steininger's avatar
Theo Steininger committed
327

328
329
330
        Parameters
        ----------
        x : Field
Theo Steininger's avatar
Theo Steininger committed
331
            The domain of x must contain `self.domain`
Theo Steininger's avatar
Theo Steininger committed
332

Theo Steininger's avatar
Theo Steininger committed
333
        spaces : tuple of ints
334
335
            If the domain of `self` and `x` are not the same, `spaces` defines
            which domains of `x` are mapped to those of `self`.
Theo Steininger's avatar
Theo Steininger committed
336

337
338
339
        Returns
        -------
        out : float, complex
Theo Steininger's avatar
Theo Steininger committed
340

341
        """
342
343
344
        if not isinstance(x, Field):
            raise ValueError("The dot-partner must be an instance of " +
                             "the NIFTy field class")
Theo Steininger's avatar
Theo Steininger committed
345

Martin Reinecke's avatar
Martin Reinecke committed
346
        # Compute the dot respecting the fact of discrete/continuous spaces
Martin Reinecke's avatar
Martin Reinecke committed
347
348
        tmp = self.scalar_weight(spaces)
        if tmp is None:
349
            fct = 1.
Martin Reinecke's avatar
Martin Reinecke committed
350
            y = self.weight(power=1)
351
        else:
Martin Reinecke's avatar
Martin Reinecke committed
352
353
            y = self
            fct = tmp
Theo Steininger's avatar
Theo Steininger committed
354

355
        if spaces is None:
Martin Reinecke's avatar
fixes    
Martin Reinecke committed
356
            return fct*dobj.vdot(y.val, x.val)
357
        else:
358
359
360
361
362
363
364
365
            spaces = utilities.cast_iseq_to_tuple(spaces)
            active_axes = []
            for i in spaces:
                active_axes += self.domain.axes[i]
            res = 0.
            for sl in utilities.get_slice_list(self.shape, active_axes):
                res += dobj.vdot(y.val, x.val[sl])
            return res*fct
Theo Steininger's avatar
Theo Steininger committed
366

Theo Steininger's avatar
Theo Steininger committed
367
    def norm(self):
Martin Reinecke's avatar
tweaks    
Martin Reinecke committed
368
        """ Computes the L2-norm of the field values.
csongor's avatar
csongor committed
369

Theo Steininger's avatar
Theo Steininger committed
370
371
        Returns
        -------
Martin Reinecke's avatar
Martin Reinecke committed
372
        norm : float
Martin Reinecke's avatar
tweaks    
Martin Reinecke committed
373
            The L2-norm of the field values.
csongor's avatar
csongor committed
374
375

        """
376
        return np.sqrt(np.abs(self.vdot(x=self)))
csongor's avatar
csongor committed
377

Martin Reinecke's avatar
tweaks    
Martin Reinecke committed
378
    def conjugate(self):
Martin Reinecke's avatar
cleanup    
Martin Reinecke committed
379
        """ Returns the complex conjugate of the field.
Theo Steininger's avatar
Theo Steininger committed
380

381
382
383
384
        Returns
        -------
        cc : field
            The complex conjugated field.
csongor's avatar
csongor committed
385
386

        """
Martin Reinecke's avatar
tweaks    
Martin Reinecke committed
387
        return Field(self.domain, self.val.conjugate(), self.dtype)
csongor's avatar
csongor committed
388

Theo Steininger's avatar
Theo Steininger committed
389
    # ---General unary/contraction methods---
390

Theo Steininger's avatar
Theo Steininger committed
391
392
    def __pos__(self):
        return self.copy()
393

Theo Steininger's avatar
Theo Steininger committed
394
    def __neg__(self):
Martin Reinecke's avatar
PEP8    
Martin Reinecke committed
395
        return Field(self.domain, -self.val, self.dtype)
csongor's avatar
csongor committed
396

Theo Steininger's avatar
Theo Steininger committed
397
    def __abs__(self):
398
        return Field(self.domain, dobj.abs(self.val), self.dtype)
csongor's avatar
csongor committed
399

400
    def _contraction_helper(self, op, spaces):
Theo Steininger's avatar
Theo Steininger committed
401
        if spaces is None:
402
            return getattr(self.val, op)()
Martin Reinecke's avatar
Martin Reinecke committed
403
404
        else:
            spaces = utilities.cast_iseq_to_tuple(spaces)
csongor's avatar
csongor committed
405

Martin Reinecke's avatar
Martin Reinecke committed
406
        axes_list = tuple(self.domain.axes[sp_index] for sp_index in spaces)
407

Martin Reinecke's avatar
Martin Reinecke committed
408
        if len(axes_list) > 0:
Theo Steininger's avatar
Theo Steininger committed
409
            axes_list = reduce(lambda x, y: x+y, axes_list)
csongor's avatar
csongor committed
410

Martin Reinecke's avatar
stage1    
Martin Reinecke committed
411
        # perform the contraction on the data
412
        data = getattr(self.val, op)(axis=axes_list)
csongor's avatar
csongor committed
413

Theo Steininger's avatar
Theo Steininger committed
414
415
416
        # check if the result is scalar or if a result_field must be constr.
        if np.isscalar(data):
            return data
csongor's avatar
csongor committed
417
        else:
Martin Reinecke's avatar
Martin Reinecke committed
418
419
            return_domain = tuple(dom
                                  for i, dom in enumerate(self.domain)
Theo Steininger's avatar
Theo Steininger committed
420
                                  if i not in spaces)
421

Martin Reinecke's avatar
updates    
Martin Reinecke committed
422
            return Field(domain=return_domain, val=data, copy=False)
csongor's avatar
csongor committed
423

424
425
    def sum(self, spaces=None):
        return self._contraction_helper('sum', spaces)
csongor's avatar
csongor committed
426

427
428
429
430
    def integrate(self, spaces=None):
        tmp = self.weight(1, spaces=spaces)
        return tmp.sum(spaces)

431
432
    def prod(self, spaces=None):
        return self._contraction_helper('prod', spaces)
csongor's avatar
csongor committed
433

434
435
    def all(self, spaces=None):
        return self._contraction_helper('all', spaces)
csongor's avatar
csongor committed
436

437
438
    def any(self, spaces=None):
        return self._contraction_helper('any', spaces)
csongor's avatar
csongor committed
439

440
441
    def min(self, spaces=None):
        return self._contraction_helper('min', spaces)
csongor's avatar
csongor committed
442

443
444
    def max(self, spaces=None):
        return self._contraction_helper('max', spaces)
csongor's avatar
csongor committed
445

446
447
    def mean(self, spaces=None):
        return self._contraction_helper('mean', spaces)
csongor's avatar
csongor committed
448

449
450
    def var(self, spaces=None):
        return self._contraction_helper('var', spaces)
csongor's avatar
csongor committed
451

452
453
    def std(self, spaces=None):
        return self._contraction_helper('std', spaces)
csongor's avatar
csongor committed
454

455
456
457
458
459
    def copy_content_from(self, other):
        if not isinstance(other, Field):
            raise TypeError("argument must be a Field")
        if other.domain != self.domain:
            raise ValueError("domains are incompatible.")
Martin Reinecke's avatar
tweaks    
Martin Reinecke committed
460
        dobj.local_data(self.val)[()] = dobj.local_data(other.val)[()]
461

Theo Steininger's avatar
Theo Steininger committed
462
    # ---General binary methods---
csongor's avatar
csongor committed
463

464
    def _binary_helper(self, other, op):
csongor's avatar
csongor committed
465
        # if other is a field, make sure that the domains match
466
        if isinstance(other, Field):
467
468
            if other.domain != self.domain:
                raise ValueError("domains are incompatible.")
Martin Reinecke's avatar
Martin Reinecke committed
469
470
            tval = getattr(self.val, op)(other.val)
            return self if tval is self.val else Field(self.domain, tval)
csongor's avatar
csongor committed
471

Martin Reinecke's avatar
Martin Reinecke committed
472
473
        tval = getattr(self.val, op)(other)
        return self if tval is self.val else Field(self.domain, tval)
csongor's avatar
csongor committed
474
475

    def __add__(self, other):
Theo Steininger's avatar
Theo Steininger committed
476
        return self._binary_helper(other, op='__add__')
477

478
    def __radd__(self, other):
Theo Steininger's avatar
Theo Steininger committed
479
        return self._binary_helper(other, op='__radd__')
csongor's avatar
csongor committed
480
481

    def __iadd__(self, other):
482
        return self._binary_helper(other, op='__iadd__')
csongor's avatar
csongor committed
483
484

    def __sub__(self, other):
Theo Steininger's avatar
Theo Steininger committed
485
        return self._binary_helper(other, op='__sub__')
csongor's avatar
csongor committed
486
487

    def __rsub__(self, other):
Theo Steininger's avatar
Theo Steininger committed
488
        return self._binary_helper(other, op='__rsub__')
csongor's avatar
csongor committed
489
490

    def __isub__(self, other):
491
        return self._binary_helper(other, op='__isub__')
csongor's avatar
csongor committed
492
493

    def __mul__(self, other):
Theo Steininger's avatar
Theo Steininger committed
494
        return self._binary_helper(other, op='__mul__')
495

496
    def __rmul__(self, other):
Theo Steininger's avatar
Theo Steininger committed
497
        return self._binary_helper(other, op='__rmul__')
csongor's avatar
csongor committed
498
499

    def __imul__(self, other):
500
        return self._binary_helper(other, op='__imul__')
csongor's avatar
csongor committed
501
502

    def __div__(self, other):
Theo Steininger's avatar
Theo Steininger committed
503
        return self._binary_helper(other, op='__div__')
csongor's avatar
csongor committed
504

Martin Reinecke's avatar
Martin Reinecke committed
505
506
507
    def __truediv__(self, other):
        return self._binary_helper(other, op='__truediv__')

csongor's avatar
csongor committed
508
    def __rdiv__(self, other):
Theo Steininger's avatar
Theo Steininger committed
509
        return self._binary_helper(other, op='__rdiv__')
csongor's avatar
csongor committed
510

Martin Reinecke's avatar
Martin Reinecke committed
511
512
513
    def __rtruediv__(self, other):
        return self._binary_helper(other, op='__rtruediv__')

csongor's avatar
csongor committed
514
    def __idiv__(self, other):
515
        return self._binary_helper(other, op='__idiv__')
516

csongor's avatar
csongor committed
517
    def __pow__(self, other):
Theo Steininger's avatar
Theo Steininger committed
518
        return self._binary_helper(other, op='__pow__')
csongor's avatar
csongor committed
519
520

    def __rpow__(self, other):
Theo Steininger's avatar
Theo Steininger committed
521
        return self._binary_helper(other, op='__rpow__')
csongor's avatar
csongor committed
522
523

    def __ipow__(self, other):
524
        return self._binary_helper(other, op='__ipow__')
csongor's avatar
csongor committed
525

Theo Steininger's avatar
Theo Steininger committed
526
    def __repr__(self):
Martin Reinecke's avatar
Martin Reinecke committed
527
        return "<nifty2go.Field>"
Theo Steininger's avatar
Theo Steininger committed
528
529
530
531

    def __str__(self):
        minmax = [self.min(), self.max()]
        mean = self.mean()
Martin Reinecke's avatar
Martin Reinecke committed
532
        return "nifty2go.Field instance\n- domain      = " + \
Theo Steininger's avatar
Theo Steininger committed
533
               repr(self.domain) + \
534
               "\n- val         = " + repr(self.val) + \
Theo Steininger's avatar
Theo Steininger committed
535
536
               "\n  - min.,max. = " + str(minmax) + \
               "\n  - mean = " + str(mean)