Mercurial > dive4elements > river
view flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/FixCalculation.java @ 4255:670e98f5a441
Fixed leak while merging facets.
The ThemeList that is used by OutputHelper to sort the
Facets for an Output now uses a list to store the ManagedFacets.
The correct order is made up by sorting the List using
Collections.sort() function of the Java JDK. Therfore, the
ManagedFacet class implements the Comparable interface. The
return value of its compareTo(other) method depends on the
value of the 'position' field.
author | Ingo Weinzierl <weinzierl.ingo@googlemail.com> |
---|---|
date | Thu, 25 Oct 2012 14:01:46 +0200 |
parents | 3cda41b5eb23 |
children | 345f3bba6f15 |
line wrap: on
line source
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.math.fitting.FunctionFactory; import de.intevation.flys.artifacts.model.Calculation; import de.intevation.flys.artifacts.model.CalculationResult; import de.intevation.flys.artifacts.model.FixingsColumn; import de.intevation.flys.artifacts.model.FixingsColumnFactory; import de.intevation.flys.artifacts.model.FixingsOverview.Fixing.Filter; import de.intevation.flys.artifacts.model.FixingsOverview.Fixing; import de.intevation.flys.artifacts.model.FixingsOverview.IdsFilter; import de.intevation.flys.artifacts.model.FixingsOverview; import de.intevation.flys.artifacts.model.FixingsOverviewFactory; 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; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.log4j.Logger; public abstract class FixCalculation extends Calculation { 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<QWD []> referenced; protected KMIndex<QWI []> outliers; public FitResult() { } public FitResult( Parameters parameters, KMIndex<QWD []> referenced, KMIndex<QWI []> outliers ) { this.parameters = parameters; this.referenced = referenced; this.outliers = outliers; } public Parameters getParameters() { return parameters; } public KMIndex<QWD []> getReferenced() { return referenced; } public KMIndex<QWI []> getOutliers() { return outliers; } } // class FitResult /** Helper class to bundle the meta information of a column * and the real data. */ protected static class Column { protected Fixing.Column meta; protected FixingsColumn data; protected int index; public Column() { } public Column(Fixing.Column meta, FixingsColumn data, int index) { this.meta = meta; this.data = data; this.index = index; } public Date getDate() { return meta.getStartTime(); } public String getDescription() { return meta.getDescription(); } public int getIndex() { return index; } public boolean getQW( double km, double [] qs, double [] ws, int index ) { qs[index] = data.getQ(km); return data.getW(km, ws, index); } public boolean getQW(double km, double [] wq) { data.getW(km, wq, 0); if (Double.isNaN(wq[0])) return false; wq[1] = data.getQ(km); return !Double.isNaN(wq[1]); } } // class Column /** * Helper class to find the data belonging to meta info more quickly. */ protected static class ColumnCache { protected Map<Integer, Column> columns; public ColumnCache() { columns = new HashMap<Integer, Column>(); } public Column getColumn(Fixing.Column meta) { Integer key = meta.getId(); Column column = columns.get(key); if (column == null) { FixingsColumn data = FixingsColumnFactory .getInstance() .getColumnData(meta); if (data != null) { column = new Column(meta, data, columns.size()); columns.put(key, column); } } return column; } } // class ColumnCache protected String river; protected double from; protected double to; protected double step; protected boolean preprocessing; protected String function; protected int [] events; protected int qSectorStart; protected int qSectorEnd; public FixCalculation() { } public FixCalculation(FixAccess access) { String river = access.getRiver(); Double from = access.getFrom(); Double to = access.getTo(); Double step = access.getStep(); String function = access.getFunction(); int [] events = access.getEvents(); Integer qSectorStart = access.getQSectorStart(); Integer qSectorEnd = access.getQSectorEnd(); Boolean preprocessing = access.getPreprocessing(); if (river == null) { addProblem("fix.missing.river"); } if (from == null) { addProblem("fix.missing.from"); } if (to == null) { addProblem("fix.missing.to"); } if (step == null) { addProblem("fix.missing.step"); } if (function == null) { addProblem("fix.missing.function"); } if (events == null || events.length < 1) { addProblem("fix.missing.events"); } if (qSectorStart == null) { addProblem("fix.missing.qstart.sector"); } if (qSectorEnd == null) { addProblem("fix.missing.qend.sector"); } if (preprocessing == null) { addProblem("fix.missing.preprocessing"); } if (!hasProblems()) { this.river = river; this.from = from; this.to = to; this.step = step; this.function = function; this.events = events; this.qSectorStart = qSectorStart; this.qSectorEnd = qSectorEnd; this.preprocessing = preprocessing; } } protected static String toString( String [] parameterNames, double [] values ) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < parameterNames.length; ++i) { if (i > 0) sb.append(", "); sb.append(parameterNames[i]).append(": ").append(values[i]); } return sb.toString(); } protected Filter createFilter() { return new IdsFilter(events); } protected List<Column> getEventColumns( FixingsOverview overview, ColumnCache cc ) { FixingsColumnFactory fcf = FixingsColumnFactory.getInstance(); Filter filter = createFilter(); List<Fixing.Column> metas = overview.filter(null, filter); List<Column> columns = new ArrayList<Column>(metas.size()); for (Fixing.Column meta: metas) { Column data = cc.getColumn(meta); if (data == null) { addProblem("fix.cannot.load.data"); } else { columns.add(data); } } return columns; } protected FitResult doFitting( FixingsOverview overview, ColumnCache cc, Function func ) { boolean debug = log.isDebugEnabled(); final List<Column> eventColumns = getEventColumns(overview, cc); 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, column.getIndex()); } } 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<QWI []> outliers = new KMIndex<QWI []>(); KMIndex<QWD []> referenced = new KMIndex<QWD []>(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); } public CalculationResult calculate() { FixingsOverview overview = FixingsOverviewFactory.getOverview(river); if (overview == null) { addProblem("fix.no.overview.available"); } Function func = FunctionFactory.getInstance() .getFunction(function); if (func == null) { addProblem("fix.invalid.function.name"); } if (hasProblems()) { return new CalculationResult(this); } return innerCalculate(overview, func); } protected abstract CalculationResult innerCalculate( FixingsOverview overview, Function function ); } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :