File Coverage

blib/lib/Astro/FITS/HdrTrans/IRCAM.pm
Criterion Covered Total %
statement 99 115 86.0
branch 15 32 46.8
condition 11 24 45.8
subroutine 19 19 100.0
pod 13 14 92.8
total 157 204 76.9


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