Merge branch 'master' of http://www.netdig.org/git/iramuteq
[iramuteq] / analysetxt.py
1 # -*- coding: utf-8 -*-
2 #Author: Pierre Ratinaud
3 #lisence : GNU GPL
4 #copyright : 2012-2013 (c) Pierre Ratinaud
5
6 import logging
7 from chemins import PathOut, ChdTxtPathOut
8 from functions import exec_rcode, check_Rresult, DoConf, print_liste
9 from time import time, sleep
10 from uuid import uuid4
11 import os
12 from PrintRScript import RchdTxt, AlcesteTxtProf
13 from OptionAlceste import OptionAlc 
14 from layout import PrintRapport
15 from openanalyse import OpenAnalyse
16 from dialog import StatDialog
17 from time import time
18
19 log = logging.getLogger('iramuteq.analyse')
20
21 class AnalyseText :
22     def __init__(self, ira, corpus, parametres = None, dlg = False, lemdial = True) :
23         self.corpus = corpus
24         self.ira = ira
25         self.parent = ira
26         self.dlg = dlg
27         self.dialok = True
28         self.parametres = parametres
29         self.lemdial = lemdial
30         self.val = False
31         if not 'pathout' in self.parametres :
32             self.pathout = PathOut(corpus.parametres['originalpath'], analyse_type = parametres['type'], dirout = corpus.parametres['pathout'])
33         else :
34             self.pathout = PathOut(filename = corpus.parametres['originalpath'], dirout = self.parametres['pathout'], analyse_type = self.parametres['type'])
35         self.parametres = self.lemparam()
36         if self.parametres is not None :
37             self.parametres = self.make_config(parametres)
38         log.info(self.pathout.dirout)
39         if self.parametres is not None :
40             self.keys = DoConf(self.ira.ConfigPath['key']).getoptions()
41             gramact = [k for k in keys if keys[k] == 1]
42             gramsup = [k for k in keys if keys[k] == 2]
43             self.parametres['pathout'] = self.pathout.mkdirout()
44             self.pathout = PathOut(dirout = self.parametres['pathout'])
45             self.pathout.createdir(self.parametres['pathout'])
46             self.parametres['corpus'] = self.corpus.parametres['uuid']
47             self.parametres['uuid'] = str(uuid4())
48             self.parametres['name'] = os.path.split(self.parametres['pathout'])[1]
49             self.parametres['type'] = parametres['type']
50             self.parametres['encoding'] = self.ira.syscoding
51             self.t1 = time()
52             self.corpus.make_lems(lem = self.parametres['lem'])
53             corpus.parse_active(gramact, gramsup)
54             result_analyse = self.doanalyse()
55             if result_analyse is None :
56                  self.time = time() - self.t1
57                  minutes, seconds = divmod(self.time, 60)
58                  hours, minutes = divmod(minutes, 60)            
59                  self.parametres['time'] = '%.0fh %.0fm %.0fs' % (hours, minutes, seconds)
60                  self.parametres['ira'] = self.pathout['Analyse.ira']
61                  DoConf().makeoptions([self.parametres['type']], [self.parametres], self.pathout['Analyse.ira'])
62                  self.ira.history.add(self.parametres)
63                  if dlg :
64                      dlg.Destroy()
65                      OpenAnalyse(self.parent, self.parametres['ira'])
66                      self.ira.tree.AddAnalyse(self.parametres)
67                      self.val = 5100
68             else :
69                  self.val = False
70                  if dlg :
71                      dlg.Destroy()
72         else :
73             if dlg :
74                 dlg.Destroy()
75             self.val = False
76
77     def doanalyse(self) :
78         pass
79
80     def lemparam(self) :
81         if self.dlg and self.lemdial:
82             dial = StatDialog(self, self.parent)
83             dial.CenterOnParent()
84             val = dial.ShowModal()
85             if val == 5100 :
86                 if dial.radio_lem.GetSelection() == 0 :
87                     lem = 1
88                 else :
89                     lem = 0            
90                 self.parametres['lem'] = lem
91                 dial.Destroy()
92                 return self.parametres
93             else :
94                 dial.Destroy()
95                 return None        
96         else :
97             return self.parametres
98
99     def make_config(self, config) :
100         if config is not None :
101             if not self.dlg : 
102                 return config
103             else :
104                 return self.preferences()
105         else :
106             return None
107
108     def readconfig(self, config) :
109         return config
110
111     def preferences(self) :
112         return self.parametres
113
114     def printRscript(self) :
115         pass
116
117     def doR(self, Rscript, wait = False, dlg = None, message = '') :
118         log.info('R code...')
119         pid = exec_rcode(self.ira.RPath, Rscript, wait = wait)
120         while pid.poll() is None :
121             if dlg :
122                 self.dlg.Pulse(message)
123                 sleep(0.2)
124             else :
125                 sleep(0.2)
126         return check_Rresult(self.ira, pid)
127
128
129
130 class Alceste(AnalyseText) :
131     def doanalyse(self) :
132         self.parametres['type'] = 'alceste'
133         self.pathout.basefiles(ChdTxtPathOut)
134         self.actives, lim = self.corpus.make_actives_nb(self.parametres['max_actives'], 1)
135         self.parametres['eff_min_forme'] = lim
136         self.parametres['nbactives'] = len(self.actives)
137         if self.parametres['classif_mode'] == 0 :
138             lenuc1, lenuc2 = self.corpus.make_and_write_sparse_matrix_from_uc(self.actives, self.parametres['tailleuc1'], self.parametres['tailleuc2'], self.pathout['TableUc1'], self.pathout['TableUc2'], self.pathout['listeuce1'], self.pathout['listeuce2'])
139             self.parametres['lenuc1'] = lenuc1
140             self.parametres['lenuc2'] = lenuc2
141         elif self.parametres['classif_mode'] == 1 :
142             self.corpus.make_and_write_sparse_matrix_from_uces(self.actives, self.pathout['TableUc1'], self.pathout['listeuce1'])
143         elif self.parametres['classif_mode'] == 2 :
144             self.corpus.make_and_write_sparse_matrix_from_uci(self.actives, self.pathout['TableUc1'], self.pathout['listeuce1'])
145         Rscript = self.printRscript()
146         self.doR(Rscript, dlg = self.dlg, message = 'CHD...')
147
148         self.corpus.make_ucecl_from_R(self.pathout['uce'])
149         self.corpus.make_and_write_profile(self.actives, self.corpus.lc, self.pathout['Contout'])
150         self.sup, lim = self.corpus.make_actives_nb(self.parametres['max_actives'], 2)
151         self.corpus.make_and_write_profile(self.sup, self.corpus.lc, self.pathout['ContSupOut'])
152         self.corpus.make_and_write_profile_et(self.corpus.lc, self.pathout['ContEtOut'])
153         self.clnb = len(self.corpus.lc)
154         self.parametres['clnb'] = self.clnb
155         Rscript = self.printRscript2()
156         self.doR(Rscript, dlg = self.dlg, message = 'profils et A.F.C. ...')
157         self.time = time() - self.t1
158         minutes, seconds = divmod(self.time, 60)
159         hours, minutes = divmod(minutes, 60)            
160         self.parametres['time'] = '%.0fh %.0fm %.0fs' % (hours, minutes, seconds)
161         self.print_graph_files()
162
163     def preferences(self) :
164         parametres = DoConf(self.parent.ConfigPath['alceste']).getoptions('ALCESTE')
165         parametres['corpus'] = self.corpus
166         parametres['pathout'] = self.pathout
167         self.dial = OptionAlc(self.parent, parametres)
168         self.dial.CenterOnParent()
169         self.dialok = self.dial.ShowModal()
170         if self.dialok == 5100 :
171             parametres['classif_mode'] = self.dial.radio_box_2.GetSelection()
172             parametres['tailleuc1'] = self.dial.spin_ctrl_1.GetValue()
173             parametres['tailleuc2'] = self.dial.spin_ctrl_2.GetValue()
174             parametres['mincl'] = self.dial.spin_ctrl_4.GetValue()
175             parametres['minforme'] = self.dial.spin_ctrl_5.GetValue()
176             parametres['nbcl_p1'] = self.dial.spin_nbcl.GetValue()
177             parametres['max_actives'] = self.dial.spin_max_actives.GetValue()
178             parametres['corpus'] = ''
179             parametres['svdmethod'] = self.dial.svdmethod[self.dial.choicesvd.GetSelection()]
180             parametres['pathout'] = self.pathout.dirout
181             parametres['mode.patate'] = self.dial.check_patate.GetValue()
182             DoConf(self.parent.ConfigPath['alceste']).makeoptions(['ALCESTE'], [parametres])
183             self.dial.Destroy()
184             print parametres
185             return parametres
186         else :
187             self.dial.Destroy()
188             return None
189
190     def printRscript(self) :
191         RchdTxt(self.pathout, self.parent.RscriptsPath, self.parametres['mincl'], self.parametres['classif_mode'], nbt = self.parametres['nbcl_p1'] - 1, svdmethod = self.parametres['svdmethod'], libsvdc = self.parent.pref.getboolean('iramuteq','libsvdc'), libsvdc_path = self.parent.pref.get('iramuteq','libsvdc_path'), R_max_mem = False, mode_patate = self.parametres['mode.patate'])
192         return self.pathout['Rchdtxt']
193
194     def printRscript2(self) :
195         AlcesteTxtProf(self.pathout, self.parent.RscriptsPath, self.clnb, 0.9)
196         return self.pathout['RTxtProfGraph']
197
198     def print_graph_files(self) :
199         mess_afc = u"La position des points n'est peut être pas exacte"
200         afc_graph_list = [[os.path.basename(self.pathout['AFC2DL_OUT']), u'Variables actives - coordonnées - 30 points par classes - facteurs 1 / 2 - %s' % mess_afc],
201                       [os.path.basename(self.pathout['AFC2DSL_OUT']), u'variables supplémentaires - coordonnées - 30 points par classes - facteurs 1 / 2 - %s' % mess_afc],
202                       [os.path.basename(self.pathout['AFC2DEL_OUT']), u'Variables illustratives - Coordonnées - 30 points par classes - facteur 1 / 2 - %s' % mess_afc],
203                       [os.path.basename(self.pathout['AFC2DCL_OUT']), u'Classes - Coordonnées - facteur 1 / 2']]
204         chd_graph_list = [[os.path.basename(self.pathout['dendro1']), u'dendrogramme à partir de chd1']]
205         if self.parametres['classif_mode'] == 0 :
206             chd_graph_list.append([os.path.basename(self.pathout['dendro2']), u'dendrogramme à partir de chd2'])
207         chd_graph_list.append([os.path.basename(self.pathout['arbre1']), u'chd1'])
208         if self.parametres['classif_mode'] == 0 :
209             chd_graph_list.append([os.path.basename(self.pathout['arbre2']), u'chd2'])       
210         print_liste(self.pathout['liste_graph_afc'],afc_graph_list)
211         print_liste(self.pathout['liste_graph_chd'],chd_graph_list)
212         PrintRapport(self, self.corpus, self.parametres)
213
214
215 keys = {'art_def' : 2,
216         'pre' : 2,
217         'adj_dem' : 2,
218         'ono' : 2,
219         'pro_per' : 2,
220         'ver_sup' : 2,
221         'adv' : 1,
222         'ver' : 1,
223         'adj_ind' : 2,
224         'adj_pos' : 2,
225         'aux' : 2,
226         'adj_int' : 2,
227         'pro_ind' : 2,
228         'adj' : 1,
229         'pro_dem' : 2,
230         'nom' : 1,
231         'art_ind' : 2,
232         'pro_pos' : 2,
233         'nom_sup' : 2,
234         'adv_sup' : 2,
235         'adj_sup' : 2,
236         'adj_num' : 2,
237         'pro_rel' : 2,
238         'con' : 2,
239         'num' : 2,
240         'nr' : 1,
241         'sw' : 2,
242 }
243
244 gramact = [k for k in keys if keys[k] == 1]
245 gramsup = [k for k in keys if keys[k] == 2]