view artifacts/src/main/java/org/dive4elements/river/artifacts/states/fixation/FixAnalysisCompute.java @ 9415:9744ce3c3853

Rework of fixanalysis computation and dWt and WQ facets. Got rid of strange remapping and bitshifting code by explicitely saving the column information and using it in the facets. The facets also put the valid station range into their xml-metadata
author gernotbelger
date Thu, 16 Aug 2018 16:27:53 +0200
parents ddcd52d239cd
children 2b83d3a96703
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.states.fixation;

import java.text.DateFormat;
import java.util.Collection;
import java.util.Date;
import java.util.List;

import org.apache.commons.lang.math.DoubleRange;
import org.apache.log4j.Logger;
import org.dive4elements.artifactdatabase.state.Facet;
import org.dive4elements.artifactdatabase.state.FacetActivity;
import org.dive4elements.artifacts.Artifact;
import org.dive4elements.artifacts.CallContext;
import org.dive4elements.river.artifacts.D4EArtifact;
import org.dive4elements.river.artifacts.access.FixAnalysisAccess;
import org.dive4elements.river.artifacts.model.CalculationResult;
import org.dive4elements.river.artifacts.model.DataFacet;
import org.dive4elements.river.artifacts.model.DateRange;
import org.dive4elements.river.artifacts.model.FacetTypes;
import org.dive4elements.river.artifacts.model.ReportFacet;
import org.dive4elements.river.artifacts.model.fixings.AnalysisPeriodEventResults;
import org.dive4elements.river.artifacts.model.fixings.FixAnalysisCalculation;
import org.dive4elements.river.artifacts.model.fixings.FixAnalysisEventsFacet;
import org.dive4elements.river.artifacts.model.fixings.FixAnalysisPeriodsFacet;
import org.dive4elements.river.artifacts.model.fixings.FixAnalysisResult;
import org.dive4elements.river.artifacts.model.fixings.FixAvSectorFacet;
import org.dive4elements.river.artifacts.model.fixings.FixDerivateFacet;
import org.dive4elements.river.artifacts.model.fixings.FixDeviationFacet;
import org.dive4elements.river.artifacts.model.fixings.FixLongitudinalAnalysisFacet;
import org.dive4elements.river.artifacts.model.fixings.FixLongitudinalAvSectorFacet;
import org.dive4elements.river.artifacts.model.fixings.FixLongitudinalDeviationFacet;
import org.dive4elements.river.artifacts.model.fixings.FixLongitudinalReferenceFacet;
import org.dive4elements.river.artifacts.model.fixings.FixReferenceEventsFacet;
import org.dive4elements.river.artifacts.model.fixings.FixResultColumn;
import org.dive4elements.river.artifacts.model.fixings.FixResultColumns;
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;

/**
 * @author <a href="mailto:raimund.renkert@intevation.de">Raimund Renkert</a>
 */
public class FixAnalysisCompute extends DefaultState implements FacetTypes {

    private static final long serialVersionUID = 1L;

    /** The log used in this class. */
    private static Logger log = Logger.getLogger(FixAnalysisCompute.class);

    private static final String I18N_REFERENCEPERIOD_SHORT = "fix.reference.period.event.short";

    private static final String I18N_ANALYSISPERIODS = "fix.analysis.periods";

    private static final String I18N_DERIVATIVE = "fix.derivative";

    private static final String I18N_ANALYSIS = "fix.analysis.short";

    private static final String I18N_DEVIATION = "fix.deviation";

    private static final String I18N_REFERENCEDEVIATION = "fix.reference.deviation";

    private static final String I18N_REFERENCEPERIOD = "state.fix.analysis.referenceperiod";

    public static final String[] SECTOR_LABELS = { "fix.mnq", "fix.mq", "fix.mhq", "fix.hq5" };

    static {
        // Active/deactivate facets.
        FacetActivity.Registry.getInstance().register("fixanalysis", new FacetActivity() {
            @Override
            public Boolean isInitialActive(final Artifact artifact, final Facet facet, final String output) {
                if (output.contains(FacetTypes.ChartType.FLSC.toString())) {
                    // Longitudinal section chart
                    final String name = facet.getName();

                    if (name.contains(FacetTypes.FIX_ANALYSIS_EVENTS_DWT) || name.contains(FacetTypes.FIX_ANALYSIS_EVENTS_LS)
                            || name.contains(FacetTypes.FIX_ANALYSIS_EVENTS_WQ) || name.contains(FacetTypes.FIX_REFERENCE_EVENTS_DWT)
                            || name.contains(FacetTypes.FIX_REFERENCE_EVENTS_LS) || name.contains(FacetTypes.FIX_REFERENCE_EVENTS_WQ)) {
                        return Boolean.FALSE;
                    }
                }
                if (output.contains(FacetTypes.ChartType.FDWC.toString()) && facet.getName().contains(FacetTypes.FIX_SECTOR_AVERAGE_DWT)) {
                    return Boolean.FALSE;
                }

                return Boolean.TRUE;
            }
        });
    }

    /**
     * The default constructor that initializes an empty State object.
     */
    public FixAnalysisCompute() {
    }

    @Override
    public Object computeAdvance(final D4EArtifact artifact, final String hash, final CallContext context, final List<Facet> facets, final Object old) {
        log.debug("FixAnalysisCompute.computeAdvance");

        CalculationResult res;

        final FixAnalysisAccess access = new FixAnalysisAccess(artifact);

        if (old instanceof CalculationResult) {
            res = (CalculationResult) old;
        } else {
            final FixAnalysisCalculation calc = new FixAnalysisCalculation(access);
            res = calc.calculate();
        }

        if (facets == null) {
            return res;
        }

        if (res.getReport().hasProblems()) {
            facets.add(new ReportFacet(ComputeType.ADVANCE, hash, this.id));
        }

        final FixAnalysisResult fr = (FixAnalysisResult) res.getData();
        if (fr == null) {
            return res;
        }

        facets.add(new DataFacet(CSV, "CSV data", ComputeType.ADVANCE, hash, this.id));
        facets.add(new DataFacet(FIX_PARAMETERS, "parameters", ComputeType.ADVANCE, hash, this.id));
        facets.add(new DataFacet(AT, "AT data", ComputeType.ADVANCE, hash, this.id));
        facets.add(new DataFacet(PDF, "PDF data", ComputeType.ADVANCE, hash, this.id));

        int maxId = -100;

        final int sectorMask = fr.getUsedSectorsInAnalysisPeriods();

        final int qsS = access.getQSectorStart();
        final int qsE = access.getQSectorEnd();

        final DateFormat df = Formatter.getDateFormatter(context.getMeta(), "dd.MM.yyyy");
        final UniqueDateFormatter cf = new UniqueDateFormatter(df);

        final AnalysisPeriodEventResults analysisEventResults = fr.getAnalysisEventResults();

        final DateRange[] periods = access.getAnalysisPeriods();

        int facetIndex = 0;

        for (int i = 0; i < periods.length; i++) {
            final DateRange period = periods[i];
            final String startDate = df.format(period.getFrom());
            final String endDate = df.format(period.getTo());

            for (int j = qsS; j <= qsE; j++) {

                // Only emit facets for sectors that really have data.
                if ((sectorMask & (1 << j)) == 0) {
                    continue;
                }

                final String sector = SECTOR_LABELS[j];
                final String description = "\u0394W (" + Resources.getMsg(context.getMeta(), sector, sector) + ")";

                final int sectorNdx = j - qsS;
                int facetNdx = i << 2;
                facetNdx = facetNdx | j;

                if (facetNdx > maxId) {
                    maxId = facetNdx;
                }

                facets.add(new FixAvSectorFacet(facetNdx, FIX_SECTOR_AVERAGE_DWT + "_" + sectorNdx, description));
                facets.add(
                        new FixLongitudinalAvSectorFacet(facetNdx, FIX_SECTOR_AVERAGE_LS + "_" + sectorNdx, description + ":" + startDate + " - " + endDate));
                // TODO: i18n
                final String dev = "Abweichung: " + description;
                facets.add(new FixLongitudinalAvSectorFacet(facetNdx, FIX_SECTOR_AVERAGE_LS_DEVIATION + "_" + sectorNdx, dev));
                facets.add(new FixAvSectorFacet(facetNdx, FIX_SECTOR_AVERAGE_WQ + "_" + sectorNdx, description));
            }

            final String eventDesc = Resources.getMsg(context.getMeta(), I18N_ANALYSIS, I18N_ANALYSIS);

            final FixResultColumns analysisEventResult = analysisEventResults.getEventResults(i);
            final Collection<FixResultColumn> columns = analysisEventResult.getSortedColumns();

            for (final FixResultColumn analysisEventColumn : columns) {

                final int columnId = analysisEventColumn.getColumnId();
                final Date d = analysisEventColumn.getDate();
                final DoubleRange stationRange = analysisEventColumn.getStationRange();

                final String facetDescription = eventDesc + (i + 1) + " - " + cf.format(d);

                facets.add(new FixAnalysisEventsFacet(facetIndex++, i, columnId, FIX_ANALYSIS_EVENTS_DWT, facetDescription, stationRange));
                facets.add(new FixLongitudinalAnalysisFacet(facetIndex++, i, columnId, FIX_ANALYSIS_EVENTS_LS, facetDescription));
                facets.add(new FixAnalysisEventsFacet(facetIndex++, i, columnId, FIX_ANALYSIS_EVENTS_WQ, facetDescription, stationRange));
            }
        }

        final IdGenerator idg = new IdGenerator(maxId + 1);

        final String i18n_ref = Resources.getMsg(context.getMeta(), I18N_REFERENCEPERIOD_SHORT, I18N_REFERENCEPERIOD_SHORT);
        final String i18n_dev = Resources.getMsg(context.getMeta(), I18N_REFERENCEDEVIATION, I18N_REFERENCEDEVIATION);

        final FixResultColumns columns = fr.getFixResultColumns();

        final Collection<FixResultColumn> fixEvents = columns.getSortedColumns();
        for (final FixResultColumn event : fixEvents) {

            final int columnId = event.getColumnId();
            final DoubleRange stationRange = event.getStationRange();

            final Date date = event.getDate();
            final String dateText = cf.format(date);
            final String facetDescription = i18n_ref + " - " + dateText;

            facets.add(new FixReferenceEventsFacet(facetIndex++, columnId, FIX_REFERENCE_EVENTS_DWT, facetDescription, stationRange));
            facets.add(new FixLongitudinalReferenceFacet(facetIndex++, columnId, FIX_REFERENCE_EVENTS_LS, facetDescription));
            facets.add(new FixReferenceEventsFacet(facetIndex++, columnId, FIX_REFERENCE_EVENTS_WQ, facetDescription, stationRange));
        }

        facets.add(new FixLongitudinalDeviationFacet(idg.next(), FIX_DEVIATION_LS, i18n_dev));

        final String i18n_ana = Resources.getMsg(context.getMeta(), I18N_ANALYSISPERIODS, I18N_ANALYSISPERIODS);
        facets.add(new FixAnalysisPeriodsFacet(idg.next(), FIX_ANALYSIS_PERIODS_DWT, i18n_ana));
        facets.add(new FixAnalysisPeriodsFacet(idg.next(), FIX_ANALYSIS_PERIODS_LS, i18n_ana));
        facets.add(new FixAnalysisPeriodsFacet(idg.next(), FIX_ANALYSIS_PERIODS_WQ, i18n_ana));

        final String i18n_refp = Resources.getMsg(context.getMeta(), I18N_REFERENCEPERIOD, I18N_REFERENCEPERIOD);
        facets.add(new DataFacet(idg.next(), FIX_REFERENCE_PERIOD_DWT, i18n_refp, ComputeType.ADVANCE, null, null));
        facets.add(new FixWQCurveFacet(idg.next(), "W/Q"));
        facets.add(new FixDerivateFacet(idg.next(), FIX_DERIVATE_CURVE, Resources.getMsg(context.getMeta(), I18N_DERIVATIVE, I18N_DERIVATIVE)));
        facets.add(new FixDeviationFacet(idg.next(), FIX_DEVIATION_DWT, Resources.getMsg(context.getMeta(), I18N_DEVIATION, I18N_DEVIATION)));

        return res;
    }
}

http://dive4elements.wald.intevation.org