teichmann@5863: /* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde teichmann@5863: * Software engineering by Intevation GmbH teichmann@5863: * teichmann@5994: * This file is Free Software under the GNU AGPL (>=v3) teichmann@5863: * and comes with ABSOLUTELY NO WARRANTY! Check out the teichmann@5994: * documentation coming with Dive4Elements River for details. teichmann@5863: */ teichmann@5863: teichmann@5831: package org.dive4elements.river.artifacts.model.fixings; sascha@3415: teichmann@6875: import gnu.trove.TIntIntHashMap; teichmann@6875: import gnu.trove.TIntObjectHashMap; teichmann@6875: import gnu.trove.TLongHashSet; teichmann@6875: sascha@3730: import java.util.Collection; raimund@3610: import java.util.Date; teichmann@6875: import java.util.TreeMap; raimund@3610: import java.util.TreeSet; raimund@3610: teichmann@6875: import org.apache.commons.logging.Log; teichmann@6875: import org.apache.commons.logging.LogFactory; teichmann@5831: import org.dive4elements.river.artifacts.model.Parameters; sascha@3415: teichmann@5831: import org.dive4elements.river.utils.KMIndex; sascha@3415: sascha@3415: public class FixAnalysisResult sascha@3450: extends FixResult sascha@3415: { teichmann@6875: private static final Log log = teichmann@6875: LogFactory.getLog(FixAnalysisResult.class); teichmann@6875: sascha@3415: protected KMIndex analysisPeriods; sascha@3415: sascha@3415: public FixAnalysisResult() { sascha@3415: } sascha@3415: sascha@3415: public FixAnalysisResult( sascha@3415: Parameters parameters, sascha@3415: KMIndex referenced, sascha@3729: KMIndex outliers, sascha@3415: KMIndex analysisPeriods sascha@3415: ) { sascha@3450: super(parameters, referenced, outliers); sascha@3415: this.analysisPeriods = analysisPeriods; sascha@3415: } sascha@3415: sascha@3415: public int getUsedSectorsInAnalysisPeriods() { sascha@3415: int result = 0; sascha@3415: for (KMIndex.Entry entry: analysisPeriods) { sascha@3415: for (AnalysisPeriod period: entry.getValue()) { sascha@3415: for (int i = 0; i < 4; ++i) { sascha@3415: result |= period.getQSectorAverage(i) != null sascha@3415: ? (1 << i) sascha@3415: : 0; sascha@3415: } sascha@3415: // XXX: Stop early on result == ~(~0 << 4)) ? sascha@3415: } sascha@3415: } sascha@3415: return result; sascha@3415: } sascha@3415: sascha@3730: public Collection getReferenceEventsDates() { raimund@3610: TreeSet dates = new TreeSet(); raimund@3610: for (KMIndex.Entry entry: referenced) { sascha@3730: QWD [] values = entry.getValue(); sascha@3730: for (int i = 0; i < values.length; i++) { sascha@3730: dates.add(values[i].date); raimund@3610: } raimund@3610: } raimund@3610: return dates; raimund@3610: } raimund@3610: teichmann@6875: // TODO Refactor to be more general to be used for analysis periods, too. teichmann@6875: public void makeReferenceEventsDatesUnique() { teichmann@6875: TLongHashSet times = new TLongHashSet(); teichmann@6875: teichmann@6875: TIntObjectHashMap already = new TIntObjectHashMap(); teichmann@6875: teichmann@6875: boolean debug = log.isDebugEnabled(); teichmann@6875: teichmann@6875: for (KMIndex.Entry entry: referenced) { teichmann@6875: for (QWD value: entry.getValue()) { teichmann@6875: // Map same index to same new value teichmann@6875: if (already.containsKey(value.index)) { teichmann@6875: value.date = (Date)already.get(value.index); teichmann@6875: continue; teichmann@6875: } teichmann@6875: long time = value.date.getTime(); teichmann@6875: if (!times.add(time)) { // same found before teichmann@6875: if (debug) { teichmann@6875: log.debug("Found date collision for: " + value.date); teichmann@6875: } teichmann@6875: do { teichmann@6875: time += 30L*1000L; // Add 30secs teichmann@6875: } teichmann@6875: while (!times.add(time)); teichmann@6875: Date newDate = new Date(time); teichmann@6875: already.put(value.index, newDate); teichmann@6875: // write back modified time teichmann@6875: value.date = newDate; teichmann@6875: } teichmann@6875: else { teichmann@6875: already.put(value.index, value.date); teichmann@6875: } teichmann@6875: } teichmann@6875: } teichmann@6875: } teichmann@6875: teichmann@6875: public Collection getReferenceEventsIndices() { teichmann@6875: TreeMap dates = new TreeMap(); teichmann@6875: for (KMIndex.Entry entry: referenced) { teichmann@6875: for (QWD value: entry.getValue()) { teichmann@6875: dates.put(value.date, value.index); teichmann@6875: } teichmann@6875: } teichmann@6875: return dates.values(); teichmann@6875: } teichmann@6875: teichmann@6875: public void remapReferenceIndicesToRank() { teichmann@6875: Collection referenceIndices = getReferenceEventsIndices(); teichmann@6875: int index = 0; teichmann@6875: TIntIntHashMap map = new TIntIntHashMap(); teichmann@6875: boolean debug = log.isDebugEnabled(); teichmann@6875: for (Integer refId: referenceIndices) { teichmann@6875: if (debug) { teichmann@6875: log.debug("map " + refId + " -> " + index); teichmann@6875: } teichmann@6875: map.put(refId, index); teichmann@6875: ++index; teichmann@6875: } teichmann@6875: teichmann@6875: // Two passes: If there are shared references do not teichmann@6875: // remap them twice. In the first pass all indices are teichmann@6875: // mapped to negative values (assuming the original data teichmann@6875: // is all positive). If a negative value is found ignore teichmann@6875: // it because it was remapped before. teichmann@6875: teichmann@6875: for (KMIndex.Entry entry: referenced) { teichmann@6875: for (QWD value: entry.getValue()) { teichmann@6875: if (value.index >= 0) { teichmann@6875: if (map.containsKey(value.index)) { teichmann@6875: value.index = -(map.get(value.index) + 1); teichmann@6875: } teichmann@6875: else { teichmann@6875: log.warn("Could not remap index: " + value.index); teichmann@6875: } teichmann@6875: } teichmann@6875: } teichmann@6875: } teichmann@6875: teichmann@6875: // In the second pass all indices are turned to positive teichmann@6875: // values again. teichmann@6875: for (KMIndex.Entry entry: referenced) { teichmann@6875: for (QWD value: entry.getValue()) { teichmann@6875: if (value.index < 0) { teichmann@6875: value.index = -(value.index + 1); teichmann@6875: } teichmann@6875: } teichmann@6875: } teichmann@6875: } teichmann@6875: sascha@3730: public Collection getAnalysisEventsDates(int analysisPeriod) { raimund@3610: TreeSet dates = new TreeSet(); raimund@3610: for (KMIndex.Entry entry: analysisPeriods) { sascha@3730: QWD [] qwds = entry.getValue()[analysisPeriod].getQWDs(); teichmann@6875: if (qwds != null) { teichmann@6875: for (QWD qwd: qwds) { teichmann@6875: dates.add(qwd.date); teichmann@6875: } raimund@3610: } raimund@3610: } raimund@3610: return dates; raimund@3610: } raimund@3610: sascha@3415: public KMIndex getAnalysisPeriods() { sascha@3415: return analysisPeriods; sascha@3415: } sascha@3415: sascha@3415: public void setAnalysisPeriods(KMIndex analysisPeriods) { sascha@3415: this.analysisPeriods = analysisPeriods; sascha@3415: } sascha@3415: } sascha@3415: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :