package Subs::UvotAttitude;
##############################################################################
#
# DESCRIPTION: Generates UVOT Attitude file
# DESCRIPTION: The creation of such attitude file will take place
# DESCRIPTION: IF and ONLY IF the sequence is "FINAL FOR ARCHIVE"
#
# HISTORY: $Log: UvotAttitude.pm,v $
# HISTORY: Revision 1.3 2013/07/16 07:15:45 apsop
# HISTORY: Don't include grism images when calling uvotskycorr,
# HISTORY: by getting the filenames by calling getNonGrismSkyImages.
# HISTORY:
# HISTORY: Revision 1.2 2012/01/12 06:52:03 apsop
# HISTORY: Changes going to proc3.15.03
# HISTORY:
# HISTORY: 2011-12-05 Jeff Guerber: Call uvotmodmap ($umodmap) with ncell=16
# HISTORY: instead of =2 (supposedly uvotmodmap has been fixed so its speed
# HISTORY: is no longer an issue).
# HISTORY:
# HISTORY: 2011-11-10 Jeff Guerber as apsop
# HISTORY: Added refattopt and alignfile params to uvotexpmap call.
# HISTORY: Read refattopt value from $procpar (sw0.par).
# HISTORY:
# HISTORY: 2011-11-03 Jeff Guerber as apsop
# HISTORY: Added refattopt to parameter lists for swiftxform and uvotimage,
# HISTORY: and alignfile for swiftxform.
# HISTORY:
#
# VERSION: 0.0
#
##############################################################################
use Subs::Sub;
use Subs::Images;
use Util::Xanadu;
use Subs::UvotNames;
@ISA = ("Subs::Images");
use strict;
sub new {
my $proto=shift;
my $self=$proto->SUPER::new();
$self->{DESCRIPTION}="Extracting attitude for UVOT";
return $self;
}
##################
# METHODS:
##################
sub body {
my $self=shift;
my $log =$self->log();
my $filename=$self->filename();
my $jobpar = $self->jobpar();
my $jobtitle = $jobpar->read('job_title');
if($jobtitle ne 'FINAL FOR ARCHIVE'){
$log->entry("Process skipped since sequence is not \"FINAL FOR ARCHIVE\"");
return;
}
my $catfile = $filename->get('hk', 'uvot', 'ct', '*');
unless( -f $catfile ){
$log->entry("No uvot catalogue file indicates no uvot data");
return;
}
$self->create_images();
$self->image_raw_to_det();
$self->create_exposure_maps();
$self->aspect_correct_sky_images();
} # end of body method
#############################################################################
# Extract images from filtered event data and raw images files
#############################################################################
sub create_images
{
my $self = shift;
my $log =$self->log();
my $filename=$self->filename();
my $procpar =$self->procpar();
my $jobpar =$self->jobpar();
$log->entry('Creating images from UVOT event and image mode data');
my $attfile = $filename->get('attitude', 's');
my $jumpatt = $filename->get('attcorr', 'p');
$attfile = $jumpatt if -f $jumpatt;
if (not $attfile) {
$log->error(2, 'no attitude file available');
return;
}
my @eventFiles = $filename->get('unfiltered', 'uvot', '*', '*');
@eventFiles = grep !/[0-9]ubl/, @eventFiles;
my @imageFiles = $filename->get('rawimage', 'uvot', '*', '*');
@imageFiles = grep !/[0-9]ubl/, @imageFiles;
@imageFiles = grep !/[0-9]udi/, @imageFiles;
unless( @eventFiles || @imageFiles ){
$log->error(1, 'No UVOT image or event files to process.');
return;
}
my $catfile = $filename->get('hk', 'uvot', 'ct', '*');
if (not -f $catfile) {
$log->entry('No UVOT exposure catalogue to update');
}else {
$log->entry('UVOT exposure catalogue update not implemented');
}
my $prefix = 'Qz3'; # a unique string
my $tool = Util::HEAdas->new('uvotimage')->is_script(1);
$tool->params({
prefix => $prefix,
attfile => $attfile,
teldeffile => 'CALDB',
alignfile => 'CALDB',
ra => $jobpar->read('ra'),
dec => $jobpar->read('dec'),
roll => $jobpar->read('roll'),
flatfield => 'no',
mod8corr => 'no',
refattopt => $procpar->read('refattopt'),
# badpix => 'no',
# catfile => $catfile,
chatter => 5
});
$tool->params({mod8corr => 'yes'})
if $jobpar->{TIMELIST}->{final};
my $swobsid = $filename->sequence_specific;
my @dataFiles = (@eventFiles, @imageFiles);
while( @dataFiles ){
my $type = $dataFiles[0] =~ /\.evt/ ? 'unfiltered' : 'rawimage';
my ($mode, $index) = ($filename->parse($dataFiles[0], $type))[1,2];
$mode = substr($mode, 0, 2);
my @infiles = ( $filename->get('rawimage', 'uvot', "$mode*", $index),
$filename->get('unfiltered', 'uvot', "$mode*", $index) );
my $expr = '('. join('|',@infiles) .')';
@dataFiles = grep !/${expr}/, @dataFiles;
$tool->params({infile => join(',', @infiles)})->run();
# move each file ${prefix}xxx to sw<obsid>xxx
foreach my $name (glob($prefix . '*')) {
my $xxx = substr($name, length($prefix));
my $fixed = $swobsid . $xxx;
if($index!=0){
$index = sprintf('%02d', $index) if length($index)<2;
$fixed =~ s/\./_${index}./;
}
if (-f $fixed) {
unlink($fixed);
}
rename($name, $fixed);
}
}
} # end create images method
###############################################################################
# convert raw coordinate images to detector coordinates
###############################################################################
sub image_raw_to_det
{
my $self=shift;
my $log =$self->log();
my $filename=$self->filename();
my $procpar =$self->procpar();
my $jobpar =$self->jobpar();
$log->entry("Converting raw grism images to detector coordinates");
my $attfile = $filename->get('attitude', 's');
my $jumpatt = $filename->get('attcorr', 'p');
$attfile = $jumpatt if -f $jumpatt;
if (not $attfile) {
$attfile = 'NONE';
}
$log->entry("Processing raw uvot images");
my $ubadpix = Util::HEAdas->new('uvotbadpix');
my $umodmap = Util::HEAdas->new('uvotmodmap');
my $uflatfield = Util::HEAdas->new('uvotflatfield');
$uflatfield->params({flatfile => 'CALDB'});
$log->entry("setting {RA,DEC,PA}_PNT in all raw images");
my $ra = $jobpar->read("ra");
my $dec = $jobpar->read("dec");
my $roll = $jobpar->read("roll");
#########################################
# create the swiftxform tool
#########################################
my $swiftxform = Util::HEAdas->new('swiftxform');
$swiftxform->params({
teldeffile => 'CALDB',
alignfile => 'CALDB',
to => 'DET',
attfile => $attfile,
ra => $jobpar->read('ra'),
dec => $jobpar->read('dec'),
roll => $jobpar->read('roll'),
aberration => 'no',
seed => $procpar->read('seed'),
refattopt => $procpar->read('refattopt'),
chatter => 4,
clobber => 'yes',
})
->is_script(1);
######################
# loop over _GRISM_ files
# since only they are converted to DET coordinates
######################
foreach my $rawFile ($filename->get('rawimage', 'uvot', 'g*', '*') ) {
{
my $imageFits = Util::FITSfile->new($rawFile);
for my $i (1 .. $imageFits->nhdus - 1) {
$imageFits->ext($i);
$imageFits->keyword('RA_PNT', $ra);
$imageFits->keyword('DEC_PNT', $dec);
$imageFits->keyword('PA_PNT', $roll);
}
}
my $badFile = $filename->corresponding('rawimage', 'badimage', $rawFile);
my $corrFile = $filename->corresponding('rawimage', 'corrimage', $rawFile);
my $mod8File = 'mod.tmp';
$log->entry("running uvotbadpix on $rawFile");
$ubadpix->params({infile => $rawFile,
badpixlist => 'CALDB',
outfile => $badFile,
clobber => 'yes',
chatter => 3})
->run();
$log->entry("running uvotmodmap on $rawFile");
$umodmap->params({infile => $rawFile,
badpixfile => $badFile,
outfile => $mod8File,
nsig => 3,
clobber => 'yes',
ncell => 16,
chatter => 3})
->run();
# uflatfield will go here
$uflatfield->params({
infile => $mod8File,
clobber => 'yes',
infile => $rawFile,
outfile => $corrFile})
->run();
# unlink($mod8File);
#########################################
# determine the DET coordinate filename
#########################################
my $detFile = $filename->corresponding("rawimage", "detimage", $rawFile);
$log->entry("converting $rawFile to $detFile");
######################
# do the conversion
######################
$swiftxform->params({
infile => $mod8File,
outfile => $detFile,
})
->run();
unlink($mod8File);
} # end of loop over files
} # end of image_raw_to_det method
###############################################################################
# generate exposure maps
###############################################################################
sub create_exposure_maps {
my $self=shift;
my $log = $self->log();
my $filename= $self->filename();
my $procpar = $self->procpar();
my $jobpar = $self->jobpar();
$log->entry("Creating exposure maps");
######################################################
# make sure there is an attitude file
######################################################
my $attitude = $filename->get('attitude', 's');
my $jumpatt = $filename->get('attcorr', 'p');
$attitude = $jumpatt if -f $jumpatt;
unless(-f $attitude) {
$log->entry("No attitude data available - can't make exposure maps");
return;
}
#########################################
# create the uvotexpmap tool
#########################################
## attdelta => 100,
my $uexpmap = Util::HEAdas->new('uvotexpmap')
->params({attfile => $attitude,
teldeffile => 'CALDB',
alignfile => 'CALDB',
method => 'SHIFTADD',
attdelta => 0.1,
aberration => 'no',
refattopt => $procpar->read('refattopt'),
chatter => 4});
my $aspect_follow_file = $filename->get('hk', 'uvot', 'af', 0);
if( -f $aspect_follow_file){
$uexpmap->params({trackfile => $aspect_follow_file});
}else{
$uexpmap->params({trackfile => 'NONE'});
}
######################
# loop over files
######################
foreach my $skyFile ($filename->get('filterimg', 'uvot', '*', '*') ) {
# exclude grism files
next if $filename->is_grism($skyFile, 'skyimage');
#########################################
# determine the exposure map filename
#########################################
my ($expFile, $maskFile) = ($skyFile) x 2;
$expFile =~ s/_sk([\._])/_ex$1/;
$maskFile =~ s/_sk([\._])/_mk$1/;
$log->entry("building exposure map $expFile for $skyFile");
my $badFile = $skyFile;
$badFile =~ s/_sk([\._])/_bp$1/;
if (not -f $badFile) {
$log->entry("no bad pixel file for $skyFile");
$badFile = 'NONE';
}
#######################
# make the exposure map
#######################
$uexpmap->params({
infile => $skyFile,
badpixfile => $badFile,
outfile => $expFile,
maskfile => $maskFile
})
->is_script(1)
->run();
} # end of loop over files
} # end of create_exposure_maps method
sub aspect_correct_sky_images
{
my $self = shift;
my $log =$self->log();
my $filename=$self->filename();
my $procpar =$self->procpar();
my $jobpar =$self->jobpar();
$log->entry('Performing aspect correction on UVOT images');
my $attfile = $filename->get('attitude', 's');
my $jumpatt = $filename->get('attcorr', 'p');
$attfile = $jumpatt if -f $jumpatt;
if (not $attfile) {
$log->error(2, 'no attitude file available');
return;
}
my @skyFiles = $filename->getNonGrismSkyImages;
if (not @skyFiles) {
$log->entry("no sky images to correct");
return;
}
my $infile = 'uvotskycorr.files';
my $fh = FileHandle->new($infile, 'w');
if (not $fh) {
$log->error(2, "unable to create $infile [$!]");
return;
}
foreach my $name (@skyFiles) {
$fh->print($name . "\n");
}
$fh->close;
my $corrfile = $filename->get('hk', 'u', 'ac', 0);
my $catspec = $procpar->read('starcatalog');
unlink($corrfile);
$log->entry('finding corrections');
my $find = Util::HEAdas->new('uvotskycorr')->is_script(1);
$find->params({
skyfile => '@' . $infile,
what => 'ID',
outfile => $corrfile,
corrfile => 'NONE',
attfile => $attfile,
catspec => $catspec,
starid => 'n.reference=50 n.observation=30 max.rate=1000',
chatter => 5
})
->run;
unlink $infile;
return if not -f $corrfile;
$log->entry('applying corrections');
$fh = FileHandle->new($infile, 'w');
if (not $fh) {
$log->error(2, "unable to create $infile [$!]");
return;
}
foreach my $name (@skyFiles) {
$fh->print($name . "\n") if -f $name;
$name =~ s/_sk([\._])/_ex$1/;
$fh->print($name . "\n") if -f $name;
}
$fh->close;
my $apply = Util::HEAdas->new('uvotskycorr')->is_script(1);
$apply->params({
skyfile => '@' . $infile,
what => 'SKY',
outfile => 'NONE',
corrfile => $corrfile,
attfile => $attfile,
catspec => $catspec,
chatter => 5,
})
->run;
#######################################################################
# Apply aspect corrections to attitude file. First check if there are
# any corrections to apply.
#######################################################################
my $corrfits = Util::FITSfile->new($corrfile)->cols('ASPCORR');
my @corrections = $corrfits->table();
if( grep(/1/, @corrections) ){
$log->entry('applying corrections to attitude file');
my $scatt = $filename->get('attitude', 's');
my $jumpatt = $filename->get('attcorr', 'p');
my $uvotatt = $filename->get('attcorr', 'u');
# print "About to make Attitude file $uvotatt\n";
my $att_corr = Util::HEAdas->new('uvotattcorr')->is_script(1);
$att_corr->params({attfile => $attfile,
corrfile => $corrfile,
clobber => 'yes',
outfile => $uvotatt})
->run();
my $sattfits = Util::FITSfile->new($scatt, 0);
my $attstatus = $sattfits->keyword('ATTSTATU');
if( $att_corr->had_error() ){
$attstatus += 2;
unlink $uvotatt;
}else{
$attstatus += 1;
my $flags = 111;
$flags = 101 unless -f $jumpatt;
my $uattfits = Util::FITSfile->new($uvotatt);
for(my $i=0; $i<3; $i++){
$uattfits->ext($i);
$uattfits->keyword('ATTFLAG', "'$flags'", 'Orgin of attitude information');
}
# my $natt = $uvotatt.'_1stcor';
# system("cp $uvotatt $natt");
}
$sattfits->keyword('ATTSTATU', $attstatus, 'Status of corrected attitude files');
}
} # end of aspect_correct_sky_images method