diff --git a/Convert_chart.jpg b/Convert_chart.jpg deleted file mode 100644 index 7bae4a4..0000000 Binary files a/Convert_chart.jpg and /dev/null differ diff --git a/KNZ_Convert.py b/KNZ_Convert.py index 1bc6636..abec264 100644 --- a/KNZ_Convert.py +++ b/KNZ_Convert.py @@ -1,17 +1,17 @@ -# @ File : KNZ_Convert.py +# @ File : KNZ_Convert.py +# +# @ Brief : GUI main functions. # # Copyright (c) 2024 - 2024 KenanZhu. All Right Reserved. # # @ Author : KenanZhu # @ Time : 2024/11/13 -# @ Brief : -# : # @ IDE : PyCharm # # ---------------------------------------------------------------------------------------- -# ---SELF--- # +# ---SELPORT--- # import rnx_convert as conv -# ---THRI--- # +# ---STDPORT--- # import queue import threading import tkinter as tk @@ -20,17 +20,18 @@ from tkinter import ttk from PIL import ImageTk from base64 import b64decode from tkinter import filedialog -# --------------------------------------------------------------------------------------- +# ------------- # +# global const InPaths = [] -# +# io oath combox index I_Box_Counter=0 O_Box_Counter=0 -# +# io format list & index I_Format_Rnx_List=0 I_RINEX_BoxList=['2','3'] O_Format_Rnx_List=0 O_RINEX_BoxList=['2.10','2.11','2.12','3.00','3.01','3.02','3.03','3.04','3.05'] -# --------------------------------------------------------------------------------------- +# ------------------------------------------------------------------------------------- # def instanceOPT(parenthwnd, func): OPTIONS(parenthwnd, func) @@ -143,14 +144,8 @@ class CALLBACK: return filedir path_len -= 1 - def Convert( - self, - Pro_style, - File_O_ynVar, - File_I_BoxVar, - File_O_BoxVar, - Convertcards, - Exec_Progress): + def Convert(self, + Pro_style, File_O_ynVar, File_I_BoxVar, File_O_BoxVar, Convertcards, Exec_Progress): # ------------------------------------------------------------------------------- # > # Method: @@ -168,7 +163,7 @@ class CALLBACK: 'text.Horizontal.TProgressbar', text='Converting...') Exec_Progress.config(value=0) - if Convertcards.index('current')==0: + if Convertcards.index('current')==0: if not File_I_BoxVar.get(): ErrorMsg+=' path' else: InPath.append(File_I_BoxVar.get()) elif Convertcards.index('current')==1: @@ -183,7 +178,7 @@ class CALLBACK: Exec_Progress.config(value=0) Pro_style.configure('text.Horizontal.TProgressbar', text=ErrorMsg) return - ### + # resqueue=queue.Queue() Pro_style.configure( 'text.Horizontal.TProgressbar', @@ -211,24 +206,11 @@ class CALLBACK: 'text.Horizontal.TProgressbar', text='Complete ! %d successful. %d fails.'%(State_O, len(InPath)-State_O)) - def _Convert( - self, - Pro_style, - File_O_ynVar, - File_I_BoxVar, - File_O_BoxVar, - Convertcards, - Exec_Progress): + def _Convert(self, + Pro_style, File_O_ynVar, File_I_BoxVar, File_O_BoxVar, Convertcards, Exec_Progress): T=threading.Thread(target=lambda : - self.Convert( - Pro_style, - File_O_ynVar, - File_I_BoxVar, - File_O_BoxVar, - Convertcards, - Exec_Progress - )) + self.Convert(Pro_style, File_O_ynVar, File_I_BoxVar, File_O_BoxVar, Convertcards, Exec_Progress)) T.start() @staticmethod @@ -294,9 +276,10 @@ class MAINGUI: # Author: @KenanZhu All Right Reserved. # ------------------------------------------------------------------------------- self.hwnd.title("KNZ_Convert") - self.hwnd.resizable(0, 0) self.func.Move_center(self.hwnd, 400, 243) - ### + self.hwnd.maxsize( 1000, 243) + self.hwnd.minsize( 400, 243) + # icon_ico = (b'AAABAAEAICAAAAEAIACoEAAAFgAAACgAAAAgAAAAQAAAAAEAIAAAAAAAABAAADjsAAA47AAAAAAAAAAAAAAAAAAAAAAAAAAAA' b'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' b'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' @@ -359,11 +342,11 @@ class MAINGUI: icon_ico = b64decode(icon_ico) icon_ico = ImageTk.PhotoImage(data=icon_ico) self.hwnd.tk.call('wm', 'iconphoto', self.hwnd._w, icon_ico) - ### + # self.initCONVERT() - ### + # self.initExecCtrl() - ### + # self.hwnd.protocol('WM_DELETE_WINDOW',self.hwnd.quit) self.hwnd.mainloop() @@ -394,22 +377,22 @@ class MAINGUI: # ------------------------------------------------------------------------------- self.SingleFrame=ttk.Frame(self.hwnd) - ### Initialize of input frame + # Initialize of input frame File_I_Frame=tk.LabelFrame( self.SingleFrame, text='Object Observation of RINEX') File_I_Frame.pack(side=tk.TOP, fill=tk.X, padx='1px', pady='0px') - ### Initialize of input box + # Initialize of input box File_I_Box=ttk.Combobox( File_I_Frame, width=47, height=4, values=('',), textvariable=self.File_I_BoxVar) - File_I_Box.pack(side=tk.LEFT, anchor='w', padx='1px', pady='1px') + File_I_Box.pack(side=tk.LEFT, fill=tk.X, expand=tk.YES, anchor='w', padx='1px', pady='1px') - ### Initialize of input Button + # Initialize of input Button File_I_Bbutton=ttk.Button( File_I_Frame, text='...', @@ -426,17 +409,17 @@ class MAINGUI: # ------------------------------------------------------------------------------- self.BatchFrame=ttk.Frame(self.hwnd) - ### + # Files_I_Frame=tk.LabelFrame( self.BatchFrame, text='Objects Observation of RINEX') Files_I_Frame.pack(side=tk.TOP, fill=tk.X, padx='1px', pady='0px') - ### + # Files_I_CtrlFrame=ttk.Frame(Files_I_Frame) Files_I_CtrlFrame.pack(side=tk.RIGHT, fill=tk.Y, anchor='e', padx='1px', pady='1px') - ### + # Files_I_CtrlInput=ttk.Button( Files_I_CtrlFrame, text='...', @@ -451,23 +434,23 @@ class MAINGUI: command=lambda :self.func.Clear_I_Files(Files_I_ShowText)) Files_I_CtrlClear.pack(side=tk.BOTTOM, anchor='e', padx='1px', pady='1px') - ### + # Files_I_ShowFrame=ttk.Frame(Files_I_Frame) - Files_I_ShowFrame.pack(side=tk.LEFT, fill=tk.X, anchor='e', padx='1px', pady='1px') + Files_I_ShowFrame.pack(side=tk.LEFT, fill=tk.X, expand=tk.YES, anchor='e', padx='1px', pady='1px') - ### + # ScrollbarX=ttk.Scrollbar(Files_I_ShowFrame,orient=tk.HORIZONTAL) ScrollbarX.pack(side=tk.BOTTOM, fill=tk.X) ScrollbarY=ttk.Scrollbar(Files_I_ShowFrame) ScrollbarY.pack(side=tk.RIGHT, fill=tk.Y) - ### + # Files_I_ShowText=tk.Text( Files_I_ShowFrame, xscrollcommand=ScrollbarX.set, yscrollcommand=ScrollbarY.set, height=4, wrap='none', font=('Segoe UI',9)) - Files_I_ShowText.pack(side=tk.LEFT, fill=tk.BOTH, anchor='w', padx='1px', pady='1px') + Files_I_ShowText.pack(side=tk.LEFT, fill=tk.X, expand=tk.YES, anchor='w', padx='1px', pady='1px') ScrollbarX.config(command=Files_I_ShowText.xview) ScrollbarY.config(command=Files_I_ShowText.yview) @@ -500,7 +483,7 @@ class MAINGUI: text='Output directory') File_O_Frame.pack(side=tk.TOP, fill=tk.X, padx='1px', pady='1px') - ### + # File_O_yn=ttk.Checkbutton( File_O_Frame, text='Directory', @@ -513,7 +496,7 @@ class MAINGUI: File_O_Button)) File_O_yn.pack(side=tk.LEFT, anchor='w', padx='1px', pady='0px') - ### + # File_O_Box=ttk.Combobox( File_O_Frame, width=36, @@ -521,9 +504,9 @@ class MAINGUI: values=('',), state=tk.DISABLED, textvariable=self.File_O_BoxVar) - File_O_Box.pack(side=tk.LEFT, anchor='w', padx='1px', pady='0px') + File_O_Box.pack(side=tk.LEFT, fill=tk.X, expand=tk.YES, anchor='w', padx='1px', pady='0px') - ### + # File_O_Button=ttk.Button( File_O_Frame, text='...', @@ -548,7 +531,7 @@ class MAINGUI: command=lambda :instanceOPT(self.hwnd,self.func) ) Conv_Option.pack(side=tk.RIGHT, padx='1px', pady='0px') - ### + # Conv_Button=ttk.Button( CtrlButtonFrame, text='Convert', @@ -561,7 +544,7 @@ class MAINGUI: self.Convertcards, self.Exec_Progress)) Conv_Button.pack(side=tk.RIGHT, padx='1px', pady='0px') - ### + # Exit_button=ttk.Button( CtrlButtonFrame, text='Exit', @@ -569,7 +552,7 @@ class MAINGUI: command=self.hwnd.quit) Exit_button.pack(side=tk.LEFT, padx='1px', pady='0px') - ### + # StateFrame=ttk.Frame(self.ExecFrame) StateFrame.pack(side=tk.TOP, fill=tk.X, padx='1px', pady='4px') self.Pro_style=ttk.Style(StateFrame) @@ -595,7 +578,8 @@ class MAINGUI: maximum=100, mode='determinate', style='text.Horizontal.TProgressbar') - self.Exec_Progress.pack(side=tk.LEFT) + self.Exec_Progress.pack(side=tk.LEFT, fill=tk.X, expand=tk.YES) + class OPTIONS: def __init__(self, parenthwnd, func): @@ -625,7 +609,7 @@ class OPTIONS: self.opthwnd.resizable(0, 0) self.func.Move_center(self.opthwnd, 310, 110) - ### Set icon + # Set icon icon_ico=(b'AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' b'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' b'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOrq6v/q6ur/6urq/+rq6v/q6ur/6urq/+rq6v/q6ur/6' @@ -646,11 +630,11 @@ class OPTIONS: icon_ico=ImageTk.PhotoImage(data=icon_ico) self.opthwnd.tk.call('wm', 'iconphoto', self.opthwnd._w, icon_ico) - ### Mian frame + # Mian frame self.MainFrame=ttk.Frame(self.opthwnd) self.MainFrame.pack() - ### init + # init self.initOPTIONS() self.initEXECTRL() @@ -702,7 +686,7 @@ class OPTIONS: state=tk.DISABLED, values=I_RTCM_BoxList) I_RTCM_Box.set(I_RTCM_BoxList[0]) - #I_RTCM_Box['state']='readonly' + # I_RTCM_Box['state']='readonly' I_RTCM_Box.pack(side=tk.RIGHT) # ------------------------------------------------------------------------------- # Target format frame @@ -743,7 +727,7 @@ class OPTIONS: state=tk.DISABLED, values=O_RTCM_BoxList) O_RTCM_Box.set(I_RTCM_BoxList[0]) - #O_RTCM_Box['state']='readonly' + # O_RTCM_Box['state']='readonly' O_RTCM_Box.pack(side=tk.RIGHT) def initEXECTRL(self): @@ -782,6 +766,8 @@ class OPTIONS: I_Format_Rnx_List=I_RINEX_BoxList.index(self.I_RINEX_Box.get()) O_Format_Rnx_List=O_RINEX_BoxList.index(self.O_RINEX_Box.get()) + +# Main program entry ---------------------------- # if __name__ == "__main__": root=tk.Tk() call=CALLBACK() diff --git a/Readme.md b/Readme.md index 06d7982..21025c7 100644 --- a/Readme.md +++ b/Readme.md @@ -18,9 +18,7 @@ the file is lossless conversion, only convert the foemat, do not modify the information. 2. The double character observation types of RINEX2.xx version will be automatically matched according to the following table: -[Convert_chart.jpg](Convert_chart.jpg) - -### About Project ### +### Update brief ### 2024/11/14: At present, the RINEX2.xx format conversion has been fully supported, the format output error of the previous version has been modified, and the conversion from 2.xx to 3.xx is currently supported. @@ -28,6 +26,9 @@ and the conversion from 2.xx to 3.xx is currently supported. 2024/11/15: Correct the output format, omit the empty observation and change the rule of match. +2024/11/17: Fully support the conversion of RINEX 2.xx & RINEX 3.xx, also support +the conversion of same major version. + ### Update plan ### 1. 2.xx and 3.xx versions are fully supported, and support mutual conversion. 2. Gradually introduce the conversion support for RTCM files. diff --git a/ReadmeCN.md b/ReadmeCN.md index c2704fd..27555d7 100644 --- a/ReadmeCN.md +++ b/ReadmeCN.md @@ -14,11 +14,10 @@ 1. 主要对2.11 & 2.10 格式的RINEX观测值文件进行无损转换,不需要额外参数输入,软件会自动转换格式,不会对原文件信息进行更改。 2. 对于RINEX2.xx版本的两字符观测值类型将按照如下表格进行自动匹配: -[Convert_chart.jpg](Convert_chart.jpg) - -### 关于项目 ### +### 更新简记 ### 2024/11/14: 目前已经对RINEX2.xx格式转换进行了全面支持,修改了上一版本的格式输出错误,目前支持2.xx转换为3.xx。 2024/11/15: 更正了输出格式,忽略空余信号并更改匹配规则 +2024/11/17: 支持RINEX2.xx格式和RINEX3.xx格式的相互转换,同时支持同一主要版本之间的转换。 ### 更新计划 ### 1. 2.xx版本与3.xx版本全面支持,支持相互转换。 diff --git a/rnx_convert.py b/rnx_convert.py index 87f0e79..1fc1302 100644 --- a/rnx_convert.py +++ b/rnx_convert.py @@ -1,19 +1,28 @@ -# @ File : rnx_convert.py +# @ File : rnx_convert.py +# +# @ Brief : RINEX Convert functions. # # Copyright (c) 2024 - 2024 KenanZhu. All Right Reserved. # # @ Author : KenanZhu -# @ Time : 2024/11/13 -# @ Brief : +# @ Time stamp : [2024/11/13] First release. +# : [2024/11/14] Correct: convert of observation type of +# 'P1/P2' of GPS is correct into 'C1W/C2W'. +# : [2024/11/15] Fix bug: remove the empty observation of +# RINEX 2.xx format. +# : [2024/11/17] Add new: complish the funtions of convert +# form RINEX 3.xx to RINEX 2.xx and also support +# convert in major version of RINEX. # : -# @ IDE : PyCharm +# @ IDE/Editor : PyCharm / VisualStudio Code # # ---------------------------------------------------------------------------------------- +# ---STDPORT--- # import re import time import math import threading - +# ------------- # emp='' bnk=' ' @@ -21,9 +30,9 @@ bnk=' ' def conv_time(): # generate convert timestamp covpro='KNZ_Convert ver1.2.5' - covtmp='COV-PGM / DATE' + covcom='COMMENT' - # Get the locate time and transform to RINEX format + # Get the locate time and transform to Uni-format y=time.localtime().tm_year m=time.localtime().tm_mon d=time.localtime().tm_mday @@ -41,14 +50,12 @@ def conv_time(): outline=(covpro + 20*bnk + localtime+ - covtmp + + covcom + '\n') return outline - - -# Convert Format ------------------------------ # +# Convert data format --------------------------- # def datefmt2_conv(inline): hou=inline[49:51] min=inline[52:54] @@ -60,9 +67,7 @@ def datefmt2_conv(inline): bnk + "UTC" + bnk + "PGM / RUN BY / DATE\n") - - -# Convert Format ------------------------------ # +# Convert data format --------------------------- # def datefmt3_conv(inline): hou=inline[49:51] min=inline[51:53] @@ -70,17 +75,15 @@ def datefmt3_conv(inline): return (inline[0:49] + hou + ':' + min + ':' + - sec + ':' + + sec + 'UTCPGM / RUN BY / DATE\n') - - -# Convert observ type of RINEX 2.xx to Uni-Format --------------- # +# Convert observ type of RINEX 2.xx to Uni-format ------------- # def obsfmt2_conv(obstypes, sys): counter =0 obstypex=[] - obsbomit='' + obsbomit=emp match sys: case 'G': @@ -144,9 +147,7 @@ def obsfmt2_conv(obstypes, sys): return obstypex - - -# Convert observ msg of RINEX 2.xx to Uni-Format ---------------- # +# Convert observ msg of RINEX 2.xx to Uni-format ---------------- # def obstype2_conv(inline, in_f, omilist): # uni-format message label obsobs='SYS / # / OBS TYPES' @@ -182,14 +183,12 @@ def obstype2_conv(inline, in_f, omilist): outline=7*bnk return outlines - - -# Convert obstpe msg of RINEX 2.xx to Uni-Format --------------- # -def obstpe2_conv(inline, outlines, desver): +# Generate the convert stamp ------------------------ # +def conv_stamp(inline, outlines, desver): oriver=inline[ 5: 9] # generate convert stamp obscov='COV-OBSERVATION DATA' - covpro='COV-RINEX VER / TYPE' + obscom='COMMENT' outlines.append( 5*bnk+ oriver+ @@ -198,16 +197,14 @@ def obstpe2_conv(inline, outlines, desver): 1*bnk+ obscov+ 24*bnk+ - covpro+ + obscom+ '\n') outlines.append(conv_time()) outlines.append( inline.replace('%s'%re.search(r'[1-9]\d*.\d*|0\.\d*[1-9]\d*', inline).group(), desver)) return - - -# Convert head_data of RINEX 2.xx to Uni-format -------------- # +# Convert RINEX 2.xx(header) to Uni-format -------------- # def rnx2_head2uni(in_f, desver, outlines, omilist): # rinex message label obscom='COMMENT' @@ -221,11 +218,11 @@ def rnx2_head2uni(in_f, desver, outlines, omilist): while True: inline=in_f.readline() # file is aleady checked so no need to judge again - if not inline: pass + if not inline: break if inline.find(obscom)>=0: outlines.append(inline) elif inline.find(obspro)>=0: outlines.append(datefmt2_conv(inline)) elif inline.find(obsobs)>=0: outlines.extend(obstype2_conv(inline, in_f, omilist)) - elif inline.find(obstpe)>=0: obstpe2_conv(inline, outlines, desver) + elif inline.find(obstpe)>=0: conv_stamp(inline, outlines, desver) elif inline.find(obsl12)>=0: continue elif inline.find(obsend)>=0: break else : outlines.append(inline) @@ -235,9 +232,7 @@ def rnx2_head2uni(in_f, desver, outlines, omilist): return 1 - - -# Convert obs of RINEX 2.xx to Uni-Format ------------------- # +# Convert RINEX 2.xx(data) to Uni-Format ------------------- # def rnx2_data2uni(in_f, outlines, omilist, obsnum): sPRN=[] scounter=0 @@ -245,7 +240,7 @@ def rnx2_data2uni(in_f, outlines, omilist, obsnum): # return false when file end inline=in_f.readline() - if not inline : return False + if not inline: return False # get epoch message & flag state year = int(inline[0 :3]) @@ -310,17 +305,13 @@ def rnx2_data2uni(in_f, outlines, omilist, obsnum): outlines.append(sPRN[i]+outline+"\n") return True - - # Convert Uni-format to RINEX 3.xx --------------------- # def uni2rnx3_data(outlines, out_path): - out_f = open(out_path, 'a') + out_f=open(out_path, 'a') out_f.writelines(outlines) out_f.close() return - - # Get observ type need be omitted --------------------- # def getomit(omilist): for i in range(len(omilist)): @@ -333,36 +324,391 @@ def getomit(omilist): omilist.pop(0) return - - -# Convert data of RINEX 2.xx to Des-format ----------------- # +# Convert RINEX 2.xx to Des-format --------------------- # def rnx2des(in_path, out_path, oriver, desver): headread=False outlines=[] omilist=[] - # convert rinex 2.xx(header) to Uni-format + # convert RINEX 2.xx(header) to Uni-format in_f=open(in_path, 'r') match rnx2_head2uni(in_f, desver, outlines, omilist): case 1: headread=True case 0: headread=False - - uni2rnx3_data(outlines, out_path) - outlines=[] - if headread: + if headread: + # convert Uni-foramt(header) to Des-format + match desver[0:1]: + case '2': addemp=uni2rnx2_data(4, outlines, out_path, True, None) + case '3': uni2rnx3_data(outlines, out_path) + outlines=[] # get each observ type and omit the empty obsnum=omilist[0] omilist.pop(0) getomit(omilist) - + + # convert RINEX 2.xx(data) to Uni-format while rnx2_data2uni(in_f, outlines, omilist, obsnum): + # convert Uni-foramt(data) to Des-format match desver[0:1]: - case '2': return 0 + case '2': uni2rnx2_data(4, outlines, out_path, False, addemp) case '3': uni2rnx3_data(outlines, out_path) outlines=[] + + elif not headread: return 0 + + in_f.close() return 1 +# Get the position of new add observ type ----------------- # +def getaddemp(alltypes, sysstype): + addemp=[[],[],[],[]] + for i in range(len(sysstype)): + for j in range(len(sysstype[i])): + for k in range(len(alltypes)): + if sysstype[i][j]==alltypes[k]: + addemp[i].append(k) + return addemp +# Filter the same obs fmt in RINEX 2.xx ----------------- # +def obsfmt_filter(alltypes): + empemp=[] + spos=npos=0 + empemp.append(len(alltypes)) + while True: + npos+=1 + if spos==empemp[0]: break + if npos==empemp[0]: + spos+=1 + npos=spos + continue + if not alltypes[spos]: continue + if not alltypes[npos]: continue + if alltypes[spos]==alltypes[npos]: + alltypes[npos]=emp + empemp.append(npos) + # restruct the data + totnum=empemp[0] + empemp=sorted(empemp[1:]) + empemp.insert(0,totnum) + empemp.clear() + # addemp.append(empemp) + # clear the empty + alltypes=[obs for obs in alltypes if obs!=emp] + return alltypes + +# Sort by observ type --------------------------- # +def sort_observ(alltypes): + alltypex=[] + temtypes=[] + freindex=['1','2','3','4', + '5','6','7','8'] + obsetype=['C','L','D','S'] + + for type in alltypes: + freidx=freindex.index(type[1:2])/ 1 + if type=='P1C' or type=='P2C': + tyeidx=obsetype.index(type[2:3])/10 + else: + tyeidx=obsetype.index(type[0:1])/10 + alltypex.append(freidx+tyeidx) + + sdx=ndx=0 + while True: + if len(alltypex)==0: + break + if (ndx+1)==len(alltypex): + temtypes.append(alltypes[sdx]) + alltypes.pop(sdx) + alltypex.pop(sdx) + sdx=ndx=0 + continue + ndx+=1 + if alltypex[ndx]<=alltypex[sdx]: + sdx=ndx + continue + return temtypes + +# Convert observ type of RINEX 3.xx to Uni-Format --------------- # +def obsfmt3_conv(alltypes): + alltypex=[] + + for type in alltypes: + if type[1:2]=='1': + if type=='C1W': type='P1' + elif type[1:2]=='2': + if type=='C2W': type='P2' + else: pass + alltypex.append(type[0:2]) + + return alltypex + +# Convert observ msg of RINEX 3.xx to Uni-Format ---------------- # +def obstype3_conv(i, sysnum, outlines, outlinex): + sysstype=[] + alltypes=[] + obstypes=[] + # rinex message label + obsobs='# / TYPES OF OBSERV' + + for j in range(sysnum): + obstypes=[] + # reject system not support in Uni-Format + match outlines[i][0:1]: + case 'G': obstypes.append(0) + case 'E': obstypes.append(1) + case 'R': obstypes.append(2) + case 'S': obstypes.append(3) + case _: + i+=1 + continue + + obsnum=int(outlines[i][1:6]) + for k in range(math.ceil(obsnum/13)): + obstypes.extend(outlines[i][6:60].split()) + if k+1==math.ceil(obsnum/13): break + i+=1 + + # check the differ observ type in glonass + if obstypes[0]==2: + try: + pos=obstypes.index('C1P') + obstypes[pos]='P1C' + except ValueError: pass + try: + pos=obstypes.index('C2P') + obstypes[pos]='P2C' + except ValueError: pass + + sysstype.append(obsfmt3_conv(obstypes[1:])) + alltypes=list(set(obstypes[1:]+alltypes)) + i+=1 + + # sort observ types + alltypes=sort_observ(alltypes) + # convert observ type into des-format + alltypes=obsfmt3_conv(alltypes) + # fliter the same observ type + alltypes=obsfmt_filter(alltypes) + # get new added pos + addemp=getaddemp(alltypes, sysstype) + + num =len(alltypes) + outline=4*bnk+'%2d'%num + + for j in range(num): + outline+=4*bnk+alltypes[j] + if (j+1)==num: + bnx=((9-num%9)*6)*bnk + outlinex.append(outline+bnx+obsobs+'\n') + outline=0*bnk + elif (j+1)%9==0: + bnx=0*bnk + outlinex.append(outline+bnx+obsobs+'\n') + outline=6*bnk + # get amout of observ tyeps + addemp.append(num) + return addemp + +# Get the total amount of sat system -------------------- # +def getsys_rnx3(in_f): + # rinex message label + obsobs='SYS / # / OBS TYPES' + readst=False + syslis=[] + sysnum=0 + + while True: + inline=in_f.readline() + if not inline: break + if inline.find(obsobs)>=0: + readst=True + sys=inline[0:1] + if sys and sys not in syslis: + syslis.append(sys) + sysnum+=1 + elif readst and inline.find(obsobs)<0: break + + in_f.seek(0) + return sysnum + +# Convert head_data of RINEX 3.xx to Uni-format -------------- # +def rnx3_head2uni(in_f, desver, outlines): + # rinex message label + # obscom='COMMENT' + obstpe='RINEX VERSION / TYPE' + # obspro='PGM / RUN BY / DATE' + # obsobs='SYS / # / OBS TYPES' + obsshi='SYS / PHASE SHIFT' + obsrsb='GLONASS COD/PHS/BIS' + obsrsl='GLONASS SLOT / FRQ #' + obsend='END OF HEADER' + + # get input head file & convert + while True: + inline=in_f.readline() + # file is aleady checked so no need to judge again + if not inline: break + #if inline.find(obscom)>=0: outlines.append(inline) + #elif inline.find(obspro)>=0: outlines.append(inline) + #elif inline.find(obsobs)>=0: outlines.append(inline) + elif inline.find(obstpe)>=0: conv_stamp(inline, outlines, desver) + elif inline.find(obsshi)>=0: continue + elif inline.find(obsrsb)>=0: continue + elif inline.find(obsrsl)>=0: continue + elif inline.find(obsend)>=0: break + else : outlines.append(inline) + + # get the end message after break + outlines.append(60*bnk+obsend+'\n') + + return 1 + +# Convert obs of RINEX 3.xx to Uni-format ------------------- # +def rnx2uni3_data(outlines, in_f): + inline=in_f.readline() + if not inline: return False + if not int(inline[30:32])==0: return True + outlines.append(inline) + satnum=int(inline[33:35]) + for i in range(satnum): + outlines.append(in_f.readline()) + return True + +# Convert RINEX 3.xx(epoch msg) to RINEX 2.xx --------------- # +def rnx3rnx2_epo(outline, sPRN): + outlines=[] + datedat=outline.split() + outline=( + '%3d%3d%3d%3d%3d%11.7f%3d%3d' + %(int(datedat[1])-2000,int(datedat[2]), int(datedat[3]),# |year |month |day + int(datedat[4]) ,int(datedat[5]),float(datedat[6]),# |hour |minute |second + int(datedat[7]) ,len(sPRN))) # |flag |satnum | + + # convert to RINEX 2.xx + satnum=len(sPRN) + for i in range(satnum): + outline+=sPRN[i] + if (i+1)==len(sPRN): + outlines.append(outline+'\n') + elif (i+1)%12==0: + outlines.append(outline+'\n') + outline=32*bnk + return outlines + +# Convert RINEX 3.xx(data of each sat) to RINEX 2.xx ------------ # +def rnx3rnx2_dat(addemp, obsnum, outline): + outlines=[] + num=range(len(addemp)) + + empdat=16*bnk + + outlinx=[empdat for i in range(obsnum)] + + for i,j in zip(num,addemp): + if not outlinx[j]==empdat: continue + if outline[i*16+3:i*16+16+3]: + outlinx[j]=outline[i*16+3:i*16+16+3]\ + .replace('\n',2*bnk).replace('\r',2*bnk) + else: continue + + outline=emp + for i in range(len(outlinx)): + outline+=outlinx[i] + + for i in range(math.ceil(len(outline)/80)): + outlines.append(outline[i*80:i*80+80]+'\n') + + return outlines + +# Convert RINEX 3.xx to RINEX 2.xx --------------------- # +def rnx3rnx2_data(outlines, addemp): + sPRN=[] + datline=[] + outlinex=[] + # filter the sat system ecxcept:# + # ---GPS-Galileo-GLONASS-SBAS---# + for i in range(len(outlines)): + if outlines[i][0:1]=='G': pass + elif outlines[i][0:1]=='E': pass + elif outlines[i][0:1]=='R': pass + elif outlines[i][0:1]=='S': pass + else: continue + datline.append(i) + sPRN.append(outlines[i][0:3]) + + outlinex.extend(rnx3rnx2_epo(outlines[0], sPRN)) + + for i in datline: + if outlines[i][0:1]=='G': idx=0 + elif outlines[i][0:1]=='E': idx=1 + elif outlines[i][0:1]=='R': idx=2 + elif outlines[i][0:1]=='S': idx=3 + else: continue + outlinex.extend(rnx3rnx2_dat(addemp[idx], addemp[4], outlines[i])) + return outlinex + +# Convert Uni-format to RINEX 2.xx --------------------- # +def uni2rnx2_data(sysnum, outlines, out_path, headordata, add_emp): + # rinex message label + obspro='PGM / RUN BY / DATE' + obsobs='SYS / # / OBS TYPES' + obsend='END OF HEADER' + + outlinex=[] + obsread=False + + # convert Uni-format to RINEX 2.xx(header) + if headordata: + for i in range(len(outlines)): + if outlines[i].find(obspro)>=0: outlinex.append(datefmt3_conv(outlines[i])) + elif outlines[i].find(obsobs)>=0: + if not obsread: + obsread=True + addemp=obstype3_conv(i, sysnum, outlines, outlinex) + else: continue + elif outlines[i].find(obsend)>=0: outlinex.append(outlines[i]) + else: outlinex.append(outlines[i]) + + # convert Uni-format to RINEX 2.xx(data) + elif not headordata: + outlinex=rnx3rnx2_data(outlines, add_emp) + + # output to destination file + out_f=open(out_path, 'a') + out_f.writelines(outlinex) + out_f.close() + + if headordata: return addemp + elif not headordata: return 0 + +# Convert data of RINEX 3.xx to Des-format ----------------- # +def rnx3des(in_path, out_path, oriver, desver): + headread=False + outlines=[] + in_f=open(in_path, 'r') + # get the amount of sat system + sysnum=getsys_rnx3(in_f) + # convert RINEX 3.xx(header) to Uni-format + match rnx3_head2uni(in_f, desver, outlines): + case 1: headread=True + case 0: headread=False + # convert Uni-foramt(header) to Des-format + if headread: + match desver[0:1]: + case '2': addemp=uni2rnx2_data(sysnum, outlines, out_path, True, None) + case '3': uni2rnx3_data(outlines, out_path) + outlines=[] + # convert RINEX 3.xx(data) to Uni-format + while rnx2uni3_data(outlines, in_f): + # convert Uni-foramt(data) to Des-format + match desver[0:1]: + case '2': uni2rnx2_data(sysnum, outlines, out_path, False, addemp) + case '3': uni2rnx3_data(outlines, out_path) + outlines=[] + + elif not headread: return 0 + + return 1 # Reject data of invaild input ----------------------- # def rnx_reject(in_path, out_path, oriver): @@ -393,8 +739,6 @@ def rnx_reject(in_path, out_path, oriver): return 1 - - # --------------------------------------------------------------------------------------- # CONVERT FUNCTION # @@ -413,12 +757,11 @@ def Convert_Un(in_path, out_path, oriver, desver, resqueue): if file_state: match oriver: case '2': rnx2des(in_path, out_path, oriver, desver) - case '3': resqueue.put(0) - else : resqueue.put(0) - - resqueue.put(1) - return + case '3': rnx3des(in_path, out_path, oriver, desver) + else : return resqueue.put(0) + return resqueue.put(1) + # Multi-threading task --------------------------- # def _Convert_Un(in_path, out_path, oriver, desver, resqueue): T=threading.Thread( @@ -426,130 +769,4 @@ def _Convert_Un(in_path, out_path, oriver, desver, resqueue): ) T.start() T.join() - return resqueue.get() - - - - - - - -# --------------------------------------------------------------- # -# The functions below are not be useable. on progress............ # -# -# -# --------------------------------------------------------------- # - -# Convert observ type of RINEX 3.xx to Uni-Format --------------- # -def obsfmt_conv_cxx(obstypes): - outlines=[] - outline='%6d'%len(obstypes) - - for i in range(len(obstypes)): - outline+='%6s'%obstypes[i] - if (i+1)==len(obstypes): - outlines.append(outline + (9 - (i+1)%9)*6*bnk + '# / TYPES OF OBSERV\n') - outline='' - elif (i+1)%9==0: - outlines.append(outline + '# / TYPES OF OBSERV\n') - outline=6*bnk - return outlines -# Convert observ msg of RINEX 3.xx to Uni-Format ---------------- # -def obstype_conv_cxx(obstypes, inline, in_f): - while True: - if inline[0:1]=='G': flag=True - elif inline[0:1]=='E': flag=True - elif inline[0:1]=='R': flag=True - elif inline[0:1]=='S': flag=True - else: flag=False - - if flag: - obsnum=int(inline[2:6]) - for i in range(math.ceil(obsnum/13)): - for obs in inline[6:60].split(): - if obs[1:2]=='3': continue - if obs[1:2]=='4': continue - if obs[2:3]=='P': obs='P'+obs[1:2] - else: obs=obs[0:2] - if obs and obs not in obstypes: - obstypes.append(obs) - - if i+1==math.ceil(obsnum/13): - break - inline=in_f.readline() - return -# Convert head_data of RINEX 3.xx to Uni-format -------------- # -def rnx3_head2uni(in_path, out_path, desver): - try: - with open(in_path, 'r'): pass - except FileNotFoundError: - return -12 - - obstypes=[] - outlines=[] - in_put=False - output=False - in_f=open(in_path, 'r') - while True: - inline=in_f.readline() - if not inline: - return 0 - - if in_put and not output: - if not inline.find('SYS / # / OBS TYPES')>=0: - output=True - - if in_put and output: - outlines.extend(obsfmt_conv_cxx(obstypes)) - in_put=False - output=False - - if inline.find('COMMENT')>=0: - outlines.append(inline) - - elif inline.find('RINEX VERSION / TYPE')>=0: - if not inline.find('OBSERVATION DATA')>=0: - return -10 - if not float(inline[5: 9])>=3: - return -10 - # Output convert message - outlines.append( - 5*bnk+'%s->%s'%(str(inline[5: 9]),str(desver))+ - 1*bnk+'COV-OBSERVATION DATA'+ - 24*bnk+'COV-RINEX VER / TYPE\n') - outlines.append(conv_time()) - outlines.append(inline.replace( - '%s'%re.search(r'[1-9]\d*.\d*|0\.\d*[1-9]\d*', inline).group(), - desver)) - - elif inline.find('PGM / RUN BY / DATE')>=0: - outlines.append(datefmt3_conv(inline)) - - elif inline.find('SYS / # / OBS TYPES')>=0: - in_put=True - obstype_conv_cxx(obstypes, inline, in_f) - - elif inline.find('SYS / PHASE SHIFT')>=0: - continue - - elif inline.find('GLONASS COD/PHS/BIS')>=0: - continue - - elif inline.find('GLONASS SLOT / FRQ #')>=0: - continue - - elif inline.find("END OF HEADER")>=0: - outlines.append(inline) - break - - else: outlines.append(inline) - - try: - with open(out_path, 'w'): pass - except PermissionError: - return -11 - - out_f=open(out_path, 'a') - out_f.writelines(outlines) - out_f.close() - return 1 \ No newline at end of file + return resqueue.get() \ No newline at end of file diff --git a/rtcm_convert.py b/rtcm_convert.py new file mode 100644 index 0000000..ab96c6f --- /dev/null +++ b/rtcm_convert.py @@ -0,0 +1,18 @@ +# @ File : rtcm_convert.py.py +# +# Copyright (c) 2024 - 2024 KenanZhu. All Right Reserved. +# +# @ Author : KenanZhu +# @ Time : 2024/11/16 +# @ Brief : +# : +# @ IDE : PyCharm +# +# ---------------------------------------------------------------------------------------- +# ---SELPORT--- # + +# ---STDPORT--- # + +# ------------- # +def Convert_Un(): + return 0 \ No newline at end of file