# HG changeset patch # User Felix Wolfsteller # Date 1376902552 -7200 # Node ID 8d98e18258462e2269a7a475242642bf957e9304 # Parent 9e81ed5650950c3e7a8abb59619f6d5186376d9e# Parent aa14ae10a85361b55dc4befe04e8d50e5a2013b9 Merged backout of changes for 1440 (gap-detection in bedquality). diff -r aa14ae10a853 -r 8d98e1825846 artifacts/doc/conf/artifacts/winfo.xml --- a/artifacts/doc/conf/artifacts/winfo.xml Mon Aug 19 10:55:13 2013 +0200 +++ b/artifacts/doc/conf/artifacts/winfo.xml Mon Aug 19 10:55:52 2013 +0200 @@ -326,6 +326,8 @@ + + @@ -382,6 +384,8 @@ + + @@ -638,6 +642,7 @@ + diff -r aa14ae10a853 -r 8d98e1825846 artifacts/doc/conf/jasper/sqrelation.jasper Binary file artifacts/doc/conf/jasper/sqrelation.jasper has changed diff -r aa14ae10a853 -r 8d98e1825846 artifacts/doc/conf/jasper/sqrelation_en.jasper Binary file artifacts/doc/conf/jasper/sqrelation_en.jasper has changed diff -r aa14ae10a853 -r 8d98e1825846 artifacts/doc/conf/mapserver/barrier_lines_class.vm --- a/artifacts/doc/conf/mapserver/barrier_lines_class.vm Mon Aug 19 10:55:13 2013 +0200 +++ b/artifacts/doc/conf/mapserver/barrier_lines_class.vm Mon Aug 19 10:55:52 2013 +0200 @@ -1,6 +1,6 @@ CLASS NAME "Damm" - EXPRESSION ("[TYP]"="Damm") + EXPRESSION /damm/i STYLE SIZE 5 OUTLINECOLOR "#008000" @@ -8,7 +8,7 @@ END CLASS NAME "Rohr 1" - EXPRESSION ("[TYP]"="Rohr 1") + EXPRESSION /rohr.1/i STYLE SIZE 5 OUTLINECOLOR "#800080" @@ -16,7 +16,7 @@ END CLASS NAME "Rohr 2" - EXPRESSION ("[TYP]"="Rohr 2") + EXPRESSION /rohr.2/i STYLE SIZE 5 OUTLINECOLOR "#808080" @@ -24,7 +24,7 @@ END CLASS NAME "Graben" - EXPRESSION ("[TYP]"="Graben") + EXPRESSION /graben/i STYLE SIZE 5 OUTLINECOLOR "#800000" @@ -32,7 +32,7 @@ END CLASS NAME "Ringdeich" - EXPRESSION ("[TYP]"="Ringdeich") + EXPRESSION /ringdeich/i STYLE SIZE 5 OUTLINECOLOR "#800000" diff -r aa14ae10a853 -r 8d98e1825846 artifacts/doc/conf/mapserver/barrier_polygons_class.vm --- a/artifacts/doc/conf/mapserver/barrier_polygons_class.vm Mon Aug 19 10:55:13 2013 +0200 +++ b/artifacts/doc/conf/mapserver/barrier_polygons_class.vm Mon Aug 19 10:55:52 2013 +0200 @@ -1,6 +1,6 @@ CLASS NAME "Ringdeich" - EXPRESSION ("[TYP]"="Ringdeich") + EXPRESSION /ringdeich/i STYLE SIZE 5 OUTLINECOLOR "#FF8000" diff -r aa14ae10a853 -r 8d98e1825846 artifacts/doc/conf/mapserver/shapefile_layer.vm --- a/artifacts/doc/conf/mapserver/shapefile_layer.vm Mon Aug 19 10:55:13 2013 +0200 +++ b/artifacts/doc/conf/mapserver/shapefile_layer.vm Mon Aug 19 10:55:52 2013 +0200 @@ -21,6 +21,8 @@ "wms_group_title" "$LAYER.getGroupTitle()" #end END + + CLASSITEM "TYP" #if ( !$LAYER.getStyle() ) #if ( $LAYER.getGroupTitle() ) diff -r aa14ae10a853 -r 8d98e1825846 artifacts/doc/conf/meta-data.xml --- a/artifacts/doc/conf/meta-data.xml Mon Aug 19 10:55:13 2013 +0200 +++ b/artifacts/doc/conf/meta-data.xml Mon Aug 19 10:55:52 2013 +0200 @@ -353,6 +353,7 @@ + @@ -401,6 +402,7 @@ + @@ -485,22 +487,23 @@ + SELECT g.id AS gauge_id, - g.name AS gauge_name, - dt.id AS dt_id, - t.start_time AS start_time, - t.stop_time AS stop_time, - dt.description AS desc, - dt.bfg_id AS bfg_id + g.name AS gauge_name, + dt.id AS dt_id, + t.start_time AS start_time, + t.stop_time AS stop_time, + dt.description AS desc, + dt.bfg_id AS bfg_id FROM gauges g JOIN discharge_tables dt ON g.id = dt.gauge_id LEFT JOIN time_intervals t ON dt.time_interval_id = t.id WHERE g.river_id = ${river_id} AND dt.kind <> 0 - AND g.station = ${fromkm} - AND g.station = ${tokm} + AND ((g.station = ${fromkm} AND g.station = ${tokm}) + OR g.official_number = ${refgauge}) ORDER BY start_time @@ -508,9 +511,6 @@ - - Hallo ANDRE23 {dc:dump-variables()} - - - - - - + + + diff -r aa14ae10a853 -r 8d98e1825846 artifacts/doc/conf/themes.xml --- a/artifacts/doc/conf/themes.xml Mon Aug 19 10:55:13 2013 +0200 +++ b/artifacts/doc/conf/themes.xml Mon Aug 19 10:55:52 2013 +0200 @@ -273,6 +273,7 @@ + diff -r aa14ae10a853 -r 8d98e1825846 artifacts/doc/conf/themes/default.xml --- a/artifacts/doc/conf/themes/default.xml Mon Aug 19 10:55:13 2013 +0200 +++ b/artifacts/doc/conf/themes/default.xml Mon Aug 19 10:55:52 2013 +0200 @@ -1459,6 +1459,20 @@ + + + + + + + + + + + @@ -1561,9 +1575,21 @@ + + + + + + + + + + - + - + - + - + + + + + + + + + + + + @@ -28,20 +42,6 @@ - - - - - - - - - - - @@ -843,7 +843,7 @@ + default="1" /> + + + + + + + + + + + @@ -1561,9 +1575,21 @@ + + + + + + + + + + - + - + - + - + { + + public KMRangeLoader(List columns, Session session) { + super(columns, session, SQL_FIXING_COLUMN_KM_RANGE_BATCH); + } + + @Override + protected void fill(SQLQuery query) { + query + .addScalar("wst_column_id", StandardBasicTypes.INTEGER) + .addScalar("start_km", StandardBasicTypes.DOUBLE) + .addScalar("stop_km", StandardBasicTypes.DOUBLE); + + List ranges = query.list(); + for (Object [] r: ranges) { + Integer cid = (Integer)r[0]; + double [] vs = new double [] { (Double)r[1], (Double)r[2] }; + cache(cid, vs); + } + } + } // class KMRangeLoader + + public static final class ColumnQRangeLoader extends BatchLoader> { + + public ColumnQRangeLoader(List columns, Session session) { + super(columns, session, SQL_FIXING_COLUMN_Q_RANGES_BATCH); + } + + @Override + protected void fill(SQLQuery query) { + query + .addScalar("wst_column_id", StandardBasicTypes.INTEGER) + .addScalar("q", StandardBasicTypes.DOUBLE) + .addScalar("start_km", StandardBasicTypes.DOUBLE) + .addScalar("stop_km", StandardBasicTypes.DOUBLE); + + int lastId = Integer.MIN_VALUE; + List column = new ArrayList(); + + List ranges = query.list(); + for (Object [] r: ranges) { + int cid = (Integer)r[0]; + + if (cid != lastId && !column.isEmpty()) { + cache(lastId, column); + column = new ArrayList(); + } + column.add(new double [] { + (Double)r[1], + (Double)r[2], + (Double)r[3] + }); + + lastId = cid; + } + + if (!column.isEmpty()) { + cache(lastId, column); + } + } + } // class ColumnQRangeLoader + + /** Helper class to store data from batching fixing columns. */ + private static final class FixColumn { + int columnId; + Date startTime; + String name; + + FixColumn(int columnId, Date startTime, String name) { + this.columnId = columnId; + this.startTime = startTime; + this.name = name; + } + } // class FixColumn + + public static final class FixColumnLoader extends BatchLoader> { + + public FixColumnLoader(List columns, Session session) { + super(columns, session, SQL_FIXING_COLUMNS_BATCH); + } + + @Override + protected void fill(SQLQuery query) { + query + .addScalar("wst_id", StandardBasicTypes.INTEGER) + .addScalar("wst_column_id", StandardBasicTypes.INTEGER) + .addScalar("start_time", StandardBasicTypes.DATE) + .addScalar("name", StandardBasicTypes.STRING); + + int lastId = Integer.MIN_VALUE; + List cols = new ArrayList(); + + List columns = query.list(); + for (Object [] c: columns) { + int wid = (Integer)c[0]; + + if (wid != lastId && !cols.isEmpty()) { + cache(lastId, cols); + cols = new ArrayList(); + } + cols.add(new FixColumn( + (Integer)c[1], + (Date) c[2], + (String) c[3])); + + lastId = wid; + } + if (!cols.isEmpty()) { + cache(lastId, cols); + } + } + } // class FixColumnLoader public static class QRange extends Range { @@ -255,34 +372,35 @@ } // for all Q ranges } - public void loadKmRange(SQLQuery query) { - query.setInteger("column_id", columnId); - - List kms = query.list(); + public void loadKmRange(KMRangeLoader loader) { - if (kms.isEmpty()) { + double [] range = loader.get(columnId); + + if (range == null) { log.warn("No km range for column " + columnId + "."); + return; } - else { - Object [] obj = kms.get(0); - start = (Double)obj[0]; - end = (Double)obj[1]; - } + start = range[0]; + end = range[1]; } public void loadQRanges( - SQLQuery query, - GaugeFinder gaugeFinder + ColumnQRangeLoader loader, + GaugeFinder gaugeFinder ) { - query.setInteger("column_id", columnId); - List list = query.list(); + List qrs = loader.get(columnId); + if (qrs == null) { + log.warn("No q ranges found for column " + columnId); + return; + } - List qRanges = new ArrayList(list.size()); + List qRanges = new ArrayList(qrs.size()); - for (Object [] row: list) { - double q = (Double)row[0]; - double start = (Double)row[1]; - double end = (Double)row[2]; + for (double [] qr: qrs) { + double q = qr[0]; + double start = qr[1]; + double end = qr[2]; + QRange qRange = new QRange(start, end, q); if (qRange.clip(this)) { qRanges.add(qRange); @@ -314,20 +432,26 @@ columns = new ArrayList(); } - public void loadColumns(SQLQuery query) { - query.setInteger("wst_id", wstId); - List list = query.list(); - for (Object [] row: list) { - int columnId = (Integer)row[0]; - Date startTime = (Date) row[1]; - String name = (String) row[2]; - columns.add(new Column(columnId, startTime, name)); + public void allColumnIds(List cIds) { + for (Column column: columns) { + cIds.add(column.columnId); } } - public void loadColumnsKmRange(SQLQuery query) { + public void loadColumns(FixColumnLoader loader) { + List fcs = loader.get(wstId); + if (fcs == null) { + log.warn("No columns for wst " + wstId); + return; + } + for (FixColumn fc: fcs) { + columns.add(new Column(fc.columnId, fc.startTime, fc.name)); + } + } + + public void loadColumnsKmRange(KMRangeLoader loader) { for (Column column: columns) { - column.loadKmRange(query); + column.loadKmRange(loader); } } @@ -338,11 +462,11 @@ } public void loadColumnsQRanges( - SQLQuery query, - GaugeFinder gaugeFinder + ColumnQRangeLoader loader, + GaugeFinder gaugeFinder ) { for (Column column: columns) { - column.loadQRanges(query, gaugeFinder); + column.loadQRanges(loader, gaugeFinder); } } @@ -427,23 +551,40 @@ } protected void loadFixingsColumns(Session session) { - SQLQuery query = session.createSQLQuery(SQL_FIXING_COLUMNS) - .addScalar("wst_column_id", StandardBasicTypes.INTEGER) - .addScalar("start_time", StandardBasicTypes.DATE) - .addScalar("name", StandardBasicTypes.STRING); + + FixColumnLoader loader = new FixColumnLoader( + allFixingIds(), + session); for (Fixing fixing: fixings) { - fixing.loadColumns(query); + fixing.loadColumns(loader); } } + protected List allFixingIds() { + List ids = new ArrayList(fixings.size()); + for (Fixing fixing: fixings) { + ids.add(fixing.getId()); + } + return ids; + } + + protected List allColumnIds() { + List cIds = new ArrayList(); + for (Fixing fixing: fixings) { + fixing.allColumnIds(cIds); + } + return cIds; + } + protected void loadFixingsColumnsKmRange(Session session) { - SQLQuery query = session.createSQLQuery(SQL_FIXING_COLUMN_KM_RANGE) - .addScalar("start_km", StandardBasicTypes.DOUBLE) - .addScalar("stop_km", StandardBasicTypes.DOUBLE); + + KMRangeLoader loader = new KMRangeLoader( + allColumnIds(), + session); for (Fixing fixing: fixings) { - fixing.loadColumnsKmRange(query); + fixing.loadColumnsKmRange(loader); } } @@ -451,13 +592,13 @@ Session session, GaugeFinder gaugeFinder ) { - SQLQuery query = session.createSQLQuery(SQL_FIXING_COLUMN_Q_RANGES) - .addScalar("q", StandardBasicTypes.DOUBLE) - .addScalar("start_km", StandardBasicTypes.DOUBLE) - .addScalar("stop_km", StandardBasicTypes.DOUBLE); + + ColumnQRangeLoader loader = new ColumnQRangeLoader( + allColumnIds(), + session); for (Fixing fixing: fixings) { - fixing.loadColumnsQRanges(query, gaugeFinder); + fixing.loadColumnsQRanges(loader, gaugeFinder); } } diff -r aa14ae10a853 -r 8d98e1825846 artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/QualityMeasurementFactory.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/QualityMeasurementFactory.java Mon Aug 19 10:55:13 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/QualityMeasurementFactory.java Mon Aug 19 10:55:52 2013 +0200 @@ -97,6 +97,7 @@ private QualityMeasurementResultTransformer() { } + /** tuples is a row. */ @Override public Object transformTuple(Object[] tuple, String[] aliases) { Map map = new HashMap(); @@ -175,6 +176,7 @@ return new QualityMeasurements(query.list()); } + /** Get all measurements. */ public static QualityMeasurements getBedMeasurements( String river, double from, diff -r aa14ae10a853 -r 8d98e1825846 artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentLoadFactory.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentLoadFactory.java Mon Aug 19 10:55:13 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentLoadFactory.java Mon Aug 19 10:55:52 2013 +0200 @@ -395,19 +395,24 @@ sqlQuery.setString("grain", "total"); List results = sqlQuery.list(); SedimentLoad load = new SedimentLoad(); - Object[] row = results.get(0); - load = new SedimentLoad( - (String) row[0], - (Date) row[1], - null, - false, - (String) row[4]); - getValues("coarse", sqlQuery, load, floatStations); - getValues("fine_middle", sqlQuery, load, floatStations); - getValues("sand", sqlQuery, load, floatStations); - getValues("suspended_sediment", sqlQuery, load, suspStations); - getValues("susp_sand_bed", sqlQuery, load, floatStations); - getValues("susp_sand", sqlQuery, load, floatStations); + if (results.isEmpty()) { + log.warn("Empty result for year calculation."); + } + else { + Object[] row = results.get(0); + load = new SedimentLoad( + (String) row[0], + (Date) row[1], + null, + false, + (String) row[4]); + } + load = getValues("coarse", sqlQuery, load, floatStations); + load = getValues("fine_middle", sqlQuery, load, floatStations); + load = getValues("sand", sqlQuery, load, floatStations); + load = getValues("suspended_sediment", sqlQuery, load, suspStations); + load = getValues("susp_sand_bed", sqlQuery, load, floatStations); + load = getValues("susp_sand", sqlQuery, load, floatStations); return load; } @@ -628,6 +633,7 @@ /** * Return sediment loads with 'unknown' fraction type. + * @param river Name of the river * @param unit Restrict result set to those of given unit. * @param type Type like year, epoch, off_epoch */ diff -r aa14ae10a853 -r 8d98e1825846 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 Mon Aug 19 10:55:13 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/Fitting.java Mon Aug 19 10:55:52 2013 +0200 @@ -8,8 +8,8 @@ package org.dive4elements.river.artifacts.model.sq; +import org.dive4elements.artifacts.common.utils.StringUtils; import org.dive4elements.river.artifacts.math.fitting.Function; -import org.dive4elements.river.artifacts.math.fitting.Linear; import java.util.ArrayList; import java.util.List; @@ -18,9 +18,8 @@ import org.apache.commons.math.optimization.fitting.CurveFitter; -import org.apache.commons.math.optimization.general.AbstractLeastSquaresOptimizer; -import org.apache.commons.math.optimization.general.GaussNewtonOptimizer; import org.apache.commons.math.optimization.general.LevenbergMarquardtOptimizer; +import org.apache.commons.math.stat.regression.SimpleRegression; import org.apache.log4j.Logger; @@ -54,13 +53,15 @@ protected Callback callback; + protected SQ.View sqView; + public Fitting() { } - public Fitting(Function function, double stdDevFactor) { - this(); + public Fitting(Function function, double stdDevFactor, SQ.View sqView) { this.function = function; this.stdDevFactor = stdDevFactor; + this.sqView = sqView; } public Function getFunction() { @@ -82,57 +83,84 @@ @Override public void initialize(List sqs) throws MathException { - AbstractLeastSquaresOptimizer optimizer = getOptimizer(); + if (USE_NON_LINEAR_FITTING + || function.getParameterNames().length != 2) { + nonLinearFitting(sqs); + } + else { + linearFitting(sqs); + } + } + + protected void linearFitting(List sqs) { + coeffs = linearRegression(sqs); + instance = function.instantiate(coeffs); + } + + protected double [] linearRegression(List 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(); + + for (SQ sq: sqs) { + double s = sqView.getS(sq); + double q = sqView.getQ(sq); + reg.addData(q, s); + } + + double m = reg.getIntercept(); + double b = reg.getSlope(); + + if (log.isDebugEnabled()) { + log.debug("m: " + m); + log.debug("b: " + 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; + } + + + protected void nonLinearFitting(List sqs) throws MathException { + + LevenbergMarquardtOptimizer optimizer = + new LevenbergMarquardtOptimizer(); CurveFitter cf = new CurveFitter(optimizer); - double [] values = new double[2]; + for (SQ sq: sqs) { - values[0] = sq.getQ(); - values[1] = sq.getS(); - transformInputValues(values); - cf.addObservedPoint(values[0], values[1]); + cf.addObservedPoint(sqView.getQ(sq), sqView.getS(sq)); } coeffs = cf.fit( function, function.getInitialGuess()); - transformCoeffsBack(coeffs); - instance = function.instantiate(coeffs); chiSqr = optimizer.getChiSquare(); } - protected Function getFunction(Function function) { - return USE_NON_LINEAR_FITTING - ? function - : Linear.INSTANCE; - } - - protected void transformInputValues(double [] values) { - if (!USE_NON_LINEAR_FITTING) { - for (int i = 0; i < values.length; ++i) { - values[i] = Math.log(values[i]); - } - } - } - - protected AbstractLeastSquaresOptimizer getOptimizer() { - return USE_NON_LINEAR_FITTING - ? new LevenbergMarquardtOptimizer() - : new GaussNewtonOptimizer(false); - } - - protected void transformCoeffsBack(double [] coeffs) { - if (!USE_NON_LINEAR_FITTING && coeffs.length > 0) { - coeffs[0] = Math.exp(coeffs[0]); - } - } - @Override public double eval(SQ sq) { - double s = instance.value(sq.q); - return sq.s - s; + double s = instance.value(sqView.getQ(sq)); + return sqView.getS(sq) - s; } @Override @@ -157,28 +185,15 @@ chiSqr); } - protected static final List onlyValid(List sqs) { - - List good = new ArrayList(sqs.size()); - - for (SQ sq: sqs) { - if (sq.isValid()) { - good.add(sq); - } - } - - return good; - } - - public boolean fit(List sqs, String method, Callback callback) { - - sqs = onlyValid(sqs); + public boolean fit(List sqs, String method, Callback callback) { if (sqs.size() < 2) { log.warn("Too less points for fitting."); return false; } + sqs = new ArrayList(sqs); + this.callback = callback; try { diff -r aa14ae10a853 -r 8d98e1825846 artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/LogSQ.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/LogSQ.java Mon Aug 19 10:55:52 2013 +0200 @@ -0,0 +1,68 @@ +/* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde + * Software engineering by Intevation GmbH + * + * This file is Free Software under the GNU AGPL (>=v3) + * and comes with ABSOLUTELY NO WARRANTY! Check out the + * documentation coming with Dive4Elements River for details. + */ + +package org.dive4elements.river.artifacts.model.sq; + +public class LogSQ extends SQ { + + public static final View LOG_SQ_VIEW = new View() { + @Override + public double getS(SQ sq) { + return ((LogSQ)sq).getLogS(); + } + + @Override + public double getQ(SQ sq) { + return ((LogSQ)sq).getLogQ(); + } + }; + + public static final Factory LOG_SQ_FACTORY = new Factory() { + @Override + public SQ createSQ(double s, double q) { + return new LogSQ(s, q); + } + }; + + protected double logS; + protected double logQ; + + protected boolean logTrans; + + public LogSQ() { + } + + public LogSQ(double s, double q) { + super(s, q); + } + + /** important: We cannot process negative s/q. */ + @Override + public boolean isValid() { + return super.isValid() && s > 0d && q > 0d; + } + + protected void ensureLogTrans() { + if (!logTrans) { + logTrans = true; + logS = Math.log(s); + logQ = Math.log(q); + } + } + + public double getLogS() { + ensureLogTrans(); + return logS; + } + + public double getLogQ() { + ensureLogTrans(); + return logQ; + } +} + diff -r aa14ae10a853 -r 8d98e1825846 artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/MeasurementFactory.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/MeasurementFactory.java Mon Aug 19 10:55:13 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/MeasurementFactory.java Mon Aug 19 10:55:52 2013 +0200 @@ -190,9 +190,10 @@ } public static Measurements getMeasurements( - String river, - double location, - DateRange dateRange + String river, + double location, + DateRange dateRange, + SQ.Factory sqFactory ) { Session session = SedDBSessionHolder.HOLDER.get(); try { @@ -202,7 +203,7 @@ List accumulated = loadFractions( session, river, location, dateRange); - return new Measurements(totals, accumulated); + return new Measurements(totals, accumulated, sqFactory); } finally { session.close(); diff -r aa14ae10a853 -r 8d98e1825846 artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/Measurements.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/Measurements.java Mon Aug 19 10:55:13 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/Measurements.java Mon Aug 19 10:55:52 2013 +0200 @@ -66,13 +66,17 @@ protected List measuments; protected List accumulated; + protected SQ.Factory sqFactory; + public Measurements() { } public Measurements( List measuments, - List accumulated + List accumulated, + SQ.Factory sqFactory ) { + this.sqFactory = sqFactory; if (log.isDebugEnabled()) { log.debug("number of measuments: " + measuments.size()); log.debug("number of accumulated: " + accumulated.size()); @@ -81,14 +85,14 @@ this.accumulated = accumulated; } - public static List extractSQ( + public List extractSQ( List measuments, SExtractor extractor ) { List result = new ArrayList(measuments.size()); int invalid = 0; for (Measurement measument: measuments) { - SQ sq = new SQ(extractor.getS(measument), measument.Q()); + SQ sq = sqFactory.createSQ(extractor.getS(measument), measument.Q()); if (sq.isValid()) { result.add(sq); } diff -r aa14ae10a853 -r 8d98e1825846 artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/SQ.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/SQ.java Mon Aug 19 10:55:13 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/SQ.java Mon Aug 19 10:55:52 2013 +0200 @@ -11,8 +11,37 @@ import java.io.Serializable; +/** Represents S/Q pairs. They are immutable! */ public class SQ implements Serializable { + public interface Factory { + SQ createSQ(double s, double q); + } + + public static final Factory SQ_FACTORY = new Factory() { + @Override + public SQ createSQ(double s, double q) { + return new SQ(s, q); + } + }; + + public interface View { + double getS(SQ sq); + double getQ(SQ sq); + } + + public static final View SQ_VIEW = new View() { + @Override + public double getS(SQ sq) { + return sq.getS(); + } + + @Override + public double getQ(SQ sq) { + return sq.getQ(); + } + }; + protected double s; protected double q; @@ -29,19 +58,10 @@ return s; } - public void setS(double s) { - this.s = s; - } - - public double getQ() { return q; } - public void setQ(double q) { - this.q = q; - } - public boolean isValid() { return !Double.isNaN(s) && !Double.isNaN(q); } diff -r aa14ae10a853 -r 8d98e1825846 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 Mon Aug 19 10:55:13 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/SQRelationCalculation.java Mon Aug 19 10:55:52 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,20 @@ 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"; + + public static final String [] EXTRA_PARAMETERS = { + "chi_sqr", + "std_dev", + "max_q", + "c_ferguson", + "c_duan", + "r2" + }; protected String river; protected double location; @@ -49,8 +64,6 @@ Double outliers = access.getOutliers(); String method = access.getOutlierMethod(); - //river = "Rhein"; - if (river == null) { // TODO: i18n addProblem("sq.missing.river"); @@ -102,31 +115,95 @@ } } + 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); + } + + 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(), + powFunction, + sqView); + } + 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(), + function, + sqView); } Measurements measurements = - MeasurementFactory.getMeasurements(river, location, period); + MeasurementFactory.getMeasurements( + river, location, period, sqFactory); SQFractionResult [] fractionResults = new SQFractionResult[SQResult.NUMBER_FRACTIONS]; + for (int i = 0; i < fractionResults.length; ++i) { List sqs = measurements.getSQs(i); SQFractionResult fractionResult; List iterations = - doFitting(function, sqs); + doFitting(function, sqs, sqView, pc); if (iterations == null) { // TODO: i18n @@ -148,13 +225,15 @@ } protected List doFitting( - final Function function, - List sqs + final Function function, + List sqs, + SQ.View sqView, + final ParameterCreator pc ) { final List iterations = new ArrayList(); - boolean success = new Fitting(function, outliers).fit( + boolean success = new Fitting(function, outliers, sqView).fit( sqs, method, new Fitting.Callback() { @@ -166,11 +245,11 @@ double standardDeviation, double chiSqr ) { - Parameters parameters = createParameters( - function.getParameterNames(), + Parameters parameters = pc.createParameters( coeffs, standardDeviation, - chiSqr); + chiSqr, + measurements); iterations.add(new SQFractionResult.Iteration( parameters, measurements, @@ -181,22 +260,178 @@ 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; + + protected Function function; + protected SQ.View view; + + public ParameterCreator( + String [] origNames, + String [] proxyNames, + Function function, + SQ.View view + ) { + this.origNames = origNames; + this.proxyNames = proxyNames; + this.function = function; + this.view = view; + } + + protected double [] transformCoeffs(double [] coeffs) { + return coeffs; + } + + private static double maxQ(SQ [] sqs) { + double max = -Double.MAX_VALUE; + for (SQ sq: sqs) { + double q = sq.getQ(); // Don't use view here! + if (q > max) { + max = q; + } + } + return Math.max(0d, max); + } + + private double cFerguson( + org.dive4elements.river.artifacts.math.Function instance, + SQ [] sqs + ) { + double sqrSum = 0d; + + for (SQ sq: sqs) { + double s = view.getS(sq); + double q = view.getQ(sq); + double diffS = s - instance.value(q); + sqrSum += diffS*diffS; + } + + return Math.exp(0.5d * sqrSum/(sqs.length-2)); + } + + private double cDuan( + org.dive4elements.river.artifacts.math.Function instance, + SQ [] sqs + ) { + double sum = 0d; + + for (SQ sq: sqs) { + double s = view.getS(sq); + double q = view.getQ(sq); + double diffS = s - instance.value(q); + sum += Math.exp(diffS); + } + return sum / sqs.length; + } + + private double r2( + org.dive4elements.river.artifacts.math.Function instance, + SQ [] sqs + ) { + double xm = 0; + double ym = 0; + for (SQ sq: sqs) { + double s = view.getS(sq); + double q = view.getQ(sq); + double fs = instance.value(q); + xm += s; + ym += fs; + } + xm /= sqs.length; + ym /= sqs.length; + + double mixXY = 0d; + double sumX = 0d; + double sumY = 0d; + + for (SQ sq: sqs) { + double s = view.getS(sq); + double q = view.getQ(sq); + double fs = instance.value(q); + + double xDiff = xm - s; + double yDiff = ym - fs; + + mixXY += xDiff*yDiff; + + sumX += xDiff*xDiff; + sumY += yDiff*yDiff; + } + + double r = mixXY/Math.sqrt(sumX*sumY); + return r*r; + } + + + public Parameters createParameters( + double [] coeffs, + double standardDeviation, + double chiSqr, + SQ [] measurements + ) { + String [] columns = StringUtils.join(EXTRA_PARAMETERS, origNames); + + 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); + parameters.set(row, "max_q", maxQ(measurements)); + + // We need to instantiate the function to calculate + // the remaining values. + org.dive4elements.river.artifacts.math.Function f = + function.instantiate(coeffs); + + parameters.set(row, "c_ferguson", cFerguson(f, measurements)); + parameters.set(row, "c_duan", cDuan(f, measurements)); + parameters.set(row, "r2", r2(f, measurements)); + + 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, + Function function, + SQ.View view + ) { + super(origNames, proxyNames, function, view); + } + + @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 : diff -r aa14ae10a853 -r 8d98e1825846 artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/SQRelationJRDataSource.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/SQRelationJRDataSource.java Mon Aug 19 10:55:13 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/SQRelationJRDataSource.java Mon Aug 19 10:55:52 2013 +0200 @@ -86,12 +86,24 @@ value = data.get(index)[3]; } else if ("total".equals(fieldName)) { - value = data.get(index)[4]; + value = data.get(index)[7]; } else if ("out".equals(fieldName)) { + value = data.get(index)[8]; + } + else if ("sd".equals(fieldName)) { + value = data.get(index)[4]; + } + else if ("qmax".equals(fieldName)) { value = data.get(index)[5]; } - else if ("variance".equals(fieldName)) { + else if ("cferg".equals(fieldName)) { + value = data.get(index)[10]; + } + else if ("cduan".equals(fieldName)) { + value = data.get(index)[9]; + } + else if ("r2".equals(fieldName)) { value = data.get(index)[6]; } return value; diff -r aa14ae10a853 -r 8d98e1825846 artifacts/src/main/java/org/dive4elements/river/artifacts/services/DischargeInfoService.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/services/DischargeInfoService.java Mon Aug 19 10:55:13 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/services/DischargeInfoService.java Mon Aug 19 10:55:52 2013 +0200 @@ -40,6 +40,8 @@ public static final String GAUGE_XPATH = "/art:gauge/text()"; + public static final String RIVER_NAME_XPATH = "/art:gauge/art:river/text()"; + public DischargeInfoService() { } @@ -58,30 +60,39 @@ String gaugeNumber = XMLUtils.xpathString( data, GAUGE_XPATH, ArtifactNamespaceContext.INSTANCE); + String river = XMLUtils.xpathString( + data, RIVER_NAME_XPATH, ArtifactNamespaceContext.INSTANCE); + if (gaugeNumber == null || (gaugeNumber = gaugeNumber.trim()).length() == 0) { logger.warn("No gauge specified. Cannot return discharge info."); return XMLUtils.newDocument(); } - logger.debug("Getting discharge for gauge: " + gaugeNumber); + logger.debug("Getting discharge for gauge: " + gaugeNumber + " at river: " + river); long gn; try { gn = Long.parseLong(gaugeNumber); } catch (NumberFormatException nfe) { - logger.warn("Invalid gauge number. Cannot return discharg info."); + logger.warn("Invalid gauge number. Cannot return discharge info."); return XMLUtils.newDocument(); } - Gauge gauge = Gauge.getGaugeByOfficialNumber(gn); + Gauge gauge; + if (river == null || river.isEmpty()) { + gauge = Gauge.getGaugeByOfficialNumber(gn); + } else { + gauge = Gauge.getGaugeByOfficialNumber(gn, river); + } + if (gauge == null) { logger.warn("No such gauge found."); return XMLUtils.newDocument(); } - logger.debug("Found gauge: " + gauge.getName()); + logger.debug("Found gauge: " + gauge.getName() + " id: " + gauge.getId()); return buildDocument(gauge); } diff -r aa14ae10a853 -r 8d98e1825846 artifacts/src/main/java/org/dive4elements/river/artifacts/states/GaugeDischargeState.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/states/GaugeDischargeState.java Mon Aug 19 10:55:13 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/states/GaugeDischargeState.java Mon Aug 19 10:55:52 2013 +0200 @@ -10,6 +10,8 @@ import java.util.List; +import java.text.DateFormat; + import org.apache.log4j.Logger; import org.dive4elements.artifacts.CallMeta; @@ -31,7 +33,10 @@ import org.dive4elements.river.artifacts.resources.Resources; import org.dive4elements.river.model.Gauge; +import org.dive4elements.river.model.DischargeTable; +import org.dive4elements.river.model.TimeInterval; +import org.dive4elements.river.utils.Formatter; /** * The only state for an GaugeDischargeState (River and km known). @@ -64,9 +69,18 @@ } Gauge gauge = artifact.getGauge(); + DischargeTable mdt = gauge.fetchMasterDischargeTable(); + TimeInterval validity = mdt.getTimeInterval(); + DateFormat df = Formatter.getDateFormatter(meta, "dd.MM.yyyy"); + String start = validity.getStartTime() != null ? + df.format(validity.getStartTime()) : "Unknown"; + String stop = validity.getStopTime() != null ? + df.format(validity.getStopTime()) : ""; + Object[] args = new Object[] { gauge.getName(), - gauge.getStation() + start, + stop }; String name = Resources.getMsg( diff -r aa14ae10a853 -r 8d98e1825846 artifacts/src/main/java/org/dive4elements/river/artifacts/states/GaugeTimerangeState.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/states/GaugeTimerangeState.java Mon Aug 19 10:55:13 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/states/GaugeTimerangeState.java Mon Aug 19 10:55:52 2013 +0200 @@ -67,7 +67,8 @@ } } - logger.warn("Could not determine time range for gauge: " + gauge); + logger.warn("Could not determine time range for gauge: " + gauge.getName() + + " id: " + gauge.getId()); return null; } diff -r aa14ae10a853 -r 8d98e1825846 artifacts/src/main/java/org/dive4elements/river/artifacts/states/fixation/FixAnalysisCompute.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/states/fixation/FixAnalysisCompute.java Mon Aug 19 10:55:13 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/states/fixation/FixAnalysisCompute.java Mon Aug 19 10:55:52 2013 +0200 @@ -9,8 +9,11 @@ package org.dive4elements.river.artifacts.states.fixation; import java.text.DateFormat; +import java.util.Collection; import java.util.Date; +import java.util.HashMap; import java.util.List; +import java.util.Map; import org.apache.log4j.Logger; @@ -41,6 +44,7 @@ import org.dive4elements.river.artifacts.model.fixings.FixWQCurveFacet; import org.dive4elements.river.artifacts.resources.Resources; import org.dive4elements.river.artifacts.states.DefaultState; +import org.dive4elements.river.utils.Formatter; import org.dive4elements.river.utils.IdGenerator; /** @@ -76,8 +80,6 @@ "fix.hq5" }; - // TODO Why does this happen here? In other cases its implemented in the - // respective artifact, not State. static { // Active/deactivate facets. FacetActivity.Registry.getInstance().register( @@ -171,15 +173,15 @@ int qsS = access.getQSectorStart(); int qsE = access.getQSectorEnd(); - // TODO: i18n - DateFormat df = DateFormat.getDateInstance(DateFormat.MEDIUM); + DateFormat df = Formatter.getDateFormatter(context.getMeta(), "dd.MM.yyyy"); + DateFormat lf = Formatter.getDateFormatter(context.getMeta(), "dd.MM.yyy'T'HH:mm"); DateRange [] periods = access.getAnalysisPeriods(); for (int i = 0; i < periods.length; i++) { DateRange period = periods[i]; String startDate = df.format(period.getFrom()); - String endDate = df.format(period.getTo()); + String endDate = df.format(period.getTo()); for (int j = qsS; j <= qsE; j++) { @@ -233,19 +235,22 @@ I18N_ANALYSIS, I18N_ANALYSIS); + Collection aeds = fr.getAnalysisEventsDates(i); + UniqueDateFormatter cf = new UniqueDateFormatter(df, lf, aeds); + int k = 0; - for (Date d: fr.getAnalysisEventsDates(i)) { + for (Date d: aeds) { int anaNdx = i << 8; anaNdx = anaNdx | k; facets.add(new FixAnalysisEventsFacet(anaNdx, FIX_ANALYSIS_EVENTS_DWT, - eventDesc + (i+1) + " - " + df.format(d))); + eventDesc + (i+1) + " - " + cf.format(d))); facets.add(new FixLongitudinalAnalysisFacet(anaNdx, FIX_ANALYSIS_EVENTS_LS, - eventDesc + (i+1) + " - " + df.format(d))); + eventDesc + (i+1) + " - " + cf.format(d))); facets.add(new FixAnalysisEventsFacet(anaNdx, FIX_ANALYSIS_EVENTS_WQ, - eventDesc + (i+1) +" - " + df.format(d))); + eventDesc + (i+1) +" - " + cf.format(d))); k++; } } @@ -259,27 +264,29 @@ I18N_REFERENCEDEVIATION, I18N_REFERENCEDEVIATION); + Collection reds = fr.getReferenceEventsDates(); + UniqueDateFormatter cf = new UniqueDateFormatter(df, lf, reds); + int i = 0; - for (Date d: fr.getReferenceEventsDates()) { + for (Date d: reds) { int refNdx = idg.next() << 8; refNdx |= i; facets.add(new FixReferenceEventsFacet(refNdx, FIX_REFERENCE_EVENTS_DWT, - i18n_ref + " - " + df.format(d))); + i18n_ref + " - " + cf.format(d))); refNdx = idg.next() << 8; refNdx = refNdx | i; facets.add(new FixLongitudinalReferenceFacet(refNdx, FIX_REFERENCE_EVENTS_LS, - i18n_ref + " - " + df.format(d))); + i18n_ref + " - " + cf.format(d))); refNdx = idg.next() << 8; refNdx |= i; facets.add(new FixReferenceEventsFacet(refNdx, FIX_REFERENCE_EVENTS_WQ, - i18n_ref + " - " + df.format(d))); + i18n_ref + " - " + cf.format(d))); i++; } - facets.add(new FixLongitudinalDeviationFacet(idg.next(), FIX_DEVIATION_LS, i18n_dev)); @@ -333,5 +340,46 @@ I18N_DEVIATION))); return res; } + + /** Little hack to format dates unique if they collide. */ + private static class UniqueDateFormatter { + + private DateFormat df; + private DateFormat lf; + private Map collisions; + + UniqueDateFormatter( + DateFormat df, + DateFormat lf, + Collection dates + ) { + this.df = df; + this.lf = lf; + collisions = build(dates); + } + + private Map build(Collection dates) { + Map collisions = new HashMap(); + for (Date d: dates) { + String s = df.format(d); + int [] count = collisions.get(s); + if (count == null) { + collisions.put(s, count = new int[1]); + } + if (++count[0] > 1) { + log.debug("date collsion found: " + d); + } + } + return collisions; + } + + String format(Date date) { + String s = df.format(date); + int [] count = collisions.get(s); + return count == null || count[0] < 2 + ? s + : lf.format(date); + } + } // class UniqueDateFormatter } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r aa14ae10a853 -r 8d98e1825846 artifacts/src/main/java/org/dive4elements/river/artifacts/states/minfo/DifferencesState.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/states/minfo/DifferencesState.java Mon Aug 19 10:55:13 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/states/minfo/DifferencesState.java Mon Aug 19 10:55:52 2013 +0200 @@ -127,9 +127,7 @@ newFacets.add(new BedDiffYearFacet( idx, BED_DIFFERENCE_MORPH_WIDTH, - createBedDiffMorphDescription( - meta, - (BedDiffYearResult)results[idx]), + createBedDiffMorphDescription(meta), ComputeType.ADVANCE, stateId, hash)); @@ -342,12 +340,9 @@ } protected String createBedDiffMorphDescription( - CallMeta meta, - BedDiffYearResult result) { - String range = result.getStart() + " - " + result.getEnd(); - + CallMeta meta) { return Resources.getMsg(meta, I18N_FACET_BED_DIFF_MORPH, - I18N_FACET_BED_DIFF_MORPH, new Object[] { range }); + I18N_FACET_BED_DIFF_MORPH); } protected String createBedDiffAbsoluteDescription( diff -r aa14ae10a853 -r 8d98e1825846 artifacts/src/main/java/org/dive4elements/river/exports/ComputedDischargeCurveGenerator.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/ComputedDischargeCurveGenerator.java Mon Aug 19 10:55:13 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/ComputedDischargeCurveGenerator.java Mon Aug 19 10:55:52 2013 +0200 @@ -104,6 +104,7 @@ * Create Y (range) axis for given index, here with a special axis * that depends on other axis (does translation and scaling for * special case at gauge in cm). + * @return A NumberAxis, possibly scaled. */ @Override protected NumberAxis createYAxis(int index) { @@ -176,7 +177,9 @@ mainValues, artifactFacet, attr, visible); } - else if (name.equals(STATIC_WKMS_INTERPOL) || name.equals(HEIGHTMARKS_POINTS)) { + else if (STATIC_WKMS_INTERPOL.equals(name) || + HEIGHTMARKS_POINTS.equals(name) || + STATIC_WQKMS_W.equals(name)) { doWAnnotations( artifactFacet.getData(context), artifactFacet, @@ -212,16 +215,16 @@ /** * Add WQ Data to plot. - * @param wqkms data as double[][] + * @param wq data as double[][] */ protected void doWQOut( - Object wqkms, + Object wq, ArtifactAndFacet aaf, Document theme, boolean visible ) { logger.debug("ComputedDischargeCurveGenerator: doWQOut"); - double [][] data = (double [][]) wqkms; + double [][] data = (double [][]) wq; XYSeries series = new StyledXYSeries(aaf.getFacetDescription(), theme); StyledSeriesBuilder.addPoints(series, data, true); diff -r aa14ae10a853 -r 8d98e1825846 artifacts/src/main/java/org/dive4elements/river/exports/HistoricalDischargeWQCurveGenerator.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/HistoricalDischargeWQCurveGenerator.java Mon Aug 19 10:55:13 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/HistoricalDischargeWQCurveGenerator.java Mon Aug 19 10:55:52 2013 +0200 @@ -124,7 +124,9 @@ artifactFacet.getData(context), artifactFacet.getFacetDescription(), theme, visible); } - else if (name.equals(HISTORICAL_DISCHARGE_WQ_CURVE)) { + else if (name.equals(HISTORICAL_DISCHARGE_WQ_CURVE) || + name.equals(DISCHARGE_CURVE) || + name.equals(GAUGE_DISCHARGE_CURVE)) { doHistoricalDischargeCurveOut( (D4EArtifact) artifactFacet.getArtifact(), artifactFacet.getData(context), diff -r aa14ae10a853 -r 8d98e1825846 artifacts/src/main/java/org/dive4elements/river/exports/MapGenerator.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/MapGenerator.java Mon Aug 19 10:55:13 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/MapGenerator.java Mon Aug 19 10:55:52 2013 +0200 @@ -120,9 +120,11 @@ setInitialExtent(extent); createWSPLGENLayer(flys, wms, attr); } - else if (FLOODMAP_USERSHAPE.equals(name)) { - createUserShapeLayer(flys, wms); - } + // FIXME: Already generated by HWSBarrierState + // wms has a wrong SRID which would break that layer + //else if (FLOODMAP_USERSHAPE.equals(name)) { + // createUserShapeLayer(flys, wms); + //} else { logger.debug("doOut: createDatabaseLayer for facet name: " + name); createDatabaseLayer(flys, wms, attr); diff -r aa14ae10a853 -r 8d98e1825846 artifacts/src/main/java/org/dive4elements/river/exports/StyledSeriesBuilder.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/StyledSeriesBuilder.java Mon Aug 19 10:55:13 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/StyledSeriesBuilder.java Mon Aug 19 10:55:52 2013 +0200 @@ -49,6 +49,7 @@ * the NaNs lead to gaps in graph. * @param distance if two consecutive entries in points[0] are more * than distance apart, create a NaN value to skip in display. + * Still, create a line segment. */ public static void addPoints(XYSeries series, double[][] points, boolean skipNANs, double distance) { if (points == null || points.length <= 1) { @@ -64,6 +65,11 @@ } // Create gap if distance >= distance. if (i != 0 && Math.abs(xPoints[i-1] - xPoints[i]) >= distance) { + // Create at least a small segment for last point. + if (!Double.isNaN(yPoints[i-1])) { + series.add(xPoints[i-1]+0.99d*(distance)/2.d, yPoints[i-1], false); + } + if (!Double.isNaN(yPoints[i-1]) && !Double.isNaN(yPoints[i])) { series.add((xPoints[i-1]+xPoints[i])/2.d, Double.NaN, false); } diff -r aa14ae10a853 -r 8d98e1825846 artifacts/src/main/java/org/dive4elements/river/exports/SyncNumberAxis.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/SyncNumberAxis.java Mon Aug 19 10:55:13 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/SyncNumberAxis.java Mon Aug 19 10:55:52 2013 +0200 @@ -18,6 +18,7 @@ /** * Axis which is to be registered with other axis and tries * to clone its range. The cloned range is transformed. + * Keeps in sync via AxisChangedEvents. */ public class SyncNumberAxis extends IdentifiableNumberAxis implements AxisChangeListener diff -r aa14ae10a853 -r 8d98e1825846 artifacts/src/main/java/org/dive4elements/river/exports/TimeseriesChartGenerator.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/TimeseriesChartGenerator.java Mon Aug 19 10:55:13 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/TimeseriesChartGenerator.java Mon Aug 19 10:55:52 2013 +0200 @@ -54,10 +54,11 @@ import org.w3c.dom.Document; /** + * Generator for diagrams with time on x axis. * @author Ingo Weinzierl */ -public abstract class TimeseriesChartGenerator extends ChartGenerator { - +public abstract class TimeseriesChartGenerator +extends ChartGenerator { /** * Inner class TimeseriesAxisDataset stores TimeSeriesCollection. diff -r aa14ae10a853 -r 8d98e1825846 artifacts/src/main/java/org/dive4elements/river/exports/fixings/FixDeltaWtGenerator.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/fixings/FixDeltaWtGenerator.java Mon Aug 19 10:55:13 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/fixings/FixDeltaWtGenerator.java Mon Aug 19 10:55:52 2013 +0200 @@ -35,7 +35,6 @@ import org.apache.log4j.Logger; import org.jfree.chart.annotations.XYTextAnnotation; -import org.jfree.data.time.Day; import org.jfree.data.time.RegularTimePeriod; import org.jfree.data.time.FixedMillisecond; import org.jfree.data.time.TimeSeries; @@ -270,9 +269,9 @@ // Draw a line spanning the analysis time. series.add(rtp, value); - rtp = new Day(qwd.dateRange.getFrom()); + rtp = new FixedMillisecond(qwd.dateRange.getFrom()); series.addOrUpdate(rtp, value); - rtp = new Day(qwd.dateRange.getTo()); + rtp = new FixedMillisecond(qwd.dateRange.getTo()); series.addOrUpdate(rtp, value); tsc.addSeries(series); diff -r aa14ae10a853 -r 8d98e1825846 artifacts/src/main/java/org/dive4elements/river/exports/minfo/BedDifferenceEpochGenerator.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/minfo/BedDifferenceEpochGenerator.java Mon Aug 19 10:55:13 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/minfo/BedDifferenceEpochGenerator.java Mon Aug 19 10:55:52 2013 +0200 @@ -262,3 +262,4 @@ } } } +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r aa14ae10a853 -r 8d98e1825846 artifacts/src/main/java/org/dive4elements/river/exports/minfo/BedQualityGenerator.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/minfo/BedQualityGenerator.java Mon Aug 19 10:55:13 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/minfo/BedQualityGenerator.java Mon Aug 19 10:55:52 2013 +0200 @@ -140,6 +140,7 @@ * @param attr * theme for facet */ + @Override public void doOut(ArtifactAndFacet artifactAndFacet, Document attr, boolean visible) { String name = artifactAndFacet.getFacetName(); diff -r aa14ae10a853 -r 8d98e1825846 artifacts/src/main/java/org/dive4elements/river/exports/process/BedDiffHeightYearProcessor.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/process/BedDiffHeightYearProcessor.java Mon Aug 19 10:55:13 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/process/BedDiffHeightYearProcessor.java Mon Aug 19 10:55:52 2013 +0200 @@ -26,6 +26,8 @@ private final static Logger logger = Logger.getLogger(BedDiffHeightYearProcessor.class); + protected static double GAP_TOLERANCE = 0.101d; + @Override public void doOut( XYChartGenerator generator, @@ -62,7 +64,7 @@ int axidx) { XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); - StyledSeriesBuilder.addPoints(series, data.getHeightPerYearData(), false, 0.101d); + StyledSeriesBuilder.addPoints(series, data.getHeightPerYearData(), false, GAP_TOLERANCE); generator.addAxisSeries(series, axidx, visible); } diff -r aa14ae10a853 -r 8d98e1825846 artifacts/src/main/java/org/dive4elements/river/exports/process/BedDiffYearProcessor.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/process/BedDiffYearProcessor.java Mon Aug 19 10:55:13 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/process/BedDiffYearProcessor.java Mon Aug 19 10:55:52 2013 +0200 @@ -26,6 +26,8 @@ private final static Logger logger = Logger.getLogger(BedDiffYearProcessor.class); + protected static double GAP_TOLERANCE = 0.101d; + @Override public void doOut( XYChartGenerator generator, @@ -71,10 +73,10 @@ XYSeries series = new StyledXYSeries(bundle.getFacetDescription(), attr); if (idx == 0) { - StyledSeriesBuilder.addPoints(series, data.getHeights1Data(), false, 0.101d); + StyledSeriesBuilder.addPoints(series, data.getHeights1Data(), false, GAP_TOLERANCE); } else { - StyledSeriesBuilder.addPoints(series, data.getHeights2Data(), false, 0.101d); + StyledSeriesBuilder.addPoints(series, data.getHeights2Data(), false, GAP_TOLERANCE); } generator.addAxisSeries(series, axidx, visible); diff -r aa14ae10a853 -r 8d98e1825846 artifacts/src/main/java/org/dive4elements/river/exports/sq/SQRelationExporter.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/sq/SQRelationExporter.java Mon Aug 19 10:55:13 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/sq/SQRelationExporter.java Mon Aug 19 10:55:52 2013 +0200 @@ -16,6 +16,7 @@ import java.util.Date; import java.util.Locale; import java.text.DateFormat; +import java.text.NumberFormat; import org.w3c.dom.Document; @@ -99,8 +100,11 @@ public static final String CSV_C_FERGUSON = "export.sqrelation.csv.header.c.ferguson"; - public static final String CSV_VARIANCE = - "export.sqrelation.csv.header.variance"; + public static final String CSV_QMAX = + "export.sqrelation.csv.header.qmax"; + + public static final String CSV_SD = + "export.sqrelation.csv.header.sd"; public static final String PDF_TITLE= "export.sqrelation.pdf.title"; @@ -136,9 +140,13 @@ msg(CSV_PARAMETER, CSV_PARAMETER), msg(CSV_COEFF_A , CSV_COEFF_A), msg(CSV_COEFF_B , CSV_COEFF_B), + msg(CSV_SD, CSV_SD), + msg(CSV_QMAX, CSV_QMAX), + msg(CSV_COEFF_R, CSV_COEFF_R), msg(CSV_N_TOTAL , CSV_N_TOTAL), msg(CSV_N_OUTLIERS, CSV_N_OUTLIERS), - msg(CSV_VARIANCE , CSV_VARIANCE) + msg(CSV_C_DUAN, CSV_C_DUAN), + msg(CSV_C_FERGUSON, CSV_C_FERGUSON) }); } @@ -160,6 +168,12 @@ ).format(result.getKm()); List retval = new ArrayList(); + NumberFormat sqAFormatter = Formatter.getSQRelationA(context); + NumberFormat sqBFormatter = Formatter.getSQRelationB(context); + NumberFormat fThreeFormatter = Formatter.getFormatter(context, 3, 3); + NumberFormat fTwoFormatter = Formatter.getFormatter(context, 2, 2); + NumberFormat fZeroFormatter = Formatter.getFormatter(context, 0, 0); + for (int i = 0; i < SQResult.NUMBER_FRACTIONS; ++i) { SQFractionResult fraction = result.getFraction(i); @@ -171,10 +185,17 @@ continue; } - String a, b, sd, o, t; - a = Formatter.getSQRelationA(context).format(parameters.getValue(0, "a")); - b = Formatter.getSQRelationB(context).format(parameters.getValue(0, "b")); - sd = Formatter.getVariance(context).format(Math.sqrt(parameters.getValue(0, "std_dev"))); + String a, b, sd, o, t, max_q, c_ferguson, c_duan, r2; + a = sqAFormatter.format(parameters.getValue(0, "a")); + b = sqBFormatter.format(parameters.getValue(0, "b")); + + /* The std_dev parameter contains the standard error actually */ + sd = fThreeFormatter.format(parameters.getValue(0, "std_dev")); + max_q = fZeroFormatter.format(parameters.getValue(0, "max_q")); + c_ferguson = fTwoFormatter.format(parameters.getValue(0, "c_ferguson")); + c_duan = fTwoFormatter.format(parameters.getValue(0, "c_duan")); + r2 = fTwoFormatter.format(parameters.getValue(0, "r2")); + o = String.valueOf(fraction.totalNumOutliers()); t = String.valueOf(fraction.numMeasurements() + o); @@ -184,9 +205,13 @@ name, a, b, - t, - o, - sd + sd, // 4 + max_q, // 5 + r2, // 6 + t, // 7 + o, // 8 + c_duan, // 9 + c_ferguson // 10 }); } return retval; @@ -229,7 +254,8 @@ source.addMetaData("outliertest", Resources.getMsg(meta, access.getOutlierMethod(), access.getOutlierMethod())); - source.addMetaData("outliers", access.getOutliers().toString()); + source.addMetaData("outliers", Formatter.getRawFormatter(context).format( + access.getOutliers())); source.addMetaData("calculation", Resources.getMsg( locale, diff -r aa14ae10a853 -r 8d98e1825846 artifacts/src/main/java/org/dive4elements/river/utils/ArtifactMapfileGenerator.java --- a/artifacts/src/main/java/org/dive4elements/river/utils/ArtifactMapfileGenerator.java Mon Aug 19 10:55:13 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/utils/ArtifactMapfileGenerator.java Mon Aug 19 10:55:52 2013 +0200 @@ -16,6 +16,7 @@ import org.dive4elements.river.artifacts.model.map.WMSLayerFacet; import org.dive4elements.river.artifacts.model.map.WSPLGENLayerFacet; import org.dive4elements.river.artifacts.resources.Resources; +import org.dive4elements.river.artifacts.states.FloodMapState; import java.io.File; import java.io.FileNotFoundException; @@ -135,11 +136,11 @@ ShapefileReader sfr = new ShapefileReader(sf, true, false, null); ShapefileHeader sfh = sfr.getHeader(); - String group = uuid + MS_USERSHAPE_PREFIX; + String group = MS_USERSHAPE_PREFIX + uuid; String groupTitle = "I18N_USER_SHAPE_TITLE"; LayerInfo info = new LayerInfo(); - info.setName(MS_USERSHAPE_PREFIX + uuid); + info.setName(MS_LAYER_PREFIX + FloodMapState.WSPLGEN_USER_RGD + uuid); if (sfh.getShapeType().isLineType()) { info.setType("LINE"); } @@ -156,7 +157,11 @@ info.setGroupTitle(groupTitle); info.setSrid(wms.getSrid()); - String nameUser = MS_LAYER_PREFIX + wms.getName(); + //String nameUser = MS_LAYER_PREFIX + wms.getName(); + // TODO: This rewrites the user-rgd mapfile fragment generated by + // HWSBarrierState. Otherwise we would have to fragments with same + // layer name. Should be refactored... + String nameUser = MS_LAYER_PREFIX + "user-rgd"; Template tpl = getTemplateByName(SHP_LAYER_TEMPLATE); if (tpl == null) { diff -r aa14ae10a853 -r 8d98e1825846 artifacts/src/main/java/org/dive4elements/river/utils/BatchLoader.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/artifacts/src/main/java/org/dive4elements/river/utils/BatchLoader.java Mon Aug 19 10:55:52 2013 +0200 @@ -0,0 +1,116 @@ +/* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde + * Software engineering by Intevation GmbH + * + * This file is Free Software under the GNU AGPL (>=v3) + * and comes with ABSOLUTELY NO WARRANTY! Check out the + * documentation coming with Dive4Elements River for details. + */ + +package org.dive4elements.river.utils; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.apache.log4j.Logger; +import org.hibernate.SQLQuery; +import org.hibernate.Session; + +/** To reduce the number of SQL queries send to the backend + * (mainly by the fixings overviews) we execute them in batches of ids + * and store the results in a small cache. + * TODO: It currently relies on dynamic SQL. + * Is there a way to use Hibernate with java.sql.Array + * in cross database compatible manner? + */ +public abstract class BatchLoader { + + private static Logger log = Logger.getLogger(BatchLoader.class); + + public static final int BATCH_SIZE = 100; + + private Map loaded; + private List rest; + private Session session; + private String sqlTemplate; + + public BatchLoader( + List columns, + Session session, + String sqlTemplate + ) { + rest = new ArrayList(columns.size()); + loaded = new HashMap(); + this.session = session; + this.sqlTemplate = sqlTemplate; + + // Insert in reverse order to minize searching. + for (int i = columns.size()-1; i >= 0; --i) { + rest.add(columns.get(i)); + } + } + + /** Searches for id and fill a batch to load containing the found id. */ + private List prepareBatch(int id) { + List batch = new ArrayList(BATCH_SIZE); + + boolean found = false; + + for (int i = rest.size()-1; batch.size() < BATCH_SIZE && i >= 0; --i) { + Integer cid = rest.get(i); + if (cid == id) { + found = true; + batch.add(cid); + rest.remove(i); + } + else if ((found && batch.size() < BATCH_SIZE) + || (!found && batch.size() < BATCH_SIZE-1)) { + batch.add(cid); + rest.remove(i); + } + } + + return batch; + } + + /** Converts id to a list of comma separated ints. */ + private static String idsAsString(List ids) { + StringBuilder sb = new StringBuilder(); + for (Iterator i = ids.iterator(); i.hasNext();) { + sb.append(i.next()); + if (i.hasNext()) { + sb.append(','); + } + } + return sb.toString(); + } + + /** Get data for id. */ + public T get(int id) { + T already = loaded.get(id); + if (already != null) { + return already; + } + + List batch = prepareBatch(id); + if (batch.isEmpty()) { + return null; + } + String sql = sqlTemplate.replace("$IDS", idsAsString(batch)); + if (log.isDebugEnabled()) { + log.debug(sql + " " + sql.length()); + } + fill(session.createSQLQuery(sql)); + return get(id); + } + + /** Call this from fill() to store data in the cache. */ + protected void cache(int key, T data) { + loaded.put(key, data); + } + + /** Override this to fill the cache */ + protected abstract void fill(SQLQuery query); +} diff -r aa14ae10a853 -r 8d98e1825846 artifacts/src/main/java/org/dive4elements/river/utils/RiverUtils.java --- a/artifacts/src/main/java/org/dive4elements/river/utils/RiverUtils.java Mon Aug 19 10:55:13 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/utils/RiverUtils.java Mon Aug 19 10:55:52 2013 +0200 @@ -491,10 +491,14 @@ public static Gauge getReferenceGauge(D4EArtifact flys) { Long officialNumber = flys.getDataAsLong("reference_gauge"); + String river = getRivername(flys); - return officialNumber != null - ? Gauge.getGaugeByOfficialNumber(officialNumber) - : null; + if (officialNumber != null && river != null) { + return Gauge.getGaugeByOfficialNumber(officialNumber, river); + } else if (officialNumber != null) { + return Gauge.getGaugeByOfficialNumber(officialNumber); + } + return null; } diff -r aa14ae10a853 -r 8d98e1825846 artifacts/src/main/resources/datacage-sql/org-h2-driver.properties --- a/artifacts/src/main/resources/datacage-sql/org-h2-driver.properties Mon Aug 19 10:55:13 2013 +0200 +++ b/artifacts/src/main/resources/datacage-sql/org-h2-driver.properties Mon Aug 19 10:55:52 2013 +0200 @@ -17,7 +17,7 @@ insert.out = INSERT INTO outs (id, artifact_id, name, description, out_type) VALUES (?, ?, ?, ?, ?) facet.id.nextval = SELECT NEXTVAL('FACETS_ID_SEQ') insert.facet = INSERT INTO facets (id, out_id, name, num, state, description) VALUES (?, ?, ?, ?, ?, ?) -update.artifact.state = UPDATE artifacts SET state = ? WHERE gid = ? +update.artifact.state = UPDATE artifacts SET state = ? WHERE id = ? update.collection.name = UPDATE collections SET name = ? WHERE gid = ? delete.artifact.from.collection = DELETE FROM collection_items WHERE collection_id = ? AND artifact_id = ? diff -r aa14ae10a853 -r 8d98e1825846 artifacts/src/main/resources/messages.properties --- a/artifacts/src/main/resources/messages.properties Mon Aug 19 10:55:13 2013 +0200 +++ b/artifacts/src/main/resources/messages.properties Mon Aug 19 10:55:52 2013 +0200 @@ -171,7 +171,7 @@ chart.computed.discharge.curve.subtitle = {0}-km: {1,number,#.###} chart.computed.discharge.curve.yaxis.label = W [{0}] chart.computed.discharge.curve.curve.label = Discharge Curve {0} km {1} -chart.computed.discharge.curve.gauge = Discharge curve at gauge {0} (km {1}) +chart.computed.discharge.curve.gauge = current DC {0} {1} - {2} chart.duration.curve.title = Duration Curve chart.duration.curve.subtitle = {0}-km: {1,number,#.###} chart.duration.curve.xaxis.label = Duration of Non-Exceedence [Days] @@ -287,7 +287,7 @@ bedquality.toplayer = 0.0m - 0.3m bedquality.sublayer = 0.1m - 0.5m facet.bedheight.diff.year = Bedheight Difference {0} -facet.bedheight.diff.morph = sounding Width {0} +facet.bedheight.diff.morph = sounding Width facet.bedheight.diff.height1 = Original Height Minuend {0} facet.bedheight.diff.height2 = Original Height Subtrahend {0} facet.bedheight.diff.absolute = Bedheight Difference/Year {0} @@ -404,9 +404,10 @@ export.sqrelation.csv.header.coeff.r = r^2 export.sqrelation.csv.header.n.total = n total export.sqrelation.csv.header.n.outliers = n outliers -export.sqrelation.csv.header.c.duan = C (DUAN) -export.sqrelation.csv.header.c.ferguson = C (FERGUSON) -export.sqrelation.csv.header.variance = Standard variance +export.sqrelation.csv.header.c.duan = C (Duan) +export.sqrelation.csv.header.c.ferguson = C (Ferguson) +export.sqrelation.csv.header.sd = Standard error +export.sqrelation.csv.header.qmax = Q max,measured export.sqrelation.pdf.file = /jasper/sqrelation_en.jasper export.sqrelation.pdf.mode = Load Discharge Relation export.minfo.bedquality.km = km diff -r aa14ae10a853 -r 8d98e1825846 artifacts/src/main/resources/messages_de.properties --- a/artifacts/src/main/resources/messages_de.properties Mon Aug 19 10:55:13 2013 +0200 +++ b/artifacts/src/main/resources/messages_de.properties Mon Aug 19 10:55:52 2013 +0200 @@ -171,7 +171,7 @@ chart.computed.discharge.curve.subtitle = {0}-km: {1,number,#.###} chart.computed.discharge.curve.yaxis.label = W [{0}] chart.computed.discharge.curve.curve.label = Abflusskurve {0} km {1} -chart.computed.discharge.curve.gauge = Abflusskurve an Pegel {0} (km {1}) +chart.computed.discharge.curve.gauge = aktuelle AT {0} {1} - {2} chart.duration.curve.title = Dauerlinie chart.duration.curve.subtitle = {0}-km: {1,number,#.###} chart.duration.curve.xaxis.label = Unterschreitungsdauer [Tage] @@ -287,7 +287,7 @@ bedquality.toplayer = 0,0m - 0,3m bedquality.sublayer = 0,1m - 0,5m facet.bedheight.diff.year = Sohlh\u00f6hendifferenz {0} -facet.bedheight.diff.morph = gepeilte Breite {0} +facet.bedheight.diff.morph = gepeilte Breite facet.bedheight.diff.height1 = H\u00f6he Minuend {0} facet.bedheight.diff.height2 = H\u00f6he Subtrahend {0} facet.bedheight.diff.absolute = Sohlh\u00f6hendifferenz/Jahr {0} @@ -402,11 +402,12 @@ export.sqrelation.csv.header.coeff.b = b export.sqrelation.csv.header.coeff.q = Q export.sqrelation.csv.header.coeff.r = r^2 -export.sqrelation.csv.header.n.total = n gesamt +export.sqrelation.csv.header.n.total = n Gesamt export.sqrelation.csv.header.n.outliers = n Ausrei\u00dfer -export.sqrelation.csv.header.c.duan = C (DUAN) -export.sqrelation.csv.header.c.ferguson = C (FERGUSON) -export.sqrelation.csv.header.variance = Standardabweichung +export.sqrelation.csv.header.c.duan = C (Duan) +export.sqrelation.csv.header.c.ferguson = C (Ferguson) +export.sqrelation.csv.header.sd = Standardfehler +export.sqrelation.csv.header.qmax = Q max,gemessen export.sqrelation.pdf.file = /jasper/sqrelation.jasper export.sqrelation.pdf.mode = Transport-Abfluss Beziehung export.minfo.bedquality.km = km diff -r aa14ae10a853 -r 8d98e1825846 artifacts/src/main/resources/messages_de_DE.properties --- a/artifacts/src/main/resources/messages_de_DE.properties Mon Aug 19 10:55:13 2013 +0200 +++ b/artifacts/src/main/resources/messages_de_DE.properties Mon Aug 19 10:55:52 2013 +0200 @@ -170,7 +170,7 @@ chart.computed.discharge.curve.subtitle = {0}-km: {1,number,#.###} chart.computed.discharge.curve.yaxis.label = W [{0}] chart.computed.discharge.curve.curve.label = Abflusskurve {0} km {1} -chart.computed.discharge.curve.gauge = Abflusskurve an Pegel {0} (km {1}) +chart.computed.discharge.curve.gauge = aktuelle AT {0} {1} - {2} chart.duration.curve.title = Dauerlinie chart.duration.curve.subtitle = {0}-km: {1,number,#.###} chart.duration.curve.xaxis.label = Unterschreitungsdauer [Tage] @@ -286,7 +286,7 @@ bedquality.sublayer = 0,1m - 0,5m facet.bedheight.diff.year = Sohlh\u00f6hendifferenz {0} facet.bedheight.diff.year.raw = Sohlh\u00f6hendifferenz {0} (Rohdaten) -facet.bedheight.diff.morph = gepeilte Breite {0} +facet.bedheight.diff.morph = gepeilte Breite facet.bedheight.diff.height1 = H\u00f6he Minuend {0} facet.bedheight.diff.height2 = H\u00f6he Subtrahend {0} facet.bedheight.diff.absolute = Sohlh\u00f6hendifferenz/Jahr {0} @@ -399,11 +399,12 @@ export.sqrelation.csv.header.coeff.b = b export.sqrelation.csv.header.coeff.q = Q export.sqrelation.csv.header.coeff.r = r^2 -export.sqrelation.csv.header.n.total = n gesamt +export.sqrelation.csv.header.n.total = n Gesamt export.sqrelation.csv.header.n.outliers = n Ausrei\u00dfer -export.sqrelation.csv.header.c.duan = C (DUAN) -export.sqrelation.csv.header.c.ferguson = C (FERGUSON) -export.sqrelation.csv.header.variance = Standardabweichung +export.sqrelation.csv.header.c.duan = C (Duan) +export.sqrelation.csv.header.c.ferguson = C (Ferguson) +export.sqrelation.csv.header.sd = Standardfehler +export.sqrelation.csv.header.qmax = Q max,gemessen export.sqrelation.pdf.file = /jasper/sqrelation.jasper export.sqrelation.pdf.mode = Transport-Abfluss Beziehung export.minfo.bedquality.km = km diff -r aa14ae10a853 -r 8d98e1825846 artifacts/src/main/resources/messages_en.properties --- a/artifacts/src/main/resources/messages_en.properties Mon Aug 19 10:55:13 2013 +0200 +++ b/artifacts/src/main/resources/messages_en.properties Mon Aug 19 10:55:52 2013 +0200 @@ -171,6 +171,7 @@ chart.computed.discharge.curve.subtitle = {0}-km: {1,number,#.###} chart.computed.discharge.curve.yaxis.label = W [{0}] chart.computed.discharge.curve.curve.label = Discharge Curve {0} km {1} +chart.computed.discharge.curve.gauge = current DC {0} {1} - {2} chart.duration.curve.title = Duration Curve chart.duration.curve.subtitle = {0}-km: {1,number,#.###} chart.duration.curve.xaxis.label = Duration of Non-Exceedence [Days] @@ -290,7 +291,7 @@ bedquality.toplayer = 0.0m - 0.3m bedquality.sublayer = 0.1m - 0.5m facet.bedheight.diff.year = Bedheight Difference {0} -facet.bedheight.diff.morph = sounding Width {0} +facet.bedheight.diff.morph = sounding Width facet.bedheight.diff.height1 = Original Height Minuend {0} facet.bedheight.diff.height2 = Original Height Subtrahend {0} facet.bedheight.diff.absolute = Bedheight Difference/Year {0} @@ -406,9 +407,10 @@ export.sqrelation.csv.header.coeff.r = r^2 export.sqrelation.csv.header.n.total = n total export.sqrelation.csv.header.n.outliers = n outliers -export.sqrelation.csv.header.c.duan = C (DUAN) -export.sqrelation.csv.header.c.ferguson = C (FERGUSON) -export.sqrelation.csv.header.variance = Standard variance +export.sqrelation.csv.header.c.duan = C (Duan) +export.sqrelation.csv.header.c.ferguson = C (Ferguson) +export.sqrelation.csv.header.sd = Standard error +export.sqrelation.csv.header.qmax = Q max,measured export.sqrelation.pdf.file = /jasper/sqrelation_en.jasper export.sqrelation.pdf.mode = Load Discharge Relation export.minfo.bedquality.km = km diff -r aa14ae10a853 -r 8d98e1825846 backend/src/main/java/org/dive4elements/river/model/CrossSection.java --- a/backend/src/main/java/org/dive4elements/river/model/CrossSection.java Mon Aug 19 10:55:13 2013 +0200 +++ b/backend/src/main/java/org/dive4elements/river/model/CrossSection.java Mon Aug 19 10:55:52 2013 +0200 @@ -241,11 +241,19 @@ List results = sqlQuery.list(); - for (Integer result: results) { + if (results.size() >= 1) { + Integer result = results.get(0); if (result == getId()) { return true; } } + else { + logger.warn("No CS found that could be master."); + } + + // TODO If there is none, might need a fallback. + // Formerly this was the most current CS (issue1157). + return false; } } diff -r aa14ae10a853 -r 8d98e1825846 backend/src/main/java/org/dive4elements/river/model/Gauge.java --- a/backend/src/main/java/org/dive4elements/river/model/Gauge.java Mon Aug 19 10:55:13 2013 +0200 +++ b/backend/src/main/java/org/dive4elements/river/model/Gauge.java Mon Aug 19 10:55:52 2013 +0200 @@ -223,7 +223,6 @@ this.mainValues = mainValues; } - public static Gauge getGaugeByOfficialNumber(long number) { Session session = SessionHolder.HOLDER.get(); @@ -237,6 +236,21 @@ return results.isEmpty() ? null : results.get(0); } + public static Gauge getGaugeByOfficialNumber(long number, String river_name) { + Session session = SessionHolder.HOLDER.get(); + + Query query = session.createQuery( + "from Gauge as gau " + + "where gau.officialNumber=:number and gau.river.name=:river_name"); + + query.setParameter("number", number); + query.setParameter("river_name", river_name); + + List results = query.list(); + + return results.isEmpty() ? null : results.get(0); + } + public DischargeTable fetchMasterDischargeTable() { for (DischargeTable dt: dischargeTables) { diff -r aa14ae10a853 -r 8d98e1825846 gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.properties --- a/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.properties Mon Aug 19 10:55:13 2013 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.properties Mon Aug 19 10:55:52 2013 +0200 @@ -369,7 +369,7 @@ error_gc_doc_not_valid = Capabilities document is not valid. error_malformed_url = The URL you have entered is not valid. error_no_dgm_selected = No DEM selected. -error_invalid_dgm_selected = You have selected an invalid DEM. +error_invalid_dgm_selected = An error occured while selecting the DEM. error_bad_dgm_range = You have selected a DEM with an invalid range. error_bad_dgm_river = You have selected a DEM for a wrong river. error_dialog_not_valid = One or more values are not valid. diff -r aa14ae10a853 -r 8d98e1825846 gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants_de.properties --- a/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants_de.properties Mon Aug 19 10:55:13 2013 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants_de.properties Mon Aug 19 10:55:52 2013 +0200 @@ -369,7 +369,7 @@ error_gc_doc_not_valid = Das Capabilities Dokument ist nicht valide. error_malformed_url = Die eingegebene URL ist ung\u00fcltig. error_no_dgm_selected = Sie haben kein DGM gew\u00e4hlt. -error_invalid_dgm_selected = Sie haben ein falsches DGM gew\u00e4hlt. +error_invalid_dgm_selected = Bei der Auswahl des DGMs ist ein Fehler aufgetreten. error_bad_dgm_range = Das gew\u00e4hlte DGM passt nicht zur gew\u00e4hlten Berechnungsstrecke. error_bad_dgm_river = Das gew\u00e4hlte DGM passt nicht zum gew\u00e4hlten Fluss. error_dialog_not_valid = Eine oder mehrere Daten sind nicht korrekt. diff -r aa14ae10a853 -r 8d98e1825846 gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants_en.properties --- a/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants_en.properties Mon Aug 19 10:55:13 2013 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants_en.properties Mon Aug 19 10:55:52 2013 +0200 @@ -367,7 +367,7 @@ error_gc_doc_not_valid = Capabilities document is not valid. error_malformed_url = The URL you have entered is not valid. error_no_dgm_selected = No DEM selected. -error_invalid_dgm_selected = You have selected an invalid DEM. +error_invalid_dgm_selected = An error occured while selecting the DEM. error_bad_dgm_range = You have selected a DEM with an invalid range. error_bad_dgm_river = You have selected a DEM for a wrong river. error_dialog_not_valid = One or more values are not valid. diff -r aa14ae10a853 -r 8d98e1825846 gwt-client/src/main/java/org/dive4elements/river/client/client/services/DischargeInfoService.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/client/services/DischargeInfoService.java Mon Aug 19 10:55:13 2013 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/services/DischargeInfoService.java Mon Aug 19 10:55:52 2013 +0200 @@ -28,7 +28,8 @@ */ DischargeInfoObject[] getDischargeInfo( String locale, - long gauge) + long gauge, + String river) throws ServerException; } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r aa14ae10a853 -r 8d98e1825846 gwt-client/src/main/java/org/dive4elements/river/client/client/services/DischargeInfoServiceAsync.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/client/services/DischargeInfoServiceAsync.java Mon Aug 19 10:55:13 2013 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/services/DischargeInfoServiceAsync.java Mon Aug 19 10:55:52 2013 +0200 @@ -21,6 +21,7 @@ void getDischargeInfo( String locale, long gauge, + String river, AsyncCallback cb); } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r aa14ae10a853 -r 8d98e1825846 gwt-client/src/main/java/org/dive4elements/river/client/client/ui/GaugeTimeRangePanel.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/GaugeTimeRangePanel.java Mon Aug 19 10:55:13 2013 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/GaugeTimeRangePanel.java Mon Aug 19 10:55:52 2013 +0200 @@ -105,7 +105,8 @@ Config config = Config.getInstance(); String url = config.getServerUrl(); - yearTable.setDataSource(new DischargeInfoDataSource(url, gauge)); + String river = artifact.getArtifactDescription().getRiver(); + yearTable.setDataSource(new DischargeInfoDataSource(url, gauge, river)); helperContainer.addMember(createHelperPanel()); diff -r aa14ae10a853 -r 8d98e1825846 gwt-client/src/main/java/org/dive4elements/river/client/client/ui/range/DischargeInfoDataSource.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/range/DischargeInfoDataSource.java Mon Aug 19 10:55:13 2013 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/range/DischargeInfoDataSource.java Mon Aug 19 10:55:52 2013 +0200 @@ -20,7 +20,7 @@ public static final String XPATH_DISCHARGE_DEFAULT = "/discharges/discharge"; - public DischargeInfoDataSource(String url, long gauge) { + public DischargeInfoDataSource(String url, long gauge, String river) { setDataFormat(DSDataFormat.XML); setRecordXPath(XPATH_DISCHARGE_DEFAULT); @@ -37,15 +37,16 @@ "end", FieldType.TEXT, "end"); setFields(desc, bfgid, start, end); - setDataURL(getServiceURL(url, gauge)); + setDataURL(getServiceURL(url, gauge, river)); } - protected String getServiceURL(String server, long gauge) { + protected String getServiceURL(String server, long gauge, String river) { String url = GWT.getModuleBaseURL(); url += "dischargeinfoxml"; url += "?server=" + server; url += "&gauge=" + String.valueOf(gauge); + url += "&river=" + river; return url; } diff -r aa14ae10a853 -r 8d98e1825846 gwt-client/src/main/java/org/dive4elements/river/client/server/DischargeInfoServiceImpl.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/server/DischargeInfoServiceImpl.java Mon Aug 19 10:55:13 2013 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/server/DischargeInfoServiceImpl.java Mon Aug 19 10:55:52 2013 +0200 @@ -48,9 +48,11 @@ public static final String XPATH_DISTANCES = "art:discharges/art:discharge"; + @Override public DischargeInfoObject[] getDischargeInfo( String locale, - long gauge) + long gauge, + String river) throws ServerException { logger.info("DichargeInfoServiceImpl.getDischargeInfo"); @@ -67,6 +69,10 @@ Element gaugeEl = ec.create("gauge"); gaugeEl.setTextContent(String.valueOf(gauge)); + Element riverEl = ec.create("river"); + riverEl.setTextContent(river); + + gaugeEl.appendChild(riverEl); doc.appendChild(gaugeEl); HttpClient client = new HttpClientImpl(url, locale); diff -r aa14ae10a853 -r 8d98e1825846 gwt-client/src/main/java/org/dive4elements/river/client/server/DischargeInfoXML.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/server/DischargeInfoXML.java Mon Aug 19 10:55:13 2013 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/server/DischargeInfoXML.java Mon Aug 19 10:55:52 2013 +0200 @@ -50,6 +50,8 @@ String gauge = req.getParameter("gauge"); + String river = req.getParameter("river"); + Document doc = XMLUtils.newDocument(); XMLUtils.ElementCreator ec = new XMLUtils.ElementCreator( @@ -60,6 +62,12 @@ Element gaugeEl = ec.create("gauge"); gaugeEl.setTextContent(gauge); + if (river != null && !river.isEmpty()) { + Element riverEl = ec.create("river"); + riverEl.setTextContent(river); + gaugeEl.appendChild(riverEl); + } + doc.appendChild(gaugeEl); HttpClient client = new HttpClientImpl(url);