Page Menu
Home
HEPForge
Search
Configure Global Search
Log In
Files
F7879427
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
8 KB
Subscribers
None
View Options
diff --git a/pyext/professor2/histos.py b/pyext/professor2/histos.py
--- a/pyext/professor2/histos.py
+++ b/pyext/professor2/histos.py
@@ -1,251 +1,263 @@
# -*- python -*-
class Histo(object):
"A simple histogram -- just a Bin container with an optional path name"
__slots__ = ["_bins", "path"]
def __init__(self, bins=None, path=None):
self._bins = bins if bins else []
self.path = path
@property
def nbins(self):
return len(self.bins)
@property
def bins(self):
return self._bins
@bins.setter
def bins(self, bs):
self._bins = bs
self._bins.sort()
for i, b in enumerate(self._bins):
b.n = i
def __len__(self):
return self.nbins
def __repr__(self):
return "<%s with %d bins>" % (self.__class__.__name__, self.nbins)
class DataHisto(Histo):
"Specialisation of Histo as a container of DataBins"
def __init__(self, dbins=None, path=None):
Histo.__init__(self, dbins, path)
def toScatter2D(self, manpath=None):
path = manpath if manpath is not None else self.path
points = [(self.bins[i].xmid, self.bins[i].val,
[self.bins[i].xmid-self.bins[i].xmin, self.bins[i].xmax-self.bins[i].xmid],
self.bins[i].errs) for i in xrange(len(self.bins))]
import yoda
return yoda.Scatter2D(points, path, path)
def mkSmearedCopy(self, SEED):
from copy import deepcopy
B=deepcopy(self.bins)
Ysmeared = [b.smearBin(SEED) for b in B]
for num, b in enumerate(B):
b.val=Ysmeared[num]
return Histo(B, self.path)
class IpolHisto(Histo):
"Specialisation of Histo as a container of IpolBins"
def __init__(self, ibins=None, path=None):
Histo.__init__(self, ibins, path)
def toDataHisto(self, *params):
"Convert this IpolBin to a DataBin with values and errors computed at params"
dbins = [ib.toDataBin(*params) for ib in self.bins]
dhist = DataHisto(dbins, self.path)
return dhist
class Bin(object):
"A base class for binned data, handling the common x-edge stuff"
__slots__ = ["xmin", "xmax", "n"]
def __init__(self, xmin, xmax, n=None):
self.xmin = xmin
self.xmax = xmax
self.n = n
@property
def xmid(self):
return (self.xmin + self.xmax) / 2.0
@property
def xedges(self):
return (self.xmin, self.xmax)
def __cmp__(self, other):
return cmp(self.xmin, other.xmin)
def smear(self, SEED):
pass
class DataBin(Bin):
"A bin containing a data value and its error(s)"
__slots__ = ["val", "_errs"]
def __init__(self, xmin, xmax, val=None, errs=None):
Bin.__init__(self, xmin, xmax)
self.val = val
self._errs = errs
# TODO: return numerical 0 if _errs is None?
@property
def err(self):
"Get a scalar error value, by averaging if necessary"
if self._errs is None:
return 0.0
elif hasattr(self._errs, "__len__"):
assert len(self._errs) == 2
return sum(self._errs) / 2.0
return self._errs
@err.setter
def err(self, e):
"Set a scalar error value"
assert not hasattr(self._errs, "__len__")
self._errs = e
@property
def errs(self):
"Get a pair of error values, by construction if necessary"
if self._errs is None:
return (0.0, 0.0)
elif hasattr(self._errs, "__len__"):
assert len(self._errs) == 2
return self._errs
return (self._errs, self._errs)
@errs.setter
def errs(self, e):
"Set a pair of error values"
if e is None:
self._errs = None
elif hasattr(e, "__len__"):
assert len(e) == 2
self._errs = e
else:
self._errs = [e,e]
def smearBin(self, SEED):
import random
random.seed(SEED)
return self.val + random.gauss(0, self.err)
def __repr__(self):
return "<%s x=[%.3g..%.3g], y=%.3g, ey=[%.3g,%.3g]>" % \
(self.__class__.__name__, self.xmin, self.xmax, self.val, self.errs[0], self.errs[1])
class IpolBin(Bin):
"""
A bin containing a value interpolation and its error(s)
TODO:
* Provide ierr and ierrs getter/setter pairs cf. err/errs on DataBin? They can't be averaged (?), so not sure it makes sense...
* Allow ipol'd error handling, with wrapped relative error parameterisation as an option?
"""
__slots__ = ["ival", "ierrs", "__dict__"]
def __init__(self, xmin, xmax, ival=None, ierrs=None, n=None):
Bin.__init__(self, xmin, xmax, n)
self.ival = ival
self.ierrs = ierrs
#def val(self, *params, vmin=None, vmax=None): #< needs Python3
# return self.ival.value(*params, vmin=vmin, vmax=vmax)
def val(self, *params, **vminmax):
"Get the interpolated value of this bin"
vmin = vminmax.get("vmin", None)
vmax = vminmax.get("vmax", None)
return self.ival.value(*params, vmin=vmin, vmax=vmax)
def der(self, *params, **vminmax):
"Get the derivative according to the parametrisation"
return self.ival.der(*params)
def grad(self, *params, **vminmax):
"Get the gradient according to the parametrisation"
return self.ival.grad(*params)
# TODO: need uniform access to two ipols regardless of what's stored (and maybe also a way to make a single avg Ipol...)
#def err(self, *params, emin=0, emax=None): #< needs Python3
def err(self, *params, **eminmax):
"Get a single, averaged interpolated error for this bin"
# emin = eminmax.get("emin", 0)
# emax = eminmax.get("emax", None)
# if self.ierrs is None:
# return 0.0
# elif hasattr(self.ierrs, "__len__"):
# assert len(self.ierrs) == 2
# return (self.ierrs[0].value(*params, vmin=emin, vmax=emax) + self.ierrs[1].value(*params, vmin=emin, vmax=emax))/2.0
# else:
# return self.ierrs.value(*params, vmin=emin, vmax=emax)
es = self.errs(*params, **eminmax)
return (es[0] + es[1])/2.0
#def errs(self, params, emin=0, emax=None): #< needs Python3
def errs(self, *params, **eminmax):
"Get a pair of interpolated errors for this bin"
emin = eminmax.get("emin", 0)
emax = eminmax.get("emax", None)
if self.ierrs is None:
return (0.0, 0.0)
elif hasattr(self.ierrs, "__len__"):
assert len(self.ierrs) == 2
return (self.ierrs[0].value(*params, vmin=emin, vmax=emax), self.ierrs[1].value(*params, vmin=emin, vmax=emax))
else:
e = self.ierrs.value(*params, vmin=emin, vmax=emax)
return (e, e)
@property
def has_const_err():
"Determine whether this bin's errors are fixed or variable -- the latter requires regularisation"
if self.ierrs is None:
return True
if hasattr(self.ierrs, "__len__"):
assert len(self.ierrs) == 2
return (self.ierrs[0].order == 0 and self.ierrs[1].order == 0)
else:
return self.ierrs.order == 0
#def toDataBin(self, *params, vmin=None, vmax=None, emin=0, emax=None): #< needs Python3
def toDataBin(self, *params, **veminmax): #< needs Python3
"Convert this IpolBin to a DataBin with values and errors computed at params, with optional range limits"
vmin = veminmax.get("vmin", None)
vmax = veminmax.get("vmax", None)
emin = veminmax.get("vmin", 0)
emax = veminmax.get("vmax", None)
db = DataBin(self.xmin, self.xmax,
val=self.val(*params, vmin=vmin, vmax=vmax),
errs=self.errs(*params, vmin=emin, vmax=emax))
return db
def __repr__(self):
s = "<%s x=[%.3g..%.3g]" % (self.__class__.__name__, self.xmin, self.xmax)
try:
s += ", %d params, ival order %d" % (self.ival.dim, self.ival.order)
except:
pass
try:
s += ", ierr order %d" % self.ierrs[0].order
except:
pass
s += ">"
return s
+
+
+
+def mkEnvelope(histos):
+ """ Take DataHistos and return coordinates for plotting """
+ # Iterate over bins, get envelope representation
+ # For each bin, return [xmin, xmax, mean(y), min(y), max(y)]
+ E=[]
+ for num, b in enumerate(histos[histos.keys()[0]].bins):
+ t_b = [x.bins[num].val for x in histos.values()]
+ E.append([b.xmin, b.xmax, sum(t_b)/len(t_b), min(t_b), max(t_b)])
+ return E
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Tue, Nov 19, 8:21 PM (1 d, 5 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3806012
Default Alt Text
(8 KB)
Attached To
rPROFESSORHG professorhg
Event Timeline
Log In to Comment