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: # # 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', # 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', to => 'DET', attfile => $attfile, ra => $jobpar->read('ra'), dec => $jobpar->read('dec'), roll => $jobpar->read('roll'), aberration => 'no', seed => $procpar->read('seed'), 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 => 2, # TODO: keeps run times for 2048^2 images to minutes # instead of hours 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 swiftxform tool ######################################### ## attdelta => 100, my $uexpmap = Util::HEAdas->new('uvotexpmap') ->params({attfile => $attitude, teldeffile => 'CALDB', method => 'SHIFTADD', attdelta => 0.1, aberration => 'no', 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->get('filterimg', 'uvot', '*', '*'); 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