| 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; |