예제 #1
0
def weibullModelAnalysis(isopachs,numberOfRuns,iterationsPerRun,limits):
	"""
	Analyses the isopach data under the assumption it follows a Weibull model
	
	Model: T(x) = theta*((x/lambda)^(k-2))*exp(-((x/lambda)^k))
	IMPORTANT: Works under the assumption x = sqrt(A/pi) rather than x = sqrt(A).
	
	Not guaranteed to provide a good fit (although with a suitable number of runs and iterations
	per run the probability is high). If a poor fit is returned, try rerunning the calculation.
	
	Arguments
	isopachs:list of Isopachs  --  list of isopachs to analyse.
	numberOfRuns:int		   --  the number of runs that the hill-climbing algorithm performs
	iterationsPerRun:int	   --  the number of iterations per run that the hill-climbing
								   algorithm performs
	limits:list of 2-tuples	--  A list of 2 2-tuples, the first 2 tuple representing
								   lower and upper bounds for parameter lambda and the 
								   second 2-tuple the bounds for parameter k.
								   
	
	Returns
	A dictionary with the following key-value mapping:
	
		dict["estimatedTotalVolume"]:float   --  the estimated total volume of the deposit (in km3).
		dict["thicknessFunction"]:func x->t  --  the thickness function, calculates T(x) (in metres).
		dict["lambda"]:float				 --  estimated value of parameter lambda
		dict["k"]:float					  --  estimated value of parameter k
		dict["theta"]:float				  --  estimated value of parameter theta
		dict["bestScore"]:float			  --  the score of the parameters returned, the closer
												 to zero it is the better the fit of the curve
		dict["isopachs"]:list of Isopachs	--  list of Isopachs analysed
		dict["limits"]:list of 2-tuples	  --  the limits for lambda and k used in calculations

		dict["mrse"]:float 					-- the mean relative squared error of the model
	"""

	sqrtAreasKM = np.array([isopach.sqrtAreaKM for isopach in isopachs])
	thicknessesM = np.array([isopach.thicknessM for isopach in isopachs])

	lamb, k, bestScore = _solveWeibullParameters(_logErrorFunction,
												 sqrtAreasKM,
												 thicknessesM,
												 numberOfRuns,
												 iterationsPerRun,
												 *limits)
	theta = calculateTheta(sqrtAreasKM, thicknessesM, lamb,k)
	
	thicknessFunction = _createThicknessFunction(lamb, k, theta)
	estimatedTotalVolumeKM3 = calculateWeibullVolume(lamb, k, theta)
	mrse = regression_methods.meanRelativeSquaredError(sqrtAreasKM, thicknessesM, thicknessFunction)

	return {"estimatedTotalVolume" : estimatedTotalVolumeKM3,
			"thicknessFunction" : thicknessFunction,
			"lambda" : lamb,
			"k" : k,
			"theta" : theta,
			"bestScore" : bestScore,
			"isopachs" : isopachs,
			"limits" : limits,
			"mrse" : mrse}
예제 #2
0
			def errorFunction(lamb,k):
				theta = calculateTheta(xs,ys,lamb,k)
				def thicknessFunction(x):
					try:
						return np.exp(np.log(theta)+(k-2)*np.log(x/lamb)-(x/lamb)**k)
					except FloatingPointError:
						return 0
				mrse = regression_methods.meanRelativeSquaredError(xs, ys, thicknessFunction)
				return math.log(mrse)
예제 #3
0
			def errorFunction(lamb,k):
				theta = calculateTheta(xs,ys,lamb,k)
				def thicknessFunction(x):
					try:
						return np.exp(np.log(theta)+(k-2)*np.log(x/lamb)-(x/lamb)**k)
					except FloatingPointError:
						return 0
				mrse = regression_methods.meanRelativeSquaredError(xs, ys, thicknessFunction)
				return math.log(mrse)
예제 #4
0
    def _updateWei(self):

        ###########
        ## Stats ##
        ###########

        fr = self.statsFrame

        # lambda
        lamb = self.currentParameters["lambda"]
        lambdaStr = helper_functions.roundToSF(lamb, NUMBER_OF_SF)
        fr.weiLambdaE.insertNew(lamb)

        # k
        k = self.currentParameters["k"]
        kStr = helper_functions.roundToSF(k, NUMBER_OF_SF)
        fr.weiKE.insertNew(k)

        # theta
        theta = self.currentParameters["theta"]
        thetaStr = helper_functions.roundToSF(theta, NUMBER_OF_SF)
        fr.weiThetaE.insertNew(theta)

        # Volume
        volume = calculateWeibullVolume(lamb, k, theta)
        volumeStr = helper_functions.roundToSF(volume, NUMBER_OF_SF)
        fr.totalEstimatedVolume_E.insertNew(volumeStr)

        # Error
        thicknessFunction = lambda x: theta * (
            (x / lamb)**(k - 2)) * math.exp(-((x / lamb)**k))
        error = regression_methods.meanRelativeSquaredError(
            self.sqrtAreaKM, self.thicknessM, thicknessFunction)
        errorStr = helper_functions.roundToSF(error, NUMBER_OF_SF)
        fr.relativeSquaredError_E.insertNew(errorStr)

        # Equation
        invLambdaStr = helper_functions.roundToSF(1 / lamb, NUMBER_OF_SF)
        kminus2Str = helper_functions.roundToSF(k - 2, NUMBER_OF_SF)
        equationStr = "T = " + thetaStr + "((" + invLambdaStr + "x)^" + kminus2Str + ")exp(-(" + invLambdaStr + "x)^" + kStr + ")"
        fr.equation_E.insertNew(equationStr)

        ############
        ## Graphs ##
        ############

        # Model
        startX = 0
        endX = (self.isopachs[-1].distanceFromVentKM() + 50) * SQRT_PI
        xs = helper_functions.getStaggeredPoints(startX, endX,
                                                 MODEL_PLOTTING_PRECISION)[1:]
        ys = [
            theta * ((x / lamb)**(k - 2)) * math.exp(-((x / lamb)**k))
            for x in xs
        ]
        self.modelGraphFrame.plotFilledLine(xs, ys, colours[0])
예제 #5
0
	def _updateWei(self):
		
		###########
		## Stats ##
		###########

		fr = self.statsFrame

		# lambda
		lamb = self.currentParameters["lambda"]
		lambdaStr = helper_functions.roundToSF(lamb, NUMBER_OF_SF)
		fr.weiLambdaE.insertNew(lamb)

		# k
		k = self.currentParameters["k"]
		kStr = helper_functions.roundToSF(k, NUMBER_OF_SF)
		fr.weiKE.insertNew(k)

		# theta
		theta = self.currentParameters["theta"]
		thetaStr = helper_functions.roundToSF(theta, NUMBER_OF_SF)
		fr.weiThetaE.insertNew(theta)

		# Volume
		volume = calculateWeibullVolume(lamb, k, theta)
		volumeStr = helper_functions.roundToSF(volume, NUMBER_OF_SF)
		fr.totalEstimatedVolume_E.insertNew(volumeStr)

		# Error
		thicknessFunction = lambda x : theta*((x/lamb)**(k-2))*math.exp(-((x/lamb)**k))
		error = regression_methods.meanRelativeSquaredError(self.sqrtAreaKM, self.thicknessM, thicknessFunction)
		errorStr = helper_functions.roundToSF(error, NUMBER_OF_SF)
		fr.relativeSquaredError_E.insertNew(errorStr)

		# Equation
		invLambdaStr = helper_functions.roundToSF(1/lamb, NUMBER_OF_SF)
		kminus2Str = helper_functions.roundToSF(k-2, NUMBER_OF_SF)
		equationStr = "T = " + thetaStr + "((" + invLambdaStr + "x)^" +kminus2Str + ")exp(-(" + invLambdaStr + "x)^" + kStr + ")"
		fr.equation_E.insertNew(equationStr)




		############
		## Graphs ##
		############

		# Model
		startX = 0
		endX = (self.isopachs[-1].distanceFromVentKM()+50)*SQRT_PI
		xs = helper_functions.getStaggeredPoints(startX,endX,MODEL_PLOTTING_PRECISION)[1:]
		ys = [theta*((x/lamb)**(k-2))*math.exp(-((x/lamb)**k)) for x in xs]
		self.modelGraphFrame.plotFilledLine(xs, ys, colours[0])
예제 #6
0
			def errorFunction(c,m):
				thicknessFunction = lambda x : c*(x**(-m))
				return math.log(regression_methods.meanRelativeSquaredError(xs, ys, thicknessFunction))
예제 #7
0
	def _updatePow(self):

		###########
		## Stats ##
		###########

		fr = self.statsFrame

		# Coefficient
		c = self.currentParameters["coefficient"]
		coefficientStr = helper_functions.roundToSF(c, NUMBER_OF_SF)
		fr.powCoefficient_E.insertNew(c)

		# Exponent
		m = self.currentParameters["exponent"]
		exponentStr = helper_functions.roundToSF(m, NUMBER_OF_SF)
		fr.powExponent_E.insertNew(m)

		# Proximal limit
		proximalLimitKM = self.currentParameters["proximalLimitKM"]
		proximalLimitStr = helper_functions.roundToSF(proximalLimitKM, NUMBER_OF_SF)
		fr.powProximalLimit_E.insertNew(proximalLimitKM)

		# Distal limit
		distalLimitKM = self.currentParameters["distalLimitKM"]
		distalLimitStr = helper_functions.roundToSF(distalLimitKM, NUMBER_OF_SF)
		fr.powDistalLimit_E.insertNew(distalLimitKM)

		# Volume
		volume = calculatePowerLawVolume(c, m, proximalLimitKM, distalLimitKM)
		volumeStr = helper_functions.roundToSF(volume, NUMBER_OF_SF)
		fr.totalEstimatedVolume_E.insertNew(volumeStr)

		# Error
		thicknessFunction = lambda x : c*(x**(-m))
		error = regression_methods.meanRelativeSquaredError(self.sqrtAreaKM, self.thicknessM, thicknessFunction)
		errorStr = helper_functions.roundToSF(error, NUMBER_OF_SF)
		fr.relativeSquaredError_E.insertNew(errorStr)

		# Equation
		equationStr = "T = " + coefficientStr
		if m > 0:
			equationStr += "x^-" + exponentStr
		elif m < 0:
			equationStr += "x^" + exponentStr[1:]
		fr.equation_E.insertNew(equationStr)

		# Suggested proximal limit
		suggestedProximalLimit = self.currentParameters["suggestedProximalLimit"]
		suggestedProximalLimitStr = helper_functions.roundToSF(suggestedProximalLimit, NUMBER_OF_SF)
		fr.powSuggestedProximalLimit_E.insertNew(suggestedProximalLimitStr)


		############
		## Graphs ##
		############

		startX = proximalLimitKM*SQRT_PI
		endX = distalLimitKM*SQRT_PI

		# Model
		xs = helper_functions.getStaggeredPoints(startX, endX, MODEL_PLOTTING_PRECISION)
		ys = [thicknessFunction(x) for x in xs]
		self.modelGraphFrame.plotFilledLine(xs, ys, color=colours[0])

		# Regression
		logXs = [np.log(a) for a in self.sqrtAreaKM]
		logYs = [np.log(t) for t in self.thicknessM]
		self.regressionGraphFrame.plotScatter(logXs, logYs, False)

		self.regressionGraphFrame.axes.set_xlabel(r"$\log{\sqrt{Area}}$")
		lineXs = [np.sqrt(startX), np.sqrt(endX)]
		lineYs = [np.log(c) - m*x for x in lineXs]
		self.regressionGraphFrame.plotLine(lineXs, lineYs, colours[0])
예제 #8
0
	def _updateExp(self, comboboxUpdate):

		n = self.currentParameters["numberOfSegments"]
		coefficients = self.currentParameters["segmentCoefficients"]
		exponents = self.currentParameters["segmentExponents"]
		limits = self.currentParameters["segmentLimits"]

		###########
		## Stats ##
		###########

		fr = self.statsFrame

		# Segment start
		start = limits[self.currentSegment]
		startStr = helper_functions.roundToSF(start, NUMBER_OF_SF)
		fr.expSegStartLimit_E.insertNew(start)
		fr.expSegStartLimit_E.setUserEditable(self.currentSegment != 0)

		# Segment end
		end = limits[self.currentSegment+1]
		endStr = helper_functions.roundToSF(end, NUMBER_OF_SF)
		fr.expSegEndLimit_E.insertNew(end)
		fr.expSegEndLimit_E.setUserEditable(self.currentSegment != n-1)

		# Segment coefficient
		coefficient = coefficients [self.currentSegment]
		coefficientStr = helper_functions.roundToSF(coefficient, NUMBER_OF_SF)
		fr.expSegCoefficent_E.insertNew(coefficient)

		# Segment exponent
		exponent = exponents[self.currentSegment]
		exponentStr = helper_functions.roundToSF(exponent, NUMBER_OF_SF)
		fr.expSegExponent_E.insertNew(exponent)

		# Segment volume
		segmentVolumes = [calculateExponentialSegmentVolume(coefficients[i], exponents[i], limits[i], limits[i+1]) for i in range(n)]
		segmentVolumeStr = helper_functions.roundToSF(segmentVolumes[self.currentSegment], NUMBER_OF_SF)
		fr.expSegVolume_E.insertNew(segmentVolumeStr)

		# Total volume
		totalVolume = sum(segmentVolumes)
		estimatedTotalVolumeStr = helper_functions.roundToSF(totalVolume, NUMBER_OF_SF)
		fr.totalEstimatedVolume_E.insertNew(estimatedTotalVolumeStr)

		# Error
		def thicknessFunction(x):
			for i in range(n):
				if limits[i] <= x < limits[i+1]:
					return coefficients[i]*math.exp(-exponents[i]*x)
		error = regression_methods.meanRelativeSquaredError(self.sqrtAreaKM, self.thicknessM, thicknessFunction)
		errorStr = helper_functions.roundToSF(error, NUMBER_OF_SF)
		fr.relativeSquaredError_E.insertNew(errorStr)

		# Equation
		equationStr = "T = " + coefficientStr
		if exponent > 0:
			equationStr += "exp(-" + exponentStr + "x)"
		elif exponent < 0:
			equationStr += "exp(" + exponentStr[1:] + "x)"
		fr.equation_E.insertNew(equationStr)



		############
		## Graphs ##
		############

		if not comboboxUpdate:
			# Model

			endXs = limits[1:-1] + [1.5*max(self.sqrtAreaKM)-0.5*min(self.sqrtAreaKM)]

			for i in range(n):
				xs = helper_functions.getStaggeredPoints(limits[i], endXs[i], MODEL_PLOTTING_PRECISION)
				ys = [coefficients[i]*math.exp(-exponents[i]*x) for x in xs]
				self.modelGraphFrame.plotFilledLine(xs, ys, color=colours[i])

			# Regression
			logThicknessM = [np.log(t) for t in self.thicknessM]
			self.regressionGraphFrame.plotScatter(self.sqrtAreaKM, logThicknessM, False)
			self.regressionGraphFrame.axes.set_xlabel(r"$\sqrt{Area}$")

			for i in range(n):
				xs = [limits[i], endXs[i]]
				ys = [np.log(thicknessFunction(x)) for x in xs]
				self.regressionGraphFrame.plotLine(xs,ys, color=colours[i])
예제 #9
0
def weibullModelAnalysis(isopachs, numberOfRuns, iterationsPerRun, limits):
    """
	Analyses the isopach data under the assumption it follows a Weibull model
	
	Model: T(x) = theta*((x/lambda)^(k-2))*exp(-((x/lambda)^k))
	IMPORTANT: Works under the assumption x = sqrt(A/pi) rather than x = sqrt(A).
	
	Not guaranteed to provide a good fit (although with a suitable number of runs and iterations
	per run the probability is high). If a poor fit is returned, try rerunning the calculation.
	
	Arguments
	isopachs:list of Isopachs  --  list of isopachs to analyse.
	numberOfRuns:int		   --  the number of runs that the hill-climbing algorithm performs
	iterationsPerRun:int	   --  the number of iterations per run that the hill-climbing
								   algorithm performs
	limits:list of 2-tuples	--  A list of 2 2-tuples, the first 2 tuple representing
								   lower and upper bounds for parameter lambda and the 
								   second 2-tuple the bounds for parameter k.
								   
	
	Returns
	A dictionary with the following key-value mapping:
	
		dict["estimatedTotalVolume"]:float   --  the estimated total volume of the deposit (in km3).
		dict["thicknessFunction"]:func x->t  --  the thickness function, calculates T(x) (in metres).
		dict["lambda"]:float				 --  estimated value of parameter lambda
		dict["k"]:float					  --  estimated value of parameter k
		dict["theta"]:float				  --  estimated value of parameter theta
		dict["bestScore"]:float			  --  the score of the parameters returned, the closer
												 to zero it is the better the fit of the curve
		dict["isopachs"]:list of Isopachs	--  list of Isopachs analysed
		dict["limits"]:list of 2-tuples	  --  the limits for lambda and k used in calculations

		dict["mrse"]:float 					-- the mean relative squared error of the model
	"""

    sqrtAreasKM = np.array([isopach.sqrtAreaKM for isopach in isopachs])
    thicknessesM = np.array([isopach.thicknessM for isopach in isopachs])

    lamb, k, bestScore = _solveWeibullParameters(_logErrorFunction,
                                                 sqrtAreasKM, thicknessesM,
                                                 numberOfRuns,
                                                 iterationsPerRun, *limits)
    theta = calculateTheta(sqrtAreasKM, thicknessesM, lamb, k)

    thicknessFunction = _createThicknessFunction(lamb, k, theta)
    estimatedTotalVolumeKM3 = calculateWeibullVolume(lamb, k, theta)
    mrse = regression_methods.meanRelativeSquaredError(sqrtAreasKM,
                                                       thicknessesM,
                                                       thicknessFunction)

    return {
        "estimatedTotalVolume": estimatedTotalVolumeKM3,
        "thicknessFunction": thicknessFunction,
        "lambda": lamb,
        "k": k,
        "theta": theta,
        "bestScore": bestScore,
        "isopachs": isopachs,
        "limits": limits,
        "mrse": mrse
    }
예제 #10
0
def exponentialModelAnalysis(isopachs, n):
    """
	Analyses the isopach data under the assumption it follows a n-segment exponential model 
	
	Model: T(x) = c*exp(-m*x)
	IMPORTANT: Works under the assumption x = sqrt(A/pi) rather than x = sqrt(A).
	
	Arguments
	isopachs:list of Isopachs -- list of isopachs to analyse
	n:int -- the number of exponential segments
	
	Returns
	A dictionary with the following key-value mapping:
	
		dict["estimatedTotalVolume"]:float		  --  the estimated total volume of the deposit.
		dict["thicknessFunction"]:func x->t		 --  the thickness function, calculates T(x) (in metres).
		dict["segmentLimits"]:list of floats		--  list of bounds for the segments. Segment i
														is valid between segmentLimits[i] and
														segmentLimits[i+1].
		dict["segmentVolumes"]:list of floats	   --  estimated tephra volumes for each segment.
		dict["segmentCoefficients"]:list of floats  --  estimated coefficients for each segment.
		dict["segmentExponents"]:list of floats	 --  estimated exponents for each segment.
		dict["segmentBts"]:list of floats		   --  estimated half-thicknesses for each segment
														(i.e. distance across which tephra thickness
														halves).
		dict["regressionLines"]:list of Lines	   --  Line objects representing each segment's
														least squares regression line used to estimate
														it's parameters.
		dict["isopachs"]:list of Isopachs		   --  list of Isopachs analysed.
		dict["numberOfSegments"]:int				--  number of exponential segments.

		dict["mrse"]:float 							-- the mean relative squared error of the model
	"""

    thicknessesM = [isopach.thicknessM for isopach in isopachs]
    logThickness = [np.log(isopach.thicknessM) for isopach in isopachs]
    sqrtAreasKM = [isopach.sqrtAreaKM for isopach in isopachs]

    regressionLines, segmentLimits = regression_methods.calculateMultiLineRegression(
        sqrtAreasKM, logThickness, n)

    segmentT0s = [np.exp(line.c) for line in regressionLines]
    segmentKs = [-line.m for line in regressionLines]
    segmentBts = [np.log(2) / (k * np.sqrt(np.pi)) for k in segmentKs]
    segmentVolumes = []

    segmentLimits[0], segmentLimits[-1] = 0, float("inf")

    for i in range(n):
        segmentVolumes.append(
            calculateExponentialSegmentVolume(segmentT0s[i], segmentKs[i],
                                              segmentLimits[i],
                                              segmentLimits[i + 1]))
    estimatedTotalVolume = sum(segmentVolumes)

    def thicknessFunction(x):
        for i in range(n):
            if segmentLimits[i] <= x < segmentLimits[i + 1]:
                return segmentT0s[i] * np.exp(-segmentKs[i] * x)
        raise ValueError(
            "x (" + str(x) +
            ") is not in the domain of the function (0 to infinity)")

    mrse = regression_methods.meanRelativeSquaredError(sqrtAreasKM,
                                                       thicknessesM,
                                                       thicknessFunction)

    return {
        "estimatedTotalVolume": estimatedTotalVolume,
        "thicknessFunction": thicknessFunction,
        "segmentLimits": segmentLimits,
        "segmentVolumes": segmentVolumes,
        "segmentCoefficients": segmentT0s,
        "segmentExponents": segmentKs,
        "segmentBts": segmentBts,
        "regressionLines": regressionLines,
        "isopachs": isopachs,
        "numberOfSegments": n,
        "mrse": mrse
    }
예제 #11
0
def exponentialModelAnalysis(isopachs,n):
	"""
	Analyses the isopach data under the assumption it follows a n-segment exponential model 
	
	Model: T(x) = c*exp(-m*x)
	IMPORTANT: Works under the assumption x = sqrt(A/pi) rather than x = sqrt(A).
	
	Arguments
	isopachs:list of Isopachs -- list of isopachs to analyse
	n:int -- the number of exponential segments
	
	Returns
	A dictionary with the following key-value mapping:
	
		dict["estimatedTotalVolume"]:float		  --  the estimated total volume of the deposit.
		dict["thicknessFunction"]:func x->t		 --  the thickness function, calculates T(x) (in metres).
		dict["segmentLimits"]:list of floats		--  list of bounds for the segments. Segment i
														is valid between segmentLimits[i] and
														segmentLimits[i+1].
		dict["segmentVolumes"]:list of floats	   --  estimated tephra volumes for each segment.
		dict["segmentCoefficients"]:list of floats  --  estimated coefficients for each segment.
		dict["segmentExponents"]:list of floats	 --  estimated exponents for each segment.
		dict["segmentBts"]:list of floats		   --  estimated half-thicknesses for each segment
														(i.e. distance across which tephra thickness
														halves).
		dict["regressionLines"]:list of Lines	   --  Line objects representing each segment's
														least squares regression line used to estimate
														it's parameters.
		dict["isopachs"]:list of Isopachs		   --  list of Isopachs analysed.
		dict["numberOfSegments"]:int				--  number of exponential segments.

		dict["mrse"]:float 							-- the mean relative squared error of the model
	"""

	thicknessesM = [isopach.thicknessM for isopach in isopachs]
	logThickness = [np.log(isopach.thicknessM) for isopach in isopachs]
	sqrtAreasKM = [isopach.sqrtAreaKM for isopach in isopachs]

	regressionLines, segmentLimits = regression_methods.calculateMultiLineRegression(sqrtAreasKM,logThickness,n)

	segmentT0s = [np.exp(line.c) for line in regressionLines]
	segmentKs = [-line.m for line in regressionLines]
	segmentBts = [np.log(2)/(k*np.sqrt(np.pi)) for k in segmentKs]
	segmentVolumes = []
	
	segmentLimits[0], segmentLimits[-1] = 0, float("inf")

	for i in range(n):
		segmentVolumes.append(calculateExponentialSegmentVolume(segmentT0s[i],segmentKs[i],segmentLimits[i],segmentLimits[i+1]))
	estimatedTotalVolume = sum(segmentVolumes)

	def thicknessFunction(x):
		for i in range(n):
			if segmentLimits[i] <= x < segmentLimits[i+1]:
				return segmentT0s[i]*np.exp(-segmentKs[i]*x)
		raise ValueError("x (" + str(x) + ") is not in the domain of the function (0 to infinity)")

	mrse = regression_methods.meanRelativeSquaredError(sqrtAreasKM, thicknessesM, thicknessFunction)

	return {"estimatedTotalVolume" : estimatedTotalVolume,
			"thicknessFunction" : thicknessFunction,
			"segmentLimits" : segmentLimits,
			"segmentVolumes" : segmentVolumes,
			"segmentCoefficients" : segmentT0s,
			"segmentExponents" : segmentKs,
			"segmentBts" : segmentBts,
			"regressionLines" : regressionLines,
			"isopachs" : isopachs,
			"numberOfSegments" : n,
			"mrse" : mrse}
예제 #12
0
			def errorFunction(c,m):
				thicknessFunction = lambda x : c*(x**(-m))
				return math.log(regression_methods.meanRelativeSquaredError(xs, ys, thicknessFunction))
예제 #13
0
	def _updatePow(self):
		
		###########
		## Stats ##
		###########

		fr = self.statsFrame

		# Coefficient
		c = self.currentParameters["coefficient"]
		coefficientStr = helper_functions.roundToSF(c, NUMBER_OF_SF)
		fr.powCoefficient_E.insertNew(c)

		# Exponent
		m = self.currentParameters["exponent"] 
		exponentStr = helper_functions.roundToSF(m, NUMBER_OF_SF)
		fr.powExponent_E.insertNew(m)

		# Proximal limit
		proximalLimitKM = self.currentParameters["proximalLimitKM"]
		proximalLimitStr = helper_functions.roundToSF(proximalLimitKM, NUMBER_OF_SF)
		fr.powProximalLimit_E.insertNew(proximalLimitKM)
		
		# Distal limit
		distalLimitKM = self.currentParameters["distalLimitKM"]
		distalLimitStr = helper_functions.roundToSF(distalLimitKM, NUMBER_OF_SF)
		fr.powDistalLimit_E.insertNew(distalLimitKM)
		
		# Volume
		volume = calculatePowerLawVolume(c, m, proximalLimitKM, distalLimitKM)
		volumeStr = helper_functions.roundToSF(volume, NUMBER_OF_SF)
		fr.totalEstimatedVolume_E.insertNew(volumeStr)

		# Error
		thicknessFunction = lambda x : c*(x**(-m))
		error = regression_methods.meanRelativeSquaredError(self.sqrtAreaKM, self.thicknessM, thicknessFunction)
		errorStr = helper_functions.roundToSF(error, NUMBER_OF_SF)
		fr.relativeSquaredError_E.insertNew(errorStr)

		# Equation
		equationStr = "T = " + coefficientStr
		if m > 0:
			equationStr += "x^-" + exponentStr
		elif m < 0:
			equationStr += "x^" + exponentStr[1:]
		fr.equation_E.insertNew(equationStr)

		# Suggested proximal limit
		suggestedProximalLimit = self.currentParameters["suggestedProximalLimit"]
		suggestedProximalLimitStr = helper_functions.roundToSF(suggestedProximalLimit, NUMBER_OF_SF)
		fr.powSuggestedProximalLimit_E.insertNew(suggestedProximalLimitStr)


		############
		## Graphs ##
		############

		startX = proximalLimitKM*SQRT_PI
		endX = distalLimitKM*SQRT_PI

		# Model
		xs = helper_functions.getStaggeredPoints(startX, endX, MODEL_PLOTTING_PRECISION)
		ys = [thicknessFunction(x) for x in xs]
		self.modelGraphFrame.plotFilledLine(xs, ys, color=colours[0])

		# Regression
		logXs = [np.log(a) for a in self.sqrtAreaKM]
		logYs = [np.log(t) for t in self.thicknessM]
		self.regressionGraphFrame.plotScatter(logXs, logYs, False)

		self.regressionGraphFrame.axes.set_xlabel(r"$\log{\sqrt{Area}}$")
		lineXs = [np.sqrt(startX), np.sqrt(endX)]
		lineYs = [np.log(c) - m*x for x in lineXs]
		self.regressionGraphFrame.plotLine(lineXs, lineYs, colours[0])
예제 #14
0
	def _updateExp(self, comboboxUpdate):
		
		n = self.currentParameters["numberOfSegments"]
		coefficients = self.currentParameters["segmentCoefficients"]
		exponents = self.currentParameters["segmentExponents"]
		limits = self.currentParameters["segmentLimits"]

		###########
		## Stats ##
		###########

		fr = self.statsFrame

		# Segment start
		start = limits[self.currentSegment]
		startStr = helper_functions.roundToSF(start, NUMBER_OF_SF)
		fr.expSegStartLimit_E.insertNew(start)
		fr.expSegStartLimit_E.setUserEditable(self.currentSegment != 0)

		# Segment end
		end = limits[self.currentSegment+1]
		endStr = helper_functions.roundToSF(end, NUMBER_OF_SF)
		fr.expSegEndLimit_E.insertNew(end)
		fr.expSegEndLimit_E.setUserEditable(self.currentSegment != n-1)

		# Segment coefficient
		coefficient = coefficients [self.currentSegment]
		coefficientStr = helper_functions.roundToSF(coefficient, NUMBER_OF_SF)
		fr.expSegCoefficent_E.insertNew(coefficient)
		
		# Segment exponent
		exponent = exponents[self.currentSegment]
		exponentStr = helper_functions.roundToSF(exponent, NUMBER_OF_SF)
		fr.expSegExponent_E.insertNew(exponent)
		
		# Segment volume
		segmentVolumes = [calculateExponentialSegmentVolume(coefficients[i], exponents[i], limits[i], limits[i+1]) for i in range(n)]
		segmentVolumeStr = helper_functions.roundToSF(segmentVolumes[self.currentSegment], NUMBER_OF_SF)
		fr.expSegVolume_E.insertNew(segmentVolumeStr)

		# Total volume
		totalVolume = sum(segmentVolumes)
		estimatedTotalVolumeStr = helper_functions.roundToSF(totalVolume, NUMBER_OF_SF)
		fr.totalEstimatedVolume_E.insertNew(estimatedTotalVolumeStr)

		# Error 
		def thicknessFunction(x):
			for i in range(n):
				if limits[i] <= x < limits[i+1]:
					return coefficients[i]*math.exp(-exponents[i]*x)
		error = regression_methods.meanRelativeSquaredError(self.sqrtAreaKM, self.thicknessM, thicknessFunction)
		errorStr = helper_functions.roundToSF(error, NUMBER_OF_SF)
		fr.relativeSquaredError_E.insertNew(errorStr)

		# Equation
		equationStr = "T = " + coefficientStr
		if exponent > 0:
			equationStr += "exp(-" + exponentStr + "x)"
		elif exponent < 0:
			equationStr += "exp(" + exponentStr[1:] + "x)"
		fr.equation_E.insertNew(equationStr)



		############
		## Graphs ##
		############
		
		if not comboboxUpdate:
			# Model

			endXs = limits[1:-1] + [1.5*max(self.sqrtAreaKM)-0.5*min(self.sqrtAreaKM)]

			for i in range(n):
				xs = helper_functions.getStaggeredPoints(limits[i], endXs[i], MODEL_PLOTTING_PRECISION)
				ys = [coefficients[i]*math.exp(-exponents[i]*x) for x in xs]
				self.modelGraphFrame.plotFilledLine(xs, ys, color=colours[i])

			# Regression
			logThicknessM = [np.log(t) for t in self.thicknessM]
			self.regressionGraphFrame.plotScatter(self.sqrtAreaKM, logThicknessM, False)
			self.regressionGraphFrame.axes.set_xlabel(r"$\sqrt{Area}$")
			
			for i in range(n):
				xs = [limits[i], endXs[i]]
				ys = [np.log(thicknessFunction(x)) for x in xs]
				self.regressionGraphFrame.plotLine(xs,ys, color=colours[i])
예제 #15
0
def powerLawModelAnalysis(isopachs, proximalLimitKM, distalLimitKM):
    """
    Analyses the isopach data under the assumption it follows a power law model
    
    Model: T(x) = c*x^(-m)
    IMPORTANT: Works under the assumption x = sqrt(A/pi) rather than x = sqrt(A).
    
    Arguments
    isopachs:list of Isopachs -- list of isopachs to analyse
    proximalLimitKM:float -- the proximal limit of integration (in km)
    distalLimitKM:float -- the distal limit of integration (in km)
    
    Returns
    A dictionary with the following key-value mapping:
    
        dict["estimatedTotalVolume"]:float          --  the estimated total volume of the deposit.
        dict["thicknessFunction"]:func x->t         --  the thickness function, calculates T(x) (in metres).
        dict["regressionLine"]:Line                 --  Line object representing the least squares
                                                        regression line used to estimate the parameters
        dict["coefficient"]:float                   --  estimated coefficient for the power curve
        dict["exponent"]:float                      --  estimated exponent for the power curve
        dict["isopachs"]:list of Isopachs           --  list of Isopachs analysed
        dict["proximalLimitKM"]:list of Isopachs    --  the proximal limit of integration used in calculations
        dict["distalLimitKM"]:list of Isopachs      --  the distal limit of integration used in calculations
        
        dict["mrse"]:float                          -- the mean relative squared error of the model
    """
    
    thicknessesM = [isopach.thicknessM for isopach in isopachs]
    sqrtAreasKM = [isopach.sqrtAreaKM for isopach in isopachs]
    logThicknessesM = [np.log(t) for t in thicknessesM]
    logSqrtAreaKM = [np.log(a) for a in sqrtAreasKM]
    
    proximalLimitSqrtAreaKM = proximalLimitKM*np.sqrt(np.pi)
    distalLimitSqrtAreaKM = distalLimitKM*np.sqrt(np.pi)

    regressionLine = regression_methods.calculateSingleLineRegression(logSqrtAreaKM, logThicknessesM)
    m = -regressionLine.m
    c = np.exp(regressionLine.c)
    estimatedTotalVolume = calculatePowerLawVolume(c, m, proximalLimitSqrtAreaKM, distalLimitSqrtAreaKM)

    def thicknessFunction(x):
        if proximalLimitSqrtAreaKM <= x <= distalLimitSqrtAreaKM:
            return c*(x**-m)
        else:
            raise ValueError("x is out of range of proximal and distal limits of integration")
    
    if len(isopachs) > 3:
        suggestedProximalLimit = calculateProximalLimitEstimate(isopachs, c, m)
    else:
        suggestedProximalLimit = "N/A"

    mrse = regression_methods.meanRelativeSquaredError(sqrtAreasKM, thicknessesM, thicknessFunction)

    return {"estimatedTotalVolume" : estimatedTotalVolume,
            "thicknessFunction" : thicknessFunction,
            "regressionLine" : regressionLine,
            "coefficient" : c,
            "exponent" : m,
            "isopachs" : isopachs,
            "proximalLimitKM" : proximalLimitKM,
            "distalLimitKM" : distalLimitKM,
            "suggestedProximalLimit" : suggestedProximalLimit,
            "mrse" : mrse}
예제 #16
0
def powerLawModelAnalysis(isopachs, proximalLimitKM, distalLimitKM):
    """
    Analyses the isopach data under the assumption it follows a power law model
    
    Model: T(x) = c*x^(-m)
    IMPORTANT: Works under the assumption x = sqrt(A/pi) rather than x = sqrt(A).
    
    Arguments
    isopachs:list of Isopachs -- list of isopachs to analyse
    proximalLimitKM:float -- the proximal limit of integration (in km)
    distalLimitKM:float -- the distal limit of integration (in km)
    
    Returns
    A dictionary with the following key-value mapping:
    
        dict["estimatedTotalVolume"]:float          --  the estimated total volume of the deposit.
        dict["thicknessFunction"]:func x->t         --  the thickness function, calculates T(x) (in metres).
        dict["regressionLine"]:Line                 --  Line object representing the least squares
                                                        regression line used to estimate the parameters
        dict["coefficient"]:float                   --  estimated coefficient for the power curve
        dict["exponent"]:float                      --  estimated exponent for the power curve
        dict["isopachs"]:list of Isopachs           --  list of Isopachs analysed
        dict["proximalLimitKM"]:list of Isopachs    --  the proximal limit of integration used in calculations
        dict["distalLimitKM"]:list of Isopachs      --  the distal limit of integration used in calculations
        
        dict["mrse"]:float                          -- the mean relative squared error of the model
    """

    thicknessesM = [isopach.thicknessM for isopach in isopachs]
    sqrtAreasKM = [isopach.sqrtAreaKM for isopach in isopachs]
    logThicknessesM = [np.log(t) for t in thicknessesM]
    logSqrtAreaKM = [np.log(a) for a in sqrtAreasKM]

    proximalLimitSqrtAreaKM = proximalLimitKM * np.sqrt(np.pi)
    distalLimitSqrtAreaKM = distalLimitKM * np.sqrt(np.pi)

    regressionLine = regression_methods.calculateSingleLineRegression(
        logSqrtAreaKM, logThicknessesM)
    m = -regressionLine.m
    c = np.exp(regressionLine.c)
    estimatedTotalVolume = calculatePowerLawVolume(c, m,
                                                   proximalLimitSqrtAreaKM,
                                                   distalLimitSqrtAreaKM)

    def thicknessFunction(x):
        if proximalLimitSqrtAreaKM <= x <= distalLimitSqrtAreaKM:
            return c * (x**-m)
        else:
            raise ValueError(
                "x is out of range of proximal and distal limits of integration"
            )

    if len(isopachs) > 3:
        suggestedProximalLimit = calculateProximalLimitEstimate(isopachs, c, m)
    else:
        suggestedProximalLimit = "N/A"

    mrse = regression_methods.meanRelativeSquaredError(sqrtAreasKM,
                                                       thicknessesM,
                                                       thicknessFunction)

    return {
        "estimatedTotalVolume": estimatedTotalVolume,
        "thicknessFunction": thicknessFunction,
        "regressionLine": regressionLine,
        "coefficient": c,
        "exponent": m,
        "isopachs": isopachs,
        "proximalLimitKM": proximalLimitKM,
        "distalLimitKM": distalLimitKM,
        "suggestedProximalLimit": suggestedProximalLimit,
        "mrse": mrse
    }