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