Commit 30cb1371e39accf566d309905b7938fb4065b16c

Authored by Erickson Silva
2 parents c7bf37c8 1d486c40
Exists in master

Merge branch 'devel'

data/preposicoes.csv
@@ -14,4 +14,6 @@ pela @@ -14,4 +14,6 @@ pela
14 pelos 14 pelos
15 pelas 15 pelas
16 ao 16 ao
17 -aos  
18 \ No newline at end of file 17 \ No newline at end of file
  18 +aos
  19 +às
  20 +a
19 \ No newline at end of file 21 \ No newline at end of file
install/linux/install.sh
@@ -30,7 +30,7 @@ read -r -p "Deseja fazer o download das dependências? [Y/n] " response @@ -30,7 +30,7 @@ read -r -p "Deseja fazer o download das dependências? [Y/n] " response
30 echo -e "# Instalando dependências...\n" 30 echo -e "# Instalando dependências...\n"
31 sudo apt-get update 31 sudo apt-get update
32 sudo apt-get install -y python-dev python-setuptools python-pip python-yaml python-numpy python-matplotlib 32 sudo apt-get install -y python-dev python-setuptools python-pip python-yaml python-numpy python-matplotlib
33 - sudo pip install nltk nltk_tgrep --upgrade 33 + sudo pip install nltk==3.0.5 nltk_tgrep --upgrade
34 34
35 fi 35 fi
36 36
src/AplicaRegras.py
@@ -6,7 +6,6 @@ @@ -6,7 +6,6 @@
6 6
7 #LAViD - Laboratório de Aplicações de Vídeo Digital 7 #LAViD - Laboratório de Aplicações de Vídeo Digital
8 8
9 -import platform  
10 import re 9 import re
11 import xml.etree.ElementTree as ET 10 import xml.etree.ElementTree as ET
12 from os.path import expanduser 11 from os.path import expanduser
@@ -38,12 +37,10 @@ class AplicaRegras(object): @@ -38,12 +37,10 @@ class AplicaRegras(object):
38 # Gera arvore a partir do arquivos regras.xml 37 # Gera arvore a partir do arquivos regras.xml
39 def get_root(self): 38 def get_root(self):
40 '''Verifica qual o SO e gera o path de onde se encontra o diretório data. 39 '''Verifica qual o SO e gera o path de onde se encontra o diretório data.
41 - '''  
42 - if "TRANSLATE_DATA" in environ: 40 + '''
  41 + if "TRANSLATE_DATA" in environ:
43 arq_regras = path.join(environ.get("TRANSLATE_DATA"), "regras.xml") 42 arq_regras = path.join(environ.get("TRANSLATE_DATA"), "regras.xml")
44 return ET.parse(arq_regras).getroot() 43 return ET.parse(arq_regras).getroot()
45 - elif platform.system() == 'Windows':  
46 - return ET.parse(environ.get("HOMEDRIVE")+'\\vlibras-libs\\vlibras-translate\data\\regras.xml').getroot()  
47 return ET.parse(expanduser("~")+'/vlibras-translate/data/regras.xml').getroot() 44 return ET.parse(expanduser("~")+'/vlibras-translate/data/regras.xml').getroot()
48 45
49 # Aplica regras morfológicas apartir do arquivo regras.xml 46 # Aplica regras morfológicas apartir do arquivo regras.xml
@@ -264,8 +261,15 @@ class AplicaRegras(object): @@ -264,8 +261,15 @@ class AplicaRegras(object):
264 # EU FELIZ PASSADO -> EU FELIZ 261 # EU FELIZ PASSADO -> EU FELIZ
265 if morfo[i] is not None and morfo[i][1] == "NTK" and morfo[i][0]: 262 if morfo[i] is not None and morfo[i][1] == "NTK" and morfo[i][0]:
266 new_node = self.gerar_no(morfo[i]) 263 new_node = self.gerar_no(morfo[i])
267 - arvore[lista_pos_arv[i-1][:-3]].insert(2, new_node)  
268 - #arvore[lista_pos_arv[i-1][:-2]].insert(2, new_node) 264 +
  265 + #arvore[lista_pos_arv[i-1][:-3]].insert(2, new_node)
  266 + #arvore[lista_pos_arv[i-1][:-3]].insert(2, new_node)
  267 +
  268 + if str(arvore[lista_pos_arv[i-1][:-3]]).count('(') > 7:
  269 + arvore[lista_pos_arv[i-1][:-2]].insert(2, new_node)
  270 + else:
  271 + arvore[lista_pos_arv[i-1][:-3]].insert(2, new_node)
  272 +
269 try: 273 try:
270 lista_pos_arv.insert(i,lista_pos_arv[i]) 274 lista_pos_arv.insert(i,lista_pos_arv[i])
271 except: 275 except:
@@ -399,9 +403,14 @@ class AplicaRegras(object): @@ -399,9 +403,14 @@ class AplicaRegras(object):
399 tag = it.get_ticket() 403 tag = it.get_ticket()
400 404
401 if tag == "NUM": 405 if tag == "NUM":
  406 + try:
  407 + num_romano = roman_to_int(it.get_word().encode('utf-8'))
  408 + lista_simplificada[it.get_count()] = [num_romano.decode('utf-8'), 'NUM-R']
  409 + except:
  410 + pass
402 num = True 411 num = True
403 412
404 - if tag[-2:] == "-P" and self.verificar_excecao_plural(it.get_word()): 413 + if tag != "NPR-P" and tag[-2:] == "-P" or tag[-2:] == "_P" and self.verificar_excecao_plural(it.get_word()):
405 singular = self.analisar_plural(it.get_word()) 414 singular = self.analisar_plural(it.get_word())
406 lista_simplificada[it.get_count()][0] = singular 415 lista_simplificada[it.get_count()][0] = singular
407 416
@@ -438,7 +447,7 @@ class AplicaRegras(object): @@ -438,7 +447,7 @@ class AplicaRegras(object):
438 return token[:-2]+"l" 447 return token[:-2]+"l"
439 return token 448 return token
440 elif(token[-1] == "s"): 449 elif(token[-1] == "s"):
441 - #TODO: Palavras paroxítonas ou proparoxítonas terminadas em S. Ex: lápis, vírus, tagênis, ônibus, etc 450 + #TODO: Palavras paroxítonas ou proparoxítonas terminadas em S. Ex: lápis, vírus, tagênis, ônibus, etc
442 return token[:-1] 451 return token[:-1]
443 else: 452 else:
444 return token 453 return token
src/AplicaSinonimos.py
@@ -27,26 +27,10 @@ class AplicaSinonimos(object): @@ -27,26 +27,10 @@ class AplicaSinonimos(object):
27 '''Percorre a lista fazendo a substituição pelos sinonimos. 27 '''Percorre a lista fazendo a substituição pelos sinonimos.
28 ''' 28 '''
29 lista_corrigida = [] 29 lista_corrigida = []
30 - palavras_compostas = self.carregar_palavras_compostas()  
31 for tupla in lista_anotada: 30 for tupla in lista_anotada:
32 sinonimo = self.verificar_sinonimo(tupla[0]) 31 sinonimo = self.verificar_sinonimo(tupla[0])
33 - try:  
34 - token_composto_2 = lista_corrigida[-1] + "_" + sinonimo  
35 - token_composto_3 = lista_corrigida[-2] + "_" + lista_corrigida[-1] + "_" + sinonimo  
36 - if token_composto_2.upper() in palavras_compostas:  
37 - lista_corrigida[-1] = token_composto_2  
38 - elif token_composto_3.upper() in palavras_compostas:  
39 - lista_corrigida.pop()  
40 - lista_corrigida[-1] = token_composto_3  
41 - else:  
42 - lista_corrigida.append(sinonimo)  
43 - except IndexError:  
44 - lista_corrigida.append(sinonimo)  
45 -  
46 - try:  
47 - return " ".join(lista_corrigida)  
48 - except:  
49 - return " ".join([str(x[0]) for x in lista_anotada]) 32 + lista_corrigida.append(sinonimo)
  33 + return self.verificar_palavra_composta(lista_corrigida)
50 34
51 # Verifica se há sinonimo do token 35 # Verifica se há sinonimo do token
52 def verificar_sinonimo(self, token): 36 def verificar_sinonimo(self, token):
@@ -56,13 +40,23 @@ class AplicaSinonimos(object): @@ -56,13 +40,23 @@ class AplicaSinonimos(object):
56 return self.dicionarios.get_sinonimo(token) 40 return self.dicionarios.get_sinonimo(token)
57 return token 41 return token
58 42
  43 + def verificar_palavra_composta(self, lista):
  44 + palavras_compostas = self.carregar_palavras_compostas()
  45 + try:
  46 + sentenca_corrigida = "_".join(lista).upper()
  47 + except:
  48 + sentenca_corrigida = "_".join([str(x[0]) for x in lista]).upper()
  49 +
  50 + for p in palavras_compostas:
  51 + if p in sentenca_corrigida:
  52 + sentenca_corrigida = sentenca_corrigida.replace(p, p.replace("_", "#*#"))
  53 + return sentenca_corrigida.replace("_", " ").replace("#*#", "_")
  54 +
59 def carregar_palavras_compostas(self): 55 def carregar_palavras_compostas(self):
60 path = self.localizar_arquivo_palavras_compostas() 56 path = self.localizar_arquivo_palavras_compostas()
61 return set(open(path).read().decode('utf-8').split()) 57 return set(open(path).read().decode('utf-8').split())
62 58
63 def localizar_arquivo_palavras_compostas(self): 59 def localizar_arquivo_palavras_compostas(self):
64 - if platform.system() == 'Windows':  
65 - return environ.get("HOMEDRIVE")+'\\vlibras-libs\\vlibras-translate\data\\palavras_compostas.csv'  
66 - elif "TRANSLATE_DATA" in environ: 60 + if "TRANSLATE_DATA" in environ:
67 return path.join(environ.get("TRANSLATE_DATA"), "palavras_compostas.csv") 61 return path.join(environ.get("TRANSLATE_DATA"), "palavras_compostas.csv")
68 return expanduser("~")+'/vlibras-translate/data/palavras_compostas.csv' 62 return expanduser("~")+'/vlibras-translate/data/palavras_compostas.csv'
69 \ No newline at end of file 63 \ No newline at end of file
src/ClassificaSentencas.py 0 → 100644
@@ -0,0 +1,165 @@ @@ -0,0 +1,165 @@
  1 +#! /usr/bin/env python2.6
  2 +# -*- coding: utf-8 -*-
  3 +
  4 +#---------------------------------
  5 +
  6 +# Editado:
  7 +
  8 +#Autor: Erickson Silva
  9 +#Email: <erickson.silva@lavid.ufpb.br> <ericksonsilva@live.com>
  10 +
  11 +#LAViD - Laboratório de Aplicações de Vídeo Digital
  12 +
  13 +#---------------------------------
  14 +
  15 +
  16 +# Donatus Brazilian Portuguese Parser
  17 +#
  18 +# Copyright (C) 2010-2013 Leonel F. de Alencar
  19 +#
  20 +# Author: Leonel F. de Alencar <leonel.de.alencar@ufc.br>
  21 +# Homepage: <http://www.leonel.profusehost.net/>
  22 +#
  23 +# Project's URL: <http://sourceforge.net/projects/donatus/>
  24 +# For license information, see LICENSE.TXT
  25 +#
  26 +# $Id: alexp.py $
  27 +
  28 +"""Este módulo contém funções que permitem utilizar o Aelius para etiquetar uma sentença, construindo entradas lexicais com base nas etiquetas atribuídas às palavras da sentença. Essas entradas lexicais são integradas em uma gramática CFG dada, que é transformada em um parser, utilizado para gerar uma árvore de estrutura sintagmática da sentença.
  29 +"""
  30 +import re,nltk, time, random
  31 +from os.path import expanduser
  32 +from os import environ, path
  33 +from Aelius.Extras import carrega
  34 +from Aelius import AnotaCorpus, Toqueniza
  35 +from unicodedata import normalize
  36 +
  37 +
  38 +class ClassificaSentencas(object):
  39 +
  40 + def __init__(self):
  41 + self.sentenca_anotada = ""
  42 + self.sleep_times = [0.1,0.2]
  43 +
  44 + def toqueniza(self, s):
  45 + """Decodifica string utilizando utf-8, retornando uma lista de tokens em unicode.
  46 + """
  47 + regex = re.compile('[%s]' % re.escape('“”'))
  48 + regex2 = re.compile('[%s]' % re.escape('«»'))
  49 + try:
  50 + decodificada = regex2.sub('',regex.sub('"',s.replace("–", "-").replace("—", "-"))).decode("utf-8")
  51 + except:
  52 + decodificada = s.decode("utf-8")
  53 + return Toqueniza.TOK_PORT.tokenize(decodificada)
  54 +
  55 + def obter_classificacao_morfologica(self):
  56 + return self.sentenca_anotada
  57 +
  58 + def etiqueta_sentenca(self, s):
  59 + """Aplica um dos etiquetadores do Aelius na etiquetagem da sentença dada como lista de tokens.
  60 + """
  61 + etiquetador = carrega("AeliusHunPos")
  62 + anotada = AnotaCorpus.anota_sentencas([s],etiquetador,"hunpos")[0]
  63 + while (anotada[0][1] is None):
  64 + time.sleep(random.choice(sleep_times))
  65 + anotada = AnotaCorpus.anota_sentencas([s],etiquetador,"hunpos")[0]
  66 + regex = re.compile('[%s]' % re.escape('!"#&\'()*+,-./:;<=>?@[\\]^_`{|}~'))
  67 + tag_punctuation = [".",",","QT","("]
  68 + anotada_corrigida = []
  69 + for x in anotada:
  70 + if x[1] not in tag_punctuation:
  71 + if x[1] == "NUM":
  72 + try:
  73 + float(x[0].replace(',', '.'))
  74 + anotada_corrigida.append(x)
  75 + continue
  76 + except:
  77 + pass
  78 +
  79 + tupla = [regex.sub('',x[0]).lower(),x[1]]
  80 + if tupla[0] != "": anotada_corrigida.append(tupla)
  81 + else:
  82 + if x[0] == ".":
  83 + anotada_corrigida.append(["[ponto]".decode("utf-8"),"SPT"])
  84 + elif x[0] == "?":
  85 + anotada_corrigida.append(["[interrogacao]".decode("utf-8"),"SPT"])
  86 + elif x[0] == "!":
  87 + anotada_corrigida.append(["[exclamacao]".decode("utf-8"),"SPT"])
  88 + return anotada_corrigida
  89 +
  90 + def gera_entradas_lexicais(self, lista):
  91 + """Gera entradas lexicais no formato CFG do NLTK a partir de lista de pares constituídos de tokens e suas etiquetas.
  92 + """
  93 + entradas=[]
  94 + for e in lista:
  95 + # é necessário substituir símbolos como "-" e "+" do CHPTB
  96 + # que não são aceitos pelo NLTK como símbolos não terminais
  97 + c=re.sub(r"[-+]","_",e[1])
  98 + c=re.sub(r"\$","_S",c)
  99 + entradas.append("%s -> '%s'" % (c, self.remove_acento(e[0])))
  100 + return entradas
  101 +
  102 + def corrige_anotacao(self, lista):
  103 + """Esta função deverá corrigir alguns dos erros de anotação mais comuns do Aelius. No momento, apenas é corrigida VB-AN depois de TR.
  104 + """
  105 + i=1
  106 + while i < len(lista):
  107 + if lista[i][1] == "VB-AN" and lista[i-1][1].startswith("TR"):
  108 + lista[i]=(lista[i][0],"VB-PP")
  109 + i+=1
  110 +
  111 + def encontra_arquivo(self):
  112 + """Encontra arquivo na pasta vlibras-translate.
  113 + """
  114 + if "TRANSLATE_DATA" in environ:
  115 + return path.join(environ.get("TRANSLATE_DATA"), "cfg.syn.nltk")
  116 + return expanduser("~") + "/vlibras-translate/data/cfg.syn.nltk"
  117 +
  118 + def extrai_sintaxe(self):
  119 + """Extrai gramática armazenada em arquivo cujo caminho é definido relativamente ao diretório nltk_data.
  120 + """
  121 + arquivo = self.encontra_arquivo()
  122 + if arquivo:
  123 + f=open(arquivo,"rU")
  124 + sintaxe=f.read()
  125 + f.close()
  126 + return sintaxe
  127 + else:
  128 + print "Arquivo %s não encontrado em nenhum dos diretórios de dados do NLTK:\n%s" % (caminho,"\n".join(nltk.data.path))
  129 +
  130 + def analisa_sentenca(self, sentenca):
  131 + """Retorna lista de árvores de estrutura sintagmática para a sentença dada sob a forma de uma lista de tokens, com base na gramática CFG cujo caminho é especificado como segundo argumento da função. Esse caminho é relativo à pasta nltk_data da instalação local do NLTK. A partir da etiquetagem morfossintática da sentença são geradas entradas lexicais que passam a integrar a gramática CFG. O caminho da gramática e o parser gerado são armazenados como tupla na variável ANALISADORES.
  132 + """
  133 + parser = self.constroi_analisador(sentenca)
  134 + codificada=[]
  135 + for t in self.sentenca_anotada:
  136 + if t[1] != "SPT":
  137 + codificada.append(self.remove_acento(t[0]).encode("utf-8"))
  138 + trees=parser.parse_one(codificada)
  139 + return trees
  140 +
  141 + def constroi_analisador(self, s):
  142 + """Constrói analisador a partir de uma única sentença não anotada, dada como lista de tokens, e uma lista de regras sintáticas no formato CFG, armazenadas em arquivo. Esta função tem um bug, causado pela maneira como o Aelius etiqueta sentenças usando o módulo ProcessaNomesProprios: quando a sentença se inicia por paravra com inicial minúscula, essa palavra não é incorporada ao léxico, mas a versão com inicial maiúscula.
  143 + """
  144 + self.sentenca_anotada = self.etiqueta_sentenca(s)
  145 + self.corrige_anotacao(self.sentenca_anotada)
  146 + entradas = self.gera_entradas_lexicais(self.sentenca_anotada)
  147 + lexico="\n".join(entradas)
  148 + gramatica="%s\n%s" % (self.extrai_sintaxe().strip(),lexico)
  149 + cfg=nltk.CFG.fromstring(gramatica)
  150 + return nltk.ChartParser(cfg)
  151 +
  152 + def remove_acento(self, texto):
  153 + try:
  154 + return normalize('NFKD', texto.encode('utf-8').decode('utf-8')).encode('ASCII', 'ignore')
  155 + except:
  156 + return normalize('NFKD', texto.encode('iso-8859-1').decode('iso-8859-1')).encode('ASCII','ignore')
  157 +
  158 + def exibe_arvores(self, arvores):
  159 + """Função 'wrapper' para a função de exibição de árvores do NLTK"""
  160 + nltk.draw.draw_trees(*arvores)
  161 +
  162 + def iniciar_classificacao(self, sentenca):
  163 + tokens = self.toqueniza(sentenca)
  164 + tree = self.analisa_sentenca(tokens)
  165 + return tree
0 \ No newline at end of file 166 \ No newline at end of file
src/ConverteExtenso.py
@@ -25,7 +25,45 @@ ext = [{&quot;um&quot;:&quot;1&quot;, &quot;dois&quot;:&quot;2&quot;, &quot;tres&quot;:&quot;3&quot;, &quot;quatro&quot;:&quot;4&quot;, &quot;cinco&quot;:&quot;5&quot;, &quot;seis&quot;:&quot;6&quot;, @@ -25,7 +25,45 @@ ext = [{&quot;um&quot;:&quot;1&quot;, &quot;dois&quot;:&quot;2&quot;, &quot;tres&quot;:&quot;3&quot;, &quot;quatro&quot;:&quot;4&quot;, &quot;cinco&quot;:&quot;5&quot;, &quot;seis&quot;:&quot;6&quot;,
25 und = {"mil":1000, "milhao":1000000, "bilhao":1000000000, "trilhao":1000000000000} 25 und = {"mil":1000, "milhao":1000000, "bilhao":1000000000, "trilhao":1000000000000}
26 unds = {"mil":"000", "milhao":"000000","milhoes":"000000", "bilhao":"000000000","bilhoes":"000000000", "trilhao":"000000000000", "trilhoes":"000000000000"} 26 unds = {"mil":"000", "milhao":"000000","milhoes":"000000", "bilhao":"000000000","bilhoes":"000000000", "trilhao":"000000000000", "trilhoes":"000000000000"}
27 27
28 - 28 +def int_to_roman(input):
  29 + if not isinstance(input, type(1)):
  30 + raise TypeError, "expected integer, got %s" % type(input)
  31 + if not 0 < input < 4000:
  32 + raise ValueError, "Argument must be between 1 and 3999"
  33 + ints = (1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1)
  34 + nums = ('M', 'CM', 'D', 'CD','C', 'XC','L','XL','X','IX','V','IV','I')
  35 + result = []
  36 +
  37 + for i in range(len(ints)):
  38 + count = int(input / ints[i])
  39 + result.append(nums[i] * count)
  40 + input -= ints[i] * count
  41 + return ''.join(result)
  42 +
  43 +def roman_to_int(input):
  44 + if not isinstance(input, type("")):
  45 + raise TypeError, "expected string, got %s" % type(input)
  46 + input = input.upper( )
  47 + nums = {'M':1000,
  48 + 'D':500,
  49 + 'C':100,
  50 + 'L':50,
  51 + 'X':10,
  52 + 'V':5,
  53 + 'I':1}
  54 + sum = 0
  55 + for i in range(len(input)):
  56 + try:
  57 + value = nums[input[i]]
  58 + if i+1 < len(input) and nums[input[i+1]] > value:
  59 + sum -= value
  60 + else: sum += value
  61 + except KeyError:
  62 + raise ValueError, 'input is not a valid Roman numeral: %s' % input
  63 +
  64 + if int_to_roman(sum) == input: return str(sum)
  65 + else:
  66 + raise ValueError, 'input is not a valid Roman numeral: %s' % input
29 67
30 def oneDigit(x): 68 def oneDigit(x):
31 return ext[0][x] 69 return ext[0][x]
src/LerDicionarios.py
@@ -8,20 +8,20 @@ @@ -8,20 +8,20 @@
8 8
9 import os 9 import os
10 import csv 10 import csv
11 -import platform  
12 11
13 -class Singleton(object): 12 +class Singleton(type):
14 ''' Permite a criação de apenas uma instância da classe 13 ''' Permite a criação de apenas uma instância da classe
15 ''' 14 '''
  15 + _instances = {}
  16 + def __call__(cls, *args, **kwargs):
  17 + if cls not in cls._instances:
  18 + cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
  19 + return cls._instances[cls]
16 20
17 - def __new__(cls, *args, **kwargs):  
18 - if '_inst' not in vars(cls):  
19 - cls._inst = object.__new__(cls, *args, **kwargs)  
20 - return cls._inst  
21 -  
22 -class LerDicionarios(Singleton): 21 +class LerDicionarios(object):
23 '''Carrega todos os arquivos (dicionários) necessários para auxiliar durante o processo de tradução. 22 '''Carrega todos os arquivos (dicionários) necessários para auxiliar durante o processo de tradução.
24 ''' 23 '''
  24 + __metaclass__ = Singleton
25 25
26 def __init__(self): 26 def __init__(self):
27 self.path = self.get_path() 27 self.path = self.get_path()
@@ -37,31 +37,13 @@ class LerDicionarios(Singleton): @@ -37,31 +37,13 @@ class LerDicionarios(Singleton):
37 self.set_vb_ligacao = [] 37 self.set_vb_ligacao = []
38 self.dic_vb_muda_negacao = [] 38 self.dic_vb_muda_negacao = []
39 self.file = '' 39 self.file = ''
40 - self.carregar_dicionarios()  
41 40
42 def get_path(self): 41 def get_path(self):
43 '''Verifica qual o SO e gera o path de onde se encontra o diretório data. 42 '''Verifica qual o SO e gera o path de onde se encontra o diretório data.
44 ''' 43 '''
45 if "TRANSLATE_DATA" in os.environ: 44 if "TRANSLATE_DATA" in os.environ:
46 return os.environ.get("TRANSLATE_DATA") 45 return os.environ.get("TRANSLATE_DATA")
47 - elif platform.system() == 'Windows':  
48 - return os.environ.get("HOMEDRIVE") + "\\vlibras-libs\\vlibras-translate\data\\"  
49 - return os.path.expanduser("~") + "/vlibras-translate/data"  
50 -  
51 - def carregar_dicionarios(self):  
52 - '''Realiza a leitura dos arquivos e atribui à estruturas de dicionários e sets.  
53 - '''  
54 - self.carregar_excecoes_plural()  
55 - self.carregar_adverbios_intensidade()  
56 - self.carregar_adverbios_tempo()  
57 - self.carregar_artigos()  
58 - self.carregar_preposicoes()  
59 - self.carregar_sinonimos()  
60 - self.carregar_subs_2_generos()  
61 - self.carregar_pronomes_tratamento()  
62 - self.carregar_verbos_infinitivo()  
63 - self.carregar_verbos_ligacao()  
64 - self.carregar_verbos_muda_negacao 46 + return os.path.expanduser("~") + "/vlibras-translate/data"
65 47
66 def montar_diretorio(self, arquivo): 48 def montar_diretorio(self, arquivo):
67 return os.path.join(self.path, arquivo) 49 return os.path.join(self.path, arquivo)
@@ -225,74 +207,104 @@ class LerDicionarios(Singleton): @@ -225,74 +207,104 @@ class LerDicionarios(Singleton):
225 def has_excecao_plural(self, token): 207 def has_excecao_plural(self, token):
226 '''Verifica se o token recebido consta no arquivo de exceções de plural. 208 '''Verifica se o token recebido consta no arquivo de exceções de plural.
227 ''' 209 '''
  210 + if not self.set_exc_plural:
  211 + self.carregar_excecoes_plural()
228 return token not in self.set_exc_plural 212 return token not in self.set_exc_plural
229 213
230 def has_adverbio_intensidade(self, token): 214 def has_adverbio_intensidade(self, token):
231 '''Verifica se o token recebido consta no arquivo de advérbios de intensidade. 215 '''Verifica se o token recebido consta no arquivo de advérbios de intensidade.
232 ''' 216 '''
  217 + if not self.dic_adv_intensidade:
  218 + self.carregar_adverbios_intensidade()
233 return self.dic_adv_intensidade.has_key(token) 219 return self.dic_adv_intensidade.has_key(token)
234 220
235 def has_adverbio_tempo(self, token): 221 def has_adverbio_tempo(self, token):
236 '''Verifica se o token recebido consta no arquivo de advérbios de tempo. 222 '''Verifica se o token recebido consta no arquivo de advérbios de tempo.
237 ''' 223 '''
  224 + if not self.set_adv_tempo:
  225 + self.carregar_adverbios_tempo()
238 return token in self.set_adv_tempo 226 return token in self.set_adv_tempo
239 227
240 def has_artigo(self, token): 228 def has_artigo(self, token):
241 '''Verifica se o token recebido consta no arquivo de artigos a serem removidos. 229 '''Verifica se o token recebido consta no arquivo de artigos a serem removidos.
242 ''' 230 '''
  231 + if not self.set_art:
  232 + self.carregar_artigos()
243 return token in self.set_art 233 return token in self.set_art
244 234
245 def has_preposicao(self, token): 235 def has_preposicao(self, token):
246 '''Verifica se o token recebido consta no arquivo de preposições a serem removidas. 236 '''Verifica se o token recebido consta no arquivo de preposições a serem removidas.
247 ''' 237 '''
  238 + if not self.set_prep:
  239 + self.carregar_preposicoes()
248 return token in self.set_prep 240 return token in self.set_prep
249 241
250 def has_sinonimo(self, token): 242 def has_sinonimo(self, token):
251 '''Verifica se o token recebido consta no arquivo de sinonimos. 243 '''Verifica se o token recebido consta no arquivo de sinonimos.
252 ''' 244 '''
  245 + if not self.dic_sin:
  246 + self.carregar_sinonimos()
253 return self.dic_sin.has_key(token) 247 return self.dic_sin.has_key(token)
254 248
255 def has_pron_tratam(self, token): 249 def has_pron_tratam(self, token):
256 '''Verifica se o token recebido consta no arquivo de pronomes de tratamento. 250 '''Verifica se o token recebido consta no arquivo de pronomes de tratamento.
257 ''' 251 '''
  252 + if not self.set_pron_trat:
  253 + self.carregar_pronomes_tratamento()
258 return token in self.set_pron_trat 254 return token in self.set_pron_trat
259 255
260 def has_subst_2_generos (self, token): 256 def has_subst_2_generos (self, token):
261 '''Verifica se o token recebido consta no arquivo de substantivos comuns de 2 generos. 257 '''Verifica se o token recebido consta no arquivo de substantivos comuns de 2 generos.
262 ''' 258 '''
  259 + if not self.set_sb_2_gen:
  260 + self.carregar_subs_2_generos()
263 return token in self.set_sb_2_gen 261 return token in self.set_sb_2_gen
264 262
265 def has_verbo_infinitivo(self, token): 263 def has_verbo_infinitivo(self, token):
266 '''Verifica se o token recebido consta no arquivo de verbos no infinitivo. 264 '''Verifica se o token recebido consta no arquivo de verbos no infinitivo.
267 ''' 265 '''
  266 + if not self.dic_vb_infinitivo:
  267 + self.carregar_verbos_infinitivo()
268 return self.dic_vb_infinitivo.has_key(token) 268 return self.dic_vb_infinitivo.has_key(token)
269 269
270 def has_verbo_ligacao(self, token): 270 def has_verbo_ligacao(self, token):
271 '''Verifica se o token recebido consta no arquivo de verbos de ligação. 271 '''Verifica se o token recebido consta no arquivo de verbos de ligação.
272 ''' 272 '''
  273 + if not self.set_vb_ligacao:
  274 + self.carregar_verbos_ligacao()
273 return token in self.set_vb_ligacao 275 return token in self.set_vb_ligacao
274 276
275 def has_verbo_muda_negacao(self, token): 277 def has_verbo_muda_negacao(self, token):
276 '''Verifica se o token recebido consta no arquivo de verbos que mudam de negação. 278 '''Verifica se o token recebido consta no arquivo de verbos que mudam de negação.
277 ''' 279 '''
  280 + if not self.dic_vb_muda_negacao:
  281 + self.carregar_verbos_muda_negacao()
278 return self.dic_vb_muda_negacao.has_key(token) 282 return self.dic_vb_muda_negacao.has_key(token)
279 283
280 def get_adverbio_intensidade(self, token): 284 def get_adverbio_intensidade(self, token):
281 '''Verifica se o token recebido consta no arquivo de advérbios de intensidade. 285 '''Verifica se o token recebido consta no arquivo de advérbios de intensidade.
282 ''' 286 '''
  287 + if not self.dic_adv_intensidade:
  288 + self.carregar_adverbios_intensidade()
283 return self.dic_adv_intensidade[token] 289 return self.dic_adv_intensidade[token]
284 290
285 def get_sinonimo(self, token): 291 def get_sinonimo(self, token):
286 '''Obtém o sinônimo do token. 292 '''Obtém o sinônimo do token.
287 ''' 293 '''
  294 + if not self.dic_sin:
  295 + self.carregar_sinonimos()
288 return self.dic_sin[token] 296 return self.dic_sin[token]
289 297
290 def get_verbo_infinitivo(self, token): 298 def get_verbo_infinitivo(self, token):
291 '''Obtém o verbo no infinitivo do token. 299 '''Obtém o verbo no infinitivo do token.
292 ''' 300 '''
  301 + if not self.dic_vb_infinitivo:
  302 + self.carregar_verbos_infinitivo()
293 return self.dic_vb_infinitivo[token] 303 return self.dic_vb_infinitivo[token]
294 304
295 def get_verbo_muda_negacao(self, token): 305 def get_verbo_muda_negacao(self, token):
296 '''Obtém o verbo que muda a negação do token. 306 '''Obtém o verbo que muda a negação do token.
297 ''' 307 '''
  308 + if not self.dic_vb_muda_negacao:
  309 + self.carregar_verbos_muda_negacao()
298 return self.dic_vb_muda_negacao[token] 310 return self.dic_vb_muda_negacao[token]
299 \ No newline at end of file 311 \ No newline at end of file
src/PortGlosa.py
@@ -11,22 +11,20 @@ from ThreadTradutor import * @@ -11,22 +11,20 @@ from ThreadTradutor import *
11 from TraduzSentencas import * 11 from TraduzSentencas import *
12 from LerDicionarios import * 12 from LerDicionarios import *
13 13
14 -  
15 tradutor = TraduzSentencas() 14 tradutor = TraduzSentencas()
16 -dicionario = LerDicionarios()  
17 taxas = [] 15 taxas = []
18 16
19 def traduzir(texto, log=None, threads=False, taxa_qualidade=False): 17 def traduzir(texto, log=None, threads=False, taxa_qualidade=False):
20 - tradutor.set_level(log) if log != None else tradutor.desativar_logging() 18 + #tradutor.set_level(log) if log != None else tradutor.desativar_logging()
21 if texto.isspace() or texto == "": 19 if texto.isspace() or texto == "":
22 #or not checar_idioma(texto): 20 #or not checar_idioma(texto):
23 return "ESCOLHER TEXTO CERTO" 21 return "ESCOLHER TEXTO CERTO"
24 22
25 - elif threads:  
26 - return iniciar_com_threads(texto, taxa_qualidade) 23 + #elif threads:
  24 + # return iniciar_com_threads(texto, taxa_qualidade)
27 25
28 - else:  
29 - return iniciar_sem_threads(texto, taxa_qualidade) 26 + #else:
  27 + return iniciar_sem_threads(texto, taxa_qualidade)
30 28
31 def iniciar_com_threads(texto, taxa_qualidade): 29 def iniciar_com_threads(texto, taxa_qualidade):
32 texto_quebrado = quebrar_texto(texto) 30 texto_quebrado = quebrar_texto(texto)
@@ -64,6 +62,7 @@ def quebrar_texto(texto): @@ -64,6 +62,7 @@ def quebrar_texto(texto):
64 if '.' not in texto: 62 if '.' not in texto:
65 return [texto] 63 return [texto]
66 64
  65 + dicionario = LerDicionarios()
67 texto_quebrado = texto.split() 66 texto_quebrado = texto.split()
68 tamanho_texto_quebrado = len(texto_quebrado) 67 tamanho_texto_quebrado = len(texto_quebrado)
69 sentencas = [] 68 sentencas = []
src/TraduzSentencas.py
@@ -6,7 +6,7 @@ @@ -6,7 +6,7 @@
6 6
7 #LAViD - Laboratório de Aplicações de Vídeo Digital 7 #LAViD - Laboratório de Aplicações de Vídeo Digital
8 8
9 -import alexp 9 +from ClassificaSentencas import *
10 from AplicaRegras import * 10 from AplicaRegras import *
11 from AplicaSinonimos import * 11 from AplicaSinonimos import *
12 import logging 12 import logging
@@ -24,6 +24,7 @@ class TraduzSentencas(object): @@ -24,6 +24,7 @@ class TraduzSentencas(object):
24 def __init__(self): 24 def __init__(self):
25 '''Instancia os aplicadores de regras e sinônimos. 25 '''Instancia os aplicadores de regras e sinônimos.
26 ''' 26 '''
  27 + self.classificador = ClassificaSentencas()
27 self.aplic_regras = AplicaRegras() 28 self.aplic_regras = AplicaRegras()
28 self.aplic_sin = AplicaSinonimos() 29 self.aplic_sin = AplicaSinonimos()
29 self.check_level() 30 self.check_level()
@@ -33,13 +34,13 @@ class TraduzSentencas(object): @@ -33,13 +34,13 @@ class TraduzSentencas(object):
33 ''' 34 '''
34 try: 35 try:
35 has_sintatica = True 36 has_sintatica = True
36 - analise_sintatica = alexp.run(sentenca) 37 + analise_sintatica = self.classificador.iniciar_classificacao(sentenca)
37 except Exception as ex: 38 except Exception as ex:
38 self.salvar_log(str(traceback.format_exc())) 39 self.salvar_log(str(traceback.format_exc()))
39 analise_sintatica = None 40 analise_sintatica = None
40 has_sintatica = False 41 has_sintatica = False
41 42
42 - analise_morfologica = alexp.getAnaliseMorfologica() 43 + analise_morfologica = self.classificador.obter_classificacao_morfologica()
43 44
44 if (isinstance(analise_sintatica,type(None))): 45 if (isinstance(analise_sintatica,type(None))):
45 regras_aplicadas = self.aplic_regras.aplicar_regras_morfo(analise_morfologica) 46 regras_aplicadas = self.aplic_regras.aplicar_regras_morfo(analise_morfologica)
src/alexp.py
@@ -1,156 +0,0 @@ @@ -1,156 +0,0 @@
1 -#! /usr/bin/env python2.6  
2 -# -*- coding: utf-8 -*-  
3 -  
4 -#---------------------------------  
5 -  
6 -# Editado:  
7 -  
8 -#Autor: Erickson Silva  
9 -#Email: <erickson.silva@lavid.ufpb.br> <ericksonsilva@live.com>  
10 -  
11 -#LAViD - Laboratório de Aplicações de Vídeo Digital  
12 -  
13 -#---------------------------------  
14 -  
15 -  
16 -# Donatus Brazilian Portuguese Parser  
17 -#  
18 -# Copyright (C) 2010-2013 Leonel F. de Alencar  
19 -#  
20 -# Author: Leonel F. de Alencar <leonel.de.alencar@ufc.br>  
21 -# Homepage: <http://www.leonel.profusehost.net/>  
22 -#  
23 -# Project's URL: <http://sourceforge.net/projects/donatus/>  
24 -# For license information, see LICENSE.TXT  
25 -#  
26 -# $Id: alexp.py $  
27 -  
28 -"""Este módulo contém funções que permitem utilizar o Aelius para etiquetar uma sentença, construindo entradas lexicais com base nas etiquetas atribuídas às palavras da sentença. Essas entradas lexicais são integradas em uma gramática CFG dada, que é transformada em um parser, utilizado para gerar uma árvore de estrutura sintagmática da sentença.  
29 -"""  
30 -import re,nltk,platform, time, random  
31 -from os.path import expanduser  
32 -from os import environ, path  
33 -from Aelius.Extras import carrega  
34 -from Aelius import AnotaCorpus  
35 -from unicodedata import normalize  
36 -  
37 -sentenca_anotada=""  
38 -sleep_times=[0.1,0.2]  
39 -  
40 -def toqueniza(s):  
41 - """Decodifica string utilizando utf-8, retornando uma lista de tokens em unicode.  
42 - """  
43 - regex = re.compile('[%s]' % re.escape('“”'))  
44 - decodificada=regex.sub('"',s.replace("–", "-").replace("—", "-")).decode("utf-8")  
45 - return AnotaCorpus.TOK_PORT.tokenize(decodificada)  
46 -  
47 -def getAnaliseMorfologica():  
48 - return sentenca_anotada  
49 -  
50 -def etiquetaSentenca(s):  
51 - """Aplica um dos etiquetadores do Aelius na etiquetagem da sentença dada como lista de tokens.  
52 - """  
53 - etiquetador = carrega("AeliusHunPos")  
54 - anotada = AnotaCorpus.anota_sentencas([s],etiquetador,"hunpos")[0]  
55 - while (anotada[0][1] is None):  
56 - time.sleep(random.choice(sleep_times))  
57 - anotada = AnotaCorpus.anota_sentencas([s],etiquetador,"hunpos")[0]  
58 - regex = re.compile('[%s]' % re.escape('!"#&\'()*+,-./:;<=>?@[\\]^_`{|}~'))  
59 - tag_punctuation = [".",",","QT","("]  
60 - anotada_corrigida = []  
61 - for x in anotada:  
62 - if x[1] not in tag_punctuation:  
63 - if x[1] == "NUM":  
64 - anotada_corrigida.append(x)  
65 - continue  
66 - tupla = [regex.sub('',x[0]).lower(),x[1]]  
67 - if tupla[0] != "": anotada_corrigida.append(tupla)  
68 - else:  
69 - if x[0] == ".":  
70 - anotada_corrigida.append(["[ponto]".decode("utf-8"),"SPT"])  
71 - elif x[0] == "?":  
72 - anotada_corrigida.append(["[interrogacao]".decode("utf-8"),"SPT"])  
73 - elif x[0] == "!":  
74 - anotada_corrigida.append(["[exclamacao]".decode("utf-8"),"SPT"])  
75 - return anotada_corrigida  
76 -  
77 -def geraEntradasLexicais(lista):  
78 - """Gera entradas lexicais no formato CFG do NLTK a partir de lista de pares constituídos de tokens e suas etiquetas.  
79 - """  
80 - entradas=[]  
81 - for e in lista:  
82 - # é necessário substituir símbolos como "-" e "+" do CHPTB  
83 - # que não são aceitos pelo NLTK como símbolos não terminais  
84 - c=re.sub(r"[-+]","_",e[1])  
85 - c=re.sub(r"\$","_S",c)  
86 - entradas.append("%s -> '%s'" % (c, removeAcento(e[0])))  
87 - return entradas  
88 -  
89 -def corrigeAnotacao(lista):  
90 - """Esta função deverá corrigir alguns dos erros de anotação mais comuns do Aelius. No momento, apenas é corrigida VB-AN depois de TR.  
91 - """  
92 - i=1  
93 - while i < len(lista):  
94 - if lista[i][1] == "VB-AN" and lista[i-1][1].startswith("TR"):  
95 - lista[i]=(lista[i][0],"VB-PP")  
96 - i+=1  
97 -  
98 -def encontraArquivo():  
99 - """Encontra arquivo na pasta vlibras-translate.  
100 - """  
101 - so = platform.system()  
102 - if "TRANSLATE_DATA" in environ:  
103 - return path.join(environ.get("TRANSLATE_DATA"), "cfg.syn.nltk")  
104 - elif so == 'Windows':  
105 - return environ.get("HOMEDRIVE") + "\\vlibras-libs\\vlibras-translate\data\cfg.syn.nltk"  
106 - return expanduser("~") + "/vlibras-translate/data/cfg.syn.nltk"  
107 -  
108 -def extraiSintaxe():  
109 - """Extrai gramática armazenada em arquivo cujo caminho é definido relativamente ao diretório nltk_data.  
110 - """  
111 - arquivo=encontraArquivo()  
112 - if arquivo:  
113 - f=open(arquivo,"rU")  
114 - sintaxe=f.read()  
115 - f.close()  
116 - return sintaxe  
117 - else:  
118 - print "Arquivo %s não encontrado em nenhum dos diretórios de dados do NLTK:\n%s" % (caminho,"\n".join(nltk.data.path))  
119 -  
120 -def analisaSentenca(sentenca):  
121 - """Retorna lista de árvores de estrutura sintagmática para a sentença dada sob a forma de uma lista de tokens, com base na gramática CFG cujo caminho é especificado como segundo argumento da função. Esse caminho é relativo à pasta nltk_data da instalação local do NLTK. A partir da etiquetagem morfossintática da sentença são geradas entradas lexicais que passam a integrar a gramática CFG. O caminho da gramática e o parser gerado são armazenados como tupla na variável ANALISADORES.  
122 - """  
123 - parser=constroiAnalisador(sentenca)  
124 - codificada=[]  
125 - for t in sentenca_anotada:  
126 - if t[1] != "SPT":  
127 - codificada.append(removeAcento(t[0]).encode("utf-8"))  
128 - trees=parser.parse_one(codificada)  
129 - return trees  
130 -  
131 -def constroiAnalisador(s):  
132 - """Constrói analisador a partir de uma única sentença não anotada, dada como lista de tokens, e uma lista de regras sintáticas no formato CFG, armazenadas em arquivo. Esta função tem um bug, causado pela maneira como o Aelius etiqueta sentenças usando o módulo ProcessaNomesProprios: quando a sentença se inicia por paravra com inicial minúscula, essa palavra não é incorporada ao léxico, mas a versão com inicial maiúscula.  
133 - """  
134 - global sentenca_anotada  
135 - sentenca_anotada=etiquetaSentenca(s)  
136 - corrigeAnotacao(sentenca_anotada)  
137 - entradas=geraEntradasLexicais(sentenca_anotada)  
138 - lexico="\n".join(entradas)  
139 - gramatica="%s\n%s" % (extraiSintaxe().strip(),lexico)  
140 - cfg=nltk.CFG.fromstring(gramatica)  
141 - return nltk.ChartParser(cfg)  
142 -  
143 -def removeAcento(texto):  
144 - try:  
145 - return normalize('NFKD', texto.encode('utf-8').decode('utf-8')).encode('ASCII', 'ignore')  
146 - except:  
147 - return normalize('NFKD', texto.encode('iso-8859-1').decode('iso-8859-1')).encode('ASCII','ignore')  
148 -  
149 -def exibeArvores(arvores):  
150 - """Função 'wrapper' para a função de exibição de árvores do NLTK"""  
151 - nltk.draw.draw_trees(*arvores)  
152 -  
153 -def run(sentenca):  
154 - tokens=toqueniza(sentenca)  
155 - tree=analisaSentenca(tokens)  
156 - return tree  
157 \ No newline at end of file 0 \ No newline at end of file