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