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