Menu

PDL_for_IDL_users

Craig DeForest Daniel Carrera

If you are used to using IDL, this document is for you. This page explains the key differences between PDL and IDL to help you get going as quickly as possible.

PDL is a numerical analysis module, built on top of the Perl language. Perl is a powerful general purpose language, giving PDL programs access to a huge number of features not usually found in numerical analysis software.

In the end, it is Perl itself that makes PDL stand out from other numerical analysis solutions such as IDL.

Perl's documentation is available on-line at http://perldoc.perl.org

PDL's documentation is available on-line at http://pdl.perl.org/PDLdocs

You can also access PDL's documentation from the interactive shell:

 perldl> help help         # How to use the help system.
 perldl> help <subject>    # Reference material on <subject>
 perldl> apropos <subject> # Search for keywords or functions.

Finally, if you need help, you can ask at the PDL mailing list:

http://mailman.jach.hawaii.edu/mailman/listinfo/perldl

Language Syntax

Basics

Run the perldl command to start the PDL shell.

In Perl, variables always start with the '$' sign, and to create a PDL object (matrix / array) you use the "pdl" constructor.

 ; IDL
 IDL> A = [1,2,3,4]
 IDL> print, A

 # PDL
 perldl> $A = pdl [1,2,3,4]
 perldl> print $A

Multi-line commands

In IDL you can use '&' to separate multiple statements in the same line. A single statement can go over over multiple lines if you put it inside a ".run" block.

 ; Multiple commands in one line.
 IDL> a = 3 & b = 4 & c = sqrt(a^2 + b^2)
 IDL> print, c

 ; One command over multiple lines.
 IDL> a = 3 & b = 4
 IDL> .run 
 - c = sqrt( 
 -    a^2 + b^2 
 - )
 IDL> print, c

The PDL shell uses ';' to separate multiple statements in the same line. PDL automatically detects when a single command spans multiple lines.

 # Multiple commands in one line.
 perldl> $a = 3; $b = 4; $c = sqrt($a**2 + $b**2)
 perldl> print $c

 # One command over multiple lines.
 perldl> $a = 3; $b = 4
 perldl> $c = sqrt(
 ..(    >     $a**2 + $b**2
 ..(    > )
 perldl> print $c

But when writing a stand-alone program, you have to terminate all statements with ';'. Line breaks don't matter at all.

BAD

 use PDL;          # Import PDL module into Perl.

 $a = pdl [1,2,3]  # ERROR!! Need a ';' here.
 print $a;

GOOD

 use PDL;          # Import PDL module into Perl.

 $a = pdl [1,2,3]; # Correct.
 print $a;

You can usually copy and paste code directly from a working program into the PDL shell.

Conditionals

A standard conditional ("if-statement") in Perl behaves like the one in IDL, with a more C-like syntax:

 ; IDL conditional
 if value gt MAX then begin
     print, "Value too large"
 endif else if value lt MIN then begin
     print, "Value too small"
 endif else begin
     print, "Value is perfect"
 endelse

 # Perl conditional
 if ($value > $MAX) {
     print "Value too large\n";
 } elsif ($value <do stuff> }

which will assign the values 1 through 10 to $i, in sequence, and execute the commands in the block each time. There are several variants of for. In particular, you can replace the iteration expression with any old list of values:

for $i(@list) { <do stuff> }

iterates over all the elements of @list, in order, rather than over a numerical range. You can even specify the list explicitly:

for $i('foo','bar','baz',17,1) { <do stuff> }

will execute your code with $i set to each of those comma-delimited values, in order. Because this is similar to the behavior of the UNIX csh's foreach construct, you can also use “foreach” instead of “for” -- they're synonyms..

Don't be confused if you encounter a loop with no explicit iterator at all! It's quite legal to say

for(1..10) { <do stuff> }

That will use perl's default operand $ as an iterator. Remember, $ works in most cases like a regular variable except that you can sometimes omit its name for brevity.

There's also a three-element version of for that follows the C language rather than FORTRAN:

for($i=0; $i <do stuff> }

This three-argument form of for has an initializer, a test, and an incrementer. The initializer sets up the loop, the test (which can be any Boolean expression) is evaluated at the top of the loop, and the incrementer is executed at the end of the loop.

while loops

The while construct looks a lot like the IDL while:

while( <boolean> ) { <do stuff> }

until loops

The until construct is just like while, but the sense of the boolean expression is inverted:

until( $i==10 ) { print $i++; }

will print “0123456789” (provided that $i is undefined to start with).

Post-checked loops and do

To get a loop that always executes at least once, you can use do (which is similar to IDL's do):

do {<stuff>} while(test);
do {<stuff>} until(test);
do {<stuff>} if(test);     # alternative form of if
do {<stuff>} unless(test); # alternative form of unless

Loop exits: next and last

You can iterate a loop prematurely, or exit the loop entirely, anywhere within the loop block, by saying next or last. That's handy if you have several exit conditions and want to exit from the middle of the block of code: it prevents your “hot code” from being nested in several levels of if statements. Usually it pops you out of the innermost loop you're in, but you can exercise greater control; see the perl man page for details.

Here's an example:

for $i(1..10) { 
   next if($i==5); 
   print $i; 
}

will print “1234678910”, because the 5 case gets skipped by the next.

Neither next nor last works with do blocks, for reasons that are historical, but they do work in naked blocks, so you can enclose your do block inside another block to make them work properly; this is explained in more detail in the perl man page. If it doesn't make sense to you, you probably don't need to know.

Variables and Types

Perl variables come in four basic sorts: scalars, which hold a single value; lists, which can hold a bunch of scalars indexed by number (they're also called arrays but are quite unlike IDL arrays; see below); hashes, which can hold a bunch of scalars indexed by string (sort of like IDL structures, but more general and without the arbitrary restrictions); and refs, which are like pointers with built-in crash protection. PDL adds a new type of variable, also called a PDL or, in English, a “piddle”, that is closely analogous to an IDL array: it is useful for holding millions of scalar values all of the same type (though a PDL can also hold a single value, or even no values at all). PDLs (the variables) are the bread-and-butter variable type for scientific computing with PDL (the language extension).

In IDL, you refer to variables by name alone. In perl/PDL, variables always have a sigil in front of them to identify both that they are variables, and what kind of value you expect to get out. In IDL, you'd say

A = 5             ; assign 5 to the variable A (short int by default)
B = indgen(5)     ; assign [0,1,2,3,4] to B (short int by default)
C = findgen(1e6)  ; assign [0..999999] to C (floats) 
D = {a:1,b:2,c:3} ; Set D to be an IDL structure

In perl/PDL, the analogous commands are:

$a = 5;      # assign 5 to the perl scalar A 
@b = (0..4); # assign the list (0,1,2,3,4) to B 
$c = xvals(1e6); # Assign the sequence 0..999999 to C.
%d = (a=>1,b=>2,c=>3); # Set %d to be a perl hash.

The sigils help sort out what's what, and also divide up the namespace -- so you can simultaneously have a scalar variable $a, a list @a, a hash %a, and a subroutine called a. The syntax keeps them straight. That can seem confusing if you're used to the idea of “one identifier, one thing” in IDL -- but putting sigils in front of the identifier expands the name space and prevents collisions like the infamous array--subroutine ambiguity in IDL. In general, scalar values are denoted by '$', lists are denoted by '@', and hashes are denoted by '%'.

A caveat: while @a is a list, its elements are themselves scalars -- so $a[5] is element number 5 from @a, and @a[5,6,7] is a list of three elements from @a. @a[5] is a trivial list of one element from $a. In some cases there is a difference between a list of one element and the element itself (see [sub:Typing-and-context:])

As far as Perl itself is concerned, PDL variables are special, magic (yes, that is a technical term) perl scalars. That is less confusing in practice than it may sound -- it just means that, anywhere you can put a single perl scalar value, you can put a PDL that contains (in principle) millions of values. For example, you can create a perl list of PDLs, each of which contains a complete FITS image, by saying something like:

for $f(@files) {
   push(@imlist, rfits($f));
}

In fact, the supplied routine mrfits does exactly that, returning a Perl list of separate images.

Scalars vs. IDL variables

IDL is a strictly typed language. Its variables have a particular type (e.g. short) that they retain until they are destroyed. Ordinary Perl variables (not PDLs) are polymorphic: they change type according to use. So you can treat numeric values as strings and they work correctly; or you can use numeric values without regard for their initial type, and they will work correctly. This is useful, for example, in loops. In IDL, loops crash by default after 32,767 iterations. That's because loop variables are short integers by default, and after 32,767 iterations the loop variable overflows to become -32,768. In Perl that never happens -- the variable gets promoted to an appropriate type that can contain the value. Similarly, if you have a number and you want to put it into a string, you can just use it in a string context and you will get What You Want.

Like IDL scalars, perl scalars can represent the undefined value. Unlike IDL, perl deals gracefully with undefined values. You can test whether a variable is defined or not, using the built-in boolean function defined(), but if you don't bother and just use an undefined value in an expression, it will evaluate as the empty string, 0, or false, whichever is appropriate.

Lists vs. IDL arrays

Perl lists are designed for handling short to midsized collections of things. Each element of the list has a separate scalar (or ref) value, so that perl lists can be completely heterogeneous. Perl has provision for handling undefined values, so you can leave some elements in the middle of a list undefined. You can index elements off the end of a list and they will be automagically created (with the undefined value, if you create them by reading from them). Or you can index elements from the back of the list instead of from the front, by using negative indices. In IDL:

A = INDGEN(10)
PRINT, A[10] ; this makes IDL throw an exception.
PRINT, A[-1] ; this also throws an exception.

In Perl:

@a = 0..9;
print $a[10]; # prints nothing (element is undefined)
print $a[-1]; # prints '9'.

Notice that the elements have the '$' sigil rather than the '@' sigil. That's because we're asking for a scalar value.

PDLs vs. IDL arrays

PDLs are very similar in concept to IDL arrays: they have fixed sizes and types. But unlike IDL arrays, PDLs can contain out-of-band BAD values. You can fake this in IDL by sticking 'nan' into floating-point arrays; but the integer types have no bad-value flag. The bad value just marks a particular element as unusable for whatever reason; further calculations that use the bad value just silently return the bad value themselves, so that you can propagate missing values in your data. You can also index and modify PDLs with rather more facility than IDL arrays; that's described in Chapter [chap:Slicing]

Hashes vs. IDL structures

Like IDL structures, perl hashes associate keyword/value pairs. The keyword is a string, and the value is a perl scalar (or ref). In PDL, as in IDL, each value can itself refer to any valid data structure in the language.

Perl hashes are considerably more flexible than IDL structures. In particular, if your perl code refers to a hash value that isn't present, you just get the undefined value, rather than throwing an exception (as it would in IDL). You can add new keyword/value pairs to your hash just by assigning to them with '=', rather than having to define a new hash. Here's an example. IDL code: add keyword/value pair ('B',2) to structure A:

W = WHERE(STRUPCASE(TAG_NAMES(A)) EQ 'B')
IF W(0) EQ -1 THEN ADD_TAG(A,'B',2) ELSE A.B = 2

perl code: add keyword/value pair ('B',2) to hash %a:

$a{'B'} = 2;

Perl refs

Refs are very easy to use in perl. They're a common way to “roll up” a complex data structure into a single perl scalar that you can hand around. They're impervious to most of the “gotchas” of C pointers, and they're more flexible than IDL pointers.

In general, you make a ref to something by naming the something, and putting a backslash in front of it. You dereference a ref by putting the appropriate sigil in front of the ref itself:

$aref = \$a;      # aref is a ref to the scalar $a
$A = $$aref;      # $A gets the value of $a (case-sensitive!).
$A = ${$aref};    # Another way to say the same thing, less ambiguously
$bref = \@b;      # bref is a ref to the list @b.
@B = @$bref;      # @B gets a copy of @b.
$B = ${$bref}[2]; # $B gets the element #2 of @b
$B = $bref->[2]; #  $B gets the element #2 of @b

The last form is common for both array elements and (with curly braces, as in '$hashref->{"KEY"}') hash values.

Perl keeps a reference count for everything living in its memory, so garbage collection is easy and automatic. You also never have to worry about dangling refs, because nothing is ever deallocated until its reference count reaches 0. In practical terms, data hang around until you have eliminated all access paths to them; then the data evaporate silently.

Refs are useful any time you want to avoid making an extra copy of perl data (e.g. if you pass a ref into a subroutine you don't end up making a copy of the whole original list or hash or whatever), or any time you want to encapsulate a hash or list into a single scalar.

PDL arrays are implemented “under the hood” as refs to opaque objects with a language interface written in C.

Expressions

Perl expressions are far more powerful than IDL expressions, largely because of the branching constructs that are borrowed from C. In particular, the 'and' and 'or' operators (and their higher-precedence versions '&&' and '||') are lazy (they only evaluate the second argument if it will affect the truth of the result), so you can use them as branching constructs; and (where appropriate) they return their first true argument, so you can very tersely say:

$val = $passed || $loaded || $default;

and $val will get the first true value between the three terms on the right-hand side. The equivalent IDL code is:

if ((size(default)(size(default)(0))+1) ne 0) then $
       value = default
if ((size(loaded)(size(loaded))(0))+1) ne 0) then $
       if (loaded ne 0) then value = default
if ((size(pass)(size(pass)(0))+1) ne 0) then $
       if (pass ne 0) then val=pass

The IDL code is complicated by the need to explicitly check the validity of each parameter, and the non-laziness of the boolean .and. and .or. operators.

Like C, perl includes a ternary operator that allows you to insert explicit conditionals into your expression. Used in moderation, the ternary operator can make many sorts of assignments clearer. Here, the first line returns the arcsine of $s or (if $s is out of range) the arcsine of 1/$s. The second line returns an axis label string depending on whether the variable $var contains a FITS header.

$arcsin = (abs($s) > 1) ? asin(1/$s) : asin($s);
$title = (defined $var->hdr->{NAXIS}) ? $var->hdr->{CTYPE1} : '(Arbitrary)');

The presence of side effects can be surprising at first but is very helpful:

$a = $data++;

is more compact and hence clearer than the IDL equivalent:

a = data
data = data + 1

Of course, you can do it that way if you want:

$a = $data;
$data = $data + 1;

Typing and context

Since perl does behind-your-back typing for normal perl variables, each expression has a context in which it is evaluated. The context tells the expression what type is should be. For example, the left-hand argument of && is evaluated in Boolean context, so whatever arithmetic or string value comes from the expression, it gets coerced into a Boolean value. Contexts are void, scalar and list. Void is the context for values that are going to be ignored (e.g. function calls that don't actually do anything with their value -- where, in IDL, you'd use a procedure call). The scalar context comes in several flavors: Boolean, arithmetic, string, and ref. The basic idea behind contexts is that most of the time they allow you to pretend that your perl variable or expression is whatever type is appropriate, and let the language take care of the casting and conversion details.

The largest context difference is between list and scalar context. Perl lists act differently depending on whether you are seeking a scalar or list value. For example, if you assign a list value to a scalar variable, the scalar gets the number of elements in the list:

@a = (4,5,6); # @a gets the list (4,5,6).
$a = @a;      # $a gets the number of elements (3).

That conversion is useful when you want to switch on the size of an array. For example, you can say

if($count == @a) { <do some stuff> }

to do some stuff if @a has exactly $count elements, or

if(@a) { <other stuff> }

to do other stuff if @a has any elements at all. (here, if is expecting a boolean value, so @a is evaluated in scalar context, yielding the number of elements. If the number is nonzero, it counts as true.)

Because perl has no other way of knowing if a perl scalar is meant as a number or string, there are different operators for comparing strings and numbers. The string comparison operators are the two-letter comparison operators that you're used to in IDL (like 'eq'), while the numerical comparisons are more similar to the C language operators (like '==').

Using IDL-like comparisons can be a trap for new users: eq evaluates its arguments in string context, and compares the strings lexically. This normally works OK, since the string representation of two equal numbers should themselves be equal. But it's very inefficient compared to == if you are trying to do arithmetic comparison. The related gt and lt operators don't work properly on numbers, because lexicographic (string) order is different than numeric order.

In general, use the

Prec.
Op.
Associativity
Action on perl scalars
Action on PDLs

1
()
NA
Grouping and function evaluation
Identical to perl scalars

2
->
Left
Dereference a ref or a method
Dereference a method or slice a PDL

3
++, --
Either (Unary)
Pre- or post- autoincrement/autodecrement
Elementwise (but see note)

4
**
Right
Exponentiation
Elementwise

5
!
Right (Unary)
Logical negation
Elementwise

5
~
Right (Unary)
Bitwise negation
Elementwise (operand is coerced to long int)

5
\ Right (Unary)
Return a ref to next scalar
Identical to perl scalars

5
+, -
Right (Unary)
Numeric no-op / numeric negation
Elementwise

6
=~, !~
Left
String operation binding
Acts on stringified PDL

7
*, /, %
Left
Multiply, divide, and modulus
Elementwise (see note)

7
x
Left
Repetition operator
Matrix multiplication

8
+, -
Left
Addition and subtraction
Elementwise

8
.
Left
String concatenation
Acts on stringified PDL

9
<<, >>
Left
Bit-shift operator
Elementwise (LHS is coerced to long int)

10
Named
Right (list operator)
Named operators - various
Act on stringified PDL (see note)

11
<, >, <=, >=
NA
Arithmetic comparison
Elementwise (see note)

11
lt, gt, le, ge
NA
String (lexical) comparisons
Forbidden

12
==, !=, <=>
NA
Arithmetic equivalence
Elementwise (see note)

12
eq, ne, cmp
NA
String equivalence
Elementwise (see note)

13
&
Left
Bitwise AND
Elementwise bitwise AND (see note)

13
|, ^
Left
Bitwise OR and XOR
Elementwise bitwise logical OR and XOR

14
&&
Left
Lazy Boolean logical AND
Scalar (rejects multi-element PDLs)

15
||
Left
Lazy Boolean logical OR
Scalar (rejects multi-element PDLs)

16
.., ...
(none)
Range list operators
Acts on stringified PDL

17
?:
Right (Ternary)
Ternary conditional operator
LHS: Scalar (rejects multi-element PDLs); MHD, RHS: identical to perl scalars

18

Right
Assignment
Assignment-by-reference (does not copy)

19
+=, etc.
Right
In-place arithmetic modifiers
Elementwise

20
,, =>
Left
List separators
Identical to Perl scalars

Descriptions of operators

Dereference operator ('->'): This is borrowed (and extended) from C's dereference-a-pointer-to-a-struct operator; it is a generic operator to dereference a method call or act on the object pointed to by a ref. Examples:

$v1 = $hash->{VAR1};            # Get item from a hash ref
$v2 = $array->[5];              # Get item from an array ref
$pdl->wfits("foo.fits");        # method call
$rad = $xy->pow(2)->sum->sqrt;  # Pipeline syntax

PDL also uses the single arrow operator to generate rectangular slices of large arrays:

$subfield = $bigarray->(2,3:5); # items 3-5 from col. 2

Don't confuse the single-arrow with the double-arrow operator that's used to identify hash fields! (below)

Grouping and function evaluation ( '(' and ')' ): These act exactly like IDL parenthesis for expression grouping and function evaluation. They can also be used for extracting subsets of individual PDLs ('slicing').

Dereferencing ('->'): this is used to follow a reference and index an element -- for example '$a->[5]' will give the 6th element of a Perl list pointed to by a list ref called '$a'.

Autoincrement and autodecrement ('++', '--'): These act like the C language autoincrement and autodecrement operators: they return their argument and (as a side effect) either increment or decrement it. Depending on placement, the side-effect happens before or after the value is grabbed (when operating on normal Perl scalars):

$a = 5; 
print ++$a, ", ";
print $a++, ", ";
print $a, "\n";

will print “6, 6, 7”.

WARNING: Because of a wart in the way that PDL functionality is grafted onto Perl, there is no difference between pre- and post-increment when you use a PDL. The reason is that PDLs are not handled as normal Perl scalars but as references to internal objects. Both pre- and post-increment operators return refs to the underlying PDL. Evaluating the term "$a++" has the same effect as "{ my $b = $a; $a+= 1; $b}", which defines a temporary variable (called "$b") and returns it (after incrementing $a). If $a is a PDL (rather than a Perl scalar), then both $a and $b get incremented by the "$a+=1", because $b is only a reference to the underlying data. Hence "$a++" and "++$a" yield the same result if $a is a PDL.

Exponentiation ('**'): works just as one might expect. The left-hand argument is the number being exponentiated, and it must be non-negative. The right-hand argument is the exponential, and can be integer or floating.

Logical negation ('!'): works like the C operator, NOT the IDL "not" operator: nonzero elements get changed to 0, and zero elements get changed to 1.

Bitwise negation ('~'): works like the IDL "not operator" - inverts the bits of its argument, which is coerced into a long int first. Hence, "$a=pdl(5); print !$a" gives "0", while "$a=pdl(5); print ~$a" gives "-6".

Referencing ('\'): generates a ref (a Perl pointer) to its argument, which can be a PDL, a Perl scalar, a Perl list or hash, or even a subroutine.

Unary-plus and unary-minus ('+', '-'): IDL lets you specify unary-minus to change the sign of a constant or variable, but not unary-plus, which does nothing to its argument. In Perl, unary-plus is actually useful, because it forces numeric context - if you apply it to a string, the string will be converted to numeric format.

String operation binding ('=~', '!~'): these are used to bind arguments to the string match and substitute operators. Perl has special syntax (called "regexp") syntax built right into the language (IDL implements regular expression mapping through function calls); these operators are used to bind a regular expression to an argument. They can be applied to PDLs, but the PDL gets stringified before the regexp operation.

Arithmetic multiply, divide, and mod ('*','/','%'): The mod (%) operator is a true mathematical modulus rather than the more common sign-inverting variety: $a % $b. is always on the interval [0,$b) provided that $b is positive, and on the interval ($b,0] provided that $b is negative. PDL generalizes mod a little further even than perl does: perl % always coerces its arguments to integers, while PDL % allows floating point operands. Hence, this little wrinkle:

print 3.3 % 2.7, ", ";
print pdl(3.3) % pdl(2.7),"\n";

prints “1, 0.6”. In general, if you use PDLs you get the more general behavior; but if you rely on it you must be careful always to use at least one PDL argument to %.

Repetition and matrix multiplication ('x'): When both arguments are ordinary perl scalars, 'x' is a useful repetition operator -- e.g.

print "-" x 79;

will print a full line of 79 dashes -- but PDL co-opts it as matrix multiplication. Matrices are addressed in (X,Y) order rather than (R,C) order -- so they look correct on screen and the expression “$m x $colvec” acts correctly, but indexing is reversed from standard math textbooks. There is a subclass of PDL called “PDL::Matrix”, that interchanges the first two dimensions so that you can index your matrices in (R,C) order if you want.

1-D PDLS are row vectors; you have to transpose them or insert a dummy 0th dimension to get column vectors - like this:

$a  = pdl(1,2);          # row vector
$m  = pdl([1,2],[3,4]);  # 2x2 matrix
$am = $a x $m;           # row times matrix: OK (yields a scalar)
$ma = $m x $a->(*1);     # matrix times column OK (yields a scalar).

In the last line, the "->(1)" inserts a dummy dimension: $a is a 2-PDL, and $a->(1) is a 1x2-PDL.

Addition and subtraction ('+', '-'): these work exactly as you expect.

String concatenation ('.'): this is used for concatenating two strings together. Its arguments get converted to strings first.

Bit-shift ('&lt;&lt;', '&gt;&gt;'): these are the C language bit-shift operators. The arguments are coerced into integer form. They work elementwise on PDLs, so (e.g.) "print pdl(1,2,3)<FILE>” operator for unformatted ASCII input, write and read for fixed length (ala FORTRAN) ASCII I/O, and syswrite and sysread for unformatted binary I/O.

Images and collections of images

Image I/O, including FITS files, is via rpic and wpic, generalized image read/write routines that handle most standard formats including PNG, JPEG, GIF, PPM, FITS, Encapsulated PostScript, and others. Some simple ways to read and write FITS files are:

$a = rpic("filename.fits"); # Works for other file formats too

$a->wpic("another-filename.fits"); # method syntax

wpic($a,"another-filename.fits"); # function syntax

You can read in a long list of FITS files with:

@files = <directory/*.fits>; # Example of UNIX-style globbing

@imgs = mrfits(@files); # @files is a list of file names.

$cube = rcube( \&amp;rpic, @files );

The output of mrfits is a perl list, each element of which is the corresponding FITS file loaded into a PDL variable. The output of rcube is a single data cube loaded with all of the images stacked in the highest dimension, so it is more useful for a collcetion of uniformly sized files.

Unlike IDL, PDL can keep a metadata header attached to each variable, so there is no need to keep track of an additional header variable for each image you load. To access fields in $a's FITS header in the example above, use (e.g.) “$a->hdr->{TELESCOP}”.

Raw binary data

There are several ways to manipulate raw binary data with no in-file header at all. One way is with the PDL::IO::FlexRaw module, which defines the commands readflex and writeflex. see Chapter [cha:File-I/O]for details.

Arbitrary collections of data

There are at least two simple ways to dump a collection of PDL variables to disk for later retrieval. The method closest to IDL's save-file format is with the PDL::IO::Storable module, which lets you write and read collections of variables to disk in a fast, opaque, binary format, using the functions store and retrieve. The PDL::IO::Dumper module translates arbitrary perl data structures into perl source code, which is a convenient quasi-human-readable format that is completely portable, but much slower and larger than the Storable format.

IDL save files

PDL can read most IDL .sav files that do not include compiled code. You need to use the PDL::IO::IDL module, which contains a single function, ridl(). ridl(<filename>) will return a Perl hash ref containing all the variables in the IDL save file. IDL numeric arrays are converted to PDLs; IDL string arrays are converted to Perl lists; and IDL structures are converted to Perl hashes.


Related

Wiki: Main_Page
Wiki: PDL_Book