Subs::UVOTReport (version 0.0)


package Subs::UVOTReport;
##############################################################################
#
# DESCRIPTION: This creates an HTML report of UVOT exposures. It is largely
# DESCRIPTION: a translation of the FITS exposure report data.
#
# HISTORY: 
# HISTORY: $Log: UVOTReport.pm,v $
# HISTORY: Revision 1.27  2006/04/27 15:47:20  apsop
# HISTORY: Allow for either INDEF or NULL values returned from FITSfile class.
# HISTORY:
# HISTORY: Revision 1.26  2006/04/14 18:26:35  apsop
# HISTORY: Fix bug in calculating intensifier exposure.
# HISTORY:
# HISTORY: Revision 1.25  2006/01/11 21:05:52  apsop
# HISTORY: Calculate exp times for blocked filter.
# HISTORY:
# HISTORY: Revision 1.24  2005/11/18 17:58:16  apsop
# HISTORY: Check for undefined values in @mode and @bin_level.
# HISTORY:
# HISTORY: Revision 1.23  2005/11/08 19:54:35  apsop
# HISTORY: <Previous comment bogus> Test for undefined mode value.
# HISTORY:
# HISTORY: Revision 1.22  2005/11/08 19:22:28  apsop
# HISTORY: Populate the TIMELIST and DATALIST hashes. Used to be an SWCheckInput.
# HISTORY:
# HISTORY: Revision 1.21  2005/09/30 17:04:17  apsop
# HISTORY: More tests for INDEF fields in the uvot cat file.
# HISTORY:
# HISTORY: Revision 1.20  2005/09/30 12:18:02  apsop
# HISTORY: Bug fix.
# HISTORY:
# HISTORY: Revision 1.19  2005/09/28 17:30:42  apsop
# HISTORY: More tests to deal with INDEF values.
# HISTORY:
# HISTORY: Revision 1.18  2005/09/27 17:44:03  apsop
# HISTORY: Put in several checks to deal with INDEF values.
# HISTORY:
# HISTORY: Revision 1.17  2005/09/19 13:35:31  apsop
# HISTORY: Only count on-target time when calculating exposure for cleaned event lists.
# HISTORY:
# HISTORY: Revision 1.16  2005/08/31 19:04:14  apsop
# HISTORY: Protect against null values.
# HISTORY:
# HISTORY: Revision 1.15  2005/08/30 14:11:06  apsop
# HISTORY: Major rework.  Replace loss column with image_loss.  Use calculated frame time. New exposure calculation.
# HISTORY:
# HISTORY: Revision 1.14  2005/03/07 22:43:56  apsop
# HISTORY: Changes to deal with UNDEF values in the input fits files.
# HISTORY:
# HISTORY: Revision 1.13  2004/09/05 19:06:21  apsop
# HISTORY: Make sure that exposure param values always get initialize to zero.
# HISTORY:
# HISTORY: Revision 1.12  2004/08/15 18:41:52  apsop
# HISTORY: Fix problem with info being available only in certain modes
# HISTORY:
# HISTORY: Revision 1.11  2004/08/13 14:27:06  apsop
# HISTORY: Update Report modules to record exposure information in job.par file.
# HISTORY:
# HISTORY: Revision 1.10  2004/05/06 20:02:34  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;
use Subs::HTMLPage;
use Subs::UvotNames;

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

sub new {
    my $proto=shift;
    my $file=$proto->filename()->get("report", "uvot");
    my $seq = $proto->jobpar()->read('sequence') .".". $proto->jobpar()->read('seqprocnum');
    my $self=$proto->SUPER::new($file, "UVOT Exposure Report for $seq");

    $self->{DESCRIPTION}="Making UVOT HTML Exposure Report";

    return $self;
}

##################
# METHODS:
##################

##############################################################################
#
##############################################################################
sub body {
    my $self=shift;

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

    my $exps;
    for(my $ifilt=0; $ifilt < @$Subs::UvotNames::filterCodes; $ifilt++){
      for(my $imode=0; $imode < @$Subs::UvotNames::modeNames; $imode++){
	$$exps[$ifilt][$imode] = 0;
      }
    }

    #######################################
    # get the exposure report file
    #######################################
    my $file = $filename->get("hk", "u", "ct", "*");
    if ( ! -f $file ) {
        $log->entry("No UVOT exposure report FITS file");
    }else{

      ########################################
      # read the FITS file
      ########################################
      my $fits = Util::FITSfile->new($file,1);

      my @expid   = $fits->cols("EXPID")->table();

      my @time    = $fits->cols("TIME")->table();
      my @exp_des = $fits->cols("EXP_DES")->table();

      my @mode = $fits->cols("MODEID")->table();
      my @submode = $fits->cols("SUBMODE")->table();
      my @filter = $fits->cols("FILTER")->table();

      my @im_x0 = $fits->cols("IM_X0_ACT")->table();
      my @im_x1 = $fits->cols("IM_X1_ACT")->table();
      my @im_y0 = $fits->cols("IM_Y0_ACT")->table();
      my @im_y1 = $fits->cols("IM_Y1_ACT")->table();

      my @ev_x0 = $fits->cols("EV_X0_ACT")->table();
      my @ev_x1 = $fits->cols("EV_X1_ACT")->table();
      my @ev_y0 = $fits->cols("EV_Y0_ACT")->table();
      my @ev_y1 = $fits->cols("EV_Y1_ACT")->table();

      my @bin_level = $fits->cols("BINLVL")->table();
      my @nevents   = $fits->cols("NEVENTS")->table();
      my @gevents   = $fits->cols("GEVENTS")->table();
      my @gimage    = $fits->cols("GIMAGE")->table();
      my @nframes   = $fits->cols("NFRAMES")->table();
      my @frame_duration = $fits->cols("FrameTime")->table();

      my @reason   = $fits->cols("REASON")->table();
      my @ifiles   = $fits->cols("IFILEREF")->table();
      my @imename  = $fits->cols("IMENAME")->table();

      #########################
      # write the HTML table 
      #########################
      $self->begin_table("Exp ID", 
			 "ICU Label", 
			 "Mode", "Submode", "Filter",
			 "Event Window", "Image Window", "Binning",
			 "Duration",
			 "Count Rate", 
			 "Image Data Loss",
			 "Completion");

      my $nrows = $fits->nrows();
      for(my $i=0; $i<$nrows; $i++) {

        my $exp_des = 0;
	$exp_des = "0x".sprintf("%x", $exp_des[$i]) if $exp_des[$i];

        my $submode = 0;
	$submode = "0x".sprintf("%x", $submode[$i]) if ($submode[$i] && $submode[$i] !~ /(INDEF|NULL)/ );

	my ($event_window_x, $event_window_y, $image_window_x, $image_window_y) = ('n/a', 'n/a', 'n/a', 'n/a');

        if(defined($mode[$i]) && $mode[$i] !~ /(INDEF|NULL)/){
	  if($mode[$i]==2 || $mode[$i]==4){
	    if(defined($ev_x1[$i]) && $ev_x1[$i] !~ /(INDEF|NULL)/ &&
	       defined($ev_x0[$i]) && $ev_x0[$i] !~ /(INDEF|NULL)/ ){
	      $event_window_x = $ev_x1[$i] - $ev_x0[$i] + 1;
	    }else{
	      $event_window_x = 'null';
	    }
	    if(defined($ev_y1[$i]) && $ev_y1[$i] !~ /(INDEF|NULL)/ && 
	       defined($ev_y0[$i]) && $ev_y0[$i] !~ /(INDEF|NULL)/ ){
	      $event_window_y = $ev_y1[$i] - $ev_y0[$i] + 1;
	    }else{
	      $event_window_y = 'null';
	    }
	  }

	  if($mode[$i]==3 || $mode[$i]==4){
	    if(defined($im_x1[$i]) && $im_x1[$i] !~ /(INDEF|NULL)/ && 
	       defined($im_x0[$i]) && $im_x0[$i] !~ /(INDEF|NULL)/){
	      $image_window_x = $im_x1[$i] - $im_x0[$i] + 1;
	    }else{
	      $image_window_x = 'null';
	    }
	    if(defined($im_y1[$i]) && $im_y1[$i] !~ /(INDEF|NULL)/ && 
	       defined($im_y0[$i]) && $im_y0[$i] !~ /(INDEF|NULL)/ ){
	      $image_window_y = $im_y1[$i] - $im_y0[$i] + 1;
	    }else{
	      $image_window_y = 'null';
	    }
	  }
	}

	my $count_rate = 'null';
	my $exposure;
	if($nframes[$i] && $nframes[$i] !~ /(INDEF|NULL)/){
	  $exposure = $nframes[$i]*$frame_duration[$i];
	  $$exps[$filter[$i]][$mode[$i]] += $exposure;

	  $count_rate = sprintf("%.1f", $nevents[$i]/$exposure) if $exposure;
	}

	my $gcounts = 0;
	if( defined($mode[$i]) && $mode[$i] !~ /(INDEF|NULL)/ ){
	  if($mode[$i]==2 || $mode[$i]==6){
	    $gcounts = $gevents[$i];
	  }else{
	    $gcounts = $gimage[$i];
	  }
	}

	my $loss = 0;
	if( $ifiles[$i] ne 'NONE' ){
	  #######################################################
	  # Determine the percentage of NULL pixels in the image
	  #######################################################
	  my $stats=Util::HEAdas->new("ftstat") 
                                ->params({infile  => $ifiles[$i] .'['. $imename[$i] .']',
					  centroid => 'no'})
		                ->verbose(0)
				->run();

	    my $parfile = $stats->parfile();
	    my $nulls = $parfile->read('null');
	    if( $nulls ){
	      $loss = $parfile->read('good') / $nulls;
	      $loss = 1/(1+$loss);
	    }
	}
	my $filter_name = $$Subs::UvotNames::filterNames[$filter[$i]];
	my $reason_name = 'UNKNOWN';
	$reason_name = $$Subs::UvotNames::reasonNames[$reason[$i]] 
	  if($reason[$i] && $reason[$i] !~ /(INDEF|NULL)/);
	my $mode_name = 'UNKNOWN';
	$mode_name = $$Subs::UvotNames::modeNames[$mode[$i]] 
	  if($mode[$i] && $mode[$i] !~ /(INDEF|NULL)/);

        $self->table_row($expid[$i], $exp_des, 
                         $mode_name ? $mode_name : 'Unknown', 
                         $submode, 
                         $filter_name ? $filter_name : 'Unknown',
                         "$event_window_x x $event_window_y",
                         "$image_window_x x $image_window_y",
                         $bin_level[$i] ? $bin_level[$i] : 'Unknown',
                         $exposure ? sprintf("%.1f s",$exposure) : 'null',
                         "$count_rate/s",
                         sprintf("%.1f%%",$loss),
                         $reason_name ? $reason_name : 'Unknown'
                         );

      }
      $self->end_table();
    }

    $self->event_exposures();

    for(my $ifilt=0; $ifilt<=10; $ifilt++){
      my $parm = $$Subs::UvotNames::filterParams{ $$Subs::UvotNames::filterCodes[$ifilt] };

      my $sumexp = $$exps[$ifilt][3] + $$exps[$ifilt][7] + $$exps[$ifilt][9] + $$exps[$ifilt][10];
      $jobpar->set({ 'uvot_image_'.$parm => sprintf('%.03f', $sumexp) });

      $sumexp = $$exps[$ifilt][2] + $$exps[$ifilt][4] + $$exps[$ifilt][6];
      $jobpar->set({ 'uvot_unf_'.$parm => sprintf('%.03f', $sumexp) });
    }
    
} # end of body method

sub event_exposures {
    my $self=shift;

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

    my $gtisum=Util::Stool->new("compute_exposure")
                          ->verbose(0);

    my $tmpgti = 'otgti.tmp';
    unlink $tmpgti;
    $gtisum->command_line("$tmpgti\[STDGTI\]");

    my $ontarget = $filename->get('gti', 's', 'ot', 0);
    my $merge = Util::Ftool->new('mgtime')
	                   ->params({merge => 'AND',
				     outgti => $tmpgti});

    foreach my $filter (keys %$Subs::UvotNames::filterParams){
      my $exposure = 0;
      my @efiles = $filename->get('event', 'uvot', "$filter*", '*');
      @efiles = $filename->get('unfiltered', 'uvot', "$filter*", '*') unless @efiles;

      foreach my $rawFile (@efiles) {
	my $rawFits = Util::FITSfile->new($rawFile);
	my $nhdus = $rawFits->nhdus();
	for(my $hdu=2; $hdu<$nhdus; $hdu++){
	  $rawFits->ext($hdu);
	  my $name = $rawFits->keyword('EXTNAME');
   	  if($name =~ /^GTI/){
 	    $merge->params({ingtis => "$ontarget $rawFile\[$name\]"})
	          ->run();

            $exposure += $gtisum->run()->stdout();
	    unlink $tmpgti;
          }
	}
      }
      $jobpar->set({'uvot_evt_' . $$Subs::UvotNames::filterParams{$filter} => sprintf('%.03f', $exposure)});
    }
}