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