From 24062d0417c82a85783475477cd6b040c9268a8f Mon Sep 17 00:00:00 2001 From: Dan Paulat Date: Sun, 25 Feb 2024 01:55:54 -0600 Subject: [PATCH 1/7] Add VIL-specific data level conversions --- .../wsr88d/rpg/product_description_block.hpp | 5 +-- .../wsr88d/rpg/product_description_block.cpp | 31 +++++++++++++++++-- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/wxdata/include/scwx/wsr88d/rpg/product_description_block.hpp b/wxdata/include/scwx/wsr88d/rpg/product_description_block.hpp index c67ccbf2..d7973026 100644 --- a/wxdata/include/scwx/wsr88d/rpg/product_description_block.hpp +++ b/wxdata/include/scwx/wsr88d/rpg/product_description_block.hpp @@ -66,8 +66,9 @@ public: std::optional data_level_code(std::uint8_t level) const; std::optional data_value(std::uint8_t level) const; - float log_offset() const; - float log_scale() const; + std::uint16_t log_start() const; + float log_offset() const; + float log_scale() const; units::angle::degrees elevation() const; diff --git a/wxdata/source/scwx/wsr88d/rpg/product_description_block.cpp b/wxdata/source/scwx/wsr88d/rpg/product_description_block.cpp index 90385e88..f09a32b4 100644 --- a/wxdata/source/scwx/wsr88d/rpg/product_description_block.cpp +++ b/wxdata/source/scwx/wsr88d/rpg/product_description_block.cpp @@ -4,6 +4,7 @@ #include #include +#include #include #include @@ -591,6 +592,20 @@ uint16_t ProductDescriptionBlock::number_of_levels() const return numberOfLevels; } +std::uint16_t ProductDescriptionBlock::log_start() const +{ + std::uint16_t logStart = std::numeric_limits::max(); + + switch (p->productCode_) + { + case 134: + logStart = p->halfword(33); + break; + } + + return logStart; +} + float ProductDescriptionBlock::log_offset() const { float logOffset = 0.0f; @@ -598,7 +613,7 @@ float ProductDescriptionBlock::log_offset() const switch (p->productCode_) { case 134: - logOffset = util ::DecodeFloat16(p->halfword(35)); + logOffset = util::DecodeFloat16(p->halfword(35)); break; } @@ -612,7 +627,7 @@ float ProductDescriptionBlock::log_scale() const switch (p->productCode_) { case 134: - logScale = util ::DecodeFloat16(p->halfword(34)); + logScale = util::DecodeFloat16(p->halfword(34)); break; } @@ -1007,6 +1022,18 @@ ProductDescriptionBlock::data_value(std::uint8_t level) const f = (level - dataOffset) / dataScale; break; + case 134: + if (level < log_start()) + { + f = (level - dataOffset) / dataScale; + } + else + { + f = static_cast(std::pow( + std::numbers::e, (level - log_offset()) / log_scale())); + } + break; + default: f = level * dataScale + dataOffset; break; From b0ebc8eab6f9ce19f8bbda9f96578fa41fd757b9 Mon Sep 17 00:00:00 2001 From: Dan Paulat Date: Sun, 25 Feb 2024 01:56:48 -0600 Subject: [PATCH 2/7] Add VIL/DVL product to level 3 lists --- wxdata/include/scwx/common/products.hpp | 1 + wxdata/source/scwx/common/products.cpp | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/wxdata/include/scwx/common/products.hpp b/wxdata/include/scwx/common/products.hpp index ce1b12cb..b4e57a36 100644 --- a/wxdata/include/scwx/common/products.hpp +++ b/wxdata/include/scwx/common/products.hpp @@ -47,6 +47,7 @@ enum class Level3ProductCategory DifferentialReflectivity, SpecificDifferentialPhase, CorrelationCoefficient, + VerticallyIntegratedLiquid, HydrometeorClassification, Unknown }; diff --git a/wxdata/source/scwx/common/products.cpp b/wxdata/source/scwx/common/products.cpp index 87144c8d..b068fa4e 100644 --- a/wxdata/source/scwx/common/products.cpp +++ b/wxdata/source/scwx/common/products.cpp @@ -47,6 +47,7 @@ static const std::unordered_map level3ProductCodeMap_ { {56, "SRM"}, {94, "DR"}, {99, "DV"}, + {134, "DVL"}, {153, "SDR"}, {154, "SDV"}, {159, "DZD"}, @@ -68,6 +69,7 @@ static const std::unordered_map {"DZD", "Digital Differential Reflectivity"}, {"DCC", "Digital Correlation Coefficient"}, {"DKD", "Digital Specific Differential Phase"}, + {"DVL", "Digital Vertically Integrated Liquid"}, {"DHC", "Digital Hydrometeor Classification"}, {"HHC", "Hybrid Hydrometeor Classification"}, {"ML", "Melting Layer"}, @@ -104,6 +106,9 @@ static const std::unordered_map> // Specific Differential Phase {"DKD", {"NXK", "NYK", "NZK", "N0K", "NAK", "N1K", "NBK", "N2K", "N3K"}}, + // Digital Vertically Integrated Liquid + {"DVL", {"DVL"}}, + // Hydrometeor Classification {"DHC", {"NXH", "NYH", "NZH", "N0H", "NAH", "N1H", "NBH", "N2H", "N3H"}}, {"HHC", {"HHC"}}, @@ -123,6 +128,7 @@ static const std::unordered_map {Level3ProductCategory::DifferentialReflectivity, "ZDR"}, {Level3ProductCategory::SpecificDifferentialPhase, "KDP"}, {Level3ProductCategory::CorrelationCoefficient, "CC"}, + {Level3ProductCategory::VerticallyIntegratedLiquid, "VIL"}, {Level3ProductCategory::HydrometeorClassification, "HC"}, {Level3ProductCategory::Unknown, "?"}}; @@ -138,6 +144,8 @@ static const std::unordered_map "Specific Differential Phase"}, {Level3ProductCategory::CorrelationCoefficient, "Correlation Coefficient"}, + {Level3ProductCategory::VerticallyIntegratedLiquid, + "Vertically Integrated Liquid"}, {Level3ProductCategory::HydrometeorClassification, "Hydrometeor Classification"}, {Level3ProductCategory::Unknown, "?"}}; @@ -151,6 +159,7 @@ static const std::unordered_map> {Level3ProductCategory::DifferentialReflectivity, {"DZD"}}, {Level3ProductCategory::SpecificDifferentialPhase, {"DKD"}}, {Level3ProductCategory::CorrelationCoefficient, {"DCC"}}, + {Level3ProductCategory::VerticallyIntegratedLiquid, {"DVL"}}, {Level3ProductCategory::HydrometeorClassification, {"DHC", "HHC"}}, {Level3ProductCategory::Unknown, {}}}; @@ -163,6 +172,7 @@ static const std::unordered_map {Level3ProductCategory::DifferentialReflectivity, "N0X"}, {Level3ProductCategory::SpecificDifferentialPhase, "N0K"}, {Level3ProductCategory::CorrelationCoefficient, "N0C"}, + {Level3ProductCategory::VerticallyIntegratedLiquid, "DVL"}, {Level3ProductCategory::HydrometeorClassification, "N0H"}}; static const std::unordered_map level3Palette_ { From 6254b0a84e5276a7895ccbd468c5b594d7720b38 Mon Sep 17 00:00:00 2001 From: Dan Paulat Date: Sun, 25 Feb 2024 18:18:50 -0600 Subject: [PATCH 3/7] Fix 16-bit floating point conversions --- test/source/scwx/util/float.test.cpp | 23 ++++++++++++++++++++--- wxdata/source/scwx/util/float.cpp | 2 +- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/test/source/scwx/util/float.test.cpp b/test/source/scwx/util/float.test.cpp index f91fe4bf..aa4bfe7e 100644 --- a/test/source/scwx/util/float.test.cpp +++ b/test/source/scwx/util/float.test.cpp @@ -7,6 +7,11 @@ namespace scwx namespace util { +class Float16Test : + public testing ::TestWithParam> +{ +}; + TEST(FloatTest, Decode32Positive1) { uint16_t msw = 0x3f80; @@ -37,14 +42,26 @@ TEST(FloatTest, Decode32Positive12345678) EXPECT_FLOAT_EQ(x, 12345678.0f); } -TEST(FloatTest, Decode16h0x5bb4) +TEST_P(Float16Test, DecodeFloat16) { - uint16_t hex = 0x5bb4; + auto param = GetParam(); + + std::uint16_t hex = param.first; float x = DecodeFloat16(hex); - EXPECT_FLOAT_EQ(x, 123.25f); + EXPECT_FLOAT_EQ(x, param.second); } +INSTANTIATE_TEST_SUITE_P( + FloatTest, + Float16Test, + testing::Values(std::pair {0x4400, 2.0f}, + std::pair {0x59ab, 90.6875f}, + std::pair {0x593e, 83.875f}, + std::pair {0x54dc, 38.875f}, + std::pair {0xc82a, -4.1640625f}, + std::pair {0x5bb4, 123.25f})); + } // namespace util } // namespace scwx diff --git a/wxdata/source/scwx/util/float.cpp b/wxdata/source/scwx/util/float.cpp index cee8ae66..3aea2dd6 100644 --- a/wxdata/source/scwx/util/float.cpp +++ b/wxdata/source/scwx/util/float.cpp @@ -19,7 +19,7 @@ float DecodeFloat16(std::uint16_t hex) static constexpr std::uint16_t S_MASK = 0x8000; static constexpr std::uint16_t S_LSB = 0; static constexpr std::uint16_t S_SHIFT = 15 - S_LSB; - static constexpr std::uint16_t E_MASK = 0x7a00; + static constexpr std::uint16_t E_MASK = 0x7c00; static constexpr std::uint16_t E_LSB = 5; static constexpr std::uint16_t E_SHIFT = 15 - E_LSB; static constexpr std::uint16_t F_MASK = 0x03ff; From 9c181d3e76ee7c8c64a59da11284920a6bf03285 Mon Sep 17 00:00:00 2001 From: Dan Paulat Date: Sun, 25 Feb 2024 18:19:21 -0600 Subject: [PATCH 4/7] Use std::expf instead of std::pow with e --- wxdata/source/scwx/wsr88d/rpg/product_description_block.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/wxdata/source/scwx/wsr88d/rpg/product_description_block.cpp b/wxdata/source/scwx/wsr88d/rpg/product_description_block.cpp index f09a32b4..ee0726c7 100644 --- a/wxdata/source/scwx/wsr88d/rpg/product_description_block.cpp +++ b/wxdata/source/scwx/wsr88d/rpg/product_description_block.cpp @@ -4,7 +4,6 @@ #include #include -#include #include #include @@ -1029,8 +1028,7 @@ ProductDescriptionBlock::data_value(std::uint8_t level) const } else { - f = static_cast(std::pow( - std::numbers::e, (level - log_offset()) / log_scale())); + f = std::expf((level - log_offset()) / log_scale()); } break; From 8a78a48dfda981cb1b29b08b7d62a1053919995b Mon Sep 17 00:00:00 2001 From: Dan Paulat Date: Sun, 25 Feb 2024 18:19:59 -0600 Subject: [PATCH 5/7] Add log parameters to color table change detection --- .../scwx/qt/view/level3_product_view.cpp | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/scwx-qt/source/scwx/qt/view/level3_product_view.cpp b/scwx-qt/source/scwx/qt/view/level3_product_view.cpp index 099e3fac..a749ec18 100644 --- a/scwx-qt/source/scwx/qt/view/level3_product_view.cpp +++ b/scwx-qt/source/scwx/qt/view/level3_product_view.cpp @@ -56,8 +56,11 @@ public: uint16_t colorTableMax_; std::shared_ptr savedColorTable_; - float savedScale_; - float savedOffset_; + float savedScale_ {1.0f}; + float savedOffset_ {0.0f}; + std::uint16_t savedLogStart_ {20u}; + float savedLogScale_ {1.0f}; + float savedLogOffset_ {0.0f}; }; Level3ProductView::Level3ProductView( @@ -247,9 +250,12 @@ void Level3ProductView::UpdateColorTableLut() return; } - float offset = descriptionBlock->offset(); - float scale = descriptionBlock->scale(); - std::uint8_t threshold = static_cast( + float offset = descriptionBlock->offset(); + float scale = descriptionBlock->scale(); + float logOffset = descriptionBlock->log_offset(); + float logScale = descriptionBlock->log_scale(); + std::uint16_t logStart = descriptionBlock->log_start(); + std::uint8_t threshold = static_cast( std::clamp(descriptionBlock->threshold(), std::numeric_limits::min(), std::numeric_limits::max())); @@ -266,6 +272,9 @@ void Level3ProductView::UpdateColorTableLut() if (p->savedColorTable_ == p->colorTable_ && // p->savedOffset_ == offset && // p->savedScale_ == scale && // + p->savedLogOffset_ == logOffset && // + p->savedLogScale_ == logScale && // + p->savedLogStart_ == logStart && // numberOfLevels > 16) { // The color table LUT does not need updated @@ -335,6 +344,9 @@ void Level3ProductView::UpdateColorTableLut() p->savedColorTable_ = p->colorTable_; p->savedOffset_ = offset; p->savedScale_ = scale; + p->savedLogOffset_ = logOffset; + p->savedLogScale_ = logScale; + p->savedLogStart_ = logStart; Q_EMIT ColorTableLutUpdated(); } From f064b74111ab3fceb9b382f414ded20f468553a6 Mon Sep 17 00:00:00 2001 From: Dan Paulat Date: Sun, 25 Feb 2024 18:30:05 -0600 Subject: [PATCH 6/7] Add NVL product to VIL list --- wxdata/source/scwx/common/products.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/wxdata/source/scwx/common/products.cpp b/wxdata/source/scwx/common/products.cpp index b068fa4e..cd472e4d 100644 --- a/wxdata/source/scwx/common/products.cpp +++ b/wxdata/source/scwx/common/products.cpp @@ -45,6 +45,7 @@ static const std::unordered_map level2Palette_ { static const std::unordered_map level3ProductCodeMap_ { {37, "NCR"}, {56, "SRM"}, + {57, "NVL"}, {94, "DR"}, {99, "DV"}, {134, "DVL"}, @@ -76,6 +77,7 @@ static const std::unordered_map {"SW", "Spectrum Width"}, {"TDR", "Digital Reflectivity"}, {"TDV", "Digital Velocity"}, + {"VIL", "Vertically Integrated Liquid"}, {"?", "Unknown"}}; static const std::unordered_map> @@ -106,8 +108,9 @@ static const std::unordered_map> // Specific Differential Phase {"DKD", {"NXK", "NYK", "NZK", "N0K", "NAK", "N1K", "NBK", "N2K", "N3K"}}, - // Digital Vertically Integrated Liquid + // Vertically Integrated Liquid {"DVL", {"DVL"}}, + {"VIL", {"NVL"}}, // Hydrometeor Classification {"DHC", {"NXH", "NYH", "NZH", "N0H", "NAH", "N1H", "NBH", "N2H", "N3H"}}, @@ -159,7 +162,7 @@ static const std::unordered_map> {Level3ProductCategory::DifferentialReflectivity, {"DZD"}}, {Level3ProductCategory::SpecificDifferentialPhase, {"DKD"}}, {Level3ProductCategory::CorrelationCoefficient, {"DCC"}}, - {Level3ProductCategory::VerticallyIntegratedLiquid, {"DVL"}}, + {Level3ProductCategory::VerticallyIntegratedLiquid, {"DVL", "VIL"}}, {Level3ProductCategory::HydrometeorClassification, {"DHC", "HHC"}}, {Level3ProductCategory::Unknown, {}}}; From 5de89be01607cd2faa700c03ab807ddf6ecf9721 Mon Sep 17 00:00:00 2001 From: Dan Paulat Date: Sun, 25 Feb 2024 19:12:04 -0600 Subject: [PATCH 7/7] gcc doesn't declare expf in std --- wxdata/source/scwx/wsr88d/rpg/product_description_block.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wxdata/source/scwx/wsr88d/rpg/product_description_block.cpp b/wxdata/source/scwx/wsr88d/rpg/product_description_block.cpp index ee0726c7..4bcd24fb 100644 --- a/wxdata/source/scwx/wsr88d/rpg/product_description_block.cpp +++ b/wxdata/source/scwx/wsr88d/rpg/product_description_block.cpp @@ -1028,7 +1028,7 @@ ProductDescriptionBlock::data_value(std::uint8_t level) const } else { - f = std::expf((level - log_offset()) / log_scale()); + f = expf((level - log_offset()) / log_scale()); } break;