Math

Functions of multidimensional arguments:

flatten(array) Flatten an array of arbitrary dimension.
mesh(ranges, nbins) Generate equally spaced mesh of nbins cells in the given range.
md_map(f, array) Multidimensional map.
refine_mesh(arr, refinement) Refine (subdivide) one-dimensional mesh arr.

Functions of scalar and multidimensional arguments:

clip(a, interval) Clip (limit) the value.
isclose(a, b[, rel_tol, abs_tol]) Return True if a and b are approximately equal, and False otherwise.

Elements:

Mean([start, pass_on_empty]) Calculate mean (average) of input values.
Sum([start]) Calculate sum of input values.

3-dimensional vector:

vector3(x, y, z) 3-dimensional vector with Cartesian, spherical and cylindrical coordinates.

Functions of multidimensional arguments

flatten(array)[source]

Flatten an array of arbitrary dimension.

array must be list or a tuple (can be nested). Depth-first flattening is used.

Return an iterator over the flattened array.

Examples:

>>> arr = [1, 2, 3]
>>> list(flatten(arr)) == arr
True
>>> arr = [[1, 2, 3, [4]], 5, [[6]], 7]
>>> list(flatten(arr))
[1, 2, 3, 4, 5, 6, 7]
>>> arr = [[1, 2, [3], 4], 5, [[6]], 7]
>>> list(flatten(arr))
[1, 2, 3, 4, 5, 6, 7]
mesh(ranges, nbins)[source]

Generate equally spaced mesh of nbins cells in the given range.

Parameters:
  • ranges – a pair of (min, max) values for 1-dimensional range, or a list of ranges in corresponding dimensions.
  • nbins – number of bins for 1-dimensional range, or a list of number of bins in corresponding dimensions.
>>> from lena.math import mesh
>>> mesh((0, 1), 2)
[0, 0.5, 1]
>>> mesh(((0, 1), (10, 12)), (1, 2))
[[0, 1], [10, 11.0, 12]]

Note that because of rounding errors two meshes should not be naively compared, they will probably appear different. One should use isclose for comparison.

>>> from lena.math import isclose
>>> isclose(mesh((0, 1), 10),
...         [0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0])
True
md_map(f, array)[source]

Multidimensional map.

Return function f mapped to contents of a multidimensional array. f is a function of one argument.

Array must be a list of (possibly nested) lists. Its contents remain unchanged. Returned array has same dimensions as the initial one. If array is not a list, LenaTypeError is raised.

>>> from lena.math import md_map
>>> arr = [-1, 1, 0]
>>> md_map(abs, arr)
[1, 1, 0]
>>> arr = [[0, -1], [2, 3]]
>>> md_map(abs, arr)
[[0, 1], [2, 3]]
refine_mesh(arr, refinement)[source]

Refine (subdivide) one-dimensional mesh arr.

refinement is the number of subdivisions. It must be not less than 1.

Note that to create a new mesh may be faster. Use this function only for convenience.

Functions of scalar and multidimensional arguments

clip(a, interval)[source]

Clip (limit) the value.

Given an interval (a_min, a_max), values of a outside the interval are clipped to the interval edges. For example, if an interval of [0, 1] is specified, values smaller than 0 become 0, and values larger than 1 become 1.

>>> clip(-1, (0, 1))
0
>>> # tuple looks better, but list can be used too
>>> clip(2, [0, 1])
1
>>> clip(0.5, (0, 1))
0.5

If a_min > a_max or if interval has length more than 2, LenaValueError is raised. If interval is not a container, LenaTypeError is raised.

isclose(a, b, rel_tol=1e-09, abs_tol=0.0)[source]

Return True if a and b are approximately equal, and False otherwise.

rel_tol is the relative tolerance. It is multiplied by the greater of the magnitudes of the two arguments; as the values get larger, so does the allowed difference between them while still considering them close.

abs_tol is the absolute tolerance. If the difference is less than either of those tolerances, the values are considered equal.

a and b must be either numbers or lists/tuples of same dimensions (may be nested), or have a method isclose. Otherwise LenaTypeError is raised. For containers, isclose is called elementwise. If every corresponding element is close, the containers are close. Dimensions are not checked to be equal.

First, a and b are checked if any of them has isclose method. If a and b both have isclose method, then they must both return True to be close. Otherwise, if only one of a or b has isclose method, it is called.

Special values of NaN, inf, and -inf are not supported.

>>> isclose(1, 2)
False
>>> isclose([1, 2, 3], (1, 2., 3))
True

This function for scalar numbers appeared in math module in Python 3.5.

Elements

Elements for mathematical calculations.

class Mean(start=0, pass_on_empty=False)[source]

Calculate mean (average) of input values.

start is the initial value of sum.

If pass_on_empty is True, then if nothing was filled, don’t yield anything. By default it raises an error (see compute()).

compute()[source]

Calculate mean and yield.

If the current context is not empty, yield (mean, context). Otherwise yield only mean.

If no values were filled (count is zero), mean can’t be calculated and LenaZeroDivisionError is raised. This can be changed to yielding nothing if pass_on_empty was initialized to True.

fill(value)[source]

Fill self with value.

The value can be a (data, context) pair. The last context value (if missing, it is considered empty) is saved for output.

reset()[source]

Reset sum, count and context.

Sum is reset to start value, count to zero and context to {}.

class Sum(start=0)[source]

Calculate sum of input values.

start is the initial value of sum.

compute()[source]

Calculate the sum and yield.

If the current context is not empty, yield (sum, context). Otherwise yield only sum.

fill(value)[source]

Fill self with value.

The value can be a (data, context) pair. The last context value (considered empty if missing) sets the current context.

reset()[source]

Reset sum and context.

Sum is reset to start value and context to {}.

3-dimensional vector

vector3 is a 3-dimensional vector. It supports spherical and cylindrical coordinates and basic vector operations.

Initialization, vector addition and scalar multiplication create new vectors:

>>> v1 = vector3(0, 1, 2)
>>> v2 = vector3(3, 4, 5)
>>> v1 + v2
vector3(3, 5, 7)
>>> v1 - v2
vector3(-3, -3, -3)
>>> 3 * v1
vector3(0, 3, 6)
>>> v1 * 3
vector3(0, 3, 6)

Vector attributes can be set and read. Vectors can be tested for exact or approximate equality with == and isclose method.

>>> v2.z = 0
>>> v2
vector3(3, 4, 0)
>>> v2.r = 10
>>> v2 == vector3(6, 8, 0)
True
>>> v2.theta = 0
>>> v2.isclose(vector3(0, 0, 10))
True
>>> from math import pi
>>> v2.phi = 0
>>> v2.theta = pi/2.
>>> v2.isclose(vector3(10, 0, 0))
True

Vector components are floats in general. Other values can be used as well, if that makes sense for the operations used (types are not tested during the initialization). For example, vectors in the examples above have integer coordinates, which will become floats if we multiply them by floats, divide or maybe rotate. For usual vector additions or subtractions, though, their coordinates will remain integer.

class vector3(x, y, z)[source]

3-dimensional vector with Cartesian, spherical and cylindrical coordinates.

Create a vector from Cartesian coordinates x, y, z.

Attributes

vector3 has usual vector attributes x, y, z, spherical coordinates r, phi, theta and cylindrical ones rho and rho2 (rho^2 = x^2 + y^2).

Spherical and Cartesian coordinates are connected by this formula:

\begin{gather*} \begin{aligned} x & = r * \cos(\phi) * \sin(\theta),\\ y & = r * \sin(\phi) * \sin(\theta),\\ z & = r * \cos(\theta),\\ \end{aligned} \end{gather*}

\(\phi \in [0, 2 \pi], \theta \in [0, \pi]\).

\(\phi\) and \(\phi + 2 \pi\) are equal.

Cartesian coordinates can be obtained and set through indices starting from 0 (v.x = v[0]). In this respect, vector3 behaves as a container of length 3.

Only Cartesian coordinates are stored internally (spherical and other coordinates are recomputed each time).

Attributes can be got and set using subscript or a function set*, get*. For example:

>>> v = vector3(1, 0, 0)
>>> v.x = 0
>>> x = v.getx()
>>> v.setx(x+1)
>>> v
vector3(1, 0, 0)

\(r^2\) and \(\cos\theta\) can be obtained with methods getr2() and getcostheta().

Comparisons

For elementwise comparison of two vectors one can use ‘==’ and ‘!=’ operators. Because of rounding errors, this can often show two same vectors as different. In general, it is recommended to use approximate comparison with isclose method.

Comparisons like ‘>’, ‘<=’ are all prohibited: if one tries to use these operators, LenaTypeError is raised.

Truth testing

vector3 is non-zero if its magnitude (r) is not 0.

Vector operations

3-dimensional vectors can be added and subtracted, multiplied or divided by a scalar. Multiplication by a scalar can be written from any side of the vector (c*v or v*c). A vector can also be negated (-v).

For other vector operations see methods below.

classmethod fromspherical(r, phi, theta)[source]

Construct vector3 from spherical coordinates.

r is magnitude, phi is azimuth angle from 0 to \(2 * \pi\), theta is polar angle from 0 (z = 1) to \(\pi\) (z = -1).

>>> from math import pi
>>> vector3.fromspherical(1, 0, 0)
vector3(0.0, 0.0, 1.0)
>>> vector3.fromspherical(1, 0, pi).isclose(vector3(0, 0, -1))
True
>>> vector3(1, 0, 0).isclose(vector3.fromspherical(1, 0, pi/2))
True
>>> vector3.fromspherical(1, pi, 0).isclose(vector3(0.0, 0.0, 1.0))
True
>>> vector3.fromspherical(1, pi/2, pi/2).isclose(vector3(0.0, 1.0, 0.0))
True
angle(B)[source]

The angle between self and B, in radians.

>>> v1 = vector3(0, 3, 4)
>>> v2 = vector3(0, 3, 4)
>>> v1.angle(v2)
0.0
>>> v2 = vector3(0, -4, 3)
>>> from math import degrees
>>> degrees(v1.angle(v2))
90.0
>>> v2 = vector3(0, -30, -40)
>>> degrees(v1.angle(v2))
180.0
cosine(B)[source]

Cosine of the angle between self and B.

>>> v1 = vector3(0, 3, 4)
>>> v2 = vector3(0, 3, 4)
>>> v1.cosine(v2)
1.0
>>> v2 = vector3(0, -4, 3)
>>> v1.cosine(v2)
0.0
>>> v2 = vector3(0, -30, -40)
>>> v1.cosine(v2)
-1.0
cross(B)[source]

The cross product between self and B, \(A\times B\).

>>> v1 = vector3(0, 3, 4)
>>> v2 = vector3(0, 1, 0)
>>> v1.cross(v2)
vector3(-4, 0, 0)
dot(B)[source]

The scalar product between self and B, \(A \cdot B\).

classmethod fromspherical(r, phi, theta)[source]

Construct vector3 from spherical coordinates.

r is magnitude, phi is azimuth angle from 0 to \(2 * \pi\), theta is polar angle from 0 (z = 1) to \(\pi\) (z = -1).

>>> from math import pi
>>> vector3.fromspherical(1, 0, 0)
vector3(0.0, 0.0, 1.0)
>>> vector3.fromspherical(1, 0, pi).isclose(vector3(0, 0, -1))
True
>>> vector3(1, 0, 0).isclose(vector3.fromspherical(1, 0, pi/2))
True
>>> vector3.fromspherical(1, pi, 0).isclose(vector3(0.0, 0.0, 1.0))
True
>>> vector3.fromspherical(1, pi/2, pi/2).isclose(vector3(0.0, 1.0, 0.0))
True
isclose(B, rel_tol=1e-09, abs_tol=0.0)[source]

Test whether two vectors are approximately equal.

Parameter semantics is the same as for the general isclose.

>>> v1 = vector3(0, 1, 2)
>>> v1.isclose(vector3(1e-11, 1, 2))
True
norm()[source]

\(A/|A|\), a unit vector in the direction of self.

>>> v1 = vector3(0, 3, 4)
>>> n1 = v1.norm()
>>> v1n = vector3(0, 0.6, 0.8)
>>> (n1 - v1n).r < 1e-6
True
proj(B)[source]

The vector projection of self along B.

A.proj(B) = \((A \cdot norm(B)) norm(B)\).

>>> v1 = vector3(0, 3, 4)
>>> v2 = vector3(0, 2, 0)
>>> v1.proj(v2)
vector3(0.0, 3.0, 0.0)
rotate(theta, B)[source]

Rotate self around B through angle theta.

From the position where B points towards us, the rotation is counterclockwise (the right hand rule).

>>> v1 = vector3(1, 1, 1)
>>> v2 = vector3(0, 1, 0)
>>> from math import pi
>>> vrot = v1.rotate(pi/2, v2)
>>> vrot.isclose(vector3(1, 1, -1))
True
scalar_proj(B)[source]

The scalar projection of self along B.

A.scalar_proj(B) = \(A \cdot norm(B)\).

>>> v1 = vector3(0, 3, 4)
>>> v2 = vector3(0, 2, 0)
>>> v1.scalar_proj(v2)
3.0