PDL::QuickStart (1)
Leading comments
Automatically generated by Pod::Man 4.09 (Pod::Simple 3.35) Standard preamble: ========================================================================
NAME
PDL::QuickStart - Quick introduction to PDL features.SYNOPSIS
A brief summary of the mainDESCRIPTION
Introduction
Perl is an extremely good and versatile scripting language, well suited to beginners and allows rapid prototyping. However until recently it did not support data structures which allowed it to do fast number crunching.However with the development of Perl v5, Perl acquired 'Objects'. To put it simply users can define their own special data types, and write custom routines to manipulate them either in low level languages (C and Fortran) or in Perl itself.
This has been fully exploited by the PerlDL developers. The '
As well as the
Help
pdl> help help $ pdldoc
pdl> foreach ( map{"$_/PDL/HtmlDocs"}@INC ) { p "$_\n" if -d $_ }
Perl Datatypes and how PDL extends them
The fundamental Perl data structures are scalar variables, e.g. $x,
which can hold numbers or strings, lists or arrays of scalars, e.g. @x,
and associative arrays/hashes of scalars, e.g. %x.
Perl v5 introduces to Perl data structures and objects. A simple scalar variable $x now be a user-defined data type or full blown object (it actually holds a reference (a smart ``pointer'') to this but that is not relevant for ordinary use of perlDL)
The fundamental idea behind perlDL is to allow $x to hold a whole 1D spectrum, or a 2D image, a 3D data cube, and so on up to large N-dimensional data sets. These can be manipulated all at once, e.g. "$a = $b + 2" does a vector operation on each value in the spectrum/image/etc.
You may well ask: "Why not just store a spectrum as a simple Perl @x style list with each pixel being a list item?" The two key answers to this are memory and speed. Because we know our spectrum consists of pure numbers we can compactly store them in a single block of memory corresponding to a C style numeric array. This takes up a
I find when using perlDL it is most useful to think of standard Perl @x variables as ``lists'' of generic ``things'' and
perlDL variables support a range of data types - arrays can be bytes, short integers (signed or unsigned), long integers, floats or double precision floats.
Usage
PerlDL is loaded into your Perl script using this command:
use PDL; # in Perl scripts: use the standard perlDL modules
There are also a lot of extension modules, e.g. PDL::Graphics::TriD. Most of these (but not all as sometimes it is not appropriate) follow a standard convention. If you say:
use PDL::Graphics::TriD;
You import everything in a standard list from the module. Sometimes you might want to import nothing (e.g. if you want to use
use PDL::Graphics::TriD qw();
And the empty "qw()" quotes are recognised as meaning 'nothing'. You can also specify a list of functions to import in the normal Perl way.
There is also an interactive shell, "perldl" or "pdl2", see perldl or pdl2 for details.
To create a new PDL variable
Here are some ways of creating a
$a = pdl [1..10]; # 1D array $a = pdl (1,2,3,4); # Ditto $a = pdl '[1 2 3 4]'; # Ditto $b = pdl [[1,2,3],[4,5,6]]; # 2D 3x2 array $b = pdl '[1 2 3; 4 5 6]'; # Ditto $b = pdl q[1,2,3; 4,5,6]; # Ditto $b = pdl <<NEWPDL # Ditto [1 2 3] [4 5 6] NEWPDL $c = pdl q[1 -2]; # 2-element piddle containing 1 and -2 $c = pdl q[1 - 2]; # 2-element piddle containing 1 and -2 $b = pdl 42 # 0-dimensional scalar $c = pdl $a; # Make a new copy $d = byte [1..10]; # See "Type conversion" $e = zeroes(3,2,4); # 3x2x4 zero-filled array $c = rfits $file; # Read FITS file @x = ( pdl(42), zeroes(3,2,4), rfits($file) ); # Is a LIST of PDL variables!
The pdl() function is used to initialise a
In addition all
(also see ``Type Conversion'' and ``Input/Output'' sections below)
Arithmetic (and boolean expressions)
$a = $b + 2; $a++; $a = $b / $c; # Etc. $c=sqrt($a); $d = log10($b+100); # Etc $e = $a>42; # Vector conditional $e = 42*($a>42) + $a*($a<=42); # Cap top $b = $a->log10 unless any ($a <= 0); # avoid floating point error $a = $a / ( max($a) - min($a) ); $f = where($a, $a > 10); # where returns a piddle of elements for # which the condition is true print $a; # $a in string context prints it in a N-dimensional format
(and other Perl operators/functions)
When using piddles in conditional expressions (i.e. "if", "unless" and "while" constructs) only piddles with exactly one element are allowed, e.g.
$a = pdl (1,0,0,1); print "is set" if $a->index(2);
Note that the boolean operators return in general multi-element piddles. Therefore, the following will raise an error
print "is ok" if $a > 3;
since "$a > 3" is a piddle with 4 elements. Rather use all or any to test if all or any of the elements fulfill the condition:
print "some are > 3" if any $a>3; print "can't take logarithm" unless all $a>0;
There are also many predefined functions, which are described on other man pages. Check PDL::Index.
Matrix functions
'x' is hijacked as the matrix multiplication operator. e.g. "$c = $a x $b";perlDL is row-major not column major so this is actually "c(i,j) = sum_k a(k,j) b(i,k)" - but when matrices are printed the results will look right. Just remember the indices are reversed. e.g.:
$a = [ $b = [ [ 1 2 3 0] [1 1] [ 1 -1 2 7] [0 2] [ 1 0 0 1] [0 2] ] [1 1] ] gives $c = [ [ 1 11] [ 8 10] [ 2 2] ]
Note: transpose() does what it says and is a convenient way to turn row vectors into column vectors.
How to write a simple function
sub dotproduct { my ($a,$b) = @_; return sum($a*$b) ; } 1;
If put in file dotproduct.pdl would be autoloaded if you are using PDL::AutoLoader (see below).
Of course, this function is already available as the inner function, see PDL::Primitive.
Type Conversion
Default for pdl() is double. Conversions are:
$a = float($b); $c = long($d); # "long" is generally a 4 byte int $d = byte($a);
Also double(), short(), ushort(), indx().
NOTE: The indx() routine is a special integer type that is the correct size for a PDL index value (dimension size, index, or offest) which can be either a 32bit (long) or 64bit (longlong) quantity depending on whether the perl is built with 32bit or 64bit support.
These routines also automatically convert Perl lists to allow the convenient shorthand:
$a = byte [[1..10],[1..10]]; # Create 2D byte array $a = float [1..1000]; # Create 1D float array
etc.
Printing
Automatically expands array in N-dimensional format:
print $a; $b = "Answer is = $a ";
Sections
Following the usual convention coordinate (0,0) is displayed at the bottom left when displaying an image. It appears at the top left when using ""print $a"" etc.
Simple sectioning uses a syntax extension to Perl, PDL::NiceSlice, that allows you to specify subranges via a null-method modifier to a
$b = $a->($x1:$x2,$y1:$y2,($z1)); # Take subsection
Here, $a is a 3-dimensional variable, and $b gets a planar cutout that is defined by the limits $x1, $x2, $y1, $y2, at the location $z1. The parenthesis around $z1 cause the trivial index to be omitted --- otherwise $b would be three-dimensional with a third dimension of order 1.
You can put
# Set part of $bigimage to values from $smallimage $bigimage->($xa:$xb,$ya:$yb) .= $smallimage;
Some other miscellany:
$c = nelem($a); # Number of pixels $val = at($object, $x,$y,$z...) # Pixel value at position, as a Perl scalar $val = $object->at($x,$y,$z...) # equivalent (method syntax OK) $b = xvals($a); # Fill array with X-coord values (also yvals(), zvals(), # axisvals($x,$axis) and rvals() for radial distance # from centre).
Input/Output
The "PDL::IO" modules implement several useful- PDL::IO::Misc
-
Ascii, FITSandFIGARO/NDF IOroutines.
- PDL::IO::FastRaw
-
Using the raw data types of your machine, an unportable but blindingly
fast IOformat. Also supports memory mapping to conserve memory as well as get more speed.
- PDL::IO::FlexRaw
- General raw data formats. Like FastRaw, only better.
- PDL::IO::Browser
- A Curses browser for arrays.
- PDL::IO::Pnm
- Portaple bitmap and pixmap support.
- PDL::IO::Pic
-
Using the previous module and netpbm, makes it possible to easily
write GIF,jpeg and whatever with simple commands.
Graphics
The philosophy behind perlDL is to make it work with a variety of existing graphics libraries since no single package will satisfy all needs and all people and this allows one to work with packages one already knows and likes. Obviously there will be some overlaps in functionality and some lack of consistency and uniformity. However this allows- PDL::Graphics::PGPLOT
-
PGPLOTprovides a simple library for line graphics and image display.
There is an easy interface to this in the internal module PDL::Graphics::PGPLOT, which calls routines in the separately available
PGPLOTtop-level module. - PDL::Graphics::PLplot
-
PLplot provides a simple library for creating graphics with multiple
output drivers, including a direct-to-piddle driver.
This module provides both high-level and low-level functionality built on PLplot. The low-level commands are pretty much direct bindings to PLplot's C interface. Read more at PDL::Graphics::PLplot.
- PDL::Graphics::IIS
-
Many astronomers like to use SAOimage and Ximtool (or there
derivations/clones). These are useful free widgets for inspection and
visualisation of images. (They are not provided with perlDL but can
easily be obtained from their official sites off the Net.)
The PDL::Graphics::IIS package provides allows one to display images in these (``
IIS''is the name of an ancient item of image display hardware whose protocols these tools conform to.) - PDL::Graphics::TriD
-
See PDL::Graphics::TriD, this is a collection
of 3D routines for OpenGL and (soon) VRMLand other 3D formats which allow 3D point, line, and surface plots fromPDL.
Autoloading
See PDL::AutoLoader. This allows one to autoload functions on demand, in a way perhaps familiar to users of MatLab.One can also write
PDL shells
The Perl script "pdl2" (or "perldl") provides a simple command line interface
to e.g.:
% perldl perlDL shell v1.354 PDL comes with ABSOLUTELY NO WARRANTY. For details, see the file 'COPYING' in the PDL distribution. This is free software and you are welcome to redistribute it under certain conditions, see the same file for details. ReadLines, NiceSlice, MultiLines enabled Reading PDL/default.perldlrc... Found docs database /home/pdl/dev/lib/perl5/site_perl/PDL/pdldoc.db Type 'help' for online help Type 'demo' for online demos Loaded PDL v2.4.9_003 (supports bad values) pdl> $x = rfits 'm51.fits' Reading IMAGE data... BITPIX = 32 size = 147456 pixels Reading 589824 bytes BSCALE = && BZERO = pdl> use PDL::Graphics::PGPLOT; pdl> imag $x Displaying 384 x 384 image from 40 to 761, using 84 colors (16-99)...
You can also run it from the Perl debugger ("perl -MPDL -d -e 1") if you want.
Miscellaneous shell features:
- p
-
The shell aliases "p" to be a convenient short form of "print", e.g.
pdl> p ones 5,3 [ [1 1 1 1 1] [1 1 1 1 1] [1 1 1 1 1] ]
- Initialization
-
The files "~/.perldlrc" and "local.perldlrc" (in the current
directory) are sourced if found. This allows the user to have global
and local PDLcode for startup.
- Help
-
Type 'help'! One can search the PDLdocumentation, and look up documentation on any function.
- Escape
- Any line starting with the "#" character is treated as a shell escape. This character is configurable by setting the Perl variable $PERLDL_ESCAPE. This could, for example, be set in "~/.perldlrc".
Overload operators
The following builtin Perl operators and functions have been overloaded to work on
+ - * / > < >= <= << >> & | ^ == != <=> ** % ! ~ sin log abs atan2 sqrt cos exp
[All the unary functions (sin etc.) may be used with inplace() - see ``Memory'' below.]
Object-Orientation and perlDL
By using overloading one can make mathematical operators do whatever you please, and
Memory usage and references
Messing around with really huge data arrays may require some care. perlDL provides many facilities to let you perform operations on big arrays without generating extra copies though this does require a bit more thought and care from the programmer.
- Simple arithmetic
-
If $a is a big image (e.g. occupying 10MB) then the command
$a = $a + 1;
eats up another 10MB of memory. This is because the expression "$a+1" creates a temporary copy of $a to hold the result, then $a is assigned a reference to that. After this, the original $a is destroyed so there is no permanent memory waste. But on a small machine, the growth in the memory footprint can be considerable. It is obviously done this way so "$c=$a+1" works as expected.
Also if one says:
$b = $a; # $b and $a now point to same data $a = $a + 1;
Then $b and $a end up being different, as one naively expects, because a new reference is created and $a is assigned to it.
However if $a was a huge memory hog (e.g. a 3D volume) creating a copy of it may not be a good thing. One can avoid this memory overhead in the above example by saying:
$a++;
The operations "++,+=,--,-=", etc. all call a special ``in-place'' version of the arithmetic subroutine. This means no more memory is needed - the downside of this is that if "$b=$a" then $b is also incremented. To force a copy explicitly:
$b = pdl $a; # Real copy
or, alternatively, perhaps better style:
$b = $a->copy;
- Functions
-
Most functions, e.g. "log()", return a result which is a transformation
of their argument. This makes for good programming practice. However many
operations can be done ``in-place'' and this may be required when large
arrays are in use and memory is at a premium. For these circumstances
the operator inplace()
is provided which prevents the extra copy and
allows the argument to be modified. e.g.:
$x = log($array); # $array unaffected log( inplace($bigarray) ); # $bigarray changed in situ
WARNINGS:-
- 1.
- The usual caveats about duplicate references apply.
- 2.
- Obviously when used with some functions which can not be applied in situ (e.g. "convolve()") unexpected effects may occur! We try to indicate "inplace()"-safe functions in the documentation.
- 3.
- Type conversions, such as"float()", may cause hidden copying.
-
Ensuring piddleness
If you have written a simple function and you don't want it to blow up in your face if you pass it a simple number rather than a
sub myfiddle { my $pdl = topdl(shift); $pdl->fiddle_foo(...); ... }
"topdl()" does