| Astro-FITS-HdrTrans documentation | Contained in the Astro-FITS-HdrTrans distribution. |
Astro::FITS::HdrTrans::ISAAC - ESO ISAAC translations
use Astro::FITS::HdrTrans::ISAAC; %gen = Astro::FITS::HdrTrans::ISAAC->translate_from_FITS( %hdr );
This class provides a generic set of translations that are specific to the ISAAC camera of the European Southern Observatory.
The name of the instrument required to match (case insensitively)
against the INSTRUME/INSTRUMENT keyword to allow this class to
translate the specified headers. Called by the default
can_translate method.
$inst = $class->this_instrument();
Returns "ISAAC".
If the telescope ofset exists in arcsec, then use it. Otherwise convert the Cartesian offsets to equatorial offsets.
$Id: SOFI.pm 14879 2008-02-13 21:51:31Z timj $
Astro::FITS::HdrTrans, Astro::FITS::HdrTrans::UKIRT.
Malcolm J. Currie <mjc@star.rl.ac.uk> Brad Cavanagh <b.cavanagh@jach.hawaii.edu>, Tim Jenness <t.jenness@jach.hawaii.edu>.
Copyright (C) 2008 Science and Technology Facilities Council. Copyright (C) 2003-2005 Particle Physics and Astronomy Research Council. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either Version 2 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
| Astro-FITS-HdrTrans documentation | Contained in the Astro-FITS-HdrTrans distribution. |
package Astro::FITS::HdrTrans::ISAAC;
use 5.006; use warnings; use strict; use Carp; # Inherit from ESO use base qw/ Astro::FITS::HdrTrans::ESO /; use vars qw/ $VERSION /; $VERSION = "1.50"; # for a constant mapping, there is no FITS header, just a generic # header that is constant my %CONST_MAP = ( POLARIMETRY => 0, ); # NULL mappings used to override base class implementations my @NULL_MAP = qw/ /; # unit mapping implies that the value propogates directly # to the output with only a keyword name change my %UNIT_MAP = ( ); # Create the translation methods __PACKAGE__->_generate_lookup_methods( \%CONST_MAP, \%UNIT_MAP, \@NULL_MAP );
sub this_instrument { return "ISAAC"; }
sub to_DEC_TELESCOPE_OFFSET { my $self = shift; my $FITS_headers = shift; my $decoffset = 0.0; if ( exists $FITS_headers->{"HIERARCH.ESO.SEQ.CUMOFFSETD"} ) { $decoffset = $FITS_headers->{"HIERARCH.ESO.SEQ.CUMOFFSETD"}; } elsif ( exists $FITS_headers->{"HIERARCH.ESO.SEQ.CUMOFFSETX"} && exists $FITS_headers->{"HIERARCH.ESO.SEQ.CUMOFFSETY"} ) { my $pixscale = 0.148; if ( exists $FITS_headers->{"HIERARCH.ESO.INS.PIXSCALE"} ) { $pixscale = $FITS_headers->{"HIERARCH.ESO.INS.PIXSCALE"}; } # Sometimes the first imaging cumulative offsets are non-zero contrary # to the documentation. my $expno = 1; if ( exists $FITS_headers->{"HIERARCH.ESO.TPL.EXPNO"} ) { $expno = $FITS_headers->{"HIERARCH.ESO.TPL.EXPNO"}; } my ( $x_as, $y_as ); my $mode = uc( $self->get_instrument_mode($FITS_headers) ); if ( $expno == 1 && ( $mode eq "IMAGE" || $mode eq "POLARIMETRY" ) ) { $x_as = 0.0; $y_as = 0.0; } else { $x_as = $FITS_headers->{"HIERARCH.ESO.SEQ.CUMOFFSETX"} * $pixscale; $y_as = $FITS_headers->{"HIERARCH.ESO.SEQ.CUMOFFSETY"} * $pixscale; } # Define degrees to radians conversion and obtain the rotation angle. my $dtor = atan2( 1, 1 ) / 45.0; my $rotangle = $self->rotation($FITS_headers); my $cosrot = cos( $rotangle * $dtor ); my $sinrot = sin( $rotangle * $dtor ); # Apply the rotation matrix to obtain the equatorial pixel offset. $decoffset = -$x_as * $sinrot + $y_as * $cosrot; } # The sense is reversed compared with UKIRT, as these measure the # place on the sky, not the motion of the telescope. return -1.0 * $decoffset; } # Filter positions 1 and 2 used for SW and 3 & 4 for LW. sub to_FILTER { my $self = shift; my $FITS_headers = shift; my $filter = "Ks"; if ( exists $FITS_headers->{"HIERARCH.ESO.INS.FILT1.ID"} ) { $filter = $FITS_headers->{"HIERARCH.ESO.INS.FILT1.ID"}; } elsif ( exists $FITS_headers->{"HIERARCH.ESO.INS.FILT3.ID"} ) { $filter = $FITS_headers->{"HIERARCH.ESO.INS.FILT3.ID"}; } return $filter; } # Fixed values for the gain depend on the camera (SW or LW), and for LW # the readout mode. sub to_GAIN { my $self = shift; my $FITS_headers = shift; my $gain = 4.6; if ( exists $FITS_headers->{"HIERARCH.ESO.INS.MODE"} ) { if ( $FITS_headers->{"HIERARCH.ESO.INS.MODE"} =~ /SW/ ) { $gain = 4.6; } else { if ( exists $FITS_headers->{"HIERARCH.ESO.DET.MODE.NAME"} ) { if ( $FITS_headers->{"HIERARCH.ESO.DET.MODE.NAME"} =~ /LowBias/ ) { $gain = 8.7; } else { $gain = 7.8; } } } } return $gain; } sub to_GRATING_DISPERSION { my $self = shift; my $FITS_headers = shift; my $dispersion = 0.0; # if ( exists $FITS_headers->{CDELT1} ) { # $dispersion = $FITS_headers->{CDELT1}; # } else { if ( exists $FITS_headers->{"HIERARCH.ESO.INS.GRAT.NAME"} && exists $FITS_headers->{"HIERARCH.ESO.INS.GRAT.ORDER"} ) { my $order = $FITS_headers->{"HIERARCH.ESO.INS.GRAT.ORDER"}; if ( $FITS_headers->{"HIERARCH.ESO.INS.GRAT.NAME"} eq "LR" ) { if ( $order == 6 ) { $dispersion = 2.36e-4; } elsif ( $order == 5 ) { $dispersion = 2.83e-4; } elsif ( $order == 4 ) { $dispersion = 3.54e-4; } elsif ( $order == 3 ) { $dispersion = 4.72e-4; } elsif ( $order == 2 ) { $dispersion = 7.09e-4; } elsif ( $order == 1 ) { if ( exists $FITS_headers->{"HIERARCH.ESO.INS.FILT1.ID"} ) { my $filter = $FITS_headers->{"HIERARCH.ESO.INS.FILT1.ID"}; if ( $filter =~/SL/ ) { $dispersion = 1.412e-3; } else { $dispersion = 1.45e-3; } } else { $dispersion = 1.41e-3; } } # Medium dispersion } elsif ( $FITS_headers->{"HIERARCH.ESO.INS.GRAT.NAME"} eq "MR" ) { if ( $order == 6 ) { $dispersion = 3.7e-5; } elsif ( $order == 5 ) { $dispersion = 4.6e-5; } elsif ( $order == 4 ) { $dispersion = 5.9e-5; } elsif ( $order == 3 ) { $dispersion = 7.8e-5; } elsif ( $order == 2 ) { $dispersion = 1.21e-4; } elsif ( $order == 1 ) { if ( exists $FITS_headers->{"HIERARCH.ESO.INS.FILT1.ID"} ) { my $filter = $FITS_headers->{"HIERARCH.ESO.INS.FILT1.ID"}; if ( $filter =~/SL/ ) { $dispersion = 2.52e-4; } else { $dispersion = 2.39e-4; } } else { $dispersion = 2.46e-4; } } } } # } return $dispersion; } # If the telescope offset exists in arcsec, then use it. Otherwise # convert the Cartesian offsets to equatorial offsets. sub to_RA_TELESCOPE_OFFSET { my $self = shift; my $FITS_headers = shift; my $raoffset = 0.0; if ( exists $FITS_headers->{"HIERARCH.ESO.SEQ.CUMOFFSETA"} ) { $raoffset = $FITS_headers->{"HIERARCH.ESO.SEQ.CUMOFFSETA"}; } elsif ( exists $FITS_headers->{"HIERARCH.ESO.SEQ.CUMOFFSETX"} && exists $FITS_headers->{"HIERARCH.ESO.SEQ.CUMOFFSETY"} ) { my $pixscale = 0.148; if ( exists $FITS_headers->{"HIERARCH.ESO.INS.PIXSCALE"} ) { $pixscale = $FITS_headers->{"HIERARCH.ESO.INS.PIXSCALE"}; } # Sometimes the first imaging cumulative offsets are non-zero contrary # to the documentation. my $expno = 1; if ( exists $FITS_headers->{"HIERARCH.ESO.TPL.EXPNO"} ) { $expno = $FITS_headers->{"HIERARCH.ESO.TPL.EXPNO"}; } my ( $x_as, $y_as ); my $mode = uc( $self->get_instrument_mode($FITS_headers) ); if ( $expno == 1 && ( $mode eq "IMAGE" || $mode eq "POLARIMETRY" ) ) { $x_as = 0.0; $y_as = 0.0; } else { $x_as = $FITS_headers->{"HIERARCH.ESO.SEQ.CUMOFFSETX"} * $pixscale; $y_as = $FITS_headers->{"HIERARCH.ESO.SEQ.CUMOFFSETY"} * $pixscale; } # Define degrees to radians conversion and obtain the rotation angle. my $dtor = atan2( 1, 1 ) / 45.0; my $rotangle = $self->rotation($FITS_headers); my $cosrot = cos( $rotangle * $dtor ); my $sinrot = sin( $rotangle * $dtor ); # Apply the rotation matrix to obtain the equatorial pixel offset. $raoffset = -$x_as * $cosrot + $y_as * $sinrot; } # The sense is reversed compared with UKIRT, as these measure the # place on the sky, not the motion of the telescope. return -1.0 * $raoffset; } # Derive the translation between observing template and recipe name. sub to_DR_RECIPE { my $self = shift; my $FITS_headers = shift; my $recipe = "QUICK_LOOK"; # Obtain the observing template. These are equivalent # to the UKIRT OT science programmes and their tied DR recipes. # However, there are some wrinkles and variations to be tested. my $template = $FITS_headers->{"HIERARCH.ESO.TPL.ID"}; my $seq = $FITS_headers->{"HIERARCH.ESO.TPL.PRESEQ"}; if ( $template =~ /ISAAC[SL]W_img_obs_AutoJitter/ || $template =~ /ISAAC[SL]W_img_obs_GenericOffset/ ) { $recipe = "JITTER_SELF_FLAT"; } elsif ( $template eq "ISAACSW_img_cal_StandardStar" || $template eq "ISAACLW_img_cal_StandardStarOff" || $template eq "ISAACSW_img_tec_Zp" || $template eq "ISAACLW_img_tec_ZpNoChop" || $seq eq "ISAAC_img_cal_StandardStar" || $seq eq "ISAACLW_img_cal_StandardStarOff" ) { $recipe = "JITTER_SELF_FLAT_APHOT"; } elsif ( $template =~ /ISAAC[SL]W_img_obs_AutoJitterOffset/ ) { $recipe = "CHOP_SKY_JITTER"; # The following two perhaps should be using NOD_CHOP and a variant of # NOD_CHOP_APHOT to cope with the three source images (central double # flux) rather than four. } elsif ( $template eq "ISAACLW_img_obs_AutoChopNod" || $seq eq "ISAACLW_img_obs_AutoChopNod" ) { $recipe = "NOD_SELF_FLAT_NO_MASK"; } elsif ( $template eq "ISAACLW_img_cal_StandardStar" || $template =~ /^ISAACLW_img_tec_Zp/ || $seq eq "ISAACLW_img_cal_StandardStar" ) { $recipe = "NOD_SELF_FLAT_NO_MASK_APHOT"; } elsif ( $template =~ /ISAAC[SL]W_img_cal_Darks/ || $seq eq "ISAAC_img_cal_Darks" ) { $recipe = "REDUCE_DARK"; } elsif ( $template =~ /ISAAC[SL]W_img_cal_TwFlats/ ) { $recipe = "SKY_FLAT_MASKED"; # Imaging spectroscopy. There appears to be no distinction # for flats from target, hence no division into POL_JITTER and # SKY_FLAT_POL. } elsif ( $template eq "ISAACSW_img_obs_Polarimetry" || $template eq "ISAACSW_img_cal_Polarimetry" ) { $recipe = "POL_JITTER"; # Spectroscopy. EXTENDED_SOURCE may be more appropriate for # the ISAACSW_spec_obs_GenericOffset template. } elsif ( $template =~ /ISAAC[SL]W_spec_obs_AutoNodOnSlit/ || $template =~ /ISAAC[SL]W_spec_obs_GenericOffset/ || $template eq "ISAACLW_spec_obs_AutoChopNod" ) { $recipe = "POINT_SOURCE"; } elsif ( $template =~ /ISAAC[SL]W_spec_cal_StandardStar/ || $template eq "ISAACLW_spec_cal_StandardStarNod" || $template =~ /ISAAC[SL]W_spec_cal_AutoNodOnSlit/ ) { $recipe = "STANDARD_STAR"; } elsif ( $template =~ /ISAAC[SL]W_spec_cal_NightCalib/ ) { if ( $self->_to_OBSERVATION_TYPE() eq "LAMP" ) { $recipe = "LAMP_FLAT"; } elsif ( $self->_to_OBSERVATION_TYPE() eq "ARC" ) { $recipe = "REDUCE_ARC"; } else { $recipe = "REDUCE_SINGLE_FRAME"; } } elsif ( $template =~ /ISAAC[SL]W_spec_cal_Arcs/ || $seq eq "ISAAC_spec_cal_Arcs" ) { $recipe = "REDUCE_ARC"; } elsif ( $template =~ /ISAAC[SL]W_spec_cal_Flats/ ) { $recipe = "LAMP_FLAT"; } return $recipe; } # Fixed values for the gain depend on the camera (SW or LW), and for LW # the readout mode. sub to_SPEED_GAIN { my $self = shift; my $FITS_headers = shift; my $spd_gain = "Normal"; if ( exists $FITS_headers->{"HIERARCH.ESO.INS.MODE"} ) { if ( $FITS_headers->{"HIERARCH.ESO.INS.MODE"} =~ /SW/ ) { $spd_gain = "Normal"; } else { if ( exists $FITS_headers->{"HIERARCH.ESO.DET.MODE.NAME"} ) { if ( $FITS_headers->{"HIERARCH.ESO.DET.MODE.NAME"} =~ /LowBias/ ) { $spd_gain = "HiGain"; } else { $spd_gain = "Normal"; } } } } return $spd_gain; } # Translate to the SLALIB name for reference frame in spectroscopy. sub to_TELESCOPE { my $self = shift; my $FITS_headers = shift; my $telescope = "VLT1"; if ( exists $FITS_headers->{TELESCOP} ) { my $scope = $FITS_headers->{TELESCOP}; if ( defined( $scope ) ) { $telescope = $scope; $telescope =~ s/ESO-//; $telescope =~ s/-U//g; } } return $telescope; }
1;