view artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixAnalysisResult.java @ 6875:437856cec419

FixA: Fixed reference events mapping. TODO: Same for analysis periods.
author Sascha L. Teichmann <teichmann@intevation.de>
date Tue, 20 Aug 2013 19:24:26 +0200
parents af13ceeba52a
children 2d96d8240e3e
line wrap: on
line source
/* 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.fixings;

import gnu.trove.TIntIntHashMap;
import gnu.trove.TIntObjectHashMap;
import gnu.trove.TLongHashSet;

import java.util.Collection;
import java.util.Date;
import java.util.TreeMap;
import java.util.TreeSet;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dive4elements.river.artifacts.model.Parameters;

import org.dive4elements.river.utils.KMIndex;

public class FixAnalysisResult
extends      FixResult
{
    private static final Log log =
        LogFactory.getLog(FixAnalysisResult.class);

    protected KMIndex<AnalysisPeriod []> analysisPeriods;

    public FixAnalysisResult() {
    }

    public FixAnalysisResult(
        Parameters                 parameters,
        KMIndex<QWD []>            referenced,
        KMIndex<QWI []>            outliers,
        KMIndex<AnalysisPeriod []> analysisPeriods
    ) {
        super(parameters, referenced, outliers);
        this.analysisPeriods = analysisPeriods;
    }

    public int getUsedSectorsInAnalysisPeriods() {
        int result = 0;
        for (KMIndex.Entry<AnalysisPeriod []> entry: analysisPeriods) {
            for (AnalysisPeriod period: entry.getValue()) {
                for (int i = 0; i < 4; ++i) {
                    result |= period.getQSectorAverage(i) != null
                        ? (1 << i)
                        : 0;
                }
                // XXX: Stop early on result == ~(~0 << 4)) ?
            }
        }
        return result;
    }

    public Collection<Date> getReferenceEventsDates() {
        TreeSet<Date> dates = new TreeSet<Date>();
        for (KMIndex.Entry<QWD []> entry: referenced) {
            QWD [] values = entry.getValue();
            for (int i = 0; i < values.length; i++) {
                dates.add(values[i].date);
            }
        }
        return dates;
    }

    // TODO Refactor to be more general to be used for analysis periods, too.
    public void makeReferenceEventsDatesUnique() {
        TLongHashSet times   = new TLongHashSet();

        TIntObjectHashMap already = new TIntObjectHashMap();

        boolean debug = log.isDebugEnabled();

        for (KMIndex.Entry<QWD []> entry: referenced) {
            for (QWD value: entry.getValue()) {
                // Map same index to same new value
                if (already.containsKey(value.index)) {
                    value.date = (Date)already.get(value.index);
                    continue;
                }
                long time = value.date.getTime();
                if (!times.add(time)) { // same found before
                    if (debug) {
                        log.debug("Found date collision for: " + value.date);
                    }
                    do {
                        time += 30L*1000L; // Add 30secs
                    }
                    while (!times.add(time));
                    Date newDate = new Date(time);
                    already.put(value.index, newDate);
                    // write back modified time
                    value.date = newDate;
                }
                else {
                    already.put(value.index, value.date);
                }
            }
        }
    }

    public Collection<Integer> getReferenceEventsIndices() {
        TreeMap<Date, Integer> dates = new TreeMap<Date, Integer>();
        for (KMIndex.Entry<QWD []> entry: referenced) {
            for (QWD value: entry.getValue()) {
                dates.put(value.date, value.index);
            }
        }
        return dates.values();
    }

    public void remapReferenceIndicesToRank() {
        Collection<Integer> referenceIndices = getReferenceEventsIndices();
        int index = 0;
        TIntIntHashMap map = new TIntIntHashMap();
        boolean debug = log.isDebugEnabled();
        for (Integer refId: referenceIndices) {
            if (debug) {
                log.debug("map " + refId + " -> " + index);
            }
            map.put(refId, index);
            ++index;
        }

        // Two passes: If there are shared references do not
        // remap them twice. In the first pass all indices are
        // mapped to negative values (assuming the original data
        // is all positive). If a negative value is found ignore
        // it because it was remapped before.

        for (KMIndex.Entry<QWD []> entry: referenced) {
            for (QWD value: entry.getValue()) {
                if (value.index >= 0) {
                    if (map.containsKey(value.index)) {
                        value.index = -(map.get(value.index) + 1);
                    }
                    else {
                        log.warn("Could not remap index: " + value.index);
                    }
                }
            }
        }

        // In the second pass all indices are turned to positive
        // values again.
        for (KMIndex.Entry<QWD []> entry: referenced) {
            for (QWD value: entry.getValue()) {
                if (value.index < 0) {
                    value.index = -(value.index + 1);
                }
            }
        }
    }

    public Collection<Date> getAnalysisEventsDates(int analysisPeriod) {
        TreeSet<Date> dates = new TreeSet<Date>();
        for (KMIndex.Entry<AnalysisPeriod []> entry: analysisPeriods) {
            QWD [] qwds = entry.getValue()[analysisPeriod].getQWDs();
            if (qwds != null) {
                for (QWD qwd: qwds) {
                    dates.add(qwd.date);
                }
            }
        }
        return dates;
    }

    public KMIndex<AnalysisPeriod []> getAnalysisPeriods() {
        return analysisPeriods;
    }

    public void setAnalysisPeriods(KMIndex<AnalysisPeriod []> analysisPeriods) {
        this.analysisPeriods = analysisPeriods;
    }
}
// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org