Package gmisclib :: Module g_place_label
[frames] | no frames]

Source Code for Module gmisclib.g_place_label

  1  #!/usr/bin/env python 
  2   
  3  import Num 
  4  import math 
  5   
  6   
7 -class boxc(object):
8 - def __init__(self, xc, yc, xw, yw):
9 self._xc = xc 10 self._yc = yc 11 self._xw = xw 12 self._yw = yw
13
14 - def xmin(self):
15 return self._xc - self._xw/2.0
16
17 - def xmax(self):
18 return self._xc + self._xw/2.0
19
20 - def ymin(self):
21 return self._yc - self._yw/2.0
22
23 - def ymax(self):
24 return self._yc + self._yw/2.0
25
26 - def w(self):
27 return self._xw
28
29 - def h(self):
30 return self._yw
31
32 - def yc(self):
33 return self._yc
34
35 - def xc(self):
36 return self._xc
37
38 - def shift(self, x, y):
39 return boxc(self._xc+x, self._yc+y, self._xw, self._yw)
40 41
42 -class text_template(object):
43 - def __init__(self, text, H, W):
44 """(0,0) is the lower left corner of the block of text.""" 45 self.lines = [] 46 self.txt = [] 47 la = text.split('\n') 48 n = len(la) 49 for (i, l) in enumerate(la): 50 self.addline(0.0, H*(n-1-i), W*len(l), H, l)
51
52 - def addline(self, x0, y0, xlength, yht, txtline):
53 """Specify LLC.""" 54 self.lines.append(boxc(x0+xlength/2.0, y0+yht/2.0, 55 xlength, yht) 56 ) 57 self.txt.append(txtline)
58
59 - def nlines(self):
60 return len(self.lines)
61 62
63 -def Gauss(y, ybar, yvar):
64 arg = (y-ybar)**2/(2*yvar) 65 return Num.exp(-Num.minimum(arg, 100.0))/math.sqrt(2*math.pi*yvar)
66
67 -def gauss(y, ybar, yvar):
68 arg = (y-ybar)**2/(2*yvar) 69 return math.exp(-arg)/math.sqrt(2*math.pi*yvar)
70
71 -def q_gauss(y, ybar, yvar):
72 return gauss(y, ybar, yvar) - 0.3*gauss(y, ybar, 40*yvar)
73 74 75
76 -class viewport(boxc):
77 - def __init__(self, fracCharHt, fracCharW, xmin, xmax, ymin, ymax):
78 self.H = fracCharHt 79 self.W = fracCharW 80 self.datasets = [] 81 self.avoidlist = [] 82 boxc.__init__(self, xmin, ymin, xmax-xmin, ymax-ymin) 83 self.YN = 100 84 self.DF = 10.0
85 86
87 - def dataset(self, x, y):
88 self.datasets.append( (x, y) )
89 90
91 - def _fom_y(self, ycand, x0, relbox):
92 rlist = [] 93 xtra_var = self.h()**2 * ((1.0/self.YN)**2 + self.H**2) 94 xbdr = self.h() * self.H 95 for (x, y) in self.datasets : 96 ovlap = Num.greater(x, x0+relbox.xmin()-xbdr) * Num.less(x, x0+relbox.xmax()+xbdr) 97 avoid = Num.compress(ovlap, y) 98 an = avoid.shape[0] 99 if an > 1: 100 asum = Num.sum(avoid, axis=0) 101 assq = Num.sum((avoid-asum/an)**2, axis=0) 102 assq += an * xtra_var 103 # Avoid the data in the relevant x-range: 104 rlist.append( (asum/an, assq/an, -self.DF) ) 105 # But be nearby: 106 rlist.append( (asum/an, 100.0*assq/an, 0.1*self.DF) ) 107 108 rn = y.shape[0] 109 if rn > 1: 110 rsum = Num.sum(y, axis=0) 111 rssq = Num.sum((y-rsum/rn)**2, axis=0) 112 rssq += rn * xtra_var 113 # Also be near the overall dataset 114 rlist.append( (rsum/rn, 2*rssq/rn, 0.1*self.DF) ) 115 116 for a in self.avoidlist: 117 veff = relbox.w()**2 + a.w()**2 118 wt = q_gauss(x0+relbox.xc(), a.xc(), veff) 119 rlist.append( (a.yc(), a.h()**2, -wt) ) 120 121 fom = Num.zeros(ycand.shape, Num.Float) 122 yco = ycand + relbox.ymin() 123 for (rbar, rvar, wt) in rlist: 124 fom += wt*Gauss(yco, rbar, rvar+relbox.h()**2) 125 return fom
126
127 - def find_y(self, x0, ttm):
128 """Figures out a good place to put a label. 129 The label is at a specified tc, but can be at any vertical 130 position. This finds a good vertical position. 131 Returns the bottom of the block of text. 132 """ 133 delta = self.h()/self.YN 134 y_candidates = (Num.arrayrange(self.YN)-(0.5*self.YN))*delta + self.yc() 135 fom = Num.zeros(y_candidates.shape, Num.Float) 136 for lbox in ttm.lines: 137 tmp = self._fom_y(y_candidates, x0, lbox) 138 Num.add(fom, tmp, fom) 139 return y_candidates[Num.argmax(fom)]
140 141
142 - def textplace(self, x0, text):
143 tt = text_template(text, self.H*self.h(), self.W*self.w()) 144 yc = self.find_y( x0, tt ) 145 for (l, bx) in zip(tt.txt, tt.lines): 146 bxs = bx.shift(x0, yc) 147 self.avoidlist.append(bxs) 148 yield (bxs.xmin(), bxs.ymin(), l)
149 150
151 - def draw_hor_line(self, xc, yc, w):
152 EPS = 0.005 153 self.avoidlist.append(boxc(xc, yc, w, EPS*self.h()))
154