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