...
[iramuteq] / ProfList.py
1 # -*- coding: utf-8 -*-
2
3 #----------------------------------------------------------------------------
4 # Name:         ListCtrl.py
5 # Author:       Pierre Ratinaud
6
7
8 #comes from ListCtrl.py from the demo tool of wxPython:
9 # Author:       Robin Dunn & Gary Dumer
10 #
11 # Created:
12 # Copyright:    (c) 1998 by Total Control Software
13 # Licence:      wxWindows license
14 #----------------------------------------------------------------------------
15
16 import os
17 import sys
18 import  wx
19 import  wx.lib.mixins.listctrl  as  listmix
20 #from tabsimi import DoSimi
21 from listlex import ListForSpec
22 from chemins import ConstructPathOut, ffr
23 from dialog import PrefUCECarac, SearchDial, message, BarFrame
24 from tableau import copymatrix
25 from search_tools import SearchFrame
26 import webbrowser
27 #import cStringIO
28 import tempfile
29 import codecs
30 from functions import progressbar, treat_var_mod, doconcorde
31 from PrintRScript import barplot
32 from textclassechd import ClasseCHD
33 from shutil import copyfile
34 from operator import itemgetter
35 from copy import copy
36
37 #---------------------------------------------------------------------------
38 class ProfListctrlPanel(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin, listmix.ColumnSorterMixin):
39     def __init__(self, parent, gparent, profclasse, Alceste=False, cl=0):
40         wx.ListCtrl.__init__( self, parent, -1, style=wx.LC_REPORT|wx.LC_VIRTUAL|wx.LC_HRULES|wx.LC_VRULES)
41
42         self.parent = parent
43         self.Alceste = Alceste
44         self.Source = gparent
45         self.cl = cl
46         self.var_mod = {}
47         self.them_mod = {}
48         self.ira = wx.GetApp().GetTopWindow()
49
50         line1 = profclasse.pop(0)
51         classen = [line for line in profclasse if line[0] != '*' and line[0] != '*****']
52         try :
53             self.lenact = profclasse.index([u'*****', u'*', u'*', u'*', u'*', u'*', '', ''])
54             profclasse.pop(self.lenact)
55         except ValueError:
56             try :
57                 self.lenact = profclasse.index([u'*', u'*', u'*', u'*', u'*', u'*', '', ''])
58                 profclasse.pop(self.lenact)
59             except ValueError:
60                 self.lenact = len(profclasse)
61         try :
62             self.lensup = profclasse.index([u'*', u'*', u'*', u'*', u'*', u'*', '', ''])
63             self.lensup = self.lensup - self.lenact
64             profclasse.pop(self.lensup)
65         except ValueError: 
66             self.lensup = len(profclasse) - self.lenact
67         self.lenet = len(profclasse) - (self.lenact + self.lensup)
68 #        print self.lenact, self.lensup, self.lenet
69         for i,  line in enumerate(classen) :
70             line[0] = i
71         dictdata = dict(zip([i for i in range(0,len(classen))], classen))
72
73         if self.lenact != 0 :
74             self.la = [dictdata[i][6] for i in range(0, self.lenact)]
75             self.lchi = [dictdata[i][4] for i in range(0, self.lenact)]
76             self.lfreq = [dictdata[i][1] for i in range(0, self.lenact)]
77         else :
78             self.la = []
79             self.lchi = []
80             self.lfreq = []
81         self.tmpchi = None
82             
83         #adding some art
84         self.il = wx.ImageList(16, 16)
85         a={"sm_up":"GO_UP","sm_dn":"GO_DOWN","w_idx":"WARNING","e_idx":"ERROR","i_idx":"QUESTION"}
86         for k,v in a.items():
87             s="self.%s= self.il.Add(wx.ArtProvider_GetBitmap(wx.ART_%s,wx.ART_TOOLBAR,(16,16)))" % (k,v)
88             exec(s)
89         self.SetImageList(self.il, wx.IMAGE_LIST_SMALL)
90
91         #adding some attributes (colourful background for each item rows)
92         self.attr1 = wx.ListItemAttr()
93         self.attr1.SetBackgroundColour((220, 220, 220))
94         self.attrsg = wx.ListItemAttr()
95         self.attrsg.SetBackgroundColour((230, 230, 230))
96         self.attr2 = wx.ListItemAttr()
97         self.attr2.SetBackgroundColour((190, 249, 236))
98         self.attr2s = wx.ListItemAttr()
99         self.attr2s.SetBackgroundColour((211, 252, 244))        
100         self.attr3 = wx.ListItemAttr()
101         self.attr3.SetBackgroundColour((245, 180, 180))
102         self.attr3s = wx.ListItemAttr()
103         self.attr3s.SetBackgroundColour((245, 190, 190))
104
105
106         self.InsertColumn(0, "num", wx.LIST_FORMAT_RIGHT)
107         self.InsertColumn(1, "eff. s.t.", wx.LIST_FORMAT_RIGHT)
108         self.InsertColumn(2, "eff. total", wx.LIST_FORMAT_RIGHT)
109         self.InsertColumn(3, "pourcentage", wx.LIST_FORMAT_RIGHT)
110         self.InsertColumn(4, "chi2", wx.LIST_FORMAT_RIGHT)
111         self.InsertColumn(5, "Type", wx.LIST_FORMAT_RIGHT)
112         self.InsertColumn(6, "forme", wx.LIST_FORMAT_RIGHT)
113         self.InsertColumn(7, "p", wx.LIST_FORMAT_RIGHT)
114         
115
116         self.SetColumnWidth(0, 60)
117         self.SetColumnWidth(1, 70)
118         self.SetColumnWidth(2, 80)
119         self.SetColumnWidth(3, 100)
120         self.SetColumnWidth(4, 70)
121         self.SetColumnWidth(5, 60)
122         self.SetColumnWidth(6, 140)
123         self.SetColumnWidth(7, wx.LIST_AUTOSIZE)
124
125         #These two should probably be passed to init more cleanly
126         #setting the numbers of items = number of elements in the dictionary
127         self.itemDataMap = dictdata
128         self.itemIndexMap = dictdata.keys()
129         self.SetItemCount(len(dictdata))
130         
131         #mixins
132         listmix.ListCtrlAutoWidthMixin.__init__(self)
133         listmix.ColumnSorterMixin.__init__(self, len(classen[0]))
134
135         #sort by genre (column 2), A->Z ascending order (1)
136         self.SortListItems(0, 1)
137
138         #events
139         #self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected)
140         self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnPopupTwo, self)
141         #self.Bind(wx.EVT_LIST_ITEM_DESELECTED, self.OnItemDeselected)
142         self.Bind(wx.EVT_LIST_COL_CLICK, self.OnColClick)
143
144         # for wxMSW
145         self.Bind(wx.EVT_COMMAND_RIGHT_CLICK, self.OnRightClick)
146
147         # for wxGTK
148         self.Bind(wx.EVT_RIGHT_UP, self.OnRightClick)
149
150         #for searching
151         search_id = wx.NewId()
152         searchall_id = wx.NewId()
153         concord_id = wx.NewId()
154         self.parent.Bind(wx.EVT_MENU, self.onsearch, id = search_id)
155         self.parent.Bind(wx.EVT_MENU, self.onsearchall, id = searchall_id)
156         self.accel_tbl = wx.AcceleratorTable([(wx.ACCEL_CTRL, ord('F'), search_id),
157                                               (wx.ACCEL_CTRL|wx.ACCEL_SHIFT, ord('F'), searchall_id)])
158         self.SetAcceleratorTable(self.accel_tbl)
159
160
161
162     def OnColClick(self,event):
163         event.Skip()
164
165     def OnItemSelected(self, event):
166         self.currentItem = event.m_itemIndex
167
168     def OnItemActivated(self, event):
169         self.currentItem = event.m_itemIndex
170
171     def getColumnText(self, index, col):
172         item = self.GetItem(index, col)
173         return item.GetText()
174
175     def OnItemDeselected(self, evt):
176         pass
177     #---------------------------------------------------
178     # These methods are callbacks for implementing the
179     # "virtualness" of the list...
180
181     def OnGetItemText(self, item, col):
182         index=self.itemIndexMap[item]
183         s = self.itemDataMap[index][col]
184         return s
185
186     def OnGetItemImage(self, item):
187         index=self.itemIndexMap[item]
188         genre=self.itemDataMap[index][2]
189
190         if genre=="Rock":
191             return self.w_idx
192         elif genre=="Jazz":
193             return self.e_idx
194         elif genre=="New Age":
195             return self.i_idx
196         else:
197             return -1
198
199     def OnGetItemAttr(self, item):
200         index=self.itemIndexMap[item]
201         if index < self.lenact :
202             if item % 2 :
203                 return self.attr1
204             else :
205                 return self.attrsg
206         elif index >= self.lenact and index < (self.lenact + self.lensup) :
207             if item % 2 :
208                 return self.attr2
209             else :
210                 return self.attr2s
211         elif index >= (self.lenact + self.lensup) :
212             if item % 2 :
213                 return self.attr3
214             else :
215                 return self.attr3s
216         else :
217             return None
218
219     #---------------------------------------------------
220     # Matt C, 2006/02/22
221     # Here's a better SortItems() method --
222     # the ColumnSorterMixin.__ColumnSorter() method already handles the ascending/descending,
223     # and it knows to sort on another column if the chosen columns have the same value.
224
225     def SortItems(self,sorter=cmp):
226         items = list(self.itemDataMap.keys())
227         items.sort(sorter)
228         self.itemIndexMap = items
229         
230         # redraw the list
231         self.Refresh()
232
233     # Used by the ColumnSorterMixin, see wx/lib/mixins/listctrl.py
234     def GetListCtrl(self):
235         return self
236
237     # Used by the ColumnSorterMixin, see wx/lib/mixins/listctrl.py
238     def GetSortImages(self):
239         return (self.sm_dn, self.sm_up)
240
241     def onsearch(self, evt) :
242         self.dial = SearchDial(self, self, 6, True)
243         self.dial.CenterOnParent()
244         self.dial.Show()
245         #self.dial.Destroy()
246
247     def onsearchall(self, evt) :
248         if 'FrameSearch' not in dir(self.Source) :
249             self.Source.FrameSearch = SearchFrame(self.parent, -1, _(u"Search...").decode('utf8'), self.Source.corpus)
250         self.dial = SearchDial(self, self.Source.FrameSearch.liste, 1, False)
251         self.dial.CenterOnParent()
252         self.dial.Show()
253         #self.dial.Destroy()
254
255     def OnRightClick(self, event):
256
257         # only do this part the first time so the events are only bound once
258         if self.Alceste:
259             if not hasattr(self, "popupID1"):
260                 self.popupID1 = wx.NewId()
261                 self.popupID2 = wx.NewId()
262                 self.popupID3 = wx.NewId()
263                 self.popupID4 = wx.NewId()
264                 self.popupID5 = wx.NewId()
265                 self.popupID6 = wx.NewId()
266                 self.popupID7 = wx.NewId()
267                 self.popupID8 = wx.NewId()
268                 self.popupID9 = wx.NewId()
269                 #self.popupID10 = wx.NewId()
270                 self.popupIDgraph = wx.NewId()
271                 self.idseg = wx.NewId()
272                 self.iducecarac = wx.NewId()
273                 self.idtablex = wx.NewId()
274                 self.idchimod = wx.NewId()
275                 self.idwordgraph = wx.NewId()
276                 self.popup_proxe = wx.NewId()
277                 self.idlexdendro = wx.NewId()
278                 self.idcloud = wx.NewId()
279                 self.idexport = wx.NewId()
280                 self.idexporttropes = wx.NewId()
281                 self.idexportowledge = wx.NewId()
282                 self.onmaketgen = wx.NewId()
283             #    self.export_classes = wx.NewId()
284    
285                 self.Bind(wx.EVT_MENU, self.OnPopupOne, id=self.popupID1)
286                 self.Bind(wx.EVT_MENU, self.OnPopupTwo, id=self.popupID2)
287                 self.Bind(wx.EVT_MENU, self.OnPopupThree, id=self.popupID3)
288                 self.Bind(wx.EVT_MENU, self.OnPopupFour, id=self.popupID4)
289                 self.Bind(wx.EVT_MENU, self.OnPopupFive, id=self.popupID5)
290                 self.Bind(wx.EVT_MENU, self.OnPopupSix, id=self.popupID6)
291                 self.Bind(wx.EVT_MENU, self.OnPopupSeven, id=self.popupID7)
292                 self.Bind(wx.EVT_MENU, self.OnPopupHeight, id=self.popupID8)
293                 self.Bind(wx.EVT_MENU, self.OnPopupNine, id=self.popupID9)
294                 #self.Bind(wx.EVT_MENU, self.OnPopupSpec, id=self.popupID10)
295                 self.Bind(wx.EVT_MENU, self.on_graph, id=self.popupIDgraph)
296                 self.Bind(wx.EVT_MENU, self.on_segments, id=self.idseg)
297                 self.Bind(wx.EVT_MENU, self.on_uce_carac, id = self.iducecarac)
298                 self.Bind(wx.EVT_MENU, self.on_tablex, id = self.idtablex)
299                 self.Bind(wx.EVT_MENU, self.quest_var_mod, id = self.idchimod)
300                 self.Bind(wx.EVT_MENU, self.onwordgraph, id = self.idwordgraph)
301                 self.Bind(wx.EVT_MENU, self.onproxe, id = self.popup_proxe)
302                 self.Bind(wx.EVT_MENU, self.onlexdendro, id = self.idlexdendro)
303                 self.Bind(wx.EVT_MENU, self.oncloud, id = self.idcloud)
304                 self.Bind(wx.EVT_MENU, self.onexport, id = self.idexport)
305                 self.Bind(wx.EVT_MENU, self.onexporttropes, id = self.idexporttropes)
306                 self.Bind(wx.EVT_MENU, self.onexportowledge, id = self.idexportowledge)
307                 self.Bind(wx.EVT_MENU, self.OnMakeTgen, id=self.onmaketgen)
308              #  self.Bind(wx.EVT_MENU, self.on_export_classes, id = self.export_classes)
309    #            self.Bind(wx.EVT_MENU, self.OnPopupThree, id=self.popupID3)
310     
311             # make a menu
312             menu = wx.Menu()
313             menu.Append(self.popupID1, _(u"Associated forms").decode('utf8'))
314             menu.Append(self.idtablex, _(u"Chi2 by cluster").decode('utf8'))
315             menu.Append(self.idlexdendro, _(u"Chi2 by cluster on dendrogram").decode('utf8'))
316             menu.Append(self.idchimod, _(u"Chi2 modalities of variable").decode('utf8'))
317             menu.Append(self.idwordgraph, _(u"Word graph").decode('utf8'))
318             #menu.Append(self.export_classes, u"Exporter le corpus...") 
319             
320             #menu.Append(self.popupID10, u"SpĆ©cificitĆ©s")
321
322             menu_conc = wx.Menu()
323             menu_conc.Append(self.popupID2, _(u"In segments of this cluster").decode('utf8'))
324             menu_conc.Append(self.popupID3, _(u"In segments of this clustering").decode('utf8'))
325             menu_conc.Append(self.popupID4, _(u"In all segments").decode('utf8'))
326             menu.AppendMenu(-1, _(u"Concordance").decode('utf8'), menu_conc)
327             menu.Append(self.onmaketgen, _(u"Make Tgen").decode('utf8'))
328             menu_cnrtl = wx.Menu()      
329             menu_cnrtl.Append(self.popupID5, _(u"Definition").decode('utf8'))
330             menu_cnrtl.Append(self.popupID6, _(u"Etymology").decode('utf8'))
331             menu_cnrtl.Append(self.popupID7, _(u"Synonymous").decode('utf8'))
332             menu_cnrtl.Append(self.popupID8, _(u"Antonym").decode('utf8'))
333             menu_cnrtl.Append(self.popupID9, _(u"Morphology").decode('utf8'))
334             menu_cnrtl.Append(self.popup_proxe, _(u"Proxemy").decode('utf8'))
335             menu.AppendMenu(-1, _(u"Tools from CNRTL (french only)").decode('utf8'), menu_cnrtl)
336             menu.AppendSeparator()
337             menu.Append(self.popupIDgraph, _(u"Graph of cluster").decode('utf8'))
338             menu.Append(self.idseg, _(u"Repeated segments").decode('utf8'))
339             menu.Append(self.iducecarac, _(u"Typical text segments").decode('utf8'))
340             menu.Append(self.idcloud, _(u"Word cloud of cluster").decode('utf8'))
341             menu.Append(self.idexport, _(u'Export...').decode('utf8'))
342             menu.Append(self.idexporttropes, _(u'Export for Tropes').decode('utf8'))
343             menu.Append(self.idexportowledge, _('Exporter for Owledge').decode('utf8'))
344             #menu.Append(self.popupID2, u"Concordancier")
345     #        menu.Append(self.popupID3, "recharger")
346     
347             self.PopupMenu(menu)
348             menu.Destroy()
349         elif 'tableau' in dir(self.Source) :
350             if not hasattr(self, "pop1"):
351                 self.pop1 = wx.NewId()
352                 self.pop2 = wx.NewId()
353                 self.pop3 = wx.NewId()
354                 self.Bind(wx.EVT_MENU, self.quest_simi, id=self.pop1)
355                 self.Bind(wx.EVT_MENU, self.on_tablex, id=self.pop2)
356                 self.Bind(wx.EVT_MENU, self.quest_var_mod, id=self.pop3)
357
358             menu = wx.Menu()
359             menu.Append(self.pop2, _(u"Chi2 by cluster").decode('utf8'))
360             menu.Append(self.pop3, _(u"Chi2 modalities of variable").decode('utf8'))
361             menu.AppendSeparator()
362             menu.Append(self.pop1, _(u"Graph of cluster").decode('utf8'))
363             self.PopupMenu(menu)
364             menu.Destroy()
365
366     def oncloud(self, evt) :
367         if 'corpus' in dir(self.Source):
368             corpus = self.Source.corpus
369         prof = [[self.la[i], self.lchi[i], self.lfreq[i]] for i, val in enumerate(self.la)]
370         parametres = copy(self.Source.parametres)
371         parametres['clusterprof'] = prof
372         parametres['type'] = 'clustercloud'
373         parametres['prof'] = self.Source.pathout['actprof_classe_%i.csv' % self.cl]
374         del  parametres['uuid']
375         #if not os.path.exists(self.Source.pathout['actprof_classe_%i.csv' % self.lc]) :
376         #    with open(self.Source.pathout['actprof_classe_%i.csv' % self.lc], 'w') as f :
377         #        f.write('\n'.join(prof).encode(self.parent.syscoding))
378         self.parent.OnClusterCloud(self.Source.corpus, parametres = parametres)
379
380     def onexport(self, evt) :
381         if 'corpus' in dir(self.Source):
382             corpus = self.Source.corpus
383         if self.Source.parametres['classif_mode'] != 2 :
384             uci = False
385         else :
386             uci = True
387         corpus.export_classe(self.Source.pathout['classe_%i_export.txt' % self.cl], self.cl, uci = uci)
388         dial = wx.MessageDialog(self, self.Source.pathout['classe_%i_export.txt' % self.cl], u"Export", wx.OK|wx.ICON_INFORMATION)
389         dial.ShowModal()
390         dial.Destroy()
391         #if 'corpus' in dir(self.Source):
392         #    corpus = self.Source.corpus
393         #ClasseCHD(self.parent, corpus, self.cl)
394     
395     def onexporttropes(self, evt) :
396         if 'corpus' in dir(self.Source):
397             corpus = self.Source.corpus
398         if self.Source.parametres['classif_mode'] != 2 :
399             uci = False
400         else :
401             uci = True
402         fileout = self.Source.pathout['export_tropes_classe_%i.txt' % self.cl]
403         corpus.export_tropes(fileout, self.cl, uci = uci)
404     
405     def onexportowledge(self, evt):
406         if 'corpus' in dir(self.Source):
407             corpus = self.Source.corpus
408         if self.Source.parametres['classif_mode'] != 2 :
409             uci = False
410         else :
411             uci = True
412         repout = self.Source.pathout['export_owledge_classe_%i' % self.cl]
413         if not os.path.exists(repout) :
414             os.mkdir(repout)
415         corpus.export_owledge(repout, self.cl, uci = uci)        
416
417     def getselectedwords(self) :
418         words = [self.getColumnText(self.GetFirstSelected(), 6)]
419         last = self.GetFirstSelected()
420         while self.GetNextSelected(last) != -1:
421             last = self.GetNextSelected(last)
422             words.append(self.getColumnText(last, 6))
423         return words
424
425     def quest_var_mod(self, evt) :  
426         word = self.getselectedwords()[0]
427         if len(word.split('_')) <= 1 :
428             dial = wx.MessageDialog(self, _(u"This is not a variable_modality form").decode('utf8'), _(u"Problem").decode('utf8'), wx.OK | wx.ICON_WARNING)
429             dial.CenterOnParent()
430             dial.ShowModal()
431             dial.Destroy()
432             return
433             
434         if 'corpus' in dir(self.Source):
435             corpus = self.Source.corpus
436             if word.startswith(u'-*') :
437                 if self.them_mod == {} :
438                     self.them_mod = self.Source.corpus.make_theme_dict()
439                 var_mod = self.them_mod
440             else :
441                 if self.var_mod == {} :
442                     self.var_mod = self.Source.corpus.make_etoiles_dict()
443                 var_mod = self.var_mod
444         else :
445             corpus = self.Source.tableau
446             if self.var_mod == {} :
447                 self.var_mod = treat_var_mod([val for val in corpus.actives] + [val for val in corpus.sups])
448             var_mod = self.var_mod
449         with codecs.open(self.Source.pathout['chisqtable'], 'r', corpus.parametres['syscoding']) as f :
450             chistable = [line.replace('\n','').replace('\r','').replace('"','').replace(',','.').split(';') for line in f]
451         title = chistable[0]
452         title.pop(0)
453         chistable.pop(0)
454         vchistable = [line[1:] for line in chistable]
455         fchistable = [line[0] for line in chistable]
456
457         var = word.split('_')
458         #words = ['_'.join([var[0],word]) for word in self.var_mod[var[0]]]
459         try :
460             words = [word for word in var_mod[var[0]]]
461         except KeyError:
462             dial = wx.MessageDialog(self, _(u"This is not a meta-data").decode('utf8'), _(u"Problem").decode('utf8'), wx.OK | wx.ICON_WARNING)
463             dial.CenterOnParent()
464             dial.ShowModal()
465             dial.Destroy()
466             return            
467         words.sort()
468         tableout = []
469         kwords = []
470         for word in words :
471             if word in fchistable :
472                 tableout.append(vchistable[fchistable.index(word)])
473                 kwords.append(word)
474         BarFrame(self.Source.parent, tableout, title, kwords)
475
476     def quest_simi(self, evt) :
477         tableau = self.Source.tableau
478         tab = tableau.make_table_from_classe(self.cl, self.la)
479         pathout = ConstructPathOut(self.Source.pathout.dirout, 'simi_classe_%i' %self.cl)
480         if self.tmpchi is None :
481             self.tmpchi = os.path.join(pathout,'chi.csv')
482             with open(self.tmpchi, 'w') as f:
483                 f.write('\n'.join([str(val) for val in self.lchi]))
484         self.filename = os.path.join(pathout,'mat01.csv')
485         tableau.printtable(self.filename, tab)
486         del tab
487         paramsimi = {'coeff' : 0,
488                           'layout' : 2,
489                           'type_graph' : 1,
490                           'arbremax' : 1,
491                           'coeff_tv' : 1,
492                           'coeff_tv_nb' : 0,
493                           'tvprop' : 0,
494                           'tvmin' : 5,
495                           'tvmax' : 30,
496                           'coeff_te' : 1,
497                           'coeff_temin' : 1,
498                           'coeff_temax' : 10,
499                           'label_v': 1,
500                           'label_e': 1,
501                           'vcex' : 0,
502                           'vcexmin' : 10,
503                           'vcexmax' : 25,
504                           'cex' : 10,
505                           'cexfromchi' : True,
506                           'sfromchi': False,
507                           'seuil_ok' : 0,
508                           'seuil' : 1,
509                           'cols' : (255,0,0),
510                           'cola' : (200,200,200),
511                           'width' : 1000,
512                           'height' : 1000,
513                           'first' : True,
514                           'keep_coord' : True,
515                           'alpha' : 20,
516                           'film': False,
517                           'com' : 0,
518                           'communities' : 0,
519                           'halo' : 0,
520                           'tmpchi': self.tmpchi,
521                           'fromprof' : True,
522                           'edgecurved' : True,
523                           }
524         act = {}
525         tableau = copymatrix(tableau)
526         tableau.chi = {}
527         tableau.lchi = self.lchi
528         #tableau.parametres['fromprof'] = True
529         for i, val in enumerate(self.la) :
530             act[val] = [self.lfreq[i]]
531             tableau.chi[val] = [self.lchi[i]]
532         paramsimi['listactives'] = copy(self.la)
533         paramsimi['actives'] = copy(act)
534         paramsimi['pathout'] = pathout
535         self.parent.SimiCluster(parametres = paramsimi, fromprof = ffr(self.filename), tableau = tableau)
536
537     def onwordgraph(self, evt):
538         word = self.getColumnText(self.GetFirstSelected(), 6)
539         if self.tmpchi is None :
540             self.tmpchi = os.path.join(self.Source.parametres['pathout'],'chi_%i.csv' % self.cl)
541             with open(self.tmpchi, 'w') as f:
542                 f.write('\n'.join([str(val) for val in self.lchi]))
543         index = self.la.index(word)
544         parametres = {'type' : 'clustersimitxt', 
545                         'pathout' : self.Source.parametres['pathout'],
546                         'word' : index ,
547                         'lem' : self.Source.parametres['lem'],
548                         'tmpchi' : self.tmpchi}
549         #try :
550         self.parent.SimiFromCluster(self.parent, self.Source.corpus, self.la, self.lfreq, self.lchi, self.cl - 1, parametres = parametres, dlg = progressbar(self.ira, 4))
551         #except :
552         #    print 'not acitve'
553
554     def on_graph(self, evt):
555         if self.tmpchi is None :
556             self.tmpchi = os.path.join(self.Source.parametres['pathout'],'chi_%i.csv' % self.cl)
557             with open(self.tmpchi, 'w') as f:
558                 f.write('\n'.join([str(val) for val in self.lchi]))
559         parametres = {'type' : 'clustersimitxt', 
560                         'pathout' : self.Source.parametres['pathout'],
561                         'lem' : self.Source.parametres['lem'],
562                         'tmpchi' : self.tmpchi}
563
564         self.parent.SimiFromCluster(self.parent, self.Source.corpus, self.la, self.lfreq, self.lchi, self.cl - 1, parametres = parametres, dlg = progressbar(self.ira, 4))
565
566     def on_segments(self,evt) :
567         dlg = progressbar(self, 2)
568         corpus = self.Source.corpus
569         uces = corpus.lc[self.cl-1]
570         if self.Source.parametres['classif_mode'] != 2 :
571             uci = False
572         else :
573             uci = True
574         l = []
575         dlg.Update(1, u'Segments...')
576         for i in range(2,10) :
577             li = corpus.find_segments_in_classe(uces, i, 1000, uci = uci)
578             if li == [] :
579                 break
580             else :
581                 l += li
582         l.sort(reverse = True)
583         d = {}
584         dlg.Update(2, 'Tri...')
585         for i, line in enumerate(l) :
586             d[i] = [line[1],line[0], line[2]]
587         first = ['','','']
588         para={'dico': d,'fline':first}
589         dlg.Destroy()
590         win = wliste(self, -1, ' - '.join([_(u"Repeated segments").decode('utf8'), "Classe %i" % self.cl]), d, first, size=(600, 500))
591         win.Show(True)
592
593     def on_uce_carac(self,evt) :
594         dial = PrefUCECarac(self, self.parent)
595         dial.CenterOnParent()
596         if dial.ShowModal() == wx.ID_OK :
597             limite = dial.spin_eff.GetValue()
598             atype = dial.radio_type.GetSelection()
599             dlg = progressbar(self,maxi = 4)
600             corpus = self.Source.corpus
601             uces = corpus.lc[self.cl-1]
602             if self.Source.parametres['classif_mode'] != 2 :
603                 uci = False
604             else :
605                 uci = True
606             tab = corpus.make_table_with_classe(uces, self.la, uci = uci)
607             tab.pop(0)
608             dlg.Update(2, u'score...')
609             if atype == 0 :
610                 ntab = [round(sum([self.lchi[i] for i, word in enumerate(line) if word == 1]),2) for line in tab]
611             else :
612                 ntab = [round(sum([self.lchi[i] for i, word in enumerate(line) if word == 1])/float(sum(line)),2) if sum(line)!=0 else 0 for line in tab]
613             ntab2 = [[ntab[i], uces[i]] for i, val in enumerate(ntab)]
614             del ntab
615             ntab2.sort(reverse = True)
616             ntab2 = ntab2[:limite]
617             nuces = [val[1] for val in ntab2]
618             dlg.Update(3, u'concordancier...')
619             ucis_txt, ucestxt = doconcorde(corpus, nuces, self.la, uci = uci)
620             items = dict([[i, '<br>'.join([ucis_txt[i], '<table bgcolor = #1BF0F7 border=0><tr><td><b>score : %.2f</b></td></tr></table><br>' % ntab2[i][0], ucestxt[i]])] for i, uce in enumerate(nuces)])
621             dlg.Destroy()
622             win = message(self, items, ' - '.join([_(u"Typical text segments").decode('utf8'), "Classe %i" % self.cl]), (750, 600), uceids = nuces)
623             #win.SetWindowStyle(wx.STAY_ON_TOP)
624             #win.html = '<html>\n' + '<br>'.join(['<br>'.join([ucis_txt[i], '<table bgcolor = #1BF0F7 border=0><tr><td><b>score : %.2f</b></td></tr></table>' % ntab2[i][0], ucestxt[i]]) for i in range(0,len(ucestxt))]) + '\n</html>'
625             #win.HtmlPage.SetPage(win.html)
626             win.Show(True)
627     
628     def on_tablex(self, evt):
629         if 'corpus' in dir(self.Source):
630             corpus = self.Source.corpus
631         else :
632             corpus = self.Source.tableau
633         with codecs.open(self.Source.pathout['chisqtable'], 'r', corpus.parametres['syscoding']) as f :
634             chistable = [line.replace('\n','').replace('\r','').replace('"','').replace(',','.').split(';') for line in f]
635         title = chistable[0]
636         title.pop(0)
637         chistable.pop(0)
638         vchistable = [line[1:] for line in chistable]
639         fchistable = [line[0] for line in chistable]
640         words = self.getselectedwords()
641         tableout = [vchistable[fchistable.index(word)] for word in words]
642         tmpgraph = tempfile.mktemp(dir=self.Source.parent.TEMPDIR)
643         nbcl = len(title)
644         nbwords = len(words)
645         BarFrame(self.Source.parent, tableout, title, words)
646
647     def onlexdendro(self, evt):
648         if 'corpus' in dir(self.Source):
649             corpus = self.Source.corpus
650         else :
651             corpus = self.Source.tableau
652         with codecs.open(self.Source.pathout['chisqtable'], 'r', corpus.parametres['syscoding']) as f :
653             chistable = [line.replace('\n','').replace('\r','').replace('"','').replace(',','.').split(';') for line in f]
654         title = chistable[0]
655         title.pop(0)
656         chistable.pop(0)
657         vchistable = [line[1:] for line in chistable]
658         fchistable = [line[0] for line in chistable]
659         words = self.getselectedwords()
660         tableout = [vchistable[fchistable.index(word)] for word in words]
661         BarFrame(self.Source.parent, tableout, title, words, tree = self.Source.pathout['Rdendro'])
662
663     def make_concord(self, uces, title, color = 'red') :
664         corpus = self.Source.corpus
665         ListWord = [self.getColumnText(self.GetFirstSelected(), 6)]
666         last = self.GetFirstSelected()
667         while self.GetNextSelected(last) != -1:
668             last = self.GetNextSelected(last)
669             ListWord.append(self.getColumnText(last, 6))
670         ucef = []
671         if self.Source.parametres['classif_mode'] != 2 :
672             for word in ListWord : 
673                 uci = False
674                 ucef += list(set(corpus.getlemuces(word)).intersection(uces))
675         else :
676             for word in ListWord : 
677                 ucef += list(set(corpus.getlemucis(word)).intersection(uces))            
678                 uci = True
679         ucis_txt, ucestxt = doconcorde(corpus, ucef, ListWord, uci = uci)
680         items = dict([[i, '<br><br>'.join([ucis_txt[i], ucestxt[i]])] for i in range(0,len(ucestxt))])
681         win = message(self, items, title, (800, 500), uceids = ucef)
682         return win
683
684     def OnPopupTwo(self, event):
685         if 'corpus' in dir(self.Source) :
686             corpus = self.Source.corpus
687             uces = corpus.lc[self.cl-1]
688             win = self.make_concord(uces, ' - '.join([_(u"Concordance").decode('utf8'), "Classe %i" % self.cl]))
689             win.Show(True)
690     
691     def OnPopupThree(self, event):
692         corpus = self.Source.corpus
693         uces = [classe[i] for classe in corpus.lc for i in range(0,len(classe))]
694         win = self.make_concord(uces, ' - '.join([_(u"Concordance").decode('utf8'), _(u"Segments of this clustering").decode('utf8')]))
695         win.Show(True)
696         
697     def OnPopupFour(self, event):
698         corpus = self.Source.corpus
699         uces = [classe[i] for classe in corpus.lc for i in range(0,len(classe))] + corpus.lc0
700         win = self.make_concord(uces, ' - '.join([_(u"Concordance").decode('utf8'), _(u"All segments").decode('utf8')]))
701         win.Show(True)
702
703     def OnPopupFive(self, event):
704         word = self.getColumnText(self.GetFirstSelected(), 6)
705         lk = "http://www.cnrtl.fr/definition/" + word
706         webbrowser.open(lk)
707
708     def OnPopupSix(self, event):  
709         word = self.getColumnText(self.GetFirstSelected(), 6)
710         lk = "http://www.cnrtl.fr/etymologie/" + word
711         webbrowser.open(lk)
712         
713     def OnPopupSeven(self, event):        
714         word = self.getColumnText(self.GetFirstSelected(), 6)
715         lk = "http://www.cnrtl.fr/synonymie/" + word
716         webbrowser.open(lk)
717         
718     def OnPopupHeight(self, event):  
719         word = self.getColumnText(self.GetFirstSelected(), 6)
720         lk = "http://www.cnrtl.fr/antonymie/" + word
721         webbrowser.open(lk)
722         
723     def OnPopupNine(self, event):            
724         word = self.getColumnText(self.GetFirstSelected(), 6)
725         lk = "http://www.cnrtl.fr/morphologie/" + word
726         webbrowser.open(lk)
727
728     def onproxe(self, evt) :
729         word = self.getColumnText(self.GetFirstSelected(), 6)
730         lk = "http://www.cnrtl.fr/proxemie/" + word
731         webbrowser.open(lk)
732
733     def OnPopupOne(self, event):
734         corpus = self.Source.corpus
735         #print 'ATTENTION PRINT ET TABLE'
736         #corpus.make_et_table()
737         word = self.getColumnText(self.GetFirstSelected(), 6)
738         lems = corpus.getlems()
739         uces = corpus.lc[self.cl-1]
740         rep = []
741         #FIXME : donner aussi eff reel a la place de nb uce
742         for forme in lems[word].formes :
743             if self.Source.parametres['classif_mode'] != 2 :
744                 ucef = list(set(corpus.getworduces(forme)).intersection(uces))
745             else :
746                 ucef = list(set(corpus.getworducis(forme)).intersection(uces))
747             #ucef = [uce for uce in corpus.formes[forme][1] if uce in uces]
748             if ucef != [] :
749                 nb = len(ucef)
750                 rep.append([corpus.getforme(forme).forme, nb])
751         rep.sort(key = itemgetter(1), reverse = True)
752         #win = message(self, u"Formes associĆ©es", wx.Size(300, 200))
753         items = dict([[i, '\t:\t'.join([str(val) for val in forme])] for i, forme in enumerate(rep)])
754         win = message(self, items, _(u"Associated forms").decode('utf8'), (300, 200))
755         #win.html = '<html>\n' + '<br>'.join([' : '.join([str(val) for val in forme]) for forme in rep]) + '\n</html>'
756         #win.HtmlPage.SetPage(win.html)
757         win.Show(True)
758     
759     def OnMakeTgen(self, evt):
760         self.parent.tree.OnTgenEditor(self.getselectedwords())    
761
762
763 class wliste(wx.Frame):
764     def __init__(self, parent, id, title, d, fline, size=(600, 500)):
765         wx.Frame.__init__(self, parent, id)
766         self.liste = ListForSpec(self, parent, d, fline[1:], menu = False)
767         self.button_1 = wx.Button(self, -1, _(u"Close").decode('utf8'))
768         self.Bind(wx.EVT_BUTTON, self.OnCloseMe, self.button_1)
769         self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
770         self.__do_layout()
771
772     def __do_layout(self):
773         sizer_1 = wx.BoxSizer(wx.VERTICAL)
774         sizer_2 = wx.BoxSizer(wx.VERTICAL)
775         sizer_2.Add(self.liste, 1, wx.EXPAND | wx.ADJUST_MINSIZE, 0)
776         sizer_2.Add(self.button_1, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ADJUST_MINSIZE, 0)
777         sizer_1.Add(sizer_2, 1, wx.EXPAND, 0)
778         self.SetAutoLayout(True)
779         self.SetSizer(sizer_1)
780         self.Layout()
781         
782     def OnCloseMe(self, event):
783         self.Close(True)
784
785     def OnCloseWindow(self, event):
786         self.Destroy()