# <<BEGIN-copyright>>
# <<END-copyright>>
"""
This module contains useful fudge math routines that do not fit into any other module.
"""
import math
try :
import numpy
numpyFloat64 = numpy.float64( 1. )
except :
numpyFloat64 = 1.
from pqu import PQU as PQUModule
import xData.standards as standardsModule
from fudge.core.utilities import brb
__metaclass__ = type
[docs]def thickenXYList( list, tester, biSectionMax = 6, interpolation = standardsModule.interpolation.linlinToken ) :
"""
This functions takes a list of (x,y) points and a function, tester.evaluateAtX, and bi-sectionally adds points to
obtain linear-linear tolerance of the returned list and tester.evaluateAtX to tester.relativeTolerance. At most
biSectionMax bi-sections are performed between each consecutive pair of inputted points. It is assumed that the
initial list of points and the function tester.evaluateAtX agree to tolerance tester.relativeTolerance. The instance
tester must contain the members relativeTolerance and absoluteTolerance as well as the method evaluateAtX. The
method evaluateAtX takes an x-value and returns its y-value.
"""
def thickenXYList2( interpolation, xl, yl, xu, yu, newList, tester, level ) :
if( level == biSectionMax ) : return
level += 1
if( ( interpolation == standardsModule.interpolation.linlinToken ) or ( interpolation == standardsModule.interpolation.loglinToken ) ) :
xMid = 0.5 * ( xl + xu )
else :
xMid = math.sqrt( xl * xu );
if( ( interpolation == standardsModule.interpolation.linlinToken ) or ( interpolation == standardsModule.interpolation.linlogToken ) ) :
yMid = 0.5 * ( yl + yu )
else :
yMid = math.sqrt( yl * yu )
y = tester.evaluateAtX( xMid )
dy = abs( y - yMid )
if( ( dy > abs( y * tester.relativeTolerance ) ) and ( dy > tester.absoluteTolerance ) ) :
newList.append( [ xMid, y ] )
thickenXYList2( interpolation, xl, yl, xMid, y, newList, tester, level )
thickenXYList2( interpolation, xMid, y, xu, yu, newList, tester, level )
if( len( list ) < 2 ) : raise Exception( "len( list ) = %d < 2" % len( list ) )
newList = []
for i1, xy in enumerate( list ) :
x2, y2 = xy
if( i1 > 0 ) : thickenXYList2( interpolation, x1, y1, x2, y2, newList, tester, 0 )
newList.append( [ x2, y2 ] )
x1, y1 = x2, y2
newList.sort( )
return( newList )
[docs]def checkForNaN( v, str, printErrors = True, indentation = "", messages = None ) :
if( v != v ) :
s = "%s: value is nan" % str
if( type( messages ) != type( None ) ) : messages.append( s )
if( printErrors ) : printWarning( '\n'.join( checkMessagesToString( s, indentation = indentation ) ) )
[docs]def isNumber( n ) :
if( type( 1. ) == type( n ) ) : return( True )
if( type( 1 ) == type( n ) ) : return( True )
if( type( numpyFloat64 ) == type( n ) ) : return( True )
return( False )
[docs]def toInt( value ) :
try :
return( int( value ) )
except :
raise TypeError( 'value must be a convertible to a int; it is of %s: str( value )[:128] = "%s"' % ( brb.getType( value ), str( value )[:128] ) )
[docs]def toFloat( value ) :
try :
return( float( value ) )
except :
raise TypeError( 'value must be a convertible to a float; it is of %s: str( value )[:128] = "%s"' % ( brb.getType( value ), str( value )[:128] ) )
[docs]def checkNumber( v, str = "", printErrors = True, indentation = "", messages = None, maxAbsFloatValue = None ) :
checkForNaN( v, str, printErrors = printErrors, indentation = indentation, messages = messages )
if( not( maxAbsFloatValue is None ) ) :
if( abs( v ) > maxAbsFloatValue ) :
s = "%s: abs of number %s exceeds maxAbsFloatValue = %s" % ( str, v, maxAbsFloatValue )
if( not( messages is None ) ) : messages.append( s )
if( printErrors ) : printWarning( '\n'.join( checkMessagesToString( s, indentation = indentation ) ) )
[docs]def getValue( n ) :
if( isNumber( n ) ) : return( n )
if( isinstance( n, PQUModule.PQU ) ) : return( n.getValue( ) )
raise Exception( 'Invalue number object = %s' % brb.getType( n ) )