Commit 4892f503045408c7e1047cb9a6967b439de8ab97
Exists in
master
Merge branch 'devel'
Showing
10 changed files
with
225 additions
and
80 deletions
Show diff stats
data/preposicoes.csv
data/regras.xml
... | ... | @@ -195,6 +195,46 @@ |
195 | 195 | <newtokenpos>next</newtokenpos> |
196 | 196 | </class> |
197 | 197 | </rule> |
198 | + <rule name = "SE"><!-- Eliminar SE --> | |
199 | + <active>true</active> | |
200 | + <count>1</count> | |
201 | + <class> | |
202 | + <title>SE</title> | |
203 | + <action>remove</action> | |
204 | + </class> | |
205 | + </rule> | |
206 | + <rule name = "CL"><!-- Eliminar conjunção --> | |
207 | + <active>true</active> | |
208 | + <count>1</count> | |
209 | + <class> | |
210 | + <title>CL</title> | |
211 | + <action>remove</action> | |
212 | + </class> | |
213 | + </rule> | |
214 | + <rule name = "CONJ"><!-- Eliminar conjunção --> | |
215 | + <active>true</active> | |
216 | + <count>1</count> | |
217 | + <class> | |
218 | + <title>CONJ</title> | |
219 | + <action>remove</action> | |
220 | + </class> | |
221 | + </rule> | |
222 | + <rule name = "+"><!-- Eliminar + --> | |
223 | + <active>true</active> | |
224 | + <count>1</count> | |
225 | + <class> | |
226 | + <title>+</title> | |
227 | + <action>remove</action> | |
228 | + </class> | |
229 | + </rule> | |
230 | + <rule name = "-R"><!-- Eliminar -R --> | |
231 | + <active>true</active> | |
232 | + <count>1</count> | |
233 | + <class> | |
234 | + <title>-R</title> | |
235 | + <action>remove</action> | |
236 | + </class> | |
237 | + </rule> | |
198 | 238 | <rule name = "D"><!-- Eliminar artigo definido masculino singular --> |
199 | 239 | <active>true</active> |
200 | 240 | <count>1</count> |
... | ... | @@ -389,7 +429,7 @@ |
389 | 429 | <newtokenpos>next</newtokenpos> |
390 | 430 | </class> |
391 | 431 | </rule> |
392 | - <rule name = "SR-P"><!-- tempo verbal - presente com AdvP(t) --> | |
432 | + <rule name = "SR-P"><!-- tempo verbal - presente com AdvP(t) --> | |
393 | 433 | <active>true</active> |
394 | 434 | <count>1</count> |
395 | 435 | <class> |
... | ... | @@ -922,7 +962,7 @@ |
922 | 962 | </class> |
923 | 963 | </rule> |
924 | 964 | <rule name = "VP(VB_ADV-NEG)"><!-- tratamento do adverbio de negação modificador da raiz do verbo --> |
925 | - <active>false</active> | |
965 | + <active>true</active> | |
926 | 966 | <count>2</count> |
927 | 967 | <class> |
928 | 968 | <title>VB</title> |
... | ... | @@ -936,7 +976,7 @@ |
936 | 976 | </class> |
937 | 977 | </rule> |
938 | 978 | <rule name = "VP(VB_ADV-NEG)"><!-- tratamento do adverbio de negação modificador de expressão facial do verbo --> |
939 | - <active>false</active> | |
979 | + <active>true</active> | |
940 | 980 | <count>2</count> |
941 | 981 | <class> |
942 | 982 | <title>VB</title> |
... | ... | @@ -1267,7 +1307,7 @@ |
1267 | 1307 | </class> |
1268 | 1308 | </rule> |
1269 | 1309 | <rule name = "AP(ADV-NEG_ADJ)"><!-- tratamento do adverbio de negação modificador do adjetivo masculino --> |
1270 | - <active>false</active> | |
1310 | + <active>true</active> | |
1271 | 1311 | <count>2</count> |
1272 | 1312 | <class> |
1273 | 1313 | <title>ADV-NEG</title> |
... | ... | @@ -1280,7 +1320,7 @@ |
1280 | 1320 | </class> |
1281 | 1321 | </rule> |
1282 | 1322 | <rule name = "AP(ADJ_ADV-NEG)"><!-- tratamento do adverbio de negação modificador do adjetivo masculino (inverso) --> |
1283 | - <active>false</active> | |
1323 | + <active>true</active> | |
1284 | 1324 | <count>2</count> |
1285 | 1325 | <class> |
1286 | 1326 | <title>ADJ</title> |
... | ... | @@ -1293,7 +1333,7 @@ |
1293 | 1333 | </class> |
1294 | 1334 | </rule> |
1295 | 1335 | <rule name = "AP(ADV-NEG_ADJ-P)"><!-- tratamento do adverbio de negação modificador do adjetivo masculino plural --> |
1296 | - <active>false</active> | |
1336 | + <active>true</active> | |
1297 | 1337 | <count>2</count> |
1298 | 1338 | <class> |
1299 | 1339 | <title>ADV-NEG</title> |
... | ... | @@ -1306,7 +1346,7 @@ |
1306 | 1346 | </class> |
1307 | 1347 | </rule> |
1308 | 1348 | <rule name = "AP(ADJ-P_ADV-NEG)"><!-- tratamento do adverbio de negação modificador do adjetivo masculino plural (inverso) --> |
1309 | - <active>false</active> | |
1349 | + <active>true</active> | |
1310 | 1350 | <count>2</count> |
1311 | 1351 | <class> |
1312 | 1352 | <title>ADJ-P</title> |
... | ... | @@ -1319,7 +1359,7 @@ |
1319 | 1359 | </class> |
1320 | 1360 | </rule> |
1321 | 1361 | <rule name = "AP(ADV-NEG_ADJ-F)"><!-- tratamento do adverbio de negação modificador do adjetivo feminino --> |
1322 | - <active>false</active> | |
1362 | + <active>true</active> | |
1323 | 1363 | <count>2</count> |
1324 | 1364 | <class> |
1325 | 1365 | <title>ADV-NEG</title> |
... | ... | @@ -1332,7 +1372,7 @@ |
1332 | 1372 | </class> |
1333 | 1373 | </rule> |
1334 | 1374 | <rule name = "AP(ADJ-F_ADV-NEG)"><!-- tratamento do adverbio de negação modificador do adjetivo feminino (inverso) --> |
1335 | - <active>false</active> | |
1375 | + <active>true</active> | |
1336 | 1376 | <count>2</count> |
1337 | 1377 | <class> |
1338 | 1378 | <title>ADJ-F</title> |
... | ... | @@ -1345,7 +1385,7 @@ |
1345 | 1385 | </class> |
1346 | 1386 | </rule> |
1347 | 1387 | <rule name = "AP(ADV-NEG_ADJ-F-P)"><!-- tratamento do adverbio de negação modificador do adjetivo feminino plural --> |
1348 | - <active>false</active> | |
1388 | + <active>true</active> | |
1349 | 1389 | <count>2</count> |
1350 | 1390 | <class> |
1351 | 1391 | <title>ADV-NEG</title> |
... | ... | @@ -1358,7 +1398,7 @@ |
1358 | 1398 | </class> |
1359 | 1399 | </rule> |
1360 | 1400 | <rule name = "AP(ADJ-F-P_ADV-NEG)"><!-- tratamento do adverbio de negação modificador do adjetivo feminino plural (inverso) --> |
1361 | - <active>false</active> | |
1401 | + <active>true</active> | |
1362 | 1402 | <count>2</count> |
1363 | 1403 | <class> |
1364 | 1404 | <title>ADJ-F-P</title> |
... | ... | @@ -1371,7 +1411,7 @@ |
1371 | 1411 | </class> |
1372 | 1412 | </rule> |
1373 | 1413 | <rule name = "AP(ADV-NEG_ADJ-G)"><!-- tratamento do adverbio de negação modificador do adjetivo geral --> |
1374 | - <active>false</active> | |
1414 | + <active>true</active> | |
1375 | 1415 | <count>2</count> |
1376 | 1416 | <class> |
1377 | 1417 | <title>ADV-NEG</title> |
... | ... | @@ -1384,7 +1424,7 @@ |
1384 | 1424 | </class> |
1385 | 1425 | </rule> |
1386 | 1426 | <rule name = "AP(ADJ-G_ADV-NEG)"><!-- tratamento do adverbio de negação modificador do adjetivo geral (inverso) --> |
1387 | - <active>false</active> | |
1427 | + <active>true</active> | |
1388 | 1428 | <count>2</count> |
1389 | 1429 | <class> |
1390 | 1430 | <title>ADJ-G</title> |
... | ... | @@ -1397,7 +1437,7 @@ |
1397 | 1437 | </class> |
1398 | 1438 | </rule> |
1399 | 1439 | <rule name = "AP(ADV-NEG_ADJ-G-P)"><!-- tratamento do adverbio de negação modificador do adjetivo geral plural --> |
1400 | - <active>false</active> | |
1440 | + <active>true</active> | |
1401 | 1441 | <count>2</count> |
1402 | 1442 | <class> |
1403 | 1443 | <title>ADV-NEG</title> |
... | ... | @@ -1410,7 +1450,7 @@ |
1410 | 1450 | </class> |
1411 | 1451 | </rule> |
1412 | 1452 | <rule name = "AP(ADJ-G-P_ADV-NEG)"><!-- tratamento do adverbio de negação modificador do adjetivo geral plural (inverso) --> |
1413 | - <active>false</active> | |
1453 | + <active>true</active> | |
1414 | 1454 | <count>2</count> |
1415 | 1455 | <class> |
1416 | 1456 | <title>ADJ-G-P</title> | ... | ... |
install/linux/install.sh
... | ... | @@ -11,13 +11,24 @@ read -r -p "Deseja fazer o download das dependências? [Y/n] " response |
11 | 11 | |
12 | 12 | wget 150.165.204.30:8080/translate/linux/aelius-install.tar.gz |
13 | 13 | |
14 | + MACHINE_TYPE=`uname -m` | |
15 | + if [ ${MACHINE_TYPE} == 'x86_64' ]; then | |
16 | + wget 150.165.204.30:8080/translate/linux/hunpos/x86_64/hunpos-tag | |
17 | + else | |
18 | + wget 150.165.204.30:8080/translate/linux/hunpos/i386/hunpos-tag | |
19 | + fi | |
20 | + | |
14 | 21 | read -r -p "Deseja instalar as dependências? [Y/n] " response |
15 | 22 | response=${response,,} # tolower |
16 | 23 | if [[ $response =~ ^(yes|y| ) ]]; then |
17 | 24 | echo -e "\n# Extraindo...\n" |
18 | 25 | tar -xf aelius-install.tar.gz -C . |
19 | - | |
26 | + mkdir bin | |
27 | + mv hunpos-tag bin/ | |
28 | + chmod 777 bin/hunpos-tag | |
29 | + | |
20 | 30 | echo -e "# Instalando dependências...\n" |
31 | + sudo apt-get update | |
21 | 32 | sudo apt-get install -y python-dev python-setuptools python-pip python-yaml python-numpy python-matplotlib |
22 | 33 | sudo pip install nltk nltk_tgrep --upgrade |
23 | 34 | ... | ... |
src/AplicaRegras.py
... | ... | @@ -10,7 +10,7 @@ import platform |
10 | 10 | import re |
11 | 11 | import xml.etree.ElementTree as ET |
12 | 12 | from os.path import expanduser |
13 | -from os import environ | |
13 | +from os import environ, path | |
14 | 14 | from collections import deque |
15 | 15 | from LerDicionarios import * |
16 | 16 | from Iterator import * |
... | ... | @@ -41,6 +41,9 @@ class AplicaRegras(object): |
41 | 41 | ''' |
42 | 42 | if platform.system() == 'Windows': |
43 | 43 | return ET.parse(environ.get("HOMEDRIVE")+'\\vlibras-libs\\vlibras-translate\data\\regras.xml').getroot() |
44 | + elif "TRANSLATE_DATA" in environ: | |
45 | + arq_regras = path.join(environ.get("TRANSLATE_DATA"), "regras.xml") | |
46 | + return ET.parse(arq_regras).getroot() | |
44 | 47 | return ET.parse(expanduser("~")+'/vlibras-translate/data/regras.xml').getroot() |
45 | 48 | |
46 | 49 | # Aplica regras morfológicas apartir do arquivo regras.xml |
... | ... | @@ -225,14 +228,15 @@ class AplicaRegras(object): |
225 | 228 | node_pai[nodes_positions[count_temp]][0][0].set_label(newprop.text) |
226 | 229 | |
227 | 230 | elif action_text == "concate_neg": |
228 | - print "TODO" | |
229 | - | |
231 | + token = filter(None, node_pai[nodes_positions[count_temp]].leaves())[0] | |
232 | + token_concate = token + "_não" | |
233 | + node_pai[nodes_positions[count_temp]][0][0][0] = token_concate | |
234 | + # TODO: PRECISA ADD NEWPROP? | |
230 | 235 | |
231 | 236 | if newprop is not None: |
232 | 237 | node_pai[nodes_positions[self.count]].set_label(newprop.text) |
233 | 238 | |
234 | 239 | break |
235 | - | |
236 | 240 | return self.converter_arv_para_lista(p_arvore) |
237 | 241 | |
238 | 242 | def adaptar_regras_morfo_arvore(self, lista, arvore): |
... | ... | @@ -255,7 +259,10 @@ class AplicaRegras(object): |
255 | 259 | |
256 | 260 | # Corrige arvore de acordo com a lista após aplicar as regras morfológicas |
257 | 261 | for i in range(0, len(morfo)): |
258 | - if morfo[i] is not None and morfo[i][1] == "NTK": | |
262 | + #TODO: Corrigir essa verificação de FUTURO e PASSADO] | |
263 | + #TODO: Exclusão do nó inteiro (VBar) - Removendo palavra junto com a marcação de tempo | |
264 | + # EU FELIZ PASSADO -> EU FELIZ | |
265 | + if morfo[i] is not None and morfo[i][1] == "NTK" and morfo[i][0]: | |
259 | 266 | new_node = self.gerar_no(morfo[i]) |
260 | 267 | arvore[lista_pos_arv[i-1][:-3]].insert(2, new_node) |
261 | 268 | #arvore[lista_pos_arv[i-1][:-2]].insert(2, new_node) |
... | ... | @@ -403,8 +410,8 @@ class AplicaRegras(object): |
403 | 410 | lista_simplificada = self.converter_extenso(lista_simplificada) |
404 | 411 | except: |
405 | 412 | pass |
406 | - | |
407 | - return " ".join([x[0] for x in lista_simplificada]) | |
413 | + | |
414 | + return lista_simplificada | |
408 | 415 | |
409 | 416 | |
410 | 417 | def analisar_plural(self, token): | ... | ... |
src/ConverteExtenso.py
... | ... | @@ -90,6 +90,8 @@ o resultado. |
90 | 90 | def convert_extenso(extenso): |
91 | 91 | global newToken, auxToken |
92 | 92 | extensoQuebrado = extenso.lower().split(" ") |
93 | + if len(extensoQuebrado) == 1 and und.has_key(simplifica(extensoQuebrado[0])): | |
94 | + return extenso | |
93 | 95 | nums = [] |
94 | 96 | it = Iterator() |
95 | 97 | it.load(extensoQuebrado) | ... | ... |
src/LerDicionarios.py
... | ... | @@ -6,8 +6,7 @@ |
6 | 6 | |
7 | 7 | #LAViD - Laboratório de Aplicações de Vídeo Digital |
8 | 8 | |
9 | -from os.path import expanduser | |
10 | -from os import environ | |
9 | +import os | |
11 | 10 | import csv |
12 | 11 | import platform |
13 | 12 | |
... | ... | @@ -44,8 +43,10 @@ class LerDicionarios(Singleton): |
44 | 43 | '''Verifica qual o SO e gera o path de onde se encontra o diretório data. |
45 | 44 | ''' |
46 | 45 | if platform.system() == 'Windows': |
47 | - return environ.get("HOMEDRIVE") + "\\vlibras-libs\\vlibras-translate\data\\" | |
48 | - return expanduser("~") + "/vlibras-translate/data/" | |
46 | + return os.environ.get("HOMEDRIVE") + "\\vlibras-libs\\vlibras-translate\data\\" | |
47 | + elif "TRANSLATE_DATA" in os.environ: | |
48 | + return os.environ.get("TRANSLATE_DATA") | |
49 | + return os.path.expanduser("~") + "/vlibras-translate/data" | |
49 | 50 | |
50 | 51 | def carregar_dicionarios(self): |
51 | 52 | '''Realiza a leitura dos arquivos e atribui à estruturas de dicionários e sets. |
... | ... | @@ -62,11 +63,14 @@ class LerDicionarios(Singleton): |
62 | 63 | self.carregar_verbos_ligacao() |
63 | 64 | self.carregar_verbos_muda_negacao |
64 | 65 | |
66 | + def montar_diretorio(self, arquivo): | |
67 | + return os.path.join(self.path, arquivo) | |
68 | + | |
65 | 69 | def carregar_excecoes_plural(self): |
66 | 70 | '''Carrega arquivo de exceções de plural. |
67 | 71 | ''' |
68 | 72 | try: |
69 | - self.file = csv.reader(open(self.path+"excecoesPlural.csv")) | |
73 | + self.file = csv.reader(open(self.montar_diretorio("excecoesPlural.csv"))) | |
70 | 74 | except IOError, (errno, strerror): |
71 | 75 | print "I/O error(%s): %s" % (errno, strerror) |
72 | 76 | print "carregar_excecoes_plural" |
... | ... | @@ -80,7 +84,7 @@ class LerDicionarios(Singleton): |
80 | 84 | '''Carrega arquivo de adverbios de intensidade. |
81 | 85 | ''' |
82 | 86 | try: |
83 | - self.file = csv.reader(open(self.path+"adverbiosIntensidade.csv"), delimiter=";") | |
87 | + self.file = csv.reader(open(self.montar_diretorio("adverbiosIntensidade.csv")), delimiter=";") | |
84 | 88 | except IOError, (errno, strerror): |
85 | 89 | print "I/O error(%s): %s" % (errno, strerror) |
86 | 90 | print "carregar_adverbios_intensidade" |
... | ... | @@ -93,7 +97,7 @@ class LerDicionarios(Singleton): |
93 | 97 | '''Carrega arquivo de advérbios de tempo. |
94 | 98 | ''' |
95 | 99 | try: |
96 | - self.file = csv.reader(open(self.path+"adverbiosTempo.csv")) | |
100 | + self.file = csv.reader(open(self.montar_diretorio("adverbiosTempo.csv"))) | |
97 | 101 | except IOError, (errno, strerror): |
98 | 102 | print "I/O error(%s): %s" % (errno, strerror) |
99 | 103 | print "carregar_adverbios_tempo" |
... | ... | @@ -107,7 +111,7 @@ class LerDicionarios(Singleton): |
107 | 111 | '''Carrega arquivo de artigos a serem removidos. |
108 | 112 | ''' |
109 | 113 | try: |
110 | - self.file = csv.reader(open(self.path+"artigos.csv")) | |
114 | + self.file = csv.reader(open(self.montar_diretorio("artigos.csv"))) | |
111 | 115 | except IOError, (errno, strerror): |
112 | 116 | print "I/O error(%s): %s" % (errno, strerror) |
113 | 117 | print "carregar_artigos" |
... | ... | @@ -121,7 +125,7 @@ class LerDicionarios(Singleton): |
121 | 125 | '''Carrega arquivo de preposições a serem removidas. |
122 | 126 | ''' |
123 | 127 | try: |
124 | - self.file = csv.reader(open(self.path+"preposicoes.csv")) | |
128 | + self.file = csv.reader(open(self.montar_diretorio("preposicoes.csv"))) | |
125 | 129 | except IOError, (errno, strerror): |
126 | 130 | print "I/O error(%s): %s" % (errno, strerror) |
127 | 131 | print "carregar_preposicoes" |
... | ... | @@ -135,7 +139,7 @@ class LerDicionarios(Singleton): |
135 | 139 | '''Carrega arquivo de sinônimos. |
136 | 140 | ''' |
137 | 141 | try: |
138 | - self.file = csv.reader(open(self.path+"sinonimos.csv"), delimiter=";") | |
142 | + self.file = csv.reader(open(self.montar_diretorio("sinonimos.csv")), delimiter=";") | |
139 | 143 | except IOError, (errno, strerror): |
140 | 144 | print "I/O error(%s): %s" % (errno, strerror) |
141 | 145 | print "carregar_sinonimos" |
... | ... | @@ -151,7 +155,7 @@ class LerDicionarios(Singleton): |
151 | 155 | '''Carrega arquivo dos substantivos comuns de 2 generos. |
152 | 156 | ''' |
153 | 157 | try: |
154 | - self.file = csv.reader(open(self.path+"subs2Generos.csv")) | |
158 | + self.file = csv.reader(open(self.montar_diretorio("subs2Generos.csv"))) | |
155 | 159 | except IOError, (errno, strerror): |
156 | 160 | print "I/O error(%s): %s" % (errno, strerror) |
157 | 161 | print "carregar_subs_2_generos" |
... | ... | @@ -165,7 +169,7 @@ class LerDicionarios(Singleton): |
165 | 169 | '''Carrega arquivo de verbos no infinitivo. |
166 | 170 | ''' |
167 | 171 | try: |
168 | - self.file = csv.reader(open(self.path+"verbosInfinitivo.csv"), delimiter=";") | |
172 | + self.file = csv.reader(open(self.montar_diretorio("verbosInfinitivo.csv")), delimiter=";") | |
169 | 173 | except IOError, (errno, strerror): |
170 | 174 | print "I/O error(%s): %s" % (errno, strerror) |
171 | 175 | print "carregar_verbos_infinitivo" |
... | ... | @@ -181,7 +185,7 @@ class LerDicionarios(Singleton): |
181 | 185 | '''Carrega arquivo de verbos de ligação. |
182 | 186 | ''' |
183 | 187 | try: |
184 | - self.file = csv.reader(open(self.path+"verbosLigacao.csv")) | |
188 | + self.file = csv.reader(open(self.montar_diretorio("verbosLigacao.csv"))) | |
185 | 189 | except IOError, (errno, strerror): |
186 | 190 | print "I/O error(%s): %s" % (errno, strerror) |
187 | 191 | print "carregar_verbos_ligacao" |
... | ... | @@ -195,7 +199,7 @@ class LerDicionarios(Singleton): |
195 | 199 | '''Carrega arquivo de pronomes de tratamento. |
196 | 200 | ''' |
197 | 201 | try: |
198 | - self.file = csv.reader(open(self.path+"pronomesTratamento.csv")) | |
202 | + self.file = csv.reader(open(self.montar_diretorio("pronomesTratamento.csv"))) | |
199 | 203 | except IOError, (errno, strerror): |
200 | 204 | print "I/O error(%s): %s" % (errno, strerror) |
201 | 205 | print "carregar_pronomes_tratamento" |
... | ... | @@ -209,7 +213,7 @@ class LerDicionarios(Singleton): |
209 | 213 | '''Carrega arquivo de verbos que mudam a negação. |
210 | 214 | ''' |
211 | 215 | try: |
212 | - self.file = csv.reader(open(self.path+"verbosMudaNegacao.csv"), delimiter=";") | |
216 | + self.file = csv.reader(open(self.montar_diretorio("verbosMudaNegacao.csv")), delimiter=";") | |
213 | 217 | except IOError, (errno, strerror): |
214 | 218 | print "I/O error(%s): %s" % (errno, strerror) |
215 | 219 | print "carregar_verbos_muda_negacao" | ... | ... |
src/PortGlosa.py
... | ... | @@ -14,43 +14,50 @@ from LerDicionarios import * |
14 | 14 | |
15 | 15 | tradutor = TraduzSentencas() |
16 | 16 | dicionario = LerDicionarios() |
17 | +taxas = [] | |
17 | 18 | |
18 | -def traduzir(texto, threads=False): | |
19 | +def traduzir(texto, log=None, threads=False, taxa_qualidade=False): | |
20 | + tradutor.set_level(log) if log != None else tradutor.desativar_logging() | |
19 | 21 | if texto.isspace() or texto == "": |
20 | 22 | return "ESCOLHER TEXTO CERTO" |
21 | 23 | |
22 | 24 | elif threads: |
23 | - return iniciar_com_threads(texto) | |
25 | + return iniciar_com_threads(texto, taxa_qualidade) | |
24 | 26 | |
25 | 27 | else: |
26 | - return iniciar_sem_threads(texto) | |
28 | + return iniciar_sem_threads(texto, taxa_qualidade) | |
27 | 29 | |
28 | -def iniciar_com_threads(texto): | |
30 | +def iniciar_com_threads(texto, taxa_qualidade): | |
29 | 31 | texto_quebrado = quebrar_texto(texto) |
30 | 32 | num_threads = len(texto_quebrado) |
31 | - texto_traduzido = [] | |
33 | + saidas = [] | |
32 | 34 | threads = [] |
33 | 35 | |
34 | 36 | for i in range(num_threads): |
35 | 37 | if texto_quebrado[i] > 0 and texto_quebrado[i] != " ": |
36 | - threads.insert(i, ThreadTradutor(texto_quebrado[i])) | |
38 | + threads.insert(i, ThreadTradutor(texto_quebrado[i],taxa_qualidade)) | |
37 | 39 | threads[i].start() |
38 | 40 | for i in range(num_threads): |
39 | 41 | threads[i].join() |
40 | - texto_traduzido.append(threads[i].obter_glosa()) | |
42 | + saidas.append(threads[i].obter_glosa()) | |
43 | + | |
44 | + if taxa_qualidade: | |
45 | + return gerar_taxa_qualidade(saidas) | |
41 | 46 | |
42 | 47 | try: |
43 | - return " ".join(texto_traduzido) | |
48 | + return " ".join(saidas) | |
44 | 49 | except: |
45 | 50 | return None |
46 | 51 | |
47 | -def iniciar_sem_threads(texto): | |
52 | +def iniciar_sem_threads(texto, taxa_qualidade): | |
48 | 53 | texto_quebrado = quebrar_texto(texto) |
49 | - texto_traduzido = [] | |
54 | + saidas = [] | |
50 | 55 | for texto in texto_quebrado: |
51 | - glosa = tradutor.iniciar_traducao(texto) | |
52 | - texto_traduzido.append(glosa) | |
53 | - return " ".join(texto_traduzido) | |
56 | + saida = tradutor.iniciar_traducao(texto, taxa_qualidade) | |
57 | + saidas.append(saida) | |
58 | + if taxa_qualidade: | |
59 | + return gerar_taxa_qualidade(saidas) | |
60 | + return " ".join(saidas) | |
54 | 61 | |
55 | 62 | def quebrar_texto(texto): |
56 | 63 | if '.' not in texto: |
... | ... | @@ -69,9 +76,24 @@ def quebrar_texto(texto): |
69 | 76 | lista_texto = [] |
70 | 77 | continue |
71 | 78 | if lista_texto: |
72 | - sentencas.append( " ".join(lista_texto)) | |
79 | + sentencas.append(" ".join(lista_texto)) | |
73 | 80 | return sentencas |
74 | 81 | |
82 | +def gerar_taxa_qualidade(lista_saidas): | |
83 | + soma_taxas = 0 | |
84 | + quant_analise_sintatica = 0 | |
85 | + glosas = [] | |
86 | + for saida in lista_saidas: | |
87 | + glosas.append(saida['glosa']) | |
88 | + soma_taxas += saida['taxa'] | |
89 | + if saida['sintatica'] is True: | |
90 | + quant_analise_sintatica += 1 | |
91 | + | |
92 | + taxa_sintatica = (float(quant_analise_sintatica)/len(lista_saidas)) * 0.20 | |
93 | + taxa_sentenca = (float(soma_taxas)/len(lista_saidas)) * 0.80 | |
94 | + return {'glosa':" ".join(glosas), 'taxa_qualidade': float("%.2f" % (taxa_sintatica+taxa_sentenca))} | |
95 | + | |
96 | + | |
75 | 97 | def ajuda(): |
76 | 98 | #TODO: Adicionar um pequeno tuto aqui |
77 | 99 | print "Help" | ... | ... |
src/ThreadTradutor.py
... | ... | @@ -12,7 +12,7 @@ from threading import Thread |
12 | 12 | class ThreadTradutor(Thread): |
13 | 13 | '''Thread que inicia uma tradução''' |
14 | 14 | |
15 | - def __init__(self, sentenca): | |
15 | + def __init__(self, sentenca, taxa): | |
16 | 16 | ''' Recebe o texto a ser traduzido e o atribui a uma variável. |
17 | 17 | Além disso, instancia variável que será armazenada a glosa e a classe responsável pelo processo de tradução. |
18 | 18 | ''' |
... | ... | @@ -20,11 +20,12 @@ class ThreadTradutor(Thread): |
20 | 20 | self.sentenca = sentenca |
21 | 21 | self.glosa = "" |
22 | 22 | self.tradutor = TraduzSentencas() |
23 | + self.taxa_qualidade = taxa | |
23 | 24 | |
24 | 25 | def run(self): |
25 | 26 | ''' Metódo executado ao 'startar' a Thread. É responsável por iniciar a tradução passando o texto como parâmetro. |
26 | 27 | ''' |
27 | - self.glosa = self.tradutor.iniciar_traducao(self.sentenca) | |
28 | + self.glosa = self.tradutor.iniciar_traducao(self.sentenca, self.taxa_qualidade) | |
28 | 29 | |
29 | 30 | def obter_glosa(self): |
30 | 31 | ''' Obtém a glosa após o processo de tradução. | ... | ... |
src/TraduzSentencas.py
1 | -#!/usr/bin/python | |
1 | + #!/usr/bin/python | |
2 | 2 | # -*- coding: utf-8 -*- |
3 | 3 | |
4 | 4 | #Autor: Erickson Silva |
... | ... | @@ -9,7 +9,12 @@ |
9 | 9 | import alexp |
10 | 10 | from AplicaRegras import * |
11 | 11 | import logging |
12 | +import logging.handlers | |
12 | 13 | import traceback |
14 | +import subprocess | |
15 | +import re, string | |
16 | +import getopt | |
17 | +import sys | |
13 | 18 | |
14 | 19 | class TraduzSentencas(object): |
15 | 20 | '''Realiza a tradução do texto em português para glosa |
... | ... | @@ -19,40 +24,88 @@ class TraduzSentencas(object): |
19 | 24 | '''Instancia os aplicadores de regras e sinônimos. |
20 | 25 | ''' |
21 | 26 | self.aplic_regras = AplicaRegras() |
22 | - #logging.basicConfig(filename='translate.log', | |
23 | - # format='%(asctime)s - %(levelname)s:\n\n%(message)s\n\n\n##############################################\n\n', | |
24 | - # level=logging.ERROR) | |
25 | - | |
26 | - def iniciar_traducao(self, sentenca): | |
27 | + self.check_level() | |
28 | + | |
29 | + def iniciar_traducao(self, sentenca, taxa=False): | |
27 | 30 | '''Metódo responsável por executar todos componentes necessários para a geração da glosa. |
28 | 31 | ''' |
29 | 32 | try: |
33 | + has_sintatica = True | |
30 | 34 | analise_sintatica = alexp.run(sentenca) |
31 | 35 | except Exception as ex: |
32 | - #self.salvar_log(str(traceback.format_exc())) | |
36 | + self.salvar_log(str(traceback.format_exc())) | |
33 | 37 | analise_sintatica = None |
38 | + has_sintatica = False | |
34 | 39 | |
35 | 40 | analise_morfologica = alexp.getAnaliseMorfologica() |
36 | - | |
41 | + | |
37 | 42 | if (isinstance(analise_sintatica,type(None))): |
38 | - #print "# ANÁLISE MORFOLÓGICA" | |
39 | 43 | regras_aplicadas = self.aplic_regras.aplicar_regras_morfo(analise_morfologica) |
40 | 44 | else: |
41 | - #print "# ANÁLISE SINTÁTICA" | |
42 | 45 | try: |
43 | 46 | regras_aplicadas = self.aplic_regras.aplicar_regras_sint(analise_morfologica, analise_sintatica) |
44 | 47 | except: |
45 | 48 | regras_aplicadas = self.aplic_regras.aplicar_regras_morfo(analise_morfologica) |
46 | 49 | |
47 | 50 | sentenca_corrigida = self.aplic_regras.simplificar_sentenca(regras_aplicadas) |
48 | - sentenca_sem_acentos = self.aplic_regras.remover_acento(sentenca_corrigida) | |
51 | + glosa = " ".join([x[0] for x in sentenca_corrigida]) | |
52 | + | |
53 | + if glosa: | |
54 | + if taxa: | |
55 | + taxa_qualidade = self.gerar_metrica_qualidade(sentenca_corrigida) | |
56 | + return {'glosa':glosa_sem_acentos, 'taxa':taxa_qualidade, 'sintatica':has_sintatica} | |
57 | + return glosa.upper().encode('utf-8') | |
58 | + return "TEXTO ERRADO ESCOLHER OUTRO" | |
49 | 59 | |
50 | - if sentenca_sem_acentos: | |
51 | - return sentenca_sem_acentos.upper().encode('utf-8') | |
52 | - return "TEXTO ERRADO ESCOLHER OUTRO" | |
53 | 60 | |
54 | 61 | def salvar_log(self, erro): |
55 | 62 | '''Salva traceback de uma excessão do analisador sintático |
56 | 63 | ''' |
57 | - logging.error(erro) | |
58 | - | |
64 | + logger = logging.getLogger('error-feedback') | |
65 | + logger.propagate = False | |
66 | + logger.error(erro) | |
67 | + | |
68 | + def criar_logger_error(self): | |
69 | + error_log = logging.getLogger('error-feedback') | |
70 | + error_log.setLevel(logging.ERROR) | |
71 | + ##print os.path.dirname(__file__) -- Salvar no direitorio do arquivo .py? | |
72 | + error_handler = logging.handlers.RotatingFileHandler('/var/tmp/vlibras-translate.log', maxBytes=1024, backupCount=5) | |
73 | + formatter = logging.Formatter('%(asctime)s - %(levelname)s:\n\n%(message)s\n\n\n##############################################\n\n') | |
74 | + error_handler.setFormatter(formatter) | |
75 | + error_log.addHandler(error_handler) | |
76 | + | |
77 | + def check_level(self): | |
78 | + for opt in sys.argv[1:]: | |
79 | + if "--log" in opt: | |
80 | + self.set_level(opt[6:]) | |
81 | + return | |
82 | + self.desativar_logging() | |
83 | + | |
84 | + def set_level(self, level): | |
85 | + numeric_level = getattr(logging, level.upper(), None) | |
86 | + if not isinstance(numeric_level, int): | |
87 | + raise ValueError('Nível de log inválido: %s' % level) | |
88 | + logging.disable(logging.NOTSET) | |
89 | + logging.getLogger().setLevel(numeric_level) | |
90 | + if numeric_level == 40 or numeric_level == 10: | |
91 | + self.criar_logger_error() | |
92 | + | |
93 | + def desativar_logging(self): | |
94 | + logging.disable(logging.DEBUG) | |
95 | + logging.disable(logging.INFO) | |
96 | + logging.disable(logging.WARNING) | |
97 | + logging.disable(logging.ERROR) | |
98 | + logging.disable(logging.CRITICAL) | |
99 | + | |
100 | + def gerar_metrica_qualidade(self, lista): | |
101 | + #TODO: resolver path do arquivo | |
102 | + arqSinais = open("sinais.txt", "r").read().split() | |
103 | + quantSinaisTotal = len(lista) | |
104 | + quantSinaisEncontradas = 0 | |
105 | + for x in lista: | |
106 | + if x[0].upper()+".anim" in arqSinais: | |
107 | + quantSinaisEncontradas += 1 | |
108 | + else: | |
109 | + if x[1] == "NPR": | |
110 | + quantSinaisTotal-=1 | |
111 | + return float(quantSinaisEncontradas)/quantSinaisTotal | ... | ... |
src/alexp.py
... | ... | @@ -29,12 +29,11 @@ |
29 | 29 | """ |
30 | 30 | import re,nltk,platform, time, random |
31 | 31 | from os.path import expanduser |
32 | -from os import environ | |
32 | +from os import environ, path | |
33 | 33 | from Aelius.Extras import carrega |
34 | 34 | from Aelius import AnotaCorpus |
35 | 35 | from unicodedata import normalize |
36 | 36 | |
37 | - | |
38 | 37 | sentenca_anotada="" |
39 | 38 | sleep_times=[0.1,0.2] |
40 | 39 | |
... | ... | @@ -46,7 +45,6 @@ def toqueniza(s): |
46 | 45 | |
47 | 46 | def getAnaliseMorfologica(): |
48 | 47 | return sentenca_anotada |
49 | - #return [list(x) for x in sentenca_anotada] | |
50 | 48 | |
51 | 49 | def etiquetaSentenca(s): |
52 | 50 | """Aplica um dos etiquetadores do Aelius na etiquetagem da sentença dada como lista de tokens. |
... | ... | @@ -56,10 +54,17 @@ def etiquetaSentenca(s): |
56 | 54 | while (anotada[0][1] is None): |
57 | 55 | time.sleep(random.choice(sleep_times)) |
58 | 56 | anotada = AnotaCorpus.anota_sentencas([s],etiquetador,"hunpos")[0] |
59 | - #anotada[0] = (anotada[0][0].lower(), anotada[0][1]) | |
60 | - #return anotada | |
57 | + regex = re.compile('[%s]' % re.escape('!"#&\'()*+,-./:;<=>?@[\\]^_`{|}~')) | |
61 | 58 | tag_punctuation = [".",",","QT","("] |
62 | - return [[x[0].lower(),x[1]] for x in anotada if x[1] not in tag_punctuation] | |
59 | + anotada_corrigida = [] | |
60 | + for x in anotada: | |
61 | + if x[1] not in tag_punctuation: | |
62 | + if x[1] == "NUM": | |
63 | + anotada_corrigida.append(x) | |
64 | + continue | |
65 | + tupla = [regex.sub('',x[0]).lower(),x[1]] | |
66 | + if tupla[0] != "": anotada_corrigida.append(tupla) | |
67 | + return anotada_corrigida | |
63 | 68 | |
64 | 69 | def geraEntradasLexicais(lista): |
65 | 70 | """Gera entradas lexicais no formato CFG do NLTK a partir de lista de pares constituídos de tokens e suas etiquetas. |
... | ... | @@ -88,8 +93,9 @@ def encontraArquivo(): |
88 | 93 | so = platform.system() |
89 | 94 | if so == 'Windows': |
90 | 95 | return environ.get("HOMEDRIVE") + "\\vlibras-libs\\vlibras-translate\data\cfg.syn.nltk" |
91 | - else: | |
92 | - return expanduser("~") + "/vlibras-translate/data/cfg.syn.nltk" | |
96 | + elif "TRANSLATE_DATA" in environ: | |
97 | + return path.join(environ.get("TRANSLATE_DATA"), "cfg.syn.nltk") | |
98 | + return expanduser("~") + "/vlibras-translate/data/cfg.syn.nltk" | |
93 | 99 | |
94 | 100 | def extraiSintaxe(): |
95 | 101 | """Extrai gramática armazenada em arquivo cujo caminho é definido relativamente ao diretório nltk_data. |
... | ... | @@ -107,7 +113,7 @@ def analisaSentenca(sentenca): |
107 | 113 | """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. |
108 | 114 | """ |
109 | 115 | parser=constroiAnalisador(sentenca) |
110 | - codificada=[removeAcento(w).encode("utf-8") for w in sentenca] | |
116 | + codificada=[removeAcento(w[0]).encode("utf-8") for w in sentenca_anotada] | |
111 | 117 | trees=parser.parse_one(codificada) |
112 | 118 | return trees |
113 | 119 | ... | ... |