File Coverage

blib/lib/Astro/FITS/HdrTrans/LCOFLOYDS.pm
Criterion Covered Total %
statement 18 111 16.2
branch 0 42 0.0
condition 0 9 0.0
subroutine 7 18 38.8
pod 11 12 91.6
total 36 192 18.7


line stmt bran cond sub pod time code
1             # -*-perl-*-
2              
3              
4             =head1 NAME
5              
6             Astro::FITS::HdrTrans::LCOFLOYDS - LCO 2.0m FLOYDS translations
7              
8             =head1 SYNOPSIS
9              
10             use Astro::FITS::HdrTrans::LCOFLOYDS;
11              
12             %gen = Astro::FITS::HdrTrans::LCOFLOYDS->translate_from_FITS( %hdr );
13              
14             =head1 DESCRIPTION
15              
16             This class provides a generic set of translations that are specific to
17             2.0m FLOYDSs at LCO.
18              
19             =cut
20              
21             use 5.006;
22 10     10   10094673 use warnings;
  10         36  
23 10     10   43 use strict;
  10         23  
  10         286  
24 10     10   39 use Carp;
  10         16  
  10         195  
25 10     10   34  
  10         31  
  10         620  
26             # Inherit from LCO base class.
27             use base qw/ Astro::FITS::HdrTrans::LCO /;
28 10     10   77  
  10         18  
  10         1395  
29             use vars qw/ $VERSION /;
30 10     10   50  
  10         17  
  10         9120  
31             $VERSION = "1.65";
32              
33             # for a constant mapping, there is no FITS header, just a generic
34             # header that is constant
35              
36             # NULL mappings used to override base-class implementations.
37             my @NULL_MAP = qw/ /;
38              
39             my %CONST_MAP = ( OBSERVATION_MODE => 'spectroscopy',
40             GRATING_NAME => 'FLOYDS GRATING',
41             GRATING_ORDER => 1,
42             GRATING_DISPERSION => 1.73/10000.0,
43             GRATING_WAVELENGTH => 0.556,
44             NSCAN_POSITIONS => 1,
45             NUMBER_OF_READS => 1,
46             SCAN_INCREMENT => 1,
47             );
48              
49             my %UNIT_MAP = (
50             SLIT_NAME => "APERTURE",
51             SLIT_WIDTH => "APERWID",
52             X_DIM => "NAXIS1",
53             Y_DIM => "NAXIS2",
54             );
55              
56              
57             # Create the translation methods
58             __PACKAGE__->_generate_lookup_methods( \%CONST_MAP, \%UNIT_MAP, \@NULL_MAP );
59              
60             =head1 METHODS
61              
62             =over 4
63              
64             =item B<this_instrument>
65              
66             The name of the instrument required to match (case insensitively)
67             against the INSTRUME/INSTRUMENT keyword to allow this class to
68             translate the specified headers. Called by the default
69             C<can_translate> method.
70              
71             $inst = $class->this_instrument();
72              
73             Returns "LCOFLOYDS".
74              
75             =cut
76              
77             return qr/(^en05)|(^en06)/i
78              
79 20     20 1 79 }
80              
81             =back
82              
83             =head1 COMPLEX CONVERSIONS
84              
85             These methods are more complicated than a simple mapping. We have to
86             provide both from- and to-FITS conversions All these routines are
87             methods and the to_ routines all take a reference to a hash and return
88             the translated value (a many-to-one mapping) The from_ methods take a
89             reference to a generic hash and return a translated hash (sometimes
90             these are many-to-many)
91              
92             =over 4
93              
94             =cut
95              
96             =item B<to_DEC_SCALE>
97              
98             Sets the declination scale in arcseconds per pixel. The C<PIXSCALE>
99             is used when it's defined. Otherwise it returns a default value of 0.2320
100             arcsec/pixel, multiplied by C<YBINNING> assuming this is defined
101              
102             =cut
103              
104             my $self = shift;
105             my $FITS_headers = shift;
106             my $decscale = 0.3860;
107 0     0 1    
108 0           # Assumes either x-y scales the same or the y corresponds to
109 0           # declination.
110             my $ccdscale = $self->via_subheader( $FITS_headers, "PIXSCALE" );
111             if ( defined $ccdscale ) {
112             $decscale = $ccdscale;
113 0           } else {
114 0 0         my $ybinning = $self->via_subheader( $FITS_headers, "YBINNING" );
115 0           if ( defined $ybinning ) {
116             $decscale = $decscale * $ybinning;
117 0           }
118 0 0         }
119 0           return $decscale;
120             }
121              
122 0           =item B<to_DEC_TELESCOPE_OFFSET>
123              
124             Sets the declination telescope offset in arcseconds. It uses the
125             C<CAT-DEC> and C<DEC> keywords to derive the offset, and if either
126             does not exist, it returns a default of 0.0.
127              
128             =cut
129              
130             my $self = shift;
131             my $FITS_headers = shift;
132             my $decoffset = 0.0;
133             if ( exists $FITS_headers->{"CAT-DEC"} && exists $FITS_headers->{DEC} ) {
134 0     0 1    
135 0           # Obtain the reference and telescope declinations positions measured in degrees.
136 0           my $refdec = $self->dms_to_degrees( $FITS_headers->{"CAT-DEC"} );
137 0 0 0       my $dec = $self->dms_to_degrees( $FITS_headers->{DEC} );
138              
139             # Find the offsets between the positions in arcseconds on the sky.
140 0           $decoffset = 3600.0 * ( $dec - $refdec );
141 0           }
142              
143             # The sense is reversed compared with UKIRT, as these measure the
144 0           # places on the sky, not the motion of the telescope.
145             return -1.0 * $decoffset;
146             }
147              
148             =item B<to_DR_RECIPE>
149 0            
150             Returns the data-reduction recipe name. The selection depends on the
151             values of the C<OBJECT> and C<OBSTYPE> keywords. The default is
152             "QUICK_LOOK". A dark returns "REDUCE_DARK", and an object's recipe is
153             "JITTER_SELF_FLAT".
154              
155             =cut
156              
157             my $self = shift;
158             my $FITS_headers = shift;
159             my $recipe = "QUICK_LOOK";
160              
161             if ( exists $FITS_headers->{OBSTYPE} ) {
162 0     0 1   if ( $FITS_headers->{OBSTYPE} =~ /ARC/i ) {
163 0           $recipe = "REDUCE_ARC";
164 0           } elsif ( $FITS_headers->{OBSTYPE} =~ /BIAS/i ) {
165             $recipe = "REDUCE_BIAS";
166 0 0         } elsif ( $FITS_headers->{OBSTYPE} =~ /DARK/i ) {
167 0 0         $recipe = "REDUCE_DARK";
    0          
    0          
    0          
    0          
    0          
168 0           } elsif ( $FITS_headers->{OBSTYPE} =~ /LAMPFLAT/i ) {
169             $recipe = "REDUCE_FLAT";
170 0           } elsif ( $FITS_headers->{OBSTYPE} =~ /EXPOSE/i ) {
171             # $recipe = "JITTER_SELF_FLAT";
172 0           $recipe = "POINT_SOURCE_NOSTD";
173             } elsif ( $FITS_headers->{OBSTYPE} =~ /STANDARD/i ) {
174 0           $recipe = "STANDARD_STAR";
175             }
176             }
177 0            
178             return $recipe;
179 0           }
180              
181             =item B<to_RA_SCALE>
182              
183 0           Sets the RA scale in arcseconds per pixel. The C<PIXSCALE>
184             is used when it's defined. Otherwise it returns a default value of 0.2320
185             arcsec/pixel, multiplied by C<XBINNING> assuming this is defined (1.0 otherwise)
186              
187             =cut
188              
189             my $self = shift;
190             my $FITS_headers = shift;
191             my $rascale = 0.3860;
192              
193             # Assumes either x-y scales the same or the x corresponds to
194             # ra.
195 0     0 1   my $ccdscale = $self->via_subheader( $FITS_headers, "PIXSCALE" );
196 0           if ( defined $ccdscale ) {
197 0           $rascale = $ccdscale;
198             } else {
199             my $xbinning = $self->via_subheader( $FITS_headers, "XBINNING" );
200             if ( defined $xbinning ) {
201 0           $rascale = $rascale * $xbinning;
202 0 0         }
203 0           }
204             return $rascale;
205 0           }
206 0 0          
207 0            
208             =item B<to_RA_TELESCOPE_OFFSET>
209              
210 0           Sets the right-ascension telescope offset in arcseconds. It uses the
211             C<CAT-RA>, C<RA>, C<CAT-DEC> keywords to derive the offset, and if any
212             of these keywords does not exist, it returns a default of 0.0.
213              
214             =cut
215              
216             my $self = shift;
217             my $FITS_headers = shift;
218             my $raoffset = 0.0;
219              
220             if ( exists $FITS_headers->{"CAT-DEC"} &&
221             exists $FITS_headers->{"CAT-RA"} && exists $FITS_headers->{RA} ) {
222              
223 0     0 1   # Obtain the reference and telescope sky positions measured in degrees.
224 0           my $refra = $self->hms_to_degrees( $FITS_headers->{"CAT-RA"} );
225 0           my $ra = $self->hms_to_degrees( $FITS_headers->{RA} );
226             my $refdec = $self->dms_to_degrees( $FITS_headers->{"CAT-DEC"} );
227 0 0 0        
      0        
228             # Find the offset between the positions in arcseconds on the sky.
229             $raoffset = 3600.0 * ( $ra - $refra ) * $self->cosdeg( $refdec );
230             }
231 0            
232 0           # The sense is reversed compared with UKIRT, as these measure the
233 0           # place son the sky, not the motion of the telescope.
234             return -1.0 * $raoffset;
235             }
236 0            
237             =item B<to_SLIT_ANGLE>
238              
239             Returns the slit PA, trapping UNKNOWN values and setting them to -999 (could
240             in principle be recalculated from HA, Dec and Latitude via some SLALIBing...
241 0            
242             =cut
243              
244             my $self = shift;
245             my $FITS_headers = shift;
246             my $slit_angle = -999.0;
247             if ( exists $FITS_headers->{APERPA} ) {
248             my $slit_pa = $FITS_headers->{APERPA};
249             if ( $slit_pa !~ /UNKNOWN/i ) {
250             $slit_angle = $slit_pa;
251             }
252 0     0 1   }
253 0           return $slit_angle;
254 0           }
255 0 0          
256 0            
257 0 0         =item B<to_X_LOWER_BOUND>
258 0            
259             Returns the lower bound along the X-axis of the area of the detector
260             as a pixel index.
261 0            
262             =cut
263              
264             my $self = shift;
265             my $FITS_headers = shift;
266             my @bounds = $self->getbounds( $FITS_headers );
267             return $bounds[ 0 ];
268             }
269              
270             =item B<to_X_UPPER_BOUND>
271              
272             Returns the upper bound along the X-axis of the area of the detector
273 0     0 1   as a pixel index.
274 0            
275 0           =cut
276 0            
277             my $self = shift;
278             my $FITS_headers = shift;
279             my @bounds = $self->getbounds( $FITS_headers );
280             return $bounds[ 1 ];
281             }
282              
283             =item B<to_Y_LOWER_BOUND>
284              
285             Returns the lower bound along the Y-axis of the area of the detector
286             as a pixel index.
287 0     0 1    
288 0           =cut
289 0            
290 0           my $self = shift;
291             my $FITS_headers = shift;
292             my @bounds = $self->getbounds( $FITS_headers );
293             return $bounds[ 2 ];
294             }
295              
296              
297             =item B<to_Y_UPPER_BOUND>
298              
299             Returns the upper bound along the Y-axis of the area of the detector
300             as a pixel index.
301 0     0 1    
302 0           =cut
303 0            
304 0           my $self = shift;
305             my $FITS_headers = shift;
306             my @bounds = $self->getbounds( $FITS_headers );
307             return $bounds[ 3 ];
308             }
309              
310             # Supplementary methods for the translations
311             # ------------------------------------------
312              
313             # Obtain the detector bounds from a section in [xl:xu,yl:yu] syntax.
314             # If the TRIMSEC header is absent, use a default which corresponds
315             # to the useful part of the array (minus bias strips).
316 0     0 1   my $self = shift;
317 0           my $FITS_headers = shift;
318 0           my @bounds = ( 1, 2048, 1, 512 );
319 0           if ( exists $FITS_headers->{CCDSUM} ) {
320             my $binning = $FITS_headers->{CCDSUM};
321             if ( $binning eq '2 2' ) {
322             @bounds = ( 1, 1024, 1, 256 );
323             }
324             }
325             if ( exists $FITS_headers->{TRIMSEC} ) {
326             my $section = $FITS_headers->{TRIMSEC};
327             if ( $section !~ /UNKNOWN/i ) {
328             $section =~ s/\[//;
329 0     0 0   $section =~ s/\]//;
330 0           $section =~ s/,/:/g;
331 0           my @newbounds = split( /:/, $section );
332 0 0         if (@newbounds == grep { $_ == 0 } @newbounds) {
333 0           print "ERR: TRIMSEC all 0\n";
334 0 0         } else {
335 0           if ( $FITS_headers->{INSTRUME} !~ /^en0/i ) {
336             # Unless this is any data (which has a bad TRIMSEC), update bounds array
337             @bounds = @newbounds;
338 0 0         }
339 0           }
340 0 0         }
341 0           }
342 0           # print("DBG: Bounds=@bounds\n");
343 0           return @bounds;
344 0           }
345 0 0          
  0            
346 0           =back
347              
348 0 0         =head1 SEE ALSO
349              
350 0           C<Astro::FITS::HdrTrans>, C<Astro::FITS::HdrTrans::LCO>.
351              
352             =head1 AUTHOR
353              
354             Tim Lister E<lt>tlister@lcogt.netE<gt>
355              
356 0           =head1 COPYRIGHT
357              
358             =cut
359              
360             1;