using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ComponentModel; using FObjBase; using FlyADBase; using FLY.Thick.Base.IService; using System.IO; namespace FLY.Thick.Base.Server { public class GM_ScanCorr:GM_ScanMotion2, IScanCorrService,Misc.ISaveToXml { #region 延时推送 MARKNO #endregion #region IScanCorrService 接口 private bool _enable = false; /// <summary> /// 使能!! /// </summary> public bool Enable { get { return _enable; } set { if (_enable != value) { _enable = value; NotifyPropertyChanged("Enable"); } } } private int _smoothfactor = 1; /// <summary> /// 修正数据滤波,平均滤波,多少个数据平均 /// </summary> public int SmoothFactor { get { return _smoothfactor; } set { if (_smoothfactor != value) { _smoothfactor = value; NotifyPropertyChanged("SmoothFactor"); } } } private int scanTimer = 2; /// <summary> /// 来回次数 /// </summary> public int ScanTimer { get { return scanTimer; } set { if (scanTimer != value) { scanTimer = value; NotifyPropertyChanged("ScanTimer"); } } } private int validbegin = 0; /// <summary> /// 有效范围.开始,单位脉冲 /// </summary> public int ValidBegin { get { return validbegin; } set { if (validbegin != value) { validbegin = value; NotifyPropertyChanged("ValidBegin"); } } } private int validend = 8000; /// <summary> /// 有效范围.结束,单位脉冲 /// </summary> public int ValidEnd { get { return validend; } set { if (validend != value) { validend = value; NotifyPropertyChanged("ValidEnd"); } } } private int _posofgrid = 8; /// <summary> /// 机架修正数据, /// </summary> public int PosOfGrid { get { return _posofgrid; } set { if (_posofgrid != value) { _posofgrid = value; } NotifyPropertyChanged("PosOfGrid"); } } private int _poslen = 9000; /// <summary> /// 机架修正数据, /// </summary> public int PosLen { get { return _poslen; } set { if (_poslen != value) { _poslen = value; } NotifyPropertyChanged("PosLen"); } } private ScanCorrGroup[] _groups = new ScanCorrGroup[2] { new ScanCorrGroup(), new ScanCorrGroup() }; public IScanCorrGroup Group0 { get { return _groups[0]; } } public IScanCorrGroup Group1 { get { return _groups[1]; } } public ScanCorrGroup[] Groups { get { return _groups; } } #endregion string param_path = "scancorr.csv"; public GM_ScanCorr(FlyAD7 flyad) : this(flyad, "scancorr.csv") { } public GM_ScanCorr(FlyAD7 flyad, string param_path) : base(flyad) { GMState = Common.CTRL_STATE.CORR; if (string.IsNullOrEmpty(param_path)) this.param_path = param_path; Load(); MakeValid(); CurrGroupIndex = 0; this.PropertyChanged += new PropertyChangedEventHandler(ScanCorr_PropertyChanged); DataPosEvent += new EndEventHandler(pollCorrect_DataPosEvent); EndEvent += new EndEventHandler(pollCorrect_EndEvent); FinishEvent += new EventHandler(pollCorrect_FinishEvent); } void MakeValid() { //确保 ForwDatas BackwDatas 大小 为 PosLen / PosOfGrid int dataLen = PosLen / PosOfGrid; List<List<int>> datasList = new List<List<int>>(); datasList.Add(Group0.ForwDatas); datasList.Add(Group0.BackwDatas); datasList.Add(Group1.ForwDatas); datasList.Add(Group1.BackwDatas); for (int i = 0; i < datasList.Count(); i++) { int idx = dataLen; List<int> datas = datasList[i]; int remove_cnt = datas.Count() - dataLen; if (remove_cnt > 0) { datas.RemoveRange(idx, remove_cnt); } else if (remove_cnt < 0) { for (int j = 0; j < (-remove_cnt); j++) { datas.Add(Misc.MyBase.NULL_VALUE); } } } if (ValidBegin < 0) ValidBegin = 0; if (ValidEnd >= PosLen) ValidEnd = PosLen - 1; } void ScanCorr_PropertyChanged(object sender, PropertyChangedEventArgs e) { if ((e.PropertyName == "ValidBegin") || (e.PropertyName == "ValidEnd")) { UpdateAvg(); } } void pollCorrect_DataPosEvent(object obj, FlyADBase.MiniGridEventArgs e) { int grid_len = PosLen / PosOfGrid; //TODO if (e.direction == Misc.DIRECTION.FORWARD) { int p = e.grid_start * 100 / grid_len; Progress = (100 * tempDataCnt + p) / (2* ScanTimer); } else { int p = (grid_len - e.grid_start) * 100 / grid_len; Progress = (100 * tempDataCnt + p) / (2 * ScanTimer); } } #region 属性,动态 private int _corrPoint; /// <summary> /// 当前操作的组 /// </summary> public int CurrGroupIndex { get { return _corrPoint; } set { _corrPoint = value; NotifyPropertyChanged("CurrGroupIndex"); } } private int _progress = 0; /// <summary> /// 进度 =100完成 /// </summary> public int Progress { get { return _progress; } set { _progress = value; if (value == 0) Ing = true; else if (value >= 100) Ing = false; NotifyPropertyChanged("Progress"); } } private bool _ing; /// <summary> /// 校正中 /// </summary> public bool Ing { get { return _ing; } set { _ing = value; NotifyPropertyChanged("Ing"); } } private int[][] tempData = new int[2][]; private int tempDataCnt = 0; private int _progress_cnt = 0; private Misc.DIRECTION _progress_direction = Misc.DIRECTION.FORWARD; #endregion public void Smooth(int index) { Groups[index].Smooth(SmoothFactor); Save(); } public override bool Start() { bool b = base.Start(); if (!b) return false; Progress = 0; ScanCnt = ScanTimer; PosOfGrid = mFlyAD.PosOfGrid; PosLen = mFlyAD.PosLen; int grid_size = PosLen / PosOfGrid; tempData[0] = new int[grid_size]; tempData[1] = new int[grid_size]; for (int i = 0; i < grid_size; i++) { tempData[0][i] = Misc.MyBase.NULL_VALUE; tempData[1][i] = Misc.MyBase.NULL_VALUE; } tempDataCnt = 0; return base.Start2(); } public void Start( int index) { Enable = false;//关闭校正,让flyad7 输出的是原始数据 //ScanTimer = scantimer; //SmoothFactor = smoothfactor; if (index < 0) index = 0; if (index > 1) index = 1; CurrGroupIndex = index; Start(); } public override void Stop() { base.Stop(); Ing = false; } public void Clear(int index) { if (index < 0) index = 0; if (index > 1) index = 1; Groups[index].Clear(); Save(); } public void Apply() { Save(); } void pollCorrect_FinishEvent(object sender, EventArgs e) { //if (!Ing) // return; if (Make()) Save(); Progress = 100; } void pollCorrect_EndEvent(object obj, FlyADBase.MiniGridEventArgs e) { //if (!Ing) // return; DataEnd(e.direction, e.posOfGrid, e.grid_start, e.buf); } void DataEnd(Misc.DIRECTION direction, int posOfGrid, int start_grid, int[] dat) { int idx = 0; if (direction == Misc.DIRECTION.BACKWARD) idx = 1; int start_pos = start_grid * posOfGrid; for (int i = 0; i < dat.Length; i++) { int grid = i + start_grid; if (grid >= tempData[idx].Length) break; if (Misc.MyBase.ISVALIDATA(tempData[idx][grid]) && Misc.MyBase.ISVALIDATA(dat[i])) { tempData[idx][grid] = (tempData[idx][grid] * tempDataCnt + dat[i]) / (tempDataCnt + 1); } else if (Misc.MyBase.ISVALIDATA(dat[i])) { tempData[idx][grid] = dat[i]; } } tempDataCnt++; Progress = 100 * tempDataCnt / (ScanTimer * 2); } void UpdateAvg() { int begin = ValidBegin / PosOfGrid; int end = ValidEnd / PosOfGrid; if (begin >= end) { begin = 0; end = PosLen / PosOfGrid - 1; } for (int i = 0; i < 2; i++) { ((ScanCorrGroup)(Groups[i])).CalAvg(begin, end); } } bool Make() { int pindex = CurrGroupIndex; if (pindex != 0) pindex = 1; //tempData 的数据必须全部都是有效的!!!! //for (int i = 0; i < 2; i++) //{ // if (tempData[i].Contains(Misc.MyBase.NULL_VALUE)) // return false; //} //make ((ScanCorrGroup)(Groups[pindex])).Make( tempData[0], tempData[1]); ((ScanCorrGroup)(Groups[pindex])).Smooth(SmoothFactor / PosOfGrid); int begin = ValidBegin / PosOfGrid; int end = ValidEnd / PosOfGrid; if (begin >= end) { begin = 0; end = PosLen / PosOfGrid - 1; } ((ScanCorrGroup)(Groups[pindex])).CalAvg(begin, end); return true; } public void CorrectADs(Misc.DIRECTION direction, int start_grid, int[] dat) { if (Enable) { for (int i = 0; i < dat.Length; i++) { int grid = start_grid + i; dat[i] = CorrectAD(direction, grid, dat[i]); } } } public int CorrectAD(Misc.DIRECTION direction, int grid, int ad) { if ((Misc.MyBase.ISVALIDATA(ad) == false) || (Misc.MyBase.ISVALIDATA(grid) == false) || (Enable == false) || ((Groups[0].ForwDatas.Count() ==0) && (Groups[1].ForwDatas.Count() ==0))) return ad; int datasize; if(Groups[0].ForwDatas.Count()>0) datasize = Groups[0].ForwDatas.Count(); else datasize = Groups[1].ForwDatas.Count(); int begin = ValidBegin / PosOfGrid; int end = ValidEnd / PosOfGrid; if (begin >= end) { begin = 0; end = PosLen / PosOfGrid - 1; } if (grid < 0) grid = 0; else if (grid >= datasize) grid = datasize - 1; else if (grid < begin) grid = begin; else if (grid > end) grid = end; int ad0 = Misc.MyBase.NULL_VALUE;//group 0 int ad1 = Misc.MyBase.NULL_VALUE;//group 1 int ad0_avg = Groups[0].AvgAD;//group 0 int ad1_avg = Groups[1].AvgAD;//group 1 if (direction == Misc.DIRECTION.FORWARD) { if(Groups[0].ForwDatas.Count>0) ad0 = Groups[0].ForwDatas[grid]; if (Groups[1].ForwDatas.Count > 0) ad1 = Groups[1].ForwDatas[grid]; } else if (direction == Misc.DIRECTION.BACKWARD) { if (Groups[0].BackwDatas.Count > 0) ad0 = Groups[0].BackwDatas[grid]; if (Groups[1].BackwDatas.Count > 0) ad1 = Groups[1].BackwDatas[grid]; } else { int ad2 = Misc.MyBase.NULL_VALUE; int ad3 = Misc.MyBase.NULL_VALUE; if (Groups[0].ForwDatas.Count > 0) { ad0 = Groups[0].ForwDatas[grid]; ad2 = Groups[0].BackwDatas[grid]; } if (Groups[1].ForwDatas.Count > 0) { ad1 = Groups[1].ForwDatas[grid]; ad3 = Groups[1].BackwDatas[grid]; } if (Misc.MyBase.ISVALIDATA(ad0) && Misc.MyBase.ISVALIDATA(ad2)) ad0 = (ad0 + ad2) / 2; else if (Misc.MyBase.ISVALIDATA(ad2)) ad0 = ad2; if (Misc.MyBase.ISVALIDATA(ad1) && Misc.MyBase.ISVALIDATA(ad3)) ad1 = (ad1 + ad3) / 2; else if (Misc.MyBase.ISVALIDATA(ad3)) ad1 = ad3; } //TODO double x, p0, p1; if (Misc.MyBase.ISVALIDATA(ad0) && Misc.MyBase.ISVALIDATA(ad1)) { // ad0_avg 与 ad1_avg 偏差必须 40%以上 double d = (double)Math.Abs(ad0_avg - ad1_avg) / (ad0_avg + ad1_avg); if (d < 0.2) { //异常 x = (double)ad0_avg / ad0; ad = (int)(x * ad); } else { p0 = (double)ad0_avg / ad0; p1 = (double)ad1_avg / ad1; x = (p0 - p1) * (ad - ad1_avg) / (ad0_avg - ad1_avg) + p1; ad = (int)(x * ad); } } else if (Misc.MyBase.ISVALIDATA(ad0)) { x = (double)ad0_avg / ad0; ad = (int)(x * ad); } else if (Misc.MyBase.ISVALIDATA(ad1)) { x = (double)ad1_avg / ad1; ad = (int)(x * ad); } return ad; } public bool Load() { if(!LoadCSV()) return Misc.SaveToXmlHepler.Load("scancorr.xml", this); return true; } public void Save() { //Misc.SaveToXmlHepler.Save("scancorr.xml", this); SaveCSV(); } void SaveCSV() { try { string filepath = param_path;// "scancorr.csv"; using (StreamWriter sw = new StreamWriter(filepath, false, Encoding.GetEncoding("GB2312"))) { sw.WriteLine("Enable" + "," + Enable.ToString()); sw.WriteLine("ScanTimer" + "," + ScanTimer.ToString()); sw.WriteLine("SmoothFactor" + "," + SmoothFactor.ToString()); sw.WriteLine("PosOfGrid" + "," + PosOfGrid.ToString()); sw.WriteLine("PosLen" + "," + PosLen.ToString()); sw.WriteLine(); int posOfGrid = PosOfGrid; int gridcnt = PosLen / PosOfGrid; //标题 StringBuilder sb_header = new StringBuilder(); sb_header.Append("position"); sb_header.Append(",Group0_forw"); sb_header.Append(",Group0_backw"); sb_header.Append(",Group1_forw"); sb_header.Append(",Group1_backw"); sw.WriteLine(sb_header.ToString()); for (int j = 0; j < gridcnt; j++) { StringBuilder sb = new StringBuilder(); sb.Append((j * posOfGrid).ToString()); sb.Append(","); if (j < Group0.ForwDatas.Count()) { int ad = Group0.ForwDatas[j]; if (Misc.MyBase.ISVALIDATA(ad)) sb.Append(ad.ToString()); } sb.Append(","); if (j < Group0.BackwDatas.Count()) { int ad = Group0.BackwDatas[j]; if (Misc.MyBase.ISVALIDATA(ad)) sb.Append(ad.ToString()); } sb.Append(","); if (j < Group1.ForwDatas.Count()) { int ad = Group1.ForwDatas[j]; if (Misc.MyBase.ISVALIDATA(ad)) sb.Append(ad.ToString()); } sb.Append(","); if (j < Group1.BackwDatas.Count()) { int ad = Group1.BackwDatas[j]; if (Misc.MyBase.ISVALIDATA(ad)) sb.Append(ad.ToString()); } sw.WriteLine(sb.ToString()); } sw.Flush(); sw.Close(); } } catch { } } bool LoadCSV() { string filepath = param_path;// "scancorr.csv"; try { bool keyvalue_state = true;//键值对模式 using (StreamReader sw = new StreamReader(filepath, Encoding.GetEncoding("GB2312"))) { while (!sw.EndOfStream) { string item; item = sw.ReadLine(); string[] items = item.Split(','); if (keyvalue_state) { if (items.Count() >= 2) { if (items[0].StartsWith("Enable")) { bool b; if (bool.TryParse(items[1], out b)) Enable = b; else return false; } else if (items[0].StartsWith("ScanTimer")) { int i; if (int.TryParse(items[1], out i)) ScanTimer = i; else return false; } else if (items[0].StartsWith("SmoothFactor")) { int i; if (int.TryParse(items[1], out i)) SmoothFactor = i; else return false; } else if (items[0].StartsWith("PosOfGrid")) { int i; if (int.TryParse(items[1], out i)) PosOfGrid = i; else return false; } else if (items[0].StartsWith("PosLen")) { int i; if (int.TryParse(items[1], out i)) PosLen = i; else return false; } else if (items[0].StartsWith("position")) { keyvalue_state = false;//正文 //标题,忽略 Group0.AvgAD = Misc.MyBase.NULL_VALUE; Group0.ForwDatas.Clear(); Group0.BackwDatas.Clear(); Group1.AvgAD = Misc.MyBase.NULL_VALUE; Group1.ForwDatas.Clear(); Group1.BackwDatas.Clear(); } } } else { //正文 if (items.Count() == 0) { //没数据了 return true; } for (int i = 1; i < 5; i++) { if (i >= items.Count()) break; int ad; if (string.IsNullOrEmpty(items[i])) ad = Misc.MyBase.NULL_VALUE; else { if (!int.TryParse(items[i], out ad)) ad = Misc.MyBase.NULL_VALUE; } switch (i) { case 1: Group0.ForwDatas.Add(ad); break; case 2: Group0.BackwDatas.Add(ad); break; case 3: Group1.ForwDatas.Add(ad); break; case 4: Group1.BackwDatas.Add(ad); break; } } } } } } catch { return false; } return true; } public string[] GetSavePropertyNames() { return new string[] { "Enable", "ScanTimer" , "SmoothFactor", "PosOfGrid", "PosLen", "Group0", "Group1" }; } } public class ScanCorrGroup : IScanCorrGroup, Misc.ISaveToXml { private int _avgad = Misc.MyBase.NULL_VALUE; /// <summary> /// 平均AD值 /// </summary> public int AvgAD { get { return _avgad; } set { _avgad = value; NotifyPropertyChanged("AvgAD"); } } private List<int> forwdatas = new List<int>(); /// <summary> /// 正方向机架AD值数据, grid数据 /// </summary> public List<int> ForwDatas { get { return forwdatas; } } private List<int> backwdatas = new List<int>(); /// <summary> /// 正方向机架AD值数据, grid数据 /// </summary> public List<int> BackwDatas { get { return backwdatas; } } public ScanCorrGroup() { Clear(); } public void Clear() { AvgAD = Misc.MyBase.NULL_VALUE; ForwDatas.Clear(); BackwDatas.Clear(); NotifyPropertyChanged("ForwDatas"); NotifyPropertyChanged("BackwDatas"); } /// <summary> /// 必须保证 f_ad, 与 b_ad 长度一致!!! /// </summary> /// <param name="avgad"></param> /// <param name="f_ad"></param> /// <param name="b_ad"></param> public void Make(int[] f_ad, int[] b_ad) { Clear(); ForwDatas.AddRange(f_ad); BackwDatas.AddRange(b_ad); NotifyPropertyChanged("ForwDatas"); NotifyPropertyChanged("BackwDatas"); } public void CalAvg(int begin, int end) { if ((ForwDatas.Count() == 0) || (BackwDatas.Count() == 0)) return;//失败,没数据 if (begin < 0) begin = 0; if (end >= ForwDatas.Count()) end = ForwDatas.Count() - 1; int sum=0; int cnt = 0; for (int i = begin; i <= end; i++) { if (Misc.MyBase.ISVALIDATA(ForwDatas[i])) { sum += ForwDatas[i]; cnt++; } if (Misc.MyBase.ISVALIDATA(BackwDatas[i])) { sum += BackwDatas[i]; cnt++; } } if (cnt > 0) AvgAD = sum / cnt; else AvgAD = Misc.MyBase.NULL_VALUE; } void Smooth(int smoothfactor, List<int> corr) { int[] result = new int[corr.Count()]; for (int i = 0; i < corr.Count(); i++) { int begin = i - smoothfactor; int end = i + smoothfactor; if (begin < 0) begin = 0; if (end >= corr.Count()) end = corr.Count() - 1; double sum = 0; int cnt = 0; for (int j = begin; j <= end; j++) { if (Misc.MyBase.ISVALIDATA(corr[j])) { sum += corr[j]; cnt++; } } if (cnt > 0) result[i] = (int)(sum / cnt); else result[i] = Misc.MyBase.NULL_VALUE; } for (int i = 0; i < corr.Count(); i++) { corr[i] = result[i]; } } /// <summary> /// 平滑处理, 中值滤波 /// </summary> /// <param name="smoothfactor"> 平均滤波的个数=smoothfactor*2+1</param> public void Smooth(int smoothfactor) { if (smoothfactor <= 0) return; Smooth(smoothfactor, ForwDatas); Smooth(smoothfactor, BackwDatas); NotifyPropertyChanged("ForwDatas"); NotifyPropertyChanged("BackwDatas"); } #region INotifyPropertyChanged 成员 protected void NotifyPropertyChanged(string propertyName) { if (this.PropertyChanged != null) this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName)); } public event PropertyChangedEventHandler PropertyChanged; #endregion public string[] GetSavePropertyNames() { return new string[]{ "AvgAD","ForwDatas","BackwDatas"}; } } }