package Subs::CheckInput; ############################################################################# # # DESCRIPTION: This subroutine class provides a number of methods for # DESCRIPTION: checking the input files for a processing run. # DESCRIPTION: It provides a simple default body method, which # DESCRIPTION: missions with specific needs may override. # DESCRIPTION: Processing scripts should run this subroutine # DESCRIPTION: (or a subclass of it) first. # # HISTORY # HISTORY: $Log: CheckInput.pm,v $ # HISTORY: Revision 1.2 2006/08/01 20:35:34 apsop # HISTORY: Add in CVS history indicator. # HISTORY: # HISTORY: 1.0 -> 1.1 2000-06-28 # HISTORY: Fixed a bug in the file trimming sectopn of the fix_overlaps method # HISTORY: # HISTORY: 1.1 -> 1.2 2001-03-05 # HISTORY: Minor adjustments in variable declarations # # VERSION: 1.2 # ############################################################################## use Subs::Sub; @ISA = ("Subs::Sub"); use strict; use Util::CoreTags; ######################################### # ######################################### sub new { #() my $proto=shift; my $self=$proto->SUPER::new(@_); $self->{DESCRIPTION}="Checking input files for validity"; return $self; } ############################### # METHODS: ############################### ############################################################################ ############################################################################ # this only calls the verify_input method without fverify requested. # Mission specific versions of this class should override this method # to do other interesting things. ############################################################################ sub body { my $self=shift; $self->verify_input(); } # end of subroutine body ########################################################################### ########################################################################### # Verify all the input files - i.e. make sure they exist, and # optionally run fverify on each of them. ########################################################################### sub verify_input { my $self=shift; my $fverify_requested=shift; my $filename=$self->filename(); my $log =$self->log(); my $jobpar =$self->jobpar(); $log->entry("Verifying the input files"); ######################################### # set up an fverify FTOOL object ######################################### my $fverify; if($fverify_requested ) { $fverify=Util::Ftool->new("fverify") ->params({outfile=>"STDOUT", prhead=>"no", testdata=>"yes"}) ->verbose(0); } ###################################### # dump the input catalog file ###################################### my $cat=$filename->get("inputcat"); my %list=Util::FITSfile->new($cat,1,'[FORMAT==\'FITS\']') ->cols("FILENAME FORMAT") ->table(); ############################## # loop over all files ############################## my $file; my $format; while( ($file,$format) = each %list ) { if( -e $file) { ################################################## # file exists, so run fverify if it's a FITS file ################################################## if($format eq "FITS" && $fverify_requested ) { ########################## # FITS file - run fverify ########################## $log->entry("Running fverify on $file"); $fverify->params({infile=>$file})->run(); if($fverify->had_error() || $fverify->parfile()->read("numerrs") ) { ################################################# # only dump the fverify output if there was an # error to avoid filling up the log with trash ################################################# $log->entry("Output from fverify"); $log->text($fverify->stdout()); } } elsif($format eq "FITS") { ###################################### # FITS file, but we won't run fverify ###################################### $log->entry("FITS file $file exists\n"); } else { ################ # non-FITS file ################ $log->entry("non-FITS file $file exists\n"); } } else { ################################# # file is missing, give an error ################################# $log->error([ 3, BAD_INPUT ], "Required input file $file is missing"); } } # end of loop over input files } # end of verify_input method ########################################################################## ########################################################################## # calculate the observation date and record it in the job.par. # This is done by reading the given start and stop mission time keywords # from the headers of a particular type of file. ########################################################################## sub determine_obsdate { my $self=shift; my $type=shift; my $start_key=shift; my $stop_key=shift; my $log=$self->log(); my $jobpar=$self->jobpar(); my $filename=$self->filename(); $log->entry("Calculating Observation start and end times\n"); ###################################################### # read all the start and stop keyword values ###################################################### my @files=$filename->any($type); my @times = Util::FITSlist->new(@files) ->extension($self->option("obsdate_ext")) ->keywords($start_key,$stop_key); #################################### # calculate the earliest start time #################################### my $tstop; my $tstart = $tstop = shift @times; foreach (@times) { if($_ < $tstart ) { $tstart = $_} if($_ > $tstop ) { $tstop = $_} } ############################################################ # create date objects corresponding to start and stop times ############################################################ my $start_date=Util::Date->new($tstart); my $stop_date =Util::Date->new($tstop ); ########################################### # record the results in the jobpar and log ########################################### $jobpar->set({tstart => $tstart, tstop => $tstop, obsdate => $start_date->date(), obstime => $start_date->time(), enddate => $stop_date->date(), endtime => $stop_date->time() }); $log->entry("Observation begins $tstart = ".$start_date->date()." ". $start_date->time() ); $log->entry("Observation ends $tstop = ".$stop_date->date()." ". $stop_date->time() ); } # end of obsdate method ############################################################################ ############################################################################ # check for and remove overlaps of adjacent input files of a given type. # This routine must be called multiple times if overlaps must be removed from # more than one file type. ############################################################################ sub fix_overlaps { my $self=shift; my $type=shift; my $ext=shift; my %keys=@_; my $filename=$self->filename(); my $log=$self->log(); ####################################################### # first get a list of all files of the given type # since if there's only one file we can just quit now ###################################################### my @files=$filename->any($type); if(@files == 1 ) { return; } ######################################################################## # there's more than one file, so we need to do some work here. # first log what we're about to do. ######################################################################## $log->entry("Checking for overlaps in extension $ext of $type files\n"); ################################################################ # loop over all files of the given type and collect their # start and stop times ################################################################ my %first; my %last; my $file; foreach $file (@files) { #################################################### # read the first and last time values from the file #################################################### my $fits=Util::FITSfile->new($file,$ext) ->cols("TIME"); my $nrows=$fits->nrows(); $first{$file}=$fits->rows(1 )->table(); $last{ $file}=$fits->rows($nrows)->table(); $log->entry("$file begins at $first{$file} and ends at $last{$file}"); } ############################################# # sort the files with the last end time first ############################################# @files=sort {$last{$b} <=> $last{$a} } keys %last; ########################################################## # loop over all the files again - remove overlaps ########################################################## my $prev=shift @files; my $this; while(($this = $prev) && ($prev=shift @files) ) { ######################################### # delete files wholely within this file ######################################### while( $prev && $first{$prev} >= $first{$this}) { $log->error(2,"Deleting $prev since it is contained within $this"); unlink $prev; $prev = shift @files; } if( ! $prev ) {last} ############################################## # do the files overlap ############################################## if( $first{$this} < $last{$prev} ) { ######################################### # files overlap partially ######################################### my $overlap = $last{$prev} - $first{$this}; $log->error(1,"$this and $prev overlap by $overlap seconds"); $log->entry("Trimming the beginning of $this"); ######################################### # so clip off the beginning of this file ######################################### my $this_fits=Util::FITSfile->new($this,$ext, "\[TIME>$last{$prev}\]"); $this_fits->copy(); ######################################## # adjust keywords ######################################## my $prev_fits=Util::FITSfile->new($prev,$ext); my $this_key; my $prev_key; while( ($this_key,$prev_key) = each %keys ) { #################################################### # copy the end keyword from the previous file # to the begin keyword from this file #################################################### $this_fits->keyword($this_key, $prev_fits->keyword($prev_key) ); } } # end if there was an overlap } # end of loop over files } # end of overlap method 1;