level2 update
This commit is contained in:
parent
57da65e4e8
commit
dce451befa
68
Cargo.lock
generated
68
Cargo.lock
generated
@ -9,7 +9,9 @@ dependencies = [
|
||||
"bzip2",
|
||||
"chrono",
|
||||
"flate2",
|
||||
"ndarray",
|
||||
"nom",
|
||||
"nom-derive",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
"thiserror",
|
||||
@ -226,6 +228,16 @@ dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "matrixmultiply"
|
||||
version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "090126dc04f95dc0d1c1c91f61bdd474b3930ca064c1edc8a849da2c6cbe1e77"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"rawpointer",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.5.0"
|
||||
@ -247,6 +259,19 @@ dependencies = [
|
||||
"adler",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ndarray"
|
||||
version = "0.15.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "adb12d4e967ec485a5f71c6311fe28158e9d6f4bc4a447b474184d0f91a8fa32"
|
||||
dependencies = [
|
||||
"matrixmultiply",
|
||||
"num-complex",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
"rawpointer",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nom"
|
||||
version = "7.1.3"
|
||||
@ -257,6 +282,37 @@ dependencies = [
|
||||
"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-complex"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ba157ca0885411de85d6ca030ba7e2a83a28636056c7c699b07c8b6f7383214"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.45"
|
||||
@ -306,6 +362,18 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rawpointer"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3"
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4"
|
||||
|
||||
[[package]]
|
||||
name = "scratch"
|
||||
version = "1.0.5"
|
||||
|
||||
@ -13,3 +13,5 @@ thiserror = "1.0.40"
|
||||
bzip2 = "0.4.4"
|
||||
nom = "7.1.3"
|
||||
chrono = "0.4.24"
|
||||
nom-derive = "0.10.1"
|
||||
ndarray = "0.15.6"
|
||||
|
||||
14
src/error.rs
14
src/error.rs
@ -1,4 +1,3 @@
|
||||
use nom::error::Error;
|
||||
use std::{error, io};
|
||||
|
||||
use thiserror::Error;
|
||||
@ -10,10 +9,19 @@ pub enum UnexpectedError {
|
||||
#[from]
|
||||
source: io::Error,
|
||||
},
|
||||
|
||||
#[error("")]
|
||||
UnknownFormat,
|
||||
|
||||
#[error("")]
|
||||
DataParseError,
|
||||
}
|
||||
|
||||
impl<I> From<nom::error::Error<I>> for UnexpectedError {
|
||||
fn from(value: nom::error::Error<I>) -> Self {
|
||||
UnexpectedError::DataParseError
|
||||
}
|
||||
}
|
||||
impl<I> From<nom::Err<I>> for UnexpectedError {
|
||||
fn from(value: nom::Err<I>) -> Self {
|
||||
UnexpectedError::DataParseError
|
||||
}
|
||||
}
|
||||
|
||||
36
src/format/cc.rs
Normal file
36
src/format/cc.rs
Normal file
@ -0,0 +1,36 @@
|
||||
struct CCHeader<'a> {
|
||||
fs_file_id: &'a str,
|
||||
ff_version_no: f32,
|
||||
fl_file_header_length: i32,
|
||||
fs_country: &'a str,
|
||||
fs_province: &'a str,
|
||||
fs_station: &'a str,
|
||||
fs_station_number: &'a str,
|
||||
fs_radar_type: &'a str,
|
||||
fs_longitude: &'a str,
|
||||
fs_latitude: &'a str,
|
||||
fl_longitude_value: i32,
|
||||
fl_latitude_value: i32,
|
||||
fl_height: i32,
|
||||
fsh_max_angle: i16,
|
||||
fsh_opti_angle: i16,
|
||||
fl_antenna_g: i32,
|
||||
fus_beam_h: u16,
|
||||
fus_beam_l: u16,
|
||||
fuc_polarization: u8,
|
||||
fus_sidelobe: u16,
|
||||
fl_power: i32,
|
||||
fl_wavelength: i32,
|
||||
fus_log_a: u16,
|
||||
fus_line_a: u16,
|
||||
fus_agcp: u16,
|
||||
fus_log_min_power: u16,
|
||||
fus_line_min_power: u16,
|
||||
fuc_clutter_t: u8,
|
||||
fuc_velocity_p: u8,
|
||||
fuc_filter_p: u8,
|
||||
fuc_noise_t: u8,
|
||||
fuc_sqit: u8,
|
||||
fuc_intensity_c: u8,
|
||||
fuc_intensity_r: u8,
|
||||
}
|
||||
222
src/format/cinrad.rs
Normal file
222
src/format/cinrad.rs
Normal file
@ -0,0 +1,222 @@
|
||||
use std::fs::File;
|
||||
use std::path::Path;
|
||||
use std::str::FromStr;
|
||||
|
||||
use chrono::prelude::*;
|
||||
use chrono::Duration;
|
||||
use ndarray::prelude::*;
|
||||
use nom::branch::alt;
|
||||
use nom::bytes::complete::*;
|
||||
use nom::multi::many0;
|
||||
use nom::sequence::tuple;
|
||||
use nom::Err;
|
||||
use nom::IResult;
|
||||
use nom::Parser;
|
||||
use nom_derive::NomLE;
|
||||
use nom_derive::Parse;
|
||||
|
||||
use crate::error::UnexpectedError;
|
||||
use crate::utils::decompress;
|
||||
|
||||
use super::Data;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct CinradBlock {
|
||||
t: RadarType,
|
||||
info: Info,
|
||||
res: Res,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum RadarType {
|
||||
SA,
|
||||
SB,
|
||||
SC,
|
||||
CA,
|
||||
CB,
|
||||
CD,
|
||||
CC,
|
||||
CC2,
|
||||
}
|
||||
|
||||
impl FromStr for RadarType {
|
||||
type Err = UnexpectedError;
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s {
|
||||
"SA" => Ok(RadarType::SA),
|
||||
"SB" => Ok(RadarType::SB),
|
||||
"SC" => Ok(RadarType::SC),
|
||||
"CA" => Ok(RadarType::CA),
|
||||
"CB" => Ok(RadarType::CB),
|
||||
"CD" => Ok(RadarType::CD),
|
||||
"CC" => Ok(RadarType::CC),
|
||||
"CC2" => Ok(RadarType::CC2),
|
||||
_ => Err(UnexpectedError::UnknownFormat),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, NomLE)]
|
||||
pub struct Info {
|
||||
time: u32,
|
||||
day: u16,
|
||||
unambiguous_distance: u16,
|
||||
azimuth: u16,
|
||||
radial_num: u16,
|
||||
radial_state: u16,
|
||||
elevation: u16,
|
||||
el_num: u16,
|
||||
first_gate_r: u16,
|
||||
first_gate_v: u16,
|
||||
gate_length_r: u16,
|
||||
gate_length_v: u16,
|
||||
gate_num_r: u16,
|
||||
gate_num_v: u16,
|
||||
sector_num: u16,
|
||||
system_coff: u32,
|
||||
r_pointer: u16,
|
||||
v_pointer: u16,
|
||||
w_pointer: u16,
|
||||
v_reso: u16,
|
||||
vcp_mode: u16,
|
||||
res2: [u16; 4],
|
||||
r_pointer_2: u16,
|
||||
v_pointer_2: u16,
|
||||
w_pointer_2: u16,
|
||||
nyquist_vel: u16,
|
||||
}
|
||||
|
||||
#[derive(Debug, NomLE)]
|
||||
pub struct Res {
|
||||
res_3: [u16; 19],
|
||||
}
|
||||
|
||||
#[derive(Debug, NomLE)]
|
||||
struct SabData {
|
||||
r: [u8; 460],
|
||||
v: [u8; 920],
|
||||
w: [u8; 920],
|
||||
res4: [u16; 2],
|
||||
}
|
||||
|
||||
#[derive(Debug, NomLE)]
|
||||
struct CabData {
|
||||
r: [u8; 800],
|
||||
v: [u8; 1600],
|
||||
w: [u8; 1600],
|
||||
res4: [u16; 2],
|
||||
}
|
||||
|
||||
#[derive(Debug, NomLE)]
|
||||
struct SpecialData {
|
||||
r: [u8; 1000],
|
||||
v: [u8; 1000],
|
||||
w: [u8; 1000],
|
||||
}
|
||||
|
||||
fn get_radar_type<S: AsRef<str>>(
|
||||
input: &Vec<u8>,
|
||||
file_name: S,
|
||||
) -> Result<RadarType, UnexpectedError> {
|
||||
let buf = &input[99..109];
|
||||
|
||||
match buf.as_ref() {
|
||||
b"CINRAD/SC" => Ok(RadarType::SC),
|
||||
b"CINRAD/CD" => Ok(RadarType::CD),
|
||||
_ => {
|
||||
let mut buf = &input[116..125];
|
||||
|
||||
if buf.as_ref() == b"CINRAD/CC" {
|
||||
Ok(RadarType::CC)
|
||||
} else {
|
||||
let f_n = file_name.as_ref();
|
||||
if f_n.starts_with("RADA") {
|
||||
let sp = f_n.split("-").collect::<Vec<_>>();
|
||||
if sp.len() > 2 {
|
||||
RadarType::from_str(sp[2])
|
||||
} else {
|
||||
Err(UnexpectedError::UnknownFormat)
|
||||
}
|
||||
} else if f_n.starts_with("Z") {
|
||||
let spart = f_n.split("_").collect::<Vec<_>>();
|
||||
if spart.len() > 7 {
|
||||
RadarType::from_str(spart[7])
|
||||
} else {
|
||||
Err(UnexpectedError::UnknownFormat)
|
||||
}
|
||||
} else {
|
||||
Err(UnexpectedError::UnknownFormat)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parse(input: &[u8], radar_type: RadarType) -> Result<(), UnexpectedError> {
|
||||
match radar_type {
|
||||
RadarType::SA | RadarType::SB => {
|
||||
let header_flag = take(28usize);
|
||||
let (_, parsed_data) = many0(tuple((
|
||||
header_flag,
|
||||
Info::parse,
|
||||
Res::parse,
|
||||
SabData::parse,
|
||||
)))(input)?;
|
||||
|
||||
parsed_data.iter().for_each(|x| {
|
||||
let ele = x.1.elevation as f64 / 8.0 * (180.0 / 4096.0);
|
||||
let azi = x.1.azimuth as f64 / 8.0 * (180.0 / 4096.0);
|
||||
let ran = x.1.radial_num;
|
||||
|
||||
if (ele - 0.5767822265625).abs() < f64::EPSILON {
|
||||
println!("ele: {:?}, azi: {:?}, ran: {:?}", ele, azi, ran);
|
||||
}
|
||||
});
|
||||
|
||||
// let (header, info, res, _) = &parsed_data;
|
||||
// let scan_time = Utc.with_ymd_and_hms(1969, 12, 31, 0, 0, 0).unwrap()
|
||||
// + Duration::days(info.day as i64)
|
||||
// + Duration::milliseconds(info.time as i64);
|
||||
|
||||
// println!("scan time :{:?}", scan_time);
|
||||
}
|
||||
RadarType::CA | RadarType::CB => {}
|
||||
RadarType::CC2 => {}
|
||||
RadarType::CC => {}
|
||||
RadarType::SC | RadarType::CD => {}
|
||||
_ => {}
|
||||
}
|
||||
// match t {
|
||||
// RadarType::SA | RadarType::SB => {
|
||||
// let (_, parsed_data) = many0(tuple((
|
||||
// Header::parse,
|
||||
// Info::parse,
|
||||
// Res::parse,
|
||||
// SabData::parse,
|
||||
// )))(input)?;
|
||||
// }
|
||||
// RadarType::CA | RadarType::CB => {
|
||||
// let (_, parsed_data) =
|
||||
// tuple((Header::parse, Info::parse, Res::parse, CabData::parse))(input)?;
|
||||
// }
|
||||
// RadarType::CC2 => {}
|
||||
// RadarType::CC => {}
|
||||
// RadarType::SC | RadarType::CD => {}
|
||||
// _ => {}
|
||||
// }
|
||||
Ok(())
|
||||
}
|
||||
pub struct Cinrad {}
|
||||
|
||||
impl Data for Cinrad {
|
||||
fn parse(path: impl AsRef<Path>) -> Result<Self, UnexpectedError> {
|
||||
let p = path.as_ref();
|
||||
let filename = p.file_name().unwrap().to_str().unwrap();
|
||||
|
||||
let mut f = File::open(p)?;
|
||||
let depressed = decompress(&mut f)?;
|
||||
let radar_type = get_radar_type(&depressed, filename)?;
|
||||
parse(&depressed, radar_type)?;
|
||||
Ok(Self {})
|
||||
}
|
||||
}
|
||||
8
src/format/mod.rs
Normal file
8
src/format/mod.rs
Normal file
@ -0,0 +1,8 @@
|
||||
mod cc;
|
||||
mod cinrad;
|
||||
use crate::error::UnexpectedError;
|
||||
pub use cinrad::Cinrad;
|
||||
use std::path::Path;
|
||||
pub trait Data: Sized {
|
||||
fn parse(path: impl AsRef<Path>) -> Result<Self, UnexpectedError>;
|
||||
}
|
||||
10
src/main.rs
10
src/main.rs
@ -1,5 +1,15 @@
|
||||
use std::fs::File;
|
||||
|
||||
mod error;
|
||||
mod format;
|
||||
mod product;
|
||||
mod utils;
|
||||
|
||||
use format::Cinrad;
|
||||
use format::Data;
|
||||
fn main() {
|
||||
println!("Hello, world!");
|
||||
|
||||
let path = "/Users/ruomu/Library/Containers/com.tencent.WeWorkMac/Data/Documents/Profiles/8174C20601DD24B17112F7CC37A11CD9/Caches/Files/2023-04/e93ebe1aba50883b9bc661d7a44aee8e/Z_RADR_I_Z9595_20230324024700_O_DOR_SA_CAP.bin.bz2";
|
||||
let cinrad = Cinrad::parse(path).unwrap();
|
||||
}
|
||||
|
||||
29
src/utils.rs
Normal file
29
src/utils.rs
Normal file
@ -0,0 +1,29 @@
|
||||
use bzip2::read::{BzDecoder, BzEncoder};
|
||||
use bzip2::Decompress;
|
||||
use flate2::bufread::DeflateDecoder;
|
||||
use std::io::{prelude::*, SeekFrom};
|
||||
use std::{fs::File, io::BufReader, io::Read};
|
||||
|
||||
pub fn decompress(file: &mut File) -> Result<Vec<u8>, std::io::Error> {
|
||||
let mut bf: [u8; 3] = [0, 0, 0];
|
||||
file.read_exact(&mut bf)?;
|
||||
|
||||
let mut result = Vec::new();
|
||||
|
||||
match bf.as_ref() {
|
||||
b"\x1f\x8b " => {
|
||||
let reader = BufReader::new(file);
|
||||
let mut decoder = DeflateDecoder::new(reader);
|
||||
decoder.read_to_end(&mut result)?;
|
||||
}
|
||||
b"BZh" => {
|
||||
file.seek(SeekFrom::Start(0))?;
|
||||
let mut bz = BzDecoder::new(file);
|
||||
bz.read_to_end(&mut result)?;
|
||||
}
|
||||
_ => {
|
||||
file.read_to_end(&mut result)?;
|
||||
}
|
||||
}
|
||||
Ok(result)
|
||||
}
|
||||
108
tools.py
Normal file
108
tools.py
Normal file
@ -0,0 +1,108 @@
|
||||
import os
|
||||
import re
|
||||
table = {
|
||||
"u": "u",
|
||||
"i" : "i",
|
||||
"b" : "i8",
|
||||
"B" : "u8",
|
||||
"S" : "&'a str",
|
||||
"f" : "f",
|
||||
}
|
||||
|
||||
_S_INFO = [
|
||||
("time", "u4"),
|
||||
("day", "u2"),
|
||||
("unambiguous_distance", "u2"),
|
||||
("azimuth", "u2"),
|
||||
("radial_num", "u2"),
|
||||
("radial_state", "u2"),
|
||||
("elevation", "u2"),
|
||||
("el_num", "u2"),
|
||||
("first_gate_r", "u2"),
|
||||
("first_gate_v", "u2"),
|
||||
("gate_length_r", "u2"),
|
||||
("gate_length_v", "u2"),
|
||||
("gate_num_r", "u2"),
|
||||
("gate_num_v", "u2"),
|
||||
("sector_num", "u2"),
|
||||
("system_coff", "u4"),
|
||||
("r_pointer", "u2"),
|
||||
("v_pointer", "u2"),
|
||||
("w_pointer", "u2"),
|
||||
("v_reso", "u2"),
|
||||
("vcp_mode", "u2"),
|
||||
("res2", "u2", 4),
|
||||
("r_pointer_2", "u2"),
|
||||
("v_pointer_2", "u2"),
|
||||
("w_pointer_2", "u2"),
|
||||
("nyquist_vel", "u2"),
|
||||
]
|
||||
|
||||
_S_INFO = [("r", "u1", 460), ("v", "u1", 920), ("w", "u1", 920), ("res4", "u2", 2)]
|
||||
|
||||
_S_INFO = [("r", "u1", 800), ("v", "u1", 1600), ("w", "u1", 1600), ("res4", "u2", 2)]
|
||||
|
||||
_S_INFO = [("r", "u1", 1000), ("v", "u1", 1000), ("w", "u1", 1000)]
|
||||
|
||||
_S_INFO = [
|
||||
("sFileID", "S4"),
|
||||
("fVersionNo", "f4"),
|
||||
("lFileHeaderLength", "i4"),
|
||||
("sCountry", "S30"),
|
||||
("sProvince", "S20"),
|
||||
("sStation", "S40"),
|
||||
("sStationNumber", "S10"),
|
||||
("sRadarType", "S20"),
|
||||
("sLongitude", "S16"),
|
||||
("sLatitude", "S16"),
|
||||
("lLongitudeValue", "i4"),
|
||||
("lLatitudeValue", "i4"),
|
||||
("lHeight", "i4"),
|
||||
("shMaxAngle", "i2"),
|
||||
("shOptiAngle", "i2"),
|
||||
("lAntennaG", "i4"),
|
||||
("usBeamH", "u2"),
|
||||
("usBeamL", "u2"),
|
||||
("ucPolarization", "B"),
|
||||
("usSidelobe", "u2"),
|
||||
("lPower", "i4"),
|
||||
("lWavelength", "i4"),
|
||||
("usLogA", "u2"),
|
||||
("usLineA", "u2"),
|
||||
("usAGCP", "u2"),
|
||||
("usLogMinPower", "u2"),
|
||||
("usLineMinPower", "u2"),
|
||||
("ucClutterT", "B"),
|
||||
("ucVelocityP", "B"),
|
||||
("ucFilterP", "B"),
|
||||
("ucNoiseT", "B"),
|
||||
("ucSQIT", "B"),
|
||||
("ucIntensityC", "B"),
|
||||
("ucIntensityR", "B"),
|
||||
]
|
||||
|
||||
|
||||
def transform(k):
|
||||
f = k[0]
|
||||
|
||||
tf = f[0]
|
||||
flag = table.get(tf)
|
||||
if len(k) == 1:
|
||||
if tf in ['S','b','B']:
|
||||
return flag
|
||||
return f"{flag}{int(f[1:])*8}"
|
||||
else:
|
||||
l = int(k[1])
|
||||
if tf in ['S','b','B']:
|
||||
return f"[{flag};{l}]"
|
||||
else:
|
||||
return f"[{flag}{int(f[1:])*8}; {l}]"
|
||||
|
||||
|
||||
def camel_to_snake(name):
|
||||
name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name)
|
||||
return re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()
|
||||
|
||||
for i in _S_INFO:
|
||||
print(f"f{camel_to_snake(i[0])}: {transform(i[1:])},")
|
||||
|
||||
Loading…
Reference in New Issue
Block a user