LIMA
Libre Multilingual Analyzer — C++ API
Loading...
Searching...
No Matches
DotDependencyGraphWriter.cpp
Go to the documentation of this file.
1// Copyright 2002-2019 CEA LIST
2// SPDX-FileCopyrightText: 2022 CEA LIST <gael.de-chalendar@cea.fr>
3//
4// SPDX-License-Identifier: MIT
5
18#include "DependencyGraph.h"
19#include "SyntacticData.h"
26
27// #include "linguisticProcessing/core/PosTagger/dotGraphWriter.h"
28// #include "linguisticProcessing/core/PosTagger/posTaggingGraphWriter.h"
29
30
31#include <fstream>
32#include <queue>
34
35//using namespace boost;
36using namespace std;
37using namespace Lima::Common::Misc;
39using namespace Lima::Common::AnnotationGraphs;
41
42namespace Lima {
43
44namespace LinguisticProcessing {
45
46namespace SyntacticAnalysis {
47
50
52 m_outputMode(FullGraph)
53{}
54
57
60 Manager* manager)
61
62{
63 DotGraphWriter::init(unitConfiguration,manager);
64
65 m_onlyDepEdges=false;
66 try
67 {
68 string onlyDepEdges=
69 unitConfiguration.getParamsValueAtKey("writeOnlyDepEdges");
70 if (onlyDepEdges == "true" ||
71 onlyDepEdges == "yes")
72 {
73 m_onlyDepEdges=true;
74 }
75 }
76 catch (NoSuchParam& ) // keep default value (false)
77 {}
78
79 try
80 {
81 string outputMode =
82 unitConfiguration.getParamsValueAtKey("outputMode");
83 if (outputMode == "SentenceBySentence")
84 {
85 m_outputMode = SentenceBySentence;
86 }
87 }
88 catch (NoSuchParam& ) // keep default value (FullGraph)
89 {
90 }
91 try
92 {
93 m_graphDotOptions = unitConfiguration.getMapAtKey("graphDotOptions");
94 }
95 catch (NoSuchMap& ) {}
96
97 try
98 {
99 m_nodeDotOptions = unitConfiguration.getMapAtKey("nodeDotOptions");
100 }
101 catch (NoSuchMap& ) {}
102
103 try
104 {
105 m_edgeDotOptions = unitConfiguration.getMapAtKey("edgeDotOptions");
106 }
107 catch (NoSuchMap& ) {}
108 try
109 {
110 m_vertexDisplay=unitConfiguration.getListsValueAtKey("vertexDisplay");
111 }
112 catch (NoSuchList& )
113 {
114 // empty display
115 }
116}
117
118
120{
121 SALOGINIT;
122
123 auto anagraph = std::dynamic_pointer_cast<AnalysisGraph>(analysis.getData("AnalysisGraph"));
124 auto posgraph = std::dynamic_pointer_cast<AnalysisGraph>(analysis.getData("PosGraph"));
125 auto annotationData = std::dynamic_pointer_cast<AnnotationData>(analysis.getData("AnnotationData"));
126 auto syntacticData = std::dynamic_pointer_cast<SyntacticData>(analysis.getData("SyntacticData"));
127 auto metadata = std::dynamic_pointer_cast<LinguisticMetaData>(analysis.getData("LinguisticMetaData"));
128 if (metadata == 0) {
129 SALOGINIT;
130 LERROR << "no LinguisticMetaData ! abort";
131 return MISSING_DATA;
132 }
133 if (m_outputMode == FullGraph)
134 {
135 string outputFileName=metadata->getMetaData("FileName") + m_outputSuffix;
136
137 std::ofstream ofs(outputFileName.c_str(), std::ofstream::binary);
138
139 if (m_onlyDepEdges)
140 {
141 // write only the dependency graph
142 // (but uses the PosTaggingVertexWriter to write the vertices
143 // of the morphological graph)
144 PosTagger::
145 PosTaggingVertexWriter<LinguisticGraph, LinguisticGraphVertex>
146 phoenixGraphVertexWriter(posgraph->getGraph(),
148 m_vertexDisplay);
149
150 DependencyGraphVertexWriter<DependencyGraph,DependencyGraphVertex>
151 vertexWriter(syntacticData->dependencyGraph(),
152 phoenixGraphVertexWriter);
153
154 DependencyGraphEdgeWriter<DependencyGraph,DependencyGraphEdge>
155 edgeWriter(syntacticData->dependencyGraph(),
156 m_language);
157
159 m_graphDotOptions,
160 m_nodeDotOptions,
161 m_edgeDotOptions);
162 boost::write_graphviz(ofs,
163 *(syntacticData->dependencyGraph()),
164 vertexWriter,
165 edgeWriter,
166 graphWriter);
167 }
168 else
169 {
170 // write the morphological graph
171 // and add the edges from the dependency graph
172 PosTagger::
173 PosTaggingVertexWriter<LinguisticGraph, LinguisticGraphVertex>
174 vertexWriter(posgraph->getGraph(),
176 m_vertexDisplay);
177
178 PosTaggingDepGraphEdgeWriter<LinguisticGraph,LinguisticGraphEdge>
179 edgeWriter(posgraph->getGraph(),m_language,
180 syntacticData->dependencyGraph(),
181 syntacticData.get());
182
184 m_graphDotOptions,
185 m_nodeDotOptions,
186 m_edgeDotOptions);
187
188 boost::write_graphviz(ofs,
189 *(syntacticData->dependencyGraph()),
190 vertexWriter,
191 edgeWriter,
192 graphWriter);
193 }
194 }
195 else if (m_outputMode == SentenceBySentence)
196 {
197 auto sb = std::dynamic_pointer_cast<SegmentationData>(analysis.getData("SentenceBoundaries"));
198 if (sb==0)
199 {
200 LERROR << "no sentence bounds ! abort";
201 return MISSING_DATA;
202 }
203 if (sb->getGraphId() != "PosGraph") {
204 LERROR << "SentenceBounds have been computed on " << sb->getGraphId() << " !";
205 LERROR << "DotDependencyGraphWriter needs SentenceBounds on PosGraph";
207 }
208
209 uint64_t i=0;
210 // ??OME2 for (SegmentationData::const_iterator boundItr=sb->begin();
211 // boundItr!=sb->end();
212 for (std::vector<Segment>::const_iterator boundItr=(sb->getSegments()).begin();
213 boundItr!=(sb->getSegments()).end();
214 boundItr++, i++)
215 {
216 LinguisticGraphVertex beginSentence=boundItr->getFirstVertex();
217 LinguisticGraphVertex endSentence=boundItr->getLastVertex();
218 // std::string firstWord;
219// LinguisticAnalysisStructure::Token* token=get(vertex_token, *anagraph->getGraph(), (*(boundItr))+1);
220// if (token != 0)
221// firstWord = limastring2utf8stdstring(token->stringForm());
222 std::ostringstream outputFileName;
223 outputFileName << metadata->getMetaData("FileName") << ".sent"<< i /*<< firstWord*/ << m_outputSuffix;
224
225 std::ofstream ofs(outputFileName.str().c_str(), std::ofstream::binary);
226
227
228 ofs << "digraph sentence" << i << " {" << std::endl;
229 ofs << " graph [";
230 for (std::map<std::string,std::string>::const_iterator graphDotOptionsIt = m_graphDotOptions.begin() ; graphDotOptionsIt != m_graphDotOptions.end(); graphDotOptionsIt++)
231 {
232 ofs << graphDotOptionsIt->first << "=" << graphDotOptionsIt->second << ",";
233 }
234 ofs <<"]"<<std::endl;
235 ofs << " node [";
236 for (std::map<std::string,std::string>::const_iterator nodeDotOptionsIt = m_nodeDotOptions.begin() ; nodeDotOptionsIt != m_nodeDotOptions.end(); nodeDotOptionsIt++)
237 {
238 ofs << nodeDotOptionsIt->first << "=" << nodeDotOptionsIt->second << ",";
239 }
240 ofs << "]"<<std::endl;
241 ofs << " edge [";
242 for (std::map<std::string,std::string>::const_iterator edgeDotOptionsIt = m_edgeDotOptions.begin() ; edgeDotOptionsIt != m_edgeDotOptions.end(); edgeDotOptionsIt++)
243 {
244 ofs << edgeDotOptionsIt->first << "=" << edgeDotOptionsIt->second << ",";
245 }
246 ofs << "]"<<std::endl;
247
248 if (m_onlyDepEdges)
249 {
250 // write only the dependency graph
251 // (but uses the PosTaggingVertexWriter to write the vertices
252 // of the morphological graph)
253
254 }
255 else
256 {
257 write_graphviz(ofs,
258 i,
259 beginSentence,
260 endSentence,
261 anagraph.get(),
262 posgraph.get(),
263 syntacticData.get(),
264 annotationData.get());
265 }
266 ofs << "}"<<std::endl;
267 }
268 }
269 else // output mode
270 {
271 LERROR << "Unknown output mode";
272 return UNKNOWN_ERROR;
273 }
274 return SUCCESS_ID;
275}
276
277//***********************************************************************
278// main function for outputing the graph
279//***********************************************************************
280void DotDependencyGraphWriter::write_graphviz(
281 std::ostream& os,
282 uint64_t sentNum,
283 const LinguisticGraphVertex begin,
284 const LinguisticGraphVertex end,
285 const AnalysisGraph* anagraph,
286 const AnalysisGraph* posgraph,
287 const SyntacticData* syntacticData,
288 const Common::AnnotationGraphs::AnnotationData* annotationData) const
289{
290 LIMA_UNUSED(sentNum);
291 LIMA_UNUSED(anagraph);
292 LIMA_UNUSED(annotationData);
293 SALOGINIT;
294 LDEBUG << "DotDependencyGraphWriter::write_graphviz begin="<<begin<<" ; end=" << end;
295// CEdgeDepRelTypePropertyMap typeMap = get(edge_deprel_type, *syntacticData->dependencyGraph());
296
297 const LinguisticGraph& lposgraph=*(posgraph->getGraph());
298 const DependencyGraph* depGraph=syntacticData->dependencyGraph();
299
300 std::set<LinguisticGraphVertex> visited;
301 std::queue<LinguisticGraphVertex> toVisit;
302 toVisit.push(begin);
303
304 LinguisticGraphOutEdgeIt outItr,outItrEnd;
305 while (!toVisit.empty())
306 {
307 LinguisticGraphVertex v=toVisit.front();
308 toVisit.pop();
309
310 os << v << " ";
311 DependencyGraphVertexWriter<DependencyGraph,DependencyGraphVertex>(
312 depGraph,PosTagger::PosTaggingVertexWriter<LinguisticGraph,LinguisticGraphVertex> (&lposgraph,m_language,m_vertexDisplay))(os,v);
313
314 for (boost::tie(outItr,outItrEnd)=out_edges(v,lposgraph);
315 outItr!=outItrEnd;
316 outItr++)
317 {
318 LinguisticGraphVertex next=target(*outItr,lposgraph);
319 if (visited.find(next)==visited.end())
320 {
321 visited.insert(next);
322 if (v != end)
323 {
324 toVisit.push(next);
325 }
326 else
327 {
328 LDEBUG << "PosTaggingDepGraphEdgeWriter reached end";
329 }
330 }
331
332 if (v != end)
333 {
334 os << v << " -> " << next << " ";
335 LTRACE << "PosTaggingDepGraphEdgeWriter for "<<v<<" -> " << next;
336 PosTaggingDepGraphEdgeWriter<LinguisticGraph,LinguisticGraphEdge>(&lposgraph,m_language,depGraph,syntacticData)(os,*outItr);
337 }
338 }
339 }
340}
341
342
343
344} // end namespace
345} // end namespace
346} // end namespace
This file is the main header file for the data related to annotation graphs.
A graph that stores the relations of syntactic dependency between the elements of a DependencyGraph.
boost::adjacency_list< boost::vecS, boost::vecS, boost::bidirectionalS, DepVertexProperties, DepEdgeProperties > DependencyGraph
The dependency graph class.
output of dependency graph with dot format
#define DOTDEPENDENCYGRAPHWRITER_CLASSID
#define LTRACE
Definition LimaCommon.h:156
#define LIMA_UNUSED(x)
Definition LimaCommon.h:224
#define LDEBUG
Definition LimaCommon.h:157
#define LERROR
Definition LimaCommon.h:161
A graph structure for linguistic analysis.
LinguisticGraph::vertex_descriptor LinguisticGraphVertex
LinguisticGraph::out_edge_iterator LinguisticGraphOutEdgeIt
boost::adjacency_list< boost::vecS, boost::vecS, boost::bidirectionalS, LinguisticVertexProperties > LinguisticGraph
Property to identify the chains in the graph.
#define SALOGINIT
Defines a Factory to create Object of type Base.
Data used for the syntactic analyzis of texts.
Holds all data that pass through the ProcessUnits Analysis data are shared pointers,...
std::shared_ptr< AnalysisData > getData(const QString &id)
return AnalysisData by id
Holds an annotation graph and gives an API to manipulate it.
std::deque< std::string > & getListsValueAtKey(const std::string &key)
std::map< std::string, std::string > & getMapAtKey(const std::string &key)
return a message when a 'param' was not found
Manage initialization of InitializableObjects using configuration module and parameters.
void init(Common::XMLConfigurationFiles::GroupConfigurationStructure &unitConfiguration, Manager *manager) override
initialize with parameters from configuration file.
An AnalysisData containing a LinguisticGraph with a language and an id.
const LinguisticGraph * getGraph(void) const
Returns the underlying graph structure.
void init(Common::XMLConfigurationFiles::GroupConfigurationStructure &unitConfiguration, Manager *manager) override
initialize with parameters from configuration file.
LimaStatusCode process(AnalysisContent &analysis) const override
Process on data in analysisContent.
This class points to a graph, its dependency graph and the structure that holds the maping between th...
SimpleFactory< MediaProcessUnit, DotDependencyGraphWriter > dotDependencyGraphWriterFactory(DOTDEPENDENCYGRAPHWRITER_CLASSID)
NAUTITIA.
LimaStatusCode
Definition LimaCommon.h:236
@ UNKNOWN_ERROR
Definition LimaCommon.h:238
@ SUCCESS_ID
Definition LimaCommon.h:237
@ INVALID_CONFIGURATION
Definition LimaCommon.h:242
@ MISSING_DATA
Definition LimaCommon.h:243
STL namespace.