
Slices(3) User Contributed Perl Documentation Slices(3)
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 twoway so you can get a unit matrix by
$a = zeroes(1000,1000);
$a>diagonal(0,1) ++;
which is usually fairly efficient. See PDL::Indexing and PDL::Tips for more examples.
These functions are usually twoway:
$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 easiertouse representation of it,
many things are much easier to accomplish, just like making the above unit matrix.
Slicing is so central to the PDL language that a special compiletime syntax has been
introduced to handle it compactly; see PDL::NiceSlice for details.
BUGS
For the moment, you can't slice the empty piddle. This should probably change: slices of
the empty piddle should probably return the empty piddle.
Many types of index errors are reported far from the indexing operation that caused them.
This is caused by the underlying architecture: slice() sets up a mapping between vari
ables, but that mapping isn't tested for correctness until it is used (potentially much
later).
FUNCTIONS
index
Signature: (a(n); int ind(); [oca] c())
"index" and "index2d" provide rudimentary index indirection.
$c = index($source,$ind);
$c = index2d($source2,$ind1,$ind2);
use the $ind variables as indices to look up values in $source. "index2d" uses separate
piddles for X and Y coordinates. For more general Ndimensional indexing, see PDL::Slices
or the PDL::NiceSlice syntax.
These functions are twoway, 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
Signature: (a(na,nb); int inda(); int indb(); [oca] c())
"index" and "index2d" provide rudimentary index indirection.
$c = index($source,$ind);
$c = index2d($source2,$ind1,$ind2);
use the $ind variables as indices to look up values in $source. "index2d" uses separate
piddles for X and Y coordinates. For more general Ndimensional indexing, see PDL::Slices
or the PDL::NiceSlice syntax.
These functions are twoway, i.e. after
$c = $a>index(pdl[0,5,8]);
$c .= pdl [0,2,4];
the changes in $c will flow back to $a.
indexND
Find selected elements in an ND piddle
$source = 10*xvals(10,10) + yvals(10,10);
$index = pdl([[2,3],[4,5]],[[6,7],[8,9]]);
print $source>indexND( $index );
[
[23 45]
[67 89]
]
IndexND collapses $index by lookup into $source. The 0th dimension of $index is treated
as coordinates in $source, and the return value has the same dimensions as the rest of
$index. The returned elements are looked up from $source. Dataflow works  propagated
assignment flows back into $source.
You can get out hyperplanes from $source, too, in the same way as with ordinary slicing:
use a lowerorder vector for the index, and the extra source dimensions are stuck on the
end of the output dimension list. Here's an example, using the same index PDL as above
but a higherdimensional source:
$source = 100*xvals(10,10,2)+10*yvals(10,10,2)+zvals(10,10,2);
$index = pdl([[2,3],[4,5]],[[6,7],[8,9]]);
print $source>indexND( $index );
[
[
[230 450]
[670 890]
]
[
[231 451]
[671 891]
]
]
WARNING: To save time, no boundary checking is done! Indices outside the boundaries of
the original array are handled, er, poorly  you can get anything from the wrong element
(wrapped) to a sliceoutofbounds error if you're out of bounds. indexBDb does boundary
checking.
The natural counterpart to indexND is whichND, which generates appropriate lists of coor
dinates for indexND. See also indexNDb, which handles boundary conditions gracefully, and
interpND, which handles floatingpoint index piddles.
indexNDb
$source = 10*xvals(10,10)+yvals(10,10);
$index = pdl([[1,3],[4,5]],[[6,7],[8,23]]);
$out = indexNDb($source, $index);
$out = indexNDb($source, $index, $method, $missing);
"indexNDb" collapses $index by lookup into $source, with boundary condition handling using
the given method (if present).
$method can be one of:
periodic
the original array is taken to describe an Ntorus.
extend
the indices are clipped to the correct dimension, effectively duplicating the values at
the boundaries out to infinity.
truncate
missing values get 0 or the missing value that you feed in (or BAD, eventually  but
BAD values aren't supported at present). Because ``truncate'' involves inserting val
ues that aren't necessarily present in the original array, it returns a copy of the
data rather than an ordinary slicebyreference, so you can't flow values back to the
original array.
forbid
missing values cause an "out of bounds" barf.
"indexNDb" is different than "indexND" only because it includes extra overhead for han
dling boundary values.
rld
Signature: (int a(n); b(n); [o]c(m))
Runlength decode a vector
Given a vector $a of the numbers of instances of values $b, runlength decode to $c.
rld($a,$b,$c=null);
rle
Signature: (c(n); int [o]a(n); [o]b(n))
Runlength 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 con
sidered.
rle($c,$a=null,$b=null);
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)
reorder
Reorders the dimensions of a PDL based on the supplied list.
Similar to the xchg method, this method reorders 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 6Dim 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 rearranged 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 3d 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 3D 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.
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 runtime changing of transformations i.e. changing the size of some
piddle at runtime.
However, the mechanism is not yet finalized and this is just a demonstration.
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 lastbutone to second elements of $a
The argument string is a commaseparated list of what to do for each dimension. The cur
rent 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),(=15:8),3:6(=1),4:6')" to express a multidimensional diagonal of $a.
Trivial outofbounds slicing is allowed: if you slice a source dimension that doesn't
exist, but only index the 0th element, then slice treats the source as if there were a
dummy dimension there. The following are all equivalent:
xvals(5)>dummy(1,1)>slice('(2),0') # Add dummy dim, then slice
xvals(5)>slice('(2),0') # Outofbounds slice adds dim.
xvals(5)>slice((2),0) # NiceSlice syntax
xvals(5)>((2))>dummy(0,1) # NiceSlice syntax
This is an error:
xvals(5)>slice('(2),1') # nontrivial outofbounds slice dies
Because slicing doesn't directly manipulate the source and destination pdl  it just sets
up a transformation between them  indexing errors often aren't reported until later.
This is either a bug or a feature, depending on whether you prefer errorreporting clarity
or speed of execution.
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
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).
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).
rotate
Signature: (x(n); int shift(); [oca]y(n))
Shift vector elements along with wrap. Flows data back&forth.
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
identvaff
Signature: (P(); C())
A vaffine identity transformation (includes thread_id copying).
Mainly for internal use.
unthread
Signature: (P(); C(); int atind)
All threaded dimensions are made real again.
See [TBD Doc] for details and examples.
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 con
tiguous 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 mem
ory efficient and slightly faster than dice
$slice = $data>dice([0,2,6],[2,1,6]); # Dicing a 2D 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 diceout (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 cer
tain 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. Contributions by Craig DeForest, deforest@boul
der.swri.edu. 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 copy
right notice should be included in the file.
perl v5.8.0 20030129 Slices(3) 
