Commit 0264d282 authored by Gauthier Quesnel's avatar Gauthier Quesnel Committed by Gauthier Quesnel
Browse files

gui: adding sources editor

parent d0a1bdca
......@@ -4,6 +4,7 @@ project(irritator-gui VERSION 0.1.0 LANGUAGES CXX)
set(gui_sources
dialog-file.cpp gui.hpp imnodes.cpp imnodes.hpp implot.h implot.cpp
window-logger.cpp node-editor.hpp node-editor.cpp simulation-editor.cpp
sources.cpp
${PROJECT_SOURCE_DIR}/../../external/imgui/imgui.cpp
${PROJECT_SOURCE_DIR}/../../external/imgui/imgui.h
${PROJECT_SOURCE_DIR}/../../external/imgui/imgui_demo.cpp
......
......@@ -23,11 +23,11 @@
#include <pwd.h>
#include <unistd.h>
#elif defined(__APPLE__)
#include <sys/param.h>
#include <sys/mount.h>
#include <errno.h>
#include <mach-o/dyld.h>
#include <pwd.h>
#include <sys/mount.h>
#include <sys/param.h>
#include <unistd.h>
#elif defined(_WIN32)
#include <KnownFolders.h>
......
......@@ -2993,6 +2993,7 @@ application_show()
ImGui::MenuItem("Simulation", nullptr, &app.show_simulation);
ImGui::MenuItem("Plot", nullptr, &app.show_plot);
ImGui::MenuItem("Sources", nullptr, &app.show_sources);
ImGui::MenuItem("Settings", nullptr, &app.show_settings);
ImGui::MenuItem("Log", nullptr, &app.show_log);
......@@ -3037,6 +3038,9 @@ application_show()
if (app.show_demo)
ImGui::ShowDemoWindow();
if (app.show_sources)
app.srcs.show(&app.show_sources);
return ret;
}
......
......@@ -6,9 +6,11 @@
#define ORG_VLEPROJECT_IRRITATOR_APP_NODE_EDITOR_2020
#include <irritator/core.hpp>
#include <irritator/external_source.hpp>
#include <filesystem>
#include <fstream>
#include <map>
#include <thread>
#include <variant>
#include <vector>
......@@ -295,6 +297,22 @@ using observation_output = std::variant<std::monostate,
file_output_id,
file_discrete_output_id>;
struct sources
{
std::map<int, irt::source::constant> csts;
std::map<int, irt::source::binary_file> bins;
std::map<int, irt::source::text_file> texts;
int csts_next_id = 1;
int bins_next_id = 1;
int texts_next_id = 1;
irt::source::constant* new_constant() noexcept;
irt::source::binary_file* new_binary_file() noexcept;
irt::source::text_file* new_text_file() noexcept;
void show(bool* is_show);
};
struct editor
{
small_string<16> name;
......@@ -358,9 +376,8 @@ struct editor
void observation_outputs_free(const u32 index) noexcept
{
observation_dispatch(index, [](auto& outs, auto out_id) {
outs.free(out_id);
});
observation_dispatch(
index, [](auto& outs, auto out_id) { outs.free(out_id); });
observation_outputs[index] = std::monostate{};
}
......@@ -516,11 +533,14 @@ struct application
void show(bool* is_open);
} settings;
sources srcs;
bool show_log = true;
bool show_simulation = true;
bool show_demo = false;
bool show_plot = true;
bool show_settings = false;
bool show_sources = false;
editor* alloc_editor();
void free_editor(editor& ed);
......
// Copyright (c) 2020 INRA Distributed under the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include "gui.hpp"
#include "node-editor.hpp"
#include <fmt/format.h>
#include <future>
#include <random>
#include <thread>
#include <cinttypes>
namespace irt {
irt::source::constant*
sources::new_constant() noexcept
{
try {
auto& elem = csts[csts_next_id++];
return &elem;
} catch (const std::exception& /*e/*/) {
return nullptr;
}
}
irt::source::binary_file*
sources::new_binary_file() noexcept
{
try {
auto& elem = bins[bins_next_id++];
return &elem;
} catch (const std::exception& /*e/*/) {
return nullptr;
}
}
irt::source::text_file*
sources::new_text_file() noexcept
{
try {
auto& elem = texts[texts_next_id++];
return &elem;
} catch (const std::exception& /*e/*/) {
return nullptr;
}
}
enum class distribution
{
uniform_int,
uniform_real,
bernouilli,
binomial,
negative_binomial,
geometric,
poisson,
exponential,
gamma,
weibull,
exterme_value,
normal,
lognormal,
chi_squared,
cauchy,
fisher_f,
student_t
};
static constexpr const char* items[] = {
"uniform-int", "uniform-real", "bernouilli",
"binomial", "negative-binomial", "geometric",
"poisson", "exponential", "gamma",
"weibull", "exterme-value", "normal",
"lognormal", "chi-squared", "cauchy",
"fisher-f", "student-t"
};
template<typename RandomGenerator, typename Distribution>
inline void
generate(std::ostream& os,
RandomGenerator& gen,
Distribution dist,
const std::size_t size,
const source::random_file_type type,
double& status) noexcept
{
try {
status = 0.0;
switch (type) {
case source::random_file_type::text: {
if (!os) {
status = -1.0;
return;
}
for (std::size_t sz = 0; sz < size; ++sz) {
status = sz * 100.0 / static_cast<double>(size);
if (!(os << dist(gen) << '\n')) {
status = -2.0;
return;
}
}
} break;
case source::random_file_type::binary: {
if (!os) {
status = -1.0;
return;
}
for (std::size_t sz = 0; sz < size; ++sz) {
status = sz * 100.0 / static_cast<double>(size);
const double value = dist(gen);
os.write(reinterpret_cast<const char*>(&value), sizeof(value));
}
} break;
}
status = 100.0;
} catch (std::exception& /*e*/) {
status = -3.0;
}
}
struct distribution_manager
{
std::thread job;
std::ofstream os;
double a, b, p, mean, lambda, alpha, beta, stddev, m, s, n;
int a32, b32, t32, k32;
distribution type = distribution::uniform_int;
bool is_running;
double status;
void start(std::mt19937_64& gen,
sz size,
irt::source::random_file_type file_type)
{
is_running = true;
switch (type) {
case distribution::uniform_int:
job = std::thread(
generate<std::mt19937_64, std::uniform_int_distribution<int>>,
std::ref(os),
std::ref(gen),
std::uniform_int_distribution(a32, b32),
size,
file_type,
std::ref(status));
break;
case distribution::uniform_real:
job = std::thread(
generate<std::mt19937_64, std::uniform_real_distribution<>>,
std::ref(os),
std::ref(gen),
std::uniform_real_distribution(a, b),
size,
file_type,
std::ref(status));
break;
case distribution::bernouilli:
job = std::thread(
generate<std::mt19937_64, std::bernoulli_distribution>,
std::ref(os),
std::ref(gen),
std::bernoulli_distribution(p),
size,
file_type,
std::ref(status));
break;
case distribution::binomial:
job = std::thread(
generate<std::mt19937_64, std::binomial_distribution<>>,
std::ref(os),
std::ref(gen),
std::binomial_distribution(t32, p),
size,
file_type,
std::ref(status));
break;
case distribution::negative_binomial:
job = std::thread(
generate<std::mt19937_64, std::negative_binomial_distribution<>>,
std::ref(os),
std::ref(gen),
std::negative_binomial_distribution(t32, p),
size,
file_type,
std::ref(status));
break;
case distribution::geometric:
job = std::thread(
generate<std::mt19937_64, std::geometric_distribution<>>,
std::ref(os),
std::ref(gen),
std::geometric_distribution(p),
size,
file_type,
std::ref(status));
break;
case distribution::poisson:
job = std::thread(
generate<std::mt19937_64, std::poisson_distribution<>>,
std::ref(os),
std::ref(gen),
std::poisson_distribution(mean),
size,
file_type,
std::ref(status));
break;
case distribution::exponential:
job = std::thread(
generate<std::mt19937_64, std::exponential_distribution<>>,
std::ref(os),
std::ref(gen),
std::exponential_distribution(lambda),
size,
file_type,
std::ref(status));
break;
case distribution::gamma:
job =
std::thread(generate<std::mt19937_64, std::gamma_distribution<>>,
std::ref(os),
std::ref(gen),
std::gamma_distribution(alpha, beta),
size,
file_type,
std::ref(status));
break;
case distribution::weibull:
job = std::thread(
generate<std::mt19937_64, std::weibull_distribution<>>,
std::ref(os),
std::ref(gen),
std::weibull_distribution(a, b),
size,
file_type,
std::ref(status));
break;
case distribution::exterme_value:
job = std::thread(
generate<std::mt19937_64, std::extreme_value_distribution<>>,
std::ref(os),
std::ref(gen),
std::extreme_value_distribution(a, b),
size,
file_type,
std::ref(status));
break;
case distribution::normal:
job =
std::thread(generate<std::mt19937_64, std::normal_distribution<>>,
std::ref(os),
std::ref(gen),
std::normal_distribution(mean, stddev),
size,
file_type,
std::ref(status));
break;
case distribution::lognormal:
job = std::thread(
generate<std::mt19937_64, std::lognormal_distribution<>>,
std::ref(os),
std::ref(gen),
std::lognormal_distribution(m, s),
size,
file_type,
std::ref(status));
break;
case distribution::chi_squared:
job = std::thread(
generate<std::mt19937_64, std::chi_squared_distribution<>>,
std::ref(os),
std::ref(gen),
std::chi_squared_distribution(n),
size,
file_type,
std::ref(status));
break;
case distribution::cauchy:
job =
std::thread(generate<std::mt19937_64, std::cauchy_distribution<>>,
std::ref(os),
std::ref(gen),
std::cauchy_distribution(a, b),
size,
file_type,
std::ref(status));
break;
case distribution::fisher_f:
job = std::thread(
generate<std::mt19937_64, std::fisher_f_distribution<>>,
std::ref(os),
std::ref(gen),
std::fisher_f_distribution(m, n),
size,
file_type,
std::ref(status));
break;
case distribution::student_t:
job = std::thread(
generate<std::mt19937_64, std::student_t_distribution<>>,
std::ref(os),
std::ref(gen),
std::student_t_distribution(n),
size,
file_type,
std::ref(status));
break;
default:
irt_unreachable();
}
}
};
void
show_random()
{
static distribution_manager dm;
static int current_item = -1;
static u64 size = 1024 * 1024;
static bool show_file_dialog = false;
static bool use_binary = true;
if (ImGui::CollapsingHeader("Random file source generator")) {
ImGui::InputScalar("length", ImGuiDataType_U64, &size);
ImGui::Checkbox("binary file", &use_binary);
int old_current = current_item;
ImGui::Combo("Distribution", &current_item, items, IM_ARRAYSIZE(items));
dm.type = static_cast<distribution>(current_item);
switch (dm.type) {
case distribution::uniform_int:
if (old_current != current_item) {
dm.a32 = 0;
dm.b32 = 100;
}
ImGui::InputInt("a", &dm.a32);
ImGui::InputInt("b", &dm.b32);
break;
case distribution::uniform_real:
if (old_current != current_item) {
dm.a = 0.0;
dm.b = 1.0;
}
ImGui::InputDouble("a", &dm.a);
ImGui::InputDouble("b", &dm.b);
break;
case distribution::bernouilli:
if (old_current != current_item) {
dm.p = 0.5;
}
ImGui::InputDouble("p", &dm.p);
break;
case distribution::binomial:
if (old_current != current_item) {
dm.p = 0.5;
dm.t32 = 1;
}
ImGui::InputDouble("p", &dm.p);
ImGui::InputInt("t", &dm.t32);
break;
case distribution::negative_binomial:
if (old_current != current_item) {
dm.p = 0.5;
dm.t32 = 1;
}
ImGui::InputDouble("p", &dm.p);
ImGui::InputInt("t", &dm.k32);
break;
case distribution::geometric:
if (old_current != current_item) {
dm.p = 0.5;
}
ImGui::InputDouble("p", &dm.p);
break;
case distribution::poisson:
if (old_current != current_item) {
dm.mean = 0.5;
}
ImGui::InputDouble("mean", &dm.mean);
break;
case distribution::exponential:
if (old_current != current_item) {
dm.lambda = 1.0;
}
ImGui::InputDouble("lambda", &dm.lambda);
break;
case distribution::gamma:
if (old_current != current_item) {
dm.alpha = 1.0;
dm.beta = 1.0;
}
ImGui::InputDouble("alpha", &dm.alpha);
ImGui::InputDouble("beta", &dm.beta);
break;
case distribution::weibull:
if (old_current != current_item) {
dm.a = 1.0;
dm.b = 1.0;
}
ImGui::InputDouble("a", &dm.a);
ImGui::InputDouble("b", &dm.b);
break;
case distribution::exterme_value:
if (old_current != current_item) {
dm.a = 1.0;
dm.b = 0.0;
}
ImGui::InputDouble("a", &dm.a);
ImGui::InputDouble("b", &dm.b);
break;
case distribution::normal:
if (old_current != current_item) {
dm.mean = 0.0;
dm.stddev = 1.0;
}
ImGui::InputDouble("mean", &dm.mean);
ImGui::InputDouble("stddev", &dm.stddev);
break;
case distribution::lognormal:
if (old_current != current_item) {
dm.m = 0.0;
dm.s = 1.0;
}
ImGui::InputDouble("m", &dm.m);
ImGui::InputDouble("s", &dm.s);
break;
case distribution::chi_squared:
if (old_current != current_item) {
dm.n = 1.0;
}
ImGui::InputDouble("n", &dm.n);
break;
case distribution::cauchy:
if (old_current != current_item) {
dm.a = 1.0;
dm.b = 0.0;
}
ImGui::InputDouble("a", &dm.a);
ImGui::InputDouble("b", &dm.b);
break;
case distribution::fisher_f:
if (old_current != current_item) {
dm.m = 1.0;
dm.n = 1.0;
}
ImGui::InputDouble("m", &dm.m);
ImGui::InputDouble("s", &dm.n);
break;
case distribution::student_t:
if (old_current != current_item) {
dm.n = 1.0;
}
ImGui::InputDouble("n", &dm.n);
break;
}
std::mt19937_64 dist(1024);
if (dm.is_running) {
ImGui::Text("File generation in progress %.2f", dm.status);
if (dm.status < 0.0 || dm.status >= 100.0) {
dm.job.join();
dm.status = 0.0;
dm.is_running = false;
dm.os.close();
}
} else if (current_item >= 0) {
if (ImGui::Button("Generate"))
show_file_dialog = true;
if (show_file_dialog) {
const char* title = "Select file path to save";
const char8_t* filters[] = { u8".dat", nullptr };