# -*- coding: iso-8859-1 -*- # Copyright 20003 - 2008: Julien Bourdaillet (julien.bourdaillet@lip6.fr), Jean-Gabriel Ganascia (jean-gabriel.ganascia@lip6.fr) # This file is part of MEDITE. # # MEDITE is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # MEDITE is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Foobar; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA import MediteAppli.synthetic #import scipy from matplotlib.numerix import arange import matplotlib.numerix.random_array #import pytz.zoneinfo.UTC import matplotlib #import Numeric import numpy.oldnumeric as Numeric # uncomment the following to use wx rather than wxagg #matplotlib.use('WX') #from matplotlib.backends.backend_wx import FigureCanvasWx as FigureCanvas # comment out the following to use wx rather than wxagg matplotlib.use('WXAgg') from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas from matplotlib.backends.backend_wxagg import NavigationToolbar2WxAgg from matplotlib.backends.backend_wx import _load_bitmap from matplotlib.figure import Figure from matplotlib.numerix.mlab import rand from matplotlib.patches import Rectangle from matplotlib.axes import Axes import wx #from wxPython.wx import * from pylab import connect class ColorManager(MediteAppli.synthetic.ListManager): """ Classe centralisant la gestion de la liste de opération génétiques utilisées """ def __init__(self,length=None): self._liste = ['blue', 'green', 'red', 'cyan', 'magenta', 'yellow', '#abbbcc', '#fbccdd', '#bcddee', '#edeeff', '#aeffaa', '#ffaabb', '#bcbbaa', '#edccbb', '#aeddcc'] if length != None: self._liste = self._liste[:length] class FMPanel(wx.Panel): """ Panel générique """ def __init__(self, frame, fm): """ Constructeur pre: isinstance(fm,MediteAppli.synthetic.FrequencyMatrix) """ wx.Panel.__init__(self,frame) self.fm = fm self.tm = fm.getItemLegend() self.cm = ColorManager() self.potm = fm.getGraphLegend() def param(self): self.title = "" def debutInitFMPanel(self): self.param() self.figure = Figure(figsize=(300,300), dpi=65) #figure sur laquelle on dessine self.figure.text(0.05,0.95,self.title) self.axes = {} # ensemble des graphiques de la figure self.handles=[] #liste des rectanlges nécessaires pour la légende def finInitFMPanel(self): self.canvas = FigureCanvas(self, -1, self.figure) # canevas self.sizer = wx.BoxSizer(wx.VERTICAL) # aligneur self.sizer.Add(self.canvas, 1, wx.TOP | wx.LEFT | wx.EXPAND) #EVT_PAINT(self, self.OnPaint) # Capture the paint message #self.canvas.mpl_connect('motion_notify_event', self.OnMove) # Capture the paint message self.SetSizer(self.sizer) self.Fit() def OnPaint(self, event): self.canvas.draw() event.Skip() def OnMove(self, event): # get the x and y pixel coords x, y = event.x, event.y if event.inaxes: axe = event.inaxes xaxis = axe.get_xaxis() fig = axe.get_figure() print xaxis.get_data_interval() print 'data coords', event.xdata, event.ydata class FMPanelHisto(FMPanel): """ Frequency Matrix Panel, panel affichant une Matrice de fréquences sous la forme d'un ensemble de graphiques en histogrammes. Chaque graphique en histogramme représente une partie du texte (ins, supp...) et chaque histogramme une étiquette""" def __init__(self, frame, fm=None): """ pre: isinstance(fm,MediteAppli.synthetic.TagFrequencyMatrix) """ FMPanel.__init__(self,frame,fm) self.debutInitFMPanel() nbLine = self.fm.getNbLine() # nb lignes nbCol = 1 # nb colonnes self.figure.subplots_adjust(hspace=0.001) # colle les graphes l'un contre l'autre self.axes[0] = self.write_axe(0,nbLine,nbCol,self.handles) # crée un graphe for i in xrange(1,nbLine-2): # crée les autres, les parties de texte seulement self.write_axe(i,nbLine,nbCol,self.handles) for i in xrange(nbLine-2,nbLine): # crée les 2 derniers pour les textes totaux self.write_axe2(i,nbLine,nbCol,self.handles) self.figure.legend(self.handles,self.tm.getDescriptions(),'upper right', handlelen = 0.01, handletextsep = 0.01) # légende self.finInitFMPanel() def param(self): self.title = u"Nombre d'étiquettes dans chaque partie du texte" def write_axe(self, num,nbLine,nbCol,handles): """ Fonction dessinant effectivement le num-ième graphique parmi nbLine*nbCol en se limitant aux parties du texte""" if num==0: self.axes[num] = self.figure.add_subplot(nbLine,nbCol,num+1) #self.axes[num].set_title(u"Nombre d'étiquettes dans chaque partie du texte")#titre else: self.axes[num] = self.figure.add_subplot(nbLine,nbCol,num+1, sharex=self.axes[0],sharey=self.axes[0]) valeurs = self.fm.getFreqLine(num) # ensemble des valeurs à dessiner d'un graphqiue val=[] for x in valeurs: val.append(x) N = len(val) ind = arange(N) # the x locations for the groups width = 0.5 # the width of the bars maxi=self.fm.getMaxGenetic() #if maxi == 0: return None # toutes les valeurs de la ligne sont nulles handles.append(self.axes[num].bar(ind, val, width, color=self.cm.getListe())) self.axes[num].axhline(y=maxi/2, zorder=1) yticks=[] for x in xrange(maxi): #échelle des ordonnées if maxi/4 == 0: yticks.append(0) ; continue if x%(maxi/4)==0: yticks.append(x) self.axes[num].set_yticks(yticks) self.axes[num].set_ylabel(self.potm.abreviations(num)) if num==nbLine-1: # pour le dernier seulement on affiche la légende self.axes[num].set_xticks(ind+width/2) self.axes[num].set_xticklabels(self.tm.getListe()) else: self.axes[num].set_xticklabels([]) def write_axe2(self, num,nbLine,nbCol,handles): """ Fonction dessinant effectivement le num-ième graphique parmi 2 derniers, les textes totaux""" if num==nbLine-2: # texte1 self.axes[num] = self.figure.add_subplot(nbLine,nbCol,num+1) else: self.axes[num] = self.figure.add_subplot(nbLine,nbCol,num+1, sharex=self.axes[nbLine-2],sharey=self.axes[nbLine-2]) # texte2 valeurs = self.fm.getFreqLine(num) # ensemble des valeurs à dessiner d'un graphqiue val=[] for x in valeurs: val.append(x) N = len(val) ind = arange(N) # the x locations for the groups width = 0.5 # the width of the bars maxi=self.fm.getMaxText() handles.append(self.axes[num].bar(ind, val, width, color=self.cm.getListe())) self.axes[num].axhline(y=maxi/2, zorder=1) yticks=[] for x in xrange(maxi): #échelle des ordonnées if x%(maxi/4)==0: yticks.append(x) self.axes[num].set_yticks(yticks) self.axes[num].set_ylabel(self.potm.abreviations(num)) if num==nbLine-1: # pour le dernier seulement on affiche la légende self.axes[num].set_xticks(ind+width/2) self.axes[num].set_xticklabels(self.tm.getListe()) else: self.axes[num].set_xticklabels([]) class FMPanelCamembert(FMPanel): """ Classe représentant la part de chaque étiquette dans chaque partie du texte. -> 8 camemberts""" def __init__(self, frame, fm=None): """ pre: isinstance(fm,MediteAppli.synthetic.FrequencyMatrix) """ FMPanel.__init__(self,frame,fm) self.debutInitFMPanel() self.dessin() self.finInitFMPanel() def dessin(self): fh=self.fauxHisto(self.nbLine,self.nbCol) # crée les autres # -2 car on ne dessine pas les BC1 et BC2 for i in xrange(self.fm.getNbLine()-2): self.write_axe_auto(i,self.nbLine,self.nbCol,self.handles) #self.figure.legend(self.handles,self.tm.getDescriptions(),'upper right', # handlelen = 0.01, handletextsep = 0.01) # légende self.figure.legend(fh,self.tm.getDescriptions(),'upper right', handlelen = 0.01, handletextsep = 0.01) # légende def param(self): self.nbLine = 2 self.nbCol = 4 self.placeFauxHisto = 8 self.title = u"Proportions d'étiquettes dans chaque partie du texte" def fauxHisto(self,nbLine,nbCol): """ Faux histo que l'on cache avec un camembert. Sert juste a avoir toutes les couleurs pour la légende car si les camemberts ont des valeurs nulles, celles-ci modifient la légende """ valeurs = self.fm.getFreqLine(0) # ensemble des valeurs à dessiner d'un graphqiue val=[] ind=[] for x in valeurs: val.append(1) ind.append(0) self.axes[0] = self.figure.add_subplot(nbLine,nbCol,self.placeFauxHisto) #print len(self.cm.getListe()) return self.axes[0].bar(ind, val, width=0, color=self.cm.getListe()) def write_axe_auto(self, num,nbLine,nbCol,handles): """ Dessine les axes automatiquement """ self.axes[num] = self.figure.add_subplot(nbLine,nbCol,num+1) #if num==0:self.axes[num].set_title(self.title)#titre valeurs = self.fm.getFreqLine(num) # ensemble des valeurs à dessiner d'un graphqiue val=[] lab=[] col=[] for i in xrange(len(valeurs)):# élimine du camembert les valeurs nulles if valeurs[i]>0: val.append(valeurs[i]) lab.append(self.tm.getListe()[i]) col.append(self.cm.getListe()[i]) #print val handles.append(self.axes[num].pie(val, labels=lab, colors=col, autopct='%1.1f%%', shadow=True)) self.axes[num].set_xlabel(self.fm.potm.getItem(num)) def write_axe_coordo(self,left,bottom,width,height, num,handles): """ Dessine un axe avec les coordonnées left,bottom,width,height num = numéro de ligne dans la matrice de données """ self.axes[num] = self.figure.add_axes([left,bottom,width,height]) valeurs = self.fm.getFreqLine(num) # ensemble des valeurs à dessiner d'un graphqiue val=[] lab=[] col=[] for i in xrange(len(valeurs)):# élimine du camembert les valeurs nulles if valeurs[i]>0: val.append(valeurs[i]) lab.append(self.tm.getListe()[i]) col.append(self.cm.getListe()[i]) handles.append(self.axes[num].pie(val, labels=lab, colors=col, autopct='%1.1f%%', shadow=True)) self.axes[num].set_xlabel(self.fm.potm.getItem(num)) def fauxHisto_coordo(self): """ Faux histo en (0,0) largeur=0.001, hauteur=0 """ valeurs = self.fm.getFreqLine(0) # ensemble des valeurs à dessiner d'un graphqiue val=[] ind=[] for x in valeurs: val.append(1) ind.append(0) self.axes[0] = self.figure.add_axes([0,0,0.001,0]) return self.axes[0].bar(ind, val, width=0, color=self.cm.getListe()) class FMPanelCamembert2(FMPanelCamembert): """ FMPanelCamembert2 pour TagFrequencyMatrix2. Suppressions et Remp1 fusionnés / Insertions et Remp2 fussionnés -> 6 camemberts""" def __init__(self, frame, fm=None): """ pre: isinstance(fm,MediteAppli.synthetic.TagFrequencyMatrix2) """ FMPanelCamembert.__init__(self,frame,fm) def dessin(self): t1 = t2 = sr1 = ir2 = d1 = d2 = 0.0 for x in self.fm.getTextLine(0): t1+=x for x in self.fm.getTextLine(1): t2+=x for x in self.fm.getFreqLine(0): sr1+=x for x in self.fm.getFreqLine(1): ir2+=x for x in self.fm.getFreqLine(2): d1+=x for x in self.fm.getFreqLine(3): d2+=x fh=self.fauxHisto_coordo() L1 = t1+t2 L2 = sr1+ir2+d1+d2 lt1 = 0.9*t1/L1 # * 0.9 pour pouvoir ajouter la légende ht1 = lt1 lt2 = 0.9*t2/L1 ht2 = lt2 assert(lt1+lt2==0.9,lt1+lt2) lsr1 = sr1/L2 lir2 = ir2/L2 ld1 = d1/L2 ld2 = d2/L2 assert(lsr1+lir2+ld1+ld2==1,lsr1+lir2+ld1+ld2) # les if >0 car si une ligne n'a que des 0 ca bug à l'affichage if lt1 > 0: self.write_axe_coordo(0.01,0,lt1,ht1,4,self.handles) if lt2 > 0: self.write_axe_coordo(lt1,0,lt2,ht2,5,self.handles) if lsr1 > 0: self.write_axe_coordo(0.01,max(ht1,ht2),lsr1,lsr1,0,self.handles) if lir2 > 0: self.write_axe_coordo(lsr1,max(ht1,ht2),lir2,lir2,1,self.handles) if ld1 > 0: self.write_axe_coordo(lsr1+lir2,max(ht1,ht2),ld1,ld1,2,self.handles) if ld2 > 0:self.write_axe_coordo(lsr1+lir2+ld1,max(ht1,ht2),ld2,ld2,3,self.handles) self.figure.legend(fh,self.tm.getDescriptions(),(0.9,0), handlelen = 0.01, handletextsep = 0.01) # légende def param(self): self.nbLine = 2 self.nbCol = 3 self.placeFauxHisto = 6 self.title = u"Proportions d'étiquettes dans chaque partie du texte" class FMPanelCamembert3(FMPanelCamembert): """ FMPanelCamembert3 pour TagFrequencyMatrix3. Suppressions et Remp1 fusionnés / Insertions et Remp2 fussionnés -> 6 camemberts""" def __init__(self, frame, fm=None): """ pre: isinstance(fm,MediteAppli.synthetic.TagFrequencyMatrix2) """ FMPanelCamembert.__init__(self,frame,fm) def dessin(self): t1 = t2 = bc1 = bc2 = d1 = d2 = bcd1 = bcd2 = 0.0 for x in self.fm.getTextLine(0): t1 += x for x in self.fm.getTextLine(1): t2 += x for x in self.fm.getFreqLine(0): bc1 += x for x in self.fm.getFreqLine(1): bc2 += x for x in self.fm.getFreqLine(2): d1 += x for x in self.fm.getFreqLine(3): d2 += x for x in self.fm.getFreqLine(4): bcd1 += x for x in self.fm.getFreqLine(5): bcd2 += x fh=self.fauxHisto_coordo() L1 = t1 + t2 # largeur totale de cette ligne L2 = bc1 + bc2 + d1 + d2 + bcd1 + bcd2 lt1 = 0.9 * t1 / L1 # * 0.9 pour pouvoir ajouter la légende ht1 = lt1 # hauteur de cette ligne lt2 = 0.9 * t2 / L1 ht2 = lt2 assert str(lt1+lt2) == '0.9', lt1+lt2 lbc1 = bc1 / L2 # largeur de ce camembert lbc2 = bc2 / L2 ld1 = d1 / L2 ld2 = d2 / L2 lbcd1 = bcd1 / L2 lbcd2 = bcd2 / L2 assert lbc1+lbc2+ld1+ld2+lbcd1+lbcd2 == 1, lbc1+lbc2+ld1+ld2+lbcd1+lbcd2 # les if >0 car si une ligne n'a que des 0 ca bug à l'affichage if lt1 > 0: self.write_axe_coordo(0.01,0,lt1,ht1,6,self.handles) if lt2 > 0: self.write_axe_coordo(lt1,0,lt2,ht2,7,self.handles) if lbc1 > 0: self.write_axe_coordo(0.01,max(ht1,ht2),lbc1,lbc1,0,self.handles) if lbc2 > 0: self.write_axe_coordo(lbc1,max(ht1,ht2),lbc2,lbc2,1,self.handles) if ld1 > 0: self.write_axe_coordo(lbc1+lbc2,max(ht1,ht2),ld1,ld1,2,self.handles) if ld2 > 0:self.write_axe_coordo(lbc1+lbc2+ld1,max(ht1,ht2),ld2,ld2,3,self.handles) if lbcd1 > 0: self.write_axe_coordo(lbc1+lbc2+ld1+ld2,max(ht1,ht2),lbcd1,lbcd1,4,self.handles) if lbcd2 > 0: self.write_axe_coordo(lbc1+lbc2+ld1+ld2+lbcd1,max(ht1,ht2),lbcd2,lbcd2,5,self.handles) self.figure.legend(fh,self.tm.getDescriptions(),(0.9,0), handlelen = 0.01, handletextsep = 0.01) # légende def param(self): self.nbLine = 2 self.nbCol = 4 self.placeFauxHisto = 6 self.title = u"Proportions d'étiquettes dans chaque partie du texte" class FMPanelCamembert4(FMPanelCamembert): """ FMPanelCamembert4 pour TextFrequencyMatrix Seulement 2 camemberts, un pour chaque texte""" def __init__(self, frame, fm=None): """ pre: isinstance(fm,MediteAppli.synthetic.TextFrequencyMatrix) """ FMPanel.__init__(self,frame,fm) #FMPanelCamembert.__init__(self,frame,fm) tot1 = tot2 = 0.0 for x in self.fm.getFreqLine(0): tot1+=x for x in self.fm.getFreqLine(1): tot2+=x self.taille={0:tot1/(tot1+tot2), 1:tot2/(tot1+tot2)} #print self.taille self.cm = ColorManager(2) self.debutInitFMPanel() self.dessin() self.finInitFMPanel() def param(self): self.nbLine = 1 self.nbCol = 2 self.placeFauxHisto = 2 self.title = u"(Supp+Remp1)/BC1 et (Ins+Remp2)/BC2" def dessin(self): fh=self.fauxHisto_coordo() self.write_axe_coordo(0.01,0,self.taille[0],self.taille[0],0,self.handles) self.write_axe_coordo(self.taille[0],0,self.taille[1],self.taille[1],1,self.handles) self.figure.legend(fh,self.tm.getDescriptions(),'upper right', handlelen = 0.01, handletextsep = 0.01) # légende if __name__=='__main__': class App(wx.App): """ Application de test """ def OnInit(self): """Create the main window and insert the custom frame""" frame = wx.Frame(None,-1) #panel = FMPanelHisto(frame,self.fm()) #panel = FMPanelCamembert2(frame,self.fm2()) #panel = FMPanelCamembert4(frame,self.tm()) panel = FMPanelCamembert3(frame,self.fm3()) frame.Show(True) return True def fm(self): """ Renvoie une TagFrequencyMatrix de test """ self.tm = MediteAppli.synthetic.TagManager() self.potm = MediteAppli.synthetic.PartOfTextManager() l = self.tm.getNbItems() freqGeneticModifs = Numeric.array( [[0 for i in xrange(l)], [1 for i in xrange(l)], [2 for i in xrange(l)], [3 for i in xrange(l)], [4 for i in xrange(l)], [5 for i in xrange(l)], [6 for i in xrange(l)], [7 for i in xrange(l)]]) freqTexts = Numeric.array( [[8 for i in xrange(l)], [9 for i in xrange(l)]]) fm = MediteAppli.synthetic.TagFrequencyMatrix(freqGeneticModifs,freqTexts) fm.setRelation([0,2,4,6],0) fm.setRelation([1,3,5,7],1) return fm def fm2(self): return MediteAppli.synthetic.TagFrequencyMatrix2(self.fm()) def fm3(self): return MediteAppli.synthetic.TagFrequencyMatrix3(self.fm()) def tm(self): import Donnees.resultatAppli d = Donnees.resultatAppli.Resultat( [(100,133)], [(0,10)], [], [], 50, "01234567890123456789012345678901234567890123456789"+"01234567890123456789012345678901234567890123456789"+"01234567890123456789012345678901234567890123456789"+"01234567890123456789012345678901234567890123456789" ,[(10,50),(133,200)], []) tm = MediteAppli.synthetic.TextFrequencyMatrix(d) #print tm.getFreqLine(0) #print tm.getFreqLine(1) return tm try: app = App(0) app.MainLoop() except Exception,e1: import traceback,sys traceback.print_exc() sys.stderr.flush()