Aaron Barth's perl script
to extract lines from a grid of models
#!/usr/local/bin/perl -w
# This routine shows how to make a table of emission-line strengths
# from the output files generated by the runcloudy program. The line
# strengths relative to H-beta are compiled from the values saved in
# the .out files. In general, it would be straightforward to write
# perl scripts to compile any desired output parameters from the
# results of any grid of models; this is just one simple example.
# First, open a filehandle for the file which will contain the table
# of fluxes. The ">" before the filename tells perl that any argument
# to the "print FLUXTABLE" command will be appended to the file
# fluxes.tbl. If a file already exists with the name fluxes.tbl, it
# will be clobbered when the "open" command is executed.
open (FLUXTABLE, ">fluxes.tbl") || die "Can't open output file: $!";
# Select lines to put in table. This list can have an arbitrary
# number of entries, and each emission line will come out in its own
# column in the fluxes.tbl file. The strings listed here must be
# exactly identical to the emission-line names given in the .out file.
# In perl, array names begin with the @ character, so this means that
# @linelist will be an array of strings rather than a single string.
@linelist = ("TOTL 1216",
"TOTL 4861",
"TOTL 6563",
"Si 2 1808",
"C 2 2326",
"C 3 977",
"N 2 6548"
);
# The variable $nlines gets the number of elements in @linelist.
$nlines = @linelist;
# We need to create a format statement to format the output that gets
# sent to fluxes.tbl. Since the number of columns in the table is
# variable, and depends on the number of entries in @linelist, we need
# to do something a bit tricky to generate an appropriate format on
# the fly. The trick is to create a string variable $format whose
# value is the format statement we want to evaluate, and then realize
# that format with the "eval $format" command. For basic information
# on how to set up a format statement, consult any introductory perl book.
$format = "format FLUXTABLE = \n"
. "@<<<<< @<<<<< " . ("@<<<<<<<< " x $nlines) . "\n"
. "\$ion, \$n, \@f \n"
. ".\n";
eval $format;
die $@ if $@;
# Now that we've set up a format we can write data to the table.
# Here's how this happens: note that in the format statement above,
# the third line contains the variable names $ion, $n, and @f. This
# means that whenever we execute a "write FLUXTABLE" command, the
# current values of these variables get written to the table in the
# format we've just defined. For starters, we need to write a line of
# column headers to the table, so we'll set these variables to the
# strings we want as the column headers and write them to the table.
$ion = "log U";
$n = "log n";
@f = @linelist;
write FLUXTABLE;
# Now, we loop over the grid variables exactly as in the runcloudy
# routine, and for each set of variables, we want to get the line
# strength relative to H-beta from the .out file. For each emission
# line, call the "getline" subroutine to get the line strength, and
# put the line strengths into the @f array. When all line strengths
# have been retrieved for a given set of grid parameters, write the
# results to the FLUXTABLE. Note that when addressing the $j-th
# element of the array @f, we use the syntax $f[$j]. The @ symbol is
# only used when referring to the array as a whole, not for addressing
# individual elements. The counter $j below loops over the elements
# in the @linelist array, and the subroutine getline is called for
# each line in the list, for each set of grid parameters.
for ($i = 3; $i <= 4; $i++) {
$ion = -1 * $i;
for ($n = 3; $n <= 4; $n++) {
$outfile = "nlr-$i-$n.out";
for ($j = 0; $j <= $nlines-1; $j++){
$f[$j] = getline($outfile, $linelist[$j]);
}
write FLUXTABLE;
}
}
close (FLUXTABLE);
# End of main routine.
#--------------------------------------------------------------------
# Subroutine getline returns the specified line flux relative to
# H-beta from the cloudy output (.out) file. If this line doesn't
# appear in the output file, the routine returns the value 0.0.
# We pass this subroutine the name of the output file and the string
# containing the name of the emission line, which are stored locally
# in the variables $filename and $linename. The "my" command
# indicates that these variables are local to this subroutine, and the
# array @_ indicates the list of values passed to the subroutine.
sub getline {
my($filename, $linename) = @_;
# Open the file $filename for reading; die if it doesn't exist.
open (OUTFILE, $filename) ||
die "Can't open $outfile: $!";
# Now we basically want to do a "grep" to find the desired emission
# line in the file OUTFILE. We can do this with a "while" loop as
# shown below. Text enclosed in /slashes/ is a "regular expression"
# used for pattern matching. The "last" statement breaks out of the
# loop once a match is found. Before searching for the line name,
# we'll scroll down the OUTFILE to the line where the list of emission
# lines begins by searching for the pattern /Emission Line Spectrum./.
# We do this because some emission line names can occur in the .out file
# prior to the actual list of line strengths.
while (<OUTFILE>) {
if (/Emission Line Spectrum./) {
last;
}
}
# Search for the line of text containing the desired emission line.
# If we find it, store the entire line in the variable $fluxstr.
$fluxstr = "";
while (<OUTFILE>) {
if (/$linename/) {
$fluxstr = $_;
last;
}
}
# If $fluxstr is blank, then the line wasn't found; return the value
# 0.0 to the main routine. Otherwise, extract the substring
# containing the emission-line flux, and return that value.
if ($fluxstr eq "") {
print "Line $linename not found in $filename.\n";
$flux = " 0.0000";
} else {
$startpos = index($fluxstr, $linename);
$flux = substr($fluxstr,$startpos+17,8);
}
close (OUTFILE);
return $flux;
}
# by A. Barth, abarth@cfa.harvard.edu