#! /bin/sh # This is the LHEA perl script: pcarsp # 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 pcarsp." exit 3 elif [ "$LHEAPERL" = noperl ]; then echo "During LHEA initialization, no acceptable version of Perl was found." echo "Cannot execute script pcarsp." 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 exec $LHEAPERL -x $0 ${1+"$@"} fi ' if(0); # Do not delete anything above this comment from an installed LHEA script! #------------------------------------------------------------------------------- #! /usr/bin/perl # J. Lochner: initial version Nov 20, 1995 # Perl script for creating XTE PCA response matrices # # 19Oct00 (MJT) short-circuited "short cut" so that pcarmf # is never called with lld=63 (workaround for # bug in pcarmf 7.0.1) require "utils.pl"; require "interface.pl"; require "getopts.pl"; &Getopts('f:a:c:l:p:d:j:m:n:e:x:y:zh'); # # Output the help if -h is specified # if (defined $opt_h) { print <. "Input the Attitude file: " - the name of the file containing the spacecraft pointings for the observation. This file may be either the XTE FILTER file, or the estimated quaternions ("FH0e_*"), either of which may be obtained via the XTE Data Finder (XDF). This may also be of the form \@filename for an ascii file containing the name of the attitude file. Finally, a value of 'none' may be used when the attitude file is unavailable or inadequate. With 'none' the resulting rsp file will assume an on-axis pointing to the target. Command line option: -a . "Input the layers included in the PHA file [L1,R1,LR1, etc, or all] " - The layers included in the input pha file. The user may input halves of particular layers (e.g. L1,R1) or combined halves (e.g. LR1 for layer 1). Command line option: -l . "Are the layers added ? [y/n]: " - whether the pcu detector layers have been added in creating the .pha file. If yes, then detector response matrices will be constructed. If no, then a separate response matrix for each requested layer will be constructed. As a special case, if all layers are included and added, then a single detector response matrix is created for each desired detector. Command line option: -j . "Input the detectors included in the PHA file [0,1,2,3,4, or all]: " - The detectors included in the input pha file. A range may be given, e.g. 0-2,4. Command line option: -p . (NOTE: "all" will not work as a command line option here: use 0-4) "Are the detectors added ? [y/n]: " - whether the detectors have been added in creating the input pha file. If yes, a single response matrix is produced from the sum of the requested detectors. The yes option is appropriate only for Type I pha files containing a single spectrum. If no, the detector matrices are left separate. The no option is appropriate for Type II pha files containing multiple spectra. Command line option: -m . Files created by the script are named by pcu number, a layer id ("xe" if entire detector), and the date (yyyy-mm-dd) of the observation. Through the -n command line option, the user may specify an alternate name for the final output file instead of using the default. Note that this applies only when the product of the script is a single matrix. The only files needed by XSPEC are certain .rsp files. The user has the option to retain or delete the .arf, .rmf, .txt, and unnecesarry .rsp files created by the script. Additional command line options: pcarsp -n -d -e -x -y -c -z -n : The user may specify the name of the final response matrix instead of using the default name. Note that this applies only when a single matrix results from the script (e.g. when the detectors are added). -d : The user may specify the date for which the matrices should be created, in the format yyyy-mm-dd. By default, matrices are created for the observation date contained in the pha file. -e : The user may specify either a local calibration file or \"caldb\" for the energy-to-channel conversion rather than using the (new as of v2.43) default of finding an appropriate file in the refdata directory. -x : The user may specify an alternate right ascension for the source position. By default, matrices are created using the object\'s ra contained in the pha file. -y : The user may specify an alternate declination for the source position. By default, matrices are created using the object\'s declination contained in the pha file. -c : The user may input the partial charge fraction to be used when computing the matrix. A non-zero value affects the shape of lines in the spectrum. It\'s default value here is 0.0, but when used, the PCA team recommends a value of 0.001. -z : The user may keep unnecessary intermediate files created by the script by specifying this option. Default is to delete the files. EOHELP1 exit; } print "PCARSP V2.43a - Ready to go !\n"; if (defined $opt_f) { print "\nInput PHA file: $opt_f \n"; $pha = $opt_f; } else { print "\nInput PHA file: "; chop($pha=); } if (defined $opt_a) { print "\nInput Attitude file: $opt_a \n"; $qfile = $opt_a; } else { print "\nInput the Attitude file: "; chop($qfile=); } if (defined $opt_l) { print "\n Layers included in PHA file: $opt_l \n"; @layer_id = &split_line($opt_l); } else { @layer_id = &getarray("\nInput the layers included in the PHA file [L1,R1,LR1, etc, or all; P for propane] "); } # change to upper case and remove any leading/trialing blanks for ($i=0; $i <= @layer_id-1; $i++) { $layer_id[$i] = "\U$layer_id[$i]"; $layer_id[$i] =~ s/ //g; } if (defined $opt_j) { print "\nLayers added ? $opt_j \n"; $add_layers = $opt_j; } else { print "\nAre layers added ? [y/n]: "; chop($add_layers=); } if (defined $opt_p) { print "\nDetectors in PHA file: $opt_p \n"; @det_id = &parse_range($opt_p,4); } else { @det_id = &get_detectors("\nInput the detectors included in the PHA file [0,1,2,3,4, or all]: ",4); } if (defined $opt_m) { print "\nDetectors added ? $opt_m \n"; $det = $opt_m; } else { print "\nAre detectors added ? [y/n]: "; chop($det=); } # # Get the date of the observation from the pha file or the -d input # if (defined $opt_d) { $now = $opt_d; } else { $now = &phadate($pha); } print "Responses will be created for date (yyyy-mm-dd) = ".$now."\n"; # # Check for gain epoch 4 and bail-out if so (12 Oct 1999) # (starts at 3/22/99 17:39:00 UT {sez PCA Digest Page}) # #if ($now gt '1999-03-22') { # print "PCARSP currently unable to handle gain epoch 4 -- aborting\n\n"; # exit; #} # Set up gain epoch boundaries # 3/21/96 18:33:39 UT begins epoch2 # 4/15/96 23:05:59 UT begins epoch3 # 3/22/99 17:38:03 UT begins epoch4 $boundepoch12 = '1996-03-21'; $boundepoch23 = '1996-04-15'; $boundepoch34 = '1999-03-22'; $epoch = 0; if ($now lt $boundepoch12) {$epoch = 1} if ($now gt $boundepoch12 and $now lt $boundepoch23) {$epoch = 2} if ($now gt $boundepoch23 and $now lt $boundepoch34) {$epoch = 3} if ($now gt $boundepoch34) {$epoch = 4} if ($epoch == 0) { print "Ambiguity in gain epoch assignment\n"; print "Exact boundaries are:\n"; print " 1996-03-21 18:33:39 UT begins epoch 2\n"; print " 1996-04-15 23:05:59 UT begins epoch 3\n"; print " 1999-03-22 17:38:03 UT begins epoch 4\n"; print "Please rerun pcarsp using the \"-d\" option\n"; print "to shift the date by one day in either direction\n"; print "to unambiguously fall into the desired gain epoch\n"; exit; } print "(gain epoch ".$epoch.")\n\n"; # # Read the e2c file option # if (defined $opt_e) { $e2c = $opt_e; } else { # $e2c = 'caldb'; # 13Jan00 - new default is to look in LHEA_DATA for latest version # of the e2c file for the correct epoch. If the "-e" option # is used to specify a file, however, NO CHECKING IS DONE! # opendir(DATDH,"$ENV{'LHEA_DATA'}"); @e2cfiles = sort grep(/^pca_e2c_/,readdir(DATDH)); closedir(DATDH); $e2c = "$ENV{'LHEA_DATA'}/".pop @e2cfiles; $epoch_pos = index $e2c,"pca_e2c_e"; $e2c_epoch = substr $e2c,$epoch_pos+9,2; if ($e2c eq "$ENV{'LHEA_DATA'}/") { # ie, no files found at all print "No PCA energy-to-channel files found in \n".$ENV{'LHEA_DATA'}."/\n"; print "Try using the \"-e filename\" option to specify the location of\n"; print "an up-to-date e2c file or \"-e caldb\" to specify the CALDB\n"; exit; } if ($e2c_epoch < $epoch) { print "Latest PCA energy-to-channel file \n(".$e2c.")\nis not applicable. "; print "Check the RXTE-GOF web site or\nwrite xtehelp\@athena.gsfc.nasa.gov "; print "for an up-to-date e2c file.\n"; exit; }; } # # Read the ra file option # if (defined $opt_x) { $ra = $opt_x; } else { $ra = 'INDEF'; } # # Read the dec file option # if (defined $opt_y) { $dec = $opt_y; } else { $dec = 'INDEF'; } # # Read the partial charge collection value # if (defined $opt_c) { $pcc = $opt_c; } else { $pcc = 0.0; } # # Create the detector and layer arrays for the "all" options # if ($det_id[0] eq "all" || $det_id[0] eq "ALL") { @det_id = (0,1,2,3,4); } $num_det = @det_id; if ($layer_id[0] eq "ALL") { @layer_id = ("L1","R1","L2","R2","L3","R3"); $all_layers = "y"; $layerlist = "xe"; } else { $layerlist = ""; for ($j=0; $j <= @layer_id-1; $j++){ $layerlist = $layerlist.$layer_id[$j]; } } $num_layers = @layer_id; # # Read Channel Descriptor, checking for gain/offset values, if necessary # $gcor = 0; print "reading channel descriptor from pha file:\n"; print ' rddescr '.$pha.' chan.txt'."\n"; @result=&runcom('rddescr "'.$pha.'" chan.txt'); if ($result[0] =~ ERROR) {die "RDDESCR failed ($result[0])";} print $result[1],"\n"; $j = @result; for ($i=0; $i<=$j-1; $i++) { if ($result[$i] =~ /GCORRMF/) {$gcor = 1} if ($result[$i] =~ /Unable to write/) {$gcor = -1} } if ($gcor == -1) { print "Gain & Offset values not found in input pha file\n"; print " Running PCAGAINSET tool on ".$pha."\n"; @result=&runcom('pcagainset "'.$pha.'" caldb'); print @result,"\n"; print "re-reading channel descriptor\n"; @result=&runcom('rddescr "'.$pha.'" chan.txt'); print $result[1],"\n"; $j = @result; for ($i=0; $i<=$j-1; $i++) { if ($result[$i] =~ /GCORRMF/) {$gcor = 1} if ($result[$i] =~ /Unable to write/) { print "unsuccessful with second try\n"; exit; } } } open(RSPLIST, "> rsp.txt"); # # Try Short cut (if all layers requested and added) # $never_true = "false"; # workaround pcarmf bug /19Oct00/ (MJT) if ($add_layers eq "y" && $all_layers eq "y" && $never_true eq "true") { $lld = 63; $create_arf = 1; print "\n"; for ($k= 0; $k <= $num_det-1; $k++) { @result = &matrix($now, "xe", $lld, $det_id[$k], $qfile, $gcor, $create_arf, $pcc); print RSPLIST $result[0]." 1.0 \n"; } } else { # # Resort to the long way for all other cases # # Initialize the associative array for the layer id's and lld codes %lld = ("L1",1,"R1",2,"LR1",3,"L2",4,"R2",8,"LR2",12,"L3",16,"R3",32,"LR3",48,"P",64); # Initialize a file which records all the layer matrices which are created open (ALL_LAYERS, "> all_layers.txt"); # Create response matrices for each desired layer, creating one arf per detector for ($k = 0; $k <= $num_det-1; $k++) { $create_arf = 1; open(LAYERLIST, "> layers.txt"); for ($j=0; $j <= $num_layers-1; $j++){ # print "pcu = ".$det_id[$k].", layer = ".$layer_id[$j].", lld code = ".$lld{$layer_id[$j]}."\n"; @result = &matrix($now, $layer_id[$j], $lld{$layer_id[$j]}, $det_id[$k], $qfile, $gcor, $create_arf, $pcc); print LAYERLIST $result[0]." 1.0 \n"; print ALL_LAYERS $result[0]."\n"; $create_arf = 0; } close(LAYERLIST); # Add layer matrices into detector matrices, or create a list of layer matrices. if ($add_layers eq "y" && $num_layers gt 1) { if ($det ne "y" && defined $opt_n) { $detrsp = $opt_n; } else { $detrsp = "p".$det_id[$k]."_".$layerlist."_".$now.".rsp"; } print "\nReady to add the layer rsp's into detector matrix ".$detrsp."\n"; print "using the command: \n"; print ' addrmf @layers.txt rmffile='.$detrsp."\n\n"; @result=&runcom('addrmf @layers.txt rmffile="'.$detrsp.'"'); print RSPLIST $detrsp." 1.0 \n"; if ($result[0] =~ ERROR) {die "ADDRMF failed ($result[0])";} } else { open (LAYERLIST,"layers.txt"); while() { print RSPLIST $_; } close(LAYERLIST); } } close(ALL_LAYERS); } # Add detector matrices, if desired close(RSPLIST); if ($det eq "y") { if (defined $opt_n) { $pcarsp = $opt_n ; } else { if ($num_det eq 5) { $pcarsp = "pca_".$layerlist."_".$now.".rsp"; } else { $pcu_tag = "p"; for ($i=0; $i<=$num_det-1; $i++) { $pcu_tag = $pcu_tag.$det_id[$i]; } $pcarsp = $pcu_tag."_".$layerlist."_".$now.".rsp"; }} print "\nReady to add the detector rsp's using the command:\n"; print ' addrmf @rsp.txt rmffile='.$pcarsp."\n"; @result=&runcom('addrmf @rsp.txt rmffile="'.$pcarsp.'"'); if ($result[0] =~ ERROR) {die "ADDRMF failed ($result[0])";} # Set the value of the RESPFILE keyword @result=&runcom('fparkey "'.$pcarsp.'" "'.$pha.'" RESPFILE'); # otherwise include the list of matrices in a RESPFILE column in the .pha file. } else { print "Ready now to include list of rsp files into .pha file\n"; # Special case when there is just one detector - use RESPFILE keyword if ($num_det == 1) { open(RSPLIST,"rsp.txt"); chop($pcarsp = ); $s = index($pcarsp,"rsp"); $pcarsp = substr($pcarsp,0,$s+3); # change the name for single detector, single layer, if necessary if ($num_layers eq 1 && defined $opt_n) { system("mv $pcarsp $opt_n"); $pcarsp = $opt_n; } @result=&runcom('fparkey "'.$pcarsp.'" "'.$pha.'" RESPFILE'); close(RSPLIST); } else { # Normal case: write file names to RESPFILE column, deleting # the RESPFILE header keyword, open (COLUMNS, "> col.txt"); print COLUMNS "RESPFILE 25A\n"; close (COLUMNS); @result=&runcom('fcreate col.txt rsp.txt !rsp.fits'); print @result,"\n"; @result=&runcom('faddcol infile="'.$pha.'" colfile="rsp.fits" colname="RESPFILE" delkey="yes" history="yes" casesen="no"'); print @result,"\n"; if ($result[0] =~ ERROR) {die "FADDCOL failed ($result[0])";} } } # Offer clean-up option if (defined $opt_z) { $cleanup = 'n'; } else { $cleanup = 'y'; # print "\nClean-up unnecessary files ? (y/n): "; # chop($cleanup=); } if ($cleanup eq "y") { system("rm -f *$now.arf"); system("rm -f *$now*.rmf"); system("rm -f layers.txt chan.txt modhead.txt"); system("rm -f col.txt") if -e col.txt; system("rm -f *shft.txt") if -e pcu0_shft.txt; system("rm -f rsp.fits") if -e rsp.fits; if ($det eq "y") { open(RSPLIST,"rsp.txt"); while() { system("rm -f $_"); } close(RSPLIST); } system("rm -f rsp.txt"); if ($add_layers eq "y") { open(ALL_LAYERS,"all_layers.txt"); while() { system("rm -f $_"); } close(ALL_LAYERS); } system("rm -f all_layers.txt"); } print "all done\n"; sub matrix { local($now,$slld,$lld,$pcu,$qfile,$gcor,$create_arf,$pcc) = @_; # # Define the file names # $file = "p".$pcu."_".$slld."_".$now; $rmf256 = $file."_256.rmf"; $shft256 = $file."_shft.rmf"; $rmf = $file.".rmf"; $arf = "p".$pcu."_xe_".$now.".arf"; $rsp = $file.".rsp"; if ($slld eq "xe") { print "Here are the files to be created for pcu".$pcu.":\n"; } else { print "Here are the files to be created for pcu".$pcu.", anode chain ".$slld.":\n"; } print " 256 channel rmf file - ".$rmf256."\n"; print " the (optional) shifted rmf - ".$shft256."\n"; print " the rebinned rmf file - ".$rmf."\n"; print " the computed arf file - ".$arf."\n"; print " the detector rsp file - ".$rsp."\n"; print "\nReady to Construct ".$rmf256." using the command:\n"; print ' pcarmf outfile="'.$rmf256.'" pcuid="'.$pcu.'" lld_code="'.$lld.'" e2cfile="'.$e2c.'" scale_hack=0 cdate="'.$now.'" pcc_coeff="'.$pcc.'" chatter=10 clobber=yes'."\n"; @result=&runcom('pcarmf outfile="'.$rmf256.'" pcuid="'.$pcu.'" lld_code="'.$lld.'" e2cfile="'.$e2c.'" scale_hack=0 cdate="'.$now.'" pcc_coeff="'.$pcc.'" chatter=10 clobber=yes'); print @result,"\n"; if ($result[0] =~ ERROR) {die "PCARMF failed ($result[0])";} if ($gcor == 1) { print "\nReady to apply gain correction using the command: \n"; $shft = "pcu".$pcu."_shft.txt"; print ' gcorrmf infile="'.$rmf256.'" shftfile="'.$shft.'" outfile="'.$shft256.'" clobber=yes'."\n"; @result = &runcom('gcorrmf infile="'.$rmf256.'" shftfile="'.$shft.'" outfile="'.$shft256.'" clobber=yes'); print @result,"\n"; if ($result[0] =~ ERROR) {die "GCORRMF failed ($result[0])";} } else {$shft256 = $rmf256} print "\nReady to rebin ".$shft256." using the command:\n"; print ' rbnrmf infile="'.$shft256.'" ebdfile="%" binfile="chan.txt" nchan="" cmpmode=".linear." outfile="'.$rmf.'" fchan=0 chatter=5 clobber=yes mode=".ql."'."\n"; @result=&runcom('rbnrmf infile="'.$shft256.'" ebdfile="%" binfile="chan.txt" nchan="" cmpmode=".linear." outfile="'.$rmf.'" fchan=0 chatter=5 clobber=yes mode=".ql."'); print @result,"\n"; if ($result[0] =~ ERROR) {die "RBNRMF failed ($result[0])";} # Construct arf file only once per detector if ($create_arf) { print "\nReady to construct ".$arf." using the command: \n"; print ' xpcaarf phafil="'.$pha.'" rmffil="'.$rmf.'" arffil="'.$arf.'" xtefilt="'.$qfile.'" collcube=caldb pcu="'.$pcu.'" ra="'.$ra.'" dec="'.$dec.'" clobber=yes'."\n"; @result=&runcom('xpcaarf phafil="'.$pha.'" rmffil="'.$rmf.'" arffil="'.$arf.'" xtefilt="'.$qfile.'" collcube=caldb pcu="'.$pcu.'" ra="'.$ra.'" dec="'.$dec.'" clobber=yes'); print @result,"\n"; if ($result[0] =~ ERROR) {die "XPCAARF failed ($result[0])";} } print "\nReady to Construct ".$rsp." using the command: \n"; print ' marfrmf rmfil="'.$rmf.'" arfil="'.$arf.'" outfil="'.$rsp.'" clobber=yes'."\n"; @result=&runcom('marfrmf rmfil="'.$rmf.'" arfil="'.$arf.'" outfil="'.$rsp.'" clobber=yes'); print @result,"\n"; if ($result[0] =~ ERROR) {die "MARFRMF failed ($result[0])";} $rsp; } sub get_detectors { # Queries for, and returns an array of integers giving the chosen elements # from an input array of the form: 1-3,6,7-10. local($inputline,$maxrange) = @_; print $inputline; chop($range = ); if ($range ne "all" && $range ne "ALL") { @range = &parse_range($range,$maxrange); if( $range[0] == -10 ) { @range = &get_detectors($inputline,$maxrange); } else { @range; } } else { @range = $range; } } sub write_history { # Copy the HISTORY keywords from input file (rmf or rsp) to the output # rsp file # For version 2.4, this routine is no longer used. Calls to this # have been deleted. local($infile,$rsp) = @_; open (MODHEAD, "> modhead.txt"); print MODHEAD "HISTORY History of I/p RMF file: ".$infile."\n"; close (MODHEAD); @result=&runcom('fmodhead "'.$rsp.'" modhead.txt'); print @result,"\n"; @result=&runcom('fkeyprint infile="'.$infile.'[1]" keynam="HISTORY" outfile="modhead.txt" exact="no" clobber="yes"'); print @result,"\n"; @result=&runcom('fmodhead "'.$rsp.'" modhead.txt'); print @result,"\n"; } sub phadate { # get the DATE-OBS value from the Spectrum extension of the PHA file # Parse its format (dd/mm/yy or yyyy-mm-ddThh:mm:ss) into yyyy-mm-dd local($i,$x,$phafile,$phaobs,$day,$month,$year,$phadate); $phafile = @_[0]; @result=&runcom('fkeyprint infile="'.$phafile.'[1]" keynam="DATE-OBS" outfile="STDOUT" exact="no" clobber="yes"'); for ($i=0;$i <= @result; $i++) { if ($result[$i] =~ /DATE-OBS/) {$phaobs = $result[$i]} } $x = index($phaobs,"'"); if (index($phaobs,"-",$x) == -1) { $day = substr($phaobs,$x+1,2); $month = substr($phaobs,$x+4,2); $year = substr($phaobs,$x+7,2); if ($year > 90) {$year = '19'.$year} $phadate = $year.'-'.$month.'-'.$day; } else { $phadate = substr($phaobs,$x+1,10); } }