File Coverage

blib/lib/PDL/Demos/BAD_demo.pm
Criterion Covered Total %
statement 4 7 57.1
branch n/a
condition n/a
subroutine 2 5 40.0
pod 0 4 0.0
total 6 16 37.5


line stmt bran cond sub pod time code
1             package PDL::Demos::BAD_demo;
2 1     1   7 use Carp;
  1         2  
  1         616  
3             require File::Spec;
4              
5             # try and find m51.fits
6             my @f = qw(PDL Demos m51.fits);
7             our $m51file = undef;
8             foreach my $path ( @INC ) {
9             my $file = File::Spec->catfile( $path, @f );
10             if ( -f $file ) { $m51file = $file; last; }
11             }
12             confess "Unable to find m51.fits within the perl libraries.\n"
13             unless defined $m51file;
14              
15             my @demos = (
16             [comment => q|
17             Welcome to this tour of the bad value support in PDL
18              
19             Each ndarray contains a flag - accessible via the badflag() method -
20             which indicates whether:
21              
22             the ndarray contains no bad values (flag equals 0)
23             the ndarray *MAY* contain bad values (flag equals 1)
24              
25             If the flag is set, then the routines (well, those that have been
26             converted) will process these bad values correctly, otherwise they
27             are ignored.
28              
29             The code has been written so as to provide as little overhead as
30             possible; therefore there should be almost no difference in the
31             time it takes to process ndarrays which do not have their bad flag
32             set.
33             |],
34              
35             [act => q|
36             # create an ndarray
37             $x = byte(1,2,3);
38             print( "Bad flag (x) == ", $x->badflag(), "\n" );
39              
40             # set bad flag, even though all the data is good
41             $x->badflag(1);
42             print( "Bad flag (x) == ", $x->badflag(), "\n" );
43              
44             # note the bad flag is infectious
45             $y = 2 * $x;
46             print( "Bad flag (y) == ", $y->badflag(), "\n\n" );
47             |],
48              
49             [act => q|
50             # the badflag is also included in the state info of
51             # ndarray
52             #
53             $z = pdl(2,3); # just an ndarray without the badflag set
54              
55             print " Type Dimension State Mem\n";
56             print "-------------------------------------------------\n";
57             print "x ", $x->info("%-6T %-15D %-5S %12M"), "\n";
58             print "y ", $y->info("%-6T %-15D %-5S %12M"), "\n";
59             print "z ", $z->info("%-6T %-15D %-5S %12M"), "\n\n";
60             |],
61              
62             [act => q|
63             print "No bad values: $x\n";
64             # set the middle value bad
65             $x->setbadat(1);
66              
67             # now print out
68             print "Some bad values: $x\n";
69             print "b contains: $y\n";
70             $z = $x + $y;
71             print "so x + y = $z\n\n";
72             |],
73              
74             [act => q|
75             # The module PDL::Bad contains a number of routines designed
76             # to make using bad values easy.
77             print "x contains ", $x->nbad, " bad elements.\n";
78             print "The bad value for type #",$x->get_datatype," is ",$x->badvalue,"\n";
79             print "It is easy to find whether a value is good: ", isgood($x), "\n\n";
80              
81             print "or to remove the bad values\n";
82             $x->inplace->setbadtoval(23);
83             print "x = $x and \$x->badflag == ", $x->badflag, "\n\n";
84             |],
85              
86             [act => q|
87             print "We can even label certain values as bad!\n";
88             $x = sequence(3,3);
89             $x = $x->setbadif( $x % 2 ); # unfortunately can not be done inplace
90             print $x;
91             |],
92              
93             [act => q|
94             # the issue of how to cope with dataflow is not fully resolved. At
95             # present, if you change the badflag of an ndarray, all its children
96             # are also changed:
97             $x = sequence( byte, 2, 3 );
98             $x = $x->setbadif( $x == 3 );
99             $y = $x->slice("(1),:");
100             print "y = $y\tbadflag = ", $y->badflag, "\n";
101              
102             $x->inplace->setbadtoval(3);
103             print "y = $y\tbadflag = ", $y->badflag, "\n\n";
104             |],
105              
106             [act => q|
107             # Note that "boolean" operators return a bad value if either of the
108             # operands are bad: one way around this is to replace all bad values
109             # by 0 or 1.
110              
111             $x = sequence(3,3); $x = $x->setbadif( $x % 2 );
112             print $x > 5;
113             print setbadtoval($x > 5,0); # set all bad values to false
114             |],
115              
116             [act => q|
117             # One area that is likely to cause confusion is the return value from
118             # comparison operators (e.g. all and any) when ALL elements are bad.
119             # The bad value is returned; if used in boolean context this causes
120             # an exception, since it is neither true nor false.
121              
122             # There is also the fact that the bad value need not relate to the
123             # type of the input ndarray (due to internal conversion to an 'int +').
124              
125             $x = ones(3); $x = $x->setbadif( $x == 1 );
126             print "Any returns: ", any( $x > 2 ), "\n";
127             print "which is the bad value of 'long' (", long->badvalue, ").\n";
128              
129             print "Whereas the bad value for \$x is: ", $x->badvalue, "\n";
130             |],
131              
132             [comment => q|
133             Many of the 'core' routines have been converted to handle bad values.
134             However, some (including most of the additional modules) have not,
135             either because it does not make sense or it's too much work to do!
136              
137             To find out the status of a particular routine, use the 'badinfo'
138             command in perldl shell (this information is also included
139             when you do 'help'), or the '-b' switch of pdldoc.
140             |],
141              
142             (!eval { require PDL::Graphics::Simple; PDL::Graphics::Simple->import; 1 })
143             ? [comment => q|
144             The rest of this demo is just a bit of eye-candy to show bad values in
145             action, and requires PDL::Graphics::Simple support in PDL which is
146             unavailable. Ending.
147             |]
148             : (
149              
150             [comment => q|
151             This demo is just a bit of eye-candy to show bad values in action,
152             and requires PDL::Graphics::Simple support in PDL. It makes use of
153             the image of M51 kindly provided by the Hubble Heritage group at
154             the Space Telescope Science Institute.
155              
156             It also serves to demonstrate that you often don't need to change
157             your code to handle bad values, as the routines may 'do it' for you.
158             |],
159              
160             [act => q|
161             # read in the image ($m51file has been set up by this demo to
162             # contain the location of the file)
163             $m51 = rfits $|.__PACKAGE__.q|::m51file;
164              
165             # display it
166             $just = { JUSTIFY => 1 };
167             imag $m51, $just;
168              
169             # These are used to create the next image
170             ( $nx, $ny ) = $m51->dims;
171             $centre = [ $nx/2, $ny/2 ];
172             |],
173              
174             [act => q|
175             # now, let's mask out the central 40 pixels and display it
176             $masked = $m51->setbadif( $m51->rvals({CENTRE=>$centre}) < 40 );
177              
178             # since imag auto-scales the output, the bad values are not displayed
179             imag $masked, $just;
180              
181             # compare the statistics of the images
182             print "Original:\n", $m51->stats, "\n";
183             print "Masked:\n", $masked->stats, "\n";
184             |],
185              
186             [act => q|
187             # let's filter it a little bit
188             use PDL::Image2D;
189             $nb = 15;
190             $filtered = med2d $masked, ones($nb,$nb), { Boundary => 'Truncate' };
191              
192             # this is a model of the diffuse component of M51
193             imag $filtered, $just;
194             |],
195              
196             [act => q|
197             # unsharp masking, to bring out the small-scale detail
198             $unsharp = $masked - $filtered;
199              
200             imag $unsharp, $just;
201             |],
202              
203             [act => q|
204             # add on some contours showing the large scale structure of the galaxy
205             erase; $w = pgswin();
206             $w->plot(with=>'image', $unsharp, with=>'contours', $filtered, $just);
207             |],
208             ) # end of graphics-only bit
209             );
210             $@ = ''; # reset
211              
212 1     1 0 4 sub info {('bad', 'Bad-value support (Optional: PDL::Graphics::Simple)')}
213              
214 0     0 0   sub demo { @demos }
215 0     0 0   sub init { 'eval "use PDL::Graphics::Simple"' }
216 0     0 0   sub done {'undef $w'}
217              
218             1;