[PATCH] S/Q: Excel compat completed: Now the data is linearized before fitting. This can be prevented by setting the system property S/Q: Excel compat completed: Now the data is linearized before fitting. This can be prevented by setting the system property "minfo.sq.calcution.non.linear.fitting" to true
Wald Commits
scm-commit at wald.intevation.org
Thu Aug 8 18:14:43 CEST 2013
# HG changeset patch
# User Sascha L. Teichmann <teichmann at intevation.de>
# Date 1375978478 -7200
# Node ID 51eb6491c537b9be0f3a2ebeb1065433ff9f160f
# Parent 70b440dc53170d804e8f892be43f8ef45421b8d9
S/Q: Excel compat completed: Now the data is linearized before fitting. This can be prevented by setting the system property S/Q: Excel compat completed: Now the data is linearized before fitting. This can be prevented by setting the system property "minfo.sq.calcution.non.linear.fitting" to true.
diff -r 70b440dc5317 -r 51eb6491c537 artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/Fitting.java
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/Fitting.java Thu Aug 08 16:19:59 2013 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/Fitting.java Thu Aug 08 18:14:38 2013 +0200
@@ -8,6 +8,7 @@
package org.dive4elements.river.artifacts.model.sq;
+import org.dive4elements.artifacts.common.utils.StringUtils;
import org.dive4elements.river.artifacts.math.fitting.Function;
import java.util.ArrayList;
@@ -83,7 +84,7 @@
public void initialize(List<SQ> sqs) throws MathException {
if (USE_NON_LINEAR_FITTING
- || function.getInitialGuess().length != 2) {
+ || function.getParameterNames().length != 2) {
nonLinearFitting(sqs);
}
else {
@@ -92,43 +93,48 @@
}
protected void linearFitting(List<SQ> sqs) {
-
- coeffs = linearRegression(sqs);
-
+ coeffs = linearRegression(sqs);
instance = function.instantiate(coeffs);
}
protected double [] linearRegression(List<SQ> sqs) {
+ String [] pns = function.getParameterNames();
+ double [] result = new double[pns.length];
+
+ if (sqs.size() < 2) {
+ log.debug("not enough points");
+ return result;
+ }
+
SimpleRegression reg = new SimpleRegression();
- int invalidPoints = 0;
for (SQ sq: sqs) {
- double s = sq.getS();
- double q = sq.getQ();
- if (s <= 0d || q <= 0d) {
- ++invalidPoints;
- continue;
- }
- reg.addData(Math.log(q), Math.log(s));
+ double s = sqView.getS(sq);
+ double q = sqView.getQ(sq);
+ reg.addData(q, s);
}
- if (sqs.size() - invalidPoints < 2) {
- log.debug("not enough points");
- return new double [] { 0, 0 };
- }
-
- double a = Math.exp(reg.getIntercept());
+ double m = reg.getIntercept();
double b = reg.getSlope();
if (log.isDebugEnabled()) {
- log.debug("invalid points: " +
- invalidPoints + " (" + sqs.size() + ")");
- log.debug("a: " + a + " (" + Math.log(a) + ")");
+ log.debug("m: " + m);
log.debug("b: " + b);
}
- return new double [] { a, b };
+ int mIdx = StringUtils.indexOf("m", pns);
+ int bIdx = StringUtils.indexOf("b", pns);
+
+ if (mIdx == -1 || bIdx == -1) {
+ log.error("index not found: " + mIdx + " " + bIdx);
+ return result;
+ }
+
+ result[bIdx] = m;
+ result[mIdx] = b;
+
+ return result;
}
@@ -140,7 +146,7 @@
CurveFitter cf = new CurveFitter(optimizer);
for (SQ sq: sqs) {
- cf.addObservedPoint(sq.getS(), sq.getQ());
+ cf.addObservedPoint(sqView.getQ(sq), sqView.getS(sq));
}
coeffs = cf.fit(
@@ -179,7 +185,7 @@
chiSqr);
}
- public boolean fit(List<SQ> sqs, String method, Callback callback) {
+ public boolean fit(List<SQ> sqs, String method, Callback callback) {
if (sqs.size() < 2) {
log.warn("Too less points for fitting.");
diff -r 70b440dc5317 -r 51eb6491c537 artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/SQRelationCalculation.java
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/SQRelationCalculation.java Thu Aug 08 16:19:59 2013 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/SQRelationCalculation.java Thu Aug 08 18:14:38 2013 +0200
@@ -8,6 +8,7 @@
package org.dive4elements.river.artifacts.model.sq;
+import org.dive4elements.artifacts.common.utils.StringUtils;
import org.dive4elements.river.artifacts.access.SQRelationAccess;
import org.dive4elements.river.artifacts.math.fitting.Function;
@@ -21,6 +22,7 @@
import org.dive4elements.river.backend.SedDBSessionHolder;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import org.apache.log4j.Logger;
@@ -30,7 +32,11 @@
private static final Logger log =
Logger.getLogger(SQRelationCalculation.class);
- public static final String SQ_FUNCTION_NAME = "sq-pow";
+ public static final boolean NON_LINEAR_FITTING =
+ Boolean.getBoolean("minfo.sq.calcution.non.linear.fitting");
+
+ public static final String SQ_POW_FUNCTION_NAME = "sq-pow";
+ public static final String SQ_LIN_FUNCTION_NAME = "linear";
protected String river;
protected double location;
@@ -49,8 +55,6 @@
Double outliers = access.getOutliers();
String method = access.getOutlierMethod();
- //river = "Rhein";
-
if (river == null) {
// TODO: i18n
addProblem("sq.missing.river");
@@ -102,20 +106,76 @@
}
}
+ public interface TransformCoeffs {
+ double [] transform(double [] coeffs);
+ }
+
+ public static final TransformCoeffs IDENTITY_TRANS =
+ new TransformCoeffs() {
+ @Override
+ public double [] transform(double [] coeffs) {
+ return coeffs;
+ }
+ };
+
+ public static final TransformCoeffs LINEAR_TRANS =
+ new TransformCoeffs() {
+ @Override
+ public double [] transform(double [] coeffs) {
+ log.debug("before transform: " + Arrays.toString(coeffs));
+ if (coeffs.length == 2) {
+ coeffs = new double [] { Math.exp(coeffs[1]), coeffs[0] };
+ }
+ log.debug("after transform: " + Arrays.toString(coeffs));
+ return coeffs;
+ }
+ };
+
protected CalculationResult internalCalculate() {
- Function function = FunctionFactory
+ Function powFunction = FunctionFactory
.getInstance()
- .getFunction(SQ_FUNCTION_NAME);
+ .getFunction(SQ_POW_FUNCTION_NAME);
- if (function == null) {
- log.error("No '" + SQ_FUNCTION_NAME + "' function found.");
+ if (powFunction == null) {
+ log.error("No '" + SQ_POW_FUNCTION_NAME + "' function found.");
// TODO: i18n
addProblem("sq.missing.sq.function");
+ return new CalculationResult(new SQResult[0], this);
}
- SQ.View sqView = SQ.SQ_VIEW;
- SQ.Factory sqFactory = SQ.SQ_FACTORY;
+ Function function;
+ SQ.View sqView;
+ SQ.Factory sqFactory;
+ ParameterCreator pc;
+
+
+ if (NON_LINEAR_FITTING) {
+ log.debug("Use non linear fitting.");
+ sqView = SQ.SQ_VIEW;
+ sqFactory = SQ.SQ_FACTORY;
+ function = powFunction;
+ pc = new ParameterCreator(
+ powFunction.getParameterNames(),
+ powFunction.getParameterNames());
+ }
+ else {
+ log.debug("Use linear fitting.");
+ sqView = LogSQ.LOG_SQ_VIEW;
+ sqFactory = LogSQ.LOG_SQ_FACTORY;
+ function = FunctionFactory
+ .getInstance()
+ .getFunction(SQ_LIN_FUNCTION_NAME);
+ if (function == null) {
+ log.error("No '" + SQ_LIN_FUNCTION_NAME + "' function found.");
+ // TODO: i18n
+ addProblem("sq.missing.sq.function");
+ return new CalculationResult(new SQResult[0], this);
+ }
+ pc = new LinearParameterCreator(
+ powFunction.getParameterNames(),
+ function.getParameterNames());
+ }
Measurements measurements =
MeasurementFactory.getMeasurements(
@@ -124,13 +184,14 @@
SQFractionResult [] fractionResults =
new SQFractionResult[SQResult.NUMBER_FRACTIONS];
+
for (int i = 0; i < fractionResults.length; ++i) {
List<SQ> sqs = measurements.getSQs(i);
SQFractionResult fractionResult;
List<SQFractionResult.Iteration> iterations =
- doFitting(function, sqs, sqView);
+ doFitting(function, sqs, sqView, pc);
if (iterations == null) {
// TODO: i18n
@@ -152,9 +213,10 @@
}
protected List<SQFractionResult.Iteration> doFitting(
- final Function function,
- List<SQ> sqs,
- SQ.View sqView
+ final Function function,
+ List<SQ> sqs,
+ SQ.View sqView,
+ final ParameterCreator pc
) {
final List<SQFractionResult.Iteration> iterations =
new ArrayList<SQFractionResult.Iteration>();
@@ -171,8 +233,7 @@
double standardDeviation,
double chiSqr
) {
- Parameters parameters = createParameters(
- function.getParameterNames(),
+ Parameters parameters = pc.createParameters(
coeffs,
standardDeviation,
chiSqr);
@@ -186,22 +247,75 @@
return success ? iterations : null;
}
- public static final Parameters createParameters(
- String [] names,
- double [] values,
- double standardDeviation,
- double chiSqr
- ) {
- String [] columns = new String[names.length + 2];
- columns[0] = "chi_sqr";
- columns[1] = "std_dev";
- System.arraycopy(names, 0, columns, 2, names.length);
- Parameters parameters = new Parameters(columns);
- int row = parameters.newRow();
- parameters.set(row, names, values);
- parameters.set(row, "chi_sqr", chiSqr);
- parameters.set(row, "std_dev", standardDeviation);
- return parameters;
+ public static class ParameterCreator {
+
+ protected String [] origNames;
+ protected String [] proxyNames;
+
+ public ParameterCreator(String [] origNames, String [] proxyNames) {
+ this.origNames = origNames;
+ this.proxyNames = proxyNames;
+ }
+
+ protected double [] transformCoeffs(double [] coeffs) {
+ return coeffs;
+ }
+
+ public Parameters createParameters(
+ double [] coeffs,
+ double standardDeviation,
+ double chiSqr
+ ) {
+ String [] columns = new String[origNames.length + 2];
+ columns[0] = "chi_sqr";
+ columns[1] = "std_dev";
+ System.arraycopy(origNames, 0, columns, 2, origNames.length);
+ Parameters parameters = new Parameters(columns);
+ int row = parameters.newRow();
+ parameters.set(row, origNames, transformCoeffs(coeffs));
+ parameters.set(row, "chi_sqr", chiSqr);
+ parameters.set(row, "std_dev", standardDeviation);
+ return parameters;
+ }
+ }
+
+ /** We need to transform the coeffs back to the original function. */
+ public static class LinearParameterCreator extends ParameterCreator {
+
+ public LinearParameterCreator(
+ String [] origNames,
+ String [] proxyNames
+ ) {
+ super(origNames, proxyNames);
+ }
+
+ @Override
+ protected double [] transformCoeffs(double [] coeffs) {
+
+ int bP = StringUtils.indexOf("m", proxyNames);
+ int mP = StringUtils.indexOf("b", proxyNames);
+
+ int aO = StringUtils.indexOf("a", origNames);
+ int bO = StringUtils.indexOf("b", origNames);
+
+ if (bP == -1 || mP == -1 || aO == -1 || bO == -1) {
+ log.error("index not found: "
+ + bP + " " + mP + " "
+ + aO + " " + bO);
+ return coeffs;
+ }
+
+ double [] ncoeffs = (double [])coeffs.clone();
+ ncoeffs[aO] = Math.exp(coeffs[mP]);
+ ncoeffs[bO] = coeffs[bP];
+
+ if (log.isDebugEnabled()) {
+ log.debug("before transform: " + Arrays.toString(coeffs));
+ log.debug("after transform: " + Arrays.toString(ncoeffs));
+ }
+
+ return ncoeffs;
+ }
}
}
// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :
More information about the Dive4elements-commits
mailing list