line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Astro::FITS::Header; |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
# --------------------------------------------------------------------------- |
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
=head1 NAME |
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
Astro::FITS::Header - Object Orientated interface to FITS HDUs |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
=head1 SYNOPSIS |
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
$header = new Astro::FITS::Header( Cards => \@array ); |
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
=head1 DESCRIPTION |
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
Stores information about a FITS header block in an object. Takes an hash |
16
|
|
|
|
|
|
|
with an array reference as an argument. The array should contain a list |
17
|
|
|
|
|
|
|
of FITS header cards as input. |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
=cut |
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
# L O A D M O D U L E S -------------------------------------------------- |
22
|
|
|
|
|
|
|
|
23
|
10
|
|
|
10
|
|
114416
|
use strict; |
|
10
|
|
|
|
|
41
|
|
|
10
|
|
|
|
|
377
|
|
24
|
10
|
|
|
10
|
|
68
|
use vars qw/ $VERSION /; |
|
10
|
|
|
|
|
45
|
|
|
10
|
|
|
|
|
555
|
|
25
|
10
|
|
|
10
|
|
55
|
use Carp; |
|
10
|
|
|
|
|
26
|
|
|
10
|
|
|
|
|
871
|
|
26
|
|
|
|
|
|
|
|
27
|
10
|
|
|
10
|
|
4051
|
use Astro::FITS::Header::Item; |
|
10
|
|
|
|
|
66
|
|
|
10
|
|
|
|
|
425
|
|
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
$VERSION = '3.09'; |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
# Operator overloads |
32
|
10
|
|
|
|
|
44
|
use overload '""' => "stringify", |
33
|
10
|
|
|
10
|
|
73
|
fallback => 1; |
|
10
|
|
|
|
|
24
|
|
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
# C O N S T R U C T O R ---------------------------------------------------- |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
=head1 METHODS |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
=head2 Constructor |
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
=over 4 |
42
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
=item B |
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
Create a new instance from an array of FITS header cards. |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
$item = new Astro::FITS::Header( Cards => \@header ); |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
returns a reference to a Header object. If you pass in no cards, |
50
|
|
|
|
|
|
|
you get the (required) first SIMPLE card for free. |
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
=cut |
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
sub new { |
56
|
41
|
|
|
41
|
1
|
5502
|
my $proto = shift; |
57
|
41
|
|
66
|
|
|
643
|
my $class = ref($proto) || $proto; |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
# bless the header block into the class |
60
|
41
|
|
|
|
|
203
|
my $block = bless { HEADER => [], |
61
|
|
|
|
|
|
|
LOOKUP => {}, |
62
|
|
|
|
|
|
|
LASTKEY => undef, |
63
|
|
|
|
|
|
|
TieRetRef => 0, |
64
|
|
|
|
|
|
|
SUBHDRS => [], |
65
|
|
|
|
|
|
|
}, $class; |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
# Configure the object, even with no arguments since configure |
68
|
|
|
|
|
|
|
# still puts the minimum SIMPLE card in. |
69
|
41
|
|
|
|
|
131
|
$block->configure( @_ ); |
70
|
|
|
|
|
|
|
|
71
|
41
|
|
|
|
|
151
|
return $block; |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
} |
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
# I T E M ------------------------------------------------------------------ |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
=back |
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
=head2 Accessor Methods |
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
=over 4 |
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
=item B |
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
Indicates whether the tied object should return multiple values |
86
|
|
|
|
|
|
|
as a single string joined by newline characters (false) or |
87
|
|
|
|
|
|
|
it should return a reference to an array containing all the values. |
88
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
Only affects the tied interface. |
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
tie %keywords, "Astro::FITS::Header", $header, tiereturnsref => 1; |
92
|
|
|
|
|
|
|
$ref = $keywords{COMMENT}; |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
Defaults to returning a single string in all cases (for backwards |
95
|
|
|
|
|
|
|
compatibility) |
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
=cut |
98
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
sub tiereturnsref { |
100
|
356
|
|
|
356
|
1
|
3129
|
my $self = shift; |
101
|
356
|
100
|
|
|
|
732
|
if (@_) { |
102
|
4
|
|
|
|
|
9
|
$self->{TieRetRef} = shift; |
103
|
|
|
|
|
|
|
} |
104
|
356
|
|
|
|
|
938
|
return $self->{TieRetRef}; |
105
|
|
|
|
|
|
|
} |
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
=item B |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
Set or return the subheaders for a Header object. Arguments must be |
110
|
|
|
|
|
|
|
given as C objects. |
111
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
$header->subhdrs(@hdrs); |
113
|
|
|
|
|
|
|
@hdrs = $header->subhdrs; |
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
This method should be used when you have additional header components |
116
|
|
|
|
|
|
|
that should be associated with the primary header but they are not |
117
|
|
|
|
|
|
|
associated with a particular name, just an ordering. |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
FITS headers that are associated with a name can be stored directly |
120
|
|
|
|
|
|
|
in the header using an C of type 'HEADER'. |
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
=cut |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
sub subhdrs { |
125
|
22
|
|
|
22
|
1
|
53
|
my $self = shift; |
126
|
|
|
|
|
|
|
|
127
|
22
|
100
|
|
|
|
61
|
if (@_) { |
128
|
|
|
|
|
|
|
# verify the class |
129
|
2
|
|
|
|
|
14
|
my $i; |
130
|
2
|
|
|
|
|
38
|
for my $h (@_) { |
131
|
4
|
50
|
|
|
|
16
|
croak "Argument $i supplied to subhdrs method is not a Astro::FITS::Header object\n" |
132
|
|
|
|
|
|
|
unless UNIVERSAL::isa( $h, "Astro::FITS::Header" ); |
133
|
4
|
|
|
|
|
8
|
$i++; |
134
|
|
|
|
|
|
|
} |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
# store them |
137
|
2
|
|
|
|
|
19
|
@{$self->{SUBHDRS}} = @_; |
|
2
|
|
|
|
|
6
|
|
138
|
|
|
|
|
|
|
} |
139
|
22
|
100
|
|
|
|
48
|
if (wantarray()) { |
140
|
1
|
|
|
|
|
1
|
return @{$self->{SUBHDRS}}; |
|
1
|
|
|
|
|
4
|
|
141
|
|
|
|
|
|
|
} else { |
142
|
21
|
|
|
|
|
118
|
return $self->{SUBHDRS}; |
143
|
|
|
|
|
|
|
} |
144
|
|
|
|
|
|
|
} |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
=item B-
|
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
Returns a FITS::Header:Item object referenced by index, C if it |
149
|
|
|
|
|
|
|
does not exist. |
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
$item = $header->item($index); |
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
=cut |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
sub item { |
156
|
539
|
|
|
539
|
1
|
323940
|
my ( $self, $index ) = @_; |
157
|
|
|
|
|
|
|
|
158
|
539
|
50
|
|
|
|
1371
|
return undef unless defined $index; |
159
|
539
|
50
|
|
|
|
777
|
return undef unless exists ${$self->{HEADER}}[$index]; |
|
539
|
|
|
|
|
1385
|
|
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
# grab and return the Header::Item at $index |
162
|
539
|
|
|
|
|
789
|
return ${$self->{HEADER}}[$index]; |
|
539
|
|
|
|
|
1297
|
|
163
|
|
|
|
|
|
|
} |
164
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
=item B |
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
Returns a Starlink::AST FrameSet object representing the WCS of the |
169
|
|
|
|
|
|
|
FITS Header. |
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
$ast = $header->get_wcs(); |
172
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
=cut |
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
sub get_wcs { |
176
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
177
|
|
|
|
|
|
|
|
178
|
0
|
|
|
|
|
0
|
require Starlink::AST; |
179
|
0
|
|
|
|
|
0
|
my $fchan = Starlink::AST::FitsChan->new(); |
180
|
0
|
|
|
|
|
0
|
for my $i ( $self->cards() ) { |
181
|
0
|
|
|
|
|
0
|
$fchan->PutFits( $i, 0); |
182
|
|
|
|
|
|
|
} |
183
|
0
|
|
|
|
|
0
|
$fchan->Clear( "Card" ); |
184
|
0
|
|
|
|
|
0
|
return $fchan->Read(); |
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
} |
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
# K E Y W O R D ------------------------------------------------------------ |
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
=item B |
192
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
Returns keyword referenced by index, C if it does not exist. |
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
$keyword = $header->keyword($index); |
196
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
=cut |
198
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
sub keyword { |
200
|
249
|
|
|
249
|
1
|
94153
|
my ( $self, $index ) = @_; |
201
|
|
|
|
|
|
|
|
202
|
249
|
50
|
|
|
|
568
|
return undef unless defined $index; |
203
|
249
|
100
|
|
|
|
350
|
return undef unless exists ${$self->{HEADER}}[$index]; |
|
249
|
|
|
|
|
696
|
|
204
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
# grab and return the keyword at $index |
206
|
247
|
|
|
|
|
388
|
return ${$self->{HEADER}}[$index]->keyword(); |
|
247
|
|
|
|
|
658
|
|
207
|
|
|
|
|
|
|
} |
208
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
# I T E M B Y N A M E ------------------------------------------------- |
210
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
=item B |
212
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
Returns an array of Header::Items for the requested keyword if called |
214
|
|
|
|
|
|
|
in list context, or the first matching Header::Item if called in scalar |
215
|
|
|
|
|
|
|
context. Returns C if the keyword does not exist. The keyword |
216
|
|
|
|
|
|
|
may be a regular expression created with the C operator. |
217
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
@items = $header->itembyname($keyword); |
219
|
|
|
|
|
|
|
$item = $header->itembyname($keyword); |
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
=cut |
224
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
sub itembyname { |
226
|
60
|
|
|
60
|
1
|
867
|
my ( $self, $keyword ) = @_; |
227
|
|
|
|
|
|
|
|
228
|
60
|
|
|
|
|
155
|
my @items = @{$self->{HEADER}}[$self->index($keyword)]; |
|
60
|
|
|
|
|
164
|
|
229
|
|
|
|
|
|
|
|
230
|
60
|
100
|
|
|
|
238
|
return wantarray ? @items : @items ? $items[0] : undef; |
|
|
100
|
|
|
|
|
|
231
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
} |
233
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
# I T E M B Y T Y P E ------------------------------------------------- |
235
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
=item B |
237
|
|
|
|
|
|
|
|
238
|
|
|
|
|
|
|
Returns an array of Header::Items for the requested type if called in |
239
|
|
|
|
|
|
|
list context, or the first matching Header::Item if called in scalar |
240
|
|
|
|
|
|
|
context. See C for a list of allowed types. |
241
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
@items = $header->itembytype( "COMMENT" ); |
243
|
|
|
|
|
|
|
@items = $header->itembytype( "HEADER" ); |
244
|
|
|
|
|
|
|
$item = $header->itembytype( "INT" ); |
245
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
=cut |
247
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
sub itembytype { |
249
|
1
|
|
|
1
|
1
|
678
|
my ( $self, $type ) = @_; |
250
|
|
|
|
|
|
|
|
251
|
1
|
50
|
|
|
|
15
|
return () unless defined $type; |
252
|
|
|
|
|
|
|
|
253
|
1
|
|
|
|
|
7
|
$type = uc($type); |
254
|
|
|
|
|
|
|
|
255
|
|
|
|
|
|
|
# No optimised lookup so brute force it |
256
|
1
|
|
|
|
|
2
|
my @items = grep { $_->type eq $type } @{ $self->{HEADER} }; |
|
123
|
|
|
|
|
222
|
|
|
1
|
|
|
|
|
4
|
|
257
|
|
|
|
|
|
|
|
258
|
1
|
0
|
|
|
|
10
|
return wantarray ? @items : @items ? $items[0] : undef; |
|
|
50
|
|
|
|
|
|
259
|
|
|
|
|
|
|
|
260
|
|
|
|
|
|
|
} |
261
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
# I N D E X -------------------------------------------------------------- |
263
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
=item B |
265
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
Returns an array of indices for the requested keyword if called in |
267
|
|
|
|
|
|
|
list context, or an empty array if it does not exist. The keyword may |
268
|
|
|
|
|
|
|
be a regular expression created with the C operator. |
269
|
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
@index = $header->index($keyword); |
271
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
If called in scalar context it returns the first item in the array, or |
273
|
|
|
|
|
|
|
C if the keyword does not exist. |
274
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
$index = $header->index($keyword); |
276
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
=cut |
278
|
|
|
|
|
|
|
|
279
|
|
|
|
|
|
|
sub index { |
280
|
385
|
|
|
385
|
1
|
1294
|
my ( $self, $keyword ) = @_; |
281
|
|
|
|
|
|
|
|
282
|
|
|
|
|
|
|
# grab the index array from lookup table |
283
|
385
|
|
|
|
|
597
|
my @index; |
284
|
|
|
|
|
|
|
|
285
|
385
|
100
|
|
|
|
782
|
if ( 'Regexp' eq ref $keyword ) { |
286
|
13
|
|
|
|
|
27
|
push @index, @{$self->{LOOKUP}{$_}} |
287
|
2
|
|
|
|
|
6
|
foreach grep { /$keyword/ && |
288
|
233
|
100
|
|
|
|
661
|
defined $self->{LOOKUP}{$_} } keys %{$self->{LOOKUP}}; |
|
2
|
|
|
|
|
44
|
|
289
|
2
|
|
|
|
|
45
|
@index = sort @index; |
290
|
|
|
|
|
|
|
} else { |
291
|
360
|
|
|
|
|
506
|
@index = @{${$self->{LOOKUP}}{$keyword}} |
|
360
|
|
|
|
|
874
|
|
292
|
383
|
|
|
|
|
1184
|
if ( exists ${$self->{LOOKUP}}{$keyword} && |
293
|
383
|
100
|
66
|
|
|
538
|
defined ${$self->{LOOKUP}}{$keyword} ); |
|
360
|
|
|
|
|
1175
|
|
294
|
|
|
|
|
|
|
} |
295
|
|
|
|
|
|
|
|
296
|
|
|
|
|
|
|
# return the values array |
297
|
385
|
50
|
|
|
|
1179
|
return wantarray ? @index : @index ? $index[0] : undef; |
|
|
100
|
|
|
|
|
|
298
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
} |
300
|
|
|
|
|
|
|
|
301
|
|
|
|
|
|
|
# V A L U E --------------------------------------------------------------- |
302
|
|
|
|
|
|
|
|
303
|
|
|
|
|
|
|
=item B |
304
|
|
|
|
|
|
|
|
305
|
|
|
|
|
|
|
Returns an array of values for the requested keyword if called in list |
306
|
|
|
|
|
|
|
context, or an empty array if it does not exist. The keyword may be |
307
|
|
|
|
|
|
|
a regular expression created with the C operator. |
308
|
|
|
|
|
|
|
|
309
|
|
|
|
|
|
|
@value = $header->value($keyword); |
310
|
|
|
|
|
|
|
|
311
|
|
|
|
|
|
|
If called in scalar context it returns the first item in the array, or |
312
|
|
|
|
|
|
|
C if the keyword does not exist. |
313
|
|
|
|
|
|
|
|
314
|
|
|
|
|
|
|
=cut |
315
|
|
|
|
|
|
|
|
316
|
|
|
|
|
|
|
sub value { |
317
|
295
|
|
|
295
|
1
|
2069
|
my ( $self, $keyword ) = @_; |
318
|
|
|
|
|
|
|
|
319
|
|
|
|
|
|
|
# resolve the values from the index array from lookup table |
320
|
295
|
|
|
|
|
673
|
my @values = map { ${$self->{HEADER}}[$_]->value() } $self->index($keyword); |
|
302
|
|
|
|
|
439
|
|
|
302
|
|
|
|
|
906
|
|
321
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
# loop over the indices and grab the values |
323
|
295
|
50
|
|
|
|
929
|
return wantarray ? @values : @values ? $values[0] : undef; |
|
|
100
|
|
|
|
|
|
324
|
|
|
|
|
|
|
|
325
|
|
|
|
|
|
|
} |
326
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
# C O M M E N T ------------------------------------------------------------- |
328
|
|
|
|
|
|
|
|
329
|
|
|
|
|
|
|
=item B |
330
|
|
|
|
|
|
|
|
331
|
|
|
|
|
|
|
Returns an array of comments for the requested keyword if called |
332
|
|
|
|
|
|
|
in list context, or an empty array if it does not exist. The keyword |
333
|
|
|
|
|
|
|
may be a regular expression created with the C operator. |
334
|
|
|
|
|
|
|
|
335
|
|
|
|
|
|
|
@comment = $header->comment($keyword); |
336
|
|
|
|
|
|
|
|
337
|
|
|
|
|
|
|
If called in scalar context it returns the first item in the array, or |
338
|
|
|
|
|
|
|
C if the keyword does not exist. |
339
|
|
|
|
|
|
|
|
340
|
|
|
|
|
|
|
$comment = $header->comment($keyword); |
341
|
|
|
|
|
|
|
|
342
|
|
|
|
|
|
|
=cut |
343
|
|
|
|
|
|
|
|
344
|
|
|
|
|
|
|
sub comment { |
345
|
14
|
|
|
14
|
1
|
1526
|
my ( $self, $keyword ) = @_; |
346
|
|
|
|
|
|
|
|
347
|
|
|
|
|
|
|
# resolve the comments from the index array from lookup table |
348
|
|
|
|
|
|
|
my @comments = |
349
|
14
|
|
|
|
|
27
|
map { ${$self->{HEADER}}[$_]->comment() } $self->index($keyword); |
|
26
|
|
|
|
|
35
|
|
|
26
|
|
|
|
|
62
|
|
350
|
|
|
|
|
|
|
|
351
|
|
|
|
|
|
|
# loop over the indices and grab the comments |
352
|
14
|
0
|
|
|
|
46
|
return wantarray ? @comments : @comments ? $comments[0] : undef; |
|
|
50
|
|
|
|
|
|
353
|
|
|
|
|
|
|
} |
354
|
|
|
|
|
|
|
|
355
|
|
|
|
|
|
|
# I N S E R T ------------------------------------------------------------- |
356
|
|
|
|
|
|
|
|
357
|
|
|
|
|
|
|
=item B |
358
|
|
|
|
|
|
|
|
359
|
|
|
|
|
|
|
Inserts a FITS header card object at position $index |
360
|
|
|
|
|
|
|
|
361
|
|
|
|
|
|
|
$header->insert($index, $item); |
362
|
|
|
|
|
|
|
|
363
|
|
|
|
|
|
|
the object $item is not copied, multiple inserts of the same object mean |
364
|
|
|
|
|
|
|
that future modifications to the one instance of the inserted object will |
365
|
|
|
|
|
|
|
modify all inserted copies. |
366
|
|
|
|
|
|
|
|
367
|
|
|
|
|
|
|
The insert position can be negative. |
368
|
|
|
|
|
|
|
|
369
|
|
|
|
|
|
|
=cut |
370
|
|
|
|
|
|
|
|
371
|
|
|
|
|
|
|
sub insert{ |
372
|
22
|
|
|
22
|
1
|
4192
|
my ($self, $index, $item) = @_; |
373
|
|
|
|
|
|
|
|
374
|
|
|
|
|
|
|
# splice the new FITS header card into the array |
375
|
|
|
|
|
|
|
# Splice automatically triggers a lookup table rebuild |
376
|
22
|
|
|
|
|
66
|
$self->splice($index, 0, $item); |
377
|
|
|
|
|
|
|
|
378
|
22
|
|
|
|
|
41
|
return; |
379
|
|
|
|
|
|
|
} |
380
|
|
|
|
|
|
|
|
381
|
|
|
|
|
|
|
|
382
|
|
|
|
|
|
|
# R E P L A C E ------------------------------------------------------------- |
383
|
|
|
|
|
|
|
|
384
|
|
|
|
|
|
|
=item B |
385
|
|
|
|
|
|
|
|
386
|
|
|
|
|
|
|
Replace FITS header card at index $index with card $item |
387
|
|
|
|
|
|
|
|
388
|
|
|
|
|
|
|
$card = $header->replace($index, $item); |
389
|
|
|
|
|
|
|
|
390
|
|
|
|
|
|
|
returns the replaced card. |
391
|
|
|
|
|
|
|
|
392
|
|
|
|
|
|
|
=cut |
393
|
|
|
|
|
|
|
|
394
|
|
|
|
|
|
|
sub replace{ |
395
|
1
|
|
|
1
|
1
|
4
|
my ($self, $index, $item) = @_; |
396
|
|
|
|
|
|
|
# remove the specified item and replace with $item |
397
|
|
|
|
|
|
|
# Splice triggers a rebuild so we do not have to |
398
|
1
|
|
|
|
|
7
|
return $self->splice( $index, 1, $item); |
399
|
|
|
|
|
|
|
} |
400
|
|
|
|
|
|
|
|
401
|
|
|
|
|
|
|
# R E M O V E ------------------------------------------------------------- |
402
|
|
|
|
|
|
|
|
403
|
|
|
|
|
|
|
=item B |
404
|
|
|
|
|
|
|
|
405
|
|
|
|
|
|
|
Removes a FITS header card object at position $index |
406
|
|
|
|
|
|
|
|
407
|
|
|
|
|
|
|
$card = $header->remove($index); |
408
|
|
|
|
|
|
|
|
409
|
|
|
|
|
|
|
returns the removed card. |
410
|
|
|
|
|
|
|
|
411
|
|
|
|
|
|
|
=cut |
412
|
|
|
|
|
|
|
|
413
|
|
|
|
|
|
|
sub remove{ |
414
|
4
|
|
|
4
|
1
|
659
|
my ($self, $index) = @_; |
415
|
|
|
|
|
|
|
# remove the FITS header card from the array |
416
|
|
|
|
|
|
|
# Splice always triggers a lookup table rebuild so we don't have to |
417
|
4
|
|
|
|
|
13
|
return $self->splice( $index, 1); |
418
|
|
|
|
|
|
|
} |
419
|
|
|
|
|
|
|
|
420
|
|
|
|
|
|
|
# R E P L A C E B Y N A M E --------------------------------------------- |
421
|
|
|
|
|
|
|
|
422
|
|
|
|
|
|
|
=item B |
423
|
|
|
|
|
|
|
|
424
|
|
|
|
|
|
|
Replace FITS header cards with keyword $keyword with card $item |
425
|
|
|
|
|
|
|
|
426
|
|
|
|
|
|
|
$card = $header->replacebyname($keyword, $item); |
427
|
|
|
|
|
|
|
|
428
|
|
|
|
|
|
|
returns the replaced card. The keyword may be a regular expression |
429
|
|
|
|
|
|
|
created with the C operator. |
430
|
|
|
|
|
|
|
|
431
|
|
|
|
|
|
|
=cut |
432
|
|
|
|
|
|
|
|
433
|
|
|
|
|
|
|
sub replacebyname{ |
434
|
1
|
|
|
1
|
1
|
655
|
my ($self, $keyword, $item) = @_; |
435
|
|
|
|
|
|
|
|
436
|
|
|
|
|
|
|
# grab the index array from lookup table |
437
|
1
|
|
|
|
|
6
|
my @index = $self->index($keyword); |
438
|
|
|
|
|
|
|
|
439
|
|
|
|
|
|
|
# loop over the keywords |
440
|
|
|
|
|
|
|
# We use a real splice rather than the class splice for efficiency |
441
|
|
|
|
|
|
|
# in order to prevent an index rebuild for each index |
442
|
1
|
|
|
|
|
10
|
my @cards = map { splice @{$self->{HEADER}}, $_, 1, $item;} @index; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
5
|
|
443
|
|
|
|
|
|
|
|
444
|
|
|
|
|
|
|
# force rebuild |
445
|
1
|
|
|
|
|
8
|
$self->_rebuild_lookup; |
446
|
|
|
|
|
|
|
|
447
|
|
|
|
|
|
|
# return removed items |
448
|
1
|
50
|
|
|
|
7
|
return wantarray ? @cards : $cards[scalar(@cards)-1]; |
449
|
|
|
|
|
|
|
|
450
|
|
|
|
|
|
|
} |
451
|
|
|
|
|
|
|
|
452
|
|
|
|
|
|
|
# R E M O V E B Y N A M E ----------------------------------------------- |
453
|
|
|
|
|
|
|
|
454
|
|
|
|
|
|
|
=item B |
455
|
|
|
|
|
|
|
|
456
|
|
|
|
|
|
|
Removes a FITS header card object by name |
457
|
|
|
|
|
|
|
|
458
|
|
|
|
|
|
|
@card = $header->removebyname($keyword); |
459
|
|
|
|
|
|
|
|
460
|
|
|
|
|
|
|
returns the removed cards. The keyword may be a regular expression |
461
|
|
|
|
|
|
|
created with the C operator. |
462
|
|
|
|
|
|
|
|
463
|
|
|
|
|
|
|
=cut |
464
|
|
|
|
|
|
|
|
465
|
|
|
|
|
|
|
sub removebyname{ |
466
|
6
|
|
|
6
|
1
|
48
|
my ($self, $keyword) = @_; |
467
|
|
|
|
|
|
|
|
468
|
|
|
|
|
|
|
# grab the index array from lookup table |
469
|
6
|
|
|
|
|
17
|
my @index = $self->index($keyword); |
470
|
|
|
|
|
|
|
|
471
|
|
|
|
|
|
|
# loop over the keywords |
472
|
|
|
|
|
|
|
# We use a real splice rather than the class splice for efficiency |
473
|
|
|
|
|
|
|
# in order to prevent an index rebuild for each index. The ugly code |
474
|
|
|
|
|
|
|
# is needed in case we have multiple indices returned, which can |
475
|
|
|
|
|
|
|
# happen if we have a regular expression passed in as a keyword. |
476
|
6
|
|
|
|
|
25
|
my $i = -1; |
477
|
6
|
|
|
|
|
25
|
my @cards = map { $i++; splice @{$self->{HEADER}}, ( $_ - $i ), 1; } sort @index; |
|
11
|
|
|
|
|
18
|
|
|
11
|
|
|
|
|
16
|
|
|
11
|
|
|
|
|
33
|
|
478
|
|
|
|
|
|
|
|
479
|
|
|
|
|
|
|
# force rebuild |
480
|
6
|
|
|
|
|
26
|
$self->_rebuild_lookup; |
481
|
|
|
|
|
|
|
|
482
|
|
|
|
|
|
|
# return removed items |
483
|
6
|
50
|
|
|
|
49
|
return wantarray ? @cards : $cards[scalar(@cards)-1]; |
484
|
|
|
|
|
|
|
} |
485
|
|
|
|
|
|
|
|
486
|
|
|
|
|
|
|
# S P L I C E -------------------------------------------------------------- |
487
|
|
|
|
|
|
|
|
488
|
|
|
|
|
|
|
=item B |
489
|
|
|
|
|
|
|
|
490
|
|
|
|
|
|
|
Implements a standard splice operation for FITS headers |
491
|
|
|
|
|
|
|
|
492
|
|
|
|
|
|
|
@cards = $header->splice($offset [,$length [, @list]]); |
493
|
|
|
|
|
|
|
$last_card = $header->splice($offset [,$length [, @list]]); |
494
|
|
|
|
|
|
|
|
495
|
|
|
|
|
|
|
Removes the FITS header cards from the header designated by $offset and |
496
|
|
|
|
|
|
|
$length, and replaces them with @list (if specified) which must be an |
497
|
|
|
|
|
|
|
array of FITS::Header::Item objects. Returns the cards removed. If offset |
498
|
|
|
|
|
|
|
is negative, counts from the end of the FITS header. |
499
|
|
|
|
|
|
|
|
500
|
|
|
|
|
|
|
=cut |
501
|
|
|
|
|
|
|
|
502
|
|
|
|
|
|
|
sub splice { |
503
|
29
|
|
|
29
|
1
|
46
|
my $self = shift; |
504
|
29
|
|
|
|
|
57
|
my ($offset, $length, @list) = @_; |
505
|
|
|
|
|
|
|
|
506
|
|
|
|
|
|
|
# If the array is empty and we get a negative offset we |
507
|
|
|
|
|
|
|
# must convert it to an offset of 0 to prevent a: |
508
|
|
|
|
|
|
|
# Modification of non-creatable array value attempted, subscript -1 |
509
|
|
|
|
|
|
|
# fatal error |
510
|
|
|
|
|
|
|
# This can occur with a tied hash and the %{$tieref} = %new |
511
|
|
|
|
|
|
|
# construct |
512
|
29
|
50
|
|
|
|
78
|
if (defined $offset) { |
513
|
29
|
100
|
66
|
|
|
39
|
$offset = 0 if (@{$self->{HEADER}} == 0 && $offset < 0); |
|
29
|
|
|
|
|
92
|
|
514
|
|
|
|
|
|
|
} |
515
|
|
|
|
|
|
|
|
516
|
|
|
|
|
|
|
# the removed cards |
517
|
29
|
|
|
|
|
49
|
my @cards; |
518
|
|
|
|
|
|
|
|
519
|
29
|
100
|
|
|
|
64
|
if (@list) { |
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
520
|
|
|
|
|
|
|
# all arguments supplied |
521
|
24
|
|
|
|
|
38
|
my $n = 0; |
522
|
24
|
|
|
|
|
40
|
for my $i (@list) { |
523
|
24
|
50
|
|
|
|
87
|
croak "Argument $n to splice must be Astro::FITS::Header::Item objects" |
524
|
|
|
|
|
|
|
unless UNIVERSAL::isa($i, "Astro::FITS::Header::Item"); |
525
|
24
|
|
|
|
|
47
|
$n++; |
526
|
|
|
|
|
|
|
} |
527
|
24
|
|
|
|
|
31
|
@cards = splice @{$self->{HEADER}}, $offset, $length, @list; |
|
24
|
|
|
|
|
77
|
|
528
|
|
|
|
|
|
|
|
529
|
|
|
|
|
|
|
} elsif (defined $length) { |
530
|
|
|
|
|
|
|
# length and (presumably) offset |
531
|
5
|
|
|
|
|
9
|
@cards = splice @{$self->{HEADER}}, $offset, $length; |
|
5
|
|
|
|
|
17
|
|
532
|
|
|
|
|
|
|
|
533
|
|
|
|
|
|
|
} elsif (defined $offset) { |
534
|
|
|
|
|
|
|
# offset only |
535
|
0
|
|
|
|
|
0
|
@cards = splice @{$self->{HEADER}}, $offset; |
|
0
|
|
|
|
|
0
|
|
536
|
|
|
|
|
|
|
} else { |
537
|
|
|
|
|
|
|
# none |
538
|
0
|
|
|
|
|
0
|
@cards = splice @{$self->{HEADER}}; |
|
0
|
|
|
|
|
0
|
|
539
|
|
|
|
|
|
|
} |
540
|
|
|
|
|
|
|
|
541
|
|
|
|
|
|
|
# update the internal lookup table and return |
542
|
29
|
|
|
|
|
87
|
$self->_rebuild_lookup(); |
543
|
29
|
100
|
|
|
|
94
|
return wantarray ? @cards : $cards[scalar(@cards)-1]; |
544
|
|
|
|
|
|
|
} |
545
|
|
|
|
|
|
|
|
546
|
|
|
|
|
|
|
# C A R D S -------------------------------------------------------------- |
547
|
|
|
|
|
|
|
|
548
|
|
|
|
|
|
|
=item B |
549
|
|
|
|
|
|
|
|
550
|
|
|
|
|
|
|
Return the object contents as an array of FITS cards. |
551
|
|
|
|
|
|
|
|
552
|
|
|
|
|
|
|
@array = $header->cards; |
553
|
|
|
|
|
|
|
|
554
|
|
|
|
|
|
|
=cut |
555
|
|
|
|
|
|
|
|
556
|
|
|
|
|
|
|
sub cards { |
557
|
7
|
|
|
7
|
1
|
377
|
my $self = shift; |
558
|
7
|
|
|
|
|
24
|
return map { "$_" } @{$self->{HEADER}}; |
|
160
|
|
|
|
|
342
|
|
|
7
|
|
|
|
|
25
|
|
559
|
|
|
|
|
|
|
} |
560
|
|
|
|
|
|
|
|
561
|
|
|
|
|
|
|
=item B |
562
|
|
|
|
|
|
|
|
563
|
|
|
|
|
|
|
Returns the highest index in use in the FITS header. |
564
|
|
|
|
|
|
|
To get the total number of header items, add 1. |
565
|
|
|
|
|
|
|
|
566
|
|
|
|
|
|
|
$number = $header->sizeof; |
567
|
|
|
|
|
|
|
|
568
|
|
|
|
|
|
|
=cut |
569
|
|
|
|
|
|
|
|
570
|
|
|
|
|
|
|
sub sizeof { |
571
|
13
|
|
|
13
|
1
|
1570
|
my $self = shift; |
572
|
13
|
|
|
|
|
23
|
return $#{$self->{HEADER}}; |
|
13
|
|
|
|
|
82
|
|
573
|
|
|
|
|
|
|
} |
574
|
|
|
|
|
|
|
|
575
|
|
|
|
|
|
|
# A L L I T E M S --------------------------------------------------------- |
576
|
|
|
|
|
|
|
|
577
|
|
|
|
|
|
|
=item B |
578
|
|
|
|
|
|
|
|
579
|
|
|
|
|
|
|
Returns the header as an array of FITS::Header:Item objects. |
580
|
|
|
|
|
|
|
|
581
|
|
|
|
|
|
|
@items = $header->allitems(); |
582
|
|
|
|
|
|
|
|
583
|
|
|
|
|
|
|
=cut |
584
|
|
|
|
|
|
|
|
585
|
|
|
|
|
|
|
sub allitems { |
586
|
19
|
|
|
19
|
1
|
36
|
my $self = shift; |
587
|
19
|
|
|
|
|
28
|
return map { $_ } @{$self->{HEADER}}; |
|
750
|
|
|
|
|
1049
|
|
|
19
|
|
|
|
|
46
|
|
588
|
|
|
|
|
|
|
} |
589
|
|
|
|
|
|
|
|
590
|
|
|
|
|
|
|
# C O N F I G U R E ------------------------------------------------------- |
591
|
|
|
|
|
|
|
|
592
|
|
|
|
|
|
|
=back |
593
|
|
|
|
|
|
|
|
594
|
|
|
|
|
|
|
=head2 General Methods |
595
|
|
|
|
|
|
|
|
596
|
|
|
|
|
|
|
=over 4 |
597
|
|
|
|
|
|
|
|
598
|
|
|
|
|
|
|
=item B |
599
|
|
|
|
|
|
|
|
600
|
|
|
|
|
|
|
Configures the object, takes an array of FITS header cards, |
601
|
|
|
|
|
|
|
an array of Astro::FITS::Header::Item objects or a simple hash as input. |
602
|
|
|
|
|
|
|
If you feed in nothing at all, it uses a default array containing |
603
|
|
|
|
|
|
|
just the SIMPLE card required at the top of all FITS files. |
604
|
|
|
|
|
|
|
|
605
|
|
|
|
|
|
|
$header->configure( Cards => \@array ); |
606
|
|
|
|
|
|
|
$header->configure( Items => \@array ); |
607
|
|
|
|
|
|
|
$header->configure( Hash => \%hash ); |
608
|
|
|
|
|
|
|
|
609
|
|
|
|
|
|
|
Does nothing if the array is not supplied. If the hash scheme is used |
610
|
|
|
|
|
|
|
and the hash contains the special key of SUBHEADERS pointing to an |
611
|
|
|
|
|
|
|
array of hashes, these will be read as proper sub headers. All other |
612
|
|
|
|
|
|
|
references in the hash will be ignored. Note that the default key |
613
|
|
|
|
|
|
|
order will be retained in the object created via the hash. |
614
|
|
|
|
|
|
|
|
615
|
|
|
|
|
|
|
=cut |
616
|
|
|
|
|
|
|
|
617
|
|
|
|
|
|
|
sub configure { |
618
|
42
|
|
|
42
|
1
|
80
|
my $self = shift; |
619
|
|
|
|
|
|
|
|
620
|
|
|
|
|
|
|
# grab the argument list |
621
|
42
|
|
|
|
|
101
|
my %args = @_; |
622
|
|
|
|
|
|
|
|
623
|
42
|
100
|
66
|
|
|
183
|
if (exists $args{Cards} && defined $args{Cards}) { |
|
|
50
|
33
|
|
|
|
|
|
|
50
|
33
|
|
|
|
|
|
|
0
|
0
|
|
|
|
|
624
|
|
|
|
|
|
|
|
625
|
|
|
|
|
|
|
# First translate each incoming card into a Item object |
626
|
|
|
|
|
|
|
# Any existing cards are removed |
627
|
40
|
|
|
|
|
383
|
@{$self->{HEADER}} = map { |
628
|
1284
|
|
|
|
|
2802
|
new Astro::FITS::Header::Item( Card => $_ ); |
629
|
40
|
|
|
|
|
57
|
} @{ $args{Cards} }; |
|
40
|
|
|
|
|
86
|
|
630
|
|
|
|
|
|
|
|
631
|
|
|
|
|
|
|
# Now build the lookup table. There would be a slight efficiency |
632
|
|
|
|
|
|
|
# gain to include this in a loop over the cards but prefer |
633
|
|
|
|
|
|
|
# to reuse the method for this rather than repeating code |
634
|
40
|
|
|
|
|
132
|
$self->_rebuild_lookup; |
635
|
|
|
|
|
|
|
|
636
|
|
|
|
|
|
|
} elsif (exists $args{Items} && defined $args{Items}) { |
637
|
|
|
|
|
|
|
# We have an array of Astro::FITS::Header::Items |
638
|
0
|
|
|
|
|
0
|
@{$self->{HEADER}} = @{ $args{Items} }; |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
639
|
0
|
|
|
|
|
0
|
$self->_rebuild_lookup; |
640
|
|
|
|
|
|
|
} elsif (exists $args{Hash} && defined $args{Hash} ) { |
641
|
|
|
|
|
|
|
# we have a hash so convert to Item objects and store |
642
|
|
|
|
|
|
|
# use a For loop instead of map since we want to |
643
|
|
|
|
|
|
|
# skip some items |
644
|
|
|
|
|
|
|
croak "Hash constructor requested but not given a hash reference" |
645
|
2
|
50
|
|
|
|
6
|
unless ref($args{Hash}) eq 'HASH'; |
646
|
2
|
|
|
|
|
3
|
my @items; |
647
|
|
|
|
|
|
|
my @subheaders; |
648
|
2
|
|
|
|
|
3
|
for my $k (keys %{$args{Hash}}) { |
|
2
|
|
|
|
|
8
|
|
649
|
2
|
50
|
33
|
|
|
9
|
if ($k eq 'SUBHEADERS' |
|
|
50
|
33
|
|
|
|
|
650
|
|
|
|
|
|
|
&& ref($args{Hash}->{$k}) eq 'ARRAY' |
651
|
|
|
|
|
|
|
&& ref($args{Hash}->{$k}->[0]) eq 'HASH') { |
652
|
|
|
|
|
|
|
# special case |
653
|
0
|
|
|
|
|
0
|
@subheaders = map { $self->new( Hash => $_ ) } @{$args{Hash}->{$k}}; |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
654
|
|
|
|
|
|
|
} elsif (not ref($args{Hash}->{$k})) { |
655
|
|
|
|
|
|
|
# if we have new lines in the value, we should duplicate the item |
656
|
|
|
|
|
|
|
# so split on new lines |
657
|
2
|
|
|
|
|
4
|
my $value = $args{Hash}->{$k}; |
658
|
2
|
50
|
|
|
|
4
|
$value = '' unless defined $value; |
659
|
2
|
|
|
|
|
6
|
my @lines = split(/^/m,$value); |
660
|
2
|
|
|
|
|
4
|
chomp(@lines); # remove the newlines |
661
|
|
|
|
|
|
|
|
662
|
2
|
|
|
|
|
4
|
push(@items, map { new Astro::FITS::Header::Item( Keyword => $k, |
|
2
|
|
|
|
|
5
|
|
663
|
|
|
|
|
|
|
Value => $_ ) } |
664
|
|
|
|
|
|
|
@lines); |
665
|
|
|
|
|
|
|
} |
666
|
|
|
|
|
|
|
} |
667
|
2
|
|
|
|
|
3
|
@{$self->{HEADER}} = @items; |
|
2
|
|
|
|
|
5
|
|
668
|
2
|
|
|
|
|
7
|
$self->_rebuild_lookup; |
669
|
2
|
50
|
|
|
|
7
|
$self->subhdrs(@subheaders) if @subheaders; |
670
|
|
|
|
|
|
|
} elsif ( !defined($self->{HEADER}) || !@{$self->{HEADER}} ) { |
671
|
0
|
|
|
|
|
0
|
@{$self->{HEADER}} = ( |
|
0
|
|
|
|
|
0
|
|
672
|
|
|
|
|
|
|
new Astro::FITS::Header::Item( Card=> "SIMPLE = T"), |
673
|
|
|
|
|
|
|
new Astro::FITS::Header::Item( Card=> "END", Type=>"END" ) |
674
|
|
|
|
|
|
|
); |
675
|
0
|
|
|
|
|
0
|
$self->_rebuild_lookup; |
676
|
|
|
|
|
|
|
} |
677
|
|
|
|
|
|
|
} |
678
|
|
|
|
|
|
|
|
679
|
|
|
|
|
|
|
=item B |
680
|
|
|
|
|
|
|
|
681
|
|
|
|
|
|
|
Given the current header and a set of C objects, |
682
|
|
|
|
|
|
|
return a merged FITS header (with the cards that have the same value |
683
|
|
|
|
|
|
|
and comment across all headers) along with, for each input, header |
684
|
|
|
|
|
|
|
objects containing all the header items that differ (including, by |
685
|
|
|
|
|
|
|
default, keys that are not present in all headers). Only the primary |
686
|
|
|
|
|
|
|
headers are merged, subheaders are ignored. |
687
|
|
|
|
|
|
|
|
688
|
|
|
|
|
|
|
($clone) = $headerr->merge_primary(); |
689
|
|
|
|
|
|
|
($same, @different) = $header->merge_primary( $fits1, $fits2, ...); |
690
|
|
|
|
|
|
|
($same, @different) = $header->merge_primary( \%options, $fits1, $fits2 ); |
691
|
|
|
|
|
|
|
|
692
|
|
|
|
|
|
|
@different can be empty if all headers match (but see the |
693
|
|
|
|
|
|
|
C option) but if any headers are different there |
694
|
|
|
|
|
|
|
will always be the same number of headers in @different as supplied to |
695
|
|
|
|
|
|
|
the function (including the reference header). A clone of the input header |
696
|
|
|
|
|
|
|
(stripped of any subheaders) is returned if no comparison headers are |
697
|
|
|
|
|
|
|
supplied. |
698
|
|
|
|
|
|
|
|
699
|
|
|
|
|
|
|
In scalar context, just returns the merged header. |
700
|
|
|
|
|
|
|
|
701
|
|
|
|
|
|
|
$merged = $header->merge_primary( @hdrs ); |
702
|
|
|
|
|
|
|
|
703
|
|
|
|
|
|
|
The options hash is itself optional. It contains the following keys: |
704
|
|
|
|
|
|
|
|
705
|
|
|
|
|
|
|
merge_unique - if an item is identical across multiple headers and only |
706
|
|
|
|
|
|
|
exists in those headers, propagate to the merged header rather |
707
|
|
|
|
|
|
|
than storing it in the difference headers. |
708
|
|
|
|
|
|
|
|
709
|
|
|
|
|
|
|
force_return_diffs - return an empty difference object per input header |
710
|
|
|
|
|
|
|
even if there are no diffs |
711
|
|
|
|
|
|
|
|
712
|
|
|
|
|
|
|
=cut |
713
|
|
|
|
|
|
|
|
714
|
|
|
|
|
|
|
sub merge_primary { |
715
|
8
|
|
|
8
|
1
|
1772
|
my $self = shift; |
716
|
|
|
|
|
|
|
|
717
|
|
|
|
|
|
|
# optional options handling |
718
|
8
|
|
|
|
|
25
|
my %opt = ( merge_unique => 0, |
719
|
|
|
|
|
|
|
force_return_diffs => 0, |
720
|
|
|
|
|
|
|
); |
721
|
8
|
100
|
|
|
|
26
|
if (ref($_[0]) eq 'HASH') { |
722
|
3
|
|
|
|
|
7
|
my $o = shift; |
723
|
3
|
|
|
|
|
15
|
%opt = ( %opt, %$o ); |
724
|
|
|
|
|
|
|
} |
725
|
|
|
|
|
|
|
|
726
|
|
|
|
|
|
|
# everything else is fits headers |
727
|
|
|
|
|
|
|
# If we do not get any additional headers we still process the full header |
728
|
|
|
|
|
|
|
# rather than shortcircuiting the logic. This is so that we can strip |
729
|
|
|
|
|
|
|
# HEADER items without having to write duplicate logic. Clearly not |
730
|
|
|
|
|
|
|
# very efficient but we do not really expect people to use this method |
731
|
|
|
|
|
|
|
# to clone a FITS header.... |
732
|
8
|
|
|
|
|
26
|
my @fits = @_; |
733
|
|
|
|
|
|
|
|
734
|
|
|
|
|
|
|
# Number of output diff arrays |
735
|
|
|
|
|
|
|
# Include this object |
736
|
8
|
|
|
|
|
19
|
my $nhdr = @fits + 1; |
737
|
|
|
|
|
|
|
|
738
|
|
|
|
|
|
|
# Go through all the items building up a hash indexed |
739
|
|
|
|
|
|
|
# by KEYWORD pointing to an array of items with that keyword |
740
|
|
|
|
|
|
|
# and an array of unique keywords in the original order they |
741
|
|
|
|
|
|
|
# appeared first. COMMENT items are stored in the |
742
|
|
|
|
|
|
|
# hash as complete cards. |
743
|
|
|
|
|
|
|
# HEADER items are currently dropped on the floor. |
744
|
8
|
|
|
|
|
13
|
my @order; |
745
|
|
|
|
|
|
|
my %items; |
746
|
8
|
|
|
|
|
14
|
my $hnum = 0; |
747
|
8
|
|
|
|
|
19
|
for my $hdr ($self, @fits) { |
748
|
17
|
|
|
|
|
37
|
for my $item ($hdr->allitems) { |
749
|
373
|
|
|
|
|
506
|
my $key; |
750
|
373
|
|
|
|
|
691
|
my $type = $item->type; |
751
|
373
|
50
|
33
|
|
|
1245
|
if (!defined $type || $type eq 'BLANK') { |
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
752
|
|
|
|
|
|
|
# blank line so skip it |
753
|
0
|
|
|
|
|
0
|
next; |
754
|
|
|
|
|
|
|
} elsif ($type eq 'COMMENT') { |
755
|
30
|
|
|
|
|
63
|
$key = $item->card; |
756
|
|
|
|
|
|
|
} elsif ($type eq 'HEADER') { |
757
|
0
|
|
|
|
|
0
|
next; |
758
|
|
|
|
|
|
|
} else { |
759
|
343
|
|
|
|
|
1949
|
$key = $item->keyword; |
760
|
|
|
|
|
|
|
} |
761
|
|
|
|
|
|
|
|
762
|
373
|
100
|
|
|
|
692
|
if (exists $items{$key}) { |
763
|
|
|
|
|
|
|
# Store the item, but in a hash with key corresponding |
764
|
|
|
|
|
|
|
# to the input header number |
765
|
197
|
|
|
|
|
251
|
push( @{ $items{$key}}, { item => $item, hnum => $hnum } ); |
|
197
|
|
|
|
|
605
|
|
766
|
|
|
|
|
|
|
} else { |
767
|
176
|
|
|
|
|
461
|
$items{$key} = [ { item => $item, hnum => $hnum } ]; |
768
|
176
|
|
|
|
|
359
|
push(@order, $key); |
769
|
|
|
|
|
|
|
} |
770
|
|
|
|
|
|
|
} |
771
|
17
|
|
|
|
|
62
|
$hnum++; |
772
|
|
|
|
|
|
|
} |
773
|
|
|
|
|
|
|
|
774
|
|
|
|
|
|
|
# create merged and difference arrays |
775
|
8
|
|
|
|
|
17
|
my @merged; |
776
|
8
|
|
|
|
|
23
|
my @difference = map { [] } (1..$nhdr); |
|
17
|
|
|
|
|
37
|
|
777
|
|
|
|
|
|
|
|
778
|
|
|
|
|
|
|
# Now loop over all of the unique keywords (taking care to |
779
|
|
|
|
|
|
|
# spot comments) |
780
|
8
|
|
|
|
|
17
|
for my $key (@order) { |
781
|
176
|
|
|
|
|
243
|
my @items = @{$items{$key}}; |
|
176
|
|
|
|
|
332
|
|
782
|
|
|
|
|
|
|
|
783
|
|
|
|
|
|
|
# compare each Item with the first. This will work even if we only have |
784
|
|
|
|
|
|
|
# one Item in the array. |
785
|
|
|
|
|
|
|
# Note that $match == 1 to start with because it always matches itself |
786
|
|
|
|
|
|
|
# but we do not bother doing the with-itself comparison. |
787
|
176
|
|
|
|
|
232
|
my $match = 1; |
788
|
176
|
|
|
|
|
317
|
for my $i (@items[1..$#items]) { |
789
|
|
|
|
|
|
|
# Ask the Items to compare using the equals() method |
790
|
197
|
100
|
|
|
|
437
|
if ($items[0]->{item}->equals( $i->{item} )) { |
791
|
184
|
|
|
|
|
377
|
$match++; |
792
|
|
|
|
|
|
|
} |
793
|
|
|
|
|
|
|
} |
794
|
|
|
|
|
|
|
|
795
|
|
|
|
|
|
|
# if we matched all the items and are merging unique OR if we |
796
|
|
|
|
|
|
|
# matched all the items and that was all the available headers |
797
|
|
|
|
|
|
|
# we store in the merged array. Else we store in the differences |
798
|
|
|
|
|
|
|
# array |
799
|
176
|
100
|
100
|
|
|
567
|
if ($match == @items && ($match == $nhdr || $opt{merge_unique})) { |
|
|
|
100
|
|
|
|
|
800
|
|
|
|
|
|
|
# Matched all the headers or merging matching unique headers |
801
|
|
|
|
|
|
|
# only need to store one |
802
|
165
|
|
|
|
|
339
|
push(@merged, $items[0]->{item}); |
803
|
|
|
|
|
|
|
|
804
|
|
|
|
|
|
|
} else { |
805
|
|
|
|
|
|
|
# Not enough of the items matched. Store to the relevant difference |
806
|
|
|
|
|
|
|
# arrays. |
807
|
11
|
|
|
|
|
33
|
for my $i (@items) { |
808
|
26
|
|
|
|
|
45
|
push(@{ $difference[$i->{hnum}] }, $i->{item}); |
|
26
|
|
|
|
|
90
|
|
809
|
|
|
|
|
|
|
} |
810
|
|
|
|
|
|
|
|
811
|
|
|
|
|
|
|
} |
812
|
|
|
|
|
|
|
|
813
|
|
|
|
|
|
|
} |
814
|
|
|
|
|
|
|
|
815
|
|
|
|
|
|
|
# and clear @difference in the special case where none have any headers |
816
|
8
|
100
|
|
|
|
19
|
if (!$opt{force_return_diffs}) { |
817
|
7
|
100
|
|
|
|
15
|
@difference = () unless grep { @$_ != 0 } @difference; |
|
15
|
|
|
|
|
45
|
|
818
|
|
|
|
|
|
|
} |
819
|
|
|
|
|
|
|
|
820
|
|
|
|
|
|
|
# unshift @merged onto the front of @difference in preparation |
821
|
|
|
|
|
|
|
# for returning it |
822
|
8
|
|
|
|
|
20
|
unshift(@difference, \@merged ); |
823
|
|
|
|
|
|
|
|
824
|
|
|
|
|
|
|
# convert back to FITS object, Construct using the Items directly |
825
|
|
|
|
|
|
|
# - they will be copied without strinfication. |
826
|
8
|
|
|
|
|
17
|
for my $d (@difference) { |
827
|
21
|
|
|
|
|
41
|
$d = $self->new( Cards => $d ); |
828
|
|
|
|
|
|
|
} |
829
|
|
|
|
|
|
|
|
830
|
|
|
|
|
|
|
# remembering that the merged array is on the front |
831
|
8
|
100
|
|
|
|
197
|
return (wantarray ? @difference : $difference[0]); |
832
|
|
|
|
|
|
|
} |
833
|
|
|
|
|
|
|
|
834
|
|
|
|
|
|
|
=item B |
835
|
|
|
|
|
|
|
|
836
|
|
|
|
|
|
|
Method to return a blessed reference to the object so that we can store |
837
|
|
|
|
|
|
|
ths object on disk using Data::Dumper module. |
838
|
|
|
|
|
|
|
|
839
|
|
|
|
|
|
|
=cut |
840
|
|
|
|
|
|
|
|
841
|
|
|
|
|
|
|
sub freeze { |
842
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
843
|
0
|
|
|
|
|
0
|
return bless $self, 'Astro::FITS::Header'; |
844
|
|
|
|
|
|
|
} |
845
|
|
|
|
|
|
|
|
846
|
|
|
|
|
|
|
=item B |
847
|
|
|
|
|
|
|
|
848
|
|
|
|
|
|
|
Append or update a card. |
849
|
|
|
|
|
|
|
|
850
|
|
|
|
|
|
|
$header->append( $card ); |
851
|
|
|
|
|
|
|
|
852
|
|
|
|
|
|
|
This method can take either an Astro::FITS::Header::Item object, an |
853
|
|
|
|
|
|
|
Astro::FITS::Header object, or a reference to an array of |
854
|
|
|
|
|
|
|
Astro::FITS::Header::Item objects. |
855
|
|
|
|
|
|
|
|
856
|
|
|
|
|
|
|
In all cases, if the given Astro::FITS::Header::Item keyword exists in |
857
|
|
|
|
|
|
|
the header, then the value will be overwritten with the one passed to |
858
|
|
|
|
|
|
|
the method. Otherwise, the card will be appended to the end of the |
859
|
|
|
|
|
|
|
header. |
860
|
|
|
|
|
|
|
|
861
|
|
|
|
|
|
|
Nothing is returned. |
862
|
|
|
|
|
|
|
|
863
|
|
|
|
|
|
|
=cut |
864
|
|
|
|
|
|
|
|
865
|
|
|
|
|
|
|
sub append { |
866
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
867
|
0
|
|
|
|
|
0
|
my $thing = shift; |
868
|
|
|
|
|
|
|
|
869
|
0
|
|
|
|
|
0
|
my @cards; |
870
|
0
|
0
|
|
|
|
0
|
if ( UNIVERSAL::isa( $thing, "Astro::FITS::Header::Item" ) ) { |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
871
|
0
|
|
|
|
|
0
|
push @cards, $thing; |
872
|
|
|
|
|
|
|
} elsif ( UNIVERSAL::isa( $thing, "Astro::FITS::Header" ) ) { |
873
|
0
|
|
|
|
|
0
|
@cards = $thing->allitems; |
874
|
|
|
|
|
|
|
} elsif ( ref( $thing ) eq 'ARRAY' ) { |
875
|
0
|
|
|
|
|
0
|
@cards = @$thing; |
876
|
|
|
|
|
|
|
} |
877
|
|
|
|
|
|
|
|
878
|
0
|
|
|
|
|
0
|
foreach my $card ( @cards ) { |
879
|
0
|
|
|
|
|
0
|
my $item = $self->itembyname( $card->keyword ); |
880
|
0
|
0
|
|
|
|
0
|
if ( defined( $item ) ) { |
881
|
|
|
|
|
|
|
|
882
|
|
|
|
|
|
|
# Update the given card. |
883
|
0
|
|
|
|
|
0
|
$self->replacebyname( $card->keyword, $card ) |
884
|
|
|
|
|
|
|
|
885
|
|
|
|
|
|
|
} else { |
886
|
|
|
|
|
|
|
|
887
|
|
|
|
|
|
|
# Don't append a SIMPLE header as that can lead to disaster and |
888
|
|
|
|
|
|
|
# strife and gnashing of teeth (and violates the FITS standard). |
889
|
0
|
0
|
|
|
|
0
|
next if ( uc( $card->keyword ) eq 'SIMPLE' ); |
890
|
|
|
|
|
|
|
|
891
|
|
|
|
|
|
|
# Retrieve the index of the END card, and insert this card |
892
|
|
|
|
|
|
|
# before that one, but only if the END header actually exists. |
893
|
0
|
|
|
|
|
0
|
my $index = $self->index( 'END' ); |
894
|
0
|
0
|
|
|
|
0
|
$index = ( defined( $index ) ? $index : -1 ); |
895
|
0
|
|
|
|
|
0
|
$self->insert( $index, $card ); |
896
|
|
|
|
|
|
|
} |
897
|
|
|
|
|
|
|
} |
898
|
|
|
|
|
|
|
|
899
|
0
|
|
|
|
|
0
|
$self->_rebuild_lookup; |
900
|
|
|
|
|
|
|
} |
901
|
|
|
|
|
|
|
|
902
|
|
|
|
|
|
|
# P R I V A T E M E T H O D S ------------------------------------------ |
903
|
|
|
|
|
|
|
|
904
|
|
|
|
|
|
|
=back |
905
|
|
|
|
|
|
|
|
906
|
|
|
|
|
|
|
=head2 Operator Overloading |
907
|
|
|
|
|
|
|
|
908
|
|
|
|
|
|
|
These operators are overloaded: |
909
|
|
|
|
|
|
|
|
910
|
|
|
|
|
|
|
=over 4 |
911
|
|
|
|
|
|
|
|
912
|
|
|
|
|
|
|
=item B<""> |
913
|
|
|
|
|
|
|
|
914
|
|
|
|
|
|
|
When the object is used in a string context the FITS header |
915
|
|
|
|
|
|
|
block is returned as a single string. |
916
|
|
|
|
|
|
|
|
917
|
|
|
|
|
|
|
=cut |
918
|
|
|
|
|
|
|
|
919
|
|
|
|
|
|
|
sub stringify { |
920
|
5
|
|
|
5
|
0
|
25
|
my $self = shift; |
921
|
5
|
|
|
|
|
16
|
return join("\n", $self->cards )."\n"; |
922
|
|
|
|
|
|
|
} |
923
|
|
|
|
|
|
|
|
924
|
|
|
|
|
|
|
=back |
925
|
|
|
|
|
|
|
|
926
|
|
|
|
|
|
|
=head2 Private methods |
927
|
|
|
|
|
|
|
|
928
|
|
|
|
|
|
|
These methods are for internal use only. |
929
|
|
|
|
|
|
|
|
930
|
|
|
|
|
|
|
=over 4 |
931
|
|
|
|
|
|
|
|
932
|
|
|
|
|
|
|
=item B<_rebuild_lookup> |
933
|
|
|
|
|
|
|
|
934
|
|
|
|
|
|
|
Private function used to rebuild the lookup table after modifying the |
935
|
|
|
|
|
|
|
header block, its easier to do it this way than go through and add one |
936
|
|
|
|
|
|
|
to the indices of all header cards following the modified card. |
937
|
|
|
|
|
|
|
|
938
|
|
|
|
|
|
|
=cut |
939
|
|
|
|
|
|
|
|
940
|
|
|
|
|
|
|
sub _rebuild_lookup { |
941
|
78
|
|
|
78
|
|
131
|
my $self = shift; |
942
|
|
|
|
|
|
|
|
943
|
|
|
|
|
|
|
# rebuild the lookup table |
944
|
|
|
|
|
|
|
|
945
|
|
|
|
|
|
|
# empty the hash |
946
|
78
|
|
|
|
|
566
|
$self->{LOOKUP} = { }; |
947
|
|
|
|
|
|
|
|
948
|
|
|
|
|
|
|
# loop over the existing header array |
949
|
78
|
|
|
|
|
149
|
for my $j (0 .. $#{$self->{HEADER}}) { |
|
78
|
|
|
|
|
242
|
|
950
|
|
|
|
|
|
|
|
951
|
|
|
|
|
|
|
# grab the keyword from each header item; |
952
|
3538
|
|
|
|
|
4557
|
my $key = ${$self->{HEADER}}[$j]->keyword(); |
|
3538
|
|
|
|
|
7341
|
|
953
|
|
|
|
|
|
|
|
954
|
|
|
|
|
|
|
# need to account to repeated keywords (e.g. COMMENT) |
955
|
3538
|
100
|
66
|
|
|
4590
|
unless ( exists ${$self->{LOOKUP}}{$key} && |
|
3538
|
|
|
|
|
7613
|
|
956
|
84
|
|
|
|
|
236
|
defined ${$self->{LOOKUP}}{$key} ) { |
957
|
|
|
|
|
|
|
# new keyword |
958
|
3454
|
|
|
|
|
5315
|
${$self->{LOOKUP}}{$key} = [ $j ]; |
|
3454
|
|
|
|
|
7631
|
|
959
|
|
|
|
|
|
|
} else { |
960
|
|
|
|
|
|
|
# keyword exists, push the current index into the array |
961
|
84
|
|
|
|
|
112
|
push( @{${$self->{LOOKUP}}{$key}}, $j ); |
|
84
|
|
|
|
|
109
|
|
|
84
|
|
|
|
|
226
|
|
962
|
|
|
|
|
|
|
} |
963
|
|
|
|
|
|
|
} |
964
|
|
|
|
|
|
|
|
965
|
|
|
|
|
|
|
} |
966
|
|
|
|
|
|
|
|
967
|
|
|
|
|
|
|
# T I E D I N T E R F A C E ----------------------------------------------- |
968
|
|
|
|
|
|
|
|
969
|
|
|
|
|
|
|
=back |
970
|
|
|
|
|
|
|
|
971
|
|
|
|
|
|
|
=head1 TIED INTERFACE |
972
|
|
|
|
|
|
|
|
973
|
|
|
|
|
|
|
The C object can also be tied to a hash: |
974
|
|
|
|
|
|
|
|
975
|
|
|
|
|
|
|
use Astro::FITS::Header; |
976
|
|
|
|
|
|
|
|
977
|
|
|
|
|
|
|
$header = new Astro::FITS::Header( Cards => \@array ); |
978
|
|
|
|
|
|
|
tie %hash, "Astro::FITS::Header", $header |
979
|
|
|
|
|
|
|
|
980
|
|
|
|
|
|
|
$value = $hash{$keyword}; |
981
|
|
|
|
|
|
|
$hash{$keyword} = $value; |
982
|
|
|
|
|
|
|
|
983
|
|
|
|
|
|
|
print "keyword $keyword is present" if exists $hash{$keyword}; |
984
|
|
|
|
|
|
|
|
985
|
|
|
|
|
|
|
foreach my $key (keys %hash) { |
986
|
|
|
|
|
|
|
print "$key = $hash{$key}\n"; |
987
|
|
|
|
|
|
|
} |
988
|
|
|
|
|
|
|
|
989
|
|
|
|
|
|
|
=head2 Basic hash translation |
990
|
|
|
|
|
|
|
|
991
|
|
|
|
|
|
|
Header value type is determined on-the-fly by parsing of the input values. |
992
|
|
|
|
|
|
|
Anything that parses as a number or a logical is converted to that before |
993
|
|
|
|
|
|
|
being put in a card (but see below). |
994
|
|
|
|
|
|
|
|
995
|
|
|
|
|
|
|
Per-card comment fields can be accessed using the tied interface by specifying |
996
|
|
|
|
|
|
|
a key name of "key_COMMENT". This works because in general "_COMMENT" is too |
997
|
|
|
|
|
|
|
long to be confused with a normal key name. |
998
|
|
|
|
|
|
|
|
999
|
|
|
|
|
|
|
$comment = $hdr{CRPIX1_COMMENT}; |
1000
|
|
|
|
|
|
|
|
1001
|
|
|
|
|
|
|
will return the comment associated with CRPIX1 header item. The comment |
1002
|
|
|
|
|
|
|
can be modified in the same way: |
1003
|
|
|
|
|
|
|
|
1004
|
|
|
|
|
|
|
$hdr{CRPIX1_COMMENT} = "An axis"; |
1005
|
|
|
|
|
|
|
|
1006
|
|
|
|
|
|
|
You can also modify the comment by slash-delimiting it when setting the |
1007
|
|
|
|
|
|
|
associated keyword: |
1008
|
|
|
|
|
|
|
|
1009
|
|
|
|
|
|
|
$hdr{CRPIX1} = "34 / Set this field manually"; |
1010
|
|
|
|
|
|
|
|
1011
|
|
|
|
|
|
|
If you want an actual slash character in your string field you must escape |
1012
|
|
|
|
|
|
|
it with a backslash. (If you're in double quotes you have to use a double |
1013
|
|
|
|
|
|
|
backslash): |
1014
|
|
|
|
|
|
|
|
1015
|
|
|
|
|
|
|
$hdr{SLASHSTR} = 'foo\/bar / field contains "foo/bar"'; |
1016
|
|
|
|
|
|
|
|
1017
|
|
|
|
|
|
|
Keywords are CaSE-inNSEnSiTIvE, unlike normal hash keywords. All |
1018
|
|
|
|
|
|
|
keywords are translated to upper case internally, per the FITS standard. |
1019
|
|
|
|
|
|
|
|
1020
|
|
|
|
|
|
|
Aside from the SIMPLE and END keywords, which are automagically placed at |
1021
|
|
|
|
|
|
|
the beginning and end of the header respectively, keywords are included |
1022
|
|
|
|
|
|
|
in the header in the order received. This gives you a modicum of control |
1023
|
|
|
|
|
|
|
over card order, but if you actually care what order they're in, you |
1024
|
|
|
|
|
|
|
probably don't want the tied interface. |
1025
|
|
|
|
|
|
|
|
1026
|
|
|
|
|
|
|
=head2 Comment cards |
1027
|
|
|
|
|
|
|
|
1028
|
|
|
|
|
|
|
Comment cards are a special case because they have no normal value and |
1029
|
|
|
|
|
|
|
their comment field is treated as the hash value. The keywords |
1030
|
|
|
|
|
|
|
"COMMENT" and "HISTORY" are magic and refer to comment cards; nearly all other |
1031
|
|
|
|
|
|
|
keywords create normal valued cards. (see "SIMPLE and END cards", below). |
1032
|
|
|
|
|
|
|
|
1033
|
|
|
|
|
|
|
=head2 Multi-card values |
1034
|
|
|
|
|
|
|
|
1035
|
|
|
|
|
|
|
Multiline string values are broken up, one card per line in the |
1036
|
|
|
|
|
|
|
string. Extra-long string values are handled gracefully: they get |
1037
|
|
|
|
|
|
|
split among multiple cards, with a backslash at the end of each card |
1038
|
|
|
|
|
|
|
image. They're transparently reassembled when you access the data, so |
1039
|
|
|
|
|
|
|
that there is a strong analogy between multiline string values and multiple |
1040
|
|
|
|
|
|
|
cards. |
1041
|
|
|
|
|
|
|
|
1042
|
|
|
|
|
|
|
In general, appending to hash entries that look like strings does what |
1043
|
|
|
|
|
|
|
you think it should. In particular, comment cards have a newline |
1044
|
|
|
|
|
|
|
appended automatically on FETCH, so that |
1045
|
|
|
|
|
|
|
|
1046
|
|
|
|
|
|
|
$hash{HISTORY} .= "Added multi-line string support"; |
1047
|
|
|
|
|
|
|
|
1048
|
|
|
|
|
|
|
adds a new HISTORY comment card, while |
1049
|
|
|
|
|
|
|
|
1050
|
|
|
|
|
|
|
$hash{TELESCOP} .= " dome B"; |
1051
|
|
|
|
|
|
|
|
1052
|
|
|
|
|
|
|
only modifies an existing TELESCOP card. |
1053
|
|
|
|
|
|
|
|
1054
|
|
|
|
|
|
|
You can make multi-line values by feeding in newline-delimited |
1055
|
|
|
|
|
|
|
strings, or by assigning from an array ref. If you ask for a tag that |
1056
|
|
|
|
|
|
|
has a multiline value it's always expanded to a multiline string, even |
1057
|
|
|
|
|
|
|
if you fed in an array ref to start with. That's by design: multiline |
1058
|
|
|
|
|
|
|
string expansion often acts as though you are getting just the first |
1059
|
|
|
|
|
|
|
value back out, because perl string-to-number conversion stops at the |
1060
|
|
|
|
|
|
|
first newline. So: |
1061
|
|
|
|
|
|
|
|
1062
|
|
|
|
|
|
|
$hash{CDELT1} = [3,4,5]; |
1063
|
|
|
|
|
|
|
print $hash{CDELT1} + 99,"\n$hash{CDELT1}"; |
1064
|
|
|
|
|
|
|
|
1065
|
|
|
|
|
|
|
prints "102\n3\n4\n5", and then |
1066
|
|
|
|
|
|
|
|
1067
|
|
|
|
|
|
|
$hash{CDELT1}++; |
1068
|
|
|
|
|
|
|
print $hash{CDELT1}; |
1069
|
|
|
|
|
|
|
|
1070
|
|
|
|
|
|
|
prints "4". |
1071
|
|
|
|
|
|
|
|
1072
|
|
|
|
|
|
|
In short, most of the time you get what you want. But you can always fall |
1073
|
|
|
|
|
|
|
back on the non-tied interface by calling methods like so: |
1074
|
|
|
|
|
|
|
|
1075
|
|
|
|
|
|
|
((tied $hash)->method()) |
1076
|
|
|
|
|
|
|
|
1077
|
|
|
|
|
|
|
If you prefer to have multi-valued items automagically become array |
1078
|
|
|
|
|
|
|
refs, then you can get that behavior using the C method: |
1079
|
|
|
|
|
|
|
|
1080
|
|
|
|
|
|
|
tie %keywords, "Astro::FITS::Header", $header, tiereturnsref => 1; |
1081
|
|
|
|
|
|
|
|
1082
|
|
|
|
|
|
|
When tiereturnsref is true, multi-valued items will be returned via a |
1083
|
|
|
|
|
|
|
reference to an array (ties do not respect calling context). Note that |
1084
|
|
|
|
|
|
|
if this is configured you will have to test each return value to see |
1085
|
|
|
|
|
|
|
whether it is returning a real value or a reference to an array if you |
1086
|
|
|
|
|
|
|
are not sure whether there will be more than one card with a duplicate |
1087
|
|
|
|
|
|
|
name. |
1088
|
|
|
|
|
|
|
|
1089
|
|
|
|
|
|
|
=head2 Type forcing |
1090
|
|
|
|
|
|
|
|
1091
|
|
|
|
|
|
|
Because perl uses behind-the-scenes typing, there is an ambiguity |
1092
|
|
|
|
|
|
|
between strings and numeric and/or logical values: sometimes you want |
1093
|
|
|
|
|
|
|
to create a STRING card whose value could parse as a number or as a |
1094
|
|
|
|
|
|
|
logical value, and perl kindly parses it into a number for you. To |
1095
|
|
|
|
|
|
|
force string evaluation, feed in a trivial array ref: |
1096
|
|
|
|
|
|
|
|
1097
|
|
|
|
|
|
|
$hash{NUMSTR} = 123; # generates an INT card containing 123. |
1098
|
|
|
|
|
|
|
$hash{NUMSTR} = "123"; # generates an INT card containing 123. |
1099
|
|
|
|
|
|
|
$hash{NUMSTR} = ["123"]; # generates a STRING card containing "123". |
1100
|
|
|
|
|
|
|
$hash{NUMSTR} = [123]; # generates a STRING card containing "123". |
1101
|
|
|
|
|
|
|
|
1102
|
|
|
|
|
|
|
$hash{ALPHA} = "T"; # generates a LOGICAL card containing T. |
1103
|
|
|
|
|
|
|
$hash{ALPHA} = ["T"]; # generates a STRING card containing "T". |
1104
|
|
|
|
|
|
|
|
1105
|
|
|
|
|
|
|
Calls to keys() or each() will, by default, return the keywords in the order |
1106
|
|
|
|
|
|
|
in which they appear in the header. |
1107
|
|
|
|
|
|
|
|
1108
|
|
|
|
|
|
|
=head2 Sub-headers |
1109
|
|
|
|
|
|
|
|
1110
|
|
|
|
|
|
|
When the key refers to a subheader entry (ie an item of type |
1111
|
|
|
|
|
|
|
"HEADER"), a hash reference is returned. If a hash reference is |
1112
|
|
|
|
|
|
|
stored in a value it is converted to a C object. |
1113
|
|
|
|
|
|
|
|
1114
|
|
|
|
|
|
|
If the special key "SUBHEADERS" is used, it will return the array of |
1115
|
|
|
|
|
|
|
subheaders, (as stored using the C method) each of which will |
1116
|
|
|
|
|
|
|
be tied to a hash. Subheaders can be stored using normal array operations. |
1117
|
|
|
|
|
|
|
|
1118
|
|
|
|
|
|
|
=head2 SIMPLE and END cards |
1119
|
|
|
|
|
|
|
|
1120
|
|
|
|
|
|
|
No FITS interface would becomplete without special cases. |
1121
|
|
|
|
|
|
|
|
1122
|
|
|
|
|
|
|
When you assign to SIMPLE or END, the tied interface ensures that they |
1123
|
|
|
|
|
|
|
are first or last, respectively, in the deck -- as the FITS standard |
1124
|
|
|
|
|
|
|
requires. Other cards are inserted in between the first and last |
1125
|
|
|
|
|
|
|
elements, in the order that you define them. |
1126
|
|
|
|
|
|
|
|
1127
|
|
|
|
|
|
|
The SIMPLE card is forced to FITS LOGICAL (boolean) type. The FITS |
1128
|
|
|
|
|
|
|
standard forbids you from setting it to F, but you can if you want -- |
1129
|
|
|
|
|
|
|
we're not the FITS police. |
1130
|
|
|
|
|
|
|
|
1131
|
|
|
|
|
|
|
The END card is forced to a null type, so any value you assign to it |
1132
|
|
|
|
|
|
|
will fall on the floor. If present in the deck, the END keyword |
1133
|
|
|
|
|
|
|
always contains the value " ", which is both more-or-less invisible |
1134
|
|
|
|
|
|
|
when printed and also true -- so you can test the return value to see |
1135
|
|
|
|
|
|
|
if an END card is present. |
1136
|
|
|
|
|
|
|
|
1137
|
|
|
|
|
|
|
SIMPLE and END come pre-defined from the constructor. If for some |
1138
|
|
|
|
|
|
|
nefarious reason you want to remove them you must explicitly do so |
1139
|
|
|
|
|
|
|
with "delete" or the appropriate method call from the object |
1140
|
|
|
|
|
|
|
interface. |
1141
|
|
|
|
|
|
|
|
1142
|
|
|
|
|
|
|
=cut |
1143
|
|
|
|
|
|
|
|
1144
|
|
|
|
|
|
|
# List of known comment-type fields |
1145
|
|
|
|
|
|
|
%Astro::FITS::Header::COMMENT_FIELD = ( |
1146
|
|
|
|
|
|
|
"COMMENT"=>1, |
1147
|
|
|
|
|
|
|
"HISTORY"=>1 |
1148
|
|
|
|
|
|
|
); |
1149
|
|
|
|
|
|
|
|
1150
|
|
|
|
|
|
|
|
1151
|
|
|
|
|
|
|
# constructor |
1152
|
|
|
|
|
|
|
sub TIEHASH { |
1153
|
25
|
|
|
25
|
|
851
|
my ( $class, $obj, %options ) = @_; |
1154
|
25
|
|
|
|
|
44
|
my $newobj = bless $obj, $class; |
1155
|
|
|
|
|
|
|
|
1156
|
|
|
|
|
|
|
# Process options |
1157
|
25
|
|
|
|
|
58
|
for my $key (keys %options) { |
1158
|
2
|
|
|
|
|
5
|
my $method = lc($key); |
1159
|
2
|
50
|
|
|
|
14
|
if ($newobj->can($method)) { |
1160
|
2
|
|
|
|
|
16
|
$newobj->$method( $options{$key}); |
1161
|
|
|
|
|
|
|
} |
1162
|
|
|
|
|
|
|
} |
1163
|
|
|
|
|
|
|
|
1164
|
25
|
|
|
|
|
77
|
return $newobj; |
1165
|
|
|
|
|
|
|
} |
1166
|
|
|
|
|
|
|
|
1167
|
|
|
|
|
|
|
# fetch key and value pair |
1168
|
|
|
|
|
|
|
# MUST return undef if the key is missing else autovivification of |
1169
|
|
|
|
|
|
|
# sub header will fail |
1170
|
|
|
|
|
|
|
|
1171
|
|
|
|
|
|
|
sub FETCH { |
1172
|
180
|
|
|
180
|
|
17080
|
my ($self, $key) = @_; |
1173
|
|
|
|
|
|
|
|
1174
|
180
|
|
|
|
|
372
|
$key = uc($key); |
1175
|
|
|
|
|
|
|
|
1176
|
|
|
|
|
|
|
# if the key is called SUBHEADERS we should tie to an array |
1177
|
180
|
100
|
|
|
|
458
|
if ($key eq 'SUBHEADERS') { |
1178
|
2
|
|
|
|
|
4
|
my @dummy; |
1179
|
2
|
|
|
|
|
9
|
tie @dummy, "Astro::FITS::HeaderCollection", scalar $self->subhdrs; |
1180
|
2
|
|
|
|
|
11
|
return \@dummy; |
1181
|
|
|
|
|
|
|
} |
1182
|
|
|
|
|
|
|
|
1183
|
|
|
|
|
|
|
# If the key has a _COMMENT suffix we are looking for a comment |
1184
|
178
|
|
|
|
|
298
|
my $wantvalue = 1; |
1185
|
178
|
|
|
|
|
244
|
my $wantcomment = 0; |
1186
|
178
|
100
|
|
|
|
429
|
if ($key =~ /_COMMENT$/) { |
1187
|
6
|
|
|
|
|
11
|
$wantvalue = 0; |
1188
|
6
|
|
|
|
|
8
|
$wantcomment = 1; |
1189
|
|
|
|
|
|
|
# Remove suffix |
1190
|
6
|
|
|
|
|
22
|
$key =~ s/_COMMENT$//; |
1191
|
|
|
|
|
|
|
} |
1192
|
|
|
|
|
|
|
|
1193
|
|
|
|
|
|
|
# if we are of type COMMENT we want to retrieve the comment only |
1194
|
|
|
|
|
|
|
# if they're asking for $key_COMMENT. |
1195
|
178
|
|
|
|
|
319
|
my $item; |
1196
|
|
|
|
|
|
|
my $t_ok; |
1197
|
178
|
100
|
100
|
|
|
1098
|
if ( $wantcomment || $key =~ /^(COMMENT)|(HISTORY)$/ || $key =~ /^END$/) { |
|
|
|
100
|
|
|
|
|
1198
|
15
|
|
|
|
|
41
|
$item = ($self->itembyname($key))[0]; |
1199
|
15
|
|
100
|
|
|
57
|
$t_ok = (defined $item) && (defined $item->type); |
1200
|
15
|
100
|
100
|
|
|
45
|
$wantvalue = 0 if ($t_ok && ($item->type eq 'COMMENT')); |
1201
|
|
|
|
|
|
|
} |
1202
|
|
|
|
|
|
|
|
1203
|
|
|
|
|
|
|
# The END card is a special case. We always return " " for the value, |
1204
|
|
|
|
|
|
|
# and undef for the comment. |
1205
|
178
|
50
|
100
|
|
|
739
|
return ($wantvalue ? " " : undef) |
|
|
100
|
66
|
|
|
|
|
|
|
|
66
|
|
|
|
|
1206
|
|
|
|
|
|
|
if ( ($t_ok && ($item->type eq 'END')) || |
1207
|
|
|
|
|
|
|
((defined $item) && ($key eq 'END')) ); |
1208
|
|
|
|
|
|
|
|
1209
|
|
|
|
|
|
|
# Retrieve all the values/comments. Note that we go through the entire |
1210
|
|
|
|
|
|
|
# header for this in case of multiple matches |
1211
|
176
|
100
|
|
|
|
572
|
my @values = ($wantvalue ? $self->value( $key ) : $self->comment($key) ); |
1212
|
|
|
|
|
|
|
|
1213
|
|
|
|
|
|
|
# Return value depends on return context. If we have one value it does not |
1214
|
|
|
|
|
|
|
# matter, just return it. In list context want all the values, in scalar |
1215
|
|
|
|
|
|
|
# context join them all with a \n |
1216
|
|
|
|
|
|
|
# Note that in a TIED hash we do not have access to the calling context |
1217
|
|
|
|
|
|
|
# we are ALWAYS in scalar context. |
1218
|
176
|
|
|
|
|
260
|
my @out; |
1219
|
|
|
|
|
|
|
|
1220
|
|
|
|
|
|
|
# Sometimes we want the array to remain an array |
1221
|
176
|
100
|
|
|
|
378
|
if ($self->tiereturnsref) { |
1222
|
4
|
|
|
|
|
10
|
@out = @values; |
1223
|
|
|
|
|
|
|
} else { |
1224
|
|
|
|
|
|
|
|
1225
|
|
|
|
|
|
|
# Join everything together with a newline |
1226
|
|
|
|
|
|
|
# BUT we are careful here to prevent stringification of references |
1227
|
|
|
|
|
|
|
# at least for the case where we only have one value. We also must |
1228
|
|
|
|
|
|
|
# handle the case where we have no value to return (without turning |
1229
|
|
|
|
|
|
|
# it into a null string since that ruins autovivification of sub headers) |
1230
|
172
|
100
|
|
|
|
350
|
if (scalar(@values) <= 1) { |
1231
|
166
|
|
|
|
|
329
|
@out = @values; |
1232
|
|
|
|
|
|
|
} else { |
1233
|
|
|
|
|
|
|
|
1234
|
|
|
|
|
|
|
# Multi values so join [protecting warnings from undef] |
1235
|
6
|
50
|
|
|
|
13
|
@out = ( join("\n", map { defined $_ ? $_ : '' } @values) ); |
|
17
|
|
|
|
|
49
|
|
1236
|
|
|
|
|
|
|
|
1237
|
|
|
|
|
|
|
# This is a hangover from the STORE (where we add a \ continuation |
1238
|
|
|
|
|
|
|
# character to multiline strings) |
1239
|
6
|
50
|
|
|
|
22
|
$out[0] =~ s/\\\n//gs if (defined($out[0])); |
1240
|
|
|
|
|
|
|
} |
1241
|
|
|
|
|
|
|
} |
1242
|
|
|
|
|
|
|
|
1243
|
|
|
|
|
|
|
# COMMENT cards get a newline appended. |
1244
|
|
|
|
|
|
|
# (Whether this should happen is controversial, but it supports |
1245
|
|
|
|
|
|
|
# the "just append a string to get a new COMMENT card" behavior |
1246
|
|
|
|
|
|
|
# described in the documentation). |
1247
|
176
|
100
|
100
|
|
|
437
|
if ($t_ok && ($item->type eq 'COMMENT')) { |
1248
|
7
|
|
|
|
|
18
|
@out = map { $_ . "\n" } @out; |
|
12
|
|
|
|
|
36
|
|
1249
|
|
|
|
|
|
|
} |
1250
|
|
|
|
|
|
|
|
1251
|
|
|
|
|
|
|
# If we have a header we need to tie it to another hash |
1252
|
176
|
|
66
|
|
|
376
|
my $ishdr = ($t_ok && $item->type eq 'HEADER'); |
1253
|
176
|
|
|
|
|
318
|
for my $hdr (@out) { |
1254
|
177
|
100
|
66
|
|
|
1085
|
if ((UNIVERSAL::isa($hdr, "Astro::FITS::Header")) || $ishdr) { |
1255
|
11
|
|
|
|
|
15
|
my %header; |
1256
|
11
|
|
|
|
|
44
|
tie %header, ref($hdr), $hdr; |
1257
|
|
|
|
|
|
|
# Change in place |
1258
|
11
|
|
|
|
|
28
|
$hdr = \%header; |
1259
|
|
|
|
|
|
|
} |
1260
|
|
|
|
|
|
|
} |
1261
|
|
|
|
|
|
|
|
1262
|
|
|
|
|
|
|
# Can only return a scalar |
1263
|
|
|
|
|
|
|
# So return the first value if tiereturnsref is false. |
1264
|
|
|
|
|
|
|
# (by this point, all the values should be joined together into the |
1265
|
|
|
|
|
|
|
# first element anyway.) |
1266
|
176
|
|
|
|
|
272
|
my $out; |
1267
|
176
|
100
|
100
|
|
|
317
|
if ($self->tiereturnsref && scalar(@out) > 1) { |
1268
|
2
|
|
|
|
|
4
|
$out = \@out; |
1269
|
|
|
|
|
|
|
} else { |
1270
|
174
|
|
|
|
|
299
|
$out = $out[0]; |
1271
|
|
|
|
|
|
|
} |
1272
|
|
|
|
|
|
|
|
1273
|
176
|
|
|
|
|
774
|
return $out; |
1274
|
|
|
|
|
|
|
} |
1275
|
|
|
|
|
|
|
|
1276
|
|
|
|
|
|
|
# store key and value pair |
1277
|
|
|
|
|
|
|
# |
1278
|
|
|
|
|
|
|
# Multiple-line kludges (CED): |
1279
|
|
|
|
|
|
|
# |
1280
|
|
|
|
|
|
|
# * Array refs get handled gracefully by being put in as multiple cards. |
1281
|
|
|
|
|
|
|
# |
1282
|
|
|
|
|
|
|
# * Multiline strings get broken up and put in as multiple cards. |
1283
|
|
|
|
|
|
|
# |
1284
|
|
|
|
|
|
|
# * Extra-long strings get broken up and put in as multiple cards, with |
1285
|
|
|
|
|
|
|
# an extra backslash at the end so that they transparently get put back |
1286
|
|
|
|
|
|
|
# together upon retrieval. |
1287
|
|
|
|
|
|
|
# |
1288
|
|
|
|
|
|
|
|
1289
|
|
|
|
|
|
|
sub STORE { |
1290
|
22
|
|
|
22
|
|
7087
|
my ($self, $keyword, $value) = @_; |
1291
|
22
|
|
|
|
|
38
|
my @values; |
1292
|
|
|
|
|
|
|
|
1293
|
|
|
|
|
|
|
# Recognize slash-delimited comments in value keywords. This is done |
1294
|
|
|
|
|
|
|
# cheesily via recursion -- would be more efficient, but less readable, |
1295
|
|
|
|
|
|
|
# to propagate the comment through the code... |
1296
|
|
|
|
|
|
|
|
1297
|
|
|
|
|
|
|
# I think this is fundamentally flawed. If I store a string "foo/bar" |
1298
|
|
|
|
|
|
|
# in a hash and then read it back I expect to get "foo/bar" not "foo". |
1299
|
|
|
|
|
|
|
# I can not be expected to know that this hash happens to be tied to |
1300
|
|
|
|
|
|
|
# a FITS header that is trying to spot FITS item formatting. - TJ |
1301
|
|
|
|
|
|
|
|
1302
|
|
|
|
|
|
|
# Make sure that we do not stringify reference arguments by mistake |
1303
|
|
|
|
|
|
|
# when looking from slashes |
1304
|
|
|
|
|
|
|
|
1305
|
22
|
100
|
66
|
|
|
200
|
if (defined $value && !ref($value) && $keyword !~ m/(_COMMENT$)|(^(COMMENT|HISTORY)$)/ and |
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
1306
|
|
|
|
|
|
|
$value =~ s:\s*(?
|
1307
|
|
|
|
|
|
|
) { |
1308
|
2
|
|
|
|
|
7
|
my $comment = $1; |
1309
|
|
|
|
|
|
|
|
1310
|
|
|
|
|
|
|
# Recurse to store the comment. This is a direct (non-method) call to |
1311
|
|
|
|
|
|
|
# keep this method monolithic. --CED 27-Jun-2003 |
1312
|
2
|
|
|
|
|
13
|
STORE($self,$keyword."_COMMENT",$comment); |
1313
|
|
|
|
|
|
|
|
1314
|
|
|
|
|
|
|
} |
1315
|
|
|
|
|
|
|
|
1316
|
|
|
|
|
|
|
# unescape (unless we are blessed) |
1317
|
22
|
100
|
66
|
|
|
80
|
if (defined $value && !ref($value)) { |
1318
|
17
|
|
|
|
|
32
|
$value =~ s:\\\\:\\:g; |
1319
|
17
|
|
|
|
|
31
|
$value =~ s:\\\/:\/:g; |
1320
|
|
|
|
|
|
|
} |
1321
|
|
|
|
|
|
|
|
1322
|
|
|
|
|
|
|
# skip the shenanigans for the normal case |
1323
|
|
|
|
|
|
|
# or if we have an Astro::FITS::Header |
1324
|
22
|
50
|
66
|
|
|
189
|
if (!defined $value) { |
|
|
100
|
100
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
1325
|
0
|
|
|
|
|
0
|
@values = ($value); |
1326
|
|
|
|
|
|
|
|
1327
|
|
|
|
|
|
|
} elsif (UNIVERSAL::isa($value, "Astro::FITS::Header")) { |
1328
|
1
|
|
|
|
|
3
|
@values = ($value); |
1329
|
|
|
|
|
|
|
|
1330
|
|
|
|
|
|
|
} elsif (ref $value eq 'HASH') { |
1331
|
|
|
|
|
|
|
# Convert a hash to a Astro::FITS::Header |
1332
|
|
|
|
|
|
|
# If this is a tied hash already just get the object |
1333
|
3
|
|
|
|
|
6
|
my $tied = tied %$value; |
1334
|
3
|
100
|
66
|
|
|
11
|
if (defined $tied && UNIVERSAL::isa($tied, "Astro::FITS::Header")) { |
1335
|
|
|
|
|
|
|
# Just take the object |
1336
|
1
|
|
|
|
|
3
|
@values = ($tied); |
1337
|
|
|
|
|
|
|
} else { |
1338
|
|
|
|
|
|
|
# Convert it to a hash |
1339
|
2
|
|
|
|
|
5
|
@values = ( Astro::FITS::Header->new( Hash => $value ) ); |
1340
|
|
|
|
|
|
|
} |
1341
|
|
|
|
|
|
|
|
1342
|
|
|
|
|
|
|
} elsif ((ref $value eq 'ARRAY') || (length $value > 70) || $value =~ m/\n/s ) { |
1343
|
3
|
|
|
|
|
6
|
my @val; |
1344
|
|
|
|
|
|
|
# @val gets intermediate breakdowns, @values gets line-by-line breakdowns. |
1345
|
|
|
|
|
|
|
|
1346
|
|
|
|
|
|
|
# Change multiline strings into array refs |
1347
|
3
|
100
|
|
|
|
18
|
if (ref $value eq 'ARRAY') { |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
1348
|
1
|
|
|
|
|
18
|
@val = @$value; |
1349
|
|
|
|
|
|
|
|
1350
|
|
|
|
|
|
|
} elsif (ref $value) { |
1351
|
0
|
|
|
|
|
0
|
croak "Can't put non-array ref values into a tied FITS header\n"; |
1352
|
|
|
|
|
|
|
|
1353
|
|
|
|
|
|
|
} elsif ( $value =~ m/\n/s ) { |
1354
|
2
|
|
|
|
|
7
|
@val = split("\n",$value); |
1355
|
2
|
|
|
|
|
5
|
chomp @val; |
1356
|
|
|
|
|
|
|
|
1357
|
|
|
|
|
|
|
} else { |
1358
|
0
|
|
|
|
|
0
|
@val = $value; |
1359
|
|
|
|
|
|
|
} |
1360
|
|
|
|
|
|
|
|
1361
|
|
|
|
|
|
|
# Cut up really long items into multiline strings |
1362
|
3
|
|
|
|
|
5
|
my($val); |
1363
|
3
|
|
|
|
|
8
|
foreach $val(@val) { |
1364
|
8
|
|
|
|
|
18
|
while ((length $val) > 70) { |
1365
|
0
|
|
|
|
|
0
|
push(@values,substr($val,0,69)."\\"); |
1366
|
0
|
|
|
|
|
0
|
$val = substr($val,69); |
1367
|
|
|
|
|
|
|
} |
1368
|
8
|
|
|
|
|
17
|
push(@values,$val); |
1369
|
|
|
|
|
|
|
} |
1370
|
|
|
|
|
|
|
} ## End of complicated case |
1371
|
|
|
|
|
|
|
else { |
1372
|
|
|
|
|
|
|
|
1373
|
|
|
|
|
|
|
|
1374
|
|
|
|
|
|
|
|
1375
|
15
|
|
|
|
|
47
|
@values = ($value); |
1376
|
|
|
|
|
|
|
} |
1377
|
|
|
|
|
|
|
|
1378
|
|
|
|
|
|
|
# Upper case the relevant item name |
1379
|
22
|
|
|
|
|
48
|
$keyword = uc($keyword); |
1380
|
|
|
|
|
|
|
|
1381
|
22
|
100
|
|
|
|
60
|
if ($keyword eq 'END') { |
1382
|
|
|
|
|
|
|
# Special case for END keyword |
1383
|
|
|
|
|
|
|
# (drops value on floor, makes sure there is one END at the end) |
1384
|
1
|
|
|
|
|
4
|
my @index = $self->index($keyword); |
1385
|
1
|
50
|
33
|
|
|
6
|
if ( @index != 1 || $index[0] != $#{$self->allitems}) { |
|
0
|
|
|
|
|
0
|
|
1386
|
1
|
|
|
|
|
2
|
my $i; |
1387
|
1
|
|
|
|
|
6
|
while (defined($i = shift @index)) { |
1388
|
0
|
|
|
|
|
0
|
$self->remove($i); |
1389
|
|
|
|
|
|
|
} |
1390
|
|
|
|
|
|
|
} |
1391
|
1
|
50
|
|
|
|
3
|
unless( @index ) { |
1392
|
1
|
|
|
|
|
12
|
my $endcard = new Astro::FITS::Header::Item(Keyword=>'END', |
1393
|
|
|
|
|
|
|
Type=>'END', |
1394
|
|
|
|
|
|
|
Value=>1); |
1395
|
1
|
|
|
|
|
7
|
$self->insert( scalar ($self->allitems) , $endcard ); |
1396
|
|
|
|
|
|
|
} |
1397
|
1
|
|
|
|
|
4
|
return; |
1398
|
|
|
|
|
|
|
|
1399
|
|
|
|
|
|
|
} |
1400
|
|
|
|
|
|
|
|
1401
|
21
|
100
|
|
|
|
55
|
if ($keyword eq 'SIMPLE') { |
1402
|
|
|
|
|
|
|
# Special case for SIMPLE keyword |
1403
|
|
|
|
|
|
|
# (sets value correctly, makes sure there is one SIMPLE at the beginning) |
1404
|
1
|
|
|
|
|
6
|
my @index = $self->index($keyword); |
1405
|
1
|
50
|
33
|
|
|
8
|
if ( @index != 1 || $index[0] != 0) { |
1406
|
1
|
|
|
|
|
54
|
my $i; |
1407
|
1
|
|
|
|
|
39
|
while (defined ($i=shift @index)) { |
1408
|
0
|
|
|
|
|
0
|
$self->remove($i); |
1409
|
|
|
|
|
|
|
} |
1410
|
|
|
|
|
|
|
} |
1411
|
1
|
50
|
|
|
|
8
|
unless( @index ) { |
1412
|
1
|
|
|
|
|
19
|
my $simplecard = new Astro::FITS::Header::Item(Keyword=>'SIMPLE', |
1413
|
|
|
|
|
|
|
Value=>$values[0], |
1414
|
|
|
|
|
|
|
Type=>'LOGICAL'); |
1415
|
1
|
|
|
|
|
9
|
$self->insert(0, $simplecard); |
1416
|
|
|
|
|
|
|
} |
1417
|
1
|
|
|
|
|
6
|
return; |
1418
|
|
|
|
|
|
|
} |
1419
|
|
|
|
|
|
|
|
1420
|
|
|
|
|
|
|
|
1421
|
|
|
|
|
|
|
# Recognise _COMMENT |
1422
|
20
|
|
|
|
|
31
|
my $havevalue = 1; |
1423
|
20
|
100
|
|
|
|
46
|
if ($keyword =~ /_COMMENT$/) { |
1424
|
3
|
|
|
|
|
10
|
$keyword =~ s/_COMMENT$//; |
1425
|
3
|
|
|
|
|
6
|
$havevalue = 0; |
1426
|
|
|
|
|
|
|
} |
1427
|
|
|
|
|
|
|
|
1428
|
20
|
|
|
|
|
47
|
my @items = $self->itembyname($keyword); |
1429
|
|
|
|
|
|
|
|
1430
|
|
|
|
|
|
|
## Remove extra items if necessary |
1431
|
20
|
100
|
|
|
|
48
|
if (scalar(@items) > scalar(@values)) { |
1432
|
2
|
|
|
|
|
5
|
my(@indices) = $self->index($keyword); |
1433
|
2
|
|
|
|
|
4
|
my($i); |
1434
|
2
|
|
|
|
|
7
|
for $i (1..(scalar(@items) - scalar(@values))) { |
1435
|
3
|
|
|
|
|
8
|
$self->remove( $indices[-$i] ); |
1436
|
|
|
|
|
|
|
} |
1437
|
|
|
|
|
|
|
} |
1438
|
|
|
|
|
|
|
|
1439
|
|
|
|
|
|
|
## Allocate new items if necessary |
1440
|
20
|
|
|
|
|
56
|
while (scalar(@items) < scalar(@values)) { |
1441
|
|
|
|
|
|
|
|
1442
|
16
|
|
|
|
|
58
|
my $item = new Astro::FITS::Header::Item(Keyword=>$keyword,Value=>undef); |
1443
|
|
|
|
|
|
|
# (No need to set type here; Item does it for us) |
1444
|
|
|
|
|
|
|
|
1445
|
16
|
|
|
|
|
60
|
$self->insert(-1,$item); |
1446
|
16
|
|
|
|
|
40
|
push(@items,$item); |
1447
|
|
|
|
|
|
|
} |
1448
|
|
|
|
|
|
|
|
1449
|
|
|
|
|
|
|
## Set values or comments |
1450
|
20
|
|
|
|
|
41
|
my($i); |
1451
|
20
|
|
|
|
|
47
|
for $i(0..$#values) { |
1452
|
25
|
100
|
|
|
|
76
|
if ($Astro::FITS::Header::COMMENT_FIELD{$keyword}) { |
|
|
100
|
|
|
|
|
|
1453
|
6
|
|
|
|
|
15
|
$items[$i]->type('COMMENT'); |
1454
|
6
|
|
|
|
|
12
|
$items[$i]->comment($values[$i]); |
1455
|
|
|
|
|
|
|
} elsif (! $havevalue) { |
1456
|
|
|
|
|
|
|
# This is actually just changing the comment |
1457
|
3
|
|
|
|
|
21
|
$items[$i]->comment($values[$i]); |
1458
|
|
|
|
|
|
|
} else { |
1459
|
16
|
100
|
100
|
|
|
97
|
$items[$i]->type( (($#values > 0) || ref $value) ? 'STRING' : undef); |
1460
|
|
|
|
|
|
|
|
1461
|
16
|
|
|
|
|
81
|
$items[$i]->value($values[$i]); |
1462
|
16
|
100
|
|
|
|
94
|
$items[$i]->type("STRING") if($#values > 0); |
1463
|
|
|
|
|
|
|
} |
1464
|
|
|
|
|
|
|
} |
1465
|
|
|
|
|
|
|
} |
1466
|
|
|
|
|
|
|
|
1467
|
|
|
|
|
|
|
|
1468
|
|
|
|
|
|
|
# reports whether a key is present in the hash |
1469
|
|
|
|
|
|
|
# SUBHEADERS only exist if there are subheaders |
1470
|
|
|
|
|
|
|
sub EXISTS { |
1471
|
12
|
|
|
12
|
|
2825
|
my ($self, $keyword) = @_; |
1472
|
12
|
|
|
|
|
26
|
$keyword = uc($keyword); |
1473
|
|
|
|
|
|
|
|
1474
|
12
|
100
|
|
|
|
33
|
if ($keyword eq 'SUBHEADERS') { |
1475
|
3
|
100
|
|
|
|
7
|
return ( scalar(@{$self->subhdrs}) > 0 ? 1 : 0); |
|
3
|
|
|
|
|
9
|
|
1476
|
|
|
|
|
|
|
} |
1477
|
|
|
|
|
|
|
|
1478
|
9
|
100
|
|
|
|
12
|
if ( !exists( ${$self->{LOOKUP}}{$keyword} ) ) { |
|
9
|
|
|
|
|
28
|
|
1479
|
2
|
|
|
|
|
10
|
return undef; |
1480
|
|
|
|
|
|
|
} |
1481
|
|
|
|
|
|
|
|
1482
|
|
|
|
|
|
|
# if we are being asked for a keyword that is associated with a COMMENT or BLANK |
1483
|
|
|
|
|
|
|
# type we return FALSE for existence. An undef type means we have to assume a valid |
1484
|
|
|
|
|
|
|
# item with unknown type |
1485
|
7
|
50
|
|
|
|
11
|
if ( exists( ${$self->{LOOKUP}}{$keyword} ) ) { |
|
7
|
|
|
|
|
17
|
|
1486
|
7
|
|
|
|
|
11
|
my $item = ${$self->{HEADER}}[${$self->{LOOKUP}}{$keyword}[0]]; |
|
7
|
|
|
|
|
17
|
|
|
7
|
|
|
|
|
11
|
|
1487
|
7
|
|
|
|
|
19
|
my $type = $item->type; |
1488
|
7
|
100
|
66
|
|
|
40
|
return undef if (defined $type && ($type eq 'COMMENT' || $type eq 'BLANK') ); |
|
|
|
66
|
|
|
|
|
1489
|
|
|
|
|
|
|
} |
1490
|
|
|
|
|
|
|
|
1491
|
6
|
|
|
|
|
20
|
return 1; |
1492
|
|
|
|
|
|
|
|
1493
|
|
|
|
|
|
|
} |
1494
|
|
|
|
|
|
|
|
1495
|
|
|
|
|
|
|
# deletes a key and value pair |
1496
|
|
|
|
|
|
|
sub DELETE { |
1497
|
1
|
|
|
1
|
|
738
|
my ($self, $keyword) = @_; |
1498
|
1
|
|
|
|
|
4
|
return $self->removebyname($keyword); |
1499
|
|
|
|
|
|
|
} |
1500
|
|
|
|
|
|
|
|
1501
|
|
|
|
|
|
|
# empties the hash |
1502
|
|
|
|
|
|
|
sub CLEAR { |
1503
|
3
|
|
|
3
|
|
1241
|
my $self = shift; |
1504
|
3
|
|
|
|
|
78
|
$self->{HEADER} = [ ]; |
1505
|
3
|
|
|
|
|
26
|
$self->{LOOKUP} = { }; |
1506
|
3
|
|
|
|
|
7
|
$self->{LASTKEY} = undef; |
1507
|
3
|
|
|
|
|
20
|
$self->{SEENKEY} = undef; |
1508
|
3
|
|
|
|
|
15
|
$self->{SUBHDRS} = [ ]; |
1509
|
|
|
|
|
|
|
} |
1510
|
|
|
|
|
|
|
|
1511
|
|
|
|
|
|
|
# implements keys() and each() |
1512
|
|
|
|
|
|
|
sub FIRSTKEY { |
1513
|
9
|
|
|
9
|
|
1140
|
my $self = shift; |
1514
|
9
|
|
|
|
|
17
|
$self->{LASTKEY} = 0; |
1515
|
9
|
|
|
|
|
19
|
$self->{SEENKEY} = {}; |
1516
|
9
|
100
|
|
|
|
13
|
return $self->_check_for_subhdr() unless @{$self->{HEADER}}; |
|
9
|
|
|
|
|
30
|
|
1517
|
8
|
|
|
|
|
14
|
return ${$self->{HEADER}}[0]->keyword(); |
|
8
|
|
|
|
|
28
|
|
1518
|
|
|
|
|
|
|
} |
1519
|
|
|
|
|
|
|
|
1520
|
|
|
|
|
|
|
# implements keys() and each() |
1521
|
|
|
|
|
|
|
sub NEXTKEY { |
1522
|
147
|
|
|
147
|
|
306
|
my ($self, $keyword) = @_; |
1523
|
|
|
|
|
|
|
|
1524
|
|
|
|
|
|
|
# abort if the number of keys we have served equals the number in the |
1525
|
|
|
|
|
|
|
# header array. One wrinkle is that if we have SUBHDRS we want to go |
1526
|
|
|
|
|
|
|
# round one more time |
1527
|
|
|
|
|
|
|
|
1528
|
147
|
100
|
|
|
|
210
|
if ($self->{LASTKEY}+1 == scalar(@{$self->{HEADER}})) { |
|
147
|
|
|
|
|
283
|
|
1529
|
10
|
|
|
|
|
23
|
return $self->_check_for_subhdr(); |
1530
|
|
|
|
|
|
|
} |
1531
|
|
|
|
|
|
|
|
1532
|
|
|
|
|
|
|
# Skip later lines of multi-line cards since the tie interface |
1533
|
|
|
|
|
|
|
# will return all the lines for a single keyword request. |
1534
|
137
|
|
|
|
|
186
|
my($a); |
1535
|
|
|
|
|
|
|
do { |
1536
|
139
|
|
|
|
|
169
|
$self->{LASTKEY} += 1; |
1537
|
139
|
|
|
|
|
214
|
$a = $self->{HEADER}->[$self->{LASTKEY}]; |
1538
|
|
|
|
|
|
|
# Got to end of header if we do not have $a |
1539
|
139
|
50
|
|
|
|
376
|
return $self->_check_for_subhdr() unless defined $a; |
1540
|
137
|
|
|
|
|
180
|
} while ( $self->{SEENKEY}->{$a->keyword}); |
1541
|
137
|
|
|
|
|
268
|
$a = $a->keyword; |
1542
|
|
|
|
|
|
|
|
1543
|
137
|
|
|
|
|
232
|
$self->{SEENKEY}->{$a} = 1; |
1544
|
137
|
|
|
|
|
389
|
return $a; |
1545
|
|
|
|
|
|
|
} |
1546
|
|
|
|
|
|
|
|
1547
|
|
|
|
|
|
|
# called if we have run out of normal keys |
1548
|
|
|
|
|
|
|
# args: $self Returns: undef or "SUBHEADER" |
1549
|
|
|
|
|
|
|
sub _check_for_subhdr { |
1550
|
11
|
|
|
11
|
|
14
|
my $self = shift; |
1551
|
11
|
100
|
100
|
|
|
20
|
if (scalar(@{ $self->subhdrs}) && !$self->{SEENKEY}->{SUBHEADERS}) { |
|
11
|
|
|
|
|
22
|
|
1552
|
2
|
|
|
|
|
5
|
$self->{SEENKEY}->{SUBHEADERS} = 1; |
1553
|
2
|
|
|
|
|
7
|
return "SUBHEADERS"; |
1554
|
|
|
|
|
|
|
} |
1555
|
9
|
|
|
|
|
37
|
return undef; |
1556
|
|
|
|
|
|
|
} |
1557
|
|
|
|
|
|
|
|
1558
|
|
|
|
|
|
|
|
1559
|
|
|
|
|
|
|
# garbage collection |
1560
|
|
|
|
|
|
|
# sub DESTROY { } |
1561
|
|
|
|
|
|
|
|
1562
|
|
|
|
|
|
|
# T I M E A T T H E B A R -------------------------------------------- |
1563
|
|
|
|
|
|
|
|
1564
|
|
|
|
|
|
|
=head1 SEE ALSO |
1565
|
|
|
|
|
|
|
|
1566
|
|
|
|
|
|
|
C, C, |
1567
|
|
|
|
|
|
|
C, C. |
1568
|
|
|
|
|
|
|
|
1569
|
|
|
|
|
|
|
=head1 COPYRIGHT |
1570
|
|
|
|
|
|
|
|
1571
|
|
|
|
|
|
|
Copyright (C) 2007-2011 Science and Technology Facilties Council. |
1572
|
|
|
|
|
|
|
Copyright (C) 2001-2007 Particle Physics and Astronomy Research Council |
1573
|
|
|
|
|
|
|
and portions Copyright (C) 2002 Southwest Research Institute. |
1574
|
|
|
|
|
|
|
All Rights Reserved. |
1575
|
|
|
|
|
|
|
|
1576
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify it under |
1577
|
|
|
|
|
|
|
the terms of the GNU General Public License as published by the Free Software |
1578
|
|
|
|
|
|
|
Foundation; either version 3 of the License, or (at your option) any later |
1579
|
|
|
|
|
|
|
version. |
1580
|
|
|
|
|
|
|
|
1581
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,but WITHOUT ANY |
1582
|
|
|
|
|
|
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A |
1583
|
|
|
|
|
|
|
PARTICULAR PURPOSE. See the GNU General Public License for more details. |
1584
|
|
|
|
|
|
|
|
1585
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License along with |
1586
|
|
|
|
|
|
|
this program; if not, write to the Free Software Foundation, Inc., 59 Temple |
1587
|
|
|
|
|
|
|
Place,Suite 330, Boston, MA 02111-1307, USA |
1588
|
|
|
|
|
|
|
|
1589
|
|
|
|
|
|
|
=head1 AUTHORS |
1590
|
|
|
|
|
|
|
|
1591
|
|
|
|
|
|
|
Alasdair Allan Eaa@astro.ex.ac.ukE, |
1592
|
|
|
|
|
|
|
Tim Jenness Et.jenness@jach.hawaii.eduE, |
1593
|
|
|
|
|
|
|
Craig DeForest Edeforest@boulder.swri.eduE, |
1594
|
|
|
|
|
|
|
Jim Lewis Ejrl@ast.cam.ac.ukE, |
1595
|
|
|
|
|
|
|
Brad Cavanagh Eb.cavanagh@jach.hawaii.eduE |
1596
|
|
|
|
|
|
|
|
1597
|
|
|
|
|
|
|
=cut |
1598
|
|
|
|
|
|
|
|
1599
|
|
|
|
|
|
|
package Astro::FITS::HeaderCollection; |
1600
|
|
|
|
|
|
|
|
1601
|
10
|
|
|
10
|
|
52178
|
use 5.006; |
|
10
|
|
|
|
|
59
|
|
1602
|
10
|
|
|
10
|
|
59
|
use warnings; |
|
10
|
|
|
|
|
32
|
|
|
10
|
|
|
|
|
687
|
|
1603
|
10
|
|
|
10
|
|
80
|
use strict; |
|
10
|
|
|
|
|
24
|
|
|
10
|
|
|
|
|
403
|
|
1604
|
10
|
|
|
10
|
|
71
|
use Carp; |
|
10
|
|
|
|
|
62
|
|
|
10
|
|
|
|
|
8907
|
|
1605
|
|
|
|
|
|
|
|
1606
|
|
|
|
|
|
|
our $VERSION; |
1607
|
|
|
|
|
|
|
$VERSION = '3.09'; |
1608
|
|
|
|
|
|
|
|
1609
|
|
|
|
|
|
|
# Class wrapper for subhdrs tie. Not (yet) a public interface |
1610
|
|
|
|
|
|
|
# we simply need a class that we can tie the subhdrs array to. |
1611
|
|
|
|
|
|
|
|
1612
|
|
|
|
|
|
|
sub TIEARRAY { |
1613
|
2
|
|
|
2
|
|
9
|
my ($class, $container) = @_; |
1614
|
|
|
|
|
|
|
# create an object, but we want to avoid blessing the actual |
1615
|
|
|
|
|
|
|
# array into this class |
1616
|
2
|
|
|
|
|
17
|
return bless { SUBHDRS => $container }, $class; |
1617
|
|
|
|
|
|
|
} |
1618
|
|
|
|
|
|
|
|
1619
|
|
|
|
|
|
|
# must return a new tie |
1620
|
|
|
|
|
|
|
sub FETCH { |
1621
|
7
|
|
|
7
|
|
33
|
my $self = shift; |
1622
|
7
|
|
|
|
|
11
|
my $index = shift; |
1623
|
|
|
|
|
|
|
|
1624
|
7
|
|
|
|
|
20
|
my $arr = $self->{SUBHDRS}; |
1625
|
7
|
50
|
33
|
|
|
34
|
if ( $index >= 0 && $index <= $#$arr ) { |
1626
|
7
|
|
|
|
|
21
|
return $self->_hdr_to_tie( $arr->[$index] ); |
1627
|
|
|
|
|
|
|
} else { |
1628
|
0
|
|
|
|
|
0
|
return undef; |
1629
|
|
|
|
|
|
|
} |
1630
|
|
|
|
|
|
|
} |
1631
|
|
|
|
|
|
|
|
1632
|
|
|
|
|
|
|
sub STORE { |
1633
|
2
|
|
|
2
|
|
4
|
my $self = shift; |
1634
|
2
|
|
|
|
|
3
|
my $index = shift; |
1635
|
2
|
|
|
|
|
4
|
my $value = shift; |
1636
|
|
|
|
|
|
|
|
1637
|
2
|
|
|
|
|
4
|
my $hdr = $self->_tie_to_hdr( $value ); |
1638
|
2
|
|
|
|
|
8
|
$self->{SUBHDRS}->[$index] = $hdr; |
1639
|
|
|
|
|
|
|
} |
1640
|
|
|
|
|
|
|
|
1641
|
|
|
|
|
|
|
sub FETCHSIZE { |
1642
|
4
|
|
|
4
|
|
878
|
my $self = shift; |
1643
|
4
|
|
|
|
|
7
|
return scalar( @{ $self->{SUBHDRS} }); |
|
4
|
|
|
|
|
21
|
|
1644
|
|
|
|
|
|
|
} |
1645
|
|
|
|
|
|
|
|
1646
|
|
|
|
|
|
|
sub STORESIZE { |
1647
|
0
|
|
|
0
|
|
0
|
croak "Tied STORESIZE for SUBHDRS not yet implemented\n"; |
1648
|
|
|
|
|
|
|
} |
1649
|
|
|
|
|
|
|
|
1650
|
|
|
|
0
|
|
|
sub EXTEND { |
1651
|
|
|
|
|
|
|
|
1652
|
|
|
|
|
|
|
} |
1653
|
|
|
|
|
|
|
|
1654
|
|
|
|
|
|
|
sub EXISTS { |
1655
|
0
|
|
|
0
|
|
0
|
my $self = shift; |
1656
|
0
|
|
|
|
|
0
|
my $index = shift; |
1657
|
0
|
|
|
|
|
0
|
my $arr = $self->{SUBHDRS}; |
1658
|
|
|
|
|
|
|
|
1659
|
0
|
0
|
0
|
|
|
0
|
return 0 if $index > $#$arr || $index < 0; |
1660
|
0
|
0
|
|
|
|
0
|
return 1 if defined $self->{SUBHDRS}->[$index]; |
1661
|
0
|
|
|
|
|
0
|
return 0; |
1662
|
|
|
|
|
|
|
} |
1663
|
|
|
|
|
|
|
|
1664
|
|
|
|
|
|
|
sub DELETE { |
1665
|
0
|
|
|
0
|
|
0
|
my $self = shift; |
1666
|
0
|
|
|
|
|
0
|
my $index = shift; |
1667
|
0
|
|
|
|
|
0
|
$self->{SUBHDRS}->[$index] = undef; |
1668
|
|
|
|
|
|
|
} |
1669
|
|
|
|
|
|
|
|
1670
|
|
|
|
|
|
|
sub CLEAR { |
1671
|
1
|
|
|
1
|
|
3
|
my $self = shift; |
1672
|
1
|
|
|
|
|
2
|
@{ $self->{SUBHDRS} } = (); |
|
1
|
|
|
|
|
4
|
|
1673
|
|
|
|
|
|
|
} |
1674
|
|
|
|
|
|
|
|
1675
|
|
|
|
|
|
|
sub PUSH { |
1676
|
1
|
|
|
1
|
|
598
|
my $self = shift; |
1677
|
1
|
|
|
|
|
3
|
my @list = @_; |
1678
|
|
|
|
|
|
|
|
1679
|
|
|
|
|
|
|
# convert |
1680
|
1
|
|
|
|
|
2
|
@list = map { $self->_tie_to_hdr($_) } @list; |
|
1
|
|
|
|
|
3
|
|
1681
|
1
|
|
|
|
|
6
|
push(@{ $self->{SUBHDRS} }, @list); |
|
1
|
|
|
|
|
4
|
|
1682
|
|
|
|
|
|
|
} |
1683
|
|
|
|
|
|
|
|
1684
|
|
|
|
|
|
|
sub POP { |
1685
|
1
|
|
|
1
|
|
333
|
my $self = shift; |
1686
|
1
|
|
|
|
|
2
|
my $popped = pop( @{ $self->{SUBHDRS} } ); |
|
1
|
|
|
|
|
2
|
|
1687
|
1
|
|
|
|
|
3
|
return $self->_hdr_to_tie($popped); |
1688
|
|
|
|
|
|
|
} |
1689
|
|
|
|
|
|
|
|
1690
|
|
|
|
|
|
|
sub SHIFT { |
1691
|
1
|
|
|
1
|
|
2
|
my $self = shift; |
1692
|
1
|
|
|
|
|
2
|
my $shifted = shift( @{ $self->{SUBHDRS} } ); |
|
1
|
|
|
|
|
2
|
|
1693
|
1
|
|
|
|
|
4
|
return $self->_hdr_to_tie($shifted); |
1694
|
|
|
|
|
|
|
} |
1695
|
|
|
|
|
|
|
|
1696
|
|
|
|
|
|
|
sub UNSHIFT { |
1697
|
1
|
|
|
1
|
|
625
|
my $self = shift; |
1698
|
1
|
|
|
|
|
2
|
my @list = @_; |
1699
|
|
|
|
|
|
|
|
1700
|
|
|
|
|
|
|
# convert |
1701
|
1
|
|
|
|
|
3
|
@list = map { $self->_tie_to_hdr($_) } @list; |
|
1
|
|
|
|
|
3
|
|
1702
|
1
|
|
|
|
|
2
|
unshift(@{ $self->{SUBHDRS} }, @list); |
|
1
|
|
|
|
|
4
|
|
1703
|
|
|
|
|
|
|
|
1704
|
|
|
|
|
|
|
} |
1705
|
|
|
|
|
|
|
|
1706
|
|
|
|
|
|
|
# internal mappings |
1707
|
|
|
|
|
|
|
|
1708
|
|
|
|
|
|
|
# Given an Astro::FITS::Header object, return the thing that |
1709
|
|
|
|
|
|
|
# should be returned to the user of the tie |
1710
|
|
|
|
|
|
|
sub _hdr_to_tie { |
1711
|
9
|
|
|
9
|
|
14
|
my $self = shift; |
1712
|
9
|
|
|
|
|
14
|
my $hdr = shift; |
1713
|
|
|
|
|
|
|
|
1714
|
9
|
50
|
|
|
|
21
|
if (defined $hdr) { |
1715
|
9
|
|
|
|
|
12
|
my %header; |
1716
|
9
|
|
|
|
|
36
|
tie %header, ref($hdr), $hdr; |
1717
|
9
|
|
|
|
|
83
|
return \%header; |
1718
|
|
|
|
|
|
|
} |
1719
|
0
|
|
|
|
|
0
|
return undef; |
1720
|
|
|
|
|
|
|
} |
1721
|
|
|
|
|
|
|
|
1722
|
|
|
|
|
|
|
# convert an input argument as either a Astro::FITS::Header object |
1723
|
|
|
|
|
|
|
# or a hash, to an internal representation (an A:F:H object) |
1724
|
|
|
|
|
|
|
sub _tie_to_hdr { |
1725
|
4
|
|
|
4
|
|
7
|
my $self = shift; |
1726
|
4
|
|
|
|
|
5
|
my $value = shift; |
1727
|
|
|
|
|
|
|
|
1728
|
4
|
50
|
|
|
|
16
|
if (UNIVERSAL::isa($value, "Astro::FITS::Header")) { |
|
|
50
|
|
|
|
|
|
1729
|
0
|
|
|
|
|
0
|
return $value; |
1730
|
|
|
|
|
|
|
} elsif (ref($value) eq 'HASH') { |
1731
|
4
|
|
|
|
|
8
|
my $tied = tied %$value; |
1732
|
4
|
100
|
66
|
|
|
19
|
if (defined $tied && UNIVERSAL::isa($tied, "Astro::FITS::Header")) { |
1733
|
|
|
|
|
|
|
# Just take the object |
1734
|
3
|
|
|
|
|
10
|
return $tied; |
1735
|
|
|
|
|
|
|
} else { |
1736
|
|
|
|
|
|
|
# Convert it to a hash |
1737
|
|
|
|
|
|
|
my @items = map { new Astro::FITS::Header::Item( Keyword => $_, |
1738
|
1
|
|
|
|
|
4
|
Value => $value->{$_} |
1739
|
1
|
|
|
|
|
2
|
) } keys (%{$value}); |
|
1
|
|
|
|
|
4
|
|
1740
|
|
|
|
|
|
|
|
1741
|
|
|
|
|
|
|
# Create the Header object. |
1742
|
1
|
|
|
|
|
3
|
return new Astro::FITS::Header( Cards => \@items ); |
1743
|
|
|
|
|
|
|
|
1744
|
|
|
|
|
|
|
} |
1745
|
|
|
|
|
|
|
} else { |
1746
|
0
|
|
|
|
|
|
croak "Do not know how to store '$value' in a SUBHEADER\n"; |
1747
|
|
|
|
|
|
|
} |
1748
|
|
|
|
|
|
|
} |
1749
|
|
|
|
|
|
|
|
1750
|
|
|
|
|
|
|
# L A S T O R D E R S ------------------------------------------------------ |
1751
|
|
|
|
|
|
|
|
1752
|
|
|
|
|
|
|
1; |