Xmipp

MultidimArray Class

Introduction

MultidimArray class is a template class to handle image arrays in Xmipp. It stores a pointer to the data array, dimension sizes, and other internal parameters. This class allows to work with arrays from one to four dimensions, i.e. stack of volumes (See handling images).

Below the MultidimArray class, you can find the MultidimArrayBase superclass. This superclass does not contain any information about the datatype of a declared Multidimarray class, and its purpose is to be used from MultidimArrayGeneric class.

Declaration

Below, we show some examples of declaration and use:

MultidimArray<double> image(256, 128);
image.initZeros();

MultidimArray<float> imFloat;
imFloat.resize(128, 128, 128);
imFloat.initRandom(0, 1);

Pixel index Origin

In Xmipp, we can distinguish to kind of indexes:

  • physical: these are related to the real access to memory and cannot be modified.
  • logical: these are related to an origin pixel, and can be modified.

By default, when a MultidimArray object is created, the origin pixel, with all its dimension indexes equal to zero, is the first pixel allocated in memory (Top left corner), so logical indexes will be as physical indexes.

Sometimes you need to operate with pixels in different MultidimArray objects that are placed in different physical indexes (maybe because pixel positions are shifted or images' size are different, as in convolution operations). To do so, you can set the pixel index origin to a different value. The usual way is to set the origin of the pixel coordinates to the center of the image as it is shown in Conventions section,

MultidimArray<double> A;
A.resize(128, 128);
A.setXmippOrigin();

although any other pixel can be selected as origin,

A.moveOriginTo(32, 32);

Moreover, you can reset the origin to the default value,

A.resetOrigin();

Pixel access

To access to a specific pixel value, there are some macro declarations intended to do this, depending on whether you want to use the physical or logical indexes.

Physical access

MultidimArray<double> A, B, result;
A.resize(128, 128);
B.resize(128, 128);

A.initRandom(0, 1);
B.initRandom(0, 1);
result.resize(128, 128);

FOR_ALL_DIRECT_ELEMENTS_IN_ARRAY3D(result)
{
dAkij(result,k,i,j) = dAkij(A,k,i,j) * dAkij(B,k,i,j);
}

Logical access

MultidimArray<double> A, B, result;
A.resize(256, 256);
B.resize(128, 128);
A.initRandom(0, 1);
B.initRandom(0, 1);

result.resize(64, 64);

FOR_ALL_ELEMENTS_IN_ARRAY3D(result)
{
A3D_ELEM(result,k,i,j) = A3D_ELEM(A,k,i,j) * A3D_ELEM(B,k,i,j);
}

Aliases

There are many functions that are developed to use as input 2D MultidimArrays only, or maybe you want to process a slice of a volume (3D image) or an image in a stack in memory as a single image. In these cases, the Alias methods allows you the declare a MultidimArray object pointing to the real data of the original object, so the MultidimArray will be seen as a 2D image and all changes will be really onto the original data.

MultidimArray<double> A, B;
A.resize(128, 128, 128);
A.initRandom(0, 1);

// Pointing to the slice 64
B.aliasSlice(A, 64);
// Only slice 64 will change
B *= 5;

Disk mapping

MultidimArray usually allocates the array in the user-space memory, but it is also possible to map the memory in disk, so the data is not occupying user memory. It is mainly intended to work with huge sized arrays, so the system swapping may be avoided. Once the MultidimArray is declared as usual, call setMmap(true) to activate mmap mode:

MultidimArray<double> A;
A.setMmap(true);
A.resize(128, 128, 128);

To revert the way the memory is allocated just set it to false:

A.setMmap(false);