1.. vigranumpy documentation master file, created by
2   sphinx-quickstart on Thu Dec 03 15:51:41 2009.
3   You can adapt this file completely to your liking, but it should at least
4   contain the root `toctree` directive.
5
6
7Vigranumpy Reference
8====================
9
10.. contents::
11
12.. toctree::
13   :maxdepth: 2
14
15Introduction
16------------
17
18Vigranumpy exports the functionality of the C++ image processing library `VIGRA <../vigra/index.html>`_ to Python. It can be invoked by importing the vigra module::
19
20    import vigra
21
22Vigranumpy is based on the popular `numpy <http://numpy.scipy.org/>`_ module and uses its ndarray data structure to represent image and volume data. It introduces the C++ wrapper class NumpyArray_ to allow transparent execution of VIGRA C++ functions on numpy arrays. Thus, vigranumpy is fully interoperable with existing numpy functionality, including various tools for image display such as matplotlib. Since vigranumpy uses `boost_python <http://www.boost.org/doc/libs>`_, it is able to support function overloading (which plain Python does not provide), so that calling syntax is largely uniform, regardless of the type and dimension of the input arguments.
23
24Basic calling syntax is similar to C++, with one important difference: Arguments for output images are optional. If no output image is provided, vigranumpy will allocate it as appropriate. In either case, the output image will be returned by the function, for example::
25
26    # allocate new result image
27    >>> smoothImage = vigra.gaussianSmoothing(inputImage, scale)
28
29    # reuse and overwrite existing result image
30    >>> smoothImage = vigra.gaussianSmoothing(inputImage, scale, out=smoothImage)
31
32Unless otherwise noted, all functions expect and create arrays with dtype=numpy.float32.
33
34Another important concern is the interpretation and ordering of the array axes. Numpy does not provide any means to attach semantics to axes, but relies purely on the convention that the most important axis is last, as in ``array[y, x]`` or ``array[z, y, x]`` ("C-order"). However, there is no way to enforce this convention in a program, since arrays can be transposed outside of the user's control (e.g. when saving data to a file). Moreover, many imaging libraries (e.g. `Image Magick <http://www.imagemagick.org/>`_, `OpenCV <http://opencv.willowgarage.com/>`_, `Qt <http://qt-project.org/>`_ and the C++ version of VIGRA) use the opposite convention where the x-axis comes first, as in ``array[x, y]`` or ``array[x, y, z]``. This makes it very difficult to convert solutions developed in Python into a fast C++ version, because one has to reverse all indices without making mistakes. Matters become even more complicated when multi-channel (e.g. color) images are considered -- should the color index now be first or last?
35
36To solve these ambiguities in a clean way, vigranumpy introduces the concept of **axistags** which is realized in class :class:`vigra.AxisTags`. Every :class:`~vigra.VigraArray` (which is a subclass of numpy.ndarray) gets a new property ``array.axistags`` that describes axis semantics, and all vigranumpy functions account for and preserve axistag information. Unfortunately, this functionality cannot easily be retrofitted to numpy.ndarray itself. Therefore, we employ the following conversion rules between Python and C++ arrays:
37
38* When the Python array has **no** ``array.axistags`` property, it is mapped to the C++ NumpyArray
39  **without** any change in axis ordering. Since most VIGRA functions can work on arbitrarily
40  transposed arrays, you will get correct results, but execution may be slower because the
41  processor cache is poorly utilized in certain axis orders.
42
43  Moreover, this may lead to overload resolution ambiguities. For example, when the array has shape
44  ``(3, 60, 40)``, vigranumpy has no way to decide if this is a 2-dimensional RGB image or
45  a 3-dimensional array that happens to have only 3 slices. Thus, vigranumpy may not always
46  execute the function you actually intended to call.
47
48* When the Python array **has** the ``array.axistags`` property, it is transposed into a
49  **canonical** axis ordering before vigranumpy executes a function, and the results are
50  transposed back into the original ordering. Likewise, functions that change axis ordering
51  (such as ``array.swapaxes(0,1)``) or reduce the number of axes (such as ``array.max(axis=1)``)
52  as well as array arithmetic operations preserve axistags (see section :ref:`sec-dtype-coercion`).
53  Thus, you can work in any desired axis order without loosing control. Overload ambiguities
54  can no longer occur because a function cannot be called when the axistags are unsuitable.
55
56Detailed information about the use of axistags is given in section :ref:`sec-vigraarray` below. Section :ref:`sec-own-modules` describes how you can take advantage of the axistags mechanism in your own C++ code.
57
58.. _sec-vigraarray:
59
60Axistags and the VigraArray Data Structure
61------------------------------------------
62
63While vigranumpy can directly work on numpy.ndarrays, this would not give us the advantages of axistags as described above. Therefore, vigranumpy introduces its own array class :class:`~vigra.VigraArray` which is a subclass of numpy.ndarray, but re-implements many of its methods so that axistags are respected. Arrays with a conforming ``axistags`` property are most easily constructed by one of the predefined :ref:`array factories <subsec-array-factories>`. A **view with axistags** can be created from an existing numpy.ndarray by means of the function :py:func:`~vigra.taggedView` (in contrast, factory functions create copies of the given arrays, not views). We illustrate the ideas by some examples::
64
65    >>> width, height, depth = 300, 200, 3
66
67    # create a 2-dimensional RGB image
68    >>> rgb = vigra.RGBImage((width, height))
69    >>> rgb.shape
70    (300, 200, 3)
71    >>> rgb.axistags             # short output: only axis keys
72    x y c
73    >>> print(rgb.axistags)      # long output
74    AxisInfo: 'x' (type: Space)
75    AxisInfo: 'y' (type: Space)
76    AxisInfo: 'c' (type: Channels) RGB
77
78    # create a 3-dimensional scalar volume
79    >>> volume = vigra.ScalarVolume((width, height, depth))
80    >>> volume.shape
81    (300, 200, 3)        # same shape as before
82    >>> volume.axistags
83    x y z                # but different semantic interpretation
84    >>> print(volume.axistags)
85    AxisInfo: 'x' (type: Space)
86    AxisInfo: 'y' (type: Space)
87    AxisInfo: 'z' (type: Space)
88
89It is also possible to attach additional information to the axistags, in particular the resolution of the axis, and a text comment. The resolution will be correctly adjusted when the image is resized::
90
91    >>> rgb.axistags['x'].resolution = 1.2  # in some unit of length
92    >>> rgb.axistags['y'].resolution = 1.4  # in some unit of length
93    >>> rgb.axistags['c'].description = 'fluorescence microscopy, DAPI and GFP staining'
94    >>> print(rgb.axistags)
95    AxisInfo: 'x' (type: Space, resolution=1.2)
96    AxisInfo: 'y' (type: Space, resolution=1.4)
97    AxisInfo: 'c' (type: Channels) fluorescence microscopy, DAPI and GFP staining
98
99    # interpolate the image to twice its original size
100    >>> rgb2 = vigra.sampling.resize(rgb, shape=(2*width-1, 2*height-1))
101    >>> print(rgb2.axistags)
102    AxisInfo: 'x' (type: Space, resolution=0.6)
103    AxisInfo: 'y' (type: Space, resolution=0.7)
104    AxisInfo: 'c' (type: Channels) fluorescence microscopy, DAPI and GFP staining
105
106When the array is transposed, the axistags are transposed accordingly. When axes are dropped from the array, the corresponding entries are dropped from the axistags property::
107
108    # transpose the volume into reverse axis order
109    >>> transposed_volume = volume.transpose()
110    >>> transposed_volume.shape
111    (3, 200, 300)
112    >>> transposed_volume.axistags
113    z y x
114
115    # get a view to the first slice (z == 0)
116    >>> first_slice = volume[..., 0]
117    >>> first_slice.shape
118    (300, 200)
119    >>> first_slice.axistags
120    x y
121
122    # get the maximum of each slice
123    >>> volume.max(axis=0).max(axis=0)
124    VigraArray(shape=(3,), axistags=z, dtype=float32, data=
125    [ 0.  0.  0.])
126
127    # likewise, but specify axes by their keys
128    >>> volume.max(axis='x').max(axis='y')
129    VigraArray(shape=(3,), axistags=z, dtype=float32, data=
130    [ 0.  0.  0.])
131
132The initial ordering of the axes is controlled by the argument ``order`` that can optionally be passed to the VigraArray constuctor or the factory functions. If ``order`` is not explicitly provided, it is determined by the static property :attr:`VigraArray.defaultOrder` (which yields 'V' order). The following orders are currently supported:
133
134.. _array-order-parameter:
135
136    'C' order:
137        Both strides and axes are arranged in descending order, as in a
138        plain numpy.ndarray. For example, axistags will be 'y x c' or
139        'z y x c'. array.flags['C_CONTIGUOUS'] will be true.
140
141    'F' order:
142        Both strides and axes are arranged in ascending order, i.e.
143        opposite to 'C' order. For example, axistags will be 'c x y'
144        or 'c x y z'. array.flags['F_CONTIGUOUS'] will be true.
145
146    'V' order:
147        VIGRA-order is an interleaved memory layout that simulates
148        vector-valued pixels or voxels: Channels will be the last axis
149        and have the smallest stride, whereas all other axes are arranged
150        in ascending order. For example, axistags will be 'x y c' or
151        'x y z c'.
152
153    'A' order:
154        Defaults to 'V' when a new array is created, and means
155        'preserve order' when an existing array is copied.
156
157The meaning of 'ascending' or 'descending' order is determined by two rules: the primary order is according to axis type (see :class:`vigra.AxisType`), where ``Channels < Space < Angle < Time < Frequency < Unknown``. The secondary order (between axes of the same type) is lexicographic, such that 'x' < 'y' < 'z'. Usage examples::
158
159    >>> rgbv = vigra.RGBImage((width, height), order='V')
160    >>> rgbv.shape
161    (300, 200, 3)
162    >>> rgbv.axistags
163    x y c
164
165    >>> rgbc = vigra.RGBImage((width, height), order='C')
166    >>> rgbc.shape
167    (200, 300, 3)
168    >>> rgbc.axistags
169    y x c
170
171    >>> rgbf = vigra.RGBImage((width, height), order='F')
172    >>> rgbf.shape
173    (3, 300, 200)
174    >>> rgbf.axistags
175    c x y
176
177Functions that reduce the array to a one-dimensional shape (``flatten()``, ``flat``, ``ravel()``, ``take()``) always transpose the array into 'C' order before flattening.
178
179Axistags are stored in a list-like class :class:`vigra.AxisTags`, whose individual entries are of type :class:`vigra.AxisInfo`. The simplest way to attach axistags to a plain numpy.ndarray (by creating a view of type VigraArray) is via the convenience function :func:`vigra.taggedView`.
180
181More On the Motivation and Use of Axistags
182------------------------------------------
183
184History of the problem
185^^^^^^^^^^^^^^^^^^^^^^
186
187A Fortran array declaration::
188
189    real f(20,10)
190
191is compiled such that the elements of the first index are consecutive in memory. In contrast, a C array declaration::
192
193    float c[20][10];
194
195places the elements of the last index consecutive in memory. The two possibilities are commonly referred to as "Fortran order" and "C order", but we will see that these terms are actually ambiguous because their meaning depends on what the array is used for.
196
197Arrays as Matrices
198^^^^^^^^^^^^^^^^^^
199
200When the array represents a matrix, users require the syntax to conform to the mathematical syntax conventions (in order to avoid bugs when typing formulas). In mathematics, m\ :sub:`ij` means that the first index i refers to rows, and the second index j refers to columns. Thus, Fortran's ``f(i, j)`` and C's ``c[i][j]`` have exactly the same meaning, but the memory layouts of the two matrices differ: Since in Fortran the first index changes quickest, this is referred to as the "column major" format (the elements of a column are consecutive in memory). In contrast, C uses the "row major" format (the elements of a row are consecutive in memory).
201
202In short: When the array is a matrix, the syntax is the same, but the memory layouts differ.
203
204Arrays as Images
205^^^^^^^^^^^^^^^^
206
207When the array represents an image, users require the memory layout to be the same as in the image files which store the data (in order to ensure fast I/O). All image formats (JPEG, TIFF, PNG, ...) follow the convention of analog television to scan an image left to right, then top to bottom. Consequently, the horizontal pixels are consecutive in memory, and therefore Fortran (where the first axis changes fastest) must use the syntax ``f(x, y)``, whereas C (where the last axis changes fastest) must use ``c[y][x]``.
208
209In short: When the array is an image, the memory layout is the same, but the syntax differs.
210
211Thus, we have four basic conventions: FM and CM for matrices, FI and CI for images. The meaning of the terms "Fortran order" and "C order" depends on whether we are talking about matrices (where they refer to FM and CM, i.e. a difference in memory layout) or images (where they refer to FI and CI, i.e. a difference in index order).
212
213Multi-Dimensional Arrays
214^^^^^^^^^^^^^^^^^^^^^^^^
215
216When we add more dimensions, the confusion increases, because there are no universally accepted memory and indexing conventions. For example, an RGB image can be stored in "interleaved format"::
217
218    RGB RGB RGB ...
219    RGB RGB RGB ...
220    :
221    :
222
223where the color values of each pixel are consecutive in memory, or in "banded format"::
224
225    R R R ...
226    R R R ...
227    :
228    G G G ...
229    G G G ...
230    :
231    B B B ...
232    B B B ...
233    :
234
235where we have a separate scalar image for each color. In Fortran, interleaved and banded images must be indexed as ``f(color, x, y)`` and ``f(x, y, color)`` respectively, whereas in C we must use ``c[y][x][color]`` or ``c[color][y][x]``.
236
237VIGRA and numpy
238^^^^^^^^^^^^^^^
239
240From the beginning, VIGRA adopted Fortran conventions, i.e. its default behavior is according to FM and FI (this is possible because VIGRA uses array classes, where the mapping from indices to memory is encapsulated in the appropriate way).
241
242In contrast, numpy adopted C conventions, i.e. its default behavior is CM and CI.
243
244In addition, both packages provide array views which keep the memory layout intact, but change the index order. Thus, VIGRA also supports the CI convention, and numpy also supports FI. Note that changing the index order is only allowed for images. Matrices always use the fixed index order dictated by mathematics where transpose(m) is a well-defined mathematical operation (which just happens to revert the index order). Therefore, the existence of array views does not imply that VIGRA supports CM or numpy supports FM.
245
246However, numpy's array constructor provides an argument 'order' which can take the values 'C' (default) and 'F' to construct arrays with C or Fortran memory order. By this mechanism, numpy also supports the FM convention (and thus all four basic possibilities).
247
248But here is the catch: When you get a numpy array view, you have no way to tell which convention it adheres to. It simply doesn't contain this information.
249
250The usual solution to this problem is to enforce a fixed axis order in the entire application, but this workaround breaks down when the application must simultaneously handle arrays with different meaning (e.g. sequences 'xyt' vs. volumes 'xyz' vs. multi-spectral images 'xyc') or when the application uses modules with conflicting requirements (e.g. numpy's 'yx' vs. PyQt's 'xy').
251
252Vigranumpy Axistags
253^^^^^^^^^^^^^^^^^^^
254
255This is precisely where axistags enter: They attach information to array views that allows the user to figure out which convention applies to a given view. Thus, the primary purpose of axistags is entirely passive - they just keep track of how users manipulate the axis order when creating new array views. The main use case of axistags is therefore to re-adjust the axis order whenever an algorithm has specific order requirements. Using axistags, one can easily ensure that arrays conform to the desired order at the beginning of every algorithm. Consider the following example: Let 'image' be a scalar 2D image with axistags. Then we can ask for the image's width and height independently of the current axis order::
256
257    width  = image.width    # this works for any axis order!
258    height = image.height
259
260Now suppose we want to execute a numpy algorithm which expects the [y, x] ordering. We simply transpose the array before calling the algorithm like this::
261
262    # adjust the axis order
263    numpy_image = image.transposeToNumpyOrder()
264
265    # execute the algorithm
266    for y in xrange(height):
267        for x in xrange(width):
268            numpy_image[y, x] = ...   # note the index order
269
270When we want to execute a VIGRA algorithm which expects the [x, y] ordering, we do::
271
272    # adjust the axis order
273    vigra_image = image.transposeToVigraOrder()
274
275    # execute the algorithm
276    for y in xrange(height):
277        for x in xrange(width):
278            vigra_image[x, y] = ...   # note the index order
279
280Notice that the order of the loops (the inner loop runs over x) is the same in both cases: To maximize cache locality and therefore speed, the inner loop should operate on consecutive memory cells. Since image memory order derives from file memory order (where the x-axis is consecutive), and array views can never change the memory order, this loop ordering is always preferable, regardless of the index order.
281
282Vigranumpy Conventions
283^^^^^^^^^^^^^^^^^^^^^^
284
285To handle axis meaning in a well-defined way, vigranumpy adopts the following conventions, which are designed such that The Right Thing (TM) should happen automatically, at least most of the time:
286
2871. When the array represents a matrix, no axistags are allowed because the index order has a fixed semantic meaning and must not be messed around with. In vigranumpy, this requirement is enforced by an assertion::
288
289    vigra_precondition( !matrix.axistags(), "matrix must not have axistags");
290
291   in the C++ gluecode functions. This applies, for example, to the feature matrices passed to a random forest and to unsupervised learning algorithms. If desired, we can introduce additional axistags for features and samples in the future because this is a common use case.
292
2932. When arrays represent image data with up to five dimensions, axistags should be used. To sort indices according to the requirements of the next algorithm to be executed, the appropriate convenience function should be called (many more convenience functions are documented in :py:class:`vigra.VigraArray`)::
294
295    numpy_array   = array.transposeToNumpyOrder()    # gives 'yx', 'zyx' etc.
296    vigra_array   = array.transposeToVigraOrder()    # gives 'xy', 'xyz' etc.
297    ilastik_array = array.view5D()                   # gives 'txyzc' (inserts singleton axes if necessary)
298    user_defined  = array.withAxes('y', 'x', 't')    # specify order explicitly (inserts singleton axes if necessary)
299
300   Algorithms with special order requirements can then check for the correct order in an assertion.
301
3023. The function ``vigra.taggedView()`` allows to attach axistags to an array very conveniently. For example, when you know from the context that the axes of a given array are to be interpreted as 'xyzt' in that order, you can make this knowledge explicit by calling::
303
304    tagged_array = vigra.taggedView(array, 'xyzt')
305
3064. When you call a vigranumpy function that executes a C++ VIGRA function, ``image.transposeToVigraOrder()`` will be invoked automatically on the input arrays, and the original axis order will be restored in the output arrays.
307
3085. When you call a vigranumpy function that is forwarded to a numpy function (in particular, a ufunc like ``+``, ``-``, ``sqrt`` etc.), ``image.transposeToNumpyOrder()`` will be invoked automatically on the input arrays, and the original axis order will be restored in the output arrays.
309
3106. When vigranumpy writes arrays to a file, it will always order the axes such that the memory order conforms to the established file conventions (e.g. values along the x-axis are consecutive). In particular, when you use ``vigra.impex.writeHDF5()`` to create HDF5 datasets, ``array.transposeToNumpyOrder()`` will be called before writing the data (this is a consequence of item 5, because ``writeHDF5()`` eventually forwards the actual work to h5py). In addition, the axistags (in numpy order) will be stored in a dataset attribute ``axistags``.
311
3127. When vigranumpy reads data from a file, it preserves the file's memory order and attaches the appropriate axistags. In case of images, the axis order follows from the usual file conventions. If you call ``vigra.impex.readHDF5()`` to read HDF5, the axistags will be read from the attribute ``axistags`` (if present). Upon return, the read functions automatically call ``array.transposeToVigraOrder()``, but this only changes the index order, not the memory layout. This latter convention was adopted to ensure that the default index order is the same in the Python and C++ versions of VIGRA.
313
3148. When you display an image via ``image.imshow()`` or ``image.show()``, the axes are re-ordered automatically such that the image is displayed upright (i.e. x goes to the right, y goes down). If you want to override this (i.e. want to enforce transposed display), you can remove the axistags by calling ``image.view(numpy.ndarray)``.
315
316Item 4. has two important consequences one should be aware of:
317
318* When a function needs parameters that depend on the axis order (such as the new shape in ``vigra.sampling.resize()`` or axis-dependent sigmas in ``vigra.filters.gaussianSmoothing()``), these parameters must be re-ordered on the C++ side in the same way as the axes. This is achieved by a call to ``NumpyArray::permuteLikewise()`` in the C++ gluecode functions.
319
320* When a vigranumpy function computes a gradient image, the gradient vector elements will always be stored in the order (dx, dy, dz), regardless of the array's original axis ordering. The same applies to any function producing vector-valued elements whose interpretation depends on the axis meaning (e.g. the Hessian matrix and the structure tensor). For example, the output of the Hessian is ordered as (dxx, dxy, dxz, dyy, dyz, dzz).
321
322Axistag Reference
323-----------------
324
325.. autoclass:: vigra.AxisType
326
327----------------
328
329.. autoclass:: vigra.AxisInfo
330    :members: key, typeFlags, resolution, description, isSpatial, isTemporal, isChannel, isFrequency, isAngular, isType, compatible
331
332----------------
333
334.. autoclass:: vigra.AxisTags
335    :members: index, channelIndex, innerNonchannelIndex, axisTypeCount, setChannelDescription, toJSON, fromJSON
336
337VigraArray Reference
338--------------------
339
340.. autoclass:: vigra.VigraArray
341    :show-inheritance:
342    :members: defaultAxistags, channelIndex, innerNonchannelIndex, channels, spatialDimensions, width, height, depth, duration, dropChannelAxis, insertChannelAxis, withAxes, view5D, asRGB, __getitem__, subarray, bindAxis, channelIter, sliceIter, spaceIter, timeIter, copyValues, swapaxes, transpose, T, transposeToOrder, transposeToDefaultOrder, transposeToNormalOrder, transposeToNumpyOrder, transposeToVigraOrder, permutationToOrder, permutationToNormalOrder, permutationFromNormalOrder, permutationToNumpyOrder, permutationFromNumpyOrder, permutationToVigraOrder, permutationFromVigraOrder, writeHDF5, writeImage, writeSlices, receiveSocket, sendSocket, qimage, show
343
344    .. attribute:: VigraArray.axistags
345
346      The :class:`~vigra.AxisTags` object of this array.
347
348    .. attribute:: VigraArray.defaultOrder
349
350      Get the default axis ordering, currently 'V' (:ref:`VIGRA order <array-order-parameter>`).
351
352-------------
353
354.. autofunction:: vigra.newaxis(axisinfo=vigra.AxisInfo())
355.. autofunction:: vigra.taggedView
356.. autofunction:: vigra.dropChannelAxis
357
358-------------
359
360.. _subsec-array-factories:
361
362.. autofunction:: vigra.Image
363.. autofunction:: vigra.ScalarImage
364.. autofunction:: vigra.Vector2Image
365.. autofunction:: vigra.Vector3Image
366.. autofunction:: vigra.Vector4Image
367.. autofunction:: vigra.RGBImage
368
369-------------
370
371.. autofunction:: vigra.Volume
372.. autofunction:: vigra.ScalarVolume
373.. autofunction:: vigra.Vector2Volume
374.. autofunction:: vigra.Vector3Volume
375.. autofunction:: vigra.Vector4Volume
376.. autofunction:: vigra.Vector6Volume
377.. autofunction:: vigra.RGBVolume
378
379
380Chunked Arrays and Data Bigger than RAM
381---------------------------------------
382
383Chunked arrays allow to allocate big data lazily, i.e. one chunk (rectangular block)
384at a time. Chunks which are currently not needed can be compressed or written
385to disk in order to free memory. This effectively allows VIGRA to work on data bigger
386than RAM.
387
388Classes
389^^^^^^^
390
391.. autoclass:: vigra.vigranumpycore.ChunkedArrayBase
392   :special-members:
393   :members:
394
395-------------
396
397.. autoclass:: vigra.vigranumpycore.ChunkedArrayHDF5Base
398   :show-inheritance:
399   :members:
400
401-------------
402
403.. autoclass:: vigra.Compression
404   :members:
405.. autoclass:: vigra.HDF5Mode
406   :members:
407
408Factory Functions
409^^^^^^^^^^^^^^^^^
410
411.. autofunction:: vigra.ChunkedArrayHDF5
412.. autofunction:: vigra.ChunkedArrayLazy
413.. autofunction:: vigra.ChunkedArrayCompressed
414.. autofunction:: vigra.ChunkedArrayTmpFile
415.. autofunction:: vigra.ChunkedArrayFull
416
417
418Import and Export Functions
419---------------------------
420
421The module vigra.impex defines read and write functions for image and volume data. Note
422that the contents of this module are automatically imported into the vigra module, so
423you may call 'vigra.readImage(...)' instead of 'vigra.impex.readImage(...)' etc.
424
425.. automodule:: vigra.impex
426   :members:
427
428
429.. _sec-dtype-coercion:
430
431Mathematical Functions and Type Coercion
432----------------------------------------
433
434vigranumpy supports all arithmetic and algebraic functions defined in
435`numpy.ufunc <http://docs.scipy.org/doc/numpy/reference/ufuncs.html#available-ufuncs>`_, but re-implements them in module `vigra.ufunc` to take full advantage of axistags.
436
437.. automodule:: vigra.ufunc
438
439
440Color and Intensity Manipulation
441--------------------------------
442
443The module vigra.colors provides functions to adjust image brightness and contrast,
444and to transform between different color spaces.
445See `Color Conversions <../vigra/group__ColorConversions.html>`_ in the C++ documentation
446for more information.
447
448.. automodule:: vigra.colors
449   :members:
450
451
452Filters
453-------
454
455The module vigra.filters provides operators that consider a window around each pixel, compute
456one or several numbers from the values in the window, and store the results in the
457corresponding pixel of the output image. This includes convolution, non-linear diffusion,
458morphological operators, feature detectors (such as the structure tensor) etc.
459
460.. automodule:: vigra.filters
461   :members:
462
463
464Sampling: Image Resizing and Image Pyramids
465-------------------------------------------
466
467The module vigra.sampling contains methods to change the number and/or location of
468the image sampling points, such as resizing, rotation, and interpolation.
469
470.. automodule:: vigra.sampling
471   :members:
472
473---------------------------------------------
474
475Spline image views implement an interpolated view for an image which can be accessed
476at real-valued coordinates (in contrast to the plain image, which can only be
477accessed at integer coordinates). Module vigra.sampling defines::
478
479    SplineImageView0
480    SplineImageView1
481    SplineImageView2
482    SplineImageView3
483    SplineImageView4
484    SplineImageView5
485
486The number denotes the spline interpolation order of the respective classes.
487Below, we describe SplineImageView3 in detail, but the other classes work
488analogously. See SplineImageView_ in the C++ documentation for more detailed information.
489
490.. autoclass:: vigra.sampling.SplineImageView3
491   :members:
492
493-------------
494
495.. autoclass:: vigra.sampling.ImagePyramid
496   :show-inheritance:
497   :members:
498
499
500Fourier Transforms
501------------------
502
503The module vigra.fourier contains functions for Fourier transforms, Cosine/Sine
504transforms, and Fourier-domain filters.
505
506.. automodule:: vigra.fourier
507   :members:
508
509
510Image Analysis
511--------------
512
513The module vigra.analysis contains segmentation algorithms (e.g. watershed), edge and
514corner detection, localization of maxima and minima etc.
515
516.. automodule:: vigra.analysis
517   :members:
518
519
520Geometry
521--------
522
523The module vigra.geometry contains geometric primitives (such as polygons) and related algorithms.
524
525.. automodule:: vigra.geometry
526   :members:
527
528
529Optimization
530------------
531
532The module vigra.optimization provides functions for constrained and unconstrained linear regression.
533
534.. automodule:: vigra.optimization
535   :members:
536
537
538Machine Learning
539----------------
540
541The module vigra.learning will eventually provide a wide range of machine learning
542tools. Right now, it only contains an implementation of the random forest classifier
543and probabilistic latent semantic analysis (pLSA) as an example for unsupervised learning.
544
545.. automodule:: vigra.learning
546   :members:
547
548.. autoclass:: vigra.learning.RandomForest
549   :members:
550
551For more information, refer to RandomForest_ in the C++ documentation.
552
553.. autoclass:: vigra.learning.RandomForestOld
554   :members:
555
556
557Noise Estimation and Normalization
558----------------------------------
559
560The module vigra.noise provides noise estimation and normalization according to a
561method proposed by Foerstner.
562
563.. automodule:: vigra.noise
564   :members:
565
566
567Histogram and Channel Representation
568------------------------------------
569
570The module vigra.histogram provides histograms and channel representation
571
572.. automodule:: vigra.histogram
573   :members:
574
575
576.. _sec-graph-algorithms:
577
578Graphs and Algorithms on Graphs
579-------------------------------
580
581The module vigra.graphs provides graphs and graph algorithms
582
583.. automodule:: vigra.graphs
584   :members:
585
586.. autoclass:: vigra.graphs.GridGraphUndirected2d
587   :members:
588
589.. autoclass:: vigra.graphs.GridGraphUndirected3d
590   :members:
591
592.. autoclass:: vigra.graphs.AdjacencyListGraph
593   :members:
594
595.. autoclass:: vigra.graphs.RegionAdjacencyGraph
596   :members:
597
598.. autoclass:: vigra.graphs.GridRegionAdjacencyGraph
599   :members:
600
601.. autoclass:: vigra.graphs.ShortestPathPathDijkstra
602   :members:
603
604
605Utilities
606----------------------------------
607
608The module vigra.utilities provides  utilities and tools
609like priority queues with changeable priorities
610
611.. automodule:: vigra.utilities
612   :members:
613
614
615.. _sec-own-modules:
616
617Writing Your Own C++ Modules
618----------------------------
619
620When you want to write your own vigranumpy extension modules, first make sure that you compile and link with the same versions of numpy and boost_python that your current vigranumpy installation uses. Otherwise, communication between new and existing modules will not work (and even crash). Then follow these steps:
621
6221. Create the main module source file. This file contains the module's 'init' function. Let's assume that the module will be called 'my_module', and the file is 'my_module.cxx'. A stub for 'my_module.cxx' typically looks like this::
623
624        // define PY_ARRAY_UNIQUE_SYMBOL (required by the numpy C-API)
625        #define PY_ARRAY_UNIQUE_SYMBOL my_module_PyArray_API
626
627        // include the vigranumpy C++ API
628        #include <Python.h>
629        #include <boost/python.hpp>
630        #include <vigra/numpy_array.hxx>
631        #include <vigra/numpy_array_converters.hxx>
632
633        ... // your includes
634
635        ... // implementation of your wrapper functions and classes
636
637        using namespace boost::python;
638
639        // the argument of the init macro must be the module name
640        BOOST_PYTHON_MODULE_INIT(my_module)
641        {
642            // initialize numpy and vigranumpy
643            vigra::import_vigranumpy();
644
645            // export a function
646            def("my_function", &my_function,
647                (arg("arg1"), arg("arg2"), ...),
648                "Documentation");
649
650            // export a class and its member functions
651            class_<MyClass>("MyClass",
652                "Documentation")
653                .def("foo", &MyClass::foo,
654                     (arg("arg1"), arg("arg2"), ...),
655                     "Documentation")
656            ;
657
658            ... // more module functionality (refer to boost_python documentation)
659        }
660
6612. When your module uses additional C++ source files, they should start with the following defines::
662
663        // this must define the same symbol as the main module file (numpy requirement)
664        #define PY_ARRAY_UNIQUE_SYMBOL my_module_PyArray_API
665        #define NO_IMPORT_ARRAY
666
6673. Implement your wrapper functions. Numpy ndarrays are passed to C++ via the wrapper classes NumpyArray_ and NumpyAnyArray_. You can influence the conversion from Python to C++ by using different instantiations of NumpyArray, as long as the Python array supports the axistags attribute (refer to :ref:`axis order definitions <array-order-parameter>` for the meaning of the term 'ascending order')::
668
669            // We add a 'using' declaration for brevity of our examples.
670            // In actual code, you should probably prefer explicit namespace qualification.
671        using namespace vigra;
672
673            // Accept any array type and return an arbitrary array type.
674            // Returning NumpyAnyArray is always safe, because at that point
675            // C++ no longer cares about the particular type of the array.
676        NumpyAnyArray foo(NumpyAnyArray array);
677
678            // Accept a 3-dimensional float32 array and transpose it
679            // into ascending axis order ('F' order).
680        void foo(NumpyArray<3, float> array);
681
682            // Accept a 2-dimensional float32 array with an arbitrary number of channels and
683            // transpose the axes into VIGRA ('V') order (channels are last, other axes ascending).
684            // Note that the NumpyArray dimension is 3 to account for the channel dimension.
685            // If the original numpy array has no channel axis, vigranumpy will automatically
686            // insert a singleton axis.
687        void foo(NumpyArray<3, Multiband<float> > array);
688
689            // Accept a 2-dimensional float32 array that has only a single channel
690            // (that is, 'array.channels == 1' must hold on the Python side).
691            // Non-channel axes are transposed into ascending order.
692            // Note that the NumpyArray dimension is now 2.
693        void foo(NumpyArray<2, Singleband<float> > array);
694
695            // Accept a float32 array that has 2 non-channel dimensions and
696            // exactly 3 channels (i.e. 'array.channels == 3' on the Python side).
697            // Non-channel axes are transposed into ascending order.
698            // Note that the NumpyArray dimension is again 2, but the pixel type is
699            // now a vector.
700            // The conversion will only succeed if the channel axis is unstrided on
701            // the Python side (that is, the following expression is True:
702            //      array.strides[array.channelIndex] == array.dtype.itemsize).
703        void foo(NumpyArray<2, TinyVector<float, 3> > array);
704        void foo(NumpyArray<2, RGBValue<float> > array);
705
706   Or course, these functions can also be templated.
707
708   When your functions return newly allocated arrays, it is usually desirable to transfer the input's axistags to the output (otherwise, vigranumpy will use :meth:`~vigra.VigraArray.defaultAxistags` as a fallback). There is a standard vigranumpy idiom for this task which assumes that the wrapped function has an optional parameter 'output' for a possibly pre-allocated output array. The axistags are then transferred by reshaping the output array with a ``taggedShape()`` (which is a combination of a shape and axistags)::
709
710        NumpyAnyArray
711        foo(NumpyArray<3, Multiband<float32> > input,
712            NumpyArray<3, Multiband<float32> > output = boost::python::object())
713        {
714            // Reshape only if the output array was not explicitly passed in.
715            // Otherwise, use the output array as is.
716            output.reshapeIfEmpty(input.taggedShape(),
717                      "error message when shape is unsuitable.");
718
719            ... // your algorithm
720        }
721
722   It is also possible to modify the tagged shape before it is applied to the output array::
723
724        input.taggedShape()
725             .resize(Shape2(new_width, new_height))
726             .setChannelCount(new_channel_count)
727             .setChannelDescription("a description")
728
729   The C++ code can be multi-threaded when you unlock Python's global interpreter lock. After unlocking, your wrapper code must not call any Python functions, so the unlock statement should go after ``output.reshapeIfEmpty()``::
730
731        NumpyAnyArray
732        foo(NumpyArray<3, Multiband<float32> > input,
733            NumpyArray<3, Multiband<float32> > output = boost::python::object())
734        {
735            output.reshapeIfEmpty(input.taggedShape(), "Message.");
736
737                // Allow parallelization from here on. The destructor of
738                // _pythread will automatically regain the global interpreter lock
739                // just before this function returns to Python.
740            PyAllowThreads _pythread;
741
742            ... // your algorithm
743        }
744
7454. Export your wrapped functions. ``boost::python::def`` is called in its usual way, with one simple extension: Since vigranumpy does not know which NumpyArray variants you are going to use, appropriate converter functions between Python and C++ must be registered on demand. You do this by enclosing your function pointer into a call to the 'registerConverters()' function::
746
747        // in the module's init function
748        def("my_function", vigra::registerConverters(&my_function),
749           (arg("arg1"), ...),
750           "Documentation");
751
752If you need more information, it is always a good idea to look at the source code of the existing vigranumpy modules.
753
754
755Indices and tables
756==================
757
758* :ref:`genindex`
759* :ref:`modindex`
760* :ref:`search`
761