From 63483a4db8b7d1df2a29d6f3065ee0d701f3130d Mon Sep 17 00:00:00 2001 From: Martin Hierholzer <martin.hierholzer@desy.de> Date: Thu, 21 Sep 2017 08:47:56 +0200 Subject: [PATCH] improved generation of dot graph --- include/Application.h | 2 ++ include/ApplicationModule.h | 4 +++- include/ControlSystemModule.h | 2 ++ include/DeviceModule.h | 2 ++ include/EntityOwner.h | 15 ++++++++++++-- include/ModuleGroup.h | 18 +++++++++++++++++ include/VariableGroup.h | 2 ++ include/VirtualModule.h | 7 ++++++- src/EntityOwner.cc | 37 ++++++++++++++++++++++++----------- 9 files changed, 74 insertions(+), 15 deletions(-) diff --git a/include/Application.h b/include/Application.h index 94d40ab8..6503d497 100644 --- a/include/Application.h +++ b/include/Application.h @@ -139,6 +139,8 @@ namespace ChimeraTK { Profiler::registerThread(name); } + ModuleType getModuleType() const override { return ModuleType::ModuleGroup; } + protected: friend class Module; diff --git a/include/ApplicationModule.h b/include/ApplicationModule.h index 8eb56f3b..19a914a3 100644 --- a/include/ApplicationModule.h +++ b/include/ApplicationModule.h @@ -63,7 +63,9 @@ namespace ChimeraTK { moduleList = std::move(rhs.moduleList); return *this; } - + + ModuleType getModuleType() const override { return ModuleType::ApplicationModule; } + protected: /** Wrapper around mainLoop(), to execute additional tasks in the thread before entering the main loop */ diff --git a/include/ControlSystemModule.h b/include/ControlSystemModule.h index ab0012a9..417b7677 100644 --- a/include/ControlSystemModule.h +++ b/include/ControlSystemModule.h @@ -35,6 +35,8 @@ namespace ChimeraTK { Module& operator[](const std::string& moduleName) const override; + ModuleType getModuleType() const override { return ModuleType::ControlSystem; } + protected: mtca4u::RegisterPath variableNamePrefix; diff --git a/include/DeviceModule.h b/include/DeviceModule.h index a4a95cb6..e40eaa71 100644 --- a/include/DeviceModule.h +++ b/include/DeviceModule.h @@ -42,6 +42,8 @@ namespace ChimeraTK { Module& operator[](const std::string& moduleName) const override; + ModuleType getModuleType() const override { return ModuleType::Device; } + protected: std::string deviceAliasOrURI; diff --git a/include/EntityOwner.h b/include/EntityOwner.h index 7bee80dc..adf3e4d4 100644 --- a/include/EntityOwner.h +++ b/include/EntityOwner.h @@ -113,10 +113,21 @@ namespace ChimeraTK { /** Create Graphviz dot graph write to file */ void dumpGraph(const std::string &fileName="graph.dot") const; - /** Create Graphviz dot graph write to stream, excluding the surrounding digraph command */ - void dumpGraphInternal(std::ostream &stream) const; + enum class ModuleType { + ApplicationModule, ModuleGroup, VariableGroup, ControlSystem, Device + }; + + /** Return the module type of this module, or in case of a VirtualModule the module type this VirtualModule was + * derived from. */ + virtual ModuleType getModuleType() const = 0; protected: + + /** Create Graphviz dot graph write to stream, excluding the surrounding digraph command */ + void dumpGraphInternal(std::ostream &stream) const; + + /** Clean a fully qualified entity name so it can be used as a dot node name (i.e. strip slashes etc.) */ + std::string cleanDotNode(std::string fullName) const; /** The name of this instance */ std::string _name; diff --git a/include/ModuleGroup.h b/include/ModuleGroup.h index f4a0cdf6..c37582bf 100644 --- a/include/ModuleGroup.h +++ b/include/ModuleGroup.h @@ -40,17 +40,35 @@ namespace ChimeraTK { /** Destructor */ virtual ~ModuleGroup() {}; + /** Move operation with the move constructor + @todo should be in the base class!? */ + ModuleGroup(ModuleGroup &&rhs) { + _name = std::move(rhs._name); + _owner = std::move(rhs._owner); + _description = std::move(rhs._description); + accessorList = std::move(rhs.accessorList); + moduleList = std::move(rhs.moduleList); + _eliminateHierarchy = rhs._eliminateHierarchy; + _tags = std::move(rhs._tags); + } + /** Move operation with the assignment operator @todo should be in the base class!? */ ModuleGroup& operator=(ModuleGroup &&rhs) { _name = std::move(rhs._name); _owner = std::move(rhs._owner); + _description = std::move(rhs._description); accessorList = std::move(rhs.accessorList); moduleList = std::move(rhs.moduleList); + _eliminateHierarchy = rhs._eliminateHierarchy; + _tags = std::move(rhs._tags); return *this; } ModuleGroup& operator=(ModuleGroup &rhs) = delete; + ModuleGroup& operator=(const ModuleGroup &rhs) = delete; + + ModuleType getModuleType() const override { return ModuleType::ModuleGroup; } }; diff --git a/include/VariableGroup.h b/include/VariableGroup.h index f6bdb9d8..381df7dd 100644 --- a/include/VariableGroup.h +++ b/include/VariableGroup.h @@ -54,6 +54,8 @@ namespace ChimeraTK { VariableGroup& operator=(VariableGroup &rhs) = delete; + ModuleType getModuleType() const override { return ModuleType::VariableGroup; } + }; } /* namespace ChimeraTK */ diff --git a/include/VirtualModule.h b/include/VirtualModule.h index 5068a8a2..0d12ff36 100644 --- a/include/VirtualModule.h +++ b/include/VirtualModule.h @@ -22,7 +22,9 @@ namespace ChimeraTK { public: /** Constructor */ - VirtualModule(const std::string &name, const std::string &description) : Module(nullptr, name, description) {} + VirtualModule(const std::string &name, const std::string &description, ModuleType moduleType) + : Module(nullptr, name, description), _moduleType(moduleType) + {} /** Copy constructor */ VirtualModule(const VirtualModule &other); @@ -36,10 +38,13 @@ namespace ChimeraTK { /** Add a virtual sub-module. The module instance will be added to an internal list. */ void addSubModule(VirtualModule module); + + ModuleType getModuleType() const override { return _moduleType; } protected: std::list<VirtualModule> submodules; + ModuleType _moduleType; }; diff --git a/src/EntityOwner.cc b/src/EntityOwner.cc index 2dc70103..ad90e90e 100644 --- a/src/EntityOwner.cc +++ b/src/EntityOwner.cc @@ -80,7 +80,7 @@ namespace ChimeraTK { VirtualModule EntityOwner::findTag(const std::string &tag, bool eliminateAllHierarchies) const { // create new module to return - VirtualModule module{_name, _description}; + VirtualModule module{_name, _description, getModuleType()}; // add everything matching the tag to the virtual module and return it findTagAndAppendToModule(module, tag, eliminateAllHierarchies, true); @@ -92,7 +92,7 @@ namespace ChimeraTK { void EntityOwner::findTagAndAppendToModule(VirtualModule &module, const std::string &tag, bool eliminateAllHierarchies, bool eliminateFirstHierarchy) const { - VirtualModule nextmodule{_name, _description}; + VirtualModule nextmodule{_name, _description, getModuleType()}; VirtualModule *moduleToAddTo; bool needToAddSubModule = false; @@ -152,20 +152,36 @@ namespace ChimeraTK { dumpGraphInternal(file); file << "}" << std::endl; file.close(); - std::cout << "HIER " << fileName << std::endl; + } + + /*********************************************************************************************************************/ + + std::string EntityOwner::cleanDotNode(std::string fullName) const { + std::replace(fullName.begin(), fullName.end(), '/', '_'); + std::replace(fullName.begin(), fullName.end(), ':', '_'); + return fullName; } /*********************************************************************************************************************/ void EntityOwner::dumpGraphInternal(std::ostream &stream) const { - std::string myDotNode = getQualifiedName(); - std::replace(myDotNode.begin(), myDotNode.end(), '/', '_'); - stream << myDotNode << "[label=\"" << getName() << "\"]" << std::endl; + std::string myDotNode = cleanDotNode(getQualifiedName()); + + stream << myDotNode << "[label=\"" << getName() << "\""; + if(_eliminateHierarchy) { + stream << ",style=dotted"; + } + if(getModuleType() == ModuleType::ModuleGroup) { + stream << ",peripheries=2"; + } + if(getModuleType() == ModuleType::ApplicationModule) { + stream << ",style=bold"; + } + stream << "]" << std::endl; for(auto &node : getAccessorList()) { - std::string dotNode = node.getQualifiedName(); - std::replace(dotNode.begin(), dotNode.end(), '/', '_'); + std::string dotNode = cleanDotNode(node.getQualifiedName()); stream << dotNode << "[label=\"{" << node.getName() << "| {"; bool first = true; for(auto tag : node.getTags()) { @@ -182,8 +198,7 @@ namespace ChimeraTK { } for(auto &submodule : getSubmoduleList()) { - std::string dotNode = submodule->getQualifiedName(); - std::replace(dotNode.begin(), dotNode.end(), '/', '_'); + std::string dotNode = cleanDotNode(submodule->getQualifiedName()); stream << " " << myDotNode << " -> " << dotNode << std::endl; submodule->dumpGraphInternal(stream); } @@ -201,7 +216,7 @@ namespace ChimeraTK { /*********************************************************************************************************************/ VirtualModule EntityOwner::flatten() { - VirtualModule nextmodule{_name, _description}; + VirtualModule nextmodule{_name, _description, getModuleType()}; for(auto &node : getAccessorListRecursive()) { nextmodule.registerAccessor(node); } -- GitLab