/*
 * Copyright (C) 2008-2015 by Holger Arndt
 *
 * This file is part of the Universal Java Matrix Package (UJMP).
 * See the NOTICE file distributed with this work for additional
 * information regarding copyright ownership and licensing.
 *
 * UJMP is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * UJMP is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with UJMP; if not, write to the
 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
 * Boston, MA  02110-1301  USA
 */

package org.ujmp.core.timeseries;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

import org.ujmp.core.Matrix;
import org.ujmp.core.collections.composite.SortedListSet;
import org.ujmp.core.doublematrix.stub.AbstractDenseDoubleMatrix2D;

public class TimeSeriesMatrix extends AbstractDenseDoubleMatrix2D {
	private static final long serialVersionUID = 4326920011599023858L;

	public enum Interpolation {
		NONE, STEPS, LINEAR
	};

	private Interpolation defaultInterpolation = Interpolation.NONE;

	private final Map seriesInterpolations = new HashMap();

	private final List> series = new ArrayList>();

	private final SortedListSet timestampsListSet = new SortedListSet();

	public TimeSeriesMatrix() {
		super(1, 1);
	}

	public void addEvent(long timestamp, Matrix value) {
		if (value.getRowCount() != 1) {
			throw new RuntimeException("matrix cannot have more than one row");
		}
		for (int id = 0; id < value.getColumnCount(); id++) {
			addEvent(timestamp, id + 1, value.getAsDouble(0, id));
		}
	}

	public Interpolation getInterpolation(int seriesId) {
		Interpolation i = seriesInterpolations.get(seriesId);
		if (i == null) {
			return defaultInterpolation;
		} else {
			return i;
		}
	}

	public Interpolation getDefaultInterpolation() {
		return defaultInterpolation;
	}

	public void setDefaultInterpolation(Interpolation defaultInterpolation) {
		this.defaultInterpolation = defaultInterpolation;
	}

	/**
	 * Adds the events of a new Matrix to the time series. The first column of
	 * the matrix must contain the timestamps.
	 * 
	 * @param events
	 *            matrix with events to add
	 */
	public void addEvents(Matrix events) {
		int seriesCount = getSeriesCount();
		for (int r = 0; r < events.getRowCount(); r++) {
			long timestamp = events.getAsLong(r, 0);
			for (int c = 1; c < events.getColumnCount(); c++) {
				double value = events.getAsDouble(r, c);
				addEvent(timestamp, seriesCount + c - 1, value);
			}
		}
	}

	public void addEvent(long timestamp, int column, double value) {
		int seriesId = column - 1;
		while (series.size() <= seriesId) {
			series.add(new TreeMap());
		}
		SortedMap map = series.get(seriesId);
		map.put(timestamp, value);
		timestampsListSet.add(timestamp);
	}

	public int getEventCount() {
		return timestampsListSet.size();
	}

	public int getSeriesCount() {
		return series.size();
	}

	public List getTimestamps() {
		return timestampsListSet;
	}

	public long[] getSize() {
		size[ROW] = getEventCount();
		size[COLUMN] = getSeriesCount() + 1;
		return size;
	}

	public long getRowCount() {
		return getEventCount();
	}

	public long getColumnCount() {
		return getSeriesCount() + 1;
	}

	public double getDouble(long row, long column) {
		return getDouble((int) row, (int) column);
	}

	public double getDouble(int row, int column) {

		if (row < 0 || column >= getColumnCount() || row >= getRowCount()) {
			return Double.NaN;
		}

		int seriesId = column - 1;
		long timestamp = timestampsListSet.get(row);
		if (column == 0) {
			return timestamp;
		} else {
			SortedMap map = series.get(seriesId);
			switch (getInterpolation(seriesId)) {
			case NONE:
				Double v = map.get(timestamp);
				if (v == null) {
					return Double.NaN;
				} else {
					return v;
				}

			case STEPS:
				Iterator it = map.keySet().iterator();
				double value = 0.0;
				while (it.hasNext()) {
					long t = it.next();
					if (t > timestamp) {
						break;
					} else {
						value = map.get(t);
					}
				}
				return value;

			default:
				throw new RuntimeException("Interpolation method not (yet) supported: "
						+ getInterpolation(seriesId));
			}
		}
	}

	public void setDouble(double value, long row, long column) {
		throw new RuntimeException("please use addEvent() for making changes");
	}

	public void setDouble(double value, int row, int column) {
		throw new RuntimeException("please use addEvent() for making changes");
	}

	public void setInterpolation(int column, Interpolation interpolation) {
		int seriesId = column - 1;
		seriesInterpolations.put(seriesId, interpolation);
	}

	public long getRowForTime(long time) {
		long rows = getRowCount();
		for (long r = 0; r < rows; r++) {
			long t = getAsLong(r, 0);
			if (t == time) {
				return r;
			}
		}
		return -1;
	}

	public double getAsDoubleForTime(long time, long column) {
		long row = getRowForTime(time);
		if (row < 0 || column >= getColumnCount()) {
			return Double.NaN;
		}
		return getAsDouble(row, column);
	}

	public long getTimestamp(long row) {
		if (row < 0 | row >= timestampsListSet.size()) {
			return 0;
		} else {
			return timestampsListSet.get((int) row);
		}
	}

	public long getMinTimestamp() {
		if (timestampsListSet.isEmpty()) {
			return 0;
		} else {
			return timestampsListSet.first();
		}
	}

	public long getMaxTimestamp() {
		if (timestampsListSet.isEmpty()) {
			return 0;
		} else {
			return timestampsListSet.last();
		}
	}

}

 

Ads help maintain this website.