#!/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)