File Coverage

blib/lib/Astro/FITS/HdrTrans/ISAAC.pm
Criterion Covered Total %
statement 18 159 11.3
branch 0 112 0.0
condition 0 69 0.0
subroutine 7 15 46.6
pod 2 9 22.2
total 27 364 7.4


line stmt bran cond sub pod time code
1              
2             =head1 NAME
3              
4             Astro::FITS::HdrTrans::ISAAC - ESO ISAAC translations
5              
6             =head1 SYNOPSIS
7              
8             use Astro::FITS::HdrTrans::ISAAC;
9              
10             %gen = Astro::FITS::HdrTrans::ISAAC->translate_from_FITS( %hdr );
11              
12             =head1 DESCRIPTION
13              
14             This class provides a generic set of translations that are specific to
15             the ISAAC camera of the European Southern Observatory.
16              
17             =cut
18              
19             use 5.006;
20 10     10   9025053 use warnings;
  10         34  
21 10     10   56 use strict;
  10         23  
  10         285  
22 10     10   41 use Carp;
  10         24  
  10         189  
23 10     10   44  
  10         15  
  10         673  
24             # Inherit from ESO
25             use base qw/ Astro::FITS::HdrTrans::ESO /;
26 10     10   49  
  10         20  
  10         1368  
27             use vars qw/ $VERSION /;
28 10     10   54  
  10         27  
  10         12827  
29             $VERSION = "1.65";
30              
31             # for a constant mapping, there is no FITS header, just a generic
32             # header that is constant
33             my %CONST_MAP = (
34             POLARIMETRY => 0,
35             );
36              
37             # NULL mappings used to override base class implementations
38             my @NULL_MAP = qw/ /;
39              
40             # unit mapping implies that the value propogates directly
41             # to the output with only a keyword name change
42              
43             my %UNIT_MAP = (
44             );
45              
46              
47             # Create the translation methods
48             __PACKAGE__->_generate_lookup_methods( \%CONST_MAP, \%UNIT_MAP, \@NULL_MAP );
49              
50             =head1 METHODS
51              
52             =over 4
53              
54             =item B<this_instrument>
55              
56             The name of the instrument required to match (case insensitively)
57             against the INSTRUME/INSTRUMENT keyword to allow this class to
58             translate the specified headers. Called by the default
59             C<can_translate> method.
60              
61             $inst = $class->this_instrument();
62              
63             Returns "ISAAC".
64              
65             =cut
66              
67             return "ISAAC";
68             }
69 20     20 1 52  
70             =back
71              
72             =head1 COMPLEX CONVERSIONS
73              
74             =over 4
75              
76             =item B<to_DEC_TELESCOPE_OFFSET>
77              
78             If the telescope ofset exists in arcsec, then use it. Otherwise
79             convert the Cartesian offsets to equatorial offsets.
80              
81             =cut
82              
83             my $self = shift;
84             my $FITS_headers = shift;
85             my $decoffset = 0.0;
86 0     0 1   if ( exists $FITS_headers->{"HIERARCH.ESO.SEQ.CUMOFFSETD"} ) {
87 0           $decoffset = $FITS_headers->{"HIERARCH.ESO.SEQ.CUMOFFSETD"};
88 0            
89 0 0 0       } elsif ( exists $FITS_headers->{"HIERARCH.ESO.SEQ.CUMOFFSETX"} &&
    0          
90 0           exists $FITS_headers->{"HIERARCH.ESO.SEQ.CUMOFFSETY"} ) {
91              
92             my $pixscale = 0.148;
93             if ( exists $FITS_headers->{"HIERARCH.ESO.INS.PIXSCALE"} ) {
94             $pixscale = $FITS_headers->{"HIERARCH.ESO.INS.PIXSCALE"};
95 0           }
96 0 0          
97 0           # Sometimes the first imaging cumulative offsets are non-zero contrary
98             # to the documentation.
99             my $expno = 1;
100             if ( exists $FITS_headers->{"HIERARCH.ESO.TPL.EXPNO"} ) {
101             $expno = $FITS_headers->{"HIERARCH.ESO.TPL.EXPNO"};
102 0           }
103 0 0         my ( $x_as, $y_as );
104 0           my $mode = uc( $self->get_instrument_mode($FITS_headers) );
105             if ( $expno == 1 && ( $mode eq "IMAGE" || $mode eq "POLARIMETRY" ) ) {
106 0           $x_as = 0.0;
107 0           $y_as = 0.0;
108 0 0 0       } else {
      0        
109 0           $x_as = $FITS_headers->{"HIERARCH.ESO.SEQ.CUMOFFSETX"} * $pixscale;
110 0           $y_as = $FITS_headers->{"HIERARCH.ESO.SEQ.CUMOFFSETY"} * $pixscale;
111             }
112 0            
113 0           # Define degrees to radians conversion and obtain the rotation angle.
114             my $dtor = atan2( 1, 1 ) / 45.0;
115              
116             my $rotangle = $self->rotation($FITS_headers);
117 0           my $cosrot = cos( $rotangle * $dtor );
118             my $sinrot = sin( $rotangle * $dtor );
119 0            
120 0           # Apply the rotation matrix to obtain the equatorial pixel offset.
121 0           $decoffset = -$x_as * $sinrot + $y_as * $cosrot;
122             }
123              
124 0           # The sense is reversed compared with UKIRT, as these measure the
125             # place on the sky, not the motion of the telescope.
126             return -1.0 * $decoffset;
127             }
128              
129 0           # Filter positions 1 and 2 used for SW and 3 & 4 for LW.
130             my $self = shift;
131             my $FITS_headers = shift;
132             my $filter = "Ks";
133             if ( exists $FITS_headers->{"HIERARCH.ESO.INS.FILT1.ID"} ) {
134 0     0 0   $filter = $FITS_headers->{"HIERARCH.ESO.INS.FILT1.ID"};
135 0           } elsif ( exists $FITS_headers->{"HIERARCH.ESO.INS.FILT3.ID"} ) {
136 0           $filter = $FITS_headers->{"HIERARCH.ESO.INS.FILT3.ID"};
137 0 0         }
    0          
138 0           return $filter;
139             }
140 0            
141             # Fixed values for the gain depend on the camera (SW or LW), and for LW
142 0           # the readout mode.
143             my $self = shift;
144             my $FITS_headers = shift;
145             my $gain = 4.6;
146             if ( exists $FITS_headers->{"HIERARCH.ESO.INS.MODE"} ) {
147             if ( $FITS_headers->{"HIERARCH.ESO.INS.MODE"} =~ /SW/ ) {
148 0     0 0   $gain = 4.6;
149 0           } else {
150 0           if ( exists $FITS_headers->{"HIERARCH.ESO.DET.MODE.NAME"} ) {
151 0 0         if ( $FITS_headers->{"HIERARCH.ESO.DET.MODE.NAME"} =~ /LowBias/ ) {
152 0 0         $gain = 8.7;
153 0           } else {
154             $gain = 7.8;
155 0 0         }
156 0 0         }
157 0           }
158             }
159 0           return $gain;
160             }
161              
162             my $self = shift;
163             my $FITS_headers = shift;
164 0           my $dispersion = 0.0;
165             # if ( exists $FITS_headers->{CDELT1} ) {
166             # $dispersion = $FITS_headers->{CDELT1};
167             # } else {
168 0     0 0   if ( exists $FITS_headers->{"HIERARCH.ESO.INS.GRAT.NAME"} &&
169 0           exists $FITS_headers->{"HIERARCH.ESO.INS.GRAT.ORDER"} ) {
170 0           my $order = $FITS_headers->{"HIERARCH.ESO.INS.GRAT.ORDER"};
171             if ( $FITS_headers->{"HIERARCH.ESO.INS.GRAT.NAME"} eq "LR" ) {
172             if ( $order == 6 ) {
173             $dispersion = 2.36e-4;
174 0 0 0       } elsif ( $order == 5 ) {
175             $dispersion = 2.83e-4;
176 0           } elsif ( $order == 4 ) {
177 0 0         $dispersion = 3.54e-4;
    0          
178 0 0         } elsif ( $order == 3 ) {
    0          
    0          
    0          
    0          
    0          
179 0           $dispersion = 4.72e-4;
180             } elsif ( $order == 2 ) {
181 0           $dispersion = 7.09e-4;
182             } elsif ( $order == 1 ) {
183 0           if ( exists $FITS_headers->{"HIERARCH.ESO.INS.FILT1.ID"} ) {
184             my $filter = $FITS_headers->{"HIERARCH.ESO.INS.FILT1.ID"};
185 0           if ( $filter =~/SL/ ) {
186             $dispersion = 1.412e-3;
187 0           } else {
188             $dispersion = 1.45e-3;
189 0 0         }
190 0           } else {
191 0 0         $dispersion = 1.41e-3;
192 0           }
193             }
194 0            
195             # Medium dispersion
196             } elsif ( $FITS_headers->{"HIERARCH.ESO.INS.GRAT.NAME"} eq "MR" ) {
197 0           if ( $order == 6 ) {
198             $dispersion = 3.7e-5;
199             } elsif ( $order == 5 ) {
200             $dispersion = 4.6e-5;
201             } elsif ( $order == 4 ) {
202             $dispersion = 5.9e-5;
203 0 0         } elsif ( $order == 3 ) {
    0          
    0          
    0          
    0          
    0          
204 0           $dispersion = 7.8e-5;
205             } elsif ( $order == 2 ) {
206 0           $dispersion = 1.21e-4;
207             } elsif ( $order == 1 ) {
208 0           if ( exists $FITS_headers->{"HIERARCH.ESO.INS.FILT1.ID"} ) {
209             my $filter = $FITS_headers->{"HIERARCH.ESO.INS.FILT1.ID"};
210 0           if ( $filter =~/SL/ ) {
211             $dispersion = 2.52e-4;
212 0           } else {
213             $dispersion = 2.39e-4;
214 0 0         }
215 0           } else {
216 0 0         $dispersion = 2.46e-4;
217 0           }
218             }
219 0           }
220             }
221             # }
222 0           return $dispersion;
223             }
224              
225             # If the telescope offset exists in arcsec, then use it. Otherwise
226             # convert the Cartesian offsets to equatorial offsets.
227             my $self = shift;
228 0           my $FITS_headers = shift;
229             my $raoffset = 0.0;
230             if ( exists $FITS_headers->{"HIERARCH.ESO.SEQ.CUMOFFSETA"} ) {
231             $raoffset = $FITS_headers->{"HIERARCH.ESO.SEQ.CUMOFFSETA"};
232              
233             } elsif ( exists $FITS_headers->{"HIERARCH.ESO.SEQ.CUMOFFSETX"} &&
234 0     0 0   exists $FITS_headers->{"HIERARCH.ESO.SEQ.CUMOFFSETY"} ) {
235 0            
236 0           my $pixscale = 0.148;
237 0 0 0       if ( exists $FITS_headers->{"HIERARCH.ESO.INS.PIXSCALE"} ) {
    0          
238 0           $pixscale = $FITS_headers->{"HIERARCH.ESO.INS.PIXSCALE"};
239             }
240              
241             # Sometimes the first imaging cumulative offsets are non-zero contrary
242             # to the documentation.
243 0           my $expno = 1;
244 0 0         if ( exists $FITS_headers->{"HIERARCH.ESO.TPL.EXPNO"} ) {
245 0           $expno = $FITS_headers->{"HIERARCH.ESO.TPL.EXPNO"};
246             }
247             my ( $x_as, $y_as );
248             my $mode = uc( $self->get_instrument_mode($FITS_headers) );
249             if ( $expno == 1 && ( $mode eq "IMAGE" || $mode eq "POLARIMETRY" ) ) {
250 0           $x_as = 0.0;
251 0 0         $y_as = 0.0;
252 0           } else {
253             $x_as = $FITS_headers->{"HIERARCH.ESO.SEQ.CUMOFFSETX"} * $pixscale;
254 0           $y_as = $FITS_headers->{"HIERARCH.ESO.SEQ.CUMOFFSETY"} * $pixscale;
255 0           }
256 0 0 0        
      0        
257 0           # Define degrees to radians conversion and obtain the rotation angle.
258 0           my $dtor = atan2( 1, 1 ) / 45.0;
259              
260 0           my $rotangle = $self->rotation($FITS_headers);
261 0           my $cosrot = cos( $rotangle * $dtor );
262             my $sinrot = sin( $rotangle * $dtor );
263              
264             # Apply the rotation matrix to obtain the equatorial pixel offset.
265 0           $raoffset = -$x_as * $cosrot + $y_as * $sinrot;
266             }
267 0            
268 0           # The sense is reversed compared with UKIRT, as these measure the
269 0           # place on the sky, not the motion of the telescope.
270             return -1.0 * $raoffset;
271             }
272 0            
273             # Derive the translation between observing template and recipe name.
274             my $self = shift;
275             my $FITS_headers = shift;
276             my $recipe = "QUICK_LOOK";
277 0            
278             # Obtain the observing template. These are equivalent
279             # to the UKIRT OT science programmes and their tied DR recipes.
280             # However, there are some wrinkles and variations to be tested.
281             my $template = $FITS_headers->{"HIERARCH.ESO.TPL.ID"};
282 0     0 0   my $seq = $FITS_headers->{"HIERARCH.ESO.TPL.PRESEQ"};
283 0            
284 0           if ( $template =~ /ISAAC[SL]W_img_obs_AutoJitter/ ||
285             $template =~ /ISAAC[SL]W_img_obs_GenericOffset/ ) {
286             $recipe = "JITTER_SELF_FLAT";
287              
288             } elsif ( $template eq "ISAACSW_img_cal_StandardStar" ||
289 0           $template eq "ISAACLW_img_cal_StandardStarOff" ||
290 0           $template eq "ISAACSW_img_tec_Zp" ||
291             $template eq "ISAACLW_img_tec_ZpNoChop" ||
292 0 0 0       $seq eq "ISAAC_img_cal_StandardStar" ||
    0 0        
    0 0        
    0 0        
    0 0        
    0 0        
    0 0        
    0 0        
    0 0        
    0 0        
    0 0        
    0 0        
    0 0        
      0        
      0        
      0        
293             $seq eq "ISAACLW_img_cal_StandardStarOff" ) {
294 0           $recipe = "JITTER_SELF_FLAT_APHOT";
295              
296             } elsif ( $template =~ /ISAAC[SL]W_img_obs_AutoJitterOffset/ ) {
297             $recipe = "CHOP_SKY_JITTER";
298              
299             # The following two perhaps should be using NOD_CHOP and a variant of
300             # NOD_CHOP_APHOT to cope with the three source images (central double
301             # flux) rather than four.
302 0           } elsif ( $template eq "ISAACLW_img_obs_AutoChopNod" ||
303             $seq eq "ISAACLW_img_obs_AutoChopNod" ) {
304             $recipe = "NOD_SELF_FLAT_NO_MASK";
305 0            
306             } elsif ( $template eq "ISAACLW_img_cal_StandardStar" ||
307             $template =~ /^ISAACLW_img_tec_Zp/ ||
308             $seq eq "ISAACLW_img_cal_StandardStar" ) {
309             $recipe = "NOD_SELF_FLAT_NO_MASK_APHOT";
310              
311             } elsif ( $template =~ /ISAAC[SL]W_img_cal_Darks/ ||
312 0           $seq eq "ISAAC_img_cal_Darks" ) {
313             $recipe = "REDUCE_DARK";
314              
315             } elsif ( $template =~ /ISAAC[SL]W_img_cal_TwFlats/ ) {
316             $recipe = "SKY_FLAT_MASKED";
317 0            
318             # Imaging spectroscopy. There appears to be no distinction
319             # for flats from target, hence no division into POL_JITTER and
320             # SKY_FLAT_POL.
321 0           } elsif ( $template eq "ISAACSW_img_obs_Polarimetry" ||
322             $template eq "ISAACSW_img_cal_Polarimetry" ) {
323             $recipe = "POL_JITTER";
324 0            
325             # Spectroscopy. EXTENDED_SOURCE may be more appropriate for
326             # the ISAACSW_spec_obs_GenericOffset template.
327             } elsif ( $template =~ /ISAAC[SL]W_spec_obs_AutoNodOnSlit/ ||
328             $template =~ /ISAAC[SL]W_spec_obs_GenericOffset/ ||
329             $template eq "ISAACLW_spec_obs_AutoChopNod" ) {
330             $recipe = "POINT_SOURCE";
331 0            
332             } elsif ( $template =~ /ISAAC[SL]W_spec_cal_StandardStar/ ||
333             $template eq "ISAACLW_spec_cal_StandardStarNod" ||
334             $template =~ /ISAAC[SL]W_spec_cal_AutoNodOnSlit/ ) {
335             $recipe = "STANDARD_STAR";
336              
337             } elsif ( $template =~ /ISAAC[SL]W_spec_cal_NightCalib/ ) {
338 0           if ( $self->_to_OBSERVATION_TYPE() eq "LAMP" ) {
339             $recipe = "LAMP_FLAT";
340             } elsif ( $self->_to_OBSERVATION_TYPE() eq "ARC" ) {
341             $recipe = "REDUCE_ARC";
342             } else {
343 0           $recipe = "REDUCE_SINGLE_FRAME";
344             }
345              
346 0 0         } elsif ( $template =~ /ISAAC[SL]W_spec_cal_Arcs/ ||
    0          
347 0           $seq eq "ISAAC_spec_cal_Arcs" ) {
348             $recipe = "REDUCE_ARC";
349 0            
350             } elsif ( $template =~ /ISAAC[SL]W_spec_cal_Flats/ ) {
351 0           $recipe = "LAMP_FLAT";
352             }
353             return $recipe;
354             }
355              
356 0           # Fixed values for the gain depend on the camera (SW or LW), and for LW
357             # the readout mode.
358             my $self = shift;
359 0           my $FITS_headers = shift;
360             my $spd_gain = "Normal";
361 0           if ( exists $FITS_headers->{"HIERARCH.ESO.INS.MODE"} ) {
362             if ( $FITS_headers->{"HIERARCH.ESO.INS.MODE"} =~ /SW/ ) {
363             $spd_gain = "Normal";
364             } else {
365             if ( exists $FITS_headers->{"HIERARCH.ESO.DET.MODE.NAME"} ) {
366             if ( $FITS_headers->{"HIERARCH.ESO.DET.MODE.NAME"} =~ /LowBias/ ) {
367 0     0 0   $spd_gain = "HiGain";
368 0           } else {
369 0           $spd_gain = "Normal";
370 0 0         }
371 0 0         }
372 0           }
373             }
374 0 0         return $spd_gain;
375 0 0         }
376 0            
377             # Translate to the SLALIB name for reference frame in spectroscopy.
378 0           my $self = shift;
379             my $FITS_headers = shift;
380             my $telescope = "VLT1";
381             if ( exists $FITS_headers->{TELESCOP} ) {
382             my $scope = $FITS_headers->{TELESCOP};
383 0           if ( defined( $scope ) ) {
384             $telescope = $scope;
385             $telescope =~ s/ESO-//;
386             $telescope =~ s/-U//g;
387             }
388 0     0 0   }
389 0           return $telescope;
390 0           }
391 0 0          
392 0           =back
393 0 0          
394 0           =head1 SEE ALSO
395 0            
396 0           C<Astro::FITS::HdrTrans>, C<Astro::FITS::HdrTrans::UKIRT>.
397              
398             =head1 AUTHOR
399 0            
400             Malcolm J. Currie E<lt>mjc@star.rl.ac.ukE<gt>
401             Brad Cavanagh E<lt>b.cavanagh@jach.hawaii.eduE<gt>,
402             Tim Jenness E<lt>t.jenness@jach.hawaii.eduE<gt>.
403              
404             =head1 COPYRIGHT
405              
406             Copyright (C) 2008 Science and Technology Facilities Council.
407             Copyright (C) 2003-2005 Particle Physics and Astronomy Research Council.
408             All Rights Reserved.
409              
410             This program is free software; you can redistribute it and/or modify it under
411             the terms of the GNU General Public License as published by the Free Software
412             Foundation; either Version 2 of the License, or (at your option) any later
413             version.
414              
415             This program is distributed in the hope that it will be useful,but WITHOUT ANY
416             WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
417             PARTICULAR PURPOSE. See the GNU General Public License for more details.
418              
419             You should have received a copy of the GNU General Public License along with
420             this program; if not, write to the Free Software Foundation, Inc., 59 Temple
421             Place, Suite 330, Boston, MA 02111-1307, USA.
422              
423             =cut
424              
425             1;