File Coverage

blib/lib/Astro/FITS/HdrTrans/GEMINI.pm
Criterion Covered Total %
statement 20 134 14.9
branch 0 42 0.0
condition 0 18 0.0
subroutine 7 23 30.4
pod 5 16 31.2
total 32 233 13.7


line stmt bran cond sub pod time code
1             package Astro::FITS::HdrTrans::GEMINI;
2              
3             =head1 NAME
4              
5             Astro::FITS::HdrTrans::GEMINI - Base class for translation of Gemini instruments
6              
7             =head1 SYNOPSIS
8              
9             use Astro::FITS::HdrTrans::GEMINI;
10              
11             =head1 DESCRIPTION
12              
13             This class provides a generic set of translations that are common to
14             instrumentation from the Gemini Observatory. It should not be used
15             directly for translation of instrument FITS headers.
16              
17             =cut
18              
19 12     12   12284494 use 5.006;
  12         77  
20 12     12   96 use warnings;
  12         38  
  12         1257  
21 12     12   118 use strict;
  12         27  
  12         516  
22 12     12   91 use Carp;
  12         51  
  12         1598  
23              
24             # Inherit from the Base translation class and not HdrTrans itself
25             # (which is just a class-less wrapper).
26              
27 12     12   104 use base qw/ Astro::FITS::HdrTrans::FITS /;
  12         32  
  12         4091  
28              
29 12     12   118 use Scalar::Util qw/ looks_like_number /;
  12         54  
  12         935  
30 12     12   87 use Astro::FITS::HdrTrans::FITS;
  12         26  
  12         99  
31              
32             our $VERSION = "1.66";
33              
34             # in each class we have three sets of data.
35             # - constant mappings
36             # - unit mappings
37             # - complex mappings
38              
39             # for a constant mapping, there is no FITS header, just a generic
40             # header that is constant
41             my %CONST_MAP = (
42             );
43              
44             # unit mapping implies that the value propogates directly
45             # to the output with only a keyword name change
46              
47             my %UNIT_MAP = (
48             AIRMASS_END => "AMEND",
49             AIRMASS_START => "AMSTART",
50             DEC_BASE => "CRVAL2",
51             EXPOSURE_TIME => "EXPTIME",
52             EQUINOX => "EQUINOX",
53             INSTRUMENT => "INSTRUME",
54             NUMBER_OF_EXPOSURES => "NSUBEXP",
55             NUMBER_OF_EXPOSURES => "COADDS",
56             OBJECT => "OBJECT",
57             X_REFERENCE_PIXEL => "CRPIX1",
58             Y_REFERENCE_PIXEL => "CRPIX2"
59             );
60              
61             # Create the translation methods
62             __PACKAGE__->_generate_lookup_methods( \%CONST_MAP, \%UNIT_MAP );
63              
64             =head1 COMPLEX CONVERSIONS
65              
66             These methods are more complicated than a simple mapping. We have to
67             provide both from- and to-FITS conversions All these routines are
68             methods and the to_ routines all take a reference to a hash and return
69             the translated value (a many-to-one mapping) The from_ methods take a
70             reference to a generic hash and return a translated hash (sometimes
71             these are many-to-many)
72              
73             =over 4
74              
75             =cut
76              
77             # Note use list context as there are multiple CD matrices in
78             # the header. We want scalar context.
79             sub to_DEC_SCALE {
80 0     0 0   my $self = shift;
81 0           my $FITS_headers = shift;
82 0           my $cd11 = $FITS_headers->{"CD1_1"};
83 0           my $cd12 = $FITS_headers->{"CD1_2"};
84 0           my $cd21 = $FITS_headers->{"CD2_1"};
85 0           my $cd22 = $FITS_headers->{"CD2_2"};
86 0           my $sgn;
87 0 0         if ( ( $cd11 * $cd22 - $cd12 * $cd21 ) < 0 ) {
88 0           $sgn = -1;
89             } else {
90 0           $sgn = 1;
91             }
92 0           abs( sqrt( $cd11**2 + $cd21**2 ) );
93             }
94              
95             sub to_DEC_TELESCOPE_OFFSET {
96 0     0 0   my $self = shift;
97 0           my $FITS_headers = shift;
98              
99             # It's simple when there's a header.
100 0           my $offset = $FITS_headers->{ "DECOFFSE" };
101              
102             # Otherwise for older data have to derive an offset from the source
103             # position and the frame position. This does assume that the
104             # reference pixel is unchanged in the group. The other headers
105             # are measured in degrees, but the offsets are in arceseconds.
106 0 0         if ( !defined( $offset ) ) {
107 0           my $decbase = $FITS_headers->{ "CRVAL2" } ;
108 0           my $dec = $FITS_headers->{ "DEC" };
109 0 0 0       if ( defined( $decbase ) && defined( $dec ) ) {
110 0           $offset = 3600.0 * ( $dec - $decbase );
111             } else {
112 0           $offset = 0.0;
113             }
114             }
115 0           return $offset;
116             }
117              
118             sub from_DEC_TELESCOPE_OFFSET {
119 0     0 0   my $self = shift;
120 0           my $generic_headers = shift;
121 0           "DECOFFSE", $generic_headers->{ "DEC_TELESCOPE_OFFSET" };
122             }
123              
124             sub to_FILTER {
125 0     0 0   my $self = shift;
126 0           my $FITS_headers = shift;
127 0           my $filter = "";
128 0           my $filter1 = $FITS_headers->{ "FILTER1" };
129 0           my $filter2 = $FITS_headers->{ "FILTER2" };
130 0           my $filter3 = $FITS_headers->{ "FILTER3" };
131              
132 0 0         if ( $filter1 =~ "open" ) {
133 0           $filter = $filter2;
134             }
135              
136 0 0         if ( $filter2 =~ "open" ) {
137 0           $filter = $filter1;
138             }
139              
140 0 0 0       if ( ( $filter1 =~ "blank" ) ||
      0        
141             ( $filter2 =~ "blank" ) ||
142             ( $filter3 =~ "blank" ) ) {
143 0           $filter = "blank";
144             }
145 0           return $filter;
146             }
147              
148             sub to_OBSERVATION_TYPE {
149 0     0 0   my $self = shift;
150 0           my $FITS_headers = shift;
151 0           my $type = $FITS_headers->{ "OBSTYPE" };
152 0 0 0       if ( $type eq "SCI" || $type eq "OBJECT-OBS" ) {
153 0           $type = "OBJECT";
154             }
155 0           return $type;
156             }
157              
158             sub to_RA_BASE {
159 0     0 0   my $self = shift;
160 0           my $FITS_headers = shift;
161 0           my $ra = 0.0;
162 0 0         if ( exists ( $FITS_headers->{CRVAL1} ) ) {
163 0           $ra = $FITS_headers->{CRVAL1};
164             }
165 0 0         $ra = defined( $ra ) ? $ra: 0.0;
166 0           return $ra;
167             }
168              
169             sub to_RA_SCALE {
170 0     0 0   my $self = shift;
171 0           my $FITS_headers = shift;
172 0           my $cd12 = $FITS_headers->{"CD1_2"};
173 0           my $cd22 = $FITS_headers->{"CD2_2"};
174 0           sqrt( $cd12**2 + $cd22**2 );
175             }
176              
177             sub to_RA_TELESCOPE_OFFSET {
178 0     0 0   my $self = shift;
179 0           my $FITS_headers = shift;
180              
181             # It's simple when there's a header.
182 0           my $offset = $FITS_headers->{ "RAOFFSET" };
183              
184             # Otherwise for older data have to derive an offset from the source
185             # position and the frame position. This does assume that the
186             # reference pixel is unchanged in the group. The other headers
187             # are measured in degrees, but the offsets are in arceseconds.
188 0 0         if ( !defined( $offset ) ) {
189 0           my $rabase = $FITS_headers->{ "CRVAL1" };
190 0           my $ra = $FITS_headers->{ "RA" };
191 0           my $dec = $FITS_headers->{ "DEC" };
192 0 0 0       if ( defined( $rabase ) && defined( $ra ) && defined( $dec ) ) {
      0        
193 0           $offset = 3600* ( $ra - $rabase ) * cosdeg( $dec );
194             } else {
195 0           $offset = 0.0;
196             }
197             }
198 0           return $offset;
199             }
200              
201             sub from_RA_TELESCOPE_OFFSET {
202 0     0 0   my $self = shift;
203 0           my $generic_headers = shift;
204 0           "RAOFFSE", $generic_headers->{ "RA_TELESCOPE_OFFSET" };
205             }
206              
207             sub to_UTSTART {
208 0     0 1   my $self = shift;
209 0           my $FITS_headers = shift;
210 0           my $return;
211 0 0         if (exists $FITS_headers->{'DATE-OBS'}) {
212 0           my $iso;
213 0 0         if ( $FITS_headers->{'DATE-OBS'} =~ /T/ ) {
    0          
    0          
214             # standard format
215 0           $iso = $FITS_headers->{'DATE-OBS'};
216             } elsif ( exists $FITS_headers->{UTSTART} ) {
217 0           $iso = $FITS_headers->{'DATE-OBS'}. "T" . $FITS_headers->{UTSTART};
218             } elsif ( exists $FITS_headers->{UT} ) {
219 0           $iso = $FITS_headers->{'DATE-OBS'}. "T" . $FITS_headers->{UT};
220             }
221 0 0         $return = $self->_parse_iso_date( $iso ) if $iso;
222             }
223 0           return $return;
224             }
225              
226             sub to_UTEND {
227 0     0 1   my $self = shift;
228 0           my $FITS_headers = shift;
229 0           my $return;
230 0 0         if ( exists $FITS_headers->{'DATE-END'} ) {
    0          
231 0           $return = $self->_parse_iso_date( $FITS_headers->{'DATE-END'} );
232             } elsif (exists $FITS_headers->{'DATE-OBS'}) {
233 0           my $iso;
234             my $ut;
235 0 0         if ( $FITS_headers->{'DATE-OBS'} =~ /T/ ) {
236 0           $ut = $FITS_headers->{'DATE-OBS'};
237 0           $ut =~ s/T.*$//;
238             } else {
239 0           $ut = $FITS_headers->{'DATE-OBS'};
240             }
241 0 0         if (exists $FITS_headers->{UTEND}) {
242 0           $iso = $ut. "T" . $FITS_headers->{UTEND};
243             }
244 0 0         $return = $self->_parse_iso_date( $iso ) if $iso;
245             }
246 0           return $return;
247             }
248              
249              
250             sub to_UTDATE {
251 0     0 1   my $self = shift;
252 0           my $FITS_headers = shift;
253 0           return $self->get_UT_date( $FITS_headers );
254             }
255              
256             sub from_UTEND {
257 0     0 1   my $self = shift;
258 0           my $generic_headers = shift;
259 0           my $utend = $generic_headers->{UTEND}->strptime( '%T' );
260 0           return ( "UTEND"=> $utend );
261             }
262              
263             sub from_UTSTART {
264 0     0 1   my $self = shift;
265 0           my $generic_headers = shift;
266 0           my $utstart = $generic_headers->{UTSTART}->strptime('%T');
267 0           return ( "UTSTART"=> $utstart );
268             }
269              
270             sub from_UTDATE {
271 0     0 0   my $self = shift;
272 0           my $generic_headers = shift;
273 0           my $ymd = $generic_headers->{UTDATE};
274 0           my $dobs = substr( $ymd, 0, 4 ) . "-" . substr( $ymd, 4, 2 ) ."-" . substr( $ymd, 6, 2 );
275 0           return ( "DATE-OBS"=>$dobs );
276             }
277              
278             # Supplementary methods for the translations
279             # ------------------------------------------
280              
281             # Returns the UT date in YYYYMMDD format.
282             sub get_UT_date {
283 0     0 0   my $self = shift;
284 0           my $FITS_headers = shift;
285              
286             # This is UT start and time.
287 0           my $dateobs = $FITS_headers->{"DATE-OBS"};
288              
289             # Extract out the data in yyyymmdd format.
290 0           return substr( $dateobs, 0, 4 ) . substr( $dateobs, 5, 2 ) . substr( $dateobs, 8, 2 );
291             }
292              
293             =back
294              
295             =head1 SEE ALSO
296              
297             C<Astro::FITS::HdrTrans>, C<Astro::FITS::HdrTrans::Base>.
298              
299             =head1 AUTHOR
300              
301             Paul Hirst <p.hirst@jach.hawaii.edu>
302             Malcolm J. Currie <mjc@star.rl.ac.uk>
303             Tim Jenness E<lt>t.jenness@jach.hawaii.eduE<gt>
304              
305             =head1 COPYRIGHT
306              
307             Copyright (C) 2007-2008 Science and Technology Facilities Council.
308             Copyright (C) 2006-2007 Particle Physics and Astronomy Research Council.
309             All Rights Reserved.
310              
311             This program is free software; you can redistribute it and/or modify
312             it under the terms of the GNU General Public License as published by
313             the Free Software Foundation; either Version 2 of the License, or (at
314             your option) any later version.
315              
316             This program is distributed in the hope that it will be useful,but
317             WITHOUT ANY WARRANTY; without even the implied warranty of
318             MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
319             General Public License for more details.
320              
321             You should have received a copy of the GNU General Public License
322             along with this program; if not, write to the Free Software
323             Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
324             USA.
325              
326             =cut
327              
328             1;