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