public void TestDistanceOneDimension() { double[] p1 = new double[1] { 2 }; double[] p2 = new double[1] { 4 }; double expectedDistance = 2; var dtw = new Dtw(); double distance = dtw.Distance(p1, p2); Assert.AreEqual(expectedDistance, distance); }
/// <summary> /// Aggregates the input features and executes the <see cref="Dtw"/> algorithm. /// </summary> /// <param name="signature1"></param> /// <param name="signature2"></param> /// <returns>Cost between <paramref name="signature1"/> and <paramref name="signature2"/></returns> public double Pair(Signature signature1, Signature signature2) { Progress = 0; Dtw dtwAlg = new Dtw(distanceMethod); double[][] testSig1 = signature1.GetAggregateFeature(InputFeatures).ToArray(); double[][] testSig2 = signature2.GetAggregateFeature(InputFeatures).ToArray(); Progress = 50;//.. double cost = dtwAlg.Compute(testSig1, testSig2); Log(LogLevel.Info, $"Paired SigID {signature1.ID} with SigID {signature2.ID}"); Log(LogLevel.Debug, $"Pairing result of SigID {signature1.ID} with SigID {signature2.ID}: {cost}"); Progress = 100; return(cost); }
//Azokat a dolgokat amiket a verifier előfeldolgoz itt nincsenek csak részben //a loadsignature-ben van valami minimáis előfeldolgozás private void GoDTWButton_Click(object sender, RoutedEventArgs e) { if (Signers == null) { LoadSignatures(); } Signature signature1 = Signers[(int)SignerComboBox1.SelectedValue - 1].Signatures[(int)SignatureComboBox1.SelectedIndex]; Signature signature2 = Signers[(int)SignerComboBox2.SelectedValue - 1].Signatures[(int)SignatureComboBox2.SelectedIndex]; //DTWScoreTextBlock.Text = Analyzer.GetCost(sig1, sig2, true).Cost.ToString(); Dtw dtw = new Dtw(signature1, signature2, FeatureFilter); OwnDTWScoreTextBlock.Text = dtw.CalculateDtwScore().ToString(); WarpingPathScoreTextBlock.Text = dtw.CalculateWarpingPathScore().ToString(); FusionScoreTextBlock.Text = FusedScore.CalculateFusionOfDtwAndWPathScore(signature1, new Signature[] { signature2 }, FeatureFilter).ToString(); }
public override double GetDistance(AudioFeature f, AudioFeature.DistanceType t) { if (!(f is Scms)) { new Exception("Can only handle AudioFeatures of type Scms, not of: " + f); return(-1); } Scms other = (Scms)f; DistanceMeasure distanceMeasure = DistanceMeasure.Euclidean; switch (t) { case AudioFeature.DistanceType.Dtw_Euclidean: distanceMeasure = DistanceMeasure.Euclidean; break; case AudioFeature.DistanceType.Dtw_SquaredEuclidean: distanceMeasure = DistanceMeasure.SquaredEuclidean; break; case AudioFeature.DistanceType.Dtw_Manhattan: distanceMeasure = DistanceMeasure.Manhattan; break; case AudioFeature.DistanceType.Dtw_Maximum: distanceMeasure = DistanceMeasure.Maximum; break; case AudioFeature.DistanceType.UCR_Dtw: return(UCRCSharp.UCR.DTW(this.GetArray(), other.GetArray())); case AudioFeature.DistanceType.CosineSimilarity: return(CosineSimilarity(this, other)); case AudioFeature.DistanceType.BitStringHamming: return(Imghash.ImagePHash.HammingDistance(this.BitString, other.BitString)); case AudioFeature.DistanceType.KullbackLeiblerDivergence: default: return(Distance(this, other, new ScmsConfiguration(Analyzer.MFCC_COEFFICIENTS))); } Dtw dtw = new Dtw(this.GetArray(), other.GetArray(), distanceMeasure, true, true, null, null, null); return(dtw.GetCost()); }
private double CalculateCost(SignModel sm1, SignModel sm2) { var seriesVariables = new List <SeriesVariable>(); seriesVariables.Add( new SeriesVariable( sm1.H_horizantal.ToArray(), sm2.H_horizantal.ToArray())); seriesVariables.Add( new SeriesVariable( sm1.H_vertical.ToArray(), sm2.H_vertical.ToArray())); var seriesVariablesArray = seriesVariables.ToArray(); var dtw = new Dtw(seriesVariablesArray); m_dtw = dtw; return(dtw.GetCost()); }
public void TestComputeTwoDimension() { double[][] signature1 = new double[3][]; //Two dimension points. another test required for one dimension points. signature1[0] = new double[] { 1, 4 }; signature1[1] = new double[] { 2, 5 }; signature1[2] = new double[] { 3, 8 }; double[][] signature2 = new double[3][]; signature2[0] = new double[] { 1, 5 }; signature2[1] = new double[] { 2, 6 }; signature2[2] = new double[] { 3, 8 }; var dtw = new Dtw(); double cost = dtw.Compute(signature1, signature2); double expectedCost = 0; Assert.AreEqual(expectedCost, cost); }
public void TestComputeOneDimension() { double[][] signature1 = new double[3][]; //One dimension points. signature1[0] = new double[] { 4 }; signature1[1] = new double[] { 5 }; signature1[2] = new double[] { 8 }; double[][] signature2 = new double[3][]; signature2[0] = new double[] { 4 }; signature2[1] = new double[] { 5 }; signature2[2] = new double[] { 8 }; var dtw = new Dtw(); double cost = dtw.Compute(signature1, signature2); double expectedCost = 0; Assert.AreEqual(expectedCost, cost); }
public void TestSameInput() { double[][] signature1 = new double[3][]; //Two dimension points. another test required for one dimension points. signature1[0] = new double[] { 1, 4 }; signature1[1] = new double[] { 2, 5 }; signature1[2] = new double[] { 3, 8 }; double[][] signature2 = new double[3][]; signature2[0] = new double[] { 1, 4 }; signature2[1] = new double[] { 2, 5 }; signature2[2] = new double[] { 3, 8 }; var dtw = new Dtw(); double cost = dtw.Compute(signature1, signature2); double expectedCost = 0; double expectedDistance = 0; double distance = dtw.Distance(signature1[1], signature2[1]); Assert.AreEqual(expectedDistance, distance); Assert.AreEqual(expectedCost, cost); }
/// <summary>Get Distance</summary> /// <seealso cref="">comirva.audio.feature.AudioFeature#GetDistance(comirva.audio.feature.AudioFeature)</seealso> public override double GetDistance(AudioFeature f, AudioFeature.DistanceType t) { if (!(f is MandelEllis)) { new Exception("Can only handle AudioFeatures of type Mandel Ellis, not of: " + f); return(-1); } MandelEllis other = (MandelEllis)f; DistanceMeasure distanceMeasure = DistanceMeasure.Euclidean; switch (t) { case AudioFeature.DistanceType.Dtw_Euclidean: distanceMeasure = DistanceMeasure.Euclidean; break; case AudioFeature.DistanceType.Dtw_SquaredEuclidean: distanceMeasure = DistanceMeasure.SquaredEuclidean; break; case AudioFeature.DistanceType.Dtw_Manhattan: distanceMeasure = DistanceMeasure.Manhattan; break; case AudioFeature.DistanceType.Dtw_Maximum: distanceMeasure = DistanceMeasure.Maximum; break; case AudioFeature.DistanceType.KullbackLeiblerDivergence: default: return(KullbackLeibler(this.gmmMe, other.gmmMe) + KullbackLeibler(other.gmmMe, this.gmmMe)); } Dtw dtw = new Dtw(this.GetArray(), other.GetArray(), distanceMeasure, true, true, null, null, null); return(dtw.GetCost()); }
public void TestComputeDifferentLenghtInput() //SameLengthInput already tested in the previous tests. { double[][] signature1 = new double[3][]; //Two dimension points. another test required for one dimension points. signature1[0] = new double[] { 1, 4 }; signature1[1] = new double[] { 2, 5 }; signature1[2] = new double[] { 3, 8 }; double[][] signature2 = new double[4][]; signature2[0] = new double[] { 1, 6 }; signature2[1] = new double[] { 2, 7 }; signature2[2] = new double[] { 3, 10 }; signature2[3] = new double[] { 4, 12 }; var dtw = new Dtw(); double cost = dtw.Compute(signature1, signature2); double expectedCost = 0.25; double expectedDistance = 2; double distance = dtw.Distance(signature1[1], signature2[1]); Assert.AreEqual(expectedDistance, distance); Assert.AreEqual(expectedCost, cost); }
/// <summary> /// Generate average of supplied series. /// </summary> public static double[] Average(List <double[]> series, int maxIterations = 100) { if (series == null || series.Count == 0) { throw new Exception("series null or empty"); } if (series.Count == 1) { return(series[0]); } if (series.Select(x => x.Length).Distinct().Count() != 1) { throw new Exception("Series must be of equal length"); } int length = series[0].Length; //initializing the average to a simple mean of every point, without DTW //double[] average = new double[length]; //for (int i = 0; i < series[0].Length; i++) //{ // average[i] = series.Average(x => x[i]); //} //initialize to a random series from the input //var r = new Random(); //double[] average = series[r.Next(0, series.Count - 1)]; //initialize to series closest to median min/max after detrending List <double[]> tempSeries = series.Select(Detrend).ToList(); List <int> maxIndexes = tempSeries.Select(x => x.IndexOfMax()).ToList(); List <int> minIndexes = tempSeries.Select(x => x.IndexOfMin()).ToList(); double medianMaxIndex = maxIndexes.Median(); double medianMinIndex = minIndexes.Median(); var distances = maxIndexes.Select((x, i) => Math.Pow(x - medianMaxIndex, 2) + Math.Pow(minIndexes[i] - medianMinIndex, 2)).ToList(); int selectedSeries = distances.IndexOfMin(); double[] average = series[selectedSeries]; //this list will hold the values of each aligned point, //later used to construct the aligned average List <double>[] points = new List <double> [length]; for (int i = 0; i < length; i++) { points[i] = new List <double>(); } double prevTotalDist = -1; double totalDist = -2; //sometimes the process gets "stuck" in a loop between two different states //so we have to set a hard limit to end the loop int count = 0; //get the path between each series and the average while (totalDist != prevTotalDist && count < maxIterations) { prevTotalDist = totalDist; //clear the points from the last calculation foreach (var list in points) { list.Clear(); } //here we do the alignment for every series foreach (double[] ts in series) { var dtw = new Dtw(new[] { new SeriesVariable(ts, average) }); Tuple <int, int>[] path = dtw.GetPath(); //use the path to distribute the points according to the warping Array.ForEach(path, x => points[x.Item2].Add(ts[x.Item1])); } //Then simply construct the new average series by taking the mean of every List in points. average = points.Select(x => x.Average()).ToArray(); //calculate Euclidean distance to stop the loop if no further improvement can be made double[] average1 = average; totalDist = series.Sum(x => x.Select((y, i) => Math.Pow(y - average1[i], 2)).Sum()); //we get convergence even though there's still work to be done count++; } return(average); }
static void DTWCsv(string[] files) { for (int fileId = 0; fileId < files.Length; fileId++) { if (File.Exists(files[fileId].Split('\\').Last() + "_pearsonDataCsv.txt")) { File.Copy(files[fileId].Split('\\').Last() + "_pearsonDataCsv.txt", files[fileId] + "_pearsonDataCsv.txt", true); //Console.WriteLine("Copied " + files[fileId].Split('\\').Last() + "_pearsonDataCsv.txt" + " to " + files[fileId] + "_pearsonDataCsv.txt"); if (File.Exists(files[fileId].Split('\\').Last() + "dtwCostInfo.txt")) { File.Copy(files[fileId].Split('\\').Last() + "_pearsonDataCsv.txt", files[fileId] + "dtwCostInfo.txt", true); } Console.WriteLine(files[fileId].Split('\\').Last() + " is already done, skipping."); continue; } var freed = GC.GetTotalMemory(false); GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, true); Console.WriteLine("Garbage Collection completed - memory:" + ((double)GC.GetTotalMemory(false) / 1024 / 1024 / 1024).ToString("0.0") + " GB (freed " + (freed / 1024 / 1024) + " MB)"); Console.WriteLine("Performing DTW on csv data " + fileId + " of " + files.Length + ".."); var watch = System.Diagnostics.Stopwatch.StartNew(); string[] data = File.ReadAllLines(files[fileId]); Console.WriteLine("Data points: " + data.Length); List <double> testDataPoints = new List <double>(); List <double> recallDataPoints = new List <double>(); foreach (var line in data) { var split = line.Replace(',', '.').Split(';'); double test = double.Parse(split[0], System.Globalization.CultureInfo.InvariantCulture); double recall = double.Parse(split[1], System.Globalization.CultureInfo.InvariantCulture); testDataPoints.Add(test); recallDataPoints.Add(recall); } // Dtw dtw = new Dtw(testDataPoints.ToArray(), recallDataPoints.ToArray(), DistanceMeasure.Euclidean, true, true, null, null, 700); Dtw dtw = new Dtw(testDataPoints.ToArray(), recallDataPoints.ToArray(), DistanceMeasure.Euclidean, true, true, slopeStepSizeDiagonal: 2, slopeStepSizeAside: 1); var path = dtw.GetPath(); var cost = dtw.GetCost(); //var distanceMatrix = dtw.GetDistanceMatrix(); //var costMatrix = dtw.GetCostMatrix(); File.WriteAllText(files[fileId].Split('\\').Last() + "dtwCostInfo.txt", "cost=" + cost + "\nbefore_length=" + data.Length + "\nbefore_cost=" + (cost / data.Length) + "\nafter_length=" + path.Length + "\nafter_cost=" + (cost / path.Length) ); //PngExporter pngify = new PngExporter(); //pngify.Width = 36000; //pngify.Height = 4000; //var model = new PlotModel() { Title = "Red = test, blue = recall" }; //var aSeries = new OxyPlot.Series.LineSeries() { Color = OxyColors.Blue, MarkerSize = 10 }; //var bSeries = new OxyPlot.Series.LineSeries() { Color = OxyColors.Red, MarkerSize = 10 }; //for (int i = 0; i < testDataPoints.Count; i++) //{ // aSeries.Points.Add(new DataPoint(i, testDataPoints[i])); //} //for (int i = 0; i < recallDataPoints.Count; i++) //{ // bSeries.Points.Add(new DataPoint(i, recallDataPoints[i])); //} //List<string> pearsonData = new List<string>(); //foreach (var pairing in path) //{ // var lineSeries = new OxyPlot.Series.LineSeries() { Color = OxyColors.Gray, MarkerSize = 0.05 }; // lineSeries.Points.Add(new DataPoint(pairing.Item1, testDataPoints[pairing.Item1])); // lineSeries.Points.Add(new DataPoint(pairing.Item2, recallDataPoints[pairing.Item2])); // model.Series.Add(lineSeries); // pearsonData.Add(testDataPoints[pairing.Item1].ToString().Replace(',', '.') + ";" + recallDataPoints[pairing.Item2].ToString().Replace(',', '.')); //} //var pears = MathNet.Numerics.Statistics.Correlation.Pearson(path.Select(x => testDataPoints[x.Item1]).ToList(), path.Select(x => recallDataPoints[x.Item2]).ToList()); //Console.WriteLine("Pearson for " + files[fileId] + ":"); //Console.WriteLine(pears.ToString()); //File.WriteAllLines(files[fileId].Split('\\').Last() + "_pearsonDataCsv.txt", pearsonData); //model.Series.Add(aSeries); //model.Series.Add(bSeries); //pngify.ExportToFile(model, files[fileId].Split('\\').Last() + "_csv.png"); watch.Stop(); Console.WriteLine("Done in " + watch.Elapsed); Console.WriteLine(""); } }
void waveSource_DataAvailable(object sender, WaveInEventArgs e) { //int max = 0; byte[] buffer = e.Buffer; int bytesRecorded = e.BytesRecorded; //WriteToFile(buffer, bytesRecorded); for (int index = 0; index < e.BytesRecorded; index += 2) { short sample = (short)((buffer[index + 1] << 8) | buffer[index + 0]); float sample32 = (sample / 32768f); //int finalSample =(sample32 * 255); //if (max < finalSample) max = finalSample; //sampleAggregator.Add(sample32); queue.Enqueue(sample32); //queue.print(); } long curTime = DateTime.Now.Ticks / TimeSpan.TicksPerSecond; if (lastDetect + 2 > curTime) { Console.WriteLine("LAST GEST" + lastDetect + 5 + " " + curTime); return; } //check if sample matches int gest = 0; double lastcost = 1000; if (isSaved1 /*&& (loop++%3==0)*/) { long curTimeMs1 = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond; //Time Calc var cost = new Dtw(saved1, queue.ToArray2()).GetCost(); long curTimeMs2 = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond; //Time Calc if (cost < lastcost && cost < thresh1) { gest = 1; lastcost = cost; Console.WriteLine("G1: " + cost); } //Debug.WriteLineIf( cost<thresh1, "1:"+cost); Console.WriteLine("Time DTW Took for Gesture 1 in ms: " + (curTimeMs2 - curTimeMs1)); //Console.WriteLine("MS 2: " + curTimeMs2); } if (isSaved2 /*&& (loop++%3==0)*/) { var cost = new Dtw(saved2, queue.ToArray2()).GetCost(); if (cost < lastcost && cost < thresh2) { gest = 2; lastcost = cost; Console.WriteLine("G2: " + cost); } //Debug.WriteLineIf(cost < thresh2, "2:"+cost); } if (isSaved3 /*&& (loop++%3==0)*/) { var cost = new Dtw(saved3, queue.ToArray2()).GetCost(); if (cost < lastcost && cost < thresh3) { gest = 3; lastcost = cost; Console.WriteLine("G3: " + cost); } //Debug.WriteLineIf(cost < thresh3, "3:"+cost); } foreach (double[] s in falseSaved) { var cost = new Dtw(s, queue.ToArray2()).GetCost(); if (cost < lastcost && cost < thresh0) { gest = 0; lastcost = cost; } } thresh1 = Convert.ToDouble("0" + txtThres1.Text); thresh2 = Convert.ToDouble("0" + txtThres2.Text); thresh3 = Convert.ToDouble("0" + txtThres3.Text); if (gest > 0) { lastDetect = DateTime.Now.Ticks / TimeSpan.TicksPerSecond; lastGesture = gest; Debug.WriteLine("DETECTED " + gest + " " + lastcost); } if (gest == 1) { lbl1.Visible = true; lbl2.Visible = false; lbl3.Visible = false; SerialForm.SendLeft(); ArrowForm.ShowLeft(); } else if (gest == 2) { lbl1.Visible = false; lbl2.Visible = true; lbl3.Visible = false; SerialForm.SendCenter(); ArrowForm.ShowCenter(); } else if (gest == 3) { lbl1.Visible = false; lbl2.Visible = false; lbl3.Visible = true; SerialForm.SendRight(); ArrowForm.ShowRight(); } else { lbl1.Visible = false; lbl2.Visible = false; lbl3.Visible = false; ArrowForm.ShowNone(); } //else Debug.WriteLine("NONE"); //Debug.WriteLine(max.ToString()); }
public void SetData(Dtw dtw) { dtwGraph.Dtw = dtw; }
private void Recalculate() { if (!CanRecalculate) return; var seriesVariables = new List<SeriesVariable>(); foreach (var selectedVariable in SelectedVariables) { seriesVariables.Add( new SeriesVariable( DataSeries.GetValues(_selectedEntities[0], selectedVariable.Name).ToArray(), DataSeries.GetValues(_selectedEntities[1], selectedVariable.Name).ToArray(), selectedVariable.Name, selectedVariable.Preprocessor, selectedVariable.Weight)); } var seriesVariablesArray = seriesVariables.ToArray(); var dtw = new Dtw( seriesVariablesArray, SelectedDistanceMeasure.Value, UseBoundaryConstraintStart, UseBoundaryConstraintEnd, UseSlopeConstraint ? SlopeConstraintDiagonal : (int?)null, UseSlopeConstraint ? SlopeConstraintAside : (int?)null, UseSakoeChibaMaxShift ? SakoeChibaMaxShift : (int?)null); if (MeasurePerformance) { var swDtwPerformance = new Stopwatch(); swDtwPerformance.Start(); for (int i = 0; i < 250; i++) { var tempDtw = new Dtw( seriesVariablesArray, SelectedDistanceMeasure.Value, UseBoundaryConstraintStart, UseBoundaryConstraintEnd, UseSlopeConstraint ? SlopeConstraintDiagonal : (int?)null, UseSlopeConstraint ? SlopeConstraintAside : (int?)null, UseSakoeChibaMaxShift ? SakoeChibaMaxShift : (int?)null); var tempDtwPath = tempDtw.GetCost(); } swDtwPerformance.Stop(); OperationDuration = swDtwPerformance.Elapsed; } Dtw = dtw; //Dtw = new Dtw( // new[] { 4.0, 4.0, 4.5, 4.5, 5.0, 5.0, 5.0, 4.5, 4.5, 4.0, 4.0, 3.5 }, // new[] { 1.0, 1.5, 2.0, 2.5, 3.5, 4.0, 3.0, 2.5, 2.0, 2.0, 2.0, 1.5 }, // SelectedDistanceMeasure.Value, // UseBoundaryConstraintStart, // UseBoundaryConstraintEnd, // UseSlopeConstraint ? SlopeConstraintDiagonal : (int?)null, // UseSlopeConstraint ? SlopeConstraintAside : (int?)null, // UseSakoeChibaMaxShift ? SakoeChibaMaxShift : (int?)null); }
private void Recalculate() { if (!CanRecalculate) { return; } var seriesVariables = new List <SeriesVariable>(); foreach (var selectedVariable in SelectedVariables) { seriesVariables.Add( new SeriesVariable( DataSeries.GetValues(_selectedEntities[0], selectedVariable.Name).ToArray(), DataSeries.GetValues(_selectedEntities[1], selectedVariable.Name).ToArray(), selectedVariable.Name, selectedVariable.Preprocessor, selectedVariable.Weight)); } var seriesVariablesArray = seriesVariables.ToArray(); var dtw = new Dtw( seriesVariablesArray, SelectedDistanceMeasure.Value, UseBoundaryConstraintStart, UseBoundaryConstraintEnd, UseSlopeConstraint ? SlopeConstraintDiagonal : (int?)null, UseSlopeConstraint ? SlopeConstraintAside : (int?)null, UseSakoeChibaMaxShift ? SakoeChibaMaxShift : (int?)null); if (MeasurePerformance) { var swDtwPerformance = new Stopwatch(); swDtwPerformance.Start(); for (int i = 0; i < 250; i++) { var tempDtw = new Dtw( seriesVariablesArray, SelectedDistanceMeasure.Value, UseBoundaryConstraintStart, UseBoundaryConstraintEnd, UseSlopeConstraint ? SlopeConstraintDiagonal : (int?)null, UseSlopeConstraint ? SlopeConstraintAside : (int?)null, UseSakoeChibaMaxShift ? SakoeChibaMaxShift : (int?)null); var tempDtwPath = tempDtw.GetCost(); } swDtwPerformance.Stop(); OperationDuration = swDtwPerformance.Elapsed; } Dtw = dtw; //Dtw = new Dtw( // new[] { 4.0, 4.0, 4.5, 4.5, 5.0, 5.0, 5.0, 4.5, 4.5, 4.0, 4.0, 3.5 }, // new[] { 1.0, 1.5, 2.0, 2.5, 3.5, 4.0, 3.0, 2.5, 2.0, 2.0, 2.0, 1.5 }, // SelectedDistanceMeasure.Value, // UseBoundaryConstraintStart, // UseBoundaryConstraintEnd, // UseSlopeConstraint ? SlopeConstraintDiagonal : (int?)null, // UseSlopeConstraint ? SlopeConstraintAside : (int?)null, // UseSakoeChibaMaxShift ? SakoeChibaMaxShift : (int?)null); }
public void OnDataChanged() { if (DrawCost && DrawDistance) { throw new Exception("Only one of the values can be drawn at once, 'cost' or 'distance'."); } double[][] matrixValues = null; if (DrawCost) { matrixValues = Dtw.GetCostMatrix(); } if (DrawDistance) { matrixValues = Dtw.GetDistanceMatrix(); } var dtwPath = Dtw.GetPath(); var xLength = Dtw.XLength; var yLength = Dtw.YLength; var cost = Dtw.GetCost(); var costNormalized = Dtw.GetCost() / Math.Sqrt(xLength * xLength + yLength * yLength); var plotModel = new PlotModel(String.Format("Dtw norm by length: {0:0.00}, total: {1:0.00}", costNormalized, cost)) { LegendTextColor = DrawCost || DrawDistance ? OxyColors.White : OxyColors.Black, }; if (matrixValues != null) { var maxMatrixValue = 0.0; for (int i = 0; i < xLength; i++) { for (int j = 0; j < yLength; j++) { maxMatrixValue = Math.Max(maxMatrixValue, Double.IsPositiveInfinity(matrixValues[i][j]) ? 0 : matrixValues[i][j]); } } for (int i = 0; i < xLength; i++) { for (int j = 0; j < yLength; j++) { var value = matrixValues[i][j]; var isValuePositiveInfinity = Double.IsPositiveInfinity(value); var intensityBytes = isValuePositiveInfinity ? new byte[] { 0, 0, 0 } : GetFauxColourRgbIntensity(value, 0, maxMatrixValue); //var intensityByte = (byte)(255 - Math.Floor(255 * intensity)); plotModel.Annotations.Add(new PolygonAnnotation { Points = new[] { new DataPoint(i - 0.5, j - 0.5), new DataPoint(i + 0.5, j - 0.5), new DataPoint(i + 0.5, j + 0.5), new DataPoint(i - 0.5, j + 0.5), }, StrokeThickness = 0, Selectable = false, Layer = AnnotationLayer.BelowAxes, Fill = OxyColor.FromArgb(255, intensityBytes[0], intensityBytes[1], intensityBytes[2]), }); } } for (int i = 0; i < 30; i++) { var intensityBytes = GetFauxColourRgbIntensity(i, 0, 29); plotModel.Annotations.Add(new RectangleAnnotation { MinimumX = -39, MaximumX = -25, MinimumY = -i - 6, MaximumY = -i - 5, Selectable = false, Fill = OxyColor.FromArgb(255, intensityBytes[0], intensityBytes[1], intensityBytes[2]) }); } plotModel.Annotations.Add(new TextAnnotation { Position = new DataPoint(-24, -5), HorizontalAlignment = HorizontalTextAlign.Left, VerticalAlignment = VerticalTextAlign.Middle, StrokeThickness = 0, Text = "0" }); plotModel.Annotations.Add(new TextAnnotation { Position = new DataPoint(-24, -34), HorizontalAlignment = HorizontalTextAlign.Left, VerticalAlignment = VerticalTextAlign.Middle, StrokeThickness = 0, Text = String.Format("{0:0.00}", maxMatrixValue), }); } var matrixPathSeries = new LineSeries("Path") { StrokeThickness = 1, Color = OxyColors.Red, }; for (int i = 0; i < dtwPath.Length; i++) { matrixPathSeries.Points.Add(new DataPoint(dtwPath[i].Item1, dtwPath[i].Item2)); } plotModel.Series.Add(matrixPathSeries); var seriesMatrixScale = (xLength + yLength) * 0.05; for (int variableIndex = 0; variableIndex < Dtw.SeriesVariables.Length; variableIndex++) { var variableA = Dtw.SeriesVariables[variableIndex]; var variableASeries = variableA.OriginalXSeries; var variableB = Dtw.SeriesVariables[variableIndex]; var variableBSeries = variableB.OriginalYSeries; var minSeriesA = variableASeries.Min(); var maxSeriesA = variableASeries.Max(); var normalizedSeriesA = variableASeries.Select(x => (x - minSeriesA) / (maxSeriesA - minSeriesA)).ToList(); var matrixSeriesA = new LineSeries(variableA.VariableName); for (int i = 0; i < normalizedSeriesA.Count; i++) { matrixSeriesA.Points.Add(new DataPoint(i, (-1 + normalizedSeriesA[i]) * seriesMatrixScale - 1 - seriesMatrixScale * (variableIndex + 1))); } plotModel.Series.Add(matrixSeriesA); var minSeriesB = variableBSeries.Min(); var maxSeriesB = variableBSeries.Max(); var normalizedSeriesB = variableBSeries.Select(x => (x - minSeriesB) / (maxSeriesB - minSeriesB)).ToList(); var matrixSeriesB = new LineSeries(variableB.VariableName); for (int i = 0; i < normalizedSeriesB.Count; i++) { matrixSeriesB.Points.Add(new DataPoint(-normalizedSeriesB[i] * seriesMatrixScale - 1 - seriesMatrixScale * (variableIndex + 1), i)); } plotModel.Series.Add(matrixSeriesB); } plotModel.Axes.Add(new LinearAxis(AxisPosition.Bottom, " Series A") { Maximum = Math.Max(xLength, yLength), PositionAtZeroCrossing = true }); plotModel.Axes.Add(new LinearAxis(AxisPosition.Left, " Series B") { Maximum = Math.Max(xLength, yLength), PositionAtZeroCrossing = true }); MatrixPlot.Model = plotModel; }