mainly translation and more
[iramuteq] / functions.py
1 #!/bin/env python
2 # -*- coding: utf-8 -*-
3 #Author: Pierre Ratinaud
4 #Copyright (c) 2008-2012 Pierre Ratinaud
5 #License: GNU/GPL
6
7 import wx
8 import re
9 from ConfigParser import ConfigParser
10 from subprocess import Popen, call, PIPE
11 import thread
12 import os
13 import ast
14 import sys
15 import csv
16 import platform
17 import traceback
18 import codecs
19 import locale
20 import datetime
21 from copy import copy
22 from shutil import copyfile
23 import shelve
24 #from dialog import BugDialog
25 import logging
26
27 log = logging.getLogger('iramuteq')
28
29
30 indices_simi = [u'cooccurrence' ,'pourcentage de cooccurrence',u'Russel',u'Jaccard', 'Kulczynski1', 'Kulczynski2', 'Mountford', 'Fager', 'simple matching', 'Hamman', 'Faith', 'Tanimoto', 'Dice', 'Phi', 'Stiles', 'Michael', 'Mozley', 'Yule', 'Yule2', 'Ochiai', 'Simpson', 'Braun-Blanquet','Chi-squared', 'Phi-squared', 'Tschuprow', 'Cramer', 'Pearson', 'binomial']
31
32
33 class History :
34     def __init__(self, filein, syscoding = 'utf8') :
35         self.filein = filein
36         self.syscoding = syscoding
37         self.corpora = {}
38         self.openedcorpus = {}
39         self.orph = []
40         self.analyses = {}
41         self.history = []
42         self.opened = {}
43         self.read()
44
45     def read(self) :
46         d = shelve.open(self.filein)
47         self.history = d.get('history', [])
48         self.matrix = d.get('matrix', [])
49         self.ordercorpus = dict([[corpus['uuid'], i] for i, corpus in enumerate(self.history)])
50         self.corpus = dict([[corpus['uuid'], corpus] for corpus in self.history])
51         self.analyses = dict([[analyse['uuid'], analyse] for corpus in self.history for analyse in corpus.get('analyses', [])])
52         self.matrixanalyse = dict([[mat['uuid'], mat] for mat in self.matrix])
53         d.close()
54
55     def write(self) :
56         d = shelve.open(self.filein)
57         d['history'] = self.history
58         d['matrix'] = self.matrix
59         d.close()
60     
61     def add(self, analyse) :
62         log.info('add to history %s' % analyse.get('corpus_name', 'pas un corpus'))
63         tosave = {'uuid' : analyse['uuid'], 'ira': analyse['ira'], 'type' : analyse['type']}
64         if analyse.get('corpus', False) :
65             if analyse['uuid'] in self.analyses :
66                 return
67             tosave['corpus'] = analyse['corpus']
68             tosave['name'] = analyse['name']
69             acorpus_uuid =  analyse['corpus']
70             if acorpus_uuid in self.corpus :
71                 if 'analyses' in self.history[self.ordercorpus[acorpus_uuid]] :
72                     self.history[self.ordercorpus[acorpus_uuid]]['analyses'].append(tosave)
73                 else :
74                     self.history[self.ordercorpus[acorpus_uuid]]['analyses'] = [tosave]
75             else :
76                 self.orph.append(tosave)
77         else :
78             tosave['corpus_name'] = analyse['corpus_name']
79             self.history.append(tosave)
80         self.write()
81         self.read()
82
83     def addMatrix(self, analyse) :
84         tosave = {'uuid' : analyse['uuid'], 'ira': analyse['ira'], 'type' : analyse['type']}
85         tosave['name'] = analyse['name']
86         self.matrix.append(tosave)
87         self.write()
88         self.read()
89
90     def addmultiple(self, analyses) :
91         log.info('add multiple')
92         for analyse in analyses :
93             tosave = {'uuid' : analyse['uuid'], 'ira': analyse['ira'], 'type' : analyse['type']}
94             corpus = analyse['corpus']
95             tosave['corpus'] = corpus
96             tosave['name'] = analyse['name']
97             if corpus in self.corpus :
98                 if 'analyses' in self.history[self.ordercorpus[corpus]] :
99                     self.history[self.ordercorpus[corpus]]['analyses'].append(tosave)
100                 else :
101                     self.history[self.ordercorpus[corpus]]['analyses'] = [tosave]
102         self.write()
103         self.read()
104
105     def delete(self, analyse, corpus = False) :
106         log.info('delete %s' % analyse.get('name', 'noname'))
107         if corpus :
108             self.history.pop(self.ordercorpus[analyse['uuid']])
109             if analyse['uuid'] in self.openedcorpus :
110                 del self.openedcorpus[analyse['uuid']]
111         elif analyse['uuid'] in self.analyses :
112             todel = [i for i, ana in enumerate(self.corpus[analyse['corpus']]['analyses']) if ana['uuid'] == analyse['uuid']][0]
113             self.history[self.ordercorpus[analyse['corpus']]]['analyses'].pop(todel)
114         elif analyse['uuid'] in self.matrixanalyse :
115             self.matrix = [mat for mat in self.matrix if mat['uuid'] != analyse['uuid']]
116         self.write()
117         self.read()
118
119     def addtab(self, analyse) :
120         self.opened[analyse['uuid']] = analyse
121
122     def rmtab(self, analyse) :
123         del self.opened[analyse['uuid']]
124
125     def clean(self) :
126         corpustodel = [corpus for corpus in self.history if not os.path.exists(corpus['ira'])]
127         print corpustodel
128         for corpus in corpustodel :
129             print 'cleaning :', corpus['corpus_name']
130             self.delete(corpus, corpus = True)
131     
132     def __str__(self) :
133         return str(self.history)
134
135 class DoConf :
136     def __init__(self, configfile=None, diff = None, parametres = None) :
137         self.configfile = configfile
138         self.conf = ConfigParser()
139         if configfile is not None :
140             self.conf.readfp(codecs.open(configfile, 'r', 'utf8'))
141         self.parametres = {}
142         if parametres is not None :
143             self.doparametres(parametres)
144
145     def doparametres(self, parametres) :
146         return parametres
147
148     def getsections(self) :
149         return self.conf.sections()
150
151     def getoptions(self, section = None, diff = None):
152         parametres = {}
153         if section is None :
154             section = self.conf.sections()[0]
155         for option in self.conf.options(section) :
156             if self.conf.get(section, option).isdigit() :
157                 parametres[option] = int(self.conf.get(section, option))
158             elif self.conf.get(section, option) == 'False' :
159                 parametres[option] = False
160             elif self.conf.get(section, option) == 'True' :
161                 parametres[option] = True
162             elif self.conf.get(section, option).startswith('(') and self.conf.get(section, option).endswith(')') :
163                 parametres[option] = ast.literal_eval(self.conf.get(section, option))
164             elif self.conf.get(section, option).startswith('[') and self.conf.get(section, option).endswith(']') :
165                 parametres[option] = ast.literal_eval(self.conf.get(section, option))
166             else :
167                 parametres[option] = self.conf.get(section, option)
168         if 'type' not in parametres :
169             parametres['type'] = section
170         return parametres
171             
172     def makeoptions(self, sections, parametres, outfile = None) :
173         txt = ''
174         for i, section in enumerate(sections) :
175             txt += '[%s]\n' % section
176             if not self.conf.has_section(section) :
177                 self.conf.add_section(section)
178             for option in parametres[i] :
179                 if isinstance(parametres[i][option], int) :
180                     self.conf.set(section, option, `parametres[i][option]`)
181                     txt += '%s = %i\n' % (option, parametres[i][option])
182                 elif isinstance(parametres[i][option], basestring) :
183                     self.conf.set(section, option, parametres[i][option].encode('utf8'))
184                     txt += '%s = %s\n' % (option, parametres[i][option])
185                 elif isinstance(parametres[i][option], wx.Colour) :
186                     self.conf.set(section, option, str(parametres[i][option]))
187                     txt += '%s = %s\n' % (option, str(parametres[i][option]))
188                 elif option == 'analyses' :
189                     pass
190                 else :
191                     self.conf.set(section, option, `parametres[i][option]`)
192                     txt += '%s = %s\n' % (option, `parametres[i][option]`)
193         if outfile is None :
194             outfile = self.configfile
195         with codecs.open(outfile, 'w', 'utf8') as f :
196             f.write(txt)
197             #self.conf.write(f)
198
199     def totext(self, parametres) :
200         #txt = ['Corpus']
201         txt = []
202         for val in parametres :
203             if isinstance(parametres[val], int) :
204                 txt.append(' \t\t: '.join([val, `parametres[val]`]))
205             elif isinstance(parametres[val], basestring) :
206                 txt.append(' \t\t: '.join([val, parametres[val]]))
207             elif val in ['listet', 'stars'] :
208                 pass
209             else :
210                 txt.append(' \t\t: '.join([val, `parametres[val]`]))
211         return '\n'.join(txt)
212
213
214 def write_tab(tab, fileout) :
215         writer = csv.writer(open(fileout, 'wb'), delimiter=';', quoting = csv.QUOTE_NONNUMERIC)
216         writer.writerows(tab)
217
218 class BugDialog(wx.Dialog):
219     def __init__(self, *args, **kwds):
220         # begin wxGlade: MyDialog.__init__
221         kwds["style"] = wx.DEFAULT_DIALOG_STYLE
222         kwds["size"] = wx.Size(500, 200)
223         wx.Dialog.__init__(self, *args, **kwds)
224         self.SetTitle(kwds['title'])
225         self.text_ctrl_1 = wx.TextCtrl(self, -1, "", style=wx.TE_MULTILINE)
226         self.text_ctrl_1.SetBackgroundColour('#DDE8EB')
227         self.button_1 = wx.Button(self, wx.ID_OK, "")
228
229         self.__set_properties()
230         self.__do_layout()
231         # end wxGlade
232
233     def __set_properties(self):
234         # begin wxGlade: MyDialog.__set_properties
235         self.SetMinSize(wx.Size(500, 200))
236         self.text_ctrl_1.SetMinSize(wx.Size(500, 200))
237         
238         # end wxGlade
239
240     def __do_layout(self):
241         # begin wxGlade: MyDialog.__do_layout
242         sizer_1 = wx.BoxSizer(wx.VERTICAL)
243         sizer_1.Add(self.text_ctrl_1, 1, wx.EXPAND, 0)
244         sizer_1.Add(self.button_1, 0, wx.ALIGN_CENTER_HORIZONTAL, 0)
245         self.SetSizer(sizer_1)
246         sizer_1.Fit(self)
247         self.Layout()
248
249
250 def CreateIraFile(DictPathOut, clusternb, corpname='corpus_name', section = 'analyse'):
251     AnalyseConf = ConfigParser()
252     AnalyseConf.read(DictPathOut['ira'])
253     AnalyseConf.add_section(section)
254     date = datetime.datetime.now().ctime()
255     AnalyseConf.set(section, 'date', str(date))
256     AnalyseConf.set(section, 'clusternb', clusternb)
257     AnalyseConf.set(section, 'corpus_name', corpname)
258
259     fileout = open(DictPathOut['ira'], 'w')
260     AnalyseConf.write(fileout)
261     fileout.close()
262
263 def sortedby(list, direct, *indices):
264
265     """
266         sortedby: sort a list of lists (e.g. a table) by one or more indices
267                   (columns of the table) and return the sorted list
268
269         e.g.
270          for list = [[2,3],[1,2],[3,1]]:
271          sortedby(list,1) will return [[3, 1], [1, 2], [2, 3]],
272          sortedby(list,0) will return [[1, 2], [2, 3], [3, 1]]
273     """
274
275     nlist = map(lambda x, indices=indices: 
276                  map(lambda i, x=x: x[i], indices) + [x],
277                  list)
278     if direct == 1:
279         nlist.sort()
280     elif direct == 2:
281         nlist.sort(reverse=True)
282     return map(lambda l: l[-1], nlist)
283
284 def add_type(line, dictlem):
285     if line[4] in dictlem:
286         line.append(dictlem[line[4]])
287     else :
288         line.append('')
289     return line
290
291 def treat_line_alceste(i, line) :
292     if line[0] == '*' or line[0] == '*****' :
293         return line + ['']
294     if line[5] == 'NA':
295         print 'NA', line[5]
296         pass
297     elif float(line[5].replace(',', '.')) < 0.0001:
298         line[5] = '< 0,0001'
299     elif float(line[5].replace(',', '.')) > 0.05:
300         line[5] = 'NS (%s)' % str(float(line[5].replace(',', '.')))[0:7]
301     else:
302         line[5] = str(float(line[5].replace(',', '.')))[0:7]
303     return [i, int(line[0]), int(line[1]), float(line[2]), float(line[3]), line[6], line[4], line[5]]
304
305 def ReadProfileAsDico(File, Alceste=False, encoding = sys.getdefaultencoding()):
306     #print 'lecture des profils : ReadProfileAsDico'
307     #if Alceste :
308     #    print 'lecture du dictionnaire de type'
309     #    dictlem = {}
310     #    for line in parent.corpus.lem_type_list :
311     #        dictlem[line[0]] = line[1]
312     dictlem = {}
313     print 'lecture des profiles'
314     #encoding = sys.getdefaultencoding()
315     FileReader = codecs.open(File, 'r', encoding)
316     Filecontent = FileReader.readlines()
317     FileReader.close()
318     DictProfile = {}
319     count = 0
320     #rows = [row.replace('\n', '').replace("'", '').replace('\"', '').replace(',', '.').replace('\r','').split(';') for row in Filecontent]
321     rows = [row.replace('\n', '').replace("'", '').replace('\"', '').replace('\r','').split(';') for row in Filecontent]
322     rows.pop(0)
323     ClusterNb = rows[0][2]
324     rows.pop(0)
325     clusters = [row[2] for row in rows if row[0] == u'**']
326     valclusters = [row[1:4] for row in rows if row[0] == u'****']
327     lp = [i for i, line in enumerate(rows) if line[0] == u'****']
328     prof = [rows[lp[i] + 1:lp[i+1] - 1] for i in range(0, len(lp)-1)] + [rows[lp[-1] + 1:len(rows)]] 
329     if Alceste :
330         prof = [[add_type(row, dictlem) for row in pr] for pr in prof]
331         prof = [[treat_line_alceste(i,line) for i, line in enumerate(pr)] for pr in prof] 
332     else :
333         prof = [[line + [''] for line in pr] for pr in prof]
334         prof = [[treat_line_alceste(i,line) for i, line in enumerate(pr)] for pr in prof]
335     for i, cluster in enumerate(clusters):
336         DictProfile[cluster] = [valclusters[i]] + prof[i]
337     return DictProfile
338
339 def GetTxtProfile(dictprofile, cluster_size) :
340     proflist = []
341     for classe in range(0, len(dictprofile)) :
342         prof = dictprofile[str(classe + 1)]
343         clinfo = cluster_size[classe]
344         proflist.append('\n'.join([' '.join(['classe %i' % (classe + 1), '-', '%s uce sur %s - %s%%' % (clinfo[0], clinfo[1], clinfo[2])]), '\n'.join(['%5s|%5s|%6s|%6s|%8s|%8s|%20s\t%10s' % tuple([str(val) for val in line]) for line in prof if len(line)==8])]))
345     return '\n\n'.join(proflist)
346
347 def formatExceptionInfo(maxTBlevel=5):
348          cla, exc, trbk = sys.exc_info()
349          try :
350             excName = cla.__name__
351          except :
352             excName = 'None'
353          try:
354              excArgs = exc.args[0]
355          except :
356              excArgs = "<no args>"
357          excTb = traceback.format_tb(trbk, maxTBlevel)
358          return (excName, excArgs, excTb)
359
360
361 #fonction des etudiants de l'iut
362 def decoupercharact(chaine, longueur, longueurOptimale, separateurs = None) :
363     """
364         on part du dernier caractère, et on recule jusqu'au début de la chaîne.
365         Si on trouve un '$', c'est fini.
366         Sinon, on cherche le meilleur candidat. C'est-à-dire le rapport poids/distance le plus important.
367     """
368     separateurs = [[u'.', 60.0], [u'?', 60.0], [u'!', 60.0], [u'£$£', 60], [u':', 50.0], [u';', 40.0], [u',', 10.0], [u' ', 0.1]]
369     trouve = False                 # si on a trouvé un bon séparateur
370     iDecoupe = 0                # indice du caractere ou il faut decouper
371     
372     # on découpe la chaine pour avoir au maximum 240 caractères
373     longueur = min(longueur, len(chaine) - 1)
374     chaineTravail = chaine[:longueur + 1]
375     nbCar = longueur
376     meilleur = ['', 0, 0]        # type, poids et position du meilleur separateur
377     
378     # on vérifie si on ne trouve pas un '$'
379     indice = chaineTravail.find(u'$')
380     if indice > -1:
381         trouve = True
382         iDecoupe = indice
383
384     # si on ne trouve rien, on cherche le meilleur séparateur
385     if not trouve:
386         while nbCar >= 0:
387             caractere = chaineTravail[nbCar]
388             distance = abs(longueurOptimale - nbCar) + 1
389             meilleureDistance = abs(longueurOptimale - meilleur[2]) + 1
390
391             # on vérifie si le caractére courant est une marque de ponctuation
392             for s in separateurs:
393                 if caractere == s[0]:
394                     # si c'est une ponctuation 
395                     
396                     if s[1] / distance > float(meilleur[1]) / meilleureDistance:
397                         # print nbCar, s[0]
398                         meilleur[0] = s[0]
399                         meilleur[1] = s[1]
400                         meilleur[2] = nbCar
401                         trouve = True
402                         iDecoupe = nbCar
403                         
404                     # et on termine la recherche
405                     break
406
407             # on passe au caractère précédant
408             nbCar = nbCar - 1
409     
410     # si on a trouvé
411     if trouve:
412         fin = chaine[iDecoupe + 1:]
413         retour = chaineTravail[:iDecoupe]
414         return len(retour) > 0, retour.split(), fin
415     # si on a rien trouvé
416     return False, chaine.split(), ''
417
418
419 exceptions = {'paragrapheOT' : u"Un problème de formatage (présence d'un marqueur de paragraphe (-*) en dehors d'un texte) est survenu Ã  la ligne ",
420               'EmptyText' : u"Texte vide (probablement un problème de formatage du corpus). Le problème est apparu Ã  la ligne ",
421               'CorpusEncoding' : u"Problème d'encodage.",
422               'TextBeforeTextMark' : u"Problème de formatage : du texte avant le premier marqueur de texte (****). Le problème est survenu Ã  la ligne ",
423 }
424
425 def BugReport(parent, error = None):
426     for ch in parent.GetChildren():
427         if "<class 'wx._windows.ProgressDialog'>" == str(type(ch)):
428             ch.Destroy()   
429     excName, exc, excTb = formatExceptionInfo()
430     if excName == 'Exception' :
431         print exc
432         if len(exc.split()) == 2 :
433             mss, linenb = exc.split()
434             if mss in exceptions :
435                 txt = exceptions[mss] + linenb
436             else :
437                 txt = exc
438         else :
439             if exc in exceptions :
440                 txt = exceptions[exc]
441             else :
442                 txt = exc
443         title = "Information"
444     else :
445         txt = u'            !== BUG ==!       \n'
446         txt += u'*************************************\n'
447         txt += '\n'.join(excTb).replace('    ', ' ')
448         txt += excName + '\n'
449         txt += exc
450         title = "Bug"
451
452     dial = BugDialog(parent, **{'title' : title})
453     if 'Rerror' in dir(parent) :
454         txt += parent.Rerror
455         parent.Rerror = ''
456     log.info(txt)
457     dial.text_ctrl_1.write(txt)
458     dial.CenterOnParent()
459     dial.ShowModal()
460     dial.Destroy()
461     
462 def PlaySound(parent):
463     if parent.pref.getboolean('iramuteq', 'sound') :
464         try:
465             if "gtk2" in wx.PlatformInfo:
466                 error = Popen(['aplay','-q',os.path.join(parent.AppliPath,'son_fin.wav')])
467             else :    
468                 sound = wx.Sound(os.path.join(parent.AppliPath, 'son_fin.wav'))
469                 sound.Play(wx.SOUND_SYNC)
470         except :
471             print 'pas de son'
472
473 def ReadDicoAsDico(dicopath):
474     with codecs.open(dicopath, 'r', 'UTF8') as f:
475         content = f.readlines()
476     dico = {}
477     for line in content :
478         if line[0] != u'':
479             line = line.rstrip('\n\r').replace(u'\n', '').replace('"', '').split('\t')
480             dico[line[0]] = line[1:]
481     return dico
482
483 def ReadLexique(parent, lang = 'french', filein = None):
484     if lang != 'other' :
485         if filein is None :
486             parent.lexique = ReadDicoAsDico(parent.DictPath.get(lang, 'french'))
487         else :
488             parent.lexique = ReadDicoAsDico(filein)
489     else :
490         parent.lexique = {}
491
492 def ReadList(filein, encoding = sys.getdefaultencoding()):
493     #file = open(filein)
494     file = codecs.open(filein, 'r', encoding)
495     content = file.readlines()
496     file.close()
497     first = content.pop(0)
498     first = first.replace('\n', '').replace('\r','').replace('\"', '').split(';')
499     dict = {}
500     i = 0
501     for line in content:
502         line = line.replace('\n', '').replace('\r','').replace('\"', '').replace(',', '.')
503         line = line.split(';')
504         nline = [line[0]]
505         for val in line[1:]:
506             if val == u'NA' :
507                 don = ''
508             else: 
509                 try:
510                     don = int(val)
511                 except:
512                     don = float('%.5f' % float(val))
513             nline.append(don)
514         dict[i] = nline
515         i += 1
516     return dict, first
517
518 def exec_RCMD(rpath, command) :
519     log.info('R CMD INSTALL %s' % command)
520     rpath = rpath.replace('\\','\\\\')
521     error = call(["%s" % rpath, 'CMD', 'INSTALL', "%s" % command])
522     return error
523
524 def exec_rcode(rpath, rcode, wait = True, graph = False):
525     log.info("R Script : %s" % rcode)
526     needX11 = False
527     if sys.platform == 'darwin' :
528         try :
529             macversion = platform.mac_ver()[0].split('.')
530             if int(macversion[1]) < 5 :
531                 needX11 = True
532             else :
533                 needX11 = False
534         except :
535             needX11 = False
536
537     rpath = rpath.replace('\\','\\\\')
538     env = os.environ.copy()
539     if sys.platform == 'darwin' and 'LC_ALL' not in env:
540         env['LC_ALL'] = 'en_US.UTF-8'
541     if not graph :
542         if wait :
543             if sys.platform == 'win32':
544                 error = call(["%s" % rpath, "--vanilla","--slave","-f", "%s" % rcode])
545             else :
546                 error = call([rpath, '--slave', "--vanilla", "-f %s" % rcode, "--encoding=UTF-8"], env = env)
547             return error
548         else :
549             if sys.platform == 'win32':
550                 pid = Popen(["%s" % rpath, '--vanilla','--slave','-f', "%s" % rcode])
551             else :
552                 pid = Popen([rpath, '--slave', "--vanilla", "-f %s" % rcode, "--encoding=UTF-8"], stderr = PIPE, env = env)
553             return pid
554     else :
555         if wait :
556             if sys.platform == 'win32':
557                 error = call(["%s" % rpath, '--vanilla','--slave','-f', "%s" % rcode])
558             elif sys.platform == 'darwin' and needX11:
559                 os.environ['DISPLAY'] = ':0.0'
560                 error = call([rpath, '--vanilla','--slave',"-f %s" % rcode, "--encoding=UTF-8"], env = env)
561             else :
562                 error = call([rpath, '--vanilla','--slave',"-f %s" % rcode, "--encoding=UTF-8"], env = env)
563             return error
564         else :
565             if sys.platform == 'win32':
566                 pid = Popen(["%s" % rpath, '--vanilla','--slave','-f', "%s" % rcode])
567             elif sys.platform == 'darwin' and needX11:
568                 os.environ['DISPLAY'] = ':0.0'
569                 pid = Popen([rpath, '--vanilla','--slave',"-f %s" % rcode, "--encoding=UTF-8"], stderr = PIPE, env = env)
570             else :
571                 pid = Popen([rpath, '--vanilla','--slave',"-f %s" % rcode, "--encoding=UTF-8"], stderr = PIPE, env = env)
572             return pid
573
574 def check_Rresult(parent, pid) :
575     if isinstance(pid, Popen) :
576         if pid.returncode != 0 :
577             error = pid.communicate()
578             error = [str(error[0]), error[1]]
579             if error[1] is None :
580                 error[1] = 'None'
581             parent.Rerror = '\n'.join([str(pid.returncode), '\n'.join(error)])
582             try :
583                 raise Exception('\n'.join([u'Erreur R', '\n'.join(error[1:])]))
584             except :
585                 BugReport(parent)
586             return False
587         else :
588             return True
589     else :
590         if pid != 0 :
591             try :
592                 raise Exception(u'Erreur R')
593             except :
594                 BugReport(parent)
595             return False
596         else :
597             return True
598
599 def print_liste(filename,liste):
600     with open(filename,'w') as f :
601         for graph in liste :
602             f.write(';'.join(graph)+'\n')
603
604 def read_list_file(filename, encoding = sys.getdefaultencoding()):
605     with codecs.open(filename,'rU', encoding) as f :
606         content=f.readlines()
607         ncontent=[line.replace('\n','').split(';') for line in content if line.strip() != '']
608     return ncontent
609         
610 class MessageImage(wx.Frame):
611     def __init__(self, parent,title, size):
612         wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = title, pos = wx.DefaultPosition, size = size, style = wx.DEFAULT_FRAME_STYLE )
613         self.SetSizeHintsSz( wx.DefaultSize, wx.DefaultSize )
614         self.imageFile = False
615         self.imagename = u"chi_classe.png"
616         self.HtmlPage = wx.html.HtmlWindow(self, -1)
617         self.HtmlPage.SetMinSize(size)
618         if "gtk2" in wx.PlatformInfo:
619             self.HtmlPage.SetStandardFonts()
620         self.HtmlPage.SetFonts('Courier', 'Courier')
621         
622         self.button_1 = wx.Button(self, wx.ID_CANCEL)
623         self.button_2 = wx.Button(self, wx.ID_SAVE)
624         self.Bind(wx.EVT_BUTTON, self.OnCloseMe, self.button_1)
625         self.Bind(wx.EVT_BUTTON, self.OnSaveImage, self.button_2)
626         self.do_layout()
627
628     def do_layout(self):
629         self.sizer_1 = wx.BoxSizer(wx.VERTICAL)
630         self.sizer_2 = wx.BoxSizer(wx.HORIZONTAL)
631         self.sizer_1.Add(self.HtmlPage, 2, wx.EXPAND, 0)
632
633         self.m_sdbSizer1 = wx.StdDialogButtonSizer()
634         self.m_sdbSizer1.AddButton(  self.button_2 )
635         self.m_sdbSizer1.AddButton(  self.button_1 )
636         self.m_sdbSizer1.Realize()
637         self.sizer_1.Add(self.m_sdbSizer1, 0, wx.EXPAND, 5)
638         self.SetSizer(self.sizer_1)
639         self.Layout()
640         self.sizer_1.Fit( self )
641
642     def addsaveimage(self, imageFile) :
643         self.imageFile = imageFile
644         
645     def OnCloseMe(self, event):
646         self.Destroy()
647
648     def OnSaveImage(self, event) :
649         dlg = wx.FileDialog(
650             self, message="Enregistrer sous...", defaultDir=os.getcwd(),
651             defaultFile= self.imagename, wildcard="png|*.png", style=wx.SAVE | wx.OVERWRITE_PROMPT
652             )
653         dlg.SetFilterIndex(2)
654         dlg.CenterOnParent()
655         if dlg.ShowModal() == wx.ID_OK:
656             path = dlg.GetPath()
657             copyfile(self.imageFile, path)
658             
659
660 def progressbar(self, maxi) :
661     if 'parent' in dir(self) :
662         parent = self.parent
663     else :
664         parent = self
665     return wx.ProgressDialog("Traitements",
666                              "Veuillez patienter...",
667                              maximum=maxi,
668                              parent=parent,
669                              style=wx.PD_APP_MODAL | wx.PD_AUTO_HIDE | wx.PD_ELAPSED_TIME | wx.PD_CAN_ABORT
670                              )
671
672
673 def treat_var_mod(variables) :
674     var_mod = {}
675     variables = list(set(variables))
676     varmod = [variable.split('_') for variable in variables]
677     vars = list(set([var[0] for var in varmod if len(var) >=2]))
678     for var in vars :
679         mods = ['_'.join(v) for v in varmod if v[0] == var]
680         var_mod[var] = mods
681     
682 #     for variable in variables :
683 #         if u'_' in variable :
684 #             forme = variable.split(u'_')
685 #             var = forme[0]
686 #             mod = forme[1]
687 #             if not var in var_mod :
688 #                 var_mod[var] = [variable]
689 #             else :
690 #                 if not mod in var_mod[var] :
691 #                     var_mod[var].append(variable)
692     return var_mod
693
694 def doconcorde(corpus, uces, mots, uci = False) :
695     if not uci :
696         ucestxt1 = [row for row in corpus.getconcorde(uces)]
697     else :
698         ucestxt1 = [row for row in corpus.getuciconcorde(uces)]
699     ucestxt1 = dict(ucestxt1)
700     ucestxt = []
701     ucis_txt = []
702     listmot = [corpus.getlems()[lem].formes for lem in mots]
703     listmot = [corpus.getforme(fid).forme for lem in listmot for fid in lem]
704     mothtml = ['<font color=red><b>'+mot+'</b></font>' for mot in listmot]
705     dmots = dict(zip(listmot, mothtml))
706     for uce in uces :
707         ucetxt = ucestxt1[uce].split()
708         ucetxt = ' '.join([dmots.get(mot, mot) for mot in ucetxt])
709         if not uci :
710             ucis_txt.append('<p><b>' + ' '.join(corpus.ucis[corpus.getucefromid(uce).uci].etoiles) + '</b></p>')
711         else :
712             ucis_txt.append('<p><b>' + ' '.join(corpus.ucis[uce].etoiles) + '</b></p>')
713         ucestxt.append(ucetxt)        
714     return ucis_txt, ucestxt
715  
716
717 def getallstcarac(corpus, analyse) :
718    pathout = PathOut(analyse['ira'])
719    profils =  ReadProfileAsDico(pathout['PROFILE_OUT'], Alceste, self.encoding)
720    print profils