# <<BEGIN-copyright>>
# <<END-copyright>>
"""
This module contains classes for dealing with a bdfls file and its contents.
"""
import os
import string
from PoPs.groups import misc as chemicalElementMiscPoPsModule
from fudge.core import fudgemisc
from fudge.core.utilities import fudgeFileMisc, subprocessing
from fudge.vis.gnuplot import plotbase
default_bdfls = None
# set default bdfls file path
_BDFLS_FILE_ = "/usr/gapps/data/nuclear/bdfls"
bdfls_EOD = " 1\n"
bdfls_mh_EOD = " 999999 1\n"
[docs]def targetToZA( za ) :
"""This routine converts an integer or string into a ZA (e.g., "FissionProductENDL99120" to 99120)."""
try :
iza = int( za )
except :
if( type( za ) == ( type( '' ) ) ) :
if( za[:2] == 'za' ) :
iza = int( za[2:8] )
elif( za[:18] == 'FissionProductENDL' ) :
iza = int( za[18:] )
else :
if( '_' in za ) :
ZA, suffix = za.split( '_' )
else :
ZA, suffix = za, None
if( suffix == 'natural' ) :
Z = ZA
A = 0
else :
for i, s in enumerate( za ) :
if( s.isdigit( ) ) : break
Z, A = za[:i], za[i:]
try :
iza = 1000 * chemicalElementMiscPoPsModule.ZFromSymbol[Z] + int ( A )
except :
raise Exception( 'Could not handle za = %s.' % `za` )
else :
raise Exception( 'za = "%s" cannot be converted into an integer' % `za` )
return( iza )
[docs]class bdfls :
"""This class reads in a bdfls file."""
def __init__( self, name = None, template = None ) :
"""Reads in the bdfls file give by template. If self's save is called with name = None,
then this methods name is used as the output bdfls file's name."""
if ( template is None ) :
if ( os.path.exists( "./bdfls" ) ) :
template = "./bdfls"
else :
if( 'BDFLSPATH' in os.environ ) :
template = os.environ[ 'BDFLSPATH' ]
elif os.path.exists( _BDFLS_FILE_ ):
template = _BDFLS_FILE_
else:
template = os.path.split(__file__)[0] + os.sep+ 'bdfls'
if ( not os.path.exists( template ) ) : raise IOError( "\n Error in bdfls.__init__: bdfls file does not exist\n %s" % template )
self.name = name
if ( name is None ) : self.name = "./" + template.split( "/" )[-1]
self.template = template
self.g = []
self.f = []
self.m = []
self.massFormat = 'old'
self.h = []
self.c = []
self.t = []
self.s = []
self.read( template )
def __repr__( self ) :
"""Returns a string that summarizes the information in this class."""
s = "File name = %s\n" % self.name
s += "Template file = %s\n" % self.template
s += " Group data\n"
for g in self.g : s += " id = %4d groups = %4d boundaries = %d\n" % ( g.id, g.n - 1, g.n )
s += " Flux data\n"
for f in self.f : s += " id = %4d lMax = %d\n" % ( f.id, f.lMax )
s += " There are %s masses\n" % len( self.m )
s += " There are %s halflifes\n" % len( self.h )
s += " There are %s constants\n" % len( self.c )
s += " Temperature data\n"
for t in self.t : s = s + " id = %4d n = %d\n" % ( t.id, t.n )
s += " There are %s subshell designators\n" % len( self.s )
return s
[docs] def addGroup( self, ebs, id, label = "", overwrite = 0 ) :
"""Adds the group with id to self's list of groups. ebs is a python list
of numbers and label is the groups label (see class bdfls_group). If overwrite
is false, a raise is triggered if self already contains group with id, else
the old one is overwritten."""
pos = None
for i in range( len( self.g ) ) :
if( self.g[i].id == id ) :
if( overwrite ) :
del self.g[i]
pos = i
break
else :
raise Exception( "\nError in bdfls.addGroup: group with id = %d already exist" % id )
elif( self.g[i].id > id ) :
pos = i
break
g = bdfls_group( ebs )
g.n = len( ebs )
g.id = id
g.label = label
g.name = 'LLNL_gid_%d' % g.id
if( pos is None ) :
self.g.append( g )
else :
self.g.insert( pos, g )
[docs] def addFlux( self, EF_ls, id, label = "", overwrite = 0 ) :
"""Adds the flux with id to self's list of fluxes. EF_ls is a python list
with the following structure:
[
[ [E0, f0], [E1, f1], ... ], # for l = 0
[ [E0, f0], [E1, f1], ... ], # for l = 1
...
]
and label is the flux's label (see class bdfls_flux). If overwrite
is false, a raise is triggered if self already contains group with id, else
the old one is overwritten."""
pos = None
for i in range( len( self.f ) ) :
if( self.f[i].id == id ) :
if( overwrite ) :
del self.f[i]
pos = i
break
else :
raise Exception( "\nError in bdfls.addFlux: flux with id = %d already exist" % id )
elif( self.f[i].id > id ) :
pos = i
break
f = bdfls_flux( EF_ls )
f.id = id
f.label = label
f.name = 'LLNL_fid_%d' % f.id
if( pos is None ) :
self.f.append( f )
else :
self.f.insert( pos, f )
[docs] def addZA( self, za, mass, halflife, warning = 1 ) :
"""Calls addZAHalflife with halflife and addZAMass with mass."""
self.addZAHalflife( za, halflife, warning )
self.addZAMass( za, mass, warning )
[docs] def addZAHalflife( self, za, halflife, warning = 1 ) :
"""Adds or changes the halflife for ZA. If warning is true and ZA is already in self's halflife list,
then a warning message is printed."""
i = 0
for h in self.h :
if ( h.za == za ) :
if ( warning ) : fudgemisc.printWarning( "changing halflife for za = %d from %s to %s" % ( za, `h.halflife`, `halflife` ) )
h.halflife = halflife
return
elif ( h.za > za ) :
self.h.insert( i, bdfls_halflife( za, halflife ) )
return
i += 1
[docs] def addZAMass( self, za, mass, warning = 1 ) :
"""Adds or changes the mass for ZA. If warning is true and ZA is already in self's mass list,
then a warning message is printed."""
i = 0
for m in self.m :
if ( m.za == za ) :
if ( warning ) : fudgemisc.printWarning( "changing mass for za = %d from %s to %s" % ( za, `m.mass`, `mass` ) )
m.mass = mass
return
elif ( m.za > za ) :
self.m.insert( i, bdfls_mass( za, mass, format = self.massFormat ) )
return
i += 1
[docs] def flux( self, id ) :
"""Returns the flux that matches id."""
if( type( id ) == type( 1 ) ) :
for f in self.f :
if( f.id == id ) : return f
else :
for f in self.f :
if( f.name == id ) : return f
raise Exception( "\nError in bdfls.flux: id does not exist (%s)" % id )
[docs] def group( self, id ) :
"""Returns the group that matches id."""
if( type( id ) == type( 1 ) ) :
for g in self.g :
if( g.id == id ) : return g
else :
for g in self.g :
if( g.name == id ) : return g
raise Exception( "\nError in bdfls.group: id does not exist (%s)" % id )
[docs] def subGroups( self, id ) :
"""Returns the sub-group ids for group id."""
subgs = []
for g in self.g :
if( g.id == id ) : continue
if( self.isSubGroup( g.id, id ) ) : subgs.append( g.id )
subgs.sort( )
return( subgs )
[docs] def isSubGroup( self, sid_, id_, eps = 0. ) :
"""Returns true if sid is a sub-group of id, false otherwise."""
sid = None
id = None
for g in self.g :
if( sid_ == g.id ) : sid = g
elif( id_ == g.id ) : id = g
if( id is None ) : raise Exception( "isSubGroup: group with id = %d does not exist" )
if( sid is None ) : raise Exception( "isSubGroup: sub group with id = %d does not exist" )
i = 0
n = id.n
for sg in sid.gb :
while( 1 ) :
if( n == i ) : return( 0 )
d = sg - id.gb[i]
if( abs( d ) <= eps ) :
i += 1
break
if( d < 0. ) : return( 0 )
i += 1
return( 1 )
[docs] def halflife( self, za ) :
"""Returns the halflife of the za if in database, else returns None."""
if( za == 'gamma' ) : return( 1e50 )
za_ = targetToZA( za )
iMin = 0
iMax = len( self.h ) - 1
while( True ) :
iMid = ( iMin + iMax ) / 2
h = self.h[iMid]
if( h.za == za_ ) : return h.halflife
if( iMin == iMax ) : break
if( h.za > za_ ) :
iMax = iMid
else :
iMin = iMid + 1
return None
[docs] def mass( self, za ) :
"""Returns the mass of the za if in database, else returns None (the mass of a za is for a neutral atom, not the nucleus)."""
if( za == 'gamma' ) : return( 0. )
za_ = targetToZA( za )
iMin = 0
iMax = len( self.m ) - 1
while( True ) :
iMid = ( iMin + iMax ) / 2
m = self.m[iMid]
if( m.za == za_ ) : return m.mass
if( iMin == iMax ) : break
if( m.za > za_ ) :
iMax = iMid
else :
iMin = iMid + 1
return None
[docs] def constant( self, i ) :
"""Returns the (i+1)^th constant from self's constant list."""
return( self.c[i].value )
[docs] def printza( self, za, im = 0, ih = 0 ) :
"""Prints the za, mass and halflife for za."""
( za, m, h ) = self.za( za, im, ih )
if ( za is None ) : return
sm = 15 * " "
if( m is not None ) : sm = "%15.8e" % m
sh = 12 * " "
if ( h is not None ) : sh = "%12e" % self.h[ih].halflife
print "%6d %s %s" % ( za, sm, sh )
[docs] def read( self, name ) :
"""Reads in the bdfls file given by name. For internal use only."""
class fileInfo :
def __init__( self, name ) :
"""For internal use only."""
self.f = open( name, "r" )
self.lineNumber = 0
self.line = None
self.linesRead = []
def close( self ) :
"""For internal use only."""
self.f.close( )
def readline( self ) :
"""For internal use only."""
if( len( self.linesRead ) > 0 ) :
self.line = self.linesRead[0]
del self.linesRead[0]
else :
self.line = self.f.readline( )
self.lineNumber += 1
return( self.line )
def unreadline( self, line ) :
self.linesRead.append( line )
self.lineNumber -= 1
def errMsg( self, routine, str ) :
"""For internal use only."""
return( '\nError in %s: %s at line %d\n%s' % ( routine, str, self.lineNumber, self.line ) )
if ( not os.path.exists( name ) ) : raise Exception( "\nError in bdfls.read: file does not exist (%s)" % name )
f = fileInfo( name )
self.Source = name
while 1 : # Read the group data.
g = bdfls_group( f )
if ( g.id is None ) : break
self.g.append( g )
while 1 : # Read the flux data.
fl = bdfls_flux( f )
if ( fl.id is None ) : break
self.f.append( fl )
line = f.readline( ) # Handle new mass format.
f.unreadline( line )
s = line.split( "#" )
self.massFormat = 'old'
if( len( s ) > 1 ) :
self.massLabel = s[1][:-1]
self.massFormat = 'Audi2003'
while 1 :
m = bdfls_mass( f, format = self.massFormat )
if ( m.za is None ) : break
self.m.append( m )
while 1 :
h = bdfls_halflife( f )
if ( h.za is None ) : break
self.h.append( h )
( self.nConstants, i ) = bdfls_read_int_label( f, 0, "bdfls.read", "constant", "number of constants" )
i = self.nConstants
while 1 :
c = bdfls_constant( f )
if ( c.value is None ) : break
self.c.append( c )
i = i - 1
if ( i != 0 ) : raise Exception( "\nError in bdfls.read: %d unread constants" % i )
while 1 :
t = bdfls_temperature( f )
if ( t.id is None ) : break
self.t.append( t )
( self.nSubshells, i ) = bdfls_read_int_label( f, 0, "bdfls.read", "subshell", "number of subshell designators" )
i = self.nSubshells
while 1 :
s = bdfls_subshell( f )
if ( s.line is None ) : break
self.s.append( s )
i = i - 1
if ( i != 0 ) : raise Exception( "\nError in bdfls.read: %d unread subshells" % i )
f.close( )
[docs] def save( self, fileName = None ) :
"""Saves the contents of self to fileName."""
if ( fileName is None ) : fileName = self.name
try :
f = open( fileName, "w" )
except :
raise Exception( "\nError in bdfls.save: cannot open file %s" % fileName )
s = `self.g`
for g in self.g : f.write( `g` )
f.write( bdfls_EOD )
for fl in self.f : f.write( `fl` )
f.write( bdfls_EOD )
if( self.massFormat == 'old' ) :
l = " nuclear masses *\n"
elif( self.massFormat == 'Audi2003' ) :
n = 0
if( len( self.m ) > 0 ) :
n = len( `self.m[0]` )
l = '#' + self.massLabel
n = 80 - ( len( l ) + n )
l = n * ' ' + l + '\n'
else :
raise Exception( '\nError in bdfls.save: bad format = "%s"' % self.format )
for m in self.m :
f.write( `m` + l )
l = "\n"
f.write( bdfls_mh_EOD )
l = " half-lives *\n"
for h in self.h :
f.write( `h` + l )
l = "\n"
f.write( bdfls_mh_EOD )
f.write( "%4d nuclear constants *\n" % self.nConstants )
for c in self.c : f.write( `c` )
f.write( bdfls_EOD )
for t in self.t : f.write( `t` )
f.write( bdfls_EOD )
f.write( "%4d subshell designators *\n" % self.nSubshells )
for s in self.s : f.write( `s` )
f.write( bdfls_EOD )
f.close( )
[docs] def setZAHalflife( self, za, halflife ) :
"""Changes the halflife for ZA. A raise is triggered is za in not in self's halflife list."""
for h in self.h :
if ( h.za == za ) :
h.halflife = halflife
return
elif ( h.za > za ) :
raise Exception( "\nError in bdfls.setZAHalflife: no such ZA = %s" % `za` )
[docs] def setZAMass( self, za, mass ) :
"""Changes the mass for ZA. A raise is triggered is za in not in self's mass list."""
for m in self.m :
if ( m.za == za ) :
m.mass = mass
return
elif ( m.za > za ) :
raise Exception( "\nError in bdfls.setZAMass: no such ZA = %s" % `za` )
[docs] def za( self, za, im = 0, ih = 0 ) :
"""Returns the tuple ( za, mass, halflife ) for za."""
m = None
lm = len( self.m )
while ( im < lm ) :
if ( self.m[im].za == za ) : m = self.m[im].mass
if ( self.m[im].za >= za ) : break
im = im + 1
h = None
lh = len( self.h )
while ( ih < lh ) :
if ( self.h[ih].za == za ) : h = self.h[ih].halflife
if ( self.h[ih].za >= za ) : break
ih = ih + 1
if ( m is None ) and ( h is None ) : za = None
return ( za, m, h )
[docs] def zas( self, ZAMin, ZAMax = None ) :
"""Print za, mass and halflife for all za between ZAMin and ZAMax inclusive."""
if ( ZAMax is None ) : ZAMax = ZAMin
im = 0
lm = len( self.m )
ih = 0
lh = len( self.h )
while ( ( im < lm ) and ( self.m[im].za < ZAMin ) ) : im = im + 1
while ( ( ih < lh ) and ( self.h[ih].za < ZAMin ) ) : ih = ih + 1
za = ZAMin
while za <= ZAMax :
if ( ( im < lm ) and ( za > self.m[im].za ) ) : im = im + 1
if ( ( ih < lh ) and ( za > self.h[ih].za ) ) : ih = ih + 1
if ( ( im == lm ) and ( ih == lh ) ) : break
if ( im == lm ) :
za = self.h[ih].za
elif ( ih == lh ) :
za = self.m[im].za
else :
za = min( self.m[im].za, self.h[ih].za )
if ( za <= ZAMax ) :
self.printza( za, im, ih )
za = za + 1
[docs]class bdfls_group :
"""A class that contains a single group."""
def __init__( self, f ) :
"""f must be a python list of number for the group boundaries or an opened python file
that is a bdfls file positioned at the start of a group."""
self.id = None
if( type( f ) == type( [] ) ) :
self.label = None
self.n = len( f )
self.gb = f
else :
self.read( f )
def __len__( self ) :
"""Return the number of group boundaries."""
return( len( self.gb ) )
def __getitem__( self, index ) :
"""Returns the (index - 1)^th boundary"""
return( self.gb[index] )
def __repr__( self ) :
"""Returns a string of the group as it would appear in a bdfls file."""
s = "%4d %-74s*\n" % ( self.id, self.label )
if ( len( s ) > 81 ) : s = s[:79] + "*\n"
s = s + "%4d *\n" % self.n
j = 0
for i in self.gb :
s = s + "%12.5e" % i
j = j + 1
if ( ( j % 6 ) == 0 ) : s = s + "\n"
if ( ( j % 6 ) != 0 ) : s = s + "\n"
return s
[docs] def plot( self, xMin = None, xMax = None, yMin = None, yMax = None, xylog = 0, xLabel = None, yLabel = None,
title = None, style = "lines" ) :
"""Plots the group boundaries.
xylog meanings::
xylog plot-type
-----------------------
0 linear-linear
1 log-linear
2 linear-log
3 log-log"""
if ( xLabel is None ) : xLabel = 'Energy (MeV)'
if ( yLabel is None ) : yLabel = 'A. U.'
dt = plotbase.parsePlotOptions( xMin, xMax, yMin, yMax, xLabel, yLabel, title )
f = fudgeFileMisc.fudgeTempFile( )
for p in self.gb: f.write( "%15.7e 0.1\n%15.7e 10.\n\n" % ( p, p ) )
f.close( )
p = os.path.join( __file__.split( 'fudge/processing/' )[0], "fudge", "vis", "gnuplot", "endl2dplot.py" )
s = [ 'python', p, 'xylog', str( xylog ) ] + dt + [ f.getName( ) ]
subprocessing.spawn( s )
[docs] def read( self, f ) :
"""Reads in the next group from a bdfls file. Sets self's id to None if not more groups to read in."""
( self.id, self.label ) = bdfls_read_int_label( f, 1, "bdfls_group.read", "group", "group id" )
if( self.id is None ) : return
self.name = 'LLNL_gid_%d' % self.id
( self.n, l ) = bdfls_read_int_label( f, 0, "bdfls_group.read", "group", "number of groups" )
self.gb = []
i = 0
while ( i < self.n ) :
if ( ( i % 6 ) == 0 ) :
l = f.readline( )
if ( l == "" ) : raise Exception( f.errMsg( 'bdfls_group.__init__', 'EOF while reading group data' ) )
if ( l == bdfls_EOD ) : raise Exception( f.errMsg( 'bdfls_group.__init__', 'EOD detected while reading group data' ) )
j = 0
self.gb.append( float( l[j:j+12] ) )
j = j + 12
i = i + 1
[docs]class bdfls_flux :
"""A class that contains a single flux."""
def __init__( self, f ) :
"""f must be a python list of number for the with the following structure:
[
[ [E0, f0], [E1, f1], ... ], # for l = 0
[ [E0, f0], [E1, f1], ... ], # for l = 1
...
]
or an opened python file that is a bdfls file positioned at the start of a flux."""
self.id = None
if( type( f ) == type( [] ) ) :
self.label = None
self.lMax = len( f ) - 1
self.n = [ len(x) for x in f ]
self.EF_l = f
else :
self.id = None
self.read( f )
def __len__( self ) :
"""Returns the number of Legendre orders for this flux."""
return( len( self.EF_l ) )
def __repr__( self ) :
"""Returns a string of the flux as it would appear in a bdfls file."""
s = "%4d %-74s*\n" % ( self.id, self.label )
if ( len( s ) > 81 ) : s = s[:79] + "*\n"
s = s + "%4d *\n" % self.lMax
r = range( self.lMax + 1 )
for i in r :
s = s + "%4d *\n" % ( 2 * self.n[i] )
k = 0
for i in r :
for j in self.EF_l[i] :
s = s + "%12.5e%12.5e" % ( j[0], j[1] )
k = k + 1
if ( ( k % 3 ) == 0 ) : s = s + "\n"
if ( ( k % 3 ) != 0 ) : s = s + "\n"
return s
[docs] def plot( self, xMin = None, xMax = None, yMin = None, yMax = None, xylog = 0, xLabel = None, yLabel = None,
title = None, style = "lines" ) :
"""Plots the fluxes
xylog meanings::
xylog plot-type
-----------------------
0 linear-linear
1 log-linear
2 linear-log
3 log-log"""
if ( xLabel is None ) : xLabel = 'Energy (MeV)'
if ( yLabel is None ) : yLabel = 'A. U.'
dt = plotbase.parsePlotOptions( xMin, xMax, yMin, yMax, xLabel, yLabel, title )
f = fudgeFileMisc.fudgeTempFile( )
for lGroup in self.EF_l:
for p in lGroup: f.write( ' '.join( map( str, p ) ) + '\n' )
f.write( '\n' )
f.close( )
p = os.path.join( __file__.split( 'fudge/processing/' )[0], "fudge", "vis", "gnuplot", "endl2dplot.py" )
s = [ 'python', p, 'xylog', str( xylog ) ] + dt + [ f.getName( ) ]
subprocessing.spawn( s )
[docs] def read( self, f ) :
"""Reads in the next flux from a bdfls file. Sets self's id to None if no more fluxes to read in."""
( self.id, self.label ) = bdfls_read_int_label( f, 1, "bdfls_flux.read", "flux", "flux id" )
if( self.id is None ) : return
self.name = 'LLNL_fid_%d' % self.id
( self.lMax, l ) = bdfls_read_int_label( f, 0, "bdfls_flux.read", "flux", "lMax" )
self.EF_l = []
self.n = []
r = range( self.lMax + 1 )
for i in r :
( n, l ) = bdfls_read_int_label( f, 0, "bdfls_flux.read", "flux", "number of flux points" )
self.n.append( n / 2 )
for i in r :
j = 0
EF = []
while ( j < self.n[i] ) :
if ( ( j % 3 ) == 0 ) :
l = f.readline( )
if ( l == "" ) : raise Exception( f.errMsg( 'bdfls_flux.__init__', 'EOD while reading flux data' ) )
if ( l == bdfls_EOD ) : f.errMsg( 'bdfls_flux.__init__', 'EOD detected while reading flux data' )
k = 0
EF.append( [ float( l[k:k+12] ), float( l[k+12:k+24] ) ] )
k = k + 24
j = j + 1
self.EF_l.append( EF )
[docs]class bdfls_mass :
"""A class that contains a single za and mass datum."""
def __init__( self, f_or_za, mass = None, format = 'old' ) :
"""f_or_za must be an integer for the za or an opened python file
that is a bdfls file positioned at a mass datum. If f_or_za
is an integer then mass is its mass; otherwise, the za and mass are
read in from the file."""
if ( type( f_or_za ) == type( 1 ) ) :
self.za = f_or_za
self.mass = mass
else :
self.read( f_or_za )
self.format = format
def __repr__( self ) :
"""Returns a string of the za and mass as they would appear in a bdfls file."""
if( self.format == 'old' ) :
s = " %6.4d" % self.za
if ( self.mass == 0 ) :
s = s + " 0."
elif ( self.mass < 1. ) :
s = s + "%14.8f" % self.mass
elif ( self.mass > ( 1.e4 - 1e-6 ) ) :
if ( self.mass <= ( 1.e5 - 1e-6 ) ) :
s = s + "%12.5f" % self.mass
elif ( self.mass <= ( 1.e6 - 1e-5 ) ) :
s = s + "%12.4f" % self.mass
elif ( self.mass <= ( 1.e7 - 1e-4 ) ) :
s = s + "%12.3f" % self.mass
elif ( self.mass <= ( 1.e8 - 1e-3 ) ) :
s = s + "%12.2f" % self.mass
elif ( self.mass <= ( 1.e9 - 1e-2 ) ) :
s = s + "%12.1f" % self.mass
elif ( self.mass <= ( 1.e10 - 1e-1 ) ) :
s = s + "%12.0f" % self.mass
else :
s = s + "%12.5e" % self.mass
else :
s = s + "%12.6f" % self.mass
if ( ( ( self.za % 1000 ) == 0 ) or ( self.za == 99120 ) or ( self.za == 99125 ) ) :
while ( s[-1] == '0' ) :
if ( s[-2] == "." ) : break
s = s[:-1]
elif( self.format == 'Audi2003' ) :
s = " %6d" % self.za
d = ' %17.12f' % self.mass
try :
while( d[-1] == '0' ) : d = d[:-1]
except :
fudgemisc.printWarning( d )
raise
s += d
else :
raise Exception( '\nError in bdfls.bdfls_mass.__repr__: bad format = "%s"' % self.format )
return s
[docs] def read( self, f ) :
"""Reads in the next mass datum from the bdfls file. Returns the tuple (za, mass) or
(None, None) if at end of mass data."""
( self.za, self.mass ) = bdfls_read_int_float( f, "bdfls_mass.read", "mass" )
[docs]class bdfls_halflife :
"""A class that contains a single za and halflife datum."""
def __init__( self, f_or_za, halflife = None ) :
"""f_or_za must be an integer for the za or an opened python file
that is a bdfls file positioned at a halflife datum. If f_or_za
is an integer then halflife is its halflife; otherwise, the za and halflife are
read in from the file."""
if ( type( f_or_za ) == type( 1 ) ) :
self.za = f_or_za
self.halflife = halflife
else :
self.read( f_or_za )
def __repr__( self ) :
"""Returns a string of the za and halflife as they would appear in a bdfls file."""
if ( self.halflife is None ) :
s = " %6d" % self.za
else :
s = " %6d%12.4e" % ( self.za, self.halflife )
return s
[docs] def read( self, f ) :
"""Reads in the next halflife datum from the bdfls file. Set za and halflife
to None if at end of halflife data."""
( self.za, self.halflife ) = bdfls_read_int_float( f, "bdfls_halflife.read", "halflife" )
[docs]class bdfls_constant :
"""A class that contains a single constant datum."""
def __init__( self, f ) :
"""f must be an opened python file that is a bdfls file positioned at a constant datum."""
self.read( f )
def __repr__( self ) :
"""Returns a string of the constant as it would appear in a bdfls file."""
return "%15.8e $%s\n" % ( self.value, self.label )
[docs] def read( self, f ) :
"""Reads in the next constand datum from the bdfls file. Sets self's value to None if at end of constant data."""
self.value = None
self.label = ""
l = f.readline( )
if ( l == bdfls_EOD ) : return
i = string.find( l, "$" )
if ( i == -1 ) : raise Exception( f.errMsg( 'bdfls_constant.read', 'missing $' ) )
try :
self.value = float( l[:i] )
except :
raise Exception( f.errMsg( 'bdfls_constant.read', 'converting constant to float' ) )
self.label = l[i+1:-1]
[docs]class bdfls_temperature :
"""A class that contains a temperaure datum."""
def __init__( self, f ) :
"""f must be an opened python file that is a bdfls file positioned at a temperature datum."""
self.read( f )
def __repr__( self ) :
"""Returns a string of the temperature data as they would appear in a bdfls file."""
s = "%4d %-74s*\n" % ( self.id, self.label )
if ( len( s ) > 81 ) : s = s[:79] + "*\n"
s = s + "%4d *\n" % self.n
for i in self.ts : s = s + "%s\n" % i
return s
[docs] def read( self, f ) :
"""Reads in the next temperature datum from the bdfls file. Set self's id
to None if at end of temerature data."""
( self.id, self.label ) = bdfls_read_int_label( f, 1, "bdfls_temperature.read", "temperature", "temperature id" )
if( self.id is None ) : return
( self.n, l ) = bdfls_read_int_label( f, 0, "bdfls_temperature.read", "temperature", "number of temperatures" )
self.ts = []
i = 0
while i < self.n :
l = f.readline( )
if ( l == "" ) : raise Exception( f.errMsg( 'bdfls_temperature.read', 'EOF while reading temperature data' ) )
self.ts.append( l[:-1] )
i = i + string.count( l, "," )
if ( l[-2] != "," ) : break
[docs]class bdfls_subshell :
"""A class that contains the subshell data."""
def __init__( self, f ) :
"""f must be an opened python file that is a bdfls file positioned at a subshell data."""
self.read( f )
def __repr__( self ) :
"""Returns a string of the subshell as it would appear in a bdfls file."""
return( self.line )
[docs] def read( self, f ) :
"""Reads in the subshell data from the bdfls file. Set self's line
to None if at end of subshell data."""
self.line = None
l = f.readline( )
if ( l == "" ) : raise Exception( f.errMsg( 'bdfls_subshell.read', 'EOF while reading subshell data' ) )
if ( l != bdfls_EOD ) : self.line = l
[docs]def bdfls_read_int_label( f, allowEOD, callingRoutine, Str1, Str2 ) :
l = f.readline( )
if ( l == bdfls_EOD ) :
if ( allowEOD ) :
return ( None, None )
else :
raise Exception( f.errMsg( callingRoutine, 'EOD detected while reading %s' % Str1 ) )
if ( l == "" ) : raise Exception( f.errMsg( callingRoutine, 'EOF while reading %s data' % Str1 ) )
if ( len( l ) != 81 ) or ( l[79] != "*" ) : raise Exception( f.errMsg( callingRoutine, 'invalid %s line' % Str2 ) )
try :
n = int( l[:4] )
except :
raise Exception( f.errMsg( callingRoutine, 'converting %s to integer' % Str2 ) )
return( n, l[5:-2] )
[docs]def bdfls_read_int_float( f, callingRoutine, Str ) :
l = f.readline( )
if ( l == bdfls_mh_EOD ) : return( None, None )
if ( ( len( l ) == 81 ) and ( l[79] != "*" ) ) : raise Exception( f.errMsg( callingRoutine, 'invalid first za/%s line', Str ) )
if ( l[:4] != " " ) : raise Exception( f.errMsg( callingRoutine, 'bad za/%s line' % Str ) )
s = l.split( )
try :
za = int( s[0] )
except :
raise Exception( f.errMsg( callingRoutine, 'converting za to integer' ) )
d = None
if ( len( s ) > 1 ) :
try :
d = float( s[1] )
except :
raise Exception( f.errMsg( callingRoutine, 'converting mass to float "%s"' % Str ) )
return( za, d )
[docs]def getDefaultBdfls( name = None, template = None ) :
global default_bdfls
if( default_bdfls is None ) :
if( name is None ) : name = "bdfls.junk"
default_bdfls = bdfls( name = name, template = template )
return( default_bdfls )
[docs]def getBdflsFile( name = None ) :
return( bdfls( name = None, template = name ) )