1
0
Fork 0
mirror of https://github.com/gwm17/Specter.git synced 2024-11-22 18:28:52 -05:00

Removed viewport functionality for now, due to linux issues. Added in basic stats for histogram regions

This commit is contained in:
Gordon McCann 2022-02-12 16:25:49 -05:00
parent 1aa7a41596
commit e049927049
7 changed files with 261 additions and 31 deletions

View File

@ -1,12 +1,23 @@
#include "SpectrumPanel.h"
#include "implot.h"
#include "misc/cpp/imgui_stdlib.h"
#include "IconsFontAwesome5.h"
namespace Navigator {
std::string GenerateStatString(const std::string& name, const StatResults& results, bool is2D = true)
{
std::stringstream stream;
stream << "Region: " << name << "\n" << "Integral: " << results.integral << "\n";
if (results.integral == 0)
return stream.str();
stream << "Centroid X: " << results.cent_x << " Std. Dev. X: " << results.sigma_x << " FWHM X: " << 2.355 * results.sigma_x << "\n";
if(is2D)
stream << "Centroid Y: " << results.cent_y << " Std. Dev. Y: " << results.sigma_y << " FWHM Y: " << 2.355 * results.sigma_y << "\n";
return stream.str();
}
SpectrumPanel::SpectrumPanel() :
m_zoomedFlag(false), m_cutModeFlag(false), m_zoomedGram(), m_totalSlots(1)
m_zoomedFlag(false), m_cutModeFlag(false), m_zoomedGram(), m_nRegions(0), m_totalSlots(1)
{
m_tableSizes[0] = 1; m_tableSizes[1] = 1;
}
@ -20,43 +31,21 @@ namespace Navigator {
//CutMap& cutMap = CutMap::GetInstance();
static bool acceptCutFlag = false;
bool result = false;
//static std::string selectedRegion = "";
if (ImGui::Begin("Active View"))
{
if (histoList.size() > 0)
{
if (m_zoomedFlag && m_zoomedGram.name != "")
{
if(ImGui::Button(ICON_FA_CUT " Draw Cut"))
{
m_newCutParams = CutParams();
m_newCutX.resize(0);
m_newCutY.resize(0);
ImGui::OpenPopup(ICON_FA_CUT " New Cut Dialog");
}
if(ImGui::BeginPopupModal(ICON_FA_CUT " New Cut Dialog"))
{
m_newCutParams.x_par = m_zoomedGram.x_par;
m_newCutParams.y_par = m_zoomedGram.y_par;
ImGui::InputText("Cut Name", &m_newCutParams.name);
ImGui::BulletText("%s", ("X Parameter: "+m_newCutParams.x_par).c_str());
ImGui::BulletText("%s", ("Y Parameter: "+m_newCutParams.y_par).c_str());
if(ImGui::Button("Accept & Draw"))
{
m_cutModeFlag = true;
ImGui::CloseCurrentPopup();
}
ImGui::SameLine();
if(ImGui::Button("Cancel"))
{
ImGui::CloseCurrentPopup();
}
ImGui::EndPopup();
}
RenderCutButton();
ImGui::SameLine();
if(ImGui::Button("Clear"))
{
HistogramMap::GetInstance().ClearHistogram(m_zoomedGram.name);
}
ImGui::SameLine();
RenderRemoveRegionButton();
if (ImPlot::BeginPlot(m_zoomedGram.name.c_str(), ImVec2(-1, -1)))
{
@ -96,6 +85,26 @@ namespace Navigator {
}
ImPlot::PlotLine(m_newCutParams.name.c_str(), m_newCutX.data(), m_newCutY.data(), m_newCutX.size());
}
if (ImPlot::IsPlotSelected()) {
auto& select = ImPlot::GetPlotSelection();
if (ImGui::IsMouseClicked(ImPlot::GetInputMap().SelectCancel)) {
ImPlot::CancelPlotSelection();
m_integralRegions.emplace_back(select, "integralRegion_"+std::to_string(m_nRegions), m_zoomedGram.name);
m_nRegions++;
}
}
for (size_t i = 0; i < m_integralRegions.size(); i++)
{
auto& region = m_integralRegions[i];
if (m_zoomedGram.name == region.histogram_name)
{
ImPlot::DragRect(i, &region.region.X.Min, &region.region.Y.Min, &region.region.X.Max, &region.region.Y.Max, ImVec4(1, 0, 1, 1));
StatResults results = HistogramMap::GetInstance().AnalyzeHistogramRegion(m_zoomedGram.name, region.region);
ImPlot::PlotText(GenerateStatString(region.name, results, m_zoomedGram.y_par != "None").c_str(), (region.region.X.Max + region.region.X.Min) * 0.5,
(region.region.Y.Min + region.region.Y.Max) * 0.5);
}
}
ImPlot::EndPlot();
}
if (acceptCutFlag)
@ -181,6 +190,15 @@ namespace Navigator {
m_zoomedFlag = true;
m_zoomedGram = spec;
}
for (size_t i = 0; i < m_integralRegions.size(); i++)
{
auto& region = m_integralRegions[i];
if (spec.name == region.histogram_name)
{
ImPlot::DragRect(i, &region.region.X.Min, &region.region.Y.Min, &region.region.X.Max, &region.region.Y.Max, ImVec4(1, 0, 1, 1));
}
}
ImPlot::EndPlot();
}
i++;
@ -193,4 +211,82 @@ namespace Navigator {
}
return result;
}
void SpectrumPanel::RenderCutButton()
{
if (ImGui::Button(ICON_FA_CUT " Draw Cut"))
{
m_newCutParams = CutParams();
m_newCutX.resize(0);
m_newCutY.resize(0);
ImGui::OpenPopup(ICON_FA_CUT " New Cut Dialog");
}
if (ImGui::BeginPopupModal(ICON_FA_CUT " New Cut Dialog"))
{
m_newCutParams.x_par = m_zoomedGram.x_par;
m_newCutParams.y_par = m_zoomedGram.y_par;
ImGui::InputText("Cut Name", &m_newCutParams.name);
ImGui::BulletText("%s", ("X Parameter: " + m_newCutParams.x_par).c_str());
ImGui::BulletText("%s", ("Y Parameter: " + m_newCutParams.y_par).c_str());
if (ImGui::Button("Accept & Draw"))
{
m_cutModeFlag = true;
ImGui::CloseCurrentPopup();
}
ImGui::SameLine();
if (ImGui::Button("Cancel"))
{
ImGui::CloseCurrentPopup();
}
ImGui::EndPopup();
}
}
void SpectrumPanel::RenderRemoveRegionButton()
{
static std::string selectedRegion = "";
if (ImGui::Button("Delete Region"))
{
selectedRegion = "";
ImGui::OpenPopup("Remove Integral Region");
}
if (ImGui::BeginPopupModal("Remove Integral Region"))
{
if (ImGui::BeginCombo("Region", selectedRegion.c_str()))
{
for (auto& region : m_integralRegions)
{
if (region.histogram_name == m_zoomedGram.name)
{
if (ImGui::Selectable(region.name.c_str(), region.name == selectedRegion, ImGuiSelectableFlags_DontClosePopups))
selectedRegion = region.name;
}
}
ImGui::EndCombo();
}
if (ImGui::Button("Ok"))
{
RemoveSelectedRegion(selectedRegion);
ImGui::CloseCurrentPopup();
}
ImGui::SameLine();
if (ImGui::Button("Cancel"))
{
ImGui::CloseCurrentPopup();
}
ImGui::EndPopup();
}
}
void SpectrumPanel::RemoveSelectedRegion(const std::string& region)
{
for (size_t i=0; i<m_integralRegions.size(); i++)
{
if (m_integralRegions[i].name == region)
{
m_integralRegions.erase(m_integralRegions.begin() + i);
break;
}
}
}
}

View File

@ -5,9 +5,21 @@
#include "Navigator/ParameterMap.h"
#include "Navigator/CutMap.h"
#include "imgui.h"
#include "implot.h"
namespace Navigator {
struct NAV_API IntegrationRegion
{
IntegrationRegion(const ImPlotRect& rect, const std::string& n, const std::string& hist_n) :
region(rect), name(n), histogram_name(hist_n)
{
}
ImPlotRect region;
std::string name = "";
std::string histogram_name = "";
};
class NAV_API SpectrumPanel
{
public:
@ -19,12 +31,17 @@ namespace Navigator {
inline const bool IsZoomed() { return m_zoomedFlag; }
private:
void RenderCutButton();
void RenderRemoveRegionButton();
void RemoveSelectedRegion(const std::string& region);
std::vector<HistogramParameters> m_selectedGrams;
std::vector<IntegrationRegion> m_integralRegions;
bool m_zoomedFlag;
bool m_cutModeFlag;
HistogramParameters m_zoomedGram;
int m_tableSizes[2];
int m_totalSlots;
int m_nRegions;
CutParams m_newCutParams;
std::vector<double> m_newCutX;
std::vector<double> m_newCutY;

View File

@ -79,6 +79,35 @@ namespace Navigator {
m_binCounts[i] = 0;
}
StatResults Histogram1D::AnalyzeRegion(double x_min, double x_max, double y_min, double y_max)
{
int bin_min, bin_max;
StatResults results;
if (x_min <= m_params.min_x)
bin_min = 0;
else
bin_min = int((x_min - m_params.min_x) / (m_binWidth));
if (x_max >= m_params.max_x)
bin_max = m_params.nbins_x - 1;
else
bin_max = int((x_max - m_params.min_x) / (m_binWidth));
for (int i = bin_min; i <= bin_max; i++)
{
results.integral += m_binCounts[i];
results.cent_x += m_binCounts[i] * (m_params.min_x + m_binWidth * i);
}
if (results.integral == 0)
return results;
results.cent_x /= double(results.integral);
for (int i = bin_min; i <= bin_max; i++)
results.sigma_x += m_binCounts[i] * ((m_params.min_x + m_binWidth * i) - results.cent_x) * ((m_params.min_x + m_binWidth * i) - results.cent_x);
results.sigma_x = std::sqrt(results.sigma_x / (results.integral - 1));
return results;
}
/*
2D Histogram class
@ -158,4 +187,64 @@ namespace Navigator {
m_binCounts[i] = 0;
m_maxBinContent = 0;
}
StatResults Histogram2D::AnalyzeRegion(double x_min, double x_max, double y_min, double y_max)
{
int xbin_min, xbin_max, ybin_min, ybin_max;
int curbin;
StatResults results;
if (x_min <= m_params.min_x)
xbin_min = 0;
else
xbin_min = int((x_min - m_params.min_x) / (m_binWidthX));
if (x_max >= m_params.max_x)
xbin_max = m_params.nbins_x - 1;
else
xbin_max = int((x_max - m_params.min_x) / (m_binWidthX));
if (y_min <= m_params.min_y)
ybin_max = m_params.nbins_y - 1;
else
ybin_max = int((m_params.max_y - y_min)) / m_binWidthY;
if (y_max >= m_params.max_y)
ybin_min = 0;
else
ybin_min = int((m_params.max_y - y_max)) / m_binWidthY;
for (int y = ybin_min; y <= ybin_max; y++)
{
for (int x = xbin_min; x <= xbin_max; x++)
{
curbin = y * m_params.nbins_x + x;
results.integral += m_binCounts[curbin];
results.cent_x += m_binCounts[curbin] * (m_params.min_x + m_binWidthX * x);
results.cent_y += m_binCounts[curbin] * (m_params.max_y - m_binWidthY * y);
}
}
if (results.integral == 0)
return results;
results.cent_x /= results.integral;
results.cent_y /= results.integral;
for (int y = ybin_min; y <= ybin_max; y++)
{
for (int x = xbin_min; x <= xbin_max; x++)
{
curbin = y * m_params.nbins_x + x;
results.sigma_x += m_binCounts[curbin] * ((m_params.min_x + m_binWidthX * x) - results.cent_x) * ((m_params.min_x + m_binWidthX * x) - results.cent_x);
results.sigma_y += m_binCounts[curbin] * ((m_params.max_y - m_binWidthY * y) - results.cent_y) * ((m_params.max_y - m_binWidthY * y) - results.cent_y);
}
}
results.sigma_x = std::sqrt(results.sigma_x / (results.integral - 1));
results.sigma_y = std::sqrt(results.sigma_y / (results.integral - 1));
return results;
}
}

View File

@ -5,6 +5,15 @@
namespace Navigator {
struct NAV_API StatResults
{
int integral = 0.0;
double cent_x = 0.0;
double cent_y = 0.0;
double sigma_x = 0.0;
double sigma_y = 0.0;
};
struct NAV_API HistogramParameters
{
HistogramParameters() {}
@ -48,6 +57,7 @@ namespace Navigator {
virtual void FillData() { NAV_WARN("Trying to fill a default histogram!"); }
virtual void Draw() {}
virtual void ClearData() {}
virtual StatResults AnalyzeRegion(double x_min, double x_max, double y_min = 0.0, double y_max = 0.0) { return StatResults(); }
inline virtual bool Is1D() const { return false; }
inline virtual bool Is2D() const { return false; }
inline HistogramParameters& GetParameters() { return m_params; }
@ -70,6 +80,7 @@ namespace Navigator {
virtual void FillData() override;
virtual void Draw() override;
virtual void ClearData() override;
virtual StatResults AnalyzeRegion(double x_min, double x_max, double y_min = 0.0, double y_max = 0.0) override;
inline virtual bool Is1D() const override { return true; }
inline virtual bool Is2D() const override { return false; }
@ -90,6 +101,7 @@ namespace Navigator {
virtual void FillData() override;
virtual void Draw() override;
virtual void ClearData() override;
virtual StatResults AnalyzeRegion(double x_min, double x_max, double y_min = 0.0, double y_max = 0.0) override;
inline virtual bool Is1D() const override { return false; }
inline virtual bool Is2D() const override { return true; }

View File

@ -1,6 +1,8 @@
#include "HistogramMap.h"
#include "ParameterMap.h"
#include "implot.h"
namespace Navigator {
HistogramMap* HistogramMap::s_instance = new HistogramMap();
@ -100,6 +102,16 @@ namespace Navigator {
return m_nullResult;
}
StatResults HistogramMap::AnalyzeHistogramRegion(const std::string& name, const ImPlotRect& region)
{
std::lock_guard<std::mutex> guard(m_histoMutex);
auto iter = m_map.find(name);
if (iter != m_map.end())
return iter->second->AnalyzeRegion(region.X.Min, region.X.Max, region.Y.Min, region.Y.Max);
else
return StatResults();
}
std::vector<HistogramParameters> HistogramMap::GetListOfHistograms()
{
std::lock_guard<std::mutex> guard(m_histoMutex);

View File

@ -6,6 +6,8 @@
#include <thread>
struct ImPlotRect;
namespace Navigator {
class NAV_API HistogramMap
@ -20,7 +22,6 @@ namespace Navigator {
void RemoveHistogram(const std::string& name);
void AddCutToHistogramDraw(const std::string& cutname, const std::string& histoname);
void AddCutToHistogramApplied(const std::string& cutname, const std::string& histoname);
void RemoveCutFromHistograms(const std::string& cutname);
@ -33,6 +34,7 @@ namespace Navigator {
void DrawHistogram(const std::string& name);
const HistogramParameters& GetHistogramParams(const std::string& name);
StatResults AnalyzeHistogramRegion(const std::string& name, const ImPlotRect& region);
std::vector<HistogramParameters> GetListOfHistograms();

View File

@ -34,7 +34,9 @@ namespace Navigator {
ImGuiIO& io = ImGui::GetIO();
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;
//Viewports are real wonky on Linux and sometimes on Mac
// Can currently cause assertion failure on checking number of monitors in ImGui sanity checks.
//io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;
ImGui::StyleColorsDark();
ImPlot::StyleColorsDark();
@ -54,7 +56,7 @@ namespace Navigator {
config.GlyphMinAdvanceX = 13.0f; // Use if you want to make the icon monospaced
config.PixelSnapH = true;
static const ImWchar icon_ranges[] = { ICON_MIN_FA, ICON_MAX_FA, 0 };
io.Fonts->AddFontFromFileTTF("fonts/fa-solid-900.ttf", 15.0f, &config, icon_ranges);
io.Fonts->AddFontFromFileTTF("fonts/fa-solid-900.ttf", 13.0f, &config, icon_ranges);
Application& app = Application::Get();
GLFWwindow* window = static_cast<GLFWwindow*>(app.GetWindow().GetNativeWindow());