add txm import
[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 make_pondtable_with_classe(self, uces, list_act) :
515         table_uce = [[0 for val in list_act] for line in range(0,len(uces))]
516         uces = dict([[uce, i] for i, uce in enumerate(uces)])
517         for i, lem in enumerate(list_act) :
518             uceseff = self.getlemuceseff(lem)
519             lemuces = list(set(uceseff.keys()).intersection(uces))
520             for uce in lemuces :
521                 table_uce[uces[uce]][i] = uceseff[uce]
522         table_uce.insert(0, list_act)
523         return table_uce 
524
525     def parse_active(self, gramact, gramsup = None) :
526         log.info('parse actives')
527         for lem in self.lems :
528             if lem.startswith('_') and lem.endswith('_') :
529                 self.lems[lem].act = 2
530             elif self.lems[lem].gram in gramact :
531                 self.lems[lem].act = 1
532             elif gramsup is not None and self.lems[lem].gram not in gramact:
533                 if self.lems[lem].gram in gramsup :
534                     self.lems[lem].act = 2
535                 else :
536                     self.lems[lem].act =  0
537             else :
538                 self.lems[lem].act = 2
539
540     def make_actives_limit(self, limit, key = 1) :
541         if self.idformes is None :
542             self.make_idformes()
543         return [lem for lem in self.lems if self.getlemeff(lem) >= limit and self.lems[lem].act == key]
544     
545     def make_actives_nb(self, nbmax, key) :
546         log.info('make_actives_nb : %i - %i' % (nbmax,key))
547         if self.idformes is None :
548             self.make_idformes()
549         allactives = [[self.lems[lem].freq, lem] for lem in self.lems if self.lems[lem].act == key and self.lems[lem].freq >= 3]
550         self.activenb = len(allactives)
551         allactives = sorted(allactives, reverse = True)
552         if len(allactives) <= nbmax :
553             log.info('nb = %i - eff min = %i ' % (len(allactives), allactives[-1][0]))
554             return [val[1] for val in allactives], allactives[-1][0]
555         else :
556             effs = [val[0] for val in allactives]
557             if effs.count(effs[nbmax - 1]) > 1 :
558                 lim = effs[nbmax - 1] + 1
559                 nok = True
560                 while nok :
561                     try :
562                         stop = effs.index(lim)
563                         nok = False
564                     except ValueError:
565                         lim -= 1
566             else :
567                 stop = nbmax - 1
568                 lim = effs[stop]
569         log.info('nb actives = %i - eff min = %i ' % (stop + 1, lim))
570         return [val[1] for val in allactives[0:stop + 1]], lim
571
572     def make_and_write_profile(self, actives, ucecl, fileout) :
573         log.info('formes/classes')
574         tab = [[lem] + [len(set(self.getlemuces(lem)).intersection(classe)) for classe in ucecl] for lem in actives]
575         tab = [[line[0]] + [`val` for val in line[1:]] for line in tab if sum(line[1:]) >= 3]
576         with open(fileout, 'w') as f :
577             f.write('\n'.join([';'.join(line) for line in tab]).encode(self.parametres['syscoding']))
578
579     def make_etoiles(self) :
580         etoiles = set([])
581         for uci in self.ucis :
582             etoiles.update(uci.etoiles[1:])
583         return list(etoiles)
584
585     def make_etoiles_dict(self) :
586         etoiles = [et for uci in self.ucis for et in uci.etoiles[1:]]
587         det = {}
588         for etoile in etoiles :
589             et = etoile.split('_')
590             if et[0] in det :
591                 try :
592                     endet = '_'.join(et[1:])
593                     if etoile in det[et[0]] :
594                         det[et[0]][etoile] += 1
595                     else :
596                         det[et[0]][etoile] = 1
597                 except IndexError :
598                     det[et[0]] += 1
599             else :
600                 try :
601                     endet = '_'.join(et[1:])
602                     det[et[0]] = {etoile :1}
603                 except IndexError :
604                     det[et[0]] = 1
605         return det
606
607     def make_etline(self, listet) :
608         etuces = [[] for et in listet]
609         for uci in self.ucis :
610             get = list(set(uci.etoiles).intersection(listet))
611             if len(get) > 1 :
612                 return '2 variables sur la meme ligne'
613             elif get != [] :
614                 etuces[listet.index(get[0])] += [uce.ident for uce in uci.uces]
615         return etuces
616
617     def make_and_write_profile_et(self, ucecl, fileout) :
618         log.info('etoiles/classes')
619         etoileuces = self.getetoileuces()
620         etoileuces = dict([[et, etoileuces[et]] for et in etoileuces if len(etoileuces[et]) > 1])
621         with open(fileout, 'w') as f :
622             f.write('\n'.join([';'.join([et] + [`len(set(etoileuces[et]).intersection(classe))` for classe in ucecl]) for et in etoileuces]).encode(self.parametres['syscoding']))
623         #etoiles = self.make_etoiles()
624         #with open(fileout, 'w') as f :
625         #    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']))
626
627     def make_colored_corpus(self) :
628         ucecl = {}
629         for i, lc in enumerate(self.lc) :
630             for uce in lc : 
631                 ucecl[uce] = i + 1
632         for uce in self.lc0 :
633             ucecl[uce] = 0
634         color = ['black'] + colors[len(self.lc) - 1]        
635         txt = '''<html>
636         <meta http-equiv="content-Type" content="text/html; charset=%s" />
637         <body>
638 ''' % sys.getdefaultencoding()
639         res = self.getalluces()
640         self.make_iduces()
641         actuci = ''
642         actpara = False
643         for uce in res :
644             if self.iduces[uce[0]].uci != actuci :
645                 actuci = self.iduces[uce[0]].uci
646                 txt += '<br><hr>' + ' '.join(self.ucis[self.iduces[uce[0]].uci].etoiles) + '<br><br>'
647                 txt += '<font color="%s">' % (color[ucecl[uce[0]]]) + uce[1] + '</font><br><br>'
648             else :
649                 txt += '<font color="%s">' % (color[ucecl[uce[0]]]) + uce[1] + '</font><br><br>'
650         return txt + '\n</body></html>'
651
652     def count_from_list(self, l, d) :
653         for val in l :
654             if val in d :
655                 d[val] += 1
656             else :
657                 d[val] = 1
658         return d
659
660     def count_from_list_cl(self, l, d, a, clnb) :
661         for val in l :
662             if val in d :
663                 d[val][a] += 1
664             else :
665                 d[val] = [0] * clnb
666                 d[val][a] = 1
667         return d
668
669     def find_segments(self, taille_segment, taille_limite) :
670         d = {}
671         for uce in self.getalluces() :
672             uce = uce[1].split()
673             d = self.count_from_list([' '.join(uce[i:i+taille_segment]) for i in range(len(uce)-(taille_segment - 1))], d)
674         l = [[d[val], val] for val in d if d[val] >= 3]
675         del(d)
676         l.sort()
677         if len(l) > taille_limite :
678             l = l[-taille_limite:]
679         return l
680
681     def find_segments_in_classe(self, list_uce, taille_segment, taille_limite):
682         d={}
683         for uce in self.getconcorde(list_uce) :
684             uce = uce[1].split()
685             d =self.count_from_list([' '.join(uce[i:i+taille_segment]) for i in range(len(uce)-(taille_segment - 1))], d)
686         l = [[d[val], val, taille_segment] for val in d if d[val] >= 3]
687         del(d)
688         l.sort()
689         if len(l) > taille_limite :
690             l = l[-taille_limite:]
691         return l
692             
693     def make_segments_profile(self, fileout, lenmin = 3, lenmax = 10, effmin = 50, lem = False) :
694         d = {}
695         for b, classe in enumerate(self.lc) :
696             for uce in self.getconcorde(classe) :
697                 uce = uce[1].split()
698                 if lem :
699                     uce = [self.formes[forme].lem for forme in uce]
700                 for taille_segment in range(lenmin,lenmax) :
701                     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))
702         result = [[seg] + [str(val) for val in d[seg]] for seg in d if sum(d[seg]) >= effmin]
703         with open(fileout, 'w') as f :
704             f.write('\n'.join([';'.join(line) for line in result]))
705     
706     def make_proftype(self, outf) :
707         res = {}
708         for lem in self.lems :
709             gram = self.lems[lem].gram
710             if not gram in res :
711                 res[gram] = [0 for val in self.lc]
712             lemuceeff = self.getlemuceseff(lem)
713             for i, classe in enumerate(self.lc) :
714                 concern = set(classe).intersection(lemuceeff.keys())
715                 res[gram][i] += sum([lemuceeff[uce] for uce in concern])
716         res = [[gram] + [`val` for val in res[gram]] for gram in res]
717         res.sort()
718         with open(outf, 'w') as f :
719             f.write('\n'.join([';'.join(line) for line in res]).encode(self.parametres['syscoding']))
720
721
722     def make_ucecl_from_R(self, filein) :
723         with open(filein, 'rU') as f :
724             c = f.readlines()
725         c.pop(0)
726         self.lc = []
727         for line in c :
728             line = line.replace('\n', '').replace('"', '').split(';')
729             self.lc.append([int(line[0]) - 1, int(line[1])])
730         classesl = [val[1] for val in self.lc]
731         clnb = max(classesl)
732         self.lc = sorted(self.lc, key=itemgetter(1))
733         self.lc = [[uce[0] for uce in self.lc if uce[1] == i] for i in range(clnb+1)]
734         self.lc0 = self.lc.pop(0)
735         #return ucecl
736     
737     def get_stat_by_cluster(self, outf, lclasses = None) :
738         log.info('get_stat_by_cluster')
739         if lclasses is None :
740             lclasses = self.lc
741         t1 = time()
742         occurrences = dict([[i + 1, 0] for i in range(len(lclasses))])
743         formescl = dict([[i + 1, 0] for i in range(len(lclasses))])
744         hapaxcl = dict([[i + 1, 0] for i in range(len(lclasses))])
745         lenclasses = dict([[i+1,len(cl)] for i, cl in enumerate(lclasses)])
746         sets = [set(cl) for cl in lclasses]
747         for forme in self.formes :
748             formeuceeff = self.getformeuceseff(forme)
749             for i, classe in enumerate(lclasses) :
750                 concern = sets[i].intersection(formeuceeff.keys())
751                 if len(concern) :
752                     occurrences[i+1] += sum([formeuceeff[uce] for uce in concern])
753                     formescl[i+1] += 1
754                     if self.formes[forme].freq == 1 :
755                         hapaxcl[i+1] += 1
756         log.info('%f' % (time() - t1))        
757         if outf is not None :
758             toprint = '\n'.join([';'.join([`i`, `occurrences[i]`, `formescl[i]`, `hapaxcl[i]`, `lenclasses[i]`, `float(hapaxcl[i])/float(formescl[i])`]) for i in occurrences])
759             with open(outf, 'w') as f :
760                 f.write(toprint)
761         else :
762             return [[`occurrences[i]`, `formescl[i]`, `hapaxcl[i]`, `lenclasses[i]`, `float(hapaxcl[i])/float(formescl[i])`] for i in occurrences]
763
764     def get_stat_by_et(self, outf, etoiles) :
765         lclasses = [self.getucesfrometoile(etoile) for etoile in etoiles]
766         stats = self.get_stat_by_cluster(None, lclasses)
767         stats = [[etoiles[i]] + val for i, val in enumerate(stats)]
768
769     def gethapaxbyet(self, etoiles) :
770         hapaxuces = [self.getlemuces(forme)[0] for forme in self.lems if self.lems[forme].freq == 1]
771         hucesdict = {}
772         for uce in hapaxuces :
773             if uce in hucesdict :
774                 hucesdict[uce] += 1
775             else :
776                 hucesdict[uce] = 1
777         etuces = [[] for et in etoiles]
778         for uci in self.ucis :
779             get = list(set(uci.etoiles).intersection(etoiles))
780             if len(get) > 1 :
781                 return '2 variables sur la meme ligne'
782             elif get != [] :
783                 etuces[etoiles.index(get[0])] += [uce.ident for uce in uci.uces]
784         etuces = [set(val) for val in etuces]
785         return [sum([hucesdict[uce] for uce in list(etuce.intersection(hapaxuces))]) for etuce in etuces]
786
787     def gethapaxuces(self) :
788         hapaxuces = [self.getlemuces(forme)[0] for forme in self.lems if self.lems[forme].freq == 1]
789         hapax = [forme for forme in self.lems if self.lems[forme].freq == 1]
790         hucesdict = {}
791         for i,uce in enumerate(hapaxuces) :
792             if uce in hucesdict :
793                 hucesdict[uce][0] += 1
794                 hucesdict[uce][1].append(hapax[i])
795             else :
796                 hucesdict[uce] = [1,[hapax[i]]]
797         huces = {}
798         for uce in hucesdict :
799             if hucesdict[uce][0] in huces :
800                 huces[hucesdict[uce][0]].append(uce)
801             else :
802                 huces[hucesdict[uce][0]] = [uce]
803         huces = zip(huces, huces.values())
804         huces.sort(reverse=True)
805         txt = """
806         <html><body>
807         """
808         for nb in huces[0:4] :
809             txt += "<p><h2>%i hapax par uce</h2><p>\n" % nb[0]
810             for uce in nb[1] :
811                 res = self.getconcorde([uce])
812                 for row in res :
813                     ucetxt = ' ' + row[1] + ' '
814                     uceid = row[0]
815                 for hap in hucesdict[uce][1] :
816                     laforme = self.getforme([forme for forme in self.lems[hap].formes][0]).forme
817                     ucetxt = ucetxt.replace(' '+laforme+' ', ' <font color=red>'+laforme+'</font> ')
818                 txt += '<p><b>' + ' '.join(self.getetbyuceid(uceid)) + '</b></p>'
819                 txt += '<p>'+ucetxt+'</p>\n'
820         txt += """
821         </body></html>
822         """
823         with open('/tmp/testhapxuce.html','w') as f :
824             f.write(txt)
825
826     def export_dictionary(self, fileout, syscoding) :
827         listformes = [[self.formes[forme].freq, forme, self.formes[forme].lem, self.formes[forme].gram] for forme in self.formes]
828         listformes.sort(reverse = True)
829         listformes = [forme[1:] + [`forme[0]`] for forme in listformes]
830         with open(fileout, 'w') as f :
831             f.write('\n'.join(['\t'.join(forme) for forme in listformes]).encode(syscoding))
832
833     def export_lems(self, fileout, syscoding) :
834         self.make_idformes()
835         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]
836         listlem.sort()
837         with open(fileout, 'w') as f :
838             f.write('\n'.join(['\t'.join(lem) for lem in listlem]).encode(syscoding))
839
840
841
842
843 class MakeUciStat :
844     def __init__(self, corpus) :
845         ucinb = corpus.getucinb()
846         ucisize = corpus.getucisize()
847         ucimean = float(sum(ucisize))/float(ucinb)
848         detoile = corpus.make_etoiles_dict()
849         
850
851 class Uci :
852     def __init__(self, iduci, line, paraset = None) :
853         self.ident = iduci
854         self.etoiles = line.split()
855         self.uces = []
856         if paraset is not None :
857             self.paras = paraset.split()
858         else :
859             self.paras = []
860
861 class Uce :
862     def __init__(self, iduce, idpara, iduci) :
863         self.ident = iduce
864         self.para = idpara
865         self.uci = iduci
866
867 class Word :
868     def __init__(self, word, gramtype, idword, lem = None, freq = None) :
869         self.forme = word
870         self.lem = lem
871         self.gram = gramtype
872         self.ident = idword
873         self.act = 1
874         if freq is not None :
875             self.freq = freq
876         else :
877             self.freq = 1
878
879 class Lem :
880     def __init__(self, parent, forme) :
881         self.formes = {forme.ident : forme.freq}
882         self.gram = forme.gram
883         self.freq = forme.freq
884         self.act = forme.act
885
886     def add_forme(self, forme) :
887         self.formes[forme.ident] = forme.freq
888         self.freq += forme.freq
889
890 def decouperlist(chaine, longueur, longueurOptimale) :
891     """
892         on part du dernier caractère, et on recule jusqu'au début de la chaîne.
893         Si on trouve un '$', c'est fini.
894         Sinon, on cherche le meilleur candidat. C'est-à-dire le rapport poids/distance le plus important.
895     """
896     separateurs = [[u'.', 6.0], [u'?', 6.0], [u'!', 6.0], [u'£$£', 6.0], [u':', 5.0], [u';', 4.0], [u',', 1.0], [u' ', 0.01]]
897     dsep = dict([[val[0],val[1]] for val in separateurs])
898     trouve = False                 # si on a trouvé un bon séparateur
899     iDecoupe = 0                # indice du caractere ou il faut decouper
900     
901     longueur = min(longueur, len(chaine) - 1)
902     chaineTravail = chaine[:longueur + 1]
903     nbCar = longueur
904     meilleur = ['', 0, 0]        # type, poids et position du meilleur separateur
905     
906     try :
907         indice = chaineTravail.index(u'$')
908         trouve = True
909         iDecoupe = indice - 1
910     except ValueError :
911         pass
912     if not trouve:
913         while nbCar >= 0:
914             caractere = chaineTravail[nbCar]
915             distance = abs(longueurOptimale - nbCar) + 1
916             meilleureDistance = abs(longueurOptimale - meilleur[2]) + 1
917             if caractere in dsep :
918                 if (float(dsep[caractere]) / distance) > (float(meilleur[1]) / meilleureDistance) :
919                     meilleur[0] = caractere
920                     meilleur[1] = dsep[caractere]
921                     meilleur[2] = nbCar
922                     trouve = True
923                     iDecoupe = nbCar
924             else :
925                 if (float(dsep[' ']) / distance) > (float(meilleur[1]) / meilleureDistance) :
926                     meilleur[0] = ' '
927                     meilleur[1] = dsep[' ']
928                     meilleur[2] = nbCar
929                     trouve = True
930                     iDecoupe = nbCar
931             nbCar = nbCar - 1
932     # si on a trouvé
933     if trouve:
934         #if meilleur[0] != ' ' :
935         #    fin = chaine[iDecoupe + 1:]
936         #    retour = chaineTravail[:iDecoupe]
937         #else :
938         fin = chaine[iDecoupe + 1:]
939         retour = chaineTravail[:iDecoupe + 1]
940         return len(retour) > 0, retour, fin
941     # si on a rien trouvé
942     return False, chaine, ''
943
944 def testetoile(line) :
945     return line.startswith(u'****')
946
947 def testint(line) :
948     return line[0:4].isdigit() and u'*' in line
949
950 def prep_txtlist(txt) :
951     return txt.split() + [u'$']
952
953 def prep_txtcharact(txt) :
954     return txt + u'$'
955
956 class BuildCorpus :
957     """
958     Class for building a corpus
959     """
960     def __init__(self, infile, parametres_corpus, lexique = None, expressions = None, dlg = None) :
961         log.info('begin building corpus...')
962         self.lexique = lexique
963         self.expressions = expressions
964         self.dlg = dlg
965         self.corpus = Corpus(self, parametres_corpus)
966         self.infile = infile
967         self.last = 0
968         self.lim = parametres_corpus.get('lim', 1000000)
969         self.encoding = parametres_corpus['encoding']
970         self.corpus.pathout = PathOut(filename = parametres_corpus['originalpath'], dirout = parametres_corpus['pathout'])
971         self.corpus.pathout.createdir(parametres_corpus['pathout'])
972         self.corpus.parametres['uuid'] = str(uuid4())
973         self.corpus.parametres['corpus_name'] = os.path.split(self.corpus.parametres['pathout'])[1]
974         self.corpus.parametres['type'] = 'corpus'
975         if self.corpus.parametres['keep_ponct'] :
976             self.ponctuation_espace = [' ', '']
977         else :
978             self.ponctuation_espace =  [' ','.', u'£$£', ';', '?', '!', ',', ':','']
979         self.cleans = []
980         self.tolist = self.corpus.parametres.get('tolist', 0)
981         self.buildcleans()
982         self.prep_makeuce()
983         #create database
984         self.connect()
985         self.dobuild()
986
987     def prep_makeuce(self) :
988         method = self.corpus.parametres.get('ucemethod', 0)
989         if method == 1 :
990             self.decouper = decouperlist
991             self.prep_txt = prep_txtlist
992             self.ucesize = self.corpus.parametres.get('ucesize', 40)
993         elif method == 0 :
994             self.decouper = decoupercharact
995             self.prep_txt = prep_txtcharact
996             self.ucesize = self.corpus.parametres.get('ucesize', 240)
997         log.info('method uce : %s' % method)
998
999     def dobuild(self) :    
1000         t1 = time()
1001         try :
1002             self.read_corpus(self.infile)
1003         except Warning, args :
1004             log.info('pas kool %s' % args)
1005             raise Warning
1006         else :    
1007             self.indexdb()
1008             self.corpus.parametres['ira'] = self.corpus.pathout['Corpus.cira']
1009             self.time = time() - t1
1010             self.dofinish()
1011             DoConf().makeoptions(['corpus'],[self.corpus.parametres], self.corpus.pathout['Corpus.cira'])
1012             log.info('time : %f' % (time() - t1))
1013
1014     def connect(self) :
1015         self.conn_f = sqlite3.connect(self.corpus.pathout['formes.db'])
1016         self.cf = self.conn_f.cursor()
1017         self.cf.execute('CREATE TABLE IF NOT EXISTS uces (id INTEGER, uces TEXT);')
1018         self.cf.execute('CREATE TABLE IF NOT EXISTS eff (id INTEGER, eff TEXT);')
1019         self.conn_f.commit()
1020         self.cf = self.conn_f.cursor()
1021         self.cf.execute('PRAGMA temp_store=MEMORY;')
1022         self.cf.execute('PRAGMA journal_mode=MEMORY;')
1023         self.cf.execute('PRAGMA  synchronous = OFF;')
1024         self.cf.execute('begin')
1025         self.conn = sqlite3.connect(self.corpus.pathout['uces.db'])
1026         self.c = self.conn.cursor()
1027         self.c.execute('CREATE TABLE IF NOT EXISTS uces (id INTEGER, uces TEXT);')
1028         self.conn.commit()
1029         self.c = self.conn.cursor()
1030         self.c.execute('PRAGMA temp_store=MEMORY;')
1031         self.c.execute('PRAGMA journal_mode=MEMORY;')
1032         self.c.execute('PRAGMA  synchronous = OFF;')
1033         self.c.execute('begin')
1034
1035     def indexdb(self) :
1036         #commit index and close db
1037         self.conn.commit()
1038         self.conn_f.commit()
1039         self.cf.execute('CREATE INDEX iduces ON uces (id);')
1040         self.cf.execute('CREATE INDEX ideff ON eff (id);')
1041         self.c.close()
1042         self.cf.close()
1043         #backup corpora
1044         self.conn_corpus = sqlite3.connect(self.corpus.pathout['corpus.db'])
1045         self.ccorpus = self.conn_corpus.cursor()
1046         self.ccorpus.execute('CREATE TABLE IF NOT EXISTS etoiles (uci INTEGER, et TEXT, paras TEXT);')
1047         self.ccorpus.execute('CREATE TABLE IF NOT EXISTS luces (uci INTEGER, para INTEGER, uce INTEGER);')
1048         self.ccorpus.execute('CREATE TABLE IF NOT EXISTS formes (ident INTEGER, forme TEXT, lem TEXT, gram TEXT, freq INTEGER);')
1049         self.conn_corpus.commit()
1050         self.ccorpus = self.conn_corpus.cursor()
1051         self.ccorpus.execute('PRAGMA temp_store=MEMORY;')
1052         self.ccorpus.execute('PRAGMA journal_mode=MEMORY;')
1053         self.ccorpus.execute('PRAGMA  synchronous = OFF;')
1054         self.ccorpus.execute('begin')
1055         self.backup_corpus()
1056         self.ccorpus.execute('CREATE INDEX iduci ON luces (uci);')
1057         self.conn_corpus.commit()
1058         self.conn_corpus.close()
1059         #self.corpus.parametres['corpus_ira'] = self.corpus.pathout['corpus.cira']
1060
1061     def buildcleans(self) :
1062         if self.corpus.parametres.get('lower', 1) :
1063             self.cleans.append(self.dolower)
1064         if self.corpus.parametres.get('firstclean', 1) :
1065             self.cleans.append(self.firstclean)
1066         if self.corpus.parametres['charact'] :
1067             self.rule = self.corpus.parametres.get('keep_caract', u"^a-zA-Z0-9àÀâÂäÄáÁéÉèÈêÊëËìÌîÎïÏòÒôÔöÖùÙûÛüÜçÇßœŒ’ñ.:,;!?*'_")
1068             self.cleans.append(self.docharact)
1069         if self.corpus.parametres.get('expressions', 1) :
1070             self.cleans.append(self.make_expression)
1071         if self.corpus.parametres.get('apos', 1) :
1072             self.cleans.append(self.doapos)
1073         if self.corpus.parametres.get('tiret', 1):
1074             self.cleans.append(self.dotiret)
1075
1076     def make_expression(self,txt) :
1077          for expression in self.expressions:
1078             if expression in txt :
1079                 txt = txt.replace(expression, self.expressions[expression][0])
1080          return txt
1081     
1082     def dolower(self, txt) :
1083         return txt.lower()
1084
1085     def docharact(self, txt) :
1086         #rule = u"^a-zA-Z0-9àÀâÂäÄáÁéÉèÈêÊëËìÌîÎïÏòÒôÔöÖùÙûÛüÜçÇßœŒ’ñ.:,;!?*'_-"
1087         list_keep = u"[" + self.rule + "]+"
1088         return re.sub(list_keep, ' ', txt)
1089     
1090     def doapos(self, txt) :
1091         return txt.replace(u'\'', u' ')
1092
1093     def dotiret(self, txt) :
1094         return txt.replace(u'-', u' ')
1095
1096     def firstclean(self, txt) :
1097         txt = txt.replace(u'’',"'")
1098         txt = txt.replace(u'œ', u'oe')
1099         return txt.replace('...',u' £$£ ').replace('?',' ? ').replace('.',' . ').replace('!', ' ! ').replace(',',' , ').replace(';', ' ; ').replace(':',' : ').replace(u'…', u' £$£ ')
1100
1101     def make_cleans(self, txt) :
1102         for clean in self.cleans :
1103             txt = clean(txt)
1104         return txt
1105
1106     def backup_uce(self) :
1107         if self.corpus.idformesuces != {} :
1108             log.info('backup %i' % len(self.corpus.idformesuces))
1109             touce = [(`forme`, ' '.join([`val` for val in  self.corpus.idformesuces[forme].keys()])) for forme in self.corpus.idformesuces]
1110             toeff = [(`forme`, ' '.join([`val` for val in  self.corpus.idformesuces[forme].values()])) for forme in self.corpus.idformesuces]
1111             self.cf.executemany('INSERT INTO uces VALUES (?,?);', touce)
1112             self.cf.executemany('INSERT INTO eff VALUES (?,?);', toeff)
1113         self.corpus.idformesuces = {}        
1114         self.count = 1
1115
1116     def backup_corpus(self) :
1117         log.info('start backup corpus')
1118         t = time()
1119         for uci in self.corpus.ucis :
1120             self.ccorpus.execute('INSERT INTO etoiles VALUES (?,?,?);' ,(uci.ident,' '.join(uci.etoiles), ' '.join(uci.paras,)))
1121             for uce in uci.uces : 
1122                 self.ccorpus.execute('INSERT INTO luces VALUES (?,?,?);',(`uci.ident`,`uce.para`,`uce.ident`,))
1123         for forme in self.corpus.formes :
1124             self.ccorpus.execute('INSERT INTO formes VALUES (?,?,?,?,?);', (`self.corpus.formes[forme].ident`, forme, self.corpus.formes[forme].lem, self.corpus.formes[forme].gram, `self.corpus.formes[forme].freq`,))
1125         log.info('%f' % (time() - t))
1126
1127     def dofinish(self) :
1128         self.corpus.parametres['date'] = datetime.datetime.now().ctime()
1129         minutes, seconds = divmod(self.time, 60)
1130         hours, minutes = divmod(minutes, 60)
1131         self.corpus.parametres['time'] = '%.0fh %.0fm %.0fs' % (hours, minutes, seconds)
1132         self.corpus.parametres['ucinb'] = self.corpus.getucinb()
1133         self.corpus.parametres['ucenb'] = self.corpus.getucenb()
1134         self.corpus.parametres['occurrences'] = self.corpus.gettotocc()
1135         self.corpus.parametres['formesnb'] = len(self.corpus.formes)
1136         hapaxnb = self.corpus.gethapaxnb()
1137         pourhapaxf = (float(hapaxnb) / len(self.corpus.formes)) * 100
1138         pourhapaxocc = (float(hapaxnb) / self.corpus.parametres['occurrences']) * 100
1139         self.corpus.parametres['hapax'] = '%i - %.2f %% des formes - %.2f %% des occurrences' % (hapaxnb, pourhapaxf, pourhapaxocc)
1140
1141
1142 class BuildFromAlceste(BuildCorpus) :
1143     def read_corpus(self, infile) :
1144         if self.dlg is not None :
1145             self.dlg.Pulse('textes : 0 - segments : 0')
1146         self.limitshow = 0
1147         self.count = 1
1148         if self.corpus.parametres['ucimark'] == 0 :
1149             self.testuci = testetoile
1150         elif  self.corpus.parametres['ucimark'] == 1 :
1151             self.testuci = testint
1152         txt = []
1153         iduci = -1
1154         idpara = -1
1155         iduce = -1
1156         try :
1157             with codecs.open(infile, 'r', self.encoding) as f :
1158                 for linenb, line in enumerate(f) :
1159                     line = line.rstrip('\n\r')
1160                     if self.testuci(line) :
1161                         iduci += 1
1162                         if txt != [] :
1163                             iduce, idpara = self.treattxt(txt, iduce, idpara, iduci - 1)
1164                             txt = []
1165                             self.corpus.ucis.append(Uci(iduci, line))
1166                         else :
1167                             if iduci > 0 :
1168                                 if self.corpus.ucis[-1].uces == [] :
1169                                     log.info(u'Empty text : %i' % linenb)
1170                                     iduci -= 1
1171                                     self.corpus.ucis.pop()
1172                             self.corpus.ucis.append(Uci(iduci, line))
1173                         if self.dlg is not None :
1174                             if not (iduci + 1) % 10 :
1175                                 self.dlg.Pulse('textes : %i - segments : %i' % (iduci + 1, iduce +1))
1176                     elif line.startswith(u'-*') :
1177                         if iduci != -1 :
1178                             if txt != [] :
1179                                 iduce, idpara = self.treattxt(txt, iduce, idpara, iduci)
1180                                 txt = []
1181                             idpara += 1
1182                             self.corpus.ucis[-1].paras.append(line.split()[0])
1183                         else :
1184                             raise Exception('paragrapheOT %i' % linenb)
1185                     elif line.strip() != '' and iduci != -1 :
1186                         txt.append(line)
1187             if txt != [] and iduci != -1 :
1188                 iduce, idpara = self.treattxt(txt, iduce, idpara, iduci)
1189                 del(txt)
1190             else :
1191                 if iduci != -1 :
1192                     iduci -= 1
1193                     self.corpus.ucis.pop()
1194                     log.info(Exception("Empty text %i" % linenb))
1195                 else :
1196                     raise Exception('EmptyText %i' % linenb)
1197             if iduci != -1  and iduce != -1:
1198                 self.backup_uce()
1199             else : 
1200                 log.info(_(u"No Text in corpora. Are you sure of the formatting ?"))
1201                 raise Exception('TextBeforeTextMark %i' % linenb)
1202         except UnicodeDecodeError :
1203             raise Exception("CorpusEncoding")
1204
1205     def treattxt(self, txt, iduce, idpara, iduci) :
1206         if self.corpus.parametres.get('ucemethod', 0) == 2 and self.corpus.parametres['douce']:
1207             txt = 'laphrasepoursplitter'.join(txt)
1208             txt = self.make_cleans(txt)
1209             txt = ' '.join([val for val in txt.split() if val not in self.ponctuation_espace])
1210             ucetxt = txt.split('laphrasepoursplitter')
1211         else :
1212             txt = ' '.join(txt)
1213             txt = self.make_cleans(txt)
1214             ucetxt = self.make_uces(txt, self.corpus.parametres['douce'])
1215         if self.corpus.ucis[-1].paras == [] :
1216             idpara += 1
1217         for uce in ucetxt :
1218             iduce += 1
1219             self.corpus.ucis[-1].uces.append(Uce(iduce, idpara, iduci))
1220             self.c.execute('INSERT INTO uces VALUES(?,?);', (`iduce`,uce))
1221             if not self.tolist :
1222                 uce = uce.split()
1223             else :
1224                 uce = list(uce)
1225             for word in uce :
1226                 self.last += 1
1227                 self.corpus.add_word(word)
1228         log.debug(' '.join([`iduci`,`idpara`,`iduce`]))
1229         if self.last > self.lim :
1230             self.backup_uce()
1231             self.last = 0
1232         return iduce, idpara
1233
1234     def make_uces(self, txt, douce = True, keep_ponct = False) :
1235         txt = ' '.join(txt.split())
1236         if douce :
1237             out = []
1238             reste, texte_uce, suite = self.decouper(self.prep_txt(txt), self.ucesize + 15, self.ucesize)
1239             while reste :
1240                 uce = ' '.join([val for val in texte_uce if val not in self.ponctuation_espace])
1241                 if uce != '' :
1242                     out.append(uce)
1243                 reste, texte_uce, suite = self.decouper(suite, self.ucesize + 15, self.ucesize)
1244             uce = ' '.join([val for val in texte_uce if val not in self.ponctuation_espace])
1245             if uce != '' : 
1246                 out.append(uce)
1247             return out
1248         else :
1249             return [' '.join([val for val in txt.split() if val not in self.ponctuation_espace])]
1250
1251 #decouper (list_sep)
1252 #make_uces (decouper)
1253 #treat_txt (make_uces)
1254 #read (treat_txt)
1255
1256 class Builder :
1257     def __init__(self, parent, dlg = None) :
1258         self.parent = parent
1259         self.dlg = dlg
1260         parametres = DoConf(os.path.join(self.parent.UserConfigPath,'corpus.cfg')).getoptions('corpus')
1261         parametres['pathout'] = PathOut(parent.filename, 'corpus').mkdirout()
1262         dial = CorpusPref(parent, parametres)
1263         dial.CenterOnParent()
1264         dial.txtpath.SetLabel(parent.filename)
1265         #dial.repout_choices.SetValue(parametres['pathout'])
1266         self.res = dial.ShowModal()
1267         if self.res == 5100 :
1268             parametres = dial.doparametres()
1269             parametres['originalpath'] = parent.filename
1270             PathOut().createdir(parametres['pathout'])
1271             ReadLexique(self.parent, lang = parametres['lang'])
1272             if parametres['lang'] != 'other' and  os.path.exists(self.parent.DictPath.get(parametres['lang']+'_exp', 'french_exp')):
1273                 self.parent.expressions = ReadDicoAsDico(self.parent.DictPath.get(parametres['lang']+'_exp', 'french_exp'))
1274             else :
1275                 self.parent.expressions = {}
1276             self.parametres = parametres
1277         else :
1278             if self.dlg is not None :
1279                 self.dlg.Destroy()
1280         dial.Destroy()
1281
1282     def doanalyse(self) :
1283         return BuildFromAlceste(self.parent.filename, self.parametres, self.parent.lexique, self.parent.expressions, dlg = self.dlg).corpus
1284
1285
1286 if __name__ == '__main__' :
1287     t1 = time()
1288     parametres = {'formesdb':'formes.db', 'ucesdb': 'uces.db', 'corpusdb' : 'corpus.db', 'syscoding' : 'utf-8', 'encoding' : encoding}
1289     intro = BuildCorpus(infile, parametres)#, tar_in, tar_infouce)#, tar_formes)
1290     print time() - t1