diff --git a/Cargo.lock b/Cargo.lock index a9a07ab..6f0218b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -732,7 +732,6 @@ dependencies = [ "iana-time-zone", "js-sys", "num-traits", - "serde", "wasm-bindgen", "windows-targets 0.52.6", ] @@ -1323,25 +1322,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "etws_loader" -version = "0.1.0" -dependencies = [ - "abi_stable", - "anyhow", - "byteorder", - "chrono", - "flate2", - "geo 0.28.0", - "nom", - "nom-derive", - "num-traits", - "radarg_plugin_interface", - "serde", - "serde_json", - "thiserror", -] - [[package]] name = "euclid" version = "0.22.10" diff --git a/Cargo.toml b/Cargo.toml index d8de7e8..9cabdf7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,6 @@ [workspace] members = [ - "etws_loader", "radarg_plugin_interface", "geo-macros", "radar-g", diff --git a/etws_loader/src/lib.rs b/etws_loader/src/lib.rs deleted file mode 100644 index b01d402..0000000 --- a/etws_loader/src/lib.rs +++ /dev/null @@ -1,188 +0,0 @@ -mod error; -use geo::{algorithm::haversine_destination::HaversineDestination, Point}; -mod parser; -use abi_stable::{ - export_root_module, - prefix_type::PrefixTypeTrait, - 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, Error> where { - if let Ok(record) = Record::parse_from_path(path.to_string()) { - 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::>(), - ); - let dimension_names = convert_vec_to_rvec( - b.info - .dimension_des - .into_iter() - .map(RString::from) - .collect::>(), - ); - - 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" => 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::>(); - - ROk(result) - } else { - RErr(Error::UnsupportedFormat) - } - } - - 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(raw: impl Iterator) -> RVec { - RVec::from(raw.collect::>()) -} - -fn convert_vec_to_rvec(raw: Vec) -> RVec { - RVec::from(raw) -} - -fn convert_nested_vec_to_rvec(raw: Vec>) -> RVec> { - RVec::from(raw.into_iter().map(RVec::from).collect::>()) -} - -#[sabi_extern_fn] -pub fn new(plugin_id: PluginId) -> RResult { - 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(); - } -} diff --git a/gi/src/pg/app.rs b/gi/src/pg/app.rs index f08d7f7..04d1ff4 100644 --- a/gi/src/pg/app.rs +++ b/gi/src/pg/app.rs @@ -61,13 +61,17 @@ impl App { &mut self.context.programs } - pub fn load_data( - &mut self, - data: &Vec, - setting: &radarg_core::config::Setting, - ) -> Result { - self.program().load_data(data, setting) + pub fn supported_modules(&mut self) -> Vec { + self.program().supported_modules() } + + // pub fn load_data( + // &mut self, + // data: &Vec, + // setting: &radarg_core::config::Setting, + // ) -> Result { + // self.program().load_data(data, setting) + // } } pub struct Context { diff --git a/gi/src/pg/mod.rs b/gi/src/pg/mod.rs index 867594e..07c14b4 100644 --- a/gi/src/pg/mod.rs +++ b/gi/src/pg/mod.rs @@ -77,20 +77,20 @@ impl Programs { PPIModule::new(&self.gl, &mut self._ppi, &mut self._text, &mut self._line) } - pub fn load_data( - &mut self, - data: &Vec, - setting: &radarg_core::config::Setting, - ) -> Result { - let data = &data[0]; - match data { - Data::RadarGridData(ref grid_data) => { - self.ppi().load_data(grid_data, setting).map(|v| v.into()) - } - _ => Err(Error::InvalidDataType), - } + pub fn supported_modules(&mut self) -> Vec { + vec![Modules::PPI(self.ppi())] } + // pub fn load_data( + // &mut self, + // data: &Vec, + // setting: &radarg_core::config::Setting, + // ) -> Result> { + // data.iter() + // .map(|d| self.ppi().load_data(, setting).map(|v| v.into())) + // .collect() + // } + pub fn draw_modules( &mut self, modules: &mut ModulePackage, @@ -108,7 +108,13 @@ impl Programs { } macro_rules! impl_module_package { - ($({$t:ty => $b: tt | $c: ty}),+) => { + ($({$t:ty => $b: tt | $module:tt | $c: ty}),+) => { + + pub enum Modules<'b, 'gl: 'b>{ + $( + $b($module<'b, 'gl>), + )+ + } #[derive(Debug)] pub enum _ModulePackage { @@ -203,7 +209,7 @@ macro_rules! impl_module_package { } impl_module_package!( - {PPIPackage => PPI | PPIModuleConfigComponent} + {PPIPackage => PPI | PPIModule | PPIModuleConfigComponent} ); impl ModulePackage { diff --git a/gi/src/pg/modules/ppi.rs b/gi/src/pg/modules/ppi.rs index ab2679d..7a92c9b 100644 --- a/gi/src/pg/modules/ppi.rs +++ b/gi/src/pg/modules/ppi.rs @@ -438,7 +438,14 @@ impl SimpleComponent for PPIModuleConfigComponent { let layer = this.value() as usize; config_ref.borrow_mut().set_layer(layer); } + }, + gtk::Button { + set_label: "Refresh", + connect_clicked[sender] => move |_| { + sender.output(OutputMsg::Refresh); + } } + } } diff --git a/gi/src/shaders/colormap.rs b/gi/src/shaders/colormap.rs index 1dc7825..3cb2343 100644 --- a/gi/src/shaders/colormap.rs +++ b/gi/src/shaders/colormap.rs @@ -32,7 +32,7 @@ impl ColorMap { float invalid = colormap_conf.w; - if (abs(value - invalid) < 0.0001) { + if (abs(value - invalid) < 0.0001 || value < vmin || value > vmax) { return vec4(0.0, 0.0, 0.0, 0.0); } diff --git a/loaders/Cargo.lock b/loaders/Cargo.lock new file mode 100644 index 0000000..ad2c6cf --- /dev/null +++ b/loaders/Cargo.lock @@ -0,0 +1,1383 @@ +# 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 = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + +[[package]] +name = "aes" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + +[[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.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" + +[[package]] +name = "approx" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6" +dependencies = [ + "num-traits", +] + +[[package]] +name = "arbitrary" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110" +dependencies = [ + "derive_arbitrary", +] + +[[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.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "bytemuck" +version = "1.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773d90827bc3feecfb67fab12e24de0749aad83c74b9504ecde46237b5cd24e2" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bzip2" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdb116a6ef3f6c3698828873ad02c3014b3c85cadb88496095628e3ef1e347f8" +dependencies = [ + "bzip2-sys", + "libc", +] + +[[package]] +name = "bzip2-sys" +version = "0.1.11+1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc" +dependencies = [ + "cc", + "libc", + "pkg-config", +] + +[[package]] +name = "cc" +version = "1.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57b6a275aa2903740dc87da01c62040406b8812552e97129a63ea8850a17c6e6" +dependencies = [ + "jobserver", + "libc", + "shlex", +] + +[[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.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "js-sys", + "num-traits", + "serde", + "wasm-bindgen", + "windows-targets", +] + +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", +] + +[[package]] +name = "const_panic" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7782af8f90fe69a4bb41e460abe1727d493403d8b2cc43201a3a3e906b24379f" + +[[package]] +name = "constant_time_eq" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[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 = "cpufeatures" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51e852e6dc9a5bed1fae92dd2375037bf2b768725bf3be87811edee3249d09ad" +dependencies = [ + "libc", +] + +[[package]] +name = "crc" +version = "3.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" +dependencies = [ + "crc-catalog", +] + +[[package]] +name = "crc-catalog" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" + +[[package]] +name = "crc32fast" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "deflate64" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da692b8d1080ea3045efaab14434d40468c3d8657e42abddfffca87b428f4c1b" + +[[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", +] + +[[package]] +name = "derive_arbitrary" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.76", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", + "subtle", +] + +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.76", +] + +[[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.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "etws_loader" +version = "0.1.0" +dependencies = [ + "abi_stable", + "anyhow", + "bytemuck", + "byteorder", + "chrono", + "flate2", + "geo", + "nom", + "nom-derive", + "num-traits", + "radarg_plugin_interface", + "serde", + "serde_json", + "thiserror", + "zip", +] + +[[package]] +name = "flate2" +version = "1.0.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "324a1be68054ef05ad64b861cc9eaf1d623d2d8cb25b4bf2cb9cdd902b4bf253" +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 = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[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 = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[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 = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +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 = "indexmap" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93ead53efc7ea8ed3cfb0c79fc8023fbb782a5432b52830b6518941cebe6505c" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "inout" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +dependencies = [ + "generic-array", +] + +[[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.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "jobserver" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" +dependencies = [ + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "libc" +version = "0.2.158" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" + +[[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.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "lockfree-object-pool" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9374ef4228402d4b7e403e5838cb880d9ee663314b0a900d5a6aabf0c213552e" + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "lzma-rs" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "297e814c836ae64db86b36cf2a557ba54368d03f6afcd7d947c266692f71115e" +dependencies = [ + "byteorder", + "crc", +] + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[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.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +dependencies = [ + "adler2", +] + +[[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-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +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.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "pbkdf2" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" +dependencies = [ + "digest", + "hmac", +] + +[[package]] +name = "pkg-config" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "proc-macro2" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "radarg_plugin_interface" +version = "0.1.0" +dependencies = [ + "abi_stable", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "redox_syscall" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" +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.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[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.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" + +[[package]] +name = "serde" +version = "1.0.209" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99fce0ffe7310761ca6bf9faf5115afbc19688edd00171d81b1bb1b116c63e09" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.209" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.76", +] + +[[package]] +name = "serde_json" +version = "1.0.127" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8043c06d9f82bd7271361ed64f415fe5e12a77fdb52e573e7f06a516dea329ad" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "simd-adler32" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "spade" +version = "2.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bd14cf9e23b5241e1b1289ed3b9afc7746c95ead8df52d9254f5ed2d40c561b" +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 = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[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.76" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578e081a14e0cefc3279b0472138c513f37b41a08d5a3cca9b6e4e8ceb6cd525" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "1.0.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.76", +] + +[[package]] +name = "time" +version = "0.3.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" +dependencies = [ + "deranged", + "num-conv", + "powerfmt", + "serde", + "time-core", +] + +[[package]] +name = "time-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + +[[package]] +name = "tstr" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f8e0294f14baae476d0dd0a2d780b2e24d66e349a9de876f5126777a37bdba7" +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 = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[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.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" +dependencies = [ + "cfg-if", + "once_cell", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.76", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.76", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" + +[[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", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.76", +] + +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.76", +] + +[[package]] +name = "zip" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc5e4288ea4057ae23afc69a4472434a87a2495cafce6632fd1c4ec9f5cf3494" +dependencies = [ + "aes", + "arbitrary", + "bzip2", + "constant_time_eq", + "crc32fast", + "crossbeam-utils", + "deflate64", + "displaydoc", + "flate2", + "hmac", + "indexmap", + "lzma-rs", + "memchr", + "pbkdf2", + "rand", + "sha1", + "thiserror", + "time", + "zeroize", + "zopfli", + "zstd", +] + +[[package]] +name = "zopfli" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5019f391bac5cf252e93bbcc53d039ffd62c7bfb7c150414d61369afe57e946" +dependencies = [ + "bumpalo", + "crc32fast", + "lockfree-object-pool", + "log", + "once_cell", + "simd-adler32", +] + +[[package]] +name = "zstd" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcf2b778a664581e31e389454a7072dab1647606d44f7feea22cd5abb9c9f3f9" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "7.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54a3ab4db68cea366acc5c897c7b4d4d1b8994a9cd6e6f841f8964566a419059" +dependencies = [ + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.13+zstd.1.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38ff0f21cfee8f97d94cef41359e0c89aa6113028ab0291aa8ca0038995a95aa" +dependencies = [ + "cc", + "pkg-config", +] diff --git a/loaders/Cargo.toml b/loaders/Cargo.toml new file mode 100644 index 0000000..bb725eb --- /dev/null +++ b/loaders/Cargo.toml @@ -0,0 +1,2 @@ +[workspace] +members = ["etws_loader"] diff --git a/etws_loader/Cargo.lock b/loaders/etws_loader/Cargo.lock similarity index 100% rename from etws_loader/Cargo.lock rename to loaders/etws_loader/Cargo.lock diff --git a/etws_loader/Cargo.toml b/loaders/etws_loader/Cargo.toml similarity index 71% rename from etws_loader/Cargo.toml rename to loaders/etws_loader/Cargo.toml index bea6ff5..95abc83 100644 --- a/etws_loader/Cargo.toml +++ b/loaders/etws_loader/Cargo.toml @@ -7,8 +7,9 @@ edition = "2021" [dependencies] abi_stable = "*" anyhow = "1.0.79" +bytemuck = "1.17.1" byteorder = "1.5.0" -chrono = {version="0.4.33", features=["serde"]} +chrono = { version = "0.4.33", features = ["serde"] } flate2 = "1.0.28" geo = "0.28.0" nom = "7.1.3" @@ -17,11 +18,12 @@ num-traits = "0.2.17" serde = { version = "1.0.196", features = ["derive"] } serde_json = "1.0.112" thiserror = "1.0.56" +zip = "2.2.0" [dependencies.radarg_plugin_interface] -version="0.1" -path="../radarg_plugin_interface" +version = "0.1" +path = "../../radarg_plugin_interface" [lib] name = "etws_loader" -crate-type = ["cdylib",'rlib'] +crate-type = ["cdylib", 'rlib'] diff --git a/loaders/etws_loader/raw.py b/loaders/etws_loader/raw.py new file mode 100644 index 0000000..14e6534 --- /dev/null +++ b/loaders/etws_loader/raw.py @@ -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 diff --git a/etws_loader/src/error.rs b/loaders/etws_loader/src/error.rs similarity index 100% rename from etws_loader/src/error.rs rename to loaders/etws_loader/src/error.rs diff --git a/loaders/etws_loader/src/lib.rs b/loaders/etws_loader/src/lib.rs new file mode 100644 index 0000000..178e685 --- /dev/null +++ b/loaders/etws_loader/src/lib.rs @@ -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, 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::>(), + ); + let dimension_names = convert_vec_to_rvec( + b.info + .dimension_des + .into_iter() + .map(RString::from) + .collect::>(), + ); + + 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" => 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::>(); + 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" => DBZ}, + { "VIL" => VIL}, + { "EB" => EB}, + { "V" => 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::>(); + + 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(raw: impl Iterator) -> RVec { + RVec::from(raw.collect::>()) +} + +fn convert_vec_to_rvec(raw: Vec) -> RVec { + RVec::from(raw) +} + +fn convert_nested_vec_to_rvec(raw: Vec>) -> RVec> { + RVec::from(raw.into_iter().map(RVec::from).collect::>()) +} + +#[sabi_extern_fn] +pub fn new(plugin_id: PluginId) -> RResult { + 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(); + } +} diff --git a/etws_loader/src/parser.rs b/loaders/etws_loader/src/parser.rs similarity index 99% rename from etws_loader/src/parser.rs rename to loaders/etws_loader/src/parser.rs index 03f16f2..3c0ca4b 100644 --- a/etws_loader/src/parser.rs +++ b/loaders/etws_loader/src/parser.rs @@ -10,7 +10,7 @@ use nom::{ use nom_derive::*; use serde::{Deserialize, Serialize}; use std::fs::File; -use std::io::{self, Read, Write}; +use std::io::Read; use std::path::Path; pub enum ValueResult { diff --git a/loaders/etws_loader/src/raw.rs b/loaders/etws_loader/src/raw.rs new file mode 100644 index 0000000..ec6e5d0 --- /dev/null +++ b/loaders/etws_loader/src/raw.rs @@ -0,0 +1,753 @@ +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, + pub azs: Vec, + pub ranges: Vec, + pub datas: HashMap<&'static str, Vec>, +} + +#[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, +} + +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>(path: P) -> io::Result { + let path = path.as_ref(); + + 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).unwrap(); + if &buf[0..4] == b"SSTM" || &buf[16..20] == b"STDM" || &buf[0..4] == b"RSTM" { + return get_radar_data(buf); + } else { + panic!("Invalid file format"); + } + } else { + let mut file = File::open(path).unwrap(); + 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 { + panic!("Invalid file format"); + } + } +} + +fn get_radar_data(data: Vec) -> io::Result { + let total_length = data.len() as u64; + // 使用 Cursor 来处理 Vec + 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).unwrap(); + + // 读取 SITE_CONFIG + let mut buffer = vec![0u8; 128]; + cursor.read_exact(&mut buffer)?; + let (_, site_config) = parse_site_config(&buffer).unwrap(); + + // 读取 TASK_CONFIG + let mut buffer = vec![0u8; 256]; + cursor.read_exact(&mut buffer)?; + let (_, task_config) = parse_task_config(&buffer).unwrap(); + + // 读取 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).unwrap(); + 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).unwrap(); + 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> { + let raw = match bin_length { + 1 => { + let new_raw: Vec = raw.into_iter().map(|v| *v as f64).collect(); + new_raw + } + 2 => { + let new_raw: Vec = cast_slice(&raw) + .into_iter() + .map(|v: &u16| *v as f64) + .collect(); + new_raw + } + 4 => { + let new_raw: Vec = cast_slice(&raw) + .into_iter() + .map(|v: &u32| *v as f64) + .collect(); + new_raw + } + 8 => { + let new_raw: Vec = cast_slice(&raw) + .into_iter() + .map(|v: &u64| *v as f64) + .collect(); + new_raw + } + _ => { + let new_raw: Vec = raw.into_iter().map(|v| *v as f64).collect(); + new_raw + } + }; + Ok(raw) +} + +fn beam_block_exact(cursor: &mut Cursor>, header: &TypeHeader) -> io::Result> { + 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>, +) -> io::Result<( + HashMap<&'static str, Vec>, + Vec, + Vec, + Vec, +)> { + 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).unwrap(); + // 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).unwrap(); + 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).unwrap(); + 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).unwrap(); + 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); + + let typ_name = types.get(typ).unwrap(); + + 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); + } + } + } + + 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(); + } +} diff --git a/radar-g/Cargo.toml b/radar-g/Cargo.toml index 47448a5..0b364d0 100644 --- a/radar-g/Cargo.toml +++ b/radar-g/Cargo.toml @@ -94,4 +94,4 @@ path = "../radarg_core" [dependencies.adw] package = "libadwaita" version = "0.7.0" -features = ["v1_4"] +features = ["v1_5"] diff --git a/radar-g/src/components/app.rs b/radar-g/src/components/app.rs index 05e5b32..1496501 100644 --- a/radar-g/src/components/app.rs +++ b/radar-g/src/components/app.rs @@ -4,43 +4,35 @@ use super::{ messages::{MonitorInputMsg, MonitorOutputMsg}, monitor::MonitorModel, setting::SettingModel, + sidebar::{SideBarInputMsg, SideBarModel}, ControlPanelOutputMsg, TimelineMsg, }; -use crate::components::sidebar::{SideBarInputMsg, SideBarModel}; use crate::datapool::{DataPool, Value}; use crate::predefined::color_mapper::{BoundaryNorm, ColorMapper, ColorMapperComb, Discrete}; use crate::widgets::{DynamicCol, ElementType}; use crate::{plugin_system::init_plugin, widgets::render::Layer, PLUGIN_MANAGER}; -use abi_stable::std_types::RStr; -use adw::prelude::*; use chrono::{prelude::*, Duration}; -use futures::future::BoxFuture; -use gi::App; -use gtk::glib; -use gtk::glib::clone; -use gtk::prelude::*; -use ndarray::{ArrayView1, ArrayViewD}; use once_cell::sync::Lazy; use radarg_core::Data; -use relm4::actions::{AccelsPlus, RelmAction, RelmActionGroup}; -use relm4::*; -use relm4::{gtk, Component, ComponentParts, ComponentSender, RelmWidgetExt, SimpleComponent}; +use relm4::{ + actions::{AccelsPlus, RelmAction, RelmActionGroup}, + adw::{self, prelude::*, MessageDialog}, + gtk::{self, glib, glib::clone, prelude::*}, + view, Component, ComponentController, ComponentParts, ComponentSender, Controller, + RelmWidgetExt, SimpleComponent, +}; use relm4_components::open_dialog::{ OpenDialog, OpenDialogMsg, OpenDialogResponse, OpenDialogSettings, }; -use smallvec::SmallVec; -use std::marker::PhantomData; -use std::num::NonZeroU32; + use std::{ - any::Any, cell::RefCell, - collections::{BTreeMap, HashMap}, path::PathBuf, rc::Rc, sync::{Arc, Mutex}, }; use tokio::{sync::oneshot, task}; -use tracing::{debug, error, info, warn}; +use tracing::*; use tracing_subscriber::fmt::layer; relm4::new_action_group!(FileActionGroup, "file"); @@ -69,9 +61,10 @@ pub enum FileIOType { pub enum AppMsg { Refresh, FileIO { typ: FileIOType }, + OpenDialog, CloseRequest, Close, - OpenDialog, + OpenFileDialog, } #[tracker::track] pub struct AppModel { @@ -186,6 +179,22 @@ impl Component for AppModel { setting_stack_page = view_stack.add_titled(model.setting.widget(), Some("setting"), "Setting") -> adw::ViewStackPage{ set_icon_name:Some("settings-filled") }, + #[name="dialog"] + adw::Dialog { + set_title: "Dialog", + set_presentation_mode: adw::DialogPresentationMode::Floating, + set_follows_content_size: true, + set_can_close: true, + + #[wrap(Some)] + set_child=>k::Box{ + set_height_request: 200, + set_width_request: 200, + gtk::Label{ + set_text:"Dialog", + }, + } + } } menu! { @@ -241,7 +250,11 @@ impl Component for AppModel { move |model_message| match model_message { MonitorOutputMsg::Attached(new_module) => { sidebar_sender.emit(SideBarInputMsg::Package(new_module)); - AppMsg::Close + AppMsg::OpenDialog + // AppMsg::Close + } + MonitorOutputMsg::Fc => { + AppMsg::OpenDialog } _ => AppMsg::Close, } @@ -305,7 +318,7 @@ impl Component for AppModel { // register_layer_actions(&widgets.main_window, sender.clone()); let action: RelmAction = { RelmAction::new_stateless(move |_| { - sender.input(AppMsg::OpenDialog); + sender.input(AppMsg::OpenFileDialog); }) }; group.add_action(action); @@ -327,9 +340,12 @@ impl Component for AppModel { relm4::main_application().quit(); } AppMsg::Close => {} - AppMsg::OpenDialog => { + AppMsg::OpenFileDialog => { self.open_dialog.emit(OpenDialogMsg::Open); } + AppMsg::OpenDialog => { + widgets.dialog.present(Some(root)); + } AppMsg::FileIO { typ: FileIOType::Open(data), } => self.render.emit(MonitorInputMsg::PushData(data)), diff --git a/radar-g/src/components/monitor/messages.rs b/radar-g/src/components/monitor/messages.rs index 1e4e90e..178603e 100644 --- a/radar-g/src/components/monitor/messages.rs +++ b/radar-g/src/components/monitor/messages.rs @@ -22,6 +22,7 @@ impl Debug for MonitorInputMsg { #[derive(Debug)] pub enum MonitorOutputMsg { Attached(Rc>), + Fc, } #[derive(Debug)] diff --git a/radar-g/src/components/monitor/monitor.rs b/radar-g/src/components/monitor/monitor.rs index e84e13c..9d6eb16 100644 --- a/radar-g/src/components/monitor/monitor.rs +++ b/radar-g/src/components/monitor/monitor.rs @@ -95,19 +95,20 @@ impl Component for MonitorModel { self.reset(); match message { MonitorInputMsg::PushData(data) => { - widgets - .renderer - .get_gi(|gi| match gi.load_data(&data, &SETTING) { - Ok(package) => { - info!("data load success!"); - let rc_package = Rc::new(RefCell::new(package)); - self.set_module_packages(vec![rc_package.clone()]); - sender.output(MonitorOutputMsg::Attached(rc_package)); - } - Err(err) => { - error!("Load Error, cause of {}", err); - } - }) + sender.output(MonitorOutputMsg::Fc); + // widgets + // .renderer + // .get_gi(|gi| match gi.load_data(&data, &SETTING) { + // Ok(package) => { + // info!("data load success!"); + // let rc_package = Rc::new(RefCell::new(package)); + // self.set_module_packages(vec![rc_package.clone()]); + // sender.output(MonitorOutputMsg::Attached(rc_package)); + // } + // Err(err) => { + // error!("Load Error, cause of {}", err); + // } + // }) } MonitorInputMsg::QueueDraw => { widgets.renderer.queue_draw(); diff --git a/radar-g/src/plugin_system/mod.rs b/radar-g/src/plugin_system/mod.rs index e3c2097..c7b7efe 100644 --- a/radar-g/src/plugin_system/mod.rs +++ b/radar-g/src/plugin_system/mod.rs @@ -16,8 +16,12 @@ use std::{ }; fn compute_plugin_path(base_name: &str) -> io::Result { - let debug_dir = "./target/debug".as_ref_::().into_::(); - let release_dir = "./target/release".as_ref_::().into_::(); + let debug_dir = "./loaders/target/debug" + .as_ref_::() + .into_::(); + let release_dir = "./loaders/target/release" + .as_ref_::() + .into_::(); let debug_path = RawLibrary::path_in_directory(&debug_dir, base_name, LibrarySuffix::NoSuffix); diff --git a/radar-g/src/widgets/render/imp.rs b/radar-g/src/widgets/render/imp.rs index 83aee86..0835e17 100644 --- a/radar-g/src/widgets/render/imp.rs +++ b/radar-g/src/widgets/render/imp.rs @@ -190,6 +190,8 @@ impl GLAreaImpl for Render { impl Render { fn ensure_canvas(&self) { use gi::{App as GI, Helper, GL}; + let widget = self.obj(); + widget.attach_buffers(); if self.gi.borrow().is_none() { info!("Creating canvas"); let (mut gi, viewport) = unsafe { diff --git a/radarg_core/src/config.rs b/radarg_core/src/config.rs index 7484440..8f4c9a3 100644 --- a/radarg_core/src/config.rs +++ b/radarg_core/src/config.rs @@ -63,7 +63,11 @@ impl Setting { name, cmap, {DBZ => "DBZ"}, {V => "VEL"}, - {VIL => "VIL"} + {VIL => "VIL"}, + {CC => "CC"}, + {KDP => "KDP"}, + {ZDR => "ZDR"}, + {PHIDP => "PHIDP"} ) } } diff --git a/radarg_core/src/radarg_data/mod.rs b/radarg_core/src/radarg_data/mod.rs index ead69bc..63b467b 100644 --- a/radarg_core/src/radarg_data/mod.rs +++ b/radarg_core/src/radarg_data/mod.rs @@ -155,6 +155,7 @@ macro_rules! raw2new { fn from(raw: RawRadarGridData) -> Self { let RawRadarGridData { data, info } = raw; let shape = info.shape.into_vec(); + println!("{:?}", shape); let data = match data { $(