Subs::BATBurst (version $)


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: $Log: BATBurst.pm,v $
# HISTORY: Revision 1.60  2014/02/27 09:22:47  apsop
# HISTORY: Don't use uat attitude file, at request of BAT Team/C.Markwardt.
# HISTORY:
# HISTORY: Revision 1.59  2013/08/19 20:29:24  apsop
# HISTORY: Only log fetch_from_repository result if fetch succeeded, to
# HISTORY: avoid a Perl message about using an undefined variable. (If
# HISTORY: unsuccessful, fetch_from_repository already logs an error.)
# HISTORY:
# HISTORY: Revision 1.58  2013/05/30 07:54:54  apsop
# HISTORY: Log fetches from BAT repository
# HISTORY:
# HISTORY: Revision 1.57  2012/01/12 06:52:03  apsop
# HISTORY: Changes going to proc3.15.03
# HISTORY:
# HISTORY: 2011-08-31 JRG as apsop: In slew_only(), skip rest & issue error
# HISTORY:  if @rows is empty (currently still returns 1 if so, but should it?)
# HISTORY:
# HISTORY: Revision 1.56  2011/01/20 17:12:44  apsop
# HISTORY: Removed older version of a subroutine and some commented code
# HISTORY:
# HISTORY: Revision 1.54  2009/04/13 14:08:03  apsop
# HISTORY: added check if bevbu.gti file exist
# HISTORY:
# HISTORY: Revision 1.53  2009/03/12 14:43:49  apsop
# HISTORY: GTI_PRE changed in 1 extension bevbu.gti file
# HISTORY:
# HISTORY: Revision 1.52  2008/12/10 14:00:30  apsop
# HISTORY: Add gtinam parameter to extractor calls.
# HISTORY:
# HISTORY: Revision 1.51  2008/05/15 19:29:14  apsop
# HISTORY: Move creation of GTI files to a SwiftSub method.  Check for existence of pointing GTIs before using.
# HISTORY:
# 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: $Revision: 1.60 $
#
##############################################################################


use Subs::Sub;


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

use Util::SwiftTags;
use Util::GTIfile;

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();
    my $gti_pre = $filename->get('burstgti', 'bat', '', 0);
    if(-e $gti_pre ){
        Util::HEAdas->new('fthedit')
       ->params({infile => $gti_pre.'[1]',
        keyword =>'EXTNAME',
        value   =>'GTI_PRE ',
        comment =>'           / name of this binary table extension'})
        ->run();
    }

} # 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';

    Util::GTIfile->new($gti_pre, $preslew_start, $preslew_stop);
    Util::GTIfile->new($gti_slew, $slew_start, $slew_stop);
    Util::GTIfile->new($gti_post, $postslew_start, $postslew_stop);

    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');

      $extractor->params({gtinam => 'GTI'})
                ->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');

      $extractor->params({gtinam => 'GTI'})
                ->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');

      $extractor->params({gtinam => 'GTI'})
                ->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.');
    unlink $gti_post;
    $gti_pre = 'bat_pre_gti.tmp';

    Util::GTIfile->new($gti_pre, 0, $trigtime);
    Util::GTIfile->new($gti_post, $trigtime, 1.E12);

    #################################################################
    # 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");
                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;
                }

		$log->entry("BATBurst.pm requesting from repository " .
			    "bgaoff: $time");
                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("fetched from repository " .
			    "bgaoff: \$gainoff=$gainoff");
                $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 $attitude = $filename->get('attcorr', 'p');
	if (-e $attitude) {
	    $log->entry("Got pat attitude file $attitude");
	} else {
            $log->error(1, "$attitude pat attitude file does not exist, trying sat file");
            $attitude = $filename->get('attitude', 's');
            if (-e $attitude) {
		$log->entry("Got sat attitude file $attitude");
	    } else {
		$log->error(1, "Unable to find attitude file, bailing");
		return;
            }
	}


        my %common = (
#               attitude => $filename->get('attitude', 's'),
                attitude => $attitude,
                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'),
#               clobber  => 'yes',
                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);

        my $idx = 0;

        my @evAux = ();

        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/;

                if($evaux ne 'NONE'){
                  $evaux = $evaux.'_'.$idx;

                  if(-e $evaux){
                    unlink $evaux;
                  }

                  push @evAux, $evaux;
                  $idx++;
                }

#               print "Running batmaskwtevt using infile=$file, auxfile=$evaux, trigtime=$trigtime\n";

                $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();
                }

        }

        if($idx > 1){

          my $Nevaux = $evAux[0];
          $Nevaux =~ s/\_0$//;

          $log->entry("Merging files $evAux[1] and $evAux[0] into $Nevaux");
          Util::HEAdas->new('ftmerge')
              ->params({infile => "$evAux[1], $evAux[0]",
                        outfile => $Nevaux,
                        clobber => 'yes'})
                ->run();


          foreach(my $i=2; $i<$idx; $i++){

            my $outfile = $Nevaux.'_merged';

            $log->entry("Merging files $evAux[$i] and $Nevaux into $outfile");
            Util::HEAdas->new('ftmerge')
                ->params({infile => "$evAux[$i], $Nevaux",
                          outfile => $outfile,
                          clobber => 'yes'})
                  ->run();

            rename $outfile, $Nevaux;

          }
          foreach my $f (@evAux){
            if(-e $f){
              unlink $f;
            }
          }


          my $auxfits = Util::FITSfile->new($Nevaux, 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();

          $auxfits->ext(1);
          $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();



        } elsif ($idx == 1){
          my $Nevaux = $evAux[0];
          $Nevaux =~ s/\_0$//;
          rename $evAux[0], $Nevaux;
        }

}




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);

        if( -f $gtipointing ){
            $extractor->gti($gtipointing)
                ->outfile($pofile, 'event');

            $extractor->params({gtinam => 'GTI'})
                ->run();
        }

        if( -f $gtinotpoint ){
            $extractor->gti($gtinotpoint)
                ->outfile($slfile, 'event');

            $extractor->params({gtinam => 'GTI'})
                ->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;
                }
          } else {
	      $log->error(1, "BATBurst,slew_only: rows is empty, file=$file");
	  }
    }

    return 1;
}


1;