line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Astro::FITS::HdrTrans::IRIS2; |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
=head1 NAME |
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
Astro::FITS::HdrTrans::IRIS2 - IRIS-2 Header translations |
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
=head1 SYNOPSIS |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
%generic_headers = translate_from_FITS(\%FITS_headers, \@header_array); |
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
%FITS_headers = transate_to_FITS(\%generic_headers, \@header_array); |
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
=head1 DESCRIPTION |
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
Converts information contained in AAO IRIS2 FITS headers to and from |
16
|
|
|
|
|
|
|
generic headers. See Astro::FITS::HdrTrans for a list of generic |
17
|
|
|
|
|
|
|
headers. |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
=cut |
20
|
|
|
|
|
|
|
|
21
|
10
|
|
|
10
|
|
13905974
|
use 5.006; |
|
10
|
|
|
|
|
43
|
|
22
|
10
|
|
|
10
|
|
54
|
use warnings; |
|
10
|
|
|
|
|
39
|
|
|
10
|
|
|
|
|
745
|
|
23
|
10
|
|
|
10
|
|
60
|
use strict; |
|
10
|
|
|
|
|
19
|
|
|
10
|
|
|
|
|
237
|
|
24
|
10
|
|
|
10
|
|
61
|
use Carp; |
|
10
|
|
|
|
|
21
|
|
|
10
|
|
|
|
|
966
|
|
25
|
|
|
|
|
|
|
|
26
|
10
|
|
|
10
|
|
781
|
use Math::Trig qw/ acos deg2rad rad2deg /; |
|
10
|
|
|
|
|
16510
|
|
|
10
|
|
|
|
|
740
|
|
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
# Inherit from Base |
29
|
10
|
|
|
10
|
|
82
|
use base qw/ Astro::FITS::HdrTrans::Base /; |
|
10
|
|
|
|
|
29
|
|
|
10
|
|
|
|
|
1991
|
|
30
|
|
|
|
|
|
|
|
31
|
10
|
|
|
10
|
|
71
|
use vars qw/ $VERSION /; |
|
10
|
|
|
|
|
21
|
|
|
10
|
|
|
|
|
21553
|
|
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
# Note that we use %02 not %03 because of historical reasons |
34
|
|
|
|
|
|
|
$VERSION = "1.64"; |
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
# for a constant mapping, there is no FITS header, just a generic |
38
|
|
|
|
|
|
|
# header that is constant |
39
|
|
|
|
|
|
|
my %CONST_MAP = ( |
40
|
|
|
|
|
|
|
COORDINATE_UNITS => 'degrees', |
41
|
|
|
|
|
|
|
GAIN => 5.2, |
42
|
|
|
|
|
|
|
NSCAN_POSITIONS => 1, |
43
|
|
|
|
|
|
|
SCAN_INCREMENT => 1, |
44
|
|
|
|
|
|
|
); |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
# NULL mappings used to override base class implementations |
47
|
|
|
|
|
|
|
my @NULL_MAP = (); |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
# unit mapping implies that the value propogates directly |
50
|
|
|
|
|
|
|
# to the output with only a keyword name change |
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
my %UNIT_MAP = ( |
53
|
|
|
|
|
|
|
DEC_BASE => "CRVAL2", |
54
|
|
|
|
|
|
|
DEC_TELESCOPE_OFFSET => "TDECOFF", |
55
|
|
|
|
|
|
|
DETECTOR_INDEX => "DINDEX", |
56
|
|
|
|
|
|
|
DETECTOR_READ_TYPE => "METHOD", |
57
|
|
|
|
|
|
|
DR_GROUP => "GRPNUM", |
58
|
|
|
|
|
|
|
DR_RECIPE => "RECIPE", |
59
|
|
|
|
|
|
|
EQUINOX => "EQUINOX", |
60
|
|
|
|
|
|
|
EXPOSURE_TIME => "EXPOSED", |
61
|
|
|
|
|
|
|
INSTRUMENT => "INSTRUME", |
62
|
|
|
|
|
|
|
NUMBER_OF_EXPOSURES => "CYCLES", |
63
|
|
|
|
|
|
|
NUMBER_OF_OFFSETS => "NOFFSETS", |
64
|
|
|
|
|
|
|
NUMBER_OF_READS => "READS", |
65
|
|
|
|
|
|
|
OBJECT => "OBJECT", |
66
|
|
|
|
|
|
|
OBSERVATION_NUMBER => "RUN", |
67
|
|
|
|
|
|
|
OBSERVATION_TYPE => "OBSTYPE", |
68
|
|
|
|
|
|
|
RA_BASE => "CRVAL1", |
69
|
|
|
|
|
|
|
RA_TELESCOPE_OFFSET => "TRAOFF", |
70
|
|
|
|
|
|
|
SLIT_ANGLE => "TEL_PA", |
71
|
|
|
|
|
|
|
SLIT_NAME => "SLIT", |
72
|
|
|
|
|
|
|
SPEED_GAIN => "SPEED", |
73
|
|
|
|
|
|
|
STANDARD => "STANDARD", |
74
|
|
|
|
|
|
|
TELESCOPE => "TELESCOP", |
75
|
|
|
|
|
|
|
WAVEPLATE_ANGLE => "WPLANGLE", |
76
|
|
|
|
|
|
|
X_DIM => "NAXIS1", |
77
|
|
|
|
|
|
|
X_LOWER_BOUND => "DETECXS", |
78
|
|
|
|
|
|
|
X_OFFSET => "RAOFF", |
79
|
|
|
|
|
|
|
X_REFERENCE_PIXEL => "CRPIX1", |
80
|
|
|
|
|
|
|
X_UPPER_BOUND => "DETECXE", |
81
|
|
|
|
|
|
|
Y_BASE => "DECBASE", |
82
|
|
|
|
|
|
|
Y_DIM => "NAXIS2", |
83
|
|
|
|
|
|
|
Y_LOWER_BOUND => "DETECYS", |
84
|
|
|
|
|
|
|
Y_OFFSET => "DECOFF", |
85
|
|
|
|
|
|
|
Y_REFERENCE_PIXEL => "CRPIX2", |
86
|
|
|
|
|
|
|
Y_UPPER_BOUND => "DETECYE", |
87
|
|
|
|
|
|
|
); |
88
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
# Create the translation methods |
91
|
|
|
|
|
|
|
__PACKAGE__->_generate_lookup_methods( \%CONST_MAP, \%UNIT_MAP, \@NULL_MAP ); |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
=head1 METHODS |
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
=over 4 |
97
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
=item B<this_instrument> |
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
The name of the instrument required to match (case insensitively) |
101
|
|
|
|
|
|
|
against the INSTRUME/INSTRUMENT keyword to allow this class to |
102
|
|
|
|
|
|
|
translate the specified headers. Called by the default |
103
|
|
|
|
|
|
|
C<can_translate> method. |
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
$inst = $class->this_instrument(); |
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
Returns "IRIS2". |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
=cut |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
sub this_instrument { |
112
|
20
|
|
|
20
|
1
|
66
|
return "IRIS2"; |
113
|
|
|
|
|
|
|
} |
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
=back |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
=head1 COMPLEX CONVERSIONS |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
These methods are more complicated than a simple mapping. We have to |
120
|
|
|
|
|
|
|
provide both from- and to-FITS conversions All these routines are |
121
|
|
|
|
|
|
|
methods and the to_ routines all take a reference to a hash and return |
122
|
|
|
|
|
|
|
the translated value (a many-to-one mapping) The from_ methods take a |
123
|
|
|
|
|
|
|
reference to a generic hash and return a translated hash (sometimes |
124
|
|
|
|
|
|
|
these are many-to-many) |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
=over 4 |
127
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
=item B<to_AIRMASS_END> |
129
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
Converts FITS header value of zenith distance into airmass value. |
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
=cut |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
sub to_AIRMASS_END { |
135
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
136
|
0
|
|
|
|
|
|
my $FITS_headers = shift; |
137
|
0
|
|
|
|
|
|
my $pi = atan2( 1, 1 ) * 4; |
138
|
0
|
|
|
|
|
|
my $return; |
139
|
0
|
0
|
|
|
|
|
if (exists($FITS_headers->{ZDEND})) { |
140
|
0
|
|
|
|
|
|
$return = 1 / cos( deg2rad($FITS_headers->{ZDEND}) ); |
141
|
|
|
|
|
|
|
} |
142
|
|
|
|
|
|
|
|
143
|
0
|
|
|
|
|
|
return $return; |
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
} |
146
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
=item B<from_AIRMASS_END> |
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
Converts airmass into zenith distance. |
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
=cut |
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
sub from_AIRMASS_END { |
154
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
155
|
0
|
|
|
|
|
|
my $generic_headers = shift; |
156
|
0
|
|
|
|
|
|
my %return_hash; |
157
|
0
|
0
|
|
|
|
|
if (exists($generic_headers->{AIRMASS_END})) { |
158
|
0
|
|
|
|
|
|
$return_hash{ZDEND} = rad2deg(acos($generic_headers->{AIRMASS_END})); |
159
|
|
|
|
|
|
|
} |
160
|
0
|
|
|
|
|
|
return %return_hash; |
161
|
|
|
|
|
|
|
} |
162
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
=item B<to_AIRMASS_START> |
164
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
Converts FITS header value of zenith distance into airmass value. |
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
=cut |
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
sub to_AIRMASS_START { |
170
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
171
|
0
|
|
|
|
|
|
my $FITS_headers = shift; |
172
|
0
|
|
|
|
|
|
my $pi = atan2( 1, 1 ) * 4; |
173
|
0
|
|
|
|
|
|
my $return; |
174
|
0
|
0
|
|
|
|
|
if (exists($FITS_headers->{ZDSTART})) { |
175
|
0
|
|
|
|
|
|
$return = 1 / cos( deg2rad($FITS_headers->{ZDSTART}) ); |
176
|
|
|
|
|
|
|
} |
177
|
|
|
|
|
|
|
|
178
|
0
|
|
|
|
|
|
return $return; |
179
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
} |
181
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
=item B<from_AIRMASS_START> |
183
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
Converts airmass into zenith distance. |
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
=cut |
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
sub from_AIRMASS_START { |
189
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
190
|
0
|
|
|
|
|
|
my $generic_headers = shift; |
191
|
0
|
|
|
|
|
|
my %return_hash; |
192
|
0
|
0
|
|
|
|
|
if (exists($generic_headers->{AIRMASS_START})) { |
193
|
0
|
|
|
|
|
|
$return_hash{ZDSTART} = rad2deg(acos($generic_headers->{AIRMASS_START})); |
194
|
|
|
|
|
|
|
} |
195
|
0
|
|
|
|
|
|
return %return_hash; |
196
|
|
|
|
|
|
|
} |
197
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
=item B<to_COORDINATE_TYPE> |
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
Converts the C<EQUINOX> FITS header into B1950 or J2000, depending |
201
|
|
|
|
|
|
|
on equinox value, and sets the C<COORDINATE_TYPE> generic header. |
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
=cut |
204
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
sub to_COORDINATE_TYPE { |
206
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
207
|
0
|
|
|
|
|
|
my $FITS_headers = shift; |
208
|
0
|
|
|
|
|
|
my $return; |
209
|
0
|
0
|
|
|
|
|
if (exists($FITS_headers->{EQUINOX})) { |
210
|
0
|
0
|
|
|
|
|
if ($FITS_headers->{EQUINOX} =~ /1950/) { |
|
|
0
|
|
|
|
|
|
211
|
0
|
|
|
|
|
|
$return = "B1950"; |
212
|
|
|
|
|
|
|
} elsif ($FITS_headers->{EQUINOX} =~ /2000/) { |
213
|
0
|
|
|
|
|
|
$return = "J2000"; |
214
|
|
|
|
|
|
|
} |
215
|
|
|
|
|
|
|
} |
216
|
0
|
|
|
|
|
|
return $return; |
217
|
|
|
|
|
|
|
} |
218
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
=item B<to_DEC_SCALE> |
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
Calculate the Declination pixel scale from the CD matrix. |
222
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
=cut |
224
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
sub to_DEC_SCALE { |
226
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
227
|
0
|
|
|
|
|
|
my $FITS_headers = shift; |
228
|
0
|
|
|
|
|
|
my $cd11 = $FITS_headers->{CD1_1}; |
229
|
0
|
|
|
|
|
|
my $cd12 = $FITS_headers->{CD1_2}; |
230
|
0
|
|
|
|
|
|
my $cd21 = $FITS_headers->{CD2_1}; |
231
|
0
|
|
|
|
|
|
my $cd22 = $FITS_headers->{CD2_2}; |
232
|
0
|
|
|
|
|
|
my $sgn; |
233
|
0
|
0
|
|
|
|
|
if ( ( $cd11 * $cd22 - $cd12 * $cd21 ) < 0 ) { |
234
|
0
|
|
|
|
|
|
$sgn = -1; |
235
|
|
|
|
|
|
|
} else { |
236
|
0
|
|
|
|
|
|
$sgn = 1; |
237
|
|
|
|
|
|
|
} |
238
|
0
|
|
|
|
|
|
return abs( sqrt( $cd11**2 + $cd21**2 ) ); |
239
|
|
|
|
|
|
|
} |
240
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
=item B<to_FILTER> |
242
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
Determine the filter name. Depends on the value of IR2_FILT. |
244
|
|
|
|
|
|
|
|
245
|
|
|
|
|
|
|
=cut |
246
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
sub to_FILTER { |
248
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
249
|
0
|
|
|
|
|
|
my $FITS_headers = shift; |
250
|
0
|
|
|
|
|
|
my $return; |
251
|
|
|
|
|
|
|
|
252
|
0
|
0
|
|
|
|
|
if ( $FITS_headers->{IR2_FILT} =~ /^OPEN$/i ) { |
253
|
0
|
|
|
|
|
|
$return = $FITS_headers->{IR2_COLD}; |
254
|
|
|
|
|
|
|
} else { |
255
|
0
|
|
|
|
|
|
$return = $FITS_headers->{IR2_FILT}; |
256
|
|
|
|
|
|
|
} |
257
|
0
|
|
|
|
|
|
$return =~ s/ //g; |
258
|
0
|
|
|
|
|
|
return $return; |
259
|
|
|
|
|
|
|
} |
260
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
=item B<to_GRATING_DISPERSION> |
262
|
|
|
|
|
|
|
|
263
|
|
|
|
|
|
|
Calculate grating dispersion. |
264
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
Dispersion is only a function of grism and blocking filter used, but |
266
|
|
|
|
|
|
|
need to allow for various choices of blocking filter |
267
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
=cut |
269
|
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
sub to_GRATING_DISPERSION { |
271
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
272
|
0
|
|
|
|
|
|
my $FITS_headers = shift; |
273
|
0
|
|
|
|
|
|
my $return; |
274
|
|
|
|
|
|
|
|
275
|
0
|
|
|
|
|
|
my $obsmode = $self->to_OBSERVATION_MODE( $FITS_headers ); |
276
|
0
|
|
|
|
|
|
my $filter = $self->to_FILTER( $FITS_headers ); |
277
|
|
|
|
|
|
|
|
278
|
0
|
0
|
|
|
|
|
if ( $obsmode eq 'spectroscopy' ) { |
279
|
0
|
0
|
0
|
|
|
|
if ( uc($filter) eq 'K' || uc($filter) eq 'KS' ) { |
|
|
0
|
0
|
|
|
|
|
|
|
0
|
0
|
|
|
|
|
|
|
0
|
0
|
|
|
|
|
280
|
0
|
|
|
|
|
|
$return = 0.0004423; |
281
|
|
|
|
|
|
|
} elsif ( uc($filter) eq 'JS' ) { |
282
|
0
|
|
|
|
|
|
$return = 0.0002322; |
283
|
|
|
|
|
|
|
} elsif ( uc($filter) eq 'J' || uc($filter) eq 'JL' ) { |
284
|
0
|
|
|
|
|
|
$return = 0.0002251; |
285
|
|
|
|
|
|
|
} elsif ( uc($filter) eq 'H' || uc($filter) eq 'HS' || uc($filter) eq 'HL' ) { |
286
|
0
|
|
|
|
|
|
$return = 0.0003413; |
287
|
|
|
|
|
|
|
} |
288
|
|
|
|
|
|
|
} |
289
|
0
|
|
|
|
|
|
return $return; |
290
|
|
|
|
|
|
|
} |
291
|
|
|
|
|
|
|
|
292
|
|
|
|
|
|
|
=item B<to_GRATING_DISPERSION> |
293
|
|
|
|
|
|
|
|
294
|
|
|
|
|
|
|
Calculate grating wavelength. |
295
|
|
|
|
|
|
|
|
296
|
|
|
|
|
|
|
Central wavelength is a function of grism + blocking filter + slit |
297
|
|
|
|
|
|
|
used. Assume offset slit used for H/Hs and Jl, otherwise centre slit |
298
|
|
|
|
|
|
|
is used. Central wavelengths computed for pixel 513, to match |
299
|
|
|
|
|
|
|
calculation used in ORAC-DR. |
300
|
|
|
|
|
|
|
|
301
|
|
|
|
|
|
|
=cut |
302
|
|
|
|
|
|
|
|
303
|
|
|
|
|
|
|
sub to_GRATING_WAVELENGTH { |
304
|
0
|
|
|
0
|
0
|
|
my $self = shift; |
305
|
0
|
|
|
|
|
|
my $FITS_headers = shift; |
306
|
0
|
|
|
|
|
|
my $return; |
307
|
|
|
|
|
|
|
|
308
|
0
|
|
|
|
|
|
my $obsmode = $self->to_OBSERVATION_MODE( $FITS_headers ); |
309
|
0
|
|
|
|
|
|
my $filter = $self->to_FILTER( $FITS_headers ); |
310
|
|
|
|
|
|
|
|
311
|
0
|
0
|
|
|
|
|
if ( $obsmode eq 'spectroscopy' ) { |
312
|
0
|
0
|
0
|
|
|
|
if ( uc( $filter ) eq 'K' || uc( $filter ) eq 'KS' ) { |
|
|
0
|
0
|
|
|
|
|
|
|
0
|
0
|
|
|
|
|
|
|
0
|
0
|
|
|
|
|
313
|
0
|
|
|
|
|
|
$return = 2.249388; |
314
|
|
|
|
|
|
|
} elsif ( uc($filter) eq 'JS' ) { |
315
|
0
|
|
|
|
|
|
$return = 1.157610; |
316
|
|
|
|
|
|
|
} elsif ( uc($filter) eq 'J' || uc($filter) eq 'JL' ) { |
317
|
0
|
|
|
|
|
|
$return = 1.219538; |
318
|
|
|
|
|
|
|
} elsif ( uc($filter) eq 'H' || uc($filter) eq 'HS' || uc($filter) eq 'HL' ) { |
319
|
0
|
|
|
|
|
|
$return = 1.636566; |
320
|
|
|
|
|
|
|
} |
321
|
|
|
|
|
|
|
} |
322
|
0
|
|
|
|
|
|
return $return; |
323
|
|
|
|
|
|
|
} |
324
|
|
|
|
|
|
|
|
325
|
|
|
|
|
|
|
=item B<to_OBSERVATION_MODE> |
326
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
Determines the observation mode from the IR2_SLIT or IR2_GRSM FITS header values. If |
328
|
|
|
|
|
|
|
IR2_SLIT value is equal to "OPEN1", then the observation mode is imaging. |
329
|
|
|
|
|
|
|
Otherwise, the observation mode is spectroscopy. If IR2_GRSM is matches SAP or SIL then |
330
|
|
|
|
|
|
|
it is spectroscopy. IR2_GRSM is used in preference to IR2_SLIT. |
331
|
|
|
|
|
|
|
|
332
|
|
|
|
|
|
|
=cut |
333
|
|
|
|
|
|
|
|
334
|
|
|
|
|
|
|
sub to_OBSERVATION_MODE { |
335
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
336
|
0
|
|
|
|
|
|
my $FITS_headers = shift; |
337
|
0
|
|
|
|
|
|
my $return; |
338
|
0
|
0
|
|
|
|
|
if (exists($FITS_headers->{IR2_GRSM})) { |
|
|
0
|
|
|
|
|
|
339
|
0
|
0
|
|
|
|
|
$return = ($FITS_headers->{IR2_GRSM} =~ /^(SAP|SIL)/i) ? "spectroscopy" : "imaging"; |
340
|
|
|
|
|
|
|
} elsif (exists($FITS_headers->{IR2_SLIT})) { |
341
|
0
|
0
|
|
|
|
|
$return = ($FITS_headers->{IR2_SLIT} eq "OPEN1") ? "imaging" : "spectroscopy"; |
342
|
|
|
|
|
|
|
} |
343
|
0
|
|
|
|
|
|
return $return; |
344
|
|
|
|
|
|
|
} |
345
|
|
|
|
|
|
|
|
346
|
|
|
|
|
|
|
=item B<to_RA_SCALE> |
347
|
|
|
|
|
|
|
|
348
|
|
|
|
|
|
|
Calculate the right-ascension pixel scale from the CD matrix. |
349
|
|
|
|
|
|
|
|
350
|
|
|
|
|
|
|
=cut |
351
|
|
|
|
|
|
|
|
352
|
|
|
|
|
|
|
sub to_RA_SCALE { |
353
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
354
|
0
|
|
|
|
|
|
my $FITS_headers = shift; |
355
|
0
|
|
|
|
|
|
my $cd12 = $FITS_headers->{CD1_2}; |
356
|
0
|
|
|
|
|
|
my $cd22 = $FITS_headers->{CD2_2}; |
357
|
0
|
|
|
|
|
|
return sqrt( $cd12**2 + $cd22**2 ); |
358
|
|
|
|
|
|
|
} |
359
|
|
|
|
|
|
|
|
360
|
|
|
|
|
|
|
=item B<to_UTDATE> |
361
|
|
|
|
|
|
|
|
362
|
|
|
|
|
|
|
Converts FITS header values into standard UT date value of the form |
363
|
|
|
|
|
|
|
YYYYMMDD. |
364
|
|
|
|
|
|
|
|
365
|
|
|
|
|
|
|
=cut |
366
|
|
|
|
|
|
|
|
367
|
|
|
|
|
|
|
sub to_UTDATE { |
368
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
369
|
0
|
|
|
|
|
|
my $FITS_headers = shift; |
370
|
0
|
|
|
|
|
|
my $return; |
371
|
0
|
0
|
|
|
|
|
if (exists($FITS_headers->{UTDATE})) { |
372
|
0
|
|
|
|
|
|
my $utdate = $FITS_headers->{UTDATE}; |
373
|
0
|
|
|
|
|
|
$utdate =~ s/://g; |
374
|
0
|
|
|
|
|
|
$return = $utdate; |
375
|
|
|
|
|
|
|
} |
376
|
|
|
|
|
|
|
|
377
|
0
|
|
|
|
|
|
return $return; |
378
|
|
|
|
|
|
|
} |
379
|
|
|
|
|
|
|
|
380
|
|
|
|
|
|
|
=item B<from_UTDATE> |
381
|
|
|
|
|
|
|
|
382
|
|
|
|
|
|
|
Converts UT date in the form C<yyyymmdd> to C<yyyy:mm:dd>. |
383
|
|
|
|
|
|
|
|
384
|
|
|
|
|
|
|
=cut |
385
|
|
|
|
|
|
|
|
386
|
|
|
|
|
|
|
sub from_UTDATE { |
387
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
388
|
0
|
|
|
|
|
|
my $generic_headers = shift; |
389
|
0
|
|
|
|
|
|
my %return_hash; |
390
|
0
|
0
|
|
|
|
|
if (exists($generic_headers->{UTDATE})) { |
391
|
0
|
|
|
|
|
|
my $date = $generic_headers->{UTDATE}; |
392
|
0
|
0
|
|
|
|
|
return () unless defined $date; |
393
|
0
|
|
|
|
|
|
$return_hash{UTDATE} = substr($date,0,4).":". |
394
|
|
|
|
|
|
|
substr($date,4,2).":".substr($date,6,2); |
395
|
|
|
|
|
|
|
} |
396
|
0
|
|
|
|
|
|
return %return_hash; |
397
|
|
|
|
|
|
|
} |
398
|
|
|
|
|
|
|
|
399
|
|
|
|
|
|
|
=item B<to_UTEND> |
400
|
|
|
|
|
|
|
|
401
|
|
|
|
|
|
|
Converts FITS header UT date/time values for the end of the observation into |
402
|
|
|
|
|
|
|
a C<Time::Piece> object. |
403
|
|
|
|
|
|
|
|
404
|
|
|
|
|
|
|
=cut |
405
|
|
|
|
|
|
|
|
406
|
|
|
|
|
|
|
sub to_UTEND { |
407
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
408
|
0
|
|
|
|
|
|
my $FITS_headers = shift; |
409
|
0
|
|
|
|
|
|
my $return; |
410
|
0
|
0
|
0
|
|
|
|
if (exists($FITS_headers->{UTDATE}) && exists($FITS_headers->{UTEND})) { |
411
|
0
|
|
|
|
|
|
my $utdate = $FITS_headers->{UTDATE}; |
412
|
0
|
|
|
|
|
|
$utdate =~ s/:/-/g; |
413
|
0
|
|
|
|
|
|
$return = $utdate . "T" . $FITS_headers->{UTEND}; |
414
|
0
|
|
|
|
|
|
$return = $self->_parse_iso_date( $return ); |
415
|
|
|
|
|
|
|
} |
416
|
0
|
|
|
|
|
|
return $return; |
417
|
|
|
|
|
|
|
} |
418
|
|
|
|
|
|
|
|
419
|
|
|
|
|
|
|
=item B<from_UTEND> |
420
|
|
|
|
|
|
|
|
421
|
|
|
|
|
|
|
Converts end date into two FITS headers for IRIS2: UTDATE |
422
|
|
|
|
|
|
|
(in the format YYYYMMDD) and UTEND (HH:MM:SS). |
423
|
|
|
|
|
|
|
|
424
|
|
|
|
|
|
|
=cut |
425
|
|
|
|
|
|
|
|
426
|
|
|
|
|
|
|
sub from_UTEND { |
427
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
428
|
0
|
|
|
|
|
|
my $generic_headers = shift; |
429
|
0
|
|
|
|
|
|
my %return_hash; |
430
|
0
|
0
|
|
|
|
|
if (exists($generic_headers->{UTEND})) { |
431
|
0
|
|
|
|
|
|
my $date = $generic_headers->{UTEND}; |
432
|
0
|
|
|
|
|
|
$return_hash{UTDATE} = sprintf("%04d:%02d:%02d", |
433
|
|
|
|
|
|
|
$date->year, $date->mon, $date->mday); |
434
|
0
|
|
|
|
|
|
$return_hash{UTEND} = sprintf("%02d:%02d:%02d", |
435
|
|
|
|
|
|
|
$date->hour, $date->minute, $date->second); |
436
|
|
|
|
|
|
|
} |
437
|
0
|
|
|
|
|
|
return %return_hash; |
438
|
|
|
|
|
|
|
} |
439
|
|
|
|
|
|
|
|
440
|
|
|
|
|
|
|
=item B<to_UTSTART> |
441
|
|
|
|
|
|
|
|
442
|
|
|
|
|
|
|
Converts FITS header UT date/time values for the start of the observation |
443
|
|
|
|
|
|
|
into a C<Time::Piece> object. |
444
|
|
|
|
|
|
|
|
445
|
|
|
|
|
|
|
=cut |
446
|
|
|
|
|
|
|
|
447
|
|
|
|
|
|
|
sub to_UTSTART { |
448
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
449
|
0
|
|
|
|
|
|
my $FITS_headers = shift; |
450
|
0
|
|
|
|
|
|
my $return; |
451
|
0
|
0
|
0
|
|
|
|
if (exists($FITS_headers->{UTDATE}) && exists($FITS_headers->{UTSTART})) { |
452
|
0
|
|
|
|
|
|
my $utdate = $FITS_headers->{UTDATE}; |
453
|
0
|
|
|
|
|
|
$utdate =~ s/:/-/g; |
454
|
0
|
|
|
|
|
|
$return = $utdate . "T" . $FITS_headers->{UTSTART} . ""; |
455
|
0
|
|
|
|
|
|
$return = $self->_parse_iso_date( $return ); |
456
|
|
|
|
|
|
|
} |
457
|
0
|
|
|
|
|
|
return $return; |
458
|
|
|
|
|
|
|
} |
459
|
|
|
|
|
|
|
|
460
|
|
|
|
|
|
|
=item B<from_UTSTART> |
461
|
|
|
|
|
|
|
|
462
|
|
|
|
|
|
|
Converts the date into two FITS headers for IRIS2: UTDATE |
463
|
|
|
|
|
|
|
(in the format YYYYMMDD) and UTSTART (HH:MM:SS). |
464
|
|
|
|
|
|
|
|
465
|
|
|
|
|
|
|
=cut |
466
|
|
|
|
|
|
|
|
467
|
|
|
|
|
|
|
sub from_UTSTART { |
468
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
469
|
0
|
|
|
|
|
|
my $generic_headers = shift; |
470
|
0
|
|
|
|
|
|
my %return_hash; |
471
|
0
|
0
|
|
|
|
|
if (exists($generic_headers->{UTSTART})) { |
472
|
0
|
|
|
|
|
|
my $date = $generic_headers->{UTSTART}; |
473
|
0
|
|
|
|
|
|
$return_hash{UTDATE} = sprintf("%04d:%02d:%02d", |
474
|
|
|
|
|
|
|
$date->year, $date->mon, $date->mday); |
475
|
0
|
|
|
|
|
|
$return_hash{UTSTART} = sprintf("%02d:%02d:%02d", |
476
|
|
|
|
|
|
|
$date->hour, $date->minute, $date->second); |
477
|
|
|
|
|
|
|
} |
478
|
0
|
|
|
|
|
|
return %return_hash; |
479
|
|
|
|
|
|
|
} |
480
|
|
|
|
|
|
|
|
481
|
|
|
|
|
|
|
=item B<to_X_BASE> |
482
|
|
|
|
|
|
|
|
483
|
|
|
|
|
|
|
Converts the decimal hours in the FITS header C<RABASE> into |
484
|
|
|
|
|
|
|
decimal degrees for the generic header C<X_BASE>. |
485
|
|
|
|
|
|
|
|
486
|
|
|
|
|
|
|
=cut |
487
|
|
|
|
|
|
|
|
488
|
|
|
|
|
|
|
sub to_X_BASE { |
489
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
490
|
0
|
|
|
|
|
|
my $FITS_headers = shift; |
491
|
0
|
|
|
|
|
|
my $return; |
492
|
0
|
0
|
|
|
|
|
if (exists($FITS_headers->{RABASE})) { |
493
|
0
|
|
|
|
|
|
$return = $FITS_headers->{RABASE} * 15; |
494
|
|
|
|
|
|
|
} |
495
|
0
|
|
|
|
|
|
return $return; |
496
|
|
|
|
|
|
|
} |
497
|
|
|
|
|
|
|
|
498
|
|
|
|
|
|
|
=item B<from_X_BASE> |
499
|
|
|
|
|
|
|
|
500
|
|
|
|
|
|
|
Converts the decimal degrees in the generic header C<X_BASE> |
501
|
|
|
|
|
|
|
into decimal hours for the FITS header C<RABASE>. |
502
|
|
|
|
|
|
|
|
503
|
|
|
|
|
|
|
=cut |
504
|
|
|
|
|
|
|
|
505
|
|
|
|
|
|
|
sub from_X_BASE { |
506
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
507
|
0
|
|
|
|
|
|
my $generic_headers = shift; |
508
|
0
|
|
|
|
|
|
my %return_hash; |
509
|
0
|
0
|
|
|
|
|
if (exists($generic_headers->{X_BASE})) { |
510
|
0
|
|
|
|
|
|
$return_hash{'RABASE'} = $generic_headers->{X_BASE} / 15; |
511
|
|
|
|
|
|
|
} |
512
|
0
|
|
|
|
|
|
return %return_hash; |
513
|
|
|
|
|
|
|
} |
514
|
|
|
|
|
|
|
|
515
|
|
|
|
|
|
|
=item B<to_X_SCALE> |
516
|
|
|
|
|
|
|
|
517
|
|
|
|
|
|
|
Converts a linear transformation matrix into a pixel scale in the right |
518
|
|
|
|
|
|
|
ascension axis. Results are in arcseconds per pixel. |
519
|
|
|
|
|
|
|
|
520
|
|
|
|
|
|
|
=cut |
521
|
|
|
|
|
|
|
|
522
|
|
|
|
|
|
|
# X_SCALE conversion courtesy Micah Johnson, from the cdelrot.pl script |
523
|
|
|
|
|
|
|
# supplied for use with XIMAGE. |
524
|
|
|
|
|
|
|
|
525
|
|
|
|
|
|
|
sub to_X_SCALE { |
526
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
527
|
0
|
|
|
|
|
|
my $FITS_headers = shift; |
528
|
0
|
|
|
|
|
|
my $return; |
529
|
0
|
0
|
0
|
|
|
|
if (exists($FITS_headers->{CD1_2}) && |
530
|
|
|
|
|
|
|
exists($FITS_headers->{CD2_2}) ) { |
531
|
0
|
|
|
|
|
|
my $cd12 = $FITS_headers->{CD1_2}; |
532
|
0
|
|
|
|
|
|
my $cd22 = $FITS_headers->{CD2_2}; |
533
|
0
|
|
|
|
|
|
$return = sqrt( $cd12**2 + $cd22**2 ) * 3600; |
534
|
|
|
|
|
|
|
} |
535
|
0
|
|
|
|
|
|
return $return; |
536
|
|
|
|
|
|
|
} |
537
|
|
|
|
|
|
|
|
538
|
|
|
|
|
|
|
=item B<to_Y_SCALE> |
539
|
|
|
|
|
|
|
|
540
|
|
|
|
|
|
|
Converts a linear transformation matrix into a pixel scale in the declination |
541
|
|
|
|
|
|
|
axis. Results are in arcseconds per pixel. |
542
|
|
|
|
|
|
|
|
543
|
|
|
|
|
|
|
=cut |
544
|
|
|
|
|
|
|
|
545
|
|
|
|
|
|
|
# Y_SCALE conversion courtesy Micah Johnson, from the cdelrot.pl script |
546
|
|
|
|
|
|
|
# supplied for use with XIMAGE. |
547
|
|
|
|
|
|
|
|
548
|
|
|
|
|
|
|
sub to_Y_SCALE { |
549
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
550
|
0
|
|
|
|
|
|
my $FITS_headers = shift; |
551
|
0
|
|
|
|
|
|
my $return; |
552
|
0
|
0
|
0
|
|
|
|
if (exists($FITS_headers->{CD1_1}) && |
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
553
|
|
|
|
|
|
|
exists($FITS_headers->{CD1_2}) && |
554
|
|
|
|
|
|
|
exists($FITS_headers->{CD2_1}) && |
555
|
|
|
|
|
|
|
exists($FITS_headers->{CD2_2}) ) { |
556
|
0
|
|
|
|
|
|
my $cd11 = $FITS_headers->{CD1_1}; |
557
|
0
|
|
|
|
|
|
my $cd12 = $FITS_headers->{CD1_2}; |
558
|
0
|
|
|
|
|
|
my $cd21 = $FITS_headers->{CD2_1}; |
559
|
0
|
|
|
|
|
|
my $cd22 = $FITS_headers->{CD2_2}; |
560
|
0
|
|
|
|
|
|
my $sgn; |
561
|
0
|
0
|
|
|
|
|
if ( ( $cd11 * $cd22 - $cd12 * $cd21 ) < 0 ) { |
562
|
0
|
|
|
|
|
|
$sgn = -1; |
563
|
|
|
|
|
|
|
} else { |
564
|
0
|
|
|
|
|
|
$sgn = 1; |
565
|
|
|
|
|
|
|
} |
566
|
0
|
|
|
|
|
|
$return = $sgn * sqrt( $cd11**2 + $cd21**2 ) * 3600; |
567
|
|
|
|
|
|
|
} |
568
|
0
|
|
|
|
|
|
return $return; |
569
|
|
|
|
|
|
|
} |
570
|
|
|
|
|
|
|
|
571
|
|
|
|
|
|
|
=back |
572
|
|
|
|
|
|
|
|
573
|
|
|
|
|
|
|
=head1 SEE ALSO |
574
|
|
|
|
|
|
|
|
575
|
|
|
|
|
|
|
C<Astro::FITS::HdrTrans>, C<Astro::FITS::HdrTrans::Base>. |
576
|
|
|
|
|
|
|
|
577
|
|
|
|
|
|
|
=head1 AUTHOR |
578
|
|
|
|
|
|
|
|
579
|
|
|
|
|
|
|
Brad Cavanagh E<lt>b.cavanagh@jach.hawaii.eduE<gt>, |
580
|
|
|
|
|
|
|
Tim Jenness E<lt>t.jenness@jach.hawaii.eduE<gt> |
581
|
|
|
|
|
|
|
|
582
|
|
|
|
|
|
|
=head1 COPYRIGHT |
583
|
|
|
|
|
|
|
|
584
|
|
|
|
|
|
|
Copyright (C) 2008 Science and Technology Facilities Council. |
585
|
|
|
|
|
|
|
Copyright (C) 2002-2007 Particle Physics and Astronomy Research Council. |
586
|
|
|
|
|
|
|
All Rights Reserved. |
587
|
|
|
|
|
|
|
|
588
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify it under |
589
|
|
|
|
|
|
|
the terms of the GNU General Public License as published by the Free Software |
590
|
|
|
|
|
|
|
Foundation; either version 2 of the License, or (at your option) any later |
591
|
|
|
|
|
|
|
version. |
592
|
|
|
|
|
|
|
|
593
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,but WITHOUT ANY |
594
|
|
|
|
|
|
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A |
595
|
|
|
|
|
|
|
PARTICULAR PURPOSE. See the GNU General Public License for more details. |
596
|
|
|
|
|
|
|
|
597
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License along with |
598
|
|
|
|
|
|
|
this program; if not, write to the Free Software Foundation, Inc., 59 Temple |
599
|
|
|
|
|
|
|
Place,Suite 330, Boston, MA 02111-1307, USA |
600
|
|
|
|
|
|
|
|
601
|
|
|
|
|
|
|
=cut |
602
|
|
|
|
|
|
|
|
603
|
|
|
|
|
|
|
1; |