1
0
Fork 0
mirror of https://github.com/gwm17/Specter.git synced 2024-11-26 12:18:51 -05:00

Cuts now implemented, drawn and applied to histograms

This commit is contained in:
Gordon McCann 2022-01-17 16:42:12 -05:00
parent a2a01e568b
commit 66e1065394
7 changed files with 34 additions and 45 deletions

View File

@ -21,10 +21,13 @@ namespace Navigator {
PushLayer(new EditorLayer(&m_histMap)); PushLayer(new EditorLayer(&m_histMap));
m_histMap.AddHistogram("myHisto", "joseph", 100, 0, 10); m_histMap.AddHistogram("myHisto", "joseph", 100, 0, 10);
m_histMap.AddHistogram("myHisto2D", "joseph", "joseph", 100, 0, 10, 100, 0, 10);
CutMap::GetInstance().AddCut("joe_cut","joseph",0.0, 7.0); CutMap::GetInstance().AddCut("joe_cut","joseph",0.0, 7.0);
CutMap::GetInstance().AddCut("joe2D_cut", "joseph", "joseph", { 1.0, 3.0, 3.0, 1.0, 1.0}, { 1.0, 1.0, 3.0, 3.0, 1.0});
m_histMap.AddCutToHistogramDraw("joe_cut", "myHisto"); m_histMap.AddCutToHistogramDraw("joe_cut", "myHisto");
m_histMap.AddCutToHistogramDraw("joe2D_cut", "myHisto2D");
m_imgui_layer = new ImGuiLayer(); m_imgui_layer = new ImGuiLayer();
PushOverlay(m_imgui_layer); PushOverlay(m_imgui_layer);

View File

@ -24,59 +24,44 @@ namespace Navigator {
} }
/*2D Cuts -- Can only be made on 2D histogram, but applied to either 1D or 2D histograms*/ /*2D Cuts -- Can only be made on 2D histogram, but applied to either 1D or 2D histograms*/
Cut2D::Cut2D(const std::string& name, const std::string& xpar, const std::string& ypar, const std::vector<Point>& points) : Cut2D::Cut2D(const std::string& name, const std::string& xpar, const std::string& ypar, const std::vector<double>& xpoints, const std::vector<double>& ypoints) :
Cut(name, xpar, ypar), m_points(points) Cut(name, xpar, ypar), m_xpoints(xpoints), m_ypoints(ypoints)
{ {
} }
Cut2D::~Cut2D() {} Cut2D::~Cut2D() {}
/* /*
Even-odd point in polygon algorithm (see Wikipedia) Even-odd point in polygon algorithm (see Wikipedia)
Walk around the sides of the polygon and check intersection with each of the sides. Walk around the sides of the polygon and check intersection with each of the sides.
Cast a ray from the point to infinity in any direction and check the number of intersections. Cast a ray from the point to infinity in any direction and check the number of intersections.
If odd number of intersections, point is inside. Even, point is outside. If odd number of intersections, point is inside. Even, point is outside.
Edge cases of point is a vertex or on a side considered. Edge cases of point is a vertex or on a side considered.
*/ */
bool Cut2D::IsInside(double x, double y) const bool Cut2D::IsInside(double x, double y) const
{ {
bool result = false; bool result = false;
size_t j = m_points.size() -1;
double slope; double slope;
for(size_t i=0; i<m_points.size(); i++) for(size_t i=0; i<(m_xpoints.size()-1); i++)
{ {
if(x == m_points[i].x && y == m_points[i].y) if(x == m_xpoints[i+1] && y == m_ypoints[i+1])
return true; return true;
else if((m_points[i].y > y) != (m_points[j].y > y)) else if((m_ypoints[i+1] > y) != (m_ypoints[i] > y))
{ {
slope = (x - m_points[i].x)*(m_points[j].y - m_points[i].y) - (m_points[j].x - m_points[i].x)*(y - m_points[i].y); slope = (x - m_xpoints[i+1])*(m_ypoints[i] - m_ypoints[i+1]) - (m_xpoints[i] - m_xpoints[i+1])*(y - m_ypoints[i+1]);
if(slope == 0.0) if(slope == 0.0)
return true; return true;
else if ((slope < 0.0) != (m_points[j].y < m_points[i].y)) else if ((slope < 0.0) != (m_ypoints[i] < m_ypoints[i+1]))
result = !result; result = !result;
} }
j=i;
} }
return result; return result;
} }
//Only in ImPlot/ImGui context!!!! //Only in ImPlot/ImGui context!!!!
/*
Again, more complicated. Want to draw the polygon that makes up the 2D-cut. To perform this,
first need to convert plot coordinates into global window coords (pixels). Then tell ImGui to add
a polyline to the draw list, make it red and closed. For this to work, this must be called within the
BeignPlot()/EndPlot() combo for which it was created (why histos own the draw commands).
*/
void Cut2D::Draw() const void Cut2D::Draw() const
{ {
std::vector<ImVec2> draw_points; ImPlot::PlotLine(m_params.name.c_str(), m_xpoints.data(), m_ypoints.data(), m_xpoints.size());
draw_points.reserve(m_points.size());
auto draw_list = ImGui::GetWindowDrawList();
for(auto& point : m_points)
draw_points.push_back(ImPlot::PlotToPixels(point.x, point.y));
draw_list->AddPolyline(draw_points.data(), static_cast<int>(draw_points.size()), ImGui::ColorConvertFloat4ToU32(colorVec), ImDrawFlags_Closed, 0.1);
} }
/* CutMap */ /* CutMap */

View File

@ -19,12 +19,6 @@ namespace Navigator {
std::string y_par; std::string y_par;
}; };
struct NAV_API Point
{
double x = 0;
double y = 0;
};
class NAV_API Cut class NAV_API Cut
{ {
public: public:
@ -65,7 +59,7 @@ namespace Navigator {
class NAV_API Cut2D : public Cut class NAV_API Cut2D : public Cut
{ {
public: public:
Cut2D(const std::string& name, const std::string& xpar, const std::string& ypar, const std::vector<Point>& points); Cut2D(const std::string& name, const std::string& xpar, const std::string& ypar, const std::vector<double>& xpoints, const std::vector<double>& ypoints);
virtual ~Cut2D(); virtual ~Cut2D();
virtual bool IsInside(double x, double y = 0) const override; virtual bool IsInside(double x, double y = 0) const override;
virtual void Draw() const override; virtual void Draw() const override;
@ -73,7 +67,8 @@ namespace Navigator {
virtual bool Is2D() const override { return true; } virtual bool Is2D() const override { return true; }
private: private:
std::vector<Point> m_points; std::vector<double> m_xpoints;
std::vector<double> m_ypoints;
const ImVec4 colorVec = {1.0, 0.0, 0.0, 0.5}; const ImVec4 colorVec = {1.0, 0.0, 0.0, 0.5};
}; };
@ -90,10 +85,10 @@ namespace Navigator {
std::lock_guard<std::mutex> guard(m_cutMutex); std::lock_guard<std::mutex> guard(m_cutMutex);
m_map[name].reset(new Cut1D(name, xpar, min, max)); m_map[name].reset(new Cut1D(name, xpar, min, max));
} }
inline void AddCut(const std::string& name, const std::string& xpar, const std::string& ypar, const std::vector<Point>& points) inline void AddCut(const std::string& name, const std::string& xpar, const std::string& ypar, const std::vector<double>& xpoints, const std::vector<double>& ypoints)
{ {
std::lock_guard<std::mutex> guard(m_cutMutex); std::lock_guard<std::mutex> guard(m_cutMutex);
m_map[name].reset(new Cut2D(name, xpar, ypar, points)); m_map[name].reset(new Cut2D(name, xpar, ypar, xpoints, ypoints));
} }
void DrawCut(const std::string& name); void DrawCut(const std::string& name);

View File

@ -36,8 +36,6 @@ namespace Navigator {
ImGui::SliderInt2("Rows, Columns", m_tableSizes, 1, 3); ImGui::SliderInt2("Rows, Columns", m_tableSizes, 1, 3);
m_totalSlots = m_tableSizes[0] * m_tableSizes[1]; m_totalSlots = m_tableSizes[0] * m_tableSizes[1];
m_selectedGrams.resize(m_totalSlots); m_selectedGrams.resize(m_totalSlots);
for (auto& gram : m_selectedGrams)
gram = m_activeList[0].name;
if (ImGui::BeginTable("Select Histograms", m_tableSizes[1])) if (ImGui::BeginTable("Select Histograms", m_tableSizes[1]))
{ {
std::string label; std::string label;
@ -50,7 +48,7 @@ namespace Navigator {
ImGui::TableNextColumn(); ImGui::TableNextColumn();
this_gram = i * m_tableSizes[1] + j; this_gram = i * m_tableSizes[1] + j;
label = "Histogram" + std::to_string(this_gram); label = "Histogram" + std::to_string(this_gram);
if (ImGui::BeginCombo(label.c_str(), m_activeList[0].name.c_str())) if (ImGui::BeginCombo(label.c_str(), m_selectedGrams[this_gram].c_str()))
{ {
for (auto& params : m_activeList) for (auto& params : m_activeList)
if (ImGui::Selectable(params.name.c_str(), params.name == m_selectedGrams[this_gram])) if (ImGui::Selectable(params.name.c_str(), params.name == m_selectedGrams[this_gram]))

View File

@ -114,6 +114,8 @@ namespace Navigator {
for(int i=0; i<m_nBinsTotal; i++) for(int i=0; i<m_nBinsTotal; i++)
m_binCounts[i] = 0; m_binCounts[i] = 0;
m_maxBinContent = 0; m_maxBinContent = 0;
m_initFlag = true;
} }
void Histogram2D::FillData(double x, double y) void Histogram2D::FillData(double x, double y)
@ -122,20 +124,22 @@ namespace Navigator {
return; return;
int bin_x = int((x - m_params.min_x)/m_binWidthX); int bin_x = int((x - m_params.min_x)/m_binWidthX);
int bin_y = int((y - m_params.min_y)/m_binWidthY); int bin_y = int((m_params.max_y - y)/m_binWidthY);
int bin = bin_y*m_params.nbins_x + bin_x; int bin = bin_y*m_params.nbins_x + bin_x;
m_binCounts[bin] += 1.0; m_binCounts[bin] += 1.0;
m_maxBinContent = m_binCounts[bin] > m_maxBinContent ? m_binCounts[bin] : m_maxBinContent; m_maxBinContent = m_binCounts[bin] > m_maxBinContent ? (m_binCounts[bin]*2) : m_maxBinContent;
} }
//Can only be used within an ImGui / ImPlot context!! //Can only be used within an ImGui / ImPlot context!!
void Histogram2D::Draw() void Histogram2D::Draw()
{ {
ImPlot::SetupAxes(m_params.x_par.c_str(), m_params.y_par.c_str(), 0, 0); ImPlot::SetupAxes(m_params.x_par.c_str(), m_params.y_par.c_str());
ImPlot::PlotHeatmap(m_params.name.c_str(), &m_binCounts.data()[0], m_params.nbins_y, m_params.nbins_x, 0, m_maxBinContent, NULL, ImPlot::PushColormap(ImPlotColormap_Viridis);
ImPlot::PlotHeatmap(m_params.name.c_str(), &m_binCounts.data()[0], m_params.nbins_y, m_params.nbins_x, 0.0, m_maxBinContent, NULL,
ImPlotPoint(m_params.min_x, m_params.min_y), ImPlotPoint(m_params.max_x, m_params.max_y)); ImPlotPoint(m_params.min_x, m_params.min_y), ImPlotPoint(m_params.max_x, m_params.max_y));
ImPlot::PopColormap();
auto& cutmap = CutMap::GetInstance(); auto& cutmap = CutMap::GetInstance();
for(auto& cut : m_params.cutsDrawnUpon) for(auto& cut : m_params.cutsDrawnUpon)
cutmap.DrawCut(cut); cutmap.DrawCut(cut);

View File

@ -33,6 +33,7 @@ namespace Navigator {
ParameterMap& pmap = ParameterMap::GetInstance(); ParameterMap& pmap = ParameterMap::GetInstance();
for (auto& pair : m_map) for (auto& pair : m_map)
{ {
xpar = pair.second->GetXParam(); xpar = pair.second->GetXParam();
ypar = pair.second->GetYParam(); ypar = pair.second->GetYParam();
@ -53,7 +54,9 @@ namespace Navigator {
auto iterx = pmap.find(xpar); auto iterx = pmap.find(xpar);
auto itery = pmap.find(ypar); auto itery = pmap.find(ypar);
if (iterx == pmap.end() || itery == pmap.end() || !iterx->second->validFlag || !itery->second->validFlag) if (iterx == pmap.end() || itery == pmap.end() || !iterx->second->validFlag || !itery->second->validFlag)
{
continue; continue;
}
else else
{ {
pair.second->FillData(iterx->second->value, itery->second->value); pair.second->FillData(iterx->second->value, itery->second->value);

View File

@ -36,6 +36,7 @@ namespace Navigator {
io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;
ImGui::StyleColorsDark(); ImGui::StyleColorsDark();
ImPlot::StyleColorsDark();
ImGuiStyle& style = ImGui::GetStyle(); ImGuiStyle& style = ImGui::GetStyle();