private void AnalyzeFftData(BatCall mergedCall, uint[] fftData, int count) { byte[] newFftData = new byte[32]; int fftIndex = 8; int max = fftData.Length - 7; int mergedIndex = 0; byte maxValue = 0; int maxFftIndex = 0; while (fftIndex < max) { uint val = fftData[fftIndex++]; val += fftData[fftIndex++]; val += fftData[fftIndex++]; val += fftData[fftIndex++]; val += fftData[fftIndex++]; val += fftData[fftIndex++]; val += fftData[fftIndex++]; val += fftData[fftIndex++]; byte average = (byte)(val / (8 * count)); if (average > maxValue) { maxFftIndex = mergedIndex; maxValue = average; } newFftData[mergedIndex++] = average; } mergedCall.FftData = newFftData; mergedCall.MaxFrequencyBin = maxFftIndex; }
public BatCallViewModel(BatNodeLog log, BatCall batCall, int index) { Index = index; _log = log; _batCall = batCall; _fftAnalyzer = new FftAnalyzer(2, 5); }
public BatCall Merge(List <RawCall> rawCalls) { BatCall mergedCall = new BatCall(); RawCall firstCall = rawCalls[0]; mergedCall.StartTimeMs = firstCall.StartTimeMs; mergedCall.ClippedSamples = 0; mergedCall.MissedSamples = 0; List <byte> powerData = new List <byte>(); ulong lastEndTime = firstCall.EndTimeMs; uint[] tempFftData = new uint[256]; foreach (RawCall rawCall in rawCalls) { if (lastEndTime < rawCall.StartTimeMs) { int delta = (int)Math.Round((rawCall.StartTimeMs - lastEndTime) / 0.251); powerData.AddRange(Enumerable.Repeat((byte)0, delta)); } powerData.AddRange(rawCall.PowerData); lastEndTime = rawCall.EndTimeMs; // We currently have a sample rate of 231kHz and a Buffer of 1024. // That means we get data from 0Hz to 115.5kHz within 256 buckets. // We'll combine 8 buckets together to get a range of about 3.6kHz per Bucket. // The fist and the last Bucket are omitted ushort[] fftData = rawCall.FftData; if (fftData.Length != 256) { return(mergedCall); } for (int i = 0; i < rawCall.FftData.Length; i++) { tempFftData[i] += rawCall.FftData[i]; } mergedCall.Duration += rawCall.Duration; mergedCall.ClippedSamples += rawCall.ClippedSamples; mergedCall.MissedSamples += rawCall.MissedSamples; } AnalyzeFftData(mergedCall, tempFftData, rawCalls.Count); mergedCall.PowerData = powerData.ToArray(); mergedCall.AveragePower = (byte)Math.Round(mergedCall.PowerData.Where(p => p > 20).DefaultIfEmpty().Average(p => p)); mergedCall.MergeCount = rawCalls.Count; return(mergedCall); }
public CallModel(BatCall call, BatNodeData data) { _data = data; Call = call; StringBuilder warnings = new StringBuilder(); if (call.MissedSamples > 0) { warnings.AppendFormat(CultureInfo.CurrentCulture, "Clipped Samples: {0}\n", call.MissedSamples); } Warnings = warnings.ToString(); DateTime startTime = _data.LogStart.AddMilliseconds(call.StartTimeMs); Date = $"{startTime:d}"; Time = $"{startTime:HH:mm:ss.ffff}"; MainFrequency = $"{call.MainFrequency} kHz"; }
public void Analyze(BatProject project, BatNode node, RawNodeData rawNodeData) { BatNodeData nodeData = node.NodeData; node.IsDirty = true; node.NodeId = rawNodeData.NodeId; node.LogStart = rawNodeData.LogStart; nodeData.Calls.Clear(); List <RawCall> rawCallsToMerge = new List <RawCall>(); BatCall currentCallData = new BatCall(); nodeData.Calls.Add(currentCallData); uint endCallTime = 0; foreach (RawCall call in rawNodeData.Calls) { if (endCallTime + 50 >= call.StartTimeMs || rawCallsToMerge.Count == 0) { rawCallsToMerge.Add(call); } else { nodeData.Calls.Add(Merge(rawCallsToMerge)); rawCallsToMerge.Clear(); } endCallTime = call.EndTimeMs; } if (rawCallsToMerge.Count > 0) { nodeData.Calls.Add(Merge(rawCallsToMerge)); } }
private void InitPlots(CallModel callModel) { BatCall call = callModel.Call; PlotModel pmPower = new PlotModel(); LineSeries pwrLineSeries = new LineSeries(); pwrLineSeries.LineJoin = LineJoin.Round; pmPower.Series.Add(pwrLineSeries); pmPower.Axes.Add(new LinearAxis { Maximum = 260, Minimum = 0, Position = AxisPosition.Left, Title = "Intensität" }); pmPower.Axes.Add(new LinearAxis { Position = AxisPosition.Bottom, Title = "Dauer [ms]" }); if (call.PowerData != null) { pwrLineSeries.Points.AddRange(call.PowerData.Select((b, i) => new DataPoint(i * 0.251, b))); } //if (call.OriginalCalls.Count > 1) //{ // int leftSum = call.OriginalCalls[0].PowerData.Length; // for (int i = 0; i < call.OriginalCalls.Count-1; i++) // { // int width = (int)Math.Round((call.OriginalCalls[i + 1].StartTimeMs - call.OriginalCalls[i].EndTimeMs) / 0.251); // double left = leftSum* 0.251; // double right = left + (width* 0.251); // RectangleAnnotation annotation = new RectangleAnnotation { Fill = OxyColors.LightGray, Layer = AnnotationLayer.BelowAxes, MinimumX = left, MaximumX = right, MinimumY = 0, MaximumY = 260 }; // //LineAnnotation lineAnnotation = new LineAnnotation { Color = OxyColors.Red, StrokeThickness = 2, LineStyle = LineStyle.Dash, Type = LineAnnotationType.Vertical, X = linePos }; // pmPower.Annotations.Add(annotation); // leftSum = leftSum + width + call.OriginalCalls[i].PowerData.Length; // } //} OnlineFilter filter = OnlineFilter.CreateBandstop(ImpulseResponse.Infinite, 20, 20, 150); LineSeries pwrLineSeriesAvg = new LineSeries(); pwrLineSeriesAvg.LineJoin = LineJoin.Round; pwrLineSeriesAvg.Color = OxyColors.Blue; pmPower.Series.Add(pwrLineSeriesAvg); //double[] input = call.PowerData.Select(d => (double)d).ToArray(); //double[] data = filter.ProcessSamples(input); //pwrLineSeriesAvg.Points.AddRange(data.Select((d, i) => new DataPoint(i * 0.251, d))); int[] window = new int[] { 2, 4, 8, 4, 2 }; int divisor = window.Sum(); byte[] input = call.PowerData; for (int i = 0; i < input.Length; i++) { double sum = 0; for (int j = 0; j < 5; j++) { int x = i + (j - 2); double q; if (x < 0) { q = input[0]; } else if (x >= input.Length) { q = input[input.Length - 1]; } else { q = input[x]; } sum += q * window[j]; } pwrLineSeriesAvg.Points.Add(new DataPoint(i * 0.251, sum / divisor)); } LineSeries pwrLineSeriesAvg2 = new LineSeries(); pwrLineSeriesAvg2.LineJoin = LineJoin.Round; pwrLineSeriesAvg2.Color = OxyColors.Crimson; pmPower.Series.Add(pwrLineSeriesAvg2); int avgCount = 7; int[] ringBuffer = Enumerable.Repeat(-1, avgCount).ToArray(); int bufferIndex = 0; for (int i = 0; i < call.PowerData.Length; i++) { ringBuffer[bufferIndex++] = call.PowerData[i]; if (bufferIndex >= ringBuffer.Length) { bufferIndex = 0; } if (i > 4) { int c = 0; double mAvg = 0; for (int j = 0; j < ringBuffer.Length; j++) { if (ringBuffer[j] >= 0) { c++; mAvg += ringBuffer[j]; } } pwrLineSeriesAvg2.Points.Add(new DataPoint((i - 4) * 0.251, mAvg / c)); } } LineAnnotation lineAnnotation = new LineAnnotation { Color = OxyColors.Red, StrokeThickness = 2, LineStyle = LineStyle.Dash, Type = LineAnnotationType.Horizontal, Y = call.AveragePower }; pmPower.Annotations.Add(lineAnnotation); Power = pmPower.AddStyles(); PlotModel pmFreq = new PlotModel(); ColumnSeries freqSeries = new ColumnSeries(); pmFreq.Series.Add(freqSeries); CategoryAxis item = new CategoryAxis(); item.Position = AxisPosition.Bottom; item.Title = "Frequenz [kHz]"; item.GapWidth = 0.1; item.IsTickCentered = true; item.LabelFormatter = i => LogAnalyzer.GetFrequencyFromFftBin((int)i).ToString(CultureInfo.CurrentCulture); item.MajorGridlineThickness = 0; pmFreq.Axes.Add(item); if (call.FftData != null) { freqSeries.Items.AddRange(call.FftData.Select((f, i) => { ColumnItem columnItem = new ColumnItem(f, i); columnItem.Color = i == call.MaxFrequencyBin ? OxyColors.Red : OxyColors.Green; return(columnItem); })); } Frequency = pmFreq.AddStyles(); }