#### Previous topic

2. formex — Formex algebra in Python

#### Next topic

4. script — Basic pyFormex script functions

# 3. arraytools — A collection of numerical array utilities.¶

These are general utility functions that depend only on the numpy array model. All pyformex modules needing numpy should import everything from this module:

```from arraytools import *
```

Classes defined in module arraytools

Functions defined in module arraytools

arraytools.isInt(obj)

Test if an object is an integer number

Returns True if the object is a single integer number, else False. The type of the object can be either a Python integer (int) or a numpy integer.

arraytools.powers(x, n)

Compute all the powers of x from zero up to n

Returns a list of arrays with same shape as x

arraytools.sind(arg, angle_spec=0.017453292519943295)

Return the sine of an angle in degrees.

For convenience, this can also be used with an angle in radians, by specifying angle_spec=RAD.

```>>> print(sind(30), sind(pi/6,RAD))
0.5 0.5
```
arraytools.cosd(arg, angle_spec=0.017453292519943295)

Return the cosine of an angle in degrees.

For convenience, this can also be used with an angle in radians, by specifying angle_spec=RAD.

```>>> print(cosd(60), cosd(pi/3,RAD))
0.5 0.5
```
arraytools.tand(arg, angle_spec=0.017453292519943295)

Return the tangens of an angle in degrees.

For convenience, this can also be used with an angle in radians, by specifying angle_spec=RAD.

arraytools.arcsind(arg, angle_spec=0.017453292519943295)

Return the angle whose sine is equal to the argument.

By default, the angle is returned in Degrees. Specifying angle_spec=RAD will return the angle in radians.

```>>> print(arcsind(0.5), arcsind(1.0,RAD))
30.0 1.57079632679
```
arraytools.arccosd(arg, angle_spec=0.017453292519943295)

Return the angle whose cosine is equal to the argument.

By default, the angle is returned in Degrees. Specifying angle_spec=RAD will return the angle in radians.

```>>> print(arccosd(0.5), arccosd(-1.0,RAD))
60.0 3.14159265359
```
arraytools.arctand(arg, angle_spec=0.017453292519943295)

Return the angle whose tangens is equal to the argument.

By default, the angle is returned in Degrees. Specifying angle_spec=RAD will return the angle in radians.

```>>> print(arctand(1.0), arctand(-1.0,RAD))
45.0 -0.785398163397
```
arraytools.arctand2(sin, cos, angle_spec=0.017453292519943295)

Return the angle whose sine and cosine values are given.

By default, the angle is returned in Degrees. Specifying angle_spec=RAD will return the angle in radians. This returns an angle in the range ]-180,180].

```>>> print(arctand2(0.0,-1.0), arctand2(-sqrt(0.5),-sqrt(0.5),RAD))
180.0 -2.35619449019
```
arraytools.niceLogSize(f)

Return the smallest integer e such that 10**e > abs(f).

This returns the number of digits before the decimal point.

```>>> print([ niceLogSize(a) for a in [1.3, 35679.23, 0.4, 0.00045676] ])
[1, 5, 0, -3]
```
arraytools.niceNumber(f, below=False)

Return a nice number close to f.

f is a float number, whose sign is disregarded.

A number close to abs(f) but having only 1 significant digit is returned. By default, the value is above abs(f). Setting below=True returns a value above.

Example:

```>>> numbers = [ 0.0837, 0.837, 8.37, 83.7, 93.7]
>>> [ str(niceNumber(f)) for f in numbers ]
['0.09', '0.9', '9.0', '90.0', '100.0']
>>> [ str(niceNumber(f,below=True)) for f in numbers ]
['0.08', '0.8', '8.0', '80.0', '90.0']
```
arraytools.dotpr(A, B, axis=-1)

Return the dot product of vectors of A and B in the direction of axis.

This multiplies the elements of the arrays A and B, and the sums the result in the direction of the specified axis. Default is the last axis. Thus, if A and B are sets of vectors in their last array direction, the result is the dot product of vectors of A with vectors of B. A and B should be broadcast compatible.

```>>> A = array( [[1.0, 1.0], [1.0,-1.0], [0.0, 5.0]] )
>>> B = array( [[5.0, 3.0], [2.0, 3.0], [1.33,2.0]] )
>>> print(dotpr(A,B))
[  8.  -1.  10.]
```
arraytools.length(A, axis=-1)

Returns the length of the vectors of A in the direction of axis.

The components of the vectors are stored along the specified array axis (default axis is the last).

arraytools.normalize(A, axis=-1)

Normalize the vectors of A in the direction of axis.

The components of the vectors are stored along the specified array axis (default axis is the last).

arraytools.projection(A, B, axis=-1)

Return the (signed) length of the projection of vector of A on B.

The components of the vectors are stored along the specified array axis (default axis is the last).

arraytools.orthog(A, B, axis=-1)

Return the component of vector of A that is orthogonal to B.

The components of the vectors are stored along the specified array axis (default axis is the last).

arraytools.norm(v, n=2)

Return thr n-norm of the vector v.

Default is the quadratic norm (vector length). n == 1 returns the sum. n<=0 returns the max absolute value.

arraytools.horner(a, u)

Compute the value of a polynom using Horner’s rule.

Parameters:

• a: float(n+1,nd), nd-dimensional coefficients of the polynom of degree n, starting from lowest degree.
• u: float(nu), parametric values where the polynom is evaluated

Returns float(nu,nd), nd-dimensional values of the polynom.

```>>> print(horner([[1.,1.,1.],[1.,2.,3.]],[0.5,1.0]))
[[ 1.5  2.   2.5]
[ 2.   3.   4. ]]
```
arraytools.solveMany(A, b, direct=True)

Solve many systems of linear equations.

Parameters:

• A: (ndof,ndof,nsys) shaped float array.
• b: (ndof,nrhs,nsys) shaped float array.

Returns: a float array x with same shape as b, where x[:,i,j] solves the system of linear equations A[:,:,j].x[:,i,j] = b[:,i,j].

For ndof in [1,2,3], all solutions are by default computed directly and simultaneously. If direct=False is specified, a general linear equation solver is called for each system of equations. This is also the method used if ndof>4.

arraytools.inside(p, mi, ma)

Return true if point p is inside bbox defined by points mi and ma

arraytools.isClose(values, target, rtol=1e-05, atol=1e-08)

Returns an array flagging the elements close to target.

values is a float array, target is a float value. values and target should be broadcastable to the same shape.

The return value is a boolean array with shape of values flagging where the values are close to target. Two values a and b are considered close if

arraytools.anyVector(v)

Create a 3D vector.

v is some data compatible with a (3)-shaped float array. Returns v as such an array.

arraytools.unitVector(v)

Return a unit vector in the direction of v.

• v is either an integer specifying one of the global axes (0,1,2), or a 3-element array or compatible.
arraytools.rotationMatrix(angle, axis=None, angle_spec=0.017453292519943295)

Return a rotation matrix over angle, optionally around axis.

The angle is specified in degrees, unless angle_spec=RAD is specified. If axis==None (default), a 2x2 rotation matrix is returned. Else, axis should specifyi the rotation axis in a 3D world. It is either one of 0,1,2, specifying a global axis, or a vector with 3 components specifying an axis through the origin. In either case a 3x3 rotation matrix is returned. Note that:

• rotationMatrix(angle,[1,0,0]) == rotationMatrix(angle,0)
• rotationMatrix(angle,[0,1,0]) == rotationMatrix(angle,1)
• rotationMatrix(angle,[0,0,1]) == rotationMatrix(angle,2)

but the latter functions calls are more efficient. The result is returned as an array.

arraytools.rotmat(x)

Create a rotation matrix defined by 3 points in space.

x is an array of 3 points. After applying the resulting rotation matrix to the global axes, the 0 axis becomes // to the vectors x0-x1, the 1 axis lies in the plane x0,x1,x2 and is orthogonal to x0-x1, and the 3 axis is orthogonal to the plane x0,x1,x2.

arraytools.trfMatrix(x, y)

Find the transformation matrix from points x0 to x1.

x and y are each arrays of 3 non-colinear points. The return value is a tuple of a translation vector and a rotation matrix. The returned translation trl and rotationmatrix rot transform the points x thus that:

• point x0 coincides with point y0,
• line x0,x1 coincides with line y0,y1
• plane x0,x1,x2 coincides with plane y0,y1,y2

The rotation is to be applied first and should be around the first point x0. The full transformation of a Coords object is thus obtained by:

```(coords-x0)*rot+trl+x0 = coords*rot+(trl+x0-x0*rot)
```
arraytools.rotMatrix(u, w=[0.0, 0.0, 1.0], n=3)

Create a rotation matrix that rotates axis 0 to the given vector.

u is a vector representing the Return either a 3x3(default) or 4x4(if n==4) rotation matrix.

arraytools.rotationAnglesFromMatrix(mat, angle_spec=0.017453292519943295)

Return rotation angles from rotation matrix mat.

This returns the three angles around the global axes 0, 1 and 2. The angles are returned in degrees, unless angle_spec=RAD.

arraytools.vectorRotation(vec1, vec2, upvec=None)

Return a rotation matrix for rotating vector vec1 to vec2.

If upvec is specified, the rotation matrix will be such that the plane of vec2 and the rotated upvec will be parallel to the original upvec.

This function is like arraytools.rotMatrix(), but allows the specification of vec1. The returned matrix should be used in postmultiplication to the Coords.

Increase the length of a single array axis.

The specified axis of the array a is increased with a value add and the new elements all get the value fill.

Parameters:

• a: array.
• add: int The value to add to the axis length. If<=0, the unchanged array is returned.
• axis: int The axis to change, default -1 (last).
• fill: int or float The value to set the new elements to.

Returns an array with same dimension and type as a, but with a length along axis equal to a.shape[axis]+add. The new elements all have the value fill.

Example:

```>>> growAxis([[1,2,3],[4,5,6]],2)
array([[1, 2, 3, 0, 0],
[4, 5, 6, 0, 0]])
```
arraytools.reorderAxis(a, order, axis=-1)

Reorder the planes of an array along the specified axis.

The elements of the array are reordered along the specified axis according to the specified order.

Parameters:

• a: array_like

• order: specifies how to reorder the elements. It is either one of the special string values defined below, or else it is an index holding a permutation of arange(self.nelems(). Each value specifies the index of the old element that should be placed at its position. Thus, the order values are the old index numbers at the position of the new index number.

order can also take one of the following predefined values, resulting in the corresponding renumbering scheme being generated:

• ‘reverse’: the elements along axis are placed in reverse order
• ‘random’: the elements along axis are placed in random order

Returns an array with the same elements of self, where only the order along the specified axis has been changed.

Example:

```>>> reorderAxis([[1,2,3],[4,5,6]],[2,0,1])
array([[3, 1, 2],
[6, 4, 5]])
```
arraytools.reverseAxis(a, axis=-1)

Reverse the elements along a computed axis.

Example:

```>>> reverseAxis([[1,2,3],[4,5,6]],0)
array([[4, 5, 6],
[1, 2, 3]])
```

Note that if the axis is known in advance, it may be more efficient to use an indexing operation:

```>>> A = array([[1,2,3],[4,5,6]])
>>> print(A[:,::-1])
[[3 2 1]
[6 5 4]]
```

The new axis is inserted before the specified one. Default is to add it at the front.

arraytools.multiplex(a, n, axis=-1)

Multiplex an array over a length n in direction of a new axis.

Inserts a new axis before the specified axis and repeats the data of the array n times in the direction of the new axis.

Returns an array with n times the original data in the direction of the specified axis (if positive) or the specified axis minus one (if negative).

Note that you can not use a negative number to multiplex if the new axis is the last one. To multiplex on the last dimension, use axis=a.ndim.

Example:

```>>> a = arange(6).reshape(2,3)
>>> for i in range(-a.ndim,a.ndim+1):
...     c = multiplex(a,4,i)
...     print("%s: %s" % (i,c.shape))
-2: (4, 2, 3)
-1: (2, 4, 3)
0: (4, 2, 3)
1: (2, 4, 3)
2: (2, 3, 4)
>>> print(multiplex(a,4))
[[[0 1 2]
[0 1 2]
[0 1 2]
[0 1 2]]

[[3 4 5]
[3 4 5]
[3 4 5]
[3 4 5]]]
```
arraytools.stack(al, axis=0)

Stack a list of arrays along a new axis.

al is a list of arrays all of the same shape. The return value is a new array with one extra axis, along which the input arrays are stacked. The position of the new axis can be specified, and is the first axis by default.

arraytools.concat(al, axis=0)

Smart array concatenation ignoring empty arrays

arraytools.minmax(a, axis=-1)

Compute the minimum and maximum along an axis.

a is an array. Returns an array of the same type as the input array, and with the same shape, except for the specified axis, which will have length 2. Along this axis are stored the minimum and maximum values along that axis in the input array.

Example:

```>>> a = array([[ [1.,0.,0.], [0.,1.,0.] ],
...            [ [2.,0.,0.], [0.,2.,0.] ] ])
>>> print(minmax(a,axis=1))
[[[ 0.  0.  0.]
[ 1.  1.  0.]]

[[ 0.  0.  0.]
[ 2.  2.  0.]]]
```
arraytools.splitrange(n, nblk)

Split the range of integers 0..n in nblk almost equal sized slices.

This divides the range of integer numbers 0..n in nblk slices of (almost) equal size. If n > nblk, returns nblk+1 integers in the range 0..n. If n <= nblk, returns range(n+1).

Example:

```>>> splitrange(7,3)
array([0, 2, 5, 7])
```
arraytools.splitar(ar, nblk, close=False)

Split an array in nblk subarrays along axis 0.

Splits the array ar along its first axis in nblk blocks of (almost) equal size.

Returns a list of nblk arrays, unless the size of the array is smaller than nblk, in which case a list with the original array is returned.

If close==True, the elements where the array is split occur in both blocks delimited by the element.

Example:

```>>> splitar(arange(7),3)
[array([0, 1]), array([2, 3, 4]), array([5, 6])]
>>> splitar(arange(7),3,close=True)
[array([0, 1, 2]), array([2, 3, 4]), array([4, 5, 6])]
```
arraytools.checkInt(value, min=None, max=None)

Check that a value is an int in the range min..max

Range borders that are None are not checked upon. Returns an int in the specified range. Raises an exception if the value is invalid.

arraytools.checkFloat(value, min=None, max=None)

Check that a value is a float in the range min..max

Range borders that are None are not checked upon. Returns a float in the specified range. Raises an exception if the value is invalid.

arraytools.checkArray(a, shape=None, kind=None, allow=None, size=None, ndim=None)

Check that an array a has the correct shape, type and/or size.

The input a is anything that can be converted into a numpy array. Either shape and/or kind and/or type can be specified and will then be checked. The dimensions where shape contains a -1 value are not checked. The number of dimensions should match. If kind does not match, but the value is included in allow, conversion to the requested type is attempted. If size is specified, the size should exactly match. If ‘ndim’ is specified, the array should have precisely ndim dimensions.

Returns the array if valid; else, an error is raised.

arraytools.checkArray1D(a, kind=None, allow=None, size=None)

Check and force an array to be 1D.

Turns the first argument into a 1D array. Optionally checks the kind of data (int/float) and the size of the array.

Returns the array if valid; else, an error is raised.

This is equivalent to calling checkArray with shape=None and then ravel the result.

arraytools.checkUniqueNumbers(nrs, nmin=0, nmax=None)

Check that an array contains a set of unique integers in a given range.

This functions tests that all integer numbers in the array are within the range math:nmin <= i < nmax

Parameters:

• nrs: an integer array of any shape.
• nmin: minimum allowed value. If set to None, the test is skipped.
• nmax: maximum allowed value + 1! If set to None, the test is skipped.

Default range is [0,unlimited].

If the numbers are no unique or one of the limits is passed, an error is raised. Else, the sorted list of unique values is returned.

Read an array from an open file.

This uses numpy.fromfile() to read an array with known shape and data type from an open file. The sep parameter can be specified as in numpy.fromfile. If an empty string is given as separator, the data is read in binary mode. In that case (only) an extra ‘n’ after the data will be stripped off.

arraytools.writeArray(file, array, sep=' ')

Write an array to an open file.

This uses numpy.tofile() to write an array to an open file. The sep parameter can be specified as in tofile.

arraytools.cubicEquation(a, b, c, d)

Solve a cubiq equation using a direct method.

a,b,c,d are the (floating point) coefficients of a third degree polynomial equation:

```a*x**3+b*x**2+c*x+d=0
```

This function computes the three roots (real and complex) of this equation and returns full information about their kind, sorting order, occurrence of double roots. It uses scaling of the variables to enhance the accuracy.

The return value is a tuple (r1,r2,r3,kind), where r1,r2 and r3 are three float values and kind is an integer specifying the kind of roots.

Depending on the value of kind, the roots are defined as follows:

kind roots
0 three real roots r1 < r2 < r3
1 three real roots r1 < r2 = r3
2 three real roots r1 = r2 < r3
3 three real roots r1 = r2 = r3
4 one real root r1 and two complex conjugate roots with real part r2 and imaginary part r3; the complex roots are thus: r2+i*r3 en r2-i*r3, where i=sqrt(-1).

If the coefficient a==0, a ValueError is raised.

Example:

```>>> cubicEquation(1.,-3.,3.,-1.)
([1.0, 1.0, 1.0], 3)
```
arraytools.uniqueOrdered(ar1, return_index=False, return_inverse=False)

Find the unique elements of an array.

This works like numpy’s unique, but uses a stable sorting algorithm. The returned index may therefore hold other entries for multiply occurring values. In such case, uniqueOrdered returns the first occurrence in the flattened array. The unique elements and the inverse index are always the same as those returned by numpy’s unique.

Parameters:

• ar1: array_like This array will be flattened if it is not already 1-D.
• return_index: bool, optional If True, also return the indices against ar1 that result in the unique array.
• return_inverse: bool, optional If True, also return the indices against the unique array that result in ar1.

Returns:

• unique: ndarray The unique values.
• unique_indices: ndarray, optional The indices of the unique values. Only provided if return_index is True.
• unique_inverse: ndarray, optional The indices to reconstruct the original array. Only provided if return_inverse is True.

Example:

```>>> a = array([2,3,4,5,6,7,8,1,2,3,4,5,6,7,8,7,8])
>>> uniq,ind,inv = unique(a,True,True)
>>> print(uniq)
[1 2 3 4 5 6 7 8]
>>> print(ind)
[7 0 1 2 3 4 5 6]
>>> print(inv)
[1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 6 7]
>>> uniq,ind,inv = uniqueOrdered(a,True,True)
>>> print(uniq)
[1 2 3 4 5 6 7 8]
>>> print(ind)
[7 0 1 2 3 4 5 6]
>>> print(inv)
[1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 6 7]
```

Notice the difference in the fourth element of the ind array.

arraytools.renumberIndex(index)

Renumber an index sequentially.

Given a one-dimensional integer array with only non-negative values, and nval being the number of different values in it, and you want to replace its elements with values in the range 0..nval, such that identical numbers are always replaced with the same number and the new values at their first occurrence form an increasing sequence 0..nval. This function will give you the old numbers corresponding with each position 0..nval.

Parameters:

• index: array_like, 1-D, integer An array with non-negative integer values

Returns:

A 1-D integer array with length equal to nval, where nval is the number of different values in index, and holding the original values corresponding to the new value 0..nval.

Remark:

Use inverseUniqueIndex() to find the inverse mapping needed to replace the values in the index by the new ones.

Example:

```>>> renumberIndex([0,5,2,2,6,0])
array([0, 5, 2, 6])
>>> inverseUniqueIndex(renumberIndex([0,5,2,2,6,0]))[[0,5,2,2,6,0]]
array([0, 1, 2, 2, 3, 0])
```
arraytools.complement(index, n=-1)

Return the complement of an index in a range(0,n).

The complement is the list of numbers from the range(0,n) that are not included in the index.

Parameters:

• index: array_like, 1-D, int or bool. If integer, it is a list with the non-negative numbers to be excluded from the range(0,n). If boolean, it normally has the length of the range and flags the elements to be returned with a False value.
• n: int: the upper limit for the range of numbers. If index is of type integer and n is not specified or is negative, it will be set equal to the largest number in index plus 1. If index is of type boolean and n is larger than the length of index, index will be padded with False values until length n.

Returns:

If index is integer: a 1-D integer array with the numbers from range(0,n) that are not included in index. If index is boolean, the negated index padded to or cut at length n.

Example:

```>>> print(complement([0,5,2,6]))
[1 3 4]
>>> print(complement([0,5,2,6],10))
[1 3 4 7 8 9]
>>> print(complement([False,True,True,True],6))
[ True False False False  True  True]
```
arraytools.inverseUniqueIndex(index)

Inverse an index.

Given a 1-D integer array with unique non-negative values, and max being the highest value in it, this function returns the position in the array of the values 0..max. Values not occurring in input index get a value -1 in the inverse index.

Parameters:

• index: array_like, 1-D, integer An array with non-negative values, which all have to be unique.

Returns:

A 1-D integer array with length max+1, with the positions in index of the values 0..max, or -1 if the value does not occur in index.

Remark:

The inverse index translates the unique index numbers in a sequential index, so that inverseUniqueIndex(index)[index] == arange(1+index.max()).

Example:

```>>> inverseUniqueIndex([0,5,2,6])
array([ 0, -1,  2, -1, -1,  1,  3])
>>> inverseUniqueIndex([0,5,2,6])[[0,5,2,6]]
array([0, 1, 2, 3])
```
arraytools.sortSubsets(a, w=None)

Sort subsets of an integer array a.

a is a 1-D integer array. Subsets of the array are the collections of equal values. w is a float array with same size of a, specifying a weight for each of the array elements in a. If no weight is specified, all elements have the same weight.

The subsets of a are sorted in order of decreasing total weight of the subsets (or number of elements if weight is None).

The return value is an integer array of the same size of a, specifying for each element the index of its subset in the sorted list of subsets.

Example:

```>>> sortSubsets([0,1,2,3,1,2,3,2,3,3])
array([3, 2, 1, 0, 2, 1, 0, 1, 0, 0])
```
```>>> sortSubsets([0,1,2,3,1,2,3,2,3,3],w=[9,8,7,6,5,4,3,2,1,0])
array([3, 1, 0, 2, 1, 0, 2, 0, 2, 2])
```
arraytools.sortByColumns(a)

Sort an array on all its columns, from left to right.

The rows of a 2-dimensional array are sorted, first on the first column, then on the second to resolve ties, etc..

Parameters:

• a: array_like, 2-D
Returns a 1-D integer array specifying the order in which the rows have to
be taken to obtain an array sorted by columns.

Example:

```>>> sortByColumns([[1,2],[2,3],[3,2],[1,3],[2,3]])
array([0, 3, 1, 4, 2])
```
arraytools.uniqueRows(a, permutations=False)

Find the unique rows of a 2-D array.

Parameters:

• a: array_like, 2-D
• permutations: bool If True, rows which are permutations of the same data are considered equal. The default is to consider permutations as different.

Returns:

• uniq: a 1-D integer array with the numbers of the unique rows from a. The order of the elements in uniq is determined by the sorting procedure: in the current implementation this is sortByColumns(). If permutations==True, a is sorted along its axis -1 before calling this sorting function.
• uniqid: a 1-D integer array with length equal to a.shape[0] with the numbers of uniq corresponding to each of the rows of a.

Example:

```>>> uniqueRows([[1,2],[2,3],[3,2],[1,3],[2,3]])
(array([0, 3, 1, 2]), array([0, 2, 3, 1, 2]))
>>> uniqueRows([[1,2],[2,3],[3,2],[1,3],[2,3]],permutations=True)
(array([0, 3, 1]), array([0, 2, 2, 1, 2]))
```
arraytools.argNearestValue(values, target)

Return the index of the item nearest to target.

Parameters:

• values: a list of float values
• target: a float value

Returns the position of the item in values that is nearest to target.

Example:

```>>> argNearestValue([0.1,0.5,0.9],0.7)
1
```
arraytools.nearestValue(values, target)

Return the item nearest to target.

values: a list of float values

target: a single value

Returns the item in values values that is nearest to target.

arraytools.inverseIndex(index, maxcon=4)

Return an inverse index.

An index is an array pointing at other items by their position. The inverse index is a collection of the reverse pointers. Negative values in the input index are disregarded.

Parameters:

• index: an array of integers, where only non-negative values are meaningful, and negative values are silently ignored. A Connectivity is a suitable argument.
• maxcon: int: an initial estimate for the maximum number of rows a single element of index occurs at. The default will usually do well, because the procedure will automatically enlarge it when needed.

Returns:

An (mr,mc) shaped integer array where:

• mr will be equal to the highest positive value in index, +1.
• mc will be equal to the highest row-multiplicity of any number in index.

Row i of the inverse index contains all the row numbers of index that contain the number i. Because the number of rows containing the number i is usually not a constant, the resulting array will have a number of columns mc corresponding to the highest row-occurrence of any single number. Shorter rows are padded with -1 values to flag non-existing entries.

Example:

```>>> inverseIndex([[0,1],[0,2],[1,2],[0,3]])
array([[ 0,  1,  3],
[-1,  0,  2],
[-1,  1,  2],
[-1, -1,  3]])
```
arraytools.matchIndex(target, values)

Find position of values in target.

This function finds the position in the array target of the elements from the array values.

Parameters:

• target: an index array with all non-negative values. If not 1-D, it will be flattened.
• values: an index array with all non-negative values. If not 1-D, it will be flattened.

Returns:

An index array with the same size as values. For each number in values, the index contains the position of that value in the flattened target, or -1 if that number does not occur in target. If an element from values occurs more than once in target, it is currently undefined which of those positions is returned.

Remark that after m = matchIndex(target,values) the equality target[m] == values holds in all the non-negative positions of m.

Example:

```>>> A = array([1,3,4,5,7,8,9])
>>> B = array([0,6,7,1,2])
>>> matchIndex(A,B)
array([-1, -1,  4,  0, -1])
```
arraytools.groupPositions(gid, values)

Compute the group positions.

Computes the positions per group in a set of group identifiers.

Parameters:

• gid: (nid,) shaped int array of group identifiers
• values: (nval,) shaped int array with unique group identifiers for which to return the positions.

Returns:

• pos: list of int arrays giving the positions in gid of each group identifier in values.
```>>> gid = array([ 2, 1, 1, 6, 6, 1 ])
>>> values = array([ 1, 2, 6 ])
>>> print(groupPositions(gid,values))
[array([1, 2, 5]), array([0]), array([3, 4])]
```
arraytools.groupArgmin(val, gid)

Compute the group minimum.

Computes the minimum value per group of a set of values tagged with a group number.

Parameters:

• val: (nval,) shaped array of values
• gid: (nval,) shaped int array of group identifiers

Returns:

• ugid: (ngrp,) shaped int array with unique group identifiers
• minpos: (ngrp,p) shape int array giving the position in val of the minimum of all values with the corresponding group identifier in ugid.

After return, the minimum values corresponding to the groups in ugid are given by val[minpos].

```>>> val = array([ 0.0, 1.0, 2.0, 3.0, 4.0, -5.0 ])
>>> gid = array([ 2, 1, 1, 6, 6, 1 ])
>>> print(groupArgmin(val,gid))
(array([1, 2, 6]), array([5, 0, 3]))
```
arraytools.vectorLength(vec)

Return the lengths of a set of vectors.

vec is an (n,3) shaped array holding a collection of vectors. The result is an (n,) shaped array with the length of each vector.

arraytools.vectorNormalize(vec)

Normalize a set of vectors.

vec is a (n,3) shaped arrays holding a collection of vectors. The result is a tuple of two arrays:

• length (n): the length of the vectors vec
• normal (n,3): unit-length vectors along vec.
arraytools.vectorPairAreaNormals(vec1, vec2)

Compute area of and normals on parallellograms formed by vec1 and vec2.

vec1 and vec2 are (n,3) shaped arrays holding collections of vectors. As a convenience, single vectors may also be specified with shape (3,), and will be converted to (1,3).

The result is a tuple of two arrays:

• area (n) : the area of the parallellogram formed by vec1 and vec2.
• normal (n,3) : (normalized) vectors normal to each couple (vec1,2).

These are calculated from the cross product of vec1 and vec2, which indeed gives area * normal.

Note that where two vectors are parallel, an area zero results and an axis with components NaN.

arraytools.vectorPairArea(vec1, vec2)

Compute area of the parallellogram formed by a vector pair vec1,vec2.

vec1 and vec2 are (n,3) shaped arrays holding collections of vectors. The result is an (n) shaped array with the area of the parallellograms formed by each pair of vectors (vec1,vec2).

arraytools.vectorPairNormals(vec1, vec2)

Compute vectors normal to vec1 and vec2.

vec1 and vec2 are (n,3) shaped arrays holding collections of vectors. The result is an (n,3) shaped array of unit length vectors normal to each couple (edg1,edg2).

arraytools.vectorTripleProduct(vec1, vec2, vec3)

Compute triple product vec1 . (vec2 x vec3).

vec1, vec2, vec3 are (n,3) shaped arrays holding collections of vectors. The result is a (n,) shaped array with the triple product of each set of corresponding vectors from vec1,vec2,vec3. This is also the square of the volume of the parallellepid formex by the 3 vectors. If vec1 is a unit normal, the result is also the area of the parallellogram (vec2,vec3) projected in the direction vec1.

arraytools.vectorPairCosAngle(v1, v2)

Return the cosinus of the angle between the vectors v1 and v2.

vec1 and vec2 are (n,3) shaped arrays holding collections of vectors. The result is an (n) shaped array with the cosinus of the angle between each pair of vectors (vec1,vec2).

arraytools.vectorPairAngle(v1, v2)

Return the angle (in radians) between the vectors v1 and v2.

vec1 and vec2 are (n,3) shaped arrays holding collections of vectors. The result is an (n) shaped array with the angle between each pair of vectors (vec1,vec2).

arraytools.percentile(values, perc=[25.0, 50.0, 75.0], wts=None)

Return the perc percentile(s) of values.

Parameters:

• values: a one-dimensional array of values for which to compute the percentile(s);
• perc: an integer, float or array specifying which percentile(s) to compute; by default, the quartiles are returned;
• wts: a one-dimensional array of weights assiged to values.

Returns the value(s) that is/are greater or equal than perc percent of values. If the result lies between two items of values, it is obtained by interpolation.

arraytools.multiplicity(a)

Return the multiplicity of the numbers in a

a is a 1-D integer array.

Returns a tuple of:

• ‘mult’: the multiplicity of the unique values in a
• ‘uniq’: the sorted list of unique values in a

Example:

```>>> multiplicity([0,3,5,1,4,1,0,7,1])
(array([2, 3, 1, 1, 1, 1]), array([0, 1, 3, 4, 5, 7]))
```
arraytools.histogram2(a, bins, range=None)

Compute the histogram of a set of data.

This function is like numpy’s histogram function, but also returns the bin index for each individual entry in the data set.

Parameters:

• a: array_like. Input data. The histogram is computed over the flattened array.
• bins: int or sequence of scalars. If bins is an int, it defines the number of equal-width bins in the given range. If bins is a sequence, it defines the bin edges, allowing for non-uniform bin widths. Both the leftmost and rightmost edges are included, thus the number of bins is len(bins)-1.
• range: (float, float), optional. The lower and upper range of the bins. If not provided, range is simply (a.min(), a.max()). Values outside the range are ignored. This parameter is ignored if bins is a sequence.

Returns:

• hist: integer array with length nbins, holding the number of elements in each bin,
• ind: a sequence of nbins integer arrays, each holding the indices of the elements fitting in the respective bins,
• xbins: array of same type as data and with length nbins+1: returns the bin edges.

Example:

```>>> hist,ind,xbins = histogram2([1,2,3,4,2,3,1],[1,2,3,4,5])
>>> print(hist)
[2 2 2 1]
>>> for i in ind: print(i)
[0 6]
[1 4]
[2 5]
[3]
>>> print(xbins)
[1 2 3 4 5]
```
arraytools.movingView(a, size)

Create a moving view along the first axis of an array

Parameters:

• a : array_like: array for wihch to create a moving view
• size : int: size of the moving view
Returns an array that is a view of the original array with an extra first

axis of length w.

Using swapaxes(0,axis) moving views over any axis can be created.

Example:

```>>> x=arange(10).reshape((5,2))
>>> print(x)
[[0 1]
[2 3]
[4 5]
[6 7]
[8 9]]
>>> print(movingView(x, 3))
[[[0 1]
[2 3]
[4 5]]

[[2 3]
[4 5]
[6 7]]

[[4 5]
[6 7]
[8 9]]]
```

Calculate rolling sum of first axis:

```>>> print(movingView(x, 3).sum(axis=0))
[[ 6  9]
[12 15]
[18 21]]
```
arraytools.movingAverage(a, n, m0=None, m1=None)

Compute the moving average along the first axis of an array.

Parameters:

• a : array_like: array to be averaged
• n : int: moving sample size
• m0 : optional, int: if specified, the first data set of a will be prepended this number of times
• m1 : optional, int: if specified, the last data set of a will be appended this number of times

Returns:

An array with the moving average over n data sets along the first axis of a. The array has the same shape as a, except possibly for the length of the first axis. If neither m0 nor m1 are set, the first axis will have a length of a.shape[0] - (n-1). If both m0 and m1 are give, the first axis will have a length of a.shape[0] - (n-1) + m0 + m1. If either m0 or m1 are set and the other not, the missing value m0 or m1 will be computed thus that the return array has a first axis with length a.shape[0].

Example:

```>>> x=arange(10).reshape((5,2))
>>> print(movingAverage(x,3))
[[ 2.  3.]
[ 4.  5.]
[ 6.  7.]]
>>> print(movingAverage(x,3,2))
[[ 0.    1.  ]
[ 0.67  1.67]
[ 2.    3.  ]
[ 4.    5.  ]
[ 6.    7.  ]]
```
arraytools.randomNoise(shape, min=0.0, max=1.0)

Create an array with random values between min and max

arraytools.unitDivisor(div, start=0)

Divide a unit interval in equal parts.

This function is intended to be used by interpolation functions that accept an input as either an int or a list of floats.

Parameters:

• div: an integer, or a list of floating point values. If it is an integer, returns a list of floating point values dividing the interval 0.0 toi 1.0 in div equal parts.
• start: Set to 1 to skip the start value (0.0) of the interval.

Returns: If div is a an integer, returns the floating point values dividing the unit interval in div equal parts. If div is a list, just returns div as a 1D array.

arraytools.uniformParamValues(n, umin=0.0, umax=1.0)

Create a set of uniformly distributed parameter values in a range.

Parameters:

• n: int: number of intervals in which the range should be divided. The number of values returned is n+1.
• umin, umax: float: start and end value of the interval. Default interval is [0.0..1.0].

Returns:

A float array with n+1 equidistant values in the range umin..umax. For n > 0, both of the endpoints are included. For n=0, a single value at the center of the interval will be returned. For n<0, an empty array is returned.

Example:

```>>> uniformParamValues(4).tolist()
[0.0, 0.25, 0.5, 0.75, 1.0]
>>> uniformParamValues(0).tolist()
[0.5]
>>> uniformParamValues(-1).tolist()
[]
>>> uniformParamValues(2,1.5,2.5).tolist()
[1.5, 2.0, 2.5]
```
arraytools.nodalSum(val, elems, avg=False, return_all=True, direction_treshold=None)

Compute the nodal sum of values defined on elements.

val is a (nelems,nplex,nval) array of values defined at points of elements. elems is a (nelems,nplex) array with nodal ids of all points of elements.

The return value is a (nelems,nplex,nval) array where each value is replaced with the sum of its value at that node. If avg=True, the values are replaced with the average instead. If return_all==True(default), returns an array with shape (nelems,nplex,3), else, returns an array with shape (maxnodenr+1,3). In the latter case, nodes not occurring in elems will have all zero values.

If a direction_tolerance is specified and nval > 1, values will only be summed if their direction is close (projection of one onto the other is higher than the specified tolerance).

arraytools.pprint(a, label='')

Pretty print an array with a label in front.

When printing a numpy array with a lable in font, the first row of the array is not aligned with the remainder. This function will solve that issue and prints the full array nicely aligned.

• a: a numpy array
• label: a sting to be printed in front of the array

Example:

```>>> a = arange(12).reshape(-1,3)
>>> pprint(a,'Reshaped range = ')
Reshaped range = [[ 0  1  2]
[ 3  4  5]
[ 6  7  8]
[ 9 10 11]]
```