diff --git a/src/handler.cpp b/src/handler.cpp index f5cfd731..22c1ecd0 100644 --- a/src/handler.cpp +++ b/src/handler.cpp @@ -7,222 +7,219 @@ #include "../imgui-stdlib/imgui_stdlib.h" std::vector getDeviceInfos() { - std::vector axisInfos; - std::vector> assignedEgus; - if (sampler.has_value()) { - for (auto const &device : sampler->sampleDevices) { - // TODO replace ADC counts with language variable - std::string egu = device.first->getEgu().value_or("ADC counts"); - auto id = device.first->getId(); - if (id.has_value()) { - Omniscope::Id deviceId = id.value(); - std::string timebase{std::to_string(deviceId.sampleRate)}; - if (captureData.find(deviceId) != captureData.end()) { - auto eguIterator = std::ranges::find( - assignedEgus, egu, - &std::pair::first); - if (eguIterator == assignedEgus.end()) { - if (assignedEgus.size() <= 3) { - ImAxis_ nextYAxis = static_cast( - ImAxis_Y1 + assignedEgus.size()); - assignedEgus.push_back( - std::make_pair(egu, nextYAxis)); - eguIterator = (assignedEgus.end() - 1); - } else { - fmt::print( - "too many Axes added, egu not added: " - "{}\nDevice id: {}", - egu, id.value()); - break; - } - } - AxisInfo axisInfo{ - std::make_pair(deviceId, - std::ref(captureData[deviceId])), - *eguIterator, timebase}; - axisInfos.push_back(axisInfo); - } + std::vector axisInfos; + std::vector samplerDvcs; // store live devices + std::vector> assignedEgus; + if (sampler.has_value()) + for (auto const &device : sampler->sampleDevices) { + // TODO replace ADC counts with language variable + std::string egu = device.first->getEgu().value_or("ADC counts"); + auto id = device.first->getId(); + if (id.has_value()) { + auto deviceId = id.value(); + samplerDvcs.push_back(deviceId); + std::string timebase{std::to_string(deviceId.sampleRate)}; + if (captureData.find(deviceId) != captureData.end()) { + auto eguIterator = std::ranges::find( + assignedEgus, egu, &std::pair::first); + if (eguIterator == assignedEgus.end()) { + if (assignedEgus.size() <= 3) { + ImAxis_ nextYAxis = + static_cast(ImAxis_Y1 + assignedEgus.size()); + assignedEgus.push_back(std::make_pair(egu, nextYAxis)); + eguIterator = (assignedEgus.end() - 1); } else { - fmt::print("Error no device id found\n"); + fmt::print("too many Axes added, egu not added: " + "{}\nDevice id: {}", + egu, id.value()); + break; } + } + AxisInfo axisInfo{ + std::make_pair(deviceId, std::ref(captureData[deviceId])), + *eguIterator, timebase}; + axisInfos.push_back(axisInfo); } + } else + fmt::println("Error no device id found"); } - return axisInfos; + // also add loaded files into plotAxes + for (auto &[device, values] : captureData) + if (std::ranges::find(samplerDvcs, device.serial, + &Omniscope::Id::serial) == samplerDvcs.end()) { + axisInfos.push_back({{device, values}, + {"y [Volts]", ImAxis_Y1}, + std::to_string(device.sampleRate)}); + } + return axisInfos; } void addPlots(const char *name, bool const flagPaused, std::function axesSetup) { - static std::set firstRun; - auto const plotRegion = ImGui::GetContentRegionAvail(); - static int activeAxes{0}; - //TODO search devices must work aswell - if (plotAxes.size() <= activeAxes) { - plotAxes = getDeviceInfos(); - activeAxes = plotAxes.size(); + static std::set firstRun; + auto const plotRegion = ImGui::GetContentRegionAvail(); + // TODO search devices must work aswell + plotAxes = getDeviceInfos(); + + if (ImPlot::BeginPlot(name, plotRegion, ImPlotFlags_NoFrame)) { + double x_min = std::numeric_limits::max(); + double x_max = std::numeric_limits::min(); + for (auto const &axes : plotAxes) { + // fmt::print("data size:{}, egu: {}\n", axes.data.second.size(), + // axes.egu.first); + if (!axes.data.second.empty()) { + x_max = std::max(x_max, axes.data.second.back().first); + // TODO save max and min value over same axis + auto [min, max] = std::minmax_element(axes.data.second.begin(), + axes.data.second.end()); + double yMin = min->first + (min->first * 0.15); + double yMax = max->second + (max->second * 0.15); + // fmt::print("yMin {}, yMax{}\n", yMin, yMax); + axesSetup(x_max, axes.egu.first, axes.egu.second, yMin, yMax); + } } - if (ImPlot::BeginPlot(name, plotRegion, ImPlotFlags_NoFrame)) { - double x_min = std::numeric_limits::max(); - double x_max = std::numeric_limits::min(); - for (auto const &axes : plotAxes) { - // fmt::print("data size:{}, egu: {}\n", axes.data.second.size(), - // axes.egu.first); - if (!axes.data.second.empty()) { - x_max = std::max(x_max, axes.data.second.back().first); - //TODO save max and min value over same axis - auto [min, max] = std::minmax_element(axes.data.second.begin(), - axes.data.second.end()); - double yMin = min->first + (min->first * 0.15); - double yMax = max->second + (max->second * 0.15); - // fmt::print("yMin {}, yMax{}\n", yMin, yMax); - axesSetup(x_max, axes.egu.first, axes.egu.second, yMin, yMax); - } - } + auto const limits = [&]() { + if (!firstRun.contains(name)) { + firstRun.insert(name); + return ImPlotRect(x_min, x_max, 0, 0); + } + return ImPlot::GetPlotLimits(); + }(); - auto const limits = [&]() { - if (!firstRun.contains(name)) { - firstRun.insert(name); - return ImPlotRect(x_min, x_max, 0, 0); - } - return ImPlot::GetPlotLimits(); + auto addPlot = [&](auto const &plot, ImAxis_ yAxis) { + if (!plot.second.empty()) { + auto const start = [&]() { + auto p = std::lower_bound(plot.second.begin(), plot.second.end(), + std::pair{limits.X.Min, 0}); + if (p != plot.second.begin()) + return p - 1; + return p; }(); - auto addPlot = [&](auto const &plot, ImAxis_ yAxis) { - if (!plot.second.empty()) { - auto const start = [&]() { - auto p = std::lower_bound( - plot.second.begin(), plot.second.end(), - std::pair{limits.X.Min, 0}); - if (p != plot.second.begin()) return p - 1; - return p; - }(); - - auto const end = [&]() { - auto p = std::upper_bound( - start, plot.second.end(), - std::pair{limits.X.Max, 0}); - if (p != plot.second.end()) return p + 1; - return p; - }(); - - std::size_t const stride = [&]() -> std::size_t { - auto const s = - std::distance(start, end) / (plotRegion.x * 2.0); - if (1 >= s) return 1; - return static_cast(s); - }(); + auto const end = [&]() { + auto p = std::upper_bound(start, plot.second.end(), + std::pair{limits.X.Max, 0}); + if (p != plot.second.end()) + return p + 1; + return p; + }(); - // determine which axes is the right one to choose - ImPlot::SetAxes(ImAxis_X1, yAxis); - ImPlot::PlotLine( - fmt::format("{}-{}", plot.first.type, plot.first.serial) - .c_str(), - std::addressof(start->first), std::addressof(start->second), - static_cast(std::distance(start, end)) / - stride, - 0, 0, 2 * sizeof(double) * stride); - } - }; - for (int count = 0; auto const &plot : plotAxes) { - ImPlot::SetNextLineStyle(ImVec4{ - colorMap[plot.data.first][0], colorMap[plot.data.first][1], - colorMap[plot.data.first][2], 1.0f}); - addPlot(plot.data, plot.egu.second); - } + std::size_t const stride = [&]() -> std::size_t { + auto const s = std::distance(start, end) / (plotRegion.x * 2.0); + if (1 >= s) + return 1; + return static_cast(s); + }(); - ImPlot::EndPlot(); + // determine which axes is the right one to choose + ImPlot::SetAxes(ImAxis_X1, yAxis); + ImPlot::PlotLine( + fmt::format("{}-{}", plot.first.type, plot.first.serial).c_str(), + std::addressof(start->first), std::addressof(start->second), + static_cast(std::distance(start, end)) / stride, 0, 0, + 2 * sizeof(double) * stride); + } + }; + for (int count = 0; auto const &plot : plotAxes) { + ImPlot::SetNextLineStyle(ImVec4{colorMap[plot.data.first][0], + colorMap[plot.data.first][1], + colorMap[plot.data.first][2], 1.0f}); + addPlot(plot.data, plot.egu.second); } + + ImPlot::EndPlot(); + } } void parseDeviceMetaData(Omniscope::MetaData metaData, std::shared_ptr &device) { - try { - nlohmann::json metaJson = nlohmann::json::parse(metaData.data); - fmt::print("{}\n", metaJson.dump()); - device->setScale(std::stod(metaJson["scale"].dump())); - device->setOffset(std::stod(metaJson["offset"].dump())); - device->setEgu(metaJson["egu"]); - } catch (...) { - fmt::print("parsing Meta Data error: {}", metaData.data); - } + try { + nlohmann::json metaJson = nlohmann::json::parse(metaData.data); + fmt::print("{}\n", metaJson.dump()); + device->setScale(std::stod(metaJson["scale"].dump())); + device->setOffset(std::stod(metaJson["offset"].dump())); + device->setEgu(metaJson["egu"]); + } catch (...) { + fmt::print("parsing Meta Data error: {}", metaData.data); + } } void initDevices() { - constexpr int VID = 0x2e8au; - constexpr int PID = 0x000au; + constexpr int VID = 0x2e8au; + constexpr int PID = 0x000au; - devices = deviceManager.getDevices(VID, PID); - for (auto &device : devices) { - auto metaDataCb = [&](auto const &msg) { - if (std::holds_alternative(msg)) { - parseDeviceMetaData(std::get(msg), device); - } - }; - auto id = device->getId().value(); - auto sampleRate = static_cast(id.sampleRate); - device->setTimeScale(static_cast(1 / sampleRate)); - if (!colorMap.contains(id)) { - ImPlot::PushColormap(ImPlotColormap_Dark); - auto c = ImPlot::GetColormapColor((colorMap.size() % 7) + 1); - colorMap[id] = std::array{c.x, c.y, c.z}; - ImPlot::PopColormap(); - } - auto &color = colorMap[id]; - device->send( - Omniscope::SetRgb{static_cast(color[0] * 255), - static_cast(color[1] * 255), - static_cast(color[2] * 255)}); - // set Callback for MetaData - device->setMessageCallback(metaDataCb); - device->send(Omniscope::GetMetaData{}); + devices = deviceManager.getDevices(VID, PID); + for (auto &device : devices) { + auto metaDataCb = [&](auto const &msg) { + if (std::holds_alternative(msg)) { + parseDeviceMetaData(std::get(msg), device); + } + }; + auto id = device->getId().value(); + auto sampleRate = static_cast(id.sampleRate); + device->setTimeScale(static_cast(1 / sampleRate)); + if (!colorMap.contains(id)) { + ImPlot::PushColormap(ImPlotColormap_Dark); + auto c = ImPlot::GetColormapColor((colorMap.size() % 7) + 1); + colorMap[id] = std::array{c.x, c.y, c.z}; + ImPlot::PopColormap(); } + auto &color = colorMap[id]; + device->send(Omniscope::SetRgb{static_cast(color[0] * 255), + static_cast(color[1] * 255), + static_cast(color[2] * 255)}); + // set Callback for MetaData + device->setMessageCallback(metaDataCb); + device->send(Omniscope::GetMetaData{}); + } } void devicesList(bool const &flagPaused) { - auto doDevice = [&](auto &device, auto msg) { - auto &color = colorMap[device->getId().value()]; - if (ImGui::ColorEdit3( - fmt::format("{:<32}", - fmt::format("{}-{}", device->getId().value().type, - device->getId().value().serial)) - .c_str(), - color.data(), - ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoPicker | - ImGuiColorEditFlags_NoTooltip)) { - device->send( - Omniscope::SetRgb{static_cast(color[0] * 255), - static_cast(color[1] * 255), - static_cast(color[2] * 255)}); - } - ImGui::SameLine(); - ImGui::TextUnformatted( - fmt::format("HW: v{}.{}.{} SW: v{}.{}.{} ", - device->getId().value().hwVersion.major, - device->getId().value().hwVersion.minor, - device->getId().value().hwVersion.patch, - device->getId().value().swVersion.major, - device->getId().value().swVersion.minor, - device->getId().value().swVersion.patch) - .c_str()); - ImGui::SameLine(); - if (device->isRunning()) - ImGui::TextUnformatted(fmt::format("{}", msg).c_str()); - else - ImGui::TextUnformatted("Error"); - }; - - if (sampler.has_value()) - for (auto &device : sampler->sampleDevices) { - if (!flagPaused) { - doDevice(device.first, appLanguage[Key::Measurement]); - } else { - doDevice(device.first, appLanguage[Key::Stop]); - } - } + auto doDevice = [&](auto &device, auto msg) { + auto &color = colorMap[device->getId().value()]; + if (ImGui::ColorEdit3( + fmt::format("{:<32}", + fmt::format("{}-{}", device->getId().value().type, + device->getId().value().serial)) + .c_str(), + color.data(), + ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoPicker | + ImGuiColorEditFlags_NoTooltip)) { + device->send( + Omniscope::SetRgb{static_cast(color[0] * 255), + static_cast(color[1] * 255), + static_cast(color[2] * 255)}); + } + ImGui::SameLine(); + ImGui::TextUnformatted(fmt::format("HW: v{}.{}.{} SW: v{}.{}.{} ", + device->getId().value().hwVersion.major, + device->getId().value().hwVersion.minor, + device->getId().value().hwVersion.patch, + device->getId().value().swVersion.major, + device->getId().value().swVersion.minor, + device->getId().value().swVersion.patch) + .c_str()); + ImGui::SameLine(); + if (device->isRunning()) + ImGui::TextUnformatted(fmt::format("{}", msg).c_str()); else - for (auto &device : devices) doDevice(device, appLanguage[Key::Ready]); + ImGui::TextUnformatted("Error"); + }; + + if (sampler.has_value()) + for (auto &device : sampler->sampleDevices) { + if (!flagPaused) { + doDevice(device.first, appLanguage[Key::Measurement]); + } else { + doDevice(device.first, appLanguage[Key::Stop]); + } + } + else + for (auto &device : devices) + doDevice(device, appLanguage[Key::Ready]); } void load_files(decltype(captureData) &loadedFiles, @@ -249,14 +246,17 @@ void load_files(decltype(captureData) &loadedFiles, if (i == 4) // fifth element (serial of scope) loadedFile.first.serial = substr; } + // each y-value is recorded at 1/sampleRate time + double step{0.00001}, base{step}; size_t indx{2}; // y_values start from line 2 of the file while (!readfile.eof()) { // fill the vector of the values double value{}; readfile >> value; - loadedFile.second.emplace_back(indx++, value); + loadedFile.second.emplace_back(base, value); static constexpr size_t bigNumber{10'000'000}; readfile.ignore(bigNumber, '\n'); // new line separator between elements + base += step; } readfile.close(); loadedFile.second.pop_back(); // pop the extra last element