...
authorpierre <ratinaud@univ-tlse2.fr>
Sun, 4 Feb 2024 21:46:06 +0000 (22:46 +0100)
committerpierre <ratinaud@univ-tlse2.fr>
Sun, 4 Feb 2024 21:46:06 +0000 (22:46 +0100)
ProfList.py
Rscripts/simi.R
elcategorizator.py [new file with mode: 0644]
functions.py
iramuteq.py
layout.py
openanalyse.py
tableau.py

index 6038edb..ebc9a53 100644 (file)
@@ -116,12 +116,12 @@ class ProfListctrlPanel(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin, listmix.Col
         self.InsertColumn(6, "forme", wx.LIST_FORMAT_RIGHT)
         self.InsertColumn(7, "p", wx.LIST_FORMAT_RIGHT)
         self.SetColumnWidth(0, 60)
-        self.SetColumnWidth(1, 70)
-        self.SetColumnWidth(2, 80)
-        self.SetColumnWidth(3, 100)
-        self.SetColumnWidth(4, 70)
-        self.SetColumnWidth(5, 60)
-        self.SetColumnWidth(6, 140)
+        self.SetColumnWidth(1, 100)
+        self.SetColumnWidth(2, 100)
+        self.SetColumnWidth(3, 120)
+        self.SetColumnWidth(4, 150)
+        self.SetColumnWidth(5, 100)
+        self.SetColumnWidth(6, 300)
         self.SetColumnWidth(7, wx.LIST_AUTOSIZE)
         #These two should probably be passed to init more cleanly
         #setting the numbers of items = number of elements in the dictionary
@@ -131,8 +131,10 @@ class ProfListctrlPanel(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin, listmix.Col
         #mixins
         listmix.ListCtrlAutoWidthMixin.__init__(self)
         listmix.ColumnSorterMixin.__init__(self, len(classen[0]))
-        #sort by genre (column 2), A->Z ascending order (1)
         self.SortListItems(0, True)
+        #sort by genre (column 2), A->Z ascending order (1)
+
+
         #events
         #self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected)
         self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnPopupTwo, self)
index 2a4c8b7..bf42008 100755 (executable)
@@ -376,7 +376,7 @@ plot.simi <- function(graph.simi, p.type = 'tkplot',filename=NULL, communities =
             require(tcltk)
             ReturnVal <- tkmessageBox(title="RGL 3 D",message="Cliquez pour commencer le film",icon="info",type="ok")
 
-            movie3d(spin3d(axis=c(0,1,0),rpm=6), movie = 'film_graph', frames = "tmpfilm", duration=10, clean=TRUE, top = TRUE, dir = movie)
+            movie3d(spin3d(axis=c(0,0,1),rpm=6), movie = 'film_graph', frames = "tmpfilm", duration=10, clean=TRUE, top = TRUE, dir = movie)
             ReturnVal <- tkmessageBox(title="RGL 3 D",message="Film fini !",icon="info",type="ok")
         }
         #play3d(spin3d(axis=c(0,1,0),rpm=6))
diff --git a/elcategorizator.py b/elcategorizator.py
new file mode 100644 (file)
index 0000000..b9f531c
--- /dev/null
@@ -0,0 +1,1005 @@
+# -*- coding: utf-8 -*-
+#Author: Pierre Ratinaud
+#Copyright (c) 2022 Pierre Ratinaud
+#License: GNU/GPL
+
+import os
+import wx
+import wx.xrc
+#from wx.lib.splitter import MultiSplitterWindow
+from listlex import *
+import pickle
+import json
+
+
+
+class CategoDict :
+    def __init__(self, pathout = None):
+        self.pathout = pathout
+        self.cate = self.readjson()
+        self.lenwords = len(self.cate['TOCATE']) + len([word for categorie in self.cate['CATE'] for word in self.cate['CATE'][categorie][1]])
+
+    def readjson(self):
+        if self.pathout is not None :
+            with open(self.pathout['cate.json'], 'r') as f :
+                cate = json.load(f)
+        else :
+            cate = {'TOCATE' : {'word1': 3, 'word2' : 2, 'word3' : 5}, 'CATE': {'cat1' : [34,{'word6':30, 'word7':4}], 'cat2' : [20,{'word20':20}]}}
+        return cate
+
+    def save(self) :
+        with open(self.pathout['cate.json'], 'w', encoding='utf8') as f :
+            f.write(json.dumps(self.cate, indent=4))
+        print("json saved!")
+
+    def exportdict(self):
+        pass
+
+    def getcate(self) :
+        cate = []
+        i = 0
+        for val in self.cate['CATE'] :
+            cate.append([i, [val, self.cate['CATE'][val][0]]])
+            i += 1
+        return dict(cate)
+
+    def getwordstocate(self) :
+        words = []
+        i = 0
+        for val in self.cate['TOCATE'] :
+            words.append([i, [val, self.cate['TOCATE'][val]]])
+            i+= 1
+        return dict(words)
+
+    def getcatewords(self, cat) :
+        catewords = []
+        i = 0
+        if cat not in self.cate['CATE'] :
+            return {}
+        for val in self.cate['CATE'][cat][1] :
+            catewords.append([i, [val, self.cate['CATE'][cat][1][val]]])
+            i += 1
+        return dict(catewords)
+
+    def getwordscate(self) :
+        wc = {}
+        for word in self.cate['TOCATE'] :
+            wc[word] = word
+        for categorie in self.cate['CATE'] :
+            for word in self.cate['CATE'][categorie][1] :
+                wc[word] = categorie
+        return wc
+
+    def addwordincate(self, categorie, word, eff) :
+        self.cate['CATE'][categorie][1][word] = eff
+        self.cate['CATE'][categorie][0] += eff
+        del(self.cate['TOCATE'][word])
+
+    def addwordinwords(self, categorie, word, eff) :
+        print(categorie, word, eff)
+        self.cate['TOCATE'][word] = eff
+        self.cate['CATE'][categorie][0] -= eff
+        del(self.cate['CATE'][categorie][1][word])
+        if self.cate['CATE'][categorie][0] == 0 :
+            del(self.cate['CATE'][categorie])
+
+    def findcatefromword(self, word) :
+        for categorie in self.cate['CATE'] :
+            if word in self.cate['CATE'][categorie][1] :
+                return categorie
+        return None
+
+    def changewordcate(self, newcate, word, eff) :
+        oldcat = self.findcatefromword(word)
+        del(self.cate['CATE'][oldcat][1][word])
+        self.cate['CATE'][oldcat][0] -= eff
+        self.cate['CATE'][newcate][1][word] = eff
+        self.cate['CATE'][newcate][0] += eff
+        if self.cate['CATE'][oldcat][0] == 0 :
+            del(self.cate['CATE'][oldcat])
+
+    def addcatefromwordtocate(self, word, eff) :
+        if word in self.cate['CATE'] :
+            return False
+        else :
+            self.cate['CATE'][word]=[eff,{word:eff}]
+            del(self.cate['TOCATE'][word])
+            return True
+
+    def addcatefromwordcate(self, word, eff) :
+        if word in self.cate['CATE'] :
+            return False
+        else :
+            oldcat = self.findcatefromword(word)
+            self.cate['CATE'][word]=[eff,{word:eff}]
+            del(self.cate['CATE'][oldcat][1][word])
+            self.cate['CATE'][oldcat][0] -= eff
+            if self.cate['CATE'][oldcat][0] == 0 :
+                del(self.cate['CATE'][oldcat])
+            return True
+
+    def delcate(self, categorie) :
+        for word in self.cate['CATE'][categorie][1] :
+            self.cate['TOCATE'][word] = self.cate['CATE'][categorie][1][word]
+        del(self.cate['CATE'][categorie])
+
+    def loadcate(self, infile) :
+        if self.cate['CATE'] != {} :
+            print("Categories should be empty")
+            return False
+        with open(infile, 'r') as f :
+            newcate = json.load(f)
+        for categorie in newcate['CATE'] :
+            self.cate['CATE'][categorie] = [0,{}]
+            for word in newcate['CATE'][categorie][1] :
+                if word in self.cate['TOCATE'] :
+                    self.cate['CATE'][categorie][1][word] = self.cate['TOCATE'][word]
+                    self.cate['CATE'][categorie][0] += self.cate['TOCATE'][word]
+                    del(self.cate['TOCATE'][word])
+
+    def makestat(self) :
+        totocat = sum([self.cate['TOCATE'][word] for word in self.cate['TOCATE']])
+        nbtocat = len(self.cate['TOCATE'])
+        nbcate = len(self.cate['CATE'])
+        totcate = sum([self.cate['CATE'][categorie][0] for categorie in self.cate['CATE']])
+        lenwordincate = len([word for categorie in self.cate['CATE'] for word in self.cate['CATE'][categorie][1]])
+        return nbtocat, totocat, nbcate, totcate, lenwordincate
+
+
+#cate = CategoDict()
+
+
+class ElCategorizator ( wx.Panel ):
+
+    def __init__( self, parent, pathout, tableau, id = wx.ID_ANY, pos = wx.DefaultPosition, size = wx.Size( 500,300 ), style = wx.TAB_TRAVERSAL, name = wx.EmptyString ):
+        wx.Panel.__init__ ( self, parent, id = id, pos = pos, size = size, style = style, name = name )
+        self.pathout = pathout
+        self.parent = parent
+        self.tableau = tableau
+
+        self.cate = CategoDict(self.pathout)
+        gsizer =  wx.BoxSizer( wx.VERTICAL )
+
+        bSizer1 = wx.BoxSizer( wx.HORIZONTAL )
+
+        self.m_listToCate = ListForWords(self, dlist = self.cate, first = ['eff'])
+        bSizer1.Add( self.m_listToCate, 2, wx.ALL|wx.EXPAND, 5 )
+
+        self.m_listCate = ListForCate(self, dlist = self.cate, first = ['eff'])
+        bSizer1.Add( self.m_listCate, 1, wx.ALL|wx.EXPAND, 5 )
+
+        self.m_listCateWords = ListForCateWords(self, dlist = self.cate, first = ['eff'])
+        bSizer1.Add( self.m_listCateWords, 1, wx.ALL|wx.EXPAND, 5 )
+
+        bSizer2 = wx.BoxSizer( wx.HORIZONTAL )
+
+        self.butsave = wx.Button( self, wx.ID_SAVE, u"Save", wx.DefaultPosition, wx.DefaultSize, 0 )
+        bSizer2.Add( self.butsave, 0, wx.ALL, 5 )
+
+        self.butcsv = wx.Button( self, wx.ID_ANY, u"Export Columns", wx.DefaultPosition, wx.DefaultSize, 0 )
+        bSizer2.Add( self.butcsv, 0, wx.ALL, 5 )
+
+        self.butdict = wx.Button( self, wx.ID_ANY, u"Export dictonary", wx.DefaultPosition, wx.DefaultSize, 0 )
+        bSizer2.Add( self.butdict, 0, wx.ALL, 5 )
+
+        self.butload = wx.Button( self, wx.ID_ANY, u"Load a categorization", wx.DefaultPosition, wx.DefaultSize, 0 )
+        bSizer2.Add( self.butload, 0, wx.ALL, 5 )
+
+        bSizer3 = wx.BoxSizer( wx.HORIZONTAL )
+
+        self.nbword = """Words : {:d} ({:d}) | """
+
+        self.stat = """ Words to categorize : {:d} ({}%) - {:d} ({}%) -- Categories : {:d} - {:d} ({}%) - {:d} ({}%)"""
+#        nbtocat, totocat, nbcate, totcate = self.cate.makestat()
+#        lenwords = self.cate.lenwords
+#        totwords = totocat + totcate
+#        prtocat = repr(nbtocat/lenwords)
+#        prtotocat = repr(totocat/totwords)
+#        prcate = repr(totcate/totwords)
+        self.wordtxt = wx.StaticText(self, -1, "")
+        bSizer3.Add( self.wordtxt, 0, wx.ALL, 5 )
+        self.stattxt = wx.StaticText(self, -1, "")
+        bSizer3.Add( self.stattxt, 0, wx.ALL, 5 )
+
+
+        gsizer.Add( bSizer2, 0, wx.EXPAND, 5 )
+        gsizer.Add( bSizer1, 2, wx.EXPAND, 5 )
+        gsizer.Add( bSizer3, 0, wx.EXPAND, 5 )
+
+        self.butsave.Bind(wx.EVT_BUTTON, self.OnSave)
+        self.butcsv.Bind(wx.EVT_BUTTON, self.OnCSV)
+        self.butdict.Bind(wx.EVT_BUTTON, self.OnDict)
+        self.butsave.SetBackgroundColour((14, 242, 14, 255))
+        self.butload.Bind(wx.EVT_BUTTON, self.OnLoad)
+        self.OnStat()
+        self.SetSizer( gsizer )
+        self.Layout()
+
+    def __del__( self ):
+        pass
+
+
+    def OnLoad(self, event) :
+        if len(self.cate.cate['CATE']) != 0 :
+            print("Categories should be empty")
+            event.Skip()
+            return
+        wildcard = "json|*.json|" \
+                   "All file|*.*"
+        dlg = wx.FileDialog(
+             self, message="Choose a file",
+             defaultDir=self.pathout.dirout,
+             defaultFile="",
+             wildcard=wildcard,
+             style=wx.FD_OPEN |
+                   wx.FD_CHANGE_DIR | wx.FD_FILE_MUST_EXIST |
+                   wx.FD_PREVIEW
+             )
+
+        if dlg.ShowModal() == wx.ID_OK:
+            paths = dlg.GetPaths()
+            path = paths[0]
+            self.cate.loadcate(path)
+            self.m_listCate.RefreshData(self.cate.getcate())
+            self.m_listToCate.RefreshData(self.cate.getwordstocate())
+        dlg.Destroy()
+
+    def OnSave(self, event) :
+        self.cate.save()
+        self.butsave.SetBackgroundColour((14, 242, 14, 255))
+
+    def OnCSV(self, event) :
+        wordscate = self.cate.getwordscate()
+        newtab = [['category%i' % i for i in range(1, len(self.tableau.selected_col)+1)]]
+        for line in self.tableau.select_col(self.tableau.selected_col):
+            newline = []
+            for word in line :
+                newline.append(wordscate.get(word,word))
+            newtab.append(newline)
+        with open(self.pathout['tableout.csv'], 'w') as f :
+            f.write('\n'.join(['\t'.join(line) for line in newtab]))
+        print("csv exported !")
+
+    def OnDict(self, event):
+        with open(self.pathout['dictionnary.txt'], 'w') as f :
+            for categorie in self.cate.cate['CATE'] :
+                f.write(categorie + ': \t' + repr(self.cate.cate['CATE'][categorie][0]) + '\n')
+                for word in self.cate.cate['CATE'][categorie][1] :
+                    f.write('\t' + word + ': \t' + repr(self.cate.cate['CATE'][categorie][1][word]) + '\n')
+            for word in self.cate.cate['TOCATE'] :
+                f.write(word + ':\t' + repr(self.cate.cate['TOCATE'][word]) + '\n')
+        print("dictionnary exported !")
+
+    def OnStat(self) :
+        nbtocat, totocat, nbcate, totcate, lenwordincate = self.cate.makestat()
+        totwords = totocat + totcate
+        prtocat = repr(round((nbtocat/self.cate.lenwords) * 100 ,2))
+        prtotocat = repr(round((totocat/totwords) * 100, 2))
+        prcate = repr(round((totcate/totwords)*100, 2))
+        prwordincate = repr(round((lenwordincate/self.cate.lenwords)*100, 2))
+        self.stattxt.SetLabel(self.stat.format(nbtocat, prtocat, totocat, prtotocat, nbcate, lenwordincate, prwordincate, totcate, prcate))
+
+    def OnAddToTable(self) :
+        wordscate = self.cate.getwordscate()
+        newtab = [['category%i' % i for i in range(1, len(self.tableau.selected_col)+1)]]
+        for line in self.tableau.select_col(self.tableau.selected_col):
+            newline = []
+            for word in line :
+                newline.append(wordscate.get(word,word))
+            newtab.append(newline)
+
+
+
+#class ListPanel(wx.Panel) :
+#     def __init__(self, parent, gparent, List):
+#        wx.Panel.__init__(self, parent, style=wx.BORDER_SUNKEN)
+#        self.parent = parent
+#        self.cate = gparent.cate
+#        self.list = List(self, dlist = gparent.cate, first = ['eff'])
+
+
+#class ElCategorizator ( wx.Panel ):
+#
+#    def __init__( self, parent, pathout, tableau, id = wx.ID_ANY, pos = wx.DefaultPosition, size = wx.Size( 500,300 ), style = wx.TAB_TRAVERSAL, name = wx.EmptyString ):
+#        wx.Panel.__init__ ( self, parent, id = id, pos = pos, size = size, style = style, name = name )
+#        self.pathout = pathout
+#        self.parent = parent
+#        self.tableau = tableau
+#
+#        self.cate = CategoDict(self.pathout)
+#
+#        splitter = MultiSplitterWindow(self, style=wx.SP_LIVE_UPDATE)
+#        self.splitter = splitter
+#        sizer = wx.BoxSizer(wx.HORIZONTAL)
+#        sizer.Add(splitter, 1, wx.EXPAND)
+#        self.SetSizer(sizer)
+#
+#        panelwords = ListPanel(splitter, self, ListForWords)
+#        splitter.AppendWindow(panelwords, 150)
+#        panelcate = ListPanel(splitter, self, ListForCate)
+#        splitter.AppendWindow(panelcate, 150)
+#        panelwordscate = ListPanel(splitter, self, ListForCateWords)
+#        splitter.AppendWindow(panelwordscate, 150)
+#        self.m_listToCate = panelwords.list
+#        self.m_listCate = panelcate.list
+#        self.m_listCateWords = panelwordscate.list
+#
+#    def __del__( self ):
+#        pass
+#
+#    def OnSave(self, event) :
+#        self.cate.save()
+#        self.butsave.SetBackgroundColour((14, 242, 14, 255))
+#
+#    def OnCSV(self, event) :
+#        wordscate = self.cate.getwordscate()
+#        newtab = [['category%i' % i for i in range(1, len(self.tableau.selected_col)+1)]]
+#        for line in self.tableau.select_col(self.tableau.selected_col):
+#            newline = []
+#            for word in line :
+#                newline.append(wordscate.get(word,word))
+#            newtab.append(newline)
+#        with open(self.pathout['tableout.csv'], 'w') as f :
+#            f.write('\n'.join(['\t'.join(line) for line in newtab]))
+#        print("csv exported !")
+#
+#    def OnDict(self, event):
+#        with open(self.pathout['dictionnary.txt'], 'w') as f :
+#            for categorie in self.cate.cate['CATE'] :
+#                f.write(categorie + ': \t' + repr(self.cate.cate['CATE'][categorie][0]) + '\n')
+#                for word in self.cate.cate['CATE'][categorie][1] :
+#                    f.write('\t' + word + ': \t' + repr(self.cate.cate['CATE'][categorie][1][word]) + '\n')
+#            for word in self.cate.cate['TOCATE'] :
+#                f.write(word + ':\t' + repr(self.cate.cate['TOCATE'][word]) + '\n')
+#        print("dictionnary exported !")
+
+
+class ListForCate(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin, listmix.ColumnSorterMixin):
+
+    def __init__(self, parent, dlist = {}, first = [], usefirst = False, menu = True):
+        wx.ListCtrl.__init__( self, parent, -1, style=wx.LC_REPORT|wx.LC_VIRTUAL|wx.LC_HRULES|wx.LC_VRULES|wx.LC_EDIT_LABELS|wx.LC_SINGLE_SEL)
+        self.parent=parent
+        self.cate = self.parent.cate
+        self.dlist= self.cate.getcate()
+        self.first = first
+        self.il = wx.ImageList(20, 20)
+        a={"sm_up":"GO_UP","sm_dn":"GO_DOWN","w_idx":"WARNING","e_idx":"ERROR","i_idx":"QUESTION", "p_idx":"PLUS"}
+        for k,v in list(a.items()):
+            s="self.%s= self.il.Add(wx.ArtProvider.GetBitmap(wx.ART_%s,wx.ART_TOOLBAR,(20,20)))" % (k,v)
+            exec(s)
+        self.SetImageList(self.il, wx.IMAGE_LIST_SMALL)
+        self.attr1 = wx.ListItemAttr()
+        self.attr1.SetBackgroundColour((230, 230, 230))
+        self.attr2 = wx.ListItemAttr()
+        self.attr2.SetBackgroundColour("light blue")
+        #self.attrselected = wx.ListItemAttr()
+        #self.attrselected.SetBackgroundColour("red")
+        self.SetListFont()
+        self.selected = {}
+        i = 0
+        for name in ['Categories'] + self.first :
+            self.InsertColumn(i,name,wx.LIST_FORMAT_LEFT)
+            i += 1
+        self.itemDataMap = self.dlist
+        self.itemIndexMap = list(self.dlist.keys())
+        self.SetItemCount(len(self.dlist))
+        listmix.ListCtrlAutoWidthMixin.__init__(self)
+        listmix.ColumnSorterMixin.__init__(self, len(self.first) + 1)
+
+        #self.SortListItems(1, False)
+        self.SetColumnWidth(0, 300)
+        self.SetColumnWidth(1, wx.LIST_AUTOSIZE)
+
+        self.Bind(wx.EVT_LIST_BEGIN_DRAG, self.StartDrag)
+        self.Bind(wx.EVT_LIST_ITEM_FOCUSED, self.ShowWords)
+        self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnBeginEdit)
+        self.Bind(wx.EVT_LIST_END_LABEL_EDIT, self.OnEndEdit)
+        self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected)
+        self.Bind(wx.EVT_LIST_COL_CLICK, self.OnSortColumn)
+
+        if self.GetItemCount() != 0 :
+            #self.SetItemState(0, wx.LIST_STATE_SELECTED, wx.LIST_STATE_SELECTED)
+            self.Select(0, on=1)
+
+        dt = MyListDropCate(self)
+        self.SetDropTarget(dt)
+
+    def OnSortColumn(self, evt) :
+        print(self.currentItem)
+        evt.Skip()
+
+    def SetListFont(self) :
+        self.SetFont(wx.Font(16, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL))
+
+    def OnGetItemImage(self, item):
+        return self.p_idx
+
+    def OnBeginEdit(self, event) :
+        self.EditLabel(event.GetIndex())
+        event.Skip()
+
+    def OnEndEdit(self, event) :
+        newlabel = event.GetLabel()
+        idx = event.GetIndex()
+        oldlabel = self.GetItemText(idx)
+        if newlabel not in self.cate.cate['CATE'] :
+            self.cate.cate['CATE'][newlabel] = self.cate.cate['CATE'][oldlabel]
+            del(self.cate.cate['CATE'][oldlabel])
+        self.RefreshData(self.cate.getcate())
+
+    def ShowWords(self, event) :
+        index = event.GetIndex()
+        try :
+            data = self.cate.getcatewords(self.GetItemText(index))
+            self.parent.m_listCateWords.RefreshData(data)
+            self.parent.m_listCateWords.SetSelection(0)
+        except :
+            pass
+        event.Skip()
+
+    def RefreshData(self, data):
+        try :
+            item = self.currentItem
+        except :
+            item = 0
+        self.itemDataMap = data
+        self.itemIndexMap = list(data.keys())
+        self.SetItemCount(len(data))
+        order = self._colSortFlag[self._col]
+        self.SortListItems(self._col, order)
+        #self.SetColumnWidth(0, wx.LIST_AUTOSIZE)
+        #self.SetColumnWidth(1, wx.LIST_AUTOSIZE)
+        #self.SetColumnWidth(0,300)
+        self.parent.OnStat()
+        self.Refresh()
+        try :
+            self.SetSelection(item)
+            self.Focus(item)
+        except :
+            pass
+
+    def GetListCtrl(self):
+        return self
+
+    def GetSortImages(self):
+        return (self.sm_dn, self.sm_up)
+
+    def SortItems(self, sorter=None):
+        try :
+            select = self.currentItem
+            word = self.GetItemData(select)[0]
+        except Exception as e: print('word',e)
+
+        listTemp = sorted(self.itemDataMap.items(),
+            key=lambda x:x[1][self._col], reverse= (self._colSortFlag[self._col]!=True))
+        dlist = dict([[line[0],line[1]] for line in listTemp])
+        self.itemDataMap = dlist
+        self.itemIndexMap = list(dlist.keys())
+        self.Refresh() # redraw the list
+        try :
+            formes = [self.getColumnText(i, 0) for i in range(self.GetItemCount())]
+            idx = [i for i, val in enumerate(formes) if val == word][0]
+            self.SetSelection(idx)
+            self.Focus(idx)
+        except Exception as e: print(e)
+
+    def OnGetItemText(self, item, col):
+        index=self.itemIndexMap[item]
+        s = self.itemDataMap[index][col]
+        if isinstance(s, (int, float)):
+            return str(s)
+        else:
+            return s #modification pour python 3
+
+    def OnGetItemAttr(self, item):
+#        if self.IsSelected(index) == True :
+#            print('selected', index)
+        index=self.itemIndexMap[item]
+        if item % 2 :
+           return self.attr1
+        else :
+           return self.attr2
+
+    def getselectedwords(self) :
+        words = [self.getColumnText(self.GetFirstSelected(), 0)]
+        last = self.GetFirstSelected()
+        while self.GetNextSelected(last) != -1:
+            last = self.GetNextSelected(last)
+            words.append(self.getColumnText(last, 0))
+        return words
+
+    def GetString(self):
+        return self.getselectedwords()[0]
+
+    def GetSelections(self):
+        return self.getselectedwords()
+
+    def getColumnText(self, index, col):
+        item = self.GetItem(index, col)
+        return item.GetText()
+
+    def GetItemData(self, item) :
+        index=self.itemIndexMap[item]
+        s = self.itemDataMap[index]
+        return s
+
+    def OnItemSelected(self, event):
+        self.currentItem = event.GetIndex() #event.m_itemIndex
+        event.Skip()
+
+    def SetSelection(self, index) :
+        for i in range(0, self.GetItemCount(), 1) :
+            self.Select(i, on=0)
+        self.Select(index, on=1)
+
+    def GetItemInfo(self, idx):
+        """
+        Collect all relevant data of a listitem, and put it in a list.
+        """
+
+        l = []
+        l.append(idx) # We need the original index, so it is easier to eventualy delete it.
+        l.append(self.GetItemData(idx)) # Itemdata.
+        l.append(self.GetItemText(idx)) # Text first column.
+        for i in range(1, self.GetColumnCount()): # Possible extra columns.
+            l.append(self.GetItem(idx, i).GetText())
+        l.append('cate')
+        return l
+
+
+    def StartDrag(self, event):
+        """
+        Put together a data object for drag-and-drop _from_ this list.
+        """
+
+        l = []
+        idx = -1
+        while True: # Find all the selected items and put them in a list.
+            idx = self.GetNextItem(idx, wx.LIST_NEXT_ALL, wx.LIST_STATE_SELECTED)
+            if idx == -1:
+                break
+            l.append(self.GetItemInfo(idx))
+
+        # Pickle the items list.
+        itemdata = pickle.dumps(l, 1)
+        # Create our own data format and use it
+        # in a Custom data object.
+        ldata = wx.CustomDataObject("ListCtrlItems")
+        ldata.SetData(itemdata)
+        # Now make a data object for the  item list.
+        data = wx.DataObjectComposite()
+        data.Add(ldata)
+
+        # Create drop source and begin drag-and-drop.
+        dropSource = wx.DropSource(self)
+        dropSource.SetData(data)
+        res = dropSource.DoDragDrop(flags=wx.Drag_DefaultMove)
+
+        # If move, we want to remove the item from this list.
+        if res == wx.DragMove and l[0][-1] != 'cate' :
+            # It's possible we are dragging/dropping from this list to this list.
+            # In which case, the index we are removing may have changed...
+
+            # Find correct position.
+            l.reverse() # Delete all the items, starting with the last item.
+            for i in l:
+                pos = self.FindItem(i[0], i[2])
+                self.DeleteItem(pos)
+
+
+    def Insert(self, x, y, seq):
+        """
+        Insert text at given x, y coordinates --- used with drag-and-drop.
+        """
+
+        # Find insertion point.
+        index, flags = self.HitTest((x, y))
+
+        if index == wx.NOT_FOUND: # Not clicked on an item.
+            if flags & (wx.LIST_HITTEST_NOWHERE|wx.LIST_HITTEST_ABOVE|wx.LIST_HITTEST_BELOW): # Empty list or below last item.
+                index = self.GetItemCount() # Append to end of list.
+            elif self.GetItemCount() > 0:
+                if y <= self.GetItemRect(0).y: # Clicked just above first item.
+                    index = -1 # Append to top of list.
+                else:
+                    index = self.GetItemCount() + 1 # Append to end of list.
+        else: # Clicked on an item.
+            # Get bounding rectangle for the item the user is dropping over.
+            rect = self.GetItemRect(index)
+
+            # If the user is dropping into the lower half of the rect,
+            # we want to insert _after_ this item.
+            # Correct for the fact that there may be a heading involved.
+            #if y > rect.y - self.GetItemRect(0).y + rect.height/2:
+            #    index += 1
+        print('Insert de ListForCate', index, flags)
+        word, eff = seq[0][1]
+        if seq[0][-1] == 'words' :
+            if index < self.GetItemCount() and index != -1 :
+                for val in seq :
+                    word, eff = val[1]
+                    self.cate.addwordincate(self.GetItemData(index)[0], word, eff)
+            else :
+                index = self.GetItemCount()
+                if self.cate.addcatefromwordtocate(word, eff) :
+                    pass
+                else :
+                    dial = wx.MessageDialog(self, "This category name is already used", style=wx.OK|wx.CENTRE).ShowModal()
+            self.dlist = self.cate.getcate()
+            self.RefreshData(self.dlist)
+            self.parent.m_listToCate.RefreshData(self.cate.getwordstocate())
+            self.parent.m_listCateWords.RefreshData(self.parent.cate.getcatewords(self.GetItemData(index)[0]))
+            for i in range(0, self.GetItemCount(), 1):
+                self.Select(i, on=0)
+            self.Select(index, on=1)
+            self.parent.butsave.SetBackgroundColour((255,0,0,255))
+        if seq[0][-1] == 'catewords' :
+            if index < self.GetItemCount() and index != -1 :
+                for val in seq :
+                    word, eff = val[1]
+                    if word not in self.cate.cate['CATE'][self.GetItemData(index)[0]][1] :
+                        self.cate.changewordcate(self.GetItemData(index)[0], word, eff)
+                        self.parent.butsave.SetBackgroundColour((255,0,0,255))
+            else :
+                index = self.GetItemCount()
+                if self.cate.addcatefromwordcate(word, eff) :
+                    self.parent.butsave.SetBackgroundColour((255,0,0,255))
+                else :
+                    dial = wx.MessageDialog(self, "This category name is already used", style=wx.OK|wx.CENTRE).ShowModal()
+                #self.cate.addwordincate(self.GetItemData(index)[0], word, eff)
+            self.dlist = self.cate.getcate()
+            self.RefreshData(self.dlist)
+            self.parent.m_listToCate.RefreshData(self.cate.getwordstocate())
+            #self.parent.m_listCateWords.RefreshData(self.parent.cate.getcatewords(self.GetItemData(index)[0]))
+            self.parent.m_listCateWords.RefreshData(self.parent.cate.getcatewords(self.GetItemData(self.currentItem)[0]))
+            #self.SetSelection(index)
+
+
+
+#        for i in seq: # Insert the item data.
+#            idx = self.InsertItem(index, i[2])
+#            self.SetItemData(idx, i[1])
+#            for j in range(1, self.GetColumnCount()):
+#                try: # Target list can have more columns than source.
+#                    self.SetItem(idx, j, i[2+j])
+#                except:
+#                    pass # Ignore the extra columns.
+#            index += 1
+
+class ListForWords(ListForCate) :
+    def __init__(self, parent, dlist = {}, first = []):
+        wx.ListCtrl.__init__( self, parent, -1, style=wx.LC_REPORT|wx.LC_VIRTUAL|wx.LC_HRULES|wx.LC_VRULES)
+        self.parent=parent
+        self.cate = self.parent.cate
+        self.dlist= self.cate.getwordstocate()
+        self.first = first
+        self.il = wx.ImageList(16, 16)
+        a={"sm_up":"GO_UP","sm_dn":"GO_DOWN","w_idx":"WARNING","e_idx":"ERROR","i_idx":"QUESTION"}
+        for k,v in list(a.items()):
+            s="self.%s= self.il.Add(wx.ArtProvider.GetBitmap(wx.ART_%s,wx.ART_TOOLBAR,(16,16)))" % (k,v)
+            exec(s)
+        self.SetImageList(self.il, wx.IMAGE_LIST_SMALL)
+        self.attr1 = wx.ListItemAttr()
+        self.attr1.SetBackgroundColour((230, 230, 230))
+        self.attr2 = wx.ListItemAttr()
+        self.attr2.SetBackgroundColour("light blue")
+        #self.attrselected = wx.ListItemAttr()
+        #self.attrselected.SetBackgroundColour("red")
+        self.SetListFont()
+        self.selected = {}
+        i = 0
+        for name in ['To categorize'] + self.first :
+            self.InsertColumn(i,name,wx.LIST_FORMAT_LEFT)
+            i += 1
+        self.itemDataMap = self.dlist
+        self.itemIndexMap = list(self.dlist.keys())
+        self.SetItemCount(len(self.dlist))
+        listmix.ListCtrlAutoWidthMixin.__init__(self)
+        listmix.ColumnSorterMixin.__init__(self, len(self.first) + 1)
+        self.SetColumnWidth(0, 400)
+        self.SetColumnWidth(1, wx.LIST_AUTOSIZE)
+
+        self.SortListItems(1, False)
+
+        self.Bind(wx.EVT_LIST_BEGIN_DRAG, self.StartDrag)
+        self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnDClick)
+        self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected)
+
+        dt = MyListDropCate(self)
+        self.SetDropTarget(dt)
+
+    def OnDClick(self, event) :
+        idx = event.GetIndex()
+        event.Skip()
+
+    def OnItemSelected(self, event):
+        self.currentItem = event.GetIndex() #event.m_itemIndex
+        event.Skip()
+
+    def OnGetItemImage(self, item):
+        return self.i_idx
+
+    def GetItemInfo(self, idx):
+        """
+        Collect all relevant data of a listitem, and put it in a list.
+        """
+
+        l = []
+        l.append(idx) # We need the original index, so it is easier to eventualy delete it.
+        l.append(self.GetItemData(idx)) # Itemdata.
+        l.append(self.GetItemText(idx)) # Text first column.
+        for i in range(1, self.GetColumnCount()): # Possible extra columns.
+            l.append(self.GetItem(idx, i).GetText())
+        l.append('words')
+        return l
+
+
+    def StartDrag(self, event):
+        """
+        Put together a data object for drag-and-drop _from_ this list.
+        """
+
+        l = []
+        idx = -1
+        while True: # Find all the selected items and put them in a list.
+            idx = self.GetNextItem(idx, wx.LIST_NEXT_ALL, wx.LIST_STATE_SELECTED)
+            if idx == -1:
+                break
+            l.append(self.GetItemInfo(idx))
+
+        # Pickle the items list.
+        itemdata = pickle.dumps(l, 1)
+        # Create our own data format and use it
+        # in a Custom data object.
+        ldata = wx.CustomDataObject("ListCtrlItems")
+        ldata.SetData(itemdata)
+        # Now make a data object for the  item list.
+        data = wx.DataObjectComposite()
+        data.Add(ldata)
+
+        # Create drop source and begin drag-and-drop.
+        dropSource = wx.DropSource(self)
+        dropSource.SetData(data)
+        res = dropSource.DoDragDrop(flags=wx.Drag_DefaultMove)
+
+
+        # If move, we want to remove the item from this list.
+        if res == wx.DragMove and l[0][-1] != 'words':
+            # It's possible we are dragging/dropping from this list to this list.
+            # In which case, the index we are removing may have changed...
+
+            # Find correct position.
+            l.reverse() # Delete all the items, starting with the last item.
+            for i in l:
+                pos = self.FindItem(i[0], i[2])
+                print('detruit : ',pos)
+                self.DeleteItem(pos)
+
+
+    def Insert(self, x, y, seq):
+        """
+        Insert text at given x, y coordinates --- used with drag-and-drop.
+        """
+
+        # Find insertion point.
+        index, flags = self.HitTest((x, y))
+
+        if index == wx.NOT_FOUND: # Not clicked on an item.
+            if flags & (wx.LIST_HITTEST_NOWHERE|wx.LIST_HITTEST_ABOVE|wx.LIST_HITTEST_BELOW): # Empty list or below last item.
+                index = self.GetItemCount() # Append to end of list.
+            elif self.GetItemCount() > 0:
+                if y <= self.GetItemRect(0).y: # Clicked just above first item.
+                    index = 0 # Append to top of list.
+                else:
+                    index = self.GetItemCount() + 1 # Append to end of list.
+        else: # Clicked on an item.
+            # Get bounding rectangle for the item the user is dropping over.
+            rect = self.GetItemRect(index)
+
+            # If the user is dropping into the lower half of the rect,
+            # we want to insert _after_ this item.
+            # Correct for the fact that there may be a heading involved.
+            if y > rect.y - self.GetItemRect(0).y + rect.height/2:
+                index += 1
+        word, eff = seq[0][1]
+        if seq[0][-1] == 'catewords' :
+            for val in seq :
+                word, eff = val[1]
+                categorie = self.cate.findcatefromword(word)
+                self.cate.addwordinwords(categorie, word, eff)
+            self.RefreshData(self.cate.getwordstocate())
+            self.parent.m_listCate.RefreshData(self.cate.getcate())
+            self.parent.m_listCateWords.RefreshData(self.cate.getcatewords(categorie))
+            self.parent.butsave.SetBackgroundColour((255,0,0,255))
+        elif seq[0][-1] == 'cate' :
+            categorie = seq[0][1][0]
+            self.cate.delcate(categorie)
+            self.RefreshData(self.cate.getwordstocate())
+            self.parent.m_listCate.RefreshData(self.cate.getcate())
+            self.parent.m_listCate.SetSelection(0)
+            self.parent.m_listCateWords.RefreshData(self.cate.getcatewords(self.parent.m_listCate.GetItemText(0)))
+            self.parent.butsave.SetBackgroundColour((255,0,0,255))
+
+
+class ListForCateWords(ListForCate) :
+    def __init__(self, parent, dlist = {}, first = []):
+        wx.ListCtrl.__init__( self, parent, -1, style=wx.LC_REPORT|wx.LC_VIRTUAL|wx.LC_HRULES|wx.LC_VRULES)
+        self.parent=parent
+        self.cate = self.parent.cate
+        self.dlist= {}
+        self.first = first
+        self.il = wx.ImageList(16, 16)
+        a={"sm_up":"GO_UP","sm_dn":"GO_DOWN","p_idx":"TIP","e_idx":"ERROR","i_idx":"QUESTION"}
+        for k,v in list(a.items()):
+            s="self.%s= self.il.Add(wx.ArtProvider.GetBitmap(wx.ART_%s,wx.ART_TOOLBAR,(16,16)))" % (k,v)
+            exec(s)
+        self.SetImageList(self.il, wx.IMAGE_LIST_SMALL)
+        self.attr1 = wx.ListItemAttr()
+        self.attr1.SetBackgroundColour((230, 230, 230))
+        self.attr2 = wx.ListItemAttr()
+        self.attr2.SetBackgroundColour("light blue")
+        #self.attrselected = wx.ListItemAttr()
+        #self.attrselected.SetBackgroundColour("red")
+        self.SetListFont()
+        self.selected = {}
+        i = 0
+        for name in ['Contents'] + self.first :
+            self.InsertColumn(i,name,wx.LIST_FORMAT_LEFT)
+            i += 1
+        self.itemDataMap = self.dlist
+        self.itemIndexMap = list(self.dlist.keys())
+        self.SetItemCount(len(self.dlist))
+        listmix.ListCtrlAutoWidthMixin.__init__(self)
+        listmix.ColumnSorterMixin.__init__(self, len(self.first) + 1)
+        self.SetColumnWidth(0, 300)
+        self.SetColumnWidth(1, wx.LIST_AUTOSIZE)
+
+        self.SortListItems(1, False)
+
+        self.Bind(wx.EVT_LIST_BEGIN_DRAG, self.StartDrag)
+        self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected)
+
+        dt = MyListDropCate(self)
+        self.SetDropTarget(dt)
+
+    def OnItemSelected(self, event):
+        self.currentItem = event.GetIndex() #event.m_itemIndex
+        event.Skip()
+
+
+    def GetItemInfo(self, idx):
+        """
+        Collect all relevant data of a listitem, and put it in a list.
+        """
+
+        l = []
+        l.append(idx) # We need the original index, so it is easier to eventualy delete it.
+        l.append(self.GetItemData(idx)) # Itemdata.
+        l.append(self.GetItemText(idx)) # Text first column.
+        for i in range(1, self.GetColumnCount()): # Possible extra columns.
+            l.append(self.GetItem(idx, i).GetText())
+        l.append('catewords')
+        return l
+
+
+    def StartDrag(self, event):
+        """
+        Put together a data object for drag-and-drop _from_ this list.
+        """
+
+        l = []
+        idx = -1
+        while True: # Find all the selected items and put them in a list.
+            idx = self.GetNextItem(idx, wx.LIST_NEXT_ALL, wx.LIST_STATE_SELECTED)
+            if idx == -1:
+                break
+            l.append(self.GetItemInfo(idx))
+
+        # Pickle the items list.
+        itemdata = pickle.dumps(l, 1)
+        # Create our own data format and use it
+        # in a Custom data object.
+        ldata = wx.CustomDataObject("ListCtrlItems")
+        ldata.SetData(itemdata)
+        # Now make a data object for the  item list.
+        data = wx.DataObjectComposite()
+        data.Add(ldata)
+
+        # Create drop source and begin drag-and-drop.
+        dropSource = wx.DropSource(self)
+        dropSource.SetData(data)
+        res = dropSource.DoDragDrop(flags=wx.Drag_DefaultMove)
+        print('current')
+        print(self.parent.m_listCate.currentItem)
+
+        # If move, we want to remove the item from this list.
+        #if res == wx.DragMove:
+        #    # It's possible we are dragging/dropping from this list to this list.
+        #    # In which case, the index we are removing may have changed...
+
+        #    # Find correct position.
+        #    l.reverse() # Delete all the items, starting with the last item.
+        #    for i in l:
+        #        pos = self.FindItem(i[0], i[2])
+        #        self.DeleteItem(pos)
+
+
+    def Insert(self, x, y, seq):
+        """
+        Insert text at given x, y coordinates --- used with drag-and-drop.
+        """
+        pass
+        # Find insertion point.
+        index, flags = self.HitTest((x, y))
+#
+#        if index == wx.NOT_FOUND: # Not clicked on an item.
+#            if flags & (wx.LIST_HITTEST_NOWHERE|wx.LIST_HITTEST_ABOVE|wx.LIST_HITTEST_BELOW): # Empty list or below last item.
+#                index = self.GetItemCount() # Append to end of list.
+#            elif self.GetItemCount() > 0:
+#                if y <= self.GetItemRect(0).y: # Clicked just above first item.
+#                    index = 0 # Append to top of list.
+#                else:
+#                    index = self.GetItemCount() + 1 # Append to end of list.
+#        else: # Clicked on an item.
+#            # Get bounding rectangle for the item the user is dropping over.
+#            rect = self.GetItemRect(index)
+#
+#            # If the user is dropping into the lower half of the rect,
+#            # we want to insert _after_ this item.
+#            # Correct for the fact that there may be a heading involved.
+#            if y > rect.y - self.GetItemRect(0).y + rect.height/2:
+#                index += 1
+        print('Insert de ListForCateWords', index,flags)
+        if seq[0][-1] == 'words' :
+            for val in seq :
+                word, eff = val[1]
+                categorie = self.parent.m_listCate.getColumnText(self.parent.m_listCate.GetFirstSelected(),0)
+                self.cate.addwordincate(categorie, word, eff)
+            self.dlist = self.cate.getwordstocate()
+            self.RefreshData(self.cate.getcatewords(categorie))
+            self.parent.m_listCate.RefreshData(self.cate.getcate())
+            self.parent.m_listToCate.RefreshData(self.dlist)
+            self.parent.butsave.SetBackgroundColour((255,0,0,255))
+
+
+class MyListDropCate(wx.DropTarget):
+    """
+    Drop target for simple lists.
+    """
+    def __init__(self, source):
+        """
+        Arguments:
+        source: source listctrl.
+        """
+        wx.DropTarget.__init__(self)
+
+        #------------
+
+        self.dv = source
+
+        #------------
+
+        # Specify the type of data we will accept.
+        self.data = wx.CustomDataObject("ListCtrlItems")
+        self.SetDataObject(self.data)
+
+    #-----------------------------------------------------------------------
+
+    # Called when OnDrop returns True.
+    # We need to get the data and do something with it.
+    def OnData(self, x, y, d):
+        """
+        ...
+        """
+
+        # Copy the data from the drag source to our data object.
+        if self.GetData():
+            # Convert it back to a list and give it to the viewer.
+            ldata = self.data.GetData()
+            l = pickle.loads(ldata)
+            self.dv.Insert(x, y, l)
+
+        # What is returned signals the source what to do
+        # with the original data (move, copy, etc.)  In this
+        # case we just return the suggested value given to us.
+        return d
index a18fbc5..da8fbae 100755 (executable)
@@ -117,7 +117,9 @@ class History :
         self.read()
 
     def read(self) :
-        d = shelve.open(self.filein)
+        with open(self.filein, 'r') as fjson :
+            d = json.load(fjson)
+#        d = shelve.open(self.filein, protocol=1)
         self.history = d.get('history', [])
         self.matrix = d.get('matrix', [])
         self.ordercorpus = dict([[corpus['uuid'], i] for i, corpus in enumerate(self.history)])
@@ -125,13 +127,16 @@ class History :
         self.analyses = dict([[analyse['uuid'], analyse] for corpus in self.history for analyse in corpus.get('analyses', [])])
         self.matrixanalyse = dict([[mat['uuid'], mat] for mat in self.matrix])
         self.ordermatrix = dict([[matrix['uuid'], i] for i, matrix in enumerate(self.matrix)])
-        d.close()
+#        d.close()
 
     def write(self) :
-        d = shelve.open(self.filein)
+        d = {}
         d['history'] = self.history
         d['matrix'] = self.matrix
-        d.close()
+        with open(self.filein, 'w') as f :
+            f.write(json.dumps(d, indent=4, default=str))
+       #d = shelve.open(self.filein, protocol=1)
+       #d.close()
 
     def add(self, analyse) :
         log.info('add to history %s' % analyse.get('corpus_name', 'pas un corpus'))
index 2938c88..2bec72a 100755 (executable)
@@ -56,6 +56,7 @@ from tabfrequence import Frequences, FreqMultiple
 from tableau import Tableau
 from tabrsimple import InputText
 from tabsimi import DoSimi
+from tabcatego import Categorisation
 from tabsplitvar import SplitMatrixFromVar
 from tabverges import Prototypical
 from textaslexico import Lexico
@@ -93,6 +94,7 @@ ID_CHECKCORPUS = wx.Window.NewControlId()
 ID_Tabcontent = wx.Window.NewControlId()
 ID_AFCM = wx.Window.NewControlId()
 ID_SIMI = wx.Window.NewControlId()
+ID_CATE = wx.Window.NewControlId()
 ID_CloseTab = wx.Window.NewControlId()
 ID_SaveTab = wx.Window.NewControlId()
 ID_CreateText = wx.Window.NewControlId()
@@ -217,7 +219,8 @@ images_analyses = {
         'preferences' : 'preferences.png',
         'exportmetatable' : 'exportmetatable.png',
         'importdmi' : 'twitter.png',
-        'labbe' : 'spec.png'
+        'labbe' : 'spec.png',
+        'categorisation' : 'spec.png',
          }
 
 
@@ -236,6 +239,8 @@ class IraFrame(wx.Frame):
         log.info('Starting Iramuteq... ' )
         log.info('version : %s' % ConfigGlob.get('DEFAULT', 'version'))
         wx.Frame.__init__(self, parent, id, title, pos, size, style)
+        #Font
+        self.SetFont(wx.Font(12, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL))
         # configuration
         self.AppliPath = AppliPath
         self.images_path = os.path.join(AppliPath,'images')
@@ -351,6 +356,7 @@ class IraFrame(wx.Frame):
                        [ID_SIMI, _("Similarities Analysis"), 'simimatrix'],
                        [ID_proto, _("Prototypical Analysis"), 'proto'],
                        [ID_Splitfromvar, _("Split from variable"), 'subcorpusmeta'],
+                       [ID_CATE, _("ElCaTeGoRiZatoR"), 'categorisation'],
                       ]
         for analyse in matanalyses :
             if not isinstance(analyse, dict) :
@@ -488,10 +494,10 @@ class IraFrame(wx.Frame):
         #------------------------------------------------------------------------------------------------
         # fichier d'historique de Iramuteq
         #------------------------------------------------------------------------------------------------
-        #if not os.path.exists(os.path.join(UserConfigPath, 'history.db')) :
-        #    with open(os.path.join(UserConfigPath, 'history.db'), 'w') as f :
-        #        f.write('')
-        self.history = History(os.path.join(UserConfigPath, 'historyIramuteq'))
+        if not os.path.exists(os.path.join(UserConfigPath, 'history.db')) :
+            with open(os.path.join(UserConfigPath, 'history.db'), 'w') as f :
+                f.write('{}')
+        self.history = History(os.path.join(UserConfigPath, 'history.db'))
         # l'extension ".db" est ajoutée automatiquement par le module
 
         #------------------------------------------------------------------------------------------------
@@ -504,7 +510,7 @@ class IraFrame(wx.Frame):
             Name("lefttree").
             Caption(_("Historic")).
             Left().
-            MinSize(wx.Size(200,500)).
+            MinSize(wx.Size(300,400)).
             Layer(1).
             Position(1).
             CloseButton(False).
@@ -602,6 +608,7 @@ class IraFrame(wx.Frame):
         self.Bind(wx.EVT_MENU, self.OnAFCM, id=ID_AFCM)
         self.Bind(wx.EVT_MENU, self.OnProto, id=ID_proto)
         self.Bind(wx.EVT_MENU, self.OnSplitVar, id = ID_Splitfromvar)
+        self.Bind(wx.EVT_MENU, self.OnCategorisation, id = ID_CATE)
         #self.Bind(wx.EVT_MENU, self.OnRCode, id=ID_RCODE) #???
         #self.Bind(wx.EVT_MENU, self.OnSplitVar, id=ID_SPLITVAR) #???
         #self.Bind(wx.EVT_MENU, self.OnCheckcorpus, id = ID_CHECKCORPUS) #???
@@ -1007,6 +1014,10 @@ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, États-Unis."""
     def OnSimiTab(self, event, matrix = None):
         self.analyse_matrix(DoSimi, matrix = matrix, analyse_type = 'simimatrix', dlgnb = 5)
 
+    def OnCategorisation(self, event, matrix = None) :
+        self.analyse_matrix(Categorisation, matrix = matrix, analyse_type = 'categorisation', dlgnb = 1)
+
+
     def OnCHDReinert(self, event, matrix = None):
         #if matrix is None :
         #    matrix = self.tree.getmatrix()
index 5fd493c..19a53af 100644 (file)
--- a/layout.py
+++ b/layout.py
@@ -38,6 +38,7 @@ from PrintRScript import write_afc_graph, print_simi3d, PrintSimiScript
 from profile_segment import ProfileSegment
 from listlex import *
 from Liste import *
+from elcategorizator import ElCategorizator
 from search_tools import SearchFrame
 from dialog import PrefGraph, PrefExport, PrefSimpleFile, PrefDendro, SimpleDialog, ImageViewer
 from guifunct import SelectColumn, PrepSimi, PrefSimi, redosimi
@@ -1397,6 +1398,11 @@ class ProtoLayout(DefaultMatLayout) :
         #self.ira.nb.SetSelection(self.ira.nb.GetPageCount() - 1)
         #self.ira.ShowAPane("Tab_content")
 
+class CateLayout(DefaultMatLayout) :
+
+    def dolayout(self) :
+        TabCate = ElCategorizator(self.ira.nb, self.pathout, self.tableau)
+        self.ira.nb.AddPage(TabCate, ' - '.join([_('ElCaTeGoRiZaToR'), self.parametres['name']]))
 
 class SimiMatLayout(DefaultMatLayout) :
 
index e894bee..873f4b3 100644 (file)
@@ -14,7 +14,7 @@ import logging
 # import des fichiers du projet
 #------------------------------------
 from chemins import ChdTxtPathOut, StatTxtPathOut, PathOut
-from layout import OpenCHDS, dolexlayout, StatLayout, WordCloudLayout, OpenCorpus, SimiLayout, SimiMatLayout, ProtoLayout, MatLayout, FreqLayout, Chi2Layout, LabbeLayout
+from layout import OpenCHDS, dolexlayout, StatLayout, WordCloudLayout, OpenCorpus, SimiLayout, SimiMatLayout, ProtoLayout, MatLayout, FreqLayout, Chi2Layout, LabbeLayout, CateLayout
 from corpus import Corpus, copycorpus
 from tableau import Tableau
 from functions import DoConf, ReadDicoAsDico
@@ -181,3 +181,6 @@ class OpenAnalyse():
             FreqLayout(self.parent, corpus, self.conf)
         elif self.conf['type'] == 'chi2' or self.conf['type'] == 'chi2mcnemar':
             Chi2Layout(self.parent, corpus, self.conf)
+        elif self.conf['type'] == 'categorisation' :
+            CateLayout(self.parent, corpus, self.conf)
+            print(self.conf)
index 032b395..7325279 100644 (file)
@@ -173,7 +173,6 @@ class Tableau() :
             self.read_ods()
         self.parametres['csvfile'] = os.path.join(self.parametres['pathout'], 'csvfile.csv')
         self.make_tmpfile()
-        print(self.parametres)
         DoConf().makeoptions(['matrix'],[self.parametres], self.parametres['ira'])
         self.parent.history.addMatrix(self.parametres)
 
@@ -181,7 +180,7 @@ class Tableau() :
         self.parametres['csvfile'] = os.path.join(self.parametres['pathout'], 'csvfile.csv')
         self.make_tmpfile()
         DoConf().makeoptions(['matrix'],[self.parametres], self.parametres['ira'])
-        self.parent.history.addMatrix(self.parametres)        
+        self.parent.history.addMatrix(self.parametres)
 
     def read_xls(self) :
         #FIXME : encodage
@@ -207,7 +206,7 @@ class Tableau() :
 
     def read_csv(self) :
         with codecs.open(self.parametres['originalpath'], 'r', self.parametres['encodage']) as f :
-            content = f.read() 
+            content = f.read()
         self.linecontent = [line.split(self.parametres['colsep']) for line in content.splitlines()]
         self.linecontent = [[val.replace('"','').replace(';',' ').replace('\t', ' ').strip() for val in line] for line in self.linecontent]
 
@@ -234,7 +233,7 @@ class Tableau() :
         else :
             self.rownames = [repr(i) for i in range(self.rownb)]
             self.idname = 'identifiant'
-        self.csvtable = [[self.idname] + self.colnames] + [[self.rownames[i]] + self.linecontent[i] for i in range(len(self.rownames))] 
+        self.csvtable = [[self.idname] + self.colnames] + [[self.rownames[i]] + self.linecontent[i] for i in range(len(self.rownames))]
         self.write_csvfile()
 
     def read_csvfile(self):
@@ -287,10 +286,9 @@ class Tableau() :
     def getactlistfromselection(self, listact) :
         selcol = self.select_col(listact)
         self.actives = self.make_dico(selcol)
-        return [[val, self.actives[val][0]] for val in self.actives]       
+        return [[val, self.actives[val][0]] for val in self.actives]
 
     def make_listactives(self) :
-        print(self.actives, self.parametres['mineff'])
         self.listactives = [val for val in self.actives if val != 'NA' and self.actives[val][0] >= self.parametres['mineff']]
 
     def write01(self, fileout, dico, linecontent) :
@@ -300,7 +298,7 @@ class Tableau() :
         for i, forme in enumerate(self.listactives) :
             for line in dico[forme][1] :
                 out[line][i] = '1'
-        #out = [[self.rownames[i]] + out[i] for i in range(len(linecontent))] 
+        #out = [[self.rownames[i]] + out[i] for i in range(len(linecontent))]
         #out.insert(0,[self.idname] + self.listactives)
         out.insert(0, self.listactives)
         with open(fileout, 'w') as f :
@@ -321,7 +319,7 @@ class Tableau() :
                     if forme[0] == '*':
                         UpdateDico(self.sups, forme, i)
                     else:
-                        UpdateDico(self.actives, forme, i)        
+                        UpdateDico(self.actives, forme, i)
         self.listactives = [val for val in self.actives if self.actives[val][0] >= self.parametres['mineff']]
         table = [['0' for i in range(len(self.listactives))] for j in range(self.rownb)]
         for i, val in enumerate(self.listactives) :
@@ -378,9 +376,9 @@ class Tableau() :
                         if sup in self.linecontent[uce]:
                             line[i + 1] += 1
             tablecontet.append([line[0]] + [repr(don) for don in line if type(don) == type(1)])
-            
+
         self.printtable(self.pathout['ContEtOut'], tablecontet)
-        self.printtable(self.pathout['Contout'], tablecont)        
+        self.printtable(self.pathout['Contout'], tablecont)
 
     def get_colnames(self) :
         return self.colnames[:]