cnrdiff 1.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- cnrdiff-1.2.0/PKG-INFO +158 -0
- cnrdiff-1.2.0/README.md +130 -0
- cnrdiff-1.2.0/cnrdiff/__init__.py +39 -0
- cnrdiff-1.2.0/cnrdiff/cnrdiff.py +352 -0
- cnrdiff-1.2.0/cnrdiff.egg-info/PKG-INFO +158 -0
- cnrdiff-1.2.0/cnrdiff.egg-info/SOURCES.txt +10 -0
- cnrdiff-1.2.0/cnrdiff.egg-info/dependency_links.txt +1 -0
- cnrdiff-1.2.0/cnrdiff.egg-info/requires.txt +2 -0
- cnrdiff-1.2.0/cnrdiff.egg-info/top_level.txt +1 -0
- cnrdiff-1.2.0/pyproject.toml +39 -0
- cnrdiff-1.2.0/setup.cfg +4 -0
- cnrdiff-1.2.0/setup.py +35 -0
cnrdiff-1.2.0/PKG-INFO
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: cnrdiff
|
|
3
|
+
Version: 1.2.0
|
|
4
|
+
Summary: A library used to compare signal-to-noise ratio
|
|
5
|
+
Home-page: https://github.com/sinognss/cnrdiff
|
|
6
|
+
Author: Sheng Guoliang
|
|
7
|
+
Author-email: Sheng Guoliang <shengguoliang@sinognss.com>, Yang Fawang <yangfawang@sinognss.com>
|
|
8
|
+
License: MIT
|
|
9
|
+
Project-URL: Homepage, https://github.com/sinognss/cnrdiff
|
|
10
|
+
Project-URL: Repository, https://github.com/sinognss/cnrdiff
|
|
11
|
+
Project-URL: Issues, https://github.com/sinognss/cnrdiff/issues
|
|
12
|
+
Keywords: cnr,signal-to-noise,gnss,rinex,bnc
|
|
13
|
+
Classifier: Intended Audience :: Science/Research
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Topic :: Scientific/Engineering
|
|
21
|
+
Requires-Python: >=3.10
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
Requires-Dist: pandas>=2.0.0
|
|
24
|
+
Requires-Dist: matplotlib>=3.7.0
|
|
25
|
+
Dynamic: author
|
|
26
|
+
Dynamic: home-page
|
|
27
|
+
Dynamic: requires-python
|
|
28
|
+
|
|
29
|
+
# CNRDIFF
|
|
30
|
+
|
|
31
|
+
A library used to compare signal-to-noise ratio.
|
|
32
|
+
|
|
33
|
+
Include CNR file format conversion, difference calculation and plotting.
|
|
34
|
+
|
|
35
|
+
*There is a GUI version available for Windows users. See [Release](https://github.com/kongolou/cnrdiff/releases).*
|
|
36
|
+
|
|
37
|
+
**Lead Programmer:**
|
|
38
|
+
- Sheng Guoliang <shengguoliang@sinognss.com>
|
|
39
|
+
|
|
40
|
+
**Contributors:**
|
|
41
|
+
- Yang Fawang <yangfawang@sinognss.com>
|
|
42
|
+
- Wang Xiaobing <wangxiaobing@sinognss.com>
|
|
43
|
+
|
|
44
|
+
## History
|
|
45
|
+
| Date | Version Info |
|
|
46
|
+
|------------|--------------|
|
|
47
|
+
| 2024-11-20 | 1.0 Released |
|
|
48
|
+
| 2024-11-29 | 1.1 Released |
|
|
49
|
+
| 2024-12-05 | 1.2 Released |
|
|
50
|
+
|
|
51
|
+
# Examples
|
|
52
|
+
The following examples use BNC QC LOG files. Note that RINEX V3 OBS files are also supported.
|
|
53
|
+
|
|
54
|
+
## Convert to CNR file
|
|
55
|
+
```python
|
|
56
|
+
cnrs = cnrdiff.log2cnr(['0002295h.log'])
|
|
57
|
+
print(cnrs['0002295h.log.cnr'])
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
**Output:**
|
|
61
|
+
```
|
|
62
|
+
0 1 2 3 4 5 6 7 8 9 10 11
|
|
63
|
+
0 2024-10-21T08:00:00 1 G03 0.00 S1C 40.0 S2C 45.0 S2W 40.0 S5I 46.0
|
|
64
|
+
1 2024-10-21T08:00:00 1 G16 0.00 S1C 44.0 S2W 34.0 None NaN None NaN
|
|
65
|
+
2 2024-10-21T08:00:00 1 G26 72.19 S1C 48.0 S2C 48.0 S2W 49.0 S5I 49.0
|
|
66
|
+
3 2024-10-21T08:00:00 1 G28 54.10 S1C 44.0 S2C 49.0 S2W 36.0 S5I 49.0
|
|
67
|
+
4 2024-10-21T08:00:00 1 G29 29.28 S1C 38.0 S2C 33.0 S2W 23.0 None NaN
|
|
68
|
+
... ... ... ... ... ... ... ... ... ... ... ... ...
|
|
69
|
+
154214 2024-10-21T09:00:00 3601 C39 69.81 S2I 49.0 S6I 47.0 None NaN None NaN
|
|
70
|
+
154215 2024-10-21T09:00:00 3601 C40 50.54 S2I 47.0 S6I 47.0 None NaN None NaN
|
|
71
|
+
154216 2024-10-21T09:00:00 3601 C45 40.91 S2I 47.0 S6I 49.0 None NaN None NaN
|
|
72
|
+
154217 2024-10-21T09:00:00 3601 C59 47.34 S2I 47.0 S6I 48.0 None NaN None NaN
|
|
73
|
+
154218 2024-10-21T09:00:00 3601 C60 31.67 S2I 43.0 S6I 45.0 None NaN None NaN
|
|
74
|
+
|
|
75
|
+
[154219 rows x 12 columns]
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Calculate difference with default parameters (mean of all epochs)
|
|
79
|
+
```python
|
|
80
|
+
logflist = ['0002295h.log', '0005295h.log', '0041295h.log']
|
|
81
|
+
cnrs = cnrdiff.log2cnr(logflist)
|
|
82
|
+
dcnrs = cnrdiff.cnr2dcnr(cnrs)
|
|
83
|
+
print(dcnrs['0005295h.log.cnr.dcnr'])
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
**Output:**
|
|
87
|
+
```
|
|
88
|
+
S1C S1X S2C S2I S2P S6I S7I S2W S5I S5X S7X
|
|
89
|
+
PRN
|
|
90
|
+
C01 NaN NaN NaN -0.940572 NaN 0.085532 -0.843655 NaN NaN NaN NaN
|
|
91
|
+
C02 NaN NaN NaN -1.191891 NaN 0.429325 -0.875868 NaN NaN NaN NaN
|
|
92
|
+
C03 NaN NaN NaN -0.871425 NaN 0.767287 -0.167453 NaN NaN NaN NaN
|
|
93
|
+
C04 NaN NaN NaN -1.157456 NaN -0.718967 -0.314079 NaN NaN NaN NaN
|
|
94
|
+
C06 NaN NaN NaN -0.649542 NaN 0.709525 -0.185782 NaN NaN NaN NaN
|
|
95
|
+
C07 NaN NaN NaN -0.628992 NaN -0.109414 -0.797001 NaN NaN NaN NaN
|
|
96
|
+
C08 NaN NaN NaN -7.029925 NaN -7.659138 -8.090604 NaN NaN NaN NaN
|
|
97
|
+
C09 NaN NaN NaN -0.430158 NaN 0.553180 -0.311580 NaN NaN NaN NaN
|
|
98
|
+
C10 NaN NaN NaN -0.613441 NaN -0.668148 -1.409331 NaN NaN NaN NaN
|
|
99
|
+
C13 NaN NaN NaN -0.420030 NaN -0.170935 -1.856699 NaN NaN NaN NaN
|
|
100
|
+
C16 NaN NaN NaN -0.250764 NaN 0.668981 -0.287420 NaN NaN NaN NaN
|
|
101
|
+
C19 NaN NaN NaN -0.715357 NaN -0.722855 NaN NaN NaN NaN NaN
|
|
102
|
+
C21 NaN NaN NaN -0.637597 NaN -0.221556 NaN NaN NaN NaN NaN
|
|
103
|
+
C22 NaN NaN NaN -1.140517 NaN 0.246876 NaN NaN NaN NaN NaN
|
|
104
|
+
C27 NaN NaN NaN -0.660690 NaN 0.482968 NaN NaN NaN NaN NaN
|
|
105
|
+
C29 NaN NaN NaN -1.968718 NaN -0.774428 NaN NaN NaN NaN NaN
|
|
106
|
+
C30 NaN NaN NaN -1.069425 NaN -0.106082 NaN NaN NaN NaN NaN
|
|
107
|
+
C36 NaN NaN NaN -0.360178 NaN 0.860317 NaN NaN NaN NaN NaN
|
|
108
|
+
C38 NaN NaN NaN -1.204633 NaN -0.822394 NaN NaN NaN NaN NaN
|
|
109
|
+
C39 NaN NaN NaN -0.246876 NaN 0.602888 NaN NaN NaN NaN NaN
|
|
110
|
+
C40 NaN NaN NaN -0.486254 NaN -0.064704 NaN NaN NaN NaN NaN
|
|
111
|
+
C45 NaN NaN NaN -1.191613 NaN -0.384615 NaN NaN NaN NaN NaN
|
|
112
|
+
C59 NaN NaN NaN -0.490419 NaN 0.075257 NaN NaN NaN NaN NaN
|
|
113
|
+
C60 NaN NaN NaN -0.384060 NaN -1.341294 NaN NaN NaN NaN NaN
|
|
114
|
+
E02 NaN 0.028881 NaN NaN NaN NaN NaN NaN NaN 0.704249 0.470425
|
|
115
|
+
E03 NaN -1.054074 NaN NaN NaN NaN NaN NaN NaN 0.616438 -0.138428
|
|
116
|
+
E07 NaN -0.602333 NaN NaN NaN NaN NaN NaN NaN 0.645376 0.058595
|
|
117
|
+
E08 NaN -0.708137 NaN NaN NaN NaN NaN NaN NaN 0.638156 -0.257706
|
|
118
|
+
E27 NaN -0.317690 NaN NaN NaN NaN NaN NaN NaN -0.507359 -1.391002
|
|
119
|
+
E29 NaN -0.891760 NaN NaN NaN NaN NaN NaN NaN -0.697708 -1.014139
|
|
120
|
+
E30 NaN -0.801444 NaN NaN NaN NaN NaN NaN NaN 0.892252 0.099417
|
|
121
|
+
G03 -1.185782 NaN -1.468857 NaN NaN NaN NaN -1.909297 -0.956679 NaN NaN
|
|
122
|
+
G04 -1.012480 NaN -1.029914 NaN NaN NaN NaN -1.265208 -0.205828 NaN NaN
|
|
123
|
+
G16 -1.130242 NaN NaN NaN NaN NaN NaN -1.521244 NaN NaN NaN
|
|
124
|
+
G26 -0.423493 NaN 0.109136 NaN NaN NaN NaN -0.277978 0.285754 NaN NaN
|
|
125
|
+
G27 -0.928958 NaN -1.408960 NaN NaN NaN NaN -2.466618 -0.895877 NaN NaN
|
|
126
|
+
G28 -0.141905 NaN 0.383505 NaN NaN NaN NaN 0.147459 0.844210 NaN NaN
|
|
127
|
+
G29 -1.328652 NaN -0.748343 NaN NaN NaN NaN -1.765429 NaN NaN NaN
|
|
128
|
+
G31 -0.170786 NaN 0.321577 NaN NaN NaN NaN 0.034713 NaN NaN NaN
|
|
129
|
+
G32 -1.343793 NaN -0.820605 NaN NaN NaN NaN -2.168564 -0.294085 NaN NaN
|
|
130
|
+
R04 -0.536518 NaN NaN NaN -1.141905 NaN NaN NaN NaN NaN NaN
|
|
131
|
+
R05 -0.286865 NaN NaN NaN 0.102194 NaN NaN NaN NaN NaN NaN
|
|
132
|
+
R06 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
|
|
133
|
+
R14 -1.866949 NaN NaN NaN -1.413515 NaN NaN NaN NaN NaN NaN
|
|
134
|
+
R15 -0.825326 NaN NaN NaN 0.395446 NaN NaN NaN NaN NaN NaN
|
|
135
|
+
R16 -2.187170 NaN NaN NaN -0.758400 NaN NaN NaN NaN NaN NaN
|
|
136
|
+
R17 -0.660695 NaN NaN NaN -0.220414 NaN NaN NaN NaN NaN NaN
|
|
137
|
+
R18 -2.040590 NaN NaN NaN 0.568744 NaN NaN NaN NaN NaN NaN
|
|
138
|
+
R24 -1.121621 NaN NaN NaN -0.724670 NaN NaN NaN NaN NaN NaN
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## Calculate difference with custom parameters
|
|
142
|
+
```python
|
|
143
|
+
logflist = ['11121980.24O', '11131980.24O']
|
|
144
|
+
dcnrflist = ['11121980.csv', '11131980.csv']
|
|
145
|
+
start = datetime.datetime(2024, 7, 16, 9, 0, 0)
|
|
146
|
+
end = datetime.datetime(2024, 7, 16, 10, 0, 0)
|
|
147
|
+
interval = 5
|
|
148
|
+
ele_cut = 20.0
|
|
149
|
+
cnrdiff.log2cnr(logflist, save=False, start=start, end=end, interval=interval, ele_cut=ele_cut)
|
|
150
|
+
cnrdiff.cnr2dcnr(cnrflist, save=dcnrflist, plot=True, how='MAX', by='SYS')
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## Convert DCNR to XLSX file
|
|
154
|
+
```python
|
|
155
|
+
>>> dcnrflist1 = ['0002295h.log.cnr.dcnr', '0005295h.log.cnr.dcnr', '0041295h.log.cnr.dcnr']
|
|
156
|
+
>>> dcnrflist2 = ['11121980.csv', '11131980.csv']
|
|
157
|
+
>>> cnrdiff.dcnr2xlsx([dcnrflist1, dcnrflist2], 'summary.xlsx')
|
|
158
|
+
```
|
cnrdiff-1.2.0/README.md
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# CNRDIFF
|
|
2
|
+
|
|
3
|
+
A library used to compare signal-to-noise ratio.
|
|
4
|
+
|
|
5
|
+
Include CNR file format conversion, difference calculation and plotting.
|
|
6
|
+
|
|
7
|
+
*There is a GUI version available for Windows users. See [Release](https://github.com/kongolou/cnrdiff/releases).*
|
|
8
|
+
|
|
9
|
+
**Lead Programmer:**
|
|
10
|
+
- Sheng Guoliang <shengguoliang@sinognss.com>
|
|
11
|
+
|
|
12
|
+
**Contributors:**
|
|
13
|
+
- Yang Fawang <yangfawang@sinognss.com>
|
|
14
|
+
- Wang Xiaobing <wangxiaobing@sinognss.com>
|
|
15
|
+
|
|
16
|
+
## History
|
|
17
|
+
| Date | Version Info |
|
|
18
|
+
|------------|--------------|
|
|
19
|
+
| 2024-11-20 | 1.0 Released |
|
|
20
|
+
| 2024-11-29 | 1.1 Released |
|
|
21
|
+
| 2024-12-05 | 1.2 Released |
|
|
22
|
+
|
|
23
|
+
# Examples
|
|
24
|
+
The following examples use BNC QC LOG files. Note that RINEX V3 OBS files are also supported.
|
|
25
|
+
|
|
26
|
+
## Convert to CNR file
|
|
27
|
+
```python
|
|
28
|
+
cnrs = cnrdiff.log2cnr(['0002295h.log'])
|
|
29
|
+
print(cnrs['0002295h.log.cnr'])
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
**Output:**
|
|
33
|
+
```
|
|
34
|
+
0 1 2 3 4 5 6 7 8 9 10 11
|
|
35
|
+
0 2024-10-21T08:00:00 1 G03 0.00 S1C 40.0 S2C 45.0 S2W 40.0 S5I 46.0
|
|
36
|
+
1 2024-10-21T08:00:00 1 G16 0.00 S1C 44.0 S2W 34.0 None NaN None NaN
|
|
37
|
+
2 2024-10-21T08:00:00 1 G26 72.19 S1C 48.0 S2C 48.0 S2W 49.0 S5I 49.0
|
|
38
|
+
3 2024-10-21T08:00:00 1 G28 54.10 S1C 44.0 S2C 49.0 S2W 36.0 S5I 49.0
|
|
39
|
+
4 2024-10-21T08:00:00 1 G29 29.28 S1C 38.0 S2C 33.0 S2W 23.0 None NaN
|
|
40
|
+
... ... ... ... ... ... ... ... ... ... ... ... ...
|
|
41
|
+
154214 2024-10-21T09:00:00 3601 C39 69.81 S2I 49.0 S6I 47.0 None NaN None NaN
|
|
42
|
+
154215 2024-10-21T09:00:00 3601 C40 50.54 S2I 47.0 S6I 47.0 None NaN None NaN
|
|
43
|
+
154216 2024-10-21T09:00:00 3601 C45 40.91 S2I 47.0 S6I 49.0 None NaN None NaN
|
|
44
|
+
154217 2024-10-21T09:00:00 3601 C59 47.34 S2I 47.0 S6I 48.0 None NaN None NaN
|
|
45
|
+
154218 2024-10-21T09:00:00 3601 C60 31.67 S2I 43.0 S6I 45.0 None NaN None NaN
|
|
46
|
+
|
|
47
|
+
[154219 rows x 12 columns]
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Calculate difference with default parameters (mean of all epochs)
|
|
51
|
+
```python
|
|
52
|
+
logflist = ['0002295h.log', '0005295h.log', '0041295h.log']
|
|
53
|
+
cnrs = cnrdiff.log2cnr(logflist)
|
|
54
|
+
dcnrs = cnrdiff.cnr2dcnr(cnrs)
|
|
55
|
+
print(dcnrs['0005295h.log.cnr.dcnr'])
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
**Output:**
|
|
59
|
+
```
|
|
60
|
+
S1C S1X S2C S2I S2P S6I S7I S2W S5I S5X S7X
|
|
61
|
+
PRN
|
|
62
|
+
C01 NaN NaN NaN -0.940572 NaN 0.085532 -0.843655 NaN NaN NaN NaN
|
|
63
|
+
C02 NaN NaN NaN -1.191891 NaN 0.429325 -0.875868 NaN NaN NaN NaN
|
|
64
|
+
C03 NaN NaN NaN -0.871425 NaN 0.767287 -0.167453 NaN NaN NaN NaN
|
|
65
|
+
C04 NaN NaN NaN -1.157456 NaN -0.718967 -0.314079 NaN NaN NaN NaN
|
|
66
|
+
C06 NaN NaN NaN -0.649542 NaN 0.709525 -0.185782 NaN NaN NaN NaN
|
|
67
|
+
C07 NaN NaN NaN -0.628992 NaN -0.109414 -0.797001 NaN NaN NaN NaN
|
|
68
|
+
C08 NaN NaN NaN -7.029925 NaN -7.659138 -8.090604 NaN NaN NaN NaN
|
|
69
|
+
C09 NaN NaN NaN -0.430158 NaN 0.553180 -0.311580 NaN NaN NaN NaN
|
|
70
|
+
C10 NaN NaN NaN -0.613441 NaN -0.668148 -1.409331 NaN NaN NaN NaN
|
|
71
|
+
C13 NaN NaN NaN -0.420030 NaN -0.170935 -1.856699 NaN NaN NaN NaN
|
|
72
|
+
C16 NaN NaN NaN -0.250764 NaN 0.668981 -0.287420 NaN NaN NaN NaN
|
|
73
|
+
C19 NaN NaN NaN -0.715357 NaN -0.722855 NaN NaN NaN NaN NaN
|
|
74
|
+
C21 NaN NaN NaN -0.637597 NaN -0.221556 NaN NaN NaN NaN NaN
|
|
75
|
+
C22 NaN NaN NaN -1.140517 NaN 0.246876 NaN NaN NaN NaN NaN
|
|
76
|
+
C27 NaN NaN NaN -0.660690 NaN 0.482968 NaN NaN NaN NaN NaN
|
|
77
|
+
C29 NaN NaN NaN -1.968718 NaN -0.774428 NaN NaN NaN NaN NaN
|
|
78
|
+
C30 NaN NaN NaN -1.069425 NaN -0.106082 NaN NaN NaN NaN NaN
|
|
79
|
+
C36 NaN NaN NaN -0.360178 NaN 0.860317 NaN NaN NaN NaN NaN
|
|
80
|
+
C38 NaN NaN NaN -1.204633 NaN -0.822394 NaN NaN NaN NaN NaN
|
|
81
|
+
C39 NaN NaN NaN -0.246876 NaN 0.602888 NaN NaN NaN NaN NaN
|
|
82
|
+
C40 NaN NaN NaN -0.486254 NaN -0.064704 NaN NaN NaN NaN NaN
|
|
83
|
+
C45 NaN NaN NaN -1.191613 NaN -0.384615 NaN NaN NaN NaN NaN
|
|
84
|
+
C59 NaN NaN NaN -0.490419 NaN 0.075257 NaN NaN NaN NaN NaN
|
|
85
|
+
C60 NaN NaN NaN -0.384060 NaN -1.341294 NaN NaN NaN NaN NaN
|
|
86
|
+
E02 NaN 0.028881 NaN NaN NaN NaN NaN NaN NaN 0.704249 0.470425
|
|
87
|
+
E03 NaN -1.054074 NaN NaN NaN NaN NaN NaN NaN 0.616438 -0.138428
|
|
88
|
+
E07 NaN -0.602333 NaN NaN NaN NaN NaN NaN NaN 0.645376 0.058595
|
|
89
|
+
E08 NaN -0.708137 NaN NaN NaN NaN NaN NaN NaN 0.638156 -0.257706
|
|
90
|
+
E27 NaN -0.317690 NaN NaN NaN NaN NaN NaN NaN -0.507359 -1.391002
|
|
91
|
+
E29 NaN -0.891760 NaN NaN NaN NaN NaN NaN NaN -0.697708 -1.014139
|
|
92
|
+
E30 NaN -0.801444 NaN NaN NaN NaN NaN NaN NaN 0.892252 0.099417
|
|
93
|
+
G03 -1.185782 NaN -1.468857 NaN NaN NaN NaN -1.909297 -0.956679 NaN NaN
|
|
94
|
+
G04 -1.012480 NaN -1.029914 NaN NaN NaN NaN -1.265208 -0.205828 NaN NaN
|
|
95
|
+
G16 -1.130242 NaN NaN NaN NaN NaN NaN -1.521244 NaN NaN NaN
|
|
96
|
+
G26 -0.423493 NaN 0.109136 NaN NaN NaN NaN -0.277978 0.285754 NaN NaN
|
|
97
|
+
G27 -0.928958 NaN -1.408960 NaN NaN NaN NaN -2.466618 -0.895877 NaN NaN
|
|
98
|
+
G28 -0.141905 NaN 0.383505 NaN NaN NaN NaN 0.147459 0.844210 NaN NaN
|
|
99
|
+
G29 -1.328652 NaN -0.748343 NaN NaN NaN NaN -1.765429 NaN NaN NaN
|
|
100
|
+
G31 -0.170786 NaN 0.321577 NaN NaN NaN NaN 0.034713 NaN NaN NaN
|
|
101
|
+
G32 -1.343793 NaN -0.820605 NaN NaN NaN NaN -2.168564 -0.294085 NaN NaN
|
|
102
|
+
R04 -0.536518 NaN NaN NaN -1.141905 NaN NaN NaN NaN NaN NaN
|
|
103
|
+
R05 -0.286865 NaN NaN NaN 0.102194 NaN NaN NaN NaN NaN NaN
|
|
104
|
+
R06 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
|
|
105
|
+
R14 -1.866949 NaN NaN NaN -1.413515 NaN NaN NaN NaN NaN NaN
|
|
106
|
+
R15 -0.825326 NaN NaN NaN 0.395446 NaN NaN NaN NaN NaN NaN
|
|
107
|
+
R16 -2.187170 NaN NaN NaN -0.758400 NaN NaN NaN NaN NaN NaN
|
|
108
|
+
R17 -0.660695 NaN NaN NaN -0.220414 NaN NaN NaN NaN NaN NaN
|
|
109
|
+
R18 -2.040590 NaN NaN NaN 0.568744 NaN NaN NaN NaN NaN NaN
|
|
110
|
+
R24 -1.121621 NaN NaN NaN -0.724670 NaN NaN NaN NaN NaN NaN
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## Calculate difference with custom parameters
|
|
114
|
+
```python
|
|
115
|
+
logflist = ['11121980.24O', '11131980.24O']
|
|
116
|
+
dcnrflist = ['11121980.csv', '11131980.csv']
|
|
117
|
+
start = datetime.datetime(2024, 7, 16, 9, 0, 0)
|
|
118
|
+
end = datetime.datetime(2024, 7, 16, 10, 0, 0)
|
|
119
|
+
interval = 5
|
|
120
|
+
ele_cut = 20.0
|
|
121
|
+
cnrdiff.log2cnr(logflist, save=False, start=start, end=end, interval=interval, ele_cut=ele_cut)
|
|
122
|
+
cnrdiff.cnr2dcnr(cnrflist, save=dcnrflist, plot=True, how='MAX', by='SYS')
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Convert DCNR to XLSX file
|
|
126
|
+
```python
|
|
127
|
+
>>> dcnrflist1 = ['0002295h.log.cnr.dcnr', '0005295h.log.cnr.dcnr', '0041295h.log.cnr.dcnr']
|
|
128
|
+
>>> dcnrflist2 = ['11121980.csv', '11131980.csv']
|
|
129
|
+
>>> cnrdiff.dcnr2xlsx([dcnrflist1, dcnrflist2], 'summary.xlsx')
|
|
130
|
+
```
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"""CNRDIFF
|
|
2
|
+
|
|
3
|
+
A library used to compare signal-to-noise ratio.
|
|
4
|
+
|
|
5
|
+
Include CNR file format conversion, difference calculation and plotting.
|
|
6
|
+
|
|
7
|
+
## Examples
|
|
8
|
+
The following examples use BNC QC LOG files. Note that RINEX V3 OBS files are also supported.
|
|
9
|
+
|
|
10
|
+
### Convert to CNR file
|
|
11
|
+
>>> cnrs = cnrdiff.log2cnr(['0002295h.log'])
|
|
12
|
+
>>> print(cnrs['0002295h.log.cnr'])
|
|
13
|
+
|
|
14
|
+
### Calculate difference with default parameters (mean of all epochs)
|
|
15
|
+
>>> logflist = ['0002295h.log', '0005295h.log', '0041295h.log']
|
|
16
|
+
>>> cnrs = cnrdiff.log2cnr(logflist)
|
|
17
|
+
>>> dcnrs = cnrdiff.cnr2dcnr(cnrs)
|
|
18
|
+
>>> print(dcnrs['0005295h.log.cnr.dcnr'])
|
|
19
|
+
|
|
20
|
+
### Calculate difference with custom parameters
|
|
21
|
+
>>> logflist = ['11121980.24O', '11131980.24O']
|
|
22
|
+
>>> dcnrflist = ['11121980.csv', '11131980.csv']
|
|
23
|
+
>>> start = datetime.datetime(2024, 7, 16, 9, 0, 0)
|
|
24
|
+
>>> end = datetime.datetime(2024, 7, 16, 10, 0, 0)
|
|
25
|
+
>>> interval = 5
|
|
26
|
+
>>> ele_cut = 20.0
|
|
27
|
+
>>> cnrdiff.log2cnr(logflist, save=False, start=start, end=end, interval=interval, ele_cut=ele_cut)
|
|
28
|
+
>>> cnrdiff.cnr2dcnr(cnrflist, save=dcnrflist, plot=True, how='MAX', by='SYS')
|
|
29
|
+
|
|
30
|
+
### Convert DCNR to XLSX file
|
|
31
|
+
>>> dcnrflist1 = ['0002295h.log.cnr.dcnr', '0005295h.log.cnr.dcnr', '0041295h.log.cnr.dcnr']
|
|
32
|
+
>>> dcnrflist2 = ['11121980.csv', '11131980.csv']
|
|
33
|
+
>>> cnrdiff.dcnr2xlsx([dcnrflist1, dcnrflist2], save='summary.xlsx')
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
from cnrdiff.cnrdiff import log2cnr, rnx2cnr, cnr2dcnr, dcnr2xlsx
|
|
37
|
+
|
|
38
|
+
__version__ = "1.2.0"
|
|
39
|
+
__all__ = ["log2cnr", "rnx2cnr", "cnr2dcnr", "dcnr2xlsx"]
|
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
import datetime
|
|
2
|
+
import os
|
|
3
|
+
import pandas as pd
|
|
4
|
+
import matplotlib.pyplot as plt
|
|
5
|
+
from typing import Literal
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def log2cnr(
|
|
9
|
+
read: list[str],
|
|
10
|
+
save: list[str] | bool = False,
|
|
11
|
+
start: datetime.datetime | None = None,
|
|
12
|
+
end: datetime.datetime | None = None,
|
|
13
|
+
interval: datetime.timedelta | float | int | None = None,
|
|
14
|
+
ele_cut: float = 0.0,
|
|
15
|
+
) -> dict[str, pd.DataFrame]:
|
|
16
|
+
"""将 BNC QC LOG 文件转换为 CNR 格式.
|
|
17
|
+
|
|
18
|
+
读取策略:
|
|
19
|
+
1. 读两遍文件。第一遍核对时间,第二遍存储数据.
|
|
20
|
+
2. 不指定起始时刻,默认起始时刻为文件中首次出现记录的时刻.
|
|
21
|
+
3. 不指定结束时刻,默认结束时刻为文件中最后一次记录的时刻.
|
|
22
|
+
4. 不指定历元间隔,默认历元间隔为文件中所有相邻时刻间隔的最小值.
|
|
23
|
+
5. 不指定高度截止角阈值,默认高度截止角阈值为 0.0°.
|
|
24
|
+
6. 历元缺失,则缺省记录,不会抛出异常.
|
|
25
|
+
7. 指定时间范围非法,抛出异常.
|
|
26
|
+
8. 指定高度截止角阈值非法,抛出异常.
|
|
27
|
+
|
|
28
|
+
Parameters:
|
|
29
|
+
read (list[str]): 需要读取的 BNC QC LOG 文件列表.
|
|
30
|
+
save (list[str] | bool, optional): 需要保存的 CNR 文件列表或是否保存.
|
|
31
|
+
start (datetime.datetime | None, optional): 起始时刻.
|
|
32
|
+
end (datetime.datetime | None, optional): 结束时刻.
|
|
33
|
+
interval (datetime.timedelta | float | int | None, optional): 历元间隔.
|
|
34
|
+
ele_cut (float = 0.0, optional): 高度截止角阈值.
|
|
35
|
+
|
|
36
|
+
Returns:
|
|
37
|
+
dict[str, pd.DataFrame]: CNR 文件数据缓存.
|
|
38
|
+
|
|
39
|
+
Raises:
|
|
40
|
+
ValueError: 指定时间范围非法.
|
|
41
|
+
ValueError: 指定高度截止角阈值非法.
|
|
42
|
+
"""
|
|
43
|
+
result = {}
|
|
44
|
+
for logfpath in read:
|
|
45
|
+
# --------第一次读取:核对时间信息--------
|
|
46
|
+
have = []
|
|
47
|
+
with open(logfpath, "r") as fr:
|
|
48
|
+
for line in fr:
|
|
49
|
+
if line.startswith(">"):
|
|
50
|
+
have.append(
|
|
51
|
+
datetime.datetime(
|
|
52
|
+
year=int(line[2:6]),
|
|
53
|
+
month=int(line[7:9]),
|
|
54
|
+
day=int(line[10:12]),
|
|
55
|
+
hour=int(line[13:15]),
|
|
56
|
+
minute=int(line[16:18]),
|
|
57
|
+
second=int(line[19:21]),
|
|
58
|
+
microsecond=int(line[22:28]),
|
|
59
|
+
)
|
|
60
|
+
)
|
|
61
|
+
# 读取策略 2
|
|
62
|
+
if start is None:
|
|
63
|
+
start = have[0]
|
|
64
|
+
if isinstance(interval, int) or isinstance(interval, float):
|
|
65
|
+
interval = datetime.timedelta(seconds=interval)
|
|
66
|
+
# 读取策略 4
|
|
67
|
+
if interval is None:
|
|
68
|
+
temp = []
|
|
69
|
+
for i, j in zip(have[1:], have[:-1]):
|
|
70
|
+
temp.append(i - j)
|
|
71
|
+
interval = min(temp)
|
|
72
|
+
# 读取策略 3
|
|
73
|
+
if end is None:
|
|
74
|
+
end = have[-1] + interval
|
|
75
|
+
expt = [(start + interval * i) for i in range((end - start) // interval)]
|
|
76
|
+
have, expt = pd.Series(have), pd.Series(expt)
|
|
77
|
+
use = expt[expt.isin(have)]
|
|
78
|
+
# 读取策略 7
|
|
79
|
+
if use.empty:
|
|
80
|
+
raise ValueError("Invalid time range.")
|
|
81
|
+
# --------第二次读取:存储卫星数据--------
|
|
82
|
+
# 读取策略 6
|
|
83
|
+
epoch = (use.index + 1).values
|
|
84
|
+
use.reset_index(drop=True, inplace=True)
|
|
85
|
+
cnr_buf = []
|
|
86
|
+
with open(logfpath, "r") as fr:
|
|
87
|
+
idx = 0
|
|
88
|
+
flag = 0 # 当前时间节点未记录存储的卫星数
|
|
89
|
+
for line in fr:
|
|
90
|
+
# 将卫星数据一颗颗写入缓存
|
|
91
|
+
if flag != 0:
|
|
92
|
+
data = line.split()
|
|
93
|
+
row = [use[idx].isoformat(), epoch[idx], data[0], float(data[1])]
|
|
94
|
+
obsn = int(data[3]) // 2
|
|
95
|
+
for i in range(obsn):
|
|
96
|
+
row.append("S" + data[4 + i * 6][1:3]) # 更正观测类型代码
|
|
97
|
+
row.append(float(data[6 + i * 6]))
|
|
98
|
+
cnr_buf.append(row)
|
|
99
|
+
flag -= 1
|
|
100
|
+
if flag == 0:
|
|
101
|
+
idx += 1
|
|
102
|
+
if line.startswith(">"):
|
|
103
|
+
if idx == use.size:
|
|
104
|
+
break
|
|
105
|
+
moment = datetime.datetime(
|
|
106
|
+
year=int(line[2:6]),
|
|
107
|
+
month=int(line[7:9]),
|
|
108
|
+
day=int(line[10:12]),
|
|
109
|
+
hour=int(line[13:15]),
|
|
110
|
+
minute=int(line[16:18]),
|
|
111
|
+
second=int(line[19:21]),
|
|
112
|
+
microsecond=int(line[22:28]),
|
|
113
|
+
)
|
|
114
|
+
if moment == use[idx]:
|
|
115
|
+
flag = int(line[30:32])
|
|
116
|
+
cnr = pd.DataFrame(cnr_buf)
|
|
117
|
+
# 读取策略 5, 8
|
|
118
|
+
if 0.0 <= ele_cut <= 90.0:
|
|
119
|
+
cnr = cnr[cnr[3] >= ele_cut]
|
|
120
|
+
else:
|
|
121
|
+
raise ValueError("Invalid elevation angle cut-off.")
|
|
122
|
+
cnrfpath = logfpath + ".cnr"
|
|
123
|
+
result[cnrfpath] = cnr
|
|
124
|
+
|
|
125
|
+
if not isinstance(save, bool):
|
|
126
|
+
for cnr, cnrfpath in zip(result.values(), save):
|
|
127
|
+
cnr.to_csv(cnrfpath, index=False, header=False)
|
|
128
|
+
elif save:
|
|
129
|
+
for cnr, logfpath in zip(result.values(), read):
|
|
130
|
+
cnrfpath = f"{logfpath}.cnr"
|
|
131
|
+
cnr.to_csv(cnrfpath, index=False, header=False)
|
|
132
|
+
|
|
133
|
+
return result
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def rnx2cnr(
|
|
137
|
+
read: list[str],
|
|
138
|
+
save: list[str] | bool = False,
|
|
139
|
+
start: datetime.datetime | None = None,
|
|
140
|
+
end: datetime.datetime | None = None,
|
|
141
|
+
interval: datetime.timedelta | float | int | None = None,
|
|
142
|
+
ele_cut: float = 0.0,
|
|
143
|
+
) -> dict[str, pd.DataFrame]:
|
|
144
|
+
"""将 RINEX V3 OBS 文件转换为 CNR 格式."""
|
|
145
|
+
result = {}
|
|
146
|
+
for rnxfpath in read:
|
|
147
|
+
# -------- Round 1 --------
|
|
148
|
+
tna = {}
|
|
149
|
+
have = []
|
|
150
|
+
with open(rnxfpath, "r") as fr:
|
|
151
|
+
line0_buf = " "
|
|
152
|
+
for line in fr:
|
|
153
|
+
if "SYS / # / OBS TYPES" in line:
|
|
154
|
+
temp = line[7:59].split()
|
|
155
|
+
if line[0] != " ":
|
|
156
|
+
tna[line[0]] = temp
|
|
157
|
+
line0_buf = line[0]
|
|
158
|
+
else:
|
|
159
|
+
tna[line0_buf] += temp
|
|
160
|
+
if line.startswith(">"):
|
|
161
|
+
have.append(
|
|
162
|
+
datetime.datetime(
|
|
163
|
+
year=int(line[2:6]),
|
|
164
|
+
month=int(line[7:9]),
|
|
165
|
+
day=int(line[10:12]),
|
|
166
|
+
hour=int(line[13:15]),
|
|
167
|
+
minute=int(line[16:18]),
|
|
168
|
+
second=int(line[19:21]),
|
|
169
|
+
microsecond=int(line[22:28]),
|
|
170
|
+
)
|
|
171
|
+
)
|
|
172
|
+
if start is None:
|
|
173
|
+
start = have[0]
|
|
174
|
+
if isinstance(interval, int) or isinstance(interval, float):
|
|
175
|
+
interval = datetime.timedelta(seconds=interval)
|
|
176
|
+
if interval is None:
|
|
177
|
+
temp = []
|
|
178
|
+
for i, j in zip(have[1:], have[:-1]):
|
|
179
|
+
temp.append(i - j)
|
|
180
|
+
interval = min(temp)
|
|
181
|
+
if end is None:
|
|
182
|
+
end = have[-1] + interval
|
|
183
|
+
expt = [(start + interval * i) for i in range((end - start) // interval)]
|
|
184
|
+
have, expt = pd.Series(have), pd.Series(expt)
|
|
185
|
+
use = expt[expt.isin(have)]
|
|
186
|
+
if use.empty:
|
|
187
|
+
raise ValueError("Invalid time range.")
|
|
188
|
+
# -------- Round 2 --------
|
|
189
|
+
epoch = (use.index + 1).values
|
|
190
|
+
use.reset_index(drop=True, inplace=True)
|
|
191
|
+
cnr_buf = []
|
|
192
|
+
with open(rnxfpath, "r") as fr:
|
|
193
|
+
idx = 0
|
|
194
|
+
flag = 0
|
|
195
|
+
tna_val = {}
|
|
196
|
+
for line in fr:
|
|
197
|
+
if flag != 0:
|
|
198
|
+
tna_val[line[0]] = [
|
|
199
|
+
line[i : (i + 16)] for i in range(1, len(line), 16)
|
|
200
|
+
]
|
|
201
|
+
row = [
|
|
202
|
+
use[idx].isoformat(),
|
|
203
|
+
epoch[idx],
|
|
204
|
+
line[0:3],
|
|
205
|
+
90.0,
|
|
206
|
+
] # TODO: 90.0
|
|
207
|
+
for i, tna_label in enumerate(tna[line[0]]):
|
|
208
|
+
if tna_label.startswith("S"):
|
|
209
|
+
row.append(tna[line[0]][i])
|
|
210
|
+
val = tna_val[line[0]][i][10:16].replace(" ", "")
|
|
211
|
+
val = float(val) if val != "" else None
|
|
212
|
+
row.append(val)
|
|
213
|
+
cnr_buf.append(row)
|
|
214
|
+
flag -= 1
|
|
215
|
+
if flag == 0:
|
|
216
|
+
idx += 1
|
|
217
|
+
if line.startswith(">"):
|
|
218
|
+
if idx == use.size:
|
|
219
|
+
break
|
|
220
|
+
moment = datetime.datetime(
|
|
221
|
+
year=int(line[2:6]),
|
|
222
|
+
month=int(line[7:9]),
|
|
223
|
+
day=int(line[10:12]),
|
|
224
|
+
hour=int(line[13:15]),
|
|
225
|
+
minute=int(line[16:18]),
|
|
226
|
+
second=int(line[19:21]),
|
|
227
|
+
microsecond=int(line[22:28]),
|
|
228
|
+
)
|
|
229
|
+
if moment == use[idx]:
|
|
230
|
+
flag = int(line[33:35])
|
|
231
|
+
cnr = pd.DataFrame(cnr_buf)
|
|
232
|
+
if 0.0 <= ele_cut <= 90.0:
|
|
233
|
+
cnr = cnr[cnr[3] >= ele_cut]
|
|
234
|
+
else:
|
|
235
|
+
raise ValueError("Invalid elevation angle cut-off.")
|
|
236
|
+
cnrfpath = rnxfpath + ".cnr"
|
|
237
|
+
result[cnrfpath] = cnr
|
|
238
|
+
|
|
239
|
+
if not isinstance(save, bool):
|
|
240
|
+
for cnr, cnrfpath in zip(result.values(), save):
|
|
241
|
+
cnr.to_csv(cnrfpath, index=False, header=False)
|
|
242
|
+
elif save:
|
|
243
|
+
for cnr, rnxfpath in zip(result.values(), read):
|
|
244
|
+
cnrfpath = f"{rnxfpath}.cnr"
|
|
245
|
+
cnr.to_csv(cnrfpath, index=False, header=False)
|
|
246
|
+
|
|
247
|
+
return result
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
def cnr2dcnr(
|
|
251
|
+
read: list[str] | dict[str, pd.DataFrame],
|
|
252
|
+
save: list[str] | bool = False,
|
|
253
|
+
plot: list[str] | bool = False,
|
|
254
|
+
how: Literal["MEAN", "MAX"] = "MEAN",
|
|
255
|
+
by: Literal["PRN", "SYS"] = "PRN",
|
|
256
|
+
) -> dict[str, pd.DataFrame]:
|
|
257
|
+
"""根据提供的 CNR 文件或缓存计算相应载噪比的差值.
|
|
258
|
+
|
|
259
|
+
Parameters:
|
|
260
|
+
read (list[str] | dict[str, pd.DataFrame]): 需要读取的 CNR 文件列表或 CNR 文件数据缓存.
|
|
261
|
+
save (list[str] | bool, optional): 需要保存的 DCNR 文件列表或是否保存.
|
|
262
|
+
plot (list[str] | bool, optional): 需要绘图的 DCNR 文件列表或是否绘图.
|
|
263
|
+
how (Literal["MEAN", "MAX"], optional): 计算差值的方式.
|
|
264
|
+
by (Literal["PRN", "SYS"], optional): 计算差值的方式.
|
|
265
|
+
|
|
266
|
+
Returns:
|
|
267
|
+
dict[str, pd.DataFrame]: DCNR 文件数据缓存.
|
|
268
|
+
"""
|
|
269
|
+
if len(read) == 0:
|
|
270
|
+
return {}
|
|
271
|
+
# get raw dcnr
|
|
272
|
+
if isinstance(read, dict):
|
|
273
|
+
raw_cnr = read
|
|
274
|
+
else:
|
|
275
|
+
raw_cnr = {}
|
|
276
|
+
for cnrfpath in read:
|
|
277
|
+
raw_cnr[cnrfpath] = pd.read_csv(cnrfpath, header=None)
|
|
278
|
+
# get pivoted dcnr
|
|
279
|
+
pivoted_cnr = []
|
|
280
|
+
for cnrfdata in raw_cnr.values():
|
|
281
|
+
match by:
|
|
282
|
+
case "PRN":
|
|
283
|
+
cnrfdata.rename(columns={2: by}, inplace=True)
|
|
284
|
+
buffer = []
|
|
285
|
+
for i in range(4, cnrfdata.shape[1], 2):
|
|
286
|
+
pc_i = cnrfdata.pivot(index=[by, 0], columns=i, values=(i + 1))
|
|
287
|
+
buffer.append(pc_i)
|
|
288
|
+
case "SYS":
|
|
289
|
+
cnrfdata[1] = cnrfdata[2].str[0]
|
|
290
|
+
cnrfdata.rename(columns={1: by}, inplace=True)
|
|
291
|
+
buffer = []
|
|
292
|
+
for i in range(4, cnrfdata.shape[1], 2):
|
|
293
|
+
pc_i = cnrfdata.pivot(index=[by, 2, 0], columns=i, values=(i + 1))
|
|
294
|
+
buffer.append(pc_i)
|
|
295
|
+
match how:
|
|
296
|
+
case "MEAN":
|
|
297
|
+
pc = pd.concat(buffer).groupby(level=by).mean(numeric_only=True)
|
|
298
|
+
case "MAX":
|
|
299
|
+
pc = pd.concat(buffer).groupby(level=by).max(numeric_only=True)
|
|
300
|
+
pc.dropna(axis=1, how="all", inplace=True)
|
|
301
|
+
pivoted_cnr.append(pc)
|
|
302
|
+
# calculate and save dcnr
|
|
303
|
+
dcnr = {}
|
|
304
|
+
if not isinstance(save, bool):
|
|
305
|
+
dcnr[save[0]] = pivoted_cnr[0]
|
|
306
|
+
for i, pc in enumerate(pivoted_cnr[1:], 1):
|
|
307
|
+
dcnr[save[i]] = pc - pivoted_cnr[0]
|
|
308
|
+
for dcnrfpath, dcnrfdata in dcnr.items():
|
|
309
|
+
dcnrfdata.to_csv(dcnrfpath)
|
|
310
|
+
elif save:
|
|
311
|
+
save = [f"{cnrfpath}.dcnr" for cnrfpath in raw_cnr.keys()]
|
|
312
|
+
dcnr[save[0]] = pivoted_cnr[0]
|
|
313
|
+
for i, pc in enumerate(pivoted_cnr[1:], 1):
|
|
314
|
+
dcnr[save[i]] = pc - pivoted_cnr[0]
|
|
315
|
+
for dcnrfpath, dcnrfdata in dcnr.items():
|
|
316
|
+
dcnrfdata.to_csv(dcnrfpath)
|
|
317
|
+
else:
|
|
318
|
+
save = [f"{cnrfpath}.dcnr" for cnrfpath in raw_cnr.keys()]
|
|
319
|
+
dcnr[save[0]] = pivoted_cnr[0]
|
|
320
|
+
for i, pc in enumerate(pivoted_cnr[1:], 1):
|
|
321
|
+
dcnr[save[i]] = pc - pivoted_cnr[0]
|
|
322
|
+
# plot dcnr
|
|
323
|
+
if not isinstance(plot, bool):
|
|
324
|
+
for dcnrfpath, dcnrfdata in dcnr.items():
|
|
325
|
+
dcnrfdata.plot(king="bar", title=dcnrfpath)
|
|
326
|
+
plt.savefig(dcnrfpath + ".png")
|
|
327
|
+
elif plot:
|
|
328
|
+
for dcnrfpath, dcnrfdata in dcnr.items():
|
|
329
|
+
dcnrfdata.plot(kind="bar", title=dcnrfpath)
|
|
330
|
+
plt.tight_layout()
|
|
331
|
+
plt.show()
|
|
332
|
+
|
|
333
|
+
return dcnr
|
|
334
|
+
|
|
335
|
+
|
|
336
|
+
def dcnr2xlsx(read: list[list[str]] | list[dict[str, pd.DataFrame]], save: str) -> None:
|
|
337
|
+
workbook = []
|
|
338
|
+
if isinstance(read[0], dict):
|
|
339
|
+
workbook = read
|
|
340
|
+
else:
|
|
341
|
+
for dcnrflist in read:
|
|
342
|
+
dcnr = {}
|
|
343
|
+
for dcnrfpath in dcnrflist:
|
|
344
|
+
dcnr[dcnrfpath] = pd.read_csv(dcnrfpath, index_col=0)
|
|
345
|
+
workbook.append(dcnr)
|
|
346
|
+
with pd.ExcelWriter(save) as writer:
|
|
347
|
+
for sheet_i, dcnr in enumerate(workbook, 1):
|
|
348
|
+
buffer = []
|
|
349
|
+
for dcnrfpath, dcnrfdata in dcnr.items():
|
|
350
|
+
dcnrfname = os.path.basename(dcnrfpath).split(".")[0]
|
|
351
|
+
buffer.append(dcnrfdata.stack().rename(dcnrfname))
|
|
352
|
+
pd.concat(buffer, axis=1).to_excel(writer, sheet_name=f"Group {sheet_i}")
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: cnrdiff
|
|
3
|
+
Version: 1.2.0
|
|
4
|
+
Summary: A library used to compare signal-to-noise ratio
|
|
5
|
+
Home-page: https://github.com/sinognss/cnrdiff
|
|
6
|
+
Author: Sheng Guoliang
|
|
7
|
+
Author-email: Sheng Guoliang <shengguoliang@sinognss.com>, Yang Fawang <yangfawang@sinognss.com>
|
|
8
|
+
License: MIT
|
|
9
|
+
Project-URL: Homepage, https://github.com/sinognss/cnrdiff
|
|
10
|
+
Project-URL: Repository, https://github.com/sinognss/cnrdiff
|
|
11
|
+
Project-URL: Issues, https://github.com/sinognss/cnrdiff/issues
|
|
12
|
+
Keywords: cnr,signal-to-noise,gnss,rinex,bnc
|
|
13
|
+
Classifier: Intended Audience :: Science/Research
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Topic :: Scientific/Engineering
|
|
21
|
+
Requires-Python: >=3.10
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
Requires-Dist: pandas>=2.0.0
|
|
24
|
+
Requires-Dist: matplotlib>=3.7.0
|
|
25
|
+
Dynamic: author
|
|
26
|
+
Dynamic: home-page
|
|
27
|
+
Dynamic: requires-python
|
|
28
|
+
|
|
29
|
+
# CNRDIFF
|
|
30
|
+
|
|
31
|
+
A library used to compare signal-to-noise ratio.
|
|
32
|
+
|
|
33
|
+
Include CNR file format conversion, difference calculation and plotting.
|
|
34
|
+
|
|
35
|
+
*There is a GUI version available for Windows users. See [Release](https://github.com/kongolou/cnrdiff/releases).*
|
|
36
|
+
|
|
37
|
+
**Lead Programmer:**
|
|
38
|
+
- Sheng Guoliang <shengguoliang@sinognss.com>
|
|
39
|
+
|
|
40
|
+
**Contributors:**
|
|
41
|
+
- Yang Fawang <yangfawang@sinognss.com>
|
|
42
|
+
- Wang Xiaobing <wangxiaobing@sinognss.com>
|
|
43
|
+
|
|
44
|
+
## History
|
|
45
|
+
| Date | Version Info |
|
|
46
|
+
|------------|--------------|
|
|
47
|
+
| 2024-11-20 | 1.0 Released |
|
|
48
|
+
| 2024-11-29 | 1.1 Released |
|
|
49
|
+
| 2024-12-05 | 1.2 Released |
|
|
50
|
+
|
|
51
|
+
# Examples
|
|
52
|
+
The following examples use BNC QC LOG files. Note that RINEX V3 OBS files are also supported.
|
|
53
|
+
|
|
54
|
+
## Convert to CNR file
|
|
55
|
+
```python
|
|
56
|
+
cnrs = cnrdiff.log2cnr(['0002295h.log'])
|
|
57
|
+
print(cnrs['0002295h.log.cnr'])
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
**Output:**
|
|
61
|
+
```
|
|
62
|
+
0 1 2 3 4 5 6 7 8 9 10 11
|
|
63
|
+
0 2024-10-21T08:00:00 1 G03 0.00 S1C 40.0 S2C 45.0 S2W 40.0 S5I 46.0
|
|
64
|
+
1 2024-10-21T08:00:00 1 G16 0.00 S1C 44.0 S2W 34.0 None NaN None NaN
|
|
65
|
+
2 2024-10-21T08:00:00 1 G26 72.19 S1C 48.0 S2C 48.0 S2W 49.0 S5I 49.0
|
|
66
|
+
3 2024-10-21T08:00:00 1 G28 54.10 S1C 44.0 S2C 49.0 S2W 36.0 S5I 49.0
|
|
67
|
+
4 2024-10-21T08:00:00 1 G29 29.28 S1C 38.0 S2C 33.0 S2W 23.0 None NaN
|
|
68
|
+
... ... ... ... ... ... ... ... ... ... ... ... ...
|
|
69
|
+
154214 2024-10-21T09:00:00 3601 C39 69.81 S2I 49.0 S6I 47.0 None NaN None NaN
|
|
70
|
+
154215 2024-10-21T09:00:00 3601 C40 50.54 S2I 47.0 S6I 47.0 None NaN None NaN
|
|
71
|
+
154216 2024-10-21T09:00:00 3601 C45 40.91 S2I 47.0 S6I 49.0 None NaN None NaN
|
|
72
|
+
154217 2024-10-21T09:00:00 3601 C59 47.34 S2I 47.0 S6I 48.0 None NaN None NaN
|
|
73
|
+
154218 2024-10-21T09:00:00 3601 C60 31.67 S2I 43.0 S6I 45.0 None NaN None NaN
|
|
74
|
+
|
|
75
|
+
[154219 rows x 12 columns]
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Calculate difference with default parameters (mean of all epochs)
|
|
79
|
+
```python
|
|
80
|
+
logflist = ['0002295h.log', '0005295h.log', '0041295h.log']
|
|
81
|
+
cnrs = cnrdiff.log2cnr(logflist)
|
|
82
|
+
dcnrs = cnrdiff.cnr2dcnr(cnrs)
|
|
83
|
+
print(dcnrs['0005295h.log.cnr.dcnr'])
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
**Output:**
|
|
87
|
+
```
|
|
88
|
+
S1C S1X S2C S2I S2P S6I S7I S2W S5I S5X S7X
|
|
89
|
+
PRN
|
|
90
|
+
C01 NaN NaN NaN -0.940572 NaN 0.085532 -0.843655 NaN NaN NaN NaN
|
|
91
|
+
C02 NaN NaN NaN -1.191891 NaN 0.429325 -0.875868 NaN NaN NaN NaN
|
|
92
|
+
C03 NaN NaN NaN -0.871425 NaN 0.767287 -0.167453 NaN NaN NaN NaN
|
|
93
|
+
C04 NaN NaN NaN -1.157456 NaN -0.718967 -0.314079 NaN NaN NaN NaN
|
|
94
|
+
C06 NaN NaN NaN -0.649542 NaN 0.709525 -0.185782 NaN NaN NaN NaN
|
|
95
|
+
C07 NaN NaN NaN -0.628992 NaN -0.109414 -0.797001 NaN NaN NaN NaN
|
|
96
|
+
C08 NaN NaN NaN -7.029925 NaN -7.659138 -8.090604 NaN NaN NaN NaN
|
|
97
|
+
C09 NaN NaN NaN -0.430158 NaN 0.553180 -0.311580 NaN NaN NaN NaN
|
|
98
|
+
C10 NaN NaN NaN -0.613441 NaN -0.668148 -1.409331 NaN NaN NaN NaN
|
|
99
|
+
C13 NaN NaN NaN -0.420030 NaN -0.170935 -1.856699 NaN NaN NaN NaN
|
|
100
|
+
C16 NaN NaN NaN -0.250764 NaN 0.668981 -0.287420 NaN NaN NaN NaN
|
|
101
|
+
C19 NaN NaN NaN -0.715357 NaN -0.722855 NaN NaN NaN NaN NaN
|
|
102
|
+
C21 NaN NaN NaN -0.637597 NaN -0.221556 NaN NaN NaN NaN NaN
|
|
103
|
+
C22 NaN NaN NaN -1.140517 NaN 0.246876 NaN NaN NaN NaN NaN
|
|
104
|
+
C27 NaN NaN NaN -0.660690 NaN 0.482968 NaN NaN NaN NaN NaN
|
|
105
|
+
C29 NaN NaN NaN -1.968718 NaN -0.774428 NaN NaN NaN NaN NaN
|
|
106
|
+
C30 NaN NaN NaN -1.069425 NaN -0.106082 NaN NaN NaN NaN NaN
|
|
107
|
+
C36 NaN NaN NaN -0.360178 NaN 0.860317 NaN NaN NaN NaN NaN
|
|
108
|
+
C38 NaN NaN NaN -1.204633 NaN -0.822394 NaN NaN NaN NaN NaN
|
|
109
|
+
C39 NaN NaN NaN -0.246876 NaN 0.602888 NaN NaN NaN NaN NaN
|
|
110
|
+
C40 NaN NaN NaN -0.486254 NaN -0.064704 NaN NaN NaN NaN NaN
|
|
111
|
+
C45 NaN NaN NaN -1.191613 NaN -0.384615 NaN NaN NaN NaN NaN
|
|
112
|
+
C59 NaN NaN NaN -0.490419 NaN 0.075257 NaN NaN NaN NaN NaN
|
|
113
|
+
C60 NaN NaN NaN -0.384060 NaN -1.341294 NaN NaN NaN NaN NaN
|
|
114
|
+
E02 NaN 0.028881 NaN NaN NaN NaN NaN NaN NaN 0.704249 0.470425
|
|
115
|
+
E03 NaN -1.054074 NaN NaN NaN NaN NaN NaN NaN 0.616438 -0.138428
|
|
116
|
+
E07 NaN -0.602333 NaN NaN NaN NaN NaN NaN NaN 0.645376 0.058595
|
|
117
|
+
E08 NaN -0.708137 NaN NaN NaN NaN NaN NaN NaN 0.638156 -0.257706
|
|
118
|
+
E27 NaN -0.317690 NaN NaN NaN NaN NaN NaN NaN -0.507359 -1.391002
|
|
119
|
+
E29 NaN -0.891760 NaN NaN NaN NaN NaN NaN NaN -0.697708 -1.014139
|
|
120
|
+
E30 NaN -0.801444 NaN NaN NaN NaN NaN NaN NaN 0.892252 0.099417
|
|
121
|
+
G03 -1.185782 NaN -1.468857 NaN NaN NaN NaN -1.909297 -0.956679 NaN NaN
|
|
122
|
+
G04 -1.012480 NaN -1.029914 NaN NaN NaN NaN -1.265208 -0.205828 NaN NaN
|
|
123
|
+
G16 -1.130242 NaN NaN NaN NaN NaN NaN -1.521244 NaN NaN NaN
|
|
124
|
+
G26 -0.423493 NaN 0.109136 NaN NaN NaN NaN -0.277978 0.285754 NaN NaN
|
|
125
|
+
G27 -0.928958 NaN -1.408960 NaN NaN NaN NaN -2.466618 -0.895877 NaN NaN
|
|
126
|
+
G28 -0.141905 NaN 0.383505 NaN NaN NaN NaN 0.147459 0.844210 NaN NaN
|
|
127
|
+
G29 -1.328652 NaN -0.748343 NaN NaN NaN NaN -1.765429 NaN NaN NaN
|
|
128
|
+
G31 -0.170786 NaN 0.321577 NaN NaN NaN NaN 0.034713 NaN NaN NaN
|
|
129
|
+
G32 -1.343793 NaN -0.820605 NaN NaN NaN NaN -2.168564 -0.294085 NaN NaN
|
|
130
|
+
R04 -0.536518 NaN NaN NaN -1.141905 NaN NaN NaN NaN NaN NaN
|
|
131
|
+
R05 -0.286865 NaN NaN NaN 0.102194 NaN NaN NaN NaN NaN NaN
|
|
132
|
+
R06 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
|
|
133
|
+
R14 -1.866949 NaN NaN NaN -1.413515 NaN NaN NaN NaN NaN NaN
|
|
134
|
+
R15 -0.825326 NaN NaN NaN 0.395446 NaN NaN NaN NaN NaN NaN
|
|
135
|
+
R16 -2.187170 NaN NaN NaN -0.758400 NaN NaN NaN NaN NaN NaN
|
|
136
|
+
R17 -0.660695 NaN NaN NaN -0.220414 NaN NaN NaN NaN NaN NaN
|
|
137
|
+
R18 -2.040590 NaN NaN NaN 0.568744 NaN NaN NaN NaN NaN NaN
|
|
138
|
+
R24 -1.121621 NaN NaN NaN -0.724670 NaN NaN NaN NaN NaN NaN
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## Calculate difference with custom parameters
|
|
142
|
+
```python
|
|
143
|
+
logflist = ['11121980.24O', '11131980.24O']
|
|
144
|
+
dcnrflist = ['11121980.csv', '11131980.csv']
|
|
145
|
+
start = datetime.datetime(2024, 7, 16, 9, 0, 0)
|
|
146
|
+
end = datetime.datetime(2024, 7, 16, 10, 0, 0)
|
|
147
|
+
interval = 5
|
|
148
|
+
ele_cut = 20.0
|
|
149
|
+
cnrdiff.log2cnr(logflist, save=False, start=start, end=end, interval=interval, ele_cut=ele_cut)
|
|
150
|
+
cnrdiff.cnr2dcnr(cnrflist, save=dcnrflist, plot=True, how='MAX', by='SYS')
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## Convert DCNR to XLSX file
|
|
154
|
+
```python
|
|
155
|
+
>>> dcnrflist1 = ['0002295h.log.cnr.dcnr', '0005295h.log.cnr.dcnr', '0041295h.log.cnr.dcnr']
|
|
156
|
+
>>> dcnrflist2 = ['11121980.csv', '11131980.csv']
|
|
157
|
+
>>> cnrdiff.dcnr2xlsx([dcnrflist1, dcnrflist2], 'summary.xlsx')
|
|
158
|
+
```
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
cnrdiff
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "cnrdiff"
|
|
7
|
+
version = "1.2.0"
|
|
8
|
+
description = "A library used to compare signal-to-noise ratio"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = {text = "MIT"}
|
|
11
|
+
requires-python = ">=3.10"
|
|
12
|
+
authors = [
|
|
13
|
+
{name = "Sheng Guoliang", email = "shengguoliang@sinognss.com"},
|
|
14
|
+
{name = "Yang Fawang", email = "yangfawang@sinognss.com"},
|
|
15
|
+
]
|
|
16
|
+
keywords = ["cnr", "signal-to-noise", "gnss", "rinex", "bnc"]
|
|
17
|
+
classifiers = [
|
|
18
|
+
"Intended Audience :: Science/Research",
|
|
19
|
+
"License :: OSI Approved :: MIT License",
|
|
20
|
+
"Programming Language :: Python :: 3",
|
|
21
|
+
"Programming Language :: Python :: 3.10",
|
|
22
|
+
"Programming Language :: Python :: 3.11",
|
|
23
|
+
"Programming Language :: Python :: 3.12",
|
|
24
|
+
"Programming Language :: Python :: 3.13",
|
|
25
|
+
"Topic :: Scientific/Engineering",
|
|
26
|
+
]
|
|
27
|
+
dependencies = [
|
|
28
|
+
"pandas>=2.0.0",
|
|
29
|
+
"matplotlib>=3.7.0",
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
[project.urls]
|
|
33
|
+
Homepage = "https://github.com/sinognss/cnrdiff"
|
|
34
|
+
Repository = "https://github.com/sinognss/cnrdiff"
|
|
35
|
+
Issues = "https://github.com/sinognss/cnrdiff/issues"
|
|
36
|
+
|
|
37
|
+
[tool.setuptools.packages.find]
|
|
38
|
+
where = ["."]
|
|
39
|
+
include = ["cnrdiff*"]
|
cnrdiff-1.2.0/setup.cfg
ADDED
cnrdiff-1.2.0/setup.py
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
from setuptools import setup, find_packages
|
|
2
|
+
|
|
3
|
+
setup(
|
|
4
|
+
name="cnrdiff",
|
|
5
|
+
version="1.2.0",
|
|
6
|
+
description="A library used to compare signal-to-noise ratio",
|
|
7
|
+
long_description=open("README.md", encoding="utf-8").read(),
|
|
8
|
+
long_description_content_type="text/markdown",
|
|
9
|
+
license="MIT",
|
|
10
|
+
author="Sheng Guoliang",
|
|
11
|
+
author_email="shengguoliang@sinognss.com",
|
|
12
|
+
python_requires=">=3.10",
|
|
13
|
+
packages=find_packages(where=".", include=["cnrdiff*"]),
|
|
14
|
+
install_requires=[
|
|
15
|
+
"pandas>=2.0.0",
|
|
16
|
+
"matplotlib>=3.7.0",
|
|
17
|
+
],
|
|
18
|
+
keywords=["cnr", "signal-to-noise", "gnss", "rinex", "bnc"],
|
|
19
|
+
classifiers=[
|
|
20
|
+
"Intended Audience :: Science/Research",
|
|
21
|
+
"License :: OSI Approved :: MIT License",
|
|
22
|
+
"Programming Language :: Python :: 3",
|
|
23
|
+
"Programming Language :: Python :: 3.10",
|
|
24
|
+
"Programming Language :: Python :: 3.11",
|
|
25
|
+
"Programming Language :: Python :: 3.12",
|
|
26
|
+
"Programming Language :: Python :: 3.13",
|
|
27
|
+
"Topic :: Scientific/Engineering",
|
|
28
|
+
],
|
|
29
|
+
url="https://github.com/sinognss/cnrdiff",
|
|
30
|
+
project_urls={
|
|
31
|
+
"Homepage": "https://github.com/sinognss/cnrdiff",
|
|
32
|
+
"Repository": "https://github.com/sinognss/cnrdiff",
|
|
33
|
+
"Issues": "https://github.com/sinognss/cnrdiff/issues",
|
|
34
|
+
},
|
|
35
|
+
)
|