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