rebuild factor
This commit is contained in:
parent
ed9e8549aa
commit
6ceebdd7f4
20
Cargo.lock
generated
20
Cargo.lock
generated
@ -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"
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
|
||||
[workspace]
|
||||
members = [
|
||||
"etws_loader",
|
||||
"radarg_plugin_interface",
|
||||
"geo-macros",
|
||||
"radar-g",
|
||||
|
||||
@ -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<RVec<LoadedData>, 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::<Vec<_>>(),
|
||||
);
|
||||
let dimension_names = convert_vec_to_rvec(
|
||||
b.info
|
||||
.dimension_des
|
||||
.into_iter()
|
||||
.map(RString::from)
|
||||
.collect::<Vec<_>>(),
|
||||
);
|
||||
|
||||
let fill_value = b.info.fill_value;
|
||||
let value_name = RString::from(b.info.value_name);
|
||||
let value_description = RString::from(b.info.value_des);
|
||||
let datetime = record.filetime.timestamp();
|
||||
|
||||
let value_key = value_name.as_str();
|
||||
|
||||
let data_type = data_type!(
|
||||
value_key,
|
||||
{ "ET" => ET },
|
||||
{ "DBZ" | "CR" | "FR" | "R" => DBZ},
|
||||
{ "VIL" => VIL},
|
||||
{ "EB" => EB},
|
||||
{ "V" => V},
|
||||
{ "ZDR" => ZDR},
|
||||
{ "PHIDP" => PHIDP},
|
||||
{ "KDP" => KDP},
|
||||
{ "CC" =>CC},
|
||||
{ "HCA" => HCA},
|
||||
{ "QPE" => QPE},
|
||||
{ "QPF" => QPF}
|
||||
);
|
||||
|
||||
let grid_info = GridDataInfo {
|
||||
shape: dimension_size,
|
||||
dimensions: dimension_values,
|
||||
dimension_names,
|
||||
fill_value,
|
||||
datetime: RSome(datetime),
|
||||
value_description: RSome(value_description),
|
||||
maybe_probe_data_type: RSome(data_type),
|
||||
value_name,
|
||||
dimension_description: "Wrong".into(),
|
||||
};
|
||||
|
||||
LoadedData::RadarGridData(RadarGridData {
|
||||
data: converted_data,
|
||||
info: grid_info,
|
||||
})
|
||||
})
|
||||
.collect::<RVec<_>>();
|
||||
|
||||
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<T>(raw: impl Iterator<Item = T>) -> RVec<T> {
|
||||
RVec::from(raw.collect::<Vec<_>>())
|
||||
}
|
||||
|
||||
fn convert_vec_to_rvec<T>(raw: Vec<T>) -> RVec<T> {
|
||||
RVec::from(raw)
|
||||
}
|
||||
|
||||
fn convert_nested_vec_to_rvec<T>(raw: Vec<Vec<T>>) -> RVec<RVec<T>> {
|
||||
RVec::from(raw.into_iter().map(RVec::from).collect::<Vec<_>>())
|
||||
}
|
||||
|
||||
#[sabi_extern_fn]
|
||||
pub fn new(plugin_id: PluginId) -> RResult<PluginType, Error> {
|
||||
let this = ETWSLoader { id: plugin_id };
|
||||
ROk(DataLoaderPlugin_TO::from_value(this, TD_Opaque))
|
||||
}
|
||||
|
||||
// 测试模块
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
// 导入外部作用域中的所有项
|
||||
use super::*;
|
||||
|
||||
// 一个简单的测试
|
||||
#[test]
|
||||
|
||||
fn test() {
|
||||
let result =
|
||||
Record::parse_from_path("/Volumes/data2/RadarArray/ShaoXing/radarData/OutputProducts/RadarProducts/BasicProductsX/20230627/20230627163400/ZJSXAA_20230627163400_VIL.dat.gz")
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
@ -61,13 +61,17 @@ impl App {
|
||||
&mut self.context.programs
|
||||
}
|
||||
|
||||
pub fn load_data(
|
||||
&mut self,
|
||||
data: &Vec<Data>,
|
||||
setting: &radarg_core::config::Setting,
|
||||
) -> Result<ModulePackage> {
|
||||
self.program().load_data(data, setting)
|
||||
pub fn supported_modules(&mut self) -> Vec<super::Modules> {
|
||||
self.program().supported_modules()
|
||||
}
|
||||
|
||||
// pub fn load_data(
|
||||
// &mut self,
|
||||
// data: &Vec<Data>,
|
||||
// setting: &radarg_core::config::Setting,
|
||||
// ) -> Result<ModulePackage> {
|
||||
// self.program().load_data(data, setting)
|
||||
// }
|
||||
}
|
||||
|
||||
pub struct Context {
|
||||
|
||||
@ -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<Data>,
|
||||
setting: &radarg_core::config::Setting,
|
||||
) -> Result<ModulePackage> {
|
||||
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<Modules> {
|
||||
vec![Modules::PPI(self.ppi())]
|
||||
}
|
||||
|
||||
// pub fn load_data(
|
||||
// &mut self,
|
||||
// data: &Vec<Data>,
|
||||
// setting: &radarg_core::config::Setting,
|
||||
// ) -> Result<Vec<ModulePackage>> {
|
||||
// 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 {
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
1383
loaders/Cargo.lock
generated
Normal file
1383
loaders/Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
2
loaders/Cargo.toml
Normal file
2
loaders/Cargo.toml
Normal file
@ -0,0 +1,2 @@
|
||||
[workspace]
|
||||
members = ["etws_loader"]
|
||||
@ -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']
|
||||
480
loaders/etws_loader/raw.py
Normal file
480
loaders/etws_loader/raw.py
Normal file
@ -0,0 +1,480 @@
|
||||
"""
|
||||
大探标准格式解析代码
|
||||
"""
|
||||
|
||||
import gc
|
||||
import numpy as np
|
||||
import struct
|
||||
|
||||
__all__ = ['get_radar_data']
|
||||
|
||||
|
||||
def get_radar_data_new(f):
|
||||
"""
|
||||
:param filename:
|
||||
:return: dbz, vel, w, zdr, cc, dp, kdp, el_n, azm, el
|
||||
"""
|
||||
|
||||
f.seek(0, 2)
|
||||
block_length_all = f.tell()
|
||||
f.seek(0)
|
||||
|
||||
GENERIC_HEADER = { # noqa
|
||||
# 共32bit,保留字节16bit
|
||||
"Magic_Number": struct.unpack('I', f.read(4)), # 魔术字 - --固定标志,用来指示雷达数据文件
|
||||
# "Major_Version": struct.unpack('h', f.read(2)), # 主版本号
|
||||
# "Minor_Version": struct.unpack('h', f.read(2)), # 次版本号
|
||||
"Major_Version": struct.unpack('H', f.read(2)), # 主版本号
|
||||
"Minor_Version": struct.unpack('H', f.read(2)), # 次版本号
|
||||
"Generic_Type": struct.unpack('I', f.read(4)),
|
||||
# 文件类型 - --1–基数据文件;2–气象产品文件;3 - --体扫配置文件;4 - --保留;5 - --体扫调度配置文件;6 - --雷达状态数据文件
|
||||
"Product_Type": struct.unpack('I', f.read(4)), # 产品类型 - --仅在文件类型为2时生效
|
||||
# 保留字节16bit
|
||||
"Reserved": f.read(16)
|
||||
}
|
||||
|
||||
# f.seek(32)
|
||||
SITE_CONFIG = { # 共128bit,保留字节46bit
|
||||
"Site_Code": struct.unpack("8s", f.read(8))[0], # 站号 - --站号具有唯一性,用来区别不同的雷达站,如Z9010
|
||||
"Site_Name": struct.unpack("32s", f.read(32))[0], # 站点名称 - --站点名称,如BeiJing
|
||||
"Latitude": struct.unpack('f', f.read(4))[0], # 纬度 - --雷达站天线所在位置纬度
|
||||
"Longitude": struct.unpack('f', f.read(4))[0], # 经度 - --雷达站天线所在位置经度
|
||||
"Antenna_Height": struct.unpack('I', f.read(4))[0], # 天线高度 - --天线馈源水平时海拔高度
|
||||
"Ground_Height": struct.unpack('I', f.read(4)), # 地面高度 - --雷达塔楼地面海拔高度
|
||||
"Frequency": struct.unpack('f', f.read(4)), # 工作频率
|
||||
# TODO gyj modify
|
||||
# "Beam_Width_Hori": struct.unpack('f', f.read(4)), # 水平波束宽度
|
||||
# "Beam_Width_Vert": struct.unpack('f', f.read(4)), # 垂直波束宽度
|
||||
"Antenna_Type": struct.unpack('I', f.read(4)), # 天线类型
|
||||
"TR_Number": struct.unpack('I', f.read(4)), # 收发单元数量
|
||||
|
||||
|
||||
"RDA_Version": struct.unpack('I', f.read(4)), # RDA版本号 - --雷达数据采集软件版本号
|
||||
# TODO gyj modify
|
||||
# 't':struct.unpack('h', f.read(2))[0],
|
||||
"Radar_Type": {1: "SA", 2: "SB", 3: "SC", 4: "SAD", 7:'SPAR',8:'SPARD',
|
||||
33: "CA", 34: "CB", 35: "CC", 36: "CCJ", 37: "CD", 38: "CAD",
|
||||
43:'CPAR',44:'CPARD',
|
||||
65: "XA", 66: "XAD",69:'XPAR',70:'XPARD'}.get(struct.unpack('h', f.read(2))[0]),
|
||||
# 雷达类型 - --1–SA;2–SB;3–SC;4–SAD;33–CA;34–CB;35–CC;36–CCJ;37–CD;38–CAD;65–XA;66–XAD
|
||||
# 7–SPAR 8–SPARD 43–CPAR 44–CPARD 69–XPAR 70–XPARD
|
||||
# "Antenna_Gain": struct.unpack('h', f.read(2)), # 天线增益 - --编码为实际100倍
|
||||
# "Transmitting_feeder_loss": struct.unpack('h', f.read(2)), # 发射馈线损耗 - --编码为实际损耗100倍
|
||||
# "Receiving_feeder_loss": struct.unpack('h', f.read(2)), # 接收馈线损耗 - --编码为实际损耗100倍
|
||||
# "Other_Loss": struct.unpack('h', f.read(2)), # 其他损耗 - --编码为实际损耗100倍
|
||||
# 保留字节46bit
|
||||
"Reserved": f.read(54)
|
||||
}
|
||||
|
||||
|
||||
# f.seek(160)
|
||||
TASK_CONFIG = { # 共256bit,保留字节40bit
|
||||
"Task_Name": struct.unpack("32s", f.read(32)), # 任务名称 - --任务名称,如VCP21
|
||||
"Task_Description": struct.unpack("128s", f.read(128)), # 任务描述
|
||||
"Polarization_Type": struct.unpack('I', f.read(4))[0], # 极化方式 - --1 – 水平极化;2 – 垂直极化;3 – 水平 / 垂直同时;4 – 水平 / 垂直交替
|
||||
"Scan_Type": struct.unpack('I', f.read(4)
|
||||
),
|
||||
# 扫描任务类型 - --0 – 体扫;1–单层PPI;2 – 单层RHI;3 – 单层扇扫;4 – 扇体扫;5 – 多层RHI;6 – 手工扫描
|
||||
# "Pulse_Width": struct.unpack('I', f.read(4)
|
||||
# ), # 脉冲宽度 - --发射脉冲宽度
|
||||
# "Scan_Start_Time": struct.unpack('I', f.read(4)
|
||||
# ), # 扫描开始时间 - --扫描开始时间为UTC标准时间计数, 1970年1月1日0时为起始计数基准点
|
||||
#TODO gyj modify
|
||||
'Scan_Beam_Number':struct.unpack('I', f.read(4)), #扫描配置中的发射波束数量
|
||||
|
||||
"Cut_Number": struct.unpack('I', f.read(4)
|
||||
), # 扫描层数 - --根据扫描任务类型确定的扫描层数,与基数据保存的层数一致
|
||||
|
||||
"Ray_Order": struct.unpack('I', f.read(4)), #径向数据排序,0 – 按径向采集时间排序,1 – 按先方位后俯仰方式排序
|
||||
|
||||
"Scan_Start_Time": struct.unpack('q', f.read(8)
|
||||
), # 扫描开始时间 s - --扫描开始时间为UTC标准时间计数, 1970年1月1日0时为起始计数基准点
|
||||
|
||||
# "Horizontal_Noise": struct.unpack('f', f.read(4)
|
||||
# ), # 水平通道噪声 - --水平通道的噪声电平
|
||||
# "Vertical_Noise": struct.unpack('f', f.read(4)
|
||||
# ), # 垂直通道噪声 - --垂直通道的噪声电平
|
||||
# "Horizontal_Calibration": struct.unpack('f', f.read(4)
|
||||
# ), # 水平通道标定值 - --水平通道的反射率标定常数
|
||||
# "Vertical_Calibration": struct.unpack('f', f.read(4)
|
||||
# ), # 水平通道噪声温度 - --垂直通道的反射率标定常数
|
||||
# "Horizontal_Noise_Temperature": struct.unpack('f', f.read(4)
|
||||
# ), # 水平通道噪声温度
|
||||
# "Vertical_Noise_Temperature": struct.unpack('f', f.read(4)
|
||||
# ), # 垂直通道噪声温度
|
||||
# "ZDR_Calibration": struct.unpack('f', f.read(4)
|
||||
# ), # ZDR标定偏差
|
||||
# "PHIDP_Calibration": struct.unpack('f', f.read(4)
|
||||
# ), # 差分相移标定偏差
|
||||
# "LDR_Calibration": struct.unpack('f', f.read(4)
|
||||
# ), # 系统LDR标定偏差
|
||||
"Reserved": f.read(68)
|
||||
# 保留字节68bit
|
||||
}
|
||||
|
||||
# CUT_CONFIG = { # 每个仰角共256bit,保留72bit
|
||||
# }
|
||||
# print(np.frombuffer(f.read(128),'S128')[0].decode('Windows-1252').encode("utf-8"))
|
||||
|
||||
cut_number = TASK_CONFIG.get("Cut_Number")[0] # 扫描层数
|
||||
Scan_Beam_Number = TASK_CONFIG.get("Scan_Beam_Number")[0] #扫描配置中的发射波束数量
|
||||
# print(cut_number)
|
||||
SCAN_CONFIG = {}
|
||||
for i in range(1, Scan_Beam_Number + 1):
|
||||
# f.seek(416)
|
||||
# 扫描波束配置块(一个)
|
||||
SCAN_CONFIG[i] = {
|
||||
'BEAM_INDEX': struct.unpack('I', f.read(4)), # 按扫描波束依次编号,一个体扫可由多个扫描波束组成,一个扫描波束可输出多个扫描仰角数据
|
||||
'BEAM_TYPE': struct.unpack('I', f.read(4)), # 扫描波束类型 1 – 宽波束 2 – 窄波束
|
||||
'SubPulse_Number': struct.unpack('I', f.read(4)), # 子脉冲数量,主工作脉冲和补盲子脉冲数量总和,以下按作用距离由远及近排列1~4
|
||||
'Tx_Beam_Direction': struct.unpack('f', f.read(4)), # 发射波束中心指向,发射波束中心的俯仰角指向-2.00~90.00
|
||||
'Tx_Beam_Width-H': struct.unpack('f', f.read(4)), # 发射波束水平宽度
|
||||
'Tx_Beam_Width-V': struct.unpack('f', f.read(4)), # 发射波束垂直宽度
|
||||
'Tx_Beam_Gain': struct.unpack('f', f.read(4)), # 发射波束中心增益
|
||||
'Reserved': f.read(100) # 保留字节100bit
|
||||
}
|
||||
|
||||
|
||||
# cut_number = SCAN_CONFIG['0'].get("SubPulse_Number")[0]
|
||||
# cut_number = 4
|
||||
# print('cut_number: ',cut_number)
|
||||
|
||||
# 子脉冲参数块(4个)
|
||||
for j in range(1, 5):
|
||||
SCAN_CONFIG[i]['%d' % j] = { # 共128bit,保留70bit
|
||||
'SubPulse_Strategy': struct.unpack('I', f.read(4)), # 子脉冲策略 0=频分 1=时分
|
||||
'SubPulse_Modulation': struct.unpack('I', f.read(4)), # 子脉冲调制方式 0=单载频 1=线性正调频ULFM 2=线性负调频DLFM 3=非线性正调频UNLFM 4=非线性负调频DNLFM
|
||||
'SubPulse_Frequency': struct.unpack('f', f.read(4)), # 子脉冲频率,点频脉冲指工作频率,调频脉冲指中心频率, 1.00~999,000.00
|
||||
'SubPulse_BandWidth': struct.unpack('f', f.read(4)), # 子脉冲带宽,对调频模式有效,表示双边带宽, MHz兆赫 1.00~99.00
|
||||
'SubPulse_Width': struct.unpack('I', f.read(4)), # 子脉冲宽度,单位为纳秒ns,信号脉冲宽度(时长)
|
||||
'Horizontal_Noise': struct.unpack('f', f.read(4)), # 水平通道噪声,dBm分贝毫瓦,水平通道的噪声电平-100.00~0.00
|
||||
'Vertical_Noise': struct.unpack('f', f.read(4)), # 垂直通道噪声,dBm分贝毫瓦,垂直通道的噪声电平-100.00~0.00
|
||||
'Horizontal_Calibration': struct.unpack('f', f.read(4)), # 水平通道标定偏差,dB分贝,水平通道的标定偏差0.00~200.00
|
||||
'Vertical_Calibration': struct.unpack('f', f.read(4)), # 垂直通道标定偏差,dB分贝,垂直通道的标定偏差0.00~200.00
|
||||
'Horizontal_Noise_Temperature': struct.unpack('f', f.read(4)), # 水平通道噪声温度,单位为K开氏温标,水平通道的噪声温度0.00~800.00
|
||||
'Vertical_Noise_Temperature': struct.unpack('f', f.read(4)), # 垂直通道噪声温度,单位为K开氏温标,垂直通道的噪声温度0.00~800.00
|
||||
'ZDR_Calibration': struct.unpack('f', f.read(4)), # ZDR标定偏差,dB分贝,水平通道的标定偏差 -10.00~10.00
|
||||
'PHIDP_Calibration': struct.unpack('f', f.read(4)), # PHIDP标定偏差,度,水平通道的标定偏差 -180.00~180.00
|
||||
'LDR_Calibration': struct.unpack('f', f.read(4)), # LDR标定偏差,dB分贝,水平通道的标定偏差 -60~0
|
||||
'Pulse_Points': struct.unpack('h', f.read(2)), # 脉冲距离库数, 0~10000,该子脉冲探测的距离库数
|
||||
'Reserved': f.read(70), # 保留字节70bit
|
||||
}
|
||||
|
||||
# # # ========== 接收仰角配置块 ========
|
||||
BEAM_CONFIG = {}
|
||||
for i in range(1, cut_number + 1):
|
||||
BEAM_CONFIG['%d' %i] = {
|
||||
'Cut_Index': struct.unpack('h', f.read(2)), #扫描层索引, 1~256, 基数据仰角编号
|
||||
'Tx_Beam_Index': struct.unpack('h', f.read(2)), # 发射波束索引, 1~256, 对应的发射波束索引
|
||||
'Rx_Beam_Elevation': struct.unpack('f', f.read(4)), #接收波束指向,度, -2.00~90.00, PPI模式的俯仰角
|
||||
'Tx_Beam_Gain': struct.unpack('f', f.read(4)), #发射波束增益,,dB分贝, 在本接收方向上,发射波束的增益
|
||||
'Rx_Beam_Width_H': struct.unpack('f', f.read(4)), #接收波束水平宽度, 度
|
||||
'Rx_Beam_Width_V': struct.unpack('f', f.read(4)), #接收波束垂直宽度, 度
|
||||
'Rx_Beam_Gain': struct.unpack('f', f.read(4)), #接收波束垂直宽度, dB分贝,
|
||||
"Process_Mode": {1: "PPP", 2: "FFT"}.get(struct.unpack('I', f.read(4))[0]), # 处理模式---1---PPP;2---FFT
|
||||
"Wave_Form": {0: "CS连续监测", 1: "CD连续多普勒", 2: "CDX多普勒扩展", 3: "Rx Test", 4: "BATCH批模式", 5: "Dual PRF双PRF",
|
||||
6: "Staggered PRT 参差PRT"}.get(struct.unpack('I', f.read(4))[0]),
|
||||
# 波形类别---0 – CS连续监测;1 – CD连续多普勒;2 – CDX多普勒扩展;3 – Rx Test;4 – BATC H批模式;5 – Dual PRF双PRF ;6---Staggered PRT 参差PRT
|
||||
"N1PRF1": struct.unpack('f', f.read(4)
|
||||
), # 第一组脉冲重复频率1---单位赫兹Hz---对于Batch、双PRF和参差PRT模式,表示高PRF值。对于其它单PRF模式,表示唯一的PRF值。
|
||||
"N1PRF2": struct.unpack('f', f.read(4)
|
||||
), # 第一组脉冲重复频率2---单位赫兹Hz---对Batch、双PRF和参差PRT模式,表示低PRF值。对其它单PRF模式,无效。
|
||||
"N2PRF1": struct.unpack('f', f.read(4)
|
||||
), # 第二组脉冲重复频率1---单位赫兹Hz---对于Batch、双PRF和参差PRT模式,表示高PRF值。对于其它单PRF模式,表示唯一的PRF值。
|
||||
"N2PRF2": struct.unpack('f', f.read(4)
|
||||
), # 第二组脉冲重复频率2---单位赫兹Hz---对Batch、双PRF和参差PRT模式,表示低PRF值。对其它单PRF模式,无效。
|
||||
|
||||
"Dealiasing_Mode": struct.unpack('I', f.read(4)), # 速度退模糊方法---1 – 单PRF;2 –双PRF3:2模式;3 –双PRF4:3模式;4 –双PRF 5:4模式
|
||||
|
||||
"Azimuth": struct.unpack('f', f.read(4)), # 方位角---RHI模式的方位角, 度,0.00~360.00, PPI模式的俯仰角同参数接收波
|
||||
# "Elevation": struct.unpack('f', f.read(4)), # 俯仰角---PPI模式的俯仰角
|
||||
"Start_Angle": struct.unpack('f', f.read(4)), # 起始角度----度,-10.00~360.00---PPI扇扫的起始方位角,或RHI模式的高限仰角
|
||||
"End_Angle": struct.unpack('f', f.read(4)), # 结束角度---度,-10.00~360.00---PPI扇扫的结束方位角,或RHI模式的低限仰角
|
||||
"Angular_Resolution": struct.unpack('f', f.read(4)), # 角度分辨率--度,---径向数据的角度分辨率,仅用于PPI扫描模式
|
||||
"Scan_Speed": struct.unpack('f', f.read(4)), # 扫描速度---度/秒---0.00~100.00---PPI扫描的方位转速,或RHI扫描的俯仰转速
|
||||
"Log_Resolution": struct.unpack('f', f.read(4)), # 强度分辨率---米---1~5,000---强度数据的距离分辨率,支持浮点分辨率
|
||||
"Doppler_Resolution": struct.unpack('f', f.read(4)), # 多普勒分辨率---米---1~5,000---多普勒数据的距离分辨率
|
||||
"Maximum_Range1": struct.unpack('I', f.read(4)), # 最大距离1---米---1~500,000---对应脉冲重复频率1的最大可探测距离
|
||||
"Maximum_Range2": struct.unpack('I', f.read(4)), # 最大距离2---米---1~500,000---对应脉冲重复频率2的最大可探测距离
|
||||
"Start_Range": struct.unpack('I', f.read(4)), # 起始距离---米---1~500,000---数据探测起始距离
|
||||
"Sample1": struct.unpack('I', f.read(4)), # 采样个数1---2~512---对应于脉冲重复频率1的采样个数
|
||||
"Sample2": struct.unpack('I', f.read(4)), # 采样个数2---2~512---对应于脉冲重复频率2的采样个数
|
||||
"Phase_Mode": struct.unpack('I', f.read(4)), # 相位编码模式---1 – 固定相位;2 – 随机相位;3 – SZ编码
|
||||
"Atmospheric_Loss": struct.unpack('f', f.read(4)), # 大气衰减---分贝/千米--0.000000~10.000000---双程大气衰减值,精度为小数点后保留6位
|
||||
"Nyquist_Speed": struct.unpack('f', f.read(4)), # 最大不模糊速度---米/秒---0~100---理论最大不模糊速度
|
||||
"Moments_Mask": struct.unpack("q", f.read(8)), # 数据类型掩码---0~0xFFFFFFFFFFFFFFFF---以掩码的形式表示当前允许获取的数据类型,其中:0–不允许获取数据;1 –允许获取数据。(json1)
|
||||
"Moments_Size_Mask": struct.unpack("q", f.read(8)),# 数据大小掩码---0~0xFFFFFFFFFFFFFFFF---以掩码形式表示每种数据类型字节数,其中:0–1个字节;1 – 2个字节(json1)
|
||||
"Misc_Filter_Mask": struct.unpack('I', f.read(4)), # 滤波设置掩码--0~0xFFFFFFFF---0–未应用;1–应用(json2)
|
||||
"SQI_Threshold": struct.unpack('f', f.read(4)), # SQI门限---0.00~1.00----
|
||||
"SIG_Threshold": struct.unpack('f', f.read(4)), # SIG门限--dB分贝---0.00~20.00
|
||||
"CSR_Threshold": struct.unpack('f', f.read(4)), # CSR门限--dB分贝--0.00~100.00
|
||||
"LOG_Threshold": struct.unpack('f', f.read(4)), # LOG门限--dB分贝--0.00~20.00
|
||||
"CPA_Threshold": struct.unpack('f', f.read(4)), # CPA门限--0.00~100.00--
|
||||
"PMI_Threshold": struct.unpack('f', f.read(4)), # PMI门限--0.00~1.00
|
||||
"DPLOG_Threshold": struct.unpack('f', f.read(4)), # DPLOG门限--0.00~100.00
|
||||
"Thresholds_r": struct.unpack('4s', f.read(4)), #阈值门限保留---水平通道的反射率标定常数 =======保留字段======
|
||||
# 这个时保留字段 "Thresholds_r":data.slice(548,552),#阈值门限保留---水平通道的反射率标定常数
|
||||
"dBT_Mask": struct.unpack('I', f.read(4)), # dBT质控掩码---0~0xFFFFFFFF---dBT数据使用的质控门限掩码,其中:0–未应用,1–应用(json3)
|
||||
"dBZ_Mask": struct.unpack('I', f.read(4)), # dBZ质控掩码---dBZ数据使用的质控门限掩码, 其中:0–未应用,1–应用(json3)
|
||||
"Velocity_Mask": struct.unpack('I', f.read(4)), # 速度质控掩码----0~0xFFFFFFFF---速度数据使用的质控门限掩码, 其中:0–未应用,1–应用(json3)
|
||||
"Spectrum_Width_Mask": struct.unpack('I', f.read(4)), # 谱宽质控掩码----0~0xFFFFFFFF--谱宽数据使用的质控门限掩码,其中:0–未应用,1–应用(json3)
|
||||
"DP_Mask": struct.unpack('I', f.read(4)), # 偏振量质控掩码----0~0xFFFFFFFF--偏振量数据使用的质控门限掩码,其中:0–未应用,1–应用(json3)
|
||||
|
||||
"Mask_Reserved": f.read(12), # 保留字节12bit
|
||||
'Reserved': f.read(4), # 保留字节4bit
|
||||
|
||||
# 保留12bit
|
||||
# "Scan_Sync": struct.unpack('I', f.read(4)), # 扫描同步标志---用于多部雷达同步扫描标识
|
||||
|
||||
"Direction": struct.unpack('I', f.read(4)), # 天线运行方向---仅对PPI模式有效1 – 顺时针;2 – 逆时针
|
||||
"Ground_Clutter_Classifier_Type": struct.unpack('h', f.read(2)), # 地物杂波图类型---1 – 所有数据不滤波;2 – 全程滤波;3 – 使用实时动态滤波图;4 – 使用静态滤波图
|
||||
"Ground_Clutter_Filter_Type": struct.unpack('h', f.read(2)),
|
||||
# 地物滤波类型---0 –不滤波;1 – 频域自适应滤波;2 - 固定宽带频域滤波器;3 - 可变宽带频域滤波器;4 - 可变最小方差频域滤波器;5 – IIR时域滤波
|
||||
"Ground_Clutter_Filter_Notch_Width": struct.unpack('h', f.read(2)), # 地物滤波宽度--0.1 米/秒--0.1~10.0
|
||||
"Ground_Clutter_Filter_Window": struct.unpack('h', f.read(2)),
|
||||
# 滤波窗口类型---滤波算法FFT窗口类型;0 – 矩形窗;1 – 汉明窗;2 – Blackman窗;3 – 自适应窗口;4 – 无
|
||||
"Reserved": f.read(44), # 保留字节44bit
|
||||
}
|
||||
#TODO
|
||||
# radar_range = np.arange(BEAM_CONFIG['1']['Sample1'][0]) * BEAM_CONFIG['1']['Log_Resolution'][0]
|
||||
data_block = f.tell()
|
||||
# print(data_block)
|
||||
# return
|
||||
|
||||
data_shape = {}
|
||||
# for J in range(radial_number):
|
||||
|
||||
|
||||
RadialData = {
|
||||
# 径向头,共128字节 保留13 字节
|
||||
"Radial_State": struct.unpack('I', f.read(4)),
|
||||
# 径向数据状态 - --0–仰角开始;1–中间数据;2–仰角结束;3–体扫开始;4–体扫结束;5–RHI开始;6–RHI结束
|
||||
"Spot_Blank": struct.unpack('I', f.read(4)), # 消隐标志 - --0–正常;1–消隐
|
||||
"Sequence_Number": struct.unpack('I', f.read(4)), # 序号 - 1~65536--每个体扫径向从1计数
|
||||
"Radial_Number": struct.unpack('I', f.read(4)), # 径向数 - 1~1000--每个扫描从1计数
|
||||
"Elevation_Number": struct.unpack('I', f.read(4)), # 仰角编号 - --仰角编号,每个体扫从1计数
|
||||
"Azimuth": struct.unpack('f', f.read(4)), # 方位角 ---度 0.00~360.00 --扫描的方位角度
|
||||
"Elevation": struct.unpack('f', f.read(4)), # 仰角 ---度 -2.00~90.00--扫描的俯仰角度
|
||||
"Seconds": struct.unpack('q', f.read(8)), # 秒 - --径向数据采集的时间,UTC计数的秒数, 从1970年1月1日0时开始计数
|
||||
"Microseconds": struct.unpack('I', f.read(4)), # 微秒 - --径向数据采集的时间除去UTC秒数后,留下的微秒数
|
||||
"Length_of_data": struct.unpack('I', f.read(4)), # 数据长度 --1~100000 --仅本径向数据块所占用的长度如有压缩,长度为压缩后数据长度
|
||||
"Moment_Number": struct.unpack('I', f.read(4)), # 数据类别数量 ---1~64 --径向数据类别(如Z,V,W等各占一种)的数量
|
||||
"Scan Beam Index": struct.unpack('h', f.read(2)), # 波束编号 ---1-32 --波束编号
|
||||
"Horizontal_Estimated_Noise": struct.unpack('h', f.read(2)), # 径向的水平估计噪声 --dB分贝 --编码为实际噪声的 - 100倍
|
||||
"Vertical_Estimated_Noise": struct.unpack('h', f.read(2)), # 径向的垂直估计噪 - --编码为实际噪声的 - 100 倍
|
||||
"PRF_FLAG": struct.unpack('I', f.read(4)), #重频标志, 11 – N1 PRF #1 ; 12 – N1 PRF #2; 21 – N2 PRF #1; 22 – N2 PRF #2; 排列方式:11128888:表示使用N1 PRF #1和PRF #2 #######################uint
|
||||
# 88882122:表示使用N2 PRF #1和PRF #2 11122122:表示使用N1和N2的PRF #1和PRF #2 (对应表2-7中09-13的描述)(8表示无效填充数据,弥补用0表示会出现的问题)
|
||||
|
||||
# "Zip_Type": struct.unpack('h', f.read(2)), # 压缩类型 - --0 - 不压缩;1 - LZO压缩
|
||||
"Reversed": f.read(70) # 保留70bit
|
||||
}
|
||||
|
||||
|
||||
radial_number = RadialData.get("Radial_Number")[0] # 径向数 J
|
||||
type_number = RadialData.get("Moment_Number")[0] # 数据类别数量 K
|
||||
|
||||
typeHeader = {}
|
||||
# for J in range(radial_number):
|
||||
# for K in range(type_number):
|
||||
|
||||
for i in range(type_number):
|
||||
# typeHeader[J][K] = {
|
||||
typeHeader = {
|
||||
# 共32字节
|
||||
"Data_Type": struct.unpack('I', f.read(4)), # 数据类型 ---1~64 --具体径向数据类型见表2 - 6
|
||||
"Scale": struct.unpack('I', f.read(4)), # 比例 --0~32768 --数据编码的比例
|
||||
"Offset": struct.unpack('I', f.read(4)), # 偏移 --0~32768 --数据编码的偏移
|
||||
"Bin_Length": struct.unpack('h', f.read(2)), # 库字节长度 - --保存一个距离库值用的字节数
|
||||
"Flags": struct.unpack('h', f.read(2)), # 标志 - --数据标志位,暂不使用
|
||||
"Length": struct.unpack('I', f.read(4)), # 长度 --1~32768 --距离库数据的长度,不包括当前的径向数据头大小
|
||||
"Reserved": f.read(12)
|
||||
}
|
||||
|
||||
block_length = typeHeader.get("Length")[0]
|
||||
bin_length = typeHeader.get("Bin_Length")[0]
|
||||
offset = typeHeader.get("Offset")[0]
|
||||
scale = typeHeader.get("Scale")[0]
|
||||
data_body = f.read(block_length)
|
||||
raw = np.frombuffer(data_body, 'u' + str(bin_length)).astype(np.float64)
|
||||
#TODO
|
||||
if i ==0:
|
||||
radar_range = np.arange(len(raw))*30
|
||||
raw[raw <= 5.] = np.nan
|
||||
# 对于保存的编码值来说,5以下的值表示特殊意义,不应该被解码。
|
||||
value = (raw - offset) / scale
|
||||
data_type = typeHeader.get("Data_Type")[0]
|
||||
data_shape[data_type] = value.shape[0]
|
||||
|
||||
block_index = f.tell()
|
||||
roll_num = int((block_length_all - data_block) / (block_index - data_block))
|
||||
azm_num = int(roll_num / cut_number)
|
||||
gc.collect()
|
||||
|
||||
# print("=========",data_shape)
|
||||
# return get_radial_data(f, cut_number, azm_num, data_shape, data_block, SITE_CONFIG, radar_range, TASK_CONFIG['Polarization_Type'])
|
||||
return get_radial_data(f, cut_number, azm_num, data_shape, data_block, SITE_CONFIG, radar_range, TASK_CONFIG['Polarization_Type'], BEAM_CONFIG)
|
||||
|
||||
|
||||
def get_radial_data(f, cut_number, azm_num, data_shape, data_block, site_config, radar_range, polar_type, BEAM_CONFIG):
|
||||
"""
|
||||
|
||||
:param f:
|
||||
:param cut_number: cut number
|
||||
:param azm_num: number of azm
|
||||
:param data_shape: length of block
|
||||
:return: dbz, vel, w, zdr, cc, dp, kdp, el_n, azm, el
|
||||
dbz:滤波后反射率(Reflectivity) dBZ
|
||||
vel:径向速度(Doppler Velocity) V
|
||||
w:谱宽(Spectrum Width) W
|
||||
zdr_:差分反射率(Differential Reflectivity ZDR
|
||||
cc_:协相关系数(Cross Correlation Coefficient) CC
|
||||
dp_:差分相移(Differential Phase) DP
|
||||
kdp_差分相移率(Specific Differential Phase) KDp
|
||||
azm:方位角 维度1
|
||||
el:仰角 维度 1
|
||||
"""
|
||||
_data_dict = {}
|
||||
for k, v in data_shape.items():
|
||||
if k == 2:
|
||||
dbz = np.empty((cut_number, azm_num, v), dtype=np.float64)
|
||||
_data_dict['reflectData'] = dbz
|
||||
elif k == 3:
|
||||
vel = np.empty((cut_number, azm_num, v), dtype=np.float64)
|
||||
_data_dict['velData'] = vel
|
||||
elif k == 4:
|
||||
w = np.empty((cut_number, azm_num, v), dtype=np.float64)
|
||||
_data_dict['widData'] = w
|
||||
elif k == 7:
|
||||
zdr = np.empty((cut_number, azm_num, v), dtype=np.float64)
|
||||
_data_dict['zdrData'] = zdr
|
||||
elif k == 9:
|
||||
cc = np.empty((cut_number, azm_num, v), dtype=np.float64)
|
||||
_data_dict['ccData'] = cc
|
||||
elif k == 10:
|
||||
dp = np.empty((cut_number, azm_num, v), dtype=np.float64)
|
||||
_data_dict['dpData'] = dp
|
||||
elif k == 11:
|
||||
kdp = np.empty((cut_number, azm_num, v), dtype=np.float64)
|
||||
_data_dict['kdpData'] = kdp
|
||||
el_n = np.empty((cut_number, azm_num), np.int32)
|
||||
azm = np.empty((cut_number, azm_num), np.float32)
|
||||
el = np.empty((cut_number, azm_num), np.float32)
|
||||
f.seek(data_block)
|
||||
for j in range(cut_number):
|
||||
for k in range(azm_num):
|
||||
RadialData = {
|
||||
# 共64字节 保留13 字节
|
||||
"Radial_State": struct.unpack('I', f.read(4)),
|
||||
# 径向数据状态 - --0–仰角开始;1–中间数据;2–仰角结束;3–体扫开始;4–体扫结束;5–RHI开始;6–RHI结束
|
||||
"Spot_Blank": struct.unpack('I', f.read(4)
|
||||
), # 消隐标志 - --0–正常;1–消隐
|
||||
"Sequence_Number": struct.unpack('I', f.read(4)
|
||||
), # 序号 - --每个体扫径向从1计数
|
||||
"Radial_Number": struct.unpack('I', f.read(4)
|
||||
), # 径向数 - --每个扫描从1计数
|
||||
"Elevation_Number": struct.unpack('I', f.read(4)
|
||||
), # 仰角编号 - --仰角编号,每个体扫从1计数
|
||||
"Azimuth": struct.unpack('f', f.read(4)
|
||||
), # 方位角 - --扫描的方位角度
|
||||
"Elevation": struct.unpack('f', f.read(4)
|
||||
), # 仰角 - --扫描的俯仰角度
|
||||
"Seconds": struct.unpack('q', f.read(8)
|
||||
), # 秒 - --径向数据采集的时间,UTC计数的秒数, 从1970年1月1日0时开始计数
|
||||
"Microseconds": struct.unpack('I', f.read(4)
|
||||
), # 微秒 - --径向数据采集的时间除去UTC秒数后,留下的微秒数
|
||||
"Length_of_data": struct.unpack('I', f.read(4)
|
||||
), # 数据长度 - --仅本径向数据块所占用的长度如有压缩,长度为压缩后数据长度
|
||||
"Moment_Number": struct.unpack('I', f.read(4)
|
||||
), # 数据类别数量 - --径向数据类别(如Z,V,W等各占一种)的数量
|
||||
"Scan Beam Index": struct.unpack('h', f.read(2)
|
||||
), # 波束编号 ---1-32 --波束编号
|
||||
"Horizontal_Estimated_Noise": struct.unpack('h', f.read(2)
|
||||
), # 径向的水平估计噪声 - --编码为实际噪声的 - 100倍
|
||||
"Vertical_Estimated_Noise": struct.unpack('h', f.read(2)
|
||||
), # 径向的垂直估计噪 - --编码为实际噪声的 - 100 倍
|
||||
|
||||
"PRF_FLAG": struct.unpack('I', f.read(4)), #重频标志, 11 – N1 PRF #1 ; 12 – N1 PRF #2; 21 – N2 PRF #1; 22 – N2 PRF #2; 排列方式:11128888:表示使用N1 PRF #1和PRF #2 #######################uint
|
||||
# 88882122:表示使用N2 PRF #1和PRF #2 11122122:表示使用N1和N2的PRF #1和PRF #2 (对应表2-7中09-13的描述)(8表示无效填充数据,弥补用0表示会出现的问题)
|
||||
# "Zip_Type": struct.unpack('h', f.read(2)
|
||||
# ), # 压缩类型 - --0 - 不压缩;1 - LZO压缩
|
||||
"Reversed": f.read(70) # 保留13bit
|
||||
}
|
||||
# print(f.tell())
|
||||
# f.seek(8672)
|
||||
el_n_ = RadialData.get("Elevation_Number")[0]
|
||||
azm_ = RadialData.get("Azimuth")[0]
|
||||
# el_ = RadialData.get("Elevation")[0]
|
||||
el_ = BEAM_CONFIG['%d' %(j+1)]["Rx_Beam_Elevation"][0]
|
||||
type_number = RadialData.get("Moment_Number")[0]
|
||||
for i in range(type_number):
|
||||
typeHeader = {
|
||||
# 共32字节
|
||||
"Data_Type": struct.unpack('I', f.read(4)), # 数据类型 - --具体径向数据类型见表2 - 6
|
||||
"Scale": struct.unpack('I', f.read(4)
|
||||
), # 比例 - --数据编码的比例
|
||||
"Offset": struct.unpack('I', f.read(4)
|
||||
), # 偏移 - --数据编码的偏移
|
||||
"Bin_Length": struct.unpack('h', f.read(2)
|
||||
), # 库字节长度 - --保存一个距离库值用的字节数
|
||||
"Flags": struct.unpack('h', f.read(2)
|
||||
), # 标志 - --数据标志位,暂不使用
|
||||
"Length": struct.unpack('I', f.read(4)
|
||||
), # 长度 - --距离库数据的长度,不包括当前的径向数据头大小
|
||||
"Reserved": f.read(12)
|
||||
}
|
||||
# print(typeHeader)
|
||||
data_type = typeHeader.get("Data_Type")[0]
|
||||
scale = typeHeader.get("Scale")[0]
|
||||
offset = typeHeader.get("Offset")[0]
|
||||
bin_length = typeHeader.get("Bin_Length")[0]
|
||||
block_length = typeHeader.get("Length")[0]
|
||||
data_body = f.read(block_length)
|
||||
dtype = "u%d" % bin_length
|
||||
# print(body)
|
||||
raw = np.frombuffer(data_body, dtype).astype(np.float64)
|
||||
# raw = np.asarray(struct.unpack(str(block_length) + "B", data_body)).astype(np.float64)
|
||||
raw[raw <= 5.] = np.nan
|
||||
value = (raw - offset) / scale
|
||||
# print(np.nanmin(value))
|
||||
# print(np.nanmax(value))
|
||||
if data_type == 2:
|
||||
# dbz[el_n_ - 1, k, :] = value
|
||||
dbz[el_n_ - 1, k, :len(value)] = value
|
||||
elif data_type == 3:
|
||||
# vel[el_n_ - 1, k, :] = value
|
||||
vel[el_n_ - 1, k, :len(value)] = value
|
||||
elif data_type == 4:
|
||||
# w[el_n_ - 1, k, :] = value
|
||||
w[el_n_ - 1, k, :len(value)] = value
|
||||
elif data_type == 7:
|
||||
# zdr[el_n_ - 1, k, :] = value
|
||||
zdr[el_n_ - 1, k, :len(value)] = value
|
||||
elif data_type == 9:
|
||||
# cc[el_n_ - 1, k, :] = value
|
||||
cc[el_n_ - 1, k, :len(value)] = value
|
||||
elif data_type == 10:
|
||||
# dp[el_n_ - 1, k, :] = value
|
||||
dp[el_n_ - 1, k, :len(value)] = value
|
||||
elif data_type == 11:
|
||||
# kdp[el_n_ - 1, k, :] = value
|
||||
kdp[el_n_ - 1, k, :len(value)] = value
|
||||
|
||||
el_n[el_n_ - 1, k] = el_n_
|
||||
azm[el_n_ - 1, k] = azm_
|
||||
el[el_n_ - 1, k] = el_
|
||||
# print(f"the No.{el_n_} elevation is {el_}")
|
||||
gc.collect()
|
||||
|
||||
result = {
|
||||
'radarNumber': site_config['Site_Code'],
|
||||
'longitude': site_config['Longitude'],
|
||||
'latitude': site_config['Latitude'],
|
||||
'altitude': site_config['Antenna_Height'],
|
||||
'radarRange': radar_range,
|
||||
'azimuthData': azm[1, :],
|
||||
'elevationData': el[:, 1],
|
||||
'polar_type': polar_type
|
||||
}
|
||||
result.update(_data_dict)
|
||||
f.close()
|
||||
return result
|
||||
252
loaders/etws_loader/src/lib.rs
Normal file
252
loaders/etws_loader/src/lib.rs
Normal file
@ -0,0 +1,252 @@
|
||||
mod error;
|
||||
mod raw;
|
||||
use raw::parse_raw_data;
|
||||
mod parser;
|
||||
use abi_stable::{
|
||||
export_root_module,
|
||||
prefix_type::PrefixTypeTrait,
|
||||
rvec, sabi_extern_fn,
|
||||
sabi_trait::prelude::TD_Opaque,
|
||||
std_types::{
|
||||
RNone, ROk,
|
||||
ROption::RSome,
|
||||
RResult::{self, RErr},
|
||||
RStr, RString, RVec,
|
||||
},
|
||||
};
|
||||
use parser::{Record, ValueResult};
|
||||
|
||||
use radarg_plugin_interface::{
|
||||
DataLoaderPlugin, DataLoaderPlugin_TO, Error, GridDataInfo, LoadedData, PluginId, PluginMod,
|
||||
PluginMod_Ref, PluginType, ProbeDataType, RadarGridData, VecResult,
|
||||
};
|
||||
|
||||
macro_rules! data_rvec {
|
||||
($data:ident, $({$parsed_vec:tt => $abi_stable_rvec:tt}),+) => {
|
||||
match $data {
|
||||
$(
|
||||
ValueResult::$parsed_vec(data) => VecResult::$abi_stable_rvec(RVec::from(data)),
|
||||
)+
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! data_type {
|
||||
($datetype:ident, $({ $($name:literal)|+ => $type:tt }),+) => {
|
||||
|
||||
match $datetype {
|
||||
$(
|
||||
$($name)|+ => ProbeDataType::$type,
|
||||
)+
|
||||
_ => ProbeDataType::Unknown
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
#[export_root_module]
|
||||
fn instantiate_root_module() -> PluginMod_Ref {
|
||||
PluginMod { new }.leak_into_prefix()
|
||||
}
|
||||
|
||||
struct ETWSLoader {
|
||||
id: PluginId,
|
||||
}
|
||||
|
||||
impl DataLoaderPlugin for ETWSLoader {
|
||||
fn plugin_id(&self) -> &PluginId {
|
||||
&self.id
|
||||
}
|
||||
|
||||
fn load(&self, path: RStr<'_>) -> RResult<RVec<LoadedData>, Error> where {
|
||||
let path = path.as_str();
|
||||
let c = Record::parse_from_path(path.to_string())
|
||||
.map(|record| {
|
||||
let result = record
|
||||
.blocks
|
||||
.into_iter()
|
||||
.map(|b| {
|
||||
let data = b.data;
|
||||
let converted_data = data_rvec!(
|
||||
data,
|
||||
{I16 => I16},
|
||||
{F32 => F32},
|
||||
{F64 => F64},
|
||||
{I32 => I32},
|
||||
{U32 => U32},
|
||||
{I64 => I64},
|
||||
{U64 => U64},
|
||||
{I8 => I8},
|
||||
{U8 => U8}
|
||||
);
|
||||
|
||||
let dimension_values = convert_nested_vec_to_rvec(b.info.dimension_values);
|
||||
let dimension_size = convert_vec_to_rvec(
|
||||
b.info
|
||||
.dimension_size
|
||||
.into_iter()
|
||||
.map(|p| p as usize)
|
||||
.collect::<Vec<_>>(),
|
||||
);
|
||||
let dimension_names = convert_vec_to_rvec(
|
||||
b.info
|
||||
.dimension_des
|
||||
.into_iter()
|
||||
.map(RString::from)
|
||||
.collect::<Vec<_>>(),
|
||||
);
|
||||
|
||||
let fill_value = b.info.fill_value;
|
||||
let value_name = RString::from(b.info.value_name);
|
||||
let value_description = RString::from(b.info.value_des);
|
||||
let datetime = record.filetime.timestamp();
|
||||
|
||||
let value_key = value_name.as_str();
|
||||
|
||||
let data_type = data_type!(
|
||||
value_key,
|
||||
{ "ET" => ET },
|
||||
{ "DBZ" | "CR" | "FR" | "R" => DBZ},
|
||||
{ "VIL" => VIL},
|
||||
{ "EB" => EB},
|
||||
{ "V" => V},
|
||||
{ "ZDR" => ZDR},
|
||||
{ "PHIDP" => PHIDP},
|
||||
{ "KDP" => KDP},
|
||||
{ "CC" =>CC},
|
||||
{ "HCA" => HCA},
|
||||
{ "QPE" => QPE},
|
||||
{ "QPF" => QPF}
|
||||
);
|
||||
|
||||
let grid_info = GridDataInfo {
|
||||
shape: dimension_size,
|
||||
dimensions: dimension_values,
|
||||
dimension_names,
|
||||
fill_value,
|
||||
datetime: RSome(datetime),
|
||||
value_description: RSome(value_description),
|
||||
maybe_probe_data_type: RSome(data_type),
|
||||
value_name,
|
||||
dimension_description: "Wrong".into(),
|
||||
};
|
||||
|
||||
LoadedData::RadarGridData(RadarGridData {
|
||||
data: converted_data,
|
||||
info: grid_info,
|
||||
})
|
||||
})
|
||||
.collect::<RVec<_>>();
|
||||
result
|
||||
})
|
||||
.or_else(|_| {
|
||||
let result = parse_raw_data(path)
|
||||
.map(|result| {
|
||||
let data = result.datas;
|
||||
|
||||
let shape = rvec![
|
||||
result.els.len() as usize,
|
||||
result.azs.len() as usize,
|
||||
result.ranges.len() as usize
|
||||
];
|
||||
|
||||
let dimensions = rvec![
|
||||
RVec::from(result.els),
|
||||
RVec::from(result.azs),
|
||||
RVec::from(result.ranges)
|
||||
];
|
||||
|
||||
let dimension_names = rvec!["el".into(), "az".into(), "range".into()];
|
||||
let datetime = result.datetime;
|
||||
|
||||
let loaded = data
|
||||
.into_iter()
|
||||
.map(move |(k, v)| {
|
||||
let data_type = data_type!(
|
||||
k,
|
||||
{ "ET" => ET },
|
||||
{ "DBZ" | "CR" | "FR" | "R" => 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::<RVec<_>>();
|
||||
|
||||
loaded
|
||||
})
|
||||
.map_err(|_| Error::UnsupportedFormat)?;
|
||||
Ok(result)
|
||||
});
|
||||
|
||||
RResult::from(c)
|
||||
}
|
||||
|
||||
fn plugin_info(&self) -> radarg_plugin_interface::PluginInfo where {
|
||||
radarg_plugin_interface::PluginInfo {
|
||||
plugin_type: "DataLoader".into(),
|
||||
name: "ETWS_Loader".into(),
|
||||
version: "0.1.0".into(),
|
||||
author: "Tsuki".into(),
|
||||
description: RSome("ETWS Loader".into()),
|
||||
url: RSome("https://keitsuki.club".into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_iter_to_rvec<T>(raw: impl Iterator<Item = T>) -> RVec<T> {
|
||||
RVec::from(raw.collect::<Vec<_>>())
|
||||
}
|
||||
|
||||
fn convert_vec_to_rvec<T>(raw: Vec<T>) -> RVec<T> {
|
||||
RVec::from(raw)
|
||||
}
|
||||
|
||||
fn convert_nested_vec_to_rvec<T>(raw: Vec<Vec<T>>) -> RVec<RVec<T>> {
|
||||
RVec::from(raw.into_iter().map(RVec::from).collect::<Vec<_>>())
|
||||
}
|
||||
|
||||
#[sabi_extern_fn]
|
||||
pub fn new(plugin_id: PluginId) -> RResult<PluginType, Error> {
|
||||
let this = ETWSLoader { id: plugin_id };
|
||||
ROk(DataLoaderPlugin_TO::from_value(this, TD_Opaque))
|
||||
}
|
||||
|
||||
// 测试模块
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
// 导入外部作用域中的所有项
|
||||
use super::*;
|
||||
|
||||
// 一个简单的测试
|
||||
#[test]
|
||||
|
||||
fn test() {
|
||||
let result =
|
||||
Record::parse_from_path("/Volumes/data2/RadarArray/ShaoXing/radarData/OutputProducts/RadarProducts/BasicProductsX/20230627/20230627163400/ZJSXAA_20230627163400_VIL.dat.gz")
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
@ -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 {
|
||||
753
loaders/etws_loader/src/raw.rs
Normal file
753
loaders/etws_loader/src/raw.rs
Normal file
@ -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<f64>,
|
||||
pub azs: Vec<f64>,
|
||||
pub ranges: Vec<f64>,
|
||||
pub datas: HashMap<&'static str, Vec<f64>>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct SiteConfig {
|
||||
site_code: String,
|
||||
site_name: String,
|
||||
latitude: f32,
|
||||
longitude: f32,
|
||||
antenna_height: u32,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct TaskConfig {
|
||||
task_name: String,
|
||||
task_description: String,
|
||||
polarization_type: u32,
|
||||
scan_type: u32,
|
||||
scan_beam_number: u32,
|
||||
cut_number: u32,
|
||||
ray_order: u32,
|
||||
scan_start_time: i64,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct BeamConfig {
|
||||
cut_index: i16,
|
||||
tx_beam_index: i16,
|
||||
rx_beam_elevation: f32,
|
||||
tx_beam_gain: f32,
|
||||
rx_beam_width_h: f32,
|
||||
rx_beam_width_v: f32,
|
||||
rx_beam_gain: f32,
|
||||
process_mode: String,
|
||||
wave_form: String,
|
||||
n1_prf1: f32,
|
||||
n1_prf2: f32,
|
||||
n2_prf1: f32,
|
||||
n2_prf2: f32,
|
||||
dealiasing_mode: u32,
|
||||
azimuth: f32,
|
||||
start_angle: f32,
|
||||
end_angle: f32,
|
||||
angular_resolution: f32,
|
||||
scan_speed: f32,
|
||||
log_resolution: f32,
|
||||
doppler_resolution: f32,
|
||||
maximum_range1: u32,
|
||||
maximum_range2: u32,
|
||||
start_range: u32,
|
||||
sample1: u32,
|
||||
sample2: u32,
|
||||
phase_mode: u32,
|
||||
atmospheric_loss: f32,
|
||||
nyquist_speed: f32,
|
||||
moments_mask: i64,
|
||||
moments_size_mask: i64,
|
||||
misc_filter_mask: u32,
|
||||
sqi_threshold: f32,
|
||||
sig_threshold: f32,
|
||||
csr_threshold: f32,
|
||||
log_threshold: f32,
|
||||
cpa_threshold: f32,
|
||||
pmi_threshold: f32,
|
||||
dplog_threshold: f32,
|
||||
thresholds_r: [u8; 4],
|
||||
dbt_mask: u32,
|
||||
dbz_mask: u32,
|
||||
velocity_mask: u32,
|
||||
spectrum_width_mask: u32,
|
||||
dp_mask: u32,
|
||||
direction: u32,
|
||||
ground_clutter_classifier_type: i16,
|
||||
ground_clutter_filter_type: i16,
|
||||
ground_clutter_filter_notch_width: i16,
|
||||
ground_clutter_filter_window: i16,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct TypeHeader {
|
||||
data_type: u32,
|
||||
scale: u32,
|
||||
offset: u32,
|
||||
bin_length: u16,
|
||||
flags: u16,
|
||||
length: u32,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct RadialData {
|
||||
radial_state: u32,
|
||||
spot_blank: u32,
|
||||
sequence_number: u32,
|
||||
radial_number: u32,
|
||||
elevation_number: u32,
|
||||
azimuth: f32,
|
||||
elevation: f32,
|
||||
seconds: i64,
|
||||
microseconds: u32,
|
||||
length_of_data: u32,
|
||||
moment_number: u32,
|
||||
scan_beam_index: i16,
|
||||
horizontal_estimated_noise: i16,
|
||||
vertical_estimated_noise: i16,
|
||||
prf_flag: u32,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct GenericHeader {
|
||||
magic_number: u32,
|
||||
major_version: u16,
|
||||
minor_version: u16,
|
||||
generic_type: u32,
|
||||
product_type: u32,
|
||||
reserved: [u8; 16],
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct SubPulseConfig {
|
||||
strategy: u32,
|
||||
modulation: u32,
|
||||
frequency: f32,
|
||||
bandwidth: f32,
|
||||
width: u32,
|
||||
horizontal_noise: f32,
|
||||
vertical_noise: f32,
|
||||
horizontal_calibration: f32,
|
||||
vertical_calibration: f32,
|
||||
horizontal_noise_temperature: f32,
|
||||
vertical_noise_temperature: f32,
|
||||
zdr_calibration: f32,
|
||||
phidp_calibration: f32,
|
||||
ldr_calibration: f32,
|
||||
pulse_points: i16,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct ScanConfig {
|
||||
beam_index: u32,
|
||||
beam_type: u32,
|
||||
sub_pulse_number: u32,
|
||||
tx_beam_direction: f32,
|
||||
tx_beam_width_h: f32,
|
||||
tx_beam_width_v: f32,
|
||||
tx_beam_gain: f32,
|
||||
sub_pulse_configs: Vec<SubPulseConfig>,
|
||||
}
|
||||
|
||||
fn parse_scan_config(input: &[u8]) -> IResult<&[u8], ScanConfig> {
|
||||
let (input, beam_index) = le_u32(input)?;
|
||||
let (input, beam_type) = le_u32(input)?;
|
||||
let (input, sub_pulse_number) = le_u32(input)?;
|
||||
let (input, tx_beam_direction) = le_f32(input)?;
|
||||
let (input, tx_beam_width_h) = le_f32(input)?;
|
||||
let (input, tx_beam_width_v) = le_f32(input)?;
|
||||
let (input, tx_beam_gain) = le_f32(input)?;
|
||||
let (input, _) = take(100usize)(input)?; // Skip reserved bytes
|
||||
|
||||
// Parse the SubPulseConfigs
|
||||
let mut sub_pulse_configs = Vec::new();
|
||||
let mut input = input;
|
||||
for _ in 0..4 {
|
||||
let (new_input, sub_pulse_config) = parse_sub_pulse_config(input)?;
|
||||
input = new_input;
|
||||
sub_pulse_configs.push(sub_pulse_config);
|
||||
}
|
||||
|
||||
let scan_config = ScanConfig {
|
||||
beam_index,
|
||||
beam_type,
|
||||
sub_pulse_number,
|
||||
tx_beam_direction,
|
||||
tx_beam_width_h,
|
||||
tx_beam_width_v,
|
||||
tx_beam_gain,
|
||||
sub_pulse_configs,
|
||||
};
|
||||
|
||||
Ok((input, scan_config))
|
||||
}
|
||||
|
||||
fn parse_sub_pulse_config(input: &[u8]) -> IResult<&[u8], SubPulseConfig> {
|
||||
let (input, strategy) = le_u32(input)?;
|
||||
let (input, modulation) = le_u32(input)?;
|
||||
let (input, frequency) = le_f32(input)?;
|
||||
let (input, bandwidth) = le_f32(input)?;
|
||||
let (input, width) = le_u32(input)?;
|
||||
let (input, horizontal_noise) = le_f32(input)?;
|
||||
let (input, vertical_noise) = le_f32(input)?;
|
||||
let (input, horizontal_calibration) = le_f32(input)?;
|
||||
let (input, vertical_calibration) = le_f32(input)?;
|
||||
let (input, horizontal_noise_temperature) = le_f32(input)?;
|
||||
let (input, vertical_noise_temperature) = le_f32(input)?;
|
||||
let (input, zdr_calibration) = le_f32(input)?;
|
||||
let (input, phidp_calibration) = le_f32(input)?;
|
||||
let (input, ldr_calibration) = le_f32(input)?;
|
||||
let (input, pulse_points) = nom::number::complete::le_i16(input)?;
|
||||
let (input, _) = take(70usize)(input)?; // Skip reserved bytes
|
||||
|
||||
let sub_pulse_config = SubPulseConfig {
|
||||
strategy,
|
||||
modulation,
|
||||
frequency,
|
||||
bandwidth,
|
||||
width,
|
||||
horizontal_noise,
|
||||
vertical_noise,
|
||||
horizontal_calibration,
|
||||
vertical_calibration,
|
||||
horizontal_noise_temperature,
|
||||
vertical_noise_temperature,
|
||||
zdr_calibration,
|
||||
phidp_calibration,
|
||||
ldr_calibration,
|
||||
pulse_points,
|
||||
};
|
||||
|
||||
Ok((input, sub_pulse_config))
|
||||
}
|
||||
|
||||
pub fn parse_raw_data<P: AsRef<Path>>(path: P) -> io::Result<RadarData> {
|
||||
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<u8>) -> io::Result<RadarData> {
|
||||
let total_length = data.len() as u64;
|
||||
// 使用 Cursor 来处理 Vec<u8>
|
||||
let mut cursor = Cursor::new(data);
|
||||
|
||||
// 读取 GENERIC_HEADER
|
||||
let mut buffer = vec![0u8; 32];
|
||||
cursor.read_exact(&mut buffer)?;
|
||||
let (_, generic_header) = parse_generic_header(&buffer).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<Vec<f64>> {
|
||||
let raw = match bin_length {
|
||||
1 => {
|
||||
let new_raw: Vec<f64> = raw.into_iter().map(|v| *v as f64).collect();
|
||||
new_raw
|
||||
}
|
||||
2 => {
|
||||
let new_raw: Vec<f64> = cast_slice(&raw)
|
||||
.into_iter()
|
||||
.map(|v: &u16| *v as f64)
|
||||
.collect();
|
||||
new_raw
|
||||
}
|
||||
4 => {
|
||||
let new_raw: Vec<f64> = cast_slice(&raw)
|
||||
.into_iter()
|
||||
.map(|v: &u32| *v as f64)
|
||||
.collect();
|
||||
new_raw
|
||||
}
|
||||
8 => {
|
||||
let new_raw: Vec<f64> = cast_slice(&raw)
|
||||
.into_iter()
|
||||
.map(|v: &u64| *v as f64)
|
||||
.collect();
|
||||
new_raw
|
||||
}
|
||||
_ => {
|
||||
let new_raw: Vec<f64> = raw.into_iter().map(|v| *v as f64).collect();
|
||||
new_raw
|
||||
}
|
||||
};
|
||||
Ok(raw)
|
||||
}
|
||||
|
||||
fn beam_block_exact(cursor: &mut Cursor<Vec<u8>>, header: &TypeHeader) -> io::Result<Vec<u8>> {
|
||||
let mut buf = vec![0u8; header.length as usize];
|
||||
cursor.read_exact(&mut buf)?;
|
||||
Ok(buf)
|
||||
}
|
||||
|
||||
fn data_type(typ: u32) -> &'static str {
|
||||
match typ {
|
||||
2 => "DBZ",
|
||||
3 => "VEL",
|
||||
4 => "SW",
|
||||
7 => "ZDR",
|
||||
9 => "CC",
|
||||
10 => "PHIDP",
|
||||
11 => "KDP",
|
||||
_ => "Unknown",
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_final_data(
|
||||
all_length: u64,
|
||||
cut_number: usize,
|
||||
mut cursor: Cursor<Vec<u8>>,
|
||||
) -> io::Result<(
|
||||
HashMap<&'static str, Vec<f64>>,
|
||||
Vec<f64>,
|
||||
Vec<f64>,
|
||||
Vec<f64>,
|
||||
)> {
|
||||
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();
|
||||
}
|
||||
}
|
||||
@ -94,4 +94,4 @@ path = "../radarg_core"
|
||||
[dependencies.adw]
|
||||
package = "libadwaita"
|
||||
version = "0.7.0"
|
||||
features = ["v1_4"]
|
||||
features = ["v1_5"]
|
||||
|
||||
@ -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<OpenAction> = {
|
||||
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)),
|
||||
|
||||
@ -22,6 +22,7 @@ impl Debug for MonitorInputMsg {
|
||||
#[derive(Debug)]
|
||||
pub enum MonitorOutputMsg {
|
||||
Attached(Rc<RefCell<ModulePackage>>),
|
||||
Fc,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -16,8 +16,12 @@ use std::{
|
||||
};
|
||||
|
||||
fn compute_plugin_path(base_name: &str) -> io::Result<PathBuf> {
|
||||
let debug_dir = "./target/debug".as_ref_::<Path>().into_::<PathBuf>();
|
||||
let release_dir = "./target/release".as_ref_::<Path>().into_::<PathBuf>();
|
||||
let debug_dir = "./loaders/target/debug"
|
||||
.as_ref_::<Path>()
|
||||
.into_::<PathBuf>();
|
||||
let release_dir = "./loaders/target/release"
|
||||
.as_ref_::<Path>()
|
||||
.into_::<PathBuf>();
|
||||
|
||||
let debug_path = RawLibrary::path_in_directory(&debug_dir, base_name, LibrarySuffix::NoSuffix);
|
||||
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -63,7 +63,11 @@ impl Setting {
|
||||
name, cmap,
|
||||
{DBZ => "DBZ"},
|
||||
{V => "VEL"},
|
||||
{VIL => "VIL"}
|
||||
{VIL => "VIL"},
|
||||
{CC => "CC"},
|
||||
{KDP => "KDP"},
|
||||
{ZDR => "ZDR"},
|
||||
{PHIDP => "PHIDP"}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -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 {
|
||||
$(
|
||||
|
||||
Loading…
Reference in New Issue
Block a user