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