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