/// <summary> /// Correlates the master and slave timeseries /// </summary> /// <returns>A tuple containing the lag , correlation and any error messages</returns> public (long[], float[], string errorMessage) CorrelateSignals(Type pageType) { string errorMessage = null; Timeserie masterTimerserie = new Timeserie(); Timeserie slaveTimerserie = new Timeserie(); for (int i = _masterTimerserie.Count - 1; i > -1; i--) { if (_masterTimerserie[i] is TableColumn) { masterTimerserie.AddData(_masterTimerserie[i]); if (pageType.Name == "HeadToHead") { break; } } } for (int i = _slaveTimerserie.Count - 1; i > -1; i--) { if (_slaveTimerserie[i] is TableColumn) { slaveTimerserie.AddData(_slaveTimerserie[i]); if (pageType.Name == "HeadToHead") { break; } } } if ((masterTimerserie.Count) != (slaveTimerserie.Count)) { errorMessage = "There must be equally many signals in the slave and master timeseries."; return(null, null, errorMessage); } if (masterTimerserie.Count == 0) { errorMessage = "The master timeseries must at least consist of one signal"; return(null, null, errorMessage); } ResampleTimeserie(masterTimerserie, slaveTimerserie); masterTimerserie.RemoveBias(); slaveTimerserie.RemoveBias(); masterTimerserie.ToHilbertEnvelope(); slaveTimerserie.ToHilbertEnvelope(); AdjustLengthOfTimeserie(masterTimerserie, slaveTimerserie); var cor = CrossCorrelation(masterTimerserie.DataAsSignleArray, slaveTimerserie.DataAsSignleArray); int zeroIndex = (int)Math.Ceiling(((masterTimerserie.Length * masterTimerserie.Count * 2f) - 1) / 2); int fromIndex = zeroIndex - masterTimerserie.Length + slaveTimerserie.NrZeros; int nrInterestingSamples = (masterTimerserie.Length + slaveTimerserie.Length - slaveTimerserie.NrZeros - masterTimerserie.NrZeros) - 1; cor = cor.Skip(fromIndex).Take(nrInterestingSamples).ToArray(); var timelag = IndexToTime(masterTimerserie, slaveTimerserie, cor.Length); return(timelag, cor, errorMessage); }
/// <summary> /// If the master timeseries have a longer duration compared to the slave timeseries and we use multiple signals to /// sync the timeseries, we need to zero pad the slaves. /// </summary> /// <param name="masterTimerseries"></param> /// <param name="slaveTimerseries"></param> private void AdjustLengthOfTimeserie(Timeserie masterTimerserie, Timeserie slaveTimerserie) { if (masterTimerserie.Length > slaveTimerserie.Length) { int nrZeros = masterTimerserie.Length - slaveTimerserie.Length; slaveTimerserie.ZeroPad(nrZeros); } if (slaveTimerserie.Length > masterTimerserie.Length) { int nrZeros = slaveTimerserie.Length - masterTimerserie.Length; masterTimerserie.ZeroPad(nrZeros); } }
/// <summary> /// Resamples the timeseries. The timeserie of the lowest sampling frequency is resampled to /// the same sampling frequency as the other timeserie /// </summary> /// <param name="masterTimerseries"></param> /// <param name="slaveTimerseries"></param> private void ResampleTimeserie(Timeserie masterTimerserie, Timeserie slaveTimerserie) { if (masterTimerserie.SamplingFreq == slaveTimerserie.SamplingFreq) { return; } else if (masterTimerserie.SamplingFreq > slaveTimerserie.SamplingFreq) { slaveTimerserie.Resample(masterTimerserie.SamplingFreq); } else { masterTimerserie.Resample(slaveTimerserie.SamplingFreq); } }
/// <summary> /// maps the index nr to a time lag /// </summary> /// <param name="master"></param> /// <param name="slave"></param> /// <param name="nrSamples"></param> /// <returns> A array mapping index to a time lag </returns> private long[] IndexToTime(Timeserie master, Timeserie slave, int nrSamples) { long durationSlave = slave.Time.Data[slave.Length - 1 - slave.NrZeros] - slave.Time.Data[0]; long durationMaster = master.Time.Data[master.Length - 1 - master.NrZeros] - master.Time.Data[0]; long shiftedFromZero = slave.Time.Data[0] - master.Time.Data[0]; long startTime = shiftedFromZero + durationSlave; long endTime = startTime - durationMaster - durationSlave; long duration = Math.Abs(startTime - endTime); float sampleTime = duration / (nrSamples - 1); long[] timeShift = new long[nrSamples]; for (int i = 0; i < nrSamples; i++) { timeShift[i] = (long)-(startTime - (i * sampleTime)); } return(timeShift); }