line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
|
2
|
|
|
|
|
|
|
=head1 NAME |
3
|
|
|
|
|
|
|
|
4
|
|
|
|
|
|
|
Astro::FITS::HdrTrans::INGRID - WHT INGRID translations |
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
=head1 SYNOPSIS |
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
use Astro::FITS::HdrTrans::INGRID; |
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
%gen = Astro::FITS::HdrTrans::INGRID->translate_from_FITS( %hdr ); |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
=head1 DESCRIPTION |
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
This class provides a generic set of translations that are specific to |
15
|
|
|
|
|
|
|
the INGRID camera of the William Herschel Telescope. |
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
=cut |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
use 5.006; |
20
|
10
|
|
|
10
|
|
8569477
|
use warnings; |
|
10
|
|
|
|
|
32
|
|
21
|
10
|
|
|
10
|
|
49
|
use strict; |
|
10
|
|
|
|
|
20
|
|
|
10
|
|
|
|
|
261
|
|
22
|
10
|
|
|
10
|
|
54
|
use Carp; |
|
10
|
|
|
|
|
14
|
|
|
10
|
|
|
|
|
218
|
|
23
|
10
|
|
|
10
|
|
48
|
|
|
10
|
|
|
|
|
19
|
|
|
10
|
|
|
|
|
659
|
|
24
|
|
|
|
|
|
|
# Inherit from FITS. |
25
|
|
|
|
|
|
|
use base qw/ Astro::FITS::HdrTrans::FITS /; |
26
|
10
|
|
|
10
|
|
59
|
|
|
10
|
|
|
|
|
17
|
|
|
10
|
|
|
|
|
1349
|
|
27
|
|
|
|
|
|
|
use vars qw/ $VERSION /; |
28
|
10
|
|
|
10
|
|
55
|
|
|
10
|
|
|
|
|
16
|
|
|
10
|
|
|
|
|
17544
|
|
29
|
|
|
|
|
|
|
$VERSION = "1.65"; |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
# For a constant mapping, there is no FITS header, just a generic |
32
|
|
|
|
|
|
|
# header that is constant. |
33
|
|
|
|
|
|
|
my %CONST_MAP = ( |
34
|
|
|
|
|
|
|
POLARIMETRY => 0, |
35
|
|
|
|
|
|
|
OBSERVATION_MODE => 'imaging', |
36
|
|
|
|
|
|
|
WAVEPLATE_ANGLE => 0, |
37
|
|
|
|
|
|
|
); |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
# NULL mappings used to override base-class implementations. |
40
|
|
|
|
|
|
|
my @NULL_MAP = qw/ /; |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
# Unit mapping implies that the value propogates directly |
43
|
|
|
|
|
|
|
# to the output with only a keyword name change. |
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
my %UNIT_MAP = ( |
46
|
|
|
|
|
|
|
AIRMASS_END => "AIRMASS", |
47
|
|
|
|
|
|
|
AIRMASS_START => "AIRMASS", |
48
|
|
|
|
|
|
|
EXPOSURE_TIME => "EXPTIME", |
49
|
|
|
|
|
|
|
FILTER => "INGF1NAM", |
50
|
|
|
|
|
|
|
INSTRUMENT => "DETECTOR", |
51
|
|
|
|
|
|
|
NUMBER_OF_EXPOSURES => "COAVERAG", |
52
|
|
|
|
|
|
|
NUMBER_OF_READS => "NUMREADS", |
53
|
|
|
|
|
|
|
OBSERVATION_NUMBER => "RUN" |
54
|
|
|
|
|
|
|
); |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
# Create the translation methods. |
58
|
|
|
|
|
|
|
__PACKAGE__->_generate_lookup_methods( \%CONST_MAP, \%UNIT_MAP, \@NULL_MAP ); |
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
=head1 METHODS |
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
=over 4 |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
=item B<this_instrument> |
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
The name of the instrument required to match (case insensitively) |
67
|
|
|
|
|
|
|
against the INSTRUME/INSTRUMENT keyword to allow this class to |
68
|
|
|
|
|
|
|
translate the specified headers. Called by the default |
69
|
|
|
|
|
|
|
C<can_translate> method. |
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
$inst = $class->this_instrument(); |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
Returns "INGRID". |
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
=cut |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
return qr/^INGRID/; |
78
|
|
|
|
|
|
|
} |
79
|
20
|
|
|
20
|
1
|
91
|
|
80
|
|
|
|
|
|
|
=back |
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
=head1 COMPLEX CONVERSIONS |
83
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
=over 4 |
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
=item B<to_DEC_BASE> |
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
Converts the base declination from sexagesimal d:m:s to decimal |
89
|
|
|
|
|
|
|
degrees using the C<CAT-DEC> keyword, defaulting to 0.0. |
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
=cut |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
my $self = shift; |
94
|
|
|
|
|
|
|
my $FITS_headers = shift; |
95
|
|
|
|
|
|
|
my $dec = 0.0; |
96
|
0
|
|
|
0
|
1
|
|
my $sexa = $FITS_headers->{"CAT-DEC"}; |
97
|
0
|
|
|
|
|
|
if ( defined( $sexa ) ) { |
98
|
0
|
|
|
|
|
|
$dec = $self->dms_to_degrees( $sexa ); |
99
|
0
|
|
|
|
|
|
} |
100
|
0
|
0
|
|
|
|
|
return $dec; |
101
|
0
|
|
|
|
|
|
} |
102
|
|
|
|
|
|
|
|
103
|
0
|
|
|
|
|
|
=item B<to_DEC_SCALE> |
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
Sets the declination scale in arcseconds per pixel. The C<CCDYPIXE> |
106
|
|
|
|
|
|
|
and C<INGPSCAL> headers are used when both are defined. Otherwise it |
107
|
|
|
|
|
|
|
returns a default value of 0.2387 arcsec/pixel, assuming north is up. |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
=cut |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
my $self = shift; |
112
|
|
|
|
|
|
|
my $FITS_headers = shift; |
113
|
|
|
|
|
|
|
my $decscale = 0.2387; |
114
|
|
|
|
|
|
|
|
115
|
0
|
|
|
0
|
1
|
|
# Assumes either x-y scales the same or the y corresponds to |
116
|
0
|
|
|
|
|
|
# declination. |
117
|
0
|
|
|
|
|
|
my $ccdypixe = $self->via_subheader( $FITS_headers, "CCDYPIXE" ); |
118
|
|
|
|
|
|
|
my $ingpscal = $self->via_subheader( $FITS_headers, "INGPSCAL" ); |
119
|
|
|
|
|
|
|
if ( defined $ccdypixe && defined $ingpscal ) { |
120
|
|
|
|
|
|
|
$decscale = $ccdypixe * 1000.0 * $ingpscal; |
121
|
0
|
|
|
|
|
|
} |
122
|
0
|
|
|
|
|
|
return $decscale; |
123
|
0
|
0
|
0
|
|
|
|
} |
124
|
0
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
=item B<to_DEC_TELESCOPE_OFFSET> |
126
|
0
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
Sets the declination telescope offset in arcseconds. It uses the |
128
|
|
|
|
|
|
|
C<CAT-DEC> and C<DEC> keywords to derive the offset, and if either |
129
|
|
|
|
|
|
|
does not exist, it returns a default of 0.0. |
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
=cut |
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
my $self = shift; |
134
|
|
|
|
|
|
|
my $FITS_headers = shift; |
135
|
|
|
|
|
|
|
my $decoffset = 0.0; |
136
|
|
|
|
|
|
|
if ( exists $FITS_headers->{"CAT-DEC"} && exists $FITS_headers->{DEC} ) { |
137
|
|
|
|
|
|
|
|
138
|
0
|
|
|
0
|
1
|
|
# Obtain the reference and telescope declinations positions measured in degrees. |
139
|
0
|
|
|
|
|
|
my $refdec = $self->dms_to_degrees( $FITS_headers->{"CAT-DEC"} ); |
140
|
0
|
|
|
|
|
|
my $dec = $self->dms_to_degrees( $FITS_headers->{DEC} ); |
141
|
0
|
0
|
0
|
|
|
|
|
142
|
|
|
|
|
|
|
# Find the offsets between the positions in arcseconds on the sky. |
143
|
|
|
|
|
|
|
$decoffset = 3600.0 * ( $dec - $refdec ); |
144
|
0
|
|
|
|
|
|
} |
145
|
0
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
# The sense is reversed compared with UKIRT, as these measure the |
147
|
|
|
|
|
|
|
# place son the sky, not the motion of the telescope. |
148
|
0
|
|
|
|
|
|
return -1.0 * $decoffset |
149
|
|
|
|
|
|
|
} |
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
=item B<to_DETECTOR_READ_TYPE> |
152
|
|
|
|
|
|
|
|
153
|
0
|
|
|
|
|
|
Returns the UKIRT-like detector type "STARE" or "NDSTARE" from the |
154
|
|
|
|
|
|
|
FITS C<REDMODE> and C<NUMREADS> keywords. |
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
This is guesswork at present. |
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
=cut |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
my $self = shift; |
161
|
|
|
|
|
|
|
my $FITS_headers = shift; |
162
|
|
|
|
|
|
|
my $read_type; |
163
|
|
|
|
|
|
|
my $readout_mode = $FITS_headers->{READMODE}; |
164
|
|
|
|
|
|
|
my $nreads = $FITS_headers->{NUMREADS}; |
165
|
|
|
|
|
|
|
if ( $readout_mode =~ /^mndr/i || |
166
|
0
|
|
|
0
|
1
|
|
( $readout_mode =~ /^cds/i && $nreads == 1 ) ) { |
167
|
0
|
|
|
|
|
|
$read_type = "STARE"; |
168
|
0
|
|
|
|
|
|
} elsif ( $readout_mode =~ /^cds/i ) { |
169
|
0
|
|
|
|
|
|
$read_type = "NDSTARE"; |
170
|
0
|
|
|
|
|
|
} |
171
|
0
|
0
|
0
|
|
|
|
return $read_type; |
|
|
0
|
0
|
|
|
|
|
172
|
|
|
|
|
|
|
} |
173
|
0
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
=item B<to_DR_RECIPE> |
175
|
0
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
Returns the data-reduction recipe name. The selection depends on the |
177
|
0
|
|
|
|
|
|
values of the C<OBJECT> and C<OBSTYPE> keywords. The default is |
178
|
|
|
|
|
|
|
"QUICK_LOOK". A dark returns "REDUCE_DARK", and an object's recipe is |
179
|
|
|
|
|
|
|
"JITTER_SELF_FLAT". |
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
=cut |
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
# No clue what the recipe is apart for a dark and assume a dither |
184
|
|
|
|
|
|
|
# pattern means JITTER_SELF_FLAT. |
185
|
|
|
|
|
|
|
my $self = shift; |
186
|
|
|
|
|
|
|
my $FITS_headers = shift; |
187
|
|
|
|
|
|
|
my $recipe = "QUICK_LOOK"; |
188
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
# Look for a dither pattern. These begin D-<n>/<m>: where |
190
|
|
|
|
|
|
|
# <m> represents the number of jitter positions in the group |
191
|
|
|
|
|
|
|
# and <n> is the number within the group. |
192
|
0
|
|
|
0
|
1
|
|
my $object = $FITS_headers->{OBJECT}; |
193
|
0
|
|
|
|
|
|
if ( $object =~ /D-\d+\/\d+/ ) { |
194
|
0
|
|
|
|
|
|
$recipe = "JITTER_SELF_FLAT"; |
195
|
|
|
|
|
|
|
} elsif ( $FITS_headers->{OBSTYPE} =~ /DARK/i ) { |
196
|
|
|
|
|
|
|
$recipe = "REDUCE_DARK"; |
197
|
|
|
|
|
|
|
} |
198
|
|
|
|
|
|
|
|
199
|
0
|
|
|
|
|
|
return $recipe; |
200
|
0
|
0
|
|
|
|
|
} |
|
|
0
|
|
|
|
|
|
201
|
0
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
=item B<to_EQUINOX> |
203
|
0
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
Returns the equinox in decimal years. It's taken from the C<CAT-EQUI> |
205
|
|
|
|
|
|
|
keyword, if it exists, defaulting to 2000.0 otherwise. |
206
|
0
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
=cut |
208
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
my $self = shift; |
210
|
|
|
|
|
|
|
my $FITS_headers = shift; |
211
|
|
|
|
|
|
|
my $equinox = 2000.0; |
212
|
|
|
|
|
|
|
if ( exists $FITS_headers->{"CAT-EQUI"} ) { |
213
|
|
|
|
|
|
|
$equinox = $FITS_headers->{"CAT-EQUI"}; |
214
|
|
|
|
|
|
|
$equinox =~ s/[BJ]//; |
215
|
|
|
|
|
|
|
} |
216
|
|
|
|
|
|
|
return $equinox; |
217
|
0
|
|
|
0
|
1
|
|
} |
218
|
0
|
|
|
|
|
|
|
219
|
0
|
|
|
|
|
|
=item B<to_GAIN> |
220
|
0
|
0
|
|
|
|
|
|
221
|
0
|
|
|
|
|
|
Returns the gain in electrons per data number. This is taken from |
222
|
0
|
|
|
|
|
|
the C<GAIN> keyword, with a default of 4.1. |
223
|
|
|
|
|
|
|
|
224
|
0
|
|
|
|
|
|
=cut |
225
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
my $self = shift; |
227
|
|
|
|
|
|
|
my $FITS_headers = shift; |
228
|
|
|
|
|
|
|
my $gain = 4.1; |
229
|
|
|
|
|
|
|
my $subval = $self->via_subheader( $FITS_headers, "GAIN" ); |
230
|
|
|
|
|
|
|
$gain = $subval if defined $subval; |
231
|
|
|
|
|
|
|
return $gain; |
232
|
|
|
|
|
|
|
} |
233
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
=item B<to_NUMBER_OF_OFFSETS> |
235
|
0
|
|
|
0
|
1
|
|
|
236
|
0
|
|
|
|
|
|
Returns the number of offsets. It uses the UKIRT convention so |
237
|
0
|
|
|
|
|
|
it is equivalent to the number of dither positions plus one. |
238
|
0
|
|
|
|
|
|
The value is derived from the C<OBJECT> keyword, with a default of 6. |
239
|
0
|
0
|
|
|
|
|
|
240
|
0
|
|
|
|
|
|
=cut |
241
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
my $self = shift; |
243
|
|
|
|
|
|
|
my $FITS_headers = shift; |
244
|
|
|
|
|
|
|
my $noffsets = 5; |
245
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
# Look for a dither pattern. These begin D-<n>/<m>: where |
247
|
|
|
|
|
|
|
# <m> represents the number of jitter positions in the group |
248
|
|
|
|
|
|
|
# and <n> is the number within the group. |
249
|
|
|
|
|
|
|
my $object = $FITS_headers->{OBJECT}; |
250
|
|
|
|
|
|
|
if ( $object =~ /D-\d+\/\d+/ ) { |
251
|
|
|
|
|
|
|
|
252
|
0
|
|
|
0
|
1
|
|
# Extract the string between the solidus and the colon. Add one |
253
|
0
|
|
|
|
|
|
# to match the UKIRT convention. |
254
|
0
|
|
|
|
|
|
$noffsets = substr( $object, index( $object, "/" ) + 1 ); |
255
|
|
|
|
|
|
|
$noffsets = substr( $noffsets, 0, index( $noffsets, ":" ) ); |
256
|
|
|
|
|
|
|
} |
257
|
|
|
|
|
|
|
return $noffsets + 1; |
258
|
|
|
|
|
|
|
} |
259
|
0
|
|
|
|
|
|
|
260
|
0
|
0
|
|
|
|
|
=item B<to_OBJECT> |
261
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
Reeturns the object name. It is extracted from the C<OBJECT> keyword. |
263
|
|
|
|
|
|
|
|
264
|
0
|
|
|
|
|
|
=cut |
265
|
0
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
my $self = shift; |
267
|
0
|
|
|
|
|
|
my $FITS_headers = shift; |
268
|
|
|
|
|
|
|
my $object = $FITS_headers->{OBJECT}; |
269
|
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
# Look for a dither pattern. These begin D-<n>/<m>: where |
271
|
|
|
|
|
|
|
# <m> represents the number of jitter positions in the group |
272
|
|
|
|
|
|
|
# and <n> is the number within the group. We want to extract |
273
|
|
|
|
|
|
|
# the actual object name. |
274
|
|
|
|
|
|
|
if ( $object =~ /D-\d+\/\d+/ ) { |
275
|
|
|
|
|
|
|
$object = substr( $object, index( $object, ":" ) + 2 ); |
276
|
|
|
|
|
|
|
} |
277
|
0
|
|
|
0
|
1
|
|
return $object; |
278
|
0
|
|
|
|
|
|
} |
279
|
0
|
|
|
|
|
|
|
280
|
|
|
|
|
|
|
=item B<to_OBSERVATION_TYPE> |
281
|
|
|
|
|
|
|
|
282
|
|
|
|
|
|
|
Determines the observation type from the C<OBSTYPE> keyword provided it is |
283
|
|
|
|
|
|
|
"TARGET" for an object dark frame. |
284
|
|
|
|
|
|
|
|
285
|
0
|
0
|
|
|
|
|
=cut |
286
|
0
|
|
|
|
|
|
|
287
|
|
|
|
|
|
|
my $self = shift; |
288
|
0
|
|
|
|
|
|
my $FITS_headers = shift; |
289
|
|
|
|
|
|
|
my $obstype = uc( $FITS_headers->{OBSTYPE} ); |
290
|
|
|
|
|
|
|
if ( $obstype eq "TARGET" ) { |
291
|
|
|
|
|
|
|
$obstype = "OBJECT"; |
292
|
|
|
|
|
|
|
} |
293
|
|
|
|
|
|
|
return $obstype; |
294
|
|
|
|
|
|
|
} |
295
|
|
|
|
|
|
|
|
296
|
|
|
|
|
|
|
=item B<to_RA_BASE> |
297
|
|
|
|
|
|
|
|
298
|
|
|
|
|
|
|
Converts the base right ascension from sexagesimal h:m:s to decimal degrees |
299
|
0
|
|
|
0
|
1
|
|
using the C<CAT-RA> keyword, defaulting to 0.0. |
300
|
0
|
|
|
|
|
|
|
301
|
0
|
|
|
|
|
|
=cut |
302
|
0
|
0
|
|
|
|
|
|
303
|
0
|
|
|
|
|
|
my $self = shift; |
304
|
|
|
|
|
|
|
my $FITS_headers = shift; |
305
|
0
|
|
|
|
|
|
my $ra = 0.0; |
306
|
|
|
|
|
|
|
my $sexa = $FITS_headers->{"CAT-RA"}; |
307
|
|
|
|
|
|
|
if ( defined( $sexa ) ) { |
308
|
|
|
|
|
|
|
$ra = $self->hms_to_degrees( $sexa ); |
309
|
|
|
|
|
|
|
} |
310
|
|
|
|
|
|
|
return $ra; |
311
|
|
|
|
|
|
|
} |
312
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
=item B<to_RA_SCALE> |
314
|
|
|
|
|
|
|
|
315
|
|
|
|
|
|
|
Sets the right-ascension scale in arcseconds per pixel. The C<CCDXPIXE> |
316
|
0
|
|
|
0
|
1
|
|
and C<INGPSCAL> headers are used when both are defined. Otherwise it |
317
|
0
|
|
|
|
|
|
returns a default value of 0.2387 arcsec/pixel, assuming east is to |
318
|
0
|
|
|
|
|
|
the left. |
319
|
0
|
|
|
|
|
|
|
320
|
0
|
0
|
|
|
|
|
=cut |
321
|
0
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
my $self = shift; |
323
|
0
|
|
|
|
|
|
my $FITS_headers = shift; |
324
|
|
|
|
|
|
|
my $rascale = -0.2387; |
325
|
|
|
|
|
|
|
|
326
|
|
|
|
|
|
|
# Assumes either x-y scales the same or the x corresponds to right |
327
|
|
|
|
|
|
|
# ascension, and right ascension decrements with increasing x. |
328
|
|
|
|
|
|
|
my $ccdxpixe = $self->via_subheader( $FITS_headers, "CCDXPIXE" ); |
329
|
|
|
|
|
|
|
my $ingpscal = $self->via_subheader( $FITS_headers, "INGPSCAL" ); |
330
|
|
|
|
|
|
|
if ( defined $ccdxpixe && defined $ingpscal ) { |
331
|
|
|
|
|
|
|
$rascale = $ccdxpixe * -1000.0 * $ingpscal; |
332
|
|
|
|
|
|
|
} |
333
|
|
|
|
|
|
|
return $rascale; |
334
|
|
|
|
|
|
|
} |
335
|
|
|
|
|
|
|
|
336
|
0
|
|
|
0
|
1
|
|
=item B<to_RA_TELESCOPE_OFFSET> |
337
|
0
|
|
|
|
|
|
|
338
|
0
|
|
|
|
|
|
Sets the right-ascension telescope offset in arcseconds. It uses the |
339
|
|
|
|
|
|
|
C<CAT-RA>, C<RA>, C<CAT-DEC> keywords to derive the offset, and if any |
340
|
|
|
|
|
|
|
of these keywords does not exist, it returns a default of 0.0. |
341
|
|
|
|
|
|
|
|
342
|
0
|
|
|
|
|
|
=cut |
343
|
0
|
|
|
|
|
|
|
344
|
0
|
0
|
0
|
|
|
|
my $self = shift; |
345
|
0
|
|
|
|
|
|
my $FITS_headers = shift; |
346
|
|
|
|
|
|
|
my $raoffset = 0.0; |
347
|
0
|
|
|
|
|
|
|
348
|
|
|
|
|
|
|
if ( exists $FITS_headers->{"CAT-DEC"} && |
349
|
|
|
|
|
|
|
exists $FITS_headers->{"CAT-RA"} && exists $FITS_headers->{RA} ) { |
350
|
|
|
|
|
|
|
|
351
|
|
|
|
|
|
|
# Obtain the reference and telescope sky positions measured in degrees. |
352
|
|
|
|
|
|
|
my $refra = $self->hms_to_degrees( $FITS_headers->{"CAT-RA"} ); |
353
|
|
|
|
|
|
|
my $ra = $self->hms_to_degrees( $FITS_headers->{RA} ); |
354
|
|
|
|
|
|
|
my $refdec = $self->dms_to_degrees( $FITS_headers->{"CAT-DEC"} ); |
355
|
|
|
|
|
|
|
|
356
|
|
|
|
|
|
|
# Find the offset between the positions in arcseconds on the sky. |
357
|
|
|
|
|
|
|
$raoffset = 3600.0 * ( $ra - $refra ) * $self->cosdeg( $refdec ); |
358
|
|
|
|
|
|
|
} |
359
|
0
|
|
|
0
|
1
|
|
|
360
|
0
|
|
|
|
|
|
# The sense is reversed compared with UKIRT, as these measure the |
361
|
0
|
|
|
|
|
|
# place son the sky, not the motion of the telescope. |
362
|
|
|
|
|
|
|
return -1.0 * $raoffset; |
363
|
0
|
0
|
0
|
|
|
|
} |
|
|
|
0
|
|
|
|
|
364
|
|
|
|
|
|
|
|
365
|
|
|
|
|
|
|
=item B<to_ROTATION> |
366
|
|
|
|
|
|
|
|
367
|
0
|
|
|
|
|
|
Returns the orientation of the detector in degrees anticlockwise |
368
|
0
|
|
|
|
|
|
from north via east. |
369
|
0
|
|
|
|
|
|
|
370
|
|
|
|
|
|
|
=cut |
371
|
|
|
|
|
|
|
|
372
|
0
|
|
|
|
|
|
my $self = shift; |
373
|
|
|
|
|
|
|
my $FITS_headers = shift; |
374
|
|
|
|
|
|
|
return $self->rotation( $FITS_headers ); |
375
|
|
|
|
|
|
|
} |
376
|
|
|
|
|
|
|
|
377
|
0
|
|
|
|
|
|
=item B<to_SPEED_GAIN> |
378
|
|
|
|
|
|
|
|
379
|
|
|
|
|
|
|
Returns the speed gain. This is either "Normal" or "HiGain", the |
380
|
|
|
|
|
|
|
selection depending on the value of the C<CCDSPEED> keyword. |
381
|
|
|
|
|
|
|
|
382
|
|
|
|
|
|
|
=cut |
383
|
|
|
|
|
|
|
|
384
|
|
|
|
|
|
|
# Fixed values for the gain depend on the camera (SW or LW), and for LW |
385
|
|
|
|
|
|
|
# the readout mode. |
386
|
|
|
|
|
|
|
my $self = shift; |
387
|
|
|
|
|
|
|
my $FITS_headers = shift; |
388
|
0
|
|
|
0
|
1
|
|
my $spd_gain; |
389
|
0
|
|
|
|
|
|
my $speed = $FITS_headers->{CCDSPEED}; |
390
|
0
|
|
|
|
|
|
if ( $speed =~ /SLOW/ ) { |
391
|
|
|
|
|
|
|
$spd_gain = "Normal"; |
392
|
|
|
|
|
|
|
} else { |
393
|
|
|
|
|
|
|
$spd_gain = "HiGain"; |
394
|
|
|
|
|
|
|
} |
395
|
|
|
|
|
|
|
return $spd_gain; |
396
|
|
|
|
|
|
|
} |
397
|
|
|
|
|
|
|
|
398
|
|
|
|
|
|
|
=item B<to_STANDARD> |
399
|
|
|
|
|
|
|
|
400
|
|
|
|
|
|
|
Returns whether or not the observation is of a standard source. It is |
401
|
|
|
|
|
|
|
deemed to be a standard when the C<OBSTYPE> keyword is "STANDARD". |
402
|
|
|
|
|
|
|
|
403
|
0
|
|
|
0
|
1
|
|
=cut |
404
|
0
|
|
|
|
|
|
|
405
|
0
|
|
|
|
|
|
my $self = shift; |
406
|
0
|
|
|
|
|
|
my $FITS_headers = shift; |
407
|
0
|
0
|
|
|
|
|
my $standard = 0; |
408
|
0
|
|
|
|
|
|
my $type = $FITS_headers->{OBSTYPE}; |
409
|
|
|
|
|
|
|
if ( uc( $type ) eq "STANDARD" ) { |
410
|
0
|
|
|
|
|
|
$standard = 1; |
411
|
|
|
|
|
|
|
} |
412
|
0
|
|
|
|
|
|
return $standard; |
413
|
|
|
|
|
|
|
} |
414
|
|
|
|
|
|
|
|
415
|
|
|
|
|
|
|
=item B<to_UTDATE> |
416
|
|
|
|
|
|
|
|
417
|
|
|
|
|
|
|
Returns the UT date as C<Time::Piece> object. It copes with non-standard |
418
|
|
|
|
|
|
|
format in C<DATE-OBS>. |
419
|
|
|
|
|
|
|
|
420
|
|
|
|
|
|
|
=cut |
421
|
|
|
|
|
|
|
|
422
|
|
|
|
|
|
|
my $self = shift; |
423
|
0
|
|
|
0
|
1
|
|
my $FITS_headers = shift; |
424
|
0
|
|
|
|
|
|
return $self->get_UT_date( $FITS_headers ); |
425
|
0
|
|
|
|
|
|
} |
426
|
0
|
|
|
|
|
|
|
427
|
0
|
0
|
|
|
|
|
=item B<to_UTEND> |
428
|
0
|
|
|
|
|
|
|
429
|
|
|
|
|
|
|
Returns the UT time of the end of the observation as a C<Time::Piece> object. |
430
|
0
|
|
|
|
|
|
|
431
|
|
|
|
|
|
|
=cut |
432
|
|
|
|
|
|
|
|
433
|
|
|
|
|
|
|
my $self = shift; |
434
|
|
|
|
|
|
|
my $FITS_headers = shift; |
435
|
|
|
|
|
|
|
|
436
|
|
|
|
|
|
|
# This is the approximate end UT. |
437
|
|
|
|
|
|
|
my $start = $self->to_UTSTART( $FITS_headers ); |
438
|
|
|
|
|
|
|
return $self->_add_seconds( $start, $FITS_headers->{EXPTIME} ); |
439
|
|
|
|
|
|
|
} |
440
|
|
|
|
|
|
|
|
441
|
0
|
|
|
0
|
1
|
|
=item B<to_UTSTART> |
442
|
0
|
|
|
|
|
|
|
443
|
0
|
|
|
|
|
|
Returns an estimated UT time of the start of the observation as a |
444
|
|
|
|
|
|
|
C<Time::Piece> object. The start time is derived from the C<DATE-OBS> |
445
|
|
|
|
|
|
|
keyword and if C<DATE-OBS> only supplies a date, the time from the |
446
|
|
|
|
|
|
|
C<UTSTART> keyword is appended before conversaion to a C<Time::Piece> |
447
|
|
|
|
|
|
|
object. |
448
|
|
|
|
|
|
|
|
449
|
|
|
|
|
|
|
=cut |
450
|
|
|
|
|
|
|
|
451
|
|
|
|
|
|
|
my $self = shift; |
452
|
|
|
|
|
|
|
my $FITS_headers = shift; |
453
|
0
|
|
|
0
|
1
|
|
my $return; |
454
|
0
|
|
|
|
|
|
if ( exists $FITS_headers->{'DATE-OBS'} ) { |
455
|
|
|
|
|
|
|
my $iso; |
456
|
|
|
|
|
|
|
if ( $FITS_headers->{'DATE-OBS'} =~ /T/ ) { |
457
|
0
|
|
|
|
|
|
# standard format |
458
|
0
|
|
|
|
|
|
$iso = $FITS_headers->{'DATE-OBS'}; |
459
|
|
|
|
|
|
|
} elsif ( exists $FITS_headers->{UTSTART} ) { |
460
|
|
|
|
|
|
|
$iso = $FITS_headers->{'DATE-OBS'}. "T" . $FITS_headers->{UTSTART}; |
461
|
|
|
|
|
|
|
} |
462
|
|
|
|
|
|
|
$return = $self->_parse_iso_date( $iso ) if $iso; |
463
|
|
|
|
|
|
|
} |
464
|
|
|
|
|
|
|
return $return; |
465
|
|
|
|
|
|
|
} |
466
|
|
|
|
|
|
|
|
467
|
|
|
|
|
|
|
=item B<to_X_LOWER_BOUND> |
468
|
|
|
|
|
|
|
|
469
|
|
|
|
|
|
|
Returns the lower bound along the X-axis of the area of the detector |
470
|
|
|
|
|
|
|
as a pixel index. |
471
|
|
|
|
|
|
|
|
472
|
0
|
|
|
0
|
1
|
|
=cut |
473
|
0
|
|
|
|
|
|
|
474
|
0
|
|
|
|
|
|
my $self = shift; |
475
|
0
|
0
|
|
|
|
|
my $FITS_headers = shift; |
476
|
0
|
|
|
|
|
|
my @bounds = $self->getbounds( $FITS_headers ); |
477
|
0
|
0
|
|
|
|
|
return $bounds[ 0 ]; |
|
|
0
|
|
|
|
|
|
478
|
|
|
|
|
|
|
} |
479
|
0
|
|
|
|
|
|
|
480
|
|
|
|
|
|
|
=item B<to_X_REFERENCE_PIXEL> |
481
|
0
|
|
|
|
|
|
|
482
|
|
|
|
|
|
|
Specifies the X-axis reference pixel near the frame centre. It uses |
483
|
0
|
0
|
|
|
|
|
the nominal reference pixel if that is correctly supplied, failing |
484
|
|
|
|
|
|
|
that it takes the average of the bounds, and if these headers are also |
485
|
0
|
|
|
|
|
|
absent, it uses a default which assumes the full array. |
486
|
|
|
|
|
|
|
|
487
|
|
|
|
|
|
|
=cut |
488
|
|
|
|
|
|
|
|
489
|
|
|
|
|
|
|
my $self = shift; |
490
|
|
|
|
|
|
|
my $FITS_headers = shift; |
491
|
|
|
|
|
|
|
my $xref; |
492
|
|
|
|
|
|
|
my @bounds = $self->getbounds( $FITS_headers ); |
493
|
|
|
|
|
|
|
if ( $bounds[ 0 ] > 1 || $bounds[ 1 ] < 1024 ) { |
494
|
|
|
|
|
|
|
$xref = nint( ( $bounds[ 0 ] + $bounds[ 1 ] ) / 2 ); |
495
|
|
|
|
|
|
|
} else { |
496
|
0
|
|
|
0
|
1
|
|
$xref = 512; |
497
|
0
|
|
|
|
|
|
} |
498
|
0
|
|
|
|
|
|
return $xref; |
499
|
0
|
|
|
|
|
|
} |
500
|
|
|
|
|
|
|
|
501
|
|
|
|
|
|
|
=item B<to_X_UPPER_BOUND> |
502
|
|
|
|
|
|
|
|
503
|
|
|
|
|
|
|
Returns the upper bound along the X-axis of the area of the detector |
504
|
|
|
|
|
|
|
as a pixel index. |
505
|
|
|
|
|
|
|
|
506
|
|
|
|
|
|
|
=cut |
507
|
|
|
|
|
|
|
|
508
|
|
|
|
|
|
|
my $self = shift; |
509
|
|
|
|
|
|
|
my $FITS_headers = shift; |
510
|
|
|
|
|
|
|
my @bounds = $self->getbounds( $FITS_headers ); |
511
|
|
|
|
|
|
|
return $bounds[ 1 ]; |
512
|
0
|
|
|
0
|
1
|
|
} |
513
|
0
|
|
|
|
|
|
|
514
|
0
|
|
|
|
|
|
=item B<to_Y_LOWER_BOUND> |
515
|
0
|
|
|
|
|
|
|
516
|
0
|
0
|
0
|
|
|
|
Returns the lower bound along the Y-axis of the area of the detector |
517
|
0
|
|
|
|
|
|
as a pixel index. |
518
|
|
|
|
|
|
|
|
519
|
0
|
|
|
|
|
|
=cut |
520
|
|
|
|
|
|
|
|
521
|
0
|
|
|
|
|
|
my $self = shift; |
522
|
|
|
|
|
|
|
my $FITS_headers = shift; |
523
|
|
|
|
|
|
|
my @bounds = $self->getbounds( $FITS_headers ); |
524
|
|
|
|
|
|
|
return $bounds[ 2 ]; |
525
|
|
|
|
|
|
|
} |
526
|
|
|
|
|
|
|
|
527
|
|
|
|
|
|
|
=item B<to_Y_REFERENCE_PIXEL> |
528
|
|
|
|
|
|
|
|
529
|
|
|
|
|
|
|
Specifies the Y-axis reference pixel near the frame centre. It uses |
530
|
|
|
|
|
|
|
the nominal reference pixel if that is correctly supplied, failing |
531
|
|
|
|
|
|
|
that it takes the average of the bounds, and if these headers are also |
532
|
0
|
|
|
0
|
1
|
|
absent, it uses a default which assumes the full array. |
533
|
0
|
|
|
|
|
|
|
534
|
0
|
|
|
|
|
|
=cut |
535
|
0
|
|
|
|
|
|
|
536
|
|
|
|
|
|
|
my $self = shift; |
537
|
|
|
|
|
|
|
my $FITS_headers = shift; |
538
|
|
|
|
|
|
|
my $yref; |
539
|
|
|
|
|
|
|
my @bounds = $self->getbounds( $FITS_headers ); |
540
|
|
|
|
|
|
|
if ( $bounds[ 2 ] > 1 || $bounds[ 3 ] < 1024 ) { |
541
|
|
|
|
|
|
|
$yref = nint( ( $bounds[ 2 ] + $bounds[ 3 ] ) / 2 ); |
542
|
|
|
|
|
|
|
} else { |
543
|
|
|
|
|
|
|
$yref = 512; |
544
|
|
|
|
|
|
|
} |
545
|
|
|
|
|
|
|
return $yref; |
546
|
0
|
|
|
0
|
1
|
|
} |
547
|
0
|
|
|
|
|
|
|
548
|
0
|
|
|
|
|
|
=item B<to_Y_UPPER_BOUND> |
549
|
0
|
|
|
|
|
|
|
550
|
|
|
|
|
|
|
Returns the upper bound along the Y-axis of the area of the detector |
551
|
|
|
|
|
|
|
as a pixel index. |
552
|
|
|
|
|
|
|
|
553
|
|
|
|
|
|
|
=cut |
554
|
|
|
|
|
|
|
|
555
|
|
|
|
|
|
|
my $self = shift; |
556
|
|
|
|
|
|
|
my $FITS_headers = shift; |
557
|
|
|
|
|
|
|
my @bounds = $self->getbounds( $FITS_headers ); |
558
|
|
|
|
|
|
|
return $bounds[ 3 ]; |
559
|
|
|
|
|
|
|
} |
560
|
|
|
|
|
|
|
|
561
|
|
|
|
|
|
|
=back |
562
|
0
|
|
|
0
|
1
|
|
|
563
|
0
|
|
|
|
|
|
# Supplementary methods for the translations |
564
|
0
|
|
|
|
|
|
# ------------------------------------------ |
565
|
0
|
|
|
|
|
|
|
566
|
0
|
0
|
0
|
|
|
|
=head1 HELPER ROUTINES |
567
|
0
|
|
|
|
|
|
|
568
|
|
|
|
|
|
|
These are INGRID-specific helper routines. |
569
|
0
|
|
|
|
|
|
|
570
|
|
|
|
|
|
|
=over 4 |
571
|
0
|
|
|
|
|
|
|
572
|
|
|
|
|
|
|
=item B<dms_to_degrees> |
573
|
|
|
|
|
|
|
|
574
|
|
|
|
|
|
|
Converts a sky angle specified in d:m:s format into decimal degrees. |
575
|
|
|
|
|
|
|
The argument is the sexagesimal-format angle. |
576
|
|
|
|
|
|
|
|
577
|
|
|
|
|
|
|
=cut |
578
|
|
|
|
|
|
|
|
579
|
|
|
|
|
|
|
my $self = shift; |
580
|
|
|
|
|
|
|
my $sexa = shift; |
581
|
|
|
|
|
|
|
my $dms; |
582
|
0
|
|
|
0
|
1
|
|
if ( defined( $sexa ) ) { |
583
|
0
|
|
|
|
|
|
my @pos = split( /:/, $sexa ); |
584
|
0
|
|
|
|
|
|
$dms = $pos[ 0 ] + $pos[ 1 ] / 60.0 + $pos [ 2 ] / 3600.; |
585
|
0
|
|
|
|
|
|
} |
586
|
|
|
|
|
|
|
return $dms; |
587
|
|
|
|
|
|
|
} |
588
|
|
|
|
|
|
|
|
589
|
|
|
|
|
|
|
# Obtain the detector bounds from a section in [xl:xu,yl:yu] syntax. |
590
|
|
|
|
|
|
|
# If the RTDATSEC header is absent, use a default which corresponds |
591
|
|
|
|
|
|
|
# to the full array. |
592
|
|
|
|
|
|
|
my $self = shift; |
593
|
|
|
|
|
|
|
my $FITS_headers = shift; |
594
|
|
|
|
|
|
|
my @bounds = ( 1, 1024, 1, 1024 ); |
595
|
|
|
|
|
|
|
if ( exists $FITS_headers->{RTDATSEC} ) { |
596
|
|
|
|
|
|
|
my $section = $FITS_headers->{RTDATSEC}; |
597
|
|
|
|
|
|
|
$section =~ s/\[//; |
598
|
|
|
|
|
|
|
$section =~ s/\]//; |
599
|
|
|
|
|
|
|
$section =~ s/,/:/g; |
600
|
|
|
|
|
|
|
@bounds = split( /:/, $section ); |
601
|
|
|
|
|
|
|
} |
602
|
|
|
|
|
|
|
return @bounds; |
603
|
|
|
|
|
|
|
} |
604
|
|
|
|
|
|
|
|
605
|
|
|
|
|
|
|
=item B<get_UT_date> |
606
|
|
|
|
|
|
|
|
607
|
0
|
|
|
0
|
1
|
|
Returns the UT date in YYYYMMDD format. It parses the non-standard |
608
|
0
|
|
|
|
|
|
ddMmmyy C<DATE-OBS> keyword. |
609
|
0
|
|
|
|
|
|
|
610
|
0
|
0
|
|
|
|
|
=cut |
611
|
0
|
|
|
|
|
|
|
612
|
0
|
|
|
|
|
|
my $self = shift; |
613
|
|
|
|
|
|
|
my $FITS_headers = shift; |
614
|
0
|
|
|
|
|
|
|
615
|
|
|
|
|
|
|
# This is UT start and time. |
616
|
|
|
|
|
|
|
my $dateobs = $FITS_headers->{"DATE-OBS"}; |
617
|
|
|
|
|
|
|
|
618
|
|
|
|
|
|
|
# Extract out the data in yyyymmdd format. |
619
|
|
|
|
|
|
|
return substr( $dateobs, 0, 4 ) . substr( $dateobs, 5, 2 ) . substr( $dateobs, 8, 2 ) |
620
|
|
|
|
|
|
|
} |
621
|
0
|
|
|
0
|
0
|
|
|
622
|
0
|
|
|
|
|
|
=item B<hms_to_degrees> |
623
|
0
|
|
|
|
|
|
|
624
|
0
|
0
|
|
|
|
|
Converts a sky angle specified in h:m:s format into decimal degrees. |
625
|
0
|
|
|
|
|
|
It takes no account of latitude. The argument is the sexagesimal |
626
|
0
|
|
|
|
|
|
format angle. |
627
|
0
|
|
|
|
|
|
|
628
|
0
|
|
|
|
|
|
=cut |
629
|
0
|
|
|
|
|
|
|
630
|
|
|
|
|
|
|
my $self = shift; |
631
|
0
|
|
|
|
|
|
my $sexa = shift; |
632
|
|
|
|
|
|
|
my $hms; |
633
|
|
|
|
|
|
|
if ( defined( $sexa ) ) { |
634
|
|
|
|
|
|
|
my @pos = split( /:/, $sexa ); |
635
|
|
|
|
|
|
|
$hms = 15.0 * ( $pos[ 0 ] + $pos[ 1 ] / 60.0 + $pos [ 2 ] / 3600. ); |
636
|
|
|
|
|
|
|
} |
637
|
|
|
|
|
|
|
return $hms; |
638
|
|
|
|
|
|
|
} |
639
|
|
|
|
|
|
|
|
640
|
|
|
|
|
|
|
=item B<rotation> |
641
|
|
|
|
|
|
|
|
642
|
0
|
|
|
0
|
1
|
|
Derives the rotation angle in degrees from the C<ROTSKYPA> keyword, with a |
643
|
0
|
|
|
|
|
|
default of 0.0. |
644
|
|
|
|
|
|
|
|
645
|
|
|
|
|
|
|
=cut |
646
|
0
|
|
|
|
|
|
|
647
|
|
|
|
|
|
|
my $self = shift; |
648
|
|
|
|
|
|
|
my $FITS_headers = shift; |
649
|
0
|
|
|
|
|
|
my $rotangle = 0.0; |
650
|
|
|
|
|
|
|
|
651
|
|
|
|
|
|
|
if ( exists $FITS_headers->{ROTSKYPA} ) { |
652
|
|
|
|
|
|
|
$rotangle = $FITS_headers->{ROTSKYPA}; |
653
|
|
|
|
|
|
|
} |
654
|
|
|
|
|
|
|
return $rotangle; |
655
|
|
|
|
|
|
|
} |
656
|
|
|
|
|
|
|
|
657
|
|
|
|
|
|
|
=back |
658
|
|
|
|
|
|
|
|
659
|
|
|
|
|
|
|
=head1 SEE ALSO |
660
|
|
|
|
|
|
|
|
661
|
0
|
|
|
0
|
1
|
|
C<Astro::FITS::HdrTrans>, C<Astro::FITS::HdrTrans::UKIRT>. |
662
|
0
|
|
|
|
|
|
|
663
|
0
|
|
|
|
|
|
=head1 AUTHOR |
664
|
0
|
0
|
|
|
|
|
|
665
|
0
|
|
|
|
|
|
Malcolm J. Currie E<lt>mjc@star.rl.ac.ukE<gt> |
666
|
0
|
|
|
|
|
|
Brad Cavanagh E<lt>b.cavanagh@jach.hawaii.eduE<gt>, |
667
|
|
|
|
|
|
|
Tim Jenness E<lt>t.jenness@jach.hawaii.eduE<gt>. |
668
|
0
|
|
|
|
|
|
|
669
|
|
|
|
|
|
|
=head1 COPYRIGHT |
670
|
|
|
|
|
|
|
|
671
|
|
|
|
|
|
|
Copyright (C) 2008 Science and Technology Facilities Council. |
672
|
|
|
|
|
|
|
Copyright (C) 2003-2005 Particle Physics and Astronomy Research Council. |
673
|
|
|
|
|
|
|
All Rights Reserved. |
674
|
|
|
|
|
|
|
|
675
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify it under |
676
|
|
|
|
|
|
|
the terms of the GNU General Public License as published by the Free Software |
677
|
|
|
|
|
|
|
Foundation; either Version 2 of the License, or (at your option) any later |
678
|
|
|
|
|
|
|
version. |
679
|
0
|
|
|
0
|
1
|
|
|
680
|
0
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,but WITHOUT ANY |
681
|
0
|
|
|
|
|
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A |
682
|
|
|
|
|
|
|
PARTICULAR PURPOSE. See the GNU General Public License for more details. |
683
|
0
|
0
|
|
|
|
|
|
684
|
0
|
|
|
|
|
|
You should have received a copy of the GNU General Public License along with |
685
|
|
|
|
|
|
|
this program; if not, write to the Free Software Foundation, Inc., 59 Temple |
686
|
0
|
|
|
|
|
|
Place, Suite 330, Boston, MA 02111-1307, USA. |
687
|
|
|
|
|
|
|
|
688
|
|
|
|
|
|
|
=cut |
689
|
|
|
|
|
|
|
|
690
|
|
|
|
|
|
|
1; |