sascha@3411: package de.intevation.flys.artifacts.model.fixings; sascha@3411: sascha@3411: import de.intevation.flys.artifacts.access.FixAnalysisAccess; sascha@3411: sascha@3411: import de.intevation.flys.artifacts.math.fitting.Function; sascha@3411: sascha@3411: import de.intevation.flys.artifacts.model.CalculationResult; sascha@3411: import de.intevation.flys.artifacts.model.DateRange; sascha@3411: sascha@3411: import de.intevation.flys.artifacts.model.FixingsOverview.AndFilter; sascha@3411: import de.intevation.flys.artifacts.model.FixingsOverview.DateRangeFilter; sascha@3411: sascha@3411: import de.intevation.flys.artifacts.model.FixingsOverview.Fixing.Filter; sascha@3411: sascha@3411: import de.intevation.flys.artifacts.model.FixingsOverview.Fixing; sascha@3411: import de.intevation.flys.artifacts.model.FixingsOverview.IdsFilter; sascha@3411: import de.intevation.flys.artifacts.model.FixingsOverview.KmFilter; sascha@3411: import de.intevation.flys.artifacts.model.FixingsOverview.SectorFilter; sascha@3411: sascha@3411: import de.intevation.flys.artifacts.model.FixingsOverview; sascha@3411: import de.intevation.flys.artifacts.model.Parameters; sascha@3411: import de.intevation.flys.artifacts.model.Range; sascha@3411: sascha@3411: import de.intevation.flys.utils.DateAverager; sascha@3411: import de.intevation.flys.utils.KMIndex; sascha@3411: sascha@3411: import java.util.ArrayList; sascha@3411: import java.util.Date; sascha@3411: import java.util.List; sascha@3411: sascha@3411: import org.apache.commons.math.stat.descriptive.moment.StandardDeviation; sascha@3411: sascha@3411: import org.apache.log4j.Logger; sascha@3411: sascha@3411: public class FixAnalysisCalculation sascha@3419: extends FixCalculation sascha@3411: { sascha@3411: private static Logger log = Logger.getLogger(FixAnalysisCalculation.class); sascha@3411: sascha@3411: protected DateRange referencePeriod; sascha@3411: protected DateRange [] analysisPeriods; sascha@3411: sascha@3411: public FixAnalysisCalculation() { sascha@3411: } sascha@3411: sascha@3411: public FixAnalysisCalculation(FixAnalysisAccess access) { sascha@3419: super(access); sascha@3411: sascha@3411: DateRange referencePeriod = access.getReferencePeriod(); sascha@3411: DateRange [] analysisPeriods = access.getAnalysisPeriods(); sascha@3411: sascha@3411: if (referencePeriod == null) { sascha@3411: addProblem("fix.missing.reference.period"); sascha@3411: } sascha@3411: sascha@3411: if (analysisPeriods == null || analysisPeriods.length < 1) { sascha@3411: addProblem("fix.missing.analysis.periods"); sascha@3411: } sascha@3411: sascha@3411: if (!hasProblems()) { sascha@3411: this.referencePeriod = referencePeriod; sascha@3411: this.analysisPeriods = analysisPeriods; sascha@3411: } sascha@3411: } sascha@3411: sascha@3437: @Override sascha@3437: public CalculationResult innerCalculate( sascha@3437: FixingsOverview overview, sascha@3437: Function func sascha@3437: ) { sascha@3603: ColumnCache cc = new ColumnCache(); sascha@3603: sascha@3603: FitResult fitResult = doFitting(overview, cc, func); sascha@3411: sascha@3435: if (fitResult == null) { sascha@3411: return new CalculationResult(this); sascha@3411: } sascha@3411: sascha@3435: KMIndex analysisPeriods = sascha@3435: calculateAnalysisPeriods( sascha@3435: func, sascha@3435: fitResult.getParameters(), sascha@3603: overview, sascha@3603: cc); sascha@3411: sascha@3411: analysisPeriods.sort(); sascha@3411: sascha@3435: FixAnalysisResult far = new FixAnalysisResult( sascha@3435: fitResult.getParameters(), sascha@3435: fitResult.getReferenced(), sascha@3435: fitResult.getOutliers(), sascha@3411: analysisPeriods); sascha@3411: sascha@3435: return new CalculationResult(far, this); sascha@3411: } sascha@3411: sascha@3434: @Override sascha@3434: protected Filter createFilter() { sascha@3434: Filter ids = super.createFilter(); sascha@3411: DateRangeFilter rdf = new DateRangeFilter( sascha@3411: referencePeriod.getFrom(), sascha@3411: referencePeriod.getTo()); sascha@3434: return new AndFilter().add(rdf).add(ids); sascha@3411: } sascha@3411: sascha@3411: protected KMIndex calculateAnalysisPeriods( sascha@3411: Function function, sascha@3411: Parameters parameters, sascha@3603: FixingsOverview overview, sascha@3603: ColumnCache cc sascha@3411: ) { sascha@3411: Range range = new Range(from, to); sascha@3411: sascha@3411: int kmIndex = parameters.columnIndex("km"); sascha@3411: int maxQIndex = parameters.columnIndex("max_q"); sascha@3411: sascha@3411: double [] wq = new double[2]; sascha@3411: sascha@3411: int [] parameterIndices = sascha@3411: parameters.columnIndices(function.getParameterNames()); sascha@3411: sascha@3411: double [] parameterValues = new double[parameterIndices.length]; sascha@3411: sascha@3411: DateAverager dateAverager = new DateAverager(); sascha@3411: sascha@3411: KMIndex results = sascha@3411: new KMIndex(parameters.size()); sascha@3411: sascha@3411: IdsFilter idsFilter = new IdsFilter(events); sascha@3411: sascha@3411: for (int row = 0, R = parameters.size(); row < R; ++row) { sascha@3411: double km = parameters.get(row, kmIndex); sascha@3411: parameters.get(row, parameterIndices, parameterValues); sascha@3411: sascha@3411: // This is the paraterized function for a given km. sascha@3411: de.intevation.flys.artifacts.math.Function instance = sascha@3411: function.instantiate(parameterValues); sascha@3411: sascha@3411: KmFilter kmFilter = new KmFilter(km); sascha@3411: sascha@3411: ArrayList periodResults = sascha@3411: new ArrayList(analysisPeriods.length); sascha@3411: sascha@3411: for (DateRange analysisPeriod: analysisPeriods) { sascha@3411: DateRangeFilter drf = new DateRangeFilter( sascha@3411: analysisPeriod.getFrom(), sascha@3411: analysisPeriod.getTo()); sascha@3411: sascha@3411: QWD [] qSectorAverages = new QWD[4]; sascha@3411: double [] qSectorStdDevs = new double[4]; sascha@3411: sascha@3411: ArrayList allQWDs = new ArrayList(); sascha@3411: sascha@3411: // for all Q sectors. sascha@3411: for (int qSector = qSectorStart; qSector < qSectorEnd; ++qSector) { sascha@3411: sascha@3411: Filter filter = new AndFilter() sascha@3411: .add(kmFilter) sascha@3411: .add(new SectorFilter(qSector)) sascha@3411: .add(drf) sascha@3411: .add(idsFilter); sascha@3411: sascha@3411: List metas = overview.filter(range, filter); sascha@3411: sascha@3411: if (metas.isEmpty()) { sascha@3411: // No fixings for km and analysis period sascha@3411: continue; sascha@3411: } sascha@3411: sascha@3411: double sumQ = 0.0; sascha@3411: double sumW = 0.0; sascha@3411: sascha@3411: StandardDeviation stdDev = new StandardDeviation(); sascha@3411: sascha@3411: List qwds = new ArrayList(metas.size()); sascha@3411: sascha@3411: dateAverager.clear(); sascha@3411: sascha@3411: for (Fixing.Column meta: metas) { sascha@3411: if (meta.findQSector(km) != qSector) { sascha@3411: // Ignore not matching sectors. sascha@3411: continue; sascha@3411: } sascha@3411: sascha@3411: Column column = cc.getColumn(meta); sascha@3411: if (column == null || !column.getQW(km, wq)) { sascha@3411: continue; sascha@3411: } sascha@3411: sascha@3411: double fw = instance.value(wq[1]); sascha@3411: if (Double.isNaN(fw)) { sascha@3411: continue; sascha@3411: } sascha@3411: sascha@3411: double dw = (wq[0] - fw)*100.0; sascha@3411: sascha@3411: stdDev.increment(dw); sascha@3411: sascha@3411: Date date = column.getDate(); sascha@3411: String description = column.getDescription(); sascha@3411: sascha@3411: QWD qwd = new QWD( sascha@3411: wq[1], wq[0], description, date, true, dw); sascha@3411: sascha@3411: qwds.add(qwd); sascha@3411: sascha@3411: sumW += wq[0]; sascha@3411: sumQ += wq[1]; sascha@3411: sascha@3411: dateAverager.add(date); sascha@3411: } sascha@3411: sascha@3411: // Calulate average per Q sector. sascha@3411: int N = qwds.size(); sascha@3411: if (N > 0) { sascha@3411: allQWDs.addAll(qwds); sascha@3411: double avgW = sumW / N; sascha@3411: double avgQ = sumQ / N; sascha@3411: sascha@3411: double avgFw = instance.value(avgQ); sascha@3411: if (!Double.isNaN(avgFw)) { sascha@3411: double avgDw = (avgW - avgFw)*100.0; sascha@3411: Date avgDate = dateAverager.getAverage(); sascha@3411: sascha@3411: String avgDescription = "avg.deltawt." + qSector; sascha@3411: sascha@3411: QWD avgQWD = new QWD( sascha@3411: avgQ, avgW, avgDescription, avgDate, true, avgDw); sascha@3411: sascha@3411: qSectorAverages[qSector] = avgQWD; sascha@3411: } sascha@3411: qSectorStdDevs[qSector] = stdDev.getResult(); sascha@3411: } sascha@3411: else { sascha@3411: qSectorStdDevs[qSector] = Double.NaN; sascha@3411: } sascha@3411: } // for all Q sectors sascha@3411: sascha@3411: QWD [] aqwds = allQWDs.toArray(new QWD[allQWDs.size()]); sascha@3411: sascha@3411: AnalysisPeriod periodResult = new AnalysisPeriod( sascha@3411: analysisPeriod, sascha@3411: aqwds, sascha@3411: qSectorAverages, sascha@3411: qSectorStdDevs); sascha@3411: periodResults.add(periodResult); sascha@3411: } sascha@3411: sascha@3411: double maxQ = -Double.MAX_VALUE; sascha@3411: for (AnalysisPeriod ap: periodResults) { sascha@3411: double q = ap.getMaxQ(); sascha@3411: if (q > maxQ) { sascha@3411: maxQ = q; sascha@3411: } sascha@3411: } sascha@3411: sascha@3411: double oldMaxQ = parameters.get(row, maxQIndex); sascha@3411: if (oldMaxQ < maxQ) { sascha@3411: parameters.set(row, maxQIndex, maxQ); sascha@3411: } sascha@3411: sascha@3411: results.add(km, periodResults.toArray( sascha@3411: new AnalysisPeriod[periodResults.size()])); sascha@3411: } sascha@3411: sascha@3411: return results; sascha@3411: } sascha@3411: } sascha@3411: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :