File Coverage

blib/lib/Astro/FITS/HdrTrans/IRCAM.pm
Criterion Covered Total %
statement 102 118 86.4
branch 15 32 46.8
condition 11 24 45.8
subroutine 20 20 100.0
pod 13 14 92.8
total 161 208 77.4


line stmt bran cond sub pod time code
1              
2             =head1 NAME
3              
4             Astro::FITS::HdrTrans::IRCAM - UKIRT IRCAM translations
5              
6             =head1 SYNOPSIS
7              
8             use Astro::FITS::HdrTrans::IRCAM;
9              
10             %gen = Astro::FITS::HdrTrans::IRCAM->translate_from_FITS( %hdr );
11              
12             =head1 DESCRIPTION
13              
14             This class provides a generic set of translations that are specific
15             to the IRCAM camera of the United Kingdom Infrared Telescope.
16              
17             =cut
18              
19             use 5.006;
20 10     10   6739700 use warnings;
  10         30  
21 10     10   60 use strict;
  10         21  
  10         288  
22 10     10   48 use Carp;
  10         22  
  10         202  
23 10     10   43  
  10         13  
  10         710  
24             # Inherit from UKIRT "Old"
25             use base qw/ Astro::FITS::HdrTrans::UKIRTOld /;
26 10     10   67  
  10         21  
  10         3656  
27             use vars qw/ $VERSION /;
28 10     10   53  
  10         17  
  10         8460  
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              
35             );
36              
37             # Unit mapping implies that the value propogates directly
38             # to the output with only a keyword name change.
39              
40             # Note that header merging fails with IRCAM in some cases because
41             # some items are duplicated in the .HEADER and .I1 but using different
42             # comment strings so the merging routine does not realise they are the
43             # same header. It is arguably an error that Astro::FITS::Header looks
44             # at comments.
45              
46             my %UNIT_MAP = (
47             AIRMASS_START => 'AMSTART',
48             # IRCAM Specific
49             OBSERVATION_NUMBER => 'RUN', # cf. OBSNUM
50             DEC_TELESCOPE_OFFSET => 'DECOFF',
51             DETECTOR_BIAS => 'DET_BIAS',
52             RA_TELESCOPE_OFFSET => 'RAOFF',
53             );
54              
55             # END observation unit maps
56             my %ENDOBS_MAP = (
57             AIRMASS_END => 'AMEND',
58             NUMBER_OF_EXPOSURES => 'NEXP', # need it from the last subheader
59             );
60              
61             # Create the translation methods
62             __PACKAGE__->_generate_lookup_methods( \%CONST_MAP, \%UNIT_MAP, undef, \%ENDOBS_MAP );
63              
64             # Im
65              
66             =head1 METHODS
67              
68             =over 4
69              
70             =item B<this_instrument>
71              
72             The name of the instrument required to match (case insensitively)
73             against the INSTRUME/INSTRUMENT keyword to allow this class to
74             translate the specified headers. Called by the default
75             C<can_translate> method.
76              
77             $inst = $class->this_instrument();
78              
79             Returns a pattern match for /^IRCAM\d?/".
80              
81             =cut
82              
83             return qr/^IRCAM\d?/i;
84             }
85 24     24 1 108  
86             =back
87              
88             =head1 COMPLEX CONVERSIONS
89              
90             =over 4
91              
92             =item B<to_DEC_SCALE>
93              
94             Pixel scale along the Declination axis in arcseconds. If the pixel
95             scale is not defined in the PIXELSIZ or CDELT2 headers, then default
96             to 0.08144 arcseconds for data taken after 19990901, or 0.286
97             arcseconds for older data. The value will always be positive.
98              
99             =cut
100              
101             my $self = shift;
102             my $FITS_headers = shift;
103             my $scale;
104 4     4 1 9 my $pixelsiz = $FITS_headers->{PIXELSIZ};
105 4         7 my $ctype2 = $FITS_headers->{CTYPE2};
106 4         6 my $cdelt2 = $FITS_headers->{CDELT2};
107 4         18 my $utdate = $self->to_UTDATE( $FITS_headers );
108 4         100  
109 4         75 # The CDELTn headers may be part of a WCS in expressed in the AIPS-convention
110 4         104 # measured in degrees (but protect against cases where it may have been in
111             # arcsec).
112             if ( defined( $cdelt2 ) && defined( $ctype2 ) && $ctype2 eq "DEC--TAN" ) {
113             $scale = $cdelt2;
114             if ( abs( $scale ) < 1.0E-3 ) {
115 4 50 33     25 $scale *= 3600.0;
      33        
116 0         0 }
117 0 0       0 } else {
118 0         0 $scale = $pixelsiz;
119             }
120              
121 4         9 # Use the default scales. The first IRCAM scale did vary with time,
122             # but the information is no longer on the UKIRT web site.
123             if ( ! defined( $scale ) ) {
124             if ( $utdate > 19990901 ) {
125             $scale = 0.08144;
126 4 50       14 } else {
127 0 0       0 $scale = 0.286;
128 0         0 }
129             }
130 0         0  
131             # Headers may be in scientific notation, but with a 'D' instead of
132             # an 'E'. Translate to an 'E' so Perl doesn't fall over.
133             $scale =~ s/D/E/;
134              
135             return abs( $scale );
136 4         16 }
137              
138 4         15 =item B<from_DEC_SCALE>
139              
140             Generate the PIXELSIZ or CDELT2 header for IRCAM2 or IRCAM3 data
141             respectively. The header will be returned in arcseconds, and will
142             always be positive.
143              
144             =cut
145              
146             my $self = shift;
147             my $generic_headers = shift;
148             my $scale = abs( $generic_headers->{DEC_SCALE} );
149              
150 4     4 1 7 # Need to find way to allow for new and old headers with differing units.
151 4         11 return ( "PIXELSIZ", $scale );
152 4         9 }
153              
154             =item B<to_POLARIMETRY>
155 4         17  
156             Checks the filter name.
157              
158             =cut
159              
160             my $self = shift;
161             my $FITS_headers = shift;
162             if ( exists( $FITS_headers->{FILTER} ) &&
163             $FITS_headers->{FILTER} =~ /pol/i ) {
164             return 1;
165 4     4 1 15 } else {
166 4         9 return 0;
167 4 50 66     15 }
168             }
169 0         0  
170             =item B<to_RA_SCALE>
171 4         157  
172             Returns the pixel scale along the RA axis in arcseconds. If the pixel
173             scale is not defined in the PIXELSIZ or CDELT1 headers, then default
174             to -0.08144 arcseconds for data taken after 19990901, or -0.286
175             arcseconds for older data. The value will always be negative.
176              
177             =cut
178              
179             my $self = shift;
180             my $FITS_headers = shift;
181             my $scale;
182             my $pixelsiz = $FITS_headers->{PIXELSIZ};
183             my $ctype1 = $FITS_headers->{CTYPE1};
184             my $cdelt1 = $FITS_headers->{CDELT1};
185 4     4 1 7 my $utdate = $self->to_UTDATE( $FITS_headers );
186 4         6  
187 4         7 # The CDELTn headers may be part of a WCS in expressed in the AIPS-convention
188 4         8 # measured in degrees (but protect against cases where it may have been in
189 4         102 # arcsec).
190 4         81 if ( defined( $cdelt1 ) && defined( $ctype1 ) && $ctype1 eq "RA---TAN" ) {
191 4         82 $scale = $cdelt1;
192             if ( abs( $scale ) < 1.0E-3 ) {
193             $scale *= 3600.0;
194             }
195             } else {
196 4 50 33     18 $scale = $pixelsiz;
      33        
197 0         0 }
198 0 0       0  
199 0         0 # Use the default scales. The first IRCAM scale did vary with time,
200             # but the information is no longer on the UKIRT web site.
201             if ( ! defined( $scale ) ) {
202 4         13 if ( $utdate > 19990901 ) {
203             $scale = -0.08144;
204             } else {
205             $scale = -0.286;
206             }
207 4 50       12 }
208 0 0       0  
209 0         0 # Headers may be in scientific notation, but with a 'D' instead of
210             # an 'E'. Translate to an 'E' so Perl doesn't fall over.
211 0         0 $scale =~ s/D/E/;
212              
213             # Correct erroneous positive RA scale in some headers.
214             if ( $scale > 0.0 ) {
215             $scale *= -1.0;
216             }
217 4         13  
218             return $scale;
219             }
220 4 50       21  
221 4         8 =item B<from_RA_SCALE>
222              
223             Generates the PIXELSIZ or CDELT1 header for IRCAM2 or IRCAM3 data
224 4         11 respectively. The header will be returned in arcseconds, and will
225             always be negative.
226              
227             =cut
228              
229             my $self = shift;
230             my $generic_headers = shift;
231             my $scale = abs( $generic_headers->{RA_SCALE} );
232              
233             # Need to find way to allow for new and old headers with differing units.
234             return ( "PIXELSIZ", $scale );
235             }
236 4     4 1 13  
237 4         5  
238 4         9 =item B<to_SPEED_GAIN>
239              
240             For data taken before 22 November 2000, the SPD_GAIN header was not
241 4         30 written. Obtain the SPEED_GAIN from the detector bias if the SPD_GAIN
242             header is not defined. If the detector bias is between 0.61 and 0.63,
243             then the SPEED_GAIN is Standard. Otherwise, it is Deepwell.
244              
245             =cut
246              
247             my $self = shift;
248             my $FITS_headers = shift;
249              
250             my $return;
251             if ( defined( $FITS_headers->{SPD_GAIN} ) ) {
252             $return = $FITS_headers->{SPD_GAIN};
253             } else {
254             my $detector_bias = $self->to_DETECTOR_BIAS( $FITS_headers );
255 4     4 1 8 if ( $detector_bias > 0.61 && $detector_bias < 0.63 ) {
256 4         8 $return = "Standard";
257             } else {
258 4         10 $return = "Deepwell";
259 4 100       12 }
260 2         110 }
261             return $return;
262 2         36 }
263 2 50 33     7  
264 0         0 =item B<from_SPEED_GAIN>
265              
266 2         5 Translates the SPEED_GAIN generic header into the SPD_GAIN
267             IRCAM-specific header. Note that this will break bi-directional tests
268             as the SPD_GAIN header did not exist in data taken before 2000
269 4         97 November 22.
270              
271             =cut
272              
273             my $self = shift;
274             my $generic_headers = shift;
275             return( "SPD_GAIN", $generic_headers->{"SPEED_GAIN"} )
276             }
277              
278             =item B<from_TELESCOPE>
279              
280             For data taken before 20000607, return 'UKIRT, Mauna Kea, HI'. For
281             data taken on and after 20000607, return
282 4     4 1 8 'UKIRT,Mauna_Kea,HI'. Returned header is C<TELESCOP>.
283 4         7  
284 4         46 =cut
285              
286             my $self = shift;
287             my $generic_headers = shift;
288             my $utdate = $generic_headers->{'UTDATE'};
289             if ( $utdate < 20000607 ) {
290             return( "TELESCOP", "UKIRT, Mauna Kea, HI" );
291             } else {
292             return( "TELESCOP", "UKIRT,Mauna_Kea,HI" );
293             }
294             }
295              
296 4     4 1 7 =item B<to_X_REFERENCE_PIXEL>
297 4         8  
298 4         8 Specify the reference pixel, which is normally near the frame centre.
299 4 50       13 Note that offsets for polarimetry are undefined.
300 0         0  
301             =cut
302 4         42  
303             my $self = shift;
304             my $FITS_headers = shift;
305             my $xref;
306              
307             # Use the average of the bounds to define the centre.
308             if ( exists $FITS_headers->{RDOUT_X1} && exists $FITS_headers->{RDOUT_X2} ) {
309             my $xl = $FITS_headers->{RDOUT_X1};
310             my $xu = $FITS_headers->{RDOUT_X2};
311             $xref = $self->nint( ( $xl + $xu ) / 2 );
312              
313             # Use a default of the centre of the full array.
314 4     4 1 7 } else {
315 4         7 $xref = 129;
316 4         5 }
317             return $xref;
318             }
319 4 100 66     11  
320 2         84 =item B<from_X_REFERENCE_PIXEL>
321 2         134  
322 2         107 Returns CRPIX1.
323              
324             =cut
325              
326 2         4 my $self = shift;
327             my $generic_headers = shift;
328 4         10 return ( "CRPIX1", $generic_headers->{"X_REFERENCE_PIXEL"} );
329             }
330              
331             =item B<to_Y_REFERENCE_PIXEL>
332              
333             Specify the reference pixel, which is normally near the frame centre.
334             Note that offsets for polarimetry are undefined.
335              
336             =cut
337              
338 4     4 1 8 my $self = shift;
339 4         7 my $FITS_headers = shift;
340 4         36 my $yref;
341              
342             # Use the average of the bounds to define the centre.
343             if ( exists $FITS_headers->{RDOUT_Y1} && exists $FITS_headers->{RDOUT_Y2} ) {
344             my $yl = $FITS_headers->{RDOUT_Y1};
345             my $yu = $FITS_headers->{RDOUT_Y2};
346             $yref = $self->nint( ( $yl + $yu ) / 2 );
347              
348             # Use a default of the centre of the full array.
349             } else {
350             $yref = 129;
351 4     4 1 7 }
352 4         7 return $yref;
353 4         7 }
354              
355             =item B<from_X_REFERENCE_PIXEL>
356 4 100 66     23  
357 2         83 Returns CRPIX2.
358 2         104  
359 2         105 =cut
360              
361             my $self = shift;
362             my $generic_headers = shift;
363 2         4 return ( "CRPIX2", $generic_headers->{"Y_REFERENCE_PIXEL"} );
364             }
365 4         11  
366             =item B<to_ROTATION>
367              
368             Returns fixed rotation values based on the UT date.
369              
370             =cut
371              
372             my $self = shift;
373             my $FITS_headers = shift;
374             my $utdate = $self->to_UTDATE($FITS_headers);
375 4     4 0 8  
376 4         6 if ($utdate < 19990901) {
377 4         33 return 1.5;
378             }
379              
380             # TODO: determine correct sense for later rotations given on the
381             # IRCAM website http://www.jach.hawaii.edu/UKIRT/instruments/ircam/scale.html
382             # Sept 99: -89.04
383             # June 01: -88.84
384              
385             return 0.0;
386             }
387 4     4 1 7  
388 4         6 =back
389 4         11  
390             =head1 SEE ALSO
391 4 50       15  
392 0         0 C<Astro::FITS::HdrTrans>, C<Astro::FITS::HdrTrans::UKIRT>.
393              
394             =head1 AUTHOR
395              
396             Malcolm J. Currie E<lt>mjc@star.rl.ac.ukE<gt>
397             Brad Cavanagh E<lt>b.cavanagh@jach.hawaii.eduE<gt>,
398             Tim Jenness E<lt>t.jenness@jach.hawaii.eduE<gt>.
399              
400 4         15 =head1 COPYRIGHT
401              
402             Copyright (C) 2008 Science and Technology Facilities Council.
403             Copyright (C) 2003-2005 Particle Physics and Astronomy Research Council.
404             All Rights Reserved.
405              
406             This program is free software; you can redistribute it and/or modify it under
407             the terms of the GNU General Public License as published by the Free Software
408             Foundation; either Version 2 of the License, or (at your option) any later
409             version.
410              
411             This program is distributed in the hope that it will be useful,but WITHOUT ANY
412             WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
413             PARTICULAR PURPOSE. See the GNU General Public License for more details.
414              
415             You should have received a copy of the GNU General Public License along with
416             this program; if not, write to the Free Software Foundation, Inc., 59 Temple
417             Place, Suite 330, Boston, MA 02111-1307, USA.
418              
419             =cut
420              
421             1;