comparison artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/collision/CollisionCalculation.java @ 9157:f9bb5d0a6ff3

Added the S-Info collision calculation and chart output
author mschaefer
date Tue, 19 Jun 2018 14:19:32 +0200
parents 23945061daec
children 1614cb14308f
comparison
equal deleted inserted replaced
9156:568961ff709a 9157:f9bb5d0a6ff3
9 */ 9 */
10 package org.dive4elements.river.artifacts.sinfo.collision; 10 package org.dive4elements.river.artifacts.sinfo.collision;
11 11
12 import java.util.ArrayList; 12 import java.util.ArrayList;
13 import java.util.Collection; 13 import java.util.Collection;
14 import java.util.HashMap;
15 import java.util.Map;
14 16
15 import org.apache.commons.lang.math.DoubleRange; 17 import org.apache.commons.lang.math.DoubleRange;
16 import org.dive4elements.artifacts.CallContext; 18 import org.dive4elements.artifacts.CallContext;
17 import org.dive4elements.river.artifacts.common.GeneralResultType; 19 import org.dive4elements.river.artifacts.common.GeneralResultType;
18 import org.dive4elements.river.artifacts.common.ResultRow; 20 import org.dive4elements.river.artifacts.common.ResultRow;
19 import org.dive4elements.river.artifacts.model.Calculation; 21 import org.dive4elements.river.artifacts.model.Calculation;
20 import org.dive4elements.river.artifacts.model.CalculationResult; 22 import org.dive4elements.river.artifacts.model.CalculationResult;
23 import org.dive4elements.river.artifacts.model.DateRange;
21 import org.dive4elements.river.artifacts.resources.Resources; 24 import org.dive4elements.river.artifacts.resources.Resources;
22 import org.dive4elements.river.artifacts.sinfo.SINFOArtifact; 25 import org.dive4elements.river.artifacts.sinfo.SINFOArtifact;
23 import org.dive4elements.river.artifacts.sinfo.common.RiverInfoProvider; 26 import org.dive4elements.river.artifacts.sinfo.common.RiverInfoProvider;
27 import org.dive4elements.river.artifacts.sinfo.common.SInfoResultType;
24 import org.dive4elements.river.artifacts.sinfo.util.CalculationUtils; 28 import org.dive4elements.river.artifacts.sinfo.util.CalculationUtils;
25 import org.dive4elements.river.artifacts.sinfo.util.RiverInfo; 29 import org.dive4elements.river.artifacts.sinfo.util.RiverInfo;
30 import org.dive4elements.river.backend.utils.DateUtil;
31 import org.dive4elements.river.model.Gauge;
26 import org.dive4elements.river.model.River; 32 import org.dive4elements.river.model.River;
33 import org.dive4elements.river.model.sinfo.CollisionAggregateValue;
34 import org.dive4elements.river.model.sinfo.CollisionValue;
27 35
28 class CollisionCalculation { 36 class CollisionCalculation {
29 37
30 // private static Logger log = Logger.getLogger(FloodDurationCalculation.class); 38 // private static Logger log = Logger.getLogger(FloodDurationCalculation.class);
31 39
37 45
38 public CalculationResult calculate(final SINFOArtifact sinfo) { 46 public CalculationResult calculate(final SINFOArtifact sinfo) {
39 47
40 final String user = CalculationUtils.findArtifactUser(this.context, sinfo); 48 final String user = CalculationUtils.findArtifactUser(this.context, sinfo);
41 49
42 /* access input data */ 50 // access input data
43 final CollisionAccess access = new CollisionAccess(sinfo); 51 final CollisionAccess access = new CollisionAccess(sinfo);
44 final River river = access.getRiver(); 52 final River river = access.getRiver();
45 final RiverInfo riverInfo = new RiverInfo(river); 53 final RiverInfo riverInfo = new RiverInfo(river);
46 54
47 final DoubleRange calcRange = access.getRange(); 55 final DoubleRange calcRange = access.getRange();
48 56
49 /* calculate results for each diff pair */ 57 // calculate results for each year or epoch
50 final Calculation problems = new Calculation(); 58 final Calculation problems = new Calculation();
51
52 final RiverInfoProvider infoProvider = RiverInfoProvider.forRange(this.context, river, calcRange);
53 59
54 final String calcModeLabel = Resources.getMsg(this.context.getMeta(), sinfo.getCalculationMode().name()); 60 final String calcModeLabel = Resources.getMsg(this.context.getMeta(), sinfo.getCalculationMode().name());
55 61
56 final int[] years = access.getYears(); 62 final CollisionCalculationResults results = new CollisionCalculationResults(calcModeLabel, user, riverInfo, calcRange, access.getYearsHeader());
57 final int[][] epochs = access.getEpochs();
58 63
59 final Collection<ResultRow> overViewRows = new ArrayList<>(); 64 final Collection<ResultRow> overViewRows = new ArrayList<>();
65
66 if (access.getYears() != null) {
67 for (final int year : access.getYears())
68 calculateOverview(overViewRows, river, access.getLowerKm(), access.getUpperKm(), year, year, false);
69 }
70 else {
71 for (final DateRange dr : access.getEpochs())
72 calculateOverview(overViewRows, river, access.getLowerKm(), access.getUpperKm(), dr.getFromYear(), dr.getToYear(), true);
73 }
74 final CollisionCalcOverviewResult overviewResult = new CollisionCalcOverviewResult(access.getYearsHeader(), overViewRows);
75 results.addResult(overviewResult, problems);
76
77 // create q-for-w-finders for all gauges of the calculation km range
78 final RiverInfoProvider infoProvider = RiverInfoProvider.forRange(this.context, river, calcRange);
79 final Map<Gauge, GaugeDischargeValuesFinder> qFinders = new HashMap<>();
80 final Map<Gauge, GaugeDischargeZoneFinder> zoneFinders = new HashMap<>();
81 for (final Gauge gauge : river.determineGauges(calcRange.getMinimumDouble(), calcRange.getMaximumDouble())) {
82 qFinders.put(gauge, GaugeDischargeValuesFinder.loadValues(gauge, problems));
83 zoneFinders.put(gauge, GaugeDischargeZoneFinder.loadValues(gauge, problems));
84 }
60 final Collection<ResultRow> detailsRows = new ArrayList<>(); 85 final Collection<ResultRow> detailsRows = new ArrayList<>();
61 86
62 // TODO: calculate 87 // calculate secondary results for each year or epoch
63 88 if (access.getYears() != null) {
64 final CollisionCalculationResults results = new CollisionCalculationResults(calcModeLabel, user, riverInfo, calcRange); 89 for (final int year : access.getYears())
65 90 calculateDetails(detailsRows, infoProvider, access.getLowerKm(), access.getUpperKm(), year, year, qFinders, zoneFinders);
66 final ResultRow row = ResultRow.create().putValue(GeneralResultType.station, 8888.888);
67 final ResultRow row2 = ResultRow.create().putValue(GeneralResultType.station, 777.888);
68
69 for (int i = 0; i < 300; i++) {
70 overViewRows.add(row);
71 overViewRows.add(row2);
72 } 91 }
73 final CollisionCalcOverviewResult overviewResult = new CollisionCalcOverviewResult("Overview", overViewRows); // TODO: get Title-Strings from messages 92 else {
74 results.addResult(overviewResult, problems); 93 for (final DateRange dr : access.getEpochs())
75 for (int i = 0; i < 200; i++) { 94 calculateDetails(detailsRows, infoProvider, access.getLowerKm(), access.getUpperKm(), dr.getFromYear(), dr.getToYear(), qFinders, zoneFinders);
76 detailsRows.add(row);
77 detailsRows.add(row2);
78 } 95 }
79 final CollisionCalcDetailResult detailResult = new CollisionCalcDetailResult("Details", detailsRows); 96 final CollisionCalcDetailResult detailResult = new CollisionCalcDetailResult("Details", detailsRows);
80 results.addResult(detailResult, problems); 97 results.addResult(detailResult, problems);
81 98
82 return new CalculationResult(results, problems); 99 return new CalculationResult(results, problems);
83 } 100 }
101
102 /**
103 * Calculates the collision counts for a km range of a river and a year or year range (epoch),
104 * and adds them to a ResultRow collection
105 */
106 private void calculateOverview(final Collection<ResultRow> rows, final River river, final double fromKm, final double toKm, final int fromYear,
107 final int toYear, final boolean isEpoch) {
108 for (final CollisionAggregateValue aggregate : CollisionAggregateValue.getValuesByKm(river, fromKm, toKm, fromYear, toYear)) {
109 rows.add(ResultRow.create().putValue(GeneralResultType.station, aggregate.getStation())
110 .putValue(SInfoResultType.years, (isEpoch? String.format("%d-%d", fromYear, toYear) : Integer.toString(fromYear)))
111 .putValue(SInfoResultType.collisionCount, aggregate.getCount()));
112 }
113 }
114
115 /**
116 * Calculates the collision details for a km range of a river and a year or year range (epoch),
117 * and adds them to a ResultRow collection
118 */
119 private void calculateDetails(final Collection<ResultRow> rows, final RiverInfoProvider riverInfo, final double fromKm, final double toKm,
120 final int fromYear, final int toYear, final Map<Gauge, GaugeDischargeValuesFinder> qFinders,
121 final Map<Gauge, GaugeDischargeZoneFinder> zoneFinders) {
122 for (final CollisionValue collision : CollisionValue.getValues(riverInfo.getRiver(), fromKm, toKm, DateUtil.getStartDateFromYear(fromYear),
123 DateUtil.getEndDateFromYear(toYear))) {
124 final Gauge gauge = riverInfo.getGauge(collision.getStation(), true);
125 final double q = qFinders.get(gauge).getDischarge(collision.getGaugeW());
126 final double qOut = Double.isInfinite(q) ? Double.NaN : q;
127 rows.add(ResultRow.create().putValue(GeneralResultType.station, collision.getStation())
128 .putValue(GeneralResultType.date, collision.getEventDate())
129 .putValue(SInfoResultType.collisionGaugeW, collision.getGaugeW())
130 .putValue(SInfoResultType.gaugeLabel, collision.getGaugeName())
131 .putValue(SInfoResultType.discharge, qOut)
132 .putValue(SInfoResultType.dischargeZone, zoneFinders.get(gauge).getDischargeZone(q)));
133 }
134 }
84 } 135 }

http://dive4elements.wald.intevation.org