# HG changeset patch # User Sascha L. Teichmann # Date 1342953510 0 # Node ID 262e7d7e58fe3a613e436f1ed09f60518540bf56 # Parent 1a636be7612babe4dc432858c3cc811151a96bf3 FixA: Made curve fitting over the given calculation range reusable. Removed dead code. flys-artifacts/trunk@5098 c6561f87-3c4e-4783-a992-168aeb5c3f6f diff -r 1a636be7612b -r 262e7d7e58fe flys-artifacts/ChangeLog --- a/flys-artifacts/ChangeLog Sun Jul 22 09:49:56 2012 +0000 +++ b/flys-artifacts/ChangeLog Sun Jul 22 10:38:30 2012 +0000 @@ -1,3 +1,9 @@ +2012-07-22 Sascha L. Teichmann + + * src/main/java/de/intevation/flys/artifacts/model/fixings/FixAnalysisCalculation.java, + src/main/java/de/intevation/flys/artifacts/model/fixings/FixCalculation.java: + Made curve fitting over the given calculation range reusable. Removed dead code. + 2012-07-22 Sascha L. Teichmann * src/main/java/de/intevation/flys/artifacts/model/fixings/FixCalculation.java, diff -r 1a636be7612b -r 262e7d7e58fe flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/FixAnalysisCalculation.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/FixAnalysisCalculation.java Sun Jul 22 09:49:56 2012 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/FixAnalysisCalculation.java Sun Jul 22 10:38:30 2012 +0000 @@ -1,7 +1,5 @@ package de.intevation.flys.artifacts.model.fixings; -import de.intevation.artifacts.common.utils.StringUtils; - import de.intevation.flys.artifacts.access.FixAnalysisAccess; import de.intevation.flys.artifacts.math.fitting.Function; @@ -9,8 +7,6 @@ import de.intevation.flys.artifacts.model.CalculationResult; import de.intevation.flys.artifacts.model.DateRange; -import de.intevation.flys.artifacts.model.FixingsColumn; -import de.intevation.flys.artifacts.model.FixingsColumnFactory; import de.intevation.flys.artifacts.model.FixingsOverview.AndFilter; import de.intevation.flys.artifacts.model.FixingsOverview.DateRangeFilter; @@ -21,7 +17,6 @@ import de.intevation.flys.artifacts.model.FixingsOverview.IdsFilter; import de.intevation.flys.artifacts.model.FixingsOverview.KmFilter; import de.intevation.flys.artifacts.model.FixingsOverview.SectorFilter; -import de.intevation.flys.artifacts.model.FixingsOverview.SectorRangeFilter; import de.intevation.flys.artifacts.model.FixingsOverview; import de.intevation.flys.artifacts.model.FixingsOverviewFactory; @@ -29,7 +24,6 @@ import de.intevation.flys.artifacts.model.Range; import de.intevation.flys.utils.DateAverager; -import de.intevation.flys.utils.DoubleUtil; import de.intevation.flys.utils.KMIndex; import java.util.ArrayList; @@ -45,13 +39,6 @@ { private static Logger log = Logger.getLogger(FixAnalysisCalculation.class); - public static final double EPSILON = 1e-4; - - // TODO: Move to base class? - public static final String [] STANDARD_COLUMNS = { - "km", "chi_sqr", "max_q", "std-dev" - }; - protected DateRange referencePeriod; protected DateRange [] analysisPeriods; @@ -80,8 +67,6 @@ public CalculationResult calculate() { - boolean debug = log.isDebugEnabled(); - FixingsOverview overview = FixingsOverviewFactory.getOverview(river); @@ -100,125 +85,27 @@ return new CalculationResult(this); } - final List eventColumns = getEventColumns(overview); + FitResult fitResult = doFitting(overview, func); - if (eventColumns.size() < 2) { - addProblem("fix.too.less.data.columns"); + if (fitResult == null) { return new CalculationResult(this); } - final double [] qs = new double[eventColumns.size()]; - final double [] ws = new double[qs.length]; - final boolean [] interpolated = new boolean[ws.length]; - - Fitting.QWDFactory qwdFactory = new Fitting.QWDFactory() { - @Override - public QWD create(double q, double w) { - // Check all the event columns for close match - // and take the description and the date from meta. - for (int i = 0; i < qs.length; ++i) { - if (Math.abs(qs[i]-q) < EPSILON - && Math.abs(ws[i]-w) < EPSILON) { - Column column = eventColumns.get(i); - return new QWD( - qs[i], ws[i], - column.getDescription(), - column.getDate(), - interpolated[i], - 0d); - } - } - log.warn("cannot find column for (" + q + ", " + w + ")"); - return new QWD(q, w); - } - }; - - Fitting fitting = new Fitting(func, qwdFactory, preprocessing); - - String [] parameterNames = func.getParameterNames(); - - Parameters results = - new Parameters( - StringUtils.join(STANDARD_COLUMNS, parameterNames)); - - boolean invalid = false; - - double [] kms = DoubleUtil.explode(from, to, step / 1000.0); - - if (debug) { - log.debug("number of kms: " + kms.length); - } - - KMIndex outliers = new KMIndex(); - KMIndex referenced = new KMIndex(kms.length); - - int kmIndex = results.columnIndex("km"); - int chiSqrIndex = results.columnIndex("chi_sqr"); - int maxQIndex = results.columnIndex("max_q"); - int stdDevIndex = results.columnIndex("std-dev"); - int [] parameterIndices = results.columnIndices(parameterNames); + KMIndex analysisPeriods = + calculateAnalysisPeriods( + func, + fitResult.getParameters(), + overview); - int numFailed = 0; - - for (int i = 0; i < kms.length; ++i) { - double km = kms[i]; - - // Fill Qs and Ws from event columns. - for (int j = 0; j < ws.length; ++j) { - interpolated[j] = !eventColumns.get(j).getQW(km, qs, ws, j); - } - - fitting.reset(); - - if (!fitting.fit(qs, ws)) { - ++numFailed; - addProblem(km, "fix.fitting.failed"); - continue; - } - - referenced.add(km, fitting.referencedToArray()); - - if (fitting.hasOutliers()) { - outliers.add(km, fitting.outliersToArray()); - } - - int row = results.newRow(); - double [] values = fitting.getParameters(); - - results.set(row, kmIndex, km); - results.set(row, chiSqrIndex, fitting.getChiSquare()); - results.set(row, stdDevIndex, fitting.getStandardDeviation()); - results.set(row, maxQIndex, fitting.getMaxQ()); - invalid |= results.set(row, parameterIndices, values); - - if (debug) { - log.debug("km: "+km+" " + toString(parameterNames, values)); - } - } - - if (debug) { - log.debug("success: " + (kms.length - numFailed)); - log.debug("failed: " + numFailed); - } - - if (invalid) { - addProblem("fix.invalid.values"); - results.removeNaNs(); - } - - KMIndex analysisPeriods = - calculateAnalysisPeriods(func, results, overview); - - outliers.sort(); - referenced.sort(); analysisPeriods.sort(); - FixAnalysisResult fr = new FixAnalysisResult( - results, - referenced, outliers, + FixAnalysisResult far = new FixAnalysisResult( + fitResult.getParameters(), + fitResult.getReferenced(), + fitResult.getOutliers(), analysisPeriods); - return new CalculationResult(fr, this); + return new CalculationResult(far, this); } @Override @@ -393,58 +280,5 @@ return results; } - - /** Fetch meta and data columns for analysis periods. */ - protected Column [][] getAnalysisColumns(FixingsOverview overview) { - - boolean debug = log.isDebugEnabled(); - if (debug) { - log.debug("number analysis periods: " + analysisPeriods.length); - } - - Column columns [][] = new Column[analysisPeriods.length][]; - - Range range = new Range(from, to); - SectorRangeFilter sectorRangeFilter = - new SectorRangeFilter(qSectorStart, qSectorEnd); - - FixingsColumnFactory fcf = FixingsColumnFactory.getInstance(); - - for (int i = 0; i < columns.length; ++i) { - - // Construct filter for period. - DateRange period = analysisPeriods[i]; - - DateRangeFilter dateRangeFilter = - new DateRangeFilter(period.getFrom(), period.getTo()); - - Filter filter = new AndFilter() - .add(dateRangeFilter) - .add(sectorRangeFilter); - - List metaCols = overview.filter(range, filter); - - if (debug) { - log.debug("number of filtered columns: " + metaCols.size()); - } - - ArrayList cols = new ArrayList(metaCols.size()); - - // Only use columns which have data. - for (Fixing.Column meta: metaCols) { - FixingsColumn data = fcf.getColumnData(meta); - if (data != null) { - cols.add(new Column(meta, data)); - } - } - - if (debug) { - log.debug("failed loading: " + (metaCols.size()-cols.size())); - } - columns[i] = cols.toArray(new Column[cols.size()]); - } - - return columns; - } } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 1a636be7612b -r 262e7d7e58fe flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/FixCalculation.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/FixCalculation.java Sun Jul 22 09:49:56 2012 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/FixCalculation.java Sun Jul 22 10:38:30 2012 +0000 @@ -1,7 +1,11 @@ package de.intevation.flys.artifacts.model.fixings; +import de.intevation.artifacts.common.utils.StringUtils; + import de.intevation.flys.artifacts.access.FixAccess; +import de.intevation.flys.artifacts.math.fitting.Function; + import de.intevation.flys.artifacts.model.Calculation; import de.intevation.flys.artifacts.model.FixingsColumn; import de.intevation.flys.artifacts.model.FixingsColumnFactory; @@ -12,6 +16,10 @@ import de.intevation.flys.artifacts.model.FixingsOverview.IdsFilter; import de.intevation.flys.artifacts.model.FixingsOverview; +import de.intevation.flys.artifacts.model.Parameters; + +import de.intevation.flys.utils.DoubleUtil; +import de.intevation.flys.utils.KMIndex; import java.util.ArrayList; import java.util.Date; @@ -26,6 +34,44 @@ { private static Logger log = Logger.getLogger(FixCalculation.class); + public static final double EPSILON = 1e-4; + + public static final String [] STANDARD_COLUMNS = { + "km", "chi_sqr", "max_q", "std-dev" + }; + + protected static class FitResult { + + protected Parameters parameters; + protected KMIndex referenced; + protected KMIndex outliers; + + public FitResult() { + } + + public FitResult( + Parameters parameters, + KMIndex referenced, + KMIndex outliers + ) { + this.parameters = parameters; + this.referenced = referenced; + this.outliers = outliers; + } + + public Parameters getParameters() { + return parameters; + } + + public KMIndex getReferenced() { + return referenced; + } + + public KMIndex getOutliers() { + return outliers; + } + } // class FitResult + /** Helper class to bundle the meta information of a column * and the real data. */ @@ -208,5 +254,124 @@ return columns; } + + protected FitResult doFitting(FixingsOverview overview, Function func) { + + boolean debug = log.isDebugEnabled(); + + final List eventColumns = getEventColumns(overview); + + if (eventColumns.size() < 2) { + addProblem("fix.too.less.data.columns"); + return null; + } + + final double [] qs = new double[eventColumns.size()]; + final double [] ws = new double[qs.length]; + final boolean [] interpolated = new boolean[ws.length]; + + Fitting.QWDFactory qwdFactory = new Fitting.QWDFactory() { + @Override + public QWD create(double q, double w) { + // Check all the event columns for close match + // and take the description and the date from meta. + for (int i = 0; i < qs.length; ++i) { + if (Math.abs(qs[i]-q) < EPSILON + && Math.abs(ws[i]-w) < EPSILON) { + Column column = eventColumns.get(i); + return new QWD( + qs[i], ws[i], + column.getDescription(), + column.getDate(), + interpolated[i], + 0d); + } + } + log.warn("cannot find column for (" + q + ", " + w + ")"); + return new QWD(q, w); + } + }; + + Fitting fitting = new Fitting(func, qwdFactory, preprocessing); + + String [] parameterNames = func.getParameterNames(); + + Parameters results = + new Parameters( + StringUtils.join(STANDARD_COLUMNS, parameterNames)); + + boolean invalid = false; + + double [] kms = DoubleUtil.explode(from, to, step / 1000.0); + + if (debug) { + log.debug("number of kms: " + kms.length); + } + + KMIndex outliers = new KMIndex(); + KMIndex referenced = new KMIndex(kms.length); + + int kmIndex = results.columnIndex("km"); + int chiSqrIndex = results.columnIndex("chi_sqr"); + int maxQIndex = results.columnIndex("max_q"); + int stdDevIndex = results.columnIndex("std-dev"); + int [] parameterIndices = results.columnIndices(parameterNames); + + int numFailed = 0; + + for (int i = 0; i < kms.length; ++i) { + double km = kms[i]; + + // Fill Qs and Ws from event columns. + for (int j = 0; j < ws.length; ++j) { + interpolated[j] = !eventColumns.get(j).getQW(km, qs, ws, j); + } + + fitting.reset(); + + if (!fitting.fit(qs, ws)) { + ++numFailed; + addProblem(km, "fix.fitting.failed"); + continue; + } + + referenced.add(km, fitting.referencedToArray()); + + if (fitting.hasOutliers()) { + outliers.add(km, fitting.outliersToArray()); + } + + int row = results.newRow(); + double [] values = fitting.getParameters(); + + results.set(row, kmIndex, km); + results.set(row, chiSqrIndex, fitting.getChiSquare()); + results.set(row, stdDevIndex, fitting.getStandardDeviation()); + results.set(row, maxQIndex, fitting.getMaxQ()); + invalid |= results.set(row, parameterIndices, values); + + if (debug) { + log.debug("km: "+km+" " + toString(parameterNames, values)); + } + } + + if (debug) { + log.debug("success: " + (kms.length - numFailed)); + log.debug("failed: " + numFailed); + } + + if (invalid) { + addProblem("fix.invalid.values"); + results.removeNaNs(); + } + + outliers.sort(); + referenced.sort(); + + return new FitResult( + results, + referenced, + outliers); + } } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :