Fork me on GitHub

pyhrf.ndarray module

This module provides classes and functions to handle multi-dimensionnal numpy array (ndarray) objects and extend them with some semantics (axes labels and axes domains). See xndarray class. (TODO: make xndarray inherit numpy.ndarray?)

exception pyhrf.ndarray.ArrayMappingError

Bases: exceptions.Exception

pyhrf.ndarray.expand_array_in_mask(flat_data, mask, flat_axis=0, dest=None, m=None)

Map the flat_axis of flat_data onto the region within mask. flat_data is then reshaped so that flat_axis is replaced with mask.shape.

Notes

m is the result of np.where(mask) -> can be passed to speed up if already done before.

Examples

>>> a = np.array([1,2,3])
>>> m = np.array([[0,1,0], [0,1,1]] )
>>> expand_array_in_mask(a,m)
array([[0, 1, 0],
       [0, 2, 3]])
>>> a = np.array([[1,2,3],[4,5,6]])
>>> m = np.array([[0,1,0], [0,1,1]] )
>>> expand_array_in_mask(a,m,flat_axis=1)
array([[[0, 1, 0],
        [0, 2, 3]],

       [[0, 4, 0],
        [0, 5, 6]]])
pyhrf.ndarray.merge(arrays, mask, axis, fill_value=0)

Merge the given arrays into a single array according to the given mask, with the given axis being mapped to those of mask. Assume that arrays[id] corresponds to mask==id and that all arrays are in the same orientation.

Arg:
  • arrays (dict of xndarrays):
  • mask (xndarray): defines the mapping between the flat axis in the
    arrays to merge and the target expanded axes.
  • axis (str): flat axis for the
pyhrf.ndarray.split_and_save(cub, axes, fn, meta_data=None, set_MRI_orientation=False, output_dir=None, format_dvalues=False)
pyhrf.ndarray.stack_cuboids(c_list, axis, domain=None, axis_pos='first')

Stack xndarray instances in list c_list along a new axis label axis. If domain (numpy array or list) is provided, it is associated to the new axis. All cuboids in c_list must have the same orientation and domains. axis_pos defines the position of the new axis: either first or last.

Examples

>>> import numpy as np
>>> from pyhrf.ndarray import xndarray, stack_cuboids
>>> c1 = xndarray(np.arange(4*3).reshape(4,3), ['x','y'])
>>> c1
axes: ['x', 'y'], array([[ 0,  1,  2],
       [ 3,  4,  5],
       [ 6,  7,  8],
       [ 9, 10, 11]])
>>> c2 = xndarray(np.arange(4*3).reshape(4,3)*2, ['x','y'])
>>> c2
axes: ['x', 'y'], array([[ 0,  2,  4],
       [ 6,  8, 10],
       [12, 14, 16],
       [18, 20, 22]])
>>> c_stacked = stack_cuboids([c1,c2], 'stack_axis', ['c1','c2'])
>>> print c_stacked.descrip()  
* shape : (2, 4, 3)
* dtype : int64
* orientation: ['stack_axis', 'x', 'y']
* value label: value
* axes domains:
  'stack_axis': array(['c1', 'c2'],
      dtype='|S2')
  'x': arange(0,3,1)
  'y': arange(0,2,1)

TODO: enable broadcasting (?)

pyhrf.ndarray.tree_to_xndarray(tree, level_labels=None)

Stack all arrays within input tree into a single array.

Parameters:
  • tree (dict) – nested dictionaries of xndarray objects. Each level of the tree correspond to a target axis, each key of the tree correspond to an element of the domain associated to that axis.
  • level_labels (list of str) – axis labels corresponding to each level of the tree
Returns:

Return type:

xndarray object

Examples

>>> from pyhrf.ndarray import xndarray, tree_to_xndarray
>>> d = { 1 : { .1 : xndarray([1,2], axes_names=['inner_axis']),                     .2 : xndarray([3,4], axes_names=['inner_axis']),                   },                                                               2 : { .1 : xndarray([1,2], axes_names=['inner_axis']),                     .2 : xndarray([3,4], axes_names=['inner_axis']),                   }                                                              }
>>> tree_to_xndarray(d, ['level_1', 'level_2'])
axes: ['level_1', 'level_2', 'inner_axis'], array([[[1, 2],
        [3, 4]],

       [[1, 2],
        [3, 4]]])
class pyhrf.ndarray.xndarray(narray, axes_names=None, axes_domains=None, value_label='value', meta_data=None)

Handles a multidimensional numpy array with axes that are labeled and mapped to domain values.

Examples

>>> c = xndarray( [ [4,5,6],[8,10,12] ], ['time','position'], {'time':[0.1,0.2]} )

Will represent the following situation:

position
------->
4  5  6 | t=0.1   |time
8 10 12 | t=0.2   v
add(c, dest=None)
astype(t)
cexpand(cmask, axis, dest=None)

Same as expand but mask is a cuboid

TODO: + unit test

cflatten(cmask, new_axis)
copy(copy_meta_data=False)

Return copy of the current cuboid. Domains are copied with a shallow dictionnary copy.

descrip()

Return a printable string describing the cuboid.

descrip_shape()
divide(c, dest=None)
expand(mask, axis, target_axes=None, target_domains=None, dest=None, do_checks=True, m=None)

Create a new xndarray instance (or store into an existing dest cuboid) where axis is expanded and values are mapped according to mask.

  • target_axes is a list of the names of the new axes replacing axis.
  • target_domains is a dict of domains for the new axes.

Examples

>>> import numpy as np
>>> from pyhrf.ndarray import xndarray
>>> c_flat = xndarray(np.arange(2*6).reshape(2,6).astype(np.int64),                               ['condition', 'voxel'],                               {'condition' : ['audio','video']})
>>> print c_flat.descrip()  
* shape : (2, 6)
* dtype : int64
* orientation: ['condition', 'voxel']
* value label: value
* axes domains:
  'condition': array(['audio', 'video'],
      dtype='|S5')
  'voxel': arange(0,5,1)
>>> mask = np.zeros((4,4,4), dtype=int)
>>> mask[:3,:2,0] = 1
>>> c_expanded = c_flat.expand(mask, 'voxel', ['x','y','z'])
>>> print c_expanded.descrip()  
* shape : (2, 4, 4, 4)
* dtype : int64
* orientation: ['condition', 'x', 'y', 'z']
* value label: value
* axes domains:
  'condition': array(['audio', 'video'],
      dtype='|S5')
  'x': arange(0,3,1)
  'y': arange(0,3,1)
  'z': arange(0,3,1)
explode(cmask, new_axis='position')

Explode array according to the given n-ary mask so that axes matchin those of mask are flatten into new_axis.

Parameters:
  • mask (-) – n-ary mask that defines “regions” used to split data
  • new_axis (-) – target flat axis
Returns:

dict of xndarray that maps a mask value to a xndarray.

explode_a(mask, axes, new_axis)

Explode array according to given n-ary mask so that axes are flatten into new_axis.

Parameters:
  • mask (-) – n-ary mask that defines “regions” used to split data
  • axes (-) – list of axes in the current object that are mapped onto the mask
  • new_axis (-) – target flat axis
Returns:

dict of xndarray that maps a mask value to a xndarray.

fill(c)
flatten(mask, axes, new_axis)

flatten cudoid.

TODO: +unit test

get_axes_domains()

Return domains associated to axes as a dict (axis_name:domain array)

get_axes_ids(axes_names)

Return the index of all axes in given axes_names

get_axis_id(axis_name)

Return the id of an axis from the given name.

get_axis_name(axis_id)

Return the name of an axis from the given index ‘axis_id’.

get_domain(axis_id)

Return the domain of the axis axis_id

Examples

>>> from pyhrf.ndarray import xndarray
>>> c = xndarray(np.random.randn(10,2), axes_names=['x','y'],                        axes_domains={'y' : ['plop','plip']})
>>> (c.get_domain('y') == np.array(['plop', 'plip'], dtype='|S4')).all()
True
>>> c.get_domain('x') #default domain made of slice indexes
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
get_domain_idx(axis, value)

Get slice index from domain value for axis ‘axis’.

get_dshape()

Return the shape of the array as dict mapping an axis name to the corresponding size

get_extra_info(fmt='dict')
get_ndims()
get_new_axis_name()

Return an axis label not already in use. Format is: dim%d

get_orientation()
get_voxel_size(axis)

Return the size of a voxel along ‘axis’, only if meta data is available.

has_axes(axes)
has_axis(axis)
len(axis)
static load(file_name)

Load cuboid from file. Supported format: nifti1. Extra axis information is retrieved from a nifti extension if available. If it’s not available, label the axes as: (sagittal, coronal, axial[, time]).

TODO: gifti.

map_onto(xmapping)

Reshape the array by mapping the axis corresponding to xmapping.value_label onto the shape of xmapping.

Parameters:xmapping (xndarray) – array whose attribute value_label matches an axis of the current array
Returns:
Return type:a new array (xndarray) where values from the current array have been mapped according to xmapping

Examples

>>> from pyhrf.ndarray import xndarray
>>> import numpy as np
>>> # data with a region axis:
>>> data = xndarray(np.arange(2*4).reshape(2,4).T * .1,                                ['time', 'region'],                                           {'time':np.arange(4)*.5, 'region':[2, 6]})
>>> data
axes: ['time', 'region'], array([[ 0. ,  0.4],
       [ 0.1,  0.5],
       [ 0.2,  0.6],
       [ 0.3,  0.7]])
>>> # 2D spatial mask of regions:
>>> region_map = xndarray(np.array([[2,2,2,6], [6,6,6,0], [6,6,0,0]]),                                   ['x','y'], value_label='region')
>>> # expand region-specific data into region mask
>>> # (duplicate values)
>>> data.map_onto(region_map)
axes: ['x', 'y', 'time'], array([[[ 0. ,  0.1,  0.2,  0.3],
        [ 0. ,  0.1,  0.2,  0.3],
        [ 0. ,  0.1,  0.2,  0.3],
        [ 0.4,  0.5,  0.6,  0.7]],

       [[ 0.4,  0.5,  0.6,  0.7],
        [ 0.4,  0.5,  0.6,  0.7],
        [ 0.4,  0.5,  0.6,  0.7],
        [ 0. ,  0. ,  0. ,  0. ]],

       [[ 0.4,  0.5,  0.6,  0.7],
        [ 0.4,  0.5,  0.6,  0.7],
        [ 0. ,  0. ,  0. ,  0. ],
        [ 0. ,  0. ,  0. ,  0. ]]])
max(axis=None)
mean(axis=None)
min(axis=None)
multiply(c, dest=None)
ptp(axis=None)
reorient(orientation)

Return a cuboid with new orientation. If cuboid is already in the right orientation, then return the current cuboid. Else, create a new one.

repeat(n, new_axis, domain=None)

Return a new cuboid with self’s data repeated ‘n’ times along a new axis labelled ‘new_axis’. Associated ‘domain’ can be provided.

rescale_values(v_min=0.0, v_max=1.0, axis=None)
roll(axis, pos=-1)

Roll xndarray by making ‘axis’ the last axis. ‘pos’ is either 0 or -1 (first or last, respectively) TODO: handle all pos.

save(file_name, meta_data=None, set_MRI_orientation=False)

Save cuboid to a file. Supported format: Nifti1. ‘meta_data’ shoud be a 2-elements tuple: (affine matrix, Nifti1Header instance). If provided, the meta_data attribute of the cuboid is ignored. All extra axis information is stored as an extension.

set_MRI_orientation()

Set orientation to sagittal,coronal,axial,[time|iteration|condition] Priority for the 4th axis: time > condition > iteration. The remaining axes are sorted in alphatical order

set_axis_domain(axis_id, domain)

Set the value domain mapped to axis_id as domain

Parameters:
  • axis_id (-) – label of the axis
  • domain (-) – value domain
Returns:

None

set_orientation(axes)

Set the cuboid orientation (inplace) according to input axes labels

split(axis)

Split a cuboid along given axis. Return an OrderedDict of cuboids.

squeeze(axis=None)

Remove all dims which have length=1. ‘axis’ selects a subset of the single-dimensional axes.

squeeze_all_but(axes)
std(axis=None)
sub_cuboid(orientation=None, **kwargs)

Return a sub cuboid. ‘kwargs’ allows argument in the form: axis=slice_value.

sub_cuboid_from_slices(orientation=None, **kwargs)

Return a sub cuboid. ‘kwargs’ allows argument in the form: axis=slice_index.

substract(c, dest=None)
sum(axis=None)
swapaxes(a1, a2)

Swap axes a1 and a2

Parameters:
  • a1 (-) – identifier of the 1st axis
  • a2 (-) – identifier of the 2nd axis
Returns:

A new cuboid wrapping a swapped view of the numpy array

to_html_table(row_axes, col_axes, inner_axes, cell_format='txt', plot_dir=None, rel_plot_dir=None, plot_fig_prefix='xarray_', plot_style='image', plot_args=None, tooltip=False, border=None)

Render the array as an html table whose column headers correspond to domain values and axis names defined by col_axes, row headers defined by row_axes and inner cell axes defined by inner_axes Data within a cell can be render as text or as a plot figure (image files are produced)

Parameters:-
Returns:html code (str)
to_latex(row_axes=None, col_axes=None, inner_axes=None, inner_separator=' | ', header_styles=None, hval_fmt=None, val_fmt='%1.2f', col_align=None)
to_tree(level_axes, leaf_axes)

Convert nested dictionary mapping where each key is a domain value and each leaf is an array or a scalar value if leaf_axes is empty.

Returns:{dv_axis1 : {dv_axis2 : {… : xndarray|scalar_type}
Return type:OrderedDict such as

Example: >>> from pyhrf.ndarray import xndarray >>> import numpy as np >>> c = xndarray(np.arange(4).reshape(2,2), axes_names=[‘a1’,’ia’], axes_domains={‘a1’:[‘out_dv1’, ‘out_dv2’], ‘ia’:[‘in_dv1’, ‘in_dv2’]}) >>> c.to_tree([‘a1’], [‘ia’]) OrderedDict([(‘out_dv1’, axes: [‘ia’], array([0, 1])), (‘out_dv2’, axes: [‘ia’], array([2, 3]))])

unstack(outer_axes, inner_axes)

Unstack the array along outer_axes and produce a xndarray of xndarrays

Parameters:
  • outer_axes (-) – list of axis names defining the target unstacked xndarray
  • inner_axes (-) – list of axis names of any given sub-array of the target unstacked xndarray
Returns:

xndarray object

Example: >>> from pyhrf.ndarray import xndarray >>> import numpy as np >>> c = xndarray(np.arange(4).reshape(2,2), axes_names=[‘a1’,’ia’], axes_domains={‘a1’:[‘out_dv1’, ‘out_dv2’], ‘ia’:[‘in_dv1’, ‘in_dv2’]}) >>> c.unstack([‘a1’], [‘ia’]) axes: [‘a1’], array([axes: [‘ia’], array([0, 1]), axes: [‘ia’], array([2, 3])], dtype=object)

var(axis=None)
static xndarray_like(c, data=None)

Return a new cuboid from data with axes, domains and value label copied from ‘c’. If ‘data’ is provided then set it as new cuboid’s data, else a zero array like c.data is used.

TODO: test

pyhrf.ndarray.xndarray_like(c, data=None)