ATLAS Offline Software
Loading...
Searching...
No Matches
GraphSvc.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
5#include "GraphSvc.h"
6#include "GaudiKernel/Algorithm.h"
7#include "Gaudi/Sequence.h"
8#include "GaudiKernel/DataHandleHolderVisitor.h"
9
10#include <fstream>
11#include <regex>
12#include <functional>
13#include <string>
14#include <string_view>
15#include <set>
16#include <list>
17#include <map>
18
19namespace GlobalSim {
20
21 StatusCode GraphSvc::initialize() {
22 return StatusCode::SUCCESS;
23 }
24
25 StatusCode GraphSvc::start() {
26
27 std::function<void(IAlgorithm*,std::set<IAlgorithm*>&,bool)> func;
28
29 std::regex sequenceNameRegex( m_topSequence.value() );
30
31 // locate the desired algs ...
32 func = [&](IAlgorithm* alg, std::set<IAlgorithm*>& thealgs, bool isAdding) {
33 isAdding = (isAdding || std::regex_search( std::string(alg->nameKey()) , sequenceNameRegex) ); // activate adding when get to target
34 if(isAdding) {
35 thealgs.insert(alg);
36 }
37 if(auto seq = dynamic_cast<Gaudi::Sequence*>( alg )) {
38 auto subalgs = seq->subAlgorithms();
39 for(auto thisAlg : *subalgs) {
40 func(thisAlg,thealgs,isAdding);
41 }
42 }
43 };
44
45 // Get the list of algorithms
46 const std::list<IAlgorithm*>& algos = m_algResourcePool->getTopAlgList();
47 std::set<IAlgorithm*> subalgs;
48 for ( IAlgorithm* ialgoPtr : algos ) {
49 func(ialgoPtr,subalgs,false);
50 }
51
52
53 DataObjIDColl globalInp, globalOutp;
54 std::map<std::string, DataObjIDColl> algosOutputDependenciesMap;
55 std::map<std::string, DataObjIDColl> algosInputDependenciesMap;
56
57 for ( IAlgorithm* ialgoPtr : subalgs ) {
58 if(ialgoPtr->isSequence()) continue; // don't look at sequences, shouldn't have any inputs/outputs
59
60 Gaudi::Algorithm* algoPtr = dynamic_cast<Gaudi::Algorithm*>( ialgoPtr );
61 if ( !algoPtr ) continue;
62 DataObjIDColl algoOutputs;
63 for ( const auto & id : algoPtr->outputDataObjs() ) {
64 globalOutp.insert( id );
65 algoOutputs.insert( id );
66 }
67
68
69
70 DataObjIDColl i1, i2;
71 DHHVisitor avis( i1, i2 );
72 algoPtr->acceptDHVisitor( &avis );
73
74 DataObjIDColl algoDependencies;
75 for ( const DataObjID& id : algoPtr->inputDataObjs() ) {
76 algoDependencies.insert( id );
77 globalInp.insert( id );
78 }
79
80 std::string algoName = ialgoPtr->nameKey();
81 if(ialgoPtr->type()!= algoName) {
82 algoName = ialgoPtr->type() + "/" + algoName;
83 }
84
85 algosInputDependenciesMap[algoName] = std::move(algoDependencies);
86 algosOutputDependenciesMap[algoName] = std::move(algoOutputs);
87
88 }
89
90
91 ATH_MSG_INFO("Creating " << m_fileName.value());
92 std::ofstream stream{ m_fileName, std::ofstream::out };
93 stream << "digraph datadeps {\n rankdir=\"LR\";\n"; // left-to-right graph
94
95 auto addNode = [&](std::string_view id, std::string_view name, std::string_view shape="box" ) {
96 stream << " " << id << " [label=\"" << name << "\";shape=" << shape << "];\n"; // adds a node
97 };
98 auto addEdge = [&](std::string_view srcId, std::string_view tgtId, std::string_view label ) {
99 stream << " " << srcId << " -> " << tgtId << " [label=\"" << label << "\"];\n"; // adds an edge
100 };
101
102 // find all inputs that do not have an output. These will be our 'starting nodes' of shape='plaintext'
103 std::map<std::string,std::pair<std::set<std::string>,std::set<std::string>>> deps;
104
105 // key is dep name, value is pair of sets, first are "producers" of dep, second a "consumers" of dep
106 // if has no producer, is a global input. if has no consumer, is a global output.
107
108 for ( const auto& [algName, ideps] : algosInputDependenciesMap ) {
109 for (const auto &dep: ideps) {
110 deps[dep.key()].second.insert(algName); // alg is a consumer
111 }
112 }
113 for ( const auto& [algName, odeps] : algosOutputDependenciesMap ) {
114 for (const auto &dep: odeps) {
115 deps[dep.key()].first.insert(algName); // alg is a producer
116 }
117 }
118
119 std::size_t algoIndex = 0ul;
120 std::map<std::string,std::string> keyToName;
121 std::string inputs,outputs;
122 // start by creating nodes of global inputs and outputs
123 for( auto& [dep, pcs] : deps) {
124 auto& [producers,consumers] = pcs;
125 if(producers.empty()) {
126 std::string algIndex = "Input_" + std::to_string( algoIndex );
127 addNode( algIndex, dep, "plaintext" );
128 keyToName[dep] = algIndex;
129 algoIndex++;
130 producers.insert(dep); // its a self-producer
131 inputs += algIndex + "; ";
132 } else if(consumers.empty()) {
133 std::string algIndex = "Output_" + std::to_string( algoIndex );
134 addNode( algIndex, dep, "plaintext" );
135 keyToName[dep] = algIndex;
136 algoIndex++;
137 consumers.insert(dep); // its a self-consumer
138 outputs += algIndex + "; ";
139 }
140 }
141 // create nodes of all algorithms
142 for ( const auto& [algName, ideps] : algosInputDependenciesMap ) {
143 std::string algIndex = "Alg_" + std::to_string( algoIndex );
144 addNode( algIndex, algName, "box" );
145 keyToName[algName] = std::move(algIndex);
146 algoIndex++;
147 }
148 // now go through deps and create link from every producer to every consumer
149 for( const auto& [dep, pcs] : deps) {
150 auto& [producers,consumers] = pcs;
151 for(auto& producer : producers) {
152 for(auto& consumer: consumers) {
153 addEdge(keyToName.at(producer),keyToName.at(consumer),dep!=producer && dep!=consumer ? dep : " ");
154 }
155 }
156 }
157
158 if(!inputs.empty()) {
159 stream << " { rank = same; " << inputs << "}\n";
160 }
161 if(!outputs.empty()) {
162 stream << " { rank = same; " << outputs << "}\n";
163 }
164
165 stream << "}\n";
166 stream.close();
167
168 return StatusCode::SUCCESS;
169
170 }
171
172 StatusCode GraphSvc::finalize() {
173 return StatusCode::SUCCESS;
174
175 }
176
177}
178
#define ATH_MSG_INFO(x)
virtual StatusCode start() override
Start - do graph calculation here, to ensure EventLoopMgr initialized already.
Definition GraphSvc.cxx:25
virtual StatusCode initialize() override
Initialise.
Definition GraphSvc.cxx:21
StringProperty m_fileName
Definition GraphSvc.h:32
virtual StatusCode finalize() override
Finalise.
Definition GraphSvc.cxx:172
StringProperty m_topSequence
Definition GraphSvc.h:33
ServiceHandle< IAlgResourcePool > m_algResourcePool
Definition GraphSvc.h:35
std::string label(const std::string &format, int i)
Definition label.h:19
AlgTool to read in LArStripNeighborhoods, and run the BDT Algorithm.