LIMA
Libre Multilingual Analyzer — C++ API
Loading...
Searching...
No Matches
SemanticRoleLabelingLoader.cpp
Go to the documentation of this file.
1// Copyright 2002-2014 CEA LIST
2// SPDX-FileCopyrightText: 2022 CEA LIST <gael.de-chalendar@cea.fr>
3//
4// SPDX-License-Identifier: MIT
5
6/************************************************************************
7 *
8 * @file SemanticRoleLabelingLoader.cpp
9 * @author Clémence Filmont
10 * @author Gael de Chalendar <gael.de-chalendar@cea.fr>
11 * @date 2014
12 * copyright Copyright (C) 2014-2016 by CEA LIST
13 ***********************************************************************/
14
17
28
29#include <QRegularExpression>
30#include "QStringList"
31#include <QString>
32#include <QFile>
33
34#include <boost/range/irange.hpp>
35
36#include <utility>
37#include <iostream>
38#include <fstream>
39#include <map>
40
41using namespace std;
45using namespace Lima::Common::AnnotationGraphs;
47using namespace Lima::Common::AnnotationGraphs;
48
49
50namespace Lima {
51namespace LinguisticProcessing {
52namespace SemanticAnalysis {
53
55
56#define NBCOLSINSRLBEFOREFRAME 11
57#define CONLLTOKENSEPARATOR "\n+"
58#define CONLLFIELDSEPARATOR "\t"
59
60// Conll handler
62{
64 virtual ~ConllHandler();
65
73 bool extractSemanticInformation(int sentenceIndex, LimaConllTokenIdMapping* limaConllMapping, const QString & sentence);
74
81 QStringList splitSegment(const QString & segment, QRegularExpression separator);
82
91 LinguisticGraphVertex getLimaTokenId(int conllTokenId, int sentenceIndex, LimaConllTokenIdMapping* limaConllMapping);
92
93
94 MediaId m_language;
97 QRegularExpression m_descriptorSeparator;
98 QRegularExpression m_tokenSeparator;
99 QVector< QPair<LinguisticGraphVertex,QString> > m_verbalClasses;
100 QVector < std::vector<std::pair<LinguisticGraphVertex,QString>> >m_semanticRoles;
102};
103
104
106{
110
111 MediaId m_language;
112 std::string m_graph;
113 QString m_model;
114};
115
116
117
118//***********************************************************************
119SemanticRoleLabelingLoaderPrivate::SemanticRoleLabelingLoaderPrivate():
120m_language(0),
121m_graph("PosGraph"),
122m_model("VerbNet")
123{}
124
125SemanticRoleLabelingLoaderPrivate::~SemanticRoleLabelingLoaderPrivate()
126{
127}
128
129//***********************************************************************
135
140
141//***********************************************************************
142
144{
145
146// SEMANTICANALYSISLOGINIT;
147 m_d->m_language=manager->getInitializationParameters().media;
148 AnalysisLoader::init(unitConfiguration,manager);
149 try
150 {
151 m_d->m_graph=unitConfiguration.getParamsValueAtKey("graph");
152 }
153 catch (NoSuchParam& ) {} // keep default value
154 try
155 {
156 m_d->m_model = QString::fromUtf8(unitConfiguration.getParamsValueAtKey("model").c_str());
157 }
158 catch (NoSuchParam& ) {} // keep default value
159}
160
161
163{
164#ifdef DEBUG_LP
166#endif
167 auto tokenList = std::dynamic_pointer_cast<AnalysisGraph>(analysis.getData(m_d->m_graph));
168 if (tokenList==0)
169 {
171 LERROR << "graph " << m_d->m_graph << " has not been produced: check pipeline" ;
172 return MISSING_DATA;
173 }
174 auto annotationData = std::dynamic_pointer_cast<AnnotationData>(analysis.getData("AnnotationData"));
175 auto limaConllMapping = std::dynamic_pointer_cast<LimaConllTokenIdMapping>(analysis.getData("LimaConllTokenIdMapping"));
176
177 QString fileName = getInputFile(analysis);
178
179 QFile file(fileName);
180
181
182 if (!file.open(QIODevice::ReadOnly))
183 {
185 LERROR << "SemanticRoleLabelingLoader::process: cannot open file" << fileName;
187 }
188 int sentenceNb=1;
189 std::map <int, QString> sentences;
190 while (!file.atEnd())
191 {
192 QByteArray text=file.readLine();
193 QString textString = QString::fromUtf8(text.constData());
194 //One assume that the input file does not start with a blank line
195 if (textString.size()<3)
196 {
197 sentenceNb++;
198 }
199 else
200 {
201 QString becomingSentence=sentences[sentenceNb]+textString;
202 sentences[sentenceNb]= becomingSentence;
203 }
204 }
205
206 ConllHandler cHandler(m_d->m_language, analysis, tokenList.get());
207 for (std::map<int,QString>::iterator it=sentences.begin(); it!=sentences.end(); ++it)
208 {
209 int sentenceIndex=it->first;
210 QString sentence=it->second;
211 if(cHandler.extractSemanticInformation(sentenceIndex, limaConllMapping.get(), sentence))
212 {
213#ifdef DEBUG_LP
214 LDEBUG << "SemanticRoleLabelingLoader::process there is/are " << cHandler.m_verbalClassNb << "verbal class(es) for this sentence " ;
215#endif
216 for (int vClassIndex=0;vClassIndex<cHandler.m_verbalClassNb;vClassIndex++)
217 {
218 LinguisticGraphVertex posGraphPredicateVertex=cHandler.m_verbalClasses[vClassIndex].first;
219 QStringList verbalClasses = cHandler.m_verbalClasses[vClassIndex].second.split("|");
220 for (auto verbalClass = verbalClasses.begin(); verbalClass != verbalClasses.end(); ++verbalClass)
221 {
222 *verbalClass = m_d->m_model + "." + *verbalClass;
223 }
224 LimaString verbalClass= verbalClasses.join("|");
225
226
227 AnnotationGraphVertex annotPredicateVertex=annotationData->createAnnotationVertex();
228 annotationData->addMatching("PosGraph", posGraphPredicateVertex, "annot", annotPredicateVertex);
229 annotationData->annotate(annotPredicateVertex, "Predicate", verbalClass);
230
231
232#ifdef DEBUG_LP
233 LDEBUG << "SemanticRoleLabelingLoader::process: annotation vertex"<< annotPredicateVertex <<"was created for the verbal class "<< annotationData->stringAnnotation(annotPredicateVertex, "Predicate") << "and the PoS graph vertex"<<posGraphPredicateVertex;
234#endif
235 std::vector <pair<LinguisticGraphVertex,QString>>::iterator semRoleIt;
236 for (semRoleIt=cHandler.m_semanticRoles[vClassIndex].begin(); semRoleIt!=cHandler.m_semanticRoles[vClassIndex].end();semRoleIt++){
237 LinguisticGraphVertex posGraphRoleVertex=(*semRoleIt).first;
238 QStringList semanticRoles = (*semRoleIt).second.split("|");
239 for (auto semanticRole = semanticRoles.begin(); semanticRole != semanticRoles.end(); ++semanticRole)
240 {
241 if (!semanticRole->isEmpty())
242 *semanticRole = m_d->m_model + "." + *semanticRole;
243 }
244 LimaString semanticRole= semanticRoles.join("|");
245
246 AnnotationGraphVertex annotRoleVertex=annotationData->createAnnotationVertex();
247 AnnotationGraphEdge roleEdge=annotationData->createAnnotationEdge(annotPredicateVertex, annotRoleVertex);
248 annotationData->annotate(roleEdge, "SemanticRole", semanticRole);
249 annotationData->addMatching("PosGraph", posGraphRoleVertex, "annot", annotRoleVertex);
250
251
252#ifdef DEBUG_LP
253 LDEBUG << "SemanticRoleLabelingLoader::process: annotation edge" << roleEdge << "annotated " << annotationData->stringAnnotation(roleEdge, "SemanticRole")<< "was created for" << verbalClass << " and the PoS graph vertices " << posGraphPredicateVertex << "and" << posGraphRoleVertex ;
254#endif
255 }
256 }
257 }
258 }
259 return SUCCESS_ID;
260}
261
262
263
265m_language(language),
266m_analysis(analysis),
267m_graph(graph),
268m_descriptorSeparator(CONLLFIELDSEPARATOR),
269m_tokenSeparator(CONLLTOKENSEPARATOR),
270m_verbalClasses(),
271m_semanticRoles(),
272m_verbalClassNb()
273{
274}
278
279// designed to be repeated on each sentence
280bool ConllHandler::extractSemanticInformation(int sentenceI, LimaConllTokenIdMapping* limaConllMapping, const QString & sent)
281{
284 QStringList sentenceTokens=cHandler.splitSegment(sent, m_tokenSeparator);
285 QString firstSentenceToken=(*sentenceTokens.constBegin());
286 int descriptorsNb = cHandler.splitSegment(firstSentenceToken, m_descriptorSeparator).size();
287 m_verbalClassNb = descriptorsNb - NBCOLSINSRLBEFOREFRAME - 1;
288 int classIndex=0;
289 if (m_verbalClassNb > 0)
290 {
291#ifdef DEBUG_LP
292 LDEBUG << "ConllHandler::extractSemanticInformation" << m_verbalClassNb << sentenceI << " : \n" << sent ;
293#endif
294 m_verbalClasses.clear();
296 m_semanticRoles.clear();
298 //repeated on each token of the sentence, that is on each line
299 for (auto it = sentenceTokens.begin(); it != sentenceTokens.end(); ++it)
300 {
301 int roleNumbers=0;
302 QStringList descriptors=cHandler.splitSegment(*it,m_descriptorSeparator);
303 if (descriptors.size()>=NBCOLSINSRLBEFOREFRAME+m_verbalClassNb)
304 {
305 int conllTokenId=descriptors[0].toInt();
306 QString conllToken=descriptors[1];
307#ifdef DEBUG_LP
308 LDEBUG << "ConllHandler::extractSemanticInformation token " << conllTokenId << conllToken;
309#endif
310 if(descriptors[NBCOLSINSRLBEFOREFRAME]!="_")
311 {
312 QString verbalClass=descriptors[NBCOLSINSRLBEFOREFRAME];
313#ifdef DEBUG_LP
314 LDEBUG << "ConllHandler::extractSemanticInformation verbalClass" << verbalClass;
315#endif
316 LinguisticGraphVertex limaTokenId=cHandler.getLimaTokenId(conllTokenId, sentenceI, limaConllMapping);
317 if (classIndex >= m_verbalClasses.size())
318 {
319 LERROR << "ConllHandler::extractSemanticInformation classIndex error" << classIndex;
320 break;
321 }
322 m_verbalClasses[classIndex]=qMakePair(limaTokenId, verbalClass);
323 classIndex++;
324 }
325
326 for (int roleTargetFieldIndex = 0; roleTargetFieldIndex<m_verbalClassNb; ++roleTargetFieldIndex)
327 {
328#ifdef DEBUG_LP
329 LDEBUG << "ConllHandler::extractSemanticInformation"<<"nb descriptors and roleTargetFieldIndex" << descriptors.size() << roleTargetFieldIndex ;
330#endif
331 if (NBCOLSINSRLBEFOREFRAME+1+roleTargetFieldIndex >= descriptors.size())
332 {
333 LERROR << "ConllHandler::extractSemanticInformation roleTargetFieldIndex error" << roleTargetFieldIndex;
334 break;
335 }
336 if (descriptors[NBCOLSINSRLBEFOREFRAME+1+roleTargetFieldIndex]!="_")
337 {
338 QString semanticRoleLabel=descriptors[NBCOLSINSRLBEFOREFRAME+1+roleTargetFieldIndex];
339
340 LinguisticGraphVertex limaTokenId=cHandler.getLimaTokenId(conllTokenId, sentenceI, limaConllMapping);
341 if(limaTokenId!=0)
342 {
343#ifdef DEBUG_LP
344 LDEBUG << "ConllHandler::extractSemanticInformation argument "<<semanticRoleLabel<<": The PoS graph token id matching the conll token id " << conllTokenId << " is " << limaTokenId;
345#endif
346 std::vector<std::pair<LinguisticGraphVertex,QString>> sRoles;
347 if (roleTargetFieldIndex >= m_semanticRoles.size())
348 {
349 LERROR << "ConllHandler::extractSemanticInformation roleTargetFieldIndex error 2" << roleTargetFieldIndex;
350 break;
351 }
352 m_semanticRoles[roleTargetFieldIndex].push_back(make_pair(limaTokenId,semanticRoleLabel));
353 }
354 roleNumbers++;
355 }
356 }
357 }
358 }
359 }
360 return classIndex;
361}
362
363
364
365QStringList ConllHandler::splitSegment(const QString & segment, QRegularExpression separator)
366{
367 QStringList segmentsSplited;
368#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
369 segmentsSplited =segment.split(QRegularExpression(separator), QString::SkipEmptyParts);
370#else
371 segmentsSplited =segment.split(QRegularExpression(separator), Qt::SkipEmptyParts);
372#endif
373 return segmentsSplited;
374}
375
376LinguisticGraphVertex ConllHandler::getLimaTokenId(int conllTokenId, int sentenceI, LimaConllTokenIdMapping* limaConllMapping)
377{
379 std::map< int,std::map< int,LinguisticGraphVertex>>::iterator limaConllMappingIt;
380 limaConllMappingIt=limaConllMapping->find(sentenceI);
381 if (limaConllMappingIt == limaConllMapping->end())
382 {
383 LERROR << "Sentence " << sentenceI << " not found";
384 return 0;
385 }
386 std::map< int,LinguisticGraphVertex> limaConllId=(*limaConllMappingIt).second;
387 std::map< int,LinguisticGraphVertex>::iterator limaConllIdIt=limaConllId.find(conllTokenId);
388 if (limaConllIdIt==limaConllId.end())
389 {
390 LERROR << "Conll token id " << conllTokenId << " not found";
391 return 0;
392 }
393 LinguisticGraphVertex limaTokenId=limaConllIdIt->second;
394 return limaTokenId;
395}
396
397}
398}
399} // end namespace
400
This file is the main header file for the data related to annotation graphs.
A graph that stores any data (annotations) referencing primarily nodes of a text anlaysis.
#define LDEBUG
Definition LimaCommon.h:157
#define LERROR
Definition LimaCommon.h:161
A graph structure for linguistic analysis.
LinguisticGraph::vertex_descriptor LinguisticGraphVertex
#define SEMANTICANALYSISLOGINIT
#define NBCOLSINSRLBEFOREFRAME
#define CONLLTOKENSEPARATOR
#define CONLLFIELDSEPARATOR
#define SEMANTICROLELABELINGLOADER_CLASSID
Defines a Factory to create Object of type Base.
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
return a message when a 'param' was not found
Manage initialization of InitializableObjects using configuration module and parameters.
const InitializationParameters & getInitializationParameters() const
get Initialization Parameters
void init(Common::XMLConfigurationFiles::GroupConfigurationStructure &unitConfiguration, Manager *manager) override
initialize with parameters from configuration file.
QString getInputFile(AnalysisContent &analysis) const
An AnalysisData containing a LinguisticGraph with a language and an id.
LimaStatusCode process(AnalysisContent &analysis) const override
Process on data in analysisContent.
void init(Common::XMLConfigurationFiles::GroupConfigurationStructure &unitConfiguration, Manager *manager) override
initialize with parameters from configuration file.
AnnotationGraph::edge_descriptor AnnotationGraphEdge
AnnotationGraph::vertex_descriptor AnnotationGraphVertex
SimpleFactory< MediaProcessUnit, SemanticRoleLabelingLoader > SemanticRoleLabelingFactory(SEMANTICROLELABELINGLOADER_CLASSID)
NAUTITIA.
LimaStatusCode
Definition LimaCommon.h:236
@ CANNOT_OPEN_FILE_ERROR
Definition LimaCommon.h:239
@ SUCCESS_ID
Definition LimaCommon.h:237
@ MISSING_DATA
Definition LimaCommon.h:243
QString LimaString
Definition LimaString.h:33
STL namespace.
bool extractSemanticInformation(int sentenceIndex, LimaConllTokenIdMapping *limaConllMapping, const QString &sentence)
extract semantic annotations associated to token
LinguisticGraphVertex getLimaTokenId(int conllTokenId, int sentenceIndex, LimaConllTokenIdMapping *limaConllMapping)
get the lima token id matching any conll token one from the same text
QStringList splitSegment(const QString &segment, QRegularExpression separator)
split a text into different types segments
ConllHandler(MediaId language, AnalysisContent &analysis, LinguisticAnalysisStructure::AnalysisGraph *graph)
QVector< std::vector< std::pair< LinguisticGraphVertex, QString > > > m_semanticRoles
QVector< QPair< LinguisticGraphVertex, QString > > m_verbalClasses