init
This commit is contained in:
parent
b5c617c9bb
commit
61930aeb02
3
.gitignore
vendored
3
.gitignore
vendored
@ -1 +1,4 @@
|
|||||||
/target
|
/target
|
||||||
|
.idea
|
||||||
|
|
||||||
|
*/target/*
|
||||||
1331
Cargo.lock
generated
1331
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -1,3 +1,3 @@
|
|||||||
|
|
||||||
[workspace]
|
[workspace]
|
||||||
members = ["mp"]
|
members = ["mp", "mp_core", "radarg_plugin_interface"]
|
||||||
|
|||||||
263
config.toml
Normal file
263
config.toml
Normal file
@ -0,0 +1,263 @@
|
|||||||
|
[common]
|
||||||
|
background = "Terrain"
|
||||||
|
path = "resources/alts.png"
|
||||||
|
plugins = "loaders"
|
||||||
|
|
||||||
|
[[cmap]]
|
||||||
|
type = "DBZ"
|
||||||
|
levels = [0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75]
|
||||||
|
colors = [
|
||||||
|
"#aaaaaa",
|
||||||
|
"#0022ff",
|
||||||
|
"#01a0f6",
|
||||||
|
"#00ecec",
|
||||||
|
"#00d800",
|
||||||
|
"#019000",
|
||||||
|
"#ffff00",
|
||||||
|
"#e7c000",
|
||||||
|
"#ff9000",
|
||||||
|
"#ff0000",
|
||||||
|
"#d60000",
|
||||||
|
"#c00000",
|
||||||
|
"#ff00f0",
|
||||||
|
"#9600b4",
|
||||||
|
"#ad90f0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[cmap]]
|
||||||
|
type = "VEL"
|
||||||
|
levels = [
|
||||||
|
-90,
|
||||||
|
-45,
|
||||||
|
-35,
|
||||||
|
-27,
|
||||||
|
-20,
|
||||||
|
-15,
|
||||||
|
-10,
|
||||||
|
-5,
|
||||||
|
-1,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
5,
|
||||||
|
10,
|
||||||
|
15,
|
||||||
|
20,
|
||||||
|
27,
|
||||||
|
1000,
|
||||||
|
]
|
||||||
|
colors = [
|
||||||
|
"#9fffff",
|
||||||
|
"#00e0ff",
|
||||||
|
"#0080ff",
|
||||||
|
"#320096",
|
||||||
|
"#00fb90",
|
||||||
|
"#00bb90",
|
||||||
|
"#008f00",
|
||||||
|
"#cdc09f",
|
||||||
|
"#000000",
|
||||||
|
"#f88700",
|
||||||
|
"#ffcf00",
|
||||||
|
"#ffff00",
|
||||||
|
"#ae0000",
|
||||||
|
"#d07000",
|
||||||
|
"#dd0000",
|
||||||
|
"#ff0000",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[cmap]]
|
||||||
|
type = "SW"
|
||||||
|
colors = [
|
||||||
|
"#E0E0E0",
|
||||||
|
"#7CE0E0",
|
||||||
|
"#00E0E0",
|
||||||
|
"#00B0B0",
|
||||||
|
"#00FEFE",
|
||||||
|
"#00C400",
|
||||||
|
"#008000",
|
||||||
|
"#FEFE00",
|
||||||
|
"#FED200",
|
||||||
|
"#FE7C00",
|
||||||
|
"#FEB0B0",
|
||||||
|
"#FE5858",
|
||||||
|
"#FE0000",
|
||||||
|
"#FEFEFE",
|
||||||
|
]
|
||||||
|
levels = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
|
||||||
|
|
||||||
|
[[cmap]]
|
||||||
|
type = "CC"
|
||||||
|
colors = [
|
||||||
|
"#003CFF",
|
||||||
|
"#00EFEF",
|
||||||
|
"#00BABF",
|
||||||
|
"#00837D",
|
||||||
|
"#008938",
|
||||||
|
"#00B729",
|
||||||
|
"#00DA0D",
|
||||||
|
"#00FF00",
|
||||||
|
"#FFFF3B",
|
||||||
|
"#FFF000",
|
||||||
|
"#FFC600",
|
||||||
|
"#FFA500",
|
||||||
|
"#FF7200",
|
||||||
|
"#FF1F00",
|
||||||
|
"#C10000",
|
||||||
|
"#D400AA",
|
||||||
|
]
|
||||||
|
levels = [
|
||||||
|
0,
|
||||||
|
0.1,
|
||||||
|
0.3,
|
||||||
|
0.5,
|
||||||
|
0.6,
|
||||||
|
0.7,
|
||||||
|
0.8,
|
||||||
|
0.85,
|
||||||
|
0.9,
|
||||||
|
0.92,
|
||||||
|
0.94,
|
||||||
|
0.95,
|
||||||
|
0.96,
|
||||||
|
0.97,
|
||||||
|
0.98,
|
||||||
|
0.99,
|
||||||
|
]
|
||||||
|
|
||||||
|
[[cmap]]
|
||||||
|
type = "KDP"
|
||||||
|
colors = [
|
||||||
|
"#00FFFF",
|
||||||
|
"#00EFEF",
|
||||||
|
"#00A8AC",
|
||||||
|
"#B4B4B4",
|
||||||
|
"#B4B4B4",
|
||||||
|
"#00C027",
|
||||||
|
"#00E80A",
|
||||||
|
"#24FF24",
|
||||||
|
"#FFFF1E",
|
||||||
|
"#FFE600",
|
||||||
|
"#FFBC00",
|
||||||
|
"#FF9800",
|
||||||
|
"#FF5E00",
|
||||||
|
"#F20F00",
|
||||||
|
"#BB003A",
|
||||||
|
"#DD009C",
|
||||||
|
"#FF00FF",
|
||||||
|
]
|
||||||
|
levels = [
|
||||||
|
-0.8,
|
||||||
|
-0.4,
|
||||||
|
-0.2,
|
||||||
|
-0.1,
|
||||||
|
0.1,
|
||||||
|
0.15,
|
||||||
|
0.22,
|
||||||
|
0.33,
|
||||||
|
0.5,
|
||||||
|
0.75,
|
||||||
|
1.1,
|
||||||
|
1.7,
|
||||||
|
2.4,
|
||||||
|
3.1,
|
||||||
|
7,
|
||||||
|
20,
|
||||||
|
]
|
||||||
|
|
||||||
|
[[cmap]]
|
||||||
|
type = "ZDR"
|
||||||
|
colors = [
|
||||||
|
"#464646",
|
||||||
|
"#505050",
|
||||||
|
"#5A5A5A",
|
||||||
|
"#646464",
|
||||||
|
"#6E6E6E",
|
||||||
|
"#787878",
|
||||||
|
"#828282",
|
||||||
|
"#8C8C8C",
|
||||||
|
"#969696",
|
||||||
|
"#AFAFAF",
|
||||||
|
"#C8C8C8",
|
||||||
|
"#DCF0DC",
|
||||||
|
"#00C027",
|
||||||
|
"#00E80A",
|
||||||
|
"#24FF24",
|
||||||
|
"#FFFF1E",
|
||||||
|
"#FFF20F",
|
||||||
|
"#FFE600",
|
||||||
|
"#FFBC00",
|
||||||
|
"#FF9800",
|
||||||
|
"#FF5E00",
|
||||||
|
"#FFFF00",
|
||||||
|
"#F20F00",
|
||||||
|
"#BB003A",
|
||||||
|
"#DD009C",
|
||||||
|
"#FF00FF",
|
||||||
|
]
|
||||||
|
levels = [
|
||||||
|
-5,
|
||||||
|
-4.5,
|
||||||
|
-4,
|
||||||
|
-3.5,
|
||||||
|
-3,
|
||||||
|
-2.5,
|
||||||
|
-2,
|
||||||
|
-1.5,
|
||||||
|
-1,
|
||||||
|
-0.5,
|
||||||
|
0,
|
||||||
|
0.5,
|
||||||
|
1,
|
||||||
|
1.5,
|
||||||
|
2,
|
||||||
|
2.5,
|
||||||
|
3,
|
||||||
|
3.5,
|
||||||
|
4,
|
||||||
|
4.5,
|
||||||
|
5,
|
||||||
|
5.5,
|
||||||
|
6,
|
||||||
|
6.5,
|
||||||
|
7,
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
[[cmap]]
|
||||||
|
type = "VIL"
|
||||||
|
levels = [
|
||||||
|
0.1,
|
||||||
|
1,
|
||||||
|
2.5,
|
||||||
|
5,
|
||||||
|
7.5,
|
||||||
|
10,
|
||||||
|
10.25,
|
||||||
|
15,
|
||||||
|
20,
|
||||||
|
25,
|
||||||
|
30,
|
||||||
|
35,
|
||||||
|
40,
|
||||||
|
45,
|
||||||
|
50,
|
||||||
|
55,
|
||||||
|
104,
|
||||||
|
]
|
||||||
|
colors = [
|
||||||
|
'#484892',
|
||||||
|
'#01a0f6',
|
||||||
|
'#00ecec',
|
||||||
|
'#01ff00',
|
||||||
|
'#00c800',
|
||||||
|
'#019000',
|
||||||
|
'#ffff00',
|
||||||
|
'#e7c000',
|
||||||
|
'#ff9000',
|
||||||
|
'#ff0000',
|
||||||
|
'#d60000',
|
||||||
|
'#c00000',
|
||||||
|
'#ff00f0',
|
||||||
|
'#ad90f0',
|
||||||
|
'#780084',
|
||||||
|
'#d8af97',
|
||||||
|
]
|
||||||
1788
loaders/Cargo.lock
generated
Normal file
1788
loaders/Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
2
loaders/Cargo.toml
Normal file
2
loaders/Cargo.toml
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
[workspace]
|
||||||
|
members = ["etws_loader"]
|
||||||
974
loaders/etws_loader/Cargo.lock
generated
Normal file
974
loaders/etws_loader/Cargo.lock
generated
Normal file
@ -0,0 +1,974 @@
|
|||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "abi_stable"
|
||||||
|
version = "0.11.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "69d6512d3eb05ffe5004c59c206de7f99c34951504056ce23fc953842f12c445"
|
||||||
|
dependencies = [
|
||||||
|
"abi_stable_derive",
|
||||||
|
"abi_stable_shared",
|
||||||
|
"const_panic",
|
||||||
|
"core_extensions",
|
||||||
|
"crossbeam-channel",
|
||||||
|
"generational-arena",
|
||||||
|
"libloading",
|
||||||
|
"lock_api",
|
||||||
|
"parking_lot",
|
||||||
|
"paste",
|
||||||
|
"repr_offset",
|
||||||
|
"rustc_version",
|
||||||
|
"serde",
|
||||||
|
"serde_derive",
|
||||||
|
"serde_json",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "abi_stable_derive"
|
||||||
|
version = "0.11.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d7178468b407a4ee10e881bc7a328a65e739f0863615cca4429d43916b05e898"
|
||||||
|
dependencies = [
|
||||||
|
"abi_stable_shared",
|
||||||
|
"as_derive_utils",
|
||||||
|
"core_extensions",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"rustc_version",
|
||||||
|
"syn 1.0.109",
|
||||||
|
"typed-arena",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "abi_stable_shared"
|
||||||
|
version = "0.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b2b5df7688c123e63f4d4d649cba63f2967ba7f7861b1664fca3f77d3dad2b63"
|
||||||
|
dependencies = [
|
||||||
|
"core_extensions",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "adler"
|
||||||
|
version = "1.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ahash"
|
||||||
|
version = "0.8.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"once_cell",
|
||||||
|
"version_check",
|
||||||
|
"zerocopy",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "allocator-api2"
|
||||||
|
version = "0.2.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "android-tzdata"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "android_system_properties"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anyhow"
|
||||||
|
version = "1.0.79"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "approx"
|
||||||
|
version = "0.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6"
|
||||||
|
dependencies = [
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "as_derive_utils"
|
||||||
|
version = "0.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ff3c96645900a44cf11941c111bd08a6573b0e2f9f69bc9264b179d8fae753c4"
|
||||||
|
dependencies = [
|
||||||
|
"core_extensions",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 1.0.109",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "autocfg"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "1.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bumpalo"
|
||||||
|
version = "3.14.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "byteorder"
|
||||||
|
version = "1.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cc"
|
||||||
|
version = "1.0.83"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cfg-if"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "chrono"
|
||||||
|
version = "0.4.33"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9f13690e35a5e4ace198e7beea2895d29f3a9cc55015fcebe6336bd2010af9eb"
|
||||||
|
dependencies = [
|
||||||
|
"android-tzdata",
|
||||||
|
"iana-time-zone",
|
||||||
|
"js-sys",
|
||||||
|
"num-traits",
|
||||||
|
"serde",
|
||||||
|
"wasm-bindgen",
|
||||||
|
"windows-targets 0.52.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "const_panic"
|
||||||
|
version = "0.2.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6051f239ecec86fde3410901ab7860d458d160371533842974fc61f96d15879b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "core-foundation-sys"
|
||||||
|
version = "0.8.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "core_extensions"
|
||||||
|
version = "1.5.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "92c71dc07c9721607e7a16108336048ee978c3a8b129294534272e8bac96c0ee"
|
||||||
|
dependencies = [
|
||||||
|
"core_extensions_proc_macros",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "core_extensions_proc_macros"
|
||||||
|
version = "1.5.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "69f3b219d28b6e3b4ac87bc1fc522e0803ab22e055da177bff0068c4150c61a6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crc32fast"
|
||||||
|
version = "1.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-channel"
|
||||||
|
version = "0.5.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "176dc175b78f56c0f321911d9c8eb2b77a78a4860b9c19db83835fea1a46649b"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-utils"
|
||||||
|
version = "0.8.19"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "earcutr"
|
||||||
|
version = "0.4.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "79127ed59a85d7687c409e9978547cffb7dc79675355ed22da6b66fd5f6ead01"
|
||||||
|
dependencies = [
|
||||||
|
"itertools",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "either"
|
||||||
|
version = "1.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "etws_loader"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"abi_stable",
|
||||||
|
"anyhow",
|
||||||
|
"byteorder",
|
||||||
|
"chrono",
|
||||||
|
"flate2",
|
||||||
|
"geo",
|
||||||
|
"nom",
|
||||||
|
"nom-derive",
|
||||||
|
"num-traits",
|
||||||
|
"radarg_plugin_interface",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"thiserror",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "flate2"
|
||||||
|
version = "1.0.28"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e"
|
||||||
|
dependencies = [
|
||||||
|
"crc32fast",
|
||||||
|
"miniz_oxide",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "float_next_after"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8bf7cc16383c4b8d58b9905a8509f02926ce3058053c056376248d958c9df1e8"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "generational-arena"
|
||||||
|
version = "0.2.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "877e94aff08e743b651baaea359664321055749b398adff8740a7399af7796e7"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "geo"
|
||||||
|
version = "0.28.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f811f663912a69249fa620dcd2a005db7254529da2d8a0b23942e81f47084501"
|
||||||
|
dependencies = [
|
||||||
|
"earcutr",
|
||||||
|
"float_next_after",
|
||||||
|
"geo-types",
|
||||||
|
"geographiclib-rs",
|
||||||
|
"log",
|
||||||
|
"num-traits",
|
||||||
|
"robust",
|
||||||
|
"rstar",
|
||||||
|
"spade",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "geo-types"
|
||||||
|
version = "0.7.13"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9ff16065e5720f376fbced200a5ae0f47ace85fd70b7e54269790281353b6d61"
|
||||||
|
dependencies = [
|
||||||
|
"approx",
|
||||||
|
"num-traits",
|
||||||
|
"rstar",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "geographiclib-rs"
|
||||||
|
version = "0.2.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e6e5ed84f8089c70234b0a8e0aedb6dc733671612ddc0d37c6066052f9781960"
|
||||||
|
dependencies = [
|
||||||
|
"libm",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hash32"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606"
|
||||||
|
dependencies = [
|
||||||
|
"byteorder",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hashbrown"
|
||||||
|
version = "0.14.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
|
||||||
|
dependencies = [
|
||||||
|
"ahash",
|
||||||
|
"allocator-api2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "heapless"
|
||||||
|
version = "0.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad"
|
||||||
|
dependencies = [
|
||||||
|
"hash32",
|
||||||
|
"stable_deref_trait",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "iana-time-zone"
|
||||||
|
version = "0.1.59"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b6a67363e2aa4443928ce15e57ebae94fd8949958fd1223c4cfc0cd473ad7539"
|
||||||
|
dependencies = [
|
||||||
|
"android_system_properties",
|
||||||
|
"core-foundation-sys",
|
||||||
|
"iana-time-zone-haiku",
|
||||||
|
"js-sys",
|
||||||
|
"wasm-bindgen",
|
||||||
|
"windows-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "iana-time-zone-haiku"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itertools"
|
||||||
|
version = "0.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57"
|
||||||
|
dependencies = [
|
||||||
|
"either",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itoa"
|
||||||
|
version = "1.0.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "js-sys"
|
||||||
|
version = "0.3.67"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9a1d36f1235bc969acba30b7f5990b864423a6068a10f7c90ae8f0112e3a59d1"
|
||||||
|
dependencies = [
|
||||||
|
"wasm-bindgen",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.152"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libloading"
|
||||||
|
version = "0.7.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libm"
|
||||||
|
version = "0.2.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lock_api"
|
||||||
|
version = "0.4.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"scopeguard",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "log"
|
||||||
|
version = "0.4.20"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memchr"
|
||||||
|
version = "2.7.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "minimal-lexical"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "miniz_oxide"
|
||||||
|
version = "0.7.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
|
||||||
|
dependencies = [
|
||||||
|
"adler",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nom"
|
||||||
|
version = "7.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
"minimal-lexical",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nom-derive"
|
||||||
|
version = "0.10.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1ff943d68b88d0b87a6e0d58615e8fa07f9fd5a1319fa0a72efc1f62275c79a7"
|
||||||
|
dependencies = [
|
||||||
|
"nom",
|
||||||
|
"nom-derive-impl",
|
||||||
|
"rustversion",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nom-derive-impl"
|
||||||
|
version = "0.10.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cd0b9a93a84b0d3ec3e70e02d332dc33ac6dfac9cde63e17fcb77172dededa62"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 1.0.109",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-traits"
|
||||||
|
version = "0.2.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"libm",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "once_cell"
|
||||||
|
version = "1.19.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "parking_lot"
|
||||||
|
version = "0.12.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
|
||||||
|
dependencies = [
|
||||||
|
"lock_api",
|
||||||
|
"parking_lot_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "parking_lot_core"
|
||||||
|
version = "0.9.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"redox_syscall",
|
||||||
|
"smallvec",
|
||||||
|
"windows-targets 0.48.5",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "paste"
|
||||||
|
version = "1.0.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.78"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.35"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "radarg_plugin_interface"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"abi_stable",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "redox_syscall"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "repr_offset"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fb1070755bd29dffc19d0971cab794e607839ba2ef4b69a9e6fbc8733c1b72ea"
|
||||||
|
dependencies = [
|
||||||
|
"tstr",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "robust"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cbf4a6aa5f6d6888f39e980649f3ad6b666acdce1d78e95b8a2cb076e687ae30"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rstar"
|
||||||
|
version = "0.12.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "133315eb94c7b1e8d0cb097e5a710d850263372fd028fff18969de708afc7008"
|
||||||
|
dependencies = [
|
||||||
|
"heapless",
|
||||||
|
"num-traits",
|
||||||
|
"smallvec",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustc_version"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
|
||||||
|
dependencies = [
|
||||||
|
"semver",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustversion"
|
||||||
|
version = "1.0.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ryu"
|
||||||
|
version = "1.0.16"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "scopeguard"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "semver"
|
||||||
|
version = "1.0.21"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde"
|
||||||
|
version = "1.0.196"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32"
|
||||||
|
dependencies = [
|
||||||
|
"serde_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_derive"
|
||||||
|
version = "1.0.196"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.48",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_json"
|
||||||
|
version = "1.0.112"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4d1bd37ce2324cf3bf85e5a25f96eb4baf0d5aa6eba43e7ae8958870c4ec48ed"
|
||||||
|
dependencies = [
|
||||||
|
"itoa",
|
||||||
|
"ryu",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "smallvec"
|
||||||
|
version = "1.13.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "spade"
|
||||||
|
version = "2.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "61addf9117b11d1f5b4bf6fe94242ba25f59d2d4b2080544b771bd647024fd00"
|
||||||
|
dependencies = [
|
||||||
|
"hashbrown",
|
||||||
|
"num-traits",
|
||||||
|
"robust",
|
||||||
|
"smallvec",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "stable_deref_trait"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "1.0.109"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "2.0.48"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror"
|
||||||
|
version = "1.0.56"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad"
|
||||||
|
dependencies = [
|
||||||
|
"thiserror-impl",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror-impl"
|
||||||
|
version = "1.0.56"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.48",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tstr"
|
||||||
|
version = "0.2.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cca3264971090dec0feef3b455a3c178f02762f7550cf4592991ac64b3be2d7e"
|
||||||
|
dependencies = [
|
||||||
|
"tstr_proc_macros",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tstr_proc_macros"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e78122066b0cb818b8afd08f7ed22f7fdbc3e90815035726f0840d0d26c0747a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "typed-arena"
|
||||||
|
version = "2.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-ident"
|
||||||
|
version = "1.0.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "version_check"
|
||||||
|
version = "0.9.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen"
|
||||||
|
version = "0.2.90"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b1223296a201415c7fad14792dbefaace9bd52b62d33453ade1c5b5f07555406"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"wasm-bindgen-macro",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-backend"
|
||||||
|
version = "0.2.90"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fcdc935b63408d58a32f8cc9738a0bffd8f05cc7c002086c6ef20b7312ad9dcd"
|
||||||
|
dependencies = [
|
||||||
|
"bumpalo",
|
||||||
|
"log",
|
||||||
|
"once_cell",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.48",
|
||||||
|
"wasm-bindgen-shared",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-macro"
|
||||||
|
version = "0.2.90"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3e4c238561b2d428924c49815533a8b9121c664599558a5d9ec51f8a1740a999"
|
||||||
|
dependencies = [
|
||||||
|
"quote",
|
||||||
|
"wasm-bindgen-macro-support",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-macro-support"
|
||||||
|
version = "0.2.90"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bae1abb6806dc1ad9e560ed242107c0f6c84335f1749dd4e8ddb012ebd5e25a7"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.48",
|
||||||
|
"wasm-bindgen-backend",
|
||||||
|
"wasm-bindgen-shared",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-shared"
|
||||||
|
version = "0.2.90"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4d91413b1c31d7539ba5ef2451af3f0b833a005eb27a631cec32bc0635a8602b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi"
|
||||||
|
version = "0.3.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||||
|
dependencies = [
|
||||||
|
"winapi-i686-pc-windows-gnu",
|
||||||
|
"winapi-x86_64-pc-windows-gnu",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-i686-pc-windows-gnu"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-x86_64-pc-windows-gnu"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-core"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
|
||||||
|
dependencies = [
|
||||||
|
"windows-targets 0.52.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-targets"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
|
||||||
|
dependencies = [
|
||||||
|
"windows_aarch64_gnullvm 0.48.5",
|
||||||
|
"windows_aarch64_msvc 0.48.5",
|
||||||
|
"windows_i686_gnu 0.48.5",
|
||||||
|
"windows_i686_msvc 0.48.5",
|
||||||
|
"windows_x86_64_gnu 0.48.5",
|
||||||
|
"windows_x86_64_gnullvm 0.48.5",
|
||||||
|
"windows_x86_64_msvc 0.48.5",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-targets"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd"
|
||||||
|
dependencies = [
|
||||||
|
"windows_aarch64_gnullvm 0.52.0",
|
||||||
|
"windows_aarch64_msvc 0.52.0",
|
||||||
|
"windows_i686_gnu 0.52.0",
|
||||||
|
"windows_i686_msvc 0.52.0",
|
||||||
|
"windows_x86_64_gnu 0.52.0",
|
||||||
|
"windows_x86_64_gnullvm 0.52.0",
|
||||||
|
"windows_x86_64_msvc 0.52.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_gnullvm"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_gnullvm"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_msvc"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_msvc"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnu"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnu"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_msvc"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_msvc"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnu"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnu"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnullvm"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnullvm"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_msvc"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_msvc"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerocopy"
|
||||||
|
version = "0.7.34"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ae87e3fcd617500e5d106f0380cf7b77f3c6092aae37191433159dda23cfb087"
|
||||||
|
dependencies = [
|
||||||
|
"zerocopy-derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerocopy-derive"
|
||||||
|
version = "0.7.34"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.48",
|
||||||
|
]
|
||||||
30
loaders/etws_loader/Cargo.toml
Normal file
30
loaders/etws_loader/Cargo.toml
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
[package]
|
||||||
|
name = "etws_loader"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["tsuki <tsuki@keitsuki.top>"]
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
abi_stable = "*"
|
||||||
|
anyhow = "1.0.79"
|
||||||
|
bytemuck = "1.17.1"
|
||||||
|
byteorder = "1.5.0"
|
||||||
|
chrono = { version = "0.4.33", features = ["serde"] }
|
||||||
|
flate2 = "1.0.28"
|
||||||
|
geo = "0.28.0"
|
||||||
|
nom = "7.1.3"
|
||||||
|
nom-derive = "0.10.1"
|
||||||
|
num-traits = "0.2.17"
|
||||||
|
serde = { version = "1.0.196", features = ["derive"] }
|
||||||
|
serde_json = "1.0.112"
|
||||||
|
thiserror = "1.0.56"
|
||||||
|
zarrs = "0.16.4"
|
||||||
|
zip = "2.2.0"
|
||||||
|
|
||||||
|
[dependencies.radarg_plugin_interface]
|
||||||
|
version = "0.1"
|
||||||
|
path = "../../radarg_plugin_interface"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
name = "etws_loader"
|
||||||
|
crate-type = ["cdylib", 'rlib']
|
||||||
480
loaders/etws_loader/raw.py
Normal file
480
loaders/etws_loader/raw.py
Normal file
@ -0,0 +1,480 @@
|
|||||||
|
"""
|
||||||
|
大探标准格式解析代码
|
||||||
|
"""
|
||||||
|
|
||||||
|
import gc
|
||||||
|
import numpy as np
|
||||||
|
import struct
|
||||||
|
|
||||||
|
__all__ = ['get_radar_data']
|
||||||
|
|
||||||
|
|
||||||
|
def get_radar_data_new(f):
|
||||||
|
"""
|
||||||
|
:param filename:
|
||||||
|
:return: dbz, vel, w, zdr, cc, dp, kdp, el_n, azm, el
|
||||||
|
"""
|
||||||
|
|
||||||
|
f.seek(0, 2)
|
||||||
|
block_length_all = f.tell()
|
||||||
|
f.seek(0)
|
||||||
|
|
||||||
|
GENERIC_HEADER = { # noqa
|
||||||
|
# 共32bit,保留字节16bit
|
||||||
|
"Magic_Number": struct.unpack('I', f.read(4)), # 魔术字 - --固定标志,用来指示雷达数据文件
|
||||||
|
# "Major_Version": struct.unpack('h', f.read(2)), # 主版本号
|
||||||
|
# "Minor_Version": struct.unpack('h', f.read(2)), # 次版本号
|
||||||
|
"Major_Version": struct.unpack('H', f.read(2)), # 主版本号
|
||||||
|
"Minor_Version": struct.unpack('H', f.read(2)), # 次版本号
|
||||||
|
"Generic_Type": struct.unpack('I', f.read(4)),
|
||||||
|
# 文件类型 - --1–基数据文件;2–气象产品文件;3 - --体扫配置文件;4 - --保留;5 - --体扫调度配置文件;6 - --雷达状态数据文件
|
||||||
|
"Product_Type": struct.unpack('I', f.read(4)), # 产品类型 - --仅在文件类型为2时生效
|
||||||
|
# 保留字节16bit
|
||||||
|
"Reserved": f.read(16)
|
||||||
|
}
|
||||||
|
|
||||||
|
# f.seek(32)
|
||||||
|
SITE_CONFIG = { # 共128bit,保留字节46bit
|
||||||
|
"Site_Code": struct.unpack("8s", f.read(8))[0], # 站号 - --站号具有唯一性,用来区别不同的雷达站,如Z9010
|
||||||
|
"Site_Name": struct.unpack("32s", f.read(32))[0], # 站点名称 - --站点名称,如BeiJing
|
||||||
|
"Latitude": struct.unpack('f', f.read(4))[0], # 纬度 - --雷达站天线所在位置纬度
|
||||||
|
"Longitude": struct.unpack('f', f.read(4))[0], # 经度 - --雷达站天线所在位置经度
|
||||||
|
"Antenna_Height": struct.unpack('I', f.read(4))[0], # 天线高度 - --天线馈源水平时海拔高度
|
||||||
|
"Ground_Height": struct.unpack('I', f.read(4)), # 地面高度 - --雷达塔楼地面海拔高度
|
||||||
|
"Frequency": struct.unpack('f', f.read(4)), # 工作频率
|
||||||
|
# TODO gyj modify
|
||||||
|
# "Beam_Width_Hori": struct.unpack('f', f.read(4)), # 水平波束宽度
|
||||||
|
# "Beam_Width_Vert": struct.unpack('f', f.read(4)), # 垂直波束宽度
|
||||||
|
"Antenna_Type": struct.unpack('I', f.read(4)), # 天线类型
|
||||||
|
"TR_Number": struct.unpack('I', f.read(4)), # 收发单元数量
|
||||||
|
|
||||||
|
|
||||||
|
"RDA_Version": struct.unpack('I', f.read(4)), # RDA版本号 - --雷达数据采集软件版本号
|
||||||
|
# TODO gyj modify
|
||||||
|
# 't':struct.unpack('h', f.read(2))[0],
|
||||||
|
"Radar_Type": {1: "SA", 2: "SB", 3: "SC", 4: "SAD", 7:'SPAR',8:'SPARD',
|
||||||
|
33: "CA", 34: "CB", 35: "CC", 36: "CCJ", 37: "CD", 38: "CAD",
|
||||||
|
43:'CPAR',44:'CPARD',
|
||||||
|
65: "XA", 66: "XAD",69:'XPAR',70:'XPARD'}.get(struct.unpack('h', f.read(2))[0]),
|
||||||
|
# 雷达类型 - --1–SA;2–SB;3–SC;4–SAD;33–CA;34–CB;35–CC;36–CCJ;37–CD;38–CAD;65–XA;66–XAD
|
||||||
|
# 7–SPAR 8–SPARD 43–CPAR 44–CPARD 69–XPAR 70–XPARD
|
||||||
|
# "Antenna_Gain": struct.unpack('h', f.read(2)), # 天线增益 - --编码为实际100倍
|
||||||
|
# "Transmitting_feeder_loss": struct.unpack('h', f.read(2)), # 发射馈线损耗 - --编码为实际损耗100倍
|
||||||
|
# "Receiving_feeder_loss": struct.unpack('h', f.read(2)), # 接收馈线损耗 - --编码为实际损耗100倍
|
||||||
|
# "Other_Loss": struct.unpack('h', f.read(2)), # 其他损耗 - --编码为实际损耗100倍
|
||||||
|
# 保留字节46bit
|
||||||
|
"Reserved": f.read(54)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# f.seek(160)
|
||||||
|
TASK_CONFIG = { # 共256bit,保留字节40bit
|
||||||
|
"Task_Name": struct.unpack("32s", f.read(32)), # 任务名称 - --任务名称,如VCP21
|
||||||
|
"Task_Description": struct.unpack("128s", f.read(128)), # 任务描述
|
||||||
|
"Polarization_Type": struct.unpack('I', f.read(4))[0], # 极化方式 - --1 – 水平极化;2 – 垂直极化;3 – 水平 / 垂直同时;4 – 水平 / 垂直交替
|
||||||
|
"Scan_Type": struct.unpack('I', f.read(4)
|
||||||
|
),
|
||||||
|
# 扫描任务类型 - --0 – 体扫;1–单层PPI;2 – 单层RHI;3 – 单层扇扫;4 – 扇体扫;5 – 多层RHI;6 – 手工扫描
|
||||||
|
# "Pulse_Width": struct.unpack('I', f.read(4)
|
||||||
|
# ), # 脉冲宽度 - --发射脉冲宽度
|
||||||
|
# "Scan_Start_Time": struct.unpack('I', f.read(4)
|
||||||
|
# ), # 扫描开始时间 - --扫描开始时间为UTC标准时间计数, 1970年1月1日0时为起始计数基准点
|
||||||
|
#TODO gyj modify
|
||||||
|
'Scan_Beam_Number':struct.unpack('I', f.read(4)), #扫描配置中的发射波束数量
|
||||||
|
|
||||||
|
"Cut_Number": struct.unpack('I', f.read(4)
|
||||||
|
), # 扫描层数 - --根据扫描任务类型确定的扫描层数,与基数据保存的层数一致
|
||||||
|
|
||||||
|
"Ray_Order": struct.unpack('I', f.read(4)), #径向数据排序,0 – 按径向采集时间排序,1 – 按先方位后俯仰方式排序
|
||||||
|
|
||||||
|
"Scan_Start_Time": struct.unpack('q', f.read(8)
|
||||||
|
), # 扫描开始时间 s - --扫描开始时间为UTC标准时间计数, 1970年1月1日0时为起始计数基准点
|
||||||
|
|
||||||
|
# "Horizontal_Noise": struct.unpack('f', f.read(4)
|
||||||
|
# ), # 水平通道噪声 - --水平通道的噪声电平
|
||||||
|
# "Vertical_Noise": struct.unpack('f', f.read(4)
|
||||||
|
# ), # 垂直通道噪声 - --垂直通道的噪声电平
|
||||||
|
# "Horizontal_Calibration": struct.unpack('f', f.read(4)
|
||||||
|
# ), # 水平通道标定值 - --水平通道的反射率标定常数
|
||||||
|
# "Vertical_Calibration": struct.unpack('f', f.read(4)
|
||||||
|
# ), # 水平通道噪声温度 - --垂直通道的反射率标定常数
|
||||||
|
# "Horizontal_Noise_Temperature": struct.unpack('f', f.read(4)
|
||||||
|
# ), # 水平通道噪声温度
|
||||||
|
# "Vertical_Noise_Temperature": struct.unpack('f', f.read(4)
|
||||||
|
# ), # 垂直通道噪声温度
|
||||||
|
# "ZDR_Calibration": struct.unpack('f', f.read(4)
|
||||||
|
# ), # ZDR标定偏差
|
||||||
|
# "PHIDP_Calibration": struct.unpack('f', f.read(4)
|
||||||
|
# ), # 差分相移标定偏差
|
||||||
|
# "LDR_Calibration": struct.unpack('f', f.read(4)
|
||||||
|
# ), # 系统LDR标定偏差
|
||||||
|
"Reserved": f.read(68)
|
||||||
|
# 保留字节68bit
|
||||||
|
}
|
||||||
|
|
||||||
|
# CUT_CONFIG = { # 每个仰角共256bit,保留72bit
|
||||||
|
# }
|
||||||
|
# print(np.frombuffer(f.read(128),'S128')[0].decode('Windows-1252').encode("utf-8"))
|
||||||
|
|
||||||
|
cut_number = TASK_CONFIG.get("Cut_Number")[0] # 扫描层数
|
||||||
|
Scan_Beam_Number = TASK_CONFIG.get("Scan_Beam_Number")[0] #扫描配置中的发射波束数量
|
||||||
|
# print(cut_number)
|
||||||
|
SCAN_CONFIG = {}
|
||||||
|
for i in range(1, Scan_Beam_Number + 1):
|
||||||
|
# f.seek(416)
|
||||||
|
# 扫描波束配置块(一个)
|
||||||
|
SCAN_CONFIG[i] = {
|
||||||
|
'BEAM_INDEX': struct.unpack('I', f.read(4)), # 按扫描波束依次编号,一个体扫可由多个扫描波束组成,一个扫描波束可输出多个扫描仰角数据
|
||||||
|
'BEAM_TYPE': struct.unpack('I', f.read(4)), # 扫描波束类型 1 – 宽波束 2 – 窄波束
|
||||||
|
'SubPulse_Number': struct.unpack('I', f.read(4)), # 子脉冲数量,主工作脉冲和补盲子脉冲数量总和,以下按作用距离由远及近排列1~4
|
||||||
|
'Tx_Beam_Direction': struct.unpack('f', f.read(4)), # 发射波束中心指向,发射波束中心的俯仰角指向-2.00~90.00
|
||||||
|
'Tx_Beam_Width-H': struct.unpack('f', f.read(4)), # 发射波束水平宽度
|
||||||
|
'Tx_Beam_Width-V': struct.unpack('f', f.read(4)), # 发射波束垂直宽度
|
||||||
|
'Tx_Beam_Gain': struct.unpack('f', f.read(4)), # 发射波束中心增益
|
||||||
|
'Reserved': f.read(100) # 保留字节100bit
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# cut_number = SCAN_CONFIG['0'].get("SubPulse_Number")[0]
|
||||||
|
# cut_number = 4
|
||||||
|
# print('cut_number: ',cut_number)
|
||||||
|
|
||||||
|
# 子脉冲参数块(4个)
|
||||||
|
for j in range(1, 5):
|
||||||
|
SCAN_CONFIG[i]['%d' % j] = { # 共128bit,保留70bit
|
||||||
|
'SubPulse_Strategy': struct.unpack('I', f.read(4)), # 子脉冲策略 0=频分 1=时分
|
||||||
|
'SubPulse_Modulation': struct.unpack('I', f.read(4)), # 子脉冲调制方式 0=单载频 1=线性正调频ULFM 2=线性负调频DLFM 3=非线性正调频UNLFM 4=非线性负调频DNLFM
|
||||||
|
'SubPulse_Frequency': struct.unpack('f', f.read(4)), # 子脉冲频率,点频脉冲指工作频率,调频脉冲指中心频率, 1.00~999,000.00
|
||||||
|
'SubPulse_BandWidth': struct.unpack('f', f.read(4)), # 子脉冲带宽,对调频模式有效,表示双边带宽, MHz兆赫 1.00~99.00
|
||||||
|
'SubPulse_Width': struct.unpack('I', f.read(4)), # 子脉冲宽度,单位为纳秒ns,信号脉冲宽度(时长)
|
||||||
|
'Horizontal_Noise': struct.unpack('f', f.read(4)), # 水平通道噪声,dBm分贝毫瓦,水平通道的噪声电平-100.00~0.00
|
||||||
|
'Vertical_Noise': struct.unpack('f', f.read(4)), # 垂直通道噪声,dBm分贝毫瓦,垂直通道的噪声电平-100.00~0.00
|
||||||
|
'Horizontal_Calibration': struct.unpack('f', f.read(4)), # 水平通道标定偏差,dB分贝,水平通道的标定偏差0.00~200.00
|
||||||
|
'Vertical_Calibration': struct.unpack('f', f.read(4)), # 垂直通道标定偏差,dB分贝,垂直通道的标定偏差0.00~200.00
|
||||||
|
'Horizontal_Noise_Temperature': struct.unpack('f', f.read(4)), # 水平通道噪声温度,单位为K开氏温标,水平通道的噪声温度0.00~800.00
|
||||||
|
'Vertical_Noise_Temperature': struct.unpack('f', f.read(4)), # 垂直通道噪声温度,单位为K开氏温标,垂直通道的噪声温度0.00~800.00
|
||||||
|
'ZDR_Calibration': struct.unpack('f', f.read(4)), # ZDR标定偏差,dB分贝,水平通道的标定偏差 -10.00~10.00
|
||||||
|
'PHIDP_Calibration': struct.unpack('f', f.read(4)), # PHIDP标定偏差,度,水平通道的标定偏差 -180.00~180.00
|
||||||
|
'LDR_Calibration': struct.unpack('f', f.read(4)), # LDR标定偏差,dB分贝,水平通道的标定偏差 -60~0
|
||||||
|
'Pulse_Points': struct.unpack('h', f.read(2)), # 脉冲距离库数, 0~10000,该子脉冲探测的距离库数
|
||||||
|
'Reserved': f.read(70), # 保留字节70bit
|
||||||
|
}
|
||||||
|
|
||||||
|
# # # ========== 接收仰角配置块 ========
|
||||||
|
BEAM_CONFIG = {}
|
||||||
|
for i in range(1, cut_number + 1):
|
||||||
|
BEAM_CONFIG['%d' %i] = {
|
||||||
|
'Cut_Index': struct.unpack('h', f.read(2)), #扫描层索引, 1~256, 基数据仰角编号
|
||||||
|
'Tx_Beam_Index': struct.unpack('h', f.read(2)), # 发射波束索引, 1~256, 对应的发射波束索引
|
||||||
|
'Rx_Beam_Elevation': struct.unpack('f', f.read(4)), #接收波束指向,度, -2.00~90.00, PPI模式的俯仰角
|
||||||
|
'Tx_Beam_Gain': struct.unpack('f', f.read(4)), #发射波束增益,,dB分贝, 在本接收方向上,发射波束的增益
|
||||||
|
'Rx_Beam_Width_H': struct.unpack('f', f.read(4)), #接收波束水平宽度, 度
|
||||||
|
'Rx_Beam_Width_V': struct.unpack('f', f.read(4)), #接收波束垂直宽度, 度
|
||||||
|
'Rx_Beam_Gain': struct.unpack('f', f.read(4)), #接收波束垂直宽度, dB分贝,
|
||||||
|
"Process_Mode": {1: "PPP", 2: "FFT"}.get(struct.unpack('I', f.read(4))[0]), # 处理模式---1---PPP;2---FFT
|
||||||
|
"Wave_Form": {0: "CS连续监测", 1: "CD连续多普勒", 2: "CDX多普勒扩展", 3: "Rx Test", 4: "BATCH批模式", 5: "Dual PRF双PRF",
|
||||||
|
6: "Staggered PRT 参差PRT"}.get(struct.unpack('I', f.read(4))[0]),
|
||||||
|
# 波形类别---0 – CS连续监测;1 – CD连续多普勒;2 – CDX多普勒扩展;3 – Rx Test;4 – BATC H批模式;5 – Dual PRF双PRF ;6---Staggered PRT 参差PRT
|
||||||
|
"N1PRF1": struct.unpack('f', f.read(4)
|
||||||
|
), # 第一组脉冲重复频率1---单位赫兹Hz---对于Batch、双PRF和参差PRT模式,表示高PRF值。对于其它单PRF模式,表示唯一的PRF值。
|
||||||
|
"N1PRF2": struct.unpack('f', f.read(4)
|
||||||
|
), # 第一组脉冲重复频率2---单位赫兹Hz---对Batch、双PRF和参差PRT模式,表示低PRF值。对其它单PRF模式,无效。
|
||||||
|
"N2PRF1": struct.unpack('f', f.read(4)
|
||||||
|
), # 第二组脉冲重复频率1---单位赫兹Hz---对于Batch、双PRF和参差PRT模式,表示高PRF值。对于其它单PRF模式,表示唯一的PRF值。
|
||||||
|
"N2PRF2": struct.unpack('f', f.read(4)
|
||||||
|
), # 第二组脉冲重复频率2---单位赫兹Hz---对Batch、双PRF和参差PRT模式,表示低PRF值。对其它单PRF模式,无效。
|
||||||
|
|
||||||
|
"Dealiasing_Mode": struct.unpack('I', f.read(4)), # 速度退模糊方法---1 – 单PRF;2 –双PRF3:2模式;3 –双PRF4:3模式;4 –双PRF 5:4模式
|
||||||
|
|
||||||
|
"Azimuth": struct.unpack('f', f.read(4)), # 方位角---RHI模式的方位角, 度,0.00~360.00, PPI模式的俯仰角同参数接收波
|
||||||
|
# "Elevation": struct.unpack('f', f.read(4)), # 俯仰角---PPI模式的俯仰角
|
||||||
|
"Start_Angle": struct.unpack('f', f.read(4)), # 起始角度----度,-10.00~360.00---PPI扇扫的起始方位角,或RHI模式的高限仰角
|
||||||
|
"End_Angle": struct.unpack('f', f.read(4)), # 结束角度---度,-10.00~360.00---PPI扇扫的结束方位角,或RHI模式的低限仰角
|
||||||
|
"Angular_Resolution": struct.unpack('f', f.read(4)), # 角度分辨率--度,---径向数据的角度分辨率,仅用于PPI扫描模式
|
||||||
|
"Scan_Speed": struct.unpack('f', f.read(4)), # 扫描速度---度/秒---0.00~100.00---PPI扫描的方位转速,或RHI扫描的俯仰转速
|
||||||
|
"Log_Resolution": struct.unpack('f', f.read(4)), # 强度分辨率---米---1~5,000---强度数据的距离分辨率,支持浮点分辨率
|
||||||
|
"Doppler_Resolution": struct.unpack('f', f.read(4)), # 多普勒分辨率---米---1~5,000---多普勒数据的距离分辨率
|
||||||
|
"Maximum_Range1": struct.unpack('I', f.read(4)), # 最大距离1---米---1~500,000---对应脉冲重复频率1的最大可探测距离
|
||||||
|
"Maximum_Range2": struct.unpack('I', f.read(4)), # 最大距离2---米---1~500,000---对应脉冲重复频率2的最大可探测距离
|
||||||
|
"Start_Range": struct.unpack('I', f.read(4)), # 起始距离---米---1~500,000---数据探测起始距离
|
||||||
|
"Sample1": struct.unpack('I', f.read(4)), # 采样个数1---2~512---对应于脉冲重复频率1的采样个数
|
||||||
|
"Sample2": struct.unpack('I', f.read(4)), # 采样个数2---2~512---对应于脉冲重复频率2的采样个数
|
||||||
|
"Phase_Mode": struct.unpack('I', f.read(4)), # 相位编码模式---1 – 固定相位;2 – 随机相位;3 – SZ编码
|
||||||
|
"Atmospheric_Loss": struct.unpack('f', f.read(4)), # 大气衰减---分贝/千米--0.000000~10.000000---双程大气衰减值,精度为小数点后保留6位
|
||||||
|
"Nyquist_Speed": struct.unpack('f', f.read(4)), # 最大不模糊速度---米/秒---0~100---理论最大不模糊速度
|
||||||
|
"Moments_Mask": struct.unpack("q", f.read(8)), # 数据类型掩码---0~0xFFFFFFFFFFFFFFFF---以掩码的形式表示当前允许获取的数据类型,其中:0–不允许获取数据;1 –允许获取数据。(json1)
|
||||||
|
"Moments_Size_Mask": struct.unpack("q", f.read(8)),# 数据大小掩码---0~0xFFFFFFFFFFFFFFFF---以掩码形式表示每种数据类型字节数,其中:0–1个字节;1 – 2个字节(json1)
|
||||||
|
"Misc_Filter_Mask": struct.unpack('I', f.read(4)), # 滤波设置掩码--0~0xFFFFFFFF---0–未应用;1–应用(json2)
|
||||||
|
"SQI_Threshold": struct.unpack('f', f.read(4)), # SQI门限---0.00~1.00----
|
||||||
|
"SIG_Threshold": struct.unpack('f', f.read(4)), # SIG门限--dB分贝---0.00~20.00
|
||||||
|
"CSR_Threshold": struct.unpack('f', f.read(4)), # CSR门限--dB分贝--0.00~100.00
|
||||||
|
"LOG_Threshold": struct.unpack('f', f.read(4)), # LOG门限--dB分贝--0.00~20.00
|
||||||
|
"CPA_Threshold": struct.unpack('f', f.read(4)), # CPA门限--0.00~100.00--
|
||||||
|
"PMI_Threshold": struct.unpack('f', f.read(4)), # PMI门限--0.00~1.00
|
||||||
|
"DPLOG_Threshold": struct.unpack('f', f.read(4)), # DPLOG门限--0.00~100.00
|
||||||
|
"Thresholds_r": struct.unpack('4s', f.read(4)), #阈值门限保留---水平通道的反射率标定常数 =======保留字段======
|
||||||
|
# 这个时保留字段 "Thresholds_r":data.slice(548,552),#阈值门限保留---水平通道的反射率标定常数
|
||||||
|
"dBT_Mask": struct.unpack('I', f.read(4)), # dBT质控掩码---0~0xFFFFFFFF---dBT数据使用的质控门限掩码,其中:0–未应用,1–应用(json3)
|
||||||
|
"dBZ_Mask": struct.unpack('I', f.read(4)), # dBZ质控掩码---dBZ数据使用的质控门限掩码, 其中:0–未应用,1–应用(json3)
|
||||||
|
"Velocity_Mask": struct.unpack('I', f.read(4)), # 速度质控掩码----0~0xFFFFFFFF---速度数据使用的质控门限掩码, 其中:0–未应用,1–应用(json3)
|
||||||
|
"Spectrum_Width_Mask": struct.unpack('I', f.read(4)), # 谱宽质控掩码----0~0xFFFFFFFF--谱宽数据使用的质控门限掩码,其中:0–未应用,1–应用(json3)
|
||||||
|
"DP_Mask": struct.unpack('I', f.read(4)), # 偏振量质控掩码----0~0xFFFFFFFF--偏振量数据使用的质控门限掩码,其中:0–未应用,1–应用(json3)
|
||||||
|
|
||||||
|
"Mask_Reserved": f.read(12), # 保留字节12bit
|
||||||
|
'Reserved': f.read(4), # 保留字节4bit
|
||||||
|
|
||||||
|
# 保留12bit
|
||||||
|
# "Scan_Sync": struct.unpack('I', f.read(4)), # 扫描同步标志---用于多部雷达同步扫描标识
|
||||||
|
|
||||||
|
"Direction": struct.unpack('I', f.read(4)), # 天线运行方向---仅对PPI模式有效1 – 顺时针;2 – 逆时针
|
||||||
|
"Ground_Clutter_Classifier_Type": struct.unpack('h', f.read(2)), # 地物杂波图类型---1 – 所有数据不滤波;2 – 全程滤波;3 – 使用实时动态滤波图;4 – 使用静态滤波图
|
||||||
|
"Ground_Clutter_Filter_Type": struct.unpack('h', f.read(2)),
|
||||||
|
# 地物滤波类型---0 –不滤波;1 – 频域自适应滤波;2 - 固定宽带频域滤波器;3 - 可变宽带频域滤波器;4 - 可变最小方差频域滤波器;5 – IIR时域滤波
|
||||||
|
"Ground_Clutter_Filter_Notch_Width": struct.unpack('h', f.read(2)), # 地物滤波宽度--0.1 米/秒--0.1~10.0
|
||||||
|
"Ground_Clutter_Filter_Window": struct.unpack('h', f.read(2)),
|
||||||
|
# 滤波窗口类型---滤波算法FFT窗口类型;0 – 矩形窗;1 – 汉明窗;2 – Blackman窗;3 – 自适应窗口;4 – 无
|
||||||
|
"Reserved": f.read(44), # 保留字节44bit
|
||||||
|
}
|
||||||
|
#TODO
|
||||||
|
# radar_range = np.arange(BEAM_CONFIG['1']['Sample1'][0]) * BEAM_CONFIG['1']['Log_Resolution'][0]
|
||||||
|
data_block = f.tell()
|
||||||
|
# print(data_block)
|
||||||
|
# return
|
||||||
|
|
||||||
|
data_shape = {}
|
||||||
|
# for J in range(radial_number):
|
||||||
|
|
||||||
|
|
||||||
|
RadialData = {
|
||||||
|
# 径向头,共128字节 保留13 字节
|
||||||
|
"Radial_State": struct.unpack('I', f.read(4)),
|
||||||
|
# 径向数据状态 - --0–仰角开始;1–中间数据;2–仰角结束;3–体扫开始;4–体扫结束;5–RHI开始;6–RHI结束
|
||||||
|
"Spot_Blank": struct.unpack('I', f.read(4)), # 消隐标志 - --0–正常;1–消隐
|
||||||
|
"Sequence_Number": struct.unpack('I', f.read(4)), # 序号 - 1~65536--每个体扫径向从1计数
|
||||||
|
"Radial_Number": struct.unpack('I', f.read(4)), # 径向数 - 1~1000--每个扫描从1计数
|
||||||
|
"Elevation_Number": struct.unpack('I', f.read(4)), # 仰角编号 - --仰角编号,每个体扫从1计数
|
||||||
|
"Azimuth": struct.unpack('f', f.read(4)), # 方位角 ---度 0.00~360.00 --扫描的方位角度
|
||||||
|
"Elevation": struct.unpack('f', f.read(4)), # 仰角 ---度 -2.00~90.00--扫描的俯仰角度
|
||||||
|
"Seconds": struct.unpack('q', f.read(8)), # 秒 - --径向数据采集的时间,UTC计数的秒数, 从1970年1月1日0时开始计数
|
||||||
|
"Microseconds": struct.unpack('I', f.read(4)), # 微秒 - --径向数据采集的时间除去UTC秒数后,留下的微秒数
|
||||||
|
"Length_of_data": struct.unpack('I', f.read(4)), # 数据长度 --1~100000 --仅本径向数据块所占用的长度如有压缩,长度为压缩后数据长度
|
||||||
|
"Moment_Number": struct.unpack('I', f.read(4)), # 数据类别数量 ---1~64 --径向数据类别(如Z,V,W等各占一种)的数量
|
||||||
|
"Scan Beam Index": struct.unpack('h', f.read(2)), # 波束编号 ---1-32 --波束编号
|
||||||
|
"Horizontal_Estimated_Noise": struct.unpack('h', f.read(2)), # 径向的水平估计噪声 --dB分贝 --编码为实际噪声的 - 100倍
|
||||||
|
"Vertical_Estimated_Noise": struct.unpack('h', f.read(2)), # 径向的垂直估计噪 - --编码为实际噪声的 - 100 倍
|
||||||
|
"PRF_FLAG": struct.unpack('I', f.read(4)), #重频标志, 11 – N1 PRF #1 ; 12 – N1 PRF #2; 21 – N2 PRF #1; 22 – N2 PRF #2; 排列方式:11128888:表示使用N1 PRF #1和PRF #2 #######################uint
|
||||||
|
# 88882122:表示使用N2 PRF #1和PRF #2 11122122:表示使用N1和N2的PRF #1和PRF #2 (对应表2-7中09-13的描述)(8表示无效填充数据,弥补用0表示会出现的问题)
|
||||||
|
|
||||||
|
# "Zip_Type": struct.unpack('h', f.read(2)), # 压缩类型 - --0 - 不压缩;1 - LZO压缩
|
||||||
|
"Reversed": f.read(70) # 保留70bit
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
radial_number = RadialData.get("Radial_Number")[0] # 径向数 J
|
||||||
|
type_number = RadialData.get("Moment_Number")[0] # 数据类别数量 K
|
||||||
|
|
||||||
|
typeHeader = {}
|
||||||
|
# for J in range(radial_number):
|
||||||
|
# for K in range(type_number):
|
||||||
|
|
||||||
|
for i in range(type_number):
|
||||||
|
# typeHeader[J][K] = {
|
||||||
|
typeHeader = {
|
||||||
|
# 共32字节
|
||||||
|
"Data_Type": struct.unpack('I', f.read(4)), # 数据类型 ---1~64 --具体径向数据类型见表2 - 6
|
||||||
|
"Scale": struct.unpack('I', f.read(4)), # 比例 --0~32768 --数据编码的比例
|
||||||
|
"Offset": struct.unpack('I', f.read(4)), # 偏移 --0~32768 --数据编码的偏移
|
||||||
|
"Bin_Length": struct.unpack('h', f.read(2)), # 库字节长度 - --保存一个距离库值用的字节数
|
||||||
|
"Flags": struct.unpack('h', f.read(2)), # 标志 - --数据标志位,暂不使用
|
||||||
|
"Length": struct.unpack('I', f.read(4)), # 长度 --1~32768 --距离库数据的长度,不包括当前的径向数据头大小
|
||||||
|
"Reserved": f.read(12)
|
||||||
|
}
|
||||||
|
|
||||||
|
block_length = typeHeader.get("Length")[0]
|
||||||
|
bin_length = typeHeader.get("Bin_Length")[0]
|
||||||
|
offset = typeHeader.get("Offset")[0]
|
||||||
|
scale = typeHeader.get("Scale")[0]
|
||||||
|
data_body = f.read(block_length)
|
||||||
|
raw = np.frombuffer(data_body, 'u' + str(bin_length)).astype(np.float64)
|
||||||
|
#TODO
|
||||||
|
if i ==0:
|
||||||
|
radar_range = np.arange(len(raw))*30
|
||||||
|
raw[raw <= 5.] = np.nan
|
||||||
|
# 对于保存的编码值来说,5以下的值表示特殊意义,不应该被解码。
|
||||||
|
value = (raw - offset) / scale
|
||||||
|
data_type = typeHeader.get("Data_Type")[0]
|
||||||
|
data_shape[data_type] = value.shape[0]
|
||||||
|
|
||||||
|
block_index = f.tell()
|
||||||
|
roll_num = int((block_length_all - data_block) / (block_index - data_block))
|
||||||
|
azm_num = int(roll_num / cut_number)
|
||||||
|
gc.collect()
|
||||||
|
|
||||||
|
# print("=========",data_shape)
|
||||||
|
# return get_radial_data(f, cut_number, azm_num, data_shape, data_block, SITE_CONFIG, radar_range, TASK_CONFIG['Polarization_Type'])
|
||||||
|
return get_radial_data(f, cut_number, azm_num, data_shape, data_block, SITE_CONFIG, radar_range, TASK_CONFIG['Polarization_Type'], BEAM_CONFIG)
|
||||||
|
|
||||||
|
|
||||||
|
def get_radial_data(f, cut_number, azm_num, data_shape, data_block, site_config, radar_range, polar_type, BEAM_CONFIG):
|
||||||
|
"""
|
||||||
|
|
||||||
|
:param f:
|
||||||
|
:param cut_number: cut number
|
||||||
|
:param azm_num: number of azm
|
||||||
|
:param data_shape: length of block
|
||||||
|
:return: dbz, vel, w, zdr, cc, dp, kdp, el_n, azm, el
|
||||||
|
dbz:滤波后反射率(Reflectivity) dBZ
|
||||||
|
vel:径向速度(Doppler Velocity) V
|
||||||
|
w:谱宽(Spectrum Width) W
|
||||||
|
zdr_:差分反射率(Differential Reflectivity ZDR
|
||||||
|
cc_:协相关系数(Cross Correlation Coefficient) CC
|
||||||
|
dp_:差分相移(Differential Phase) DP
|
||||||
|
kdp_差分相移率(Specific Differential Phase) KDp
|
||||||
|
azm:方位角 维度1
|
||||||
|
el:仰角 维度 1
|
||||||
|
"""
|
||||||
|
_data_dict = {}
|
||||||
|
for k, v in data_shape.items():
|
||||||
|
if k == 2:
|
||||||
|
dbz = np.empty((cut_number, azm_num, v), dtype=np.float64)
|
||||||
|
_data_dict['reflectData'] = dbz
|
||||||
|
elif k == 3:
|
||||||
|
vel = np.empty((cut_number, azm_num, v), dtype=np.float64)
|
||||||
|
_data_dict['velData'] = vel
|
||||||
|
elif k == 4:
|
||||||
|
w = np.empty((cut_number, azm_num, v), dtype=np.float64)
|
||||||
|
_data_dict['widData'] = w
|
||||||
|
elif k == 7:
|
||||||
|
zdr = np.empty((cut_number, azm_num, v), dtype=np.float64)
|
||||||
|
_data_dict['zdrData'] = zdr
|
||||||
|
elif k == 9:
|
||||||
|
cc = np.empty((cut_number, azm_num, v), dtype=np.float64)
|
||||||
|
_data_dict['ccData'] = cc
|
||||||
|
elif k == 10:
|
||||||
|
dp = np.empty((cut_number, azm_num, v), dtype=np.float64)
|
||||||
|
_data_dict['dpData'] = dp
|
||||||
|
elif k == 11:
|
||||||
|
kdp = np.empty((cut_number, azm_num, v), dtype=np.float64)
|
||||||
|
_data_dict['kdpData'] = kdp
|
||||||
|
el_n = np.empty((cut_number, azm_num), np.int32)
|
||||||
|
azm = np.empty((cut_number, azm_num), np.float32)
|
||||||
|
el = np.empty((cut_number, azm_num), np.float32)
|
||||||
|
f.seek(data_block)
|
||||||
|
for j in range(cut_number):
|
||||||
|
for k in range(azm_num):
|
||||||
|
RadialData = {
|
||||||
|
# 共64字节 保留13 字节
|
||||||
|
"Radial_State": struct.unpack('I', f.read(4)),
|
||||||
|
# 径向数据状态 - --0–仰角开始;1–中间数据;2–仰角结束;3–体扫开始;4–体扫结束;5–RHI开始;6–RHI结束
|
||||||
|
"Spot_Blank": struct.unpack('I', f.read(4)
|
||||||
|
), # 消隐标志 - --0–正常;1–消隐
|
||||||
|
"Sequence_Number": struct.unpack('I', f.read(4)
|
||||||
|
), # 序号 - --每个体扫径向从1计数
|
||||||
|
"Radial_Number": struct.unpack('I', f.read(4)
|
||||||
|
), # 径向数 - --每个扫描从1计数
|
||||||
|
"Elevation_Number": struct.unpack('I', f.read(4)
|
||||||
|
), # 仰角编号 - --仰角编号,每个体扫从1计数
|
||||||
|
"Azimuth": struct.unpack('f', f.read(4)
|
||||||
|
), # 方位角 - --扫描的方位角度
|
||||||
|
"Elevation": struct.unpack('f', f.read(4)
|
||||||
|
), # 仰角 - --扫描的俯仰角度
|
||||||
|
"Seconds": struct.unpack('q', f.read(8)
|
||||||
|
), # 秒 - --径向数据采集的时间,UTC计数的秒数, 从1970年1月1日0时开始计数
|
||||||
|
"Microseconds": struct.unpack('I', f.read(4)
|
||||||
|
), # 微秒 - --径向数据采集的时间除去UTC秒数后,留下的微秒数
|
||||||
|
"Length_of_data": struct.unpack('I', f.read(4)
|
||||||
|
), # 数据长度 - --仅本径向数据块所占用的长度如有压缩,长度为压缩后数据长度
|
||||||
|
"Moment_Number": struct.unpack('I', f.read(4)
|
||||||
|
), # 数据类别数量 - --径向数据类别(如Z,V,W等各占一种)的数量
|
||||||
|
"Scan Beam Index": struct.unpack('h', f.read(2)
|
||||||
|
), # 波束编号 ---1-32 --波束编号
|
||||||
|
"Horizontal_Estimated_Noise": struct.unpack('h', f.read(2)
|
||||||
|
), # 径向的水平估计噪声 - --编码为实际噪声的 - 100倍
|
||||||
|
"Vertical_Estimated_Noise": struct.unpack('h', f.read(2)
|
||||||
|
), # 径向的垂直估计噪 - --编码为实际噪声的 - 100 倍
|
||||||
|
|
||||||
|
"PRF_FLAG": struct.unpack('I', f.read(4)), #重频标志, 11 – N1 PRF #1 ; 12 – N1 PRF #2; 21 – N2 PRF #1; 22 – N2 PRF #2; 排列方式:11128888:表示使用N1 PRF #1和PRF #2 #######################uint
|
||||||
|
# 88882122:表示使用N2 PRF #1和PRF #2 11122122:表示使用N1和N2的PRF #1和PRF #2 (对应表2-7中09-13的描述)(8表示无效填充数据,弥补用0表示会出现的问题)
|
||||||
|
# "Zip_Type": struct.unpack('h', f.read(2)
|
||||||
|
# ), # 压缩类型 - --0 - 不压缩;1 - LZO压缩
|
||||||
|
"Reversed": f.read(70) # 保留13bit
|
||||||
|
}
|
||||||
|
# print(f.tell())
|
||||||
|
# f.seek(8672)
|
||||||
|
el_n_ = RadialData.get("Elevation_Number")[0]
|
||||||
|
azm_ = RadialData.get("Azimuth")[0]
|
||||||
|
# el_ = RadialData.get("Elevation")[0]
|
||||||
|
el_ = BEAM_CONFIG['%d' %(j+1)]["Rx_Beam_Elevation"][0]
|
||||||
|
type_number = RadialData.get("Moment_Number")[0]
|
||||||
|
for i in range(type_number):
|
||||||
|
typeHeader = {
|
||||||
|
# 共32字节
|
||||||
|
"Data_Type": struct.unpack('I', f.read(4)), # 数据类型 - --具体径向数据类型见表2 - 6
|
||||||
|
"Scale": struct.unpack('I', f.read(4)
|
||||||
|
), # 比例 - --数据编码的比例
|
||||||
|
"Offset": struct.unpack('I', f.read(4)
|
||||||
|
), # 偏移 - --数据编码的偏移
|
||||||
|
"Bin_Length": struct.unpack('h', f.read(2)
|
||||||
|
), # 库字节长度 - --保存一个距离库值用的字节数
|
||||||
|
"Flags": struct.unpack('h', f.read(2)
|
||||||
|
), # 标志 - --数据标志位,暂不使用
|
||||||
|
"Length": struct.unpack('I', f.read(4)
|
||||||
|
), # 长度 - --距离库数据的长度,不包括当前的径向数据头大小
|
||||||
|
"Reserved": f.read(12)
|
||||||
|
}
|
||||||
|
# print(typeHeader)
|
||||||
|
data_type = typeHeader.get("Data_Type")[0]
|
||||||
|
scale = typeHeader.get("Scale")[0]
|
||||||
|
offset = typeHeader.get("Offset")[0]
|
||||||
|
bin_length = typeHeader.get("Bin_Length")[0]
|
||||||
|
block_length = typeHeader.get("Length")[0]
|
||||||
|
data_body = f.read(block_length)
|
||||||
|
dtype = "u%d" % bin_length
|
||||||
|
# print(body)
|
||||||
|
raw = np.frombuffer(data_body, dtype).astype(np.float64)
|
||||||
|
# raw = np.asarray(struct.unpack(str(block_length) + "B", data_body)).astype(np.float64)
|
||||||
|
raw[raw <= 5.] = np.nan
|
||||||
|
value = (raw - offset) / scale
|
||||||
|
# print(np.nanmin(value))
|
||||||
|
# print(np.nanmax(value))
|
||||||
|
if data_type == 2:
|
||||||
|
# dbz[el_n_ - 1, k, :] = value
|
||||||
|
dbz[el_n_ - 1, k, :len(value)] = value
|
||||||
|
elif data_type == 3:
|
||||||
|
# vel[el_n_ - 1, k, :] = value
|
||||||
|
vel[el_n_ - 1, k, :len(value)] = value
|
||||||
|
elif data_type == 4:
|
||||||
|
# w[el_n_ - 1, k, :] = value
|
||||||
|
w[el_n_ - 1, k, :len(value)] = value
|
||||||
|
elif data_type == 7:
|
||||||
|
# zdr[el_n_ - 1, k, :] = value
|
||||||
|
zdr[el_n_ - 1, k, :len(value)] = value
|
||||||
|
elif data_type == 9:
|
||||||
|
# cc[el_n_ - 1, k, :] = value
|
||||||
|
cc[el_n_ - 1, k, :len(value)] = value
|
||||||
|
elif data_type == 10:
|
||||||
|
# dp[el_n_ - 1, k, :] = value
|
||||||
|
dp[el_n_ - 1, k, :len(value)] = value
|
||||||
|
elif data_type == 11:
|
||||||
|
# kdp[el_n_ - 1, k, :] = value
|
||||||
|
kdp[el_n_ - 1, k, :len(value)] = value
|
||||||
|
|
||||||
|
el_n[el_n_ - 1, k] = el_n_
|
||||||
|
azm[el_n_ - 1, k] = azm_
|
||||||
|
el[el_n_ - 1, k] = el_
|
||||||
|
# print(f"the No.{el_n_} elevation is {el_}")
|
||||||
|
gc.collect()
|
||||||
|
|
||||||
|
result = {
|
||||||
|
'radarNumber': site_config['Site_Code'],
|
||||||
|
'longitude': site_config['Longitude'],
|
||||||
|
'latitude': site_config['Latitude'],
|
||||||
|
'altitude': site_config['Antenna_Height'],
|
||||||
|
'radarRange': radar_range,
|
||||||
|
'azimuthData': azm[1, :],
|
||||||
|
'elevationData': el[:, 1],
|
||||||
|
'polar_type': polar_type
|
||||||
|
}
|
||||||
|
result.update(_data_dict)
|
||||||
|
f.close()
|
||||||
|
return result
|
||||||
23
loaders/etws_loader/src/error.rs
Normal file
23
loaders/etws_loader/src/error.rs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
use nom::error::Error;
|
||||||
|
use thiserror::Error;
|
||||||
|
#[derive(Debug, Error)]
|
||||||
|
pub enum ETWSError {
|
||||||
|
#[error("IO Error")]
|
||||||
|
IOError {
|
||||||
|
#[from]
|
||||||
|
source: std::io::Error,
|
||||||
|
},
|
||||||
|
#[error("Unsupported Format")]
|
||||||
|
FormatError {
|
||||||
|
#[from]
|
||||||
|
source: anyhow::Error,
|
||||||
|
},
|
||||||
|
#[error("Binary Error")]
|
||||||
|
NomError,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> From<nom::Err<nom::error::Error<&'a [u8]>>> for ETWSError {
|
||||||
|
fn from(value: nom::Err<nom::error::Error<&'a [u8]>>) -> Self {
|
||||||
|
ETWSError::NomError
|
||||||
|
}
|
||||||
|
}
|
||||||
252
loaders/etws_loader/src/lib.rs
Normal file
252
loaders/etws_loader/src/lib.rs
Normal file
@ -0,0 +1,252 @@
|
|||||||
|
mod error;
|
||||||
|
mod raw;
|
||||||
|
use raw::parse_raw_data;
|
||||||
|
mod parser;
|
||||||
|
use abi_stable::{
|
||||||
|
export_root_module,
|
||||||
|
prefix_type::PrefixTypeTrait,
|
||||||
|
rvec, sabi_extern_fn,
|
||||||
|
sabi_trait::prelude::TD_Opaque,
|
||||||
|
std_types::{
|
||||||
|
RNone, ROk,
|
||||||
|
ROption::RSome,
|
||||||
|
RResult::{self, RErr},
|
||||||
|
RStr, RString, RVec,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
use parser::{Record, ValueResult};
|
||||||
|
|
||||||
|
use radarg_plugin_interface::{
|
||||||
|
DataLoaderPlugin, DataLoaderPlugin_TO, Error, GridDataInfo, LoadedData, PluginId, PluginMod,
|
||||||
|
PluginMod_Ref, PluginType, ProbeDataType, RadarGridData, VecResult,
|
||||||
|
};
|
||||||
|
|
||||||
|
macro_rules! data_rvec {
|
||||||
|
($data:ident, $({$parsed_vec:tt => $abi_stable_rvec:tt}),+) => {
|
||||||
|
match $data {
|
||||||
|
$(
|
||||||
|
ValueResult::$parsed_vec(data) => VecResult::$abi_stable_rvec(RVec::from(data)),
|
||||||
|
)+
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! data_type {
|
||||||
|
($datetype:ident, $({ $($name:literal)|+ => $type:tt }),+) => {
|
||||||
|
|
||||||
|
match $datetype {
|
||||||
|
$(
|
||||||
|
$($name)|+ => ProbeDataType::$type,
|
||||||
|
)+
|
||||||
|
_ => ProbeDataType::Unknown
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[export_root_module]
|
||||||
|
fn instantiate_root_module() -> PluginMod_Ref {
|
||||||
|
PluginMod { new }.leak_into_prefix()
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ETWSLoader {
|
||||||
|
id: PluginId,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DataLoaderPlugin for ETWSLoader {
|
||||||
|
fn plugin_id(&self) -> &PluginId {
|
||||||
|
&self.id
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load(&self, path: RStr<'_>) -> RResult<RVec<LoadedData>, Error> where {
|
||||||
|
let path = path.as_str();
|
||||||
|
let c = Record::parse_from_path(path.to_string())
|
||||||
|
.map(|record| {
|
||||||
|
let result = record
|
||||||
|
.blocks
|
||||||
|
.into_iter()
|
||||||
|
.map(|b| {
|
||||||
|
let data = b.data;
|
||||||
|
let converted_data = data_rvec!(
|
||||||
|
data,
|
||||||
|
{I16 => I16},
|
||||||
|
{F32 => F32},
|
||||||
|
{F64 => F64},
|
||||||
|
{I32 => I32},
|
||||||
|
{U32 => U32},
|
||||||
|
{I64 => I64},
|
||||||
|
{U64 => U64},
|
||||||
|
{I8 => I8},
|
||||||
|
{U8 => U8}
|
||||||
|
);
|
||||||
|
|
||||||
|
let dimension_values = convert_nested_vec_to_rvec(b.info.dimension_values);
|
||||||
|
let dimension_size = convert_vec_to_rvec(
|
||||||
|
b.info
|
||||||
|
.dimension_size
|
||||||
|
.into_iter()
|
||||||
|
.map(|p| p as usize)
|
||||||
|
.collect::<Vec<_>>(),
|
||||||
|
);
|
||||||
|
let dimension_names = convert_vec_to_rvec(
|
||||||
|
b.info
|
||||||
|
.dimension_des
|
||||||
|
.into_iter()
|
||||||
|
.map(RString::from)
|
||||||
|
.collect::<Vec<_>>(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let fill_value = b.info.fill_value;
|
||||||
|
let value_name = RString::from(b.info.value_name);
|
||||||
|
let value_description = RString::from(b.info.value_des);
|
||||||
|
let datetime = record.filetime.timestamp();
|
||||||
|
|
||||||
|
let value_key = value_name.as_str();
|
||||||
|
|
||||||
|
let data_type = data_type!(
|
||||||
|
value_key,
|
||||||
|
{ "ET" => ET },
|
||||||
|
{ "DBZ" | "CR" | "FR" | "R" | "CR0" | "CR1" | "CR2" => DBZ},
|
||||||
|
{ "VIL" => VIL},
|
||||||
|
{ "EB" => EB},
|
||||||
|
{ "V" => V},
|
||||||
|
{ "ZDR" => ZDR},
|
||||||
|
{ "PHIDP" => PHIDP},
|
||||||
|
{ "KDP" => KDP},
|
||||||
|
{ "CC" =>CC},
|
||||||
|
{ "HCA" => HCA},
|
||||||
|
{ "QPE" => QPE},
|
||||||
|
{ "QPF" => QPF}
|
||||||
|
);
|
||||||
|
|
||||||
|
let grid_info = GridDataInfo {
|
||||||
|
shape: dimension_size,
|
||||||
|
dimensions: dimension_values,
|
||||||
|
dimension_names,
|
||||||
|
fill_value,
|
||||||
|
datetime: RSome(datetime),
|
||||||
|
value_description: RSome(value_description),
|
||||||
|
maybe_probe_data_type: RSome(data_type),
|
||||||
|
value_name,
|
||||||
|
dimension_description: "Wrong".into(),
|
||||||
|
};
|
||||||
|
|
||||||
|
LoadedData::RadarGridData(RadarGridData {
|
||||||
|
data: converted_data,
|
||||||
|
info: grid_info,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.collect::<RVec<_>>();
|
||||||
|
result
|
||||||
|
})
|
||||||
|
.or_else(|_| {
|
||||||
|
let result = parse_raw_data(path)
|
||||||
|
.map(|result| {
|
||||||
|
let data = result.datas;
|
||||||
|
|
||||||
|
let shape = rvec![
|
||||||
|
result.els.len() as usize,
|
||||||
|
result.azs.len() as usize,
|
||||||
|
result.ranges.len() as usize
|
||||||
|
];
|
||||||
|
|
||||||
|
let dimensions = rvec![
|
||||||
|
RVec::from(result.els),
|
||||||
|
RVec::from(result.azs),
|
||||||
|
RVec::from(result.ranges)
|
||||||
|
];
|
||||||
|
|
||||||
|
let dimension_names = rvec!["el".into(), "az".into(), "range".into()];
|
||||||
|
let datetime = result.datetime;
|
||||||
|
|
||||||
|
let loaded = data
|
||||||
|
.into_iter()
|
||||||
|
.map(move |(k, v)| {
|
||||||
|
let data_type = data_type!(
|
||||||
|
k,
|
||||||
|
{ "ET" => ET },
|
||||||
|
{ "DBZ" | "CR" | "FR" | "R" | "CR0" | "CR1" | "CR2" => DBZ},
|
||||||
|
{ "VIL" => VIL},
|
||||||
|
{ "EB" => EB},
|
||||||
|
{ "V" | "VEL" => V},
|
||||||
|
{ "ZDR" => ZDR},
|
||||||
|
{ "PHIDP" => PHIDP},
|
||||||
|
{ "KDP" => KDP},
|
||||||
|
{ "CC" =>CC},
|
||||||
|
{ "HCA" => HCA},
|
||||||
|
{ "QPE" => QPE},
|
||||||
|
{ "QPF" => QPF}
|
||||||
|
);
|
||||||
|
let radar_data = RadarGridData {
|
||||||
|
data: VecResult::F64(RVec::from(v)),
|
||||||
|
info: GridDataInfo {
|
||||||
|
shape: shape.clone(),
|
||||||
|
dimensions: dimensions.clone(),
|
||||||
|
dimension_names: dimension_names.clone(),
|
||||||
|
fill_value: 0.0,
|
||||||
|
datetime: RSome(datetime),
|
||||||
|
value_description: RNone,
|
||||||
|
maybe_probe_data_type: RSome(data_type),
|
||||||
|
value_name: RString::from(k),
|
||||||
|
dimension_description: "Wrong".into(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
LoadedData::RadarGridData(radar_data)
|
||||||
|
})
|
||||||
|
.collect::<RVec<_>>();
|
||||||
|
|
||||||
|
loaded
|
||||||
|
})
|
||||||
|
.map_err(|_| Error::UnsupportedFormat)?;
|
||||||
|
Ok(result)
|
||||||
|
});
|
||||||
|
|
||||||
|
RResult::from(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn plugin_info(&self) -> radarg_plugin_interface::PluginInfo where {
|
||||||
|
radarg_plugin_interface::PluginInfo {
|
||||||
|
plugin_type: "DataLoader".into(),
|
||||||
|
name: "ETWS_Loader".into(),
|
||||||
|
version: "0.1.0".into(),
|
||||||
|
author: "Tsuki".into(),
|
||||||
|
description: RSome("ETWS Loader".into()),
|
||||||
|
url: RSome("https://keitsuki.club".into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn convert_iter_to_rvec<T>(raw: impl Iterator<Item = T>) -> RVec<T> {
|
||||||
|
RVec::from(raw.collect::<Vec<_>>())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn convert_vec_to_rvec<T>(raw: Vec<T>) -> RVec<T> {
|
||||||
|
RVec::from(raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn convert_nested_vec_to_rvec<T>(raw: Vec<Vec<T>>) -> RVec<RVec<T>> {
|
||||||
|
RVec::from(raw.into_iter().map(RVec::from).collect::<Vec<_>>())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[sabi_extern_fn]
|
||||||
|
pub fn new(plugin_id: PluginId) -> RResult<PluginType, Error> {
|
||||||
|
let this = ETWSLoader { id: plugin_id };
|
||||||
|
ROk(DataLoaderPlugin_TO::from_value(this, TD_Opaque))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 测试模块
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
// 导入外部作用域中的所有项
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
// 一个简单的测试
|
||||||
|
#[test]
|
||||||
|
|
||||||
|
fn test() {
|
||||||
|
let result =
|
||||||
|
Record::parse_from_path("/Volumes/data2/RadarArray/ShaoXing/radarData/OutputProducts/RadarProducts/BasicProductsX/20230627/20230627163400/ZJSXAA_20230627163400_VIL.dat.gz")
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
376
loaders/etws_loader/src/parser.rs
Normal file
376
loaders/etws_loader/src/parser.rs
Normal file
@ -0,0 +1,376 @@
|
|||||||
|
use crate::error::ETWSError;
|
||||||
|
use byteorder::{BigEndian, ByteOrder, LittleEndian};
|
||||||
|
use chrono::{DateTime, NaiveDateTime, Utc};
|
||||||
|
use flate2::read::GzDecoder;
|
||||||
|
use nom::{
|
||||||
|
bytes::complete::{tag, take},
|
||||||
|
multi::count,
|
||||||
|
IResult,
|
||||||
|
};
|
||||||
|
use nom_derive::*;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io::Read;
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
|
pub enum ValueResult {
|
||||||
|
I64(Vec<i64>),
|
||||||
|
F64(Vec<f64>),
|
||||||
|
I32(Vec<i32>),
|
||||||
|
F32(Vec<f32>),
|
||||||
|
I16(Vec<i16>),
|
||||||
|
U64(Vec<u64>),
|
||||||
|
U32(Vec<u32>),
|
||||||
|
I8(Vec<i8>),
|
||||||
|
U8(Vec<u8>),
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ValueTypes {
|
||||||
|
I64,
|
||||||
|
F64,
|
||||||
|
I32,
|
||||||
|
F32,
|
||||||
|
U64,
|
||||||
|
U32,
|
||||||
|
I16,
|
||||||
|
I8,
|
||||||
|
U8,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
enum Order {
|
||||||
|
BigEndian,
|
||||||
|
LittleEndian,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Record {
|
||||||
|
pub filetime: DateTime<Utc>,
|
||||||
|
pub blocks: Vec<ParsedBlock>, // Fill in generic types appropriately
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! match_in_macro {
|
||||||
|
($block:ident,$len:ident,$input:ident,$offset:ident,$scale:ident,$fill_value:ident,$(($branch:path, $t:ty, $bigger:ty,$raw_result:path, $bigger_result:path)),+) => {
|
||||||
|
{
|
||||||
|
use std::mem;
|
||||||
|
let need_trans = $offset != 0.0 || $scale != 1.0;
|
||||||
|
let trans_to_bigger = $offset.trunc() != $offset || $scale != 1.0;
|
||||||
|
match $block {
|
||||||
|
$(
|
||||||
|
$branch => {
|
||||||
|
let ratio = mem::size_of::<$t>() / mem::size_of::<u8>();
|
||||||
|
let (input, result) = take($len * ratio)($input)?;
|
||||||
|
let result = unsafe {
|
||||||
|
let ptr = result.as_ptr() as *const $t;
|
||||||
|
let slice = std::slice::from_raw_parts(ptr, $len);
|
||||||
|
let slice = slice.to_vec();
|
||||||
|
|
||||||
|
if trans_to_bigger {
|
||||||
|
let offset = $offset as $bigger;
|
||||||
|
let scale = $scale as $bigger;
|
||||||
|
$bigger_result(
|
||||||
|
slice
|
||||||
|
.into_iter()
|
||||||
|
.map(|p| if (p as f64 - $fill_value).abs() < f64::EPSILON {p as $bigger} else {(p as $bigger - offset) / scale} )
|
||||||
|
.collect::<Vec<$bigger>>(),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
$raw_result(if need_trans {
|
||||||
|
let offset = $offset as $t;
|
||||||
|
slice.into_iter().map(|p| if (p as f64 - $fill_value).abs() < f64::EPSILON {p} else {p - offset}).collect::<Vec<$t>>()
|
||||||
|
} else {
|
||||||
|
slice
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Ok((input, result))
|
||||||
|
},
|
||||||
|
)+
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Record {
|
||||||
|
pub fn parse_from_path(path: impl AsRef<Path>) -> Result<Self, ETWSError> {
|
||||||
|
let path = path.as_ref();
|
||||||
|
if !(path.ends_with(".dat") || !path.ends_with(".dat.gz")) {
|
||||||
|
return Err(std::io::Error::new(
|
||||||
|
std::io::ErrorKind::InvalidInput,
|
||||||
|
"Invalid file extension",
|
||||||
|
)
|
||||||
|
.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
if !path.exists() {
|
||||||
|
return Err(std::io::Error::new(std::io::ErrorKind::NotFound, "File not found").into());
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut file = File::open(path)?;
|
||||||
|
let binary_data = if path.extension().unwrap() == "gz" {
|
||||||
|
let mut result: Vec<u8> = Vec::new();
|
||||||
|
let mut decoder = GzDecoder::new(file);
|
||||||
|
decoder.read_to_end(&mut result)?;
|
||||||
|
result
|
||||||
|
} else {
|
||||||
|
let mut result = Vec::new();
|
||||||
|
file.read_to_end(&mut result)?;
|
||||||
|
result
|
||||||
|
};
|
||||||
|
|
||||||
|
let (_, parsed) =
|
||||||
|
Self::_parse(binary_data.as_slice()).map_err(|_| anyhow::Error::msg("Parse error"))?;
|
||||||
|
|
||||||
|
Ok(parsed)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _parse(binary_data: &[u8]) -> IResult<&[u8], Record> {
|
||||||
|
let start_tag = b"UNI_DATA";
|
||||||
|
let (input, _) = tag(start_tag)(binary_data)?;
|
||||||
|
let (input, order) = Self::_parse_split_fn(input, 8, 8, Self::_parse_order)?;
|
||||||
|
let (input, hlen) = take(4usize)(input)?;
|
||||||
|
|
||||||
|
let hlen = match order {
|
||||||
|
Order::BigEndian => BigEndian::read_u32(hlen),
|
||||||
|
_ => LittleEndian::read_u32(hlen),
|
||||||
|
};
|
||||||
|
let (input, record_info) = Self::_parse_split_fn(input, 0, 8, |input| {
|
||||||
|
let (input, p) = take(hlen)(input)?;
|
||||||
|
let p: RecordInfo = serde_json::from_slice(p).unwrap();
|
||||||
|
Ok((input, p))
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let (input, blocks) =
|
||||||
|
count(Self::_parse_block_fn(order), record_info.block_num as usize)(input)?;
|
||||||
|
|
||||||
|
let data_time =
|
||||||
|
NaiveDateTime::parse_from_str(&record_info.file_time, r"%Y%m%d%H%M%S").unwrap();
|
||||||
|
let filetime = data_time.and_utc();
|
||||||
|
|
||||||
|
Ok((input, Record { filetime, blocks }))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _parse_order(input: &[u8]) -> IResult<&[u8], Order> {
|
||||||
|
let (input, order) = take(4usize)(input)?;
|
||||||
|
let result = if order == b"LEND" {
|
||||||
|
Order::LittleEndian
|
||||||
|
} else {
|
||||||
|
Order::BigEndian
|
||||||
|
};
|
||||||
|
let (input, _) = take(4usize)(input)?;
|
||||||
|
Ok((input, result))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _parse_split(input: &[u8], s: usize, fore: usize, after: usize) -> IResult<&[u8], &[u8]> {
|
||||||
|
let (input, _) = take(fore)(input)?;
|
||||||
|
let (input, result) = take(s)(input)?;
|
||||||
|
let (input, _) = take(after)(input)?;
|
||||||
|
Ok((input, result))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _parse_split_fn<E, F: Fn(&[u8]) -> IResult<&[u8], E>>(
|
||||||
|
input: &[u8],
|
||||||
|
fore: usize,
|
||||||
|
after: usize,
|
||||||
|
f: F,
|
||||||
|
) -> IResult<&[u8], E> {
|
||||||
|
let (input, _) = take(fore)(input)?;
|
||||||
|
let (input, result) = (f)(input)?;
|
||||||
|
let (input, _) = take(after)(input)?;
|
||||||
|
Ok((input, result))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _parse_block_fn(order: Order) -> impl FnMut(&[u8]) -> IResult<&[u8], ParsedBlock> {
|
||||||
|
move |input| Self::_parse_split_fn(input, 0, 0, |input| Self::_parse_block(input, order))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _parse_block(input: &[u8], order: Order) -> IResult<&[u8], ParsedBlock> {
|
||||||
|
let (input, _) = take(8usize)(input)?;
|
||||||
|
let (input, hlen1) = Self::_parse_u32(input, order)?;
|
||||||
|
let (input, block_info) = Self::_parse_split_fn(input, 0, 8, |input| {
|
||||||
|
let (input, p) = take(hlen1)(input)?;
|
||||||
|
|
||||||
|
let p: BlockJsonInfo = serde_json::from_slice(p).unwrap();
|
||||||
|
Ok((input, p))
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let (input, _) = take(8usize)(input)?; // skip 8 bytes
|
||||||
|
let (input, hlen2) = Self::_parse_u32(input, order)?;
|
||||||
|
let dimension_size = block_info.dimension_size.clone();
|
||||||
|
let size = dimension_size.iter().fold(1, |acc, x| acc * x) as usize;
|
||||||
|
let value_type = block_info.value_type.clone();
|
||||||
|
let value_type = Self::_parse_type(&value_type);
|
||||||
|
|
||||||
|
let (input, data) = Self::_parse_matrix(
|
||||||
|
input,
|
||||||
|
value_type,
|
||||||
|
order,
|
||||||
|
size,
|
||||||
|
block_info.value_offset,
|
||||||
|
block_info.value_scale,
|
||||||
|
block_info.fill_value,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
Ok((
|
||||||
|
input,
|
||||||
|
ParsedBlock {
|
||||||
|
info: block_info,
|
||||||
|
data,
|
||||||
|
},
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _parse_i32(input: &[u8], order: Order) -> IResult<&[u8], i32> {
|
||||||
|
let (input, hlen) = take(4usize)(input)?;
|
||||||
|
let hlen = match order {
|
||||||
|
Order::BigEndian => BigEndian::read_i32(hlen),
|
||||||
|
_ => LittleEndian::read_i32(hlen),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok((input, hlen))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _parse_u32(input: &[u8], order: Order) -> IResult<&[u8], u32> {
|
||||||
|
let (input, hlen) = take(4usize)(input)?;
|
||||||
|
let hlen = match order {
|
||||||
|
Order::BigEndian => BigEndian::read_u32(hlen),
|
||||||
|
_ => LittleEndian::read_u32(hlen),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok((input, hlen))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _parse_i64(input: &[u8], order: Order) -> IResult<&[u8], i64> {
|
||||||
|
let (input, hlen) = take(8usize)(input)?;
|
||||||
|
let hlen = match order {
|
||||||
|
Order::BigEndian => BigEndian::read_i64(hlen),
|
||||||
|
_ => LittleEndian::read_i64(hlen),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok((input, hlen))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _parse_u64(input: &[u8], order: Order) -> IResult<&[u8], u64> {
|
||||||
|
let (input, hlen) = take(8usize)(input)?;
|
||||||
|
let hlen = match order {
|
||||||
|
Order::BigEndian => BigEndian::read_u64(hlen),
|
||||||
|
_ => LittleEndian::read_u64(hlen),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok((input, hlen))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _parse_type<'a>(type_str: &'a str) -> ValueTypes {
|
||||||
|
match type_str {
|
||||||
|
"b" => ValueTypes::I8,
|
||||||
|
"B" => ValueTypes::U8,
|
||||||
|
"i" => ValueTypes::I32,
|
||||||
|
"I" => ValueTypes::U32,
|
||||||
|
"f" => ValueTypes::F32,
|
||||||
|
"d" => ValueTypes::F64,
|
||||||
|
"h" => ValueTypes::I16,
|
||||||
|
_ => panic!("Invalid type"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _parse_matrix(
|
||||||
|
input: &[u8],
|
||||||
|
type_: ValueTypes,
|
||||||
|
order: Order,
|
||||||
|
len: usize,
|
||||||
|
offset: f32,
|
||||||
|
scale: f32,
|
||||||
|
fill_value: f64,
|
||||||
|
) -> IResult<&[u8], ValueResult> {
|
||||||
|
match_in_macro!(
|
||||||
|
type_,
|
||||||
|
len,
|
||||||
|
input,
|
||||||
|
offset,
|
||||||
|
scale,
|
||||||
|
fill_value,
|
||||||
|
(
|
||||||
|
ValueTypes::I64,
|
||||||
|
i64,
|
||||||
|
f64,
|
||||||
|
ValueResult::I64,
|
||||||
|
ValueResult::F64
|
||||||
|
),
|
||||||
|
(
|
||||||
|
ValueTypes::F64,
|
||||||
|
f64,
|
||||||
|
f64,
|
||||||
|
ValueResult::F64,
|
||||||
|
ValueResult::F64
|
||||||
|
),
|
||||||
|
(
|
||||||
|
ValueTypes::U64,
|
||||||
|
u64,
|
||||||
|
f64,
|
||||||
|
ValueResult::U64,
|
||||||
|
ValueResult::F64
|
||||||
|
),
|
||||||
|
(
|
||||||
|
ValueTypes::I32,
|
||||||
|
i32,
|
||||||
|
f32,
|
||||||
|
ValueResult::I32,
|
||||||
|
ValueResult::F32
|
||||||
|
),
|
||||||
|
(
|
||||||
|
ValueTypes::F32,
|
||||||
|
f32,
|
||||||
|
f32,
|
||||||
|
ValueResult::F32,
|
||||||
|
ValueResult::F32
|
||||||
|
),
|
||||||
|
(
|
||||||
|
ValueTypes::U32,
|
||||||
|
u32,
|
||||||
|
f32,
|
||||||
|
ValueResult::U32,
|
||||||
|
ValueResult::F32
|
||||||
|
),
|
||||||
|
(
|
||||||
|
ValueTypes::I16,
|
||||||
|
i16,
|
||||||
|
f32,
|
||||||
|
ValueResult::I16,
|
||||||
|
ValueResult::F32
|
||||||
|
),
|
||||||
|
(ValueTypes::I8, i8, f32, ValueResult::I8, ValueResult::F32),
|
||||||
|
(ValueTypes::U8, u8, f32, ValueResult::U8, ValueResult::F32)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
struct RecordInfo {
|
||||||
|
file_time: String,
|
||||||
|
block_num: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct BlockJsonInfo {
|
||||||
|
pub value_name: String,
|
||||||
|
pub value_des: String,
|
||||||
|
pub value_type: String,
|
||||||
|
pub dimension_size: Vec<u64>,
|
||||||
|
pub dimension: usize,
|
||||||
|
pub dimension_des: Vec<String>,
|
||||||
|
pub dimension_start: Vec<f64>,
|
||||||
|
pub dimension_end: Vec<f64>,
|
||||||
|
pub dimension_values: Vec<Vec<f64>>,
|
||||||
|
pub fill_value: f64,
|
||||||
|
pub value_scale: f32,
|
||||||
|
pub value_offset: f32,
|
||||||
|
pub radar_alt: Option<f64>,
|
||||||
|
pub radar_lat: Option<f64>,
|
||||||
|
pub radar_lon: Option<f64>,
|
||||||
|
pub radar_name: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ParsedBlock {
|
||||||
|
pub info: BlockJsonInfo,
|
||||||
|
pub data: ValueResult,
|
||||||
|
}
|
||||||
808
loaders/etws_loader/src/raw.rs
Normal file
808
loaders/etws_loader/src/raw.rs
Normal file
@ -0,0 +1,808 @@
|
|||||||
|
use crate::error::ETWSError;
|
||||||
|
use abi_stable::std_types::vec;
|
||||||
|
use bytemuck::cast_slice;
|
||||||
|
use nom::{
|
||||||
|
bytes::complete::take,
|
||||||
|
combinator::map,
|
||||||
|
number::complete::{le_f32, le_i16, le_i64, le_u16, le_u32},
|
||||||
|
sequence::tuple,
|
||||||
|
IResult,
|
||||||
|
};
|
||||||
|
use zip::read::ZipArchive;
|
||||||
|
|
||||||
|
use std::{
|
||||||
|
collections::HashMap,
|
||||||
|
io::{self, Cursor, Read, Seek, SeekFrom},
|
||||||
|
process::id,
|
||||||
|
};
|
||||||
|
use std::{fs::File, path::Path};
|
||||||
|
|
||||||
|
const SUPPORTED_TYPE: [u32; 7] = [2, 3, 4, 7, 9, 10, 11];
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct RadarData {
|
||||||
|
pub datetime: i64,
|
||||||
|
pub els: Vec<f64>,
|
||||||
|
pub azs: Vec<f64>,
|
||||||
|
pub ranges: Vec<f64>,
|
||||||
|
pub datas: HashMap<&'static str, Vec<f64>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct SiteConfig {
|
||||||
|
site_code: String,
|
||||||
|
site_name: String,
|
||||||
|
latitude: f32,
|
||||||
|
longitude: f32,
|
||||||
|
antenna_height: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct TaskConfig {
|
||||||
|
task_name: String,
|
||||||
|
task_description: String,
|
||||||
|
polarization_type: u32,
|
||||||
|
scan_type: u32,
|
||||||
|
scan_beam_number: u32,
|
||||||
|
cut_number: u32,
|
||||||
|
ray_order: u32,
|
||||||
|
scan_start_time: i64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct BeamConfig {
|
||||||
|
cut_index: i16,
|
||||||
|
tx_beam_index: i16,
|
||||||
|
rx_beam_elevation: f32,
|
||||||
|
tx_beam_gain: f32,
|
||||||
|
rx_beam_width_h: f32,
|
||||||
|
rx_beam_width_v: f32,
|
||||||
|
rx_beam_gain: f32,
|
||||||
|
process_mode: String,
|
||||||
|
wave_form: String,
|
||||||
|
n1_prf1: f32,
|
||||||
|
n1_prf2: f32,
|
||||||
|
n2_prf1: f32,
|
||||||
|
n2_prf2: f32,
|
||||||
|
dealiasing_mode: u32,
|
||||||
|
azimuth: f32,
|
||||||
|
start_angle: f32,
|
||||||
|
end_angle: f32,
|
||||||
|
angular_resolution: f32,
|
||||||
|
scan_speed: f32,
|
||||||
|
log_resolution: f32,
|
||||||
|
doppler_resolution: f32,
|
||||||
|
maximum_range1: u32,
|
||||||
|
maximum_range2: u32,
|
||||||
|
start_range: u32,
|
||||||
|
sample1: u32,
|
||||||
|
sample2: u32,
|
||||||
|
phase_mode: u32,
|
||||||
|
atmospheric_loss: f32,
|
||||||
|
nyquist_speed: f32,
|
||||||
|
moments_mask: i64,
|
||||||
|
moments_size_mask: i64,
|
||||||
|
misc_filter_mask: u32,
|
||||||
|
sqi_threshold: f32,
|
||||||
|
sig_threshold: f32,
|
||||||
|
csr_threshold: f32,
|
||||||
|
log_threshold: f32,
|
||||||
|
cpa_threshold: f32,
|
||||||
|
pmi_threshold: f32,
|
||||||
|
dplog_threshold: f32,
|
||||||
|
thresholds_r: [u8; 4],
|
||||||
|
dbt_mask: u32,
|
||||||
|
dbz_mask: u32,
|
||||||
|
velocity_mask: u32,
|
||||||
|
spectrum_width_mask: u32,
|
||||||
|
dp_mask: u32,
|
||||||
|
direction: u32,
|
||||||
|
ground_clutter_classifier_type: i16,
|
||||||
|
ground_clutter_filter_type: i16,
|
||||||
|
ground_clutter_filter_notch_width: i16,
|
||||||
|
ground_clutter_filter_window: i16,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct TypeHeader {
|
||||||
|
data_type: u32,
|
||||||
|
scale: u32,
|
||||||
|
offset: u32,
|
||||||
|
bin_length: u16,
|
||||||
|
flags: u16,
|
||||||
|
length: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct RadialData {
|
||||||
|
radial_state: u32,
|
||||||
|
spot_blank: u32,
|
||||||
|
sequence_number: u32,
|
||||||
|
radial_number: u32,
|
||||||
|
elevation_number: u32,
|
||||||
|
azimuth: f32,
|
||||||
|
elevation: f32,
|
||||||
|
seconds: i64,
|
||||||
|
microseconds: u32,
|
||||||
|
length_of_data: u32,
|
||||||
|
moment_number: u32,
|
||||||
|
scan_beam_index: i16,
|
||||||
|
horizontal_estimated_noise: i16,
|
||||||
|
vertical_estimated_noise: i16,
|
||||||
|
prf_flag: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct GenericHeader {
|
||||||
|
magic_number: u32,
|
||||||
|
major_version: u16,
|
||||||
|
minor_version: u16,
|
||||||
|
generic_type: u32,
|
||||||
|
product_type: u32,
|
||||||
|
reserved: [u8; 16],
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct SubPulseConfig {
|
||||||
|
strategy: u32,
|
||||||
|
modulation: u32,
|
||||||
|
frequency: f32,
|
||||||
|
bandwidth: f32,
|
||||||
|
width: u32,
|
||||||
|
horizontal_noise: f32,
|
||||||
|
vertical_noise: f32,
|
||||||
|
horizontal_calibration: f32,
|
||||||
|
vertical_calibration: f32,
|
||||||
|
horizontal_noise_temperature: f32,
|
||||||
|
vertical_noise_temperature: f32,
|
||||||
|
zdr_calibration: f32,
|
||||||
|
phidp_calibration: f32,
|
||||||
|
ldr_calibration: f32,
|
||||||
|
pulse_points: i16,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct ScanConfig {
|
||||||
|
beam_index: u32,
|
||||||
|
beam_type: u32,
|
||||||
|
sub_pulse_number: u32,
|
||||||
|
tx_beam_direction: f32,
|
||||||
|
tx_beam_width_h: f32,
|
||||||
|
tx_beam_width_v: f32,
|
||||||
|
tx_beam_gain: f32,
|
||||||
|
sub_pulse_configs: Vec<SubPulseConfig>,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_scan_config(input: &[u8]) -> IResult<&[u8], ScanConfig> {
|
||||||
|
let (input, beam_index) = le_u32(input)?;
|
||||||
|
let (input, beam_type) = le_u32(input)?;
|
||||||
|
let (input, sub_pulse_number) = le_u32(input)?;
|
||||||
|
let (input, tx_beam_direction) = le_f32(input)?;
|
||||||
|
let (input, tx_beam_width_h) = le_f32(input)?;
|
||||||
|
let (input, tx_beam_width_v) = le_f32(input)?;
|
||||||
|
let (input, tx_beam_gain) = le_f32(input)?;
|
||||||
|
let (input, _) = take(100usize)(input)?; // Skip reserved bytes
|
||||||
|
|
||||||
|
// Parse the SubPulseConfigs
|
||||||
|
let mut sub_pulse_configs = Vec::new();
|
||||||
|
let mut input = input;
|
||||||
|
for _ in 0..4 {
|
||||||
|
let (new_input, sub_pulse_config) = parse_sub_pulse_config(input)?;
|
||||||
|
input = new_input;
|
||||||
|
sub_pulse_configs.push(sub_pulse_config);
|
||||||
|
}
|
||||||
|
|
||||||
|
let scan_config = ScanConfig {
|
||||||
|
beam_index,
|
||||||
|
beam_type,
|
||||||
|
sub_pulse_number,
|
||||||
|
tx_beam_direction,
|
||||||
|
tx_beam_width_h,
|
||||||
|
tx_beam_width_v,
|
||||||
|
tx_beam_gain,
|
||||||
|
sub_pulse_configs,
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok((input, scan_config))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_sub_pulse_config(input: &[u8]) -> IResult<&[u8], SubPulseConfig> {
|
||||||
|
let (input, strategy) = le_u32(input)?;
|
||||||
|
let (input, modulation) = le_u32(input)?;
|
||||||
|
let (input, frequency) = le_f32(input)?;
|
||||||
|
let (input, bandwidth) = le_f32(input)?;
|
||||||
|
let (input, width) = le_u32(input)?;
|
||||||
|
let (input, horizontal_noise) = le_f32(input)?;
|
||||||
|
let (input, vertical_noise) = le_f32(input)?;
|
||||||
|
let (input, horizontal_calibration) = le_f32(input)?;
|
||||||
|
let (input, vertical_calibration) = le_f32(input)?;
|
||||||
|
let (input, horizontal_noise_temperature) = le_f32(input)?;
|
||||||
|
let (input, vertical_noise_temperature) = le_f32(input)?;
|
||||||
|
let (input, zdr_calibration) = le_f32(input)?;
|
||||||
|
let (input, phidp_calibration) = le_f32(input)?;
|
||||||
|
let (input, ldr_calibration) = le_f32(input)?;
|
||||||
|
let (input, pulse_points) = nom::number::complete::le_i16(input)?;
|
||||||
|
let (input, _) = take(70usize)(input)?; // Skip reserved bytes
|
||||||
|
|
||||||
|
let sub_pulse_config = SubPulseConfig {
|
||||||
|
strategy,
|
||||||
|
modulation,
|
||||||
|
frequency,
|
||||||
|
bandwidth,
|
||||||
|
width,
|
||||||
|
horizontal_noise,
|
||||||
|
vertical_noise,
|
||||||
|
horizontal_calibration,
|
||||||
|
vertical_calibration,
|
||||||
|
horizontal_noise_temperature,
|
||||||
|
vertical_noise_temperature,
|
||||||
|
zdr_calibration,
|
||||||
|
phidp_calibration,
|
||||||
|
ldr_calibration,
|
||||||
|
pulse_points,
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok((input, sub_pulse_config))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parse_raw_data<P: AsRef<Path>>(path: P) -> Result<RadarData, ETWSError> {
|
||||||
|
let path = path.as_ref();
|
||||||
|
|
||||||
|
if path.extension().is_none() {
|
||||||
|
if path.is_file() {
|
||||||
|
let mut file = File::open(path)?;
|
||||||
|
let mut buf = Vec::new();
|
||||||
|
file.read_to_end(&mut buf).unwrap();
|
||||||
|
if &buf[0..4] == b"SSTM" || &buf[16..20] == b"STDM" || &buf[0..4] == b"RSTM" {
|
||||||
|
return get_radar_data(buf);
|
||||||
|
} else {
|
||||||
|
return Err(ETWSError::FormatError {
|
||||||
|
source: anyhow::anyhow!("Invalid file format"),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return Err(ETWSError::IOError {
|
||||||
|
source: io::Error::new(io::ErrorKind::NotFound, "File not found"),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if path.extension().unwrap() == "zip" {
|
||||||
|
let file = File::open(path).unwrap();
|
||||||
|
let mut archive = ZipArchive::new(file).unwrap();
|
||||||
|
let mut file = archive.by_index(0).unwrap();
|
||||||
|
|
||||||
|
let mut buf = Vec::new();
|
||||||
|
file.read_to_end(&mut buf)?;
|
||||||
|
if buf.len() < 4 {
|
||||||
|
return Err(ETWSError::FormatError {
|
||||||
|
source: anyhow::anyhow!("Invalid file format"),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if &buf[0..4] == b"SSTM" || &buf[16..20] == b"STDM" || &buf[0..4] == b"RSTM" {
|
||||||
|
return get_radar_data(buf);
|
||||||
|
} else {
|
||||||
|
return Err(ETWSError::FormatError {
|
||||||
|
source: anyhow::anyhow!("Invalid file format"),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else if path.extension().unwrap() == ".gz" {
|
||||||
|
let file = File::open(path)?;
|
||||||
|
let mut archive = flate2::read::GzDecoder::new(file);
|
||||||
|
let mut buf = Vec::new();
|
||||||
|
archive.read_to_end(&mut buf)?;
|
||||||
|
if buf.len() < 4 {
|
||||||
|
return Err(ETWSError::FormatError {
|
||||||
|
source: anyhow::anyhow!("Invalid file format"),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if &buf[0..4] == b"SSTM" || &buf[16..20] == b"STDM" || &buf[0..4] == b"RSTM" {
|
||||||
|
return get_radar_data(buf);
|
||||||
|
} else {
|
||||||
|
return Err(ETWSError::FormatError {
|
||||||
|
source: anyhow::anyhow!("Invalid file format"),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let mut file = File::open(path)?;
|
||||||
|
let mut buf = Vec::new();
|
||||||
|
file.read_to_end(&mut buf)?;
|
||||||
|
if buf.len() < 4 {
|
||||||
|
return Err(ETWSError::FormatError {
|
||||||
|
source: anyhow::anyhow!("Invalid file format"),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if &buf[0..4] == b"SSTM" || &buf[16..20] == b"STDM" || &buf[0..4] == b"RSTM" {
|
||||||
|
return get_radar_data(buf);
|
||||||
|
} else {
|
||||||
|
return Err(ETWSError::FormatError {
|
||||||
|
source: anyhow::anyhow!("Invalid file format"),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_radar_data(data: Vec<u8>) -> Result<RadarData, ETWSError> {
|
||||||
|
let total_length = data.len() as u64;
|
||||||
|
// 使用 Cursor 来处理 Vec<u8>
|
||||||
|
let mut cursor = Cursor::new(data);
|
||||||
|
|
||||||
|
// 读取 GENERIC_HEADER
|
||||||
|
let mut buffer = vec![0u8; 32];
|
||||||
|
cursor.read_exact(&mut buffer)?;
|
||||||
|
let (_, generic_header) = parse_generic_header(&buffer)?;
|
||||||
|
|
||||||
|
// 读取 SITE_CONFIG
|
||||||
|
let mut buffer = vec![0u8; 128];
|
||||||
|
cursor.read_exact(&mut buffer)?;
|
||||||
|
let (_, site_config) = parse_site_config(&buffer)?;
|
||||||
|
|
||||||
|
// 读取 TASK_CONFIG
|
||||||
|
let mut buffer = vec![0u8; 256];
|
||||||
|
cursor.read_exact(&mut buffer)?;
|
||||||
|
let (_, task_config) = parse_task_config(&buffer)?;
|
||||||
|
|
||||||
|
// 读取 SCAN_CONFIG
|
||||||
|
let mut scan_configs = Vec::new();
|
||||||
|
for _ in 0..task_config.scan_beam_number {
|
||||||
|
let mut buffer = vec![0u8; 640];
|
||||||
|
cursor.read_exact(&mut buffer)?;
|
||||||
|
let (_, scan_config) = parse_scan_config(&buffer)?;
|
||||||
|
scan_configs.push(scan_config);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 读取 BEAM_CONFIG
|
||||||
|
let mut beam_configs = Vec::new();
|
||||||
|
for _ in 0..task_config.cut_number {
|
||||||
|
let mut buffer = vec![0u8; 256];
|
||||||
|
cursor.read_exact(&mut buffer)?;
|
||||||
|
let (_, beam_config) = parse_beam_config(&buffer)?;
|
||||||
|
beam_configs.push(beam_config);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 读取 RADIAL_DATA
|
||||||
|
|
||||||
|
let (datas, els, azs, ranges) =
|
||||||
|
parse_final_data(total_length, task_config.cut_number as usize, cursor)?;
|
||||||
|
|
||||||
|
// 构建并返回 RadarData 结构体
|
||||||
|
let radar_data = RadarData {
|
||||||
|
datetime: task_config.scan_start_time,
|
||||||
|
els,
|
||||||
|
azs,
|
||||||
|
ranges,
|
||||||
|
datas,
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(radar_data)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_generic_header(input: &[u8]) -> IResult<&[u8], GenericHeader> {
|
||||||
|
let (input, magic_number) = le_u32(input)?;
|
||||||
|
let (input, major_version) = le_u16(input)?;
|
||||||
|
let (input, minor_version) = le_u16(input)?;
|
||||||
|
let (input, generic_type) = le_u32(input)?;
|
||||||
|
let (input, product_type) = le_u32(input)?;
|
||||||
|
let (input, reserved) = take(16usize)(input)?;
|
||||||
|
|
||||||
|
let generic_header = GenericHeader {
|
||||||
|
magic_number,
|
||||||
|
major_version,
|
||||||
|
minor_version,
|
||||||
|
generic_type,
|
||||||
|
product_type,
|
||||||
|
reserved: reserved.try_into().unwrap(),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok((input, generic_header))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_site_config(input: &[u8]) -> IResult<&[u8], SiteConfig> {
|
||||||
|
let (input, site_code) = take(8usize)(input)?;
|
||||||
|
let (input, site_name) = take(32usize)(input)?;
|
||||||
|
let (input, latitude) = le_f32(input)?;
|
||||||
|
let (input, longitude) = le_f32(input)?;
|
||||||
|
let (input, antenna_height) = le_u32(input)?;
|
||||||
|
let (input, _) = take(4usize)(input)?; // Skip reserved bytes
|
||||||
|
|
||||||
|
let site_config = SiteConfig {
|
||||||
|
site_code: String::from_utf8(site_code.to_vec())
|
||||||
|
.unwrap()
|
||||||
|
.trim_end_matches('\0')
|
||||||
|
.to_string(),
|
||||||
|
site_name: String::from_utf8(site_name.to_vec())
|
||||||
|
.unwrap()
|
||||||
|
.trim_end_matches('\0')
|
||||||
|
.to_string(),
|
||||||
|
latitude,
|
||||||
|
longitude,
|
||||||
|
antenna_height,
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok((input, site_config))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_task_config(input: &[u8]) -> IResult<&[u8], TaskConfig> {
|
||||||
|
let (input, task_name) = take(32usize)(input)?;
|
||||||
|
let (input, task_description) = take(128usize)(input)?;
|
||||||
|
let (input, polarization_type) = le_u32(input)?;
|
||||||
|
let (input, scan_type) = le_u32(input)?;
|
||||||
|
let (input, scan_beam_number) = le_u32(input)?;
|
||||||
|
let (input, cut_number) = le_u32(input)?;
|
||||||
|
let (input, ray_order) = le_u32(input)?;
|
||||||
|
let (input, scan_start_time) = le_i64(input)?;
|
||||||
|
let (input, _) = take(68usize)(input)?; // Skip reserved bytes
|
||||||
|
|
||||||
|
let task_config = TaskConfig {
|
||||||
|
task_name: String::from_utf8_lossy(task_name).to_string(),
|
||||||
|
task_description: String::from_utf8_lossy(task_description).to_string(),
|
||||||
|
polarization_type,
|
||||||
|
scan_type,
|
||||||
|
scan_beam_number,
|
||||||
|
cut_number,
|
||||||
|
ray_order,
|
||||||
|
scan_start_time,
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok((input, task_config))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn single_beam_block(raw: &[u8], bin_length: usize) -> io::Result<Vec<f64>> {
|
||||||
|
let raw = match bin_length {
|
||||||
|
1 => {
|
||||||
|
let new_raw: Vec<f64> = raw.into_iter().map(|v| *v as f64).collect();
|
||||||
|
new_raw
|
||||||
|
}
|
||||||
|
2 => {
|
||||||
|
let new_raw: Vec<f64> = cast_slice(&raw)
|
||||||
|
.into_iter()
|
||||||
|
.map(|v: &u16| *v as f64)
|
||||||
|
.collect();
|
||||||
|
new_raw
|
||||||
|
}
|
||||||
|
4 => {
|
||||||
|
let new_raw: Vec<f64> = cast_slice(&raw)
|
||||||
|
.into_iter()
|
||||||
|
.map(|v: &u32| *v as f64)
|
||||||
|
.collect();
|
||||||
|
new_raw
|
||||||
|
}
|
||||||
|
8 => {
|
||||||
|
let new_raw: Vec<f64> = cast_slice(&raw)
|
||||||
|
.into_iter()
|
||||||
|
.map(|v: &u64| *v as f64)
|
||||||
|
.collect();
|
||||||
|
new_raw
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
let new_raw: Vec<f64> = raw.into_iter().map(|v| *v as f64).collect();
|
||||||
|
new_raw
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Ok(raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn beam_block_exact(cursor: &mut Cursor<Vec<u8>>, header: &TypeHeader) -> io::Result<Vec<u8>> {
|
||||||
|
let mut buf = vec![0u8; header.length as usize];
|
||||||
|
cursor.read_exact(&mut buf)?;
|
||||||
|
Ok(buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn data_type(typ: u32) -> &'static str {
|
||||||
|
match typ {
|
||||||
|
2 => "DBZ",
|
||||||
|
3 => "VEL",
|
||||||
|
4 => "SW",
|
||||||
|
7 => "ZDR",
|
||||||
|
9 => "CC",
|
||||||
|
10 => "PHIDP",
|
||||||
|
11 => "KDP",
|
||||||
|
_ => "Unknown",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_final_data(
|
||||||
|
all_length: u64,
|
||||||
|
cut_number: usize,
|
||||||
|
mut cursor: Cursor<Vec<u8>>,
|
||||||
|
) -> Result<
|
||||||
|
(
|
||||||
|
HashMap<&'static str, Vec<f64>>,
|
||||||
|
Vec<f64>,
|
||||||
|
Vec<f64>,
|
||||||
|
Vec<f64>,
|
||||||
|
),
|
||||||
|
ETWSError,
|
||||||
|
> {
|
||||||
|
let position = cursor.position();
|
||||||
|
let mut radial_buffer = vec![0u8; 128];
|
||||||
|
let mut header_buffer = vec![0u8; 32];
|
||||||
|
cursor.read_exact(&mut radial_buffer)?;
|
||||||
|
|
||||||
|
// First Block
|
||||||
|
let (_, radial_data) = parse_radial_data(&radial_buffer)?;
|
||||||
|
// Radial_number: I don't know why not use it.
|
||||||
|
// let radial_number = radial_data.radial_number as usize;
|
||||||
|
|
||||||
|
// 变量类型
|
||||||
|
let type_number = radial_data.moment_number as usize;
|
||||||
|
let mut gate_len = vec![0; type_number];
|
||||||
|
let mut types = vec!["Unknown"; type_number];
|
||||||
|
|
||||||
|
// final datas
|
||||||
|
let mut datas = HashMap::new();
|
||||||
|
|
||||||
|
for idx in 0..type_number {
|
||||||
|
cursor.read_exact(&mut header_buffer)?;
|
||||||
|
let (_, header) = parse_type_header(&header_buffer)?;
|
||||||
|
let first_beam_block = beam_block_exact(&mut cursor, &header)?;
|
||||||
|
let first_beam = single_beam_block(&first_beam_block, header.bin_length as usize)?;
|
||||||
|
gate_len[idx] = first_beam.len();
|
||||||
|
|
||||||
|
let data_type = data_type(header.data_type);
|
||||||
|
if data_type == "Unknown" {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
types[idx] = data_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
let first_block_position = cursor.position();
|
||||||
|
let roll_num = (all_length - position) / (first_block_position - position);
|
||||||
|
let azm_number = (roll_num / cut_number as u64) as usize;
|
||||||
|
|
||||||
|
for idx in 0..type_number {
|
||||||
|
if types[idx] == "Unknown" {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
datas.insert(
|
||||||
|
types[idx],
|
||||||
|
vec![0f64; cut_number * azm_number * gate_len[idx]],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset Cursor
|
||||||
|
cursor.set_position(position);
|
||||||
|
|
||||||
|
let mut els = vec![0f64; cut_number];
|
||||||
|
let mut azs = vec![0f64; azm_number];
|
||||||
|
|
||||||
|
for e in 0..cut_number {
|
||||||
|
for a in 0..azm_number {
|
||||||
|
cursor.read_exact(&mut radial_buffer)?;
|
||||||
|
let (_, radial_data) = parse_radial_data(&radial_buffer)?;
|
||||||
|
els[e] = radial_data.elevation as f64;
|
||||||
|
azs[a] = radial_data.azimuth as f64;
|
||||||
|
let type_number = radial_data.moment_number as usize;
|
||||||
|
for typ in 0..type_number {
|
||||||
|
cursor.read_exact(&mut header_buffer)?;
|
||||||
|
let (_, header) = parse_type_header(&header_buffer)?;
|
||||||
|
let beam_block = beam_block_exact(&mut cursor, &header)?;
|
||||||
|
let mut beam = single_beam_block(&beam_block, header.bin_length as usize)?;
|
||||||
|
|
||||||
|
beam.iter_mut()
|
||||||
|
.for_each(|v| *v = (*v - header.offset as f64) / header.scale as f64);
|
||||||
|
|
||||||
|
if let Some(typ_name) = types.get(typ) {
|
||||||
|
if typ_name == &"Unknown" {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let e = radial_data.elevation_number as usize - 1;
|
||||||
|
|
||||||
|
datas.get_mut(typ_name).unwrap()[e * (azm_number * gate_len[typ])
|
||||||
|
+ a * gate_len[typ]
|
||||||
|
..e * (azm_number * gate_len[typ]) + (a + 1) * gate_len[typ]]
|
||||||
|
.copy_from_slice(&beam);
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut ranges = vec![0f64; gate_len[0]];
|
||||||
|
|
||||||
|
ranges
|
||||||
|
.iter_mut()
|
||||||
|
.enumerate()
|
||||||
|
.for_each(|(idx, r)| *r = idx as f64 * 30.0);
|
||||||
|
|
||||||
|
Ok((datas, els, azs, ranges))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_beam_config(input: &[u8]) -> IResult<&[u8], BeamConfig> {
|
||||||
|
let (input, cut_index) = le_i16(input)?;
|
||||||
|
let (input, tx_beam_index) = le_i16(input)?;
|
||||||
|
let (input, rx_beam_elevation) = le_f32(input)?;
|
||||||
|
let (input, tx_beam_gain) = le_f32(input)?;
|
||||||
|
let (input, rx_beam_width_h) = le_f32(input)?;
|
||||||
|
let (input, rx_beam_width_v) = le_f32(input)?;
|
||||||
|
let (input, rx_beam_gain) = le_f32(input)?;
|
||||||
|
let (input, process_mode) = map(le_u32, |v| match v {
|
||||||
|
1 => "PPP".to_string(),
|
||||||
|
2 => "FFT".to_string(),
|
||||||
|
_ => "Unknown".to_string(),
|
||||||
|
})(input)?;
|
||||||
|
let (input, wave_form) = map(le_u32, |v| match v {
|
||||||
|
0 => "CS连续监测".to_string(),
|
||||||
|
1 => "CD连续多普勒".to_string(),
|
||||||
|
2 => "CDX多普勒扩展".to_string(),
|
||||||
|
3 => "Rx Test".to_string(),
|
||||||
|
4 => "BATCH批模式".to_string(),
|
||||||
|
5 => "Dual PRF双PRF".to_string(),
|
||||||
|
6 => "Staggered PRT 参差PRT".to_string(),
|
||||||
|
_ => "Unknown".to_string(),
|
||||||
|
})(input)?;
|
||||||
|
let (input, n1_prf1) = le_f32(input)?;
|
||||||
|
let (input, n1_prf2) = le_f32(input)?;
|
||||||
|
let (input, n2_prf1) = le_f32(input)?;
|
||||||
|
let (input, n2_prf2) = le_f32(input)?;
|
||||||
|
let (input, dealiasing_mode) = le_u32(input)?;
|
||||||
|
let (input, azimuth) = le_f32(input)?;
|
||||||
|
let (input, start_angle) = le_f32(input)?;
|
||||||
|
let (input, end_angle) = le_f32(input)?;
|
||||||
|
let (input, angular_resolution) = le_f32(input)?;
|
||||||
|
let (input, scan_speed) = le_f32(input)?;
|
||||||
|
let (input, log_resolution) = le_f32(input)?;
|
||||||
|
let (input, doppler_resolution) = le_f32(input)?;
|
||||||
|
let (input, maximum_range1) = le_u32(input)?;
|
||||||
|
let (input, maximum_range2) = le_u32(input)?;
|
||||||
|
let (input, start_range) = le_u32(input)?;
|
||||||
|
let (input, sample1) = le_u32(input)?;
|
||||||
|
let (input, sample2) = le_u32(input)?;
|
||||||
|
let (input, phase_mode) = le_u32(input)?;
|
||||||
|
let (input, atmospheric_loss) = le_f32(input)?;
|
||||||
|
let (input, nyquist_speed) = le_f32(input)?;
|
||||||
|
let (input, moments_mask) = le_i64(input)?;
|
||||||
|
let (input, moments_size_mask) = le_i64(input)?;
|
||||||
|
let (input, misc_filter_mask) = le_u32(input)?;
|
||||||
|
let (input, sqi_threshold) = le_f32(input)?;
|
||||||
|
let (input, sig_threshold) = le_f32(input)?;
|
||||||
|
let (input, csr_threshold) = le_f32(input)?;
|
||||||
|
let (input, log_threshold) = le_f32(input)?;
|
||||||
|
let (input, cpa_threshold) = le_f32(input)?;
|
||||||
|
let (input, pmi_threshold) = le_f32(input)?;
|
||||||
|
let (input, dplog_threshold) = le_f32(input)?;
|
||||||
|
let (input, thresholds_r) = take(4usize)(input)?;
|
||||||
|
let (input, dbt_mask) = le_u32(input)?;
|
||||||
|
let (input, dbz_mask) = le_u32(input)?;
|
||||||
|
let (input, velocity_mask) = le_u32(input)?;
|
||||||
|
let (input, spectrum_width_mask) = le_u32(input)?;
|
||||||
|
let (input, dp_mask) = le_u32(input)?;
|
||||||
|
let (input, direction) = le_u32(input)?;
|
||||||
|
let (input, ground_clutter_classifier_type) = le_i16(input)?;
|
||||||
|
let (input, ground_clutter_filter_type) = le_i16(input)?;
|
||||||
|
let (input, ground_clutter_filter_notch_width) = le_i16(input)?;
|
||||||
|
let (input, ground_clutter_filter_window) = le_i16(input)?;
|
||||||
|
let (input, _) = take(44usize)(input)?;
|
||||||
|
|
||||||
|
let beam_config = BeamConfig {
|
||||||
|
cut_index,
|
||||||
|
tx_beam_index,
|
||||||
|
rx_beam_elevation,
|
||||||
|
tx_beam_gain,
|
||||||
|
rx_beam_width_h,
|
||||||
|
rx_beam_width_v,
|
||||||
|
rx_beam_gain,
|
||||||
|
process_mode,
|
||||||
|
wave_form,
|
||||||
|
n1_prf1,
|
||||||
|
n1_prf2,
|
||||||
|
n2_prf1,
|
||||||
|
n2_prf2,
|
||||||
|
dealiasing_mode,
|
||||||
|
azimuth,
|
||||||
|
start_angle,
|
||||||
|
end_angle,
|
||||||
|
angular_resolution,
|
||||||
|
scan_speed,
|
||||||
|
log_resolution,
|
||||||
|
doppler_resolution,
|
||||||
|
maximum_range1,
|
||||||
|
maximum_range2,
|
||||||
|
start_range,
|
||||||
|
sample1,
|
||||||
|
sample2,
|
||||||
|
phase_mode,
|
||||||
|
atmospheric_loss,
|
||||||
|
nyquist_speed,
|
||||||
|
moments_mask,
|
||||||
|
moments_size_mask,
|
||||||
|
misc_filter_mask,
|
||||||
|
sqi_threshold,
|
||||||
|
sig_threshold,
|
||||||
|
csr_threshold,
|
||||||
|
log_threshold,
|
||||||
|
cpa_threshold,
|
||||||
|
pmi_threshold,
|
||||||
|
dplog_threshold,
|
||||||
|
thresholds_r: thresholds_r.try_into().unwrap(),
|
||||||
|
dbt_mask,
|
||||||
|
dbz_mask,
|
||||||
|
velocity_mask,
|
||||||
|
spectrum_width_mask,
|
||||||
|
dp_mask,
|
||||||
|
direction,
|
||||||
|
ground_clutter_classifier_type,
|
||||||
|
ground_clutter_filter_type,
|
||||||
|
ground_clutter_filter_notch_width,
|
||||||
|
ground_clutter_filter_window,
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok((input, beam_config))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_radial_data(input: &[u8]) -> IResult<&[u8], RadialData> {
|
||||||
|
let (input, radial_state) = le_u32(input)?;
|
||||||
|
let (input, spot_blank) = le_u32(input)?;
|
||||||
|
let (input, sequence_number) = le_u32(input)?;
|
||||||
|
let (input, radial_number) = le_u32(input)?;
|
||||||
|
let (input, elevation_number) = le_u32(input)?;
|
||||||
|
let (input, azimuth) = le_f32(input)?;
|
||||||
|
let (input, elevation) = le_f32(input)?;
|
||||||
|
let (input, seconds) = le_i64(input)?;
|
||||||
|
let (input, microseconds) = le_u32(input)?;
|
||||||
|
let (input, length_of_data) = le_u32(input)?;
|
||||||
|
let (input, moment_number) = le_u32(input)?;
|
||||||
|
let (input, scan_beam_index) = le_i16(input)?;
|
||||||
|
let (input, horizontal_estimated_noise) = le_i16(input)?;
|
||||||
|
let (input, vertical_estimated_noise) = le_i16(input)?;
|
||||||
|
let (input, prf_flag) = le_u32(input)?;
|
||||||
|
let (input, _) = take(70usize)(input)?; // Skip reserved bytes
|
||||||
|
|
||||||
|
let radial_data = RadialData {
|
||||||
|
radial_state,
|
||||||
|
spot_blank,
|
||||||
|
sequence_number,
|
||||||
|
radial_number,
|
||||||
|
elevation_number,
|
||||||
|
azimuth,
|
||||||
|
elevation,
|
||||||
|
seconds,
|
||||||
|
microseconds,
|
||||||
|
length_of_data,
|
||||||
|
moment_number,
|
||||||
|
scan_beam_index,
|
||||||
|
horizontal_estimated_noise,
|
||||||
|
vertical_estimated_noise,
|
||||||
|
prf_flag,
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok((input, radial_data))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_type_header(input: &[u8]) -> IResult<&[u8], TypeHeader> {
|
||||||
|
let (input, data_type) = le_u32(input)?;
|
||||||
|
let (input, scale) = le_u32(input)?;
|
||||||
|
let (input, offset) = le_u32(input)?;
|
||||||
|
let (input, bin_length) = le_u16(input)?;
|
||||||
|
let (input, flags) = le_u16(input)?;
|
||||||
|
let (input, length) = le_u32(input)?;
|
||||||
|
let (input, _) = take(12usize)(input)?; // Skip reserved bytes
|
||||||
|
|
||||||
|
let type_header = TypeHeader {
|
||||||
|
data_type,
|
||||||
|
scale,
|
||||||
|
offset,
|
||||||
|
bin_length,
|
||||||
|
flags,
|
||||||
|
length,
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok((input, type_header))
|
||||||
|
}
|
||||||
|
|
||||||
|
mod test {
|
||||||
|
use crate::raw::parse_raw_data;
|
||||||
|
|
||||||
|
use super::get_radar_data;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test() {
|
||||||
|
use std::fs::File;
|
||||||
|
let radar_data = parse_raw_data(
|
||||||
|
"/Users/tsuki/Desktop/Z_RADR_I_X5775_20230726180000_O_DOR-XPD-CAP-FMT.BIN.zip",
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -5,5 +5,10 @@ edition = "2021"
|
|||||||
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
glam = "0.29.2"
|
||||||
|
log = "0.4.22"
|
||||||
makepad-widgets = { git = "https://github.com/makepad/makepad", branch = "rik", version = "0.6.0" }
|
makepad-widgets = { git = "https://github.com/makepad/makepad", branch = "rik", version = "0.6.0" }
|
||||||
# makepad-widgets = { path = "/Users/tsuki/projects/makepad/widgets", version = "0.6.0" }
|
mp_core = { path = "../mp_core", version = "*" }
|
||||||
|
once_cell = "1.20.2"
|
||||||
|
tracing = "0.1.40"
|
||||||
|
tracing-subscriber = "0.3.18"
|
||||||
|
|||||||
263
mp/config.toml
Normal file
263
mp/config.toml
Normal file
@ -0,0 +1,263 @@
|
|||||||
|
[common]
|
||||||
|
background = "Terrain"
|
||||||
|
path = "resources/alts.png"
|
||||||
|
plugins = "loaders"
|
||||||
|
|
||||||
|
[[cmap]]
|
||||||
|
type = "DBZ"
|
||||||
|
levels = [0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75]
|
||||||
|
colors = [
|
||||||
|
"#aaaaaa",
|
||||||
|
"#0022ff",
|
||||||
|
"#01a0f6",
|
||||||
|
"#00ecec",
|
||||||
|
"#00d800",
|
||||||
|
"#019000",
|
||||||
|
"#ffff00",
|
||||||
|
"#e7c000",
|
||||||
|
"#ff9000",
|
||||||
|
"#ff0000",
|
||||||
|
"#d60000",
|
||||||
|
"#c00000",
|
||||||
|
"#ff00f0",
|
||||||
|
"#9600b4",
|
||||||
|
"#ad90f0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[cmap]]
|
||||||
|
type = "VEL"
|
||||||
|
levels = [
|
||||||
|
-90,
|
||||||
|
-45,
|
||||||
|
-35,
|
||||||
|
-27,
|
||||||
|
-20,
|
||||||
|
-15,
|
||||||
|
-10,
|
||||||
|
-5,
|
||||||
|
-1,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
5,
|
||||||
|
10,
|
||||||
|
15,
|
||||||
|
20,
|
||||||
|
27,
|
||||||
|
1000,
|
||||||
|
]
|
||||||
|
colors = [
|
||||||
|
"#9fffff",
|
||||||
|
"#00e0ff",
|
||||||
|
"#0080ff",
|
||||||
|
"#320096",
|
||||||
|
"#00fb90",
|
||||||
|
"#00bb90",
|
||||||
|
"#008f00",
|
||||||
|
"#cdc09f",
|
||||||
|
"#000000",
|
||||||
|
"#f88700",
|
||||||
|
"#ffcf00",
|
||||||
|
"#ffff00",
|
||||||
|
"#ae0000",
|
||||||
|
"#d07000",
|
||||||
|
"#dd0000",
|
||||||
|
"#ff0000",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[cmap]]
|
||||||
|
type = "SW"
|
||||||
|
colors = [
|
||||||
|
"#E0E0E0",
|
||||||
|
"#7CE0E0",
|
||||||
|
"#00E0E0",
|
||||||
|
"#00B0B0",
|
||||||
|
"#00FEFE",
|
||||||
|
"#00C400",
|
||||||
|
"#008000",
|
||||||
|
"#FEFE00",
|
||||||
|
"#FED200",
|
||||||
|
"#FE7C00",
|
||||||
|
"#FEB0B0",
|
||||||
|
"#FE5858",
|
||||||
|
"#FE0000",
|
||||||
|
"#FEFEFE",
|
||||||
|
]
|
||||||
|
levels = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
|
||||||
|
|
||||||
|
[[cmap]]
|
||||||
|
type = "CC"
|
||||||
|
colors = [
|
||||||
|
"#003CFF",
|
||||||
|
"#00EFEF",
|
||||||
|
"#00BABF",
|
||||||
|
"#00837D",
|
||||||
|
"#008938",
|
||||||
|
"#00B729",
|
||||||
|
"#00DA0D",
|
||||||
|
"#00FF00",
|
||||||
|
"#FFFF3B",
|
||||||
|
"#FFF000",
|
||||||
|
"#FFC600",
|
||||||
|
"#FFA500",
|
||||||
|
"#FF7200",
|
||||||
|
"#FF1F00",
|
||||||
|
"#C10000",
|
||||||
|
"#D400AA",
|
||||||
|
]
|
||||||
|
levels = [
|
||||||
|
0,
|
||||||
|
0.1,
|
||||||
|
0.3,
|
||||||
|
0.5,
|
||||||
|
0.6,
|
||||||
|
0.7,
|
||||||
|
0.8,
|
||||||
|
0.85,
|
||||||
|
0.9,
|
||||||
|
0.92,
|
||||||
|
0.94,
|
||||||
|
0.95,
|
||||||
|
0.96,
|
||||||
|
0.97,
|
||||||
|
0.98,
|
||||||
|
0.99,
|
||||||
|
]
|
||||||
|
|
||||||
|
[[cmap]]
|
||||||
|
type = "KDP"
|
||||||
|
colors = [
|
||||||
|
"#00FFFF",
|
||||||
|
"#00EFEF",
|
||||||
|
"#00A8AC",
|
||||||
|
"#B4B4B4",
|
||||||
|
"#B4B4B4",
|
||||||
|
"#00C027",
|
||||||
|
"#00E80A",
|
||||||
|
"#24FF24",
|
||||||
|
"#FFFF1E",
|
||||||
|
"#FFE600",
|
||||||
|
"#FFBC00",
|
||||||
|
"#FF9800",
|
||||||
|
"#FF5E00",
|
||||||
|
"#F20F00",
|
||||||
|
"#BB003A",
|
||||||
|
"#DD009C",
|
||||||
|
"#FF00FF",
|
||||||
|
]
|
||||||
|
levels = [
|
||||||
|
-0.8,
|
||||||
|
-0.4,
|
||||||
|
-0.2,
|
||||||
|
-0.1,
|
||||||
|
0.1,
|
||||||
|
0.15,
|
||||||
|
0.22,
|
||||||
|
0.33,
|
||||||
|
0.5,
|
||||||
|
0.75,
|
||||||
|
1.1,
|
||||||
|
1.7,
|
||||||
|
2.4,
|
||||||
|
3.1,
|
||||||
|
7,
|
||||||
|
20,
|
||||||
|
]
|
||||||
|
|
||||||
|
[[cmap]]
|
||||||
|
type = "ZDR"
|
||||||
|
colors = [
|
||||||
|
"#464646",
|
||||||
|
"#505050",
|
||||||
|
"#5A5A5A",
|
||||||
|
"#646464",
|
||||||
|
"#6E6E6E",
|
||||||
|
"#787878",
|
||||||
|
"#828282",
|
||||||
|
"#8C8C8C",
|
||||||
|
"#969696",
|
||||||
|
"#AFAFAF",
|
||||||
|
"#C8C8C8",
|
||||||
|
"#DCF0DC",
|
||||||
|
"#00C027",
|
||||||
|
"#00E80A",
|
||||||
|
"#24FF24",
|
||||||
|
"#FFFF1E",
|
||||||
|
"#FFF20F",
|
||||||
|
"#FFE600",
|
||||||
|
"#FFBC00",
|
||||||
|
"#FF9800",
|
||||||
|
"#FF5E00",
|
||||||
|
"#FFFF00",
|
||||||
|
"#F20F00",
|
||||||
|
"#BB003A",
|
||||||
|
"#DD009C",
|
||||||
|
"#FF00FF",
|
||||||
|
]
|
||||||
|
levels = [
|
||||||
|
-5,
|
||||||
|
-4.5,
|
||||||
|
-4,
|
||||||
|
-3.5,
|
||||||
|
-3,
|
||||||
|
-2.5,
|
||||||
|
-2,
|
||||||
|
-1.5,
|
||||||
|
-1,
|
||||||
|
-0.5,
|
||||||
|
0,
|
||||||
|
0.5,
|
||||||
|
1,
|
||||||
|
1.5,
|
||||||
|
2,
|
||||||
|
2.5,
|
||||||
|
3,
|
||||||
|
3.5,
|
||||||
|
4,
|
||||||
|
4.5,
|
||||||
|
5,
|
||||||
|
5.5,
|
||||||
|
6,
|
||||||
|
6.5,
|
||||||
|
7,
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
[[cmap]]
|
||||||
|
type = "VIL"
|
||||||
|
levels = [
|
||||||
|
0.1,
|
||||||
|
1,
|
||||||
|
2.5,
|
||||||
|
5,
|
||||||
|
7.5,
|
||||||
|
10,
|
||||||
|
10.25,
|
||||||
|
15,
|
||||||
|
20,
|
||||||
|
25,
|
||||||
|
30,
|
||||||
|
35,
|
||||||
|
40,
|
||||||
|
45,
|
||||||
|
50,
|
||||||
|
55,
|
||||||
|
104,
|
||||||
|
]
|
||||||
|
colors = [
|
||||||
|
'#484892',
|
||||||
|
'#01a0f6',
|
||||||
|
'#00ecec',
|
||||||
|
'#01ff00',
|
||||||
|
'#00c800',
|
||||||
|
'#019000',
|
||||||
|
'#ffff00',
|
||||||
|
'#e7c000',
|
||||||
|
'#ff9000',
|
||||||
|
'#ff0000',
|
||||||
|
'#d60000',
|
||||||
|
'#c00000',
|
||||||
|
'#ff00f0',
|
||||||
|
'#ad90f0',
|
||||||
|
'#780084',
|
||||||
|
'#d8af97',
|
||||||
|
]
|
||||||
@ -12,6 +12,8 @@ live_design! {
|
|||||||
flow: Down
|
flow: Down
|
||||||
spacing: 10.
|
spacing: 10.
|
||||||
padding: 15.
|
padding: 15.
|
||||||
|
height: Fit
|
||||||
|
width: Fill
|
||||||
draw_bg: {
|
draw_bg: {
|
||||||
instance border_width: 1.0
|
instance border_width: 1.0
|
||||||
instance border_color: (THEME_COLOR_U_2)
|
instance border_color: (THEME_COLOR_U_2)
|
||||||
@ -88,6 +90,8 @@ live_design! {
|
|||||||
flow: Down,
|
flow: Down,
|
||||||
spacing: 15.,
|
spacing: 15.,
|
||||||
|
|
||||||
|
scroll_bars: <ScrollBars> {show_scroll_x: false, show_scroll_y: true}
|
||||||
|
|
||||||
<H4>{ text: "Controller"}
|
<H4>{ text: "Controller"}
|
||||||
|
|
||||||
<Group> {
|
<Group> {
|
||||||
|
|||||||
@ -5,3 +5,5 @@ pub use makepad_widgets::makepad_platform;
|
|||||||
pub mod app_ui;
|
pub mod app_ui;
|
||||||
pub mod shaders;
|
pub mod shaders;
|
||||||
pub mod widgets;
|
pub mod widgets;
|
||||||
|
|
||||||
|
pub mod render;
|
||||||
|
|||||||
@ -1,3 +1,48 @@
|
|||||||
|
use log::*;
|
||||||
|
use mp_core::{config::Setting, datapool::DataPool, plugin_system::PluginManager};
|
||||||
|
use once_cell::sync::Lazy;
|
||||||
|
use std::env;
|
||||||
|
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
||||||
|
|
||||||
|
static CONFIG: Lazy<Setting> = Lazy::new(|| Setting::new());
|
||||||
|
static PLUGIN_MANAGER: Lazy<PluginManager> = Lazy::new(|| {
|
||||||
|
PluginManager::new(
|
||||||
|
env::current_dir().unwrap().join(
|
||||||
|
(CONFIG.common.plugins)
|
||||||
|
.as_ref()
|
||||||
|
.unwrap_or(&"loaders".into()),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
});
|
||||||
|
static DATAPOOL: Lazy<DataPool> = Lazy::new(|| DataPool::new(&PLUGIN_MANAGER, 10));
|
||||||
|
|
||||||
|
// static DATA_POOL: Lazy<DataPool> = Lazy::new(|| Data);
|
||||||
fn main() {
|
fn main() {
|
||||||
|
// Init logger
|
||||||
|
// Logger Filter
|
||||||
|
let filter = tracing_subscriber::filter::targets::Targets::new()
|
||||||
|
.with_targets(vec![
|
||||||
|
("radarg_plugin_interface", tracing::Level::INFO),
|
||||||
|
("mp_core", tracing::Level::INFO),
|
||||||
|
])
|
||||||
|
.with_target("mp", tracing::level_filters::LevelFilter::DEBUG);
|
||||||
|
|
||||||
|
// Logger Registry
|
||||||
|
tracing_subscriber::registry()
|
||||||
|
.with(tracing_subscriber::fmt::layer())
|
||||||
|
.with(filter)
|
||||||
|
.init();
|
||||||
|
|
||||||
|
// Default Plugin Dir
|
||||||
|
let plugin_dir = env::current_dir().unwrap().join("loaders");
|
||||||
|
info!("Plugin Dir: {:?}", plugin_dir);
|
||||||
|
|
||||||
|
// Init data pool
|
||||||
|
info!("Init DataPool.... DataPool Length: {}", DATAPOOL.len());
|
||||||
|
|
||||||
|
// Init Setting
|
||||||
|
info!("Init Settings");
|
||||||
|
info!("Settings: {:?}", CONFIG.common);
|
||||||
mp::app::app_main();
|
mp::app::app_main();
|
||||||
}
|
}
|
||||||
|
|||||||
1
mp/src/render/camera.rs
Normal file
1
mp/src/render/camera.rs
Normal file
@ -0,0 +1 @@
|
|||||||
|
pub struct Camera {}
|
||||||
33
mp/src/render/grid_data.rs
Normal file
33
mp/src/render/grid_data.rs
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
use makepad_widgets::{Cx, Texture, TextureFormat};
|
||||||
|
use mp_core::data::RadarGridData;
|
||||||
|
pub struct GridData {
|
||||||
|
texture: Texture,
|
||||||
|
clear_buffer: bool,
|
||||||
|
shape: Option<Vec<u32>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GridData {
|
||||||
|
pub fn new(cx: &mut Cx) -> Self {
|
||||||
|
let texture = Texture::new_with_format(cx, TextureFormat::Unknown);
|
||||||
|
GridData {
|
||||||
|
texture,
|
||||||
|
clear_buffer: true,
|
||||||
|
shape: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update(&mut self, cx: &mut Cx, data: &RadarGridData) {
|
||||||
|
let data = data.data.cast_to::<f32>();
|
||||||
|
self.clear_buffer = false;
|
||||||
|
// self.shape = Some(data.dim().into());
|
||||||
|
// self.texture.put_back_vec_f32(cx, data.into(), None);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clear(&mut self) {
|
||||||
|
self.clear_buffer = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn texture(&self) -> &Texture {
|
||||||
|
&self.texture
|
||||||
|
}
|
||||||
|
}
|
||||||
2
mp/src/render/mod.rs
Normal file
2
mp/src/render/mod.rs
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
pub mod camera;
|
||||||
|
pub mod grid_data;
|
||||||
@ -1,11 +1,27 @@
|
|||||||
use makepad_platform::*;
|
use crate::render::grid_data::GridData;
|
||||||
use makepad_widgets::*;
|
use makepad_widgets::*;
|
||||||
|
|
||||||
live_design! {
|
live_design! {
|
||||||
PPI = {{PPI}} {
|
PPI = {{PPI}} {
|
||||||
|
|
||||||
|
uniform three_d: int
|
||||||
|
//
|
||||||
|
uniform conf: vec4
|
||||||
|
varing pos: vec4
|
||||||
|
|
||||||
|
// Data
|
||||||
|
texture data: texture3d
|
||||||
|
// ColorMAPPER
|
||||||
|
textrue color_map: texture1d
|
||||||
|
|
||||||
fn vertex(self) -> vec4 {
|
fn vertex(self) -> vec4 {
|
||||||
let pos = geometry * vec2(1., 1.);
|
|
||||||
return vec4(pos, 0., 1.);
|
if (three_d == 1) {
|
||||||
|
return vec4(self.position,)
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return vec4(self.position, 1.0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pixel(self) -> vec4 {
|
fn pixel(self) -> vec4 {
|
||||||
@ -22,6 +38,10 @@ pub struct PPI {
|
|||||||
draw_vars: DrawVars,
|
draw_vars: DrawVars,
|
||||||
#[live]
|
#[live]
|
||||||
geometry: GeometryQuad2D,
|
geometry: GeometryQuad2D,
|
||||||
|
#[calc]
|
||||||
|
pub position: Vec3,
|
||||||
|
#[calc]
|
||||||
|
pub value: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LiveHook for PPI {
|
impl LiveHook for PPI {
|
||||||
@ -37,5 +57,7 @@ impl LiveHook for PPI {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl PPI {
|
impl PPI {
|
||||||
pub fn update_draw_call_vars(&mut self) {}
|
pub fn update_draw_call_vars(&mut self, data: &GridData) {
|
||||||
|
self.draw_vars.texture_slots[0] = Some(data.texture().clone());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
23
mp_core/Cargo.toml
Normal file
23
mp_core/Cargo.toml
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
[package]
|
||||||
|
name = "mp_core"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
abi_stable = "0.11.3"
|
||||||
|
chrono = "0.4.38"
|
||||||
|
core_extensions = "1.5.3"
|
||||||
|
dirs = "5.0.1"
|
||||||
|
futures = "0.3.31"
|
||||||
|
ndarray = { version = "0.16.1", features = ["rayon"] }
|
||||||
|
num-traits = "0.2.19"
|
||||||
|
once_cell = "1.20.2"
|
||||||
|
quick_cache = "0.6.9"
|
||||||
|
rust-embed = "8.5.0"
|
||||||
|
serde = { version = "1.0.214", features = ["derive"] }
|
||||||
|
thiserror = "1.0.65"
|
||||||
|
tokio = { version = "1.41.0", features = ["full"] }
|
||||||
|
toml = "0.8.19"
|
||||||
|
|
||||||
|
[dependencies.radarg_plugin_interface]
|
||||||
|
path = "../radarg_plugin_interface"
|
||||||
142
mp_core/src/config.rs
Normal file
142
mp_core/src/config.rs
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
use crate::data::ProbeDataType;
|
||||||
|
use crate::errors::ConfigError;
|
||||||
|
use crate::utils::color_tools::hex_to_rgba_u8;
|
||||||
|
use crate::Asset;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::{env, path::PathBuf};
|
||||||
|
use toml;
|
||||||
|
|
||||||
|
// 定义一个宏 find_cmap,用于在给定的集合中查找特定类型的元素
|
||||||
|
macro_rules! find_cmap {
|
||||||
|
// 宏的参数:$c 是要匹配的值,$find_on 是要查找的集合,$b 和 $name 是匹配模式和类型名称
|
||||||
|
($c:ident,$find_on:ident,$({$b:tt => $name:literal}),*) => {
|
||||||
|
|
||||||
|
{
|
||||||
|
// 初始化 cmap 为 None
|
||||||
|
let mut cmap = None;
|
||||||
|
// 根据 $c 的值进行匹配
|
||||||
|
match $c {
|
||||||
|
$(
|
||||||
|
// 如果 $c 匹配到 $b,则在 $find_on 集合中查找类型名称为 $name 的元素
|
||||||
|
$b => {
|
||||||
|
let find_v = $find_on.iter().find(|cb| cb.type_name == $name).map(|cb| cb);
|
||||||
|
// 将找到的元素赋值给 cmap
|
||||||
|
cmap = find_v;
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
// 如果没有匹配到任何模式,则保持 cmap 为 None
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
// 返回 cmap
|
||||||
|
cmap
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize, Debug)]
|
||||||
|
|
||||||
|
pub struct Setting {
|
||||||
|
pub common: Common,
|
||||||
|
pub cmap: Vec<CB>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Setting {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
use std::fs::read_to_string;
|
||||||
|
use std::io::*;
|
||||||
|
let current_dir = env::current_dir().unwrap();
|
||||||
|
|
||||||
|
if !current_dir.join("config.toml").exists() {
|
||||||
|
let default_config = Asset::get("config.toml").unwrap();
|
||||||
|
|
||||||
|
let folder_path = current_dir.clone();
|
||||||
|
let conf = folder_path.join("config.toml");
|
||||||
|
|
||||||
|
let mut file = std::fs::File::create_new(&conf).unwrap();
|
||||||
|
file.write_all(&default_config.data).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
let file = read_to_string(current_dir.join("config.toml")).unwrap();
|
||||||
|
let setting: Setting = toml::from_str(&file).unwrap();
|
||||||
|
setting
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn find(&self, name: &ProbeDataType) -> Option<&CB> {
|
||||||
|
let cmap = &self.cmap;
|
||||||
|
use ProbeDataType::*;
|
||||||
|
find_cmap!(
|
||||||
|
name, cmap,
|
||||||
|
{DBZ => "DBZ"},
|
||||||
|
{V => "VEL"},
|
||||||
|
{VIL => "VIL"},
|
||||||
|
{CC => "CC"},
|
||||||
|
{KDP => "KDP"},
|
||||||
|
{ZDR => "ZDR"},
|
||||||
|
{PHIDP => "PHIDP"}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize, Debug)]
|
||||||
|
pub struct CB {
|
||||||
|
#[serde(rename = "type")]
|
||||||
|
pub type_name: String,
|
||||||
|
pub colors: Vec<String>,
|
||||||
|
pub levels: Vec<f32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CB {
|
||||||
|
pub fn value_range(&self) -> [f32; 2] {
|
||||||
|
let mut range = [0.0, 0.0];
|
||||||
|
let levels = &self.levels;
|
||||||
|
range[0] = levels[0];
|
||||||
|
range[1] = levels[levels.len() - 1];
|
||||||
|
range
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn color(&self) -> Result<Vec<[u8; 4]>, ConfigError> {
|
||||||
|
if self.colors.len() != self.levels.len() - 1 {
|
||||||
|
return Err(ConfigError::FormatError(
|
||||||
|
"The number of colors and levels are not matched".to_string(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut result = self
|
||||||
|
.colors
|
||||||
|
.iter()
|
||||||
|
.map(|v| hex_to_rgba_u8(v))
|
||||||
|
.collect::<std::result::Result<Vec<_>, String>>()
|
||||||
|
.map_err(|v| ConfigError::FormatError(v.to_string()))?;
|
||||||
|
|
||||||
|
let mut span = Vec::with_capacity(self.levels.len() - 1);
|
||||||
|
|
||||||
|
for idx in 0..self.levels.len() - 1 {
|
||||||
|
let start = self.levels[idx];
|
||||||
|
let end = self.levels[idx + 1];
|
||||||
|
let range = end - start;
|
||||||
|
span.push(range);
|
||||||
|
}
|
||||||
|
|
||||||
|
let range = self.value_range();
|
||||||
|
let all_range = range[1] - range[0];
|
||||||
|
|
||||||
|
for (level, r) in span.iter().zip(result.iter_mut()) {
|
||||||
|
r[3] = ((*level / all_range) * 255.0) as u8;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize, Debug)]
|
||||||
|
pub struct Common {
|
||||||
|
pub background: BackgroundType,
|
||||||
|
pub path: PathBuf,
|
||||||
|
pub plugins: Option<PathBuf>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize, Debug)]
|
||||||
|
pub enum BackgroundType {
|
||||||
|
Terrain,
|
||||||
|
Earth,
|
||||||
|
}
|
||||||
401
mp_core/src/data/mod.rs
Normal file
401
mp_core/src/data/mod.rs
Normal file
@ -0,0 +1,401 @@
|
|||||||
|
use chrono::Utc;
|
||||||
|
use ndarray::ArrayD;
|
||||||
|
use num_traits::FromPrimitive;
|
||||||
|
use radarg_plugin_interface::{
|
||||||
|
LoadedData, ProbeDataType as RPT, RadarGridData as RawRadarGridData, VecResult::*,
|
||||||
|
};
|
||||||
|
use std::{
|
||||||
|
fmt::Display,
|
||||||
|
hash::Hash,
|
||||||
|
sync::{atomic::AtomicUsize, Arc},
|
||||||
|
};
|
||||||
|
|
||||||
|
// Data's unique identifier
|
||||||
|
static DATA_ID: AtomicUsize = AtomicUsize::new(0);
|
||||||
|
|
||||||
|
// Data Struct
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct Data {
|
||||||
|
pub id: usize,
|
||||||
|
pub description: String,
|
||||||
|
_data: _Data,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Debug for Data {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"Data {{ id: {}, description: {}",
|
||||||
|
self.id, self.description
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialEq for Data {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
self.id == other.id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Hash for Data {
|
||||||
|
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
||||||
|
self.id.hash(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Eq for Data {}
|
||||||
|
|
||||||
|
impl Display for Data {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "{}", self._data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub(crate) enum _Data {
|
||||||
|
RadarGridData(Arc<RadarGridData>),
|
||||||
|
JsonData,
|
||||||
|
PlainText(String),
|
||||||
|
Binary(Vec<u8>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for _Data {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
_Data::RadarGridData(info) => write!(f, "RadarGridData: {}", info),
|
||||||
|
_Data::JsonData => write!(f, "JsonData"),
|
||||||
|
_Data::PlainText(_) => write!(f, "PlainText"),
|
||||||
|
_Data::Binary(_) => write!(f, "Binary"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct RadarGridData {
|
||||||
|
pub data: ArrayData,
|
||||||
|
pub info: GridDataInfo,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RadarGridData {
|
||||||
|
pub fn get_data(&self) -> &ArrayData {
|
||||||
|
&self.data
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn coord_type<'a>(&'a self) -> Option<CoordType<'a>> {
|
||||||
|
let names = &self.info.dimension_names;
|
||||||
|
let dimension_keys = names.iter().map(|v| v.as_str()).collect::<Vec<_>>();
|
||||||
|
|
||||||
|
if dimension_keys.contains(&"lon") {
|
||||||
|
let shape_len = self.data.shape().len();
|
||||||
|
if shape_len == 2 {
|
||||||
|
Some(CoordType::Cartesian {
|
||||||
|
hgt: None,
|
||||||
|
lat: &self.info.dimensions[0],
|
||||||
|
lon: &self.info.dimensions[1],
|
||||||
|
})
|
||||||
|
} else if shape_len == 3 {
|
||||||
|
Some(CoordType::Cartesian {
|
||||||
|
hgt: Some(&self.info.dimensions[0]),
|
||||||
|
lat: &self.info.dimensions[1],
|
||||||
|
lon: &self.info.dimensions[2],
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
} else if dimension_keys.contains(&"el") {
|
||||||
|
let shape_len = self.data.shape().len();
|
||||||
|
if shape_len == 2 {
|
||||||
|
Some(CoordType::Polar {
|
||||||
|
elevation: None,
|
||||||
|
azimuth: &self.info.dimensions[0],
|
||||||
|
range: &self.info.dimensions[1],
|
||||||
|
})
|
||||||
|
} else if shape_len == 3 {
|
||||||
|
Some(CoordType::Polar {
|
||||||
|
elevation: Some(&self.info.dimensions[0]),
|
||||||
|
azimuth: &self.info.dimensions[1],
|
||||||
|
range: &self.info.dimensions[2],
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn invalid_value(&self) -> f64 {
|
||||||
|
self.info.fill_value
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn datetime(&self) -> Option<chrono::DateTime<Utc>> {
|
||||||
|
self.info.datetime
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn data_type(&self) -> ProbeDataType {
|
||||||
|
self.info
|
||||||
|
.maybe_probe_data_type
|
||||||
|
.unwrap_or(ProbeDataType::Unknown)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum CoordType<'a> {
|
||||||
|
Cartesian {
|
||||||
|
hgt: Option<&'a Vec<f64>>,
|
||||||
|
lat: &'a Vec<f64>,
|
||||||
|
lon: &'a Vec<f64>,
|
||||||
|
},
|
||||||
|
Polar {
|
||||||
|
range: &'a Vec<f64>,
|
||||||
|
azimuth: &'a Vec<f64>,
|
||||||
|
elevation: Option<&'a Vec<f64>>,
|
||||||
|
},
|
||||||
|
Other,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for CoordType<'_> {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
CoordType::Cartesian { .. } => write!(f, "Cartesian"),
|
||||||
|
CoordType::Polar { .. } => write!(f, "Polar"),
|
||||||
|
CoordType::Other => write!(f, "Other"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for RadarGridData {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "shape: {:?}, dimension_names: {:?}, fill_value: {}, datetime: {:?}, value_description: {:?}, value_name: {}, maybe_probe_data_type: {:?}, dimension_description: {}",
|
||||||
|
self.info.shape, self.info.dimension_names, self.info.fill_value, self.info.datetime, self.info.value_description, self.info.value_name, self.info.maybe_probe_data_type, self.info.dimension_description)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Default)]
|
||||||
|
pub struct GridDataInfo {
|
||||||
|
pub shape: Vec<usize>,
|
||||||
|
pub dimensions: Vec<Vec<f64>>,
|
||||||
|
pub dimension_names: Vec<String>,
|
||||||
|
pub fill_value: f64,
|
||||||
|
pub datetime: Option<chrono::DateTime<Utc>>,
|
||||||
|
pub value_description: Option<String>,
|
||||||
|
pub value_name: String,
|
||||||
|
pub maybe_probe_data_type: Option<ProbeDataType>,
|
||||||
|
pub dimension_description: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub enum ProbeDataType {
|
||||||
|
// Single
|
||||||
|
R,
|
||||||
|
V,
|
||||||
|
SW,
|
||||||
|
CC,
|
||||||
|
ZDR,
|
||||||
|
PHIDP,
|
||||||
|
KDP,
|
||||||
|
HCA,
|
||||||
|
DBZ,
|
||||||
|
QPE,
|
||||||
|
QPF,
|
||||||
|
VIL,
|
||||||
|
OHP,
|
||||||
|
THP,
|
||||||
|
ET,
|
||||||
|
EB,
|
||||||
|
// Unknown
|
||||||
|
Unknown,
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! raw2new {
|
||||||
|
($({$raw_bc:tt | $typ:ty | $from:ident}),+, ($({$raw_rdt:tt}),+)) => {
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum ArrayData {
|
||||||
|
$(
|
||||||
|
$raw_bc(ArrayD<$typ>),
|
||||||
|
)+
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ArrayData {
|
||||||
|
pub fn shape(&self) -> &[usize] {
|
||||||
|
match self {
|
||||||
|
$(
|
||||||
|
ArrayData::$raw_bc(v) => v.shape(),
|
||||||
|
)+
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn cast_to<T: FromPrimitive>(&self) -> ArrayD<T> {
|
||||||
|
match self {
|
||||||
|
$(
|
||||||
|
ArrayData::$raw_bc(v) => v.map(|v| T::$from(*v).unwrap()),
|
||||||
|
)+
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn scale_offset(&self, scale: f64, offset: f64) -> ArrayD<f32>{
|
||||||
|
match self {
|
||||||
|
$(
|
||||||
|
ArrayData::$raw_bc(v) => v.mapv(|v| v as f32 * scale as f32 + offset as f32),
|
||||||
|
)+
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn scale_offset_to_pixel(&self, fill_value:f32, min:f32, max:f32) -> ArrayD<u8>{
|
||||||
|
match self {
|
||||||
|
$(
|
||||||
|
ArrayData::$raw_bc(v) => v.mapv(|v| {
|
||||||
|
if (v as f32 - fill_value).abs() < 1e-6 {
|
||||||
|
0
|
||||||
|
} else {
|
||||||
|
let v = (v as f32 - min) / (max - min) * 254.0;
|
||||||
|
v as u8 + 1
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
)+
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$(
|
||||||
|
pub fn $raw_bc(&self) -> &ArrayD<$typ> {
|
||||||
|
match self {
|
||||||
|
ArrayData::$raw_bc(v) => v,
|
||||||
|
_ => panic!("Unsupported data type"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)+
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<RawRadarGridData> for RadarGridData {
|
||||||
|
fn from(raw: RawRadarGridData) -> Self {
|
||||||
|
let RawRadarGridData { data, info } = raw;
|
||||||
|
let shape = info.shape.into_vec();
|
||||||
|
// println!("{:?}", shape);
|
||||||
|
|
||||||
|
let data = match data {
|
||||||
|
$(
|
||||||
|
$raw_bc(v) => {
|
||||||
|
ArrayData::$raw_bc(ArrayD::from_shape_vec(shape.clone(), v.to_vec()).unwrap())
|
||||||
|
}
|
||||||
|
)+
|
||||||
|
_ => panic!("Unsupported data type"),
|
||||||
|
};
|
||||||
|
|
||||||
|
let dimensions = info.dimensions.into_iter().map(|v| v.into()).collect();
|
||||||
|
let dimension_names = info.dimension_names.into_iter().map(|v| v.into()).collect();
|
||||||
|
let value_description = info.value_description.into_option().map(|v| v.into());
|
||||||
|
|
||||||
|
let maybe_probe_data_type = info.maybe_probe_data_type.map(|v| match v {
|
||||||
|
$(
|
||||||
|
RPT::$raw_rdt => ProbeDataType::$raw_rdt,
|
||||||
|
)+
|
||||||
|
RPT::Unknown => ProbeDataType::Unknown,
|
||||||
|
}).into_option();
|
||||||
|
|
||||||
|
let datetime = info.datetime.into_option().map(|v| chrono::DateTime::from_timestamp(v,0).unwrap());
|
||||||
|
|
||||||
|
let info = GridDataInfo {
|
||||||
|
shape,
|
||||||
|
dimensions: dimensions,
|
||||||
|
dimension_names,
|
||||||
|
fill_value: info.fill_value,
|
||||||
|
datetime,
|
||||||
|
value_description,
|
||||||
|
value_name: info.value_name.into_string(),
|
||||||
|
maybe_probe_data_type,
|
||||||
|
dimension_description: info.dimension_description.into_string(),
|
||||||
|
};
|
||||||
|
Self { data, info }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
raw2new!(
|
||||||
|
{ F32 | f32 | from_f32 },
|
||||||
|
{ F64 | f64 | from_f64 },
|
||||||
|
{ I32 | i32 | from_i32 },
|
||||||
|
{ I16 | i16 | from_i16 },
|
||||||
|
{ U64 | u64 | from_u64 },
|
||||||
|
{ U32 | u32 | from_u32 },
|
||||||
|
{ I8 | i8 | from_i8 },
|
||||||
|
{ U8 | u8 | from_u8 },
|
||||||
|
{ I64 | i64 | from_i64 },
|
||||||
|
(
|
||||||
|
{ R },
|
||||||
|
{ V },
|
||||||
|
{ SW },
|
||||||
|
{ CC },
|
||||||
|
{ ZDR },
|
||||||
|
{ PHIDP },
|
||||||
|
{ KDP },
|
||||||
|
{ HCA },
|
||||||
|
{ DBZ },
|
||||||
|
{ QPE },
|
||||||
|
{ QPF },
|
||||||
|
{ VIL },
|
||||||
|
{ OHP },
|
||||||
|
{ THP },
|
||||||
|
{ ET },
|
||||||
|
{ EB }
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
impl From<LoadedData> for _Data {
|
||||||
|
fn from(value: LoadedData) -> Self {
|
||||||
|
match value {
|
||||||
|
LoadedData::Binary(v) => _Data::Binary(v.into_vec()),
|
||||||
|
LoadedData::JsonData => _Data::JsonData,
|
||||||
|
LoadedData::PlainText(v) => _Data::PlainText(v.into_string()),
|
||||||
|
LoadedData::RadarGridData(v) => _Data::RadarGridData(Arc::new(v.into())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<LoadedData> for Data {
|
||||||
|
fn from(value: LoadedData) -> Self {
|
||||||
|
let description = match &value {
|
||||||
|
LoadedData::Binary(_) => "Binary".into(),
|
||||||
|
LoadedData::JsonData => "JsonData".into(),
|
||||||
|
LoadedData::PlainText(_) => "PlainText".into(),
|
||||||
|
LoadedData::RadarGridData(v) => format!("{}", v.info.value_name),
|
||||||
|
};
|
||||||
|
Data {
|
||||||
|
id: DATA_ID.fetch_add(1, std::sync::atomic::Ordering::SeqCst),
|
||||||
|
description: description,
|
||||||
|
_data: value.into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> TryFrom<&'a Data> for &'a () {
|
||||||
|
type Error = crate::errors::DataError;
|
||||||
|
|
||||||
|
fn try_from(value: &'a Data) -> Result<Self, Self::Error> {
|
||||||
|
Ok(&())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> TryFrom<&'a Data> for &'a Arc<RadarGridData> {
|
||||||
|
type Error = crate::errors::DataError;
|
||||||
|
|
||||||
|
fn try_from(value: &'a Data) -> Result<Self, Self::Error> {
|
||||||
|
match &value._data {
|
||||||
|
_Data::RadarGridData(v) => Ok(&v),
|
||||||
|
_ => Err(crate::errors::DataError::FormatError),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> TryFrom<&'a Data> for &'a RadarGridData {
|
||||||
|
type Error = crate::errors::DataError;
|
||||||
|
|
||||||
|
fn try_from(value: &'a Data) -> Result<Self, Self::Error> {
|
||||||
|
match &value._data {
|
||||||
|
_Data::RadarGridData(v) => Ok(&*v),
|
||||||
|
_ => Err(crate::errors::DataError::FormatError),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
109
mp_core/src/datapool/mod.rs
Normal file
109
mp_core/src/datapool/mod.rs
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
use super::data::Data;
|
||||||
|
use crate::errors::DataError;
|
||||||
|
use crate::plugin_system::PluginManager;
|
||||||
|
use once_cell::sync::Lazy;
|
||||||
|
use quick_cache::sync::Cache;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::fmt::Display;
|
||||||
|
use std::ops::Deref;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
static RUNTIME: Lazy<tokio::runtime::Runtime> =
|
||||||
|
Lazy::new(|| tokio::runtime::Runtime::new().unwrap());
|
||||||
|
|
||||||
|
pub type DataValue = Value<Data>;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct Value<T: Display>(Arc<HashMap<usize, Arc<T>>>);
|
||||||
|
|
||||||
|
impl Value<Data> {
|
||||||
|
pub fn new(data: Vec<Data>) -> Self {
|
||||||
|
let mut hashmap = HashMap::new();
|
||||||
|
for data in data {
|
||||||
|
hashmap.insert(data.id, Arc::new(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
Self(Arc::new(hashmap))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get(&self, key: usize) -> Option<&Arc<Data>> {
|
||||||
|
self.0.get(&key)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn iter(&self) -> std::collections::hash_map::Iter<'_, usize, Arc<Data>> {
|
||||||
|
self.0.iter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Display> Value<T> {
|
||||||
|
pub fn len(&self) -> usize {
|
||||||
|
self.0.len()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Display> Deref for Value<T> {
|
||||||
|
type Target = HashMap<usize, Arc<T>>;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct DataPool {
|
||||||
|
plugin_manager: &'static PluginManager,
|
||||||
|
pool: Cache<PathBuf, Value<Data>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DataPool {
|
||||||
|
pub fn new(plugin_manager: &'static PluginManager, cap: usize) -> Self {
|
||||||
|
Self {
|
||||||
|
plugin_manager,
|
||||||
|
pool: Cache::new(cap),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_or_load(&self, path: impl Into<PathBuf>) -> Result<Value<Data>, DataError> {
|
||||||
|
let path = path.into();
|
||||||
|
self.pool.get_or_insert_with(&path, || {
|
||||||
|
self.plugin_manager.try_load_data(&path).map(Value::new)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn len(&self) -> usize {
|
||||||
|
self.pool.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_or_load_async(
|
||||||
|
&self,
|
||||||
|
path: impl Into<PathBuf>,
|
||||||
|
) -> Result<Value<Data>, DataError> {
|
||||||
|
let path = path.into();
|
||||||
|
|
||||||
|
let plugin_manager = self.plugin_manager;
|
||||||
|
|
||||||
|
self.pool
|
||||||
|
.get_or_insert_async(&path.clone(), async move {
|
||||||
|
RUNTIME
|
||||||
|
.spawn_blocking(move || plugin_manager.try_load_data(&path))
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
.map(Value::new)
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_or_insert_batch_async<A: Into<PathBuf>, P: IntoIterator<Item = A>>(
|
||||||
|
&self,
|
||||||
|
paths: P,
|
||||||
|
) -> Vec<Result<Value<Data>, DataError>> {
|
||||||
|
use futures::future::join_all;
|
||||||
|
|
||||||
|
let tasks = paths
|
||||||
|
.into_iter()
|
||||||
|
.map(|path| self.get_or_load_async(path.into()));
|
||||||
|
|
||||||
|
let results = join_all(tasks).await;
|
||||||
|
results
|
||||||
|
}
|
||||||
|
}
|
||||||
42
mp_core/src/errors.rs
Normal file
42
mp_core/src/errors.rs
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
use radarg_plugin_interface::Error as PluginError;
|
||||||
|
use thiserror::Error;
|
||||||
|
|
||||||
|
#[derive(Error, Debug)]
|
||||||
|
pub enum DataError {
|
||||||
|
#[error("value")]
|
||||||
|
FormatError,
|
||||||
|
#[error("")]
|
||||||
|
IOError(#[from] std::io::Error),
|
||||||
|
#[error("")]
|
||||||
|
Plugin(#[from] PluginError),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Error)]
|
||||||
|
pub enum PipelineError {
|
||||||
|
#[error("data error")]
|
||||||
|
DataError(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Error)]
|
||||||
|
pub enum ConfigError {
|
||||||
|
#[error("")]
|
||||||
|
IOError(#[from] std::io::Error),
|
||||||
|
#[error("")]
|
||||||
|
TomlError(#[from] toml::de::Error),
|
||||||
|
#[error("")]
|
||||||
|
VarError(#[from] std::env::VarError),
|
||||||
|
#[error("Can't find and create default Config")]
|
||||||
|
DefaultConfigError,
|
||||||
|
#[error("Format Error, {0}")]
|
||||||
|
FormatError(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Error)]
|
||||||
|
pub enum PoolError {
|
||||||
|
#[error("")]
|
||||||
|
TimestampError,
|
||||||
|
#[error("Data Pool is full")]
|
||||||
|
PoolFull,
|
||||||
|
#[error("Data Pool is not initialized")]
|
||||||
|
PoolInitialized(&'static str),
|
||||||
|
}
|
||||||
16
mp_core/src/lib.rs
Normal file
16
mp_core/src/lib.rs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
pub mod config;
|
||||||
|
pub mod data;
|
||||||
|
pub mod datapool;
|
||||||
|
pub mod errors;
|
||||||
|
pub mod plugin_system;
|
||||||
|
mod utils;
|
||||||
|
use rust_embed::RustEmbed;
|
||||||
|
|
||||||
|
#[derive(RustEmbed)]
|
||||||
|
#[folder = "statics/"]
|
||||||
|
pub struct Asset;
|
||||||
|
|
||||||
|
pub use config::Setting;
|
||||||
|
pub use data::{Data, RadarGridData};
|
||||||
|
pub use datapool::{DataPool, DataValue};
|
||||||
|
pub use plugin_system::PluginManager;
|
||||||
111
mp_core/src/plugin_system/mod.rs
Normal file
111
mp_core/src/plugin_system/mod.rs
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
use super::data::Data;
|
||||||
|
use crate::errors::DataError;
|
||||||
|
use abi_stable::{
|
||||||
|
library::{lib_header_from_path, LibrarySuffix, RawLibrary},
|
||||||
|
std_types::{RBox, ROk, RStr},
|
||||||
|
};
|
||||||
|
use core_extensions::*;
|
||||||
|
use radarg_plugin_interface::{DataLoaderPlugin_TO, PluginId, PluginMod_Ref};
|
||||||
|
use std::{
|
||||||
|
collections::HashMap,
|
||||||
|
io,
|
||||||
|
path::{Path, PathBuf},
|
||||||
|
};
|
||||||
|
|
||||||
|
fn compute_plugin_path(base_dir: &Path, base_name: &str) -> io::Result<PathBuf> {
|
||||||
|
let debug_dir = base_dir.join("target/debug");
|
||||||
|
|
||||||
|
let release_dir = base_dir.join("target/release");
|
||||||
|
|
||||||
|
// let debug_dir = "./loaders/target/debug"
|
||||||
|
// .as_ref_::<Path>()
|
||||||
|
// .into_::<PathBuf>();
|
||||||
|
// let release_dir = "./loaders/target/release"
|
||||||
|
// .as_ref_::<Path>()
|
||||||
|
// .into_::<PathBuf>();
|
||||||
|
|
||||||
|
let debug_path = RawLibrary::path_in_directory(&debug_dir, base_name, LibrarySuffix::NoSuffix);
|
||||||
|
|
||||||
|
let release_path =
|
||||||
|
RawLibrary::path_in_directory(&release_dir, base_name, LibrarySuffix::NoSuffix);
|
||||||
|
|
||||||
|
match (debug_path.exists(), release_path.exists()) {
|
||||||
|
(false, false) => debug_path,
|
||||||
|
(true, false) => debug_path,
|
||||||
|
(false, true) => release_path,
|
||||||
|
(true, true) => {
|
||||||
|
if debug_path.metadata()?.modified()? < release_path.metadata()?.modified()? {
|
||||||
|
release_path
|
||||||
|
} else {
|
||||||
|
debug_path
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.piped(Ok)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn init_plugin(
|
||||||
|
base_dir: &Path,
|
||||||
|
base_name: impl AsRef<str>,
|
||||||
|
) -> Result<(PluginId, DataLoaderPlugin_TO<'static, RBox<()>>), DataError> {
|
||||||
|
let library_path: PathBuf = compute_plugin_path(base_dir, base_name.as_ref())?;
|
||||||
|
let res = (|| {
|
||||||
|
let header = lib_header_from_path(&library_path)?;
|
||||||
|
header.init_root_module::<PluginMod_Ref>()
|
||||||
|
})()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let plugin_constructor = res.new();
|
||||||
|
let new_id = PluginId {
|
||||||
|
named: base_name.as_ref().to_owned().into(),
|
||||||
|
instance: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
let plugin = plugin_constructor(new_id.clone()).unwrap();
|
||||||
|
|
||||||
|
Ok((new_id, plugin))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct PluginManager {
|
||||||
|
registered_plugins: HashMap<PluginId, DataLoaderPlugin_TO<'static, RBox<()>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PluginManager {
|
||||||
|
pub fn new<P: AsRef<Path>>(plugin_dir: P) -> Result<Self, DataError> {
|
||||||
|
let mut this = Self {
|
||||||
|
registered_plugins: HashMap::new(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let (id, plugin) = init_plugin(plugin_dir.as_ref(), "etws_loader")?;
|
||||||
|
|
||||||
|
this.registered_plugins.insert(id, plugin);
|
||||||
|
|
||||||
|
Ok(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_plugin(&self, id: &PluginId) -> Option<&DataLoaderPlugin_TO<'static, RBox<()>>> {
|
||||||
|
self.registered_plugins.get(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_plugin_by_name(
|
||||||
|
&self,
|
||||||
|
name: &str,
|
||||||
|
) -> Option<&DataLoaderPlugin_TO<'static, RBox<()>>> {
|
||||||
|
self.registered_plugins
|
||||||
|
.iter()
|
||||||
|
.find(|(id, _)| id.named == name)
|
||||||
|
.map(|(_, p)| p)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn try_load_data<P: AsRef<Path>>(&self, path: P) -> Result<Vec<Data>, DataError> {
|
||||||
|
let path: &Path = path.as_ref();
|
||||||
|
let path_rstr = RStr::from(path.to_str().unwrap());
|
||||||
|
|
||||||
|
for plugin in self.registered_plugins.values() {
|
||||||
|
if let ROk(result) = plugin.load(path_rstr) {
|
||||||
|
return Ok(result.into_iter().map(|v| v.into()).collect());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(DataError::FormatError)
|
||||||
|
}
|
||||||
|
}
|
||||||
18
mp_core/src/utils/color_tools.rs
Normal file
18
mp_core/src/utils/color_tools.rs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
pub fn hex_to_rgba_u8(hex: &str) -> Result<[u8; 4], String> {
|
||||||
|
let hex = hex.trim_start_matches('#');
|
||||||
|
|
||||||
|
if hex.len() != 6 && hex.len() != 8 {
|
||||||
|
return Err("Hex color should be in #RRGGBB or #RRGGBBAA format".to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
let r = u8::from_str_radix(&hex[0..2], 16).map_err(|e| e.to_string())?;
|
||||||
|
let g = u8::from_str_radix(&hex[2..4], 16).map_err(|e| e.to_string())?;
|
||||||
|
let b = u8::from_str_radix(&hex[4..6], 16).map_err(|e| e.to_string())?;
|
||||||
|
let a = if hex.len() == 8 {
|
||||||
|
u8::from_str_radix(&hex[6..8], 16).map_err(|e| e.to_string())?
|
||||||
|
} else {
|
||||||
|
255 // 默认不透明
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok([r, g, b, a])
|
||||||
|
}
|
||||||
1
mp_core/src/utils/mod.rs
Normal file
1
mp_core/src/utils/mod.rs
Normal file
@ -0,0 +1 @@
|
|||||||
|
pub mod color_tools;
|
||||||
263
mp_core/statics/config.toml
Normal file
263
mp_core/statics/config.toml
Normal file
@ -0,0 +1,263 @@
|
|||||||
|
[common]
|
||||||
|
background = "Terrain"
|
||||||
|
path = "resources/alts.png"
|
||||||
|
plugins = "loaders"
|
||||||
|
|
||||||
|
[[cmap]]
|
||||||
|
type = "DBZ"
|
||||||
|
levels = [0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75]
|
||||||
|
colors = [
|
||||||
|
"#aaaaaa",
|
||||||
|
"#0022ff",
|
||||||
|
"#01a0f6",
|
||||||
|
"#00ecec",
|
||||||
|
"#00d800",
|
||||||
|
"#019000",
|
||||||
|
"#ffff00",
|
||||||
|
"#e7c000",
|
||||||
|
"#ff9000",
|
||||||
|
"#ff0000",
|
||||||
|
"#d60000",
|
||||||
|
"#c00000",
|
||||||
|
"#ff00f0",
|
||||||
|
"#9600b4",
|
||||||
|
"#ad90f0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[cmap]]
|
||||||
|
type = "VEL"
|
||||||
|
levels = [
|
||||||
|
-90,
|
||||||
|
-45,
|
||||||
|
-35,
|
||||||
|
-27,
|
||||||
|
-20,
|
||||||
|
-15,
|
||||||
|
-10,
|
||||||
|
-5,
|
||||||
|
-1,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
5,
|
||||||
|
10,
|
||||||
|
15,
|
||||||
|
20,
|
||||||
|
27,
|
||||||
|
1000,
|
||||||
|
]
|
||||||
|
colors = [
|
||||||
|
"#9fffff",
|
||||||
|
"#00e0ff",
|
||||||
|
"#0080ff",
|
||||||
|
"#320096",
|
||||||
|
"#00fb90",
|
||||||
|
"#00bb90",
|
||||||
|
"#008f00",
|
||||||
|
"#cdc09f",
|
||||||
|
"#000000",
|
||||||
|
"#f88700",
|
||||||
|
"#ffcf00",
|
||||||
|
"#ffff00",
|
||||||
|
"#ae0000",
|
||||||
|
"#d07000",
|
||||||
|
"#dd0000",
|
||||||
|
"#ff0000",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[cmap]]
|
||||||
|
type = "SW"
|
||||||
|
colors = [
|
||||||
|
"#E0E0E0",
|
||||||
|
"#7CE0E0",
|
||||||
|
"#00E0E0",
|
||||||
|
"#00B0B0",
|
||||||
|
"#00FEFE",
|
||||||
|
"#00C400",
|
||||||
|
"#008000",
|
||||||
|
"#FEFE00",
|
||||||
|
"#FED200",
|
||||||
|
"#FE7C00",
|
||||||
|
"#FEB0B0",
|
||||||
|
"#FE5858",
|
||||||
|
"#FE0000",
|
||||||
|
"#FEFEFE",
|
||||||
|
]
|
||||||
|
levels = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
|
||||||
|
|
||||||
|
[[cmap]]
|
||||||
|
type = "CC"
|
||||||
|
colors = [
|
||||||
|
"#003CFF",
|
||||||
|
"#00EFEF",
|
||||||
|
"#00BABF",
|
||||||
|
"#00837D",
|
||||||
|
"#008938",
|
||||||
|
"#00B729",
|
||||||
|
"#00DA0D",
|
||||||
|
"#00FF00",
|
||||||
|
"#FFFF3B",
|
||||||
|
"#FFF000",
|
||||||
|
"#FFC600",
|
||||||
|
"#FFA500",
|
||||||
|
"#FF7200",
|
||||||
|
"#FF1F00",
|
||||||
|
"#C10000",
|
||||||
|
"#D400AA",
|
||||||
|
]
|
||||||
|
levels = [
|
||||||
|
0,
|
||||||
|
0.1,
|
||||||
|
0.3,
|
||||||
|
0.5,
|
||||||
|
0.6,
|
||||||
|
0.7,
|
||||||
|
0.8,
|
||||||
|
0.85,
|
||||||
|
0.9,
|
||||||
|
0.92,
|
||||||
|
0.94,
|
||||||
|
0.95,
|
||||||
|
0.96,
|
||||||
|
0.97,
|
||||||
|
0.98,
|
||||||
|
0.99,
|
||||||
|
]
|
||||||
|
|
||||||
|
[[cmap]]
|
||||||
|
type = "KDP"
|
||||||
|
colors = [
|
||||||
|
"#00FFFF",
|
||||||
|
"#00EFEF",
|
||||||
|
"#00A8AC",
|
||||||
|
"#B4B4B4",
|
||||||
|
"#B4B4B4",
|
||||||
|
"#00C027",
|
||||||
|
"#00E80A",
|
||||||
|
"#24FF24",
|
||||||
|
"#FFFF1E",
|
||||||
|
"#FFE600",
|
||||||
|
"#FFBC00",
|
||||||
|
"#FF9800",
|
||||||
|
"#FF5E00",
|
||||||
|
"#F20F00",
|
||||||
|
"#BB003A",
|
||||||
|
"#DD009C",
|
||||||
|
"#FF00FF",
|
||||||
|
]
|
||||||
|
levels = [
|
||||||
|
-0.8,
|
||||||
|
-0.4,
|
||||||
|
-0.2,
|
||||||
|
-0.1,
|
||||||
|
0.1,
|
||||||
|
0.15,
|
||||||
|
0.22,
|
||||||
|
0.33,
|
||||||
|
0.5,
|
||||||
|
0.75,
|
||||||
|
1.1,
|
||||||
|
1.7,
|
||||||
|
2.4,
|
||||||
|
3.1,
|
||||||
|
7,
|
||||||
|
20,
|
||||||
|
]
|
||||||
|
|
||||||
|
[[cmap]]
|
||||||
|
type = "ZDR"
|
||||||
|
colors = [
|
||||||
|
"#464646",
|
||||||
|
"#505050",
|
||||||
|
"#5A5A5A",
|
||||||
|
"#646464",
|
||||||
|
"#6E6E6E",
|
||||||
|
"#787878",
|
||||||
|
"#828282",
|
||||||
|
"#8C8C8C",
|
||||||
|
"#969696",
|
||||||
|
"#AFAFAF",
|
||||||
|
"#C8C8C8",
|
||||||
|
"#DCF0DC",
|
||||||
|
"#00C027",
|
||||||
|
"#00E80A",
|
||||||
|
"#24FF24",
|
||||||
|
"#FFFF1E",
|
||||||
|
"#FFF20F",
|
||||||
|
"#FFE600",
|
||||||
|
"#FFBC00",
|
||||||
|
"#FF9800",
|
||||||
|
"#FF5E00",
|
||||||
|
"#FFFF00",
|
||||||
|
"#F20F00",
|
||||||
|
"#BB003A",
|
||||||
|
"#DD009C",
|
||||||
|
"#FF00FF",
|
||||||
|
]
|
||||||
|
levels = [
|
||||||
|
-5,
|
||||||
|
-4.5,
|
||||||
|
-4,
|
||||||
|
-3.5,
|
||||||
|
-3,
|
||||||
|
-2.5,
|
||||||
|
-2,
|
||||||
|
-1.5,
|
||||||
|
-1,
|
||||||
|
-0.5,
|
||||||
|
0,
|
||||||
|
0.5,
|
||||||
|
1,
|
||||||
|
1.5,
|
||||||
|
2,
|
||||||
|
2.5,
|
||||||
|
3,
|
||||||
|
3.5,
|
||||||
|
4,
|
||||||
|
4.5,
|
||||||
|
5,
|
||||||
|
5.5,
|
||||||
|
6,
|
||||||
|
6.5,
|
||||||
|
7,
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
[[cmap]]
|
||||||
|
type = "VIL"
|
||||||
|
levels = [
|
||||||
|
0.1,
|
||||||
|
1,
|
||||||
|
2.5,
|
||||||
|
5,
|
||||||
|
7.5,
|
||||||
|
10,
|
||||||
|
10.25,
|
||||||
|
15,
|
||||||
|
20,
|
||||||
|
25,
|
||||||
|
30,
|
||||||
|
35,
|
||||||
|
40,
|
||||||
|
45,
|
||||||
|
50,
|
||||||
|
55,
|
||||||
|
104,
|
||||||
|
]
|
||||||
|
colors = [
|
||||||
|
'#484892',
|
||||||
|
'#01a0f6',
|
||||||
|
'#00ecec',
|
||||||
|
'#01ff00',
|
||||||
|
'#00c800',
|
||||||
|
'#019000',
|
||||||
|
'#ffff00',
|
||||||
|
'#e7c000',
|
||||||
|
'#ff9000',
|
||||||
|
'#ff0000',
|
||||||
|
'#d60000',
|
||||||
|
'#c00000',
|
||||||
|
'#ff00f0',
|
||||||
|
'#ad90f0',
|
||||||
|
'#780084',
|
||||||
|
'#d8af97',
|
||||||
|
]
|
||||||
BIN
radarg_plugin_interface/.DS_Store
vendored
Normal file
BIN
radarg_plugin_interface/.DS_Store
vendored
Normal file
Binary file not shown.
422
radarg_plugin_interface/Cargo.lock
generated
Normal file
422
radarg_plugin_interface/Cargo.lock
generated
Normal file
@ -0,0 +1,422 @@
|
|||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "abi_stable"
|
||||||
|
version = "0.11.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "69d6512d3eb05ffe5004c59c206de7f99c34951504056ce23fc953842f12c445"
|
||||||
|
dependencies = [
|
||||||
|
"abi_stable_derive",
|
||||||
|
"abi_stable_shared",
|
||||||
|
"const_panic",
|
||||||
|
"core_extensions",
|
||||||
|
"crossbeam-channel",
|
||||||
|
"generational-arena",
|
||||||
|
"libloading",
|
||||||
|
"lock_api",
|
||||||
|
"parking_lot",
|
||||||
|
"paste",
|
||||||
|
"repr_offset",
|
||||||
|
"rustc_version",
|
||||||
|
"serde",
|
||||||
|
"serde_derive",
|
||||||
|
"serde_json",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "abi_stable_derive"
|
||||||
|
version = "0.11.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d7178468b407a4ee10e881bc7a328a65e739f0863615cca4429d43916b05e898"
|
||||||
|
dependencies = [
|
||||||
|
"abi_stable_shared",
|
||||||
|
"as_derive_utils",
|
||||||
|
"core_extensions",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"rustc_version",
|
||||||
|
"syn 1.0.109",
|
||||||
|
"typed-arena",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "abi_stable_shared"
|
||||||
|
version = "0.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b2b5df7688c123e63f4d4d649cba63f2967ba7f7861b1664fca3f77d3dad2b63"
|
||||||
|
dependencies = [
|
||||||
|
"core_extensions",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "as_derive_utils"
|
||||||
|
version = "0.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ff3c96645900a44cf11941c111bd08a6573b0e2f9f69bc9264b179d8fae753c4"
|
||||||
|
dependencies = [
|
||||||
|
"core_extensions",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 1.0.109",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "autocfg"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "1.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cfg-if"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "const_panic"
|
||||||
|
version = "0.2.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6051f239ecec86fde3410901ab7860d458d160371533842974fc61f96d15879b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "core_extensions"
|
||||||
|
version = "1.5.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "92c71dc07c9721607e7a16108336048ee978c3a8b129294534272e8bac96c0ee"
|
||||||
|
dependencies = [
|
||||||
|
"core_extensions_proc_macros",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "core_extensions_proc_macros"
|
||||||
|
version = "1.5.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "69f3b219d28b6e3b4ac87bc1fc522e0803ab22e055da177bff0068c4150c61a6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-channel"
|
||||||
|
version = "0.5.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "176dc175b78f56c0f321911d9c8eb2b77a78a4860b9c19db83835fea1a46649b"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-utils"
|
||||||
|
version = "0.8.19"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "generational-arena"
|
||||||
|
version = "0.2.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "877e94aff08e743b651baaea359664321055749b398adff8740a7399af7796e7"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itoa"
|
||||||
|
version = "1.0.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.152"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libloading"
|
||||||
|
version = "0.7.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lock_api"
|
||||||
|
version = "0.4.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"scopeguard",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "parking_lot"
|
||||||
|
version = "0.12.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
|
||||||
|
dependencies = [
|
||||||
|
"lock_api",
|
||||||
|
"parking_lot_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "parking_lot_core"
|
||||||
|
version = "0.9.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"redox_syscall",
|
||||||
|
"smallvec",
|
||||||
|
"windows-targets",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "paste"
|
||||||
|
version = "1.0.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.78"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.35"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "radarg_plugin_interface"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"abi_stable",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "redox_syscall"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "repr_offset"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fb1070755bd29dffc19d0971cab794e607839ba2ef4b69a9e6fbc8733c1b72ea"
|
||||||
|
dependencies = [
|
||||||
|
"tstr",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustc_version"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
|
||||||
|
dependencies = [
|
||||||
|
"semver",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ryu"
|
||||||
|
version = "1.0.16"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "scopeguard"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "semver"
|
||||||
|
version = "1.0.21"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde"
|
||||||
|
version = "1.0.196"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32"
|
||||||
|
dependencies = [
|
||||||
|
"serde_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_derive"
|
||||||
|
version = "1.0.196"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.48",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_json"
|
||||||
|
version = "1.0.112"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4d1bd37ce2324cf3bf85e5a25f96eb4baf0d5aa6eba43e7ae8958870c4ec48ed"
|
||||||
|
dependencies = [
|
||||||
|
"itoa",
|
||||||
|
"ryu",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "smallvec"
|
||||||
|
version = "1.13.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "1.0.109"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "2.0.48"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tstr"
|
||||||
|
version = "0.2.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cca3264971090dec0feef3b455a3c178f02762f7550cf4592991ac64b3be2d7e"
|
||||||
|
dependencies = [
|
||||||
|
"tstr_proc_macros",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tstr_proc_macros"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e78122066b0cb818b8afd08f7ed22f7fdbc3e90815035726f0840d0d26c0747a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "typed-arena"
|
||||||
|
version = "2.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-ident"
|
||||||
|
version = "1.0.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi"
|
||||||
|
version = "0.3.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||||
|
dependencies = [
|
||||||
|
"winapi-i686-pc-windows-gnu",
|
||||||
|
"winapi-x86_64-pc-windows-gnu",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-i686-pc-windows-gnu"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-x86_64-pc-windows-gnu"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-targets"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
|
||||||
|
dependencies = [
|
||||||
|
"windows_aarch64_gnullvm",
|
||||||
|
"windows_aarch64_msvc",
|
||||||
|
"windows_i686_gnu",
|
||||||
|
"windows_i686_msvc",
|
||||||
|
"windows_x86_64_gnu",
|
||||||
|
"windows_x86_64_gnullvm",
|
||||||
|
"windows_x86_64_msvc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_gnullvm"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_msvc"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnu"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_msvc"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnu"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnullvm"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_msvc"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
|
||||||
11
radarg_plugin_interface/Cargo.toml
Normal file
11
radarg_plugin_interface/Cargo.toml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
[package]
|
||||||
|
name = "radarg_plugin_interface"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["tsuki <tsuki@keitsuki.top>"]
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
abi_stable = "0.11.3"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
impls = []
|
||||||
BIN
radarg_plugin_interface/src/.DS_Store
vendored
Normal file
BIN
radarg_plugin_interface/src/.DS_Store
vendored
Normal file
Binary file not shown.
48
radarg_plugin_interface/src/error.rs
Normal file
48
radarg_plugin_interface/src/error.rs
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
use abi_stable::{
|
||||||
|
std_types::{RBoxError, RVec},
|
||||||
|
StableAbi,
|
||||||
|
};
|
||||||
|
|
||||||
|
use std::{
|
||||||
|
error::Error as ErrorTrait,
|
||||||
|
fmt::{self, Display},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[repr(u8)]
|
||||||
|
#[derive(Debug, StableAbi)]
|
||||||
|
pub enum Error {
|
||||||
|
UnsupportedFormat,
|
||||||
|
FileError(RBoxError),
|
||||||
|
Custom(RBoxError),
|
||||||
|
/// A list of errors.
|
||||||
|
Many(RVec<Error>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for Error {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
Error::UnsupportedFormat => {
|
||||||
|
writeln!(
|
||||||
|
f,
|
||||||
|
"Plugin ooes not support this command:\n\
|
||||||
|
\t\n\
|
||||||
|
Because of this error:\n\n\
|
||||||
|
Supported commands:\
|
||||||
|
"
|
||||||
|
)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
Error::Custom(e) => Display::fmt(e, f),
|
||||||
|
Error::Many(list) => {
|
||||||
|
for e in list {
|
||||||
|
writeln!(f, "{}", e)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
_ => Ok(()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ErrorTrait for Error {}
|
||||||
143
radarg_plugin_interface/src/lib.rs
Normal file
143
radarg_plugin_interface/src/lib.rs
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
use abi_stable::{
|
||||||
|
declare_root_module_statics,
|
||||||
|
library::RootModule,
|
||||||
|
package_version_strings, sabi_trait,
|
||||||
|
sabi_types::VersionStrings,
|
||||||
|
std_types::{RBox, RCowStr, ROption, RResult, RStr, RString, RVec},
|
||||||
|
StableAbi,
|
||||||
|
};
|
||||||
|
mod error;
|
||||||
|
pub use self::error::Error;
|
||||||
|
|
||||||
|
pub mod utils;
|
||||||
|
|
||||||
|
/// The identifier for a plugin.
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, StableAbi, Hash)]
|
||||||
|
pub struct PluginId {
|
||||||
|
pub named: RCowStr<'static>,
|
||||||
|
pub instance: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Plugin Can be loaded from a file path
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Clone, Debug, StableAbi)]
|
||||||
|
pub enum LoadedData {
|
||||||
|
RadarGridData(RadarGridData),
|
||||||
|
JsonData,
|
||||||
|
PlainText(RString),
|
||||||
|
Binary(RVec<u8>),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(StableAbi, Clone, Debug)]
|
||||||
|
pub struct RadarGridData {
|
||||||
|
pub data: VecResult,
|
||||||
|
pub info: GridDataInfo,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(StableAbi, Clone, Debug)]
|
||||||
|
pub enum VecResult {
|
||||||
|
I64(RVec<i64>),
|
||||||
|
F64(RVec<f64>),
|
||||||
|
I32(RVec<i32>),
|
||||||
|
I16(RVec<i16>),
|
||||||
|
F32(RVec<f32>),
|
||||||
|
U64(RVec<u64>),
|
||||||
|
U32(RVec<u32>),
|
||||||
|
Bool(RVec<bool>),
|
||||||
|
I8(RVec<i8>),
|
||||||
|
U8(RVec<u8>),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(StableAbi, Clone, Debug)]
|
||||||
|
pub struct GridDataInfo {
|
||||||
|
pub shape: RVec<usize>,
|
||||||
|
pub dimensions: RVec<RVec<f64>>,
|
||||||
|
pub dimension_names: RVec<RString>,
|
||||||
|
pub fill_value: f64,
|
||||||
|
pub datetime: ROption<i64>,
|
||||||
|
pub value_description: ROption<RString>,
|
||||||
|
pub value_name: RString,
|
||||||
|
pub maybe_probe_data_type: ROption<ProbeDataType>,
|
||||||
|
pub dimension_description: RString,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(StableAbi, Clone, Copy, Debug)]
|
||||||
|
pub enum ProbeDataType {
|
||||||
|
// Single
|
||||||
|
R,
|
||||||
|
V,
|
||||||
|
SW,
|
||||||
|
CC,
|
||||||
|
ZDR,
|
||||||
|
PHIDP,
|
||||||
|
KDP,
|
||||||
|
HCA,
|
||||||
|
DBZ,
|
||||||
|
QPE,
|
||||||
|
QPF,
|
||||||
|
VIL,
|
||||||
|
OHP,
|
||||||
|
THP,
|
||||||
|
ET,
|
||||||
|
EB,
|
||||||
|
// Unknown
|
||||||
|
Unknown,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Debug, StableAbi)]
|
||||||
|
#[sabi(impl_InterfaceType(Sync, Send, Debug))]
|
||||||
|
pub struct PluginInfo {
|
||||||
|
pub plugin_type: RStr<'static>,
|
||||||
|
pub name: RStr<'static>,
|
||||||
|
pub version: RStr<'static>,
|
||||||
|
pub author: RStr<'static>,
|
||||||
|
pub description: ROption<RStr<'static>>,
|
||||||
|
pub url: ROption<RStr<'static>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type PluginType = DataLoaderPlugin_TO<'static, RBox<()>>;
|
||||||
|
|
||||||
|
#[sabi_trait]
|
||||||
|
pub trait DataLoaderPlugin: Send + Sync {
|
||||||
|
fn load(&self, path: RStr<'_>) -> RResult<RVec<LoadedData>, Error>;
|
||||||
|
fn plugin_id(&self) -> &PluginId;
|
||||||
|
fn plugin_info(&self) -> PluginInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The root module of a`plugin` dynamic library.
|
||||||
|
///
|
||||||
|
/// To load this module,
|
||||||
|
/// call <PluginMod as RootModule>::load_from_directory(some_directory_path)
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(StableAbi)]
|
||||||
|
#[sabi(kind(Prefix(prefix_ref = PluginMod_Ref)))]
|
||||||
|
#[sabi(missing_field(panic))]
|
||||||
|
pub struct PluginMod {
|
||||||
|
/// Constructs the plugin.
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// The `#[sabi(last_prefix_field)]` attribute here means that this is the last field in this struct
|
||||||
|
/// that was defined in the first compatible version of the library
|
||||||
|
/// (0.1.0, 0.2.0, 0.3.0, 1.0.0, 2.0.0 ,etc),
|
||||||
|
/// requiring new fields to always be added below preexisting ones.
|
||||||
|
///
|
||||||
|
/// The `#[sabi(last_prefix_field)]` attribute would stay on this field until the library
|
||||||
|
/// bumps its "major" version,
|
||||||
|
/// at which point it would be moved to the last field at the time.
|
||||||
|
///
|
||||||
|
#[sabi(last_prefix_field)]
|
||||||
|
pub new: extern "C" fn(PluginId) -> RResult<PluginType, Error>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RootModule for PluginMod_Ref {
|
||||||
|
declare_root_module_statics! {PluginMod_Ref}
|
||||||
|
const BASE_NAME: &'static str = "data_loader_plugin";
|
||||||
|
const NAME: &'static str = "data_loader_plugin";
|
||||||
|
const VERSION_STRINGS: VersionStrings = package_version_strings!();
|
||||||
|
}
|
||||||
1
radarg_plugin_interface/src/utils.rs
Normal file
1
radarg_plugin_interface/src/utils.rs
Normal file
@ -0,0 +1 @@
|
|||||||
|
|
||||||
Loading…
Reference in New Issue
Block a user