123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576 |
- using Avalonia.Collections;
- using Avalonia.Controls;
- using OxyPlot;
- using OxyPlot.Series;
- using Shaker.Models;
- using ShakerApp.Tools;
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.Data;
- using System.Diagnostics;
- using System.Diagnostics.CodeAnalysis;
- using System.Linq;
- using System.Text;
- namespace ShakerApp.ViewModels
- {
- public abstract class BaseDataReviewItemViewModel:DisplayViewModelBase<IModel>,IDataReviewItem
- {
- public BaseDataReviewItemViewModel()
- {
- TimeDomainReview = new TimeDomainReviewViewModel(this);
- THDReview = new THDReviewViewModel(this);
- ButtonVisibily = false;
- }
- private protected ShakerConfigModel ShakerConfig = new ShakerConfigModel();
- private protected ShakerControlModel ShakerControl = new ShakerControlModel();
- private protected DeviceInfoModel DeviceInfo = new DeviceInfoModel();
- private protected bool isopen = false;
- public bool IsOpen => isopen;
- public abstract MainPageType PageType { get; }
- public string File { get; } = string.Empty;
- [AllowNull]
- private protected TDMS.ITDMSFile tdmsfile;
- [AllowNull]
- public TimeDomainReviewViewModel TimeDomainReview { get; }
- [AllowNull]
- public THDReviewViewModel THDReview { get; }
- public virtual void OpenFile(string path)
- {
- tdmsfile?.Close();
- tdmsfile?.Dispose();
- tdmsfile = TDMS.TDMSDataBuilder.OpenExisting(path);
- isopen = true;
- InitConfig();
- }
- public virtual void InitData(TDMS.ITDMSFile file)
- {
- tdmsfile?.Close();
- tdmsfile?.Dispose();
- tdmsfile = file;
- isopen = true;
- InitConfig();
- }
- private protected virtual void InitConfig()
- {
- if (tdmsfile == null) return;
- var group = tdmsfile.Contains(nameof(ShakerConfigModel)) ? tdmsfile[nameof(ShakerConfigModel)] : null;
- if (group == null) return;
- GetConfig(ShakerConfig, group!);
- group = tdmsfile.Contains(nameof(ShakerControlModel)) ? tdmsfile[nameof(ShakerControlModel)] : null;
- if (group == null) return;
- GetConfig(ShakerControl, group!);
- group = tdmsfile.Contains(nameof(DeviceInfoModel)) ? tdmsfile[nameof(DeviceInfoModel)] : null;
- if (group == null) return;
- GetConfig(DeviceInfo, group!);
- TimeDomainReview.InitData();
- THDReview.InitData();
- InitData();
- }
- private protected void GetConfig<T>(T config,TDMS.ITDMSChannelGroup group)
- {
- typeof(T).GetFields(System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public)
- .ToList()
- .ForEach(x =>
- {
- if (x.FieldType.IsAssignableTo(typeof(IList)) || x.FieldType.IsArray)
- {
- if (group.TryGetProperty<string>(x.Name, out var val) && !string.IsNullOrEmpty(val))
- {
- byte[] bytes = new byte[val.Length / 2];
- for (int i = 0; i < bytes.Length; i++)
- {
- bytes[i] = System.Convert.ToByte(val.Substring(i * 2, 2), 16);
- }
- x.SetValue(config,ShakerApp.Tools.Tools.Deserialize(x.FieldType, bytes));
- }
- else
- {
- x.SetValue(config,Activator.CreateInstance(x.FieldType));
- }
- }
- else if(x.FieldType == typeof(string))
- {
- if (group.TryGetProperty<string>(x.Name, out var val) && !string.IsNullOrEmpty(val))
- {
- x.SetValue(config,val);
- }
- else
- {
- x.SetValue(config,string.Empty);
- }
- }
- else if (x.FieldType.IsEnum)
- {
- if (group.TryGetProperty<string>(x.Name, out var val) && !string.IsNullOrEmpty(val))
- {
- x.SetValue(config,Enum.Parse(x.FieldType, val));
- }
- else
- {
- x.SetValue(config,Enum.GetValues(x.FieldType));
- }
- }
- else if (x.FieldType == typeof(byte))
- {
- if (group.TryGetProperty<string>(x.Name, out var val) && !string.IsNullOrEmpty(val) && byte.TryParse(val, out var b))
- {
- x.SetValue(config,b);
- }
- else
- {
- x.SetValue(config,(byte)0);
- }
- }
- else if (x.FieldType == typeof(sbyte))
- {
- if (group.TryGetProperty<string>(x.Name, out var val) && !string.IsNullOrEmpty(val) && sbyte.TryParse(val, out var b))
- {
- x.SetValue(config,b);
- }
- else
- {
- x.SetValue(config,(sbyte)0);
- }
- }
- else if (x.FieldType == typeof(short))
- {
- if (group.TryGetProperty<string>(x.Name, out var val) && !string.IsNullOrEmpty(val) && short.TryParse(val, out var b))
- {
- x.SetValue(config,b);
- }
- else
- {
- x.SetValue(config,(short)0);
- }
- }
- else if (x.FieldType == typeof(ushort))
- {
- if (group.TryGetProperty<string>(x.Name, out var val) && !string.IsNullOrEmpty(val) && ushort.TryParse(val, out var b))
- {
- x.SetValue(config,b);
- }
- else
- {
- x.SetValue(config,(ushort)0);
- }
- }
- else if (x.FieldType == typeof(int))
- {
- if (group.TryGetProperty<string>(x.Name, out var val) && !string.IsNullOrEmpty(val) && int.TryParse(val, out var b))
- {
- x.SetValue(config,b);
- }
- else
- {
- x.SetValue(config,(int)0);
- }
- }
- else if (x.FieldType == typeof(uint))
- {
- if (group.TryGetProperty<string>(x.Name, out var val) && !string.IsNullOrEmpty(val) && uint.TryParse(val, out var b))
- {
- x.SetValue(config,b);
- }
- else
- {
- x.SetValue(config,(uint)0);
- }
- }
- else if (x.FieldType == typeof(long))
- {
- if (group.TryGetProperty<string>(x.Name, out var val) && !string.IsNullOrEmpty(val) && long.TryParse(val, out var b))
- {
- x.SetValue(config,b);
- }
- else
- {
- x.SetValue(config,(long)0);
- }
- }
- else if (x.FieldType == typeof(ulong))
- {
- if (group.TryGetProperty<string>(x.Name, out var val) && !string.IsNullOrEmpty(val) && ulong.TryParse(val, out var b))
- {
- x.SetValue(config,b);
- }
- else
- {
- x.SetValue(config,(ulong)0);
- }
- }
- else if (x.FieldType == typeof(float))
- {
- if (group.TryGetProperty<string>(x.Name, out var val) && !string.IsNullOrEmpty(val) && float.TryParse(val, out var b))
- {
- x.SetValue(config,b);
- }
- else
- {
- x.SetValue(config,(float)0);
- }
- }
- else if (x.FieldType == typeof(double))
- {
- if (group.TryGetProperty<string>(x.Name, out var val) && !string.IsNullOrEmpty(val) && double.TryParse(val, out var b))
- {
- x.SetValue(config,b);
- }
- else
- {
- x.SetValue(config,(double)0);
- }
- }
- else if (x.FieldType == typeof(bool))
- {
- if (group.TryGetProperty<string>(x.Name, out var val) && !string.IsNullOrEmpty(val) && bool.TryParse(val, out var b))
- {
- x.SetValue(config,b);
- }
- else
- {
- x.SetValue(config,false);
- }
- }
- });
- }
- public virtual void CloseFile()
- {
- tdmsfile?.Close();
- tdmsfile?.Dispose();
- tdmsfile = null;
- }
- public class TimeDomainReviewViewModel : DisplayViewModelBase<IModel>
- {
- private bool isinint = false;
- List<OxyPlot.Series.LineSeries> _LineSeries = new List<OxyPlot.Series.LineSeries>();
- public OxyPlot.PlotModel PlotModel { get; } = new OxyPlot.PlotModel();
- private BaseDataReviewItemViewModel _Parent;
- public uint SampleRate { get => sampleRate; set =>SetProperty(ref sampleRate , value); }
- public uint TotalPages
- {
- get => Math.Clamp(totalPages, 1, uint.MaxValue);
- set
- {
- SetProperty(ref totalPages, value);
- OnPropertyChanged(nameof(MaxPageIndex));
- OnPropertyChanged(nameof(MaxReadPages));
- OnPropertyChanged(nameof(PageIndex));
- OnPropertyChanged(nameof(ReadPages));
- }
- }
- public uint PageIndex
- {
- get =>Math.Clamp(pageIndex,MinPageIndex,MaxPageIndex);
- set
- {
- SetProperty(ref pageIndex, value);
- OnPropertyChanged(nameof(MaxReadPages));
- OnPropertyChanged(nameof(ReadPages));
- LoadData();
- }
- }
- public uint MinPageIndex => 1;
- public uint MaxPageIndex => TotalPages;
- public uint ReadPages
- {
- get =>Math.Clamp(readPages,MinReadPages,MaxReadPages);
- set
- {
- SetProperty(ref readPages, value);
- LoadData();
- }
- }
- public uint MinReadPages => 1;
- public uint MaxReadPages => Math.Clamp(TotalPages - PageIndex + 1, 1, 10000);
- public TimeDomainReviewViewModel(BaseDataReviewItemViewModel parent)
- {
- _Parent = parent;
- PlotModel.Axes.Add(new OxyPlot.Axes.LinearAxis()
- {
- MajorGridlineStyle = OxyPlot.LineStyle.Solid,
- Position = OxyPlot.Axes.AxisPosition.Bottom,
- Key = "X",
- Title = App.Current?.FindResource("Time") +"",
- Unit = "s",
- MinimumPadding = 0,
- MaximumPadding = 0,
- });
- PlotModel.Axes.Add(new OxyPlot.Axes.LinearAxis()
- {
- MajorGridlineStyle = OxyPlot.LineStyle.Solid,
- Position = OxyPlot.Axes.AxisPosition.Left,
- Key = "Y",
- Title = App.Current?.FindResource("")+"",
- MinimumPadding = 0,
- MaximumPadding = 0,
- });
- PlotModel.Legends.Add(new OxyPlot.Legends.Legend()
- {
- IsLegendVisible = true,
- });
- }
- private TDMS.ITDMSChannelGroup? _DataGroup;
- private List<TDMS.ITDMSChannel> _Channels = new List<TDMS.ITDMSChannel>();
- private uint readPages;
- private uint pageIndex;
- private uint totalPages;
- private uint sampleRate;
- public override void InitData()
- {
- isinint = false;
- base.InitData();
- _DataGroup = _Parent.tdmsfile.Contains(BaseMainPageViewModel<IModel>.TimeDomainData) ? _Parent.tdmsfile[BaseMainPageViewModel<IModel>.TimeDomainData] : null;
- if (_DataGroup == null)
- {
- DataReviewViewModel.Instance.ShowError(App.Current?.FindResource("TestFileReadError")+"");
- return;
- }
- _Channels.Clear();
- _LineSeries.Clear();
- PlotModel.Series.Clear();
- if(_DataGroup.ChildCount ==0)
- {
- DataReviewViewModel.Instance.ShowError(App.Current?.FindResource("TestFileReadError") + "");
- return;
- }
- PlotModel.InvalidatePlot(false);
- for(ulong i=0;i<_DataGroup.ChildCount;i++)
- {
- _Channels.Add(_DataGroup[(int)i]!);
- _LineSeries.Add(new OxyPlot.Series.LineSeries()
- {
- XAxisKey = "X",
- YAxisKey = "Y",
- DataFieldX = nameof(OxyPlot.DataPoint.X),
- DataFieldY = nameof(OxyPlot.DataPoint.Y),
- Title = App.Current?.FindResource(_Channels[^1].Name)+"",
- Tag = _Channels[^1].Unit,
- });
- PlotModel.Series.Add(_LineSeries[^1]);
- }
- PlotModel.InvalidatePlot(true);
- SampleRate = _Parent.ShakerConfig.SampleRate;
- TotalPages = (uint)Math.Ceiling(_Channels[0].ChildCount / (double)SampleRate);
- ReadPages = 1;
- PageIndex = 1;
- isinint = true;
- LoadData();
- }
- private void LoadData()
- {
- if (!isinint) return;
- uint start = (PageIndex - 1) * SampleRate;
- uint len = ReadPages * SampleRate;
- len = (uint)Math.Clamp(len, len, _Channels[^1].ChildCount - start);
- double pro = 1d / SampleRate;
- //var datas = Enumerable.Repeat(new OxyPlot.DataPoint(), 1000_000).ToList();
- PlotModel.InvalidatePlot(false);
-
- for(int i=0;i<_Channels.Count;i++)
- {
- uint index = 0;
- _LineSeries[i].ItemsSource = _Channels[i].GetDataValues<double>(start, len).Select(x =>
- {
- return new OxyPlot.DataPoint((index++) * pro, x);
- }).ToList();
- // _LineSeries[i].ItemsSource = datas;
- }
- PlotModel.InvalidatePlot(true);
- }
- }
- public class THDReviewViewModel:DisplayViewModelBase<IModel>
- {
- private int[] indexLenght = new int[0];
- private List<TDMS.ITDMSChannel> channels = new List<TDMS.ITDMSChannel>();
- [AllowNull]
- TDMS.ITDMSChannel freqchannel;
- ulong datalen = 0;
- public uint MaxFrame => 10000;
- public uint Current
- {
- get => current;
- set
- {
- SetProperty(ref current, value);
- LoadData();
- }
- }
- public AvaloniaList<uint> Frames { get; } = new AvaloniaList<uint>();
- public bool IsFixed { get => isFixed; set =>SetProperty(ref isFixed ,value); }
- BaseDataReviewItemViewModel _parent;
- TDMS.ITDMSChannelGroup? _Group;
- private uint current = 1;
- private bool isFixed = true;
- public override string Title => IsFixed ? "SweepCount" : "THD";
- public THDReviewViewModel(BaseDataReviewItemViewModel parent)
- {
- _parent = parent;
- PlotModel.Axes.Add(new OxyPlot.Axes.LinearAxis()
- {
- Position = OxyPlot.Axes.AxisPosition.Bottom,
- MajorGridlineStyle = OxyPlot.LineStyle.Solid,
- Key="X",
- Title = App.Current?.FindResource("FrameXTitle")+ "",
- });
- PlotModel.Axes.Add(new OxyPlot.Axes.LinearAxis()
- {
- Position = OxyPlot.Axes.AxisPosition.Left,
- MajorGridlineStyle = OxyPlot.LineStyle.Solid,
- Title="THD",
- Unit ="%",
- Key ="Y",
- });
- PlotModel.Legends.Add(new OxyPlot.Legends.Legend()
- {
- IsLegendVisible = true,
- });
- }
- public override void InitData()
- {
- base.InitData();
- if(_parent.PageType == MainPageType.SinePage && _parent is SineDataReviewViewModel sine)
- {
- if(sine.SweepConfig.SignalType == SignalType.Fixed)
- {
- PlotModel.Axes[0].Title = App.Current?.FindResource("FrameXTitle") + "";
- PlotModel.Axes[0].Unit = "";
- }
- else
- {
- PlotModel.Axes[0].Title = App.Current?.FindResource("Frequency") + "";
- PlotModel.Axes[0].Unit = "Hz";
- }
- IsFixed = sine.SweepConfig.SignalType == SignalType.Fixed;
- OnPropertyChanged(nameof(Title));
- }
- channels.Clear();
- PlotModel.Series.Clear();
- _Group = _parent.tdmsfile.Contains(BaseMainPageViewModel<IModel>.THDData) ? _parent.tdmsfile[BaseMainPageViewModel<IModel>.THDData] : null;
-
- if(IsEnabled && _Group!=null)
- {
- for(int i=0; i < (int)_Group.ChildCount;i++)
- {
- var ch = _Group[i];
- if (ch == null || !ShakerDataViewModel.Instance.AllowTHDChannels.Contains(ch.Name)) continue;
- channels.Add(ch);
- PlotModel.Series.Add(new OxyPlot.Series.LineSeries()
- {
- XAxisKey = "X",
- YAxisKey = "Y",
- DataFieldX = nameof(DataPoint.X),
- DataFieldY = nameof(DataPoint.Y),
- Title = App.Current?.FindResource(ch.Name)+"",
- });
- }
- freqchannel = _Group.Contains(nameof(SweepData.Frequency)) ? _Group[nameof(SweepData.Frequency)] : null;
- var sweepindexchannel = _Group.Contains(nameof(SineMainPageViewModel.SweepIndex)) ? _Group[nameof(SineMainPageViewModel.SweepIndex)] : null;
- if(sweepindexchannel!=null)
- {
- var max = sweepindexchannel.GetDataValues<int>((uint)sweepindexchannel.ChildCount-1, 1)[0];
- indexLenght = new int[max+1];
- int index = 0;
- for(int i=0;i<max+1;i++)
- {
- while (true)
- {
- uint readlen = Math.Min(MaxFrame, (uint)(sweepindexchannel.ChildCount - (uint)index));
- if (readlen == 0) break;
- var temp = sweepindexchannel.GetDataValues<int>((uint)index, readlen);
- int c = temp.Count(x => x == i);
- indexLenght[i] += c;
- if (c == readlen)
- {
- index += (int)readlen;
- continue;
- }
- else
- {
- if (temp[^1]!=i)
- {
- index += c;
- break;
- }
- }
- }
- }
- Frames.Clear();
- Frames.AddRange(Enumerable.Range(1, max+1).Select(x => (uint)x).ToList());
- }
- else
- {
- indexLenght = new int[0];
- var total = (int)Math.Ceiling(datalen / (float)MaxFrame);
- Frames.Clear();
- Frames.AddRange(Enumerable.Range(1, total).Select(x => (uint)x).ToList());
- }
- datalen = channels.Min(x => x.ChildCount);
- Current = 1;
- }
- else
- {
- PlotModel.InvalidatePlot(false);
- PlotModel.InvalidatePlot(true);
- }
- OnPropertyChanged(nameof(Frames));
- OnPropertyChanged(nameof(IsEnabled));
- }
- private void LoadData()
- {
- if (datalen == 0) return;
- if (_parent is not SineDataReviewViewModel sine) return;
- uint start = (Current - 1) * MaxFrame;
- uint len = (uint)Math.Min(datalen - (ulong)start, (ulong)MaxFrame);
- PlotModel.InvalidatePlot(false);
- if(freqchannel==null || sine.SweepConfig.SignalType == SignalType.Fixed)
- {
- for (int i = 0; i < channels.Count; i++)
- {
- int index = 0;
- (PlotModel.Series[i] as LineSeries)!.ItemsSource = channels[i].GetDataValues<float>(start, len).Select(x =>
- {
- return new DataPoint(index++, x * 100);
- }).ToList();
- }
- }
- else
- {
- start = 0;
- var indexindex = Frames.ToList().FindIndex(x => x == Current);
- if(indexindex>0)
- {
- start = (uint)indexLenght.Skip(indexindex).Sum();
- }
- len = (uint)indexLenght[indexindex];
- var freq = freqchannel.GetDataValues<double>(start, len);
- for (int i = 0; i < channels.Count; i++)
- {
- int index = 0;
- (PlotModel.Series[i] as LineSeries)!.ItemsSource = channels[i].GetDataValues<float>(start, len).Select(x =>
- {
- return new DataPoint(freq[index++], x * 100);
- }).ToList();
- }
- }
- PlotModel.InvalidatePlot(true);
- }
- public OxyPlot.PlotModel PlotModel { get; } = new OxyPlot.PlotModel();
- public bool IsEnabled => _Group != null && _Group.ChildCount > 0;
- }
- }
- }
|