From 730c1a9ba7e25bffe9b6533ad48d1f9441cba3f5 Mon Sep 17 00:00:00 2001 From: Dan Paulat Date: Mon, 22 Jan 2024 23:59:04 -0600 Subject: [PATCH] Inherit DigitalRadarData from GenericRadarData --- .../scwx/wsr88d/rda/digital_radar_data.hpp | 10 +- .../scwx/wsr88d/rda/digital_radar_data.cpp | 228 +++++++++++++++++- 2 files changed, 223 insertions(+), 15 deletions(-) diff --git a/wxdata/include/scwx/wsr88d/rda/digital_radar_data.hpp b/wxdata/include/scwx/wsr88d/rda/digital_radar_data.hpp index 200cfbe9..bf96024e 100644 --- a/wxdata/include/scwx/wsr88d/rda/digital_radar_data.hpp +++ b/wxdata/include/scwx/wsr88d/rda/digital_radar_data.hpp @@ -1,9 +1,6 @@ #pragma once -#include - -#include -#include +#include namespace scwx { @@ -12,7 +9,7 @@ namespace wsr88d namespace rda { -class DigitalRadarData : public Level2Message +class DigitalRadarData : public GenericRadarData { public: explicit DigitalRadarData(); @@ -56,6 +53,9 @@ public: std::uint16_t tover() const; std::uint16_t radial_spot_blanking_status() const; + std::shared_ptr + moment_data_block(DataBlockType type) const; + bool Parse(std::istream& is); static std::shared_ptr Create(Level2MessageHeader&& header, diff --git a/wxdata/source/scwx/wsr88d/rda/digital_radar_data.cpp b/wxdata/source/scwx/wsr88d/rda/digital_radar_data.cpp index b84c6aff..6d840d79 100644 --- a/wxdata/source/scwx/wsr88d/rda/digital_radar_data.cpp +++ b/wxdata/source/scwx/wsr88d/rda/digital_radar_data.cpp @@ -20,6 +20,8 @@ constexpr float kRangeScale = 0.001f; class DigitalRadarData::Impl { public: + class MomentDataBlock; + explicit Impl() {}; ~Impl() = default; @@ -49,13 +51,59 @@ public: std::uint16_t tover_ {}; std::uint16_t radialSpotBlankingStatus_ {}; - std::vector reflectivity_ {}; - std::vector dopplerVelocity_ {}; - std::vector dopplerSpectrumWidth_ {}; + std::shared_ptr reflectivityDataBlock_ {nullptr}; + std::shared_ptr dopplerVelocityDataBlock_ {nullptr}; + std::shared_ptr dopplerSpectrumWidthDataBlock_ {nullptr}; +}; + +class DigitalRadarData::Impl::MomentDataBlock : + public GenericRadarData::MomentDataBlock +{ +public: + explicit MomentDataBlock(const DigitalRadarData* self, DataBlockType type); + ~MomentDataBlock() = default; + + MomentDataBlock(const MomentDataBlock&) = delete; + MomentDataBlock& operator=(const MomentDataBlock&) = delete; + + MomentDataBlock(MomentDataBlock&&) noexcept = default; + MomentDataBlock& operator=(MomentDataBlock&&) noexcept = default; + + std::uint16_t number_of_data_moment_gates() const; + units::kilometers data_moment_range() const; + std::uint16_t data_moment_range_raw() const; + units::kilometers data_moment_range_sample_interval() const; + std::uint16_t data_moment_range_sample_interval_raw() const; + std::int16_t snr_threshold_raw() const; + std::uint8_t data_word_size() const; + float scale() const; + float offset() const; + const void* data_moments() const; + + std::vector& data_moment_vector() const; + +private: + class Impl; + std::unique_ptr p; +}; + +class DigitalRadarData::Impl::MomentDataBlock::Impl +{ +public: + explicit Impl() {}; + ~Impl() = default; + + std::uint16_t numberOfDataMomentGates_ {}; + std::uint16_t dataMomentRange_ {}; + std::uint16_t dataMomentRangeSampleInterval_ {}; + float scale_ {}; + float offset_ {}; + + std::vector dataMoments_ {}; }; DigitalRadarData::DigitalRadarData() : - Level2Message(), p(std::make_unique()) + GenericRadarData(), p(std::make_unique()) { } DigitalRadarData::~DigitalRadarData() = default; @@ -222,6 +270,151 @@ std::uint16_t DigitalRadarData::radial_spot_blanking_status() const return p->radialSpotBlankingStatus_; } +std::shared_ptr +DigitalRadarData::moment_data_block(DataBlockType type) const +{ + std::shared_ptr block = nullptr; + + switch (type) + { + case DataBlockType::MomentRef: + block = p->reflectivityDataBlock_; + break; + + case DataBlockType::MomentVel: + block = p->dopplerVelocityDataBlock_; + break; + + case DataBlockType::MomentSw: + block = p->dopplerSpectrumWidthDataBlock_; + break; + + default: + break; + } + + return block; +} + +DigitalRadarData::Impl::MomentDataBlock::MomentDataBlock( + const DigitalRadarData* self, DataBlockType type) +{ + switch (type) + { + case DataBlockType::MomentRef: + p->numberOfDataMomentGates_ = self->number_of_surveillance_bins(); + p->dataMomentRange_ = self->surveillance_range_raw(); + p->dataMomentRangeSampleInterval_ = + self->surveillance_range_sample_interval_raw(); + + // Table III-E Base Data Scaling + // Rnum = (R / 2) - 33.0 + p->scale_ = 2.0f; + p->offset_ = 66.0f; // (33.0 * 2) + break; + + case DataBlockType::MomentVel: + p->numberOfDataMomentGates_ = self->number_of_doppler_bins(); + p->dataMomentRange_ = self->doppler_range_raw(); + p->dataMomentRangeSampleInterval_ = + self->doppler_range_sample_interval_raw(); + + // Table III-E Base Data Scaling + if (self->doppler_velocity_resolution() == 2) // 2 = 0.5 m/s + { + // Vnum = (V / 2) - 64.5 + p->scale_ = 2.0f; + p->offset_ = 129.0f; // (64.5 * 2) + } + else // 4 = 1.0 m/s + { + // Vnum = V - 129.0 + p->scale_ = 1.0f; + p->offset_ = 129.0f; + } + break; + + case DataBlockType::MomentSw: + p->numberOfDataMomentGates_ = self->number_of_doppler_bins(); + p->dataMomentRange_ = self->doppler_range_raw(); + p->dataMomentRangeSampleInterval_ = + self->doppler_range_sample_interval_raw(); + + // Table III-E Base Data Scaling + // SWnum = (SW / 2) - 64.5 + p->scale_ = 2.0f; + p->offset_ = 129.0f; // (64.5 * 2) + break; + } +} +std::uint16_t +DigitalRadarData::Impl::MomentDataBlock::number_of_data_moment_gates() const +{ + return p->numberOfDataMomentGates_; +} + +units::kilometers +DigitalRadarData::Impl::MomentDataBlock::data_moment_range() const +{ + return units::kilometers {p->dataMomentRange_ * kRangeScale}; +} + +std::uint16_t +DigitalRadarData::Impl::MomentDataBlock::data_moment_range_raw() const +{ + return p->dataMomentRange_; +} + +units::kilometers +DigitalRadarData::Impl::MomentDataBlock::data_moment_range_sample_interval() + const +{ + return units::kilometers {p->dataMomentRangeSampleInterval_ * + kRangeScale}; +} + +std::uint16_t +DigitalRadarData::Impl::MomentDataBlock::data_moment_range_sample_interval_raw() + const +{ + return p->dataMomentRangeSampleInterval_; +} + +std::int16_t DigitalRadarData::Impl::MomentDataBlock::snr_threshold_raw() const +{ + // Table III Digital Radar Data (Message Type 1) Note 10: + // Value of 00 (prior to scaling) is Signal Below Threshold, value of 01 + // (prior to scaling) is Signal Overlaid + return 2; +} + +std::uint8_t DigitalRadarData::Impl::MomentDataBlock::data_word_size() const +{ + // Data moments are 8-bit for Digital Radar Data + return 8; +} + +float DigitalRadarData::Impl::MomentDataBlock::scale() const +{ + return p->scale_; +} + +float DigitalRadarData::Impl::MomentDataBlock::offset() const +{ + return p->offset_; +} + +const void* DigitalRadarData::Impl::MomentDataBlock::data_moments() const +{ + return p->dataMoments_.data(); +} + +std::vector& +DigitalRadarData::Impl::MomentDataBlock::data_moment_vector() const +{ + return p->dataMoments_; +} + bool DigitalRadarData::Parse(std::istream& is) { logger_->trace("Parsing Digital Radar Data (Message Type 1)"); @@ -337,31 +530,46 @@ bool DigitalRadarData::Parse(std::istream& is) if (messageValid && p->surveillancePointer_ != 0) { + p->reflectivityDataBlock_ = std::make_shared( + this, DataBlockType::MomentRef); + auto& reflectivity = p->reflectivityDataBlock_->data_moment_vector(); + is.seekg(isBegin + std::streamoff(p->surveillancePointer_), std::ios_base::beg); - p->reflectivity_.resize(p->numberOfSurveillanceBins_); - is.read(reinterpret_cast(p->reflectivity_.data()), + reflectivity.resize(p->numberOfSurveillanceBins_); + is.read(reinterpret_cast(reflectivity.data()), p->numberOfSurveillanceBins_); } if (messageValid && p->velocityPointer_ != 0) { + p->dopplerVelocityDataBlock_ = std::make_shared( + this, DataBlockType::MomentVel); + auto& dopplerVelocity = + p->dopplerVelocityDataBlock_->data_moment_vector(); + is.seekg(isBegin + std::streamoff(p->velocityPointer_), std::ios_base::beg); - p->dopplerVelocity_.resize(p->numberOfDopplerBins_); - is.read(reinterpret_cast(p->dopplerVelocity_.data()), + dopplerVelocity.resize(p->numberOfDopplerBins_); + is.read(reinterpret_cast(dopplerVelocity.data()), p->numberOfDopplerBins_); } if (messageValid && p->spectralWidthPointer_ != 0) { + p->dopplerSpectrumWidthDataBlock_ = + std::make_shared(this, + DataBlockType::MomentVel); + auto& dopplerSpectrumWidth = + p->dopplerSpectrumWidthDataBlock_->data_moment_vector(); + is.seekg(isBegin + std::streamoff(p->spectralWidthPointer_), std::ios_base::beg); - p->dopplerSpectrumWidth_.resize(p->numberOfDopplerBins_); - is.read(reinterpret_cast(p->dopplerSpectrumWidth_.data()), + dopplerSpectrumWidth.resize(p->numberOfDopplerBins_); + is.read(reinterpret_cast(dopplerSpectrumWidth.data()), p->numberOfDopplerBins_); }