Subs::SwiftSub (version $)


package Subs::SwiftSub;

##############################################################################
#
# DESCRIPTION: SwiftSub.pm: Swift-specific extension of Subs:Sub.pm.
# DESCRIPTION: Sets various parameters in job.par and logs software versions
# DESCRIPTION: in use.  Provides sub good_attitude_fraction.
#
# HISTORY: $Log: SwiftSub.pm,v $
# HISTORY: Revision 1.15  2014/04/30 09:07:28  apsop
# HISTORY: Not using Util::Parfile after all, so comment out the use statement.
# HISTORY:
# HISTORY: Revision 1.14  2014/04/30 08:54:05  apsop
# HISTORY: Can't get Util::Parfile to read ftools.par either,
# HISTORY: so go back to reading it manually.
# HISTORY: Also log the SOFTVER we come up with.
# HISTORY:
# HISTORY: Revision 1.13  2014/04/29 09:27:16  apsop
# HISTORY: Util::Parfile couldn't find just 'ftools.par',
# HISTORY: so try it specifying full path in syspfiles.
# HISTORY:
# HISTORY: Revision 1.12  2014/04/28 23:00:33  apsop
# HISTORY: fversion gave the wrong version string because the FTOOLS env var
# HISTORY: doesn't get set.  So go back to reading ftools.par (but in a more
# HISTORY: standard way).
# HISTORY:
# HISTORY: Revision 1.11  2014/03/01 10:00:28  apsop
# HISTORY: Log whether is a FINAL FOR ARCHIVE run.
# HISTORY:
# HISTORY: Revision 1.10  2014/02/28 09:48:42  apsop
# HISTORY: Log sdc_hea_patches and append its value to softver.  Run fversion to get
# HISTORY: heasoft version (this also logs it).  Run xrtversion to log the XRT s/w
# HISTORY: version.
# HISTORY:
# HISTORY: Revision 1.9  2011/01/20 17:50:10  apsop
# HISTORY: Added code to check the job title also, and consider the sequence
# HISTORY: being processed to be in its final stage if such parameter is
# HISTORY: "FINAL FOR ARCHIVE"
# HISTORY:
# HISTORY: Revision 1.8  2008/06/02 13:32:58  apsop
# HISTORY: Trap the case where total exposure is zero.
# HISTORY:
# HISTORY: Revision 1.7  2008/05/16 14:31:06  apsop
# HISTORY: Add good_attitude_fraction method.
# HISTORY:
# HISTORY: Revision 1.6  2007/04/01 19:13:19  apsop
# HISTORY: Calculate version numbers and store in job par.
# HISTORY:
# HISTORY: Revision 1.5  2006/04/28 18:41:46  apsop
# HISTORY: Fix bug in testing for presence of queue file.
# HISTORY:
# HISTORY: Revision 1.4  2005/11/08 19:22:28  apsop
# HISTORY: Populate the TIMELIST and DATALIST hashes. Used to be an SWCheckInput.
# HISTORY:
# HISTORY: Revision 1.3  2004/05/06 20:02:34  dah
# HISTORY: Add version number back into the header comments.
# HISTORY:
# HISTORY: Revision 1.2  2004/04/16 20:21:18  dah
# HISTORY: Begin using embedded history records
# HISTORY:
#
# VERSION: $Revision: 1.15 $
#
#
##############################################################################


use Subs::Sub;
use Util::AttTool;
use Util::GTIfile;
#  use Util::Parfile;

@ISA = ("Subs::Sub");
use strict;

sub BEGIN {
  my $procpar  = Subs::Sub->procpar();
  my $filename = Subs::Sub->filename();
  my $log      = Subs::Sub->log();
  my $jobpar   = Subs::Sub->jobpar();

  Util::AttTool->dirs($procpar->read('acs2fits'), $procpar->read('headas').'/lib');

  ###############################################
  # Put info on data already processed into hash
  ###############################################
  my @data = split(' ', $jobpar->read('datalist'));
  @{$jobpar->{DATALIST}}{@data} = (1) x @data;

  #####################################################
  # Hash about relative times, ie time since burst and
  # final processing
  #####################################################
  $jobpar->{TIMELIST} = {};
  foreach (glob('day_*.flag')){
    $jobpar->{TIMELIST}->{ (/(day_\w+)\.flag/)[0] } = 1;
  }

  #################################################################
  # Figure out if this is a FINAL FOR ARCHIVE run and set job.par's
  # finalproc parameter if it is.
  #################################################################

  if (-f 'final_for_archive.lock' ||
      $jobpar->read('reprocess') eq 'yes' ||
      $jobpar->read('job_title') eq 'FINAL FOR ARCHIVE') {
      $jobpar->{TIMELIST}->{final} = 1;
      $jobpar->set({finalproc => 'yes'});
      $log->entry("This is a FINAL FOR ARCHIVE-type run.");
  } else {
      $log->entry("Not a FINAL FOR ARCHIVE-type run.");
  }

  ########################################################################
  # Get software versions and set job.par's softver parameter.
  #
  # Note: fversion, ftversion, swiftversion, xrtversion don't have parfiles
  # (really!  see $HEADAS/syspfiles/), so using Util::HEAdas for them gives
  # errors.
  # Note: Util::Tool will log the stdout to job log.
  #
  # fversion gives the wrong result because it needs ENV(FTOOLS) which
  # isn't set in Tools.pm, but it just gets its version string from
  # ftools.par anyway, so read that ourself.  (ftversion has the version
  # number hardcoded, but it's a different number.)
  #
  # Can't get Util::Parfile to work reading ftools.par either.  (Hmm,
  # ftools.par seems to have the version string in the comment field
  # instead of the value field!)  So do need to open, read. and parse it
  # manually.
  #
  ########################################################################
  my $headas    = $procpar->read('headas');
  my $headasbin = $headas . '/bin';
  my $syspfiles = $headas . '/syspfiles';

#   my $fversion = Util::Tool->new($headasbin, 'fversion')
#       ->run();
#   my $fver = $fversion->stdout();

#   my $ftoolspar = Util::Parfile->new("${syspfiles}/ftools.par");
#   my $fver = $ftoolspar->read('version');

  my $fver;
  open VER, "${syspfiles}/ftools.par";
  while (<VER>){
      $fver = $1 if /version,s,h,+"([^",]*)"/;
  }
  close VER;

  $log->entry("HEAsoft version from ftools.par:");
  $log->text( "${fver}\n" );   # to match swiftversion & xrtversion in log

  my $sversion = Util::Tool->new($headasbin, 'swiftversion')
      ->run();
  my $sver = $sversion->stdout();
  chomp $sver;

  my $xversion = Util::Tool->new($headasbin, 'xrtversion')
      ->run();
  my $xver = $xversion->stdout();
  chomp $xver;

  my $sdc_pl = $procpar->read('sdc_hea_patches');
  $log->entry("SDC patches to HEAsoft:  $sdc_pl ");

  #########################################################################
  # Sometimes for an 'official' release Swift puts '_S' at the end of the
  # version.  (Although the last version we have that did that was from
  # 2005.)
  #########################################################################
  $sver =~ s/_S$//;

  my $soft_version = "Hea_${fver}_${sver}_SDCpatch_${sdc_pl}";
  $jobpar->set({softver => $soft_version});
  $log->entry("SOFTVER will be $soft_version ");

  #####################
  # Get caldb versions
  #####################
  my $caldb = $procpar->read('caldb');
  my @cal_vers;
  foreach my $inst qw(bat uvota xrt mis){
    my $fits = Util::FITSfile->new("$caldb/data/swift/$inst/caldb.indx");
    my $ckey = $fits->keyword('CALDBVER');
    $ckey = '?' unless $ckey;
    push @cal_vers, substr($inst, 0, 1) . $ckey;
  }
  $jobpar->set({caldbver => join('_', @cal_vers)});

  #####################################################
  # Get the earliest and latest times from the queue
  # file
  #####################################################
  my $qname = $jobpar->read('sequence') . '.queue';
  if( -f $qname && open(QUEUE, "$qname") ){
    my (@starts, @stops);
    while(<QUEUE>){
      my @fields = split(' ');
      push @starts, $fields[2];
      push @stops,  $fields[3];
    }
    close QUEUE;
    $jobpar->{TIMELIST}->{start} = (sort {$a <=> $b} @starts)[0];
    $jobpar->{TIMELIST}->{stop}  = (sort {$b <=> $a} @stops)[0];
  }else{
    $log->error(1, "Unable to open $qname, $!");
  }
}


sub good_attitude_fraction {

  my $self = shift;
  my $start = shift;
  my $stop = shift;

  my $log     = $self->log();
  my $filename= $self->filename();
  my $procpar = $self->procpar();
  my $jobpar  = $self->jobpar();

  #######################################################################
  # Make GTI file from start and stop times and get total exposure time.
  #######################################################################
  my $attitude_gti = $filename->get('gti', 's', 'at');
  my $mgtime = Util::Ftool->new('mgtime')->params({merge => 'AND'});
  my $exp_gti_file = 'exp_gti_file.tmp';
  unlink $exp_gti_file;

  my $exp_gti_fits = Util::GTIfile->new($exp_gti_file, $start, $stop);
  my $total_exp_time = $exp_gti_fits->sum();
  ################################
  # Return unity if zero exposure
  ################################
  return 1.0 if $total_exp_time == 0;

  ########################################
  # Merge exposure GTI with attitude GTI.
  ########################################
  my $exp_good_attitude_file = 'exp_goodatt_file.tmp';
  unlink $exp_good_attitude_file;
  $mgtime->params({ingtis => "$exp_gti_file, $attitude_gti",
		   outgti => $exp_good_attitude_file})
    ->run();

  #######################################################################
  # Get percent good attitude, and write keyword to image extension.
  #######################################################################
  my $good_attitude_time = Util::GTIfile->new($exp_good_attitude_file)->sum();
  my $good_fraction =  $good_attitude_time/$total_exp_time;

  unlink ($exp_gti_file, $exp_good_attitude_file);

  return $good_fraction;
}