NAME

PDL::Slices -- Stupid index tricks


SYNOPSIS

  use PDL;
  $a = ones(3,3);
  $b = $a->slice('-1:0,(1)');
  $c = $a->dummy(2);


DESCRIPTION

This package provides many of the powerful PerlDL core index manipulation routines. These routines are usually two-way so you can get a unit matrix by

 $a = zeroes(1000,1000);
 $a->diagonal(0,1) ++;

which is usually fairly efficient. See the PDL::Indexing manpage and the PDL::Tips manpage for more examples.

These functions are usually two-way:

 $b = $a->slice("1:3");
 $b += 5;               # $a is changed!

If you want to force a copy and no ``flow'' backwards, you need

 $b = $a->slice("1:3")->copy;
 $b += 5;               # $a is not changed.

alternatively, you can use

 $b = $a->slice("1:3")->sever;

which does not copy the struct but beware that after

 $b = $a->slice("1:3");
 $c = $b->sever;

the variables $b and $c point to the same object but with ->copy they do not.

The fact that there is this kind of flow makes PDL a very powerful language in many ways: since you can alter the original data by altering some easier-to-use representation of it, many things are much easier to accomplish, just like making the above unit matrix.


FUNCTIONS

index

  Signature: (a(n); int ind(); [oca] c())

These functions provide rudimentary index indirection.

 $c = a(ind());
 $c = a(ind1(),ind2());

It would be useful to have a more complete function for this at some point, or at least a perl wrapper, that allows

 $c = $a->islice("1:2",$ind1,"3:4",$ind2);

with many dimensions.

This function is two-way, i.e. after

 $c = $a->index(pdl[0,5,8]);
 $c .= pdl [0,2,4];

the changes in $c will flow back to $a.

index barfs if any of the index values are bad.

index2d

  Signature: (a(na,nb); int inda(); int indb(); [oca] c())

These functions provide rudimentary index indirection.

 $c = a(ind());
 $c = a(ind1(),ind2());

It would be useful to have a more complete function for this at some point, or at least a perl wrapper, that allows

 $c = $a->islice("1:2",$ind1,"3:4",$ind2);

with many dimensions.

This function is two-way, i.e. after

 $c = $a->index(pdl[0,5,8]);
 $c .= pdl [0,2,4];

the changes in $c will flow back to $a.

index2d barfs if either of the index values are bad.

rld

  Signature: (int a(n); b(n); [o]c(m))

Run-length decode a vector

Given a vector $a of the numbers of instances of values $b, run-length decode to $c.

 rld($a,$b,$c=null);

rld does not process bad values. It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.

rle

  Signature: (c(n); int [o]a(n); [o]b(n))

Run-length encode a vector

Given vector $c, generate a vector $a with the number of each element, and a vector $b of the unique values. Only the elements up to the first instance of `0' in $a should be considered.

 rle($c,$a=null,$b=null);

rle does not process bad values. It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.

xchg

  Signature: (P(); C(); int n1; int n2)

exchange two dimensions

Negative dimension indices count from the end.

The command

 $b = $a->xchg(2,3);

creates $b to be like $a except that the dimensions 2 and 3 are exchanged with each other i.e.

 $b->at(5,3,2,8) == $a->at(5,3,8,2)

xchg does not process bad values. It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.

reorder

Re-orders the dimensions of a PDL based on the supplied list.

Similar to the xchg method, this method re-orders the dimensions of a PDL. While the xchg method swaps the position of two dimensions, the reorder method can change the positions of many dimensions at once.

 # Completely reverse the dimension order of a 6-Dim array.
 $reOrderedPDL = $pdl->reorder(5,4,3,2,1,0);

The argument to reorder is an array representing where the current dimensions should go in the new array. In the above usage, the argument to reorder (5,4,3,2,1,0) indicates that the old dimensions ($pdl's dims) should be re-arranged to make the new pdl ($reOrderPDL) according to the following:

   Old Position   New Position
   ------------   ------------
   5              0
   4              1
   3              2
   2              3
   1              4
   0              5

Example:

 perldl> $a = sequence(5,3,2);    # Create a 3-d Array
 perldl> p $a
 [
  [
   [ 0  1  2  3  4]
   [ 5  6  7  8  9]
   [10 11 12 13 14]
  ]
  [
   [15 16 17 18 19]
   [20 21 22 23 24]
   [25 26 27 28 29]
  ]
 ]
 perldl> p $a->reorder(2,1,0); # Reverse the order of the 3-D PDL
 [
  [
   [ 0 15]
   [ 5 20]
   [10 25]
  ]
  [
   [ 1 16]
   [ 6 21]
   [11 26]
  ]
  [
   [ 2 17]
   [ 7 22]
   [12 27]
  ]
  [
   [ 3 18]
   [ 8 23]
   [13 28]
  ]
  [
   [ 4 19]
   [ 9 24]
   [14 29]
  ]
 ]

The above is a simple example that could be duplicated by calling $a->xchg(0,2), but it demonstrates the basic functionality of reorder.

As this is an index function, any modifications to the result PDL will change the parent.

mv

  Signature: (P(); C(); int n1; int n2)

move a dimension to another position

The command

 $b = $a->mv(4,1);

creates $b to be like $a except that the dimension 4 is moved to the place 1, so:

 $b->at(1,2,3,4,5,6) == $a->at(1,5,2,3,4,6);

The other dimensions are moved accordingly. Negative dimension indices count from the end.

mv does not process bad values. It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.

oneslice

  Signature: (P(); C(); int nth; int from; int step; int nsteps)

experimental function - not for public use

 $a = oneslice();

This is not for public use currently. See the source if you have to. This function can be used to accomplish run-time changing of transformations i.e. changing the size of some piddle at run-time.

However, the mechanism is not yet finalized and this is just a demonstration.

oneslice does not process bad values. It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.

slice

  Signature: (P(); C(); char* str)

Returns a rectangular slice of the original piddle

 $a->slice('1:3');  #  return the second to fourth elements of $a
 $a->slice('3:1');  #  reverse the above
 $a->slice('-2:1'); #  return last-but-one to second elements of $a

The argument string is a comma-separated list of what to do for each dimension. The current formats include the following, where a, b and c are integers and can take legal array index values (including -1 etc):

:
takes the whole dimension intact.

''
(nothing) is a synonym for ``:'' (This means that $a->slice(':,3') is equal to $a->slice(',3')).

a
slices only this value out of the corresponding dimension.

(a)
means the same as ``a'' by itself except that the resulting dimension of length one is deleted (so if $a has dims (3,4,5) then $a->slice(':,(2),:') has dimensions (3,5) whereas $a->slice(':,2,:') has dimensions (3,1,5)).

a:b
slices the range a to b inclusive out of the dimension.

a:b:c
slices the range a to b, with step c (i.e. 3:7:2 gives the indices (3,5,7)). This may be confusing to Matlab users but several other packages already use this syntax.

'*'
inserts an extra dimension of width 1 and

'*a'
inserts an extra (dummy) dimension of width a.

An extension is planned for a later stage allowing $a->slice('(=1),(=1|5:8),3:6(=1),4:6') to express a multidimensional diagonal of $a.

slice does not process bad values. It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.

using

Returns array of column numbers requested

 line $pdl->using(1,2);

Plot, as a line, column 1 of $pdl vs. column 2

 perldl> $pdl = rcols("file");
 perldl> line $pdl->using(1,2);

diagonalI

  Signature: (P(); C(); SV *list)

Returns the multidimensional diagonal over the specified dimensions.

The diagonal is placed at the first (by number) dimension that is diagonalized. The other diagonalized dimensions are removed. So if $a has dimensions (5,3,5,4,6,5) then after

 $b = $a->diagonal(0,2,5);

the piddle $b has dimensions (5,3,4,6) and $b->at(2,1,0,1) refers to $a->at(2,1,2,0,1,2).

NOTE: diagonal doesn't handle threadids correctly. XXX FIX

diagonalI does not process bad values. It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.

lags

  Signature: (P(); C(); int nthdim; int step; int n)

Returns a piddle of lags to parent.

Usage:

  $lags = $a->lags($nthdim,$step,$nlags);

I.e. if $a contains

 [0,1,2,3,4,5,6,7]

then

 $b = $a->lags(0,2,2);

is a (5,2) matrix

 [2,3,4,5,6,7]
 [0,1,2,3,4,5]

This order of returned indices is kept because the function is called ``lags'' i.e. the nth lag is n steps behind the original.

$step and $nlags must be positive. $nthdim can be negative and will then be counted from the last dim backwards in the usual way (-1 = last dim).

lags does not process bad values. It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.

splitdim

  Signature: (P(); C(); int nthdim; int nsp)

Splits a dimension in the parent piddle (opposite of clump)

After

 $b = $a->splitdim(2,3);

the expression

 $b->at(6,4,x,y,3,6) == $a->at(6,4,x+3*y)

is always true (x has to be less than 3).

splitdim does not process bad values. It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.

rotate

  Signature: (x(n); int shift(); [oca]y(n))

Shift vector elements along with wrap. Flows data back&forth.

rotate does not process bad values. It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.

threadI

  Signature: (P(); C(); int id; SV *list)

internal

Put some dimensions to a threadid.

 $b = $a->threadI(0,1,5); # thread over dims 1,5 in id 1

threadI does not process bad values. It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.

identvaff

  Signature: (P(); C())

A vaffine identity transformation (includes thread_id copying).

Mainly for internal use.

identvaff does not process bad values. It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.

unthread

  Signature: (P(); C(); int atind)

All threaded dimensions are made real again.

See [TBD Doc] for details and examples.

unthread does not process bad values. It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.

dice

Dice rows/columns/planes out of a PDL using indexes for each dimension.

This function can be used to extract irregular subsets along many dimension of a PDL, e.g. only certain rows in an image, or planes in a cube. This can of course be done with the usual dimension tricks but this saves having to figure it out each time!

This method is similar in functionality to the slice method, but slice requires that contiguous ranges or ranges with constant offset be extracted. ( i.e. slice requires ranges of the form 1,2,3,4,5 or 2,4,6,8,10). Because of this restriction, slice is more memory efficient and slightly faster than dice

 $slice = $data->dice([0,2,6],[2,1,6]); # Dicing a 2-D array

The arguments to dice are arrays (or 1D PDLs) for each dimension in the PDL. These arrays are used as indexes to which rows/columns/cubes,etc to dice-out (or extract) from the $data PDL.

Use X to select all indices along a given dimension (compare also mslice). As usual (in slicing methods) trailing dimensions can be omitted implying X'es for those.

 perldl> $a = sequence(10,4)
 perldl> p $a
 [
  [ 0  1  2  3  4  5  6  7  8  9]
  [10 11 12 13 14 15 16 17 18 19]
  [20 21 22 23 24 25 26 27 28 29]
  [30 31 32 33 34 35 36 37 38 39]
 ]
 perldl> p $a->dice([1,2],[0,3]) # Select columns 1,2 and rows 0,3
 [
  [ 1  2]
  [31 32]
 ]
 perldl> p $a->dice(X,[0,3])
 [
  [ 0  1  2  3  4  5  6  7  8  9]
  [30 31 32 33 34 35 36 37 38 39]
 ]
 perldl> p $a->dice([0,2,5])
 [
  [ 0  2  5]
  [10 12 15]
  [20 22 25]
  [30 32 35]
 ]

As this is an index function, any modifications to the slice change the parent (use the .= operator).

dice_axis

Dice rows/columns/planes from a single PDL axis (dimension) using index along a specified axis

This function can be used to extract irregular subsets along any dimension, e.g. only certain rows in an image, or planes in a cube. This can of course be done with the usual dimension tricks but this saves having to figure it out each time!

 $slice = $data->dice_axis($axis,$index);
 perldl> $a = sequence(10,4)
 perldl> $idx = pdl(1,2)
 perldl> p $a->dice_axis(0,$idx) # Select columns
 [
  [ 1  2]
  [11 12]
  [21 22]
  [31 32]
 ]
 perldl> $t = $a->dice_axis(1,$idx) # Select rows
 perldl> $t.=0
 perldl> p $a
 [
  [ 0  1  2  3  4  5  6  7  8  9]
  [ 0  0  0  0  0  0  0  0  0  0]
  [ 0  0  0  0  0  0  0  0  0  0]
  [30 31 32 33 34 35 36 37 38 39]
 ]

The trick to using this is that the index selects elements along the dimensions specified, so if you have a 2D image axis=0 will select certain X values - i.e. extract columns

As this is an index function, any modifications to the slice change the parent.


AUTHOR

Copyright (C) 1997 Tuomas J. Lukka. All rights reserved. There is no warranty. You are allowed to redistribute this software / documentation under certain conditions. For details, see the file COPYING in the PDL distribution. If this file is separated from the PDL distribution, the copyright notice should be included in the file.