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