extern "C" { # include } #include #include #include #include #include "app.hh" #include "input.hh" namespace pg { class Block final : public App { public: static inline TypeInfo kType = TypeInfo::Create("Block"); Block() noexcept { } void Update() noexcept { const auto id = "Block | "+ std::to_string(reinterpret_cast(this)); const auto em = ImGui::GetFontSize(); ImGui::SetNextWindowSize({40*em, 24*em}, ImGuiCond_Once); if (ImGui::Begin(id.c_str())) { UpdateParams(); ImGui::SameLine(); UpdatePlots(); if (msg_.size() > 0) { ImGui::TextUnformatted(msg_.c_str()); } } ImGui::End(); } void UpdateParams() noexcept { const auto em = ImGui::GetFontSize(); bool mod = false; ImGui::BeginGroup(); ImGui::PushItemWidth(6*em); mod |= ImGui::DragInt("input_slot", &src_, 1, 0, 1024); mod |= ImGui::DragInt("time", &time_, 1, 0, 1024); mod |= ImGui::DragInt("dur", &dur_, 1, 1, BLKY_SENSOR_MAX_DUR); mod |= ImGui::DragInt2("blocks", block_, 1, 1, 16); mod |= ImGui::DragInt2("sensors", sensor_); mod |= ImGui::DragFloat("var thresh", &var_thresh_); ImGui::PopItemWidth(); ImGui::EndGroup(); if (mod) Calc(); } void UpdatePlots() noexcept { const auto em = ImGui::GetFontSize(); ImGui::BeginGroup(); auto avail = ImGui::GetContentRegionAvail(); avail.x -= em; avail.y -= em; if (ImPlot::BeginPlot("correls", avail)) { ImPlot::SetupAxisLimits(ImAxis_X1, 0, 1); ImPlot::SetupAxisLimits(ImAxis_Y1, 0, 1); ImPlot::PlotHeatmap( "correls_avg", correl_avg_.data(), block_[1], block_[0], 0, 1, "%.2f"); ImPlot::PlotHeatmap( "correls_var", correl_var_.data(), block_[1], block_[0], 0, var_thresh_, "%.4f"); ImPlot::PlotHeatmap( "correls_avg_filtered", correl_avg_filtered_.data(), block_[1], block_[0], 0, 1, "%.2f"); ImPlot::EndPlot(); } ImGui::EndGroup(); } private: int src_ = 0; int time_ = 0; int dur_ = 30; int block_[2] = {1, 1}; int sensor_[2] = {1, 1}; float var_thresh_ = .1f; std::string msg_; std::vector correls_ = {0}; std::vector correl_avg_ = {0}; std::vector correl_var_ = {0}; std::vector correl_avg_filtered_ = {0}; void Calc() noexcept try { auto data = Input::instance().slots(static_cast(src_)); if (!data) throw "missing input"; const auto block_x = static_cast(block_[0]); const auto block_y = static_cast(block_[1]); const auto block_n = block_x*block_y; const auto block_w = 1.f / static_cast(block_x); const auto block_h = 1.f / static_cast(block_y); const auto sensor_x = static_cast(sensor_[0]); const auto sensor_y = static_cast(sensor_[1]); const auto sensor_n = sensor_x*sensor_y; const auto sensor_interval_x = block_w / static_cast(sensor_x); const auto sensor_interval_y = block_h / static_cast(sensor_y); correls_.clear(); correls_.reserve(block_n*sensor_n*3); for (size_t by = 0; by < block_y; ++by) { for (size_t bx = 0; bx < block_x; ++bx) { for (size_t sy = 0; sy < sensor_y; ++sy) { for (size_t sx = 0; sx < sensor_x; ++sx) { const auto xf = block_w*static_cast(bx) + sensor_interval_x*(static_cast(sx)+.5f); const auto yf = block_h*static_cast(by) + sensor_interval_y*(static_cast(sy)+.5f); for (size_t i = 0; i < 3; ++i) { const auto samp = data->FetchSamples( static_cast(time_), static_cast(dur_), xf, yf, i); blky_sensor_t sensor = {}; blky_sensor_feed(&sensor, samp.data(), samp.size()); correls_.push_back(sensor.correl); } } } } } correl_avg_.clear(); correl_avg_.reserve(block_n); correl_var_.clear(); correl_var_.reserve(block_n); correl_avg_filtered_.clear(); correl_avg_filtered_.reserve(block_n); const auto correls_per_block = sensor_n*3; for (size_t bi = 0; bi < block_n; ++bi) { const size_t st = bi*correls_per_block; const size_t ed = st + correls_per_block; double sum = 0; for (size_t i = st; i < ed; ++i) { sum += std::abs(correls_[i]); } const auto avg = sum / static_cast(correls_per_block); correl_avg_.push_back(avg); double var = 0; for (size_t i = st; i < ed; ++i) { const auto diff = std::abs(correls_[i]) - avg; var += diff*diff; } var /= static_cast(correls_per_block); correl_var_.push_back(var); if (var < var_thresh_) { correl_avg_filtered_.push_back(avg); } else { correl_avg_filtered_.push_back(-1); } } } catch (const char* msg) { msg_ = msg; } }; } // namespace pg