...
[iramuteq] / functions.py
1 #!/bin/env python
2 # -*- coding: utf-8 -*-
3 #Author: Pierre Ratinaud
4 #Copyright (c) 2008-2012 Pierre Ratinaud
5 #Lisense: 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         for analyse in analyses :
92             tosave = {'uuid' : analyse['uuid'], 'ira': analyse['ira'], 'type' : analyse['type']}
93             corpus = analyse['uuid']
94             tosave['corpus'] = corpus
95             tosave['name'] = analyse['name']
96             if corpus in self.corpus :
97                 if 'analyses' in self.history[self.ordercorpus[corpus]] :
98                     self.history[self.ordercorpus[corpus]]['analyses'].append(tosave)
99                 else :
100                     self.history[self.ordercorpus[corpus]]['analyses'] = [tosave]
101         self.write()
102         self.read()
103
104     def delete(self, analyse, corpus = False) :
105         if corpus :
106             self.history.pop(self.ordercorpus[analyse['uuid']])
107             if analyse['uuid'] in self.openedcorpus :
108                 del self.openedcorpus[analyse['uuid']]
109         elif analyse['uuid'] in self.analyses :
110             todel = [i for i, ana in enumerate(self.corpus[analyse['corpus']]['analyses']) if ana['uuid'] == analyse['uuid']][0]
111             self.history[self.ordercorpus[analyse['corpus']]]['analyses'].pop(todel)
112         elif analyse['uuid'] in self.matrixanalyse :
113             self.matrix = [mat for mat in self.matrix if mat['uuid'] != analyse['uuid']]
114         self.write()
115         self.read()
116
117     def addtab(self, analyse) :
118         self.opened[analyse['uuid']] = analyse
119
120     def rmtab(self, analyse) :
121         del self.opened[analyse['uuid']]
122     
123     def __str__(self) :
124         return str(self.history)
125
126 class DoConf :
127     def __init__(self, configfile=None, diff = None, parametres = None) :
128         self.configfile = configfile
129         self.conf = ConfigParser()
130         if configfile is not None :
131             self.conf.readfp(codecs.open(configfile, 'r', 'utf8'))
132         self.parametres = {}
133         if parametres is not None :
134             self.doparametres(parametres)
135
136     def doparametres(self, parametres) :
137         return parametres
138
139     def getsections(self) :
140         return self.conf.sections()
141
142     def getoptions(self, section = None, diff = None):
143         parametres = {}
144         if section is None :
145             section = self.conf.sections()[0]
146         for option in self.conf.options(section) :
147             if self.conf.get(section, option).isdigit() :
148                 parametres[option] = int(self.conf.get(section, option))
149             elif self.conf.get(section, option) == 'False' :
150                 parametres[option] = False
151             elif self.conf.get(section, option) == 'True' :
152                 parametres[option] = True
153             elif self.conf.get(section, option).startswith('(') and self.conf.get(section, option).endswith(')') :
154                 parametres[option] = ast.literal_eval(self.conf.get(section, option))
155             elif self.conf.get(section, option).startswith('[') and self.conf.get(section, option).endswith(']') :
156                 parametres[option] = ast.literal_eval(self.conf.get(section, option))
157             else :
158                 parametres[option] = self.conf.get(section, option)
159         if 'type' not in parametres :
160             parametres['type'] = section
161         return parametres
162             
163     def makeoptions(self, sections, parametres, outfile = None) :
164         txt = ''
165         for i, section in enumerate(sections) :
166             txt += '[%s]\n' % section
167             if not self.conf.has_section(section) :
168                 self.conf.add_section(section)
169             for option in parametres[i] :
170                 if isinstance(parametres[i][option], int) :
171                     self.conf.set(section, option, `parametres[i][option]`)
172                     txt += '%s = %i\n' % (option, parametres[i][option])
173                 elif isinstance(parametres[i][option], basestring) :
174                     self.conf.set(section, option, parametres[i][option].encode('utf8'))
175                     txt += '%s = %s\n' % (option, parametres[i][option])
176                 elif isinstance(parametres[i][option], wx.Colour) :
177                     self.conf.set(section, option, str(parametres[i][option]))
178                     txt += '%s = %s\n' % (option, str(parametres[i][option]))
179                 elif option == 'analyses' :
180                     pass
181                 else :
182                     self.conf.set(section, option, `parametres[i][option]`)
183                     txt += '%s = %s\n' % (option, `parametres[i][option]`)
184         if outfile is None :
185             outfile = self.configfile
186         with codecs.open(outfile, 'w', 'utf8') as f :
187             f.write(txt)
188             #self.conf.write(f)
189
190     def totext(self, parametres) :
191         #txt = ['Corpus']
192         txt = []
193         for val in parametres :
194             if isinstance(parametres[val], int) :
195                 txt.append(' \t\t: '.join([val, `parametres[val]`]))
196             elif isinstance(parametres[val], basestring) :
197                 txt.append(' \t\t: '.join([val, parametres[val]]))
198             elif val in ['listet', 'stars'] :
199                 pass
200             else :
201                 txt.append(' \t\t: '.join([val, `parametres[val]`]))
202         return '\n'.join(txt)
203
204
205 def write_tab(tab, fileout) :
206         writer = csv.writer(open(fileout, 'wb'), delimiter=';', quoting = csv.QUOTE_NONNUMERIC)
207         writer.writerows(tab)
208
209 class BugDialog(wx.Dialog):
210     def __init__(self, *args, **kwds):
211         # begin wxGlade: MyDialog.__init__
212         kwds["style"] = wx.DEFAULT_DIALOG_STYLE
213         kwds["size"] = wx.Size(500, 200)
214         wx.Dialog.__init__(self, *args, **kwds)
215         self.text_ctrl_1 = wx.TextCtrl(self, -1, "", style=wx.TE_MULTILINE)
216         self.button_1 = wx.Button(self, wx.ID_OK, "")
217
218         self.__set_properties()
219         self.__do_layout()
220         # end wxGlade
221
222     def __set_properties(self):
223         # begin wxGlade: MyDialog.__set_properties
224         self.SetTitle("Bug")
225         self.SetMinSize(wx.Size(500, 200))
226         self.text_ctrl_1.SetMinSize(wx.Size(500, 200))
227         
228         # end wxGlade
229
230     def __do_layout(self):
231         # begin wxGlade: MyDialog.__do_layout
232         sizer_1 = wx.BoxSizer(wx.VERTICAL)
233         sizer_1.Add(self.text_ctrl_1, 1, wx.EXPAND, 0)
234         sizer_1.Add(self.button_1, 0, wx.ALIGN_CENTER_HORIZONTAL, 0)
235         self.SetSizer(sizer_1)
236         sizer_1.Fit(self)
237         self.Layout()
238
239
240 def CreateIraFile(DictPathOut, clusternb, corpname='corpus_name', section = 'analyse'):
241     AnalyseConf = ConfigParser()
242     AnalyseConf.read(DictPathOut['ira'])
243     AnalyseConf.add_section(section)
244     date = datetime.datetime.now().ctime()
245     AnalyseConf.set(section, 'date', str(date))
246     AnalyseConf.set(section, 'clusternb', clusternb)
247     AnalyseConf.set(section, 'corpus_name', corpname)
248
249     fileout = open(DictPathOut['ira'], 'w')
250     AnalyseConf.write(fileout)
251     fileout.close()
252
253 def sortedby(list, direct, *indices):
254
255     """
256         sortedby: sort a list of lists (e.g. a table) by one or more indices
257                   (columns of the table) and return the sorted list
258
259         e.g.
260          for list = [[2,3],[1,2],[3,1]]:
261          sortedby(list,1) will return [[3, 1], [1, 2], [2, 3]],
262          sortedby(list,0) will return [[1, 2], [2, 3], [3, 1]]
263     """
264
265     nlist = map(lambda x, indices=indices: 
266                  map(lambda i, x=x: x[i], indices) + [x],
267                  list)
268     if direct == 1:
269         nlist.sort()
270     elif direct == 2:
271         nlist.sort(reverse=True)
272     return map(lambda l: l[-1], nlist)
273
274 def add_type(line, dictlem):
275     if line[4] in dictlem:
276         line.append(dictlem[line[4]])
277     else :
278         line.append('')
279     return line
280
281 def treat_line_alceste(i, line) :
282     if line[0] == '*' or line[0] == '*****' :
283         return line + ['']
284     if line[5] == 'NA':
285         print 'NA', line[5]
286         pass
287     elif float(line[5].replace(',', '.')) < 0.0001:
288         line[5] = '< 0,0001'
289     elif float(line[5].replace(',', '.')) > 0.05:
290         line[5] = 'NS (%s)' % str(float(line[5].replace(',', '.')))[0:7]
291     else:
292         line[5] = str(float(line[5].replace(',', '.')))[0:7]
293     return [i, int(line[0]), int(line[1]), float(line[2]), float(line[3]), line[6], line[4], line[5]]
294
295 def ReadProfileAsDico(File, Alceste=False, encoding = sys.getdefaultencoding()):
296     #print 'lecture des profils : ReadProfileAsDico'
297     #if Alceste :
298     #    print 'lecture du dictionnaire de type'
299     #    dictlem = {}
300     #    for line in parent.corpus.lem_type_list :
301     #        dictlem[line[0]] = line[1]
302     dictlem = {}
303     print 'lecture des profiles'
304     #encoding = sys.getdefaultencoding()
305     FileReader = codecs.open(File, 'r', encoding)
306     Filecontent = FileReader.readlines()
307     FileReader.close()
308     DictProfile = {}
309     count = 0
310     rows = [row.replace('\n', '').replace("'", '').replace('\"', '').replace(',', '.').replace('\r','').split(';') for row in Filecontent]
311     rows.pop(0)
312     ClusterNb = rows[0][2]
313     rows.pop(0)
314     clusters = [row[2] for row in rows if row[0] == u'**']
315     valclusters = [row[1:4] for row in rows if row[0] == u'****']
316     lp = [i for i, line in enumerate(rows) if line[0] == u'****']
317     prof = [rows[lp[i] + 1:lp[i+1] - 1] for i in range(0, len(lp)-1)] + [rows[lp[-1] + 1:len(rows)]] 
318     if Alceste :
319         prof = [[add_type(row, dictlem) for row in pr] for pr in prof]
320         prof = [[treat_line_alceste(i,line) for i, line in enumerate(pr)] for pr in prof] 
321     else :
322         prof = [[line + [''] for line in pr] for pr in prof]
323         prof = [[treat_line_alceste(i,line) for i, line in enumerate(pr)] for pr in prof]
324     for i, cluster in enumerate(clusters):
325         DictProfile[cluster] = [valclusters[i]] + prof[i]
326     return DictProfile
327
328 def GetTxtProfile(dictprofile, cluster_size) :
329     proflist = []
330     for classe in range(0, len(dictprofile)) :
331         prof = dictprofile[str(classe + 1)]
332         clinfo = cluster_size[classe]
333         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])]))
334     return '\n\n'.join(proflist)
335
336 def formatExceptionInfo(maxTBlevel=5):
337          cla, exc, trbk = sys.exc_info()
338          try :
339             excName = cla.__name__
340          except :
341             excName = 'None'
342          try:
343              excArgs = exc.args[0]
344          except :
345              excArgs = "<no args>"
346          excTb = traceback.format_tb(trbk, maxTBlevel)
347          return (excName, excArgs, excTb)
348
349
350 #fonction des etudiants de l'iut
351 def decoupercharact(chaine, longueur, longueurOptimale, separateurs = None) :
352     """
353         on part du dernier caractère, et on recule jusqu'au début de la chaîne.
354         Si on trouve un '$', c'est fini.
355         Sinon, on cherche le meilleur candidat. C'est-à-dire le rapport poids/distance le plus important.
356     """
357     separateurs = [[u'.', 60.0], [u'?', 60.0], [u'!', 60.0], [u'£$£', 60], [u':', 50.0], [u';', 40.0], [u',', 10.0], [u' ', 0.1]]
358     trouve = False                 # si on a trouvé un bon séparateur
359     iDecoupe = 0                # indice du caractere ou il faut decouper
360     
361     # on découpe la chaine pour avoir au maximum 240 caractères
362     longueur = min(longueur, len(chaine) - 1)
363     chaineTravail = chaine[:longueur + 1]
364     nbCar = longueur
365     meilleur = ['', 0, 0]        # type, poids et position du meilleur separateur
366     
367     # on vérifie si on ne trouve pas un '$'
368     indice = chaineTravail.find(u'$')
369     if indice > -1:
370         trouve = True
371         iDecoupe = indice
372
373     # si on ne trouve rien, on cherche le meilleur séparateur
374     if not trouve:
375         while nbCar >= 0:
376             caractere = chaineTravail[nbCar]
377             distance = abs(longueurOptimale - nbCar) + 1
378             meilleureDistance = abs(longueurOptimale - meilleur[2]) + 1
379
380             # on vérifie si le caractére courant est une marque de ponctuation
381             for s in separateurs:
382                 if caractere == s[0]:
383                     # si c'est une ponctuation 
384                     
385                     if s[1] / distance > float(meilleur[1]) / meilleureDistance:
386                         # print nbCar, s[0]
387                         meilleur[0] = s[0]
388                         meilleur[1] = s[1]
389                         meilleur[2] = nbCar
390                         trouve = True
391                         iDecoupe = nbCar
392                         
393                     # et on termine la recherche
394                     break
395
396             # on passe au caractère précédant
397             nbCar = nbCar - 1
398     
399     # si on a trouvé
400     if trouve:
401         fin = chaine[iDecoupe + 1:]
402         retour = chaineTravail[:iDecoupe]
403         return len(retour) > 0, retour.split(), fin
404     # si on a rien trouvé
405     return False, chaine.split(), ''
406
407 def BugReport(parent, error = None):
408     for ch in parent.GetChildren():
409         if "<class 'wx._windows.ProgressDialog'>" == str(type(ch)):
410             ch.Destroy()   
411     excName, exc, excTb = formatExceptionInfo()
412     if excName == 'Exception' :
413         txt = 'Message :\n'
414     else :
415         txt = u'            !== BUG ==!       \n'
416         txt += u'*************************************\n'
417         txt += '\n'.join(excTb).replace('    ', ' ')
418         txt += excName + '\n'
419     txt += exc
420
421     dial = BugDialog(parent)
422     if 'Rerror' in dir(parent) :
423         txt += parent.Rerror
424         parent.Rerror = ''
425     log.info(txt)
426     dial.text_ctrl_1.write(txt)
427     dial.CenterOnParent()
428     dial.ShowModal()
429     dial.Destroy()
430     
431 def PlaySound(parent):
432     if parent.pref.getboolean('iramuteq', 'sound') :
433         try:
434             if "gtk2" in wx.PlatformInfo:
435                 error = Popen(['aplay','-q',os.path.join(parent.AppliPath,'son_fin.wav')])
436             else :    
437                 sound = wx.Sound(os.path.join(parent.AppliPath, 'son_fin.wav'))
438                 sound.Play(wx.SOUND_SYNC)
439         except :
440             print 'pas de son'
441
442 def ReadDicoAsDico(dicopath):
443     with codecs.open(dicopath, 'r', 'UTF8') as f:
444         content = f.readlines()
445     dico = {}
446     for line in content :
447         if line[0] != u'':
448             line = line.replace(u'\n', '').replace('"', '').split('\t')
449             dico[line[0]] = line[1:]
450     return dico
451
452 def ReadLexique(parent, lang = 'french', filein = None):
453     if lang != 'other' :
454         if filein is None :
455             parent.lexique = ReadDicoAsDico(parent.DictPath.get(lang, 'french'))
456         else :
457             parent.lexique = ReadDicoAsDico(filein)
458     else :
459         parent.lexique = {}
460
461 def ReadList(filein, encoding = sys.getdefaultencoding()):
462     #file = open(filein)
463     file = codecs.open(filein, 'r', encoding)
464     content = file.readlines()
465     file.close()
466     first = content.pop(0)
467     first = first.replace('\n', '').replace('\r','').replace('\"', '').split(';')
468     dict = {}
469     i = 0
470     for line in content:
471         line = line.replace('\n', '').replace('\r','').replace('\"', '').replace(',', '.')
472         line = line.split(';')
473         nline = [line[0]]
474         for val in line[1:]:
475             if val == u'NA' :
476                 don = ''
477             else: 
478                 try:
479                     don = int(val)
480                 except:
481                     don = float('%.5f' % float(val))
482             nline.append(don)
483         dict[i] = nline
484         i += 1
485     return dict, first
486
487 def exec_RCMD(rpath, command) :
488     log.info('R CMD INSTALL %s' % command)
489     rpath = rpath.replace('\\','\\\\')
490     error = call(["%s" % rpath, 'CMD', 'INSTALL', "%s" % command])
491     return error
492
493 def exec_rcode(rpath, rcode, wait = True, graph = False):
494     log.info("R Script : %s" % rcode)
495     needX11 = False
496     if sys.platform == 'darwin' :
497         try :
498             macversion = platform.mac_ver()[0].split('.')
499             print macversion
500             if int(macversion[1]) < 5 :
501                 needX11 = True
502             else :
503                 needX11 = False
504         except :
505             needX11 = False
506
507     rpath = rpath.replace('\\','\\\\')
508     if not graph :
509         if wait :
510             if sys.platform == 'win32':
511                 error = call(["%s" % rpath, "--vanilla","--slave","-f", "%s" % rcode])
512             else :
513                 error = call([rpath, '--vanilla','--slave',"-f %s" % rcode])
514             return error
515         else :
516             if sys.platform == 'win32':
517                 pid = Popen(["%s" % rpath, '--vanilla','--slave','-f', "%s" % rcode])
518             else :
519                 pid = Popen([rpath, '--vanilla','--slave',"-f %s" % rcode], stderr = PIPE)
520             return pid
521     else :
522         if wait :
523             if sys.platform == 'win32':
524                 error = call(["%s" % rpath, '--vanilla','--slave','-f', "%s" % rcode])
525             elif sys.platform == 'darwin' and needX11:
526                 os.environ['DISPLAY'] = ':0.0'
527                 error = call([rpath, '--vanilla','--slave',"-f %s" % rcode])
528             else :
529                 error = call([rpath, '--vanilla','--slave',"-f %s" % rcode])
530             return error
531         else :
532             if sys.platform == 'win32':
533                 pid = Popen(["%s" % rpath, '--vanilla','--slave','-f', "%s" % rcode])
534             elif sys.platform == 'darwin' and needX11:
535                 os.environ['DISPLAY'] = ':0.0'
536                 pid = Popen([rpath, '--vanilla','--slave',"-f %s" % rcode], stderr = PIPE)
537             else :
538                 pid = Popen([rpath, '--vanilla','--slave',"-f %s" % rcode], stderr = PIPE)
539             return pid
540
541 def check_Rresult(parent, pid) :
542     if isinstance(pid, Popen) :
543         if pid.returncode != 0 :
544             error = pid.communicate()
545             error = [str(error[0]), error[1]]
546             if error[1] is None :
547                 error[1] = 'None'
548             parent.Rerror = '\n'.join([str(pid.returncode), '\n'.join(error)])
549             try :
550                 raise Exception('\n'.join([u'Erreur R', '\n'.join(error[1:])]))
551             except :
552                 BugReport(parent)
553             return False
554         else :
555             return True
556     else :
557         if pid != 0 :
558             try :
559                 raise Exception(u'Erreur R')
560             except :
561                 BugReport(parent)
562             return False
563         else :
564             return True
565
566 def print_liste(filename,liste):
567     with open(filename,'w') as f :
568         for graph in liste :
569             f.write(';'.join(graph)+'\n')
570
571 def read_list_file(filename, encoding = sys.getdefaultencoding()):
572     with codecs.open(filename,'rU', encoding) as f :
573         content=f.readlines()
574         ncontent=[line.replace('\n','').split(';') for line in content if line.strip() != '']
575     return ncontent
576         
577 class MessageImage(wx.Frame):
578     def __init__(self, parent,title, size):
579         wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = title, pos = wx.DefaultPosition, size = size, style = wx.DEFAULT_FRAME_STYLE )
580         self.SetSizeHintsSz( wx.DefaultSize, wx.DefaultSize )
581         self.imageFile = False
582         self.imagename = u"chi_classe.png"
583         self.HtmlPage = wx.html.HtmlWindow(self, -1)
584         self.HtmlPage.SetMinSize(size)
585         if "gtk2" in wx.PlatformInfo:
586             self.HtmlPage.SetStandardFonts()
587         self.HtmlPage.SetFonts('Courier', 'Courier')
588         
589         self.button_1 = wx.Button(self, wx.ID_CANCEL)
590         self.button_2 = wx.Button(self, wx.ID_SAVE)
591         self.Bind(wx.EVT_BUTTON, self.OnCloseMe, self.button_1)
592         self.Bind(wx.EVT_BUTTON, self.OnSaveImage, self.button_2)
593         self.do_layout()
594
595     def do_layout(self):
596         self.sizer_1 = wx.BoxSizer(wx.VERTICAL)
597         self.sizer_2 = wx.BoxSizer(wx.HORIZONTAL)
598         self.sizer_1.Add(self.HtmlPage, 2, wx.EXPAND, 0)
599
600         self.m_sdbSizer1 = wx.StdDialogButtonSizer()
601         self.m_sdbSizer1.AddButton(  self.button_2 )
602         self.m_sdbSizer1.AddButton(  self.button_1 )
603         self.m_sdbSizer1.Realize()
604         self.sizer_1.Add(self.m_sdbSizer1, 0, wx.EXPAND, 5)
605         self.SetSizer(self.sizer_1)
606         self.Layout()
607         self.sizer_1.Fit( self )
608
609     def addsaveimage(self, imageFile) :
610         self.imageFile = imageFile
611         
612     def OnCloseMe(self, event):
613         self.Destroy()
614
615     def OnSaveImage(self, event) :
616         dlg = wx.FileDialog(
617             self, message="Enregistrer sous...", defaultDir=os.getcwd(),
618             defaultFile= self.imagename, wildcard="png|*.png", style=wx.SAVE | wx.OVERWRITE_PROMPT
619             )
620         dlg.SetFilterIndex(2)
621         dlg.CenterOnParent()
622         if dlg.ShowModal() == wx.ID_OK:
623             path = dlg.GetPath()
624             copyfile(self.imageFile, path)
625             
626
627 def progressbar(self, maxi) :
628     if 'parent' in dir(self) :
629         parent = self.parent
630     else :
631         parent = self
632     return wx.ProgressDialog("Traitements",
633                              "Veuillez patienter...",
634                              maximum=maxi,
635                              parent=parent,
636                              style=wx.PD_APP_MODAL | wx.PD_AUTO_HIDE | wx.PD_ELAPSED_TIME | wx.PD_CAN_ABORT
637                              )
638
639
640 def treat_var_mod(variables) :
641     var_mod = {}
642     for variable in variables :
643         if u'_' in variable :
644             forme = variable.split(u'_')
645             var = forme[0]
646             mod = forme[1]
647             if not var in var_mod :
648                 var_mod[var] = [variable]
649             else :
650                 if not mod in var_mod[var] :
651                     var_mod[var].append(variable)
652     return var_mod