Source code for IMTreatment.core.fields

# -*- coding: utf-8 -*-
#!/bin/env python3

# Copyright (C) 2003-2007 Gaby Launay

# Author: Gaby Launay  <gaby.launay@tutanota.com>
# URL: https://framagit.org/gabylaunay/IMTreatment
# Version: 1.0

# This file is part of IMTreatment.

# IMTreatment 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.

# IMTreatment 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/>.

import numpy as np
import copy
from ..utils.types import ARRAYTYPES, INTEGERTYPES, NUMBERTYPES, STRINGTYPES
from . import field as field
from . import scalarfield as sf
from . import vectorfield as vf


[docs]class Fields(object): """ Class representing a set of fields. These fields can have differente positions along axes, or be successive view of the same area. It's recommended to use TemporalVelocityFields or SpatialVelocityFields instead of this one. """ def __init__(self): self.fields = np.array([], dtype=object) def __len__(self): return len(self.fields) def __iter__(self): return self.fields.__iter__() def __getitem__(self, fieldnumber): return self.fields[fieldnumber]
[docs] def copy(self): """ Return a copy of the velocityfields """ return copy.deepcopy(self)
[docs] def scale(self, scalex=None, scaley=None, scalev=None, inplace=False): """ Scale the Fields. Parameters ---------- scalex, scaley, scalev : numbers or Unum objects Scale for the axis and the values. inplace : boolean . """ if inplace: tmp_f = self else: tmp_f = self.copy() # scale the fields for i, _ in enumerate(tmp_f.fields): tmp_f.fields[i].scale(scalex=scalex, scaley=scaley, scalev=scalev, inplace=True) # returning if not inplace: return tmp_f
[docs] def rotate(self, angle, inplace=False): """ Rotate the fields. Parameters ---------- angle : integer Angle in degrees (positive for trigonometric direction). In order to preserve the orthogonal grid, only multiples of 90° are accepted (can be negative multiples). inplace : boolean, optional If 'True', fields is rotated in place, else, the function return rotated fields. Returns ------- rotated_field : TemporalFields or child object, optional Rotated fields. """ # check params if not isinstance(angle, NUMBERTYPES): raise TypeError() if angle % 90 != 0: raise ValueError() if not isinstance(inplace, bool): raise TypeError() # get data if inplace: tmp_field = self else: tmp_field = self.copy() # normalize angle angle = angle % 360 # rotate the parent field.Field.rotate(tmp_field, angle, inplace=True) # rotate fields for i in np.arange(len(tmp_field.fields)): tmp_field.fields[i].rotate(angle=angle, inplace=True) # returning if not inplace: return tmp_field
[docs] def add_field(self, field, copy=True): """ Add a field to the existing fields. Parameters ---------- field : sf.VectorField or sf.ScalarField object The field to add. """ if not isinstance(field, (vf.VectorField, sf.ScalarField)): raise TypeError("'vectorfield' must be a VelocityField object") if copy: ofield = field.copy() else: ofield = field self.fields = np.append(self.fields, ofield)
[docs] def remove_field(self, fieldnumbers): """ Remove a field of the existing fields. Parameters ---------- fieldnumber : integer or list of integers Velocity field(s) number(s) to remove. """ if isinstance(fieldnumbers, INTEGERTYPES): fieldnumbers = [fieldnumbers] for nmb in fieldnumbers: self.fields = np.delete(self.fields, nmb)
[docs] def set_origin(self, x=None, y=None): """ Modify the axis in order to place the origin at the actual point (x, y) Parameters ---------- x : number y : number """ if x is not None: if not isinstance(x, NUMBERTYPES): raise TypeError("'x' must be a number") for tmp_field in self.fields: tmp_field.set_origin(x, None) if y is not None: if not isinstance(y, NUMBERTYPES): raise TypeError("'y' must be a number") for tmp_field in self.fields: tmp_field.set_origin(None, y)
[docs] def smooth(self, tos='uniform', size=None, inplace=False, **kw): """ Smooth the fields in place. Warning : fill up the field (should be used carefully with masked field borders) Parameters ---------- tos : string, optional Type of smoothing, can be 'uniform' (default) or 'gaussian' (See ndimage module documentation for more details) size : number, optional Size of the smoothing (is radius for 'uniform' and sigma for 'gaussian') in indice number. Default is 3 for 'uniform' and 1 for 'gaussian'. inplace : boolean, optional If True, Field is smoothed in place, else, the smoothed field is returned. kw : dic Additional parameters for ndimage methods (See ndimage documentation) """ if inplace: tmp_f = self else: tmp_f = self.copy() # loop on fields for i, _ in enumerate(tmp_f.fields): tmp_f.fields[i].smooth(tos=tos, size=size, inplace=True, **kw) # returning if not inplace: return tmp_f