/// <summary> /// 新增加一个数据判断通过后才入库。 /// 添加成功后返回true。 /// </summary> /// <param name="key"></param> public virtual Boolean CheckAndAdd(double newVal, NumeralWindowData buffer) { if (ErrorJudge.IsFirst) { ErrorJudge.SetReferenceValue(newVal); } else { ErrorJudge.SetReferenceValue(this.CurrentValue); } if (ErrorJudge.IsOverLimit(newVal))//判断是否超限 { var list = buffer.ToList(); list.Insert(0, newVal); NumeralWindowData newBuffer = new NumeralWindowData(list); if (ErrorJudge.IsJumped(buffer)) //跳跃,则重新计算整数值,否则认为是粗差,直接忽略。 { CurrentAdjustment = null; //重新计算滤波值, Add(newVal); return(true); } return(false); } else { Add(newVal); return(true); } }
/// <summary> /// 获取数窗口 /// </summary> /// <param name="refKey"></param> /// <returns></returns> public NumeralWindowData <TKey> GetNumeralWindowData(TKey refKey) { foreach (var item in Cashes.Data) { if (item.Key.Contains(refKey)) { return(Cashes[item.Key]); } } //提取数据 NumeralWindowData <TKey> window = new NumeralWindowData <TKey>(int.MaxValue); var seg = this.GetSegmentKeyValue(refKey); if (seg.Value == null) { return(null); } foreach (var item in seg.Value.Data) { window.Add(item.Key, item.Value); } //缓存 Cashes[seg.Key] = window; return(window); }
/// <summary> /// 判断是否是跳变。通过后续缓存窗口数据判断。 /// 请先调用 IsOverTolerance 确定超限后,再调用我。 /// 这里假定粗差只出现少数几次或1次。 /// </summary> /// <param name="buffer"></param> /// <returns></returns> public bool IsJumped(IEnumerable <double> buffer) { //算法:如果缓存中下面几个全超限,则认为不是粗差,是跳变。 var nextFive = new NumeralWindowData(buffer); return(IsOverLimit(nextFive.AverageValue)); }
public static NumeralWindowData operator +(NumeralWindowData data, double val) { NumeralWindowData result = new NumeralWindowData(data.Count); foreach (var item in data) { result.Add(item + val); } return(result); }
/// <summary> /// 获取差分指定次的数据窗口结果,后减前 /// </summary> /// <returns></returns> public NumeralWindowData <TKey> GetDifferWindow(int differCount) { NumeralWindowData <TKey> result = this; for (int i = 0; i < differCount; i++) { result = result.GetDifferWindow(); } return(result); }
public static NumeralWindowData <TKey> operator +(NumeralWindowData <TKey> data, double val) { NumeralWindowData <TKey> result = new NumeralWindowData <TKey>(data.Count); foreach (var item in data.Data) { result.Add(item.Key, item.Value + val); } return(result); }
/// <summary> /// 获取差分一次的数据窗口结果。 /// </summary> /// <returns></returns> public NumeralWindowData GetDifferWindow() { double[] differs = new double[WindowSize - 1]; for (int i = 0; i < WindowSize - 1; i++) { differs[i] = this[i + 1] - this[i]; } NumeralWindowData differWindow = new NumeralWindowData(differs); return(differWindow); }
/// <summary> /// 计算整数偏差。新偏差与原数据应该控制在 0.5 以内。 /// </summary> /// <param name="buffer"></param> /// <returns></returns> public int CaculateIntBias(NumeralWindowData buffer) { var average = buffer.AverageValue; var newIntBias = Geo.Utils.DoubleUtil.GetNearstIntBias(average, this.CurrentValue); if (IntBias != newIntBias) { OnIntBiasChanged(newIntBias); } return(newIntBias); }
/// <summary> /// 判断是否是跳变。通过后续缓存窗口数据判断。 /// 请先调用 IsOverTolerance 确定超限后,再调用我。 /// 这里假定粗差只出现少数几次或1次。 /// </summary> /// <param name="buffer"></param> /// <param name="referValue"></param> /// <returns></returns> public bool IsJumped(IEnumerable <double> buffer, double referValue) { if (buffer == null) { return(false); } //算法:如果缓存中下面几个全超限,则认为不是粗差,是跳变。 var nextFive = new NumeralWindowData(buffer); return(IsOverLimit(nextFive.AverageValue, referValue)); }
/// <summary> /// 拟合后返回各项的拟合误差 /// </summary> /// <param name="polyFitOrder"></param> /// <returns></returns> public NumeralWindowData <TKey> GetFitErrorWindow(int polyFitOrder) { NumeralWindowData <TKey> errors = new NumeralWindowData <TKey>(this.WindowSize) { KeyToDouble = KeyToDouble }; var fitter = BuildPolyfitter(polyFitOrder); var firstKey = this.TheVeryFirstKey; foreach (var item in this.OrderedData) { var x = KeyToDouble(item.Key) - KeyToDouble(firstKey); var error = item.Value - fitter.GetY(x); errors.Add(item.Key, error); } return(errors); }
/// <summary> /// 按键间隔分离小窗口。如果间之间的间距超过了指定宽度,则分离成两个或多个子窗口。 /// </summary> /// <param name="funcKeyToDouble">将Key转换为数值</param> /// <param name="maxKeySpan"></param> /// <returns></returns> public List <NumeralWindowData <TKey> > Split(Func <TKey, double> funcKeyToDouble, double maxKeySpan) { var initSelects = new List <NumeralWindowData <TKey> >(); var window = new NumeralWindowData <TKey>(Int16.MaxValue); initSelects.Add(window); var lastKeyVal = Double.MinValue; foreach (var kv in this.Data) { var key = kv.Key; var val = kv.Value; var keVal = funcKeyToDouble(kv.Key); if (window.Count < 1) { window.Add(kv.Key, kv.Value); lastKeyVal = keVal; continue; } var differ = Math.Abs(lastKeyVal - keVal); var isPassed = differ <= maxKeySpan; if (isPassed) { window.Add(kv.Key, kv.Value); } else { //update window size window.WindowSize = window.Count; //create new window = new NumeralWindowData <TKey>(Int16.MaxValue); initSelects.Add(window); } //update lastKeyVal = keVal; } window.WindowSize = window.Count; return(initSelects); }
/// <summary> /// 采用平均值方法,对值进行比较,如果超限则就地分解。 /// </summary> /// <param name="errorTimes"></param> /// <returns></returns> public List <NumeralWindowData <TKey> > SplitByAverage(int errorTimes) { //1.初选,采用平均法,放大方差要求,将数据进行分段。 //遍历, var initSelects = new List <NumeralWindowData <TKey> >(); var window = new NumeralWindowData <TKey>(Int16.MaxValue); initSelects.Add(window); foreach (var kv in this.Data) { var key = kv.Key; var val = kv.Value; if (window.Count < 1) { window.Add(kv.Key, kv.Value); continue; } var ave = window.Average; var differ = Math.Abs(ave.Value - kv.Value); var rms = ave.Rms == 0 ? double.MaxValue : ave.Rms; var errorThreshold = errorTimes * rms; var isPassed = differ <= errorThreshold; if (isPassed) { window.Add(kv.Key, kv.Value); } else { window.WindowSize = window.Count; window = new NumeralWindowData <TKey>(Int16.MaxValue); initSelects.Add(window); } } window.WindowSize = window.Count; return(initSelects); }
/// <summary> /// 按照指定长度截断。最后如果太小,则直接追加到上一个。 /// </summary> /// <param name="aboutSize">大致大小</param> /// <returns></returns> private List <NumeralWindowData <TKey> > Split(int aboutSize) { if (this.Count <= aboutSize) { return(new List <NumeralWindowData <TKey> >() { this }); } var initSelects = new List <NumeralWindowData <TKey> >(); var window = new NumeralWindowData <TKey>(aboutSize); foreach (var kv in this.Data) { if (window.IsFull) { initSelects.Add(window); window = new NumeralWindowData <TKey>(aboutSize); } window.Add(kv.Key, kv.Value); } //检查,最后如果太小,则直接追加到上一个。 if (window.Count < aboutSize / 2) { var last = initSelects.Last(); last.WindowSize += window.Count; last.Add(window.Data); } else { initSelects.Add(window); } return(initSelects); }
/// <summary> /// 新增加一个数据判断通过后才入库。 /// 添加成功后返回true。 /// </summary> /// <param name="key"></param> public override Boolean CheckAndAdd(double newVal, NumeralWindowData buffer) { //这里同父类一样,采用原始数据判断,以减少计算量。 if (ErrorJudge.IsFirst) // 第一次取其小数 { IntBias = CaculateIntBias(buffer.GetNeatlyWindowData()); ErrorJudge.SetReferenceValue(newVal); } else { ErrorJudge.SetReferenceValue(this.IntFraction.Value); } var fraction = newVal - IntBias; if (ErrorJudge.IsOverLimit(newVal))//判断是否超限 { var list = buffer.InsertAndReturnNew(0, newVal); if (ErrorJudge.IsJumped(list))//跳跃,则重新计算整数值,否则认为是粗差,直接忽略。 { var newBuffer2 = new NumeralWindowData(list); var biasBuffer = newBuffer2.GetNeatlyWindowData(); IntBias = CaculateIntBias(biasBuffer); fraction = newVal - IntBias; Add(fraction); return(true); } return(false); } else { Add(fraction); return(true); } }
/// <summary> /// 设置缓存。 /// </summary> /// <param name="Buffers"></param> /// <returns></returns> public CyclicalNumerFilter SetBuffer(NumeralWindowData Buffers) { this.Buffers = Buffers; return(this); }