visidata-pdr 0.1.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.
@@ -0,0 +1,28 @@
1
+ # BSD 3-Clause License
2
+
3
+ Copyright (c) 2026, Million Concepts. All rights reserved.
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions are met:
7
+
8
+ 1. Redistributions of source code must retain the above copyright notice, this
9
+ list of conditions and the following disclaimer.
10
+
11
+ 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ this list of conditions and the following disclaimer in the documentation
13
+ and/or other materials provided with the distribution.
14
+
15
+ 3. Neither the name of the copyright holder nor the names of its
16
+ contributors may be used to endorse or promote products derived from
17
+ this software without specific prior written permission.
18
+
19
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,4 @@
1
+ include sample_data/**/*.CSV
2
+ include sample_data/**/*.LBL
3
+ include tests/*.vdj
4
+ include tests/golden/*.tsv
@@ -0,0 +1,47 @@
1
+ Metadata-Version: 2.4
2
+ Name: visidata_pdr
3
+ Version: 0.1.0
4
+ Summary: Load tabular data understood by PDR into VisiData
5
+ Author-email: Zack Weinberg <zack@millionconcepts.com>
6
+ License-Expression: BSD-3-Clause
7
+ Project-URL: Repository, https://github.com/MillionConcepts/visidata-pdr
8
+ Classifier: Development Status :: 3 - Alpha
9
+ Classifier: Environment :: Console
10
+ Classifier: Environment :: Console :: Curses
11
+ Classifier: Operating System :: OS Independent
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Intended Audience :: Science/Research
14
+ Classifier: Topic :: Scientific/Engineering :: Astronomy
15
+ Classifier: Topic :: Scientific/Engineering :: Visualization
16
+ Requires-Python: >=3.11
17
+ Description-Content-Type: text/markdown
18
+ License-File: LICENSE.md
19
+ Requires-Dist: pdr[fits,pillow,pvl]>=1.4.4
20
+ Requires-Dist: visidata>=3.3
21
+ Dynamic: license-file
22
+
23
+ # visidata_pdr: Load tabular data into VisiData using PDR
24
+
25
+ This [VisiData][] plugin adds a loader that can load any type of tabular
26
+ data understood by the [Planetary Data Reader][PDR] (PDR).
27
+
28
+ [VisiData]: https://www.visidata.org/
29
+ [PDR]: https://github.com/MillionConcepts/pdr
30
+
31
+ ## Usage
32
+
33
+ After installing the plugin, the `pdr` loader can read any data file
34
+ that `pdr.open()` would understand. For example, suppose you have
35
+ downloaded the [Mars Global Surveyor][]’s
36
+ [Thermal Emission Spectrometer data set][] and you want to look at
37
+ the first batch of data (MY24; 1999-02-28T21):
38
+
39
+ ```
40
+ $ vd -f pdr TES_COD_IR_MY24_Ls090_Ls120.xml
41
+ ```
42
+
43
+ It would also work to specify the `.dat` file. Either way, both the
44
+ data and the label must be available.
45
+
46
+ [Mars Global Surveyor]: https://atmos.nmsu.edu/data_and_services/atmospheres_data/MARS/mgs.html
47
+ [Thermal Emission Spectrometer data set]: https://atmos.nmsu.edu/data_and_services/atmospheres_data/MARS/montabone.html
@@ -0,0 +1,25 @@
1
+ # visidata_pdr: Load tabular data into VisiData using PDR
2
+
3
+ This [VisiData][] plugin adds a loader that can load any type of tabular
4
+ data understood by the [Planetary Data Reader][PDR] (PDR).
5
+
6
+ [VisiData]: https://www.visidata.org/
7
+ [PDR]: https://github.com/MillionConcepts/pdr
8
+
9
+ ## Usage
10
+
11
+ After installing the plugin, the `pdr` loader can read any data file
12
+ that `pdr.open()` would understand. For example, suppose you have
13
+ downloaded the [Mars Global Surveyor][]’s
14
+ [Thermal Emission Spectrometer data set][] and you want to look at
15
+ the first batch of data (MY24; 1999-02-28T21):
16
+
17
+ ```
18
+ $ vd -f pdr TES_COD_IR_MY24_Ls090_Ls120.xml
19
+ ```
20
+
21
+ It would also work to specify the `.dat` file. Either way, both the
22
+ data and the label must be available.
23
+
24
+ [Mars Global Surveyor]: https://atmos.nmsu.edu/data_and_services/atmospheres_data/MARS/mgs.html
25
+ [Thermal Emission Spectrometer data set]: https://atmos.nmsu.edu/data_and_services/atmospheres_data/MARS/montabone.html
@@ -0,0 +1,107 @@
1
+ # pyproject.toml documentation for reference:
2
+ # https://packaging.python.org/en/latest/
3
+ # https://setuptools.pypa.io/en/latest/userguide/
4
+
5
+ [project]
6
+ name = "visidata_pdr"
7
+ version = "0.1.0"
8
+ description = "Load tabular data understood by PDR into VisiData"
9
+ readme = "README.md"
10
+ license = "BSD-3-Clause"
11
+ license-files = ["LICENSE.md"]
12
+
13
+ authors = [
14
+ { name = "Zack Weinberg", email = "zack@millionconcepts.com" },
15
+ ]
16
+
17
+ classifiers = [
18
+ "Development Status :: 3 - Alpha",
19
+ "Environment :: Console",
20
+ "Environment :: Console :: Curses",
21
+ "Operating System :: OS Independent",
22
+ "Programming Language :: Python :: 3",
23
+ "Intended Audience :: Science/Research",
24
+ "Topic :: Scientific/Engineering :: Astronomy",
25
+ "Topic :: Scientific/Engineering :: Visualization",
26
+ ]
27
+
28
+ requires-python = ">=3.11"
29
+ dependencies = [
30
+ "pdr[fits,pillow,pvl] >= 1.4.4",
31
+ "visidata >= 3.3",
32
+ ]
33
+
34
+ [project.urls]
35
+ Repository = "https://github.com/MillionConcepts/visidata-pdr"
36
+
37
+ [project.entry-points."visidata.plugins"]
38
+ visidata_pdr = "visidata_pdr.visidata_pdr"
39
+
40
+
41
+ [build-system]
42
+ requires = ["setuptools >= 77"]
43
+ build-backend = "setuptools.build_meta"
44
+
45
+ [tool.setuptools.packages.find]
46
+ include = [
47
+ "visidata_pdr",
48
+ "visidata_pdr.*",
49
+ ]
50
+ namespaces=false
51
+ where = ["."]
52
+
53
+
54
+ ## Lint configuration
55
+ [tool.ruff]
56
+ # These need to agree with .editorconfig
57
+ line-length = 80
58
+ indent-width = 4
59
+ # This needs to agree with the requires-python line
60
+ target-version = "py311"
61
+ # Files that should not be linted. Put a short explanatory comment
62
+ # above each.
63
+ exclude = [
64
+ ]
65
+
66
+ [tool.ruff.lint]
67
+ # There are lots more checks ruff can do but this is a sensible default.
68
+ # Unfortunately, many of the other lint groups combine high-value checks
69
+ # with much lower-value or purely stylistic checks.
70
+ #
71
+ # To facilitate maintenance, this list should be kept in the same order
72
+ # as the list of groups in <https://docs.astral.sh/ruff/rules/>.
73
+ select = [
74
+ # "ANN", # missing type annotations (visidata and pdr are both untyped)
75
+ "FBT", # forbid boolean positional arguments (keyword args are ok)
76
+ "RET", # missing return values
77
+ # "TC", # debatable rules about type-only imports
78
+ "SIM115", # open() without 'with' block (other SIM checks are debatable)
79
+ "NPY", # warns about deprecated NumPy APIs
80
+ "PD", # warns about deprecated Pandas APIs
81
+ "PT", # warns about a variety of easy mistakes when writing tests
82
+ "E1", # inconsistent indentation (stylistic but very important)
83
+ # "E2", # purely stylistic rules about whitespace around operators
84
+ # "E3", # purely stylistic rules about blank lines
85
+ "E4", # import-related mistakes
86
+ "E5", # backslash-related mistakes
87
+ # "E6", # there are no E6xx rules
88
+ "E7", # more code that can be simplified,
89
+ # "E8", # there are no E8xx rules
90
+ "E9", # I/O errors while running ruff
91
+ "W", # mostly whitespace errors; also, invalid \-escapes in strings
92
+ "F", # grab bag of constructs that are almost certainly wrong
93
+ "PGH", # no blanket lint annotations
94
+ ]
95
+ ignore = [
96
+ # stylistic rule (line length) lumped in with E5
97
+ "E501",
98
+ # better addressed by not using fonts in which l/I/1 or 0/O are
99
+ # visually ambiguous
100
+ "E741",
101
+ # stylistic rule lumped with RET ("never use 'else' after an
102
+ # if block ending with a 'return'"; in many cases the version
103
+ # with the 'else' is easier to read)
104
+ "RET505",
105
+ # stylistic rule (line length in docstrings) lumped in with W
106
+ "W505",
107
+ ]
@@ -0,0 +1,231 @@
1
+ 130464317.3009,1,1,6923.889052
2
+ 130464322.3021,1,1,6929.701254
3
+ 130464327.3031,1,1,6924.215512
4
+ 130464332.3059,1,1,6917.436778
5
+ 130464337.3067,1,1,6922.094841
6
+ 130464342.3063,1,1,6905.830743
7
+ 130464347.3058,1,1,6899.567757
8
+ 130464352.3053,1,1,6898.709318
9
+ 130464357.3065,1,1,6894.739111
10
+ 130464362.3074,1,1,6891.932896
11
+ 130464367.3084,1,1,6887.096172
12
+ 130464372.3104,1,1,6889.150879
13
+ 130464377.3103,1,1,6892.712098
14
+ 130464382.3099,1,1,6875.185849
15
+ 130464387.3095,1,1,6877.571465
16
+ 130464392.3083,1,1,6877.449824
17
+ 130464397.3072,1,1,6877.223269
18
+ 130464402.3081,1,1,6871.954239
19
+ 130464407.3090,1,1,6862.180044
20
+ 130464412.3095,1,1,6918.194310
21
+ 130464417.3120,1,1,6864.203335
22
+ 130464422.3142,1,1,6866.328851
23
+ 130464427.3159,1,1,6873.340604
24
+ 130464432.3185,1,1,6923.814555
25
+ 130464437.3197,1,1,6952.018657
26
+ 130464442.3195,1,1,6972.957281
27
+ 130464447.3204,1,1,6993.795175
28
+ 130464452.3221,1,1,7000.904434
29
+ 130464457.3221,1,1,7028.452034
30
+ 130464462.3216,1,1,7024.868166
31
+ 130464467.3214,1,1,7050.362550
32
+ 130464472.3200,1,1,6983.033167
33
+ 130464477.3204,1,1,7090.037171
34
+ 130464482.3230,1,1,7134.714044
35
+ 130464487.3251,1,1,7309.197433
36
+ 130464492.3251,1,1,7373.193516
37
+ 130464497.3243,1,1,7409.147023
38
+ 130464502.3253,1,1,7420.665214
39
+ 130464507.3268,1,1,7354.977425
40
+ 130464512.3282,1,1,7285.702350
41
+ 130464517.3295,1,1,7145.473796
42
+ 130464522.3309,1,1,7397.842957
43
+ 130464527.3316,1,1,7477.598991
44
+ 130464532.3325,1,1,7457.332264
45
+ 130464537.3355,1,1,7449.067309
46
+ 130464542.3376,1,1,7399.806545
47
+ 130464547.3384,1,1,7302.698995
48
+ 130464552.3378,1,0,7847.218608
49
+ 130464557.3358,1,0,7832.279827
50
+ 130464562.3345,1,1,7162.152287
51
+ 130464567.3334,1,1,7741.368531
52
+ 130464572.3330,1,0,7782.875580
53
+ 130464577.3324,1,0,7764.748579
54
+ 130464582.3317,1,0,7745.733852
55
+ 130464587.3314,1,0,7725.733655
56
+ 130464592.3323,1,0,7704.779140
57
+ 130464597.3349,1,0,7682.756163
58
+ 130464602.3351,1,0,7659.624321
59
+ 130464607.3336,1,0,7635.367124
60
+ 130464612.3337,1,0,7609.896109
61
+ 130464617.3337,1,0,7583.073118
62
+ 130464622.3344,1,0,7554.942510
63
+ 130464627.3369,1,0,7525.365822
64
+ 130464632.3371,1,0,7494.277440
65
+ 130464637.3361,1,0,7461.586210
66
+ 130464642.3374,1,0,7427.223392
67
+ 130464647.3397,1,0,7391.013526
68
+ 130464652.3418,1,0,7352.944213
69
+ 130464657.3423,1,0,7312.897064
70
+ 130464662.3428,1,0,7270.686788
71
+ 130464667.3446,1,0,7226.241009
72
+ 130464672.3469,1,0,7179.407188
73
+ 130464677.3488,1,0,7130.033325
74
+ 130464682.3493,1,0,7078.005523
75
+ 130464687.3505,1,0,7023.106078
76
+ 130464692.3518,1,0,6965.193773
77
+ 130464697.3527,1,0,6904.095800
78
+ 130464702.3538,1,1,6672.071845
79
+ 130464707.3532,1,1,6713.186628
80
+ 130464712.3529,1,1,6701.551238
81
+ 130464717.3526,1,1,6600.733173
82
+ 130464722.3522,1,1,6648.883552
83
+ 130464727.3548,1,0,6458.202451
84
+ 130464732.3563,1,1,6501.334293
85
+ 130464737.3567,1,0,6273.427936
86
+ 130464742.3594,1,0,6172.983742
87
+ 130464747.3607,1,0,6066.787764
88
+ 130464752.3592,1,0,5954.562325
89
+ 130464757.3601,1,0,5835.812189
90
+ 130464762.3628,1,0,5710.252921
91
+ 130464767.3636,1,0,5577.570618
92
+ 130464772.3638,1,1,6176.901892
93
+ 130464777.3645,1,1,5921.668024
94
+ 130464782.3662,1,1,5416.793635
95
+ 130464787.3696,1,1,5992.577894
96
+ 130464792.3734,1,1,5753.413007
97
+ 130464797.3779,1,1,4843.806615
98
+ 130464802.3818,1,0,4419.173921
99
+ 130464807.3830,1,1,5704.772236
100
+ 130464812.3849,1,0,4005.496641
101
+ 130464817.3862,1,0,3783.875620
102
+ 130464822.3899,1,0,3552.159917
103
+ 130464827.3938,1,0,3310.640997
104
+ 130464832.3962,1,0,3059.441419
105
+ 130464837.3997,1,0,2798.783542
106
+ 130464842.4011,1,0,2529.223205
107
+ 130464847.4024,1,0,2251.108133
108
+ 130464852.4054,1,0,1965.065031
109
+ 130464857.4107,1,0,1671.729368
110
+ 130464862.4168,1,0,1372.110262
111
+ 130464867.4360,1,0,1066.428885
112
+ 130464872.4581,1,0,756.433176
113
+ 130464877.5161,1,0,441.137369
114
+ 130464882.7997,1,0,123.676379
115
+ 130464888.0595,1,0,215.226944
116
+ 130464893.1080,1,0,536.190849
117
+ 130464898.1279,1,0,848.202390
118
+ 130464903.1289,1,0,1155.560313
119
+ 130464908.1381,1,0,1458.902329
120
+ 130464913.1455,1,1,2057.533493
121
+ 130464918.1464,1,1,4275.314272
122
+ 130464923.1524,1,0,2330.701288
123
+ 130464928.1622,1,0,2606.304380
124
+ 130464933.1696,1,0,2872.972920
125
+ 130464938.1712,1,0,3130.208554
126
+ 130464943.1713,1,0,3377.805273
127
+ 130464948.1729,1,0,3615.716259
128
+ 130464953.1743,1,0,3843.615075
129
+ 130464958.1738,1,0,4061.554215
130
+ 130464963.1742,1,0,4269.661673
131
+ 130464968.1742,1,0,4467.886939
132
+ 130464973.1759,1,0,4656.686152
133
+ 130464978.1775,1,0,4836.016124
134
+ 130464983.1767,1,0,5006.270919
135
+ 130464988.1790,1,0,5167.790892
136
+ 130464993.1815,1,0,5320.874391
137
+ 130464998.1815,1,0,5465.826908
138
+ 130465003.1829,1,0,5602.902653
139
+ 130465008.1857,1,0,5732.799765
140
+ 130465013.1864,1,0,5855.525293
141
+ 130465018.1877,1,0,5971.561122
142
+ 130465023.1887,1,0,6081.304961
143
+ 130465028.1883,1,0,6184.980350
144
+ 130465033.1884,1,0,6282.984627
145
+ 130465038.1902,1,0,6375.663229
146
+ 130465043.1919,1,0,6463.286265
147
+ 130465048.1916,1,0,6546.119969
148
+ 130465053.1928,1,0,6624.439524
149
+ 130465058.1959,1,0,6698.561491
150
+ 130465063.1984,1,0,6768.665298
151
+ 130465068.2004,1,0,6834.987388
152
+ 130465073.2018,1,0,6897.779928
153
+ 130465078.2025,1,0,6957.220849
154
+ 130465083.2020,1,0,7013.497971
155
+ 130465088.2026,1,0,7066.790033
156
+ 130465093.2036,1,0,7117.333367
157
+ 130465098.2044,1,0,7165.251432
158
+ 130465103.2066,1,0,7210.666540
159
+ 130465108.2067,1,0,7253.734054
160
+ 130465113.2064,1,0,7294.592843
161
+ 130465118.2070,1,0,7333.374671
162
+ 130465123.2075,1,0,7370.182069
163
+ 130465128.2091,1,0,7405.127522
164
+ 130465133.2106,1,0,7438.336506
165
+ 130465138.2104,1,0,7469.869459
166
+ 130465143.2097,1,0,7499.831226
167
+ 130465148.2096,1,0,7528.301367
168
+ 130465153.2110,1,0,7555.370476
169
+ 130465158.2123,1,0,7581.114049
170
+ 130465163.2118,1,0,7605.579750
171
+ 130465168.2105,1,0,7628.830079
172
+ 130465173.2091,1,0,7650.964039
173
+ 130465178.2083,1,0,7672.003629
174
+ 130465183.2088,1,0,7692.036376
175
+ 130465188.2088,1,0,7711.048222
176
+ 130465193.2090,1,0,7729.192361
177
+ 130465198.2098,1,0,7746.430529
178
+ 130465203.2094,1,0,7762.836086
179
+ 130465208.2085,1,0,7778.367759
180
+ 130465213.2074,1,0,7793.196539
181
+ 130465218.2067,1,0,7807.304008
182
+ 130465223.2068,1,0,7820.697619
183
+ 130465228.2081,1,0,7833.435199
184
+ 130465233.2087,1,0,7845.508038
185
+ 130465238.2090,1,0,7857.030084
186
+ 130465243.2093,1,0,7867.913208
187
+ 130465248.2100,1,0,7878.286840
188
+ 130465253.2114,1,0,7888.093951
189
+ 130465258.2115,1,0,7897.387694
190
+ 130465263.2107,1,0,7906.222652
191
+ 130465268.2092,1,0,7914.545242
192
+ 130465273.2073,1,0,7922.462419
193
+ 130465278.2053,1,0,7929.902465
194
+ 130465283.2034,1,0,7936.975054
195
+ 130465288.2020,1,0,7943.598175
196
+ 130465293.2012,1,0,7949.862993
197
+ 130465298.2013,1,0,7955.762290
198
+ 130465303.2026,1,0,7961.258886
199
+ 130465308.2028,1,0,7966.474656
200
+ 130465313.2023,1,0,7971.358805
201
+ 130465318.2035,1,0,7975.879095
202
+ 130465323.2043,1,0,7980.100841
203
+ 130465328.2049,1,0,7984.058476
204
+ 130465333.2052,1,1,8018.656356
205
+ 130465338.2058,1,1,5364.486708
206
+ 130465343.2070,1,1,6192.670664
207
+ 130465348.2085,1,1,6234.238889
208
+ 130465353.2100,1,1,6207.618222
209
+ 130465358.2110,1,1,6213.036042
210
+ 130465363.2114,1,1,6239.071767
211
+ 130465368.2116,1,1,6251.046927
212
+ 130465373.2120,1,1,6268.562429
213
+ 130465378.2107,1,1,6262.782753
214
+ 130465383.2106,1,1,6273.199704
215
+ 130465388.2115,1,1,6282.567026
216
+ 130465393.2135,1,1,6293.079537
217
+ 130465398.2167,1,1,6302.125513
218
+ 130465403.2192,1,1,6287.219001
219
+ 130465408.2216,1,1,6280.118439
220
+ 130465413.2218,1,1,6285.061829
221
+ 130465418.2199,1,1,6285.421464
222
+ 130465423.2184,1,1,6276.411359
223
+ 130465428.2179,1,1,6267.978200
224
+ 130465433.2190,1,1,6272.597497
225
+ 130465438.2197,1,1,6268.720632
226
+ 130465443.2192,1,1,6268.187694
227
+ 130465448.2185,1,1,6269.295974
228
+ 130465453.2188,1,1,6265.557845
229
+ 130465458.2216,1,1,6263.092567
230
+ 130465463.2225,1,1,6255.225464
231
+ 130465468.2221,1,1,6251.342355
@@ -0,0 +1,108 @@
1
+ PDS_VERSION_ID = PDS3
2
+ RECORD_TYPE = STREAM
3
+ RECORD_BYTES = 32 /* Largest actual record in the file */
4
+ FILE_RECORDS = 231
5
+ ^SPREADSHEET = "ODY2004050_S253.CSV"
6
+ DATA_SET_ID = "MER1-M-RSS-1-EDR-V1.0"
7
+ TARGET_NAME = "MARS"
8
+ INSTRUMENT_HOST_NAME = "MARS EXPLORATION ROVER 1"
9
+ INSTRUMENT_NAME = "RADIO SCIENCE SUBSYSTEM"
10
+ INSTRUMENT_ID = "RSS"
11
+ PRODUCER_ID = "DSN"
12
+ PRODUCT_CREATION_TIME = 2004-02-20T00:00:00
13
+ PRODUCT_TYPE = UHFD
14
+ PRODUCT_ID = "ODY2004050_S253.CSV"
15
+ ORIGINAL_PRODUCT_ID = "ody2004050_S253.asc"
16
+ START_TIME = 2004-02-19T12:05:17
17
+ STOP_TIME = 2004-02-19T12:24:28
18
+ HARDWARE_MODEL_ID = "C/TT-505"
19
+ DESCRIPTION = "Ultra-High Frequency Doppler (UHFD)
20
+ files are the results of measurements made by the UHF radio
21
+ system on the Mars Odyssey Orbiter (ODY). The ODY UHF radio system
22
+ uses a reference frequency near 401 MHz. The reference frequency is
23
+ multiplied by the ratio 160/147 to generate a signal near 437 MHz
24
+ which can be used to transmit commands to vehicles on Mars
25
+ such as MER 1 and MER 2, and receives signals back at 401 MHz.
26
+ The ODY UHF radio measures the difference in frequency between
27
+ the reference and received carrier frequencies which
28
+ provides a (Doppler) measure of the relative velocity of the
29
+ surface vehicle. Each UHFD file contains ASCII records with
30
+ 4 fields; commas are used to separate fields within
31
+ each record. The first field of each record is the time of the
32
+ measurement in seconds past the J2000 reference epoch
33
+ (which is 2000-01-01T12:00:00 UTC).
34
+ The second field of each record is an integer flag which indicates
35
+ the reference frequency. The third field is an integer flag
36
+ which indicates data quality (0 indicates valid, 1 indicates bad);
37
+ the fourth field is the frequency difference measurement in Hz.
38
+
39
+ The measurement is the absolute value of the difference of the received
40
+ frequency minus the reference frequency. For Mars Odyssey, the only
41
+ available reference frequency is 401.584625 MHz. The frequency of the
42
+ signal transmitted by ODY is a fixed multiple, 160/147, of the
43
+ reference frequency. For the MER radio operating in coherent mode,
44
+ the received frequency is multiplied by a fixed multiple, 147/160, to
45
+ generate the signal transmitted back to the orbiter.
46
+ For example, when ODY is directly overhead the rover, the signal
47
+ received from MER and the ODY reference frequency are the same and
48
+ the measurement is zero, indicating zero velocity of the rover relative to
49
+ ODY along the line of sight to the orbiter. In general, the absolute value
50
+ of the velocity along the line of sight is (to first order in v/c)
51
+ v = (c/2) *F(measurement)/F(reference)
52
+ where c is the speed of light.
53
+
54
+ The size of each record is variable; the maximum record size
55
+ consists of 14 characters for the TIME field, 1 character for the
56
+ LO FLAG field, one character from the DATA QUALITY field, 11 characters
57
+ for the FREQUENCY field, three single-character delimiters (comma),
58
+ plus ASCII carriage-return and line-feed at end of each record."
59
+
60
+ OBJECT = SPREADSHEET
61
+ ROWS = 227
62
+ ROW_BYTES = 32 /* Largest actual record in the file */
63
+ FIELDS = 4
64
+ FIELD_DELIMITER = "COMMA"
65
+
66
+ OBJECT = FIELD
67
+ NAME = "TIME"
68
+ DATA_TYPE = "ASCII_REAL"
69
+ FIELD_NUMBER = 1
70
+ BYTES = 14 /* Maximum item bytes */
71
+ DESCRIPTION = "The time of the measurement in seconds past the
72
+ J2000 reference epoch (which is 2000-01-01T12:00:00 UTC)."
73
+ END_OBJECT = FIELD
74
+
75
+ OBJECT = FIELD
76
+ NAME = "LO FLAG"
77
+ DATA_TYPE = "ASCII_INTEGER"
78
+ BYTES = 1
79
+ FIELD_NUMBER = 2
80
+ DESCRIPTION = "Flag which indicates
81
+ the reference local oscillator (LO) frequency against which the
82
+ frequency of the received carrier is measured. For ODY, the
83
+ flag is always '1' since only one reference frequency is available."
84
+ END_OBJECT = FIELD
85
+
86
+ OBJECT = FIELD
87
+ NAME = "DATA QUALITY"
88
+ DATA_TYPE = "ASCII_INTEGER"
89
+ BYTES = 1
90
+ FIELD_NUMBER = 3
91
+ DESCRIPTION = "Flag which indicates data quality
92
+ (0 indicates valid, 1 indicates bad). Data may be flagged as 'bad' due
93
+ either to telemetry indicating a bad receiver condition or to telemetry
94
+ integrity checks indicating errors in telemetry record from ODY
95
+ to the DSN containing the measurement data."
96
+ END_OBJECT = FIELD
97
+
98
+ OBJECT = FIELD
99
+ NAME = "FREQUENCY"
100
+ DATA_TYPE = "ASCII_REAL"
101
+ BYTES = 11 /* Maximum item bytes */
102
+ FIELD_NUMBER = 4
103
+ DESCRIPTION = "Frequency difference measurement in Hz."
104
+ END_OBJECT = FIELD
105
+
106
+ END_OBJECT = SPREADSHEET
107
+
108
+ END
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,232 @@
1
+ TIME LO FLAG DATA QUALITY FREQUENCY
2
+ 130464317.3009 1 1 6923.889052
3
+ 130464322.3021 1 1 6929.701254
4
+ 130464327.3031 1 1 6924.215512
5
+ 130464332.3059 1 1 6917.436778
6
+ 130464337.3067 1 1 6922.094841
7
+ 130464342.3063 1 1 6905.830743
8
+ 130464347.3058 1 1 6899.567757
9
+ 130464352.3053 1 1 6898.709318
10
+ 130464357.3065 1 1 6894.739111
11
+ 130464362.3074 1 1 6891.932896
12
+ 130464367.3084 1 1 6887.096172
13
+ 130464372.3104 1 1 6889.150879
14
+ 130464377.3103 1 1 6892.712098
15
+ 130464382.3099 1 1 6875.185849
16
+ 130464387.3095 1 1 6877.571465
17
+ 130464392.3083 1 1 6877.449824
18
+ 130464397.3072 1 1 6877.223269
19
+ 130464402.3081 1 1 6871.954239
20
+ 130464407.3090 1 1 6862.180044
21
+ 130464412.3095 1 1 6918.194310
22
+ 130464417.3120 1 1 6864.203335
23
+ 130464422.3142 1 1 6866.328851
24
+ 130464427.3159 1 1 6873.340604
25
+ 130464432.3185 1 1 6923.814555
26
+ 130464437.3197 1 1 6952.018657
27
+ 130464442.3195 1 1 6972.957281
28
+ 130464447.3204 1 1 6993.795175
29
+ 130464452.3221 1 1 7000.904434
30
+ 130464457.3221 1 1 7028.452034
31
+ 130464462.3216 1 1 7024.868166
32
+ 130464467.3214 1 1 7050.362550
33
+ 130464472.3200 1 1 6983.033167
34
+ 130464477.3204 1 1 7090.037171
35
+ 130464482.3230 1 1 7134.714044
36
+ 130464487.3251 1 1 7309.197433
37
+ 130464492.3251 1 1 7373.193516
38
+ 130464497.3243 1 1 7409.147023
39
+ 130464502.3253 1 1 7420.665214
40
+ 130464507.3268 1 1 7354.977425
41
+ 130464512.3282 1 1 7285.702350
42
+ 130464517.3295 1 1 7145.473796
43
+ 130464522.3309 1 1 7397.842957
44
+ 130464527.3316 1 1 7477.598991
45
+ 130464532.3325 1 1 7457.332264
46
+ 130464537.3355 1 1 7449.067309
47
+ 130464542.3376 1 1 7399.806545
48
+ 130464547.3384 1 1 7302.698995
49
+ 130464552.3378 1 0 7847.218608
50
+ 130464557.3358 1 0 7832.279827
51
+ 130464562.3345 1 1 7162.152287
52
+ 130464567.3334 1 1 7741.368531
53
+ 130464572.3330 1 0 7782.875580
54
+ 130464577.3324 1 0 7764.748579
55
+ 130464582.3317 1 0 7745.733852
56
+ 130464587.3314 1 0 7725.733655
57
+ 130464592.3323 1 0 7704.779140
58
+ 130464597.3349 1 0 7682.756163
59
+ 130464602.3351 1 0 7659.624321
60
+ 130464607.3336 1 0 7635.367124
61
+ 130464612.3337 1 0 7609.896109
62
+ 130464617.3337 1 0 7583.073118
63
+ 130464622.3344 1 0 7554.942510
64
+ 130464627.3369 1 0 7525.365822
65
+ 130464632.3371 1 0 7494.277440
66
+ 130464637.3361 1 0 7461.586210
67
+ 130464642.3374 1 0 7427.223392
68
+ 130464647.3397 1 0 7391.013526
69
+ 130464652.3418 1 0 7352.944213
70
+ 130464657.3423 1 0 7312.897064
71
+ 130464662.3428 1 0 7270.686788
72
+ 130464667.3446 1 0 7226.241009
73
+ 130464672.3469 1 0 7179.407188
74
+ 130464677.3488 1 0 7130.033325
75
+ 130464682.3493 1 0 7078.005523
76
+ 130464687.3505 1 0 7023.106078
77
+ 130464692.3518 1 0 6965.193773
78
+ 130464697.3527 1 0 6904.095800
79
+ 130464702.3538 1 1 6672.071845
80
+ 130464707.3532 1 1 6713.186628
81
+ 130464712.3529 1 1 6701.551238
82
+ 130464717.3526 1 1 6600.733173
83
+ 130464722.3522 1 1 6648.883552
84
+ 130464727.3548 1 0 6458.202451
85
+ 130464732.3563 1 1 6501.334293
86
+ 130464737.3567 1 0 6273.427936
87
+ 130464742.3594 1 0 6172.983742
88
+ 130464747.3607 1 0 6066.787764
89
+ 130464752.3592 1 0 5954.562325
90
+ 130464757.3601 1 0 5835.812189
91
+ 130464762.3628 1 0 5710.252921
92
+ 130464767.3636 1 0 5577.570618
93
+ 130464772.3638 1 1 6176.901892
94
+ 130464777.3645 1 1 5921.668024
95
+ 130464782.3662 1 1 5416.793635
96
+ 130464787.3696 1 1 5992.577894
97
+ 130464792.3734 1 1 5753.413007
98
+ 130464797.3779 1 1 4843.806615
99
+ 130464802.3818 1 0 4419.173921
100
+ 130464807.3830 1 1 5704.772236
101
+ 130464812.3849 1 0 4005.496641
102
+ 130464817.3862 1 0 3783.875620
103
+ 130464822.3899 1 0 3552.159917
104
+ 130464827.3938 1 0 3310.640997
105
+ 130464832.3962 1 0 3059.441419
106
+ 130464837.3997 1 0 2798.783542
107
+ 130464842.4011 1 0 2529.223205
108
+ 130464847.4024 1 0 2251.108133
109
+ 130464852.4054 1 0 1965.065031
110
+ 130464857.4107 1 0 1671.729368
111
+ 130464862.4168 1 0 1372.110262
112
+ 130464867.4360 1 0 1066.428885
113
+ 130464872.4581 1 0 756.433176
114
+ 130464877.5161 1 0 441.137369
115
+ 130464882.7997 1 0 123.676379
116
+ 130464888.0595 1 0 215.226944
117
+ 130464893.1080 1 0 536.190849
118
+ 130464898.1279 1 0 848.202390
119
+ 130464903.1289 1 0 1155.560313
120
+ 130464908.1381 1 0 1458.902329
121
+ 130464913.1455 1 1 2057.533493
122
+ 130464918.1464 1 1 4275.314272
123
+ 130464923.1524 1 0 2330.701288
124
+ 130464928.1622 1 0 2606.304380
125
+ 130464933.1696 1 0 2872.972920
126
+ 130464938.1712 1 0 3130.208554
127
+ 130464943.1713 1 0 3377.805273
128
+ 130464948.1729 1 0 3615.716259
129
+ 130464953.1743 1 0 3843.615075
130
+ 130464958.1738 1 0 4061.554215
131
+ 130464963.1742 1 0 4269.661673
132
+ 130464968.1742 1 0 4467.886939
133
+ 130464973.1759 1 0 4656.686152
134
+ 130464978.1775 1 0 4836.016124
135
+ 130464983.1767 1 0 5006.270919
136
+ 130464988.1790 1 0 5167.790892
137
+ 130464993.1815 1 0 5320.874391
138
+ 130464998.1815 1 0 5465.826908
139
+ 130465003.1829 1 0 5602.902653
140
+ 130465008.1857 1 0 5732.799765
141
+ 130465013.1864 1 0 5855.525293
142
+ 130465018.1877 1 0 5971.561122
143
+ 130465023.1887 1 0 6081.304961
144
+ 130465028.1883 1 0 6184.980350
145
+ 130465033.1884 1 0 6282.984627
146
+ 130465038.1902 1 0 6375.663229
147
+ 130465043.1919 1 0 6463.286265
148
+ 130465048.1916 1 0 6546.119969
149
+ 130465053.1928 1 0 6624.439524
150
+ 130465058.1959 1 0 6698.561491
151
+ 130465063.1984 1 0 6768.665298
152
+ 130465068.2004 1 0 6834.987388
153
+ 130465073.2018 1 0 6897.779928
154
+ 130465078.2025 1 0 6957.220849
155
+ 130465083.2020 1 0 7013.497971
156
+ 130465088.2026 1 0 7066.790033
157
+ 130465093.2036 1 0 7117.333367
158
+ 130465098.2044 1 0 7165.251432
159
+ 130465103.2066 1 0 7210.666540
160
+ 130465108.2067 1 0 7253.734054
161
+ 130465113.2064 1 0 7294.592843
162
+ 130465118.2070 1 0 7333.374671
163
+ 130465123.2075 1 0 7370.182069
164
+ 130465128.2091 1 0 7405.127522
165
+ 130465133.2106 1 0 7438.336506
166
+ 130465138.2104 1 0 7469.869459
167
+ 130465143.2097 1 0 7499.831226
168
+ 130465148.2096 1 0 7528.301367
169
+ 130465153.2110 1 0 7555.370476
170
+ 130465158.2123 1 0 7581.114049
171
+ 130465163.2118 1 0 7605.579750
172
+ 130465168.2105 1 0 7628.830079
173
+ 130465173.2091 1 0 7650.964039
174
+ 130465178.2083 1 0 7672.003629
175
+ 130465183.2088 1 0 7692.036376
176
+ 130465188.2088 1 0 7711.048222
177
+ 130465193.2090 1 0 7729.192361
178
+ 130465198.2098 1 0 7746.430529
179
+ 130465203.2094 1 0 7762.836086
180
+ 130465208.2085 1 0 7778.367759
181
+ 130465213.2074 1 0 7793.196539
182
+ 130465218.2067 1 0 7807.304008
183
+ 130465223.2068 1 0 7820.697619
184
+ 130465228.2081 1 0 7833.435199
185
+ 130465233.2087 1 0 7845.508038
186
+ 130465238.2090 1 0 7857.030084
187
+ 130465243.2093 1 0 7867.913208
188
+ 130465248.2100 1 0 7878.286840
189
+ 130465253.2114 1 0 7888.093951
190
+ 130465258.2115 1 0 7897.387694
191
+ 130465263.2107 1 0 7906.222652
192
+ 130465268.2092 1 0 7914.545242
193
+ 130465273.2073 1 0 7922.462419
194
+ 130465278.2053 1 0 7929.902465
195
+ 130465283.2034 1 0 7936.975054
196
+ 130465288.2020 1 0 7943.598175
197
+ 130465293.2012 1 0 7949.862993
198
+ 130465298.2013 1 0 7955.762290
199
+ 130465303.2026 1 0 7961.258886
200
+ 130465308.2028 1 0 7966.474656
201
+ 130465313.2023 1 0 7971.358805
202
+ 130465318.2035 1 0 7975.879095
203
+ 130465323.2043 1 0 7980.100841
204
+ 130465328.2049 1 0 7984.058476
205
+ 130465333.2052 1 1 8018.656356
206
+ 130465338.2058 1 1 5364.486708
207
+ 130465343.2070 1 1 6192.670664
208
+ 130465348.2085 1 1 6234.238889
209
+ 130465353.2100 1 1 6207.618222
210
+ 130465358.2110 1 1 6213.036042
211
+ 130465363.2114 1 1 6239.071767
212
+ 130465368.2116 1 1 6251.046927
213
+ 130465373.2120 1 1 6268.562429
214
+ 130465378.2107 1 1 6262.782753
215
+ 130465383.2106 1 1 6273.199704
216
+ 130465388.2115 1 1 6282.567026
217
+ 130465393.2135 1 1 6293.079537
218
+ 130465398.2167 1 1 6302.125513
219
+ 130465403.2192 1 1 6287.219001
220
+ 130465408.2216 1 1 6280.118439
221
+ 130465413.2218 1 1 6285.061829
222
+ 130465418.2199 1 1 6285.421464
223
+ 130465423.2184 1 1 6276.411359
224
+ 130465428.2179 1 1 6267.978200
225
+ 130465433.2190 1 1 6272.597497
226
+ 130465438.2197 1 1 6268.720632
227
+ 130465443.2192 1 1 6268.187694
228
+ 130465448.2185 1 1 6269.295974
229
+ 130465453.2188 1 1 6265.557845
230
+ 130465458.2216 1 1 6263.092567
231
+ 130465463.2225 1 1 6255.225464
232
+ 130465468.2221 1 1 6251.342355
@@ -0,0 +1,8 @@
1
+ #!vd -p
2
+ {"longname": "open-file", "input": "sample_data/pds3_mer_rss_uhfd/ODY2004050_S253.LBL"}
3
+ {"longname": "columns-sheet", "sheet": "ODY2004050_S253/SPREADSHEET"}
4
+ {"longname": "edit-cell", "sheet": "ODY2004050_S253/SPREADSHEET_columns", "col": "fmtstr", "row": 0, "input": "{:0.4f}"}
5
+ {"longname": "edit-cell", "sheet": "ODY2004050_S253/SPREADSHEET_columns", "col": "fmtstr", "row": 3, "input": "{:0.6f}"}
6
+ {"longname": "edit-cell", "sheet": "ODY2004050_S253/SPREADSHEET_columns", "col": "width", "row": 0, "input": "16"}
7
+ {"longname": "edit-cell", "sheet": "ODY2004050_S253/SPREADSHEET_columns", "col": "width", "row": 3, "input": "15"}
8
+ {"longname": "jump-prev"}
@@ -0,0 +1 @@
1
+ from .visidata_pdr import open_pdr as open_pdr
@@ -0,0 +1,262 @@
1
+ """
2
+ Load tabular data into VisiData using PDR
3
+ """
4
+
5
+ from visidata import (
6
+ VisiData, Column, TableSheet, TextSheet, asyncthread
7
+ )
8
+ from visidata.loaders._pandas import PandasSheet
9
+ from visidata.loaders.npy import NpySheet
10
+
11
+
12
+ def a_type(thing):
13
+ """
14
+ Return the name of the type of 'thing', with the correct
15
+ English indefinite article prepended and some of Python's
16
+ cryptic abbreviations expanded, e.g. 'a string', 'an integer'.
17
+
18
+ If 'thing' is already a type object, uses the name of 'thing'
19
+ itself, not the name of type(thing) (which would always be "type").
20
+ """
21
+ if not isinstance(thing, type):
22
+ thing = type(thing)
23
+ name = thing.__name__
24
+
25
+ # None is unique and therefore doesn't take any articles at all.
26
+ if name in ("None", "NoneType"):
27
+ return "None"
28
+
29
+ name = ({
30
+ "bool": "boolean",
31
+ "dict": "dictionary",
32
+ "float": "real number",
33
+ "int": "integer",
34
+ "ndarray": "numpy array",
35
+ "str": "string",
36
+ }).get(name, name)
37
+
38
+ # Technically, "an" should be used if the word begins with a vowel
39
+ # *sound*, whether or not it begins with a vowel *letter*.
40
+ # However, determining this accurately is difficult: to give just
41
+ # one example, it should be "a numpy array" but "an ndarray".
42
+ # Approximating based on the usual vowel letters is Good Enough For Now.
43
+ # (The rule is also accent-dependent, but that almost exclusively affects
44
+ # words beginning with H, and I can't think of any that would come up.)
45
+ return ("an " if name[0] in "aeiouAEIOU" else "a ") + name
46
+
47
+
48
+ class PDRSource:
49
+ """
50
+ Object to be used as the .source of one of the Lazy sheets below.
51
+ get() loads the relevant data only when needed.
52
+ """
53
+
54
+ def __init__(self, container, key):
55
+ self.container = container
56
+ self.key = key
57
+ self.data = None
58
+
59
+ def get(self):
60
+ if self.data is None:
61
+ self.data = self.container[self.key]
62
+ return self.data
63
+
64
+ def __str__(self):
65
+ return f"pdr.Data({self.container.filename!r}).{self.key}"
66
+
67
+
68
+ class LazyTextSheet(TextSheet):
69
+ def iterload(self):
70
+ if not hasattr(self, "_lines"):
71
+ lines = self.source.get()
72
+ if isinstance(lines, str):
73
+ lines = lines.splitlines()
74
+ elif isinstance(lines, list):
75
+ if not all(isinstance(l, str) for l in lines):
76
+ self.vd.fail("LazyTextSheet: source is a list but"
77
+ " some of its items are not strings")
78
+ else:
79
+ self.vd.fail(f"LazyTextSheet: source is {a_type(lines)}"
80
+ " (expected a string or list of strings)")
81
+ self._lines = lines
82
+
83
+ yield from self.readlines(self._lines)
84
+
85
+
86
+ class LazyNpySheet(NpySheet):
87
+ def iterload(self):
88
+ if not hasattr(self, "npy"):
89
+ np = self.vd.importExternal("numpy")
90
+ npy = self.source.get()
91
+ if not isinstance(npy, np.ndarray):
92
+ self.vd.fail(f"LazyNpySheet: source is {a_type(npy)}"
93
+ " (expected a numpy array)")
94
+ self.npy = npy
95
+
96
+ return super().iterload()
97
+
98
+
99
+ class LazyPandasSheet(PandasSheet):
100
+ def dtype_to_type(self, dtype):
101
+ """
102
+ Patch PandasSheet with a workaround for
103
+ https://github.com/saulpw/visidata/issues/2960
104
+ whose fix is not yet released
105
+ """
106
+ pd = self.vd.importExternal("pandas")
107
+ if isinstance(dtype, pd.Series):
108
+ dtype = dtype.dtype
109
+ return super().dtype_to_type(dtype)
110
+
111
+ @asyncthread
112
+ def reload(self):
113
+ if not hasattr(self, '_pdr_source'):
114
+ pd = self.vd.importExternal("pandas")
115
+ df = self.source.get()
116
+ if not isinstance(df, pd.DataFrame):
117
+ self.vd.fail(f"LazyPandasSheet: source is {a_type(df)}"
118
+ " (expected a DataFrame)")
119
+
120
+ self._pdr_source = self.source
121
+ self.source = df
122
+
123
+ # we're already in an async thread
124
+ PandasSheet.reload.__wrapped__(self)
125
+
126
+
127
+ def sheet_class_for_obj(vd, stem, key, source):
128
+ # note: Data.type_of() is why we need pdr 1.4.4 or later
129
+ try:
130
+ expected_type = source.type_of(key)
131
+ except FileNotFoundError as e:
132
+ vd.warning(
133
+ f"{stem}/{key}: data unavailable (need file {e.filename})"
134
+ )
135
+ return None
136
+ except TypeError as e:
137
+ vd.warning(
138
+ f"{stem}/{key}: PDR cannot load this object ({e})"
139
+ )
140
+ return None
141
+ except Exception as e:
142
+ vd.warning(
143
+ f"{stem}/{key}: unable to determine expected object type ({e})"
144
+ )
145
+ return None
146
+
147
+ match expected_type.__name__:
148
+ case "DataFrame":
149
+ return LazyPandasSheet
150
+
151
+ case "ndarray":
152
+ return LazyNpySheet
153
+
154
+ case "str":
155
+ return LazyTextSheet
156
+
157
+ case other:
158
+ # the other possibilities should only come up for headers,
159
+ # which we skip anyway
160
+ vd.warning(
161
+ f"{stem}: skipping {key} with object type {other}"
162
+ )
163
+ return None
164
+
165
+
166
+ def filtered_keys(source):
167
+ # it _seems_ like we don't need to weed out "header" objects in PDS4
168
+ is_pds4 = source.standard == "PDS4"
169
+ return [
170
+ key for key in sorted(source.keys())
171
+ if key.upper() not in ("LABEL", "HEADER") and (
172
+ is_pds4 or (
173
+ key in source.metadata
174
+ and "HEADER_TYPE" not in source.metadata[key]
175
+ )
176
+ )
177
+ ]
178
+
179
+
180
+ class PDSMetaSheet(TableSheet):
181
+ rowtype = "label metadata" # rowdef: (str, any)
182
+ columns = [
183
+ Column("tag", getter=lambda col,row: row[0]),
184
+ Column("value", getter=lambda col,row: row[1]),
185
+ ]
186
+
187
+ def beforeLoad(self):
188
+ for key in filtered_keys(self.source):
189
+ if self.source._target_path(key) is None:
190
+ self.vd.warning(
191
+ f"data not available for {self._pdr_stem}/{key}"
192
+ )
193
+ continue
194
+
195
+ SheetClass = sheet_class_for_obj(
196
+ self.vd,
197
+ self._pdr_stem,
198
+ key,
199
+ self.source
200
+ )
201
+ if SheetClass is not None:
202
+ self.vd.push(
203
+ SheetClass(
204
+ f"{self._pdr_stem}/{key}",
205
+ source=PDRSource(self.source, key)
206
+ ),
207
+ load=False
208
+ )
209
+ self.vd.push(self)
210
+
211
+ def iterload(self):
212
+ def il_recursive(md, base):
213
+ if hasattr(md, "items"):
214
+ for k, v in md.items():
215
+ yield from il_recursive(v, f"{base}.{k}")
216
+ elif isinstance(md, list):
217
+ for i, v in enumerate(v):
218
+ yield from il_recursive(v, f"{base}[{i}]")
219
+ else:
220
+ yield (base, md)
221
+
222
+ yield ("standard", self.source.standard)
223
+ for k, v in self.source.metadata.items():
224
+ yield from il_recursive(v, k)
225
+
226
+
227
+ @VisiData.api
228
+ def open_pdr(vd, p):
229
+ pdr = vd.importExternal("pdr")
230
+ data = pdr.open(p)
231
+ stem = p.base_stem
232
+ return PDSMetaSheet(
233
+ f"{stem}/metadata",
234
+ source=data,
235
+ _pdr_stem=stem,
236
+ )
237
+
238
+
239
+ @VisiData.api
240
+ def guess_pdr(vd, p):
241
+ pdr = vd.importExternal("pdr")
242
+
243
+ # It's easiest to just go ahead and try to open it. PDR already
244
+ # tries pretty hard to do minimal work at open time.
245
+ try:
246
+ data = pdr.open(p)
247
+ except Exception:
248
+ return None
249
+
250
+ if data.standard in ("PDS3", "PDS4"):
251
+ likelihood = 10
252
+ elif data.standard == "FITS":
253
+ likelihood = 7 # leave room for a dedicated FITS loader
254
+ else:
255
+ likelihood = 3
256
+
257
+ # If we could pass `data` from here to the *open function*,
258
+ # that would be worth doing, but AFAICT we can't do that.
259
+ return {
260
+ "filetype": "pdr",
261
+ "_likelihood": likelihood
262
+ }
@@ -0,0 +1,47 @@
1
+ Metadata-Version: 2.4
2
+ Name: visidata_pdr
3
+ Version: 0.1.0
4
+ Summary: Load tabular data understood by PDR into VisiData
5
+ Author-email: Zack Weinberg <zack@millionconcepts.com>
6
+ License-Expression: BSD-3-Clause
7
+ Project-URL: Repository, https://github.com/MillionConcepts/visidata-pdr
8
+ Classifier: Development Status :: 3 - Alpha
9
+ Classifier: Environment :: Console
10
+ Classifier: Environment :: Console :: Curses
11
+ Classifier: Operating System :: OS Independent
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Intended Audience :: Science/Research
14
+ Classifier: Topic :: Scientific/Engineering :: Astronomy
15
+ Classifier: Topic :: Scientific/Engineering :: Visualization
16
+ Requires-Python: >=3.11
17
+ Description-Content-Type: text/markdown
18
+ License-File: LICENSE.md
19
+ Requires-Dist: pdr[fits,pillow,pvl]>=1.4.4
20
+ Requires-Dist: visidata>=3.3
21
+ Dynamic: license-file
22
+
23
+ # visidata_pdr: Load tabular data into VisiData using PDR
24
+
25
+ This [VisiData][] plugin adds a loader that can load any type of tabular
26
+ data understood by the [Planetary Data Reader][PDR] (PDR).
27
+
28
+ [VisiData]: https://www.visidata.org/
29
+ [PDR]: https://github.com/MillionConcepts/pdr
30
+
31
+ ## Usage
32
+
33
+ After installing the plugin, the `pdr` loader can read any data file
34
+ that `pdr.open()` would understand. For example, suppose you have
35
+ downloaded the [Mars Global Surveyor][]’s
36
+ [Thermal Emission Spectrometer data set][] and you want to look at
37
+ the first batch of data (MY24; 1999-02-28T21):
38
+
39
+ ```
40
+ $ vd -f pdr TES_COD_IR_MY24_Ls090_Ls120.xml
41
+ ```
42
+
43
+ It would also work to specify the `.dat` file. Either way, both the
44
+ data and the label must be available.
45
+
46
+ [Mars Global Surveyor]: https://atmos.nmsu.edu/data_and_services/atmospheres_data/MARS/mgs.html
47
+ [Thermal Emission Spectrometer data set]: https://atmos.nmsu.edu/data_and_services/atmospheres_data/MARS/montabone.html
@@ -0,0 +1,16 @@
1
+ LICENSE.md
2
+ MANIFEST.in
3
+ README.md
4
+ pyproject.toml
5
+ sample_data/pds3_mer_rss_uhfd/ODY2004050_S253.CSV
6
+ sample_data/pds3_mer_rss_uhfd/ODY2004050_S253.LBL
7
+ tests/ody2004050_s253.vdj
8
+ tests/golden/ody2004050_s253.tsv
9
+ visidata_pdr/__init__.py
10
+ visidata_pdr/visidata_pdr.py
11
+ visidata_pdr.egg-info/PKG-INFO
12
+ visidata_pdr.egg-info/SOURCES.txt
13
+ visidata_pdr.egg-info/dependency_links.txt
14
+ visidata_pdr.egg-info/entry_points.txt
15
+ visidata_pdr.egg-info/requires.txt
16
+ visidata_pdr.egg-info/top_level.txt
@@ -0,0 +1,2 @@
1
+ [visidata.plugins]
2
+ visidata_pdr = visidata_pdr.visidata_pdr
@@ -0,0 +1,2 @@
1
+ pdr[fits,pillow,pvl]>=1.4.4
2
+ visidata>=3.3
@@ -0,0 +1 @@
1
+ visidata_pdr