windows
[iramuteq] / corpus.py
1 # -*- coding: utf-8 -*-
2 #Author: Pierre Ratinaud
3 #Copyright (c) 2008-2020 Pierre Ratinaud
4 #modification pour python 3 : Laurent Mérat, 6x7 - mai 2020
5 #License: GNU/GPL
6
7 #------------------------------------
8 # import des modules python
9 #------------------------------------
10 import codecs
11 import os
12 import locale
13 import sys
14 from time import time
15 import re
16 import sqlite3
17 import itertools
18 import logging
19 from operator import itemgetter
20 from uuid import uuid4
21 import datetime
22 from copy import copy
23
24 #------------------------------------
25 # import des fichiers du projet
26 #------------------------------------
27 from functions import decoupercharact, ReadDicoAsDico, DoConf, ReadLexique, progressbar
28 from chemins import PathOut
29 from dialog import CorpusPref, SubTextFromMetaDial, MergeClusterFrame
30 from colors import colors
31
32 import langue
33 langue.run()
34
35
36 log = logging.getLogger('iramuteq.corpus')
37
38
39 def copycorpus(corpus) :
40     log.info('copy corpus')
41     copy_corpus = Corpus(corpus.parent, parametres = corpus.parametres)
42     copy_corpus.ucis = corpus.ucis
43     copy_corpus.formes = corpus.formes
44     copy_corpus.pathout = corpus.pathout
45     copy_corpus.conn_all()
46     return copy_corpus
47
48 def CopyUce(uce) :
49     return Uce(uce.ident, uce.para, uce.uci)
50
51 def CopyUci(uci):
52     nuci = Uci(uci.ident, '')
53     nuci.etoiles = copy(uci.etoiles)
54     nuci.uces = [CopyUce(uce) for uce in uci.uces]
55     nuci.paras = copy(uci.paras)
56     return nuci
57
58
59 class Corpus :
60
61     """Corpus class
62     list of text
63     """
64     def __init__(self, parent, parametres = {}, read = False) :
65         self.parent = parent
66         self.parametres = parametres
67         self.cformes = None
68         self.connformes = None
69         self.connuces = None
70         self.conncorpus = None
71         self.islem = False
72         self.cuces = None
73         self.ucis = []
74         self.formes = {}
75         self.flems = {}
76         self.lems = None
77         self.idformesuces = {}
78         self.iduces = None
79         self.idformes = None
80         self.uceuci = None
81         if read :
82             self.pathout = PathOut(dirout = parametres['pathout'])
83             self.read_corpus()
84
85     def add_word(self, word) :
86         if word in self.formes :
87             self.formes[word].freq += 1
88             if self.formes[word].ident in self.idformesuces :
89                 if self.ucis[-1].uces[-1].ident in self.idformesuces[self.formes[word].ident] :
90                     self.idformesuces[self.formes[word].ident][self.ucis[-1].uces[-1].ident] += 1
91                 else :
92                     self.idformesuces[self.formes[word].ident][self.ucis[-1].uces[-1].ident] = 1
93             else :
94                 self.idformesuces[self.formes[word].ident] = {self.ucis[-1].uces[-1].ident: 1}
95         else :
96             if word in self.parent.lexique :
97                 gramtype = self.parent.lexique[word][1]
98                 lem = self.parent.lexique[word][0]
99             elif word.isdigit() :
100                 gramtype = 'num'
101                 lem = word
102             else :
103                 gramtype = 'nr'
104                 lem = word
105             self.formes[word] =  Word(word, gramtype, len(self.formes), lem)
106             self.idformesuces[self.formes[word].ident] = {self.ucis[-1].uces[-1].ident : 1}
107
108     def add_word_from_forme(self, word, stident):
109         if word.forme in self.formes :
110             self.formes[word.forme].freq += 1
111             if self.formes[word.forme].ident in self.idformesuces :
112                 if stident in self.idformesuces[self.formes[word.forme].ident] :
113                     self.idformesuces[self.formes[word.forme].ident][stident] += 1
114                 else :
115                     self.idformesuces[self.formes[word.forme].ident][stident] = 1
116             else :
117                 self.idformesuces[self.formes[word.forme].ident] = {stident: 1}
118         else :
119             self.formes[word.forme] = Word(word.forme, word.gram, len(self.formes), word.lem)
120             self.idformesuces[self.formes[word.forme].ident] = {stident : 1}
121
122     def conn_all(self): 
123         """connect corpus to db"""
124         if self.connformes is None :
125             log.info('connexion corpus')
126             self.connuces = sqlite3.connect(self.pathout['uces.db'])
127             self.cuces = self.connuces.cursor()
128             self.connformes = sqlite3.connect(self.pathout['formes.db'])
129             self.cformes = self.connformes.cursor()
130             self.conncorpus = sqlite3.connect(self.pathout['corpus.db'])
131             self.ccorpus = self.conncorpus.cursor()
132             self.cformes.execute('PRAGMA temp_store=MEMORY;')
133             self.cformes.execute('PRAGMA journal_mode=MEMORY;')
134             self.cformes.execute('PRAGMA  synchronous = OFF;')
135             self.cuces.execute('PRAGMA temp_store=MEMORY;')
136             self.cuces.execute('PRAGMA journal_mode=MEMORY;')
137             self.cuces.execute('PRAGMA  synchronous = OFF;')
138             self.ccorpus.execute('PRAGMA temp_store=MEMORY;')
139             self.ccorpus.execute('PRAGMA journal_mode=MEMORY;')
140             self.ccorpus.execute('PRAGMA  synchronous = OFF;')
141
142     def read_corpus(self) :
143         log.info('read corpus')
144         self.parametres['syscoding'] = 'utf8'
145         if self.conncorpus is None :
146             self.conn_all()
147         res = self.ccorpus.execute('SELECT * FROM etoiles;')
148         for row in res :
149             self.ucis.append(Uci(row[0], row[1], row[2]))
150             uces = self.conncorpus.cursor().execute('SELECT * FROM luces where uci=?;',(repr(self.ucis[-1].ident),))
151             for uce in uces:
152                 self.ucis[-1].uces.append(Uce(uce[2], uce[1], uce[0]))
153         res = self.ccorpus.execute('SELECT * FROM formes;')
154         self.formes = dict([[forme[1], Word(forme[1], forme[3], forme[0], lem = forme[2], freq = forme[4])] for forme in res])
155         self.ccorpus.close()
156
157     def getworduces(self, wordid) :
158         if isinstance(wordid, str) :
159             wordid = self.formes[wordid].ident
160         res = self.cformes.execute('SELECT uces FROM uces where id=? ORDER BY id;', (repr(wordid),))
161         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]))
162
163     def getworducis(self, wordid) :
164         res = self.getworduces(wordid)
165         return list(set([self.getucefromid(uce).uci for uce in res]))
166
167     def getformeuceseff(self, formeid) :
168         if isinstance(formeid, str) :
169             formeid = self.formes[formeid].ident
170         res = self.cformes.execute('SELECT uces FROM uces where id=? ORDER BY id;', (repr(formeid),))
171         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]))
172         query = 'SELECT eff FROM eff where id=%i ORDER BY id' % formeid
173         res = self.cformes.execute(query)
174         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]))
175         formeuceeff = {}
176         for i, uce in enumerate(uces) :
177             formeuceeff[uce] = formeuceeff.get(uce, 0) + eff[i]
178         return formeuceeff
179
180     def getlemuces(self, lem) :
181         formesid = ', '.join([repr(val) for val in self.lems[lem].formes])
182         query = 'SELECT uces FROM uces where id IN (%s) ORDER BY id' % formesid
183         res = self.cformes.execute(query)
184         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]))))
185
186     def gettgenst(self, tgen):
187         formesid = []
188         for lem in tgen :
189             if lem in self.lems :
190                 formesid += self.lems[lem].formes
191             else :
192                 print('abscent : %s' % lem)
193         query = 'SELECT uces FROM uces where id IN %s ORDER BY id' % str(tuple(formesid))
194         res = self.cformes.execute(query)
195         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]))))
196
197     def gettgenstprof(self, tgen, classe, i, clnb):
198         tgenst = []
199         for lem in tgen :
200             if lem in self.lems :
201                 lemst = self.getlemuces(lem)
202                 tgenst += lemst
203                 if not lem in self.tgenlem :
204                     self.tgenlem[lem] = [0] * clnb
205                 self.tgenlem[lem][i] = len(set(lemst).intersection(classe))
206             else :
207                 print('abscent: ',lem)
208         return list(set(tgenst))
209
210     def gettgentxt(self, tgen):
211         sts = self.gettgenst(tgen)
212         return list(set([self.getucefromid(val).uci for val in sts]))
213
214     def getlemucis(self, lem) :
215         uces = self.getlemuces(lem)
216         return list(set([self.getucefromid(val).uci for val in uces]))
217
218     def getlemuceseff(self, lem, luces = None) :
219         formesid = ', '.join([repr(val) for val in self.lems[lem].formes])
220         query = 'SELECT uces FROM uces where id IN (%s) ORDER BY id' % formesid
221         res = self.cformes.execute(query)
222         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]))
223         query = 'SELECT eff FROM eff where id IN (%s) ORDER BY id' % formesid
224         res = self.cformes.execute(query)
225         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]))
226         lemuceeff = {}
227         for i, uce in enumerate(uces) :
228             lemuceeff[uce] = lemuceeff.get(uce, 0) + eff[i]
229         return lemuceeff
230
231     def getlemclustereff(self, lem, cluster) :
232         return len(list(set(self.lc[cluster]).intersection(self.getlemuces(lem))))
233
234     def getlemeff(self, lem) :
235         return self.lems[lem].freq
236
237     def getlems(self) :
238         return self.lems
239
240     def getforme(self, formeid) :
241         if self.idformes is None : self.make_idformes()
242         return self.idformes[formeid]
243
244     def gettotocc(self) :
245         return sum([self.formes[forme].freq for forme in self.formes])
246
247     def getucemean(self) :
248         return float(self.gettotocc())/self.getucenb()
249
250     def getucenb(self) :
251         return self.ucis[-1].uces[-1].ident + 1
252
253     def getucinb(self) :
254         return self.ucis[-1].ident + 1
255
256     def getucisize(self) :
257         ucesize = self.getucesize()
258         return [sum(ucesize[uci.uces[0].ident:(uci.uces[-1].ident + 1)]) for uci in self.ucis]
259
260     def getucesize(self) :
261         res = self.getalluces()
262         return [len(uce[1].split()) for uce in res]
263
264     def getconcorde(self, uces) :
265         return self.cuces.execute('select * from uces where id IN (%s) ORDER BY id;' % ', '.join([repr(i) for i in uces])) 
266
267     def getuciconcorde(self, ucis) :
268         uces = [[val,[uce.ident for uce in self.ucis[val].uces]] for val in ucis]
269         uces = [[val[0], '\n'.join([row[1] for row in self.getconcorde(val[1])])] for val in uces]
270         return uces
271
272     def getuciconcorde_uces(self, uciid, uceid) :
273         uces = [uce.ident for uce in self.ucis[uciid].uces]
274         uces = [row for row in self.getconcorde(uces)]
275         return uces
276
277     def getwordconcorde(self, word) :
278         return self.getconcorde(self.getworduces(word))
279
280     def getlemconcorde(self, lem) :
281         return self.getconcorde(self.getlemuces(lem))
282
283     def getalluces(self) :
284         return self.cuces.execute('SELECT * FROM uces')
285
286     def getallucis(self):
287         uces = [row[1] for row in self.getalluces()]
288         return [[uci.ident, '\n'.join([uces[uce.ident] for uce in uci.uces])] for uci in self.ucis]
289
290     def getucesfrometoile(self, etoile) :
291         return [uce.ident for uci in self.ucis for uce in uci.uces if etoile in uci.etoiles]
292
293     def getetoileuces(self) :
294         log.info('get uces etoiles')
295         etoileuces = {}
296         idpara = 0
297         for uci in self.ucis :
298             etoiles = uci.etoiles[1:]
299             for et in etoiles :
300                 if et in etoileuces :
301                     etoileuces[et] += [uce.ident for uce in uci.uces]
302                 else :
303                     etoileuces[et] = [uce.ident for uce in uci.uces]
304             if uci.paras != [] :
305                 for et in uci.paras :
306                     if et in etoileuces :
307                         etoileuces[et] += [uce.ident for uce in uci.uces if uce.para == idpara]
308                     else :
309                         etoileuces[et] = [uce.ident for uce in uci.uces if uce.para == idpara]
310                     idpara += 1
311             else :
312                 idpara += 1
313         return etoileuces
314
315     def getetoileucis(self):
316         etoileuces = {}
317         for uci in self.ucis :
318             etoiles = uci.etoiles[1:]
319             for et in etoiles :
320                 if et in etoileuces :
321                     etoileuces[et] += [uci.ident]
322                 else :
323                     etoileuces[et] = [uci.ident]
324         return etoileuces
325
326     def getucefromid(self, uceid) :
327         if self.iduces is None : self.make_iduces()
328         return self.iduces[uceid]
329
330     def gethapaxnb(self) :
331         return len([None for forme in self.formes if self.formes[forme].freq == 1])
332
333     def getactivesnb(self, key) :
334         return len([lem for lem in self.lems if self.lems[lem].act == key])
335
336 # fonction inactive mais avec une incertitude concernant l'indentation sur le dernier else
337 #    def make_lems(self, lem = True) :
338 #        log.info('make lems')
339 #        self.lems = {}
340 #        for forme in self.formes :
341 #            if self.formes[forme].lem in self.lems :
342 #                if self.formes[forme].ident not in self.lems[self.formes[forme].lem] :
343 #                    self.lems[self.formes[forme].lem][self.formes[forme].ident] = 0
344 #            else :
345 #                    self.lems[self.formes[forme].lem] = {self.formes[forme].ident : 0}
346
347     def getetbyuceid(self, uceid) :
348         if self.uceuci is None : self.uceuci = dict([[uce.ident,uci.ident] for uci in self.ucis for uce in uci.uces])
349         return self.ucis[self.uceuci[uceid]].etoiles
350
351     def make_lems(self, lem = True) :
352         log.info('make lems')
353         self.lems = {}
354         if lem :
355             for forme in self.formes :
356                 if self.formes[forme].lem in self.lems :
357                     if self.formes[forme].ident not in self.lems[self.formes[forme].lem].formes :
358                         self.lems[self.formes[forme].lem].add_forme(self.formes[forme])
359                 else :
360                     self.lems[self.formes[forme].lem] = Lem(self, self.formes[forme])
361         else :
362             self.lems = dict([[forme, Lem(self, self.formes[forme])] for forme in self.formes])
363
364     def make_lems_from_dict(self, dictionnaire, dolem = True) :
365         log.info('make lems from dict')
366         self.lems = {}
367         for forme in self.formes :
368             if self.formes[forme].forme in dictionnaire :
369                 lem = dictionnaire[forme][0]
370                 gram = dictionnaire[forme][1]
371             elif forme.isdigit() :
372                 gram = 'num'
373                 lem = forme
374             else :
375                 gram = 'nr'
376                 lem = forme
377             self.formes[forme].lem = lem
378             self.formes[forme].gram = gram
379             if dolem :
380                 if self.formes[forme].lem in self.lems :
381                     if self.formes[forme].ident not in self.lems[self.formes[forme].lem].formes :
382                         self.lems[self.formes[forme].lem].add_forme(self.formes[forme])
383                 else :
384                     self.lems[self.formes[forme].lem] = Lem(self, self.formes[forme])
385             else :
386                 self.lems[forme] = Lem(self, self.formes[forme])
387
388     def make_idformes(self) :
389         self.idformes = dict([[self.formes[forme].ident, self.formes[forme]] for forme in self.formes])
390
391     def make_iduces(self) :
392         if self.iduces is None :
393             self.iduces = dict([[uce.ident, uce] for uci in self.ucis for uce in uci.uces])
394
395     def make_lexitable(self, mineff, etoiles, gram = 0) :
396         if gram == 0 :
397             grams = {1:'', 2:''}
398         else :
399             grams = {gram :''}
400         tokeep = [lem for lem in self.lems if self.lems[lem].freq >= mineff and self.lems[lem].act in grams]
401         etuces = [[] for et in etoiles]
402         for uci in self.ucis :
403             get = list(set(uci.etoiles).intersection(etoiles))
404             if len(get) > 1 :
405                 log.info('2 variables sur une ligne')
406             if get != [] :
407                 etuces[etoiles.index(get[0])] += [uce.ident for uce in uci.uces]
408         etuces = [set(val) for val in etuces]
409         tab = []
410         for lem in tokeep :
411             deff = self.getlemuceseff(lem)
412             ucesk = list(deff.keys())
413             line = [lem] + [sum([deff[uce] for uce in et.intersection(ucesk)]) for et in etuces]
414             if sum(line[1:]) >= mineff :
415                 tab.append(line)
416         tab.insert(0, [''] + etoiles)
417         return tab
418
419     def make_tgen_table(self, tgen, etoiles, tot = None):
420         lclasses = [self.getucesfrometoile(etoile) for etoile in etoiles]
421         sets = [set(cl) for cl in lclasses]
422         totoccurrences = dict([[val, 0] for val in etoiles])
423         if tot is None :
424             for forme in self.formes :
425                 formeuceeff = self.getformeuceseff(forme)
426                 for i, classe in enumerate(lclasses) :
427                     concern = sets[i].intersection(list(formeuceeff.keys()))
428                     if len(concern) :
429                         totoccurrences[etoiles[i]] += sum([formeuceeff[uce] for uce in concern])
430         #tgenoccurrences = dict([[val, 0] for val in etoiles])
431         tgenoccurrences = {}
432         for t in tgen.tgen :
433             tgenoccurrences[t] = dict([[val, 0] for val in etoiles])
434             for lem in tgen[t] :
435                 lemuceeff = self.getlemuceseff(lem)
436                 for i, classe in enumerate(lclasses) :
437                     concern = sets[i].intersection(list(lemuceeff.keys()))
438                     if len(concern) :
439                         tgenoccurrences[t][etoiles[i]] += sum([lemuceeff[uce] for uce in concern])
440         return tgenoccurrences, totoccurrences
441
442     def make_tgen_profile(self, tgen, ucecl, uci = False) :
443         log.info('tgen/classes')
444         self.tgenlem = {}
445         clnb = len(ucecl)
446         if uci :
447             #FIXME :  NE MARCHE PLUS CHANGER CA
448             tab = [[lem] + [len(set(self.gettgentxt(tgen[lem])).intersection(classe)) for i, classe in enumerate(ucecl)] for lem in tgen]
449         else :
450             tab = [[lem] + [len(set(self.gettgenstprof(tgen[lem], classe, i, clnb)).intersection(classe)) for i, classe in enumerate(ucecl)] for lem in tgen]
451         tab = [[line[0]] + [val for val in line[1:]] for line in tab if sum(line[1:]) >= 3]
452         return tab
453
454         #i = 0
455         #nam = 'total'
456         #while nam + `i` in tgen :
457         #    i += 1
458         #nam = nam + `i`
459         #last = [nam] + [`len(classe)` for classe in ucecl]
460         #tab += [last]
461         #line0 = ['tgen'] + ['_'.join(['cluster', `i+1`]) for i in range(len(ucecl))]
462         #tab = [line0] + tab
463         #with open(fileout, 'w') as f :
464         #    f.write('\n'.join(['\t'.join(line) for line in tab]).encode(self.parametres['syscoding']))        
465
466     def make_efftype_from_etoiles(self, etoiles) :
467         dtype = {}
468         etuces = [[] for et in etoiles]
469         for uci in self.ucis :
470             get = list(set(uci.etoiles).intersection(etoiles))
471             if len(get) > 1 :
472                 return '2 variables sur la meme ligne'
473             elif get != [] :
474                 etuces[etoiles.index(get[0])] += [uce.ident for uce in uci.uces]
475         etuces = [set(val) for val in etuces]
476         for lem in self.lems :
477             deff = self.getlemuceseff(lem)
478             ucesk = list(deff.keys())
479             gram = self.lems[lem].gram
480             if gram in dtype :
481                 dtype[gram] = [i + j for i, j in zip(dtype[gram], [sum([deff[uce] for uce in et.intersection(ucesk)]) for et in etuces])]
482             else :
483                 dtype[gram] = [sum([deff[uce] for uce in et.intersection(ucesk)]) for et in etuces]
484         tabout = [[gram] + dtype[gram] for gram in dtype]
485         tabout.insert(0, [''] + etoiles)
486         return tabout
487
488     def make_uceactsize(self, actives) :
489         res = self.getalluces()
490         ucesize = {}
491         for lem in actives: 
492             deff = self.getlemuceseff(lem)
493             for uce in deff :
494                 ucesize[uce] = ucesize.get(uce, 0) + 1
495         return ucesize
496
497     def make_uc(self, actives, lim1, lim2) :
498         uceactsize = self.make_uceactsize(actives)
499         last1 = 0
500         last2 = 0
501         uc1 = [[]]
502         uc2 = [[]]
503         lastpara = 0
504         for uce in [uce for uci in self.ucis for uce in uci.uces] :
505             if uce.para == lastpara :
506                 if last1 <= lim1 :
507                     last1 += uceactsize.get(uce.ident,0)
508                     uc1[-1].append(uce.ident)
509                 else :
510                     uc1.append([uce.ident])
511                     last1 = 0
512                 if last2 <= lim2 :
513                     last2 += uceactsize.get(uce.ident, 0)
514                     uc2[-1].append(uce.ident)
515                 else :
516                     uc2.append([uce.ident])
517                     last2 = 0
518             else :
519                 last1 = uceactsize.get(uce.ident, 0)
520                 last2 = uceactsize.get(uce.ident, 0)
521                 lastpara = uce.para
522                 uc1.append([uce.ident])
523                 uc2.append([uce.ident])
524         return uc1, uc2
525
526     def make_and_write_sparse_matrix_from_uc(self, actives, sizeuc1, sizeuc2, uc1out, uc2out, listuce1out, listuce2out) :
527         uc1, uc2 = self.make_uc(actives, sizeuc1, sizeuc2)
528         log.info('taille uc1 : %i - taille uc2 : %i' % (len(uc1), len(uc2)))
529         self.write_ucmatrix(uc1, actives, uc1out)
530         self.write_ucmatrix(uc2, actives, uc2out)
531         listuce1 = [['uce', 'uc']] + [[repr(uce), repr(i)] for i, ucl in enumerate(uc1) for uce in ucl]
532         listuce2 = [['uce', 'uc']] + [[repr(uce), repr(i)] for i, ucl in enumerate(uc2) for uce in ucl]
533         with open(listuce1out, 'w') as f :
534             f.write('\n'.join([';'.join(line) for line in listuce1]))
535         with open(listuce2out, 'w') as f :
536             f.write('\n'.join([';'.join(line) for line in listuce2]))
537         return len(uc1), len(uc2)
538
539     def write_ucmatrix(self, uc, actives, fileout) :
540         log.info('write uc matrix %s' % fileout)
541         uces_uc = dict([[uce, i] for i, ucl in enumerate(uc) for uce in ucl])
542         deja_la = {}
543         nbl = 0
544         with open(fileout + '~', 'w+') as f :
545             for i, lem in enumerate(actives) :
546                 for uce in self.getlemuces(lem):
547                     if (uces_uc[uce], i) not in deja_la :
548                         nbl += 1
549                         f.write(''.join([' '.join([repr(uces_uc[uce]+1),repr(i+1),repr(1)]),'\n']))
550                         deja_la[(uces_uc[uce], i)] = 0
551             f.seek(0)
552             with open(fileout, 'w') as ffin :        
553                 ffin.write("%%%%MatrixMarket matrix coordinate integer general\n%i %i %i\n" % (len(uc), len(actives), nbl))
554                 for line in f :
555                     ffin.write(line)
556         os.remove(fileout + '~')
557         del(deja_la)
558
559     def export_corpus(self, outf) :
560         #outf = 'export_corpus.txt'
561         self.make_iduces()
562         res = self.getalluces()
563         self.make_iduces()
564         actuci = ''
565         actpara = False
566         with open(outf,'w', encoding='utf8') as f :
567             for uce in res :
568                 if self.iduces[uce[0]].uci == actuci and self.iduces[uce[0]].para == actpara :
569                     f.write(uce[1] + '\n')
570                 elif self.iduces[uce[0]].uci != actuci :
571                     actuci = self.iduces[uce[0]].uci
572                     if self.ucis[self.iduces[uce[0]].uci].paras == [] :
573                         actpara = self.iduces[uce[0]].para
574                         f.write('\n' + ' '.join(self.ucis[self.iduces[uce[0]].uci].etoiles) + '\n' + uce[1] + '\n')
575                     else :
576                         ident = 0
577                         actpara = self.iduces[uce[0]].para
578                         f.write('\n'.join([' '.join(self.ucis[self.iduces[uce[0]].uci].etoiles), self.ucis[self.iduces[uce[0]].uci].paras[ident], uce[1]] + '\n'))
579                 elif self.iduces[uce[0]].para != actpara :
580                     actpara = self.iduces[uce[0]].para
581                     ident += 1
582                     f.write('\n'.join([self.ucis[self.iduces[uce[0]].uci].paras[ident], uce[1]]) + '\n')
583
584     def export_meta_table(self, outf) :
585         metas = [[repr(i)] + text.etoiles[1:] for i, text in enumerate(self.ucis)]
586         longueur_max = max([len(val) for val in metas])
587         first = ['column_%i' % i for i in range(longueur_max)]
588         metas.insert(0, first)
589         with open(outf, 'w', encoding='utf8') as f :
590             f.write('\n'.join(['\t'.join(line) for line in metas]))
591
592     def export_corpus_classes(self, outf, alc = True, lem = False, uci = False) :
593         ucecl = {}
594         for i, lc in enumerate(self.lc) :
595             for uce in lc : 
596                 ucecl[uce] = i + 1
597         for uce in self.lc0 :
598             ucecl[uce] = 0
599         if not uci :
600             res = self.getalluces()
601             self.make_iduces()
602         else :
603             res = self.getallucis()
604         with open(outf, 'w', encoding='utf8') as f :
605             for uce in res :
606                 guce = uce[1]
607                 if not uci :
608                     actuci = self.iduces[uce[0]].uci
609                 else :
610                     actuci = uce[0]
611                 if lem :
612                     guce = ' '.join([self.formes[forme].lem for forme in guce.split()])
613                 if alc :
614                     etline = ' '.join(self.ucis[actuci].etoiles + ['*classe_%i' % ucecl[uce[0]]])
615                 else :
616                     etline = ' '.join(['<' + '='.join(et.split('_')) + '>' for et in self.ucis[actuci].etoiles[1:]])
617                 f.write(etline + '\n')
618                 f.write(guce + '\n\n')
619
620     def export_classe(self, outf, classe, lem = False, uci = False) :
621         sts = self.lc[classe - 1]
622         if not uci :
623             res = self.getconcorde(sts)
624             self.make_iduces()
625         else :
626             res = self.getuciconcorde(sts)
627         with open(outf, 'w', encoding='utf8') as f :
628             for uce in res :
629                 guce = uce[1]
630                 if not uci :
631                     f.write(' '.join(self.ucis[self.iduces[uce[0]].uci].etoiles) + '\n')
632                 else :
633                     f.write(' '.join(self.ucis[uce[0]].etoiles) + '\n')
634                 if lem :
635                     guce = ' '.join([self.formes[forme].lem for forme in guce.split()])
636                 f.write(guce + '\n\n')
637
638     def export_owledge(self, rep, classe, lem = False, uci = False) :
639         sts = self.lc[classe - 1]
640         if not uci :
641             res = self.getconcorde(sts)
642             self.make_iduces()
643         else :
644             res = self.getuciconcorde(sts)
645         for uce in res :
646             ident = uce[0]
647             guce = uce[1]
648             outf = '.'.join([repr(ident), 'txt'])
649             outf = os.path.join(rep, outf)
650             if lem :
651                 guce = ' '.join([self.formes[forme].lem for forme in guce.split()])
652             with open(outf, 'w', encoding='utf8') as f :
653                 f.write(guce) #.encode('cp1252', errors = 'replace'))
654
655     def export_tropes(self, fileout, classe, lem = False, uci = False) :
656         sts = self.lc[classe - 1]
657         if not uci :
658             res = self.getconcorde(sts)
659             self.make_iduces()
660         else :
661             res = self.getuciconcorde(sts)
662         with open(fileout, 'w', encoding='utf8') as f :
663             for uce in res :
664                 guce = uce[1]
665                 if lem :
666                     guce = ' '.join([self.formes[forme].lem for forme in guce.split()])
667                 f.write(guce) #.encode('cp1252', errors = 'replace'))
668                 f.write('\n')
669
670     def make_and_write_sparse_matrix_from_uces(self, actives, outfile, listuce = False) :
671         log.info('make_and_write_sparse_matrix_from_uces %s' % outfile)
672         nbl = 0
673         with open(outfile + '~', 'w+') as f :
674             for i, lem in enumerate(actives) :
675                 for uce in sorted(self.getlemuces(lem)) :
676                     nbl += 1
677                     f.write(''.join([' '.join([repr(uce+1), repr(i+1),repr(1)]),'\n']))
678             f.seek(0)
679             with open(outfile, 'w') as ffin :
680                 ffin.write("%%%%MatrixMarket matrix coordinate integer general\n%i %i %i\n" % (self.getucenb(), len(actives), nbl))
681                 for line in f :
682                     ffin.write(line)
683         os.remove(outfile + '~')
684         if listuce :
685             with open(listuce, 'w') as f :
686                 f.write('\n'.join(['uce;uc'] + [';'.join([repr(i),repr(i)]) for i in range(0, self.getucenb())]))
687
688     def make_and_write_sparse_matrix_from_uci(self, actives, outfile, listuci = False) :
689         log.info('make_and_write_sparse_matrix_from_ucis %s' % outfile)
690         nbl = 0
691         with open(outfile + '~', 'w+') as f :
692             for i, lem in enumerate(actives) :
693                 for uci in sorted(self.getlemucis(lem)) :
694                     nbl += 1
695                     f.write(''.join([' '.join([repr(uci+1), repr(i+1),repr(1)]),'\n']))
696             f.seek(0)
697             with open(outfile, 'w') as ffin :
698                 ffin.write("%%%%MatrixMarket matrix coordinate integer general\n%i %i %i\n" % (self.getucinb(), len(actives), nbl))
699                 for line in f :
700                     ffin.write(line)
701         os.remove(outfile + '~')
702         if listuci :
703             with open(listuci, 'w') as f :
704                 f.write('\n'.join(['uci;uc'] + [';'.join([repr(i),repr(i)]) for i in range(0, self.getucinb())]))
705
706     def make_and_write_sparse_matrix_from_classe(self, actives, uces, outfile) :
707         log.info('make_and_write_sparse_matrix_from_classe %s' % outfile)
708         nbl = 0
709         duces = dict([[uce, i] for i, uce in enumerate(uces)])
710         with open(outfile + '~', 'w+') as f :
711             for i, lem in enumerate(actives) :
712                 uces_ok = list(set(self.getlemuces(lem)).intersection(uces))
713                 for uce in uces_ok :
714                     f.write(''.join([' '.join([repr(duces[uce]+1),repr(i+1),repr(1)]),'\n']))
715             f.seek(0)
716             with open(outfile, 'w') as ffin :
717                 ffin.write("%%%%MatrixMarket matrix coordinate integer general\n%i %i %i\n" % (len(uces), len(actives), nbl))
718                 for line in f :
719                     ffin.write(line)
720         os.remove(outfile + '~')
721
722     def make_table_with_classe(self, uces, list_act, uci = False) :
723         table_uce = [[0 for val in list_act] for line in range(0,len(uces))]
724         uces = dict([[uce, i] for i, uce in enumerate(uces)])
725         if uci :
726             getlem = self.getlemucis
727         else :
728             getlem = self.getlemuces
729         for i, lem in enumerate(list_act) :
730             lemuces = list(set(getlem(lem)).intersection(uces))
731             for uce in lemuces :
732                 table_uce[uces[uce]][i] = 1
733         table_uce.insert(0, list_act)
734         return table_uce
735
736     def make_pondtable_with_classe(self, uces, list_act) :
737         table_uce = [[0 for val in list_act] for line in range(0,len(uces))]
738         uces = dict([[uce, i] for i, uce in enumerate(uces)])
739         for i, lem in enumerate(list_act) :
740             uceseff = self.getlemuceseff(lem)
741             lemuces = list(set(uceseff.keys()).intersection(uces))
742             for uce in lemuces :
743                 table_uce[uces[uce]][i] = uceseff[uce]
744         table_uce.insert(0, list_act)
745         return table_uce
746
747     def parse_active(self, gramact, gramsup = None) :
748         log.info('parse actives')
749         for lem in self.lems :
750             if lem.startswith('_') and lem.endswith('_') :
751                 self.lems[lem].act = 2
752             elif self.lems[lem].gram in gramact :
753                 self.lems[lem].act = 1
754             elif gramsup is not None and self.lems[lem].gram not in gramact:
755                 if self.lems[lem].gram in gramsup :
756                     self.lems[lem].act = 2
757                 else :
758                     self.lems[lem].act =  0
759             else :
760                 self.lems[lem].act = 2
761
762     def make_actives_limit(self, limit, key = 1) :
763         if self.idformes is None :
764             self.make_idformes()
765         return [lem for lem in self.lems if self.getlemeff(lem) >= limit and self.lems[lem].act == key]
766
767     def make_actives_nb(self, nbmax, key) :
768         log.info('make_actives_nb : %i - %i' % (nbmax,key))
769         if self.idformes is None :
770             self.make_idformes()
771         allactives = [[self.lems[lem].freq, lem] for lem in self.lems if self.lems[lem].act == key and self.lems[lem].freq >= 3]
772         self.activenb = len(allactives)
773         allactives = sorted(allactives, reverse = True)
774         if self.activenb == 0 :
775             return [], 0
776         if len(allactives) <= nbmax :
777             log.info('nb = %i - eff min = %i ' % (len(allactives), allactives[-1][0]))
778             return [val[1] for val in allactives], allactives[-1][0]
779         else :
780             effs = [val[0] for val in allactives]
781             if effs.count(effs[nbmax - 1]) > 1 :
782                 lim = effs[nbmax - 1] + 1
783                 nok = True
784                 while nok :
785                     try :
786                         stop = effs.index(lim)
787                         nok = False
788                     except ValueError:
789                         lim -= 1
790             else :
791                 stop = nbmax - 1
792                 lim = effs[stop]
793         log.info('nb actives = %i - eff min = %i ' % (stop + 1, lim))
794         return [val[1] for val in allactives[0:stop]], lim
795
796     def make_and_write_profile(self, actives, ucecl, fileout, uci = False) :
797         log.info('formes/classes')
798         if uci :
799             tab = [[lem] + [len(set(self.getlemucis(lem)).intersection(classe)) for classe in ucecl] for lem in actives]
800         else :
801             tab = [[lem] + [len(set(self.getlemuces(lem)).intersection(classe)) for classe in ucecl] for lem in actives]
802         tab = [[line[0]] + [repr(val) for val in line[1:]] for line in tab if sum(line[1:]) >= 3]
803         with open(fileout, 'w', encoding='utf8') as f :
804             f.write('\n'.join([';'.join(line) for line in tab]))
805
806     def make_etoiles(self) :
807         etoiles = set([])
808         for uci in self.ucis :
809             etoiles.update(uci.etoiles[1:])
810         return list(etoiles)
811
812     def make_themes(self):
813         themes = set([])
814         for uci in self.ucis :
815             themes.update(uci.paras)
816         return list(themes)
817
818     def make_etoiles_dict(self) :
819         etoiles = [et for uci in self.ucis for et in uci.etoiles[1:]]
820         det = {}
821         for etoile in etoiles :
822             et = etoile.split('_')
823             if et[0] in det :
824                 try :
825                     endet = '_'.join(et[1:])
826                     if etoile in det[et[0]] :
827                         det[et[0]][etoile] += 1
828                     else :
829                         det[et[0]][etoile] = 1
830                 except IndexError :
831                     det[et[0]] += 1
832             else :
833                 try :
834                     endet = '_'.join(et[1:])
835                     det[et[0]] = {etoile :1}
836                 except IndexError :
837                     det[et[0]] = 1
838         return det
839
840     def make_theme_dict(self):
841         themes = [val for uci in self.ucis for val in uci.paras]
842         det = {}
843         for theme in themes :
844             th = theme.split('_')
845             if th[0] in det :
846                 try :
847                     endth = '_'.join(th[1:])
848                     if theme in det[th[0]] :
849                         det[th[0]][theme] += 1
850                     else :
851                         det[th[0]][theme] = 1
852                 except IndexError :
853                     det[th[0]] += 1
854             else :
855                 try :
856                     endth = '_'.join(th[1:])
857                     det[th[0]] = {theme:1}
858                 except IndexError :
859                     det[th[0]] = 1
860         return det
861
862     def make_etline(self, listet) :
863         etuces = [[] for et in listet]
864         for uci in self.ucis :
865             get = list(set(uci.etoiles).intersection(listet))
866             if len(get) > 1 :
867                 return '2 variables sur la meme ligne'
868             elif get != [] :
869                 etuces[listet.index(get[0])] += [uce.ident for uce in uci.uces]
870         return etuces
871
872     def make_and_write_profile_et(self, ucecl, fileout, uci = False) :
873         log.info('etoiles/classes')
874         if not uci :
875             etoileuces = self.getetoileuces()
876         else :
877             etoileuces = self.getetoileucis()
878         etoileuces = dict([[et, etoileuces[et]] for et in etoileuces if len(etoileuces[et]) > 1])
879         with open(fileout, 'w', encoding='utf8') as f :
880             f.write('\n'.join([';'.join([et] + [repr(len(set(etoileuces[et]).intersection(classe))) for classe in ucecl]) for et in etoileuces])) #.encode(self.parametres['syscoding'])
881         #etoiles = self.make_etoiles()
882         #with open(fileout, 'w') as f :
883         #    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']))
884
885     def make_colored_corpus(self, uci = False) :
886         ucecl = {}
887         for i, lc in enumerate(self.lc) :
888             for uce in lc :
889                 ucecl[uce] = i + 1
890         for uce in self.lc0 :
891             ucecl[uce] = 0
892         color = ['black'] + colors[len(self.lc) - 1]
893         txt = '''<html>
894         <meta http-equiv="content-Type" content="text/html; charset=utf8" />
895         <body>
896 '''
897         if not uci :
898             res = self.getalluces()
899             self.make_iduces()
900             actuci = ''
901             actpara = False
902             for uce in res :
903                 if self.iduces[uce[0]].uci != actuci :
904                     actuci = self.iduces[uce[0]].uci
905                     txt += '<br><hr>' + ' '.join(self.ucis[self.iduces[uce[0]].uci].etoiles) + '<br><br>'
906                     txt += '<font color="%s">' % (color[ucecl[uce[0]]]) + uce[1] + '</font><br><br>'
907                 else :
908                     txt += '<font color="%s">' % (color[ucecl[uce[0]]]) + uce[1] + '</font><br><br>'
909         else :
910             res = self.getallucis()
911             actuci = ''
912             for uce in res :
913                 if self.ucis[uce[0]].ident != actuci :
914                     actuci = self.ucis[uce[0]].ident
915                     txt += '<br><hr>' + ' '.join(self.ucis[self.ucis[uce[0]].ident].etoiles) + '<br><br>'
916                     txt += '<font color="%s">' % (color[ucecl[uce[0]]]) + uce[1] + '</font><br><br>'
917                 else :
918                     txt += '<font color="%s">' % (color[ucecl[uce[0]]]) + uce[1] + '</font><br><br>'
919         return txt + '\n</body></html>'
920
921     def make_cut_corpus(self, uci = False) :
922         txt = ''
923         if not uci :
924             res = self.getalluces()
925             self.make_iduces()
926             actuci = ''
927             actpara = False
928             for uce in res :
929                 if self.iduces[uce[0]].uci != actuci :
930                     actuci = self.iduces[uce[0]].uci
931                     txt += '\n' + ' '.join(self.ucis[self.iduces[uce[0]].uci].etoiles) + '\n'
932                     txt += ''.join(['\n',uce[1],'\n'])
933                 else :
934                     txt +=  ''.join(['\n',uce[1],'\n'])
935         else :
936             res = self.getallucis()
937             actuci = ''
938             for uce in res :
939                 if self.ucis[uce[0]].ident != actuci :
940                     actuci = self.ucis[uce[0]].ident
941                     txt += '\n' + ' '.join(self.ucis[self.ucis[uce[0]].ident].etoiles) + '\n'
942                     txt +=  ''.join(['\n',uce[1],'\n'])
943                 else :
944                     txt += ''.join(['\n',uce[1],'\n'])
945         return txt
946
947     def count_from_list(self, l, d) :
948         for val in l :
949             if val in d :
950                 d[val] += 1
951             else :
952                 d[val] = 1
953         return d
954
955     def count_from_list_cl(self, l, d, a, clnb) :
956         for val in l :
957             if val in d :
958                 d[val][a] += 1
959             else :
960                 d[val] = [0] * clnb
961                 d[val][a] = 1
962         return d
963
964     def find_segments(self, taille_segment, taille_limite) :
965         d = {}
966         for uce in self.getalluces() :
967             uce = uce[1].split()
968             d = self.count_from_list([' '.join(uce[i:i+taille_segment]) for i in range(len(uce)-(taille_segment - 1))], d)
969         l = [[d[val], val] for val in d if d[val] >= 3]
970         del(d)
971         l.sort()
972         if len(l) > taille_limite :
973             l = l[-taille_limite:]
974         return l
975
976     def find_segments_in_classe(self, list_uce, taille_segment, taille_limite, uci = False):
977         d={}
978         if not uci :
979             concorde = self.getconcorde
980         else :
981             concorde = self.getuciconcorde
982         for uce in concorde(list_uce) :
983             uce = uce[1].split()
984             d =self.count_from_list([' '.join(uce[i:i+taille_segment]) for i in range(len(uce)-(taille_segment - 1))], d)
985         l = [[d[val], val, taille_segment] for val in d if d[val] >= 3]
986         del(d)
987         l.sort()
988         if len(l) > taille_limite :
989             l = l[-taille_limite:]
990         return l
991
992     def make_segments_profile(self, fileout, lenmin = 3, lenmax = 10, effmin = 50, lem = False) :
993         d = {}
994         for b, classe in enumerate(self.lc) :
995             for uce in self.getconcorde(classe) :
996                 uce = uce[1].split()
997                 if lem :
998                     uce = [self.formes[forme].lem for forme in uce]
999                 for taille_segment in range(lenmin,lenmax) :
1000                     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))
1001         result = [[seg] + [str(val) for val in d[seg]] for seg in d if sum(d[seg]) >= effmin]
1002         with open(fileout, 'w', encoding='utf8') as f :
1003             f.write('\n'.join([';'.join(line) for line in result]))
1004
1005     def make_proftype(self, outf) :
1006         res = {}
1007         for lem in self.lems :
1008             gram = self.lems[lem].gram
1009             if not gram in res :
1010                 res[gram] = [0 for val in self.lc]
1011             lemuceeff = self.getlemuceseff(lem)
1012             for i, classe in enumerate(self.lc) :
1013                 concern = set(classe).intersection(list(lemuceeff.keys()))
1014                 res[gram][i] += sum([lemuceeff[uce] for uce in concern])
1015         res = [[gram] + [repr(val) for val in res[gram]] for gram in res]
1016         res.sort()
1017         with open(outf, 'w', encoding='utf8') as f :
1018             f.write('\n'.join([';'.join(line) for line in res]))
1019
1020     def make_ucecl_from_R(self, filein) :
1021         with open(filein, 'r') as f :
1022             c = f.readlines()
1023         c.pop(0)
1024         self.lc = []
1025         for line in c :
1026             line = line.replace('\n', '').replace('"', '').split(';')
1027             self.lc.append([int(line[0]) - 1, int(line[1])])
1028         classesl = [val[1] for val in self.lc]
1029         clnb = max(classesl)
1030         self.lc = sorted(self.lc, key=itemgetter(1))
1031         self.lc = [[uce[0] for uce in self.lc if uce[1] == i] for i in range(clnb+1)]
1032         self.lc0 = self.lc.pop(0)
1033         #return ucecl
1034
1035     def get_stat_by_cluster(self, outf, lclasses = None) :
1036         log.info('get_stat_by_cluster')
1037         if lclasses is None :
1038             lclasses = self.lc
1039         t1 = time()
1040         occurrences = dict([[i + 1, 0] for i in range(len(lclasses))])
1041         formescl = dict([[i + 1, 0] for i in range(len(lclasses))])
1042         hapaxcl = dict([[i + 1, 0] for i in range(len(lclasses))])
1043         lenclasses = dict([[i+1,len(cl)] for i, cl in enumerate(lclasses)])
1044         sets = [set(cl) for cl in lclasses]
1045         for forme in self.formes :
1046             formeuceeff = self.getformeuceseff(forme)
1047             for i, classe in enumerate(lclasses) :
1048                 concern = sets[i].intersection(list(formeuceeff.keys()))
1049                 if len(concern) :
1050                     occurrences[i+1] += sum([formeuceeff[uce] for uce in concern])
1051                     formescl[i+1] += 1
1052                     if self.formes[forme].freq == 1 :
1053                         hapaxcl[i+1] += 1
1054         log.info('%f' % (time() - t1))
1055         if outf is not None :
1056             toprint = '\n'.join([';'.join([repr(i), repr(occurrences[i]), repr(formescl[i]), repr(hapaxcl[i]), repr(lenclasses[i]), repr(float(hapaxcl[i])/float(formescl[i]))]) for i in occurrences])
1057             with open(outf, 'w', encoding='utf8') as f :
1058                 f.write(toprint)
1059         else :
1060             return [[repr(occurrences[i]), repr(formescl[i]), repr(hapaxcl[i]), repr(lenclasses[i]), repr(float(hapaxcl[i])/float(formescl[i]))] for i in occurrences]
1061
1062     def get_stat_by_et(self, outf, etoiles) :
1063         lclasses = [self.getucesfrometoile(etoile) for etoile in etoiles]
1064         stats = self.get_stat_by_cluster(None, lclasses)
1065         stats = [[etoiles[i]] + val for i, val in enumerate(stats)]
1066
1067     def gethapaxbyet(self, etoiles) :
1068         hapaxuces = [self.getlemuces(forme)[0] for forme in self.lems if self.lems[forme].freq == 1]
1069         hucesdict = {}
1070         for uce in hapaxuces :
1071             if uce in hucesdict :
1072                 hucesdict[uce] += 1
1073             else :
1074                 hucesdict[uce] = 1
1075         etuces = [[] for et in etoiles]
1076         for uci in self.ucis :
1077             get = list(set(uci.etoiles).intersection(etoiles))
1078             if len(get) > 1 :
1079                 return '2 variables sur la meme ligne'
1080             elif get != [] :
1081                 etuces[etoiles.index(get[0])] += [uce.ident for uce in uci.uces]
1082         etuces = [set(val) for val in etuces]
1083         return [sum([hucesdict[uce] for uce in list(etuce.intersection(hapaxuces))]) for etuce in etuces]
1084
1085     def gethapaxuces(self) :
1086         hapaxuces = [self.getlemuces(forme)[0] for forme in self.lems if self.lems[forme].freq == 1]
1087         hapax = [forme for forme in self.lems if self.lems[forme].freq == 1]
1088         hucesdict = {}
1089         for i,uce in enumerate(hapaxuces) :
1090             if uce in hucesdict :
1091                 hucesdict[uce][0] += 1
1092                 hucesdict[uce][1].append(hapax[i])
1093             else :
1094                 hucesdict[uce] = [1,[hapax[i]]]
1095         huces = {}
1096         for uce in hucesdict :
1097             if hucesdict[uce][0] in huces :
1098                 huces[hucesdict[uce][0]].append(uce)
1099             else :
1100                 huces[hucesdict[uce][0]] = [uce]
1101         huces = list(zip(huces, list(huces.values())))
1102         huces.sort(reverse=True)
1103         txt = """
1104         <html><body>
1105         """
1106         for nb in huces[0:4] :
1107             txt += "<p><h2>%i hapax par uce</h2><p>\n" % nb[0]
1108             for uce in nb[1] :
1109                 res = self.getconcorde([uce])
1110                 for row in res :
1111                     ucetxt = ' ' + row[1] + ' '
1112                     uceid = row[0]
1113                 for hap in hucesdict[uce][1] :
1114                     laforme = self.getforme([forme for forme in self.lems[hap].formes][0]).forme
1115                     ucetxt = ucetxt.replace(' '+laforme+' ', ' <font color=red>'+laforme+'</font> ')
1116                 txt += '<p><b>' + ' '.join(self.getetbyuceid(uceid)) + '</b></p>'
1117                 txt += '<p>'+ucetxt+'</p>\n'
1118         txt += """
1119         </body></html>
1120         """
1121         with open('/tmp/testhapxuce.html','w', encoding='utf8') as f :
1122             f.write(txt)
1123
1124     def export_dictionary(self, fileout, syscoding) :
1125         listformes = [[self.formes[forme].freq, forme, self.formes[forme].lem, self.formes[forme].gram] for forme in self.formes]
1126         listformes.sort(reverse = True)
1127         listformes = [forme[1:] + [repr(forme[0])] for forme in listformes]
1128         with open(fileout, 'w', encoding='utf8') as f :
1129             f.write('\n'.join(['\t'.join(forme) for forme in listformes]))
1130
1131     def export_lems(self, fileout, syscoding) :
1132         self.make_idformes()
1133         listlem = [[lem, '\t'.join(['\t'.join([self.idformes[forme].forme, repr(self.lems[lem].formes[forme])]) for forme in self.lems[lem].formes])] for lem in self.lems]
1134         listlem.sort()
1135         with open(fileout, 'w', encoding='utf8') as f :
1136             f.write('\n'.join(['\t'.join(lem) for lem in listlem]))
1137
1138
1139 class MakeUciStat :
1140     def __init__(self, corpus) :
1141         ucinb = corpus.getucinb()
1142         ucisize = corpus.getucisize()
1143         ucimean = float(sum(ucisize))/float(ucinb)
1144         detoile = corpus.make_etoiles_dict()
1145
1146 class Uci :
1147     def __init__(self, iduci, line, paraset = None) :
1148         self.ident = iduci
1149         self.etoiles = line.split()
1150         self.uces = []
1151         if paraset is not None :
1152             self.paras = paraset.split()
1153         else :
1154             self.paras = []
1155
1156 class Uce :
1157     def __init__(self, iduce, idpara, iduci) :
1158         self.ident = iduce
1159         self.para = idpara
1160         self.uci = iduci
1161
1162 class Word :
1163     def __init__(self, word, gramtype, idword, lem = None, freq = None) :
1164         self.forme = word
1165         self.lem = lem
1166         self.gram = gramtype
1167         self.ident = idword
1168         self.act = 1
1169         if freq is not None :
1170             self.freq = freq
1171         else :
1172             self.freq = 1
1173
1174 class Lem :
1175     def __init__(self, parent, forme) :
1176         self.formes = {forme.ident : forme.freq}
1177         self.gram = forme.gram
1178         self.freq = forme.freq
1179         self.act = forme.act
1180
1181     def add_forme(self, forme) :
1182         self.formes[forme.ident] = forme.freq
1183         self.freq += forme.freq
1184
1185
1186 def decouperlist(chaine, longueur, longueurOptimale) :
1187     """
1188         on part du dernier caractère, et on recule jusqu'au début de la chaîne.
1189         Si on trouve un '$', c'est fini.
1190         Sinon, on cherche le meilleur candidat. C'est-à-dire le rapport poids/distance le plus important.
1191     """
1192     separateurs = [['.', 6.0], ['?', 6.0], ['!', 6.0], ['£$£', 6.0], [':', 5.0], [';', 4.0], [',', 1.0], [' ', 0.01]]
1193     dsep = dict([[val[0],val[1]] for val in separateurs])
1194     trouve = False                 # si on a trouvé un bon séparateur
1195     iDecoupe = 0                # indice du caractere ou il faut decouper
1196     longueur = min(longueur, len(chaine) - 1)
1197     chaineTravail = chaine[:longueur + 1]
1198     nbCar = longueur
1199     meilleur = ['', 0, 0]        # type, poids et position du meilleur separateur
1200     try :
1201         indice = chaineTravail.index('$')
1202         trouve = True
1203         iDecoupe = indice - 1
1204     except ValueError :
1205         pass
1206     if not trouve:
1207         while nbCar >= 0:
1208             caractere = chaineTravail[nbCar]
1209             distance = abs(longueurOptimale - nbCar) + 1
1210             meilleureDistance = abs(longueurOptimale - meilleur[2]) + 1
1211             if caractere in dsep :
1212                 if (float(dsep[caractere]) / distance) > (float(meilleur[1]) / meilleureDistance) :
1213                     meilleur[0] = caractere
1214                     meilleur[1] = dsep[caractere]
1215                     meilleur[2] = nbCar
1216                     trouve = True
1217                     iDecoupe = nbCar
1218             else :
1219                 if (float(dsep[' ']) / distance) > (float(meilleur[1]) / meilleureDistance) :
1220                     meilleur[0] = ' '
1221                     meilleur[1] = dsep[' ']
1222                     meilleur[2] = nbCar
1223                     trouve = True
1224                     iDecoupe = nbCar
1225             nbCar = nbCar - 1
1226     # si on a trouvé
1227     if trouve:
1228
1229         #if meilleur[0] != ' ' :
1230         #    fin = chaine[iDecoupe + 1:]
1231         #    retour = chaineTravail[:iDecoupe]
1232         #else :
1233
1234         fin = chaine[iDecoupe + 1:]
1235         retour = chaineTravail[:iDecoupe + 1]
1236         return len(retour) > 0, retour, fin
1237     # si on a rien trouvé
1238     return False, chaine, ''
1239
1240 def testetoile(line) :
1241     return line.startswith('****')
1242
1243 def testint(line) :
1244     return line[0:4].isdigit() and '*' in line
1245
1246 def prep_txtlist(txt) :
1247     return txt.split() + ['$']
1248
1249 def prep_txtcharact(txt) :
1250     return txt + '$'
1251
1252
1253 class BuildCorpus :
1254     """
1255     Class for building a corpus
1256     """
1257
1258     def __init__(self, infile, parametres_corpus, lexique = None, expressions = None, dlg = None) :
1259         log.info('begin building corpus...')
1260         self.lexique = lexique
1261         self.expressions = expressions
1262         self.dlg = dlg
1263         self.corpus = Corpus(self, parametres_corpus)
1264         self.infile = infile
1265         self.last = 0
1266         self.lim = parametres_corpus.get('lim', 1000000)
1267         self.encoding = parametres_corpus['encoding']
1268         self.corpus.pathout = PathOut(filename = parametres_corpus['originalpath'], dirout = parametres_corpus['pathout'])
1269         self.corpus.pathout.createdir(parametres_corpus['pathout'])
1270         self.corpus.parametres['uuid'] = str(uuid4())
1271         self.corpus.parametres['corpus_name'] = parametres_corpus['corpus_name'] #os.path.split(self.corpus.parametres['pathout'])[1]
1272         self.corpus.parametres['type'] = 'corpus'
1273         if self.corpus.parametres['keep_ponct'] :
1274             self.ponctuation_espace = [' ', '']
1275         else :
1276             self.ponctuation_espace =  [' ','.', '£$£', ';', '?', '!', ',', ':','']
1277         self.cleans = []
1278         self.tolist = self.corpus.parametres.get('tolist', 0)
1279         self.buildcleans()
1280         self.prep_makeuce()
1281         #create database
1282         self.connect()
1283         self.dobuild()
1284
1285     def prep_makeuce(self) :
1286         method = self.corpus.parametres.get('ucemethod', 0)
1287         if method == 1 :
1288             self.decouper = decouperlist
1289             self.prep_txt = prep_txtlist
1290             self.ucesize = self.corpus.parametres.get('ucesize', 40)
1291         elif method == 0 :
1292             self.decouper = decoupercharact
1293             self.prep_txt = prep_txtcharact
1294             self.ucesize = self.corpus.parametres.get('ucesize', 240)
1295         log.info('method uce : %s' % method)
1296
1297     def dobuild(self) :
1298         t1 = time()
1299         try :
1300             self.read_corpus(self.infile)
1301         except Warning as args :
1302             log.info('pas kool %s' % args)
1303             raise Warning
1304         else :
1305             self.indexdb()
1306             self.corpus.parametres['ira'] = self.corpus.pathout['Corpus.cira']
1307             self.time = time() - t1
1308             self.dofinish()
1309             DoConf().makeoptions(['corpus'],[self.corpus.parametres], self.corpus.pathout['Corpus.cira'])
1310             log.info('time : %f' % (time() - t1))
1311
1312     def connect(self) :
1313         self.conn_f = sqlite3.connect(self.corpus.pathout['formes.db'])
1314         self.cf = self.conn_f.cursor()
1315         self.cf.execute('CREATE TABLE IF NOT EXISTS uces (id INTEGER, uces TEXT);')
1316         self.cf.execute('CREATE TABLE IF NOT EXISTS eff (id INTEGER, eff TEXT);')
1317         self.conn_f.commit()
1318         self.cf = self.conn_f.cursor()
1319         self.cf.execute('PRAGMA temp_store=MEMORY;')
1320         self.cf.execute('PRAGMA journal_mode=MEMORY;')
1321         self.cf.execute('PRAGMA  synchronous = OFF;')
1322         self.cf.execute('begin')
1323         self.conn = sqlite3.connect(self.corpus.pathout['uces.db'])
1324         self.c = self.conn.cursor()
1325         self.c.execute('CREATE TABLE IF NOT EXISTS uces (id INTEGER, uces TEXT);')
1326         self.conn.commit()
1327         self.c = self.conn.cursor()
1328         self.c.execute('PRAGMA temp_store=MEMORY;')
1329         self.c.execute('PRAGMA journal_mode=MEMORY;')
1330         self.c.execute('PRAGMA  synchronous = OFF;')
1331         self.c.execute('begin')
1332
1333     def indexdb(self) :
1334         #commit index and close db
1335         self.conn.commit()
1336         self.conn_f.commit()
1337         self.cf.execute('CREATE INDEX iduces ON uces (id);')
1338         self.cf.execute('CREATE INDEX ideff ON eff (id);')
1339         self.c.close()
1340         self.cf.close()
1341         #backup corpus
1342         self.conn_corpus = sqlite3.connect(self.corpus.pathout['corpus.db'])
1343         self.ccorpus = self.conn_corpus.cursor()
1344         self.ccorpus.execute('CREATE TABLE IF NOT EXISTS etoiles (uci INTEGER, et TEXT, paras TEXT);')
1345         self.ccorpus.execute('CREATE TABLE IF NOT EXISTS luces (uci INTEGER, para INTEGER, uce INTEGER);')
1346         self.ccorpus.execute('CREATE TABLE IF NOT EXISTS formes (ident INTEGER, forme TEXT, lem TEXT, gram TEXT, freq INTEGER);')
1347         self.conn_corpus.commit()
1348         self.ccorpus = self.conn_corpus.cursor()
1349         self.ccorpus.execute('PRAGMA temp_store=MEMORY;')
1350         self.ccorpus.execute('PRAGMA journal_mode=MEMORY;')
1351         self.ccorpus.execute('PRAGMA  synchronous = OFF;')
1352         self.ccorpus.execute('begin')
1353         self.backup_corpus()
1354         self.ccorpus.execute('CREATE INDEX iduci ON luces (uci);')
1355         self.conn_corpus.commit()
1356         self.conn_corpus.close()
1357         #self.corpus.parametres['corpus_ira'] = self.corpus.pathout['corpus.cira']
1358
1359     def buildcleans(self) :
1360         if self.corpus.parametres.get('lower', 1) :
1361             self.cleans.append(self.dolower)
1362         if self.corpus.parametres.get('firstclean', 1) :
1363             self.cleans.append(self.firstclean)
1364         if self.corpus.parametres['charact'] :
1365             self.rule = self.corpus.parametres.get('keep_caract', "^a-zA-Z0-9àÀâÂäÄáÁéÉèÈêÊëËìÌîÎïÏòÒôÔöÖùÙûÛüÜçÇßœŒ’ñ.:,;!?*'_")
1366             self.cleans.append(self.docharact)
1367         if self.corpus.parametres.get('expressions', 1) :
1368             self.cleans.append(self.make_expression)
1369         if self.corpus.parametres.get('apos', 1) :
1370             self.cleans.append(self.doapos)
1371         if self.corpus.parametres.get('tiret', 1):
1372             self.cleans.append(self.dotiret)
1373
1374     def make_expression(self,txt) :
1375         exp = list(self.expressions.keys())
1376         exp.sort(reverse=True)
1377         for expression in exp :
1378             if expression in txt :
1379                 txt = txt.replace(expression, self.expressions[expression][0])
1380         return txt
1381
1382     def dolower(self, txt) :
1383         return txt.lower()
1384
1385     def docharact(self, txt) :
1386         #rule = u"^a-zA-Z0-9àÀâÂäÄáÁéÉèÈêÊëËìÌîÎïÏòÒôÔöÖùÙûÛüÜçÇßœŒ’ñ.:,;!?*'_-"
1387         list_keep = "[" + self.rule + "]+"
1388         return re.sub(list_keep, ' ', txt)
1389
1390     def doapos(self, txt) :
1391         return txt.replace('\'', ' ')
1392
1393     def dotiret(self, txt) :
1394         return txt.replace('-', ' ')
1395
1396     def firstclean(self, txt) :
1397         txt = txt.replace('’',"'")
1398         txt = txt.replace('œ', 'oe')
1399         return txt.replace('...',' £$£ ').replace('?',' ? ').replace('.',' . ').replace('!', ' ! ').replace(',',' , ').replace(';', ' ; ').replace(':',' : ').replace('…', ' £$£ ')
1400
1401     def make_cleans(self, txt) :
1402         for clean in self.cleans :
1403             txt = clean(txt)
1404         return txt
1405
1406     def backup_uce(self) :
1407         if self.corpus.idformesuces != {} :
1408             log.info('backup %i' % len(self.corpus.idformesuces))
1409             touce = [(repr(forme), ' '.join([repr(val) for val in  list(self.corpus.idformesuces[forme].keys())])) for forme in self.corpus.idformesuces]
1410             toeff = [(repr(forme), ' '.join([repr(val) for val in  list(self.corpus.idformesuces[forme].values())])) for forme in self.corpus.idformesuces]
1411             self.cf.executemany('INSERT INTO uces VALUES (?,?);', touce)
1412             self.cf.executemany('INSERT INTO eff VALUES (?,?);', toeff)
1413         self.corpus.idformesuces = {}
1414         self.count = 1
1415
1416     def backup_corpus(self) :
1417         log.info('start backup corpus')
1418         t = time()
1419         for uci in self.corpus.ucis :
1420             self.ccorpus.execute('INSERT INTO etoiles VALUES (?,?,?);' ,(uci.ident,' '.join(uci.etoiles), ' '.join(uci.paras,)))
1421             for uce in uci.uces :
1422                 self.ccorpus.execute('INSERT INTO luces VALUES (?,?,?);',(repr(uci.ident),repr(uce.para),repr(uce.ident),))
1423         for forme in self.corpus.formes :
1424             self.ccorpus.execute('INSERT INTO formes VALUES (?,?,?,?,?);', (repr(self.corpus.formes[forme].ident), forme, self.corpus.formes[forme].lem, self.corpus.formes[forme].gram, repr(self.corpus.formes[forme].freq),))
1425         log.info('%f' % (time() - t))
1426
1427     def dofinish(self) :
1428         self.corpus.parametres['date'] = datetime.datetime.now().ctime()
1429         minutes, seconds = divmod(self.time, 60)
1430         hours, minutes = divmod(minutes, 60)
1431         self.corpus.parametres['time'] = '%.0fh %.0fm %.0fs' % (hours, minutes, seconds)
1432         self.corpus.parametres['ucinb'] = self.corpus.getucinb()
1433         self.corpus.parametres['ucenb'] = self.corpus.getucenb()
1434         self.corpus.parametres['occurrences'] = self.corpus.gettotocc()
1435         self.corpus.parametres['formesnb'] = len(self.corpus.formes)
1436         hapaxnb = self.corpus.gethapaxnb()
1437         pourhapaxf = (float(hapaxnb) / len(self.corpus.formes)) * 100
1438         pourhapaxocc = (float(hapaxnb) / self.corpus.parametres['occurrences']) * 100
1439         self.corpus.parametres['hapax'] = '%i - %.2f %% des formes - %.2f %% des occurrences' % (hapaxnb, pourhapaxf, pourhapaxocc)
1440
1441 class BuildSubCorpus(BuildCorpus):
1442
1443     def __init__(self, corpus, parametres, dlg = None) :
1444         log.info('begin subcorpus...')
1445         self.dlg = dlg
1446         self.ori = corpus
1447         self.infile = None
1448         self.corpus = Corpus(self, {'type' : 'corpus', 'originalpath' : corpus.parametres['originalpath'], 'encoding' : corpus.parametres['encoding']})
1449         self.last = 0
1450         self.parametres = parametres
1451         self.encoding = corpus.parametres['encoding']
1452         self.corpus.parametres['corpus_name'] = parametres['corpus_name']
1453         self.corpus.pathout = PathOut(filename = corpus.parametres['originalpath'], dirout = parametres['pathout'])
1454         self.corpus.pathout.createdir(parametres['pathout'])
1455         self.corpus.parametres['pathout'] = parametres['pathout']
1456         self.corpus.parametres['meta'] = parametres.get('meta', False)
1457         self.corpus.parametres['uuid'] = str(uuid4())
1458         if parametres.get('frommeta', False) :
1459             print('make subtexts')
1460             self.corpus.ucis = [CopyUci(uci) for uci in self.ori.ucis if set(parametres['meta']).intersection(uci.etoiles) != set()]
1461         elif parametres.get('fromtheme', False) :
1462             print('make subtexts from theme')
1463             idpara = 0
1464             for uci in self.ori.ucis :
1465                 if uci.paras != [] :
1466                     newuce = []
1467                     newpara = []
1468                     for et in uci.paras :
1469                         if et in parametres['meta'] :
1470                             newuce += [CopyUce(uce) for uce in uci.uces if uce.para == idpara]
1471                             newpara.append(et)
1472                         idpara += 1
1473                     if newuce != [] :
1474                         nuci = CopyUci(uci)
1475                         nuci.uces = newuce
1476                         nuci.paras = newpara
1477                         self.corpus.ucis.append(nuci)
1478                 else :
1479                     idpara += 1
1480         elif parametres.get('fromclusters', False) :
1481             self.parametres['uceids'] = [st for i in self.parametres['meta'] for st in self.parametres['lc'][i]]
1482             self.fromuceids()
1483         elif parametres.get('fromuceids', False) :
1484             self.fromuceids()
1485         #create database
1486         self.connect()
1487         self.dobuild()
1488
1489     def fromuceids(self):
1490         print('fromuceids')
1491         dictucekeep = dict(list(zip(self.parametres['uceids'], self.parametres['uceids'])))
1492         idpara = 0
1493         for uci in self.ori.ucis :
1494             if uci.paras == [] :
1495                 keepuces = [CopyUce(uce) for uce in uci.uces if uce.ident in dictucekeep]
1496                 if keepuces != [] :
1497                     nuci = CopyUci(uci)
1498                     nuci.uces = keepuces
1499                     self.corpus.ucis.append(nuci)
1500                 idpara += 1
1501             else :
1502                 newuces = []
1503                 newpara = []
1504                 for et in uci.paras :
1505                     keepuces = [CopyUce(uce) for uce in uci.uces if uce.ident in dictucekeep]
1506                     idpara += 1
1507                     if keepuces != [] :
1508                         newuces += keepuces
1509                         newpara.append(et)
1510                 if newuces != [] :
1511                     nuci = CopyUci(uci)
1512                     nuci.uces = newuces
1513                     nuci.paras = newpara
1514                     self.corpus.ucis.append(nuci)
1515
1516     def read_corpus(self, infile = None):
1517         self.olduceid = [uce.ident for uci in self.corpus.ucis for uce in uci.uces]
1518         ident_uci = 0
1519         ident_uce = 0
1520         ident_para = -1
1521         lastpara = -1
1522         newuceident = {}
1523         print('redo text, para and st ident')
1524         for uci in self.corpus.ucis :
1525             uci.ident = ident_uci
1526             ident_uci += 1
1527             for uce in uci.uces :
1528                 uce.uci = uci.ident
1529                 if uce.para != lastpara :
1530                     ident_para += 1
1531                     lastpara = uce.para
1532                     uce.para = ident_para
1533                 else :
1534                     uce.para = ident_para
1535                 newuceident[uce.ident] = ident_uce
1536                 uce.ident = ident_uce
1537                 ident_uce += 1
1538         print('backup st text and forms')
1539         for row in self.ori.getconcorde(self.olduceid) :
1540             self.c.execute('INSERT INTO uces VALUES(?,?);', (repr(newuceident[row[0]]), row[1]))
1541             for word in row[1].split() :
1542                 self.corpus.add_word_from_forme(self.ori.formes[word], newuceident[row[0]])
1543         self.backup_uce()
1544         print('done')
1545
1546 class BuildFromAlceste(BuildCorpus) :
1547
1548     def read_corpus(self, infile) :
1549         if self.dlg is not None :
1550             self.dlg.Pulse('textes : 0 - segments : 0')
1551         self.limitshow = 0
1552         self.count = 1
1553         if self.corpus.parametres['ucimark'] == 0 :
1554             self.testuci = testetoile
1555         elif  self.corpus.parametres['ucimark'] == 1 :
1556             self.testuci = testint
1557         txt = []
1558         iduci = -1
1559         idpara = -1
1560         iduce = -1
1561         try :
1562             with codecs.open(infile, 'r', self.encoding) as f :
1563                 for linenb, line in enumerate(f) :
1564                     line = line.rstrip('\n\r')#FIXME .lstrip(codecs.BOM).lstrip(codecs.BOM_UTF8)
1565                     if self.testuci(line) :
1566                         iduci += 1
1567                         if txt != [] :
1568                             iduce, idpara = self.treattxt(txt, iduce, idpara, iduci - 1)
1569                             txt = []
1570                             self.corpus.ucis.append(Uci(iduci, line))
1571                         else :
1572                             if iduci > 0 :
1573                                 if self.corpus.ucis[-1].uces == [] :
1574                                     log.info('Empty text : %i' % linenb)
1575                                     iduci -= 1
1576                                     self.corpus.ucis.pop()
1577                             self.corpus.ucis.append(Uci(iduci, line))
1578                         if self.dlg is not None :
1579                             if not (iduci + 1) % 10 :
1580                                 self.dlg.Pulse('textes : %i - segments : %i' % (iduci + 1, iduce +1))
1581                     elif line.startswith('-*') :
1582                         if iduci != -1 :
1583                             if txt != [] :
1584                                 iduce, idpara = self.treattxt(txt, iduce, idpara, iduci)
1585                                 txt = []
1586                             idpara += 1
1587                             self.corpus.ucis[-1].paras.append(line.split()[0])
1588                         else :
1589                             raise Exception('paragrapheOT %i' % linenb)
1590                     elif line.strip() != '' and iduci != -1 :
1591                         txt.append(line)
1592             if txt != [] and iduci != -1 :
1593                 iduce, idpara = self.treattxt(txt, iduce, idpara, iduci)
1594                 del(txt)
1595             else :
1596                 if iduci != -1 :
1597                     iduci -= 1
1598                     self.corpus.ucis.pop()
1599                     log.info(Exception("Empty text %i" % linenb))
1600                 else :
1601                     raise Exception('EmptyText %i' % linenb)
1602             if iduci != -1  and iduce != -1:
1603                 self.backup_uce()
1604             else :
1605                 log.info(_("No Text in corpus. Are you sure of the formatting ?"))
1606                 raise Exception('TextBeforeTextMark %i' % linenb)
1607         except UnicodeDecodeError :
1608             raise Exception("CorpusEncoding")
1609
1610     def treattxt(self, txt, iduce, idpara, iduci) :
1611         if self.corpus.parametres.get('ucemethod', 0) == 2 and self.corpus.parametres['douce']:
1612             txt = 'laphrasepoursplitter'.join(txt)
1613             txt = self.make_cleans(txt)
1614             txt = ' '.join([val for val in txt.split() if val not in self.ponctuation_espace])
1615             ucetxt = txt.split('laphrasepoursplitter')
1616         else :
1617             txt = ' '.join(txt)
1618             txt = self.make_cleans(txt)
1619             ucetxt = self.make_uces(txt, self.corpus.parametres['douce'])
1620         if self.corpus.ucis[-1].paras == [] :
1621             idpara += 1
1622         for uce in ucetxt :
1623             iduce += 1
1624             self.corpus.ucis[-1].uces.append(Uce(iduce, idpara, iduci))
1625             self.c.execute('INSERT INTO uces VALUES(?,?);', (repr(iduce),uce))
1626             if not self.tolist :
1627                 uce = uce.split()
1628             else :
1629                 uce = list(uce)
1630             for word in uce :
1631                 self.last += 1
1632                 self.corpus.add_word(word)
1633         log.debug(' '.join([repr(iduci),repr(idpara),repr(iduce)]))
1634         if self.last > self.lim :
1635             self.backup_uce()
1636             self.last = 0
1637         return iduce, idpara
1638
1639     def make_uces(self, txt, douce = True, keep_ponct = False) :
1640         txt = ' '.join(txt.split())
1641         if douce :
1642             out = []
1643             reste, texte_uce, suite = self.decouper(self.prep_txt(txt), self.ucesize + 15, self.ucesize)
1644             while reste :
1645                 uce = ' '.join([val for val in texte_uce if val not in self.ponctuation_espace])
1646                 if uce != '' :
1647                     out.append(uce)
1648                 reste, texte_uce, suite = self.decouper(suite, self.ucesize + 15, self.ucesize)
1649             uce = ' '.join([val for val in texte_uce if val not in self.ponctuation_espace])
1650             if uce != '' :
1651                 out.append(uce)
1652             return out
1653         else :
1654             return [' '.join([val for val in txt.split() if val not in self.ponctuation_espace])]
1655
1656 #decouper (list_sep)
1657 #make_uces (decouper)
1658 #treat_txt (make_uces)
1659 #read (treat_txt)
1660
1661 class Builder :
1662
1663     def __init__(self, parent, dlg = None) :
1664         self.parent = parent
1665         self.dlg = dlg
1666         parametres = DoConf(os.path.join(self.parent.UserConfigPath,'corpus.cfg')).getoptions('corpus')
1667         parametres['pathout'] = PathOut(parent.filename, 'corpus').mkdirout()
1668         parametres['corpus_name'] = os.path.split(parametres['pathout'])[1]
1669         dial = CorpusPref(parent, parametres)
1670         dial.CenterOnParent()
1671         dial.txtpath.SetLabel(parent.filename)
1672         #dial.repout_choices.SetValue(parametres['pathout'])
1673         self.res = dial.ShowModal()
1674         if self.dlg is not None :
1675             self.dlg = progressbar(self.parent, self.dlg)
1676         if self.res == 5100 :
1677             parametres = dial.doparametres()
1678             parametres['originalpath'] = parent.filename
1679             PathOut().createdir(parametres['pathout'])
1680             if parametres.get('dictionary', False) :
1681                 filein = parametres['dictionary']
1682             else :
1683                 filein = None
1684             if dial.corpusname.GetValue() != '' :
1685                 parametres['corpus_name'] = dial.corpusname.GetValue()
1686             dial.Destroy()
1687             ReadLexique(self.parent, lang = parametres['lang'], filein = filein)
1688             if parametres['lang'] != 'other' and  os.path.exists(self.parent.DictPath.get(parametres['lang']+'_exp', 'french_exp')):
1689                 self.parent.expressions = ReadDicoAsDico(self.parent.DictPath.get(parametres['lang']+'_exp', 'french_exp'))
1690             else :
1691                 self.parent.expressions = {}
1692             self.parametres = parametres
1693         else :
1694             dial.Destroy()
1695             if self.dlg is not None :
1696                 self.dlg.Destroy()
1697
1698     def doanalyse(self) :
1699         return BuildFromAlceste(self.parent.filename, self.parametres, self.parent.lexique, self.parent.expressions, dlg = self.dlg).corpus
1700
1701 class SubBuilder :
1702
1703     def __init__(self, parent, corpus, parametres = None, dlg = None):
1704         self.parent = parent
1705         self.ori = corpus
1706         self.dlg = dlg
1707         corpus_name = 'Sub' + corpus.parametres['corpus_name']
1708         if dlg is not None :
1709             busy = wx.BusyInfo(_("Please wait..."), self)
1710             wx.SafeYield()
1711         parametres['corpus_name'] = corpus_name
1712         if parametres.get('frommeta', False) :
1713             parametres['meta'] = corpus.make_etoiles()
1714         elif parametres.get('fromtheme', False) :
1715             parametres['meta'] = corpus.make_themes()
1716         elif parametres.get('fromclusters', False) :
1717             parametres['meta'] = [' '.join(['classe', repr(i)]) for i in range(1,parametres['clnb'] + 1)]
1718         else :
1719             parametres['meta'] = []
1720         if 'fromclusters' not in parametres :
1721             parametres['meta'].sort()
1722         if dlg is not None :
1723             del busy
1724         dial = SubTextFromMetaDial(parent, parametres)
1725         self.res = dial.ShowModal()
1726         if self.res == 5100 :
1727             if dial.subcorpusname.GetValue() != '' :
1728                 corpus_name = ''.join([l for l in dial.subcorpusname.GetValue() if l.isalnum() or l in ['_']])
1729             if corpus_name != '' :
1730                 parametres['corpus_name'] = corpus_name
1731             else :
1732                 parametres['corpus_name'] = 'Sub' + corpus.parametres['corpus_name']
1733             pathout = os.path.join(corpus.parametres['pathout'], parametres['corpus_name'])
1734             i = 1
1735             while os.path.exists(pathout + '_%i' % i) :
1736                 i += 1
1737             parametres['pathout'] = pathout + '_%i' % i
1738             meta = dial.m_listBox1.GetSelections()
1739             if not 'fromclusters' in parametres :
1740                 parametres['meta'] = [parametres['meta'][val] for val in meta]
1741             else :
1742                 parametres['meta'] = meta
1743             self.parametres = parametres
1744             dial.Destroy()
1745         else :
1746             dial.Destroy()
1747
1748     def doanalyse(self):
1749         return BuildSubCorpus(self.ori, parametres = self.parametres, dlg = self.dlg).corpus
1750
1751 class BuildMergeFromClusters(BuildCorpus):
1752
1753     def __init__(self, analyses, parametres, dlg = None) :
1754         log.info('begin subcorpus...')
1755         self.dlg = dlg
1756         self.infile = None
1757         self.corpus = Corpus(self, {'type' : 'corpus', 'originalpath' : 'MergeFromClusters', 'encoding' : 'merge'})
1758         self.last = 0
1759         self.analyses = analyses
1760         self.lcl = []
1761         self.parametres = parametres
1762         #self.encoding = corpus.parametres['encoding']
1763         self.corpus.parametres['corpus_name'] = parametres['corpus_name']
1764         self.corpus.pathout = PathOut(filename = 'MFC', dirout = parametres['pathout'])
1765         self.corpus.pathout.createdir(parametres['pathout'])
1766         self.corpus.parametres['pathout'] = parametres['pathout']
1767         self.corpus.parametres['meta'] = parametres.get('meta', False)
1768         self.corpus.parametres['uuid'] = str(uuid4())
1769         for i, analyse in enumerate(analyses) :
1770             self.lcl.append([])
1771             self.analyseid = i
1772             corpus_uuid = analyse['corpus']
1773             #if corpus_uuid not in self.parent.history.openedcorpus :
1774             irapath = parametres['corpusira'][i]
1775             corpus = Corpus(self, parametres = DoConf(irapath).getoptions('corpus'), read = True)
1776             ucepath = os.path.join(analyse['pathout'], 'uce.csv')
1777             corpus.make_ucecl_from_R(ucepath)
1778             self.ori = corpus
1779             for j, cl in enumerate(parametres['clusters'][i]) :
1780                #print cl, self.ori.lc[cl-1]
1781                self.parametres['uceids'] = self.ori.lc[cl-1]#[st for st in self.ori['lc'][cl-1]]
1782                self.lcl[i] += self.ori.lc[cl-1]
1783                self.et = parametres['newet'][i][j]
1784                self.fromuceids()
1785         #create database
1786         self.connect()
1787         self.dobuild()
1788
1789     def fromuceids(self):
1790         print('fromuceids')
1791         dictucekeep = dict(list(zip(self.parametres['uceids'], self.parametres['uceids'])))
1792         idpara = 0
1793         for uci in self.ori.ucis :
1794             if uci.paras == [] :
1795                 keepuces = [CopyUce(uce) for uce in uci.uces if uce.ident in dictucekeep]
1796                 if keepuces != [] :
1797                     nuci = CopyUci(uci)
1798                     nuci.uces = keepuces
1799                     nuci.etoiles.append(self.et)
1800                     nuci.analyseid = self.analyseid
1801                     self.corpus.ucis.append(nuci)
1802                 idpara += 1
1803             else :
1804                 newuces = []
1805                 newpara = []
1806                 for et in uci.paras :
1807                     keepuces = [CopyUce(uce) for uce in uci.uces if uce.ident in dictucekeep]
1808                     idpara += 1
1809                     if keepuces != [] :
1810                         newuces += keepuces
1811                         newpara.append(et)
1812                 if newuces != [] :
1813                     nuci = CopyUci(uci)
1814                     nuci.uces = newuces
1815                     nuci.paras = newpara
1816                     nuci.etoiles.append(self.et)
1817                     nuci.analyseid = self.analyseid
1818                     self.corpus.ucis.append(nuci)
1819             #print nuci.etoiles, nuci.ident, nuci.uces
1820
1821     def read_corpus(self, infile = None):
1822         #self.olduceid = [uce.ident for uci in self.corpus.ucis for uce in uci.uces]
1823         ident_uci = 0
1824         ident_uce = 0
1825         ident_para = -1
1826         lastpara = -1
1827         newuceident = {}
1828         print('redo text, para and st ident')
1829         for uci in self.corpus.ucis :
1830             #print uci.ident, ident_uci, [uce.ident for uce in uci.uces], uci.etoiles
1831             uci.ident = ident_uci
1832             ident_uci += 1
1833             for uce in uci.uces :
1834                 uce.uci = uci.ident
1835                 if uce.para != lastpara :
1836                     ident_para += 1
1837                     lastpara = uce.para
1838                     uce.para = ident_para
1839                 else :
1840                     uce.para = ident_para
1841                 newuceident['%i-%i' %(uci.analyseid, uce.ident)] = ident_uce
1842                 uce.ident = ident_uce
1843                 #print uce.ident
1844                 ident_uce += 1
1845         print('backup st text and forms')
1846         rowid = 0
1847         for i, analyse in enumerate(self.analyses) :
1848             #print analyse, self.parametres['corpusira']
1849             irapath = self.parametres['corpusira'][i]
1850             old = Corpus(self, parametres = DoConf(irapath).getoptions('corpus'), read = True)
1851             for row in old.getconcorde(self.lcl[i]) :
1852                 self.c.execute('INSERT INTO uces VALUES(?,?);', (newuceident['%i-%i' % (i,row[0])], row[1]))
1853                 for word in row[1].split() :
1854                     self.corpus.add_word_from_forme(old.formes[word], newuceident['%i-%i' % (i,row[0])])
1855                 rowid += 1
1856         self.backup_uce()
1857         print('done')
1858
1859
1860 class MergeClusters :
1861
1862     def __init__(self, parent, parametres = None, dlg = None):
1863         self.parent = parent
1864         #self.ori = corpus
1865         self.dlg = dlg
1866         corpus_name = 'MergeFromClusters'
1867         if dlg is not None :
1868             busy = wx.BusyInfo(_("Please wait..."), self)
1869             wx.SafeYield()
1870         parametres['corpus_name'] = corpus_name
1871         if dlg is not None :
1872             del busy
1873         dial = MergeClusterFrame(parent)
1874         dial.m_textCtrl4.SetValue(corpus_name)
1875         self.res = dial.ShowModal()
1876         if self.res == 5100 :
1877             self.analyses = {}
1878             self.clusters = {}
1879             self.newet = {}
1880             self.corpusira = {}
1881             if dial.m_textCtrl4.GetValue() != '' :
1882                 corpus_name = ''.join([l for l in dial.m_textCtrl4.GetValue() if l.isalnum() or l in ['_']])
1883             if corpus_name != '' :
1884                 parametres['corpus_name'] = corpus_name
1885             else :
1886                 parametres['corpus_name'] = 'MergeFromClusters'
1887             for cl in dial.selected :
1888                 corpus_uuid = cl[1]
1889                 #if corpus_uuid not in self.parent.history.openedcorpus :
1890                 irapath = self.parent.history.corpus[corpus_uuid]['ira']
1891                 #corpus = Corpus(self.parent, parametres = DoConf(irapath).getoptions('corpus'), read = True)
1892                 #self.parent.history.openedcorpus[corpus_uuid] = corpus
1893                 if cl[0] not in self.analyses :
1894                     analyse = DoConf(dial.irapath[cl[0]]).getoptions()
1895                     #ucepath = os.path.join(os.path.dirname(dial.irapath[cl[0]]), 'uce.csv')
1896                     #corpus = copycorpus(self.parent.history.openedcorpus[corpus_uuid])
1897                     #corpus.make_ucecl_from_R(ucepath)
1898                     self.analyses[cl[0]] = analyse
1899                     self.clusters[cl[0]] = [cl[2]]
1900                     self.newet[cl[0]] = [dial.selected[cl]]
1901                     self.corpusira[cl[0]] = irapath
1902                 else :
1903                     self.clusters[cl[0]].append(cl[2])
1904                     self.newet[cl[0]].append(dial.selected[cl])
1905             analyses = [val for val in self.clusters]
1906             clusters = [self.clusters[val] for val in analyses]
1907             self.newet = [self.newet[val] for val in analyses]
1908             corpusira = [self.corpusira[val] for val in analyses]
1909             analyses = [self.analyses[val] for val in analyses]
1910             pathout = os.path.dirname(os.path.dirname(analyses[0]['pathout']))
1911             self.analyses = analyses
1912             pathout = os.path.join(pathout, parametres['corpus_name'])
1913             i = 1
1914             while os.path.exists(pathout + '_%i' % i) :
1915                 i += 1
1916             parametres['pathout'] = pathout + '_%i' % i
1917             self.parametres = parametres
1918             self.parametres['clusters'] = clusters
1919             self.parametres['newet'] = self.newet
1920             self.parametres['corpusira'] = corpusira
1921             dial.Destroy()
1922         else :
1923             dial.Destroy()
1924
1925     def doanalyse(self):
1926         return BuildMergeFromClusters(self.analyses, parametres = self.parametres, dlg = self.dlg).corpus
1927