AJMR-Python-Baird/LAVegMOD_DM/function.py

206 lines
8.1 KiB
Python

#!/usr/bin/env python
##\file
# This file defined the base Function class.
# This class is used to provide a piece-wise
# linear function for use in the model. The
# primary use of this these classes is presenting
# the information from the species establishment
# and senescenes tables.
#
# Standard Python Modules
import exceptions
import numpy
import random
import scipy
import scipy.interpolate as interp
import xlrd
# Third Party Modules
import matplotlib as mpl
import matplotlib.pylab as plt
import mpl_toolkits.mplot3d.axes3d as Axes3D
import pandas
class Function(object):
xValue = list()
yValue = list()
def __init__(self, xValue, yValue):
if len(xValue) != len(yValue):
msg = 'Function: Error: Number of elements in xValue an yValue must match'
msg += ' len(xValue) = ' + str(len(xValue)) + ' len(yValue) = ' + str(len(yValue))
raise exceptions.RuntimeError(msg)
self.xValue = xValue
self.yValue = yValue
def toIndex(self, x, vec):
if ( x < vec[0] or vec[-1] < x ):
msg = 'Function: Error: x out of range\n'
msg += 'x = ' + str(x) + '\n'
msg += 'vec[0] = ' + str(vec[0]) + '\n'
msg += 'vec[-1] = ' + str(vec[-1]) + '\n'
raise exceptions.RuntimeError(msg)
b = 0 # b = the "bottom" index
t = len(vec)-1 # t = the "top" index
m = int(scipy.ceil((b+t)/2.0)) # m = the middle index
if ( x == vec[t] ):
b = t-1
scale = 1.0
return b,scale
while ( vec[b+1] <= x ):
if ( vec[b] <= x and x < vec[m] ):
t = m
else:
b = m
m = int(scipy.ceil((b+t)/2.0))
scale = (x - vec[b])/(vec[b+1] - vec[b])
return b,scale
def __getitem__(self, x):
b,scale = self.toIndex(x, self.xValue)
return self.yValue[b]*(1.0 - scale) + self.yValue[b+1]*scale
class ReadVegTable1D(object):
def __init__(self):
pass
def read(self, filename, modelType, species):
try:
data = pandas.read_excel(filename, modelType, index_col=None )
xValue = list( data.ix[:,0] )
yValue = list( data[species] )
return {'elvValue':xValue, 'rate':yValue}
except exceptions.IOError as error:
errorMessage = 'ReadVegTable1D: Error: Could not open file for reading : ' + filename + '\n'
errorMessage += 'ReadVegTable1D: Error: Addition error info : ' + str(error) + '\n'
raise exceptions.RuntimeError(errorMessage)
except xlrd.biffh.XLRDError as error:
errorMessage = 'ReadVegTable1D: Error: Could not find sheet named ' + modelType + ' in file ' + filename + '\n'
errorMessage += 'ReadVegTable1D: Error: Additional error info : ' + str(error) + '\n'
raise exceptions.RuntimeError(errorMessage)
except exceptions.KeyError as error:
errorMessage = 'ReadVegTable1D: Error: Could not find species named ' + species + ' in sheet ' + modelType + ' in file ' + filename +'\n'
errorMessage += 'ReadVegTable1D: Error: Additional error info : ' + str(error) + '\n'
raise exceptions.RuntimeError(errorMessage)
class Function2DFast(object):
def __init__(self, xValue, yValue, data):
# xValue = wave amplitudes
# yValue = mean salinity
# data = senescence and growth rates
if ( len(yValue) != numpy.size(data, 0) ):
msg = 'Function2DFast: Error: number of elements in yValue must match number of rows in data'
msg += ' len(yValue) = ' + str(len(yValue)) + ' data.shape = ' + str(data.shape)
raise exceptions.RuntimeError(msg)
if ( len(xValue) != numpy.size(data, 1) ):
msg = 'Function2DFast: Error: number of elements in xValue must match number of columns in data'
msg += ' len(xValue) = ' + str(len(Value)) + ' size(data) = ' + str(data.shape)
raise exceptions.RuntimeError(msg)
self.xValue = xValue
self.yValue = yValue
self.data = data
def toIndex(self, x, vec):
if ( x < vec[0] or vec[-1] < x ):
msg = 'Function2DFast: Error: x out of range\n'
msg += 'x = ' + str(x) + '\n'
msg += 'vec[0] = ' + str(vec[0]) + '\n'
msg += 'vec[-1] = ' + str(vec[-1]) + '\n'
raise exceptions.RuntimeError(msg)
b = 0 # b = the "bottom" index
t = len(vec)-1 # t = the "top" index
m = int(scipy.ceil((b+t)/2.0)) # m = the middle index
if ( x == vec[t] ):
b = t-1
scale = 1.0
return b,scale
while ( vec[b+1] <= x ):
if ( vec[b] <= x and x < vec[m] ):
t = m
else:
b = m
m = int(scipy.ceil((b+t)/2.0))
scale = (x - vec[b])/(vec[b+1] - vec[b])
return b,scale
def __getitem__(self, item):
i, i_scale = self.toIndex(item[0], self.xValue)
j, j_scale = self.toIndex(item[1], self.yValue)
x0 = self.data[j ,i] * (1.0 - i_scale) + self.data[j ,i+1]*i_scale
x1 = self.data[j+1,i] * (1.0 - i_scale) + self.data[j+1,i+1]*i_scale
return x0*(1.0 - j_scale) + x1*j_scale
class Function2D(object):
def __init__(self, xValue, yValue, data = 0):
# xValue = wave amplitudes
# yValue = mean salinity
# data = senescence and growth rates
if len(yValue) != numpy.size(data, 0):
msg = 'Function2D: Error: number of elements in yValue must match number of rows in data'
msg += ' len(yValue) = ' + str(len(yValue)) + ' data.shape = ' + str(data.shape)
raise exceptions.RuntimeError(msg)
if len(xValue) != numpy.size(data, 1):
msg = 'Function2D: Error: number of elements in xValue must match number of columns in data'
msg += ' len(xValue) = ' + str(len(Value)) + ' size(data) = ' + str(data.shape)
raise exceptions.RuntimeError(msg)
self.point = numpy.array( [ [x,y] for y in yValue for x in xValue ] )
self.value = numpy.array( [elt for row in data for elt in row] )
self.minX = min( xValue )
self.maxX = max( xValue )
self.minY = min( yValue )
self.maxY = max( yValue )
def __getitem__(self, item):
if ( item[0] < self.minX or self.maxX < item[0] ):
raise exceptions.RuntimeError('Function2D: Error: x coordinate out of range. ' + str(item[0]) + ' not in ' + '[ ' + str(self.minX) + ', ' + str(self.maxX) + ' ]' )
if ( item[1] < self.minY or self.maxY < item[1] ):
raise exceptions.RuntimeError('Function2D: Error: y coordinate out of range. ' + str(item[1]) + ' not in ' + '[ ' + str(self.minY) + ', ' + str(self.maxY) + ' ]' )
return interp.griddata(self.point, self.value, ([item[0]],[item[1]] ), method='linear')[0]
class ReadVegTable2D(object):
def __init__(self):
pass
def read(self, filename, species):
try:
data = pandas.read_excel(filename, species, index_col=None, parse_cols=range(1,23), skiprows=1)
waValue = data.columns.values.tolist()[1:len(data.columns)]
spcode = data.columns.values.tolist()[0]
salValue = data[spcode].tolist()
rate = numpy.asarray(data)[:,1:22]
return {'spcode':spcode, 'waValue':waValue, 'salValue':salValue, 'rate':rate }
except exceptions.IOError as error:
errorMessage = 'ReadVegTable2D: Error: Could not open file for reading : ' + filename + '\n'
errorMessage += 'ReadVegTable2D: Error: Addition error info : ' + str(error) + '\n'
raise exceptions.RuntimeError(errorMessage)
except xlrd.biffh.XLRDError as error:
errorMessage = 'ReadVegTable2D: Error: Could not find sheet named ' + species + ' in file : ' + filename + '\n'
errorMessage += 'ReadVegTable2D: Error: Addition error info : ' + str(error) + '\n'
raise exceptions.RuntimeError(errorMessage)