File Coverage

blib/lib/Astro/FITS/HdrTrans/SCUBA2.pm
Criterion Covered Total %
statement 65 68 95.5
branch 15 26 57.6
condition 2 6 33.3
subroutine 15 15 100.0
pod 8 8 100.0
total 105 123 85.3


line stmt bran cond sub pod time code
1              
2             =head1 NAME
3              
4             Astro::FITS::HdrTrans::SCUBA2 - JCMT SCUBA-2 translations
5              
6             =head1 DESCRIPTION
7              
8             Converts information contained in SCUBA-2 FITS headers to and from
9             generic headers. See L<Astro::FITS::HdrTrans> for a list of generic
10             headers.
11              
12             =cut
13              
14             use 5.006;
15 10     10   26372692 use warnings;
  10         31  
16 10     10   43 use strict;
  10         16  
  10         274  
17 10     10   45 use Carp;
  10         28  
  10         200  
18 10     10   37  
  10         18  
  10         619  
19             use base qw/ Astro::FITS::HdrTrans::JCMT /;
20 10     10   55  
  10         17  
  10         1335  
21             use vars qw/ $VERSION /;
22 10     10   51  
  10         16  
  10         5610  
23             $VERSION = "1.65";
24              
25             # For a constant mapping, there is no FITS header, just a generic
26             # header that is constant.
27             my %CONST_MAP = (
28             BACKEND => 'SCUBA-2',
29             DATA_UNITS => 'pW',
30             );
31              
32             # NULL mappings used to override base class implementations
33             my @NULL_MAP = ();
34              
35             # Unit mapping implies that the value propogates directly
36             # to the output with only a keyword name change.
37              
38             my %UNIT_MAP = (
39             FILTER => "FILTER",
40             INSTRUMENT => "INSTRUME",
41             DR_GROUP => "DRGROUP",
42             OBSERVATION_TYPE => "OBS_TYPE",
43             UTDATE => "UTDATE",
44             TELESCOPE => "TELESCOP",
45             AMBIENT_TEMPERATURE => 'ATSTART',
46             );
47              
48             # Values that are derived from the last subheader entry
49             my %ENDOBS_MAP = (
50             AIRMASS_END => 'AMEND',
51             AZIMUTH_END => 'AZEND',
52             ELEVATION_END => 'ELEND',
53             );
54              
55             # Create the translation methods
56             __PACKAGE__->_generate_lookup_methods( \%CONST_MAP, \%UNIT_MAP, \@NULL_MAP, \%ENDOBS_MAP );
57              
58             =head1 METHODS
59              
60             =over 4
61              
62             =item B<this_instrument>
63              
64             The name of the instrument required to match (case insensitively)
65             against the INSTRUME/INSTRUMENT keyword to allow this class to
66             translate the specified headers. Called by the default
67             C<can_translate> method.
68              
69             $inst = $class->this_instrument();
70              
71             Returns "SCUBA-2".
72              
73             =cut
74              
75             return "SCUBA-2";
76             }
77 21     21 1 47  
78             =back
79              
80             =head1 COMPLEX CONVERSIONS
81              
82             These methods are more complicated than a simple mapping. We have to
83             provide both from- and to-FITS conversions All these routines are
84             methods and the to_ routines all take a reference to a hash and return
85             the translated value (a many-to-one mapping) The from_ methods take a
86             reference to a generic hash and return a translated hash (sometimes
87             these are many-to-many)
88              
89             =over 4
90              
91             =item B<to_OBSERVATION_MODE>
92              
93             If Observation type is SCIENCE, return the sample mode, else
94             return the sample mode and observation type. For example, "STARE",
95             "SCAN", "SCAN_POINTING".
96              
97             Do not currently take into account polarimeter or FTS.
98              
99             =cut
100              
101             my $self = shift;
102             my $FITS_headers = shift;
103              
104 3     3 1 8 my $return;
105 3         6 if ( exists( $FITS_headers->{'SAM_MODE'} ) &&
106             exists( $FITS_headers->{'OBS_TYPE'} ) ) {
107 3         7 my $sam_mode = $FITS_headers->{'SAM_MODE'};
108 3 50 33     11 $sam_mode =~ s/\s//g;
109             my $obs_type = $FITS_headers->{'OBS_TYPE'};
110 3         130 $obs_type =~ s/\s//g;
111 3         158  
112 3         10 $return = $sam_mode;
113 3         142 if ($obs_type !~ /science/i) {
114             if ($obs_type =~ /(setup)/i) {
115 3         7 $return = lc($1);
116 3 100       12 } else {
117 2 50       7 $return .= "_$obs_type";
118 0         0 }
119             }
120 2         7 }
121             return $return;
122             }
123              
124 3         8 =item B<to_SUBSYSTEM_IDKEY>
125              
126             =cut
127              
128             my $self = shift;
129             my $FITS_headers = shift;
130              
131             # Try the general headers first
132 3     3 1 9 my $general = $self->SUPER::to_SUBSYSTEM_IDKEY( $FITS_headers );
133 3         7 return ( defined $general ? $general : "FILTER" );
134             }
135              
136 3         20 =item B<to_DR_RECIPE>
137 3 50       15  
138             Fix up recipes that were incorrect in the early years of the
139             observing tool.
140              
141             Converts SASSy survey data to use the SASSy recipe.
142              
143             =cut
144              
145             my $class = shift;
146             my $FITS_headers = shift;
147             my $dr = $FITS_headers->{RECIPE};
148             my $survey = $FITS_headers->{SURVEY};
149              
150 3     3 1 9 if (defined $survey && $survey =~ /sassy/i) {
151 3         7 if ($dr !~ /sassy/i) {
152 3         12 $dr = "REDUCE_SASSY";
153 3         151 }
154             }
155 3 50 33     160 return $dr;
156 0 0       0 }
157 0         0  
158             =item B<to_POLARIMETER>
159              
160 3         9 Determine if POL-2 is in the beam, based on the INBEAM header.
161              
162             =cut
163              
164             my $class = shift;
165             my $FITS_headers = shift;
166              
167             my $inbeam = $FITS_headers->{'INBEAM'};
168              
169             return 0 unless defined $inbeam;
170 3     3 1 8  
171 3         6 return ($inbeam =~ /\bpol/i) ? 1 : 0;
172             }
173 3         11  
174             =item B<from_POLARIMETER>
175 3 100       149  
176             Attempt to recreate the INBEAM header. Since this also
177 2 50       14 depends on FTS-2, use the _reconstruct_INBEAM method.
178              
179             =cut
180              
181             my $class = shift;
182             my $generic_headers = shift;
183              
184             return $class->_reconstruct_INBEAM($generic_headers);
185             }
186              
187             =item B<to_FOURIER_TRANSFORM_SPECTROMETER>
188 1     1 1 3  
189 1         2 Determine if FTS-2 is in the beam, based on the INBEAM header.
190              
191 1         22 =cut
192              
193             my $class = shift;
194             my $FITS_headers = shift;
195              
196             my $inbeam = $FITS_headers->{'INBEAM'};
197              
198             return 0 unless defined $inbeam;
199              
200             return ($inbeam =~ /\bfts/i) ? 1 : 0;
201 3     3 1 10 }
202 3         7  
203             =item B<from_FOURIER_TRANSFORM_SPECTROMETER>
204 3         10  
205             Attempt to recreate the INBEAM header. Since this also
206 3 100       151 depends on POL-2, use the _reconstruct_INBEAM method.
207              
208 2 50       14 =cut
209              
210             my $class = shift;
211             my $generic_headers = shift;
212              
213             return $class->_reconstruct_INBEAM($generic_headers);
214             }
215              
216              
217             =item B<_reconstruct_INBEAM>
218              
219 1     1 1 2 Since the INBEAM header becomes multiple generic headers, we need to look at
220 1         3 them all to reconstruct it. In order to work within the confines of the
221             Astro::FITS::HdrTrans::Base::translate_to_FITS method, we need to work
222 1         4 on a per-generic header basis. This internal method can then be used for
223             the "from_" method for each of these. It will end up returning the same
224             INBEAM header each time -- the versions generated from different generic
225             headers will overwrite eachother in the Base translate_to_FITS method
226             but that shouldn't be a problem.
227              
228             Note that the INBEAM header may not be reconstructed exactly. For example
229             it will just include the short form "pol" even if it would originally have
230             included specific POL-2 components instead.
231              
232             =cut
233              
234             my $class = shift;
235             my $generic_headers = shift;
236              
237             my @components;
238              
239             push @components, 'fts2' if $generic_headers->{'FOURIER_TRANSFORM_SPECTROMETER'};
240              
241             push @components, 'pol' if $generic_headers->{'POLARIMETER'};
242              
243             my $inbeam = undef;
244 2     2   4  
245 2         4 $inbeam = join(' ', @components) if scalar @components;
246              
247 2         4 return (INBEAM => $inbeam);
248             }
249 2 50       7  
250             =back
251 2 50       8  
252             =head1 SEE ALSO
253 2         3  
254             C<Astro::FITS::HdrTrans>, C<Astro::FITS::HdrTrans::Base>
255 2 50       9  
256             =head1 AUTHOR
257 2         40  
258             Tim Jenness E<lt>t.jenness@jach.hawaii.eduE<gt>
259              
260             =head1 COPYRIGHT
261              
262             Copyright (C) 2007-2009,2011,2013 Science & Technology Facilities Council.
263             Copyright (C) 2003-2005 Particle Physics and Astronomy Research Council.
264             All Rights Reserved.
265              
266             This program is free software; you can redistribute it and/or modify it under
267             the terms of the GNU General Public License as published by the Free Software
268             Foundation; either Version 2 of the License, or (at your option) any later
269             version.
270              
271             This program is distributed in the hope that it will be useful,but WITHOUT ANY
272             WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
273             PARTICULAR PURPOSE. See the GNU General Public License for more details.
274              
275             You should have received a copy of the GNU General Public License along with
276             this program; if not, write to the Free Software Foundation, Inc., 59 Temple
277             Place, Suite 330, Boston, MA 02111-1307, USA.
278              
279             =cut
280              
281             1;