Package obitools :: Package carto
[hide private]
[frames] | no frames]

Source Code for Package obitools.carto

  1  # -*- coding: latin1 -*- 
  2   
  3   
  4   
  5  from obitools import SVGdraw 
  6  import math 
  7   
8 -class Map(object):
9 """ 10 Map represente une instance d'une carte genetique physique. 11 Une telle carte est definie par la longueur de la sequence 12 qui lui est associe. 13 14 A une carte est associe un certain nombre de niveaux (Level) 15 eux meme decoupe en sous-niveau (SubLevel) 16 Les sous niveaux contiennent eux des features 17 """
18 - def __init__(self,name,seqlength,scale=1):
19 """ 20 Constructeur d'une nouvelle carte 21 22 *Param*: 23 24 name 25 nom de la carte 26 27 seqlength 28 longueur de la sequence associee a la carte 29 30 scale 31 echelle de la carte indicant combien de pixel 32 correspondent a une unite de la carte 33 """ 34 self.name = name 35 self.seqlength = seqlength 36 self.scale = scale 37 self.levels = {} 38 self.basicHSize = 10
39
40 - def __str__(self):
41 return '<%s>' % self.name
42
43 - def __getitem__(self,level):
44 """ 45 retourne le niveau *level* de la carte et 46 le cree s'il n'existe pas 47 """ 48 if not isinstance(level,int): 49 raise TypeError('level must be an non Zero integer value') 50 elif level==0: 51 raise AssertionError('Level cannot be set to 0') 52 try: 53 return self.levels[level] 54 except KeyError: 55 self.levels[level] = Level(level,self) 56 return self.levels[level]
57
58 - def getBasicHSize(self):
59 """ 60 retourne la hauteur de base d'un element de cartographie 61 exprimee en pixel 62 """ 63 return self.basicHSize
64
65 - def getScale(self):
66 """ 67 Retourne l'echelle de la carte en nombre de pixels par 68 unite physique de la carte 69 """ 70 return self.scale
71 72 73
74 - def getNegativeBase(self):
75 return reduce(lambda x,y:x-y,[self.levels[z].getHeight() 76 for z in self.levels 77 if z < 0],self.getHeight())
78
79 - def getPositiveBase(self):
80 return self.getNegativeBase() - 3 * self.getBasicHSize()
81
82 - def getHeight(self):
83 return reduce(lambda x,y:x+y,[z.getHeight() for z in self.levels.values()],0) \ 84 + 4 * self.getBasicHSize()
85
86 - def toXML(self,file=None,begin=0,end=None):
87 dessin = SVGdraw.drawing() 88 if end==None: 89 end = self.seqlength 90 hauteur= self.getHeight() 91 largeur=(end-begin+1)*self.scale 92 svg = SVGdraw.svg((begin*self.scale,0,largeur,hauteur), 93 '%fpx' % (self.seqlength * self.scale), 94 '%dpx' % hauteur) 95 96 centre = self.getPositiveBase() + (1 + 1/4) * self.getBasicHSize() 97 svg.addElement(SVGdraw.rect(0,centre,self.seqlength * self.scale,self.getBasicHSize()/2)) 98 for e in self.levels.values(): 99 svg.addElement(e.getElement()) 100 dessin.setSVG(svg) 101 return dessin.toXml(file)
102
103 -class Feature(object):
104 pass
105
106 -class Level(object):
107
108 - def __init__(self,level,map):
109 if not isinstance(map,Map): 110 raise AssertionError('map is not an instance of class Map') 111 if level in map.levels: 112 raise AssertionError('Level %d already define for map %s' % (level,map)) 113 else: 114 map.levels[level] = self 115 self.map = map 116 self.level = level 117 self.sublevels = {}
118
119 - def __getitem__(self,sublevel):
120 """ 121 retourne le niveau *sublevel* du niveau en 122 le creant s'il n'existe pas 123 """ 124 if not isinstance(sublevel,int): 125 raise TypeError('sublevel must be a positive integer value') 126 elif sublevel<0: 127 raise AssertionError('Level cannot be negative') 128 try: 129 return self.sublevels[sublevel] 130 except KeyError: 131 self.sublevels[sublevel] = SubLevel(sublevel,self) 132 return self.sublevels[sublevel]
133
134 - def getBase(self):
135 if self.level < 0: 136 base = self.map.getNegativeBase() 137 base += reduce(lambda x,y:x+y,[self.map.levels[z].getHeight() 138 for z in self.map.levels 139 if z <0 and z >= self.level],0) 140 return base 141 else: 142 base = self.map.getPositiveBase() 143 base -= reduce(lambda x,y:x+y,[self.map.levels[z].getHeight() 144 for z in self.map.levels 145 if z >0 and z < self.level],0) 146 return base
147
148 - def getElement(self):
149 objet = SVGdraw.group('level%d' % self.level) 150 for e in self.sublevels.values(): 151 objet.addElement(e.getElement()) 152 return objet
153 154 155
156 - def getHeight(self):
157 return reduce(lambda x,y:x+y,[z.getHeight() for z in self.sublevels.values()],0) \ 158 + 2 * self.map.getBasicHSize()
159
160 -class SubLevel(object):
161
162 - def __init__(self,sublevel,level):
163 if not isinstance(level,Level): 164 raise AssertionError('level is not an instance of class Level') 165 if level in level.sublevels: 166 raise AssertionError('Sublevel %d already define for level %s' % (sublevel,level)) 167 else: 168 level.sublevels[sublevel] = self 169 self.level = level 170 self.sublevel = sublevel 171 self.features = {}
172
173 - def getHeight(self):
174 return max([x.getHeight() for x in self.features.values()]+[0]) + 4 * self.level.map.getBasicHSize()
175
176 - def getBase(self):
177 base = self.level.getBase() 178 if self.level.level < 0: 179 base -= self.level.getHeight() - 2 * self.level.map.getBasicHSize() 180 base += reduce(lambda x,y:x+y,[self.level.sublevels[z].getHeight() 181 for z in self.level.sublevels 182 if z <= self.sublevel],0) 183 base -= 2* self.level.map.getBasicHSize() 184 else: 185 base -= reduce(lambda x,y:x+y,[self.level.sublevels[z].getHeight() 186 for z in self.level.sublevels 187 if z < self.sublevel],0) 188 base -= self.level.map.getBasicHSize() 189 return base
190
191 - def getElement(self):
192 base = self.getBase() 193 objet = SVGdraw.group('sublevel%d' % self.sublevel) 194 for e in self.features.values(): 195 objet.addElement(e.getElement(base)) 196 return objet
197
198 - def add(self,feature):
199 if not isinstance(feature,Feature): 200 raise TypeError('feature must be an instance oof Feature') 201 if feature.name in self.features: 202 raise AssertionError('A feature with the same name (%s) have already be insert in this sublevel' 203 % feature.name) 204 self.features[feature.name]=feature 205 feature.sublevel=self
206
207 -class SimpleFeature(Feature):
208
209 - def __init__(self,name,begin,end,visiblename=False,color=0):
210 self.begin = begin 211 self.end = end 212 self.name = name 213 self.color = color 214 self.sublevel = None 215 self.visiblename=visiblename
216
217 - def getHeight(self):
218 if not self.sublevel: 219 raise AssertionError('Not affected Simple feature') 220 if self.visiblename: 221 return self.sublevel.level.map.getBasicHSize() * 2 222 else: 223 return self.sublevel.level.map.getBasicHSize()
224
225 - def getElement(self,base):
226 scale = self.sublevel.level.map.getScale() 227 y = base - self.sublevel.level.map.getBasicHSize() 228 x = self.begin * scale 229 width = (self.end - self.begin + 1) * scale 230 heigh = self.sublevel.level.map.getBasicHSize() 231 232 objet = SVGdraw.rect(x,y,width,heigh,stroke=self.color) 233 objet.addElement(SVGdraw.description(self.name)) 234 235 return objet
236
237 -class BoxFeature(SimpleFeature):
238
239 - def getHeight(self):
240 if not self.sublevel: 241 raise AssertionError('Not affected Box feature') 242 if self.visiblename: 243 return self.sublevel.level.map.getBasicHSize() * 4 244 else: 245 return self.sublevel.level.map.getBasicHSize() * 3
246
247 - def getElement(self,base):
248 scale = self.sublevel.level.map.getScale() 249 y = base - self.sublevel.level.map.getBasicHSize() * 2 250 x = self.begin * scale 251 width = (self.end - self.begin + 1) * scale 252 height = self.sublevel.level.map.getBasicHSize() * 3 253 254 objet = SVGdraw.rect(x,y,width,height,stroke=self.color,fill="none") 255 objet.addElement(SVGdraw.description(self.name)) 256 257 return objet
258
259 -class MultiPartFeature(Feature):
260
261 - def __init__(self,name,*args,**kargs):
262 self.limits = args 263 self.name = name 264 try: 265 self.color = kargs['color'] 266 except KeyError: 267 self.color = "black" 268 269 try: 270 self.visiblename=kargs['visiblename'] 271 except KeyError: 272 self.visiblename=None 273 274 try: 275 self.flatlink=kargs['flatlink'] 276 except KeyError: 277 self.flatlink=False 278 279 try: 280 self.roundlink=kargs['roundlink'] 281 except KeyError: 282 self.roundlink=False 283 284 self.sublevel = None
285 286
287 - def getHeight(self):
288 if not self.sublevel: 289 raise AssertionError('Not affected Simple feature') 290 if self.visiblename: 291 return self.sublevel.level.map.getBasicHSize() * 3 292 else: 293 return self.sublevel.level.map.getBasicHSize() * 2
294
295 - def getElement(self,base):
296 scale = self.sublevel.level.map.getScale() 297 298 y = base - self.sublevel.level.map.getBasicHSize() 299 height = self.sublevel.level.map.getBasicHSize() 300 objet = SVGdraw.group(self.name) 301 for (debut,fin) in self.limits: 302 x = debut * scale 303 width = (fin - debut + 1) * scale 304 part = SVGdraw.rect(x,y,width,height,fill=self.color) 305 objet.addElement(part) 306 307 debut = self.limits[0][1] 308 for (fin,next) in self.limits[1:]: 309 debut*=scale 310 fin*=scale 311 path = SVGdraw.pathdata(debut,y + height / 2) 312 delta = height / 2 313 if self.roundlink: 314 path.qbezier((debut+fin)/2, y - delta,fin,y + height / 2) 315 else: 316 if self.flatlink: 317 delta = - height / 2 318 path.line((debut+fin)/2, y - delta) 319 path.line(fin,y + height / 2) 320 path = SVGdraw.path(path,fill="none",stroke=self.color) 321 objet.addElement(path) 322 debut = next 323 324 objet.addElement(SVGdraw.description(self.name)) 325 326 return objet
327
328 -class TagFeature(Feature):
329
330 - def __init__(self,name,begin,length,ratio,visiblename=False,color=0):
331 self.begin = begin 332 self.length = length 333 self.ratio = ratio 334 self.name = name 335 self.color = color 336 self.sublevel = None 337 self.visiblename=visiblename
338
339 - def getHeight(self):
340 if not self.sublevel: 341 raise AssertionError('Not affected Tag feature') 342 343 return self.sublevel.level.map.getBasicHSize()*11
344
345 - def getElement(self,base):
346 scale = self.sublevel.level.map.getScale() 347 height = math.floor(max(1,self.sublevel.level.map.getBasicHSize()* 10 * self.ratio)) 348 y = base + self.sublevel.level.map.getBasicHSize() - height 349 x = self.begin * scale 350 width = self.length * scale 351 objet = SVGdraw.rect(x,y,width,height,stroke=self.color) 352 objet.addElement(SVGdraw.description(self.name)) 353 354 return objet
355 356 if __name__ == '__main__': 357 carte = Map('essai',20000,scale=0.5) 358 carte[-1][0].add(SimpleFeature('toto',100,300)) 359 carte[1][0].add(SimpleFeature('toto',100,300)) 360 carte[1][1].add(SimpleFeature('toto',200,1000)) 361 362 carte[1][0].add(MultiPartFeature('bout',(1400,1450),(1470,1550),(1650,1800),color='red',flatlink=True)) 363 carte[1][0].add(MultiPartFeature('titi',(400,450),(470,550),(650,800),color='red',flatlink=True)) 364 carte[-1][1].add(MultiPartFeature('titi',(400,450),(470,550),(650,800),color='green')) 365 carte[-1][2].add(MultiPartFeature('titi',(400,450),(470,550),(650,800),color='purple',roundlink=True)) 366 367 carte[-1][1].add(BoxFeature('tutu',390,810,color='purple')) 368 carte[1][0].add(BoxFeature('tutu',390,810,color='red')) 369 carte[2][0].add(TagFeature('t1',1400,20,0.8)) 370 carte[2][0].add(TagFeature('t2',1600,20,0.2)) 371 carte.basicHSize=6 372 print carte.toXML('truc.svg',begin=0,end=1000) 373 print carte.toXML('truc2.svg',begin=460,end=2000) 374