package Util::Catalog;
##############################################################################
#
# DESCRIPTION: This class is useful for generating catalogs of files.
# DESCRIPTION: Calling the "make" method will create a FITS output catalog
# DESCRIPTION: with the standard format. The genral user does not need
# DESCRIPTION: to worry about any of the other methods.
# DESCRIPTION:
# DESCRIPTION: Certain catalog information is accumulated in the class data.
# DESCRIPTION: This makes it more efficient to generate more than one catalog
# DESCRIPTION: containing identical files.
# DESCRIPTION: It also allows the "all_files" and "fits_files" methods to
# DESCRIPTION: give lists
# DESCRIPTION: of files in the union of all catalogs created so far.
# DESCRIPTION:
# DESCRIPTION: Sub-classes may change the format of the catalog file
# DESCRIPTION: by overriding some of the methods. The Util::HTMLcatalog class
# DESCRIPTION: does this.
#
# HISTORY:
# HISTORY: 2005-05-27
# HISTORY: Add capability a file type to have more than one file class
# HISTORY:
#
# VERSION: 1.0
#
##############################################################################
use Util::Stool;
use strict;
my $FILENAME;
my $LOG;
my $isFITS;
my $HEADER_TEMPLATE;
my $KEYWORD_TEMPLATE;
my %SIZE;
my %FORMAT;
my %FILES_OF_TYPE;
my %ALL_FILES;
my %FITS_FILES;
my %FUTURE_FILES;
####################################
# initialize some of the class data
####################################
sub BEGIN {
#####################################
# initialize variables
#####################################
%SIZE=();
%FORMAT=();
%FILES_OF_TYPE=();
%ALL_FILES=();
%FITS_FILES=();
####################################################
# text for header template file
####################################################
$HEADER_TEMPLATE ="FILENAME 64A\n";
$HEADER_TEMPLATE.="FORMAT 16A\n";
$HEADER_TEMPLATE.="TYPE 32A\n";
$HEADER_TEMPLATE.="FILECLAS 32A\n";
$HEADER_TEMPLATE.="DESCRIP 64A\n";
$HEADER_TEMPLATE.="FILESIZE 1J kilobytes\n";
$HEADER_TEMPLATE.="ARCHSIZE 1J kilobytes\n";
$HEADER_TEMPLATE.="CHECKSUM 1J\n";
$HEADER_TEMPLATE.="GZIP_CRC 8A\n";
}
#########################
# constructor
#########################
sub new { #(catalog_type)
my $proto = shift;
my $class = ref($proto) || $proto;
#######################################
# be sure we are initialized
#######################################
unless( $FILENAME) {
print STDERR "Util::Catalog not initialized properly";
exit 1;
}
#####################################
# initialize some variables
#####################################
my $self={};
$self->{CAT_TYPE}=shift;
$self->{CAT_NAME}=$FILENAME->get($self->{CAT_TYPE});
$self->{DATA}="";
#########################################################
# put references to these variables in $self so that they
# can be accessed by sub-classes
#########################################################
$self->{FILENAME}=$FILENAME;
$self->{LOG}=$LOG;
$self->{HEADER_TEMPLATE}=\$HEADER_TEMPLATE;
$self->{KEYWORD_TEMPLATE}=\$KEYWORD_TEMPLATE;
$self->{SIZE}=\%SIZE;
$self->{FORMAT}=\%FORMAT;
$self->{FILES_OF_TYPE}=\%FILES_OF_TYPE;
$self->{ALL_FILES}=\%ALL_FILES;
$self->{FITS_FILES}=\%FITS_FILES;
$self->{FUTURE_FILES}=\%FUTURE_FILES;
bless($self,$class);
return $self;
}
###################################
# ACCESSORS:
###################################
##############################################################
# set or return the filename generator object for this class
##############################################################
sub filename {
my $self=shift;
if(@_) {
#####################################
# we are setting the filename object
#####################################
$FILENAME=shift;
######################################################
# text for keywords template file
######################################################
my $origin=$FILENAME->procpar()->read("origin");
my $seq =$FILENAME->sequence();
my $ver =$FILENAME->version();
$KEYWORD_TEMPLATE ="ORIGIN=$origin / Place this file was created\n";
$LOG=$FILENAME->log();
} # end if setting FILENAME object
return $FILENAME;
}
#########################################################################
# set the files which we should not expect to exist yet when we
# are making the catalog.
#########################################################################
sub future_files { #(type=>format, type=>format...)
my $self=shift;
%FUTURE_FILES=@_;
my $type;
foreach $type (keys %FUTURE_FILES ) {
$FORMAT{$FILENAME->get($type)}=$FUTURE_FILES{$type};
$SIZE{$FILENAME->get($type)}=0;
}
}
#############################################################
# returns a list of all FITS format files appearing in all
# catalogs created so far.
#############################################################
sub fits_files {
my $self=shift;
return keys %FITS_FILES;
}
#############################################################
# returns a list of all files appearing in all
# catalogs created so far.
#############################################################
sub all_files {
my $self=shift;
return keys %ALL_FILES;
}
###################
# METHODS:
###################
######################################################
# determine the format (FITS, ASCII, etc.) of a file.
######################################################
sub format {
my $self=shift;
my $file=shift;
######################################################
# determine the file format if we don't know it already
######################################################
unless( $FORMAT{$file} ) {
######################################################
# create the isFITS tool if it doesn't already exist
######################################################
unless($isFITS) {
$isFITS=Util::Stool->new("isFITS")
->verbose(0)
}
######################
# determine the format
######################
$FORMAT{$file}=$isFITS->command_line($file)
->run()
->stdout();
chomp($FORMAT{$file});
}
############################
# return the file size
############################
return $FORMAT{$file};
} # end of format method
#############################################
# determine the size of a file in kilobytes
#############################################
sub size {
my $self=shift;
my $file=shift;
######################################################
# calculate the file size if we don't know it already
######################################################
unless( defined $SIZE{$file} ) {
$SIZE{$file}=int((-s $file)/1024+.5);
}
############################
# return the file size
############################
return $SIZE{$file};
} # end of size method
######################################
# add a file to the catalog
######################################
sub add_file {
my $self=shift;
my $file=shift;
my $type=shift;
my $classes=shift;
my $description=shift;
#print "file=|$file| type=|$type| class=|$class| desc=|$description|\n";
my $format=$self->format($file);
my $size =$self->size($file);
$ALL_FILES{$file}=$type;
if($format eq 'FITS' ) { $FITS_FILES{$file}=$type }
foreach my $class (@$classes){
$self->{DATA}.="$file $format $type $class '$description' ";
$self->{DATA}.="$size 0 0 'ffffffff'\n";
}
}
#######################################
# return all the files of a given type
#######################################
sub files_of_type {
my $self=shift;
my $type=shift;
unless($FILES_OF_TYPE{$type} ) {
#############################################
# need to determine the files for this type
############################################
if($FUTURE_FILES{$type}) {
##########################################
# the file of this type may not exist yet
##########################################
my $file=$FILENAME->get($type);
if( -f $file && ! $SIZE{file} ) {
##########################################
# the file has been created already
# but has zero size, so set its size as
# unknown so it will be determined later
##########################################
$SIZE{$file}=undef;
}
$FILES_OF_TYPE{$type}=[$file];
} else {
######################################################
# only add the files of this type which already exist
######################################################
$FILES_OF_TYPE{$type}=[];
foreach ($FILENAME->any($type)) {
if(-f ) {push @{$FILES_OF_TYPE{$type}}, ($_) }
}
} # end if files should exist already
} # end if we needed to determine the files for this type
return @{$FILES_OF_TYPE{$type}};
}
###################################################
# add all the files of a given type to the catalog
###################################################
sub add_type {
my $self=shift;
my $type=shift;
my $description=$FILENAME->description($type);
my $classes =$FILENAME->class($self->{CAT_TYPE},$type);
my $file;
foreach $file ($self->files_of_type($type) ) {
$self->add_file($file,$type,$classes,$description);
}
}
#########################################################
# add all the files of all the file types to the catalog
#########################################################
sub fill {
my $self=shift;
my $type;
foreach $type ($FILENAME->types($self->{CAT_TYPE}) ) {
$self->add_type($type);
}
}
###############################################################
# actually write the catalog file
###############################################################
sub close {
my $self=shift;
##################################
# create the template files
##################################
my $header_template="$self->{CAT_TYPE}_header_template.tmp";
open HEADER, ">$header_template";
print HEADER $HEADER_TEMPLATE;
close HEADER;
my $keyword_template="$self->{CAT_TYPE}_keyword_template.tmp";
open KEYWORD, ">$keyword_template";
print KEYWORD $KEYWORD_TEMPLATE;
close KEYWORD;
my $data_template="$self->{CAT_TYPE}_data_template.tmp";
open DATA, ">$data_template";
print DATA $self->{DATA};
close DATA;
#################################################################
# run fcreate - destroy it explicitly to be sure the parfile is
# not hanging around later when we look for leftover files
#################################################################
unlink $self->{CAT_NAME};
Util::Ftool->new("fcreate")
->params({outfile => $self->{CAT_NAME},
datafile => $data_template,
cdfile => $header_template,
headfile => $keyword_template,
tbltype => "binary",
nskip => 0,
nrows => 0,
history => "no",
morehdr => 0,
extname => "CATALOG",
clobber => "yes" })
->run()
->DESTROY();
#################################
# clean up the temporary files
#################################
unlink $data_template;
unlink $header_template;
unlink $keyword_template;
} # end of close method
########################################
# fill and close the catalog
########################################
sub make {
my $self=shift;
$LOG->entry("Creating $self->{CAT_NAME}");
$self->fill();
$self->close();
return $self;
}
###########################################################
# add the name of the catalog to the parfile
###########################################################
sub register_in_parfile {
my $self=shift;
my $param=shift || $self->{CAT_TYPE};
$FILENAME->jobpar()->set({$param=>$self->{CAT_NAME}});
}
1;