satdump/src-interface/viewer/radiation_handler.cpp
2024-03-04 10:57:02 -05:00

217 lines
8.4 KiB
C++

#include "radiation_handler.h"
#include "imgui/pfd/pfd_utils.h"
#include "resources.h"
#include "core/module.h"
#include "core/style.h"
#include "common/widgets/themed_widgets.h"
#include "main_ui.h"
#include "common/image/image_meta.h"
namespace satdump
{
void RadiationViewerHandler::init()
{
products = (RadiationProducts *)ViewerHandler::products;
for (int c = 0; c < (int)products->channel_counts.size(); c++)
select_channel_image_str += products->get_channel_name(c) + '\0';
update();
}
RadiationViewerHandler::~RadiationViewerHandler()
{
handler_thread_pool.stop();
for (int i = 0; i < handler_thread_pool.size(); i++)
{
if (handler_thread_pool.get_thread(i).joinable())
handler_thread_pool.get_thread(i).join();
}
}
void RadiationViewerHandler::update()
{
if (selected_visualization_id == 0)
{
handler_thread_pool.clear_queue();
handler_thread_pool.push([this](int)
{ async_image_mutex.lock();
is_updating = true;
logger->info("Update map...");
RadiationMapCfg cfg;
cfg.channel = select_channel_image_id + 1;
cfg.radius = 5;
cfg.min = map_min;
cfg.max = map_max;
map_img = make_radiation_map(*products, cfg);
image_view.update(map_img);
logger->info("Done");
is_updating = false;
async_image_mutex.unlock(); });
}
else if (selected_visualization_id == 1)
{
graph_values.clear();
graph_values.resize(products->channel_counts.size());
for (int c = 0; c < (int)products->channel_counts.size(); c++)
{
for (int i = 0; i < (int)products->channel_counts[c].size(); i++)
graph_values[c].push_back(products->channel_counts[c][i]);
}
}
}
void RadiationViewerHandler::drawMenu()
{
if (ImGui::CollapsingHeader("View"))
{
if (ImGui::RadioButton(u8"\uf84c Map", &selected_visualization_id, 0))
update();
if (ImGui::RadioButton(u8"\uf437 Graph", &selected_visualization_id, 1))
update();
if (selected_visualization_id == 0)
{
if (ImGui::Combo("###mapchannelcomboid", &select_channel_image_id, select_channel_image_str.c_str()))
update();
ImGui::SetNextItemWidth(ImGui::GetWindowWidth() / 2);
if (ImGui::DragInt("##Min", &map_min, 1.0f, 0, 255, "Min: %d", ImGuiSliderFlags_AlwaysClamp))
update();
ImGui::SameLine();
ImGui::SetNextItemWidth(ImGui::GetWindowWidth() / 2);
if (ImGui::DragInt("##Max", &map_max, 1.0f, 0, 255, "Max: %d", ImGuiSliderFlags_AlwaysClamp))
update();
}
bool save_disabled = selected_visualization_id != 0 || is_updating;
if (save_disabled)
style::beginDisabled();
if (ImGui::Button("Save"))
{
handler_thread_pool.push([this](int)
{ async_image_mutex.lock();
is_updating = true;
logger->info("Saving Image...");
std::string default_path = config::main_cfg["satdump_directories"]["default_image_output_directory"]["value"].get<std::string>();
std::string saved_at = save_image_dialog(products->instrument_name + "_map", default_path, "Save Map", &map_img, &viewer_app->save_type);
if (saved_at == "")
logger->info("Save cancelled");
else
logger->info("Saved current map at %s", saved_at.c_str());
is_updating = false;
async_image_mutex.unlock(); });
}
if (save_disabled)
style::endDisabled();
if (!canBeProjected())
style::beginDisabled();
if (ImGui::Button("Add to Projections"))
addCurrentToProjections();
ImGui::SameLine();
proj_notif.draw();
if (!canBeProjected())
style::endDisabled();
}
}
void RadiationViewerHandler::drawContents(ImVec2 win_size)
{
if (selected_visualization_id == 0)
{
image_view.draw(win_size);
}
else if (selected_visualization_id == 1)
{
ImGui::BeginChild("RadiationPlot");
for (int i = 0; i < (int)products->channel_counts.size(); i++)
{
ImGui::BeginChild(("RadiationPlotChild##" + std::to_string(i)).c_str(), ImVec2(ImGui::GetWindowWidth(), 50 * ui_scale));
widgets::ThemedPlotLines(style::theme.plot_bg.Value, products->get_channel_name(i).c_str(), graph_values[i].data(),
graph_values[i].size(), 0, NULL, 0, 255, ImVec2(ImGui::GetWindowWidth() - 100 * ui_scale, 30 * ui_scale));
ImGui::Spacing();
ImGui::Separator();
ImGui::Spacing();
ImGui::EndChild();
}
ImGui::EndChild();
}
}
float RadiationViewerHandler::drawTreeMenu()
{
return 0;
}
bool RadiationViewerHandler::canBeProjected()
{
return selected_visualization_id == 0;
}
void RadiationViewerHandler::addCurrentToProjections()
{
if (canBeProjected())
{
try
{
RadiationMapCfg cfg;
cfg.channel = select_channel_image_id + 1;
cfg.radius = 5;
cfg.min = map_min;
cfg.max = map_max;
auto map_img = make_radiation_map(*products, cfg, true);
double tl_lon = -180;
double tl_lat = 90;
double br_lon = 180;
double br_lat = -90;
nlohmann::json proj_cfg;
proj_cfg["type"] = "equirec";
proj_cfg["offset_x"] = tl_lon;
proj_cfg["offset_y"] = tl_lat;
proj_cfg["scalar_x"] = (br_lon - tl_lon) / double(map_img.width());
proj_cfg["scalar_y"] = (br_lat - tl_lat) / double(map_img.height());
image::set_metadata_proj_cfg(map_img, proj_cfg);
// Create projection title
std::string timestring, object_name, instrument_name, composite_name;
composite_name = "Channel " + std::to_string(select_channel_image_id);
if (products->has_timestamps(select_channel_image_id))
timestring = "[" + timestamp_to_string(get_median(products->get_timestamps(select_channel_image_id))) + "] ";
else
timestring = "";
if (products->has_tle())
object_name = products->get_tle().name;
else
object_name = "";
if (timestring != "" || object_name != "")
object_name += "\n";
if (instrument_cfg.contains("name"))
instrument_name = instrument_cfg["name"];
else
instrument_name = products->instrument_name;
viewer_app->projection_layers.push_back({ timestring + object_name + instrument_name + " - " + composite_name, map_img });
// if (rotate_image)
// viewer_app->projection_layers[viewer_app->projection_layers.size() - 1].img.mirror(true, true);
proj_notif.set_message(style::theme.green, "Added!");
}
catch (std::exception &e)
{
logger->error("Could not project image! %s", e.what());
}
}
else
{
logger->error("Current image can't be projected!");
}
}
}