PDL Tour

Introduction

Welcome to a short tour of PDL's capabilities. This tour shows some of the main selling points of PDL. However, because we want this script to run everywhere, some modules which require external modules for use are explicitly excluded, namely

[*]: this module has its separate demos in a subdirectory.

Note that your own scripts must start with "use PDL;" to work properly, so that you can simply say "perl script.pl" or you can just try some of the commands illustrated in the demos by just retyping them at the pdl command prompt.


Generation of PDLs

PDLs or "piddles" are N-dimensional data cubes. There are several ways of generating piddles:

We generate a zero filled 5x5 matrix:


pdl> $a = zeroes 5,5;
pdl> print $a;

[
 [0 0 0 0 0]
 [0 0 0 0 0]
 [0 0 0 0 0]
 [0 0 0 0 0]
 [0 0 0 0 0]
]

Now, don't think that the number of dimensions is limited to two:

pdl> $m = zeroes(3,2,2); # 3x2x2 cube
pdl> print $m;

[
 [
  [0 0 0]
  [0 0 0]
 ]
 [
  [0 0 0]
  [0 0 0]
 ]
]

Mathematical operations

Operators like increment work...

pdl> $a ++;
pdl> print $a;

[
 [1 1 1 1 1]
 [1 1 1 1 1]
 [1 1 1 1 1]
 [1 1 1 1 1]
 [1 1 1 1 1]
]

"xvals" and "yvals" (yes, there is also zvals...) give you piddles which give the coordinate value.

pdl> $b = xvals $a;
pdl> print $b;

[
 [0 1 2 3 4]
 [0 1 2 3 4]
 [0 1 2 3 4]
 [0 1 2 3 4]
 [0 1 2 3 4]
]

So you can do things like

pdl> $b = $a + 0.1 * xvals($a) + 0.01 * yvals($a);
pdl> print $b;

[
 [   1  1.1  1.2  1.3  1.4]
 [1.01 1.11 1.21 1.31 1.41]
 [1.02 1.12 1.22 1.32 1.42]
 [1.03 1.13 1.23 1.33 1.43]
 [1.04 1.14 1.24 1.34 1.44]
]

Arithmetic operations work:

pdl> $x = xvals(10) / 5;
pdl> print $x,"\n";
pdl> print ((sin $x),"\n");

[0 0.2 0.4 0.6 0.8 1 1.2 1.4 1.6 1.8]
[0 0.19866933 0.38941834 0.56464247 0.71735609 0.84147098 0.93203909 0.98544973  0.9995736 0.97384763]

Slices

You can also take slices:


pdl> print $b;
pdl> print $b->slice(":,2:3");  # rows 2 and 3

[
 [   1  1.1  1.2  1.3  1.4]
 [1.01 1.11 1.21 1.31 1.41]
 [1.02 1.12 1.22 1.32 1.42]
 [1.03 1.13 1.23 1.33 1.43]
 [1.04 1.14 1.24 1.34 1.44]
]

[
 [1.02 1.12 1.22 1.32 1.42]
 [1.03 1.13 1.23 1.33 1.43]
]

pdl> print $b->slice("2:3,:");  # or columns 2 and 3

[
 [ 1.2  1.3]
 [1.21 1.31]
 [1.22 1.32]
 [1.23 1.33]
 [1.24 1.34]
]

pdl> print $b;
pdl> print $b->diagonal(0,1),"\n"; # 0 and 1 are the dimensions

[
 [   1  1.1  1.2  1.3  1.4]
 [1.01 1.11 1.21 1.31 1.41]
 [1.02 1.12 1.22 1.32 1.42]
 [1.03 1.13 1.23 1.33 1.43]
 [1.04 1.14 1.24 1.34 1.44]
]
[1 1.11 1.22 1.33 1.44]

One of the really nifty features is that the slices are actually references back to the original piddle:

pdl> $diag = $b->diagonal(0,1);
pdl> print $b;
pdl> print $diag,"\n";
pdl> $diag+=100;
pdl> print "AFTER:\n";
pdl> print $diag,"\n";
pdl> print "Now, guess what \$b looks like?\n";

[
 [   1  1.1  1.2  1.3  1.4]
 [1.01 1.11 1.21 1.31 1.41]
 [1.02 1.12 1.22 1.32 1.42]
 [1.03 1.13 1.23 1.33 1.43]
 [1.04 1.14 1.24 1.34 1.44]
]
[1 1.11 1.22 1.33 1.44]
AFTER:
[101 101.11 101.22 101.33 101.44]
Now, guess what $b looks like?

pdl> # Yes, it has changed:
pdl> print $b;

[
 [   101    1.1    1.2    1.3    1.4]
 [  1.01 101.11   1.21   1.31   1.41]
 [  1.02   1.12 101.22   1.32   1.42]
 [  1.03   1.13   1.23 101.33   1.43]
 [  1.04   1.14   1.24   1.34 101.44]
]

Another example (we only modify elements 0,2 and 4 of each row):


pdl> $t = $b->slice("0:4:2"); $t += 50;
pdl> print $b;

[
 [   151    1.1   51.2    1.3   51.4]
 [ 51.01 101.11  51.21   1.31  51.41]
 [ 51.02   1.12 151.22   1.32  51.42]
 [ 51.03   1.13  51.23 101.33  51.43]
 [ 51.04   1.14  51.24   1.34 151.44]
]

There are lots of useful functions in e.g. PDL::Primitive and PDL::Slices - we can't show you all but here are some examples:


pdl> print $b;
pdl> print $b->sum, "\n";
pdl> print $b->sumover,"\n"; # Only over first dim.

[
 [   151    1.1   51.2    1.3   51.4]
 [ 51.01 101.11  51.21   1.31  51.41]
 [ 51.02   1.12 151.22   1.32  51.42]
 [ 51.03   1.13  51.23 101.33  51.43]
 [ 51.04   1.14  51.24   1.34 151.44]
]
1280.5
[256 256.05 256.1 256.15 256.2]

pdl> print $b->xchg(0,1);
pdl> print $b->minimum,"\n"; # over first dim.
pdl> print $b->min,"\n";

[
 [   151  51.01  51.02  51.03  51.04]
 [   1.1 101.11   1.12   1.13   1.14]
 [  51.2  51.21 151.22  51.23  51.24]
 [   1.3   1.31   1.32 101.33   1.34]
 [  51.4  51.41  51.42  51.43 151.44]
]
[1.1 1.31 1.12 1.13 1.14]
1.1

pdl> print $b->random;

[
 [ 0.51385498  0.17572021  0.30862427  0.53451538  0.94760132]
 [ 0.17172241  0.70220947  0.22640991  0.49475098  0.12469482]
 [0.083892822  0.38961792  0.27722168  0.36804199  0.98342896]
 [ 0.53536987  0.76565552  0.64645386  0.76712036   0.7802124]
 [ 0.82293701   0.1519165  0.62545776  0.31466675  0.34689331]
]

Manipulation of parts of piddles

Here are some more advanced tricks for selecting parts of 1-D vectors:


pdl> $a = (xvals 12)/3;
pdl> $i = which(sin($a)> 0.5);   # Indices of those sines> 0.5
pdl> print $a,"\n";
pdl> print $i,"\n";
pdl> print $a->index($i),"\n";
pdl> # and we can have the effect of the last command in one
pdl> # go using 'where' instead of 'which' and 'index' as in
pdl> print $a->where(sin($a)> 0.5),"\n";
pdl> # and finally take the sin of these elements
pdl> # (to show that these are indeed the correct ones)
pdl> print sin($a->index($i)),"\n";

[0 0.33333333 0.66666667 1  1.3333333  1.6666667 2  2.3333333  2.6666667 3  3.3333333  3.6666667]
[2 3 4 5 6 7]
[0.66666667 1  1.3333333  1.6666667 2  2.3333333]
[0.66666667 1  1.3333333  1.6666667 2  2.3333333]
[ 0.6183698 0.84147098  0.9719379 0.99540796 0.90929743 0.72308588]