Package reflectometry :: Package reduction :: Module ticker

Source Code for Module reflectometry.reduction.ticker

  1  """ 
  2  Experimental replacements for log formatting and tick marks. 
  3  """ 
  4   
  5   
  6  from __future__ import division 
  7  import sys, os, re, time, math, warnings 
  8  import numpy as npy 
  9  import matplotlib as mpl 
 10  from matplotlib import verbose, rcParams 
 11  from matplotlib import cbook 
 12  from matplotlib import transforms as mtrans 
 13  from matplotlib import ticker 
 14   
 15   
16 -class LogFormatterMathtext(ticker.LogFormatter):
17 """ 18 Format values for log axis; using exponent = log_base(value) 19 """ 20
21 - def __call__(self, x, pos=None):
22 'Return the format for tick val x at position pos' 23 self.verify_intervals() 24 25 b = self._base 26 fx = math.log(abs(x))/math.log(b) 27 isDecade = self.is_decade(fx) 28 29 usetex = rcParams['text.usetex'] 30 # Make sure sign shows up properly 31 if x < 0: b = -b 32 33 if not isDecade and self.labelOnlyBase: 34 s = '' 35 elif not isDecade: 36 #if usetex: 37 # s = r'$%g^{%.2f}$'% (b, fx) 38 #else: 39 # s = '$\mathdefault{%g^{%.2f}}$'% (b, fx) 40 s = '%g'%(x) 41 else: 42 exp = self.nearest_long(fx) 43 if exp == 0: 44 s = 1 45 elif exp == 1: 46 s = '%g'%(x) 47 elif usetex: 48 s = r'$%g^{%d}$'% (b, self.nearest_long(fx)) 49 else: 50 s = r'$\mathdefault{%g^{%d}}$'% (b, self.nearest_long(fx)) 51 52 return s
53 54
55 -def decade_down(x, base=10):
56 'floor x to the nearest lower decade' 57 58 lx = math.floor(math.log(x)/math.log(base)) 59 return base**lx
60
61 -def decade_up(x, base=10):
62 'ceil x to the nearest higher decade' 63 lx = math.ceil(math.log(x)/math.log(base)) 64 return base**lx
65
66 -def is_decade(x,base=10):
67 lx = math.log(x)/math.log(base) 68 return lx==int(lx)
69
70 -class LogLocator(ticker.Locator):
71 """ 72 Determine the tick locations for log axes 73 """ 74
75 - def __init__(self, base=10.0, subs=[1.0], ntics=5):
76 """ 77 place ticks on the location= base**i*subs[j] 78 """ 79 self.base(base) 80 self.subs(subs) 81 self.numticks = 15 82 83 # Linear subtics 84 self._ntics = 5 85 self._trim = True 86 self._integer = False 87 self._steps = [1.,2.,5.]
88
89 - def base(self,base):
90 """ 91 set the base of the log scaling (major tick every base**i, i interger) 92 """ 93 self._base=base+0.0
94
95 - def subs(self,subs):
96 """ 97 set the minor ticks the log scaling every base**i*subs[j] 98 """ 99 if subs is None: 100 self._subs = None # autosub 101 else: 102 self._subs = npy.asarray(subs)+0.0
103
104 - def _set_numticks(self):
105 self.numticks = 15 # todo; be smart here; this is just for dev
106
107 - def linear_tics(self, vmin, vmax):
108 nbins = self._ntics 109 scale, offset = ticker.scale_range(vmin, vmax, nbins) 110 vmin -= offset 111 vmax -= offset 112 raw_step = (vmax-vmin)/nbins 113 scaled_raw_step = raw_step/scale 114 115 for step in [1,2,5,10]: 116 if step < scaled_raw_step: 117 continue 118 step *= scale 119 best_vmin = step*divmod(vmin, step)[0] 120 best_vmax = best_vmin + step*nbins 121 if (best_vmax >= vmax): 122 break 123 if self._trim: 124 extra_bins = int(divmod((best_vmax - vmax), step)[0]) 125 nbins -= extra_bins 126 return (npy.arange(nbins+1) * step + best_vmin + offset)
127 128
129 - def __call__(self):
130 'Return the locations of the ticks' 131 self.verify_intervals() 132 b=self._base 133 134 linvmin, linvmax = self.viewInterval.get_bounds() 135 136 vmin = math.log(linvmin)/math.log(b) 137 vmax = math.log(linvmax)/math.log(b) 138 if vmax<vmin: 139 vmin, vmax = vmax, vmin 140 if vmax-vmin <= 1.: 141 return self.linear_tics(linvmin, linvmax) 142 143 144 ticklocs = [] 145 146 numdec = math.floor(vmax)-math.ceil(vmin) 147 148 if self._subs is None: # autosub 149 if numdec>10: subs = npy.array([1.0]) 150 elif numdec>6: subs = npy.arange(2.0, b, 2.0) 151 else: subs = npy.arange(2.0, b) 152 else: 153 subs = self._subs 154 155 stride = 1 156 while numdec/stride+1 > self.numticks: 157 stride += 1 158 159 for decadeStart in b**npy.arange(math.floor(vmin), 160 math.ceil(vmax)+stride, stride): 161 ticklocs.extend( subs*decadeStart ) 162 163 return npy.array(ticklocs)
164
165 - def autoscale(self):
166 'Try to choose the view limits intelligently' 167 self.verify_intervals() 168 169 vmin, vmax = self.dataInterval.get_bounds() 170 if vmax<vmin: 171 vmin, vmax = vmax, vmin 172 173 minpos = self.dataInterval.minpos() 174 175 if minpos<=0: 176 raise RuntimeError('No positive data to plot') 177 if vmin<=0: 178 vmin = minpos 179 if not is_decade(vmin,self._base): vmin = decade_down(vmin,self._base) 180 if not is_decade(vmax,self._base): vmax = decade_up(vmax,self._base) 181 if vmin==vmax: 182 vmin = decade_down(vmin,self._base) 183 vmax = decade_up(vmax,self._base) 184 return mtrans.nonsingular(vmin, vmax)
185