/// <summary> /// 转换 /// </summary> /// <param name="str"></param> /// <param name="type"></param> /// <returns></returns> public static Object Convert(string str, ValueType type) { if (String.IsNullOrWhiteSpace(str) || String.Equals("NULL", str.Trim(), StringComparison.CurrentCultureIgnoreCase)) { return(null); } switch (type) { case ValueType.Float: return(Geo.Utils.DoubleUtil.TryParse(str, null)); //case ValueType.Int: // return int.Parse(str); case ValueType.Long: return(long.Parse(str)); case ValueType.Time: return(new Time(DateTime.Parse(str))); case ValueType.Bool: return(Boolean.Parse(str)); case ValueType.RmsedNumeral: return(RmsedNumeral.Parse(str)); default: return(str); } }
/// <summary> /// 修复效果不理想。2017.10.10 /// 多项式拟合检核新数据,通过则直接添加,返回修正后的该值 /// 如果未满,则直接添加,不检核。 /// 如果数据达到最大断裂数,则清空之前数据重新对齐添加。 /// 采用Tag存储对齐数据。 /// </summary> /// <param name="key">关键字</param> /// <param name="newVal"></param> /// <param name="order"></param> /// <param name="maxRmsTimes"></param> /// <param name="referVal">参考值</param> /// <returns>添加则返回true,否则false</returns> public double FitCheckAddAndAlign(TKey key, double newVal, double referVal = 0, int order = 2, double maxRmsTimes = 10) { //对齐功能,第一次 if (this.Tag == null || this.Count == 0) { this.Tag = (referVal - newVal); } var correctedNewVal = newVal + (double)(Tag); if (!this.IsFull) { this.Add(key, correctedNewVal); return(correctedNewVal); } //干净拟合数据 var neatWin = GetNeatlyWindowData(order, 3, true); RmsedNumeral nextFitVal = neatWin.GetPolyFitValue(key, order); var differ = Math.Abs(nextFitVal.Value - correctedNewVal); if (differ > nextFitVal.Rms * maxRmsTimes) { //采用拟合值修复采用参考值修复 Tag = (nextFitVal.Value - newVal); correctedNewVal = newVal + (double)(Tag); this.Clear(); } Add(key, correctedNewVal); return(correctedNewVal); }
/// <summary> /// 对齐后的数据,进行滤波。 /// </summary> /// <param name="aligned"></param> /// <returns></returns> private RmsedNumeral FilterAlignedValue(RmsedNumeral aligned) { var result = AdjustFilter.Filter(aligned); this.CurrentFilteredFraction = result; return(result); }
/// <summary> /// 滤波 /// </summary> /// <param name="newVal"></param> /// <returns></returns> public RmsedNumeral Filter(RmsedNumeral newVal) { var builder = new OneDimAdjustMatrixBuilder(newVal, PrevAdjustment); var sp = new SimpleKalmanFilter(); var a = sp.Run(builder); var est = a.Estimated; this.PrevAdjustment = a;//update return(new RmsedNumeral(est[0], est.GetRmsVector()[0])); }
/// <summary> ///具有认为阶梯的对齐。 /// 多项式拟合检核新数据,通过则直接添加,返回修正后的该值 /// 如果未满,则直接添加,不检核。 /// 如果数据达到最大断裂数,则清空之前数据重新对齐添加。 /// 采用Tag存储对齐数据。 /// </summary> /// <param name="key">关键字</param> /// <param name="newVal"></param> /// <param name="order"></param> /// <param name="maxRmsTimes"></param> /// <param name="referVal">参考值</param> /// <returns>添加则返回true,否则false</returns> public double FitCheckAddAndAlignWithStep(TKey key, double newVal, out bool isReseted, double referVal = 0, int order = 2, double maxRmsTimes = 10, double step = 100) { //对齐功能,第一次 if (this.Tag == null || this.Count == 0) { this.Tag = Math.Round(referVal - newVal); isReseted = true; } //整数对齐,第一次 var correctedNewVal = newVal + (double)(Tag); if (!this.IsFull) { //在未满前,也应该做出判断。此处采用参考值判断。 if (Math.Abs(correctedNewVal - referVal) > 1000) { Tag = GetAligner(newVal, referVal, step, 0); correctedNewVal = newVal + (double)(Tag); isReseted = true; } else { isReseted = false; } this.Add(key, correctedNewVal); return(correctedNewVal); } //干净拟合数据 var neatWin = GetNeatlyWindowData(order, 3, true); RmsedNumeral nextFitVal = neatWin.GetPolyFitValue(key, order); var differ = Math.Abs(nextFitVal.Value - correctedNewVal); if (differ > nextFitVal.Rms * maxRmsTimes) { //避免和前一个修正采用相同方向的偏移。但围绕参考值,不至于太远。 var fitVal = nextFitVal.Value; Tag = GetAligner(newVal, referVal, step, fitVal); correctedNewVal = newVal + (double)(Tag); this.Clear(); isReseted = true; } else { isReseted = false; } Add(key, correctedNewVal); return(correctedNewVal); }
/// <summary> /// 采用四舍五入法,获取本分组MW的小数部分[-0.5, 0.5],将所有分段的MW合并,加权平均。以第RMS最小的为基准,作差比较,确保在同一个小数区间 /// </summary> /// <param name="maxRms"></param> /// <returns></returns> public BaseDictionary <TKey, RmsedNumeral> GetAverageRoundFraction(double maxRms = 0.5) { var dat = new BaseDictionary <TKey, RmsedNumeral>(); foreach (var item in this.Data) { var list = item.Value.Values; RmsedNumeral ave = Geo.Utils.DoubleUtil.GetAverageRoundFraction(list, maxRms, 3); if (ave != null) { dat[item.Key] = ave; } } return(dat); }
/// <summary> /// 第一次,初值,周跳发生后,也采用本法赋值。 /// </summary> /// <param name="rawValue"></param> /// <returns></returns> private RmsedNumeral GetInitValue(RmsedNumeral rawValue) { //上一次小数作为参考,以使本次最为接近 if (CurrentFilteredFraction != null) { FactionCutter.ReferenceValue = CurrentFilteredFraction.Value; } //计算整数部分或周跳的大小 var bufferAve = Buffers.AverageValue;//采用平均数,避免跳跃 var alignedFraction = FactionCutter.Filter(bufferAve); this.IntegerPart = (int)(bufferAve - alignedFraction); this.CurrentFilteredFraction = new RmsedNumeral(alignedFraction, rawValue.Rms); log.Debug("截取了整数部分 " + this.IntegerPart); return(this.CurrentFilteredFraction); }
/// <summary> /// 多项式拟合检核新数据,通过则添加,返回ture,否则清空,添加该数据,并返回false。 /// 如果未满,则直接添加,不检核,并返回true。 /// </summary> /// <param name="newVal"></param> /// <param name="order"></param> /// <param name="errorTimes"></param> /// <param name="nextIndex"></param> /// <returns></returns> public bool PolyfitCheckAddOrClear(double newVal, int order, double errorTimes = 3, double nextIndex = 0) { if (!this.IsFull) { this.Add(newVal); return(true); } RmsedNumeral rmsedVal = GetNextLsPolyFitValue(nextIndex, order); var error = Math.Abs(newVal - rmsedVal.Value); var maxError = rmsedVal.Rms * errorTimes; if (error > maxError) { this.Clear(); this.Add(newVal); return(false); } this.Add(newVal); return(true); }
/// <summary> /// 计算返回滤波后的数据,为小数部分的滤波值。 /// </summary> /// <returns></returns> public CyclicalNumerFilter Calculate() { if (_isCurrentSolved) { return(this); } _isCurrentSolved = true; Index++; //决定截取整数部分 if (IsNeedInitValue()) { this.CurrentFilteredFraction = GetInitValue(CurrentRawValue); } else { var isError = IsGrossError(); if (isError) //用于判断是周跳,还是粗差。 { var isGrossError = ErrorJudge.IsJumped(Buffers, CurrentRawValue.Value); //注意缓存为未对齐数据 if (isGrossError) //粗差,剔除,返回原来的。 //粗差不动,沿用当前 { return(this); } else //发生周跳,重新初始化 { var init = GetInitValue(CurrentRawValue);// this.CurrentFilteredFraction = FilterAlignedValue(init); } } else { //滤波 this.CurrentFilteredFraction = FilterAlignedValue(new RmsedNumeral(CurrentRawValue.Value - IntegerPart, CurrentRawValue.Rms)); } } this.CurrentFilteredValue = new RmsedNumeral(CurrentFilteredFraction.Value + IntegerPart, CurrentFilteredFraction.Rms); return(this); }
/// <summary> /// 采用滑动平均值方法,对值进行比较,如果超限则就地分解。 /// </summary> /// <param name="errorTimes"></param> /// <param name="judgeWindowSize"></param> /// <returns></returns> public List <NumeralWindowData <TKey> > SplitByMovingAverage(int errorTimes, int judgeWindowSize = 10) { //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; } RmsedNumeral ave = window.SubNumeralWindow(window.Count - judgeWindowSize, judgeWindowSize).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> public override void Clear() { this.LastAverage = this.Average; base.Clear(); }
/// <summary> /// 返回滤波后的值.为小数部分的滤波值。 /// </summary> /// <param name="rawValue">具有整周的原始值。</param> /// <returns></returns> public RmsedNumeral Filter(RmsedNumeral rawValue) { SetRawValue(rawValue).Calculate(); return(CurrentFilteredFraction); }
/// <summary> /// 设置当前值。 /// </summary> /// <param name="rawValue"></param> /// <returns></returns> public CyclicalNumerFilter SetRawValue(RmsedNumeral rawValue) { this._isCurrentSolved = false; this.CurrentRawValue = rawValue; return(this); }
/// <summary> /// 是否为 0 /// </summary> /// <param name="val"></param> /// <returns></returns> public static bool IsZero(RmsedNumeral val) { return(val.Rms == 0 && val.Value == 0); }
/// <summary> /// 是否为 0 或则无效 /// </summary> /// <param name="val"></param> /// <returns></returns> public static bool IsZeroOrNotValid(RmsedNumeral val) { return(IsZero(val) || !IsValid(val)); }
/// <summary> /// 是否有效 /// </summary> /// <param name="val"></param> /// <returns></returns> public static bool IsValid(RmsedNumeral val) { return(Geo.Utils.DoubleUtil.IsValid(val.Value) && Geo.Utils.DoubleUtil.IsValid(val.Rms)); }