Handle negative data moment ranges for level 2 data

This commit is contained in:
Dan Paulat 2024-01-27 16:39:49 -06:00
parent fb7f25e0bd
commit a0f43b5f3f
6 changed files with 81 additions and 75 deletions

View file

@ -522,17 +522,17 @@ void Level2ProductView::ComputeSweep()
} }
// Compute threshold at which to display an individual bin (minimum of 2) // Compute threshold at which to display an individual bin (minimum of 2)
const uint16_t snrThreshold = const std::uint16_t snrThreshold =
std::max<int16_t>(2, momentData0->snr_threshold_raw()); std::max<std::int16_t>(2, momentData0->snr_threshold_raw());
// Start radial is always 0, as coordinates are calculated for each sweep // Start radial is always 0, as coordinates are calculated for each sweep
constexpr std::uint16_t startRadial = 0u; constexpr std::uint16_t startRadial = 0u;
for (auto& radialPair : *radarData) for (auto& radialPair : *radarData)
{ {
uint16_t radial = radialPair.first; std::uint16_t radial = radialPair.first;
auto& radialData = radialPair.second; auto& radialData = radialPair.second;
auto momentData = radialData->moment_data_block(p->dataBlockType_); auto momentData = radialData->moment_data_block(p->dataBlockType_);
if (momentData0->data_word_size() != momentData->data_word_size()) if (momentData0->data_word_size() != momentData->data_word_size())
{ {
@ -541,65 +541,70 @@ void Level2ProductView::ComputeSweep()
} }
// Compute gate interval // Compute gate interval
const std::uint16_t dataMomentInterval = const std::int32_t dataMomentInterval =
momentData->data_moment_range_sample_interval_raw(); momentData->data_moment_range_sample_interval_raw();
const std::uint16_t dataMomentIntervalH = dataMomentInterval / 2; const std::int32_t dataMomentIntervalH = dataMomentInterval / 2;
const std::uint16_t dataMomentRange = const std::int32_t dataMomentRange = std::max<std::int32_t>(
std::max(momentData->data_moment_range_raw(), dataMomentIntervalH); momentData->data_moment_range_raw(), dataMomentIntervalH);
// Compute gate size (number of base 250m gates per bin) // Compute gate size (number of base 250m gates per bin)
const uint16_t gateSizeMeters = const std::int32_t gateSizeMeters =
static_cast<uint16_t>(radarProductManager->gate_size()); static_cast<std::int32_t>(radarProductManager->gate_size());
const uint16_t gateSize = const std::int32_t gateSize =
std::max<uint16_t>(1, dataMomentInterval / gateSizeMeters); std::max<std::int32_t>(1, dataMomentInterval / gateSizeMeters);
// Compute gate range [startGate, endGate) // Compute gate range [startGate, endGate)
const uint16_t startGate = const std::int32_t startGate =
(dataMomentRange - dataMomentIntervalH) / gateSizeMeters; (dataMomentRange - dataMomentIntervalH) / gateSizeMeters;
const uint16_t numberOfDataMomentGates = const std::int32_t numberOfDataMomentGates =
std::min<uint16_t>(momentData->number_of_data_moment_gates(), std::min<std::int32_t>(momentData->number_of_data_moment_gates(),
static_cast<uint16_t>(gates)); static_cast<std::int32_t>(gates));
const uint16_t endGate = const std::int32_t endGate = std::min<std::int32_t>(
std::min<uint16_t>(startGate + numberOfDataMomentGates * gateSize, startGate + numberOfDataMomentGates * gateSize,
common::MAX_DATA_MOMENT_GATES); static_cast<std::int32_t>(common::MAX_DATA_MOMENT_GATES));
const uint8_t* dataMomentsArray8 = nullptr; const std::uint8_t* dataMomentsArray8 = nullptr;
const uint16_t* dataMomentsArray16 = nullptr; const std::uint16_t* dataMomentsArray16 = nullptr;
const uint8_t* cfpMomentsArray = nullptr; const std::uint8_t* cfpMomentsArray = nullptr;
if (momentData->data_word_size() == 8) if (momentData->data_word_size() == 8)
{ {
dataMomentsArray8 = dataMomentsArray8 =
reinterpret_cast<const uint8_t*>(momentData->data_moments()); reinterpret_cast<const std::uint8_t*>(momentData->data_moments());
} }
else else
{ {
dataMomentsArray16 = dataMomentsArray16 =
reinterpret_cast<const uint16_t*>(momentData->data_moments()); reinterpret_cast<const std::uint16_t*>(momentData->data_moments());
} }
if (cfpMoments.size() > 0) if (cfpMoments.size() > 0)
{ {
cfpMomentsArray = reinterpret_cast<const uint8_t*>( cfpMomentsArray = reinterpret_cast<const std::uint8_t*>(
radialData->moment_data_block(wsr88d::rda::DataBlockType::MomentCfp) radialData->moment_data_block(wsr88d::rda::DataBlockType::MomentCfp)
->data_moments()); ->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) 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 // Store data moment value
if (dataMomentsArray8 != nullptr) if (dataMomentsArray8 != nullptr)
{ {
uint8_t dataValue = dataMomentsArray8[i]; std::uint8_t dataValue = dataMomentsArray8[i];
if (dataValue < snrThreshold && dataValue != RANGE_FOLDED) if (dataValue < snrThreshold && dataValue != RANGE_FOLDED)
{ {
continue; continue;
} }
for (size_t m = 0; m < vertexCount; m++) for (std::size_t m = 0; m < vertexCount; m++)
{ {
dataMoments8[mIndex++] = dataMomentsArray8[i]; dataMoments8[mIndex++] = dataMomentsArray8[i];
@ -611,13 +616,13 @@ void Level2ProductView::ComputeSweep()
} }
else else
{ {
uint16_t dataValue = dataMomentsArray16[i]; std::uint16_t dataValue = dataMomentsArray16[i];
if (dataValue < snrThreshold && dataValue != RANGE_FOLDED) if (dataValue < snrThreshold && dataValue != RANGE_FOLDED)
{ {
continue; continue;
} }
for (size_t m = 0; m < vertexCount; m++) for (std::size_t m = 0; m < vertexCount; m++)
{ {
dataMoments16[mIndex++] = dataMomentsArray16[i]; dataMoments16[mIndex++] = dataMomentsArray16[i];
} }
@ -626,18 +631,18 @@ void Level2ProductView::ComputeSweep()
// Store vertices // Store vertices
if (gate > 0) if (gate > 0)
{ {
const uint16_t baseCoord = gate - 1; const std::uint16_t baseCoord = gate - 1;
size_t offset1 = ((startRadial + radial) % radials * std::size_t offset1 = ((startRadial + radial) % radials *
common::MAX_DATA_MOMENT_GATES + common::MAX_DATA_MOMENT_GATES +
baseCoord) * baseCoord) *
2; 2;
size_t offset2 = offset1 + gateSize * 2; std::size_t offset2 = offset1 + gateSize * 2;
size_t offset3 = (((startRadial + radial + 1) % radials) * std::size_t offset3 = (((startRadial + radial + 1) % radials) *
common::MAX_DATA_MOMENT_GATES + common::MAX_DATA_MOMENT_GATES +
baseCoord) * baseCoord) *
2; 2;
size_t offset4 = offset3 + gateSize * 2; std::size_t offset4 = offset3 + gateSize * 2;
vertices[vIndex++] = coordinates[offset1]; vertices[vIndex++] = coordinates[offset1];
vertices[vIndex++] = coordinates[offset1 + 1]; vertices[vIndex++] = coordinates[offset1 + 1];
@ -661,16 +666,16 @@ void Level2ProductView::ComputeSweep()
} }
else else
{ {
const uint16_t baseCoord = gate; const std::uint16_t baseCoord = gate;
size_t offset1 = ((startRadial + radial) % radials * std::size_t offset1 = ((startRadial + radial) % radials *
common::MAX_DATA_MOMENT_GATES + common::MAX_DATA_MOMENT_GATES +
baseCoord) * baseCoord) *
2; 2;
size_t offset2 = (((startRadial + radial + 1) % radials) * std::size_t offset2 = (((startRadial + radial + 1) % radials) *
common::MAX_DATA_MOMENT_GATES + common::MAX_DATA_MOMENT_GATES +
baseCoord) * baseCoord) *
2; 2;
vertices[vIndex++] = p->latitude_; vertices[vIndex++] = p->latitude_;
vertices[vIndex++] = p->longitude_; vertices[vIndex++] = p->longitude_;
@ -866,25 +871,26 @@ Level2ProductView::GetBinLevel(const common::Coordinate& coordinate) const
// Compute gate interval // Compute gate interval
auto momentData = (*radarData)[*radial]->moment_data_block(dataBlockType); 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(); momentData->data_moment_range_sample_interval_raw();
const std::uint16_t dataMomentIntervalH = dataMomentInterval / 2; const std::int32_t dataMomentIntervalH = dataMomentInterval / 2;
const std::uint16_t dataMomentRange = const std::int32_t dataMomentRange = std::max<std::int32_t>(
std::max(momentData->data_moment_range_raw(), dataMomentIntervalH); momentData->data_moment_range_raw(), dataMomentIntervalH);
// Compute gate size (number of base 250m gates per bin) // Compute gate size (number of base 250m gates per bin)
const std::uint16_t gateSizeMeters = const std::int32_t gateSizeMeters =
static_cast<std::uint16_t>(radarProductManager->gate_size()); static_cast<std::int32_t>(radarProductManager->gate_size());
// Compute gate range [startGate, endGate) // Compute gate range [startGate, endGate)
const std::uint16_t startGate = const std::int32_t startGate =
(dataMomentRange - dataMomentIntervalH) / gateSizeMeters; (dataMomentRange - dataMomentIntervalH) / gateSizeMeters;
const std::uint16_t numberOfDataMomentGates = const std::int32_t numberOfDataMomentGates =
momentData->number_of_data_moment_gates(); 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 // Coordinate is beyond radar range
return std::nullopt; return std::nullopt;

View file

@ -31,9 +31,9 @@ public:
std::uint16_t elevation_angle_raw() const; std::uint16_t elevation_angle_raw() const;
units::degrees<float> elevation_angle() const; units::degrees<float> elevation_angle() const;
std::uint16_t elevation_number() const; std::uint16_t elevation_number() const;
std::uint16_t surveillance_range_raw() const; std::int16_t surveillance_range_raw() const;
units::kilometers<float> surveillance_range() const; units::kilometers<float> surveillance_range() const;
std::uint16_t doppler_range_raw() const; std::int16_t doppler_range_raw() const;
units::kilometers<float> doppler_range() const; units::kilometers<float> doppler_range() const;
std::uint16_t surveillance_range_sample_interval_raw() const; std::uint16_t surveillance_range_sample_interval_raw() const;
units::kilometers<float> surveillance_range_sample_interval() const; units::kilometers<float> surveillance_range_sample_interval() const;

View file

@ -120,7 +120,7 @@ public:
std::uint16_t number_of_data_moment_gates() const; std::uint16_t number_of_data_moment_gates() const;
units::kilometers<float> data_moment_range() const; units::kilometers<float> data_moment_range() const;
std::uint16_t data_moment_range_raw() const; std::int16_t data_moment_range_raw() const;
units::kilometers<float> data_moment_range_sample_interval() const; units::kilometers<float> data_moment_range_sample_interval() const;
std::uint16_t data_moment_range_sample_interval_raw() const; std::uint16_t data_moment_range_sample_interval_raw() const;
float snr_threshold() const; float snr_threshold() const;

View file

@ -79,7 +79,7 @@ public:
virtual std::uint16_t number_of_data_moment_gates() const = 0; virtual std::uint16_t number_of_data_moment_gates() const = 0;
virtual units::kilometers<float> data_moment_range() const = 0; virtual units::kilometers<float> 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<float> virtual units::kilometers<float>
data_moment_range_sample_interval() const = 0; data_moment_range_sample_interval() const = 0;
virtual std::uint16_t data_moment_range_sample_interval_raw() const = 0; virtual std::uint16_t data_moment_range_sample_interval_raw() const = 0;

View file

@ -33,8 +33,8 @@ public:
std::uint16_t radialStatus_ {}; std::uint16_t radialStatus_ {};
std::uint16_t elevationAngle_ {}; std::uint16_t elevationAngle_ {};
std::uint16_t elevationNumber_ {}; std::uint16_t elevationNumber_ {};
std::uint16_t surveillanceRange_ {}; std::int16_t surveillanceRange_ {};
std::uint16_t dopplerRange_ {}; std::int16_t dopplerRange_ {};
std::uint16_t surveillanceRangeSampleInterval_ {}; std::uint16_t surveillanceRangeSampleInterval_ {};
std::uint16_t dopplerRangeSampleInterval_ {}; std::uint16_t dopplerRangeSampleInterval_ {};
std::uint16_t numberOfSurveillanceBins_ {}; std::uint16_t numberOfSurveillanceBins_ {};
@ -71,7 +71,7 @@ public:
std::uint16_t number_of_data_moment_gates() const; std::uint16_t number_of_data_moment_gates() const;
units::kilometers<float> data_moment_range() const; units::kilometers<float> data_moment_range() const;
std::uint16_t data_moment_range_raw() const; std::int16_t data_moment_range_raw() const;
units::kilometers<float> data_moment_range_sample_interval() const; units::kilometers<float> data_moment_range_sample_interval() const;
std::uint16_t data_moment_range_sample_interval_raw() const; std::uint16_t data_moment_range_sample_interval_raw() const;
std::int16_t snr_threshold_raw() const; std::int16_t snr_threshold_raw() const;
@ -94,7 +94,7 @@ public:
~Impl() = default; ~Impl() = default;
std::uint16_t numberOfDataMomentGates_ {}; std::uint16_t numberOfDataMomentGates_ {};
std::uint16_t dataMomentRange_ {}; std::int16_t dataMomentRange_ {};
std::uint16_t dataMomentRangeSampleInterval_ {}; std::uint16_t dataMomentRangeSampleInterval_ {};
float scale_ {}; float scale_ {};
float offset_ {}; float offset_ {};
@ -162,7 +162,7 @@ std::uint16_t DigitalRadarData::elevation_number() const
return p->elevationNumber_; return p->elevationNumber_;
} }
std::uint16_t DigitalRadarData::surveillance_range_raw() const std::int16_t DigitalRadarData::surveillance_range_raw() const
{ {
return p->surveillanceRange_; return p->surveillanceRange_;
} }
@ -172,7 +172,7 @@ units::kilometers<float> DigitalRadarData::surveillance_range() const
return units::kilometers<float> {p->surveillanceRange_ * kRangeScale}; return units::kilometers<float> {p->surveillanceRange_ * kRangeScale};
} }
std::uint16_t DigitalRadarData::doppler_range_raw() const std::int16_t DigitalRadarData::doppler_range_raw() const
{ {
return p->dopplerRange_; return p->dopplerRange_;
} }
@ -363,7 +363,7 @@ DigitalRadarData::Impl::MomentDataBlock::data_moment_range() const
return units::kilometers<float> {p->dataMomentRange_ * kRangeScale}; return units::kilometers<float> {p->dataMomentRange_ * kRangeScale};
} }
std::uint16_t std::int16_t
DigitalRadarData::Impl::MomentDataBlock::data_moment_range_raw() const DigitalRadarData::Impl::MomentDataBlock::data_moment_range_raw() const
{ {
return p->dataMomentRange_; return p->dataMomentRange_;

View file

@ -54,7 +54,7 @@ public:
explicit Impl() {} explicit Impl() {}
std::uint16_t numberOfDataMomentGates_ {0}; std::uint16_t numberOfDataMomentGates_ {0};
std::uint16_t dataMomentRange_ {0}; std::int16_t dataMomentRange_ {0};
std::uint16_t dataMomentRangeSampleInterval_ {0}; std::uint16_t dataMomentRangeSampleInterval_ {0};
std::uint16_t tover_ {0}; std::uint16_t tover_ {0};
std::int16_t snrThreshold_ {0}; std::int16_t snrThreshold_ {0};
@ -92,7 +92,7 @@ DigitalRadarDataGeneric::MomentDataBlock::data_moment_range() const
return units::kilometers<float> {p->dataMomentRange_ * 0.001f}; return units::kilometers<float> {p->dataMomentRange_ * 0.001f};
} }
std::uint16_t std::int16_t
DigitalRadarDataGeneric::MomentDataBlock::data_moment_range_raw() const DigitalRadarDataGeneric::MomentDataBlock::data_moment_range_raw() const
{ {
return p->dataMomentRange_; return p->dataMomentRange_;