using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace HeuristicLab.Problems.Instances.DataAnalysis.Regression.Matlab.Api.Types { using TMLTimeseriesValueDT = IMLValueVariable>>; public class MLTimeseries : IMLValueVariable>>, IMLTimeseries { private readonly object _locker = new object(); private string[] _dataHeaders; protected MLTimeseries() { Data = new List>(); Name = string.Empty; } /// /// Creates a new timeseries from the given collection of timeseries. /// All values will be merged into one time series. /// /// public MLTimeseries(IEnumerable timeseries) : this() { var dataHeaders = new List(); var times = new SortedSet(); // The time values have to be unique and sorted. foreach (var item in timeseries) { foreach (var dataHeader in item.DataHeader) { dataHeaders.Add(dataHeader); } foreach (var time in item.Times) { times.Add(time); } } var numberOfElements = dataHeaders.Count; Parallel.ForEach(times, (time) => { //foreach (var time in times) { var values = new double[numberOfElements]; int idx = 0; foreach (var item in timeseries) { double[] vs = item.GetValuesByTime(time); foreach (var v in vs) { values[idx++] = v; } } lock (_locker) { Data.Add(new KeyValuePair(time, values)); } }); _dataHeaders = dataHeaders.ToArray(); } public MLTimeseries(string name, object times, object data) : this() { Name = name; if (!(times is double[,]) || !(data is double[,])) { throw new ArgumentException(string.Format("Invalid datatype: times={0}, data={1}", times.GetType(), data.GetType())); } var t = times as double[,]; var d = data as double[,]; if (t.GetLength(0) != d.GetLength(0)) { throw new ArgumentException(string.Format("Number of elements are not equal: times={0}, data={1}", t.GetLength(0), d.GetLength(0))); } var valueColumns = d.GetLength(1); _dataHeaders = new string[valueColumns]; for (int i = 0; i < valueColumns; i++) { _dataHeaders[i] = string.Format("{0}:{1}", Name, i); } for (int i = 0; i < t.GetLength(0); i++) { var time = t[i, 0]; var vals = new double[valueColumns]; for (int j = 0; j < valueColumns; j++) { vals[j] = d[i, j]; } Data.Add(new KeyValuePair(time, vals)); } } private MLTimeseries(IMLTimeseries original) : this() { Name = ((TMLTimeseriesValueDT)original).Name; _dataHeaders = (string[])original.DataHeader.Clone(); foreach (var entry in ((TMLTimeseriesValueDT)original).Data) { Data.Add(new KeyValuePair(entry.Key, entry.Value)); } } public string Name { get; set; } public IList> Data { get; set; } public MLDatatype Datatype { get { return MLDatatype.Timeseries; } } public string[] DataHeader { get { return _dataHeaders; } } public double[] this[int idx] { get { var entry = Data[idx]; var values = new double[entry.Value.Length + 1]; values[0] = Data[idx].Key; for (int i = 1; i < values.Length; i++) { values[i] = entry.Value[i - 1]; } return values; } } public double[] Times { get { return Data.Select(x => x.Key).ToArray(); } } public double GetTimeAt(int idx) { if (idx < Data.Count) { return Data[idx].Key; } return double.MaxValue; } public int Count { get { return Data.Count; } } public double[] GetValuesByTime(double time) { double[] value; if (Data.Count < 0) { value = new double[] { 0.0 }; } value = Data.Where(x => x.Key <= time).LastOrDefault().Value; if (value == null) { return new double[Data[0].Value.Length]; } return value; } public IMLTimeseries ToTimeseries() { return new MLTimeseries(this); } } }