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.29 2008/06/02 13:35:00 apsop
# HISTORY: Test for existence of catalog file. Fix bug in an initializing ifiles array.
# HISTORY:
# HISTORY: Revision 1.28 2008/05/15 19:35:47 apsop
# HISTORY: Add column for good attitude fraction. Look for catalog entries in the damaged image file.
# HISTORY:
# 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::SwiftSub;
use Subs::HTMLPage;
use Subs::UvotNames;
use Util::GTIfile;
@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;
}
}
#########################
# 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",
"Good Attitude Fraction",
"Completion");
my @table_rows;
#######################################
# get the exposure report file
#######################################
foreach my $file_mode ('ct', 'di'){
my $file;
if( $file_mode eq 'ct' ){
$file = $filename->get("hk", "u", "ct", 0)
}else{
$file = $filename->get('rawimage', 'uvot', 'di', 0);
}
if ( ! -f $file ) {
$log->entry("No UVOT exposure report file $file .");
}else{
my $fits = Util::FITSfile->new($file,'EXPCATALOG');
###########################################
# Make sure there is a catalogue extension
###########################################
my @extensions = $fits->list_hdus();
unless( grep(/EXPCATALOG/, @extensions) ){
$log->entry("No catalog extension in $file.");
next;
}
########################################
# read the FITS file
########################################
my @expid = $fits->cols("EXPID")->table();
my @estart = $fits->cols("ESTART")->table();
my @estop = $fits->cols("ESTOP")->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 @imename = $fits->cols("IMENAME")->table();
my @ifiles;
my $nrows = $fits->nrows();
if( $file_mode eq 'ct' ){
@ifiles = $fits->cols("IFILEREF")->table();
}else{
@ifiles = ($file) x $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;
my $good_att;
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 $fits_file = Util::FITSfile->new($ifiles[$i], $imename[$i]);
$good_att = $fits_file->keyword('GOOD_ATT');
}else{
$good_att = Subs::SwiftSub::good_attitude_fraction($self, $estart[$i], $estop[$i]);
}
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)/);
push @table_rows, [$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),
defined($good_att) ? sprintf("%.2f", $good_att) : 'n/a',
$reason_name ? $reason_name : 'Unknown'
];
}
}
}
@table_rows = sort {$$a[0] cmp $$b[0]} @table_rows;
foreach my $table_row (@table_rows){
$self->table_row(@$table_row);
}
$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 $tmpgti = 'otgti.tmp';
unlink $tmpgti;
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();
my $gtifits = Util::GTIfile->new($tmpgti);
$exposure += $gtifits->sum();
unlink $tmpgti;
}
}
}
$jobpar->set({'uvot_evt_' . $$Subs::UvotNames::filterParams{$filter} => sprintf('%.03f', $exposure)});
}
}