Merge branch 'master' of http://www.iramuteq.org/git/iramuteq
[iramuteq] / tabchi2.py
1 #!/bin/env python
2 # -*- coding: utf-8 -*-
3 #Author: Pierre Ratinaud
4 #Copyright (c) 2010 Pierre Ratinaud
5 #License: GNU/GPL
6
7 import HTML
8 import os
9 import string
10 import wx
11 import os
12 import sys
13 import tempfile
14 from chemins import ffr,FFF
15 import wx.lib.sized_controls as sc
16 from time import sleep
17 from functions import exec_rcode, check_Rresult
18 from dialog import ChiDialog, PrefChi
19 from analysematrix import AnalyseMatrix
20                     
21 def make_res(line) :
22     if float(line[5]) <= 0.05 and line[6] != 'warning':
23         line.append('green')
24     elif float(line[5]) <= 0.05 and line[6] == 'warning':
25         line.append('blue')
26     else :
27         line.append('red')
28     return line
29
30 def clean_line(result) :
31     return [[val for val in line if val != '**'] for line in result]
32
33 def make_table(tabs, tab_title, res) :
34     return ['<br>'.join(['<font color=%s>%s</font>' % (res[i][-1], tab_title), HTML.table(tab)]) for i,tab in enumerate(tabs)]
35
36 def make_restab(res) :
37     return ['<br>'.join(['<font color=%s>%s</font>'% (line[-1], u'Résultats'),HTML.table([['chi', line[3]],['p', line[5]]])]) for i,line in enumerate(res)]
38
39 def make_htmlgraphs(graphs) :
40     return ['<img src=%s>' % os.path.basename(val) for val in graphs]
41
42 def make_link_list(res, text) :
43     return ['<a name=back_%i></a><a href=#%i><font color=%s>%s</font></a>' % (i, i, chi[-1], text[i]) for i, chi in enumerate(res)]
44
45 def make_title(res, text) :
46     return ['<a name=%i></a><br><font color=%s>%s</font><br><a href=#back_%i>retour</a><br>' % (i, val[-1], text[i], i) for i, val in enumerate(res)] 
47
48
49 chioption = { 'valobs' : True,
50               'valtheo' : True,
51               'resi' : False,
52               'contrib' : True,
53               'pourcent' : False,
54               'pourcentl' : True,
55               'pourcentc' : True,
56               'graph' : True,
57               'bw' : False,
58               }
59
60 class ChiSquare(AnalyseMatrix):
61     def doparametres(self, dlg = None):
62         if dlg is None :
63             return
64         dial = ChiDialog(self.parent, -1, u"Chi2", chioption, self.tableau, size=(400, 350),
65                      style = wx.DEFAULT_DIALOG_STYLE
66                      )
67         dial.CenterOnParent()
68         val = dial.ShowModal()
69         if val==wx.ID_OK :     
70             self.colsel1 = dial.list_box_1.GetSelections()
71             self.colsel2 = dial.list_box_2.GetSelections()
72             if dial.chiopt :
73                 chioption['valobs'] = dial.dial.check1.GetValue()
74                 chioption['valtheo'] = dial.dial.check2.GetValue()
75                 chioption['resi'] = dial.dial.check3.GetValue()
76                 chioption['contrib'] = dial.dial.check4.GetValue()
77                 chioption['pourcent'] = dial.dial.check5.GetValue()
78                 chioption['pourcentl'] = dial.dial.check6.GetValue()
79                 chioption['pourcentc'] = dial.dial.check7.GetValue()
80                 chioption['graph'] = dial.dial.check8.GetValue()
81                 chioption['bw'] = dial.dial.checkbw.GetValue()
82                 dial.dial.Destroy()
83             dial.Destroy()
84             self.parametres.update(chioption)
85             self.chioption = chioption
86         else :
87             if dial.chiopt :
88                 dial.dial.Destroy()
89             dial.Destroy()
90             self.parametres = None
91             
92     def doanalyse(self):
93
94
95             #self.dlg=wx.ProgressDialog("Traitements",
96             #           "Veuillez patienter...",
97             #           maximum = 4,
98             #           parent=parent,
99             #           style = wx.PD_APP_MODAL|wx.PD_AUTO_HIDE|wx.PD_ELAPSED_TIME
100             #            )
101
102
103             
104         self.count += 1
105         keepGoing = self.dlg.Update(self.count,u"Analyse dans R...")
106         #analyse=MakeChi2(self.parent, self.colsel1, self.colsel2, self.chioption, self.tableau)
107         #self.tableau = tableau
108         self.OutFrame=tempfile.mktemp(dir=self.parent.TEMPDIR)
109         print self.OutFrame
110         #self.parent=parent
111         self.encode=self.parent.encode
112         self.TEMPDIR=self.parent.TEMPDIR
113         self.RPath=self.parent.PathPath.get('PATHS','rpath')
114         self.TextCroise=[]
115         for i in self.colsel1 :
116             for j in self.colsel2 :
117                 self.TextCroise.append(self.tableau.colnames[i] + ' / ' + self.tableau.colnames[j])
118         rchioption = {}
119         for val in self.chioption :
120             if self.chioption[val]:
121                 rchioption[val] = 'TRUE'
122             else :
123                 rchioption[val] = 'FALSE'
124         txt="""
125         source("%s")
126         """%ffr(self.parent.RscriptsPath['Rfunct'])
127 #        if parent.tableau.: rownames=1
128 #        else : rownames='NULL'
129 #        if parent.g_header : header = 'TRUE'
130 #        else : header = 'FALSE'
131         txt += """
132         source("%s")
133         """ % ffr(self.parent.RscriptsPath['Rgraph'])
134         txt += """
135         doobs <- %s
136         doexp <- %s
137         docontrib <- %s
138         doresi <- %s
139         dopr <- %s
140         doprl <- %s
141         doprc <- %s
142         dograph <- %s
143         bw <- %s
144         """ % (rchioption['valobs'], rchioption['valtheo'], rchioption['contrib'], rchioption['resi'], rchioption['pourcent'], rchioption['pourcentl'], rchioption['pourcentc'], rchioption['graph'], rchioption['bw'])
145         txt+="""
146         datadm <- read.csv2("%s", encoding="%s", header = TRUE, row.names = 1, sep='\\t', quote = '"', na.string = '')
147         listres<-list()
148         listcol<-list()
149         cont<-1
150         """%(ffr(self.tableau.parametres['csvfile']), self.tableau.parametres['syscoding'])
151         if len(self.colsel1)==1:
152             strsel1=str(self.colsel1).replace(',','')
153         else:
154             strsel1=str(self.colsel1)
155         if len(self.colsel2)==1:
156             strsel2=str(self.colsel2).replace(',','')
157         else:
158             strsel2=str(self.colsel2)
159         txt+="""
160         for (i in c%s) {""" % strsel1
161         txt+="""
162             for (j in c%s) {""" % strsel2
163         txt+="""
164                 tab<-table(datadm[,i+1],datadm[,j+1])
165                 if (min(dim(tab)) != 1) {
166                     chi<-chisq.test(tab)
167                     CS<-colSums(tab)
168                     RS<-rowSums(tab)
169                     GT<-sum(tab)
170                     chi$contrib<-(tab-chi$expected)/sqrt(chi$expected * ((1 - RS/GT) %%*%% t(1 - CS/GT)))
171                     listres[[cont]]<-chi
172                     listcol[[cont]]<-ncol(tab)
173                     cont<-cont+1
174                 } else {
175                     chi <- list(observed = tab, residuals = tab, contrib = tab, statistic = 0, p.value = 1, expected = tab, message = 'pas de calcul')
176                     listres[[cont]] <- chi
177                     listcol[[cont]]<-ncol(tab)
178                     cont <- cont + 1
179                 }
180             }
181         }
182         maxcol<-max(unlist(listcol))+1
183         if (maxcol<7) {maxcol<-7}
184         frameout<-matrix('*',1,maxcol)
185         count<-0
186         for (chi in listres) {
187             if (min(chi$expected)<5) {
188                 att<-"warning"
189             } else {
190                 att<-""
191             }
192             if ('message' %%in%% attributes(chi)$names) {
193                 att <- "Ce chi2 n\'a pas été calculé"
194                 nom_colresi<-colnames(chi$observed)
195                 chi$prl <- chi$expected
196                 chi$prc <- chi$expected
197                 st <- sum(chi$observed)
198             } else {
199                 nom_colresi<-colnames(chi$observed)
200                 st <- sum(chi$observed)
201                 sc <- colSums(chi$observed)
202                 sr <- rowSums(chi$observed)
203                 chi$prl <- round((chi$observed/sr)*100,2)
204                 chi$prc <- t(round((t(chi$observed)/sc)*100,2))
205             }
206             fileout<-paste('histo_',count,sep='')
207             fileout<-paste(fileout,'.png',sep='')
208             count<-count+1
209             fileout<-file.path("%s",fileout)
210             if (max(nchar(colnames(chi$observed)))>15) {
211                 leg <- 1:length(colnames(chi$observed))
212             } else {
213                 leg <- colnames(chi$observed)
214             }
215             if (dograph) {
216                 width<-ncol(chi$observed)*100
217                 if (width < 350) {width <- 350}
218                 open_file_graph(fileout,width = width, height = 300)
219                 par(mar=c(0,0,0,0))
220                 layout(matrix(c(1,2),1,2, byrow=TRUE),widths=c(3,1))
221                 par(mar=c(2,2,1,0))
222                 par(cex=0.8)
223                 if (!bw) colors <- rainbow(length(rownames(chi$observed)))
224                 else colors <- gray.colors(length(rownames(chi$observed)))
225                 barplot(chi$prl,names.arg = leg, beside=TRUE,border=NA, col=colors)
226                 par(mar=c(0,0,0,0))
227                 par(cex=0.8)
228                 plot(0, axes = FALSE, pch = '')
229                 legend(x = 'center' , rownames(chi$observed), fill = colors)
230                 dev.off()
231             }
232             chi$prl <- cbind(chi$prl, total = rowSums(chi$prl))
233             chi$prc <- rbind(chi$prc, total = colSums(chi$prc))
234             chi$observed<-rbind(chi$observed,total=colSums(chi$observed))
235             chi$observed<-cbind(chi$observed,total=rowSums(chi$observed))
236             chi$pr <- round((chi$observed/st)*100,2)
237             chi$expected<-rbind(chi$expected,total=colSums(chi$expected))
238             chi$expected<-cbind(chi$expected,total=rowSums(chi$expected))
239             chi$expected<-round(chi$expected,digits=2)
240             chi$residuals<-round(chi$residuals,digits=2)
241             chi$contrib<-round(chi$contrib, digits=2)
242             nom_col<-colnames(chi$observed)
243            
244             if (ncol(chi$observed)<maxcol) {
245                 for (i in 1:(maxcol-ncol(chi$observed))) {
246                     chi$observed<-cbind(chi$observed,'**')
247                     chi$pr<-cbind(chi$pr,'**')
248                     chi$prl<-cbind(chi$prl,'**')
249                     chi$prc<-cbind(chi$prc,'**')
250                     chi$expected<-cbind(chi$expected,'**')
251                     chi$residuals<-cbind(chi$residuals,'**')
252                     chi$contrib<-cbind(chi$contrib,'**')
253                     nom_col<-append(nom_col,'**')
254                     nom_colresi<-append(nom_colresi,'**')
255                 }
256                 chi$residuals<-cbind(chi$residuals,'**')
257                 chi$contrib<-cbind(chi$contrib,'**')
258                 nom_colresi<-append(nom_colresi,'**')
259                 chi$prc<-cbind(chi$prc,'**')
260             } else if (ncol(chi$observed)==maxcol) {
261                 chi$residuals<-cbind(chi$residuals,'**')
262                 chi$contrib<-cbind(chi$contrib,'**')
263                 nom_colresi<-append(nom_colresi,'**')
264                 chi$prc<-cbind(chi$prc,'**')
265             }
266             if (doobs) {
267                 li<-matrix('*obs*',1,maxcol)
268                 frameout<-rbind(frameout,li)
269                 frameout<-rbind(frameout,nom_col)
270                 frameout<-rbind(frameout,chi$observed)
271             }
272             if (doexp) {
273                 li<-matrix('*exp*',1,maxcol)
274                 frameout<-rbind(frameout,li)
275                 frameout<-rbind(frameout,nom_col)
276                 frameout<-rbind(frameout,chi$expected)
277             }
278             if (doresi) {
279                 li<-matrix('*resi*',1,maxcol)
280                 frameout<-rbind(frameout,li)
281                 frameout<-rbind(frameout,nom_colresi)
282                 frameout<-rbind(frameout,chi$residuals)
283             }
284             if (docontrib) {
285                 li<-matrix('*contrib*',1,maxcol)
286                 frameout<-rbind(frameout,li)
287                 frameout<-rbind(frameout,nom_colresi)
288                 frameout<-rbind(frameout,chi$contrib)
289             }
290             if (dopr) {
291                 li<-matrix('*pr*', 1, maxcol)
292                 frameout<-rbind(frameout,li)
293                 frameout<-rbind(frameout,nom_col)
294                 frameout<-rbind(frameout,chi$pr)
295             }
296             if (doprl) {
297                 li<-matrix('*prl*', 1, maxcol)
298                 frameout<-rbind(frameout,li)
299                 frameout<-rbind(frameout,nom_col)
300                 frameout<-rbind(frameout,chi$prl)
301             }
302             if (doprc) {
303                 li<-matrix('*prc*', 1, maxcol)
304                 frameout<-rbind(frameout,li)
305                 frameout<-rbind(frameout,nom_colresi)
306                 frameout<-rbind(frameout,chi$prc)
307             }
308             res<-c('****','chi',chi$statistic,'p',chi$p.value,att,fileout)
309             frameout<-rbind(frameout,res)
310         }
311         li<-matrix('fin_analyse',1,maxcol)
312         frameout<-rbind(frameout,li)
313         write.csv2(frameout,file="%s")
314         """ % (ffr(self.parametres['pathout']),ffr(self.OutFrame))
315         tmpfile=tempfile.mktemp(dir=self.TEMPDIR)
316         print tmpfile
317         tmpscript=open(tmpfile,'w')
318         tmpscript.write(txt)
319         tmpscript.close()
320         pid = exec_rcode(self.RPath, tmpfile, wait = False)
321         while pid.poll() == None :
322             sleep(0.2)
323         check_Rresult(self.parent, pid)            
324         self.count += 1
325         keepGoing = self.dlg.Update(self.count,u"Ecriture des résultats")
326          
327         listfileout = self.dolayout(self.chioption)
328             #listfileout=dlg.ShowChi2(ColSel1,ColSel2)
329             #parent.FreqNum += 1
330             #parent.DictTab[u"Chi2_%s*"%parent.FreqNum]=listfileout
331 #             parent.newtab = wx.html.HtmlWindow(parent.nb, -1)
332 #             if "gtk2" in wx.PlatformInfo:
333 #                 parent.newtab.SetStandardFonts()
334 #             parent.newtab.LoadPage(listfileout[len(listfileout)-1])
335 #             parent.nb.AddPage(parent.newtab,u"Chi2_%s*"%parent.FreqNum)
336 #             parent.nb.SetSelection(parent.nb.GetPageCount()-1)
337 #             parent.ShowTab(wx.EVT_BUTTON)
338 #             parent.DisEnSaveTabAs(True)
339 #        self.count += 1
340 #        keepGoing = self.dlg.Update(self.count,u"Fini")
341
342     def dolayout(self, option):
343         ListFile=[False]
344         file=open(self.OutFrame,'rU')
345         content=file.readlines()
346         file.close()
347         lcont = [line.replace('"','').replace('\n','').split(';') for line in content]
348     
349         lcont.pop(0)
350         lcont.pop(0)
351         
352         allcoord = []
353         names = []
354
355         res = [chi for chi in lcont if chi[0]=='res']
356         res = [make_res(line) for line in res]
357         coord_res = [i for i,chi in enumerate(lcont) if chi[0]=='res']
358         if option['valobs']:
359             allcoord.append([i for i,chi in enumerate(lcont) if chi[1]=='*obs*'])
360             names.append(u'Valeurs observées')
361         if option['valtheo'] :
362             allcoord.append([i for i,chi in enumerate(lcont) if chi[1]=='*exp*'])
363             names.append(u'Valeurs théoriques')
364         if option['resi'] :
365             allcoord.append([i for i,chi in enumerate(lcont) if chi[1]=='*resi*'])
366             names.append(u'Residuals')
367         if option['contrib'] :
368             allcoord.append([i for i,chi in enumerate(lcont) if chi[1]=='*contrib*'])
369             names.append(u'Contributions a posteriori')
370         if option['pourcent'] : 
371             allcoord.append([i for i,chi in enumerate(lcont) if chi[1]=='*pr*'])
372             names.append(u'Pourcentages')
373         if option['pourcentl'] :
374             allcoord.append([i for i,chi in enumerate(lcont) if chi[1]=='*prl*'])
375             names.append(u'Pourcentages en ligne')
376         if option['pourcentc'] :
377             allcoord.append([i for i,chi in enumerate(lcont) if chi[1]=='*prc*'])
378             names.append(u'Pourcentages en colonne')
379     
380         allcoord.append(coord_res)
381         allhtml = [[clean_line(lcont[allcoord[i][j]+1:allcoord[i+1][j]]) for j, line in enumerate(allcoord[i])] for i, tab in enumerate(allcoord) if i!=len(allcoord)-1]
382         allhtml = [make_table(val,names[i],res) for i,val in enumerate(allhtml)]
383         links = make_link_list(res, self.TextCroise)
384         html_res = make_restab(res)
385         allhtml.insert(0,html_res)
386         titles = make_title(res, self.TextCroise)
387         allhtml.insert(0,titles)
388         
389         if option['graph'] :
390             graphs = [line[7] for line in res]
391             ListFile += graphs
392             html_graphs = make_htmlgraphs(graphs)
393             allhtml.append(html_graphs)
394
395         header=u"""
396         <html>\n
397         <meta http-equiv="content-Type" content="text/html; charset=%s" />\n
398         <body>\n
399         <h1>Test du Chi2</h1>\n
400         <br>
401         <table border=1><tr><td>
402         Légende : <br>
403         <font color=green>p &lt;= 0.05</font><br>
404         <font color=blue>p &lt;= 0.05 mais il y a des valeurs théoriques &lt; 5</font><br>
405         <font color=red>p &gt; 0.05</font>
406         </td></tr></table><br><br>
407         """%self.parent.SysEncoding
408
409         pretxt = '<br>\n'.join(links)+'<br><hr><br>\n'
410         txt = '<br><hr><br>\n'.join(['<br><br>'.join([tab[i] for tab in allhtml]) for i,val in enumerate(res)])
411         txt = header + pretxt + txt + '\n</body></html>'
412
413         fileout=os.path.join(self.parametres['pathout'],'resultats-chi2.html')
414         with open(fileout, 'w') as f :
415             f.write(txt)
416         ListFile.append(fileout)         
417         return ListFile