Source code for mrfmsim_marohn.component.grid

#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""Defines the grid objects. Performance wise it is faster to start a grid
based on a cuboid shape, the RectGrid can be used directly or inherited for
additional functions.
"""

import numpy as np
from mrfmsim.component import ComponentBase
from mrfmsim_marohn import UNITS
import math


[docs]class Grid(ComponentBase): """Instantiate a rectangular grid with length, step and origin. The resulting grid has equal spacing in each dimension. """ _units = UNITS def __init__(self, shape, step, origin=[0, 0, 0]): """Construct the grid object. The grid's step sizes, lengths, and the number of points are fixed at instantiation time. The grid's step sizes and lengths number is thus *not* updated if you manually reset the ``L`` or ``dL`` elements of the object manually later. If the lengths (``L``, etc) is not an integer multiple of the step sizes (``dL``, etc), then use for the lengths the closest multiple of the step sizes. This rounding is done silently and no error is flagged. .. Note:: The grid shape is forced to be odd in the x and y directions, to avoid artifact when convolve. :param np.array length: array of lengths along (x, y, z) :param np.array step: a list of step sizes :param np.array origin: the grid origin :ivar np.array grid_length: actual lengths of the grid. This is recalculated based on the rounded value of grid shape and step size. :ivar np.array grid_origin: grid origin :ivar np.array grid_step: grid setup size in x, y, z direction :ivar float v_voxel: the volume of each grid voxel :ivar tuple grid_shape: grid dimension (number of points in x, y, z direction) :ivar np.array _range: range in (x, y, z direction), shape (3, 2) :ivar np.array grid_array: the grid coordinates in x, y, z direction """ self.grid_origin = np.array(origin, dtype=np.float64) self.grid_step = np.array(step, dtype=np.float64) self.grid_voxel = self.grid_step.prod() self.grid_shape = np.array(shape) self.grid_range = (self.grid_shape - [1, 1, 1]) * self.grid_step self.grid_length = self.grid_shape * self.grid_step
[docs] @staticmethod def grid_extents(length, origin): """Calculate grid extents based on the grid length and origin. The result is column stacked into a dimension of (3, 2) """ return np.column_stack((-length / 2 + origin, length / 2 + origin))
@property def grid_array(self): """Generate an open mesh-grid of the given grid dimensions. The benefit of the property is that it cannot be modified, therefore, it is not included when using ``vars()`` to obtain the object dictionary. It also generates at runtime. """ extents = self.grid_extents(self.grid_range, self.grid_origin) return np.ogrid[ extents[0][0] : extents[0][1] : self.grid_shape[0] * 1j, extents[1][0] : extents[1][1] : self.grid_shape[1] * 1j, extents[2][0] : extents[2][1] : self.grid_shape[2] * 1j, ]
[docs] def extend_grid_method(self, ext_pts): """Extend the grid by the number of points in the x, y, z direction (one side). :param int ext_pts: points to extend along x direction (cantilever motion direction). """ ext_shape = np.array([ self.grid_shape[0] + np.array(ext_pts) * 2, self.grid_shape[1], self.grid_shape[2], ]) ext_range = (ext_shape - [1, 1, 1]) * self.grid_step extents = self.grid_extents(ext_range, self.grid_origin) return np.ogrid[ extents[0][0] : extents[0][1] : ext_shape[0] * 1j, extents[1][0] : extents[1][1] : ext_shape[1] * 1j, extents[2][0] : extents[2][1] : ext_shape[2] * 1j, ]