Package medite :: Package MediteAppli :: Module synthetic
[hide private]
[frames] | no frames]

Source Code for Module medite.MediteAppli.synthetic

   1  # -*- coding: iso-8859-1 -*- 
   2  # Copyright 20003 - 2008: Julien Bourdaillet (julien.bourdaillet@lip6.fr), Jean-Gabriel Ganascia (jean-gabriel.ganascia@lip6.fr) 
   3  # This file is part of MEDITE. 
   4  # 
   5  #    MEDITE is free software; you can redistribute it and/or modify 
   6  #    it under the terms of the GNU General Public License as published by 
   7  #    the Free Software Foundation; either version 2 of the License, or 
   8  #    (at your option) any later version. 
   9  # 
  10  #    MEDITE is distributed in the hope that it will be useful, 
  11  #    but WITHOUT ANY WARRANTY; without even the implied warranty of 
  12  #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
  13  #    GNU General Public License for more details. 
  14  # 
  15  #    You should have received a copy of the GNU General Public License 
  16  #    along with Foobar; if not, write to the Free Software 
  17  #    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
  18   
  19  import os,os.path,sys,string,logging,htmlentitydefs,bisect  
  20  import contract 
  21  import constantes 
  22  import Donnees.resultatAppli  
  23  import Controleurs.DGManager 
  24  import Utile.constantesDonnees 
  25  from string import Template 
  26  import utile 
  27  #import scipy 
  28  import numpy.oldnumeric as Numeric 
  29   
30 -class ListManager(object):
31 """ Classe centralisant la gestion d'une liste de valeurs fixes """
32 - def __init__(self):
33 self._liste = []
34 - def getListe(self):
35 """ Liste des tags """ 36 return self._liste
37 - def getItem(self,pos):
38 return self._liste[pos]
39 - def getNbItems(self):
40 """ Nombre de tags """ 41 return len(self._liste)
42 - def itemToPos(self,item):
43 """ Renvoie la position du tag dans la liste des tags """ 44 #return self._liste.index(item) 45 try: return self._liste.index(item) 46 except ValueError: raise ValueError("list.index(x): x not in list, x="+str(item))
47 - def posToItem(self,pos):
48 """ Renvoie le tag correspondant à cette position dans la liste de tags """ 49 if not(0<=pos<=len(self._liste)): raise LookupError("index out of range") 50 else: return self._liste[pos]
51 - def pref(self,item,num):
52 """ renvoie le préfixe de item 53 pre: isinstance(item,str) or isinstance(item,list) 54 """ 55 if isinstance(item,str): return self.__pref(item,num) 56 res = [] 57 for x in item: 58 res.append(self.__pref(x,num)) 59 return res
60 - def __pref(self,item,num):
61 res = item[:num] 62 #sepTable = string.maketrans("çéèàùâêîôûäëïöüÿÇÉÈÀÙÂÊÎÔÛÄËÏÖÜ","ceeauaeiouaeiouyCEEAUAEIOUAEIOU") 63 #res = res.translate(sepTable) 64 if item[-1]=='1' or item[-1]=='2': res += ' T'+item[-1] 65 return res
66
67 -class TagManager(ListManager):
68 """ Classe centralisant la gestion de la liste de tags utilisés """
69 - def __init__(self):
70 self._liste = ['ABR', 'ADJ', 'ADV', 'DET', 'INT', 'KON', 'NAM', 'NOM', 'NUM', 71 'PRO', 'PRP', 'PUN', 'SENT', 'SYM', 'VER']
72 - def getDescriptions(self):
73 return [u'Abréviation', 'Adjectif', 'Adverbe', u'Déterminant', 'Interjection', 74 'Conjonction', 'Nom propre', 'Nom', u'Numéral', 'Pronom', u'Préposition', 75 'Ponctuation', 'Mot phrase', 'Symbole', 'Verbe']
76
77 -class TagManager2(TagManager):
78 """ Classe centralisant la gestion de la liste de tags utilisés """
79 - def __init__(self):
80 #self._liste = ['Supp + Remp1', 'Ins + Remp2', 'BC1', 'BC2'] 81 self._liste = ['Modifications', 'BC']
82 - def getDescriptions(self):
83 #return ['Suppressions + Remplacements 1', 'Insertions + Remplacements 2', 84 # 'Blocs Communs', 'Blocs Communs'] 85 return ['Modifications', 'Blocs Communs']
86
87 -class PartOfTextManager(ListManager):
88 """ Classe centralisant la gestion des différentes parties du texte """
89 - def __init__(self):
90 self._liste = ['Suppressions', 'Insertions', 'Remplacements1', 'Remplacements2', 91 u'Déplacements1', u'Déplacements2', 'Blocs Communs 1', 92 'Blocs Communs 2', 'Texte1', 'Texte2']
93 - def abreviations(self,num=None):
94 """ Renvoie une abréviation ou toute la liste 95 pre: num==None or num<=len(self._liste) """ 96 res = self.pref(self._liste[:2],3) + self.pref(self._liste[2:4],4) + self.pref(self._liste[4:],3) 97 if num==None: return res 98 else: return res[num]
99
100 -class PartOfTextManager2(PartOfTextManager):
101 """ (Sup,Remp1) et (Ins,Remp2) sont fusionnés """
102 - def __init__(self):
103 self._liste = ['Suppressions + Remp1', 'Insertions + Remp2', 104 u'Déplacements1', u'Déplacements2', 'Blocs Communs 1', 105 'Blocs Communs 2', 'Texte1', 'Texte2']
106
107 -class PartOfTextManager3(PartOfTextManager):
108 """ Affiche les BC et les Dep """
109 - def __init__(self):
110 self._liste = ['Blocs Communs 1','Blocs Communs 2', 111 u'Déplacements1', u'Déplacements2', 112 u'BC1 + Dép1', u'BC2 + Dép2', 113 'Texte1', 'Texte2']
114
115 -class PartOfTextManager4(PartOfTextManager):
116 """ (Sup+Remp1)/BC1 et (Ins+Remp2)/BC2 """
117 - def __init__(self):
118 self._liste = ['Texte1', 'Texte2']
119
120 -class TreeTaggerWrapper(object):
121 """Classe qui interface le TreeTagger. A partir d'un texte, renovie une liste 122 des tokens étiquetés, en appellant la fonction etiquetage()"""
123 - def __init__(self):
124 self._REPTAGGER = os.path.join(constantes.REPMEDITE,"TreeTagger") 125 if not os.path.isdir(self._REPTAGGER): raise IOError,"Le dossier TreeTagger est absent." 126 #self._TAGGER = os.path.join(self._REPTAGGER,"tag-french.bat") 127 self._TAGGER = "tag-french.bat" # nom du tagger
128 #if not os.path.isfile(self._TAGGER): raise IOError,"Le TreeTagger est absent." 129
130 - def exec_pipe(self,directory,cmd,arg):
131 """ Exécute la commande cmd en lui passant sur stdin arg et en récupérant le résultat sur stdout 132 133 pre: isinstance(directory,str) 134 isinstance(cmd,str) 135 isinstance(arg,str) 136 os.path.isfile(cmd) 137 post: isinstance(__return__,str) 138 """ 139 curDir=os.getcwd() 140 os.chdir(directory) 141 #print "directory",directory 142 #print "cmd",cmd 143 fi,fo,fe = os.popen3(cmd,'t') 144 assert(fi != None) 145 assert(fo != None) 146 #fi.writelines(arg) 147 fi.close() 148 resultat = fo.readlines() 149 err = fe.readlines() 150 fo.close() 151 fe.close() 152 if 'ERROR' in err: sys.stderr.write(str(err)) 153 if len(resultat)==0: raise ValueError,u"Résultat de la commande vide." 154 resultat = ''.join(resultat) 155 os.chdir(curDir) 156 return resultat
157
158 - def etiquetage(self,texte):
159 """ Lance l'étiqueteur sur le texte et renvoie une liste [(token,tag)] 160 161 post: isinstance(__return__,list) 162 """ 163 nom_fichier_temp = "medTemp.txt" 164 fichier_temp = os.path.join(self._REPTAGGER,"medTemp.txt") 165 ft = open(fichier_temp, 'w') 166 ft.write(texte) 167 ft.close() 168 #if not os.path.isfile(fichier_temp): raise IOError,u"Fichier temporaire non créé." 169 #textTagged = self.exec_pipe(self._REPTAGGER,self._TAGGER +' "'+ fichier_temp+'"', "") 170 #textTagged = self.exec_pipe(self._REPTAGGER,self._TAGGER, fichier_temp) 171 # le tagger et le fichier à tagger doivent se trouver dans le même dossier 172 textTagged = self.exec_pipe(self._REPTAGGER,self._TAGGER + ' ' +nom_fichier_temp,'') 173 os.remove(fichier_temp) 174 lLines = textTagged.splitlines() 175 if len(lLines)==0: raise ValueError,u"L'étiquetage a échoué." 176 lTokenTag = [] 177 for l in lLines: 178 lTok = l.split() 179 if len(lTok)<=1: continue 180 # le token dans lTok[0] et le tag dans lTok[1] auquel on enlève le soustag 181 #print "1",lTok,"2" 182 end = lTok[1].find(':') 183 if end==-1: end=len(lTok[1]) 184 lTokenTag.append((lTok[0],lTok[1][:end])) 185 return lTokenTag
186 187 188
189 -class TaggerExtension(object):
190 """Classe gérant l'étiquetage des textes """
191 - def __init__(self,res):
192 """ Constructeur 193 194 pre: isinstance(res,Donnees.resultatAppli.Resultat) 195 """ 196 197 self.resultatMedite = res 198 self.tm = TagManager()
199
200 - def etiquetage(self):
201 """ Lance l'étiqueteur sur le texte et renvoie une liste [(token,tag)] 202 203 On traite les 2 fichiers séparément car si le 1er ne se termine pas 204 par un séparateur, son denier mot est concaténé au 1er du 2e fichier. 205 206 post: isinstance(__return__,list) 207 """ 208 tagger = TreeTaggerWrapper() 209 texte = self.resultatMedite.getTextesConcatenes() 210 lgSource=self.resultatMedite.getLgSource() 211 lTokenTag = [] 212 lTokenTag = tagger.etiquetage(texte[:lgSource]) 213 self._printTaggerOutput(lTokenTag, 'TreeTaggerOutputGauche.txt') 214 #print 'lTokenTag='+str(lTokenTag) 215 a = tagger.etiquetage(texte[lgSource:]) 216 self._printTaggerOutput(a, 'TreeTaggerOutputDroite.txt') 217 #print 'a='+str(a) 218 lTokenTag.extend(a) 219 return lTokenTag
220
221 - def _printTaggerOutput(self, liste, nom):
222 fichier = open(os.path.join(constantes.REPMEDITE,nom),'w') 223 for token,tag in liste: 224 fichier.write(token + '\t' + tag + '\n') 225 fichier.close()
226
227 - def extractLTokenPos_(self):
228 """ Extrait à partir du texte original une liste [(token, position)] 229 230 Traite le texte source puis le texte cible 231 232 post: isinstance(__return__,list) 233 """ 234 texte = self.resultatMedite.getTextesConcatenes() 235 lgSource = self.resultatMedite.getLgSource() 236 lTokenPos = [] 237 lTokenPos = self.extractLTokenPos__(texte[:lgSource],0) 238 #print lTokenPos 239 b = self.extractLTokenPos__(texte[lgSource:],lgSource) 240 lTokenPos.extend(b) 241 #print 'b='+str(b) 242 return lTokenPos
243
244 - def extractLTokenPos__(self,texte,debutTexte):
245 """ Extrait à partir du texte original une liste [(token, position)] 246 247 pre: isinstance(texte,str) and isinstance(debutTexte,int) and debutTexte>=0 248 post: isinstance(__return__,list) 249 """ 250 lTokenPos = [] 251 currentToken = [] 252 debutToken = i = 0 253 while i < len(texte): 254 #print 'texte[i]='+texte[i] 255 assert len(currentToken) <= len(texte),(len(currentToken), len(texte)) # pas + de token que de caractères 256 assert len(lTokenPos) <= len(texte),(len(lTokenPos), len(texte)) # pas de token > au texte 257 if (texte[i] in """ .-'[]{}`"(),;:!?%»«\t\r\n\f"""):# or (i==lgSource): 258 if len(currentToken) > 0: 259 lTokenPos.append((''.join(currentToken), debutToken+debutTexte)) 260 #print ''.join(currentToken) +' added' 261 #print lTokenPos[-1] 262 currentToken = [] 263 debutToken = i 264 # les mêmes sauf espace et retour ligne cad ceux qui ne sont pas des 265 # signes de ponctuation 266 if i < len(texte) and texte[i] in """.-'[]{}`"(),;:!?%»«""": 267 lTokenPos.append((texte[i], debutToken+debutTexte)) 268 #print texte[i] + ' added' 269 i += 1 270 else: 271 while i < len(texte) and (texte[i] in " \t\r\n\f"): i+=1 272 debutToken = i 273 #if i==lgSource: i+=1 274 else: 275 currentToken.append(texte[i]) 276 i+=1 277 if currentToken != []: 278 lTokenPos.append((''.join(currentToken), debutToken+debutTexte)) 279 #print ''.join(currentToken) 280 return lTokenPos
281
282 - def alignement(self):
283 """ Aligne la liste (token,tag) et la liste (token,position) en une liste [(debutToken,finToken,tag)] 284 285 post: isinstance(__return__,list) 286 """ 287 lTokenTag = self.etiquetage() 288 lTokenPos = self.extractLTokenPos_() 289 return self.alignement_(lTokenPos, lTokenTag)
290
291 - def alignement_(self, lTokenPos, lTokenTag):
292 """ Aligne les 2 listes en créant une liste [(debutToken,finToken,tag)] 293 294 pre: isinstance(lTokenTag, list) 295 isinstance(lTokenPos, list) 296 post: isinstance(__return__,list) 297 """ 298 res = [] 299 maxi = maxj = 0 300 while lTokenPos <> [] or lTokenTag <> []: 301 #print (len(lTokenTag), len(lTokenPos)) 302 if lTokenPos == []: 303 raise ValueError, "lTokenPos can't be []" 304 elif lTokenTag == []: 305 raise ValueError, "lTokenTag can't be []" 306 elif lTokenPos[0][0] == lTokenTag[0][0]: 307 res.append((lTokenPos[0][1],lTokenPos[0][1]+len(lTokenPos[0][0]),lTokenTag[0][1])) 308 lTokenPos = lTokenPos[1:] 309 lTokenTag = lTokenTag[1:] 310 else: 311 i = j = 0 312 startPos = endPos = lTokenPos[j][1] 313 conclTag = lTokenTag[i][0] 314 conclPos = lTokenPos[j][0] 315 while conclTag != conclPos: 316 if len(conclTag) < len(conclPos): 317 i += 1 318 conclTag += lTokenTag[i][0] 319 endPos += len(lTokenTag[i][0]) 320 if i > maxi: maxi = i 321 else: 322 j += 1 323 conclPos += lTokenPos[j][0] 324 endPos += len(lTokenPos[j][0]) 325 if j > maxj: maxj = j 326 #print conclTag 327 #print conclPos 328 res.append((startPos,endPos,lTokenTag[i][1])) 329 #sys.stdout.write("align: "+str(conclTag)+" / "+str(conclPos)+" / "+str(lTokenTag[0])+" lTokenTag[i][1]) "+str(lTokenTag[i][1])+ " / i="+str(i)+" / j=+"+str(j)+"\n") 330 lTokenTag = lTokenTag[i+1:] 331 lTokenPos = lTokenPos[j+1:] 332 if i > maxi: maxi = i 333 if j > maxj: maxj = j 334 #print res[-1] 335 sys.stdout.write("len(s1) "+str(len(lTokenPos))+" / len(s2)"+str(len(lTokenTag))+" / maxi="+str(maxi)+"\n") 336 return res
337
338 - def post_traitement_alignement(self,liste):
339 """ Conversion de la liste [(debut,fin,tag)] en dictionnaire 340 pre: isinstance(liste,list) 341 post: isinstance(__return__,dict) 342 """ 343 dic = {} 344 for (debut,fin,tag) in liste: 345 dic[debut] = (fin,tag) 346 return dic
347
348 - def calcul_frequences(self,la,da):
349 """ Crée la matrice de fréquences 350 pre: isinstance(la,list) 351 isinstance(da,dict) 352 post: isinstance(__return__,TagFrequencyMatrix) 353 """ 354 a = self.__sum_tag(self.resultatMedite.getListeDeplacementsT1(),da), 355 b = self.__sum_tag(self.resultatMedite.getListeDeplacementsT2(),da) 356 L1=[] ; L2=[] 357 for d,f in self.resultatMedite.getListeDeplacementsT1(): 358 L1.append(self.resultatMedite.getTextesConcatenes()[d:f]) 359 for d,f in self.resultatMedite.getListeDeplacementsT2(): 360 L2.append(self.resultatMedite.getTextesConcatenes()[d:f]) 361 362 for d,f in self.resultatMedite.getListeDeplacementsT2(): 363 c=self.resultatMedite.getTextesConcatenes()[d:f] 364 if c in L1: L1.remove(c) 365 for d,f in self.resultatMedite.getListeDeplacementsT1(): 366 d=self.resultatMedite.getTextesConcatenes()[d:f] 367 if d in L2: L2.remove(d) 368 logging.debug('L1='+str(L1)) 369 logging.debug('L2='+str(L2)) 370 371 L3=[] ; L4=[] 372 for d,f in self.resultatMedite.getBlocsCommunsT1(): 373 L3.append(self.resultatMedite.getTextesConcatenes()[d:f]) 374 for d,f in self.resultatMedite.getBlocsCommunsT2(): 375 L4.append(self.resultatMedite.getTextesConcatenes()[d:f]) 376 377 for d,f in self.resultatMedite.getBlocsCommunsT2(): 378 c=self.resultatMedite.getTextesConcatenes()[d:f] 379 if c in L3: L3.remove(c) 380 for d,f in self.resultatMedite.getBlocsCommunsT1(): 381 d=self.resultatMedite.getTextesConcatenes()[d:f] 382 if d in L4: L4.remove(d) 383 logging.debug('L3='+str(L3)) 384 logging.debug('L4='+str(L4)) 385 assert len(L3) == len(L4) == 0, (len(L3), len(L4)) 386 387 freqGeneticModifs = Numeric.array( 388 [self.__sum_tag(self.resultatMedite.getListeSuppressions(),da), 389 self.__sum_tag(self.resultatMedite.getListeInsertions(),da), 390 self.__sum_tag(self.resultatMedite.getListeRemplacementsT1(),da), 391 self.__sum_tag(self.resultatMedite.getListeRemplacementsT2(),da), 392 self.__sum_tag(self.resultatMedite.getListeDeplacementsT1(),da), 393 self.__sum_tag(self.resultatMedite.getListeDeplacementsT2(),da), 394 self.__sum_tag(self.resultatMedite.getBlocsCommunsT1(),da, False), 395 self.__sum_tag(self.resultatMedite.getBlocsCommunsT2(),da, False)]) 396 freqTexts = Numeric.array( 397 [self.__sum_tag(self.__filtre(la,0,self.resultatMedite.getLgSource()),da), 398 self.__sum_tag(self.__filtre(la,self.resultatMedite.getLgSource(),len(self.resultatMedite.getTextesConcatenes())),da)]) 399 fm = TagFrequencyMatrix(freqGeneticModifs,freqTexts) 400 fm.setRelation([0,2,4,6],0) 401 fm.setRelation([1,3,5,7],1) 402 print freqGeneticModifs 403 #print freqGeneticModifs[5] 404 return fm
405 406
407 - def __sum_tag(self,liste,da,p=False):
408 """ Prend une liste [(deb,fin)] et renvoie un array des fréquences des tags dans celle-ci 409 410 pre: isinstance(da,dict) 411 isinstance(liste,list) 412 forall([x in liste], isintance(x[0],int) and isinstance(x[1],int)) 413 post: forall([0<=__return__[i]<=len(liste) for i in arrayrange(__return__)]) 414 """ 415 tab = Numeric.zeros(self.tm.getNbItems()) # tableau des fréquences initialisé à 0 416 for inter in liste: 417 if p: 418 print self.resultatMedite.getTextesConcatenes()[inter[0]:inter[1]] 419 print inter 420 pos = inter[0] 421 while pos < inter[1]: 422 if da.has_key(pos): 423 (fin,tag) = da[pos] 424 #if fin <= inter[1]:# on incrémente que si le mot appartient à l'intervalle 425 tab[self.tm.itemToPos(tag)]+=1 426 if p: print str(da[pos])+ ' ajouté' 427 #else: assert fin >= inter[1] 428 pos = fin #+= fin-inter[0] # on décale de la longueur du mot 429 else: pos += 1 430 return tab
431
432 - def __filtre(self,liste,deb,fin):
433 """ Renvoie la sous-liste des items de liste compris entre deb et fin """ 434 res=[] 435 for x in liste: 436 if deb <= x[0] < fin: 437 res.append(x) 438 return res
439
440 - def run(self):
441 """post: assert_(isinstance(__return__,FrequencyMatrix))""" 442 la = self.alignement() 443 da = self.post_traitement_alignement(la) 444 fm = self.calcul_frequences(la,da) 445 return fm
446
447 -class FrequencyMatrix(object):
448 """ Matrice de fréquences """
449 - def __init__(self,nbLine,nbCol):
450 """ pre: isinstance(nbLine,int) and isinstance(nbCol,int) and nbLine>0 and nbCol>0 """ 451 self.freqGeneticModifs = Numeric.array([[0]*nbCol]*nbLine) 452 self.tm = TagManager() 453 self.potm = PartOfTextManager() 454 self.name = 'FrequencyMatrix'
455 - def __str__(self):
456 return self.name+'\nfreqGeneticModifs = '+str(self.freqGeneticModifs)
457 - def getNbLine(self):
458 """ Nombre total de lignes """ 459 return len(self.freqGeneticModifs)
460 - def getNbColumn(self):
461 """ Nombre de colonnes """ 462 return len(self.freqGeneticModifs[0])
463 - def getFreqLine(self,index):
464 """ Renvoie une ligne de fréquence cad une ligne correspondant à une partie de texte """ 465 if isinstance(index,int): 466 return self.freqGeneticModifs[index] 467 else: return self.freqGeneticModifs[self.potm.itemToPos(index)]
468 - def getMax(self):
469 """ Renvoie la valeur max sur toute la matrice """ 470 res=0 471 for i in xrange(self.getNbLine()): 472 for j in self.getFreqLine(i): 473 if j>res: res=j 474 return res
475 - def getItemLegend(self):
476 return self.tm
477 - def getGraphLegend(self):
478 return self.potm
479
480 -class TagFrequencyMatrix(FrequencyMatrix):
481 """ Matrice de fréquences de tags. 482 483 En ligne les modifications génétiques et en colonne les tags, 484 self.freqGeneticModifs représentes les fréquences de tags pour chaque type de modif génétique, 485 self.freqTexts représentes les fréquences de tags pour les 2 textes 486 chaque ligne de freqGeneticModifs est en relation avec une ligne de freqTexts """
487 - def __init__(self, freqGeneticModifs, freqTexts):
488 """#pre: isinstance(freqGeneticModifs,Numeric.array) 489 # isinstance(freqTexts,Numeric.array) """ 490 self.freqGeneticModifs = freqGeneticModifs 491 self.freqTexts = freqTexts 492 self.tm = TagManager() 493 self.potm = PartOfTextManager() 494 self.dRelation = {} 495 self.name = 'TagFrequencyMatrix'
496 - def __str__(self):
497 return self.name+'\nfreqGeneticModifs = '+str(self.freqGeneticModifs)+ \ 498 '\nfreqTexts = '+str(self.freqTexts)
499 - def setRelation(self,posGeneticModifs,posTexts):
500 """Met en relation une partie du texte et un texte, par exemple insertion et texte cible. 501 pre: isinstance(posGeneticModifs,list) 502 isinstance(posTexts,int) """ 503 for pos in posGeneticModifs: 504 self.dRelation[pos] = posTexts
505 - def getRelation(self,posGeneticModifs):
506 """pre: isinstance(posGeneticModifs,int) """ 507 try: return self.dRelation[posGeneticModifs] 508 except LookupError: return -1
509 - def getNbLine(self):
510 """ Nombre total de lignes """ 511 return len(self.freqGeneticModifs)+len(self.freqTexts)
512 - def getFreqLine(self,index):
513 """ Renvoie une ligne de fréquence cad une ligne correspondant à une partie de texte """ 514 if isinstance(index,int): 515 maxi=len(self.freqGeneticModifs) 516 if index>=maxi: return self.freqTexts[index-maxi] 517 else: return self.freqGeneticModifs[index] 518 else: return self.freqGeneticModifs[self.potm.itemToPos(index)]
519 - def getTextLine(self,index):
520 """ Renvoie la ligne de fréquence du texte source ou cible """ 521 if isinstance(index,int): 522 return self.freqTexts[index]
523 - def getFreqColumn(self,index):
524 """ Renvoie une colonne d'étiquettes """ 525 if not isinstance(index,int): 526 index = self.potm.itemToPos(index) 527 res=[] 528 for i in xrange(self.freqGeneticModifs.shape()[0]): 529 res.append(self.freqGeneticModifs[i][index]) 530 return Numeric.array(res)
531 - def getMaxGenetic(self):
532 """ Renvoie la valeur max sur la matrice de freq genetic""" 533 res=0 534 for i in xrange(len(self.freqGeneticModifs)): 535 for j in self.getFreqLine(i): 536 if j>res: res=j 537 return res
538 - def getMaxText(self):
539 """ Renvoie la valeur max sur la matrice des 2 textes""" 540 res=0 541 for i in xrange(2): 542 for j in self.getTextLine(i): 543 if j>res: res=j 544 return res
545
546 -class TagFrequencyMatrix2(TagFrequencyMatrix):
547 """ Matrice de fréquences où (Sup,Remp1) sont fusionnés et (Ins,Remp2) aussi """
548 - def __init__(self, fm):
549 """pre: isinstance(fm,FrequencyMatrix) """ 550 self.tm = TagManager() 551 self.potm = PartOfTextManager2() 552 self.freqGeneticModifs = Numeric.array([[0]*fm.getNbColumn()]*4) # 4 lignes 553 #print self.freqGeneticModifs 554 for i in xrange(fm.getNbColumn()): # (Sup + Remp1) 555 self.freqGeneticModifs[0,i] = fm.freqGeneticModifs[0,i] + fm.freqGeneticModifs[2,i] 556 for i in xrange(fm.getNbColumn()): # (Ins + Remp2) 557 self.freqGeneticModifs[1,i] = fm.freqGeneticModifs[1,i] + fm.freqGeneticModifs[3,i] 558 self.freqGeneticModifs[2] = fm.freqGeneticModifs[4] # Dep1 559 self.freqGeneticModifs[3] = fm.freqGeneticModifs[5] # Dep2 560 self.freqTexts = fm.freqTexts 561 self.dRelation = {} 562 fm.setRelation([0,2],0) 563 fm.setRelation([1,3],1) 564 self.name = 'TagFrequencyMatrix2'
565
566 -class TagFrequencyMatrix3(TagFrequencyMatrix):
567 """ Matrice de fréquences avec les lignes BC1, BC2, Dep1, Dep2, 568 BC1+Dep1, BC2+Dep2 et Texte1, Texte2 """
569 - def __init__(self, fm):
570 """pre: isinstance(fm,FrequencyMatrix) """ 571 self.tm = TagManager() 572 self.potm = PartOfTextManager3() 573 self.freqGeneticModifs = Numeric.array([[0]*fm.getNbColumn()]*6) # 6 lignes 574 #print self.freqGeneticModifs 575 self.freqGeneticModifs[0] = fm.freqGeneticModifs[6] # BC1 576 self.freqGeneticModifs[1] = fm.freqGeneticModifs[7] # BC2 577 self.freqGeneticModifs[2] = fm.freqGeneticModifs[4] # Dep1 578 self.freqGeneticModifs[3] = fm.freqGeneticModifs[5] # Dep2 579 for i in xrange(fm.getNbColumn()): # (BC1 + Dep1) 580 self.freqGeneticModifs[4,i] = fm.freqGeneticModifs[6,i] + fm.freqGeneticModifs[4,i] 581 for i in xrange(fm.getNbColumn()): # (BC2 + Dep2) 582 self.freqGeneticModifs[5,i] = fm.freqGeneticModifs[7,i] + fm.freqGeneticModifs[5,i] 583 584 self.freqTexts = fm.freqTexts 585 self.dRelation = {} 586 fm.setRelation([0,2,4],0) 587 fm.setRelation([1,3,5],1) 588 self.name = 'TagFrequencyMatrix3'
589
590 -class TextFrequencyMatrix(FrequencyMatrix):
591 """ Rapports (Sup+Remp1)/BC1 et (Ins+Remp2)/BC2 en caractères et non en tags """
592 - def __init__(self,res):
593 """ 594 pre: isinstance(res,Donnees.resultatAppli.Resultat) 595 """ 596 FrequencyMatrix.__init__(self,2,2) # 2 lignes * 2 col 597 self.tm = TagManager2() 598 self.potm = PartOfTextManager4() 599 #self.freqGeneticModifs = Numeric.array([[0]*2]*2) # 2 lignes * 2 col 600 for (d,f) in res.getListeSuppressions()+res.getListeRemplacementsT1(): 601 self.freqGeneticModifs[0,0] += f-d 602 for (d,f) in res.getBlocsCommunsT1(): 603 self.freqGeneticModifs[0,1] += f-d 604 for (d,f) in res.getListeInsertions()+res.getListeRemplacementsT2(): 605 self.freqGeneticModifs[1,0] += f-d 606 for (d,f) in res.getBlocsCommunsT2(): 607 self.freqGeneticModifs[1,1] += f-d 608 self.name = 'TextFrequencyMatrix'
609
610 -class Bloc(object):
611 """Bloc décrivant une partie de texte 612 613 Les propriétés sont en lecture seule -> Bloc n'est pas mutable."""
614 - def __init__(self, type_, debut, fin, listeDeplacements=[]):
615 assert type_ in ['BC','I','S','R'], "Unauthorized type for Bloc: "+type_ 616 self._end_init(type_, debut, fin, listeDeplacements)
617
618 - def _end_init(self, type_, debut, fin, listeDeplacements):
619 """Fin de l'initialisation""" 620 self.type = type_ # Type du bloc 621 assert 0 <= debut < fin, "Invalid Bloc limits" 622 self.debut = debut # Début du bloc 623 self.fin = fin # Fin du bloc 624 if __debug__ and len(listeDeplacements) > 0: 625 assert debut <= listeDeplacements[0][0] < listeDeplacements[-1][1] <= fin, "Moves outside Bloc limits" 626 for d in listeDeplacements: assert isinstance(d, list),str(type(d))+str(d) 627 self.lDep = listeDeplacements # Liste des déplacements inclus dans le bloc
628
629 - def __str__(self):
630 return ''.join(['Bloc(',self.type,',',str(self.debut),',', 631 str(self.fin),',',str(self.lDep),')'])
632 633 #def getType(self): return self._type 634 #type = property(getType, doc='Type du bloc') 635 636 #def getDebut(self): return self._debut 637 #debut = property(getDebut, doc='Début du bloc') 638 639 #def getFin(self): return self._fin 640 #fin = property(getFin, doc='Fin du bloc') 641 642 #def getLD(self): return self._lDep 643 #def setLD(self, value): 644 # if len(value) > 0: 645 # assert debut <= value[0][0] < value[-1][1] <= fin 646 # self.__lDep = value 647 #lDep = property(getLD, doc='Liste des déplacements inclus dans le bloc') 648 649 #def getLongueur(self): return self.getFin() - self.getDebut()
650 - def getLongueur(self): return self.fin - self.debut
651 longueur = property(getLongueur, doc='Longueur du bloc') 652
653 - def getLongueurDep(self):
654 res = 0 655 for (d,f) in self.lDep: res += f - d 656 return res
657 longueur_deplacement = property(getLongueurDep, doc='Longueur totale des deplacements')
658 659
660 -class BlocWD(Bloc):
661 """Bloc où le type D est permis"""
662 - def __init__(self, type_, debut, fin, listeDeplacements=[]):
663 assert type_ in ['BC','I','S','R','D'], "Unauthorized type for BlocWD: "+type_ 664 self._end_init(type_, debut, fin, listeDeplacements)
665
666 - def getLongueurDep(self):
667 """Si le bloc est D alors pas besoin de voir sa liste de déplacements""" 668 if self.type == 'D': return self.longueur 669 for (d,f) in self.lDep: res += f - d 670 return res
671
672 -class BiBlocList__(object):
673 """ Construit une liste de Bibloc 674 675 Un Bibloc est un tuplet de 2 Bloc alignés. 676 Un Bloc est un objet (type,début,fin,listeDep) ou None si il est vide. 677 type est soit I,S,R,BC 678 debut et fin sont les limites du bloc dans la chaine de texte. 679 listeDep est une liste éventuellement vide listant tous les intervalles de déplacement compris dans le bloc. 680 Les blocs I et S sont alignés forcément avec des blocs None. 681 Les blocs R et BC sont alignés forcément avec des blocs respectivement R et BC. """
682 - def __init__(self,resultat,planTravail,depOrdonnes=True):
683 """ Constructeur 684 685 Si on utilise l'ancien algo d'identification des remplacements et déplacements, 686 on peut avoir des blocs présents uniquement dans resultat.getListeDeplacements(). 687 Ceux-ci sont alors ajoutés comme des S ou des I. 688 689 dd: si depOrdonnes=False, pas d'assertion d'ordre sur les déplacement-> recherche d'un dep en O(n) dans __decoreDep1() 690 sinon si depOrdonnes=True, assertion d'ordre respectée -> recherche en O(log n) dans __decoreDep2() 691 692 pre: isinstance(resultat,Donnees.resultatAppli.Resultat) 693 isinstance(planTravail,Donnees.planTravail.PlanTravail) """ 694 self.depOrdonnes = depOrdonnes 695 #def gg(liste): 696 # if len(liste)>0: return str(liste[0]) 697 # else: return '' 698 self.texte = resultat.getTextesConcatenes() 699 self.lgSource = resultat.getLgSource() 700 self.planTravail = planTravail # sert seulement à l'affichage du rapport 701 702 liste = [] 703 lBCT1 = resultat.getBlocsCommunsT1() 704 lBCT2 = resultat.getBlocsCommunsT2() 705 assert len(lBCT1) == len(lBCT2),str(len(lBCT1))+'/'+str(len(lBCT2)) 706 lRempT1 = resultat.getListeRemplacementsT1() 707 lRempT2 = resultat.getListeRemplacementsT2() 708 assert len(lRempT1) == len(lRempT2) 709 lIns = resultat.getListeInsertions() 710 lSup = resultat.getListeSuppressions() 711 lDepT1 = resultat.getListeDeplacementsT1() #; print lDepT1 712 lDepT2 = resultat.getListeDeplacementsT2() # ; print lDepT2 713 i=0 714 len_lBCT1 = len(lBCT1) ; len_lBCT2 = len(lBCT2) ; len_lRempT1 = len(lRempT1) 715 len_lRempT2 = len(lRempT2) ; len_lSup = len(lSup) ; len_lIns = len(lIns) 716 len_lDepT1 = len(lDepT1) ; len_lDepT2 = len(lDepT2) 717 while (len_lBCT1 > 0 or len_lBCT2 > 0 or len_lRempT1 > 0 or 718 len_lRempT2 > 0 or len_lSup > 0 or len_lIns > 0 or 719 len_lDepT1 > 0 or len_lDepT2 > 0): 720 assert len_lBCT1 == len_lBCT2 721 assert len_lRempT1 == len_lRempT2 722 #print len_lDepT1,len_lDepT2 723 c="""print '-----------------------' 724 print len(lSup),len(lRempT1),len(lBCT1),len(lDepT1) 725 print len(lIns),len(lRempT2),len(lBCT2),len(lDepT2) 726 print gg(lSup),gg(lRempT1),gg(lBCT1),gg(lDepT1) 727 print gg(lIns),gg(lRempT2),gg(lBCT2),gg(lDepT2)""" 728 # pour ajouter un bloc sup soit les 2 listes sont vides 729 # soit BC vides et <= dep car dans ce cas le dep sera inclus dans le sup 730 # soit < BC car pas de chevauchement entre sup et dep 731 if (len_lSup > 0 and 732 ((len_lBCT1 == 0 and len_lDepT1 == 0) or 733 (len_lBCT1 == 0 and lSup[0][0] <= lDepT1[0][0]) or 734 (len_lDepT1 == 0 and lSup[0][0] < lBCT1[0][0]) or 735 (len_lBCT1 > 0 and len_lDepT1 > 0 and lSup[0][0] < lBCT1[0][0] and lSup[0][0] <= lDepT1[0][0]))): # ajout sup 736 depInBloc1 = self.__decoreDep(lSup[0], lDepT1) #décoration avec les déplacements 737 liste.append((Bloc('S',lSup[0][0],lSup[0][1],depInBloc1),None)) # ajout du bibloc 738 lSup.pop(0) ; len_lSup -= 1 ; len_lDepT1 -= len(depInBloc1) 739 elif (len_lIns > 0 and 740 ((len_lBCT2 == 0 and len_lDepT2 == 0) or 741 (len_lBCT2 == 0 and lIns[0][0] <= lDepT2[0][0]) or 742 (len_lDepT2 == 0 and lIns[0][0] < lBCT2[0][0]) or 743 (len_lBCT2 > 0 and len_lDepT2 > 0 and lIns[0][0] < lBCT2[0][0] and lIns[0][0] <= lDepT2[0][0]))): # ajout ins 744 depInBloc2 = self.__decoreDep(lIns[0], lDepT2) #décoration avec les déplacements 745 liste.append((None,Bloc('I',lIns[0][0],lIns[0][1],depInBloc2))) # ajout du bibloc 746 lIns.pop(0) ; len_lIns -= 1 ; len_lDepT2 -= len(depInBloc2) 747 # si depT1 < rempT1 et BCT1, ajout dep comme une sup 748 elif (len_lDepT1 > 0 and 749 ((len_lBCT1 == 0 and len_lRempT1 == 0) or 750 (len_lBCT1 == 0 and lDepT1[0][0] < lRempT1[0][0]) or 751 (len_lRempT1 == 0 and lDepT1[0][0] < lBCT1[0][0]) or 752 (len_lBCT1 > 0 and len_lRempT1 > 0 and lDepT1[0][0] < lBCT1[0][0] and lDepT1[0][0] <lRempT1[0][0]))): 753 liste.append((Bloc('S',lDepT1[0][0],lDepT1[0][1],[[lDepT1[0][0],lDepT1[0][1]]]),None)) # ajout du bibloc 754 lDepT1.pop(0) ; len_lDepT1 -= 1 755 elif (len_lDepT2 > 0 and 756 ((len_lBCT2 == 0 and len_lRempT2 == 0) or 757 (len_lBCT2 == 0 and lDepT2[0][0] < lRempT2[0][0]) or 758 (len_lRempT2 == 0 and lDepT2[0][0] < lBCT2[0][0]) or 759 (len_lBCT2 > 0 and len_lRempT2 > 0 and lDepT2[0][0] < lBCT2[0][0] and lDepT2[0][0] <lRempT2[0][0]))): # ajout dep comme une ins 760 liste.append((None,Bloc('I',lDepT2[0][0],lDepT2[0][1],[[lDepT2[0][0],lDepT2[0][1]]]))) # ajout du bibloc 761 lDepT2.pop(0) ; len_lDepT2 -= 1 762 elif (len_lRempT1 > 0 and len_lRempT2 > 0 and 763 ((len_lBCT1 == 0 and len_lBCT2 == 0) or 764 (lRempT1[0][0] < lBCT1[0][0] and lRempT2[0][0] < lBCT2[0][0]))): 765 com="""((len_lBCT1 == 0 and len_lBCT2 == 0 and len_lDepT1 == 0 and len_lDepT2 == 0) or 766 (len_lBCT1 == 0 and len_lBCT2 == 0 and len_lDepT1 == 0 and lRempT2[0][0] <= lDepT2[0][0]) or 767 (len_lBCT1 == 0 and len_lBCT2 == 0 and lRempT1[0][0] <= lDepT1[0][0] and len_lDepT2 == 0) or 768 (len_lBCT1 == 0 and len_lBCT2 == 0 and lRempT1[0][0] <= lDepT1[0][0] and lRempT2[0][0] <= lDepT2[0][0]) or 769 (len_lBCT1 > 0 and len_lBCT2 > 0 and len_lDepT1 == 0 and len_lDepT2 == 0 and lRempT1[0][0] < lBCT1[0][0] and lRempT2[0][0] < lBCT2[0][0]) or 770 (len_lBCT1 > 0 and len_lBCT2 > 0 and len_lDepT1 == 0 and lRempT2[0][0] <= lDepT2[0][0] and lRempT1[0][0] < lBCT1[0][0] and lRempT2[0][0] < lBCT2[0][0]) or 771 (len_lBCT1 > 0 and len_lBCT2 > 0 and lRempT1[0][0] <= lDepT1[0][0] and len_lDepT2 == 0 and lRempT1[0][0] < lBCT1[0][0] and lRempT2[0][0] < lBCT2[0][0]) or 772 (len_lBCT1 > 0 and len_lBCT2 > 0 and len_lDepT1 > 0 and len_lDepT2 > 0 and 773 lRempT1[0][0] < lBCT1[0][0] and lRempT2[0][0] < lBCT2[0][0] ))): # and lRempT1[0][0] <= lDepT1[0][0] and lRempT2[0][0] <= lDepT2[0][0]))): # ajout remp 774 """ 775 depInBloc1 = self.__decoreDep(lRempT1[0], lDepT1) #décoration avec les déplacements 776 depInBloc2 = self.__decoreDep(lRempT2[0], lDepT2) #décoration avec les déplacements 777 liste.append((Bloc('R',lRempT1[0][0],lRempT1[0][1],depInBloc1), 778 Bloc('R',lRempT2[0][0],lRempT2[0][1],depInBloc2))) # ajout du bibloc 779 #print liste[-1][0],liste[-1][1] 780 lRempT1.pop(0) ; len_lRempT1 -= 1 ; len_lDepT1 -= len(depInBloc1) 781 lRempT2.pop(0) ; len_lRempT2 -= 1 ; len_lDepT2 -= len(depInBloc2) 782 783 # elif len_lDepT1 > 0 and (len_lBCT1 == 0 or lDepT1[0][0] < lBCT1[0][0]): # ajout dep comme une sup 784 # liste.append((Bloc('S',lDepT1[0][0],lDepT1[0][1],[[lDepT1[0][0],lDepT1[0][1]]]),None)) # ajout du bibloc 785 # lDepT1 = lDepT1[1:] 786 # elif len_lDepT2 > 0 and (len_lBCT2 == 0 or lDepT2[0][0] < lBCT2[0][0]): # ajout dep comme une ins 787 # liste.append((None,Bloc('I',lDepT2[0][0],lDepT2[0][1],[[lDepT2[0][0],lDepT2[0][1]]]))) # ajout du bibloc 788 # lDepT2 = lDepT2[1:] 789 else: # ajout BC 790 liste.append((Bloc('BC',lBCT1[0][0],lBCT1[0][1],[]),Bloc('BC',lBCT2[0][0],lBCT2[0][1],[]))) # ajout du bibloc 791 lBCT1.pop(0) ; len_lBCT1 -= 1 792 lBCT2.pop(0) ; len_lBCT2 -= 1 793 794 self.liste = liste # liste des biblocs 795 if __debug__: 796 assert len_lSup == len_lIns == 0 797 assert len_lRempT1 == len_lRempT2 == 0 798 assert len_lBCT1 == len_lBCT2 == 0 799 assert len_lDepT1 == len_lDepT2 == 0 800 self._testOrdre() 801 self._testNonPerte(resultat) 802 803 if len(resultat.getListeRemplacements()) == 0: 804 self.evaluation() 805 logging.debug('extractRemplacements()') 806 self.extractRemplacements()
807
808 - def __decoreDep(self, intervalle, lDep):
809 if not self.depOrdonnes: 810 return self.__decoreDep_1(intervalle, lDep) 811 else: 812 return self.__decoreDep_3(intervalle, lDep)
813 - def __decoreDep_1(self, intervalle, lDep):
814 """ Extrait de la liste générale des déplacement lDep les déplacements se situant à l'intérieur du bloc 815 816 Attention !! modifie lDep 817 Comme sur les déplacements on n'a pas d'assertions sur l'ordre, 818 on parcourt à chaque appel de cette fonction toute la liste des déplacements.""" 819 #if len(lDep) == 0: return [],[] 820 if len(lDep) == 0: return [] 821 res = [] 822 nouvelleLDep = [] 823 for [d,f] in lDep: 824 #assert isinstance(d, list),str(type(d))+str(d) 825 if intervalle[0] <= d and f <= intervalle[1] : # déplacement inlcus dans l'intervalle 826 res.append([d,f]) 827 else: nouvelleLDep.append([d,f]) 828 assert len(lDep) == len(nouvelleLDep) + len(res) 829 lDep = nouvelleLDep 830 #return nouvelleLDep,res 831 return res
832
833 - def __decoreDep_2(self, intervalle, lDep):
834 """ Extrait de la liste générale des déplacement lDep les déplacements se situant à l'intérieur du bloc 835 836 Attention !! modifie lDep et retourne res2 837 Ici assertion d'ordre sur les dep, recherhe d'un dep en log(n) 838 """ 839 #if len(lDep) == 0: return [],[] 840 if len(lDep) == 0: return [] 841 deb = bisect.bisect(lDep, intervalle[0]) 842 fin = bisect.bisect(lDep, intervalle[1]) 843 assert deb <= fin 844 if deb == fin: # aucun déplacement n'existe dans la liste entre les 2 intervalles 845 #return lDep,[] 846 return [] 847 else: 848 res2 = lDep[deb:fin] 849 lDep[deb:fin] = [] 850 #lDep = lDep[:deb]+lDep[fin:] 851 #return lDep[:deb]+lDep[fin:], lDep[deb:fin] 852 return res2
853
854 - def __decoreDep_3(self, intervalle, lDep):
855 """ Extrait de la liste générale des déplacement lDep les déplacements se situant à l'intérieur du bloc 856 857 Attention !! modifie lDep et retourne res2 858 Ici assertion d'ordre sur les dep, recherhe d'un dep en temps linéaire 859 comme lDep[0] est toujours >= intervalle (parce que l'ordre est maintenu par la 860 fonction appelante), on commence la recherche à partir de là 861 """ 862 if len(lDep) == 0: return [] 863 res2 = [] 864 i = 0 865 while lDep[0] < intervalle[1] and lDep[1] <= intervalle[1]: 866 i+= 1 867 res2.append(lDep.pop(0)) # mofifie lDep !! 868 return res2
869 870
871 - def _testOrdre(self):
872 """ Teste le bon ordre des blocs dans la liste """ 873 posT1 = 0 # position courante dans le texte source 874 posT2 = self.lgSource # position courante dans le texte cible 875 prevB1 = prevB2 = (0,0,0,[]) 876 for (B1,B2) in self.liste: 877 if B1 is not None: 878 # la position précédente est <= au début du bloc courant 879 assert posT1 <= B1.debut,str(posT1)+' '+str(prevB1)+' '+str(B1) 880 posT1 = B1.fin 881 for dep in B1.lDep:# les déplacements sont bien inclus dans le bloc courant 882 assert B1.debut <= dep[0] <= dep[1] <= B1.fin 883 prevB1 = B1 884 if B2 is not None: 885 assert posT2 <= B2.debut, str(posT2)+' '+str(prevB2)+' '+str(B2) 886 posT2 = B2.fin 887 for dep in B2.lDep: 888 assert B2.debut <= dep[0] <= dep[1] <= B2.fin 889 prevB2 = B2
890
891 - def _testNonPerte(self, resultat):
892 """Teste la non-perte de données lors de la création du BiblocList 893 894 On teste si chaque element dans les listes de la donnée en entrée (param Resultat) 895 est bien présent en sortie dans self.liste """ 896 # BC T1 897 for (d,f) in resultat.getBlocsCommunsT1(): 898 for (B1,B2) in self.liste: 899 if (B1 is not None and B1.type == 'BC' and B1.debut == d and B1.fin == f): break 900 else: raise AssertionError("Bloc BC1 "+str((d,f))+" lost during BiblocList creation") 901 # BC T2 902 for (d,f) in resultat.getBlocsCommunsT2(): 903 for (B1,B2) in self.liste: 904 if (B2 is not None and B2.type == 'BC' and B2.debut == d and B2.fin == f): break 905 else: raise AssertionError("Bloc BC2 "+str((d,f))+" lost during BiblocList creation") 906 # Suppressions 907 for (d,f) in resultat.getListeSuppressions(): 908 for (B1,B2) in self.liste: 909 if (B1 is not None and (B1.type == 'S' or B1.type == 'R') and 910 B1.debut == d and B1.fin == f): break 911 else: raise AssertionError("Bloc S "+str((d,f))+" lost during BiblocList creation") 912 # Insertions 913 for (d,f) in resultat.getListeInsertions(): 914 for (B1,B2) in self.liste: 915 if (B2 is not None and (B2.type == 'I' or B2.type == 'R') and 916 B2.debut == d and B2.fin == f): break 917 else: raise AssertionError("Bloc I "+str((d,f))+" lost during BiblocList creation") 918 # Remplacements T1 919 for (d,f) in resultat.getListeRemplacementsT1(): 920 for (B1,B2) in self.liste: 921 if (B1 is not None and B1.type == 'R' and B1.debut == d and B1.fin == f): break 922 else: raise AssertionError("Bloc R1 "+str((d,f))+" lost during BiblocList creation") 923 # Remplacements T2 924 for (d,f) in resultat.getListeRemplacementsT2(): 925 for (B1,B2) in self.liste: 926 if (B2 is not None and B2.type == 'R' and B2.debut == d and B2.fin == f): break 927 else: raise AssertionError("Bloc R2 "+str((d,f))+" lost during BiblocList creation") 928 # Dep T1 929 for (d,f) in resultat.getListeDeplacementsT1(): 930 for (B1,B2) in self.liste: 931 if (B1 is not None and ((B1.type == 'D' and B1.debut == d and B1.fin == f) or 932 ((B1.type == 'S' or B1.type == 'R') and [d,f] in B1.lDep) or 933 (B1.type == 'S' and B1.debut == d and B1.fin == f))): break 934 else: raise AssertionError("Bloc Dep1 "+str((d,f))+" lost during BiblocList creation") 935 # BC T2 936 for (d,f) in resultat.getListeDeplacementsT2(): 937 for (B1,B2) in self.liste: 938 if (B2 is not None and ((B2.type == 'D' and B2.debut == d and B2.fin == f) or 939 ((B2.type == 'I' or B2.type == 'R') and [d,f] in B2.lDep) or 940 (B2.type == 'I' and B2.debut == d and B2.fin == f))): break 941 else: raise AssertionError("Bloc Dep2 "+str((d,f))+" lost during BiblocList creation")
942 943
944 - def extractRemplacements(self):
945 """ Recherche les S et I correspondant au critère de transformation en R et les convertit. 946 947 Convertit chaque paire de bibloc (S,None) et (None,I) se suivant en un bibloc (R,R) 948 Modifie directement self.liste plutôt que de recréer une nouvelle liste 949 ce qui est memory expensive""" 950 if len(self.liste) == 0: return 951 if __debug__: old_liste = self.liste[:] 952 tool = utile.Utile() 953 ratio_min_remplacement = float(100)/self.planTravail.getParam().getp2() 954 i = len(self.liste) - 2 955 while i >= 0: 956 biBloc = self.liste[i] # bibloc courant 957 biBlocSuiv = self.liste[i+1] # bibloc suivant 958 # on cherche un biblox S et un bibloc I qui se suivent et compatilbes 959 # pour être transformés en (R,R) 960 if (biBloc[0] is not None and biBloc[0].type == 'S' and biBlocSuiv[1] is not None and biBlocSuiv[1].type == 'I' and 961 tool.adequation_remplacement(self.texte[biBloc[0].debut:biBloc[0].fin], 962 self.texte[biBlocSuiv[1].debut:biBlocSuiv[1].fin], ratio_min_remplacement)): 963 self.liste[i:i+2] = [(Bloc('R',biBloc[0].debut,biBloc[0].fin,biBloc[0].lDep), 964 Bloc('R',biBlocSuiv[1].debut,biBlocSuiv[1].fin,biBlocSuiv[1].lDep))] 965 i -= 1 966 967 if __debug__: 968 self._testOrdre() 969 # on teste si on n'a perdu aucun elt de l'ancienne liste 970 for (B1,B2) in old_liste: 971 if B1 is not None: 972 for (BN1,BN2) in self.liste: 973 if (BN1 != None and B1.debut == BN1.debut and B1.fin == BN1.fin and 974 ((B1.type == 'S' and (BN1.type == 'S' or BN1.type == 'R') or 975 (B1.type == 'BC' and B1.type == 'BC')))): break 976 else: raise AssertionError, "elt B1 lost"+str(B1)+str(B2) 977 if B2 is not None: 978 for (BN1,BN2) in self.liste: 979 if (BN2 != None and B2.debut == BN2.debut and B2.fin == BN2.fin and 980 ((B2.type == 'I' and (BN2.type == 'I' or BN2.type == 'R') or 981 (B2.type == 'BC' and B2.type == 'BC')))): break 982 else: raise AssertionError, "elt B2 lost"+str(B1)+str(B2)
983
984 - def extractRemplacements__(self):
985 """ Recherche les S et I correspondant au critère de transformation en R et les convertit. 986 987 Convertit chaque paire de bibloc (S,None) et (None,I) se suivant en un bibloc (R,R) """ 988 if len(self.liste) == 0: return 989 tool = utile.Utile() 990 ratio_min_remplacement = float(100)/self.planTravail.getParam().getp2() 991 nouvelleListe = [] 992 dernierAjout = 'bloc' 993 for i in xrange(len(self.liste)-1): 994 biBloc = self.liste[i] # bibloc courant 995 biBlocSuiv = self.liste[i+1] # bibloc suivant 996 # on cherche un biblox S et un bibloc I qui se suivent et compatilbes 997 # pour être transformés en (R,R) 998 if (biBloc[0] is not None and biBloc[0].type == 'S' and biBlocSuiv[1] is not None and biBlocSuiv[1].type == 'I' and 999 tool.adequation_remplacement(self.texte[biBloc[0].debut:biBloc[0].fin], 1000 self.texte[biBlocSuiv[1].debut:biBlocSuiv[1].fin], ratio_min_remplacement)): 1001 nouvelleListe.append((Bloc('R',biBloc[0].debut,biBloc[0].fin,biBloc[0].lDep), 1002 Bloc('R',biBlocSuiv[1].debut,biBlocSuiv[1].fin,biBlocSuiv[1].lDep))) 1003 dernierAjout = 'R' 1004 # ce bibloc vient d'être transformé en R 1005 elif (biBloc[1] is not None and biBloc[1].type == 'I' and dernierAjout == 'R'): 1006 dernierAjout = 'bloc' 1007 else: 1008 nouvelleListe.append(biBloc) 1009 dernierAjout = 'bloc' 1010 if dernierAjout == 'bloc': 1011 nouvelleListe.append(self.liste[-1]) 1012 old_liste = self.liste 1013 self.liste = nouvelleListe 1014 if __debug__: 1015 self._testOrdre() 1016 # on teste si on n'a perdu aucun elt de l'ancienne liste 1017 for (B1,B2) in old_liste: 1018 if B1 is not None: 1019 for (BN1,BN2) in self.liste: 1020 if (BN1 != None and B1.debut == BN1.debut and B1.fin == BN1.fin and 1021 ((B1.type == 'S' and (BN1.type == 'S' or BN1.type == 'R') or 1022 (B1.type == 'BC' and B1.type == 'BC')))): break 1023 else: raise AssertionError, "elt B1 lost"+str(B1)+str(B2) 1024 if B2 is not None: 1025 for (BN1,BN2) in self.liste: 1026 if (BN2 != None and B2.debut == BN2.debut and B2.fin == BN2.fin and 1027 ((B2.type == 'I' and (BN2.type == 'I' or BN2.type == 'R') or 1028 (B2.type == 'BC' and B2.type == 'BC')))): break 1029 else: raise AssertionError, "elt B2 lost"+str(B1)+str(B2)
1030 1031
1032 - def toResultat(self):
1033 """ Transfomre la liste de biblocs en un Resultat 1034 1035 Attention !! la liste des PAIRES de blocs déplacés n'est pas remplie """ 1036 supp = []; ins = []; rempT1 = []; rempT2 = [] 1037 BCT1 = [];BCT2 = []; depT1 = []; depT2 = [] 1038 for (B1,B2) in self.liste: # parcours toute la liste de biblocs 1039 if B1 is not None: # suivant le type de B1, l'ajoute dans la bonne liste 1040 B1_type = B1.type 1041 if B1_type == 'S': supp.append([B1.debut,B1.fin]) 1042 elif B1_type == 'R': rempT1.append([B1.debut,B1.fin]) 1043 elif B1_type == 'D': depT1.append([B1.debut,B1.fin]) 1044 else: BCT1.append([B1.debut,B1.fin]) 1045 depT1.extend(B1.lDep) 1046 if B2 is not None:# suivant le type de B2, l'ajoute dans la bonne liste 1047 B2_type = B2.type 1048 if B2_type == 'I': ins.append([B2.debut,B2.fin]) 1049 elif B2_type == 'R': rempT2.append([B2.debut,B2.fin]) 1050 elif B2_type == 'D': depT2.append([B2.debut,B2.fin]) 1051 else: BCT2.append([B2.debut,B2.fin]) 1052 depT2.extend(B2.lDep) 1053 # on extend pour former les listes des 2 fichiers pour éviter d'utliser 1054 # la concaténation de liste qui crée une nouvelle liste 1055 depT1.extend(depT2) ; del depT2 1056 rempT1.extend(rempT2) ; del rempT2 1057 BCT1.extend(BCT2) ; del BCT2 1058 return Donnees.resultatAppli.Resultat(ins, supp, depT1, rempT1, 1059 self.lgSource, self.texte, BCT1, [])
1060
1061 - def evaluation(self):
1062 """Evalue l'alignement""" 1063 seq1 = self.lgSource 1064 seq2 = len(self.texte) - seq1 1065 ins = sup = remp1 = remp2 = bc1 = bc2 = dep1 = dep2 = 0.0 1066 for (B1,B2) in self.liste: 1067 if B1 is not None: 1068 B1_type = B1.type 1069 if B1_type == 'S': sup += B1.longueur 1070 elif B1_type == 'R': remp1 += B1.longueur 1071 elif B1_type == 'BC': bc1 += B1.longueur 1072 if B1_type == 'D': dep1 += B1.longueur 1073 else: dep1 += B1.longueur_deplacement 1074 if B2 is not None: 1075 B2_type = B2.type 1076 if B2_type == 'I': ins += B2.longueur 1077 elif B2_type == 'R': remp2 += B2.longueur 1078 elif B2_type == 'BC': bc2 += B2.longueur 1079 if B2_type == 'D': dep2 += B2.longueur 1080 else: dep2 += B2.longueur_deplacement 1081 1082 #if self.planTravail.getParam().get assert bc1 == bc2,str(bc1)+' '+str(bc2) 1083 formules = ['(bc1 + bc2)', 1084 '(dep1 + dep2)', 1085 '(bc1 + bc2) / (seq1 + seq2)', 1086 '(dep1 + dep2) / (seq1 + seq2)', 1087 '(bc1 + bc2 - dep1 - dep2)', 1088 '(bc1 + bc2 - dep1 - dep2) / (seq1 + seq2)', 1089 '(bc1 + bc2 - sup - ins - remp1 - remp2)', 1090 '(bc1 + bc2 - sup - ins - remp1 - remp2) / (seq1 + seq2)', 1091 '(bc1 + bc2 - sup - ins - remp1 - remp2 - dep1 - dep2)', 1092 '(bc1 + bc2 - sup - ins - remp1 - remp2 - dep1 - dep2) / (seq1 + seq2)', 1093 #'(sup + ins + remp1 + remp2 + dep1 + dep2)', 1094 #'(sup + ins + remp1 + remp2 + dep1 + dep2) / (seq1 + seq2)' 1095 ] 1096 #res = '' 1097 for f in formules: 1098 #res += f + ' = ' + str(round(eval(f),4)) + '\n' 1099 logging.info(f + ' = ' + str(round(eval(f),4)))
1100 #logging.info( ins, sup, remp1, remp2, bc1, bc2, dep1, dep2) 1101 #print res 1102
1103 - def print_html(self, dossierOutput=None):
1104 """ Imprime un rapport html à partir de la liste de biblocs 1105 dossierOutput: dossier où écrire le fichier HTML """ 1106 if len(self.liste) > 10: 1107 self.print_html_streaming(dossierOutput) 1108 else: 1109 self.print_html_oneshot(dossierOutput)
1110
1111 - def print_html_streaming(self, dossierOutput=None):
1112 """ Imprime un rapport html en plusieurs fois pour éviter de construire 1113 toute la chaine à substituer en mémoire 1114 dossierOutput: dossier où écrire le fichier HTML """ 1115 # ouverture du template ne contenant que le début du raport 1116 template = os.path.join(Utile.constantesDonnees.REPPRIVE,"template_rapport_stream.html") 1117 ftemplate = open(template,'r') 1118 stemplate = ''.join(ftemplate.readlines()) 1119 dgm = Controleurs.DGManager.DGManager() 1120 s = Template(stemplate) 1121 # substitution des variables 1122 sres = s.safe_substitute( 1123 FILE1 = dgm.getEtatPath(self.planTravail.getAuteur(), self.planTravail.getOeuvre(),self.planTravail.getVersionSource(),self.planTravail.getEtatSource()), 1124 FILE2 = dgm.getEtatPath(self.planTravail.getAuteur(), self.planTravail.getOeuvre(),self.planTravail.getVersionCible(),self.planTravail.getEtatCible()), 1125 PARAM_PIVOTS = self.planTravail.getParam().getp1(), 1126 RATIO_REMPLACEMENTS = self.planTravail.getParam().getp2(), 1127 SEUIL_DEPLACEMENTS = self.planTravail.getParam().getp3(), 1128 PARAM_CASSE = self.__paramToON(self.planTravail.getParam().getp5()), 1129 PARAM_SEPARATEURS = self.__paramToON(self.planTravail.getParam().getp6()), 1130 PARAM_DIACRITIQUES = self.__paramToON(self.planTravail.getParam().getp7())) 1131 # écriture du rapport 1132 if dossierOutput is not None: 1133 chemin = os.path.join(dossierOutput,"rapport.html") 1134 else: chemin = os.path.join(constantes.REPMEDITE,"rapport.html") 1135 fres = open(chemin,'w') 1136 fres.write(sres) # écriture de la première partie 1137 # ecriture en streaming de la table 1138 self.__listeToHtmlTable(stream=True, fileBuffer=fres) 1139 fres.write('</tbody></table><p></p></body></html>') 1140 fres.close()
1141
1142 - def print_html_oneshot(self, dossierOutput=None):
1143 """ Imprime un rapport html en une seule fois 1144 dossierOutput: dossier où écrire le fichier HTML """ 1145 # ouverture du template 1146 template = os.path.join(Utile.constantesDonnees.REPPRIVE,"template_rapport.html") 1147 ftemplate = open(template,'r') 1148 stemplate = ''.join(ftemplate.readlines()) 1149 dgm = Controleurs.DGManager.DGManager() 1150 s = Template(stemplate) 1151 # substitution des variables 1152 sres = s.safe_substitute( 1153 FILE1 = dgm.getEtatPath(self.planTravail.getAuteur(), self.planTravail.getOeuvre(),self.planTravail.getVersionSource(),self.planTravail.getEtatSource()), 1154 FILE2 = dgm.getEtatPath(self.planTravail.getAuteur(), self.planTravail.getOeuvre(),self.planTravail.getVersionCible(),self.planTravail.getEtatCible()), 1155 PARAM_PIVOTS = self.planTravail.getParam().getp1(), 1156 RATIO_REMPLACEMENTS = self.planTravail.getParam().getp2(), 1157 SEUIL_DEPLACEMENTS = self.planTravail.getParam().getp3(), 1158 PARAM_CASSE = self.__paramToON(self.planTravail.getParam().getp5()), 1159 PARAM_SEPARATEURS = self.__paramToON(self.planTravail.getParam().getp6()), 1160 PARAM_DIACRITIQUES = self.__paramToON(self.planTravail.getParam().getp7()), 1161 TABLE=self.__listeToHtmlTable()) 1162 # écriture du rapport 1163 if dossierOutput is not None: 1164 chemin = os.path.join(dossierOutput,"rapport.html") 1165 else: chemin = os.path.join(constantes.REPMEDITE,"rapport.html") 1166 fres = open(chemin,'w') 1167 fres.write(sres) 1168 fres.close()
1169
1170 - def __paramToON(self,param):
1171 """ Renvoie 'Oui' ou 'Non' en fonction d'un param booléen """ 1172 if param: return "Oui" 1173 else: return "Non"
1174
1175 - def __listeToHtmlTable(self, stream=False, fileBuffer=None):
1176 """ Convertit la liste de BiBlocs en une table html 1177 1178 Chaque Bibloc est convertit en une ligne <tr></tr> d'une table html 1179 Si stream, on ecrit régulièrement dans fileBuffer la table courante et 1180 on la réinitialise ensuite sinon on crée une grosse chaine que l'on renvoie""" 1181 assert stream==False or (stream and fileBuffer is not None) 1182 res = [] ; i = 0 1183 for (B1,B2) in self.liste: 1184 res.append('<tr>')# += "<tr>" # début de ligne 1185 # colonne gauche 1186 if B1 is None: res.append('<td></td>') # += "<td></td>" # bloc vide 1187 else: 1188 B1_type = B1.type 1189 if B1_type == 'S': res.extend(['<td style="background-color: #FF0000">',self.__souligneTexte(B1),'</td>']) # supp 1190 elif B1_type == 'R': res.extend(['<td style="background-color: #0000FF"> ',self.__souligneTexte(B1),'</td>']) # remp 1191 elif B1_type == 'D': res.extend(['<td>',self.__souligneTexte(B1),'</td>']) # dep 1192 else: res.extend(['<td>',self.__keepMEP(self.texte[B1.debut:B1.fin]),'</td>']) # BC 1193 # colonne droite 1194 if B2 is None: res.append('<td></td>') # bloc vide 1195 else: 1196 B2_type = B2.type 1197 if B2_type == 'I': res.extend(['<td style="background-color: #00FF00">',self.__souligneTexte(B2),'</td>']) #ins 1198 elif B2_type == 'R': res.extend(['<td style="background-color: #0000FF">',self.__souligneTexte(B2),'</td>']) # remp 1199 elif B2_type == 'D': res.extend(['<td>',self.__souligneTexte(B2),'</td>']) # dep 1200 else: res.extend(['<td>',self.__keepMEP(self.texte[B2.debut:B2.fin]),'</td>']) # BC 1201 res.append('</tr>\n') # fin de ligne 1202 if stream and i%50 == 0: 1203 fileBuffer.write(''.join(res)) 1204 res = [] 1205 1206 if stream: 1207 fileBuffer.write(''.join(res)) 1208 res = [] 1209 else: 1210 return ''.join(res)
1211
1212 - def __souligneTexte(self,bloc):
1213 """ Renvoie une chaine html avec le texte souligné aux caractères déplacés """ 1214 if bloc.type == 'D': 1215 return ('<span style="text-decoration: underline; font-weight: bold">'+ 1216 self.__keepMEP(self.texte[bloc.debut:bloc.fin])+'</span>') 1217 res = "" 1218 deb = i = bloc.debut 1219 fin = bloc.fin 1220 lDep = bloc.lDep[:] # on copie pour ne pas modifier la liste originale 1221 # on parcours tout le bloc pour chercher les déplacements à l'intérieur de celui-ci 1222 while i < fin: 1223 # si le caractère courant est le début d'un déplacement 1224 # <= (au lieu de ==) à cause des chevauchements de déplacements du genre ('I', 5221, 5239, [(5224, 5230), (5226, 5231), (5236, 5239)]) 1225 if len(lDep) > 0 and lDep[0][0] <= i: 1226 res += '<span style="text-decoration: underline; font-weight: bold">'+self.__keepMEP(self.texte[i:lDep[0][1]])+'</span>' 1227 i = lDep[0][1] 1228 lDep.pop(0) 1229 elif len(lDep) > 0 and lDep[0][0] > i: # si on est sur du texte normal 1230 res += self.__keepMEP(self.texte[i:lDep[0][0]]) 1231 i = lDep[0][0] 1232 else: # si pas ou plus de déplacement 1233 assert len(lDep)==0 1234 res += self.__keepMEP(self.texte[i:fin]) 1235 i = fin 1236 return res
1237
1238 - def __keepMEP(self, texte):
1239 """ Fonction chargée de conserver la mise en page du texte original 1240 1241 Remplace les retours à la ligne par des <br> et les espaces par des &nbsp; 1242 1243 Le remplacement des espaces par des nbsp est très utile pour visulaiser des 1244 alignements de code source mais plus discutable pour de la langue nat. 1245 De même mais de façon moins importante pour les br.""" 1246 return texte 1247 res = "" 1248 for i in xrange(len(texte)): 1249 if texte[i] in '\r\n': res += '<br>' 1250 #elif texte[i] in ' ': res += '&nbsp;' 1251 else: # remplace tous les caractères spéciaux par leur code html comme &nbsp; 1252 try: res += '&' + htmlentitydefs.codepoint2name[ord(texte[i])] + ';' 1253 except KeyError: res += texte[i] 1254 return res
1255
1256 -class BiBlocListWD__(BiBlocList__):
1257 """BiblocList avec type déplacement (D) autorisé """
1258 - def __init__(self,resultat,planTravail,depOrdonnes=True):
1259 BiBlocList.__init__(self,resultat,planTravail,depOrdonnes) 1260 self.evaluation() 1261 logging.debug('extractDeplacements()') 1262 self.extractDeplacements() 1263 self.evaluation()
1264
1265 - def extractDeplacements(self):
1266 """ Extraction des déplacements 1267 1268 Teste les blocs insérés et supprimés. 1269 Si le rapport des déplacements à l'intérieur d'un bloc est supérieur au seuil 1270 Alors ce bloc est scindé en une liste de blocs (I ou S) et D 1271 Modifie directement self.liste""" 1272 tool = utile.Utile() 1273 ratio_seuil_lissage = float(self.planTravail.getParam().getp3()) /100 1274 #nouvelleListe = [] 1275 i = len(self.liste) - 1 1276 while i >= 0: 1277 (B1,B2) = self.liste[i] 1278 if (B1 is not None and B1.type == 'S'): # bloc S 1279 assert B2 is None 1280 supMoinsDep = tool.soustr_l_intervalles([[B1.debut,B1.fin]], B1.lDep) # bloc S moins les dep 1281 ratio_lissage = float(tool.longueur(supMoinsDep))/(B1.fin-B1.debut) # ratio du bloc 1282 if ratio_lissage <= ratio_seuil_lissage: 1283 self.liste[i:i+1] = self.__extractDepInsSup(supMoinsDep,B1.lDep,'S') 1284 elif (B2 is not None and B2.type == 'I'):# bloc I 1285 assert B1 is None 1286 insMoinsDep = tool.soustr_l_intervalles([[B2.debut,B2.fin]], B2.lDep) 1287 ratio_lissage = float(tool.longueur(insMoinsDep))/(B2.fin-B2.debut) 1288 if ratio_lissage <= ratio_seuil_lissage: 1289 self.liste[i:i+1] = self.__extractDepInsSup(insMoinsDep,B2.lDep,'I') 1290 i -= 1 1291 if __debug__: 1292 self._testOrdre()
1293
1294 - def extractDeplacements__old(self):
1295 """ Extraction des déplacements 1296 1297 Teste les blocs insérés et supprimés. 1298 Si le rapport des déplacements à l'intérieur d'un bloc est supérieur au seuil 1299 Alors ce bloc est scindé en une liste de blocs (I ou S) et D""" 1300 tool = utile.Utile() 1301 ratio_seuil_lissage = float(self.planTravail.getParam().getp3()) /100 1302 nouvelleListe = [] 1303 for (B1,B2) in self.liste: 1304 if (B1 is not None and B1.type == 'S'): # bloc S 1305 assert B2 is None 1306 supMoinsDep = tool.soustr_l_intervalles([[B1.debut,B1.fin]], B1.lDep) # bloc S moins les dep 1307 ratio_lissage = float(tool.longueur(supMoinsDep))/(B1.fin-B1.debut) # ratio du bloc 1308 if ratio_lissage > ratio_seuil_lissage: 1309 nouvelleListe.append((B1,None)) 1310 else: 1311 nouvelleListe.extend(self.__extractDepInsSup(supMoinsDep,B1.lDep,'S')) 1312 elif (B2 is not None and B2.type == 'I'):# bloc I 1313 assert B1 is None 1314 insMoinsDep = tool.soustr_l_intervalles([[B2.debut,B2.fin]], B2.lDep) 1315 ratio_lissage = float(tool.longueur(insMoinsDep))/(B2.fin-B2.debut) 1316 if ratio_lissage > ratio_seuil_lissage: 1317 nouvelleListe.append((None,B2)) 1318 else: 1319 nouvelleListe.extend(self.__extractDepInsSup(insMoinsDep,B2.lDep,'I')) 1320 else: # autres blocs: R et BC 1321 nouvelleListe.append((B1,B2)) 1322 self.liste = nouvelleListe 1323 if __debug__: 1324 self._testOrdre()
1325
1326 - def __extractDepInsSup(self,lSupOrIns,listeDep,SorI):
1327 """On scinde effectivement le blocs en une liste de blocs (S ou I) et D 1328 1329 lSupOrIns: liste de (I ou S) 1330 listeDep: liste de D 1331 SorI: traite-on des S ou des I ? 1332 pre: isinstance(lSupOrIns,list) and isinstance(listeDep,list) 1333 (SorI == 'S' or SorI == 'I') """ 1334 nouvelleListe = [] 1335 len_listeDep = len(listeDep) 1336 prevdeb = nbDep = 0 1337 while len(lSupOrIns) > 0 or len(listeDep) > 0: 1338 # on a ajouté tous les D, on peut ajouter le reste des (I ou S) 1339 if len(listeDep) == 0: 1340 for (deb,fin) in lSupOrIns: # pour chaque bloc (I ou S) 1341 assert prevdeb <= deb # assertion d'ordre 1342 prevdeb = deb 1343 if SorI == 'S': nouvelleListe.append((Bloc('S',deb,fin,[]),None)) # ajout effectif 1344 else: nouvelleListe.append((None,Bloc('I',deb,fin,[]))) 1345 lSupOrIns = [] 1346 # on a ajouté tous les (I ou S), on peut ajouter les reste des D 1347 elif len(lSupOrIns) == 0: 1348 for (deb,fin) in listeDep: # pour chaque bloc D 1349 assert prevdeb <= deb 1350 prevdeb = deb 1351 if SorI == 'S': nouvelleListe.append((BlocWD('D',deb,fin,[]),None)) 1352 else: nouvelleListe.append((None,BlocWD('D',deb,fin,[]))) 1353 nbDep += 1 1354 listeDep = [] 1355 # si bloc courant (I ou S) <= bloc courant D alors on l'ajoute 1356 elif lSupOrIns[0][0] <= listeDep[0][0]: 1357 assert prevdeb <= lSupOrIns[0][0] 1358 prevdeb = lSupOrIns[0][0] 1359 if SorI == 'S': nouvelleListe.append((Bloc('S',lSupOrIns[0][0],lSupOrIns[0][1],[]),None)) 1360 else: nouvelleListe.append((None,Bloc('I',lSupOrIns[0][0],lSupOrIns[0][1],[]))) 1361 #lSupOrIns = lSupOrIns[1:] 1362 lSupOrIns.pop(0) 1363 else: 1364 assert prevdeb <= listeDep[0][0] 1365 prevdeb = listeDep[0][0] 1366 if SorI == 'S': nouvelleListe.append((BlocWD('D',listeDep[0][0],listeDep[0][1],[]),None)) 1367 else: nouvelleListe.append((None,BlocWD('D',listeDep[0][0],listeDep[0][1],[]))) 1368 listeDep.pop(0) 1369 nbDep += 1 1370 assert len(listeDep) == len(lSupOrIns) == 0 # les 2 listes ont du etre traitées entièrement 1371 assert nbDep == len_listeDep 1372 return nouvelleListe
1373 1374
1375 -class BiBlocList(object):
1376 """ Construit une liste de Bibloc 1377 1378 Un Bibloc est un tuplet de 2 Bloc alignés. 1379 Un Bloc est un objet (type,début,fin,listeDep) ou None si il est vide. 1380 type est soit I,S,R,BC 1381 debut et fin sont les limites du bloc dans la chaine de texte. 1382 listeDep est une liste éventuellement vide listant tous les intervalles de déplacement compris dans le bloc. 1383 Les blocs I et S sont alignés forcément avec des blocs None. 1384 Les blocs R et BC sont alignés forcément avec des blocs respectivement R et BC. """
1385 - def __init__(self,resultat,planTravail,depOrdonnes=True):
1386 """ Constructeur 1387 1388 Si on utilise l'ancien algo d'identification des remplacements et déplacements, 1389 on peut avoir des blocs présents uniquement dans resultat.getListeDeplacements(). 1390 Ceux-ci sont alors ajoutés comme des S ou des I. 1391 1392 dd: si depOrdonnes=False, pas d'assertion d'ordre sur les déplacement-> recherche d'un dep en O(n) dans __decoreDep1() 1393 sinon si depOrdonnes=True, assertion d'ordre respectée -> recherche en O(log n) dans __decoreDep2() 1394 1395 pre: isinstance(resultat,Donnees.resultatAppli.Resultat) 1396 isinstance(planTravail,Donnees.planTravail.PlanTravail) """ 1397 self.depOrdonnes = depOrdonnes 1398 #def gg(liste): 1399 # if len(liste)>0: return str(liste[0]) 1400 # else: return '' 1401 self.texte = resultat.getTextesConcatenes() 1402 self.lgSource = resultat.getLgSource() 1403 self.planTravail = planTravail # sert seulement à l'affichage du rapport 1404 1405 liste = [] 1406 lBCT1 = resultat.getBlocsCommunsT1() 1407 lBCT2 = resultat.getBlocsCommunsT2() 1408 assert len(lBCT1) == len(lBCT2),str(len(lBCT1))+'/'+str(len(lBCT2)) 1409 lRempT1 = resultat.getListeRemplacementsT1() 1410 lRempT2 = resultat.getListeRemplacementsT2() 1411 assert len(lRempT1) == len(lRempT2) 1412 lIns = resultat.getListeInsertions() 1413 lSup = resultat.getListeSuppressions() 1414 lDepT1 = resultat.getListeDeplacementsT1() #; print lDepT1 1415 lDepT2 = resultat.getListeDeplacementsT2() # ; print lDepT2 1416 i=0 1417 len_lBCT1 = len(lBCT1) ; len_lBCT2 = len(lBCT2) ; len_lRempT1 = len(lRempT1) 1418 len_lRempT2 = len(lRempT2) ; len_lSup = len(lSup) ; len_lIns = len(lIns) 1419 len_lDepT1 = len(lDepT1) ; len_lDepT2 = len(lDepT2) 1420 while (len_lBCT1 > 0 or len_lBCT2 > 0 or len_lRempT1 > 0 or 1421 len_lRempT2 > 0 or len_lSup > 0 or len_lIns > 0 or 1422 len_lDepT1 > 0 or len_lDepT2 > 0): 1423 assert len_lBCT1 == len_lBCT2 1424 assert len_lRempT1 == len_lRempT2 1425 #if i%1000==0: logging.debug('itération %d',i) 1426 i += 1 1427 #print len_lDepT1,len_lDepT2 1428 c="""print '-----------------------' 1429 print len(lSup),len(lRempT1),len(lBCT1),len(lDepT1) 1430 print len(lIns),len(lRempT2),len(lBCT2),len(lDepT2) 1431 print gg(lSup),gg(lRempT1),gg(lBCT1),gg(lDepT1) 1432 print gg(lIns),gg(lRempT2),gg(lBCT2),gg(lDepT2)""" 1433 # pour ajouter un bloc sup soit les 2 listes sont vides 1434 # soit BC vides et <= dep car dans ce cas le dep sera inclus dans le sup 1435 # soit < BC car pas de chevauchement entre sup et dep 1436 if (len_lSup > 0 and 1437 ((len_lBCT1 == 0 and len_lDepT1 == 0) or 1438 (len_lBCT1 == 0 and lSup[0][0] <= lDepT1[0][0]) or 1439 (len_lDepT1 == 0 and lSup[0][0] < lBCT1[0][0]) or 1440 (len_lBCT1 > 0 and len_lDepT1 > 0 and lSup[0][0] < lBCT1[0][0] and lSup[0][0] <= lDepT1[0][0]))): # ajout sup 1441 depInBloc1 = self.__decoreDep(lSup[0], lDepT1) #décoration avec les déplacements 1442 liste.append((('S',lSup[0][0],lSup[0][1],depInBloc1),None)) # ajout du bibloc 1443 lSup.pop(0) ; len_lSup -= 1 ; len_lDepT1 -= len(depInBloc1) 1444 elif (len_lIns > 0 and 1445 ((len_lBCT2 == 0 and len_lDepT2 == 0) or 1446 (len_lBCT2 == 0 and lIns[0][0] <= lDepT2[0][0]) or 1447 (len_lDepT2 == 0 and lIns[0][0] < lBCT2[0][0]) or 1448 (len_lBCT2 > 0 and len_lDepT2 > 0 and lIns[0][0] < lBCT2[0][0] and lIns[0][0] <= lDepT2[0][0]))): # ajout ins 1449 depInBloc2 = self.__decoreDep(lIns[0], lDepT2) #décoration avec les déplacements 1450 liste.append((None,('I',lIns[0][0],lIns[0][1],depInBloc2))) # ajout du bibloc 1451 lIns.pop(0) ; len_lIns -= 1 ; len_lDepT2 -= len(depInBloc2) 1452 # si depT1 < rempT1 et BCT1, ajout dep comme une sup 1453 elif (len_lDepT1 > 0 and 1454 ((len_lBCT1 == 0 and len_lRempT1 == 0) or 1455 (len_lBCT1 == 0 and lDepT1[0][0] < lRempT1[0][0]) or 1456 (len_lRempT1 == 0 and lDepT1[0][0] < lBCT1[0][0]) or 1457 (len_lBCT1 > 0 and len_lRempT1 > 0 and lDepT1[0][0] < lBCT1[0][0] and lDepT1[0][0] <lRempT1[0][0]))): 1458 liste.append((('S',lDepT1[0][0],lDepT1[0][1],[[lDepT1[0][0],lDepT1[0][1]]]),None)) # ajout du bibloc 1459 lDepT1.pop(0) ; len_lDepT1 -= 1 1460 elif (len_lDepT2 > 0 and 1461 ((len_lBCT2 == 0 and len_lRempT2 == 0) or 1462 (len_lBCT2 == 0 and lDepT2[0][0] < lRempT2[0][0]) or 1463 (len_lRempT2 == 0 and lDepT2[0][0] < lBCT2[0][0]) or 1464 (len_lBCT2 > 0 and len_lRempT2 > 0 and lDepT2[0][0] < lBCT2[0][0] and lDepT2[0][0] <lRempT2[0][0]))): # ajout dep comme une ins 1465 liste.append((None,('I',lDepT2[0][0],lDepT2[0][1],[[lDepT2[0][0],lDepT2[0][1]]]))) # ajout du bibloc 1466 lDepT2.pop(0) ; len_lDepT2 -= 1 1467 elif (len_lRempT1 > 0 and len_lRempT2 > 0 and 1468 ((len_lBCT1 == 0 and len_lBCT2 == 0) or 1469 (lRempT1[0][0] < lBCT1[0][0] and lRempT2[0][0] < lBCT2[0][0]))): 1470 com="""((len_lBCT1 == 0 and len_lBCT2 == 0 and len_lDepT1 == 0 and len_lDepT2 == 0) or 1471 (len_lBCT1 == 0 and len_lBCT2 == 0 and len_lDepT1 == 0 and lRempT2[0][0] <= lDepT2[0][0]) or 1472 (len_lBCT1 == 0 and len_lBCT2 == 0 and lRempT1[0][0] <= lDepT1[0][0] and len_lDepT2 == 0) or 1473 (len_lBCT1 == 0 and len_lBCT2 == 0 and lRempT1[0][0] <= lDepT1[0][0] and lRempT2[0][0] <= lDepT2[0][0]) or 1474 (len_lBCT1 > 0 and len_lBCT2 > 0 and len_lDepT1 == 0 and len_lDepT2 == 0 and lRempT1[0][0] < lBCT1[0][0] and lRempT2[0][0] < lBCT2[0][0]) or 1475 (len_lBCT1 > 0 and len_lBCT2 > 0 and len_lDepT1 == 0 and lRempT2[0][0] <= lDepT2[0][0] and lRempT1[0][0] < lBCT1[0][0] and lRempT2[0][0] < lBCT2[0][0]) or 1476 (len_lBCT1 > 0 and len_lBCT2 > 0 and lRempT1[0][0] <= lDepT1[0][0] and len_lDepT2 == 0 and lRempT1[0][0] < lBCT1[0][0] and lRempT2[0][0] < lBCT2[0][0]) or 1477 (len_lBCT1 > 0 and len_lBCT2 > 0 and len_lDepT1 > 0 and len_lDepT2 > 0 and 1478 lRempT1[0][0] < lBCT1[0][0] and lRempT2[0][0] < lBCT2[0][0] ))): # and lRempT1[0][0] <= lDepT1[0][0] and lRempT2[0][0] <= lDepT2[0][0]))): # ajout remp 1479 """ 1480 depInBloc1 = self.__decoreDep(lRempT1[0], lDepT1) #décoration avec les déplacements 1481 depInBloc2 = self.__decoreDep(lRempT2[0], lDepT2) #décoration avec les déplacements 1482 liste.append((('R',lRempT1[0][0],lRempT1[0][1],depInBloc1), 1483 ('R',lRempT2[0][0],lRempT2[0][1],depInBloc2))) # ajout du bibloc 1484 #print liste[-1][0],liste[-1][1] 1485 lRempT1.pop(0) ; len_lRempT1 -= 1 ; len_lDepT1 -= len(depInBloc1) 1486 lRempT2.pop(0) ; len_lRempT2 -= 1 ; len_lDepT2 -= len(depInBloc2) 1487 1488 # elif len_lDepT1 > 0 and (len_lBCT1 == 0 or lDepT1[0][0] < lBCT1[0][0]): # ajout dep comme une sup 1489 # liste.append((Bloc('S',lDepT1[0][0],lDepT1[0][1],[[lDepT1[0][0],lDepT1[0][1]]]),None)) # ajout du bibloc 1490 # lDepT1 = lDepT1[1:] 1491 # elif len_lDepT2 > 0 and (len_lBCT2 == 0 or lDepT2[0][0] < lBCT2[0][0]): # ajout dep comme une ins 1492 # liste.append((None,Bloc('I',lDepT2[0][0],lDepT2[0][1],[[lDepT2[0][0],lDepT2[0][1]]]))) # ajout du bibloc 1493 # lDepT2 = lDepT2[1:] 1494 else: # ajout BC 1495 liste.append((('BC',lBCT1[0][0],lBCT1[0][1],[]),('BC',lBCT2[0][0],lBCT2[0][1],[]))) # ajout du bibloc 1496 lBCT1.pop(0) ; len_lBCT1 -= 1 1497 lBCT2.pop(0) ; len_lBCT2 -= 1 1498 1499 self.liste = liste # liste des biblocs 1500 if False and __debug__: 1501 assert len_lSup == len_lIns == 0 1502 assert len_lRempT1 == len_lRempT2 == 0 1503 assert len_lBCT1 == len_lBCT2 == 0 1504 assert len_lDepT1 == len_lDepT2 == 0 1505 self._testOrdre() 1506 self._testNonPerte(resultat) 1507 1508 if len(resultat.getListeRemplacements()) == 0: 1509 try: 1510 self.evaluation() 1511 except ZeroDivisionError: 1512 logging.debug("Erreur d'evaluation ZeroDivisionError") 1513 logging.debug('extractRemplacements()') 1514 self.extractRemplacements()
1515
1516 - def __decoreDep(self, intervalle, lDep):
1517 if not self.depOrdonnes: 1518 return self.__decoreDep_1(intervalle, lDep) 1519 else: 1520 return self.__decoreDep_3(intervalle, lDep)
1521 - def __decoreDep_1(self, intervalle, lDep):
1522 """ Extrait de la liste générale des déplacement lDep les déplacements se situant à l'intérieur du bloc 1523 1524 Attention !! modifie lDep 1525 Comme sur les déplacements on n'a pas d'assertions sur l'ordre, 1526 on parcourt à chaque appel de cette fonction toute la liste des déplacements.""" 1527 #if len(lDep) == 0: return [],[] 1528 if len(lDep) == 0: return [] 1529 res = [] 1530 nouvelleLDep = [] 1531 for [d,f] in lDep: 1532 #assert isinstance(d, list),str(type(d))+str(d) 1533 if intervalle[0] <= d and f <= intervalle[1] : # déplacement inlcus dans l'intervalle 1534 res.append([d,f]) 1535 else: nouvelleLDep.append([d,f]) 1536 assert len(lDep) == len(nouvelleLDep) + len(res) 1537 lDep = nouvelleLDep 1538 #return nouvelleLDep,res 1539 return res
1540
1541 - def __decoreDep_2(self, intervalle, lDep):
1542 """ Extrait de la liste générale des déplacement lDep les déplacements se situant à l'intérieur du bloc 1543 1544 Attention !! modifie lDep et retourne res2 1545 Ici assertion d'ordre sur les dep, recherhe d'un dep en log(n) 1546 """ 1547 #if len(lDep) == 0: return [],[] 1548 if len(lDep) == 0: return [] 1549 deb = bisect.bisect(lDep, intervalle[0]) 1550 fin = bisect.bisect(lDep, intervalle[1]) 1551 assert deb <= fin 1552 if deb == fin: # aucun déplacement n'existe dans la liste entre les 2 intervalles 1553 #return lDep,[] 1554 return [] 1555 else: 1556 res2 = lDep[deb:fin] 1557 lDep[deb:fin] = [] 1558 #lDep = lDep[:deb]+lDep[fin:] 1559 #return lDep[:deb]+lDep[fin:], lDep[deb:fin] 1560 return res2
1561
1562 - def __decoreDep_3(self, intervalle, lDep):
1563 """ Extrait de la liste générale des déplacement lDep les déplacements se situant à l'intérieur du bloc 1564 1565 Attention !! modifie lDep et retourne res2 1566 Ici assertion d'ordre sur les dep, recherhe d'un dep en temps linéaire 1567 comme lDep[0] est toujours >= intervalle (parce que l'ordre est maintenu par la 1568 fonction appelante), on commence la recherche à partir de là 1569 """ 1570 if len(lDep) == 0: return [] 1571 res2 = [] 1572 i = 0 1573 1574 # print 'dep',lDep[0] 1575 # print 'inter',intervalle[1],intervalle[0] 1576 while len(lDep)>0 and (lDep[0][0] >= intervalle[0]) and (lDep[0][1] <= intervalle[1]): 1577 i+= 1 1578 res2.append(lDep.pop(0)) # mofifie lDep !! 1579 return res2
1580
1581 - def _testOrdre(self):
1582 """ Teste le bon ordre des blocs dans la liste """ 1583 posT1 = 0 # position courante dans le texte source 1584 posT2 = self.lgSource # position courante dans le texte cible 1585 prevB1 = prevB2 = (0,0,0,[]) 1586 for (B1,B2) in self.liste: 1587 if B1 is not None: 1588 # la position précédente est <= au début du bloc courant 1589 assert posT1 <= B1[1],str(posT1)+' '+str(prevB1)+' '+str(B1) 1590 posT1 = B1[2] 1591 for dep in B1[3]:# les déplacements sont bien inclus dans le bloc courant 1592 assert B1[1] <= dep[0] <= dep[1] <= B1[2] 1593 prevB1 = B1 1594 if B2 is not None: 1595 assert posT2 <= B2[1], str(posT2)+' '+str(prevB2)+' '+str(B2) 1596 posT2 = B2[2] 1597 for dep in B2[3]: 1598 assert B2[1] <= dep[0] <= dep[1] <= B2[2] 1599 prevB2 = B2
1600
1601 - def _testNonPerte(self, resultat):
1602 """Teste la non-perte de données lors de la création du BiblocList 1603 1604 On teste si chaque element dans les listes de la donnée en entrée (param Resultat) 1605 est bien présent en sortie dans self.liste """ 1606 # BC T1 1607 for (d,f) in resultat.getBlocsCommunsT1(): 1608 for (B1,B2) in self.liste: 1609 if (B1 is not None and B1[0] == 'BC' and B1[1] == d and B1[2] == f): break 1610 else: raise AssertionError("Bloc BC1 "+str((d,f))+" lost during BiblocList creation") 1611 # BC T2 1612 for (d,f) in resultat.getBlocsCommunsT2(): 1613 for (B1,B2) in self.liste: 1614 if (B2 is not None and B2[0] == 'BC' and B2[1] == d and B2[2] == f): break 1615 else: raise AssertionError("Bloc BC2 "+str((d,f))+" lost during BiblocList creation") 1616 # Suppressions 1617 for (d,f) in resultat.getListeSuppressions(): 1618 for (B1,B2) in self.liste: 1619 if (B1 is not None and (B1[0] == 'S' or B1[0] == 'R') and 1620 B1[1] == d and B1[2] == f): break 1621 else: raise AssertionError("Bloc S "+str((d,f))+" lost during BiblocList creation") 1622 # Insertions 1623 for (d,f) in resultat.getListeInsertions(): 1624 for (B1,B2) in self.liste: 1625 if (B2 is not None and (B2[0] == 'I' or B2[0] == 'R') and 1626 B2[1] == d and B2[2] == f): break 1627 else: raise AssertionError("Bloc I "+str((d,f))+" lost during BiblocList creation") 1628 # Remplacements T1 1629 for (d,f) in resultat.getListeRemplacementsT1(): 1630 for (B1,B2) in self.liste: 1631 if (B1 is not None and B1[0] == 'R' and B1[1] == d and B1[2] == f): break 1632 else: raise AssertionError("Bloc R1 "+str((d,f))+" lost during BiblocList creation") 1633 # Remplacements T2 1634 for (d,f) in resultat.getListeRemplacementsT2(): 1635 for (B1,B2) in self.liste: 1636 if (B2 is not None and B2[0] == 'R' and B2[1] == d and B2[2] == f): break 1637 else: raise AssertionError("Bloc R2 "+str((d,f))+" lost during BiblocList creation") 1638 # Dep T1 1639 for (d,f) in resultat.getListeDeplacementsT1(): 1640 for (B1,B2) in self.liste: 1641 if (B1 is not None and ((B1[0] == 'D' and B1[1] == d and B1[2] == f) or 1642 ((B1[0] == 'S' or B1[0] == 'R') and [d,f] in B1[3]) or 1643 (B1[0] == 'S' and B1[1] == d and B1[2] == f))): break 1644 else: raise AssertionError("Bloc Dep1 "+str((d,f))+" lost during BiblocList creation") 1645 # BC T2 1646 for (d,f) in resultat.getListeDeplacementsT2(): 1647 for (B1,B2) in self.liste: 1648 if (B2 is not None and ((B2[0] == 'D' and B2[1] == d and B2[2] == f) or 1649 ((B2[0] == 'I' or B2[0] == 'R') and [d,f] in B2[3]) or 1650 (B2[0] == 'I' and B2[1] == d and B2[2] == f))): break 1651 else: raise AssertionError("Bloc Dep2 "+str((d,f))+" lost during BiblocList creation")
1652 1653
1654 - def extractRemplacements(self):
1655 """ Recherche les S et I correspondant au critère de transformation en R et les convertit. 1656 1657 Convertit chaque paire de bibloc (S,None) et (None,I) se suivant en un bibloc (R,R) 1658 Modifie directement self.liste plutôt que de recréer une nouvelle liste 1659 ce qui est memory expensive""" 1660 if len(self.liste) == 0: return 1661 if __debug__: old_liste = self.liste[:] 1662 tool = utile.Utile() 1663 ratio_min_remplacement = float(100)/self.planTravail.getParam().getp2() 1664 i = len(self.liste) - 2 1665 while i >= 0: 1666 if i%1000 == 0: logging.debug("itérationR %d",i) 1667 biBloc = self.liste[i] # bibloc courant 1668 biBlocSuiv = self.liste[i+1] # bibloc suivant 1669 # on cherche un biblox S et un bibloc I qui se suivent et compatilbes 1670 # pour être transformés en (R,R) 1671 if (biBloc[0] is not None and biBloc[0][0] == 'S' and 1672 biBlocSuiv[1] is not None and biBlocSuiv[1][0] == 'I' and 1673 tool.adequation_remplacement(self.texte[biBloc[0][1]:biBloc[0][2]], 1674 self.texte[biBlocSuiv[1][1]:biBlocSuiv[1][2]], ratio_min_remplacement)): 1675 self.liste[i:i+2] = [(('R',biBloc[0][1],biBloc[0][2],biBloc[0][3]), 1676 ('R',biBlocSuiv[1][1],biBlocSuiv[1][2],biBlocSuiv[1][3]))] 1677 i -= 1 1678 1679 if False and __debug__: 1680 self._testOrdre() 1681 # on teste si on n'a perdu aucun elt de l'ancienne liste 1682 for (B1,B2) in old_liste: 1683 if B1 is not None: 1684 for (BN1,BN2) in self.liste: 1685 if (BN1 is not None and B1[1] == BN1[1] and B1[2] == BN1[2] and 1686 (((B1[0] == 'S' or B1[0] == 'D') and (BN1[0] == 'S' or BN1[0] == 'R' or BN1[0] == 'D') or 1687 (B1[0] == 'BC' and B1[0] == 'BC')))): break 1688 else: raise AssertionError, "elt B1 lost"+str(B1)+str(B2) 1689 if B2 is not None: 1690 for (BN1,BN2) in self.liste: 1691 if (BN2 is not None and B2[1] == BN2[1] and B2[2] == BN2[2] and 1692 (((B2[0] == 'I' or B2[0] == 'D') and (BN2[0] == 'I' or BN2[0] == 'R' or BN1[0] == 'D') or 1693 (B2[0] == 'BC' and B2[0] == 'BC')))): break 1694 else: raise AssertionError, "elt B2 lost"+str(B1)+str(B2)
1695
1696 - def extractRemplacements__(self):
1697 """ Recherche les S et I correspondant au critère de transformation en R et les convertit. 1698 1699 Convertit chaque paire de bibloc (S,None) et (None,I) se suivant en un bibloc (R,R) """ 1700 if len(self.liste) == 0: return 1701 tool = utile.Utile() 1702 ratio_min_remplacement = float(100)/self.planTravail.getParam().getp2() 1703 nouvelleListe = [] 1704 dernierAjout = 'bloc' 1705 for i in xrange(len(self.liste)-1): 1706 biBloc = self.liste[i] # bibloc courant 1707 biBlocSuiv = self.liste[i+1] # bibloc suivant 1708 # on cherche un biblox S et un bibloc I qui se suivent et compatilbes 1709 # pour être transformés en (R,R) 1710 if (biBloc[0] is not None and biBloc[0][0] == 'S' and biBlocSuiv[1] is not None and biBlocSuiv[1][0] == 'I' and 1711 tool.adequation_remplacement(self.texte[biBloc[0][1]:biBloc[0][2]], 1712 self.texte[biBlocSuiv[1][1]:biBlocSuiv[1][2]], ratio_min_remplacement)): 1713 nouvelleListe.append((Bloc('R',biBloc[0][1],biBloc[0][2],biBloc[0][3]), 1714 Bloc('R',biBlocSuiv[1][1],biBlocSuiv[1][2],biBlocSuiv[1][3]))) 1715 dernierAjout = 'R' 1716 # ce bibloc vient d'être transformé en R 1717 elif (biBloc[1] is not None and biBloc[1][0] == 'I' and dernierAjout == 'R'): 1718 dernierAjout = 'bloc' 1719 else: 1720 nouvelleListe.append(biBloc) 1721 dernierAjout = 'bloc' 1722 if dernierAjout == 'bloc': 1723 nouvelleListe.append(self.liste[-1]) 1724 old_liste = self.liste 1725 self.liste = nouvelleListe 1726 if __debug__: 1727 self._testOrdre() 1728 # on teste si on n'a perdu aucun elt de l'ancienne liste 1729 for (B1,B2) in old_liste: 1730 if B1 is not None: 1731 for (BN1,BN2) in self.liste: 1732 if (BN1 != None and B1[1] == BN1[1] and B1[2] == BN1[2] and 1733 ((B1[0] == 'S' and (BN1[0] == 'S' or BN1[0] == 'R') or 1734 (B1[0] == 'BC' and B1[0] == 'BC')))): break 1735 else: raise AssertionError, "elt B1 lost"+str(B1)+str(B2) 1736 if B2 is not None: 1737 for (BN1,BN2) in self.liste: 1738 if (BN2 != None and B2[1] == BN2[1] and B2[2] == BN2[2] and 1739 ((B2[0] == 'I' and (BN2[0] == 'I' or BN2[0] == 'R') or 1740 (B2[0] == 'BC' and B2[0] == 'BC')))): break 1741 else: raise AssertionError, "elt B2 lost"+str(B1)+str(B2)
1742 1743
1744 - def toResultat(self):
1745 """ Transfomre la liste de biblocs en un Resultat 1746 1747 Attention !! la liste des PAIRES de blocs déplacés n'est pas remplie """ 1748 supp = []; ins = []; rempT1 = []; rempT2 = [] 1749 BCT1 = [];BCT2 = []; depT1 = []; depT2 = [] 1750 for (B1,B2) in self.liste: # parcours toute la liste de biblocs 1751 if B1 is not None: # suivant le type de B1, l'ajoute dans la bonne liste 1752 B1_type = B1[0] 1753 if B1_type == 'S': supp.append([B1[1],B1[2]]) 1754 elif B1_type == 'R': rempT1.append([B1[1],B1[2]]) 1755 elif B1_type == 'D': depT1.append([B1[1],B1[2]]) 1756 else: BCT1.append([B1[1],B1[2]]) 1757 depT1.extend(B1[3]) 1758 if B2 is not None:# suivant le type de B2, l'ajoute dans la bonne liste 1759 B2_type = B2[0] 1760 if B2_type == 'I': ins.append([B2[1],B2[2]]) 1761 elif B2_type == 'R': rempT2.append([B2[1],B2[2]]) 1762 elif B2_type == 'D': depT2.append([B2[1],B2[2]]) 1763 else: BCT2.append([B2[1],B2[2]]) 1764 depT2.extend(B2[3]) 1765 # on extend pour former les listes des 2 fichiers pour éviter d'utliser 1766 # la concaténation de liste qui crée une nouvelle liste 1767 depT1.extend(depT2) ; del depT2 1768 rempT1.extend(rempT2) ; del rempT2 1769 BCT1.extend(BCT2) ; del BCT2 1770 return Donnees.resultatAppli.Resultat(ins, supp, depT1, rempT1, 1771 self.lgSource, self.texte, BCT1, [])
1772
1773 - def evaluation(self, c1=0.5, c2=0.35, c3=0.15):
1774 """Evalue l'alignement""" 1775 assert c1+c2+c3 == 1 1776 sep = """ !\r,\n:\t;-?"'`’()""" 1777 seq1 = self.lgSource 1778 seq2 = len(self.texte) - seq1 1779 texte = self.texte 1780 ins = sup = remp1 = remp2 = bc1 = bc2 = dep1 = dep2 = 0.0 1781 nb_bc1 = nb_bc2 = nb_dep1 = nb_dep2 = nb_sup = nb_ins = nb_remp1 = nb_remp2 = 0 1782 front_bloc = front_bloc_sep = 0 1783 lBC = [] ; lDep = [] ; lIns = [] ; lSup = [] ; lRemp = [] 1784 for (B1,B2) in self.liste: 1785 if B1 is not None: 1786 B1_type = B1[0] 1787 if B1_type == 'S': 1788 sup += B1[2]-B1[1] ; nb_sup += 1 ; front_bloc += 1 1789 bisect.insort_right(lSup,B1[2]-B1[1]) 1790 if B1[1] == 0: front_bloc_sep += 1 1791 elif (texte[B1[1]] in sep) or (texte[B1[1]-1] in sep): front_bloc_sep += 1 1792 elif B1_type == 'R': 1793 remp1 += B1[2]-B1[1] ; nb_remp1 += 1 ; front_bloc += 1 1794 bisect.insort_right(lRemp,B1[2]-B1[1]) 1795 if B1[1] == 0: front_bloc_sep += 1 1796 elif (texte[B1[1]] in sep) or (texte[B1[1]-1] in sep): front_bloc_sep += 1 1797 elif B1_type == 'BC': 1798 bc1 += B1[2]-B1[1] ; nb_bc1 += 1 ; front_bloc += 1 1799 bisect.insort_right(lBC,B1[2]-B1[1]) 1800 if B1[1] == 0: front_bloc_sep += 1 1801 elif (texte[B1[1]] in sep) or (texte[B1[1]-1] in sep): front_bloc_sep += 1 1802 if B1_type == 'D': 1803 dep1 += B1[2]-B1[1] ; nb_dep1 += 1 ; front_bloc += 1 1804 bisect.insort_right(lDep,B1[2]-B1[1]) 1805 if B1[1] == 0: front_bloc_sep += 1 1806 elif (texte[B1[1]] in sep) or (texte[B1[1]-1] in sep): front_bloc_sep += 1 1807 else: 1808 for (d,f) in B1[3]: # boucle sur les dep internes 1809 dep1 += f-d ; nb_dep1 += 1; bisect.insort_right(lDep,f-d) 1810 if B2 is not None: 1811 B2_type = B2[0] 1812 if B2_type == 'I': 1813 ins += B2[2]-B2[1] ; nb_ins += 1 ; front_bloc += 1 1814 bisect.insort_right(lIns,B2[2]-B2[1]) 1815 if B2[1] == seq1: front_bloc_sep += 1 1816 elif (texte[B2[1]] in sep) or (texte[B2[1]-1] in sep): front_bloc_sep += 1 1817 elif B2_type == 'R': 1818 remp2 += B2[2]-B2[1] ; nb_remp2 += 1 ; front_bloc += 1 1819 bisect.insort_right(lRemp,B2[2]-B2[1]) 1820 if B2[1] == seq1: front_bloc_sep += 1 1821 elif (texte[B2[1]] in sep) or (texte[B2[1]-1] in sep): front_bloc_sep += 1 1822 elif B2_type == 'BC': 1823 bc2 += B2[2]-B2[1] ; nb_bc2 += 1 ; front_bloc += 1 1824 bisect.insort_right(lBC,B2[2]-B2[1]) 1825 if B2[1] == seq1: front_bloc_sep += 1 1826 elif (texte[B2[1]] in sep) or (texte[B2[1]-1] in sep): front_bloc_sep += 1 1827 if B2_type == 'D': 1828 dep2 += B2[2]-B2[1] ; nb_dep2 += 1 ; front_bloc += 1 1829 bisect.insort_right(lDep,B2[2]-B2[1]) 1830 if B2[1] == seq1: front_bloc_sep += 1 1831 elif (texte[B2[1]] in sep) or (texte[B2[1]-1] in sep): front_bloc_sep += 1 1832 else: 1833 for (d,f) in B2[3]: # boucle sur les dep internes 1834 dep2 += f-d ; nb_dep2 += 1 ; bisect.insort_right(lDep,f-d) 1835 assert sum(lBC) == bc1+bc2 and len(lBC) == nb_bc1+nb_bc2 1836 assert sum(lDep) == dep1+dep2 and len(lDep) == nb_dep1+nb_dep2 1837 assert front_bloc_sep <= front_bloc 1838 #if self.planTravail.getParam().get assert bc1 == bc2,str(bc1)+' '+str(bc2) 1839 formules = ['seq1', 1840 'seq2', 1841 '(bc1 + bc2)', 1842 '(nb_bc1 + nb_bc2)', 1843 '(0.0+bc1 + bc2) / (nb_bc1 + nb_bc2)', 1844 'lBC[len(lBC)/2]', 1845 '(dep1 + dep2)', 1846 '(nb_dep1 + nb_dep2)', 1847 '(0.0+dep1 + dep2) / (nb_dep1 + nb_dep2)', 1848 'lDep[len(lDep)/2]', 1849 '(bc1 + bc2) / (seq1 + seq2)', 1850 '(dep1 + dep2) / (seq1 + seq2)', 1851 '(bc1 + bc2 + dep1 + dep2)', 1852 '(nb_bc1 + nb_bc2 + nb_dep1 + nb_dep2)', 1853 '(bc1 + bc2 + dep1 + dep2) / (seq1 + seq2)', 1854 '(bc1 + bc2 - dep1 - dep2)', 1855 '(bc1 + bc2 - dep1 - dep2) / (seq1 + seq2)', 1856 '(bc1 + bc2 - sup - ins - remp1 - remp2)', 1857 '(bc1 + bc2 - sup - ins - remp1 - remp2) / (seq1 + seq2)', 1858 '(bc1 + bc2 - sup - ins - remp1 - remp2 - dep1 - dep2)', 1859 '(bc1 + bc2 - sup - ins - remp1 - remp2 - dep1 - dep2) / (seq1 + seq2)', 1860 #'(sup + ins + remp1 + remp2 + dep1 + dep2)', 1861 #'(sup + ins + remp1 + remp2 + dep1 + dep2) / (seq1 + seq2)' 1862 ] 1863 #res = '' 1864 for f in formules: 1865 try: 1866 #res += f + ' = ' + str(round(eval(f),4)) + '\n' 1867 logging.info(f + ' = ' + str(round(eval(f),4))) 1868 except Exception: #ZeroDivisionError,IndexError: 1869 continue 1870 #logging.info( ins, sup, remp1, remp2, bc1, bc2, dep1, dep2) 1871 #print res 1872 # dico pour chque type de bloc des sommes et nb de blocs 1873 dicoSommes = {} 1874 dicoSommes['inv'] = [bc1+bc2,nb_bc1,nb_bc2] 1875 dicoSommes['sup'] = [sup,nb_sup] 1876 dicoSommes['ins'] = [ins,nb_ins] 1877 dicoSommes['remp'] = [remp1+remp2,nb_remp1,nb_remp2] 1878 dicoSommes['dep'] = [dep1+dep2,nb_dep1,nb_dep2] 1879 dicoSommes['lTexte1'] = seq1 1880 dicoSommes['lTexte2'] = seq2 1881 dicoSommes['front'] = (front_bloc, front_bloc_sep) 1882 1883 x = (1.0+((bc1 + bc2 - sup - ins - remp1 - remp2 - dep1 - dep2) / (seq1 +seq2)))/2.0 1884 pri1 = (bc1 + bc2 + dep1 + dep2) / (bc1 + bc2 + dep1 + dep2 + sup + ins + remp1 + remp2) 1885 pri2 = (bc1 + bc2) / (bc1 + bc2 + dep1 + dep2) 1886 pri3 = (remp1 + remp2) / (sup + ins + remp1 + remp2) 1887 pri = (pri1 + pri2 + pri3) / 3.0 1888 assert 0 <= pri1 <= 1, pri1 1889 assert 0 <= pri2 <= 1, pri2 1890 assert 0 <= pri3 <= 1, pri3 1891 #assert 0 <= x <= 1 1892 if nb_bc1+nb_bc2 > 0: y1 = ((0.0+bc1 + bc2) /(nb_bc1 + nb_bc2))/lBC[-1] 1893 else: y1 = 0 1894 if nb_sup > 0: y2 = ((0.0+sup) / nb_sup) / lSup[-1] 1895 else: y2 = 0 1896 if nb_ins > 0: y3 = ((0.0+ins) / nb_ins) / lIns[-1] 1897 else: y3 = 0 1898 if nb_remp1+nb_remp2 > 0: y4 = ((0.0+remp1+remp2) / (nb_remp1 +nb_remp2))/ lRemp[-1] 1899 else: y4 = 0 1900 if nb_dep1+nb_dep2 > 0: y5 = ((0.0+dep1+dep2) / (nb_dep1 + nb_dep2))/ lDep[-1] 1901 else: y5 = 0 1902 assert 0 <= y1 <= 1, y1 1903 assert 0 <= y2 <= 1, y2 1904 assert 0 <= y3 <= 1, y3 1905 assert 0 <= y4 <= 1, y4 1906 assert 0 <= y5 <= 1, y5 1907 #y = (0.0+(((0.0+bc1 + bc2) / max(1.0,(nb_bc1 + nb_bc2)))/lBC[-1]) + 1908 1909 # (((0.0+sup) / max(1.0,nb_sup)) / lSup[-1]) + 1910 # (((0.0+ins) / max(1.0,nb_ins)) / lIns[-1]) + 1911 # (((0.0+remp1+remp2) / max(1.0,(nb_remp1 +nb_remp2)))/ lRemp[-1]) + 1912 # (((0.0+dep1+dep2) / max(1.0,(nb_dep1 + nb_dep2)))/ lDep[-1])) / 5.0 1913 y = (y1 + y2 + y3 + y4 + y5) / 5.0 1914 assert 0 <= y <= 1 ,y 1915 z0 = (0.0+bc1+bc2) / (0.0+bc1+bc2+dep1+dep2) 1916 z1 = (0.0+dep1+dep2) / (dep1+dep2+ins+sup+remp1+remp2) 1917 z2 = (0.0+remp1+remp2) / (sup+ins+remp1+remp2) 1918 z = (0.0+z1+z2)/2.0 1919 assert 0 <= z <= 1,z 1920 1921 1922 sep = (0.0 + front_bloc_sep) / front_bloc 1923 assert 0 <= sep <= 1, sep 1924 1925 sim_old = c1 * x + c2 * y + c3 *z 1926 assert 0 <= sim_old <= 1,sim_old 1927 sim = (pri + y + sep ) / 3.0 1928 assert 0 <= sim <= 1,sim 1929 1930 logging.info('x = ' + str(round(x,4))) 1931 logging.info('y = ' + str(round(y,4))) 1932 logging.info('z = ' + str(round(z,4))) 1933 logging.info('sim_old = ' + str(round(sim_old,4))) 1934 logging.info('pri1 = ' + str(round(pri1,4))) 1935 logging.info('pri2 = ' + str(round(pri2,4))) 1936 logging.info('pri3 = ' + str(round(pri3,4))) 1937 logging.info('pri = ' + str(round(pri,4))) 1938 logging.info('yINV = ' + str(round(y1,4))) 1939 logging.info('ySUP = ' + str(round(y2,4))) 1940 logging.info('yINS = ' + str(round(y3,4))) 1941 logging.info('yREMP = ' + str(round(y4,4))) 1942 logging.info('yDEP = ' + str(round(y5,4))) 1943 logging.info('y = ' + str(round(y,4))) 1944 logging.info('sep = ' + str(round(sep,4))) 1945 logging.info('sim = ' + str(round(sim,4))) 1946 return x,y,z,sim,dicoSommes,[y1,y2,y3,y4,y5],[z0,z1,z2], (pri1,pri2,pri3),sep
1947
1948 - def print_html(self, dossierOutput=None):
1949 """ Imprime un rapport html à partir de la liste de biblocs 1950 dossierOutput: dossier où écrire le fichier HTML """ 1951 if len(self.liste) > 10: 1952 self.print_html_streaming(dossierOutput) 1953 else: 1954 self.print_html_oneshot(dossierOutput)
1955
1956 - def print_html_streaming(self, dossierOutput=None, justPrintEntete=False):
1957 """ Imprime un rapport html en plusieurs fois pour éviter de construire 1958 toute la chaine à substituer en mémoire 1959 dossierOutput: dossier où écrire le fichier HTML """ 1960 # ouverture du template ne contenant que le début du raport 1961 template = os.path.join(Utile.constantesDonnees.REPPRIVE,"template_rapport_stream.html") 1962 ftemplate = open(template,'r') 1963 stemplate = ''.join(ftemplate.readlines()) 1964 dgm = Controleurs.DGManager.DGManager() 1965 s = Template(stemplate) 1966 # substitution des variables 1967 sres = s.safe_substitute( 1968 FILE1 = dgm.getEtatPath(self.planTravail.getAuteur(), self.planTravail.getOeuvre(),self.planTravail.getVersionSource(),self.planTravail.getEtatSource()), 1969 FILE2 = dgm.getEtatPath(self.planTravail.getAuteur(), self.planTravail.getOeuvre(),self.planTravail.getVersionCible(),self.planTravail.getEtatCible()), 1970 PARAM_PIVOTS = self.planTravail.getParam().getp1(), 1971 RATIO_REMPLACEMENTS = self.planTravail.getParam().getp2(), 1972 SEUIL_DEPLACEMENTS = self.planTravail.getParam().getp3(), 1973 PARAM_CASSE = self.__paramToON(self.planTravail.getParam().getp5()), 1974 PARAM_SEPARATEURS = self.__paramToON(self.planTravail.getParam().getp6()), 1975 PARAM_DIACRITIQUES = self.__paramToON(self.planTravail.getParam().getp7())) 1976 # écriture du rapport 1977 if dossierOutput is not None: 1978 chemin = os.path.join(dossierOutput,"rapport.html") 1979 else: chemin = os.path.join(constantes.REPMEDITE,"rapport.html") 1980 fres = open(chemin,'w') 1981 fres.write(sres) # écriture de la première partie 1982 if justPrintEntete: 1983 return fres 1984 # ecriture en streaming de la table 1985 self.__listeToHtmlTable(stream=True, fileBuffer=fres) 1986 fres.write('</tbody></table><p></p></body></html>') 1987 fres.close()
1988
1989 - def printTableLine(self, fBuffer):
1990 self.__listeToHtmlTable(stream=True, fileBuffer=fBuffer)
1991 - def printCloseTable(self, fBuffer):
1992 fBuffer.write('</tbody></table><p></p></body></html>') 1993 fBuffer.close()
1994
1995 - def print_html_oneshot(self, dossierOutput=None):
1996 """ Imprime un rapport html en une seule fois 1997 dossierOutput: dossier où écrire le fichier HTML """ 1998 # ouverture du template 1999 template = os.path.join(Utile.constantesDonnees.REPPRIVE,"template_rapport.html") 2000 ftemplate = open(template,'r') 2001 stemplate = ''.join(ftemplate.readlines()) 2002 dgm = Controleurs.DGManager.DGManager() 2003 s = Template(stemplate) 2004 # substitution des variables 2005 sres = s.safe_substitute( 2006 FILE1 = dgm.getEtatPath(self.planTravail.getAuteur(), self.planTravail.getOeuvre(),self.planTravail.getVersionSource(),self.planTravail.getEtatSource()), 2007 FILE2 = dgm.getEtatPath(self.planTravail.getAuteur(), self.planTravail.getOeuvre(),self.planTravail.getVersionCible(),self.planTravail.getEtatCible()), 2008 PARAM_PIVOTS = self.planTravail.getParam().getp1(), 2009 RATIO_REMPLACEMENTS = self.planTravail.getParam().getp2(), 2010 SEUIL_DEPLACEMENTS = self.planTravail.getParam().getp3(), 2011 PARAM_CASSE = self.__paramToON(self.planTravail.getParam().getp5()), 2012 PARAM_SEPARATEURS = self.__paramToON(self.planTravail.getParam().getp6()), 2013 PARAM_DIACRITIQUES = self.__paramToON(self.planTravail.getParam().getp7()), 2014 TABLE=self.__listeToHtmlTable()) 2015 # écriture du rapport 2016 if dossierOutput is not None: 2017 chemin = os.path.join(dossierOutput,"rapport.html") 2018 else: chemin = os.path.join(constantes.REPMEDITE,"rapport.html") 2019 fres = open(chemin,'w') 2020 fres.write(sres) 2021 fres.close()
2022
2023 - def __paramToON(self,param):
2024 """ Renvoie 'Oui' ou 'Non' en fonction d'un param booléen """ 2025 if param: return "Oui" 2026 else: return "Non"
2027
2028 - def __listeToHtmlTable(self, stream=False, fileBuffer=None):
2029 """ Convertit la liste de BiBlocs en une table html 2030 2031 Chaque Bibloc est convertit en une ligne <tr></tr> d'une table html 2032 Si stream, on ecrit régulièrement dans fileBuffer la table courante et 2033 on la réinitialise ensuite sinon on crée une grosse chaine que l'on renvoie""" 2034 assert stream==False or (stream and fileBuffer is not None) 2035 res = [] ; i = 0 2036 for (B1,B2) in self.liste: 2037 res.append('<tr>')# += "<tr>" # début de ligne 2038 # colonne gauche 2039 if B1 is None: res.append('<td></td>') # += "<td></td>" # bloc vide 2040 else: 2041 B1_type = B1[0] 2042 if B1_type == 'S': res.extend(['<td style="background-color: #FF0000">',self.__souligneTexte(B1),'</td>']) # supp 2043 elif B1_type == 'R': res.extend(['<td style="background-color: #0000FF"> ',self.__souligneTexte(B1),'</td>']) # remp 2044 elif B1_type == 'D': res.extend(['<td>',self.__souligneTexte(B1),'</td>']) # dep 2045 else: res.extend(['<td>',self.__keepMEP(self.texte[B1[1]:B1[2]]),'</td>']) # BC 2046 # colonne droite 2047 if B2 is None: res.append('<td></td>') # bloc vide 2048 else: 2049 B2_type = B2[0] 2050 if B2_type == 'I': res.extend(['<td style="background-color: #00FF00">',self.__souligneTexte(B2),'</td>']) #ins 2051 elif B2_type == 'R': res.extend(['<td style="background-color: #0000FF">',self.__souligneTexte(B2),'</td>']) # remp 2052 elif B2_type == 'D': res.extend(['<td>',self.__souligneTexte(B2),'</td>']) # dep 2053 else: res.extend(['<td>',self.__keepMEP(self.texte[B2[1]:B2[2]]),'</td>']) # BC 2054 res.append('</tr>\n') # fin de ligne 2055 if stream and i%50 == 0: 2056 fileBuffer.write(''.join(res)) 2057 res = [] 2058 2059 if stream: 2060 fileBuffer.write(''.join(res)) 2061 res = [] 2062 else: 2063 return ''.join(res)
2064
2065 - def __souligneTexte(self,bloc):
2066 """ Renvoie une chaine html avec le texte souligné aux caractères déplacés """ 2067 if bloc[0] == 'D': 2068 return ('<span style="text-decoration: underline; font-weight: bold">'+ 2069 self.__keepMEP(self.texte[bloc[1]:bloc[2]])+'</span>') 2070 res = "" 2071 deb = i = bloc[1] 2072 fin = bloc[2] 2073 lDep = bloc[3][:] # on copie pour ne pas modifier la liste originale 2074 # on parcours tout le bloc pour chercher les déplacements à l'intérieur de celui-ci 2075 while i < fin: 2076 # si le caractère courant est le début d'un déplacement 2077 # <= (au lieu de ==) à cause des chevauchements de déplacements du genre ('I', 5221, 5239, [(5224, 5230), (5226, 5231), (5236, 5239)]) 2078 if len(lDep) > 0 and lDep[0][0] <= i: 2079 res += '<span style="text-decoration: underline; font-weight: bold">'+self.__keepMEP(self.texte[i:lDep[0][1]])+'</span>' 2080 i = lDep[0][1] 2081 lDep.pop(0) 2082 elif len(lDep) > 0 and lDep[0][0] > i: # si on est sur du texte normal 2083 res += self.__keepMEP(self.texte[i:lDep[0][0]]) 2084 i = lDep[0][0] 2085 else: # si pas ou plus de déplacement 2086 assert len(lDep)==0 2087 res += self.__keepMEP(self.texte[i:fin]) 2088 i = fin 2089 return res
2090
2091 - def __keepMEP(self, texte):
2092 """ Fonction chargée de conserver la mise en page du texte original 2093 2094 Remplace les retours à la ligne par des <br> et les espaces par des &nbsp; 2095 2096 Le remplacement des espaces par des nbsp est très utile pour visulaiser des 2097 alignements de code source mais plus discutable pour de la langue nat. 2098 De même mais de façon moins importante pour les br.""" 2099 return texte 2100 res = "" 2101 for i in xrange(len(texte)): 2102 if texte[i] in '\r\n': res += '<br>' 2103 #elif texte[i] in ' ': res += '&nbsp;' 2104 else: # remplace tous les caractères spéciaux par leur code html comme &nbsp; 2105 try: res += '&' + htmlentitydefs.codepoint2name[ord(texte[i])] + ';' 2106 except KeyError: res += texte[i] 2107 return res
2108 2109
2110 -class BiBlocListWD(BiBlocList):
2111 """BiblocList avec type déplacement (D) autorisé """
2112 - def __init__(self,resultat,planTravail,depOrdonnes=True):
2113 BiBlocList.__init__(self,resultat,planTravail,depOrdonnes) 2114 try: 2115 self.evaluation() 2116 except ZeroDivisionError: 2117 logging.debug("Erreur d'evaluation ZeroDivisionError") 2118 logging.debug('extractDeplacements()') 2119 self.extractDeplacements() 2120 try: 2121 self.evaluation() 2122 except ZeroDivisionError: 2123 logging.debug("Erreur d'evaluation ZeroDivisionError")
2124
2125 - def extractDeplacements(self):
2126 """ Extraction des déplacements 2127 2128 Teste les blocs insérés et supprimés. 2129 Si le rapport des déplacements à l'intérieur d'un bloc est supérieur au seuil 2130 Alors ce bloc est scindé en une liste de blocs (I ou S) et D 2131 Modifie directement self.liste 2132 2133 AssertionError: 270455 ('D', 270444, 270455, []) ('D', 270450, 270455, [])""" 2134 tool = utile.Utile() 2135 ratio_seuil_lissage = float(self.planTravail.getParam().getp3()) /100 2136 #nouvelleListe = [] 2137 i = len(self.liste) - 1 2138 while i >= 0: 2139 if i%1000 == 0: logging.debug("itérationD %d",i) 2140 (B1,B2) = self.liste[i] 2141 if (B1 is not None and B1[0] == 'S'): # bloc S 2142 assert B2 is None 2143 supMoinsDep = tool.soustr_l_intervalles([[B1[1],B1[2]]], B1[3]) # bloc S moins les dep 2144 ratio_lissage = float(tool.longueur(supMoinsDep))/(B1[2]-B1[1]) # ratio du bloc 2145 if ratio_lissage <= ratio_seuil_lissage: 2146 self.liste[i:i+1] = self.__extractDepInsSup(supMoinsDep,B1[3],'S') 2147 elif (B2 is not None and B2[0] == 'I'):# bloc I 2148 assert B1 is None 2149 insMoinsDep = tool.soustr_l_intervalles([[B2[1],B2[2]]], B2[3]) 2150 ratio_lissage = float(tool.longueur(insMoinsDep))/(B2[2]-B2[1]) 2151 if ratio_lissage <= ratio_seuil_lissage: 2152 self.liste[i:i+1] = self.__extractDepInsSup(insMoinsDep,B2[3],'I') 2153 i -= 1
2154 #if __debug__: 2155 # self._testOrdre() 2156
2157 - def extractDeplacements__old(self):
2158 """ Extraction des déplacements 2159 2160 Teste les blocs insérés et supprimés. 2161 Si le rapport des déplacements à l'intérieur d'un bloc est supérieur au seuil 2162 Alors ce bloc est scindé en une liste de blocs (I ou S) et D""" 2163 tool = utile.Utile() 2164 ratio_seuil_lissage = float(self.planTravail.getParam().getp3()) /100 2165 nouvelleListe = [] 2166 for (B1,B2) in self.liste: 2167 if (B1 is not None and B1[0] == 'S'): # bloc S 2168 assert B2 is None 2169 supMoinsDep = tool.soustr_l_intervalles([[B1[1],B1[2]]], B1[3]) # bloc S moins les dep 2170 ratio_lissage = float(tool.longueur(supMoinsDep))/(B1[2]-B1[1]) # ratio du bloc 2171 if ratio_lissage > ratio_seuil_lissage: 2172 nouvelleListe.append((B1,None)) 2173 else: 2174 nouvelleListe.extend(self.__extractDepInsSup(supMoinsDep,B1[3],'S')) 2175 elif (B2 is not None and B2[0] == 'I'):# bloc I 2176 assert B1 is None 2177 insMoinsDep = tool.soustr_l_intervalles([[B2[1],B2[2]]], B2[3]) 2178 ratio_lissage = float(tool.longueur(insMoinsDep))/(B2[2]-B2[1]) 2179 if ratio_lissage > ratio_seuil_lissage: 2180 nouvelleListe.append((None,B2)) 2181 else: 2182 nouvelleListe.extend(self.__extractDepInsSup(insMoinsDep,B2[3],'I')) 2183 else: # autres blocs: R et BC 2184 nouvelleListe.append((B1,B2)) 2185 self.liste = nouvelleListe 2186 if __debug__: 2187 self._testOrdre()
2188
2189 - def __extractDepInsSup(self,lSupOrIns,listeDep,SorI):
2190 """On scinde effectivement le blocs en une liste de blocs (S ou I) et D 2191 2192 lSupOrIns: liste de (I ou S) 2193 listeDep: liste de D 2194 SorI: traite-on des S ou des I ? 2195 pre: isinstance(lSupOrIns,list) and isinstance(listeDep,list) 2196 (SorI == 'S' or SorI == 'I') """ 2197 nouvelleListe = [] 2198 len_listeDep = len(listeDep) 2199 prevdeb = nbDep = 0 2200 while len(lSupOrIns) > 0 or len(listeDep) > 0: 2201 # on a ajouté tous les D, on peut ajouter le reste des (I ou S) 2202 if len(listeDep) == 0: 2203 for (deb,fin) in lSupOrIns: # pour chaque bloc (I ou S) 2204 assert prevdeb <= deb # assertion d'ordre 2205 prevdeb = deb 2206 if SorI == 'S': nouvelleListe.append((('S',deb,fin,[]),None)) # ajout effectif 2207 else: nouvelleListe.append((None,('I',deb,fin,[]))) 2208 lSupOrIns = [] 2209 # on a ajouté tous les (I ou S), on peut ajouter les reste des D 2210 elif len(lSupOrIns) == 0: 2211 for (deb,fin) in listeDep: # pour chaque bloc D 2212 assert prevdeb <= deb 2213 prevdeb = deb 2214 if SorI == 'S': nouvelleListe.append((('D',deb,fin,[]),None)) 2215 else: nouvelleListe.append((None,('D',deb,fin,[]))) 2216 nbDep += 1 2217 listeDep = [] 2218 # si bloc courant (I ou S) <= bloc courant D alors on l'ajoute 2219 elif lSupOrIns[0][0] <= listeDep[0][0]: 2220 assert prevdeb <= lSupOrIns[0][0] 2221 prevdeb = lSupOrIns[0][0] 2222 if SorI == 'S': nouvelleListe.append((('S',lSupOrIns[0][0],lSupOrIns[0][1],[]),None)) 2223 else: nouvelleListe.append((None,('I',lSupOrIns[0][0],lSupOrIns[0][1],[]))) 2224 #lSupOrIns = lSupOrIns[1:] 2225 lSupOrIns.pop(0) 2226 else: 2227 assert prevdeb <= listeDep[0][0] 2228 prevdeb = listeDep[0][0] 2229 if SorI == 'S': nouvelleListe.append((('D',listeDep[0][0],listeDep[0][1],[]),None)) 2230 else: nouvelleListe.append((None,('D',listeDep[0][0],listeDep[0][1],[]))) 2231 listeDep.pop(0) 2232 nbDep += 1 2233 assert len(listeDep) == len(lSupOrIns) == 0 # les 2 listes ont du etre traitées entièrement 2234 assert nbDep == len_listeDep 2235 return nouvelleListe
2236
2237 -class BiBlocListWDListe(BiBlocListWD):
2238 - def __init__(self, liste, planTravail, texte, lg_texte1):
2239 self.liste = liste 2240 self.texte = texte 2241 self.lgSource = lg_texte1 2242 self.planTravail = planTravail # sert seulement à l'affichage du rapport 2243 2244 #self.extractInsSup() 2245 logging.debug('extractRemplacements') 2246 self.extractRemplacements() 2247 logging.debug('extractDeplacements') 2248 self.extractDeplacements()
2249
2250 - def extractInsSup(self):
2251 """ a jeter """ 2252 liste = self.liste 2253 lastFin1 = self.lgSource ; lastFin2 = len(self.texte) 2254 lastBC1 = lastBC2 = len(liste)-1 2255 for i in xrange(len(liste)-1,-1,-1): 2256 B1,B2 = liste[i] 2257 #print B1,B2 2258 if B2 is not None and B2[0] == 'D': 2259 accu = [] 2260 while (i-1 >= 0 and liste[i-1][1] is not None and 2261 (liste[i-1][1][0] == 'D' or liste[i-1][1][0] == 'BC')): 2262 accu.append(B2) 2263 i -= 1 2264 B2 = liste[i][1] 2265 accu.append(B2) 2266 if i-1 < 0: start = self.lgSource 2267 else: start = liste[i-1][0][2] # fin bloc précédent dans la liste 2268 assert i <= lastBC2+1 2269 liste[i:lastBC2+1] = [(None,('I',start,lastFin2,[(B[1],B[2]) for B in accu]))] 2270 lastFin2 = start ; lastBC2 = i 2271 elif B1 is not None and B1[0] == 'D': 2272 accu = [] 2273 while (i-1 >= 0 and liste[i-1][0] is not None and 2274 (liste[i-1][0][0] == 'D' or liste[i-1][1][0] == 'BC')): 2275 accu.append(B1) 2276 i -= 1 2277 B1 = liste[i][0] 2278 accu.append(B1) 2279 if i-1 < 0: start = 0 2280 else: start = liste[i-1][1][2] # fin bloc précédent dans la liste 2281 assert i <= lastBC1+1 2282 liste[i:lastBC1+1] = [(('S',start,lastFin1,[(B[1],B[2]) for B in accu]),None)] 2283 lastFin1 = start ; lastBC1 = i 2284 else: # BC 2285 accu = [(B1,B2)] 2286 print B1,B2 2287 assert B1[0] == 'BC' and B2[0] == 'BC', str(B1)+str(B2) 2288 if liste[lastBC1][0][1] - B1[2] > 0: 2289 accu.append((('S',B1[2],liste[lastBC1][0][1],[]),None)) 2290 if liste[lastBC2][1][1] - B2[2] > 0: 2291 accu.append((None,('I',B2[2],liste[lastBC2][1][1],[]))) 2292 liste[i:i+1] = accu 2293 lastBC1 = lastBC2 = i 2294 lastFin1 = B1[1] ; lastFin2 = B2[1] 2295 i -= 1 2296 B1,B2 = liste[0] 2297 accu = [] 2298 if B1 is not None and B1[1] != 0: 2299 accu.append(()) 2300 #print '-----------------------------' 2301 print liste 2302 self.liste = liste
2303