=head1 NAME
Astro::FITS::HdrTrans::JAC - Base class for translation of Joint
Astronomy Centre instruments.
=head1 SYNOPSIS
use Astro::FITS::HdrTrans::JAC;
=head1 DESCRIPTION
This class provides a generic set of translations that are common to
instrumentation from the Joint Astronomy Centre. It should not be used
directly for translation of instrument FITS headers.
=cut
use 5.006;
use strict;
use Carp;
# Cache UTC definition
our $UTC = DateTime::TimeZone->new( name => 'UTC' );
# Inherit from the Base translation class and not HdrTrans itself
# (which is just a class-less wrapper).
our $VERSION = "1.66";
# in each class we have three sets of data.
# - constant mappings
# - unit mappings
# - complex mappings
# For a constant mapping, there is no FITS header, just a generic
# header that is constant.
my %CONST_MAP = (
);
# Unit mapping implies that the value propagates directly
# to the output with only a keyword name change.
my %UNIT_MAP = (
MSBID => 'MSBID',
MSB_TRANSACTION_ID => 'MSBTID',
SHIFT_TYPE => "OPER_SFT",
);
# Create the translation methods.
__PACKAGE__->_generate_lookup_methods( \%CONST_MAP, \%UNIT_MAP );
=head1 METHODS
=over 4
=item B<translate_from_FITS>
This routine overrides the base class implementation to enable the
caches to be cleared and for the location of the DATE-OBS/DATE-END field to
be found so that base class implementations will work correctly.
This means that some conversion methods (in particular those using time in
a base class) may not work properly outside the context of a full translation
unless they have been subclassed locally.
=cut
sub translate_from_FITS {
my $class = shift;
my $headers = shift;
# sort out DATE-OBS and DATE-END
$class->_fix_dates( $headers );
# Go to the base class
return $class->SUPER::translate_from_FITS( $headers, @_ );
}
=back
=head1 COMPLEX CONVERSIONS
These methods are more complicated than a simple mapping. We have to
provide both from- and to-FITS conversions All these routines are
methods and the to_ routines all take a reference to a hash and return
the translated value (a many-to-one mapping). The from_ methods take
a reference to a generic hash and return a translated hash (sometimes
these are many-to-many).
=over 4
=item B<to_OBSERVATION_ID>
Converts the C<OBSID> header directly into the C<OBSERVATION_ID>
generic header, or if that header does not exist, converts the
C<INSTRUME>, C<RUNNR>, and C<DATE-OBS> headers into C<OBSERVATION_ID>.
The form of the observation ID string is documented in
=cut
sub to_OBSERVATION_ID {
my $self = shift;
my $FITS_headers = shift;
my $return;
if ( exists( $FITS_headers->{'OBSID'} ) &&
defined( $FITS_headers->{'OBSID'} ) ) {
$return = $FITS_headers->{'OBSID'};
} else {
my $instrume = $self->to_INSTRUMENT( $FITS_headers );
my $obsnum = $self->to_OBSERVATION_NUMBER( $FITS_headers );
my $dateobs = $self->to_UTSTART( $FITS_headers );
if ( defined $dateobs && defined $obsnum && defined $instrume ) {
my $datetime = $dateobs->datetime;
$datetime =~ s/-//g;
$datetime =~ s/://g;
$return = join '_', (lc $instrume), $obsnum, $datetime;
}
}
return $return;
}
=item B<_fix_dates>
Sort out DATE-OBS and DATE-END in cases where they are not available directly.
This is mainly an issue with database retrievals where the date format is not
FITS compliant.
Astro::FITS::HdrTrans::JAC->_fix_dates( \%headers );
=cut
sub _fix_dates {
my ( $class, $FITS_headers ) = @_;
# DATE-OBS can be from DATE_OBS
# For compatability with Sybase database, also accept LONGDATEOBS LONGDATE
__PACKAGE__->_try_dates( $FITS_headers, 'DATE-OBS', qw/ DATE_OBS LONGDATEOBS LONGDATE / );
# DATE-END can be from DATE_END
# For compatability with Sybase database, also accept LONGDATEEND
__PACKAGE__->_try_dates( $FITS_headers, 'DATE-END', qw/ DATE_END LONGDATEEND / );
return;
}
# helper routine for _fix_dates
sub _try_dates {
my ( $class, $FITS_headers, $outkey, @tests ) = @_;
if (!exists $FITS_headers->{$outkey}) {
for my $key (@tests) {
if ( exists( $FITS_headers->{$key} ) ) {
my $date = _convert_mysql_date( $FITS_headers->{$key} );
if( defined( $date ) ) {
$FITS_headers->{$outkey} = $date->datetime;
last;
}
}
}
}
return;
}
# Convert MySQL date string to DateTime object.
# For compatability, also accepts Sybase date strings.
sub _convert_mysql_date {
my $date = shift;
$date =~ s/\s*$//;
if ($date =~ /\s*(\d\d\d\d)-(\d\d)-(\d\d)\s+(\d{1,2}):(\d\d):(\d\d)/) {
my $return = DateTime->new( year => $1,
month => $2,
day => $3,
hour => $4,
minute => $5,
second => $6,
time_zone => $UTC,
);
return $return;
} elsif ($date =~ /\s*(\w+)\s+(\d{1,2})\s+(\d{4})\s+(\d{1,2}):(\d\d):(\d\d)(?::\d\d\d)?(AM|PM)/) {
my $hour = $4;
if (uc($7) eq 'AM' && $hour == 12) {
$hour = 0;
} elsif ( uc($7) eq 'PM' && $hour < 12 ) {
$hour += 12;
}
my %mon_lookup = ( 'Jan' => 1,
'Feb' => 2,
'Mar' => 3,
'Apr' => 4,
'May' => 5,
'Jun' => 6,
'Jul' => 7,
'Aug' => 8,
'Sep' => 9,
'Oct' => 10,
'Nov' => 11,
'Dec' => 12 );
my $month = $mon_lookup{$1};
my $return = DateTime->new( year => $3,
month => $month,
day => $2,
hour => $hour,
minute => $5,
second => $6,
time_zone => $UTC,
);
return $return;
} else {
return undef;
}
}
=back
=head1 SEE ALSO
C<Astro::FITS::HdrTrans>, C<Astro::FITS::HdrTrans::Base>.
=head1 AUTHOR
Brad Cavanagh E<lt>b.cavanagh@jach.hawaii.eduE<gt>.
=head1 COPYRIGHT
Copyright (C) 2007 Science and Technology Facilities Council.
Copyright (C) 2006 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.
=cut
1;