Subs::BATBurst (version # VERSION: 0.0 )


package Subs::BATBurst;
##############################################################################

#

# DESCRIPTION: This subroutine does calibration of BAT event data.

# DESCRIPTION: It runs bateconvert to do energy scale calibrations,

# DESCRIPTION: and then runs batmaskwtevt to calculate mask weights for

# DESCRIPTION: each event which correspond to the burst position.

#

# DESCRIPTION: Port of Craig Markwardt's BAT::maskwt module to SDC.

#

#

# HISTORY: 

# HISTORY: $Log: BATBurst.pm,v $
# HISTORY: Revision 1.50  2007/10/23 14:21:55  apsop
# HISTORY: Bug fix for interval algorithm.
# HISTORY:

# HISTORY: Revision 1.49  2007/10/22 20:38:12  apsop

# HISTORY: Craig;s algorithm for determining pre, slew, and post intervals.

# HISTORY:

# HISTORY: Revision 1.47  2007/10/11 18:16:41  apsop

# HISTORY: Change slew_start criteria to handle non-slew bursts.

# HISTORY:

# HISTORY: Revision 1.46  2007/10/09 16:52:34  apsop

# HISTORY: Refine algorithm for determining slew time intervals for a burst.

# HISTORY:

# HISTORY: Revision 1.45  2007/10/08 21:06:36  apsop

# HISTORY: Use proper targ-pointing GTI instead of on-target GTI for time intervals.

# HISTORY:

# HISTORY: Revision 1.44  2007/10/05 14:19:45  apsop

# HISTORY: Change of algorhythm for determining the pre and post slew intervals of a burst.  Now use on-target GTIs.

# HISTORY:

# HISTORY: Revision 1.43  2007/09/12 18:07:08  apsop

# HISTORY: Throw error if cant find gain/offset file, instead of crashing bateconvert task.

# HISTORY:

# HISTORY: Revision 1.42  2007/03/15 21:34:10  apsop

# HISTORY: For slew-only the data, allow for possible absence of slew file as well as pointing file.

# HISTORY:

# HISTORY: Revision 1.41  2007/02/12 02:14:14  apsop

# HISTORY: Another bug fix for db file editing.

# HISTORY:

# HISTORY: Revision 1.40  2007/02/10 21:46:17  apsop

# HISTORY: Fix bug in editing of badb.hk file.

# HISTORY:

# HISTORY: Revision 1.39  2007/02/08 14:27:59  apsop

# HISTORY: Allow for possibility that slew-only data can actually contain some pointing data.

# HISTORY:

# HISTORY: Revision 1.38  2007/01/31 20:23:40  apsop

# HISTORY: Identify bat event data taken during slews and tag as such.

# HISTORY:

# HISTORY: Revision 1.37  2006/09/10 20:07:22  apsop

# HISTORY: Add new distfile parameter for build 19.

# HISTORY:

# HISTORY: Revision 1.36  2006/04/27 16:27:02  apsop

# HISTORY: Set parameter pcodethresh to 0.05 in batmaskwtevt task.

# HISTORY:

# HISTORY: Revision 1.35  2006/01/16 17:50:21  apsop

# HISTORY: Dont split or update TSTART of dph files that dont need it.

# HISTORY:

# HISTORY: Revision 1.34  2005/12/19 16:10:32  apsop

# HISTORY: Add timing keywords to evaux file - should really be done in bat tool.

# HISTORY:

# HISTORY: Revision 1.33  2005/11/16 01:03:20  apsop

# HISTORY: Only make evaux file for slew-pointing event data.

# HISTORY:

# HISTORY: Revision 1.32  2005/11/08 17:01:20  apsop

# HISTORY: Change qualcal call for new filename.

# HISTORY:

# HISTORY: Revision 1.31  2005/07/05 14:56:16  apsop

# HISTORY: Caught SDC up to date with BAT pipeline with exception of BAT

# HISTORY: position refinement.

# HISTORY:

# HISTORY: Revision 1.30  2005/06/01 16:03:07  apsop

# HISTORY: Change the burst gti file type from gti to burstgti.Subs/BATIntervals.pm

# HISTORY:

# HISTORY: Revision 1.29  2005/04/19 15:40:18  apsop

# HISTORY: Change calmode parameter to INDEF.

# HISTORY:

# HISTORY: Revision 1.28  2005/04/06 15:40:31  apsop

# HISTORY: Change to using CALDB for cal parameters.

# HISTORY:

# HISTORY: Revision 1.27  2005/03/25 22:53:53  apsop

# HISTORY: Change pointing gti extname form STDGTI to GTI

# HISTORY:

# HISTORY: Revision 1.26  2005/03/07 20:22:31  apsop

# HISTORY: Comment out filtering of TIME<1000.  This now done in StartEndTimes.

# HISTORY:

# HISTORY: Revision 1.25  2005/02/09 23:39:01  apsop

# HISTORY: Added message identifiers.

# HISTORY:

# HISTORY: Revision 1.24  2005/02/08 18:26:52  apsop

# HISTORY: Fix bateconvert call to work with build 11.  Remove events with time of less than 1000.

# HISTORY:

# HISTORY: Revision 1.23  2004/12/07 17:34:57  apsop

# HISTORY: Change log message to error message when bat files cannot be split.  Downstream error messages that result have been changed to log messages.

# HISTORY:

# HISTORY: Revision 1.22  2004/12/05 23:26:54  apsop

# HISTORY: Split event list after calibration

# HISTORY:

# HISTORY: Revision 1.21  2004/11/19 21:46:48  apsop

# HISTORY: New version of xrt2fits.

# HISTORY:

# HISTORY: Revision 1.20  2004/11/10 18:01:06  apsop

# HISTORY: Replace SimpleFITS call for getting TSTART with FITSfile call.

# HISTORY:

# HISTORY: Revision 1.19  2004/11/09 22:03:14  apsop

# HISTORY: Reverted mode of short events GTI.

# HISTORY:

# HISTORY: Revision 1.18  2004/11/08 18:38:40  apsop

# HISTORY: Updated with Craig's BAT::maskwt code.

# HISTORY:

# HISTORY: Revision 1.17  2004/10/25 14:47:27  apsop

# HISTORY: Fix bugs in splitting of DPH files.

# HISTORY:

# HISTORY: Revision 1.16  2004/10/24 20:00:55  apsop

# HISTORY: Rework of split_events method.  Now make pemanent GTI file.

# HISTORY:

# HISTORY: Revision 1.15  2004/08/30 13:23:06  apsop

# HISTORY: Fix up parameters for batmaskwtevt, including using bat_z and origin_z

# HISTORY:

# HISTORY: Revision 1.14  2004/08/16 15:23:09  apsop

# HISTORY: Turn on writing of HISTORY keywords.

# HISTORY:

# HISTORY: Revision 1.13  2004/08/13 14:28:31  apsop

# HISTORY: Test for case where slew times cannot be determined.

# HISTORY:

# HISTORY: Revision 1.12  2004/06/29 14:21:13  apsop

# HISTORY: Add residfile and pulserfile to bateconvert call.

# HISTORY:

# HISTORY: Revision 1.11  2004/06/11 19:49:48  apsop

# HISTORY: Handle case where there is no pointing time.

# HISTORY:

# HISTORY: Revision 1.10  2004/05/06 20:02:33  dah

# HISTORY: Add version number back into the header comments.

# HISTORY:

# HISTORY: Revision 1.9  2004/04/16 20:21:18  dah

# HISTORY: Begin using embedded history records

# HISTORY:

#

# VERSION: 0.0

#

#

##############################################################################



use Subs::Sub;


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

use Util::SwiftTags;


sub new {
    my $proto=shift;
    my $self=$proto->SUPER::new();

    $self->{DESCRIPTION}="BAT Burst Processing";

    return $self;
}

##################

# METHODS:

##################


sub body {
    my $self=shift;

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

    ################################################

    # Events file times of less than 1000 are bogus

    ################################################

    my @event_files = $filename->get('unfiltered', 'bat', 'ev??to', '*');
    # my $copy = Util::HEAdas->new('ftcopy');

    # my $filter = '[EVENTS][TIME > 1000]';

    foreach my $unf (@event_files){
      my ($inst, $mode, $index) = $filename->parse($unf, 'unfiltered');
      my $new_name = $filename->get('unfiltered', 'bat', substr($mode,0,4).'sp', $index);

      # $copy->params({infile => $unf . $filter,

      #               outfile => $new_name})

      #     ->run();

      # unlink $unf;

      rename $unf, $new_name;
    }

    $self->calibrate_events;

    unless( $self->slew_only() ){
      $self->mask_weight_events;
    }
     
    ###################################################

    # Split up the bat event list based on time period

    ###################################################

    $self->split_events();

} # end of body method



sub determine_trigger_time
{
    my $self = shift;

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

    my $root = $filename->sequence_specific();

# this could be done once and stored in $jobpar


    my $ack = Util::BATCave::get_tdrss_ack($self);
 
    if (not $ack) {
      $log->error([ 1, BAT_NO_CENTROID ],
              'No burst ack message to provide trigger time.');
      return;
    }

    my $batack = Util::FITSfile->new($ack, 0);
    my $trigtime = $batack->keyword('TRIGTIME');

    $log->entry("BAT trigger time based on $ack is $trigtime .");
 
    return $trigtime;
}



################################################################

# Split up the bat event lists and dph's based on time period

###############################################################


sub split_events{
    my $self=shift;

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

    my @dph_files = $filename->get('rawdph', 'bat', 'svto', '*');

    my @event_files = $filename->get('unfiltered', 'bat', 'evshsp', '*');

    my $trigtime = $self->determine_trigger_time;

    if (not $trigtime) {
      $log->error([ 1, BAT_NO_CENTROID ],
              'No trigger time so will not split BAT event files.');

      foreach my $raw (@dph_files){
	my ($inst, $mode, $index) = $filename->parse($raw, 'dph');
	my $new_name = $filename->get('rawdph', 'bat', 'svpb'.substr($mode,4), $index);
	rename $raw, $new_name;
      }

      return;
    }

    ####################################

    # Do the splitting of events lists

    #####################################


    $log->entry("Split BAT event lists based on end of slew time.");

# TODO: want to rename this from po => as, but po set in Attitude.pm

    my $gtipath =  $filename->get('gti', 's', 'po', 0);
    my (@start, @stop, @ot_start, @ot_stop);

    if (-f $gtipath) {
       my $spo_gti =  Util::FITSfile->new($gtipath, 'GTI');
       @start = $spo_gti->cols('START')->table();
       @stop =  $spo_gti->cols('STOP')->table();

       my $ot_path = $filename->get('gti', 's', 'tp', 0);
       if( -f $ot_path){
	 my $sot_gti =  Util::FITSfile->new($ot_path, 'GTI');
	 @ot_start = $sot_gti->cols('START')->table();
	 @ot_stop =  $sot_gti->cols('STOP')->table();
       }
    }else {
      $log->error([ 1, BAT_NO_GTIS ],
              'No spo GTI so will not split BAT event files.');
    }

    #######################################################################

    # Slewing senarios which are handled:

    #

    #   point       -----------            -------------

    #              |           |          |             |

    #   slew  -----             ----------               ---------

    #                   *

    #                trigger

    #

    #

    #

    #   point             -----            -------------

    #                    |     |          |             |

    #   slew  -----------       ----------               ---------

    #             *

    #          trigger

    #

    #

    #

    #   point       ------------------------------------------------

    #              |

    #   slew  ----- 

    #                   *

    #                trigger

    #

    ###########################################################################


    my ($slew_stop, $slew_start, $preslew_start, $preslew_stop, $postslew_start, $postslew_stop);

    #

    # Definitions of terms:

    #

    #   * "Pre-slew" - the pointing which contains the trigger (or in

    #   rare cases where the trigger is during the settling interval,

    #   the pointing that just follows the trigger).

    #

    #   * "Pre-burst" - the portion of the pre-slew pointing which

    #   contains no burst emission.  (this is selected in BATImages.pm

    #   as the GTI intersection of the pre-slew interval with

    #   GTI_BKG1). Note that this could be empty if the burst emission

    #   occupies all of the pointing.

    #

    #   * "Slew" - the slew which follows the trigger.  Note the slew

    #   may not be a slew to the burst position.

    #

    #   * "After-slew" - the pointing which follows the "slew"

    #   interval.  Note the following pointing may not always be

    #   pointed at the burst.

    #

    # Defaults:

    #   * If no good pointing is available during the trigger:

    #       pre-slew = all of the event data  (and no slew or after-slew data)

    #   * If no "after-slew" pointing is available:

    #       pre-slew = normal

    #       slew     = all data after pre-slew

    #


    if(@start){
      my ($i, $ifound);

      # Find the pointing that precedes the trigger time

      foreach $i (reverse(0 .. $#start)) {

	if ($trigtime >= $start[$i]) {
	  # Double check that the trigger comes *during* the pointing.

	  # This may fail if the trigger comes during the settling period.

	  # In that case, advance to the next pointing.

	  $ifound = $i;
	  if ($trigtime >= $stop[$i]) { $ifound = $i + 1; }
	  last;
	}
      }
      
      if (defined($ifound)) {

	# We found a pointing interval that brackets the trigger!

	# Extract start/stop times based on this interval and the

	# following one if it exists.


	$preslew_start = $start[$ifound];
	$preslew_stop  = $stop[$ifound];
	$slew_start    = $stop[$ifound];
	$slew_stop     = $start[$ifound+1];   # May be undefined

	$postslew_start= $start[$ifound+1];   # May be undefined

	$postslew_stop = $stop[$ifound+1];    # May be undefined

      }
    }

    # Fill in the defaults

    $preslew_start  = 0 unless $preslew_start;
    $preslew_stop   = 1.0E12 unless $preslew_stop;
    $slew_start     = 1.1E12 unless $slew_start;
    $slew_stop      = 1.1E12 unless $slew_stop;
    $postslew_start = 1.2E12 unless $postslew_start;
    $postslew_stop  = 1.2E12 unless $postslew_stop;

    $log->entry("Slew start/stop based on ACS settled flags: $slew_start / $slew_stop .");
    $log->entry("Pre-slew start/stop: $preslew_start / $preslew_stop .");
    $log->entry("Post-slew start/stop: $postslew_start / $postslew_stop .");

    ##############################

    # Set up to split event files

    ##############################

    my $gti_pre = $filename->get('burstgti', 'bat', '', 0);
    my $gti_post = 'bat_post_gti.tmp';
    my $gti_slew = 'bat_slew_gti.tmp';

    my $datafile = 'bat_data.tmp';
    my $cdfile = 'bat_cols.tmp';
    my $hdfile = 'bat_head.tmp';

    open COLS, ">$cdfile";
    open HEAD, ">$hdfile";

    print COLS "START 1D s\n";
    print COLS "STOP 1D s\n";

    print HEAD "EXTNAME = 'GTI_PRE '  / name of this binary table extension\n";
    print HEAD "HDUCLASS= 'OGIP    '  / format conforms to OGIP/GSFC conventions\n";
    print HEAD "HDUCLAS1= 'GTI     '  / Extension contains Good Time Intervals\n";
    print HEAD "HDUCLAS2= 'STANDARD'  / Extension contains Good Time Intervals\n";
    print HEAD "TIMESYS = 'TT      '  / time measured from\n";
    print HEAD "MJDREFI =       51910 / MJD reference day\n";
    print HEAD "MJDREFF = 7.428703700000000E-04 / MJD reference (fraction of day)\n";
    print HEAD "CLOCKAPP=           F / default\n";
    print HEAD "TIMEUNIT= 's       '  / unit for time keywords\n";

    close COLS;
    close HEAD;

    my $table = Util::Ftool->new('fcreate')
                           ->params({cdfile => $cdfile,
				     datafile => $datafile,
				     headfile => $hdfile});

    open DATA, ">$datafile";
    print DATA "$preslew_start $preslew_stop\n";
    close DATA;

    $table->params({outfile => $gti_pre})
          ->run();
    
    open DATA, ">$datafile";
    print DATA "$slew_start $slew_stop\n";
    close DATA;

    $table->params({outfile => $gti_slew})
          ->run();
    
    open DATA, ">$datafile";
    print DATA "$postslew_start $postslew_stop\n";
    close DATA;

    $table->params({outfile => $gti_post})
          ->run();

    my $extractor = Util::Extractor->new();
    foreach my $unf (@event_files) {

      $log->entry("Splitting file $unf.");

      my ($inst, $mode, $index) = $filename->parse($unf, 'unfiltered');
      my $submode = substr($mode, 0, 4);
	
      $extractor->instrument('bat', 'EVENT')
	        ->infiles($unf);

      my $post_file = $filename->get('unfiltered', 'b', $submode.'as', $index);
      $extractor->gti($gti_post)
	        ->outfile($post_file, 'event')
		->run();
      unlink $post_file
	unless Util::FITSfile->new($post_file, 'EVENTS')->nrows();
      
      my $pre_file = $filename->get('unfiltered', 'b', $submode.'ps', $index);
      $extractor->gti($gti_pre)
	        ->outfile($pre_file, 'event')
	        ->run();
      unlink $pre_file
	unless Util::FITSfile->new($pre_file, 'EVENTS')->nrows();

      my $slew_file = $filename->get('unfiltered', 'b', $submode.'sl', $index);
      $extractor->gti($gti_slew)
	        ->outfile($slew_file, 'event')
	        ->run();
      unlink $slew_file
	unless Util::FITSfile->new($slew_file, 'EVENTS')->nrows();
    }

    ##############################################

    # Combine gtis together into gti product file

    ##############################################

    my $fappend = Util::Ftool->new('fappend')
                             ->params({outfile => $gti_pre});

    $fappend->params({infile => "$gti_slew\[1\]\[col EXTNAME='GTI_SLEW'\]"})
            ->run();

    $fappend->params({infile => "$gti_post\[1\]\[col EXTNAME='GTI_POST'\]"})
            ->run();

    unlink $gti_post, $gti_slew;

    ############################

    # Set up to split DPH files

    ############################

    my $gti_merged = 'gti_merged.tmp';

    $fappend->params({infile => $gti_merged.'[1]'});
    my $mgtime = Util::Ftool->new('mgtime')
			     ->params({merge => 'AND'});
    my $fdelhdu = Util::Ftool->new('fdelhdu')
			     ->params({confirm => 'no',
				       proceed => 'yes'});
    
    $log->entry('Do splitting of DPH files based on slew times.');
    $gti_pre = 'bat_pre_gti.tmp';

    open DATA, ">$datafile";
    print DATA "0 $trigtime\n";
    close DATA;

    $table->params({outfile => $gti_pre})
          ->run();

    open DATA, ">$datafile";
    print DATA "$trigtime 1.E12\n";
    close DATA;

    $table->params({outfile => $gti_post})
          ->run();

    unlink $datafile;
    unlink $cdfile;
    unlink $hdfile;
    
    #################################################################

    # Do the splitting of dphs

    #################################################################

    foreach my $unf (@dph_files) {

      $log->entry("Splitting file $unf.");

      my ($inst, $mode, $index) = $filename->parse($unf, 'dph');
      my $gaoff = substr($mode, 4);

      ##########################

      # Get the after burst part

      ##########################

      my $post_file = $filename->get('rawdph', 'b', 'svab'.$gaoff, $index);
      my $post_start = Util::FITSfile->new($unf)->keyword('TSTART');
      if($post_start >= $trigtime){
	rename $unf, $post_file;
	next;
      }

      Util::Ftool->new('fcopy')
	         ->params({infile => "$unf\[BAT_DPH\][gtifilter(\'${gti_post}\[1\]\')]",
			   outfile => $post_file})
	         ->run();

      my $post_fits = Util::FITSfile->new($post_file, 'BAT_DPH');
      if( $post_fits->nrows() ){
	$post_fits->keyword('TSTART', $trigtime);

	$fdelhdu->params({infile => $post_file.'[GTI]'})
                ->run();
        $mgtime->params({ingtis => "$unf\[GTI\], $gti_post\[1\]",
			 outgti => $gti_merged})
               ->run();
	$fappend->params({outfile => $post_file})
                ->run();
	$post_fits->ext('STDGTI');
	$post_fits->keyword('TSTART', $trigtime);
	$post_fits->keyword('EXTNAME', 'GTI');

	unlink $gti_merged;
      }else{
	unlink $post_file;
      }
      
      ########################

      # Get the pre-burst part

      ########################

      my $pre_file = $filename->get('rawdph', 'b', 'svpb'.$gaoff, $index);
      Util::Ftool->new('fcopy')
	         ->params({infile => "$unf\[BAT_DPH\][gtifilter(\'${gti_pre}\[1\]\')]",
			   outfile => $pre_file})
		 ->run();

      my $pre_fits = Util::FITSfile->new($pre_file, 'BAT_DPH');
      if( $pre_fits->nrows() ){
	$pre_fits->keyword('TSTOP', $trigtime);

	$fdelhdu->params({infile => $pre_file.'[GTI]'})
                ->run();
        $mgtime->params({ingtis => "$unf\[GTI\], $gti_pre\[1\]",
			 outgti => $gti_merged})
               ->run();
	$fappend->params({outfile => $pre_file})
                ->run();
	$pre_fits->ext('STDGTI');
	$pre_fits->keyword('TSTOP', $trigtime);
	$pre_fits->keyword('EXTNAME', 'GTI');

	unlink $gti_merged;
      }else{
	unlink $pre_file;
      }

      unlink $unf;
    }
    unlink $gti_pre, $gti_post;
}



sub calibrate_events
{
	my $self = shift;

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


	###############################################

	# make sure we have some event data to work on 

	###############################################

	my @all_event_files = $filename->get('unfiltered', 'bat', 'evsh??', '*');
	unless(@all_event_files) {
		$log->entry("No BAT event mode data\n");
		return;
	}


	############################################################

	# fill calibrated energy column

	# here we need to add a system to handle the calibration

	# files. (shared across sequences)

	###########################################################

	$log->entry("Running bateconvert on all event files");


	my %common = (
		residfile => 'CALDB',
		pulserfile => 'CALDB',
		fltpulserfile => 'CALDB',
		outfile => 'NONE',
		clobber => 'yes',
		chatter => 3,
		history => 'yes',
		calmode => 'INDEF',
		zeroit  => 'no',
		scaled_energy => 'yes'
	);


	my $tool = Util::HEAdas->new('bateconvert')
			->params(\%common);

	foreach my $unf (@all_event_files) {

		$log->entry("Calibrating $unf");

		###############################################

		# get the gain offset calibration file to use

		# for this event file

		###############################################

		my $unf_fits = Util::FITSfile->new($unf, 0);
		my $time = $unf_fits->keyword('TSTART');
		unless($time) {
		  $log->error(2, "unable to calibrate $unf, missing TSTART");
		  next;
		}

		my $gainoff = $filename->fetch_from_repository('bgaoff', 'b', '', $time);
		unless($gainoff) {
		  $log->error(2, "unable to obtain gain/offset file for time $time");
		  next;
		}

		$log->entry("Using gain/offset cal file $gainoff based on a start time of $time .");

		###########################

		# now run the calibration

		###########################

		$tool->params({
					calfile => $gainoff,
					infile => $unf,
				})
			->run;

    } # end of bateconvert loop over files


}



sub mask_weight_events
{
	my $self = shift;

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

	$log->entry('Computing BAT mask weighting for the desired source');


	my @events = $filename->get('unfiltered', 'bat', 'evsh??', '*');

	if (not @events) {
		$log->entry('no BAT (short) event files to process');
		return;
	}


	my %common = (
		attitude => $filename->get('attitude', 's'),
		ra => $jobpar->read('burst_ra'),
		dec => $jobpar->read('burst_dec'),
		bat_z => $jobpar->read('bat_z'),
		aperture => 'CALDB',
		detmask  => $filename->get('qualcal', 'bat', ''),
		coord_type => 'sky',
		rebalance => 'yes',
		corrections => 'flatfield,ndets,pcode,maskwt',
		teldef => 'CALDB',
		distfile => 'CALDB',
		origin_z => $jobpar->read('bat_origin_z'),
		pcodethresh => 0.05
	);

	my $tool = Util::HEAdas->new('batmaskwtevt')
			->params(\%common);

	my $trigtime = $self->determine_trigger_time;

	my $stats=Util::HEAdas->new("ftstat") 
			      ->verbose(0);

	foreach my $file (@events) {

		# set TRIGTIME in EVENT extension


		if ($trigtime) {
			Util::FITSfile->new($file, 'EVENTS')
					->keyword(TRIGTIME => $trigtime,
						'[s] MET Trigger Time')
					;
		}
		
		my $evaux = 'NONE';
		$evaux = $filename->get('eventaux', 'b', '', 0)
		  if $file=~/bevshsp/;

		$tool->params({
					infile => $file,
					auxfile => $evaux,
				})
			->run;

		if($evaux ne 'NONE'){
		  my $auxfits = Util::FITSfile->new($evaux, 1);
		  $auxfits->specs('[col TIME]');
		  
		  $stats->params({infile  => $auxfits->fullname(),
				  centroid => 'no'})
		        ->run();

		  my $parfile = $stats->parfile();
		  my $start = Util::Date->new( $parfile->read('min') );
		  my $stop  = Util::Date->new( $parfile->read('max') );

		  $auxfits->ext(0);
		  $auxfits->specs('');

		  $auxfits->begin_many_keywords();
		  $auxfits->keyword('TSTART', $start->seconds());
		  $auxfits->keyword('TSTOP', $stop->seconds());
		  $auxfits->keyword('DATE-OBS', $start->date() .'T'.$start->time() );
		  $auxfits->keyword('DATE-END', $stop->date() .'T'.$stop->time() );
		  $auxfits->end_many_keywords();
		}
	}

}

sub slew_only {
  my $self = shift;

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

  ##########################################################

  # if automatic target, should be more than just slew data

  ##########################################################

  return 0 if( Util::BATCave::get_tdrss_ack($self) );
  
  my @events = $filename->get('unfiltered', 'bat', 'evsh??', '*');
  my $gtipointing =  $filename->get('gti', 's', 'po', 0);
  my $gtinotpoint =  $filename->get('gti', 's', 'np', 0);

  if( @events == 1 ){
    my $file = $events[0];
    my $pofile = $filename->get('unfiltered', 'bat', 'evshpo', 0);
    my $slfile = $filename->get('unfiltered', 'bat', 'evshsl', 0);
    my $extractor = Util::Extractor->new();
    
    $extractor->instrument('bat', 'EVENT')
              ->infiles($file);

    $extractor->gti($gtipointing)
              ->outfile($pofile, 'event')
	      ->run();
    
    $extractor->gti($gtinotpoint)
              ->outfile($slfile, 'event')
	      ->run();

    unlink $file;

    my $pofits = Util::FITSfile->new($pofile);
    my $slfits = Util::FITSfile->new($slfile);

    my $non_slew = $pofits->keyword("NAXIS2");
    my $is_slew = $slfits->keyword("NAXIS2");

    if($non_slew){
      $pofits->keyword('OBS_MODE', 'POINTING');
    }else{
      unlink $pofile;
    }

    if($is_slew){
      $slfits->keyword('OBS_MODE', 'SLEW');
    }else{
      unlink $slfile;
    }

    ##################################

    # Update the entries in the db file

    ##################################

    my $hkfile = $filename->get('hk', 'proc', 'badb', 0);
    my $hkfits = Util::FITSfile->new($hkfile)->cols('filename');
    my @names = $hkfits->table();
    my $row = 1;
    my @rows;
    foreach my $name (@names){
      push @rows, $row if $file eq $name;
      $row++;
    }
    $row = shift @rows;

    if(@rows){
      Util::HEAdas->new('ftdelrow')
	          ->params({infile => $hkfile,
			    outfile => 'none',
			    rows => join(',',@rows),
			    confirm => 'YES'})
                  ->run();
    }

    my $edit = Util::HEAdas->new('ftedit')
                           ->params({infile => $hkfile,
				     row => $row,
				     history => 'yes'});

    if($is_slew){
      $edit->params({column => 'filename',
		     value => $slfile})
	   ->run();

      $edit->params({column => 'pointing_mode',
		     value => 'SLEW'})
           ->run();
    
      $edit->params({column => 'start_time',
		     value => $slfits->keyword('TSTART')})
           ->run();
      $edit->params({column => 'exp_start',
		     value => $slfits->keyword('TSTART')})
           ->run();

      $edit->params({column => 'stop_time',
		     value => $slfits->keyword('TSTOP')})
	   ->run();
      $edit->params({column => 'exp_stop',
		     value => $slfits->keyword('TSTOP')})
	  ->run();
    }

    #################################################################

    # If there is both slew and non-slew data, need to add an hk row

    #################################################################

    my $hktemp = "badb.tmp";
    my $hktemp1 = "badb1.tmp";      
    if( $is_slew && $non_slew ){
      Util::HEAdas->new('ftcopy')
                  ->params({outfile => $hktemp,
			    infile => $hkfile . "[1][#row==$row]"})

	           ->run();
      
      $edit->params({infile => $hktemp,
			row => 1});
    }
      
    ################################################

    # Add a db entry for pointing file if it exists

    ################################################

    if( $non_slew ){
      $pofits->keyword('OBS_MODE', 'POINTING');


      $edit->params({column => 'filename',
		     value => $pofile})
	   ->run();

      $edit->params({column => 'pointing_mode',
		     value => 'POINTING'})
	   ->run();

      $edit->params({column => 'start_time',
		     value => $pofits->keyword('TSTART')})
	   ->run();
      $edit->params({column => 'exp_start',
		     value => $pofits->keyword('TSTART')})
	   ->run();

      $edit->params({column => 'stop_time',
		     value => $pofits->keyword('TSTOP')})
	   ->run();
      $edit->params({column => 'exp_stop',
		     value => $pofits->keyword('TSTOP')})
	   ->run();
    }

    if( $is_slew && $non_slew ){
      Util::HEAdas->new('ftmerge')
	          ->params({infile => "$hkfile,$hktemp",
			    outfile => $hktemp1})
		  ->run();
      
      rename $hktemp1, $hkfile;
      unlink $hktemp;
    }
  }

  return 1;
}


1;