fully working merging of data from last and current scan

This commit is contained in:
AdenKoperczak 2025-04-07 12:36:06 -04:00
parent 8b7a3e9781
commit 094d286b41
No known key found for this signature in database
GPG key ID: 9843017036F62EE7
5 changed files with 140 additions and 153 deletions

View file

@ -1520,87 +1520,17 @@ RadarProductManager::GetLevel2Data(wsr88d::rda::DataBlockType dataBlockType,
std::vector<float> elevationCuts {}; std::vector<float> elevationCuts {};
std::chrono::system_clock::time_point foundTime {}; std::chrono::system_clock::time_point foundTime {};
auto records = p->GetLevel2ProductRecords(time);
//TODO decide when to use chunked vs archived data. //TODO decide when to use chunked vs archived data.
if (true) if constexpr (true)
{ {
auto currentFile = std::dynamic_pointer_cast<wsr88d::Ar2vFile>( auto currentFile = std::dynamic_pointer_cast<wsr88d::Ar2vFile>(
p->level2ChunksProviderManager_->provider_->LoadLatestObject()); p->level2ChunksProviderManager_->provider_->LoadLatestObject());
auto lastFile = std::dynamic_pointer_cast<wsr88d::Ar2vFile>(
p->level2ChunksProviderManager_->provider_->LoadSecondLatestObject());
auto radarFile =
std::make_shared<wsr88d::Ar2vFile>(currentFile, lastFile);
std::tie(radarData, elevationCut, elevationCuts) = std::tie(radarData, elevationCut, elevationCuts) =
radarFile->GetElevationScan(dataBlockType, elevation, time); currentFile->GetElevationScan(dataBlockType, elevation, time);
/*
auto currentFile = std::dynamic_pointer_cast<wsr88d::Ar2vFile>(
p->level2ChunksProviderManager_->provider_->LoadLatestObject());
std::shared_ptr<wsr88d::rda::ElevationScan> currentRadarData = nullptr;
float currentElevationCut = 0.0f;
std::vector<float> currentElevationCuts;
if (currentFile != nullptr)
{
std::tie(currentRadarData, currentElevationCut, currentElevationCuts) =
currentFile->GetElevationScan(dataBlockType, elevation, time);
}
std::shared_ptr<wsr88d::rda::ElevationScan> lastRadarData = nullptr;
float lastElevationCut = 0.0f;
std::vector<float> lastElevationCuts;
auto lastFile = std::dynamic_pointer_cast<wsr88d::Ar2vFile>(
p->level2ChunksProviderManager_->provider_->LoadSecondLatestObject());
if (lastFile != nullptr)
{
std::tie(lastRadarData, lastElevationCut, lastElevationCuts) =
lastFile->GetElevationScan(dataBlockType, elevation, time);
}
if (currentRadarData != nullptr)
{
if (lastRadarData != nullptr)
{
auto& radarData0 = (*currentRadarData)[0];
auto collectionTime = std::chrono::floor<std::chrono::seconds>(
scwx::util::TimePoint(radarData0->modified_julian_date(),
radarData0->collection_time()));
// TODO merge data
radarData = currentRadarData;
elevationCut = currentElevationCut;
elevationCuts = std::move(currentElevationCuts);
foundTime = collectionTime;
}
else
{
auto& radarData0 = (*currentRadarData)[0];
auto collectionTime = std::chrono::floor<std::chrono::seconds>(
scwx::util::TimePoint(radarData0->modified_julian_date(),
radarData0->collection_time()));
radarData = currentRadarData;
elevationCut = currentElevationCut;
elevationCuts = std::move(currentElevationCuts);
foundTime = collectionTime;
}
}
else if (lastRadarData != nullptr)
{
auto& radarData0 = (*lastRadarData)[0];
auto collectionTime = std::chrono::floor<std::chrono::seconds>(
scwx::util::TimePoint(radarData0->modified_julian_date(),
radarData0->collection_time()));
radarData = lastRadarData;
elevationCut = lastElevationCut;
elevationCuts = std::move(lastElevationCuts);
foundTime = collectionTime;
}
*/
} }
else else
{ {
auto records = p->GetLevel2ProductRecords(time);
for (auto& recordPair : records) for (auto& recordPair : records)
{ {
auto& record = recordPair.second; auto& record = recordPair.second;

View file

@ -561,8 +561,7 @@ void Level2ProductView::ComputeSweep()
Q_EMIT SweepNotComputed(types::NoUpdateReason::NotLoaded); Q_EMIT SweepNotComputed(types::NoUpdateReason::NotLoaded);
return; return;
} }
// TODO do not do this when updating from live data if ((radarData == p->elevationScan_) &&
if (false && (radarData == p->elevationScan_) &&
smoothingEnabled == p->lastSmoothingEnabled_ && smoothingEnabled == p->lastSmoothingEnabled_ &&
(showSmoothedRangeFolding == p->lastShowSmoothedRangeFolding_ || (showSmoothedRangeFolding == p->lastShowSmoothedRangeFolding_ ||
!smoothingEnabled)) !smoothingEnabled))

View file

@ -32,7 +32,8 @@ public:
Ar2vFile(Ar2vFile&&) noexcept; Ar2vFile(Ar2vFile&&) noexcept;
Ar2vFile& operator=(Ar2vFile&&) noexcept; Ar2vFile& operator=(Ar2vFile&&) noexcept;
Ar2vFile(std::shared_ptr<Ar2vFile> current, std::shared_ptr<Ar2vFile> last); Ar2vFile(const std::shared_ptr<Ar2vFile>& current,
const std::shared_ptr<Ar2vFile>& last);
std::uint32_t julian_date() const; std::uint32_t julian_date() const;
std::uint32_t milliseconds() const; std::uint32_t milliseconds() const;

View file

@ -637,7 +637,9 @@ AwsLevel2ChunksDataProvider::LoadObjectByTime(
std::shared_ptr<wsr88d::NexradFile> std::shared_ptr<wsr88d::NexradFile>
AwsLevel2ChunksDataProvider::LoadLatestObject() AwsLevel2ChunksDataProvider::LoadLatestObject()
{ {
return p->currentScan_.nexradFile_; return std::make_shared<wsr88d::Ar2vFile>(p->currentScan_.nexradFile_,
p->lastScan_.nexradFile_);
//return p->currentScan_.nexradFile_;
} }
std::shared_ptr<wsr88d::NexradFile> std::shared_ptr<wsr88d::NexradFile>

View file

@ -9,7 +9,6 @@
#include <fstream> #include <fstream>
#include <sstream> #include <sstream>
#include <set>
#if defined(_MSC_VER) #if defined(_MSC_VER)
# pragma warning(push) # pragma warning(push)
@ -559,114 +558,171 @@ bool IsRadarDataIncomplete(
return angleDelta > kIncompleteDataAngleThreshold_; return angleDelta > kIncompleteDataAngleThreshold_;
} }
Ar2vFile::Ar2vFile(std::shared_ptr<Ar2vFile> current, Ar2vFile::Ar2vFile(const std::shared_ptr<Ar2vFile>& current,
std::shared_ptr<Ar2vFile> last) : const std::shared_ptr<Ar2vFile>& last) :
Ar2vFile() Ar2vFile()
{ {
/*p->vcpData_ = std::make_shared<rda::VolumeCoveragePatternData>( // This is only used to index right now, so not a huge deal
*current->vcp_data());*/ p->vcpData_ = nullptr;
p->vcpData_ = nullptr; // TODO
/*
use index_ to go through each block type, and elevation.
get the latest time.
if the latest time is not complete, get the previous time (possibly in
last), and merge
*/
if (current == nullptr) // Reconstruct index from the other's indexes
if (current != nullptr)
{ {
return; for (const auto& type : current->p->index_)
}
for (const auto& type : current->p->index_)
{
for (const auto& elevation : type.second)
{ {
const auto& mostRecent = elevation.second.crbegin(); for (const auto& elevation : type.second)
if (mostRecent == elevation.second.crend())
{ {
continue; // Get the most recent scan
} const auto& mostRecent = elevation.second.crbegin();
if (mostRecent == elevation.second.crend())
if (IsRadarDataIncomplete(mostRecent->second))
{
std::shared_ptr<rda::ElevationScan> secondMostRecent =
nullptr;
auto maybe = elevation.second.rbegin();
++maybe;
if (maybe == elevation.second.rend())
{ {
if (last == nullptr) continue;
}
// Merge this scan with the last one if it is incomplete
if (IsRadarDataIncomplete(mostRecent->second))
{
std::shared_ptr<rda::ElevationScan> secondMostRecent = nullptr;
// check if this volume scan has an earlier elevation scan
auto maybe = elevation.second.rbegin(); // TODO name
++maybe;
if (maybe == elevation.second.rend())
{ {
// Nothing to merge with if (last == nullptr)
p->index_[type.first][elevation.first][mostRecent->first] = {
mostRecent->second; // Nothing to merge with
continue; p->index_[type.first][elevation.first][mostRecent->first] =
mostRecent->second;
continue;
}
// get the scan from the last scan
auto elevationScan =
std::get<std::shared_ptr<rda::ElevationScan>>(
last->GetElevationScan(
type.first, elevation.first, {}));
if (elevationScan == nullptr)
{
// Nothing to merge with
p->index_[type.first][elevation.first][mostRecent->first] =
mostRecent->second;
continue;
}
secondMostRecent = elevationScan;
}
else
{
secondMostRecent = maybe->second;
} }
auto elevationScan = // Make the new scan
std::get<std::shared_ptr<rda::ElevationScan>>( auto newScan = std::make_shared<rda::ElevationScan>();
last->GetElevationScan(type.first, elevation.first, {}));
if (elevationScan == nullptr) // Copy over the new radials
for (const auto& radial : *(mostRecent->second))
{ {
// Nothing to merge with (*newScan)[radial.first] = radial.second;
p->index_[type.first][elevation.first][mostRecent->first] =
mostRecent->second;
continue;
} }
secondMostRecent = elevationScan; /* Correctly order the old radials. The radials need to be in
* order for the rendering to work, and the index needs to start
* at 0 and increase by one from there. Since the new radial
* should have index 0, the old radial needs to be reshaped to
* match the new radials indexing.
*/
const double lowestAzm =
mostRecent->second->cbegin()->second->azimuth_angle().value();
const double heighestAzm = mostRecent->second->crbegin()
->second->azimuth_angle()
.value();
std::uint16_t index = mostRecent->second->crbegin()->first + 1;
// Sort by the azimuth. Makes the rest of this way easier
auto secondMostRecentAzmMap =
std::map<float, std::shared_ptr<rda::GenericRadarData>>();
for (const auto& radial : *secondMostRecent)
{
secondMostRecentAzmMap[radial.second->azimuth_angle()
.value()] = radial.second;
}
if (lowestAzm <= heighestAzm) // New scan does not contain 0/360
{
// Get the radials following the new radials
for (const auto& radial : secondMostRecentAzmMap)
{
if (radial.first > heighestAzm)
{
(*newScan)[index] = radial.second;
++index;
}
}
// Get the radials before the new radials
for (const auto& radial : secondMostRecentAzmMap)
{
if (radial.first < lowestAzm)
{
(*newScan)[index] = radial.second;
++index;
}
else
{
break;
}
}
}
else // New scan includes 0/360
{
// The radials will already be in the right order
for (const auto& radial : secondMostRecentAzmMap)
{
if (radial.first > heighestAzm && radial.first < lowestAzm)
{
(*newScan)[index] = radial.second;
++index;
}
}
}
p->index_[type.first][elevation.first][mostRecent->first] =
newScan;
} }
else else
{ {
secondMostRecent = maybe->second; p->index_[type.first][elevation.first][mostRecent->first] =
mostRecent->second;
} }
auto newScan = std::make_shared<rda::ElevationScan>();
// Convert old into new coords
logger_->error(
"old {}, new {}",
secondMostRecent->cbegin()->second->azimuth_angle().value(),
mostRecent->second->cbegin()->second->azimuth_angle().value());
// TODO Ordering these correctly
for (const auto& radial : *secondMostRecent)
{
(*newScan)[radial.first] = radial.second;
}
for (const auto& radial : *(mostRecent->second))
{
(*newScan)[radial.first] = radial.second;
}
p->index_[type.first][elevation.first][mostRecent->first] =
newScan;
}
else
{
p->index_[type.first][elevation.first][mostRecent->first] =
mostRecent->second;
} }
} }
} }
// Go though last, adding other elevations TODO // Go though last, adding other elevations
if (last != nullptr) if (last != nullptr)
{ {
for (const auto& type : last->p->index_) for (const auto& type : last->p->index_)
{ {
// Find the highest elevation this type has for the current scan
// Start below any reasonable elevation
// NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers)
float highestCurrentElevation = -90; float highestCurrentElevation = -90;
const auto& maybe1 = p->index_.find(type.first); const auto& maybe1 = p->index_.find(type.first);
if (maybe1 != p->index_.cend()) if (maybe1 != p->index_.cend())
{ {
const auto& maybe2 = maybe1->second.crbegin(); const auto& maybe2 = maybe1->second.crbegin();
if (maybe2 != maybe1->second.crend()) { if (maybe2 != maybe1->second.crend()) {
highestCurrentElevation = maybe2->first + 0.01; // Add a slight offset to ensure good floating point compare.
// NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers)
highestCurrentElevation = maybe2->first + 0.01f;
} }
} }
for (const auto& elevation : type.second) for (const auto& elevation : type.second)
{ {
// Only add elevations above the current scan's elevation
if (elevation.first > highestCurrentElevation) if (elevation.first > highestCurrentElevation)
{ {
const auto& mostRecent = elevation.second.crbegin(); const auto& mostRecent = elevation.second.crbegin();
@ -680,7 +736,6 @@ Ar2vFile::Ar2vFile(std::shared_ptr<Ar2vFile> current,
} }
} }
} }
} }
} // namespace wsr88d } // namespace wsr88d