e6836308acc16d00490c3a392f831c3016a91f99
[iramuteq] / corpus.py
1 # -*- coding: utf-8 -*-
2 #Author: Pierre Ratinaud
3
4 import codecs
5 import os
6 import gettext
7 _ = gettext.gettext
8 import locale
9 import sys
10 from time import time
11 from functions import decoupercharact, ReadDicoAsDico, DoConf
12 import re
13 import sqlite3
14 import itertools
15 import logging
16 from operator import itemgetter
17 from uuid import uuid4
18 from chemins import PathOut
19 from dialog import CorpusPref
20 from functions import ReadLexique, ReadDicoAsDico
21 from colors import colors
22 import datetime
23
24
25 log = logging.getLogger('iramuteq.corpus')
26
27
28 def copycorpus(corpus) :
29     log.info('copy corpus')
30     copy_corpus = Corpus(corpus.parent, parametres = corpus.parametres)
31     copy_corpus.ucis = corpus.ucis
32     copy_corpus.formes = corpus.formes
33     copy_corpus.pathout = corpus.pathout
34     copy_corpus.conn_all()
35     return copy_corpus
36
37
38
39 class Corpus :
40     """Corpus class
41     list of text
42     """
43     def __init__(self, parent, parametres = {}, read = False) :
44         self.parent = parent
45         self.parametres = parametres
46         self.cformes = None         
47         self.connformes = None
48         self.connuces = None
49         self.conncorpus = None
50         self.islem = False
51         self.cuces = None
52         self.ucis = []
53         self.formes = {}
54         self.flems = {}
55         self.lems = None
56         self.idformesuces = {}
57         self.iduces = None
58         self.idformes = None
59         self.uceuci = None
60         if read :
61             self.pathout = PathOut(dirout = parametres['pathout'])
62             self.read_corpus()
63
64     def add_word(self, word) :
65         if word in self.formes :
66             self.formes[word].freq += 1
67             if self.formes[word].ident in self.idformesuces :
68                 if self.ucis[-1].uces[-1].ident in self.idformesuces[self.formes[word].ident] :
69                     self.idformesuces[self.formes[word].ident][self.ucis[-1].uces[-1].ident] += 1
70                 else :
71                     self.idformesuces[self.formes[word].ident][self.ucis[-1].uces[-1].ident] = 1
72             else :
73                 self.idformesuces[self.formes[word].ident] = {self.ucis[-1].uces[-1].ident: 1}
74         else :
75             if word in self.parent.lexique :
76                 gramtype = self.parent.lexique[word][1]
77                 lem = self.parent.lexique[word][0]
78             elif word.isdigit() :
79                 gramtype = u'num'
80                 lem = word
81             else :
82                 gramtype = u'nr'
83                 lem = word
84             self.formes[word] =  Word(word, gramtype, len(self.formes), lem)
85             self.idformesuces[self.formes[word].ident] = {self.ucis[-1].uces[-1].ident : 1}
86
87     def conn_all(self): 
88         """connect corpus to db"""
89         if self.connformes is None :
90             log.info('connexion corpus')
91             self.connuces = sqlite3.connect(self.pathout['uces.db'])
92             self.cuces = self.connuces.cursor()
93             self.connformes = sqlite3.connect(self.pathout['formes.db'])
94             self.cformes = self.connformes.cursor()
95             self.conncorpus = sqlite3.connect(self.pathout['corpus.db'])
96             self.ccorpus = self.conncorpus.cursor()
97             self.cformes.execute('PRAGMA temp_store=MEMORY;')
98             self.cformes.execute('PRAGMA journal_mode=MEMORY;')
99             self.cformes.execute('PRAGMA  synchronous = OFF;')
100             self.cuces.execute('PRAGMA temp_store=MEMORY;')
101             self.cuces.execute('PRAGMA journal_mode=MEMORY;')
102             self.cuces.execute('PRAGMA  synchronous = OFF;')
103             self.ccorpus.execute('PRAGMA temp_store=MEMORY;')
104             self.ccorpus.execute('PRAGMA journal_mode=MEMORY;')
105             self.ccorpus.execute('PRAGMA  synchronous = OFF;')
106
107     def read_corpus(self) :
108         log.info('read corpus')
109         self.parametres['syscoding'] = sys.getdefaultencoding()
110         if self.conncorpus is None :
111             self.conn_all()
112         res = self.ccorpus.execute('SELECT * FROM etoiles;')
113         for row in res :
114             self.ucis.append(Uci(row[0], row[1], row[2]))
115             uces = self.conncorpus.cursor().execute('SELECT * FROM luces where uci=?;',(`self.ucis[-1].ident`,))
116             for uce in uces:
117                 self.ucis[-1].uces.append(Uce(uce[2], uce[1], uce[0]))
118         res = self.ccorpus.execute('SELECT * FROM formes;')
119         self.formes = dict([[forme[1], Word(forme[1], forme[3], forme[0], lem = forme[2], freq = forme[4])] for forme in res])
120         self.ccorpus.close()
121     
122     def getworduces(self, wordid) :
123         if isinstance(wordid, basestring) :
124             wordid = self.formes[wordid].ident
125         res = self.cformes.execute('SELECT uces FROM uces where id=? ORDER BY id;', (`wordid`,))
126         return list(itertools.chain(*[[int(val) for val in row[0].split()] if not isinstance(row[0], int) else [row[0]] for row in res]))
127
128     def getformeuceseff(self, formeid) :
129         if isinstance(formeid, basestring) :
130             formeid = self.formes[formeid].ident
131         res = self.cformes.execute('SELECT uces FROM uces where id=? ORDER BY id;', (`formeid`,))
132         uces = list(itertools.chain(*[[int(val) for val in row[0].split()] if not isinstance(row[0], int) else [row[0]] for row in res]))
133         query = 'SELECT eff FROM eff where id=%i ORDER BY id' % formeid
134         res = self.cformes.execute(query)
135         eff = list(itertools.chain(*[[int(val) for val in row[0].split()] if not isinstance(row[0], int) else [row[0]] for row in res]))
136         formeuceeff = {}
137         for i, uce in enumerate(uces) :
138             formeuceeff[uce] = formeuceeff.get(uce, 0) + eff[i]
139         return formeuceeff    
140
141     def getlemuces(self, lem) :
142         formesid = ', '.join([`val` for val in self.lems[lem].formes])
143         query = 'SELECT uces FROM uces where id IN (%s) ORDER BY id' % formesid
144         res = self.cformes.execute(query)
145         return list(set(list(itertools.chain(*[[int(val) for val in row[0].split()] if not isinstance(row[0], int) else [row[0]] for row in res]))))
146
147     def getlemucis(self, lem) :
148         uces = self.getlemuces(lem)
149         return list(set([self.getucefromid(val).uci for val in uces]))
150
151     def getlemuceseff(self, lem, luces = None) :
152         formesid = ', '.join([`val` for val in self.lems[lem].formes])
153         query = 'SELECT uces FROM uces where id IN (%s) ORDER BY id' % formesid
154         res = self.cformes.execute(query)
155         uces = list(itertools.chain(*[[int(val) for val in row[0].split()] if not isinstance(row[0], int) else [row[0]] for row in res]))
156         query = 'SELECT eff FROM eff where id IN (%s) ORDER BY id' % formesid
157         res = self.cformes.execute(query)
158         eff = list(itertools.chain(*[[int(val) for val in row[0].split()] if not isinstance(row[0], int) else [row[0]] for row in res]))
159         lemuceeff = {}
160         for i, uce in enumerate(uces) :
161             lemuceeff[uce] = lemuceeff.get(uce, 0) + eff[i]
162         return lemuceeff    
163
164     def getlemclustereff(self, lem, cluster) :
165         return len(list(set(self.lc[cluster]).intersection(self.getlemuces(lem))))
166
167     def getlemeff(self, lem) :
168         return self.lems[lem].freq
169
170     def getlems(self) :
171         return self.lems
172
173     def getforme(self, formeid) :
174         if self.idformes is None : self.make_idformes()
175         return self.idformes[formeid]
176
177     def gettotocc(self) :
178         return sum([self.formes[forme].freq for forme in self.formes])
179
180     def getucemean(self) :
181         return float(self.gettotocc())/self.getucenb()
182
183     def getucenb(self) :
184         return self.ucis[-1].uces[-1].ident + 1
185
186     def getucinb(self) :
187         return self.ucis[-1].ident + 1
188
189     def getucisize(self) :
190         ucesize = self.getucesize()
191         return [sum(ucesize[uci.uces[0].ident:(uci.uces[-1].ident + 1)]) for uci in self.ucis]
192     
193     def getucesize(self) :
194         res = self.getalluces()
195         return [len(uce[1].split()) for uce in res]
196
197     def getconcorde(self, uces) :
198         return self.cuces.execute('select * from uces where id IN (%s);' % ', '.join([`i` for i in uces])) 
199
200     def getwordconcorde(self, word) :
201         return self.getconcorde(self.getworduces(word))
202
203     def getlemconcorde(self, lem) :
204         return self.getconcorde(self.getlemuces(lem))
205
206     def getalluces(self) :
207         return self.cuces.execute('SELECT * FROM uces')
208
209     def getucesfrometoile(self, etoile) :
210         return [uce.ident for uci in self.ucis for uce in uci.uces if etoile in uci.etoiles]
211
212     def getetoileuces(self) :
213         log.info('get uces etoiles')
214         etoileuces = {}
215         idpara = 0
216         for uci in self.ucis :
217             etoiles = uci.etoiles[1:]
218             for et in etoiles :
219                 if et in etoileuces :
220                     etoileuces[et] += [uce.ident for uce in uci.uces]
221                 else :
222                     etoileuces[et] = [uce.ident for uce in uci.uces]
223             if uci.paras != [] :
224                 for et in uci.paras :
225                     if et in etoileuces :
226                         etoileuces[et] += [uce.ident for uce in uci.uces if uce.para == idpara]
227                     else :
228                         etoileuces[et] = [uce.ident for uce in uci.uces if uce.para == idpara]
229                     idpara += 1
230             else :
231                 idpara += 1
232         return etoileuces
233
234     def getucefromid(self, uceid) :
235         if self.iduces is None : self.make_iduces()
236         return self.iduces[uceid]
237
238     def gethapaxnb(self) :
239         return len([None for forme in self.formes if self.formes[forme].freq == 1])
240
241     def getactivesnb(self, key) :
242         return len([lem for lem in self.lems if self.lems[lem].act == key])
243 #    def make_lems(self, lem = True) :
244 #        log.info('make lems')
245 #        self.lems = {}
246 #        for forme in self.formes :
247 #            if self.formes[forme].lem in self.lems :
248 #                if self.formes[forme].ident not in self.lems[self.formes[forme].lem] :
249 #                    self.lems[self.formes[forme].lem][self.formes[forme].ident] = 0
250 #            else :
251 #                    self.lems[self.formes[forme].lem] = {self.formes[forme].ident : 0}
252
253     def getetbyuceid(self, uceid) :
254         if self.uceuci is None : self.uceuci = dict([[uce.ident,uci.ident] for uci in self.ucis for uce in uci.uces])
255         return self.ucis[self.uceuci[uceid]].etoiles
256
257     def make_lems(self, lem = True) :
258         log.info('make lems')
259         self.lems = {}
260         if lem :
261             for forme in self.formes :
262                 if self.formes[forme].lem in self.lems :
263                     if self.formes[forme].ident not in self.lems[self.formes[forme].lem].formes :
264                         self.lems[self.formes[forme].lem].add_forme(self.formes[forme])
265                 else :
266                     self.lems[self.formes[forme].lem] = Lem(self, self.formes[forme])
267         else :
268             self.lems = dict([[forme, Lem(self, self.formes[forme])] for forme in self.formes])
269                 
270     def make_idformes(self) :
271         self.idformes = dict([[self.formes[forme].ident, self.formes[forme]] for forme in self.formes])
272
273     def make_iduces(self) :
274         if self.iduces is None :
275             self.iduces = dict([[uce.ident, uce] for uci in self.ucis for uce in uci.uces])
276
277     def make_lexitable(self, mineff, etoiles, gram = 0) :
278         if gram == 0 :
279             grams = {1:'', 2:''}
280         else :
281             grams = {gram :''}
282         tokeep = [lem for lem in self.lems if self.lems[lem].freq >= mineff and self.lems[lem].act in grams]
283         etuces = [[] for et in etoiles]
284         for uci in self.ucis :
285             get = list(set(uci.etoiles).intersection(etoiles))
286             if len(get) > 1 :
287                 log.info('2 variables sur une ligne')
288             if get != [] :
289                 etuces[etoiles.index(get[0])] += [uce.ident for uce in uci.uces]
290         etuces = [set(val) for val in etuces]
291         tab = []
292         for lem in tokeep :
293             deff = self.getlemuceseff(lem)
294             ucesk = deff.keys()
295             tab.append([lem] + [sum([deff[uce] for uce in et.intersection(ucesk)]) for et in etuces])
296         tab.insert(0, [''] + etoiles)
297         return tab
298     
299     def make_efftype_from_etoiles(self, etoiles) :
300         dtype = {}
301         etuces = [[] for et in etoiles]
302         for uci in self.ucis :
303             get = list(set(uci.etoiles).intersection(etoiles))
304             if len(get) > 1 :
305                 return '2 variables sur la meme ligne'
306             elif get != [] :
307                 etuces[etoiles.index(get[0])] += [uce.ident for uce in uci.uces]
308         etuces = [set(val) for val in etuces]
309         for lem in self.lems :
310             deff = self.getlemuceseff(lem)
311             ucesk = deff.keys()
312             gram = self.lems[lem].gram
313             if gram in dtype :
314                 dtype[gram] = [i + j for i, j in zip(dtype[gram], [sum([deff[uce] for uce in et.intersection(ucesk)]) for et in etuces])]
315             else :
316                 dtype[gram] = [sum([deff[uce] for uce in et.intersection(ucesk)]) for et in etuces]
317         tabout = [[gram] + dtype[gram] for gram in dtype]
318         tabout.insert(0, [''] + etoiles)
319         return tabout
320
321     def make_uceactsize(self, actives) :
322         res = self.getalluces()
323         ucesize = {}
324         for lem in actives: 
325             deff = self.getlemuceseff(lem)
326             for uce in deff :
327                 ucesize[uce] = ucesize.get(uce, 0) + 1
328         return ucesize
329
330     def make_uc(self, actives, lim1, lim2) :
331         uceactsize = self.make_uceactsize(actives)
332         last1 = 0
333         last2 = 0
334         uc1 = [[]]
335         uc2 = [[]]
336         lastpara = 0
337         for uce in [uce for uci in self.ucis for uce in uci.uces] :
338             if uce.para == lastpara :
339                 if last1 <= lim1 :
340                     last1 += uceactsize.get(uce.ident,0)
341                     uc1[-1].append(uce.ident)
342                 else :
343                     uc1.append([uce.ident])
344                     last1 = 0
345                 if last2 <= lim2 :
346                     last2 += uceactsize.get(uce.ident, 0)
347                     uc2[-1].append(uce.ident)
348                 else :
349                     uc2.append([uce.ident])
350                     last2 = 0
351             else :
352                 last1 = uceactsize.get(uce.ident, 0)
353                 last2 = uceactsize.get(uce.ident, 0)
354                 lastpara = uce.para
355                 uc1.append([uce.ident])
356                 uc2.append([uce.ident])
357         return uc1, uc2
358
359     def make_and_write_sparse_matrix_from_uc(self, actives, sizeuc1, sizeuc2, uc1out, uc2out, listuce1out, listuce2out) :
360         uc1, uc2 = self.make_uc(actives, sizeuc1, sizeuc2)
361         log.info('taille uc1 : %i - taille uc2 : %i' % (len(uc1), len(uc2)))
362         self.write_ucmatrix(uc1, actives, uc1out)
363         self.write_ucmatrix(uc2, actives, uc2out)
364         listuce1 = [['uce', 'uc']] + [[`uce`, `i`] for i, ucl in enumerate(uc1) for uce in ucl]
365         listuce2 = [['uce', 'uc']] + [[`uce`, `i`] for i, ucl in enumerate(uc2) for uce in ucl]
366         with open(listuce1out, 'w') as f :
367             f.write('\n'.join([';'.join(line) for line in listuce1]))
368         with open(listuce2out, 'w') as f :
369             f.write('\n'.join([';'.join(line) for line in listuce2]))
370         return len(uc1), len(uc2)
371
372     def write_ucmatrix(self, uc, actives, fileout) :
373         log.info('write uc matrix %s' % fileout)
374         uces_uc = dict([[uce, i] for i, ucl in enumerate(uc) for uce in ucl])
375         deja_la = {}
376         nbl = 0
377         with open(fileout + '~', 'w+') as f :
378             for i, lem in enumerate(actives) :
379                 for uce in self.getlemuces(lem):
380                     if (uces_uc[uce], i) not in deja_la :
381                         nbl += 1
382                         f.write(''.join([' '.join([`uces_uc[uce]+1`,`i+1`,`1`]),'\n']))
383                         deja_la[(uces_uc[uce], i)] = 0
384             f.seek(0)
385             with open(fileout, 'w') as ffin :        
386                 ffin.write("%%%%MatrixMarket matrix coordinate integer general\n%i %i %i\n" % (len(uc), len(actives), nbl))
387                 for line in f :
388                     ffin.write(line)
389         os.remove(fileout + '~')
390         del(deja_la)
391
392     def export_corpus(self, outf) :
393         #outf = 'export_corpus.txt'
394         self.make_iduces()
395         res = self.getalluces()
396         self.make_iduces()
397         actuci = ''
398         actpara = False
399         with open(outf,'w') as f :
400             for uce in res :
401                 if self.iduces[uce[0]].uci == actuci and self.iduces[uce[0]].para == actpara :
402                     f.write(uce[1].encode(self.parametres['syscoding']) + '\n')
403                 elif self.iduces[uce[0]].uci != actuci :
404                     actuci = self.iduces[uce[0]].uci
405                     if self.ucis[self.iduces[uce[0]].uci].paras == [] :
406                         actpara = self.iduces[uce[0]].para
407                         f.write('\n' + ' '.join(self.ucis[self.iduces[uce[0]].uci].etoiles).encode(self.parametres['syscoding']) + '\n' + uce[1].encode(self.parametres['syscoding']) + '\n')
408                     else :
409                         ident = 0
410                         actpara = self.iduces[uce[0]].para
411                         f.write('\n'.join([' '.join(self.ucis[self.iduces[uce[0]].uci].etoiles).encode(self.parametres['syscoding']), self.ucis[self.iduces[uce[0]].uci].paras[ident].encode(self.parametres['syscoding']), uce[1].encode(self.parametres['syscoding'])]) + '\n')
412                 elif self.iduces[uce[0]].para != actpara :
413                     actpara = self.iduces[uce[0]].para
414                     ident += 1
415                     f.write('\n'.join([self.ucis[self.iduces[uce[0]].uci].paras[ident].encode(self.parametres['syscoding']), uce[1].encode(self.parametres['syscoding'])]) + '\n')
416     
417     def export_corpus_classes(self, outf, alc = True, lem = False) :
418         ucecl = {}
419         for i, lc in enumerate(self.lc) :
420             for uce in lc : 
421                 ucecl[uce] = i + 1
422         for uce in self.lc0 :
423             ucecl[uce] = 0
424         res = self.getalluces()
425         self.make_iduces()
426         with open(outf, 'w') as f :
427             for uce in res :
428                 guce = uce[1]
429                 actuci = self.iduces[uce[0]].uci
430                 if lem :
431                     guce = ' '.join([self.formes[forme].lem for forme in guce.split()])
432                 if alc :
433                     etline = ' '.join(self.ucis[self.iduces[uce[0]].uci].etoiles + ['*classe_%i' % ucecl[uce[0]]])
434                 else :
435                     etline = ' '.join(['<' + '='.join(et.split('_')) + '>' for et in self.ucis[self.iduces[uce[0]].uci].etoiles[1:]])
436                 f.write(etline.encode(self.parametres['syscoding']) + '\n')
437                 f.write(guce.encode(self.parametres['syscoding']) + '\n\n')
438
439     def export_classe(self, outf, classe, lem = False) :
440         sts = self.lc[classe - 1] 
441         res = self.getconcorde(sts)
442         self.make_iduces()
443         with open(outf, 'w') as f :
444             for uce in res :
445                 guce = uce[1]
446                 f.write(' '.join(self.ucis[self.iduces[uce[0]].uci].etoiles).encode(self.parametres['syscoding']) + '\n')
447                 if lem :
448                     guce = ' '.join([self.formes[forme].lem for forme in guce.split()])
449                 f.write(guce.encode(self.parametres['syscoding']) + '\n\n')
450
451     def make_and_write_sparse_matrix_from_uces(self, actives, outfile, listuce = False) :
452         log.info('make_and_write_sparse_matrix_from_uces %s' % outfile)
453         nbl = 0
454         with open(outfile + '~', 'w+') as f :
455             for i, lem in enumerate(actives) :
456                 for uce in sorted(self.getlemuces(lem)) :
457                     nbl += 1
458                     f.write(''.join([' '.join([`uce+1`, `i+1`,`1`]),'\n']))
459             f.seek(0)
460             with open(outfile, 'w') as ffin :        
461                 ffin.write("%%%%MatrixMarket matrix coordinate integer general\n%i %i %i\n" % (self.getucenb(), len(actives), nbl))
462                 for line in f :
463                     ffin.write(line)
464         os.remove(outfile + '~')
465         if listuce :
466             with open(listuce, 'w') as f :
467                 f.write('\n'.join(['uce;uc'] + [';'.join([`i`,`i`]) for i in range(0, self.getucenb())]))
468
469     def make_and_write_sparse_matrix_from_uci(self, actives, outfile, listuci = False) :
470         log.info('make_and_write_sparse_matrix_from_ucis %s' % outfile)
471         nbl = 0
472         with open(outfile + '~', 'w+') as f :
473             for i, lem in enumerate(actives) :
474                 for uci in sorted(self.getlemucis(lem)) :
475                     nbl += 1
476                     f.write(''.join([' '.join([`uci+1`, `i+1`,`1`]),'\n']))
477             f.seek(0)
478             with open(outfile, 'w') as ffin :        
479                 ffin.write("%%%%MatrixMarket matrix coordinate integer general\n%i %i %i\n" % (self.getucinb(), len(actives), nbl))
480                 for line in f :
481                     ffin.write(line)
482         os.remove(outfile + '~')
483         if listuci :
484             with open(listuci, 'w') as f :
485                 f.write('\n'.join(['uci;uc'] + [';'.join([`i`,`i`]) for i in range(0, self.getucinb())]))
486                     
487     def make_and_write_sparse_matrix_from_classe(self, actives, uces, outfile) :
488         log.info('make_and_write_sparse_matrix_from_classe %s' % outfile)
489         nbl = 0
490         duces = dict([[uce, i] for i, uce in enumerate(uces)])
491         with open(outfile + '~', 'w+') as f :
492             for i, lem in enumerate(actives) :
493                 uces_ok = list(set(self.getlemuces(lem)).intersection(uces))
494                 for uce in uces_ok :
495                     f.write(''.join([' '.join([`duces[uce]+1`,`i+1`,`1`]),'\n']))
496             f.seek(0)
497             with open(outfile, 'w') as ffin :        
498                 ffin.write("%%%%MatrixMarket matrix coordinate integer general\n%i %i %i\n" % (self.getucenb(), len(actives), nbl))
499                 for line in f :
500                     ffin.write(line)
501         os.remove(outfile + '~')
502     
503     def make_table_with_classe(self, uces, list_act) :
504         table_uce = [[0 for val in list_act] for line in range(0,len(uces))]
505         uces = dict([[uce, i] for i, uce in enumerate(uces)])
506         for i, lem in enumerate(list_act) :
507             lemuces = list(set(self.getlemuces(lem)).intersection(uces))
508             for uce in lemuces :
509                 table_uce[uces[uce]][i] = 1
510         table_uce.insert(0, list_act)
511         return table_uce      
512     
513     def make_pondtable_with_classe(self, uces, list_act) :
514         table_uce = [[0 for val in list_act] for line in range(0,len(uces))]
515         uces = dict([[uce, i] for i, uce in enumerate(uces)])
516         for i, lem in enumerate(list_act) :
517             uceseff = self.getlemuceseff(lem)
518             lemuces = list(set(uceseff.keys()).intersection(uces))
519             for uce in lemuces :
520                 table_uce[uces[uce]][i] = uceseff[uce]
521         table_uce.insert(0, list_act)
522         return table_uce 
523
524     def parse_active(self, gramact, gramsup = None) :
525         log.info('parse actives')
526         for lem in self.lems :
527             if lem.startswith('_') and lem.endswith('_') :
528                 self.lems[lem].act = 2
529             elif self.lems[lem].gram in gramact :
530                 self.lems[lem].act = 1
531             elif gramsup is not None and self.lems[lem].gram not in gramact:
532                 if self.lems[lem].gram in gramsup :
533                     self.lems[lem].act = 2
534                 else :
535                     self.lems[lem].act =  0
536             else :
537                 self.lems[lem].act = 2
538
539     def make_actives_limit(self, limit, key = 1) :
540         if self.idformes is None :
541             self.make_idformes()
542         return [lem for lem in self.lems if self.getlemeff(lem) >= limit and self.lems[lem].act == key]
543     
544     def make_actives_nb(self, nbmax, key) :
545         log.info('make_actives_nb : %i - %i' % (nbmax,key))
546         if self.idformes is None :
547             self.make_idformes()
548         allactives = [[self.lems[lem].freq, lem] for lem in self.lems if self.lems[lem].act == key and self.lems[lem].freq >= 3]
549         self.activenb = len(allactives)
550         allactives = sorted(allactives, reverse = True)
551         if self.activenb == 0 :
552             return [], 0
553         if len(allactives) <= nbmax :
554             log.info('nb = %i - eff min = %i ' % (len(allactives), allactives[-1][0]))
555             return [val[1] for val in allactives], allactives[-1][0]
556         else :
557             effs = [val[0] for val in allactives]
558             if effs.count(effs[nbmax - 1]) > 1 :
559                 lim = effs[nbmax - 1] + 1
560                 nok = True
561                 while nok :
562                     try :
563                         stop = effs.index(lim)
564                         nok = False
565                     except ValueError:
566                         lim -= 1
567             else :
568                 stop = nbmax - 1
569                 lim = effs[stop]
570         log.info('nb actives = %i - eff min = %i ' % (stop + 1, lim))
571         return [val[1] for val in allactives[0:stop + 1]], lim
572
573     def make_and_write_profile(self, actives, ucecl, fileout) :
574         log.info('formes/classes')
575         tab = [[lem] + [len(set(self.getlemuces(lem)).intersection(classe)) for classe in ucecl] for lem in actives]
576         tab = [[line[0]] + [`val` for val in line[1:]] for line in tab if sum(line[1:]) >= 3]
577         with open(fileout, 'w') as f :
578             f.write('\n'.join([';'.join(line) for line in tab]).encode(self.parametres['syscoding']))
579
580     def make_etoiles(self) :
581         etoiles = set([])
582         for uci in self.ucis :
583             etoiles.update(uci.etoiles[1:])
584         return list(etoiles)
585
586     def make_etoiles_dict(self) :
587         etoiles = [et for uci in self.ucis for et in uci.etoiles[1:]]
588         det = {}
589         for etoile in etoiles :
590             et = etoile.split('_')
591             if et[0] in det :
592                 try :
593                     endet = '_'.join(et[1:])
594                     if etoile in det[et[0]] :
595                         det[et[0]][etoile] += 1
596                     else :
597                         det[et[0]][etoile] = 1
598                 except IndexError :
599                     det[et[0]] += 1
600             else :
601                 try :
602                     endet = '_'.join(et[1:])
603                     det[et[0]] = {etoile :1}
604                 except IndexError :
605                     det[et[0]] = 1
606         return det
607
608     def make_etline(self, listet) :
609         etuces = [[] for et in listet]
610         for uci in self.ucis :
611             get = list(set(uci.etoiles).intersection(listet))
612             if len(get) > 1 :
613                 return '2 variables sur la meme ligne'
614             elif get != [] :
615                 etuces[listet.index(get[0])] += [uce.ident for uce in uci.uces]
616         return etuces
617
618     def make_and_write_profile_et(self, ucecl, fileout) :
619         log.info('etoiles/classes')
620         etoileuces = self.getetoileuces()
621         etoileuces = dict([[et, etoileuces[et]] for et in etoileuces if len(etoileuces[et]) > 1])
622         with open(fileout, 'w') as f :
623             f.write('\n'.join([';'.join([et] + [`len(set(etoileuces[et]).intersection(classe))` for classe in ucecl]) for et in etoileuces]).encode(self.parametres['syscoding']))
624         #etoiles = self.make_etoiles()
625         #with open(fileout, 'w') as f :
626         #    f.write('\n'.join([';'.join([etoile] + [`len(set(self.getucesfrometoile(etoile)).intersection(classe))` for classe in ucecl]) for etoile in etoiles]).encode(self.parametres['syscoding']))
627
628     def make_colored_corpus(self) :
629         ucecl = {}
630         for i, lc in enumerate(self.lc) :
631             for uce in lc : 
632                 ucecl[uce] = i + 1
633         for uce in self.lc0 :
634             ucecl[uce] = 0
635         color = ['black'] + colors[len(self.lc) - 1]        
636         txt = '''<html>
637         <meta http-equiv="content-Type" content="text/html; charset=%s" />
638         <body>
639 ''' % sys.getdefaultencoding()
640         res = self.getalluces()
641         self.make_iduces()
642         actuci = ''
643         actpara = False
644         for uce in res :
645             if self.iduces[uce[0]].uci != actuci :
646                 actuci = self.iduces[uce[0]].uci
647                 txt += '<br><hr>' + ' '.join(self.ucis[self.iduces[uce[0]].uci].etoiles) + '<br><br>'
648                 txt += '<font color="%s">' % (color[ucecl[uce[0]]]) + uce[1] + '</font><br><br>'
649             else :
650                 txt += '<font color="%s">' % (color[ucecl[uce[0]]]) + uce[1] + '</font><br><br>'
651         return txt + '\n</body></html>'
652
653     def count_from_list(self, l, d) :
654         for val in l :
655             if val in d :
656                 d[val] += 1
657             else :
658                 d[val] = 1
659         return d
660
661     def count_from_list_cl(self, l, d, a, clnb) :
662         for val in l :
663             if val in d :
664                 d[val][a] += 1
665             else :
666                 d[val] = [0] * clnb
667                 d[val][a] = 1
668         return d
669
670     def find_segments(self, taille_segment, taille_limite) :
671         d = {}
672         for uce in self.getalluces() :
673             uce = uce[1].split()
674             d = self.count_from_list([' '.join(uce[i:i+taille_segment]) for i in range(len(uce)-(taille_segment - 1))], d)
675         l = [[d[val], val] for val in d if d[val] >= 3]
676         del(d)
677         l.sort()
678         if len(l) > taille_limite :
679             l = l[-taille_limite:]
680         return l
681
682     def find_segments_in_classe(self, list_uce, taille_segment, taille_limite):
683         d={}
684         for uce in self.getconcorde(list_uce) :
685             uce = uce[1].split()
686             d =self.count_from_list([' '.join(uce[i:i+taille_segment]) for i in range(len(uce)-(taille_segment - 1))], d)
687         l = [[d[val], val, taille_segment] for val in d if d[val] >= 3]
688         del(d)
689         l.sort()
690         if len(l) > taille_limite :
691             l = l[-taille_limite:]
692         return l
693             
694     def make_segments_profile(self, fileout, lenmin = 3, lenmax = 10, effmin = 50, lem = False) :
695         d = {}
696         for b, classe in enumerate(self.lc) :
697             for uce in self.getconcorde(classe) :
698                 uce = uce[1].split()
699                 if lem :
700                     uce = [self.formes[forme].lem for forme in uce]
701                 for taille_segment in range(lenmin,lenmax) :
702                     d =self.count_from_list_cl([' '.join(uce[i:i+taille_segment]) for i in range(len(uce)-(taille_segment - 1))], d, b, len(self.lc))
703         result = [[seg] + [str(val) for val in d[seg]] for seg in d if sum(d[seg]) >= effmin]
704         with open(fileout, 'w') as f :
705             f.write('\n'.join([';'.join(line) for line in result]))
706     
707     def make_proftype(self, outf) :
708         res = {}
709         for lem in self.lems :
710             gram = self.lems[lem].gram
711             if not gram in res :
712                 res[gram] = [0 for val in self.lc]
713             lemuceeff = self.getlemuceseff(lem)
714             for i, classe in enumerate(self.lc) :
715                 concern = set(classe).intersection(lemuceeff.keys())
716                 res[gram][i] += sum([lemuceeff[uce] for uce in concern])
717         res = [[gram] + [`val` for val in res[gram]] for gram in res]
718         res.sort()
719         with open(outf, 'w') as f :
720             f.write('\n'.join([';'.join(line) for line in res]).encode(self.parametres['syscoding']))
721
722
723     def make_ucecl_from_R(self, filein) :
724         with open(filein, 'rU') as f :
725             c = f.readlines()
726         c.pop(0)
727         self.lc = []
728         for line in c :
729             line = line.replace('\n', '').replace('"', '').split(';')
730             self.lc.append([int(line[0]) - 1, int(line[1])])
731         classesl = [val[1] for val in self.lc]
732         clnb = max(classesl)
733         self.lc = sorted(self.lc, key=itemgetter(1))
734         self.lc = [[uce[0] for uce in self.lc if uce[1] == i] for i in range(clnb+1)]
735         self.lc0 = self.lc.pop(0)
736         #return ucecl
737     
738     def get_stat_by_cluster(self, outf, lclasses = None) :
739         log.info('get_stat_by_cluster')
740         if lclasses is None :
741             lclasses = self.lc
742         t1 = time()
743         occurrences = dict([[i + 1, 0] for i in range(len(lclasses))])
744         formescl = dict([[i + 1, 0] for i in range(len(lclasses))])
745         hapaxcl = dict([[i + 1, 0] for i in range(len(lclasses))])
746         lenclasses = dict([[i+1,len(cl)] for i, cl in enumerate(lclasses)])
747         sets = [set(cl) for cl in lclasses]
748         for forme in self.formes :
749             formeuceeff = self.getformeuceseff(forme)
750             for i, classe in enumerate(lclasses) :
751                 concern = sets[i].intersection(formeuceeff.keys())
752                 if len(concern) :
753                     occurrences[i+1] += sum([formeuceeff[uce] for uce in concern])
754                     formescl[i+1] += 1
755                     if self.formes[forme].freq == 1 :
756                         hapaxcl[i+1] += 1
757         log.info('%f' % (time() - t1))        
758         if outf is not None :
759             toprint = '\n'.join([';'.join([`i`, `occurrences[i]`, `formescl[i]`, `hapaxcl[i]`, `lenclasses[i]`, `float(hapaxcl[i])/float(formescl[i])`]) for i in occurrences])
760             with open(outf, 'w') as f :
761                 f.write(toprint)
762         else :
763             return [[`occurrences[i]`, `formescl[i]`, `hapaxcl[i]`, `lenclasses[i]`, `float(hapaxcl[i])/float(formescl[i])`] for i in occurrences]
764
765     def get_stat_by_et(self, outf, etoiles) :
766         lclasses = [self.getucesfrometoile(etoile) for etoile in etoiles]
767         stats = self.get_stat_by_cluster(None, lclasses)
768         stats = [[etoiles[i]] + val for i, val in enumerate(stats)]
769
770     def gethapaxbyet(self, etoiles) :
771         hapaxuces = [self.getlemuces(forme)[0] for forme in self.lems if self.lems[forme].freq == 1]
772         hucesdict = {}
773         for uce in hapaxuces :
774             if uce in hucesdict :
775                 hucesdict[uce] += 1
776             else :
777                 hucesdict[uce] = 1
778         etuces = [[] for et in etoiles]
779         for uci in self.ucis :
780             get = list(set(uci.etoiles).intersection(etoiles))
781             if len(get) > 1 :
782                 return '2 variables sur la meme ligne'
783             elif get != [] :
784                 etuces[etoiles.index(get[0])] += [uce.ident for uce in uci.uces]
785         etuces = [set(val) for val in etuces]
786         return [sum([hucesdict[uce] for uce in list(etuce.intersection(hapaxuces))]) for etuce in etuces]
787
788     def gethapaxuces(self) :
789         hapaxuces = [self.getlemuces(forme)[0] for forme in self.lems if self.lems[forme].freq == 1]
790         hapax = [forme for forme in self.lems if self.lems[forme].freq == 1]
791         hucesdict = {}
792         for i,uce in enumerate(hapaxuces) :
793             if uce in hucesdict :
794                 hucesdict[uce][0] += 1
795                 hucesdict[uce][1].append(hapax[i])
796             else :
797                 hucesdict[uce] = [1,[hapax[i]]]
798         huces = {}
799         for uce in hucesdict :
800             if hucesdict[uce][0] in huces :
801                 huces[hucesdict[uce][0]].append(uce)
802             else :
803                 huces[hucesdict[uce][0]] = [uce]
804         huces = zip(huces, huces.values())
805         huces.sort(reverse=True)
806         txt = """
807         <html><body>
808         """
809         for nb in huces[0:4] :
810             txt += "<p><h2>%i hapax par uce</h2><p>\n" % nb[0]
811             for uce in nb[1] :
812                 res = self.getconcorde([uce])
813                 for row in res :
814                     ucetxt = ' ' + row[1] + ' '
815                     uceid = row[0]
816                 for hap in hucesdict[uce][1] :
817                     laforme = self.getforme([forme for forme in self.lems[hap].formes][0]).forme
818                     ucetxt = ucetxt.replace(' '+laforme+' ', ' <font color=red>'+laforme+'</font> ')
819                 txt += '<p><b>' + ' '.join(self.getetbyuceid(uceid)) + '</b></p>'
820                 txt += '<p>'+ucetxt+'</p>\n'
821         txt += """
822         </body></html>
823         """
824         with open('/tmp/testhapxuce.html','w') as f :
825             f.write(txt)
826
827     def export_dictionary(self, fileout, syscoding) :
828         listformes = [[self.formes[forme].freq, forme, self.formes[forme].lem, self.formes[forme].gram] for forme in self.formes]
829         listformes.sort(reverse = True)
830         listformes = [forme[1:] + [`forme[0]`] for forme in listformes]
831         with open(fileout, 'w') as f :
832             f.write('\n'.join(['\t'.join(forme) for forme in listformes]).encode(syscoding))
833
834     def export_lems(self, fileout, syscoding) :
835         self.make_idformes()
836         listlem = [[lem, '\t'.join(['\t'.join([self.idformes[forme].forme, `self.lems[lem].formes[forme]`]) for forme in self.lems[lem].formes])] for lem in self.lems]
837         listlem.sort()
838         with open(fileout, 'w') as f :
839             f.write('\n'.join(['\t'.join(lem) for lem in listlem]).encode(syscoding))
840
841
842
843
844 class MakeUciStat :
845     def __init__(self, corpus) :
846         ucinb = corpus.getucinb()
847         ucisize = corpus.getucisize()
848         ucimean = float(sum(ucisize))/float(ucinb)
849         detoile = corpus.make_etoiles_dict() 
850
851 class Uci :
852     def __init__(self, iduci, line, paraset = None) :
853         self.ident = iduci
854         self.etoiles = line.split()
855         self.uces = []
856         if paraset is not None :
857             self.paras = paraset.split()
858         else :
859             self.paras = []
860
861 class Uce :
862     def __init__(self, iduce, idpara, iduci) :
863         self.ident = iduce
864         self.para = idpara
865         self.uci = iduci
866
867 class Word :
868     def __init__(self, word, gramtype, idword, lem = None, freq = None) :
869         self.forme = word
870         self.lem = lem
871         self.gram = gramtype
872         self.ident = idword
873         self.act = 1
874         if freq is not None :
875             self.freq = freq
876         else :
877             self.freq = 1
878
879 class Lem :
880     def __init__(self, parent, forme) :
881         self.formes = {forme.ident : forme.freq}
882         self.gram = forme.gram
883         self.freq = forme.freq
884         self.act = forme.act
885
886     def add_forme(self, forme) :
887         self.formes[forme.ident] = forme.freq
888         self.freq += forme.freq
889
890 def decouperlist(chaine, longueur, longueurOptimale) :
891     """
892         on part du dernier caractère, et on recule jusqu'au début de la chaîne.
893         Si on trouve un '$', c'est fini.
894         Sinon, on cherche le meilleur candidat. C'est-à-dire le rapport poids/distance le plus important.
895     """
896     separateurs = [[u'.', 6.0], [u'?', 6.0], [u'!', 6.0], [u'£$£', 6.0], [u':', 5.0], [u';', 4.0], [u',', 1.0], [u' ', 0.01]]
897     dsep = dict([[val[0],val[1]] for val in separateurs])
898     trouve = False                 # si on a trouvé un bon séparateur
899     iDecoupe = 0                # indice du caractere ou il faut decouper
900     
901     longueur = min(longueur, len(chaine) - 1)
902     chaineTravail = chaine[:longueur + 1]
903     nbCar = longueur
904     meilleur = ['', 0, 0]        # type, poids et position du meilleur separateur
905     
906     try :
907         indice = chaineTravail.index(u'$')
908         trouve = True
909         iDecoupe = indice - 1
910     except ValueError :
911         pass
912     if not trouve:
913         while nbCar >= 0:
914             caractere = chaineTravail[nbCar]
915             distance = abs(longueurOptimale - nbCar) + 1
916             meilleureDistance = abs(longueurOptimale - meilleur[2]) + 1
917             if caractere in dsep :
918                 if (float(dsep[caractere]) / distance) > (float(meilleur[1]) / meilleureDistance) :
919                     meilleur[0] = caractere
920                     meilleur[1] = dsep[caractere]
921                     meilleur[2] = nbCar
922                     trouve = True
923                     iDecoupe = nbCar
924             else :
925                 if (float(dsep[' ']) / distance) > (float(meilleur[1]) / meilleureDistance) :
926                     meilleur[0] = ' '
927                     meilleur[1] = dsep[' ']
928                     meilleur[2] = nbCar
929                     trouve = True
930                     iDecoupe = nbCar
931             nbCar = nbCar - 1
932     # si on a trouvé
933     if trouve:
934         #if meilleur[0] != ' ' :
935         #    fin = chaine[iDecoupe + 1:]
936         #    retour = chaineTravail[:iDecoupe]
937         #else :
938         fin = chaine[iDecoupe + 1:]
939         retour = chaineTravail[:iDecoupe + 1]
940         return len(retour) > 0, retour, fin
941     # si on a rien trouvé
942     return False, chaine, ''
943
944 def testetoile(line) :
945     return line.startswith(u'****')
946
947 def testint(line) :
948     return line[0:4].isdigit() and u'*' in line
949
950 def prep_txtlist(txt) :
951     return txt.split() + [u'$']
952
953 def prep_txtcharact(txt) :
954     return txt + u'$'
955
956 class BuildCorpus :
957     """
958     Class for building a corpus
959     """
960     def __init__(self, infile, parametres_corpus, lexique = None, expressions = None, dlg = None) :
961         log.info('begin building corpus...')
962         self.lexique = lexique
963         self.expressions = expressions
964         self.dlg = dlg
965         self.corpus = Corpus(self, parametres_corpus)
966         self.infile = infile
967         self.last = 0
968         self.lim = parametres_corpus.get('lim', 1000000)
969         self.encoding = parametres_corpus['encoding']
970         self.corpus.pathout = PathOut(filename = parametres_corpus['originalpath'], dirout = parametres_corpus['pathout'])
971         self.corpus.pathout.createdir(parametres_corpus['pathout'])
972         self.corpus.parametres['uuid'] = str(uuid4())
973         self.corpus.parametres['corpus_name'] = os.path.split(self.corpus.parametres['pathout'])[1]
974         self.corpus.parametres['type'] = 'corpus'
975         if self.corpus.parametres['keep_ponct'] :
976             self.ponctuation_espace = [' ', '']
977         else :
978             self.ponctuation_espace =  [' ','.', u'£$£', ';', '?', '!', ',', ':','']
979         self.cleans = []
980         self.tolist = self.corpus.parametres.get('tolist', 0)
981         self.buildcleans()
982         self.prep_makeuce()
983         #create database
984         self.connect()
985         self.dobuild()
986
987     def prep_makeuce(self) :
988         method = self.corpus.parametres.get('ucemethod', 0)
989         if method == 1 :
990             self.decouper = decouperlist
991             self.prep_txt = prep_txtlist
992             self.ucesize = self.corpus.parametres.get('ucesize', 40)
993         elif method == 0 :
994             self.decouper = decoupercharact
995             self.prep_txt = prep_txtcharact
996             self.ucesize = self.corpus.parametres.get('ucesize', 240)
997         log.info('method uce : %s' % method)
998
999     def dobuild(self) :    
1000         t1 = time()
1001         try :
1002             self.read_corpus(self.infile)
1003         except Warning, args :
1004             log.info('pas kool %s' % args)
1005             raise Warning
1006         else :    
1007             self.indexdb()
1008             self.corpus.parametres['ira'] = self.corpus.pathout['Corpus.cira']
1009             self.time = time() - t1
1010             self.dofinish()
1011             DoConf().makeoptions(['corpus'],[self.corpus.parametres], self.corpus.pathout['Corpus.cira'])
1012             log.info('time : %f' % (time() - t1))
1013
1014     def connect(self) :
1015         self.conn_f = sqlite3.connect(self.corpus.pathout['formes.db'])
1016         self.cf = self.conn_f.cursor()
1017         self.cf.execute('CREATE TABLE IF NOT EXISTS uces (id INTEGER, uces TEXT);')
1018         self.cf.execute('CREATE TABLE IF NOT EXISTS eff (id INTEGER, eff TEXT);')
1019         self.conn_f.commit()
1020         self.cf = self.conn_f.cursor()
1021         self.cf.execute('PRAGMA temp_store=MEMORY;')
1022         self.cf.execute('PRAGMA journal_mode=MEMORY;')
1023         self.cf.execute('PRAGMA  synchronous = OFF;')
1024         self.cf.execute('begin')
1025         self.conn = sqlite3.connect(self.corpus.pathout['uces.db'])
1026         self.c = self.conn.cursor()
1027         self.c.execute('CREATE TABLE IF NOT EXISTS uces (id INTEGER, uces TEXT);')
1028         self.conn.commit()
1029         self.c = self.conn.cursor()
1030         self.c.execute('PRAGMA temp_store=MEMORY;')
1031         self.c.execute('PRAGMA journal_mode=MEMORY;')
1032         self.c.execute('PRAGMA  synchronous = OFF;')
1033         self.c.execute('begin')
1034
1035     def indexdb(self) :
1036         #commit index and close db
1037         self.conn.commit()
1038         self.conn_f.commit()
1039         self.cf.execute('CREATE INDEX iduces ON uces (id);')
1040         self.cf.execute('CREATE INDEX ideff ON eff (id);')
1041         self.c.close()
1042         self.cf.close()
1043         #backup corpora
1044         self.conn_corpus = sqlite3.connect(self.corpus.pathout['corpus.db'])
1045         self.ccorpus = self.conn_corpus.cursor()
1046         self.ccorpus.execute('CREATE TABLE IF NOT EXISTS etoiles (uci INTEGER, et TEXT, paras TEXT);')
1047         self.ccorpus.execute('CREATE TABLE IF NOT EXISTS luces (uci INTEGER, para INTEGER, uce INTEGER);')
1048         self.ccorpus.execute('CREATE TABLE IF NOT EXISTS formes (ident INTEGER, forme TEXT, lem TEXT, gram TEXT, freq INTEGER);')
1049         self.conn_corpus.commit()
1050         self.ccorpus = self.conn_corpus.cursor()
1051         self.ccorpus.execute('PRAGMA temp_store=MEMORY;')
1052         self.ccorpus.execute('PRAGMA journal_mode=MEMORY;')
1053         self.ccorpus.execute('PRAGMA  synchronous = OFF;')
1054         self.ccorpus.execute('begin')
1055         self.backup_corpus()
1056         self.ccorpus.execute('CREATE INDEX iduci ON luces (uci);')
1057         self.conn_corpus.commit()
1058         self.conn_corpus.close()
1059         #self.corpus.parametres['corpus_ira'] = self.corpus.pathout['corpus.cira']
1060
1061     def buildcleans(self) :
1062         if self.corpus.parametres.get('lower', 1) :
1063             self.cleans.append(self.dolower)
1064         if self.corpus.parametres.get('firstclean', 1) :
1065             self.cleans.append(self.firstclean)
1066         if self.corpus.parametres['charact'] :
1067             self.rule = self.corpus.parametres.get('keep_caract', u"^a-zA-Z0-9àÀâÂäÄáÁéÉèÈêÊëËìÌîÎïÏòÒôÔöÖùÙûÛüÜçÇßœŒ’ñ.:,;!?*'_")
1068             self.cleans.append(self.docharact)
1069         if self.corpus.parametres.get('expressions', 1) :
1070             self.cleans.append(self.make_expression)
1071         if self.corpus.parametres.get('apos', 1) :
1072             self.cleans.append(self.doapos)
1073         if self.corpus.parametres.get('tiret', 1):
1074             self.cleans.append(self.dotiret)
1075
1076     def make_expression(self,txt) :
1077          for expression in self.expressions:
1078             if expression in txt :
1079                 txt = txt.replace(expression, self.expressions[expression][0])
1080          return txt
1081     
1082     def dolower(self, txt) :
1083         return txt.lower()
1084
1085     def docharact(self, txt) :
1086         #rule = u"^a-zA-Z0-9àÀâÂäÄáÁéÉèÈêÊëËìÌîÎïÏòÒôÔöÖùÙûÛüÜçÇßœŒ’ñ.:,;!?*'_-"
1087         list_keep = u"[" + self.rule + "]+"
1088         return re.sub(list_keep, ' ', txt)
1089     
1090     def doapos(self, txt) :
1091         return txt.replace(u'\'', u' ')
1092
1093     def dotiret(self, txt) :
1094         return txt.replace(u'-', u' ')
1095
1096     def firstclean(self, txt) :
1097         txt = txt.replace(u'’',"'")
1098         txt = txt.replace(u'œ', u'oe')
1099         return txt.replace('...',u' £$£ ').replace('?',' ? ').replace('.',' . ').replace('!', ' ! ').replace(',',' , ').replace(';', ' ; ').replace(':',' : ').replace(u'…', u' £$£ ')
1100
1101     def make_cleans(self, txt) :
1102         for clean in self.cleans :
1103             txt = clean(txt)
1104         return txt
1105
1106     def backup_uce(self) :
1107         if self.corpus.idformesuces != {} :
1108             log.info('backup %i' % len(self.corpus.idformesuces))
1109             touce = [(`forme`, ' '.join([`val` for val in  self.corpus.idformesuces[forme].keys()])) for forme in self.corpus.idformesuces]
1110             toeff = [(`forme`, ' '.join([`val` for val in  self.corpus.idformesuces[forme].values()])) for forme in self.corpus.idformesuces]
1111             self.cf.executemany('INSERT INTO uces VALUES (?,?);', touce)
1112             self.cf.executemany('INSERT INTO eff VALUES (?,?);', toeff)
1113         self.corpus.idformesuces = {}        
1114         self.count = 1
1115
1116     def backup_corpus(self) :
1117         log.info('start backup corpus')
1118         t = time()
1119         for uci in self.corpus.ucis :
1120             self.ccorpus.execute('INSERT INTO etoiles VALUES (?,?,?);' ,(uci.ident,' '.join(uci.etoiles), ' '.join(uci.paras,)))
1121             for uce in uci.uces : 
1122                 self.ccorpus.execute('INSERT INTO luces VALUES (?,?,?);',(`uci.ident`,`uce.para`,`uce.ident`,))
1123         for forme in self.corpus.formes :
1124             self.ccorpus.execute('INSERT INTO formes VALUES (?,?,?,?,?);', (`self.corpus.formes[forme].ident`, forme, self.corpus.formes[forme].lem, self.corpus.formes[forme].gram, `self.corpus.formes[forme].freq`,))
1125         log.info('%f' % (time() - t))
1126
1127     def dofinish(self) :
1128         self.corpus.parametres['date'] = datetime.datetime.now().ctime()
1129         minutes, seconds = divmod(self.time, 60)
1130         hours, minutes = divmod(minutes, 60)
1131         self.corpus.parametres['time'] = '%.0fh %.0fm %.0fs' % (hours, minutes, seconds)
1132         self.corpus.parametres['ucinb'] = self.corpus.getucinb()
1133         self.corpus.parametres['ucenb'] = self.corpus.getucenb()
1134         self.corpus.parametres['occurrences'] = self.corpus.gettotocc()
1135         self.corpus.parametres['formesnb'] = len(self.corpus.formes)
1136         hapaxnb = self.corpus.gethapaxnb()
1137         pourhapaxf = (float(hapaxnb) / len(self.corpus.formes)) * 100
1138         pourhapaxocc = (float(hapaxnb) / self.corpus.parametres['occurrences']) * 100
1139         self.corpus.parametres['hapax'] = '%i - %.2f %% des formes - %.2f %% des occurrences' % (hapaxnb, pourhapaxf, pourhapaxocc)
1140
1141
1142 class BuildFromAlceste(BuildCorpus) :
1143     def read_corpus(self, infile) :
1144         if self.dlg is not None :
1145             self.dlg.Pulse('textes : 0 - segments : 0')
1146         self.limitshow = 0
1147         self.count = 1
1148         if self.corpus.parametres['ucimark'] == 0 :
1149             self.testuci = testetoile
1150         elif  self.corpus.parametres['ucimark'] == 1 :
1151             self.testuci = testint
1152         txt = []
1153         iduci = -1
1154         idpara = -1
1155         iduce = -1
1156         try :
1157             with codecs.open(infile, 'r', self.encoding) as f :
1158                 for linenb, line in enumerate(f) :
1159                     line = line.rstrip('\n\r')
1160                     if self.testuci(line) :
1161                         iduci += 1
1162                         if txt != [] :
1163                             iduce, idpara = self.treattxt(txt, iduce, idpara, iduci - 1)
1164                             txt = []
1165                             self.corpus.ucis.append(Uci(iduci, line))
1166                         else :
1167                             if iduci > 0 :
1168                                 if self.corpus.ucis[-1].uces == [] :
1169                                     log.info(u'Empty text : %i' % linenb)
1170                                     iduci -= 1
1171                                     self.corpus.ucis.pop()
1172                             self.corpus.ucis.append(Uci(iduci, line))
1173                         if self.dlg is not None :
1174                             if not (iduci + 1) % 10 :
1175                                 self.dlg.Pulse('textes : %i - segments : %i' % (iduci + 1, iduce +1))
1176                     elif line.startswith(u'-*') :
1177                         if iduci != -1 :
1178                             if txt != [] :
1179                                 iduce, idpara = self.treattxt(txt, iduce, idpara, iduci)
1180                                 txt = []
1181                             idpara += 1
1182                             self.corpus.ucis[-1].paras.append(line.split()[0])
1183                         else :
1184                             raise Exception('paragrapheOT %i' % linenb)
1185                     elif line.strip() != '' and iduci != -1 :
1186                         txt.append(line)
1187             if txt != [] and iduci != -1 :
1188                 iduce, idpara = self.treattxt(txt, iduce, idpara, iduci)
1189                 del(txt)
1190             else :
1191                 if iduci != -1 :
1192                     iduci -= 1
1193                     self.corpus.ucis.pop()
1194                     log.info(Exception("Empty text %i" % linenb))
1195                 else :
1196                     raise Exception('EmptyText %i' % linenb)
1197             if iduci != -1  and iduce != -1:
1198                 self.backup_uce()
1199             else : 
1200                 log.info(_(u"No Text in corpora. Are you sure of the formatting ?"))
1201                 raise Exception('TextBeforeTextMark %i' % linenb)
1202         except UnicodeDecodeError :
1203             raise Exception("CorpusEncoding")
1204
1205     def treattxt(self, txt, iduce, idpara, iduci) :
1206         if self.corpus.parametres.get('ucemethod', 0) == 2 and self.corpus.parametres['douce']:
1207             txt = 'laphrasepoursplitter'.join(txt)
1208             txt = self.make_cleans(txt)
1209             txt = ' '.join([val for val in txt.split() if val not in self.ponctuation_espace])
1210             ucetxt = txt.split('laphrasepoursplitter')
1211         else :
1212             txt = ' '.join(txt)
1213             txt = self.make_cleans(txt)
1214             ucetxt = self.make_uces(txt, self.corpus.parametres['douce'])
1215         if self.corpus.ucis[-1].paras == [] :
1216             idpara += 1
1217         for uce in ucetxt :
1218             iduce += 1
1219             self.corpus.ucis[-1].uces.append(Uce(iduce, idpara, iduci))
1220             self.c.execute('INSERT INTO uces VALUES(?,?);', (`iduce`,uce))
1221             if not self.tolist :
1222                 uce = uce.split()
1223             else :
1224                 uce = list(uce)
1225             for word in uce :
1226                 self.last += 1
1227                 self.corpus.add_word(word)
1228         log.debug(' '.join([`iduci`,`idpara`,`iduce`]))
1229         if self.last > self.lim :
1230             self.backup_uce()
1231             self.last = 0
1232         return iduce, idpara
1233
1234     def make_uces(self, txt, douce = True, keep_ponct = False) :
1235         txt = ' '.join(txt.split())
1236         if douce :
1237             out = []
1238             reste, texte_uce, suite = self.decouper(self.prep_txt(txt), self.ucesize + 15, self.ucesize)
1239             while reste :
1240                 uce = ' '.join([val for val in texte_uce if val not in self.ponctuation_espace])
1241                 if uce != '' :
1242                     out.append(uce)
1243                 reste, texte_uce, suite = self.decouper(suite, self.ucesize + 15, self.ucesize)
1244             uce = ' '.join([val for val in texte_uce if val not in self.ponctuation_espace])
1245             if uce != '' : 
1246                 out.append(uce)
1247             return out
1248         else :
1249             return [' '.join([val for val in txt.split() if val not in self.ponctuation_espace])]
1250
1251 #decouper (list_sep)
1252 #make_uces (decouper)
1253 #treat_txt (make_uces)
1254 #read (treat_txt)
1255
1256 class Builder :
1257     def __init__(self, parent, dlg = None) :
1258         self.parent = parent
1259         self.dlg = dlg
1260         parametres = DoConf(os.path.join(self.parent.UserConfigPath,'corpus.cfg')).getoptions('corpus')
1261         parametres['pathout'] = PathOut(parent.filename, 'corpus').mkdirout()
1262         dial = CorpusPref(parent, parametres)
1263         dial.CenterOnParent()
1264         dial.txtpath.SetLabel(parent.filename)
1265         #dial.repout_choices.SetValue(parametres['pathout'])
1266         self.res = dial.ShowModal()
1267         if self.res == 5100 :
1268             parametres = dial.doparametres()
1269             parametres['originalpath'] = parent.filename
1270             PathOut().createdir(parametres['pathout'])
1271             ReadLexique(self.parent, lang = parametres['lang'])
1272             if parametres['lang'] != 'other' and  os.path.exists(self.parent.DictPath.get(parametres['lang']+'_exp', 'french_exp')):
1273                 self.parent.expressions = ReadDicoAsDico(self.parent.DictPath.get(parametres['lang']+'_exp', 'french_exp'))
1274             else :
1275                 self.parent.expressions = {}
1276             self.parametres = parametres
1277         else :
1278             if self.dlg is not None :
1279                 self.dlg.Destroy()
1280         dial.Destroy()
1281
1282     def doanalyse(self) :
1283         return BuildFromAlceste(self.parent.filename, self.parametres, self.parent.lexique, self.parent.expressions, dlg = self.dlg).corpus
1284
1285
1286 if __name__ == '__main__' :
1287     t1 = time()
1288     parametres = {'formesdb':'formes.db', 'ucesdb': 'uces.db', 'corpusdb' : 'corpus.db', 'syscoding' : 'utf-8', 'encoding' : encoding}
1289     intro = BuildCorpus(infile, parametres)#, tar_in, tar_infouce)#, tar_formes)
1290     print time() - t1