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