From 3e4452ca3a7a7cea45fed04f74acdcde3950f628 Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Thu, 5 Apr 2018 16:08:58 +0200 Subject: [PATCH] Support layer and interaction transparancy. Refs #1 --- src/fmri/ActivityAnimation.cpp | 2 ++ src/fmri/Animation.cpp | 10 ++++++---- src/fmri/Animation.hpp | 18 ++++++++++++++++++ src/fmri/FlatLayerVisualisation.cpp | 2 ++ src/fmri/LayerVisualisation.cpp | 6 ++++++ src/fmri/LayerVisualisation.hpp | 16 ++++++++++++++++ src/fmri/Options.cpp | 18 ++++++++++++++++-- src/fmri/Options.hpp | 4 ++++ src/fmri/RenderingState.cpp | 16 ++++++++++++++-- src/fmri/RenderingState.hpp | 8 ++++++-- src/fmri/main.cpp | 2 +- src/tools/launcher.cpp | 24 +++++++++++++++++++++++- 12 files changed, 114 insertions(+), 12 deletions(-) diff --git a/src/fmri/ActivityAnimation.cpp b/src/fmri/ActivityAnimation.cpp index 0b51506..ad61333 100644 --- a/src/fmri/ActivityAnimation.cpp +++ b/src/fmri/ActivityAnimation.cpp @@ -58,6 +58,8 @@ ActivityAnimation::ActivityAnimation( lineIndices.push_back(i); lineIndices.push_back(i + interactions.size()); } + + patchTransparancy(colorBuf.begin(), colorBuf.end()); } void ActivityAnimation::draw(float timeScale) diff --git a/src/fmri/Animation.cpp b/src/fmri/Animation.cpp index ee4a011..f665a09 100644 --- a/src/fmri/Animation.cpp +++ b/src/fmri/Animation.cpp @@ -1,5 +1,7 @@ -// -// Created by bert on 13/02/18. -// - #include "Animation.hpp" +#include "RenderingState.hpp" + +float fmri::Animation::getAlpha() +{ + return fmri::RenderingState::instance().interactionAlpha(); +} diff --git a/src/fmri/Animation.hpp b/src/fmri/Animation.hpp index 2b9cf82..b7d5ef0 100644 --- a/src/fmri/Animation.hpp +++ b/src/fmri/Animation.hpp @@ -1,6 +1,8 @@ #pragma once +#include "utils.hpp" + namespace fmri { class Animation @@ -10,5 +12,21 @@ namespace fmri virtual void draw(float step) = 0; + private: + static float getAlpha(); + + protected: + template + void patchTransparancy(It begin, It end) + { + if constexpr (std::tuple_size::value >= 4) { + const auto alpha = getAlpha(); + for (; begin != end; ++begin) { + Color &color = *begin; + color[3] = alpha; + } + } + } + }; } diff --git a/src/fmri/FlatLayerVisualisation.cpp b/src/fmri/FlatLayerVisualisation.cpp index e97750e..4cff1ee 100644 --- a/src/fmri/FlatLayerVisualisation.cpp +++ b/src/fmri/FlatLayerVisualisation.cpp @@ -68,6 +68,8 @@ FlatLayerVisualisation::FlatLayerVisualisation(const LayerData &layer, Ordering assert(indexPos == indexBuffer.end()); assert(colorPos == colorBuffer.end()); + + patchTransparancy(colorBuffer.begin(), colorBuffer.end()); } void FlatLayerVisualisation::render() diff --git a/src/fmri/LayerVisualisation.cpp b/src/fmri/LayerVisualisation.cpp index 6ca9d45..5dfc733 100644 --- a/src/fmri/LayerVisualisation.cpp +++ b/src/fmri/LayerVisualisation.cpp @@ -1,6 +1,7 @@ #include "LayerVisualisation.hpp" #include "Range.hpp" #include "utils.hpp" +#include "RenderingState.hpp" const std::vector &fmri::LayerVisualisation::nodePositions() const { @@ -25,6 +26,11 @@ void fmri::LayerVisualisation::initNodePositions void fmri::LayerVisualisation::initNodePositions(size_t n, float spacing) { diff --git a/src/fmri/LayerVisualisation.hpp b/src/fmri/LayerVisualisation.hpp index 06eb85e..90cad82 100644 --- a/src/fmri/LayerVisualisation.hpp +++ b/src/fmri/LayerVisualisation.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include "utils.hpp" namespace fmri { @@ -19,10 +20,25 @@ namespace fmri virtual void render() = 0; virtual const std::vector& nodePositions() const; + private: + static float getAlpha(); + protected: std::vector nodePositions_; template void initNodePositions(size_t n, float spacing); + + template + void patchTransparancy(It begin, It end) + { + if constexpr (std::tuple_size::value >= 4) { + const auto alpha = getAlpha(); + for (; begin != end; ++begin) { + Color &color = *begin; + color[3] = alpha; + } + } + } }; } diff --git a/src/fmri/Options.cpp b/src/fmri/Options.cpp index 5260cc1..bb3845d 100644 --- a/src/fmri/Options.cpp +++ b/src/fmri/Options.cpp @@ -70,6 +70,8 @@ Options Options::parse(const int argc, char *const argv[]) ("labels,l", value(&options.labelsPath), "labels file") ("means,m", value(&options.meansPath), "means file") ("path-color,p", value(), "color for paths") + ("layer-opacity", value(&options.layerTransparancy_), "Opacity for layers") + ("interaction-opacity", value(&options.interactionTransparancy_), "Opacity for interactions") ("dump,d", value(&options.dumpPath), "dump convolutional images in this directory"); options_description composed = desc; @@ -92,12 +94,12 @@ Options Options::parse(const int argc, char *const argv[]) // Sanity checks check_file(options.modelPath); check_file(options.weightsPath); - check_file(options.meansPath); + if (!options.meansPath.empty()) check_file(options.meansPath); + if (!options.labelsPath.empty()) check_file(options.labelsPath); std::for_each(options.inputPaths.begin(), options.inputPaths.end(), check_file); return options; } catch (required_option& e) { - std::cerr << e.get_option_name() << std::endl; if (e.get_option_name() == "--input") { std::cerr << "No input files specified" << std::endl; } else { @@ -149,6 +151,8 @@ std::optional Options::imageDumper() const } Options::Options() noexcept : + layerTransparancy_(1), + interactionTransparancy_(1), pathColor_({1, 1, 1, 0.1}) { } @@ -157,3 +161,13 @@ const Color &Options::pathColor() const { return pathColor_; } + +float Options::layerTransparancy() const +{ + return layerTransparancy_; +} + +float Options::interactionTransparancy() const +{ + return interactionTransparancy_; +} diff --git a/src/fmri/Options.hpp b/src/fmri/Options.hpp index 285687b..2830d54 100644 --- a/src/fmri/Options.hpp +++ b/src/fmri/Options.hpp @@ -22,10 +22,14 @@ namespace fmri { const Color& pathColor() const; std::optional> labels() const; std::optional imageDumper() const; + float layerTransparancy() const; + float interactionTransparancy() const; const vector& inputs() const; private: + float layerTransparancy_; + float interactionTransparancy_; Color pathColor_; string modelPath; string weightsPath; diff --git a/src/fmri/RenderingState.cpp b/src/fmri/RenderingState.cpp index 3ca5544..f2e4a8b 100644 --- a/src/fmri/RenderingState.cpp +++ b/src/fmri/RenderingState.cpp @@ -341,9 +341,11 @@ bool RenderingState::renderInteractionPaths() const return options.renderInteractionPaths; } -void RenderingState::loadOptions(const Options &options) +void RenderingState::loadOptions(const Options &programOptions) { - this->options.pathColor = options.pathColor(); + options.pathColor = programOptions.pathColor(); + options.layerAlpha = programOptions.layerTransparancy(); + options.interactionAlpha = programOptions.interactionTransparancy(); } const Color &RenderingState::pathColor() const @@ -369,3 +371,13 @@ RenderingState::RenderingState() noexcept // Set initial point size glPointSize(3); } + +float RenderingState::interactionAlpha() const +{ + return options.interactionAlpha; +} + +float RenderingState::layerAlpha() const +{ + return options.layerAlpha; +} diff --git a/src/fmri/RenderingState.hpp b/src/fmri/RenderingState.hpp index 27e9c87..e9d9994 100644 --- a/src/fmri/RenderingState.hpp +++ b/src/fmri/RenderingState.hpp @@ -43,15 +43,17 @@ namespace fmri /** * Load rendering-specific options from the given options object. * - * @param options + * @param programOptions */ - void loadOptions(const Options& options); + void loadOptions(const Options& programOptions); /** * @return Whether the network should only render activated nodes, rather than all of them. */ bool renderActivatedOnly() const; bool renderInteractionPaths() const; const Color& pathColor() const; + float interactionAlpha() const; + float layerAlpha() const; static RenderingState& instance(); @@ -63,6 +65,8 @@ namespace fmri bool renderInteractions = true; bool activatedOnly = false; bool renderInteractionPaths = false; + float layerAlpha; + float interactionAlpha; Color pathColor; } options; std::array pos; diff --git a/src/fmri/main.cpp b/src/fmri/main.cpp index 8d88273..4115460 100644 --- a/src/fmri/main.cpp +++ b/src/fmri/main.cpp @@ -59,8 +59,8 @@ int main(int argc, char *argv[]) // Prepare data for simulations Options options = Options::parse(argc, argv); - loadSimulationData(options); RenderingState::instance().loadOptions(options); + loadSimulationData(options); // Register callbacks glutReshapeFunc(changeWindowSize); diff --git a/src/tools/launcher.cpp b/src/tools/launcher.cpp index 49d5973..b3d3d97 100644 --- a/src/tools/launcher.cpp +++ b/src/tools/launcher.cpp @@ -31,7 +31,6 @@ auto file_filter_for_extension(std::string_view extension) return filter; } - char * color_string(Gtk::ColorButton &button) { char* buffer = new char[2 * 4 + 2]; // 2 per channel, plus #, plus null byte @@ -62,6 +61,15 @@ char* wrap_string(std::string_view str) { return wrapper; } + +void float_parameter(std::vector &argv, std::string_view flag, double value) +{ + char buffer[100]; + argv.push_back(wrap_string(flag)); + std::sprintf(buffer, "%f", value); + argv.push_back(wrap_string(buffer)); +} + class Launcher : public Gtk::Window { public: Launcher(); @@ -78,6 +86,8 @@ private: Gtk::FileChooserButton meansChooser; Gtk::FileChooserButton inputChooser; Gtk::ColorButton pathColor; + Gtk::Scale layerTransparancy; + Gtk::Scale interactionTransparancy; Gtk::Button startButton; void start(); @@ -99,6 +109,8 @@ Launcher::Launcher() meansChooser("Select means file"), inputChooser("Select input directory", Gtk::FileChooserAction::FILE_CHOOSER_ACTION_SELECT_FOLDER), pathColor(Gdk::RGBA("rgba(255, 255, 255, 0.1)")), + layerTransparancy(Gtk::Adjustment::create(1, 0, 1, 0.0, 1.f / 256)), + interactionTransparancy(Gtk::Adjustment::create(1, 0, 1, 0.0, 1.f / 256)), startButton("Start FMRI") { set_default_size(400, -1); @@ -126,6 +138,8 @@ Launcher::Launcher() addRowWithLabel("Input directory", inputChooser); addRowWithLabel("Means (optional)", meansChooser); addRowWithLabel("Path color", pathColor); + addRowWithLabel("Layer transparancy", layerTransparancy); + addRowWithLabel("Interaction transparancy", interactionTransparancy); startButton.signal_clicked().connect(sigc::mem_fun(*this, &Launcher::start)); grid.attach_next_to(startButton, Gtk::PositionType::POS_BOTTOM, 2, 1); @@ -162,6 +176,9 @@ void Launcher::start() color_string(pathColor), }; + float_parameter(argv, "--layer-opacity", layerTransparancy.get_adjustment()->get_value()); + float_parameter(argv, "--interaction-opacity", interactionTransparancy.get_adjustment()->get_value()); + if (labelChooser.get_file()) { argv.push_back(wrap_string("-l")); argv.push_back(wrap_string(labelChooser.get_file()->get_path())); @@ -178,6 +195,11 @@ void Launcher::start() argv.push_back(nullptr); execv(executable.c_str(), argv.data()); + + // Discard all allocated memory. + std::for_each(argv.begin(), argv.end(), std::default_delete()); + Gtk::MessageDialog dialog(*this, "Failed to start for unknown reasons."); + dialog.run(); } bool Launcher::hasFile(const Gtk::FileChooserButton& fileChooser, const std::string& error)