#! /bin/sh # This is the LHEA perl script: /cvmfs/extras-fp7.egi.eu/extras/heasoft/ftools/x86_64-unknown-linux-gnu-libc2.19-0/bin/pcaextlc2 # The purpose of this special block is to make this script work with # the user's local perl, regardless of where that perl is installed. # The variable LHEAPERL is set by the initialization script to # point to the local perl installation. #------------------------------------------------------------------------------- eval ' if [ "x$LHEAPERL" = x ]; then echo "Please run standard LHEA initialization before attempting to run /cvmfs/extras-fp7.egi.eu/extras/heasoft/ftools/x86_64-unknown-linux-gnu-libc2.19-0/bin/pcaextlc2." exit 3 elif [ "$LHEAPERL" = noperl ]; then echo "During LHEA initialization, no acceptable version of Perl was found." echo "Cannot execute script /cvmfs/extras-fp7.egi.eu/extras/heasoft/ftools/x86_64-unknown-linux-gnu-libc2.19-0/bin/pcaextlc2." exit 3 elif [ `$LHEAPERL -v < /dev/null 2> /dev/null | grep -ic "perl"` -eq 0 ]; then echo "LHEAPERL variable does not point to a usable perl." exit 3 else # Force Perl into 32-bit mode (to match the binaries) if necessary: if [ "x$HD_BUILD_ARCH_32_BIT" = xyes ]; then if [ `$LHEAPERL -V 2> /dev/null | grep -ic "USE_64_BIT"` -ne 0 ]; then VERSIONER_PERL_PREFER_32_BIT=yes export VERSIONER_PERL_PREFER_32_BIT fi fi exec $LHEAPERL -x $0 ${1+"$@"} fi ' if(0); # Do not delete anything above this comment from an installed LHEA script! #------------------------------------------------------------------------------- #!/usr/bin/perl # # File: pcaextlc2 # # Description: Extract PCA Standard2 spectrum and background, and optional deadtime correction # # Author: C. B. Markwardt # # use Getopt::Std; getopts(':h'); if (defined $opt_h) { print <= 1); print "----------------------------------------\n" if ($chatter >= 2); $accumulate = "ONE"; # Only support one light curve at a time # Parameter validation $clobstr = $clobber ? "YES" : "NO"; $cleanstr = $cleanup ? "YES" : "NO"; undef $filtfile if ($filtfile =~ m/^none$/i); undef $bkg_infile if ($bkg_infile =~ m/^none$/i); if ($lcmode =~ m/^SUM$/i) { $lcmode = "SUM"; } elsif ($lcmode =~ m/^RATE$/i) { $lcmode = "RATE"; } else { die "ERROR: lcmode must be either SUM or RATE"; } die "ERROR: binsz must be greater than zero" if ($binsz <= 0); die "ERROR: binsz must be a multiple of 16" if (int($binsz/16.0) != ($binsz/16.0)); if ($deadcorrtype =~ m/^LIVE$/i) { $deadcorrtype = "LIVE"; print " Using LIVE-time correction\n" if ($chatter >= 5); } elsif ($deadcorrtype =~ m/^ON$/i) { $deadcorrtype = "ON"; print " Using ON-time correction\n" if ($chatter >= 5); } elsif ($deadcorrtype =~ m/^NONE$/i) { $deadcorrtype = "NONE"; } else { die "ERROR: $deadcorrtype must be either 'LIVE', 'ON' or 'NONE'"; } # Check for input files because saextrct gives very misleading # error messages. if ($src_infile =~ m/^@(.*)$/) { die "ERROR: Input file $1 does not exist" if ( ! -r "$1" ); } if ($bkg_infile =~ m/^@(.*)$/) { die "ERROR: Input file $1 does not exist" if ( ! -r "$1" ); } print " PCUs: $pculist\n" if ($chatter >= 2); print " Layers: $layerlist\n" if ($chatter >= 2); @columns = &parse_pcus_columns($pculist,$layerlist); print " (normalized PCU list: $pculist)\n" if ($chatter >= 5); print " (normalized layer list: $layerlist)\n" if ($chatter >= 5); $ncols = $#columns + 1; print " Standard2 Columns Requested: $ncols\n" if ($chatter >= 2); print " (".join(", ",@columns).")\n" if ($chatter >= 5); if (! defined($columns[0]) ) { die "ERROR: invalid PCU list '$pculist' or layer list '$layerlist' (PCUs must be in range 0-4 and layer list in range 1-3)"; } # Create column list file $colfile = "$outfile"."_cols.lis"; $atcolfile = "@"."$colfile"; open(COLUMNFILE,">$colfile") || die "ERROR: could not open '$colfile' for writing"; push @scratchfiles, $colfile; foreach $col (@columns) { print COLUMNFILE "$col\n"; } close(COLUMNFILE); print " (Column file $colfile ".((-f $colfile)?"found":"not found").")\n" if ($chatter >= 5); undef $ltcolums; undef $ltprefix; if ($deadcorrtype eq "LIVE") { $ltprefix = "LiveTimePcu"; } elsif ($deadcorrtype eq "ON") { $ltprefix = "OnTimePcu"; } if ($ltprefix) { $ltcolumns = join(",", map { "$ltprefix"."$_" } split(/,/,$pculist)); } &extract_lc($src_infile,$outfile,$binsz,$deadcorrtype,"Source",$pculist,$layerlist, $accumulate, $lcmode, $atcolfile, $ltcolumns, $gtiorfile, $gtiandfile, $timemin, $timemax, $timeint, $chmin, $chmax, $chbin, $chint, $lcbinarray, $gtiarray, $maxmiss, $gticols, $timecol, $obsdate, $obstime, $phasefile, $ephem, $period, $phaseint, $mfracexp, $mlcinten, $tnull, $timezero, $chatter); if ($bkg_infile) { my $bkgoutfile = "$outfile"."_bkg.lc"; push @scratchfiles, $bkgoutfile; &extract_lc($bkg_infile,$bkgoutfile,$binsz,$deadcorrtype,"Background",$pculist,$layerlist, $accumulate, $lcmode, $atcolfile, $ltcolumns, $gtiorfile, $gtiandfile, $timemin, $timemax, $timeint, $chmin, $chmax, $chbin, $chint, $lcbinarray, $gtiarray, $maxmiss, $gticols, $timecol, $obsdate, $obstime, $phasefile, $ephem, $period, $phaseint, $mfracexp, $mlcinten, $tnull, $timezero, $chatter); # OK, now we have a background file, paste the background values # to the main output file. $tmpfile = "$outfile"."_tmpbkg.lc"; $lccol = ($lcmode eq 'RATE')?'RATE':'COUNTS'; $colexpr = "BACKV = $lccol; ". "BACKE = ERROR; "; $cmd = "ftpaste ". "infile='$outfile' ". "pastefile='$bkgoutfile"."[col $colexpr]' ". "outfile='$tmpfile' ". "copyall=YES clobber=YES chatter=1 "; unlink($tmpfile); print " Attaching background to source light curve\n" if ($chatter >= 2); print "COMMAND: $cmd\n" if ($chatter >= 5); @results = `$cmd`; push @scratchfiles, "$tmpfile"; if ($? || ! -f "$tmpfile") { warn "Error reported by 'ftpaste'"; print "\nError Log\n========================================\n"; print @results; print "\n========================================\n"; die "ERROR: could not create '$tmpfile' (via ftpaste background to source)"; } if ($bkgsub) { $colexpr = "*;". "$lccol = $lccol - BACKV; ". "#TTYPE#(Background subtracted $lccol) = \"$lccol\"; ". "ERROR = SQRT(ERROR*ERROR + BACKE*BACKE); ". "#TTYPE#(Source & Bkg error in quadrature) = \"ERROR\"; ". "#BACKAPP(background is subtracted) = T; "; $cmd = "ftcopy ". "infile='$tmpfile"."[col $colexpr]' ". "outfile='$outfile' ". "copyall=YES clobber=YES chatter=1 "; unlink($outfile); print " Performing background subtraction\n" if ($chatter >= 2); print "COMMAND: $cmd\n" if ($chatter >= 5); @results = `$cmd`; if ($? || ! -f "$outfile") { warn "Error reported by 'ftcopy'"; print "\nError Log\n========================================\n"; print @results; print "\n========================================\n"; die "ERROR: could not create '$outfile' (via ftcopy background sub)"; } } else { # Not doing any background subtraction, so just rename output rename($tmpfile,$outfile); } } print " Done\n" if ($chatter >= 2); return $status; } sub extract_lc { my ($infile,$outfile,$binsz,$deadcorrtype,$srctype,$pculist,$layerlist, $accumulate, $lcmode, $columns, $ltcolumns, $gtiorfile, $gtiandfile, $timemin, $timemax, $timeint, $chmin, $chmax, $chbin, $chint, $lcbinarray, $gtiarray, $maxmiss, $gticols, $timecol, $obsdate, $obstime, $phasefile, $ephem, $period, $phaseint, $mfracexp, $mlcinten, $tnull, $timezero, $chatter) = (@_); my ($cmd, $tmpfile); my ($outroot, $extenlc); $outroot = "$outfile"; $extenlc = "_tmp.lc"; # Because saextrct stupidly can't take an outfile # Full name of dummy output file created by saextrct (will be renamed) $tmpfile = "$outroot"."$extenlc"; # Run SAEXTRCT and obtain spectrum without deadtime correction $cmd = "saextrct binsz='$binsz' ". "infile='$infile' ". "outroot='$outroot' extenlc='$extenlc' clobber='YES' ". "accumulate='$accumulate' printmode='LC' lcmode='$lcmode' ". "columns='$columns' ". "gtiorfile='$gtiorfile' gtiandfile='$gtiandfile' ". "timemin='$timemin' timemax='$timemax' timeint='$timeint' ". "chmin='$chmin' chmax='$chmax' chbin='$chbin' chint='$chint' ". "lcbinarray='$lcbinarray' gtiarray='$gtiarray' maxmiss='$maxmiss' ". "gticols='$gticols' timecol='$timecol' obsdate='$obsdate' obstime='$obstime' ". "phasefile='$phasefile' ephem='$ephem' period='$period' phaseint='$phaseint' ". "mfracexp='$mfracexp' mlcinten='INDEF' writesum='-' writemean='-' ". "tnull='$tnull' timezero='$timezero' ". "extenpha='.pha' multiple='NO' spmode='SUM' mspinten=INDEF ". "sensecase='NO' chkit='NO' negative='IGNORE' dryrun='NO' bailout='NO' "; print " Extracting raw $srctype light curve\n" if ($chatter >= 2); print "COMMAND: $cmd\n" if ($chatter >= 5); unlink($tmpfile); @results = `$cmd`; if ($? || ! -f "$tmpfile") { warn "Error reported by 'saextrct'"; print "\nError Log\n========================================\n"; print @results; print "\n========================================\n"; die "ERROR: could not create '$tmpfile'"; } # Rename to final output name push @scratchfiles, "$tmpfile"; rename($tmpfile, $outfile); if (($deadcorrtype eq "LIVE" || $deadcorrtype eq "ON") && $ltcolumns) { $outroot = "$outfile"; $extenlc = "_expo.lc"; # Because saextrct stupidly can't take an outfile # Full name of dummy output file created by saextrct (will be renamed) $ltfile = "$outroot"."$extenlc"; # Run SAEXTRCT and calculate live/on time value $cmd = "saextrct binsz='$binsz' ". "infile='$infile' ". "outroot='$outroot' extenlc='$extenlc' clobber='YES' ". "accumulate='ONE' printmode='LC' lcmode='SUM' ". "columns='$ltcolumns' ". "gtiorfile='$gtiorfile' gtiandfile='$gtiandfile' ". "timemin='$timemin' timemax='$timemax' timeint='$timeint' ". "chmin='INDEF' chmax='INDEF' chbin='INDEF' chint='INDEF' ". "lcbinarray='$lcbinarray' gtiarray='$gtiarray' maxmiss='$maxmiss' ". "gticols='$gticols' timecol='$timecol' obsdate='$obsdate' obstime='$obstime' ". "phasefile='$phasefile' ephem='$ephem' period='$period' phaseint='$phaseint' ". "mfracexp='$mfracexp' mlcinten='INDEF' writesum='-' writemean='-' ". "tnull='$tnull' timezero='$timezero' ". "extenpha='.pha' multiple='NO' spmode='SUM' mspinten=INDEF ". "sensecase='NO' chkit='NO' negative='IGNORE' dryrun='NO' bailout='NO' "; print " Extracting $srctype $deadcorrtype-time series\n" if ($chatter >= 2); print "COMMAND: $cmd\n" if ($chatter >= 5); &headas_clobberfile($ltfile); @results = `$cmd`; push @scratchfiles, "$ltfile"; if ($? || ! -f "$ltfile") { warn "Error reported by 'saextrct'"; print "\nError Log\n========================================\n"; print @results; print "\n========================================\n"; die "ERROR: could not create '$ltfile'"; } # Attach this column to the output light curve with ftpaste $ltcol = ($deadcorrtype eq "LIVE")? "LiveTime" : "OnTime"; $colexpr = "$ltcol = COUNTS; ". "#TTYPE#(PCU*seconds exposure) = \"$ltcol\"; ". "#TUNIT#(Physical unit of field) = \"s\"; ". "#TDISP#(Display format of field) = \"F10.3\"; "; $cmd = "ftpaste ". "infile='$outfile' ". "pastefile='$ltfile"."[col $colexpr]' ". "outfile='$tmpfile' ". "copyall=YES clobber=YES chatter=1 "; print " Attaching $srctype $deadcorrtype-time series\n" if ($chatter >= 2); print "COMMAND: $cmd\n" if ($chatter >= 5); unlink($tmpfile); @results = `$cmd`; push @scratchfiles, "$tmpfile"; if ($? || ! -f "$tmpfile") { warn "Error reported by 'ftpaste'"; print "\nError Log\n========================================\n"; print @results; print "\n========================================\n"; die "ERROR: could not create '$tmpfile' (via ftpaste)"; } # Now compute the live-time corrected $colexpr = "*; ". # Keep all original columns "TIME; ". "#TDISP# = \"F14.3\"; ". "FRACEXP; ". "#TDISP# = \"F7.5\"; "; $deadapp = ($deadcorrtype eq 'LIVE')?'T':'F'; $colexpr .= "#DEADAPP(deadtime correction applied?) = $deadapp;"; $colexpr .= "#BACKAPP(background subtracted?) = F;"; if ($lcmode eq 'RATE') { # Example: # If binsz=32 and we have a bin with 16 sec exposure, # old RATE = 100.0 # old FRACEXP = 0.5 # LiveTime = 15.87 # New rate will be, # = 100.0 / ( 15.87 / 32.0 / 0.5) # = 100.819 $colexpr .= "RATE = RATE / ($ltcol / $binsz / FRACEXP); ". "#TDISP# = \"F12.3\"; ". "ERROR = ERROR / ($ltcol / $binsz / FRACEXP); ". "#TDISP# = \"F12.3\"; "; } else { $colexpr .= "COUNTS; ". # Note that counts don't change "#TDISP# = \"F12.3\"; ". "ERROR; ". # Error doesn't change either "#TDISP# = \"F12.3\"; ". "FRACEXP = $ltcol / ($binsz);". "#TTYPE#(NUM_PCU_ON*FRACEXP) = \"FRACEXP\";"; } $cmd = "ftcopy ". "infile='$tmpfile"."[col $colexpr]' ". "outfile='$outfile' ". "copyall=YES clobber=YES chatter=1 "; print " Correcting $srctype for $deadcorrtype-time\n" if ($chatter >= 2); print "COMMAND: $cmd\n" if ($chatter >= 5); unlink($outfile); @results = `$cmd`; if ($? || ! -f "$outfile") { warn "Error reported by 'ftcopy'"; print "\nError Log\n========================================\n"; print @results; print "\n========================================\n"; die "ERROR: could not create '$outfile' (via ftcopy livetime)"; } # Whew! done with live time correction } return; } # # parse_pcus_columns # $pculist - input list of PCUs or "ALL" # $layerlist - input list of layers or "ALL" # sub parse_pcus_columns { my ($pculist,$layerlist) = (@_); my (@pcus, @layers); my ($pcu, $layer); my (@columnlist); if ($pculist =~ m/^all$/i) { $pculist = "0,1,2,3,4"; } if ($pculist =~ m/^(\d+)-(\d+)$/) { $pculist = join(",",($1 .. $2)); } if ($layerlist =~ m/^all$/i) { $layerlist = "1,2,3"; } if ($layerlist =~ m/^(\d+)-(\d+)$/) { $layerlist = join(",",($1 .. $2)); } @pcus = split(/,/,"$pculist"); @layers = split(/,/,"$layerlist"); foreach $pcu (@pcus) { die "ERROR: PCU list must be in range 0-4" if ($pcu < 0 || $pcu > 4); return undef if ($pcu !~ m/^[0-4]$/); foreach $layer (@layers) { if ($layer =~ m/^[1-3]$/) { die "ERROR: layer list must be in range 1-3" if ($layer < 1 || $layer > 3); push @columnlist, "X".$layer."LSpecPcu".$pcu; push @columnlist, "X".$layer."RSpecPcu".$pcu; } elsif ($layer =~ m/^X[1-3][LR]$/) { push @columnlist, $layer."SpecPcu".$pcu; } else { die "ERROR: unrecognized layer $layer"; } } } # Return normalized pculist and layerlist $_[0] = $pculist; $_[1] = $layerlist; return @columnlist; }