/// <summary> /// 格式化输出的头部。若启用 删除观测值为 0 的数据。 则需要缓存。 /// </summary> /// <param name="OldHeader"></param> /// <returns></returns> private RinexObsFileHeader BuildOutputHeader(RinexObsFileHeader OldHeader) { RinexObsFileHeader newHeader = (RinexObsFileHeader)OldHeader.Clone(); //输出版本 if (Option.IsEnableRinexVertion) { newHeader.Version = this.Option.Version; log.Info("输出版本:" + Option.Version); } if (Option.IsUseFileNameAsSiteName) { newHeader.SiteInfo.SiteName = Gdp.Utils.StringUtil.SubString(newHeader.FileName.ToUpper(), 0, Option.SiteNameLength.Value); } if (Option.SiteNameLength.Enabled) { newHeader.SiteInfo.SiteName = Gdp.Utils.StringUtil.SubString(newHeader.SiteInfo.SiteName, 0, Option.SiteNameLength.Value); } if (Option.IsUpperSiteName) { newHeader.SiteInfo.SiteName = newHeader.SiteInfo.SiteName.ToUpper(); } //采用间隔 if (Option.IsEnableInterval) { newHeader.Interval = Option.Interval; log.Info("指定的采样率:" + Option.Interval); } //是否启用卫星系统过滤, 为修改 header.ObsCodes,不仅如此,内容也要及时删除,以免多余劳动 if (Option.IsEnableSatelliteTypes) { newHeader.RemoveOther(Option.SatelliteTypes); log.Info("将移除非此系统:" + Gdp.Utils.StringUtil.ToString(Option.SatelliteTypes)); } //移除对于无电离层组合多余的观测量 if (Option.IsRemoveRedundantObsForIonoFree) { newHeader.IsRemoveRedundantObsForIonoFree(); log.Info("移除对于双频无电离层组合多余的观测值"); } //删除观测值为 0 的数据。 if (Option.IsEnableMinObsCodeAppearRatio) { //缓存 var tables = BuildObsCodeTables(newHeader.ObsCodes); //采用新头部的 var ratios = GetObsCodeRatios(tables); //出现率低于 x 的代码 var minRatio = Option.MinObsCodeAppearRatio; this.ObsCodesToBeRemove = new Dictionary <SatelliteType, List <string> >(); var ObsCodes = new Dictionary <SatelliteType, List <string> >(); foreach (var kv in ratios) { List <string> okCodes = new List <string>(); List <string> badCodes = new List <string>(); foreach (var item in kv.Value) { if (item.Value > minRatio) { okCodes.Add(item.Key); } else { badCodes.Add(item.Key); } if (item.Value != 1) { log.Info(FileName + " " + kv.Key + " " + item.Key + " 出勤率 " + item.Value); } } ObsCodes.Add(kv.Key, okCodes); ObsCodesToBeRemove.Add(kv.Key, badCodes); } newHeader.ObsCodes = ObsCodes; } //删除其它观测码 if (Option.IsReomveOtherCodes) { foreach (var collection in newHeader.ObsCodes) { List <string> tobeRemoves = new List <string>(); foreach (var item in collection.Value) { if (!Option.OnlyCodes.Contains(item)) { tobeRemoves.Add(item); } } foreach (var item in tobeRemoves) { collection.Value.Remove(item); } } log.Info("将移除非此观测码:" + Gdp.Utils.StringUtil.ToString(Option.ObsCodes)); } if (Option.IsEnableObsTypes) { newHeader.RemoveOther(Option.ObsTypes); } //删除观测频率 if (Option.IsEnableRemoveIndicatedFrequence) { foreach (var collection in newHeader.ObsCodes) { List <string> tobeRemoves = new List <string>(); foreach (var item in collection.Value) { foreach (var freqNum in Option.FrequenceNumToBeRemoved) { if (item.Contains(freqNum.ToString())) { tobeRemoves.Add(item); break; } } } foreach (var item in tobeRemoves) { collection.Value.Remove(item); } } log.Info("将移除频率:" + Gdp.Utils.StringUtil.ToString(Option.FrequenceNumToBeRemoved)); } return(newHeader); }
/// <summary> /// 格式化输出的头部。 /// </summary> /// <param name="OldHeader"></param> /// <returns></returns> private RinexObsFileHeader BuildOutputHeader(RinexObsFileHeader OldHeader) { RinexObsFileHeader newHeader = (RinexObsFileHeader)OldHeader.Clone(); //输出版本 if (Option.IsEnableRinexVertion) { newHeader.Version = this.Option.Version; log.Info("输出版本:" + Option.Version); } //采用间隔 if (Option.IsEnableInterval) { newHeader.Interval = Option.Interval; log.Info("指定的采样率:" + Option.Interval); } //是否启用卫星系统过滤, 为修改 header.ObsCodes,不仅如此,内容也要及时删除,以免多余劳动 if (Option.IsEnableSatelliteTypes) { newHeader.RemoveOther(Option.SatelliteTypes); log.Info("将移除非此系统:" + Geo.Utils.StringUtil.ToString(Option.SatelliteTypes)); } //观测类型过滤 if (Option.IsEnableObsTypes) { newHeader.RemoveOther(Option.ObsTypes); log.Info("将移除非此观测值:" + Geo.Utils.StringUtil.ToString(Option.ObsTypes)); } //删除观测值为 0 的数据。 if (Option.IsEnableMinObsCodeAppearRatio) { //缓存 var tables = BuildObsCodeTables(newHeader.ObsCodes); //采用新头部的 var ratios = GetObsCodeRatios(tables); //出现率低于 x 的代码 var minRatio = Option.MinObsCodeAppearRatio; this.ObsCodesToBeRemove = new Dictionary <SatelliteType, List <string> >(); var ObsCodes = new Dictionary <SatelliteType, List <string> >(); foreach (var kv in ratios) { List <string> okCodes = new List <string>(); List <string> badCodes = new List <string>(); foreach (var item in kv.Value) { if (item.Value > minRatio) { okCodes.Add(item.Key); } else { badCodes.Add(item.Key); } if (item.Value != 1) { log.Info(FileName + " " + kv.Key + " " + item.Key + " 出勤率 " + item.Value); } } ObsCodes.Add(kv.Key, okCodes); ObsCodesToBeRemove.Add(kv.Key, badCodes); } newHeader.ObsCodes = ObsCodes; } //删除其它观测码 if (Option.IsReomveOtherCodes) { foreach (var collection in newHeader.ObsCodes) { List <string> tobeRemoves = new List <string>(); foreach (var item in collection.Value) { if (!Option.OnlyCodes.Contains(item)) { tobeRemoves.Add(item); } } foreach (var item in tobeRemoves) { collection.Value.Remove(item); } } log.Info("将移除非此观测码:" + Geo.Utils.StringUtil.ToString(Option.ObsCodes)); } return(newHeader); }
/// <summary> /// 数据刚刚进入,立即执行,最优先的执行,初探 /// </summary> /// <param name="current"></param> public override void RawRevise(RinexEpochObservation current) { //时段过滤 if (Option.IsEnableTimePeriod) { if (!Option.TimePeriod.Contains(current.ReceiverTime)) { current.Clear(); return; } } //采样率时间赋值 if (this.CurrentIndex == 0 || this.CurrentIndex == -1) { this.CurrentIndex = 1; InitSeconds = current.ReceiverTime.DateTime.TimeOfDay.TotalSeconds; if (Option.IsEnableInterval && Option.Interval > 1 && InitSeconds % 5 != 0) // 若非0, 5秒整数倍的采样间隔,则强制采用10秒整数倍间隔 { InitSeconds = 0; } } //采样间隔过滤 if (Option.IsEnableInterval) { //首先考虑采样率大于1s var diff = Math.Round(current.ReceiverTime.DateTime.TimeOfDay.TotalSeconds - InitSeconds) % Option.Interval; if (diff > 0.5 && Option.Interval > 1)//相差0.5s,认为是同一个历元 { current.Clear(); return; } //采样率太小,直接过滤 if (current.ReceiverTime - PrevOkEpoch < Option.Interval) { current.Clear(); return; } //10s 以上的整数必须为10倍的整数秒,如 30s采样率,只能出现 00 和 30 秒 if (Option.Interval >= 10 && Option.Interval <= 30 && current.ReceiverTime.Seconds % Option.Interval > 1) { current.Clear(); return; } } //移除其它系统 if (Option.IsEnableSatelliteTypes) { current.RemoveOther(Option.SatelliteTypes); } //观测类型过滤凭借第一字母判断,此处过滤可以加快速度,避免多余计算 if (Option.IsEnableObsTypes) { current.RemoveOthers(Option.ObsTypes); } //删除观测频率 if (Option.IsEnableRemoveIndicatedFrequence) { current.RemoveFrequences(Option.FrequenceNumToBeRemoved); // log.Info("除频率:" + Geo.Utils.StringUtil.ToString(Option.FrequenceNumToBeRemoved)); } //移除不能组成电离层组合的卫星 if (Option.IsRemoveIonoFreeUnavaliable) { List <RinexSatObsData> list = new List <RinexSatObsData>(); foreach (var sat in current) { if (!sat.IsIonoFreeCombinationAvaliable) { list.Add(sat); } } foreach (var item in list) { current.Remove(item.Prn); } } //移除卫星中对于双频无电离层组合多余的观测值 if (Option.IsRemoveRedundantObsForIonoFree) { foreach (var sat in current) { sat.RemoveRedundantObsForIonoFree(); } } //观测码数量不足的移除 if (ObsCodesToBeRemove != null && ObsCodesToBeRemove.Count > 0) { foreach (var sat in current) { if (!ObsCodesToBeRemove.ContainsKey(sat.Prn.SatelliteType)) { continue; } var codes = this.ObsCodesToBeRemove[sat.Prn.SatelliteType]; foreach (var item in codes) { sat.Remove(item); } } } //移除指定卫星 if (Option.IsEnableRemoveSats && Option.SatsToBeRemoved != null && Option.SatsToBeRemoved.Count > 0) { current.Remove(Option.SatsToBeRemoved); } //卫星高度角过滤 if (Option.SatCutOffAngle.Enabled && !XYZ.IsZeroOrEmpty(OldHeader.ApproxXyz)) { //如果星历范围不包括,则不做更改 if (EphemerisService.TimePeriod.Contains(current.ReceiverTime)) { List <RinexSatObsData> list = new List <RinexSatObsData>(); foreach (var item in current) { var eph = EphemerisService.Get(item.Prn, current.ReceiverTime); Polar polar = null; if (eph != null) { polar = CoordTransformer.XyzToGeoPolar(eph.XYZ, OldHeader.ApproxXyz); } //移除了没有星历的卫星 if (polar == null || polar.Elevation < Option.SatCutOffAngle.Value) { list.Add(item); } } foreach (var item in list) { current.Remove(item.Prn); } } } //删除指定数据为空的卫星 if (Option.IsDeleteVacantSat) { List <SatelliteNumber> tobeDeletes = new List <SatelliteNumber>(); foreach (var sat in current) { foreach (var item in Option.NotVacantCodeList) { if (sat.TryGetValue(item) == 0) { tobeDeletes.Add(sat.Prn); } } } current.Remove(tobeDeletes); } base.RawRevise(current); //小时段过滤 if (Option.IsEnableMinEpochCount) { SmallObsPeriodRemover.Revise(ref current); } }
/// <summary> /// 处理过程 /// </summary> /// <param name="current"></param> public override void Process(RinexEpochObservation current) { if (this.CurrentIndex == 0) { InitSeconds = current.ReceiverTime.DateTime.TimeOfDay.TotalSeconds; if (Option.IsEnableInterval && Option.Interval > 1 && InitSeconds % 5 != 0) // 若非0, 5秒整数倍的采样间隔,则强制采用10秒整数倍间隔 { InitSeconds = 0; } //首次建立头文件,需要缓存支持 this.CurrentHeader = BuildOutputHeader(OldHeader); } //移除其它系统 if (Option.IsEnableSatelliteTypes) { current.RemoveOther(Option.SatelliteTypes); } //采样间隔 if (Option.IsEnableInterval) { //首先考虑采样率大于1s var diff = Math.Round(current.ReceiverTime.DateTime.TimeOfDay.TotalSeconds - InitSeconds) % Option.Interval; if (diff > 0.5 && Option.Interval > 1) { return; } else { int i = 0; } //采样率小于1s if (current.ReceiverTime - PrevOkEpoch < Option.Interval) { return; } } if (current.ReceiverTime >= new Time(2017, 8, 11, 23)) { int i = 0; } PrevOkEpoch = current.ReceiverTime; current.Header = this.CurrentHeader; //时段过滤 if (Option.IsEnableTimePeriod) { if (!Option.TimePeriod.Contains(current.ReceiverTime)) { return; } } if (Option.IsEnableRemoveSats && Option.SatsToBeRemoved != null && Option.SatsToBeRemoved.Count > 0) { current.Remove(Option.SatsToBeRemoved); } //删除指定数据为空的卫星 if (Option.IsDeleteVacantSat) { List <SatelliteNumber> tobeDeletes = new List <SatelliteNumber>(); foreach (var sat in current) { if (sat.Prn == SatelliteNumber.Parse("G15")) { int ii = 0; } foreach (var item in Option.NotVacantCodeList) { if (sat.TryGetValue(item) == 0) { tobeDeletes.Add(sat.Prn); } } } current.Remove(tobeDeletes); } //移除观测值为 0 的 if (Option.IsRemoveZeroPhaseSat) { List <SatelliteNumber> tobeDeletes = new List <SatelliteNumber>(); foreach (var sat in current) { foreach (var item in CurrentHeader.ObsCodes) { if (sat.Prn.SatelliteType == item.Key) { foreach (var code in item.Value) { if (code.StartsWith("L") && sat.TryGetValue(code) == 0) { tobeDeletes.Add(sat.Prn); } } } } } current.Remove(tobeDeletes); } //移除观测值为 0 的 if (Option.IsRemoveZeroRangeSat) { List <SatelliteNumber> tobeDeletes = new List <SatelliteNumber>(); foreach (var sat in current) { foreach (var item in CurrentHeader.ObsCodes) { if (sat.Prn.SatelliteType == item.Key) { foreach (var code in item.Value) { if ((code.StartsWith("C") || code.StartsWith("P")) && sat.TryGetValue(code) == 0) { tobeDeletes.Add(sat.Prn); } } } } } current.Remove(tobeDeletes); } //是否启用卫星系统过滤,此处多余,只需在头部判断即可。 //if(Option.IsEnableSatelliteTypes){ // current.RemoveOthers(Option.SatelliteTypes); //} ////观测类型过滤凭借第一字母判断 //if (Option.IsEnableObsTypes) //{ // current.RemoveOthers(Option.ObsTypes); //} //观测码数量不足的移除 if (ObsCodesToBeRemove != null && ObsCodesToBeRemove.Count > 0) { foreach (var sat in current) { if (!ObsCodesToBeRemove.ContainsKey(sat.Prn.SatelliteType)) { continue; } var codes = this.ObsCodesToBeRemove[sat.Prn.SatelliteType]; foreach (var item in codes) { sat.Remove(item); } } } if (Option.SatCutOffAngle.Enabled && !XYZ.IsZeroOrEmpty(CurrentHeader.ApproxXyz)) { List <RinexSatObsData> list = new List <RinexSatObsData>(); foreach (var item in current) { var eph = GlobalNavEphemerisService.Instance.Get(item.Prn, current.ReceiverTime); var angle = CoordTransformer.XyzToGeoPolar(eph.XYZ, CurrentHeader.ApproxXyz); if (angle.Elevation < Option.SatCutOffAngle.Value) { list.Add(item); } } foreach (var item in list) { current.Remove(item.Prn); } } if (Option.IsConvertPhaseToLength) { foreach (var item in current) { if (item.Prn.SatelliteType == SatelliteType.G) { foreach (var val in item) { if (val.Key.Contains("L1")) { val.Value.Value = val.Value.Value * Frequence.GpsL1.WaveLength; } if (val.Key.Contains("L2")) { val.Value.Value = val.Value.Value * Frequence.GpsL2.WaveLength; } } } } } //判断并写入文件 WriteToFile(current); }