1
2 '''
3 @author: David Vilares
4 '''
5 import codecs
6 import os
7 from miopia.analyzer.Analyzer import Analyzer
8 from miopia.util.exceptions.UnknownSOException import UnknownSOException
9 from miopia.analyzer.SentimentInfo import SentimentInfo
10 from miopia.analyzer.NegationInfo import NegationInfo
11 from miopia.analyzer.NegationRules import NegationRules
12 from miopia.analyzer.SemanticCategory import SemanticCategory
13 from miopia.parser.SentimentDependencyGraph import SentimentDependencyGraphNodeKeys
14 from miopia.preparator.LexicalSentimentInfo import LexicalValenceShifter
15
17 """
18 Instances of L{SentimentAnalyzer} evaluates
19 L{SentimentDependencyGraph}'s of a text, returning a summary in a L{SentimentInfo} object
20 """
21
22
23 - def __init__(self, parser, dictionaries,conf,
24 preprocessor, lexical_processor):
25 """
26 @param parser: An instance of L{Parser}
27 @param dictionaries: An instance of L{Dictionary}
28 @param conf: An instance of L{AnalyzerConfiguration}
29 @param preprocessor: An instance of L{PreProcessor}
30 @param lexical_processor: An instance of L{LexicalProcessor}
31 """
32 self._conf = conf
33 self._sentence_lsi = None
34
35 self._visit_functions_dict = {SemanticCategory.NOUN: self._visit_noun,
36 SemanticCategory.ADJECTIVE: self._visit_adjective,
37 SemanticCategory.ADVERB: self._visit_adverb,
38 SemanticCategory.VERB: self._visit_verb,
39 SemanticCategory.INTENSIFIER: self._visit_intensifier,
40 SemanticCategory.SUBORDINATE_ADVERSATIVE: self._visit_adversative,
41 SemanticCategory.NEGATION: self._visit_negation,
42 SemanticCategory.NEGATION_WITHOUT: self._visit_without_negation,
43 SemanticCategory.EMOTICON: self._visit_emoticon,
44 SemanticCategory.OTHER: self._visit_other
45 }
46 super(SentimentAnalyzer,self).__init__(parser,dictionaries,preprocessor,lexical_processor)
47
48
63
64
65
67 """
68 @param dependency_graphs: A list of L{SentimentDependencyGraph}
69 @return: A tuple ([L{SentimentDependencyGraph}],L{SentimentInfo})
70 The first element is a list of the dependency graphs of the texts. Each
71 node contains their own L{src.miope.anayzer.SentimentInfo}. The second element is
72 SentimentInfo object containing the general information for the whole text
73 """
74 semantic_orientation, positive_words, negative_words = 0,0,0
75 number_intensifiers, length_text, number_words = 0,0,0
76 subjectivity = False
77 i = 0
78 for dg in dependency_graphs:
79
80 if lsi is None : self._sentence_lsi = None
81 try:
82 self._sentence_lsi = lsi.get_sentence_info(i+1)
83 except AttributeError:
84 self._sentence_lsi = None
85 root_node = dg.get_by_address(0)
86 self.evaluate(dg,root_node)
87 subjectivity = subjectivity or root_node[SentimentDependencyGraphNodeKeys.SUBJECTIVITY]
88 positive_words+= root_node[SentimentDependencyGraphNodeKeys.POSITIVE_WORDS]
89 negative_words+= root_node[SentimentDependencyGraphNodeKeys.NEGATIVE_WORDS]
90 number_intensifiers+= root_node[SentimentDependencyGraphNodeKeys.NUMBER_OF_INTENSIFIERS]
91 length_text+= root_node[SentimentDependencyGraphNodeKeys.LENGTH_TEXT]
92 number_words+= root_node[SentimentDependencyGraphNodeKeys.NUMBER_OF_WORDS]
93 if i >= len(dependency_graphs)-3:
94 semantic_orientation+= self._conf.get_final_sentences_weight()*root_node[SentimentDependencyGraphNodeKeys.SEMANTIC_ORIENTATION]
95 else:
96 semantic_orientation+= root_node[SentimentDependencyGraphNodeKeys.SEMANTIC_ORIENTATION]
97 i = i +1
98
99 return dependency_graphs,SentimentInfo (0.,semantic_orientation,
100 subjectivity,positive_words,
101 negative_words, number_intensifiers,
102 length_text, number_words)
103
104
106 """
107 It analyzes a file in ConLL-X format
108 @todo: param lsi not integrated yet.
109 @param file_path: The path to the ConLL file
110 @param **kwargs: Optional key 'lsi' (L{LexicalSentimentInfo})
111 @return A tuple ([L{SentimentDependencyGraph}],L{SentimentInfo})
112 """
113 try:
114 lsi=kwargs['lsi']
115 except KeyError:
116 lsi = None
117 dependency_graphs = self._parser.parse_from_conll(file_path)
118 return self._analyze_graphs(dependency_graphs, lsi)
119
120
121 - def analyze_dir(self,dir_path,input_encoding='utf-8'):
122 """
123 It analyzes a directory of plain texts
124 @param dir_path: Path to the directory of plain files to be analysed
125 @param input_encoding: Encoding of the texts inside the directory
126 @return A list of tuples (text_id,([L{SentimentDependencyGraph}],L{SentimentInfo}))
127 """
128 list_of_tagged_sentences = []
129 list_id_and_linguistic_info = []
130 dict_lsi = {}
131 files = os.listdir(dir_path)
132 for file_id in files:
133 text = codecs.open(dir_path+os.sep+file_id,encoding=input_encoding).read()
134 tagged_sentences, lsi = self._preanalyze(text)
135 list_of_tagged_sentences.append((file_id,tagged_sentences))
136 dict_lsi[file_id] = lsi
137
138 files_parsed = self._parser.parse_dir(list_of_tagged_sentences)
139 for file_id,dependency_graphs in files_parsed:
140 list_id_and_linguistic_info.append((file_id,
141 self._analyze_graphs(dependency_graphs,
142 dict_lsi[file_id])[1]))
143 return list_id_and_linguistic_info
144
145
147 raise NotImplementedError
148
150 """
151 @param text: The string to be analysed.. Use unicode
152 @return A tuple ([L{SentimentDependencyGraph}],L{SentimentInfo})
153 """
154 tagged_sentences, lsi = self._preanalyze(text)
155 dependency_graphs = self._parser.parse(tagged_sentences)
156 return self._analyze_graphs(dependency_graphs, lsi)
157
158
160 """
161 It analyzes a plain file
162 @param file_path: The path to the input plain file to be analysed
163 @param input_encoding: The encoding of the file
164 @return A tuple ([L{SentimentDependencyGraph}],L{SentimentInfo})
165 """
166 f = codecs.open(file_path,encoding=input_encoding)
167 text = f.read()
168 tagged_sentences, lsi = self._preanalyze(text)
169 dependency_graphs = self._parser.parse(tagged_sentences)
170 f.close()
171 return self._analyze_graphs(dependency_graphs, lsi)
172
173
174
175
177 """
178 This method analyzes recursively an instance of a L{SentimentDependencyGraph}
179 @param graph: A L{SentimentDependencyGraph} object
180 @param node: A node of a L{SentimentDependencyGraph}
181 @return: A L{SentimentInfo}
182 """
183 if graph.is_leaf(node):
184 sentiment_info = self.get_sentiment_info(graph,node)
185 self.add_sentiment_info_to_node(node, sentiment_info)
186 return sentiment_info
187 else:
188 semantic_category = self.get_semantic_category(graph,node)
189 f = self.visit_function(semantic_category)
190 return f(graph,node)
191
192
193
205
206
207
208
209
210
211
212
213
214
215
216
217
219 """
220 @param graph: A L{SentimentDependencyGraph} object
221 @param node: A node of the graph
222 @return: A instance of the L{SentimentInfo} with the sentiment info
223 of that node, considered in an isolated way.
224 """
225 lexical_category = graph.get_lexical_category(node)
226 semantic_category = self.get_semantic_category(graph, node)
227 word = graph.get_word(node)
228 len_word = (lambda node: len(word) if not graph.is_root_node(node) else 0)(node)
229 number_words = (lambda node: 1 if not graph.is_root_node(node) else 0)(node)
230 lemma = self._dictionaries.get_lemma(lexical_category,word)
231
232 pond = 1
233 semantic_orientation = 0
234
235
236 if self._sentence_lsi is not None:
237 try:
238 pond+=self._get_lexical_ponderation(self._sentence_lsi[graph.get_address(node)])
239 except KeyError:
240 pass
241
242 if graph.is_intensifier(node,self._dictionaries):
243 try:
244
245 return SentimentInfo(pond*self._dictionaries.get_semantic_orientation(lemma,semantic_category),
246 semantic_orientation, False,0,0,1,len_word,number_words)
247 except UnknownSOException:
248 return SentimentInfo(0,semantic_orientation, False,0,0,0,len_word,number_words)
249 else:
250 try:
251 pond+= 0.2
252 semantic_orientation = self._dictionaries.get_semantic_orientation(lemma,semantic_category)*pond
253 return SentimentInfo(0, semantic_orientation ,True,
254 int(semantic_orientation>0),
255 int(semantic_orientation<0),
256 0,len_word,number_words)
257 except UnknownSOException:
258 return SentimentInfo(0,semantic_orientation,False,0,0,0,len_word,number_words)
259
261 """
262 @param semantic_category: A value of L{SemanticCategory}
263 @return: An specific visit function according the semantic category of the word
264 """
265
266 return self._visit_functions_dict[semantic_category]
267
268
270 """
271 It aggregates the L{SentimentInfo} of a list of children nodes.
272 @param graph: An instance of a L{SentimentDependencyGraph}
273 @param children: A list of id's of the node children. Id's are integers.
274 @return: A L{SentimentInfo} object with the aggregated
275 sentiment info for the children nodes
276 """
277 semantic_orientation_children, intensification = 0,0
278 positive_words, negative_words = 0,0
279 number_intensifiers, length_text, number_words =0,0,0
280 subjectivity = False
281
282 for child in children:
283 child_node = graph.get_by_address(child)
284 self.evaluate(graph,child_node)
285 positive_words+= child_node[SentimentDependencyGraphNodeKeys.POSITIVE_WORDS]
286 negative_words+= child_node[SentimentDependencyGraphNodeKeys.NEGATIVE_WORDS]
287 number_intensifiers+= child_node[SentimentDependencyGraphNodeKeys.NUMBER_OF_INTENSIFIERS]
288 length_text+= child_node[SentimentDependencyGraphNodeKeys.LENGTH_TEXT]
289 subjectivity = subjectivity or child_node[SentimentDependencyGraphNodeKeys.SUBJECTIVITY]
290 number_words+= child_node[SentimentDependencyGraphNodeKeys.NUMBER_OF_WORDS]
291 intensification+= child_node[SentimentDependencyGraphNodeKeys.INTENSIFICATION]
292 semantic_orientation_children+= child_node[SentimentDependencyGraphNodeKeys.SEMANTIC_ORIENTATION]
293
294 return SentimentInfo(intensification, semantic_orientation_children,
295 subjectivity, positive_words,negative_words,
296 number_intensifiers,length_text,number_words)
297
298
299
301 """
302 The default function for joining the semantic orientation of two
303 L{src.miope.analyzer.SentimentInfo} objects.
304 @param parent: The L{SentimentInfo} object which contains the semantic info information of a parent node.
305 @param children: The L{SentimentInfo} object which contains the semantic info information of their children.
306 """
307
308 return (1+parent.get_int() + children.get_int())*parent.get_so() + children.get_so()
309
311 """
312 The default function for joining the semantic orientation of two
313 L{src.miope.analyzer.SentimentInfo} objects.
314 @param parent: The L{SentimentInfo} object which contains the semantic info information of a parent node.
315 @param children: The L{SentimentInfo} object which contains the semantic info information of their children.
316 """
317 return parent.get_int() + children.get_int()
318
320 """
321 It swaps the positive and negative words of a
322 L{SentimentInfo} object.
323 @param sentiment_info: The L{SentimentInfo} object
324 @return: The swapped L{SentimentInfo} object
325 """
326 aux_pos = sentiment_info.get_pos_words()
327 aux_neg = sentiment_info.get_neg_words()
328 sentiment_info.set_neg_words(aux_pos)
329 sentiment_info.set_pos_words(aux_neg)
330 return sentiment_info
331
332
333 - def _join_sentiment_info(self,parent, children,
334 f_join_semantic_orientation,
335 f_join_intensification = None):
336 """
337 @param parent: The parent L{SentimentInfo} object
338 @param children: The joined L{SentimentInfo} object of the children
339 @param f_join_semantic_orientation: A function detailing how to join
340 the semantic orientation of the parent and their children
341 """
342
343 if f_join_intensification is None:
344 intensification = 0.
345 else:
346 intensification = f_join_intensification(parent,children)
347 semantic_orientation = f_join_semantic_orientation(parent, children)
348 subjectivity = parent.get_subjectivity() or children.get_subjectivity()
349 positive_words = parent.get_pos_words() + children.get_pos_words()
350 negative_words = parent.get_neg_words() + children.get_neg_words()
351 number_intensifiers = (parent.get_number_intensifiers()
352 + children.get_number_intensifiers())
353 length_text = parent.get_length_text() + children.get_length_text()
354 number_words = parent.get_number_words() + children.get_number_words()
355 return SentimentInfo(intensification, semantic_orientation,
356 subjectivity, positive_words, negative_words,
357 number_intensifiers, length_text, number_words)
358
359
361 """
362 This function processes a noun node and realizes
363 the recursive calls to their children.
364 @param graph: L{SentimentDependencyGraph}
365 @param node: A noun node of the graph
366 @return A L{SentimentInfo}. It contains
367 the joined sentiment info of the noun node and their children.
368 """
369 node_sentiment_info = self.get_sentiment_info(graph,node)
370 children = graph.get_deps(node)
371 children_sentiment_info = self._compute_children(graph, children)
372 sentiment_info = self._join_sentiment_info(node_sentiment_info,
373 children_sentiment_info,
374 self._default_join_semantic_orientation)
375 self.add_sentiment_info_to_node(node, sentiment_info)
376 return sentiment_info
377
378
380 """
381 This function processes an adjective node and realizes
382 the recursive calls to their children.
383 @param graph: L{SentimentDependencyGraph}
384 @param node: A adjective node of the graph
385 @return A L{SentimentInfo}. It contains
386 the joined sentiment info of the adjective node and their children.
387 """
388 node_sentiment_info = self.get_sentiment_info(graph,node)
389 children = graph.get_deps(node)
390 children_sentiment_info = self._compute_children(graph, children)
391 sentiment_info = self._join_sentiment_info(node_sentiment_info,
392 children_sentiment_info,
393 self._default_join_semantic_orientation)
394 self.add_sentiment_info_to_node(node, sentiment_info)
395 return sentiment_info
396
397
399 """
400 This function processes a verb node and realizes
401 the recursive calls to their children.
402 @param graph: L{SentimentDependencyGraph}
403 @param node: A verb node of the graph
404 @return A L{SentimentInfo}. It contains
405 the joined sentiment info of the verb node and their children.
406 """
407 node_sentiment_info = self.get_sentiment_info(graph,node)
408 children = graph.get_deps(node)
409 children_sentiment_info = self._compute_children(graph, children)
410 sentiment_info = self._join_sentiment_info(node_sentiment_info,
411 children_sentiment_info,
412 self._default_join_semantic_orientation)
413 self.add_sentiment_info_to_node(node, sentiment_info)
414 return sentiment_info
415
417 """
418 This function processes an adverb node and realizes
419 the recursive calls to their children.
420 @param graph: L{SentimentDependencyGraph}
421 @param node: An adverb node of the graph
422 @return A L{SentimentInfo}. It contains
423 the joined sentiment info of the adverb node and their children.
424 """
425 node_sentiment_info = self.get_sentiment_info(graph,node)
426 children = graph.get_deps(node)
427 children_sentiment_info = self._compute_children(graph, children)
428 sentiment_info = self._join_sentiment_info(node_sentiment_info,
429 children_sentiment_info,
430 self._default_join_semantic_orientation)
431
432 self.add_sentiment_info_to_node(node, sentiment_info)
433 return sentiment_info
434
435
437 """
438 This function processes an intensfier node and realizes
439 the recursive calls to their children.
440 @param graph: L{SentimentDependencyGraph}
441 @param node: An intensifier node of the graph
442 @return A L{SentimentInfo}. It contains
443 the joined sentiment info of the intensifier node and their children.
444 """
445 node_sentiment_info = self.get_sentiment_info(graph,node)
446 children = graph.get_deps(node)
447 children_sentiment_info = self._compute_children(graph, children)
448 sentiment_info = self._join_sentiment_info(node_sentiment_info,
449 children_sentiment_info,
450 self._default_join_semantic_orientation,
451 self._default_join_intensification)
452 self.add_sentiment_info_to_node(node, sentiment_info)
453 return sentiment_info
454
455
456
458 """
459 This function processes an artificial adversative node and realizes
460 the recursive calls to their children.
461 @param graph: L{SentimentDependencyGraph}
462 @param node: An artificial adversative node of the graph
463 @return A L{SentimentInfo}. It contains
464 the joined sentiment info of the adversative node and their children.
465 """
466
467 nodes_before_adversative = []
468 nodes_after_adversative = []
469
470
471
472 def is_restrict_adversative(tag):
473 """
474 It determines if the artificial adversative node is
475 restrictive
476 """
477 return tag.split(":")[1].split("@")[0] == 'restrict'
478
479
480 children = graph.get_deps(node)
481 tag = graph.get_tag(node)
482 adversative_id = graph._get_adversative_id(node)
483 for c in children:
484 if c < adversative_id: nodes_before_adversative.append(c)
485 else: nodes_after_adversative.append(c)
486 nodes_before_sentiment_info = self._compute_children(graph,
487 nodes_before_adversative)
488 nodes_after_sentiment_info = self._compute_children(graph, nodes_after_adversative)
489
490 if is_restrict_adversative(tag):
491 adv_pond = self._conf.get_restrictive_adv_weight()
492 main_pond = self._conf.get_restrictive_main_weight()
493 else:
494 adv_pond = 0.
495 main_pond = 1.
496
497 join_function = lambda b,a : adv_pond*b.get_so()+main_pond*a.get_so()
498 sentiment_info = self._join_sentiment_info(nodes_before_sentiment_info,
499 nodes_after_sentiment_info,
500 join_function,
501 self._default_join_intensification)
502 self.add_sentiment_info_to_node(node, sentiment_info)
503 return sentiment_info
504
505
506
508 """
509 A function to shift the semantic orientation of a 'without' semantic dependent words
510 @param semantic_orientation: An integer
511 @return The shifted semantic orientation
512 """
513 return (semantic_orientation + self._conf.get_without_shift()
514 * (-1 if semantic_orientation >= 0 else 1))
515
517 """
518 A function to shift the semantic orientation of a negation semantic dependent words
519 @param semantic_orientation: An integer
520 @return The shifted semantic orientation
521 """
522 return (semantic_orientation + self._conf.get_neg_shift()
523 * (-1 if semantic_orientation >= 0 else 1))
524
526 """
527 It determines if the node is an adjunct branch
528 @param node: A node of L{SentimentDependencyGraph}
529 @return: A boolean.
530 """
531 list_adjunct = ['cc','creg']
532 return graph.get_rel(node) in list_adjunct
533
535 """
536 It determines if a node is subjective
537 @param graph: An instance of L{SentimentDependencyGraph}
538 @param node: A node of the graph
539 @return: A boolean
540 """
541 return self.get_sentiment_info(graph,node).get_subjectivity()
542
545 """
546 @param graph: An instance of L{SentimentDependencyGraph}
547 @param children_nodes: A list of the children_nodes
548 @param inclusion_function: A function to determine if a node should
549 be negated or not.
550 @param include_all_branches: A boolean. True: It negates all the nodes
551 that match the inclusion function. False: It only includes the
552 first node that match the inclusion function
553 @return A tuple ([negated_nodes],[non_negated_nodes])
554 """
555 negated_branches = []
556 other_branches = []
557 include_branch = True
558 for child in children_nodes:
559 if inclusion_function(graph,child) and include_branch:
560 negated_branches.append(graph.get_address(child))
561 include_branch = include_all_branches
562 else:
563 other_branches.append(graph.get_address(child))
564 return negated_branches, other_branches
565
566
567
569 """
570 This function processes a 'without' node and realizes
571 the recursive calls to their children.
572 @param graph: An instance of L{SentimentDependencyGraph}
573 @param node: An artificial without node of the graph
574 @return A L{SentimentInfo}. It contains
575 the joined sentiment info of the without node and their children.
576 """
577
578 node_sentiment_info = self.get_sentiment_info(graph,node)
579 children = graph.get_deps(node)
580 children_sentiment_info = self._compute_children(graph, children)
581 children_sentiment_info = self._swap_pos_neg_words(children_sentiment_info)
582 join_function_semantic_orientation = lambda p,c: self._shift_negation_without(c.get_so())*(p.get_subjectivity()*
583 c.get_subjectivity())
584 sentiment_info = self._join_sentiment_info(node_sentiment_info,
585 children_sentiment_info,
586 join_function_semantic_orientation,
587 self._default_join_intensification)
588 self.add_sentiment_info_to_node(node, sentiment_info)
589 return sentiment_info
590
591
593 """
594 This method analyzes the children of a node and determines which branches must be negated and
595 which not.
596 @param graph: An instance of L{SentimentDependencyGraph}
597 @param node: A node of the graph
598 @return: A L{NegationInfo} object
599 """
600 children_id = graph.get_deps(node)
601
602 if self.is_subjective_node(graph,node):
603 return NegationInfo([],children_id, NegationRules.verb)
604 children_nodes = map(graph.get_by_address,children_id)
605
606 neg_branch, other_branch = self._negated_and_other_branches(graph,children_nodes,
607 lambda graph,child: graph.get_rel(child) in ['cd','atr','cpred'],
608 True)
609 if neg_branch != []:
610 return NegationInfo(neg_branch,other_branch,NegationRules.branch)
611
612 neg_branch, other_branch = self._negated_and_other_branches(graph,children_nodes,
613 self._is_adjunct_node, False)
614 if neg_branch != []:
615 return NegationInfo(neg_branch,other_branch,NegationRules.branch)
616
617 return NegationInfo(children_id,[],NegationRules.default)
618
619
638
658
660 """
661 This function negates the negated branches specified in kwargs['negated_branches'].
662 The branches inside the parameter kwargs['other_branches'] are not negated
663 @param graph: An instance of L{SentimentDependencyGraph}
664 @param node: A node of the graph
665 @param **kwargs: Keys ={'negated_branches','other_branches'}.
666 The parameter 'negated_branches' represent a list of nodes
667 at the same level are negated. The parameter 'other_branches'
668 represent a list of node at the same level that are not negated.
669 """
670 node_sentiment_info = self.get_sentiment_info(graph,node)
671 negated_sentiment_info = self._compute_children(graph,
672 kwargs['negated_branches'])
673 negated_sentiment_info = self._swap_pos_neg_words(negated_sentiment_info)
674 other_sentiment_info = self._compute_children(graph,
675 kwargs['other_branches'])
676 join_function = lambda n,o: self._shift_negation(n.get_so())+o.get_so()
677 joined_sentiment_info = self._join_sentiment_info(negated_sentiment_info,
678 other_sentiment_info,
679 join_function,
680 self._default_join_intensification
681 )
682 final_sentiment_info = self._join_sentiment_info(node_sentiment_info,
683 joined_sentiment_info,
684 self._default_join_semantic_orientation,
685 self._default_join_intensification)
686 self.add_sentiment_info_to_node(node, final_sentiment_info)
687 return final_sentiment_info
688
689
690
700
701
702
704 """
705 This function processes a negation node and realizes
706 the recursive calls to their children.
707 @param graph: L{SentimentDependencyGraph}
708 @param node: A negation node of the graph
709 @return A L{SentimentInfo}. It has computed
710 the joined sentiment info of the negation node and their children.
711 """
712 scope_of_negation = self._scope_negation_detection(graph, node)
713 neg_branches = scope_of_negation.get_neg_branches()
714 non_negated_branches = scope_of_negation.get_other_branches()
715 type_delimiter = scope_of_negation.get_delimiter()
716 return self._negation_function(type_delimiter)(graph,node,negated_branches=neg_branches,
717 other_branches=non_negated_branches)
718
720 """
721 This function processes a emoticon node and realizes
722 the recursive calls to their children.
723 @param graph: L{SentimentDependencyGraph}
724 @param node: A emoticon node of the graph
725 @return A L{SentimentInfo}. It has computed
726 the joined sentiment info of the emoticon node and their children.
727 """
728 node_sentiment_info = self.get_sentiment_info(graph,node)
729 children = graph.get_deps(node)
730 children_sentiment_info = self._compute_children(graph, children)
731 sentiment_info = self._join_sentiment_info(node_sentiment_info,
732 children_sentiment_info,
733 self._default_join_semantic_orientation,
734 self._default_join_intensification)
735 self.add_sentiment_info_to_node(node, sentiment_info)
736 return sentiment_info
737
738
740 """
741 This function processes an other node and realizes
742 the recursive calls to their children.
743 @param graph: L{SentimentDependencyGraph}
744 @param node: An other node of the graph
745 @return A L{SentimentInfo}. It has computed
746 the joined sentiment info of the 'other' node and their children.
747 """
748 node_sentiment_info = self.get_sentiment_info(graph,node)
749 children = graph.get_deps(node)
750 children_sentiment_info = self._compute_children(graph, children)
751
752
753
754 join_function = self._default_join_semantic_orientation
755 sentiment_info = self._join_sentiment_info(node_sentiment_info,
756 children_sentiment_info,
757 join_function,
758 self._default_join_intensification)
759 self.add_sentiment_info_to_node(node, sentiment_info)
760 return sentiment_info
761