From 940ab236779cbd54745834bfc7349f64df26c48a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steinar=20Elgs=C3=A6ter?= Date: Wed, 6 Dec 2023 08:44:18 +0100 Subject: [PATCH] timeseriesanalysis.todict --- TimeSeriesAnalysis.csproj | 2 +- TimeSeriesAnalysis/TimeSeriesDataSet.cs | 299 +++++++++++++----------- 2 files changed, 164 insertions(+), 137 deletions(-) diff --git a/TimeSeriesAnalysis.csproj b/TimeSeriesAnalysis.csproj index 2adaab5c..755d0840 100644 --- a/TimeSeriesAnalysis.csproj +++ b/TimeSeriesAnalysis.csproj @@ -14,7 +14,7 @@ False https://github.com/equinor/timeseriesanalysis readme.md - 1.2.58 + 1.2.59 Equinor Equinor true diff --git a/TimeSeriesAnalysis/TimeSeriesDataSet.cs b/TimeSeriesAnalysis/TimeSeriesDataSet.cs index da18fa51..c1eefb5f 100644 --- a/TimeSeriesAnalysis/TimeSeriesDataSet.cs +++ b/TimeSeriesAnalysis/TimeSeriesDataSet.cs @@ -119,87 +119,6 @@ public bool AddConstant(string signalName, double value) return true; } - private void Fill(DateTime[] dateTimes, Dictionary variableDict) - { - if (variableDict.ContainsKey("Time")) - { - variableDict.Remove("Time"); - } - if (variableDict.ContainsKey("time")) - { - variableDict.Remove("time"); - } - dataset = variableDict; - N = dataset[dataset.Keys.First()].Length; - if (dateTimes.Length > 1) - { - timeStamps = dateTimes.ToList(); - } - } - - - public double GetTimeBase() - { - if (timeStamps.Count > 2) - { - return timeStamps[2].Subtract(timeStamps[1]).TotalSeconds; - } - else - return 0; - } - - /// - /// Define a new signal, specifying only its inital value - /// - /// - /// the value of time zero - /// number of time stamps - /// what value to fill in for future undefined times, default:nan - public void InitNewSignal(string signalName, double initalValue, int N, double nonYetSimulatedValue = double.NaN) - { - Add(signalName, Vec.Concat(new double[] { initalValue }, - Vec.Fill(nonYetSimulatedValue, N - 1))); - } - - /// - /// Loads the CsvContent(which can be read from a file) into a TimeSeriesDataSet object - /// - /// - /// - /// - /// - public bool LoadFromCsv(CsvContent csvContent, char separator = ';', string dateTimeFormat = "yyyy-MM-dd HH:mm:ss") - { - bool isOK = CSV.LoadDataFromCsvContentAsTimeSeries(csvContent, separator, out DateTime[] dateTimes, - out Dictionary variableDict, dateTimeFormat); - if (isOK) - { - Fill(dateTimes, variableDict); - } - return isOK; - } - - - - /// - /// Removes a signal from the dataset - /// - /// - /// - public bool Remove(string signalName) - { - if (dataset.ContainsKey(signalName)) - { - dataset.Remove(signalName); - return true; - } - else - { - return false; - } - } - - /// /// Adds all signals in a given set to this set @@ -220,27 +139,6 @@ public bool AddSet(TimeSeriesDataSet inputDataSet) return true; } - /// - /// Combine this data set with the inputDataset into a new set - /// - /// - /// the newly created dataset - public TimeSeriesDataSet Combine(TimeSeriesDataSet inputDataSet) - { - TimeSeriesDataSet dataSet = new TimeSeriesDataSet(this); - foreach (string signalName in inputDataSet.GetSignalNames()) - { - double[] values = inputDataSet.GetValues(signalName); - N = values.Length;// todo:check that all are equal length - - bool isOk = dataSet.Add(signalName, values); - } - if (inputDataSet.GetTimeStamps() != null) - { - dataSet.SetTimeStamps(inputDataSet.GetTimeStamps().ToList()); - } - return dataSet; - } /// /// Add a single data point @@ -299,57 +197,67 @@ public bool ContainsSignal(string signalID) return dataset.ContainsKey(signalID); } - /// - /// Returns a copy of the dataset that is downsampled by the given factor + /// Combine this data set with the inputDataset into a new set /// - /// value greater than 1 indicating that every nth value of the orignal data will be transferred - /// - public TimeSeriesDataSet CreateDownsampledCopy(int downsampleFactor) + /// + /// the newly created dataset + public TimeSeriesDataSet Combine(TimeSeriesDataSet inputDataSet) { - TimeSeriesDataSet ret = new TimeSeriesDataSet(); + TimeSeriesDataSet dataSet = new TimeSeriesDataSet(this); + foreach (string signalName in inputDataSet.GetSignalNames()) + { + double[] values = inputDataSet.GetValues(signalName); + N = values.Length;// todo:check that all are equal length - ret.timeStamps = Vec.Downsample(timeStamps.ToArray(), downsampleFactor).ToList(); - ret.N = ret.timeStamps.Count(); - ret.dataset_constants = dataset_constants; - foreach (var item in dataset) + bool isOk = dataSet.Add(signalName, values); + } + if (inputDataSet.GetTimeStamps() != null) { - ret.dataset[item.Key] = Vec.Downsample(item.Value, downsampleFactor); + dataSet.SetTimeStamps(inputDataSet.GetTimeStamps().ToList()); } - return ret; + return dataSet; } - /// - /// Creates internal timestamps from a given start time and timebase, must be called after filling the values - /// - /// the time between samples in the dataset, in total seconds - /// start time, can be null, which can be usedful for testing - public void CreateTimestamps(double timeBase_s, DateTime? t0 = null) + + private void Fill(DateTime[] dateTimes, Dictionary variableDict) { - if (t0 == null) + if (variableDict.ContainsKey("Time")) { - t0 = new DateTime(2010, 1, 1);//intended for testing + variableDict.Remove("Time"); } + if (variableDict.ContainsKey("time")) + { + variableDict.Remove("time"); + } + dataset = variableDict; + N = dataset[dataset.Keys.First()].Length; + if (dateTimes.Length > 1) + { + timeStamps = dateTimes.ToList(); + } + } - var times = new List(); - DateTime time = t0.Value; - for (int i = 0; i < N; i++) + + public double GetTimeBase() + { + if (timeStamps.Count > 2) { - times.Add(time); - time = time.AddSeconds(timeBase_s); + return timeStamps[2].Subtract(timeStamps[1]).TotalSeconds; } - timeStamps = times; + else + return 0; } /// /// Get all signals in the dataset as a matrix /// /// the signals as a 2d-matrix, and the an array of strings with corresponding signal names - public (double[,], string[]) GetAsMatrix(List indicesToIgnore=null) + public (double[,], string[]) GetAsMatrix(List indicesToIgnore = null) { List listOfVectors = (List)dataset.Values.ToList(); double[][] jagged = Array2D.CreateJaggedFromList(listOfVectors, indicesToIgnore); - double[,] ret2D = Array2D.Created2DFromJagged(jagged); + double[,] ret2D = Array2D.Created2DFromJagged(jagged); return (ret2D.Transpose(), dataset.Keys.ToArray()); } @@ -369,7 +277,7 @@ public void CreateTimestamps(double timeBase_s, DateTime? t0 = null) { return null; } - else if (timeIdx > dataset[signalName].Count()-1) + else if (timeIdx > dataset[signalName].Count() - 1) { return null; } @@ -516,6 +424,92 @@ public double[] GetValues(string signalName) } } + internal List GetIndicesToIgnore() + { + if (indicesToIgnore == null) + return new List(); + // + return indicesToIgnore; + } + + + + + /// + /// Define a new signal, specifying only its inital value + /// + /// + /// the value of time zero + /// number of time stamps + /// what value to fill in for future undefined times, default:nan + public void InitNewSignal(string signalName, double initalValue, int N, double nonYetSimulatedValue = double.NaN) + { + Add(signalName, Vec.Concat(new double[] { initalValue }, + Vec.Fill(nonYetSimulatedValue, N - 1))); + } + + /// + /// Loads the CsvContent(which can be read from a file) into a TimeSeriesDataSet object + /// + /// + /// + /// + /// + public bool LoadFromCsv(CsvContent csvContent, char separator = ';', string dateTimeFormat = "yyyy-MM-dd HH:mm:ss") + { + bool isOK = CSV.LoadDataFromCsvContentAsTimeSeries(csvContent, separator, out DateTime[] dateTimes, + out Dictionary variableDict, dateTimeFormat); + if (isOK) + { + Fill(dateTimes, variableDict); + } + return isOK; + } + + + + + + /// + /// Returns a copy of the dataset that is downsampled by the given factor + /// + /// value greater than 1 indicating that every nth value of the orignal data will be transferred + /// + public TimeSeriesDataSet CreateDownsampledCopy(int downsampleFactor) + { + TimeSeriesDataSet ret = new TimeSeriesDataSet(); + + ret.timeStamps = Vec.Downsample(timeStamps.ToArray(), downsampleFactor).ToList(); + ret.N = ret.timeStamps.Count(); + ret.dataset_constants = dataset_constants; + foreach (var item in dataset) + { + ret.dataset[item.Key] = Vec.Downsample(item.Value, downsampleFactor); + } + return ret; + } + + /// + /// Creates internal timestamps from a given start time and timebase, must be called after filling the values + /// + /// the time between samples in the dataset, in total seconds + /// start time, can be null, which can be usedful for testing + public void CreateTimestamps(double timeBase_s, DateTime? t0 = null) + { + if (t0 == null) + { + t0 = new DateTime(2010, 1, 1);//intended for testing + } + + var times = new List(); + DateTime time = t0.Value; + for (int i = 0; i < N; i++) + { + times.Add(time); + time = time.AddSeconds(timeBase_s); + } + timeStamps = times; + } @@ -537,6 +531,26 @@ public double[] GetValues(string signalName) return isOk; } + /// + /// Removes a signal from the dataset + /// + /// + /// + public bool Remove(string signalName) + { + if (dataset.ContainsKey(signalName)) + { + dataset.Remove(signalName); + return true; + } + else + { + return false; + } + } + + + /// /// The given indices will be skipped in any subsequent simulation of the dataset /// @@ -636,12 +650,25 @@ public void SetTimeStamps(List times) return true; } - internal List GetIndicesToIgnore() + /// + /// Create a dictionary of all dataset values. Constants are padded out to be of N length. + /// + /// Returns the dataset as a dictionary + Dictionary ToDict() { - if (indicesToIgnore == null) - return new List(); - // - return indicesToIgnore; + Dictionary ret = new Dictionary(); + ret.Concat(dataset); + Vec vec = new Vec(); + foreach (var constant in dataset_constants) + { + if (N.HasValue) + { + ret.Add(constant.Key, Vec.Fill(constant.Value, N.Value)); + } + } + return ret; } + + } }