use
5.006;
our
$VERSION
=
"1.66"
;
our
$UTC
= DateTime::TimeZone->new(
name
=>
'UTC'
);
my
%CONST_MAP
= (
INST_DHS
=>
'ACSIS'
,
);
my
%UNIT_MAP
= (
AIRMASS_END
=>
'AMEND'
,
AMBIENT_TEMPERATURE
=>
'ATSTART'
,
AZIMUTH_END
=>
'AZEND'
,
BACKEND
=>
'BACKEND'
,
BANDWIDTH_MODE
=>
'BWMODE'
,
CHOP_ANGLE
=>
'CHOP_PA'
,
CHOP_COORDINATE_SYSTEM
=>
'CHOP_CRD'
,
CHOP_FREQUENCY
=>
'CHOP_FRQ'
,
CHOP_THROW
=>
'CHOP_THR'
,
ELEVATION_END
=>
'ELEND'
,
FRONTEND
=>
'INSTRUME'
,
NUMBER_OF_CYCLES
=>
'NUM_CYC'
,
SWITCH_MODE
=>
'SW_MODE'
,
SPECIES
=>
'MOLECULE'
,
VELOCITY_TYPE
=>
'DOPPLER'
,
SIDEBAND_MODE
=>
'SB_MODE'
,
SPECTRUM_NUMBER
=>
'SPECID'
,
SUBSYSTEM_NUMBER
=>
'SUBSYSNR'
,
OBSERVED_SIDEBAND
=>
'OBS_SB'
,
TRACKING_SIDEBAND
=>
'TRACK_SB'
,
);
__PACKAGE__->_generate_lookup_methods( \
%CONST_MAP
, \
%UNIT_MAP
);
sub
can_translate {
my
$self
=
shift
;
my
$headers
=
shift
;
if
(
exists
$headers
->{BACKEND} &&
defined
$headers
->{BACKEND} &&
$headers
->{BACKEND} =~ /^ACSIS/i
) {
return
1;
}
elsif
(
exists
$headers
->{BACKEND} &&
defined
$headers
->{BACKEND} &&
$headers
->{BACKEND} =~ /^DAS/i &&
! (
exists
$headers
->{
'GSDFILE'
} &&
exists
$headers
->{
'SCA#'
})) {
return
1;
}
elsif
(
exists
$headers
->{INST_DHS} &&
defined
$headers
->{INST_DHS} &&
$headers
->{INST_DHS} eq
'ACSIS'
) {
return
1;
}
else
{
return
0;
}
}
sub
to_DR_RECIPE {
my
$class
=
shift
;
my
$FITS_headers
=
shift
;
my
$dr
=
$FITS_headers
->{RECIPE};
if
(
defined
(
$dr
) ) {
$dr
=
uc
(
$dr
);
}
else
{
$dr
=
'REDUCE_SCIENCE'
;
}
my
$obstype
=
$class
->to_OBSERVATION_TYPE(
$FITS_headers
);
my
$pol
=
$class
->to_POLARIMETER(
$FITS_headers
);
my
$standard
=
$class
->to_STANDARD(
$FITS_headers
);
my
$utdate
=
$class
->to_UTDATE(
$FITS_headers
);
my
$freq_sw
=
$class
->_is_FSW(
$FITS_headers
);
if
((
defined
$utdate
) and
$utdate
< 20080701) {
if
((
defined
$obstype
) &&
$obstype
=~ /skydip/i &&
$dr
eq
'REDUCE_SCIENCE'
) {
$dr
=
"REDUCE_SKYDIP"
;
}
}
my
$is_sci
= ( (
defined
$obstype
) and
$obstype
=~ /science|raster|scan|grid|jiggle/i );
if
(
$standard
&&
$is_sci
) {
$dr
=
"REDUCE_STANDARD"
;
}
if
((
defined
$utdate
) &&
$utdate
> 20081115 &&
$pol
&&
$is_sci
) {
$dr
.=
"_POL"
unless
$dr
=~ /_POL$/;
}
if
(
$dr
eq
'REDUCE_SCIENCE'
) {
$dr
.=
'_'
. (
$freq_sw
?
'FSW'
:
'GRADIENT'
);
}
return
$dr
;
}
sub
from_DR_RECIPE {
my
$class
=
shift
;
my
$generic_headers
=
shift
;
my
$dr
=
$generic_headers
->{DR_RECIPE};
my
$ut
=
$generic_headers
->{UTDATE};
if
(
defined
$ut
&&
$ut
< 20080615) {
if
(
defined
$dr
&&
$dr
eq
'REDUCE_SKYDIP'
) {
$dr
=
'REDUCE_SCIENCE'
;
}
}
return
(
"RECIPE"
=>
$dr
);
}
sub
to_POLARIMETER {
my
$class
=
shift
;
my
$FITS_headers
=
shift
;
my
$inbeam
=
$FITS_headers
->{INBEAM};
my
$utdate
=
$class
->to_UTDATE(
$FITS_headers
);
if
( (
defined
$utdate
) &&
$utdate
> 20081115 &&
defined
(
$inbeam
) &&
$inbeam
=~ /pol/i ) {
return
1;
}
return
0;
}
sub
from_POLARIMETER {
my
$class
=
shift
;
my
$generic_headers
=
shift
;
my
$pol
=
$generic_headers
->{POLARIMETER};
if
(
$pol
) {
return
(
"INBEAM"
=>
"POL"
);
}
return
(
"INBEAM"
=>
undef
);
}
sub
to_REFERENCE_LOCATION {
my
$self
=
shift
;
my
$FITS_headers
=
shift
;
my
$ref_location
=
undef
;
my
(
$system
,
$base_lon
,
$base_lat
);
$system
=
defined
(
$FITS_headers
->{
'TRACKSYS'
} ) ?
$FITS_headers
->{
'TRACKSYS'
} :
undef
;
$system
=~ s/\s+$//
if
defined
(
$system
);
$base_lon
=
defined
(
$FITS_headers
->{
'BASEC1'
} ) ?
$FITS_headers
->{
'BASEC1'
} :
undef
;
$base_lat
=
defined
(
$FITS_headers
->{
'BASEC2'
} ) ?
$FITS_headers
->{
'BASEC2'
} :
undef
;
my
$ref_lon
=
undef
;
if
(
defined
(
$system
) &&
defined
(
$base_lon
) ) {
if
(
defined
(
$FITS_headers
->{
'SKYREFX'
} ) ) {
my
$ref_x
=
$FITS_headers
->{
'SKYREFX'
};
my
@comps
=
split
( /\s+/,
$ref_x
);
my
$offset_lon
=
$comps
[1] / 3600.0;
$ref_lon
=
sprintf
(
"%.2f"
,
$base_lon
+
$offset_lon
);
}
}
my
$ref_lat
=
undef
;
if
(
defined
(
$system
) &&
defined
(
$base_lat
) ) {
if
(
defined
(
$FITS_headers
->{
'SKYREFY'
} ) ) {
my
$ref_y
=
$FITS_headers
->{
'SKYREFY'
};
my
@comps
=
split
( /\s+/,
$ref_y
);
my
$offset_lat
=
$comps
[1] / 3600.0;
$ref_lat
=
sprintf
(
"%.2f"
,
$base_lat
+
$offset_lat
);
}
}
if
(
defined
(
$ref_lon
) &&
defined
(
$ref_lat
) ) {
$ref_location
=
$system
.
"_"
.
$ref_lon
.
"_"
.
$ref_lat
;
}
return
$ref_location
;
}
sub
to_SAMPLE_MODE {
my
$self
=
shift
;
my
$FITS_headers
=
shift
;
my
$sam_mode
;
if
(
defined
$FITS_headers
->{
'SAM_MODE'
} ) {
if
((
uc
$FITS_headers
->{
'SAM_MODE'
} ) eq
'RASTER'
) {
$sam_mode
=
'scan'
;
}
else
{
$sam_mode
=
lc
(
$FITS_headers
->{
'SAM_MODE'
} );
}
}
return
$sam_mode
;
}
sub
to_SURVEY {
my
$self
=
shift
;
my
$FITS_headers
=
shift
;
my
$survey
;
if
(
defined
(
$FITS_headers
->{
'SURVEY'
} ) ) {
$survey
=
$FITS_headers
->{
'SURVEY'
};
}
else
{
my
$project
=
$FITS_headers
->{
'PROJECT'
};
if
(
defined
(
$project
) ) {
if
(
$project
=~ /JLS([GNS])/ ) {
if
( $1 eq
'G'
) {
$survey
=
'GBS'
;
}
elsif
( $1 eq
'N'
) {
$survey
=
'NGS'
;
}
elsif
( $1 eq
'S'
) {
$survey
=
'SLS'
;
}
}
}
}
return
$survey
;
}
sub
to_EXPOSURE_TIME {
my
$self
=
shift
;
my
$FITS_headers
=
shift
;
$self
->_fix_dates(
$FITS_headers
);
my
$return
;
if
(
exists
(
$FITS_headers
->{
'DATE-OBS'
} ) &&
exists
(
$FITS_headers
->{
'DATE-END'
} ) ) {
my
$start
=
$self
->to_UTSTART(
$FITS_headers
);
my
$end
=
$self
->to_UTEND(
$FITS_headers
);
if
(
defined
$start
and
defined
$end
) {
my
$duration
=
$end
-
$start
;
$return
=
$duration
->seconds;
}
}
return
$return
;
}
sub
to_INSTRUMENT {
my
$self
=
shift
;
my
$FITS_headers
=
shift
;
my
$return
;
if
(
exists
(
$FITS_headers
->{
'INSTRUME'
} ) ) {
if
(
$FITS_headers
->{
'INSTRUME'
} =~ /^HARP/ ||
$FITS_headers
->{
'INSTRUME'
} =~ /^FE_HARP/ ) {
$return
=
"HARP"
;
}
else
{
$return
=
$FITS_headers
->{
'INSTRUME'
};
}
}
return
$return
;
}
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
{
$self
->_fix_dates(
$FITS_headers
);
my
$backend
=
$self
->to_BACKEND(
$FITS_headers
);
my
$obsnum
=
$self
->to_OBSERVATION_NUMBER(
$FITS_headers
);
my
$dateobs
=
$self
->to_UTSTART(
$FITS_headers
);
if
(
defined
(
$backend
) &&
defined
(
$obsnum
) &&
defined
(
$dateobs
) ) {
my
$datetime
=
$dateobs
->datetime;
$datetime
=~ s/-//g;
$datetime
=~ s/://g;
$return
=
join
'_'
, (
lc
$backend
),
$obsnum
,
$datetime
;
}
}
return
$return
;
}
sub
to_OBSERVATION_MODE {
my
$self
=
shift
;
my
$FITS_headers
=
shift
;
my
$return
;
if
(
exists
(
$FITS_headers
->{
'SAM_MODE'
} ) &&
exists
(
$FITS_headers
->{
'SW_MODE'
} ) &&
exists
(
$FITS_headers
->{
'OBS_TYPE'
} ) ) {
my
$sam_mode
=
$FITS_headers
->{
'SAM_MODE'
};
$sam_mode
=~ s/\s//g;
$sam_mode
=
"raster"
if
$sam_mode
eq
"scan"
;
my
$sw_mode
=
$FITS_headers
->{
'SW_MODE'
};
$sw_mode
=~ s/\s//g;
my
$obs_type
=
$FITS_headers
->{
'OBS_TYPE'
};
$obs_type
=
"science"
unless
$obs_type
;
$obs_type
=~ s/\s//g;
$return
= ( (
$obs_type
=~ /science/i )
?
join
'_'
,
$sam_mode
,
$sw_mode
:
join
'_'
,
$sam_mode
,
$sw_mode
,
$obs_type
);
}
return
$return
;
}
sub
to_OBSERVATION_TYPE {
my
$self
=
shift
;
my
$FITS_headers
=
shift
;
my
$return
;
my
$ot
=
$FITS_headers
->{OBS_TYPE};
$ot
=
"science"
unless
$ot
;
if
(
$ot
) {
my
$obs_type
=
lc
(
$ot
);
if
(
$obs_type
=~ /science/ ) {
if
(
defined
(
$FITS_headers
->{
'SAM_MODE'
} ) ) {
my
$sam_mode
=
$FITS_headers
->{
'SAM_MODE'
};
if
(
$sam_mode
=~ /raster|scan/ ) {
$return
=
"raster"
;
}
elsif
(
$sam_mode
=~ /grid/ ) {
$return
=
"grid"
;
}
elsif
(
$sam_mode
=~ /jiggle/ ) {
$return
=
"jiggle"
;
}
else
{
croak
"Unexpected sample mode: '$sam_mode'"
;
}
}
}
elsif
(
$obs_type
=~ /focus/ ) {
$return
=
"focus"
;
}
elsif
(
$obs_type
=~ /pointing/ ) {
$return
=
"pointing"
;
}
elsif
(
$obs_type
=~ /skydip/) {
$return
=
"skydip"
;
}
else
{
croak
"Unexpected OBS_TYPE of '$obs_type'\n"
;
}
}
return
$return
;
}
sub
to_REST_FREQUENCY {
my
$self
=
shift
;
my
$FITS_headers
=
shift
;
my
$frameset
=
shift
;
my
$return
;
if
(
defined
(
$frameset
) &&
UNIVERSAL::isa(
$frameset
,
"Starlink::AST::FrameSet"
) ) {
eval
{
my
$frequency
=
$frameset
->Get(
"restfreq"
);
$return
=
$frequency
* 1_000_000_000;
};
}
elsif
(
exists
(
$FITS_headers
->{
'RESTFREQ'
} ) ||
(
exists
(
$FITS_headers
->{
'SUBHEADERS'
} ) &&
exists
(
$FITS_headers
->{
'SUBHEADERS'
}->[0]->{
'RESTFREQ'
} ) ) ) {
$return
=
exists
(
$FITS_headers
->{
'RESTFREQ'
} ) ?
$FITS_headers
->{
'RESTFREQ'
} :
$FITS_headers
->{
'SUBHEADERS'
}->[0]->{
'RESTFREQ'
};
$return
*= 1_000_000_000;
}
return
$return
;
}
sub
to_SYSTEM_VELOCITY {
my
$self
=
shift
;
my
$FITS_headers
=
shift
;
my
$frameset
=
shift
;
my
$return
;
if
(
exists
(
$FITS_headers
->{
'DOPPLER'
} ) &&
defined
$FITS_headers
->{DOPPLER} ) {
my
$doppler
=
uc
(
$FITS_headers
->{
'DOPPLER'
} );
if
(
defined
(
$frameset
) &&
UNIVERSAL::isa(
$frameset
,
"Starlink::AST::FrameSet"
) ) {
eval
{
my
$sourcevrf
=
uc
(
$frameset
->Get(
"sourcevrf"
) );
$return
=
substr
(
$doppler
, 0, 3 ) .
substr
(
$sourcevrf
, 0, 3 );
};
}
if
(!
defined
$return
) {
if
(
exists
(
$FITS_headers
->{
'SPECSYS'
} ) ) {
my
$specsys
=
uc
(
$FITS_headers
->{
'SPECSYS'
} );
$return
=
substr
(
$doppler
, 0, 3 ) .
substr
(
$specsys
, 0, 3 );
}
else
{
my
$specsys
=
''
;
if
(
$doppler
eq
'RADIO'
) {
$specsys
=
'LSRK'
;
}
elsif
(
$doppler
eq
'OPTICAL'
) {
$specsys
=
'HELIOCENTRIC'
;
}
$return
=
substr
(
$doppler
, 0, 3 ) .
substr
(
$specsys
, 0, 3 );
}
}
}
return
$return
;
}
sub
to_TRANSITION {
my
$self
=
shift
;
my
$FITS_headers
=
shift
;
my
$transition
=
$FITS_headers
->{
'TRANSITI'
};
return
undef
unless
defined
$transition
;
$transition
=~ s/^ *//;
$transition
=~ s/ *$//;
$transition
=~ s/ +/ /g;
return
$transition
;
}
sub
from_TRANSITION {
my
$self
=
shift
;
my
$generic_headers
=
shift
;
my
$transition
=
$generic_headers
->{
'TRANSITION'
};
return
(
TRANSITI
=>
$transition
);
}
sub
to_VELOCITY {
my
$self
=
shift
;
my
$FITS_headers
=
shift
;
my
$frameset
=
shift
;
my
$velocity
=
undef
;
if
(
defined
(
$frameset
) &&
UNIVERSAL::isa(
$frameset
,
"Starlink::AST::FrameSet"
) ) {
my
$sourcesys
=
"VRAD"
;
if
(
defined
(
$FITS_headers
->{
'DOPPLER'
} ) ) {
if
(
$FITS_headers
->{
'DOPPLER'
} =~ /rad/i ) {
$sourcesys
=
"VRAD"
;
}
elsif
(
$FITS_headers
->{
'DOPPLER'
} =~ /opt/i ) {
$sourcesys
=
"VOPT"
;
}
elsif
(
$FITS_headers
->{
'DOPPLER'
} =~ /red/i ) {
$sourcesys
=
"REDSHIFT"
;
}
}
eval
{
$frameset
->Set(
sourcesys
=>
$sourcesys
);
$velocity
=
$frameset
->Get(
"sourcevel"
);
};
}
else
{
if
(
exists
(
$FITS_headers
->{
'DOPPLER'
} ) &&
(
exists
(
$FITS_headers
->{
'ZSOURCE'
} ) ||
exists
(
$FITS_headers
->{
'SUBHEADERS'
}->[0]->{
'ZSOURCE'
} ) ) ) {
my
$doppler
=
uc
(
$FITS_headers
->{
'DOPPLER'
} );
my
$zsource
=
exists
(
$FITS_headers
->{
'ZSOURCE'
} ) ?
$FITS_headers
->{
'ZSOURCE'
} :
$FITS_headers
->{
'SUBHEADERS'
}->[0]->{
'ZSOURCE'
};
if
(
$doppler
eq
'REDSHIFT'
) {
$velocity
=
$zsource
;
}
elsif
(
$doppler
eq
'OPTICAL'
) {
$velocity
=
$zsource
* CLIGHT;
}
elsif
(
$doppler
eq
'RADIO'
) {
$velocity
= ( CLIGHT *
$zsource
) / ( 1 +
$zsource
);
}
}
}
return
$velocity
;
}
sub
to_SUBSYSTEM_IDKEY {
my
$self
=
shift
;
my
$FITS_headers
=
shift
;
my
$general
=
$self
->SUPER::to_SUBSYSTEM_IDKEY(
$FITS_headers
);
return
(
defined
$general
?
$general
:
"SUBSYSNR"
);
}
sub
_is_FSW {
my
$class
=
shift
;
my
$FITS_headers
=
shift
;
my
$fsw
=
$FITS_headers
->{SW_MODE};
if
(
defined
(
$fsw
) &&
$fsw
=~ /freqsw/i ) {
return
1;
}
return
0;
}
1;