From a0f43b5f3f1d9802ec12d1dc3d61f4af73ccb656 Mon Sep 17 00:00:00 2001 From: Dan Paulat Date: Sat, 27 Jan 2024 16:39:49 -0600 Subject: [PATCH] Handle negative data moment ranges for level 2 data --- .../scwx/qt/view/level2_product_view.cpp | 130 +++++++++--------- .../scwx/wsr88d/rda/digital_radar_data.hpp | 4 +- .../wsr88d/rda/digital_radar_data_generic.hpp | 2 +- .../scwx/wsr88d/rda/generic_radar_data.hpp | 2 +- .../scwx/wsr88d/rda/digital_radar_data.cpp | 14 +- .../wsr88d/rda/digital_radar_data_generic.cpp | 4 +- 6 files changed, 81 insertions(+), 75 deletions(-) diff --git a/scwx-qt/source/scwx/qt/view/level2_product_view.cpp b/scwx-qt/source/scwx/qt/view/level2_product_view.cpp index 24d7eacc..0e95ddd3 100644 --- a/scwx-qt/source/scwx/qt/view/level2_product_view.cpp +++ b/scwx-qt/source/scwx/qt/view/level2_product_view.cpp @@ -522,17 +522,17 @@ void Level2ProductView::ComputeSweep() } // Compute threshold at which to display an individual bin (minimum of 2) - const uint16_t snrThreshold = - std::max(2, momentData0->snr_threshold_raw()); + const std::uint16_t snrThreshold = + std::max(2, momentData0->snr_threshold_raw()); // Start radial is always 0, as coordinates are calculated for each sweep constexpr std::uint16_t startRadial = 0u; for (auto& radialPair : *radarData) { - uint16_t radial = radialPair.first; - auto& radialData = radialPair.second; - auto momentData = radialData->moment_data_block(p->dataBlockType_); + std::uint16_t radial = radialPair.first; + auto& radialData = radialPair.second; + auto momentData = radialData->moment_data_block(p->dataBlockType_); if (momentData0->data_word_size() != momentData->data_word_size()) { @@ -541,65 +541,70 @@ void Level2ProductView::ComputeSweep() } // Compute gate interval - const std::uint16_t dataMomentInterval = + const std::int32_t dataMomentInterval = momentData->data_moment_range_sample_interval_raw(); - const std::uint16_t dataMomentIntervalH = dataMomentInterval / 2; - const std::uint16_t dataMomentRange = - std::max(momentData->data_moment_range_raw(), dataMomentIntervalH); + const std::int32_t dataMomentIntervalH = dataMomentInterval / 2; + const std::int32_t dataMomentRange = std::max( + momentData->data_moment_range_raw(), dataMomentIntervalH); // Compute gate size (number of base 250m gates per bin) - const uint16_t gateSizeMeters = - static_cast(radarProductManager->gate_size()); - const uint16_t gateSize = - std::max(1, dataMomentInterval / gateSizeMeters); + const std::int32_t gateSizeMeters = + static_cast(radarProductManager->gate_size()); + const std::int32_t gateSize = + std::max(1, dataMomentInterval / gateSizeMeters); // Compute gate range [startGate, endGate) - const uint16_t startGate = + const std::int32_t startGate = (dataMomentRange - dataMomentIntervalH) / gateSizeMeters; - const uint16_t numberOfDataMomentGates = - std::min(momentData->number_of_data_moment_gates(), - static_cast(gates)); - const uint16_t endGate = - std::min(startGate + numberOfDataMomentGates * gateSize, - common::MAX_DATA_MOMENT_GATES); + const std::int32_t numberOfDataMomentGates = + std::min(momentData->number_of_data_moment_gates(), + static_cast(gates)); + const std::int32_t endGate = std::min( + startGate + numberOfDataMomentGates * gateSize, + static_cast(common::MAX_DATA_MOMENT_GATES)); - const uint8_t* dataMomentsArray8 = nullptr; - const uint16_t* dataMomentsArray16 = nullptr; - const uint8_t* cfpMomentsArray = nullptr; + const std::uint8_t* dataMomentsArray8 = nullptr; + const std::uint16_t* dataMomentsArray16 = nullptr; + const std::uint8_t* cfpMomentsArray = nullptr; if (momentData->data_word_size() == 8) { dataMomentsArray8 = - reinterpret_cast(momentData->data_moments()); + reinterpret_cast(momentData->data_moments()); } else { dataMomentsArray16 = - reinterpret_cast(momentData->data_moments()); + reinterpret_cast(momentData->data_moments()); } if (cfpMoments.size() > 0) { - cfpMomentsArray = reinterpret_cast( + cfpMomentsArray = reinterpret_cast( radialData->moment_data_block(wsr88d::rda::DataBlockType::MomentCfp) ->data_moments()); } - for (uint16_t gate = startGate, i = 0; gate + gateSize <= endGate; + for (std::int32_t gate = startGate, i = 0; gate + gateSize <= endGate; gate += gateSize, ++i) { - size_t vertexCount = (gate > 0) ? 6 : 3; + if (gate < 0) + { + continue; + } + + std::size_t vertexCount = (gate > 0) ? 6 : 3; // Store data moment value if (dataMomentsArray8 != nullptr) { - uint8_t dataValue = dataMomentsArray8[i]; + std::uint8_t dataValue = dataMomentsArray8[i]; if (dataValue < snrThreshold && dataValue != RANGE_FOLDED) { continue; } - for (size_t m = 0; m < vertexCount; m++) + for (std::size_t m = 0; m < vertexCount; m++) { dataMoments8[mIndex++] = dataMomentsArray8[i]; @@ -611,13 +616,13 @@ void Level2ProductView::ComputeSweep() } else { - uint16_t dataValue = dataMomentsArray16[i]; + std::uint16_t dataValue = dataMomentsArray16[i]; if (dataValue < snrThreshold && dataValue != RANGE_FOLDED) { continue; } - for (size_t m = 0; m < vertexCount; m++) + for (std::size_t m = 0; m < vertexCount; m++) { dataMoments16[mIndex++] = dataMomentsArray16[i]; } @@ -626,18 +631,18 @@ void Level2ProductView::ComputeSweep() // Store vertices if (gate > 0) { - const uint16_t baseCoord = gate - 1; + const std::uint16_t baseCoord = gate - 1; - size_t offset1 = ((startRadial + radial) % radials * - common::MAX_DATA_MOMENT_GATES + - baseCoord) * - 2; - size_t offset2 = offset1 + gateSize * 2; - size_t offset3 = (((startRadial + radial + 1) % radials) * - common::MAX_DATA_MOMENT_GATES + - baseCoord) * - 2; - size_t offset4 = offset3 + gateSize * 2; + std::size_t offset1 = ((startRadial + radial) % radials * + common::MAX_DATA_MOMENT_GATES + + baseCoord) * + 2; + std::size_t offset2 = offset1 + gateSize * 2; + std::size_t offset3 = (((startRadial + radial + 1) % radials) * + common::MAX_DATA_MOMENT_GATES + + baseCoord) * + 2; + std::size_t offset4 = offset3 + gateSize * 2; vertices[vIndex++] = coordinates[offset1]; vertices[vIndex++] = coordinates[offset1 + 1]; @@ -661,16 +666,16 @@ void Level2ProductView::ComputeSweep() } else { - const uint16_t baseCoord = gate; + const std::uint16_t baseCoord = gate; - size_t offset1 = ((startRadial + radial) % radials * - common::MAX_DATA_MOMENT_GATES + - baseCoord) * - 2; - size_t offset2 = (((startRadial + radial + 1) % radials) * - common::MAX_DATA_MOMENT_GATES + - baseCoord) * - 2; + std::size_t offset1 = ((startRadial + radial) % radials * + common::MAX_DATA_MOMENT_GATES + + baseCoord) * + 2; + std::size_t offset2 = (((startRadial + radial + 1) % radials) * + common::MAX_DATA_MOMENT_GATES + + baseCoord) * + 2; vertices[vIndex++] = p->latitude_; vertices[vIndex++] = p->longitude_; @@ -866,25 +871,26 @@ Level2ProductView::GetBinLevel(const common::Coordinate& coordinate) const // Compute gate interval auto momentData = (*radarData)[*radial]->moment_data_block(dataBlockType); - const std::uint16_t dataMomentInterval = + const std::int32_t dataMomentInterval = momentData->data_moment_range_sample_interval_raw(); - const std::uint16_t dataMomentIntervalH = dataMomentInterval / 2; - const std::uint16_t dataMomentRange = - std::max(momentData->data_moment_range_raw(), dataMomentIntervalH); + const std::int32_t dataMomentIntervalH = dataMomentInterval / 2; + const std::int32_t dataMomentRange = std::max( + momentData->data_moment_range_raw(), dataMomentIntervalH); // Compute gate size (number of base 250m gates per bin) - const std::uint16_t gateSizeMeters = - static_cast(radarProductManager->gate_size()); + const std::int32_t gateSizeMeters = + static_cast(radarProductManager->gate_size()); // Compute gate range [startGate, endGate) - const std::uint16_t startGate = + const std::int32_t startGate = (dataMomentRange - dataMomentIntervalH) / gateSizeMeters; - const std::uint16_t numberOfDataMomentGates = + const std::int32_t numberOfDataMomentGates = momentData->number_of_data_moment_gates(); - const std::uint16_t gate = s12 / dataMomentInterval - startGate; + const std::int32_t gate = s12 / dataMomentInterval - startGate; - if (gate > numberOfDataMomentGates || gate > common::MAX_DATA_MOMENT_GATES) + if (gate < 0 || gate > numberOfDataMomentGates || + gate > common::MAX_DATA_MOMENT_GATES) { // Coordinate is beyond radar range return std::nullopt; diff --git a/wxdata/include/scwx/wsr88d/rda/digital_radar_data.hpp b/wxdata/include/scwx/wsr88d/rda/digital_radar_data.hpp index bf96024e..01c2cd41 100644 --- a/wxdata/include/scwx/wsr88d/rda/digital_radar_data.hpp +++ b/wxdata/include/scwx/wsr88d/rda/digital_radar_data.hpp @@ -31,9 +31,9 @@ public: std::uint16_t elevation_angle_raw() const; units::degrees elevation_angle() const; std::uint16_t elevation_number() const; - std::uint16_t surveillance_range_raw() const; + std::int16_t surveillance_range_raw() const; units::kilometers surveillance_range() const; - std::uint16_t doppler_range_raw() const; + std::int16_t doppler_range_raw() const; units::kilometers doppler_range() const; std::uint16_t surveillance_range_sample_interval_raw() const; units::kilometers surveillance_range_sample_interval() const; diff --git a/wxdata/include/scwx/wsr88d/rda/digital_radar_data_generic.hpp b/wxdata/include/scwx/wsr88d/rda/digital_radar_data_generic.hpp index 42ee713a..ba911898 100644 --- a/wxdata/include/scwx/wsr88d/rda/digital_radar_data_generic.hpp +++ b/wxdata/include/scwx/wsr88d/rda/digital_radar_data_generic.hpp @@ -120,7 +120,7 @@ public: std::uint16_t number_of_data_moment_gates() const; units::kilometers data_moment_range() const; - std::uint16_t data_moment_range_raw() const; + std::int16_t data_moment_range_raw() const; units::kilometers data_moment_range_sample_interval() const; std::uint16_t data_moment_range_sample_interval_raw() const; float snr_threshold() const; diff --git a/wxdata/include/scwx/wsr88d/rda/generic_radar_data.hpp b/wxdata/include/scwx/wsr88d/rda/generic_radar_data.hpp index 085f7849..2b4b49e3 100644 --- a/wxdata/include/scwx/wsr88d/rda/generic_radar_data.hpp +++ b/wxdata/include/scwx/wsr88d/rda/generic_radar_data.hpp @@ -79,7 +79,7 @@ public: virtual std::uint16_t number_of_data_moment_gates() const = 0; virtual units::kilometers data_moment_range() const = 0; - virtual std::uint16_t data_moment_range_raw() const = 0; + virtual std::int16_t data_moment_range_raw() const = 0; virtual units::kilometers data_moment_range_sample_interval() const = 0; virtual std::uint16_t data_moment_range_sample_interval_raw() const = 0; diff --git a/wxdata/source/scwx/wsr88d/rda/digital_radar_data.cpp b/wxdata/source/scwx/wsr88d/rda/digital_radar_data.cpp index abd03a12..f98dafcd 100644 --- a/wxdata/source/scwx/wsr88d/rda/digital_radar_data.cpp +++ b/wxdata/source/scwx/wsr88d/rda/digital_radar_data.cpp @@ -33,8 +33,8 @@ public: std::uint16_t radialStatus_ {}; std::uint16_t elevationAngle_ {}; std::uint16_t elevationNumber_ {}; - std::uint16_t surveillanceRange_ {}; - std::uint16_t dopplerRange_ {}; + std::int16_t surveillanceRange_ {}; + std::int16_t dopplerRange_ {}; std::uint16_t surveillanceRangeSampleInterval_ {}; std::uint16_t dopplerRangeSampleInterval_ {}; std::uint16_t numberOfSurveillanceBins_ {}; @@ -71,7 +71,7 @@ public: std::uint16_t number_of_data_moment_gates() const; units::kilometers data_moment_range() const; - std::uint16_t data_moment_range_raw() const; + std::int16_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; @@ -94,7 +94,7 @@ public: ~Impl() = default; std::uint16_t numberOfDataMomentGates_ {}; - std::uint16_t dataMomentRange_ {}; + std::int16_t dataMomentRange_ {}; std::uint16_t dataMomentRangeSampleInterval_ {}; float scale_ {}; float offset_ {}; @@ -162,7 +162,7 @@ std::uint16_t DigitalRadarData::elevation_number() const return p->elevationNumber_; } -std::uint16_t DigitalRadarData::surveillance_range_raw() const +std::int16_t DigitalRadarData::surveillance_range_raw() const { return p->surveillanceRange_; } @@ -172,7 +172,7 @@ units::kilometers DigitalRadarData::surveillance_range() const return units::kilometers {p->surveillanceRange_ * kRangeScale}; } -std::uint16_t DigitalRadarData::doppler_range_raw() const +std::int16_t DigitalRadarData::doppler_range_raw() const { return p->dopplerRange_; } @@ -363,7 +363,7 @@ DigitalRadarData::Impl::MomentDataBlock::data_moment_range() const return units::kilometers {p->dataMomentRange_ * kRangeScale}; } -std::uint16_t +std::int16_t DigitalRadarData::Impl::MomentDataBlock::data_moment_range_raw() const { return p->dataMomentRange_; diff --git a/wxdata/source/scwx/wsr88d/rda/digital_radar_data_generic.cpp b/wxdata/source/scwx/wsr88d/rda/digital_radar_data_generic.cpp index 94492a8e..4870c1c3 100644 --- a/wxdata/source/scwx/wsr88d/rda/digital_radar_data_generic.cpp +++ b/wxdata/source/scwx/wsr88d/rda/digital_radar_data_generic.cpp @@ -54,7 +54,7 @@ public: explicit Impl() {} std::uint16_t numberOfDataMomentGates_ {0}; - std::uint16_t dataMomentRange_ {0}; + std::int16_t dataMomentRange_ {0}; std::uint16_t dataMomentRangeSampleInterval_ {0}; std::uint16_t tover_ {0}; std::int16_t snrThreshold_ {0}; @@ -92,7 +92,7 @@ DigitalRadarDataGeneric::MomentDataBlock::data_moment_range() const return units::kilometers {p->dataMomentRange_ * 0.001f}; } -std::uint16_t +std::int16_t DigitalRadarDataGeneric::MomentDataBlock::data_moment_range_raw() const { return p->dataMomentRange_;