Skip to content

Commit

Permalink
Merge pull request #297 from dpaulat/feature/level2-sweeps
Browse files Browse the repository at this point in the history
Intermediate Level 2 Sweeps
  • Loading branch information
dpaulat authored Nov 28, 2024
2 parents 5dd3013 + ae91686 commit dbfacdf
Show file tree
Hide file tree
Showing 10 changed files with 240 additions and 213 deletions.
20 changes: 7 additions & 13 deletions scwx-qt/source/scwx/qt/main/main_window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ class MainWindowImpl : public QObject

std::vector<map::MapWidget*> maps_;

std::chrono::system_clock::time_point volumeTime_ {};
std::chrono::system_clock::time_point selectedTime_ {};

public slots:
void UpdateMapParameters(double latitude,
Expand Down Expand Up @@ -997,22 +997,15 @@ void MainWindowImpl::ConnectAnimationSignals()

connect(timelineManager_.get(),
&manager::TimelineManager::SelectedTimeUpdated,
[this]()
{
for (auto map : maps_)
{
QMetaObject::invokeMethod(
map, static_cast<void (QWidget::*)()>(&QWidget::update));
}
});
connect(timelineManager_.get(),
&manager::TimelineManager::VolumeTimeUpdated,
[this](std::chrono::system_clock::time_point dateTime)
{
volumeTime_ = dateTime;
selectedTime_ = dateTime;

for (auto map : maps_)
{
map->SelectTime(dateTime);
QMetaObject::invokeMethod(
map, static_cast<void (QWidget::*)()>(&QWidget::update));
}
});

Expand Down Expand Up @@ -1400,7 +1393,8 @@ void MainWindowImpl::SelectRadarProduct(map::MapWidget* mapWidget,
UpdateRadarProductSettings();
}

mapWidget->SelectRadarProduct(group, productName, productCode, volumeTime_);
mapWidget->SelectRadarProduct(
group, productName, productCode, selectedTime_);
}

void MainWindowImpl::SetActiveMap(map::MapWidget* mapWidget)
Expand Down
224 changes: 130 additions & 94 deletions scwx-qt/source/scwx/qt/manager/radar_product_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,13 +91,7 @@ class ProviderManager : public QObject
const std::string& radarId,
common::RadarProductGroup group,
const std::string& product) :
radarId_ {radarId},
group_ {group},
product_ {product},
refreshEnabled_ {false},
refreshTimer_ {threadPool_},
refreshTimerMutex_ {},
provider_ {nullptr}
radarId_ {radarId}, group_ {group}, product_ {product}
{
connect(this,
&ProviderManager::NewDataAvailable,
Expand All @@ -115,10 +109,10 @@ class ProviderManager : public QObject
const std::string radarId_;
const common::RadarProductGroup group_;
const std::string product_;
bool refreshEnabled_;
boost::asio::steady_timer refreshTimer_;
std::mutex refreshTimerMutex_;
std::shared_ptr<provider::NexradDataProvider> provider_;
bool refreshEnabled_ {false};
boost::asio::steady_timer refreshTimer_ {threadPool_};
std::mutex refreshTimerMutex_ {};
std::shared_ptr<provider::NexradDataProvider> provider_ {nullptr};

signals:
void NewDataAvailable(common::RadarProductGroup group,
Expand All @@ -136,24 +130,8 @@ class RadarProductManagerImpl
initialized_ {false},
level3ProductsInitialized_ {false},
radarSite_ {config::RadarSite::Get(radarId)},
coordinates0_5Degree_ {},
coordinates1Degree_ {},
level2ProductRecords_ {},
level2ProductRecentRecords_ {},
level3ProductRecordsMap_ {},
level3ProductRecentRecordsMap_ {},
level2ProductRecordMutex_ {},
level3ProductRecordMutex_ {},
level2ProviderManager_ {std::make_shared<ProviderManager>(
self_, radarId_, common::RadarProductGroup::Level2)},
level3ProviderManagerMap_ {},
level3ProviderManagerMutex_ {},
initializeMutex_ {},
level3ProductsInitializeMutex_ {},
loadLevel2DataMutex_ {},
loadLevel3DataMutex_ {},
availableCategoryMap_ {},
availableCategoryMutex_ {}
self_, radarId_, common::RadarProductGroup::Level2)}
{
if (radarSite_ == nullptr)
{
Expand Down Expand Up @@ -198,9 +176,9 @@ class RadarProductManagerImpl
void RefreshData(std::shared_ptr<ProviderManager> providerManager);
void RefreshDataSync(std::shared_ptr<ProviderManager> providerManager);

std::tuple<std::shared_ptr<types::RadarProductRecord>,
std::chrono::system_clock::time_point>
GetLevel2ProductRecord(std::chrono::system_clock::time_point time);
std::map<std::chrono::system_clock::time_point,
std::shared_ptr<types::RadarProductRecord>>
GetLevel2ProductRecords(std::chrono::system_clock::time_point time);
std::tuple<std::shared_ptr<types::RadarProductRecord>,
std::chrono::system_clock::time_point>
GetLevel3ProductRecord(const std::string& product,
Expand Down Expand Up @@ -247,30 +225,30 @@ class RadarProductManagerImpl
std::shared_ptr<config::RadarSite> radarSite_;
std::size_t cacheLimit_ {6u};

std::vector<float> coordinates0_5Degree_;
std::vector<float> coordinates1Degree_;
std::vector<float> coordinates0_5Degree_ {};
std::vector<float> coordinates1Degree_ {};

RadarProductRecordMap level2ProductRecords_;
RadarProductRecordList level2ProductRecentRecords_;
RadarProductRecordMap level2ProductRecords_ {};
RadarProductRecordList level2ProductRecentRecords_ {};
std::unordered_map<std::string, RadarProductRecordMap>
level3ProductRecordsMap_;
level3ProductRecordsMap_ {};
std::unordered_map<std::string, RadarProductRecordList>
level3ProductRecentRecordsMap_;
std::shared_mutex level2ProductRecordMutex_;
std::shared_mutex level3ProductRecordMutex_;
level3ProductRecentRecordsMap_ {};
std::shared_mutex level2ProductRecordMutex_ {};
std::shared_mutex level3ProductRecordMutex_ {};

std::shared_ptr<ProviderManager> level2ProviderManager_;
std::unordered_map<std::string, std::shared_ptr<ProviderManager>>
level3ProviderManagerMap_;
std::shared_mutex level3ProviderManagerMutex_;
level3ProviderManagerMap_ {};
std::shared_mutex level3ProviderManagerMutex_ {};

std::mutex initializeMutex_;
std::mutex level3ProductsInitializeMutex_;
std::mutex loadLevel2DataMutex_;
std::mutex loadLevel3DataMutex_;
std::mutex initializeMutex_ {};
std::mutex level3ProductsInitializeMutex_ {};
std::mutex loadLevel2DataMutex_ {};
std::mutex loadLevel3DataMutex_ {};

common::Level3ProductCategoryMap availableCategoryMap_;
std::shared_mutex availableCategoryMutex_;
common::Level3ProductCategoryMap availableCategoryMap_ {};
std::shared_mutex availableCategoryMutex_ {};

std::unordered_map<boost::uuids::uuid,
std::shared_ptr<ProviderManager>,
Expand Down Expand Up @@ -1173,60 +1151,91 @@ void RadarProductManagerImpl::PopulateProductTimes(
});
}

std::tuple<std::shared_ptr<types::RadarProductRecord>,
std::chrono::system_clock::time_point>
RadarProductManagerImpl::GetLevel2ProductRecord(
std::map<std::chrono::system_clock::time_point,
std::shared_ptr<types::RadarProductRecord>>
RadarProductManagerImpl::GetLevel2ProductRecords(
std::chrono::system_clock::time_point time)
{
std::shared_ptr<types::RadarProductRecord> record {nullptr};
RadarProductRecordMap::const_pointer recordPtr {nullptr};
std::chrono::system_clock::time_point recordTime {time};
std::map<std::chrono::system_clock::time_point,
std::shared_ptr<types::RadarProductRecord>>
records {};
std::vector<RadarProductRecordMap::const_pointer> recordPtrs {};

// Ensure Level 2 product records are updated
PopulateLevel2ProductTimes(time);

if (!level2ProductRecords_.empty() &&
time == std::chrono::system_clock::time_point {})
{
// If a default-initialized time point is given, return the latest record
recordPtr = &(*level2ProductRecords_.rbegin());
}
else
{
recordPtr =
scwx::util::GetBoundedElementPointer(level2ProductRecords_, time);
}
std::shared_lock lock {level2ProductRecordMutex_};

if (recordPtr != nullptr)
{
// Don't check for an exact time match for level 2 products
recordTime = recordPtr->first;
record = recordPtr->second.lock();
if (!level2ProductRecords_.empty() &&
time == std::chrono::system_clock::time_point {})
{
// If a default-initialized time point is given, return the latest
// record
recordPtrs.push_back(&(*level2ProductRecords_.rbegin()));
}
else
{
// Get the requested record
auto recordIt =
scwx::util::GetBoundedElementIterator(level2ProductRecords_, time);

if (recordIt != level2ProductRecords_.cend())
{
recordPtrs.push_back(&(*(recordIt)));

// The requested time may be in the previous record, so get that too
if (recordIt != level2ProductRecords_.cbegin())
{
recordPtrs.push_back(&(*(--recordIt)));
}
}
}
}

if (recordPtr != nullptr && record == nullptr &&
recordTime != std::chrono::system_clock::time_point {})
// For each record pointer
for (auto& recordPtr : recordPtrs)
{
// Product is expired, reload it
std::shared_ptr<request::NexradFileRequest> request =
std::make_shared<request::NexradFileRequest>(radarId_);
std::shared_ptr<types::RadarProductRecord> record {nullptr};
std::chrono::system_clock::time_point recordTime {time};

QObject::connect(
request.get(),
&request::NexradFileRequest::RequestComplete,
self_,
[this](std::shared_ptr<request::NexradFileRequest> request)
{
if (request->radar_product_record() != nullptr)
if (recordPtr != nullptr)
{
// Don't check for an exact time match for level 2 products
recordTime = recordPtr->first;
record = recordPtr->second.lock();
}

if (recordPtr != nullptr && record == nullptr &&
recordTime != std::chrono::system_clock::time_point {})
{
// Product is expired, reload it
std::shared_ptr<request::NexradFileRequest> request =
std::make_shared<request::NexradFileRequest>(radarId_);

QObject::connect(
request.get(),
&request::NexradFileRequest::RequestComplete,
self_,
[this](std::shared_ptr<request::NexradFileRequest> request)
{
Q_EMIT self_->DataReloaded(request->radar_product_record());
}
});
if (request->radar_product_record() != nullptr)
{
Q_EMIT self_->DataReloaded(request->radar_product_record());
}
});

self_->LoadLevel2Data(recordTime, request);
self_->LoadLevel2Data(recordTime, request);
}

if (record != nullptr)
{
// Return valid records
records.insert_or_assign(recordTime, record);
}
}

return {record, recordTime};
return records;
}

std::tuple<std::shared_ptr<types::RadarProductRecord>,
Expand Down Expand Up @@ -1399,19 +1408,46 @@ RadarProductManager::GetLevel2Data(wsr88d::rda::DataBlockType dataBlockType,
{
std::shared_ptr<wsr88d::rda::ElevationScan> radarData = nullptr;
float elevationCut = 0.0f;
std::vector<float> elevationCuts;
std::vector<float> elevationCuts {};
std::chrono::system_clock::time_point foundTime {};

std::shared_ptr<types::RadarProductRecord> record;
std::tie(record, time) = p->GetLevel2ProductRecord(time);
auto records = p->GetLevel2ProductRecords(time);

if (record != nullptr)
for (auto& recordPair : records)
{
std::tie(radarData, elevationCut, elevationCuts) =
record->level2_file()->GetElevationScan(
dataBlockType, elevation, time);
auto& record = recordPair.second;

if (record != nullptr)
{
std::shared_ptr<wsr88d::rda::ElevationScan> recordRadarData = nullptr;
float recordElevationCut = 0.0f;
std::vector<float> recordElevationCuts;

std::tie(recordRadarData, recordElevationCut, recordElevationCuts) =
record->level2_file()->GetElevationScan(
dataBlockType, elevation, time);

if (recordRadarData != nullptr)
{
auto& radarData0 = (*recordRadarData)[0];
auto collectionTime =
scwx::util::TimePoint(radarData0->modified_julian_date(),
radarData0->collection_time());

// Find the newest radar data, not newer than the selected time
if (radarData == nullptr ||
(collectionTime <= time && foundTime < collectionTime))
{
radarData = recordRadarData;
elevationCut = recordElevationCut;
elevationCuts = std::move(recordElevationCuts);
foundTime = collectionTime;
}
}
}
}

return {radarData, elevationCut, elevationCuts, time};
return {radarData, elevationCut, elevationCuts, foundTime};
}

std::tuple<std::shared_ptr<wsr88d::rpg::Level3Message>,
Expand Down Expand Up @@ -1449,7 +1485,7 @@ std::vector<std::string> RadarProductManager::GetLevel3Products()

void RadarProductManager::SetCacheLimit(size_t cacheLimit)
{
p->cacheLimit_ = cacheLimit;
p->cacheLimit_ = std::max<std::size_t>(cacheLimit, 6u);
}

void RadarProductManager::UpdateAvailableProducts()
Expand Down
1 change: 1 addition & 0 deletions scwx-qt/source/scwx/qt/manager/radar_product_manager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ class RadarProductManager : public QObject

/**
* @brief Set the maximum number of products of each type that may be cached.
* The cache limit cannot be set lower than 6.
*
* @param [in] cacheLimit The maximum number of products of each type
*/
Expand Down
Loading

0 comments on commit dbfacdf

Please sign in to comment.