Page MenuHomeHEPForge

No OneTemporary

Index: trunk/unfold.py
===================================================================
--- trunk/unfold.py (revision 20)
+++ trunk/unfold.py (revision 21)
@@ -1,130 +1,115 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
import sys
import numpy as np
from math import *
from utils import *
from aru import *
from kernel import MyKernel
def GetData(inputFileName):
from ROOT import TFile
ntuple = TFile.Open(inputFileName).GetListOfKeys()[0].ReadObj()
data = np.empty(ntuple.GetEntries())
for i in xrange(ntuple.GetEntries()):
ntuple.GetEntry(i)
data[i] = ntuple.GetArgs()[0]
return data
# define input/output, minimal checks
try:
inputFilename = sys.argv[1]
outputFilename = sys.argv[2]
if not os.path.exists(inputFilename):
raise SystemExit("Input file %s does not exist."%inputFilename)
if os.path.exists(outputFilename):
raise SystemExit("Output file %s does exist, I don't dare to overwrite."%outputFilename)
except IndexError:
raise SystemExit("Wrong number of arguments. Usage: unfold.py <inputFile> <outputFile>")
# inputFile contains the raw data as a TNtupleD with a single branch
print "reading data..."
data = GetData(inputFilename)
# replace implementation of MyKernel by a proper kernel
kernel = MyKernel()
# x-range to be unfolded, may be set to other values
xmin = np.min(data)
xmax = np.max(data)
# customize number of knots (use a sufficiently large number) and their positions
nKnots = 20
xknots = np.linspace(xmin,xmax,nKnots)
# main program, encapsulated in ARU object
print "unfolding..."
aru = ARU(kernel, ToVector(xknots))
-c_coefs, c_cov = aru.Unfold(ToVector(data))
+coefs, cov = aru.Unfold(ToVector(data))
unfolded = aru.GetUnfoldedSpline()
folded = aru.GetFoldedSpline()
-c_refCoefs = aru.GetReferenceCoefficients()
+refCoefs = aru.GetReferenceCoefficients()
-coefs = Extract(c_coefs)
-cov = Extract(c_cov)
+coefs = Extract(coefs)
+cov = Extract(cov)
# writing the output file with contents
# - TNtupleD with variables
# x : sample value
# yref : final reference distribution (for checking)
# yfitted : folded distribution (the actual fit to the data)
# yunfolded: unfolded distribution (the solution)
# ysigma : uncertainty of yunfolded
# - TVectorD, coefficients of the solution
# - TMatrixDSym, covariance matrix of the solution
print "Writing result..."
-class Sigma(object):
- def __init__(self,unfolded, coefs, cov):
- self.unfolded = unfolded
- self.coefs = coefs
- self.cov = cov
- def __call__(self,x):
- n = self.unfolded.GetSize()
- bs = [ unfolded.Basis(k)(x) for k in xrange(n) ]
- return np.sqrt( np.dot(np.dot(bs,cov),bs) )
-
xs = np.linspace(xmin,xmax,200)
-yref = np.vectorize(lambda x: unfolded(c_refCoefs,x))(xs)
-yfitted = np.vectorize(lambda x: folded (c_coefs,x))(xs)
-yunfolded = np.vectorize(lambda x: unfolded(c_coefs,x))(xs)
-sigma = Sigma(unfolded, coefs, cov)
-ysigma = np.vectorize(sigma)(xs)
+yref = np.vectorize(lambda x: unfolded(refCoefs,x))(xs)
+yfitted = np.vectorize(lambda x: folded (coefs,x))(xs)
+yunfolded = np.vectorize(lambda x: unfolded(coefs,x))(xs)
+ysigma = GetSigma(unfolded,cov,xs)
from ROOT import TNtupleD, TFile, TMatrixDSym, TVectorD
nt = TNtupleD("nt","","x:yref:yfitted:yunfolded:ysigma")
for i in xrange(len(xs)):
nt.Fill(xs[i],yref[i],yfitted[i],yunfolded[i],ysigma[i])
rootCoefs = TVectorD(len(coefs))
rootCov = TMatrixDSym(len(coefs))
for i in xrange(len(coefs)):
rootCoefs[i] = coefs[i]
for j in xrange(len(coefs)):
rootCov[i][j] = cov[i][j]
f = TFile.Open(outputFilename,"RECREATE")
nt.Write()
rootCoefs.Write()
rootCov.Write()
f.Close()
try:
# draw everything, if matplotlib is installed
from matplotlib import pyplot as plt
- from matplotlib.patches import Polygon
- poly = Polygon(MakeSigmaPatch(unfolded, c_coefs, cov, xknots), closed=True)
- poly.set(ec="b",fc="b",alpha=0.1,fill=True,zorder=0)
- plt.gca().add_patch(poly)
-
plt.plot(xs,yref,"y",lw=2,label="$g(x)$",zorder=1)
plt.plot(xs,yfitted,"r",lw=1,label="$f(y)$",zorder=2)
plt.plot(xs,yunfolded,"b",lw=2,label="$b(x)$",zorder=2)
+ plt.fill_between(xs,yunfolded-ysigma,yunfolded+ysigma,edgecolor="b",facecolor="b",alpha=0.1,zorder=0)
xh, w, werr = GetScaledHistogram(data,bins=20,range=(xmin,xmax))
plt.errorbar(xh,w,werr,fmt="ko",capsize=0,label="data",zorder=3)
plt.ylim(ymin=0)
plt.xlim(xmin,xmax)
plt.xlabel("x")
plt.ylabel(r"$N_\mathrm{data} \times p.d.f.$")
plt.legend(loc="upper left")
plt.show()
except ImportError:
print "Install matplotlib to get plots of the solution."
Index: trunk/tests/blobel.py
===================================================================
--- trunk/tests/blobel.py (revision 20)
+++ trunk/tests/blobel.py (revision 21)
@@ -1,87 +1,82 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
import numpy as np
from matplotlib import pyplot as plt
from utils import *
from aru import *
from kernel import BlobelKernel
kernel = BlobelKernel()
print "generate"
try:
np.random.seed(int(sys.argv[1]))
except IndexError:
np.random.seed(1)
nMC = 5000
def Model(x):
b = (1.0,10.0,5.0)
g = (2.0,0.2,0.2)
c = (0.4,0.8,1.5)
result = 0.0
for k in xrange(3):
result += b[k]*g[k]**2/((x-c[k])**2+g[k]**2)
return result
rxs = []
while True:
xy = np.random.rand(2)
x = xy[0]*2
y = xy[1]*12
if y < Model(x):
rxs.append(x)
if len(rxs) == nMC:
break
data = []
for x in rxs:
y = kernel.Y(x) + 0.1*np.random.randn()
z = np.random.rand()
if z < kernel.Efficiency(y):
data.append(y)
xknots = np.linspace(0,2,20)
aru = ARU(kernel, ToVector(xknots))
coefs, cov = aru.Unfold(ToVector(data))
unfolded = aru.GetUnfoldedSpline()
folded = aru.GetFoldedSpline()
refCoefs = aru.GetReferenceCoefficients()
# draw everything
xs = np.linspace(xknots[0],xknots[-1],200)
from scipy.integrate import quad
ymodel = nMC*Model(xs)/quad(Model,0,2)[0]
yprior = np.vectorize(lambda x: unfolded(refCoefs,x))(xs)
yfitted = np.vectorize(lambda x: folded (coefs,x))(xs[xs<1.8])
yunfolded = np.vectorize(lambda x: unfolded(coefs,x))(xs)
-
-plt.figure(1)
-
-from matplotlib.patches import Polygon
-poly = Polygon(MakeSigmaPatch(unfolded, coefs, cov, xknots), closed=True)
-poly.set(ec="b",fc="b",alpha=0.1,fill=True,zorder=0)
-plt.gca().add_patch(poly)
+ysigma = GetSigma(unfolded,cov,xs)
plt.plot(xs,ymodel,"g--",lw=2,label="$t(x)$",zorder=1)
plt.plot(xs,yprior,"y",lw=3,label="$g(x)$",zorder=1)
plt.plot(xs[xs<1.8],yfitted,"r",lw=1,label="$f(y)$",zorder=3)
plt.plot(xs,yunfolded,"b",lw=2,label="$b(x)$",zorder=2)
+plt.fill_between(xs,yunfolded-ysigma,yunfolded+ysigma,edgecolor="b",facecolor="b",alpha=0.1,zorder=0)
xh, w, werr = GetScaledHistogram(data,bins=20,range=(folded.GetStart(),folded.GetStop()))
plt.errorbar(xh,w,werr,fmt="ko",capsize=0,label="data",zorder=4)
plt.ylim(ymin=0)
plt.xlabel("x")
plt.ylabel(r"$\mathrm{d}N / \mathrm{d} x$")
plt.legend(loc="upper left").get_frame().set_visible(0)
plt.show()
Index: trunk/tests/foldspline.py
===================================================================
--- trunk/tests/foldspline.py (revision 0)
+++ trunk/tests/foldspline.py (revision 21)
@@ -0,0 +1,44 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+import numpy as np
+from matplotlib import pyplot as plt
+from math import *
+from pyik.mplext import *
+from pyik.numpyext import *
+from aru import *
+from kernel import *
+
+kernel = GaussianKernel(0.1);
+
+nKnots = 10
+xknots = KnotVector(nKnots);
+for i in xrange(nKnots):
+ xknots[i] = float(i)/(nKnots-1)
+
+unfolded = SplineFunction1D(xknots)
+folded = FoldedSplineFunction1D(kernel, unfolded)
+
+xs = np.linspace(-0.1,1.1,200)
+
+selKnot = 1
+f1 = lambda x : unfolded[selKnot](x)
+f2 = lambda x : folded[selKnot](x)
+f1s = np.vectorize(f1)(xs)
+f2s = np.vectorize(f2)(xs)
+
+from scipy.integrate import *
+
+f1ia = unfolded[selKnot].Integral()
+f1ib = quad(f1,unfolded.GetStart(),unfolded.GetStop())[0]
+f2ia = folded[selKnot].Integral(folded.GetStart(),folded.GetStop())
+f2ib = quad(f2,folded.GetStart(),folded.GetStop())[0]
+
+print f1ia,"[ %g, acc. %i ]"%(f1ib,log10(abs(f1ia-f1ib)))
+print f2ia,"[ %.12g, acc. %i ]"%(f2ib,log10(abs(f2ia-f2ib)))
+
+f1mask = f1s>0
+f2mask = f2s>0
+plt.plot(xs[f1mask],f1s[f1mask],"k-")
+plt.plot(xs[f2mask],f2s[f2mask],"r-")
+plt.xlim(xknots[0],xknots[xknots.size()-1])
+plt.show()
Property changes on: trunk/tests/foldspline.py
___________________________________________________________________
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: trunk/tests/regfit.py
===================================================================
--- trunk/tests/regfit.py (revision 20)
+++ trunk/tests/regfit.py (revision 21)
@@ -1,86 +1,83 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
import numpy as np
from matplotlib import pyplot as plt
from pyik.mplext import auto_adjust
from utils import *
from aru import *
from kernel import *
print "generate"
np.random.seed(int(sys.argv[1]))
nMC = int(sys.argv[2])
norms = (0.3,0.7)
means = (0.3,0.7)
sigmas = (0.1,0.05)
kernelSigma = 0.1
# ~norms = (1.,20.)
# ~means = (0.4,0.6)
# ~sigmas = (0.05,0.2)
# ~kernelSigma = 0.1
model = ToyModel(norms,means,sigmas)
data = model.rvs(nMC)
kernel = GaussianKernel(kernelSigma)
data += kernelSigma*np.random.randn(nMC)
-xknots = np.linspace(0,1,40)
+xknots = np.linspace(0,1,20)
aru = ARU(kernel, ToVector(xknots))
-c_coefs, c_cov = aru.Unfold(ToVector(data))
+coefs, cov = aru.Unfold(ToVector(data))
unfolded = aru.GetUnfoldedSpline()
folded = aru.GetFoldedSpline()
-c_refCoefs = aru.GetReferenceCoefficients()
+refCoefs = aru.GetReferenceCoefficients()
modelNorm = np.sum((folded.GetStart()<=data)*(data<=folded.GetStop()))
csum = 0.0
for k in xrange(unfolded.GetSize()):
- csum += c_coefs[k]*unfolded[k].Integral()
+ csum += coefs[k]*unfolded[k].Integral()
print "integral comparison",modelNorm, csum
# draw everything
xs = np.linspace(0,1,200)
ysmodel = nMC*model(xs)
-ysprior = np.vectorize(lambda x: unfolded(c_refCoefs,x))(xs)
-ysfitted = np.vectorize(lambda x: folded (c_coefs,x))(xs)
-ysunfolded = np.vectorize(lambda x: unfolded(c_coefs,x))(xs)
-
-from matplotlib.patches import Polygon
-poly = Polygon(MakeSigmaPatch(unfolded, c_coefs, c_cov, xknots), closed=True)
-poly.set(ec="b",fc="b",alpha=0.1,fill=True,zorder=0)
-plt.gca().add_patch(poly)
+ysprior = np.vectorize(lambda x: unfolded(refCoefs,x))(xs)
+ysfitted = np.vectorize(lambda x: folded (coefs,x))(xs)
+ysunfolded = np.vectorize(lambda x: unfolded(coefs,x))(xs)
+yssigma = GetSigma(unfolded,cov,xs)
plt.plot(xs,ysmodel,"g--",lw=2,label="$t(x)$",zorder=1)
plt.plot(xs,ysprior,"y",lw=3,label="$g(x)$",zorder=1)
plt.plot(xs,ysfitted,"r",lw=1,label="$f(y)$",zorder=3)
plt.plot(xs,ysunfolded,"b",lw=2,label="$b(x)$",zorder=2)
+plt.fill_between(xs, ysunfolded-yssigma, ysunfolded+yssigma, edgecolor="b", facecolor="b", alpha=0.1, zorder=0)
xh, w, werr = GetScaledHistogram(data,bins=20,range=(0,1))
plt.errorbar(xh,w,werr,fmt="ko",capsize=0,label="data",zorder=4)
# ~print "noreg fit"
# ~c_coefs_noreg = std.vector("double")(nBasis,1)
# ~objective.SetWeight(0)
# ~Fit(objective,c_coefs_noreg)
# ~yunreg = np.vectorize(lambda xx: unfolded(c_coefs_noreg,xx))(x)
# ~plt.plot(x,yunreg,"b:",lw=1,label="$b_\mathrm{w=0}(x)$",zorder=1)
plt.ylim(ymin=0)
plt.xlabel("x")
plt.ylabel(r"$\mathrm{d}N / \mathrm{d} x$")
plt.legend(loc="upper left").get_frame().set_visible(0)
plt.show()
Index: trunk/src/Integrator.h
===================================================================
--- trunk/src/Integrator.h (revision 20)
+++ trunk/src/Integrator.h (revision 21)
@@ -1,164 +1,155 @@
/*
This file is part of ARU, a software to unfold detector effects
from data distributions.
Copyright (C) 2011 Karlsruhe Instiute of Technology,
contact Hans Dembinski <hans.dembinski@kit.edu>
ARU is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
ARU is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with ARU. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _Aru_Integrator_h_
#define _Aru_Integrator_h_
#include <cmath>
#include <vector>
#include <stdexcept>
#include <string>
#include <sstream>
#include <limits>
namespace Aru {
namespace OfflineIntegrator {
// based on Offline/Utilities/Math/Integrator.h
// from the Pierre Auger Observatory;
// LICENSE.Auger applies to everything inside
// the current namespace
inline
double
PolynomialInterpolation(const size_t n,
const double px[],
const double py[],
const double x,
double& dy)
{
if (!n)
return 0;
double minDist = std::fabs(x - px[0]);
size_t k = 0;
double c[n];
double d[n];
c[0] = py[0];
d[0] = py[0];
double oldx = px[0];
for (size_t i = 1; i < n; ++i) {
const double newx = px[i];
oldx = newx;
const double dist = std::fabs(x - newx);
if (dist < minDist) {
minDist = dist;
k = i;
}
c[i] = d[i] = py[i];
}
double y = py[k];
for (size_t m = 1; m < n; ++m) {
const size_t nm = n - m;
for (size_t i = 0; i < nm; ++i) {
const double xa = px[i];
const double xb = px[i+m];
const double dx = xb - xa;
const double cd = (c[i+1] - d[i]) / dx;
c[i] = (x-xa)*cd;
d[i] = (x-xb)*cd;
}
dy = (2*k < nm) ? c[k] : d[--k];
y += dy;
}
return y;
}
/// average of a function represented with equidistant boxes
template<class Functor>
inline
double
GetBoxAverage(const Functor& functor, const double start, const double step, const size_t n)
{
double sum = 0;
for (size_t i = 0; i < n; ++i) {
const double x = start + i*step;
sum += functor(x);
}
return sum/n;
}
template<class Functor>
- inline
- double
- GetTrapezoidalAverage(const Functor& functor,
- const double previousApproximation,
- const double a, const double delta, const size_t level)
- {
- const size_t n = 1 << (level - 1); // = 2^(level-1)
- const double step = delta/n;
- return 0.5*(previousApproximation +
- GetBoxAverage(functor, a+0.5*step, step, n));
- }
-
- template<class Functor>
double
Integrate(const Functor& functor, const double a, const double b,
const double accuracy = 1e-8,
const size_t order = 5, const size_t maxIterations = 15)
{
// calculates trapezoidal average of functor as
// a function of decreasing stepsize h, then
// extrapolates series to h = 0
const double delta = b - a;
const double eps = 0.5*accuracy;
std::vector<double> tInt(maxIterations+1);
std::vector<double> tStep(maxIterations+1);
- double oldInt = tInt[0] = GetBoxAverage(functor, a, delta, 2);
+ tInt[0] = GetBoxAverage(functor, a, delta, 2);
tStep[0] = delta;
+ tInt[1] = 0.5*(tInt[0] + functor(a+0.5*delta));
+ tStep[1] = delta/4; // h^2
double extrapolation = 0;
- for (size_t i=1; i <= maxIterations; ++i) {
- oldInt = tInt[i] = GetTrapezoidalAverage(functor, oldInt, a, delta, i);
- tStep[i] = delta/(1 << (2*i));
+ for (size_t i=2; i <= maxIterations; ++i) {
+ const size_t n = 1 << (i - 1); // = 2^(j-1)
+ const double step = delta/n;
+ tInt[i] = 0.5*(tInt[i-1] + GetBoxAverage(functor, a+0.5*step, step, n));
+ tStep[i] = delta/(1 << (2*i)); // h^2
const int first = i - order + 1;
if (first < 0) continue;
double residual;
extrapolation =
PolynomialInterpolation(order, &tStep[first], &tInt[first], 0, residual);
if (std::isnan(extrapolation))
throw std::runtime_error("got nan during integration");
if (std::fabs(residual) < eps*std::fabs(extrapolation))
return delta*extrapolation;
}
if (std::fabs(extrapolation) > accuracy)
throw std::runtime_error("maximal level reached in integration, result still inaccurate");
return delta*extrapolation;
}
} // NS OfflineIntegrator
using OfflineIntegrator::Integrate;
}
#endif
Index: trunk/utils.py
===================================================================
--- trunk/utils.py (revision 20)
+++ trunk/utils.py (revision 21)
@@ -1,430 +1,404 @@
# -*- coding: utf-8 -*-
# This file is part of ARU, a software to unfold detector effects
# from data distributions.
#
# Copyright (C) 2011 Karlsruhe Instiute of Technology,
# contact Hans Dembinski <hans.dembinski@kit.edu>
#
# ARU is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Foobar is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Foobar. If not, see <http://www.gnu.org/licenses/>.
import numpy as np
from math import *
from scipy.stats import norm
def Extract(obj):
"""
Extracts data from ROOT objects and returns corresponding Numpy arrays.
Extract can be used with a string argument. In this case, the string is
interpreted as a filename of a ROOT file. The ROOT file is opened and
Extract is applied on each object inside the file. The result is returned
as a dictionary, mapping the key names to the outputs.
Authors
-------
Hans Dembinski <hans.dembinski@kit.edu>
"""
import ROOT
import numpy as np
from aru import Vector, Matrix
if isinstance(obj, Vector):
a = np.empty(obj.size())
for i in xrange(len(a)):
a[i] = obj[i]
return a
if isinstance(obj, Matrix):
m = obj.GetShape(0)
n = obj.GetShape(1)
a = np.empty((m,n))
for i in xrange(m):
for j in xrange(n):
a[i,j] = obj[i][j]
return a
if isinstance(obj, ROOT.std.vector("double")):
a = np.empty(obj.size())
for i in xrange(len(a)):
a[i] = obj[i]
return a
if isinstance(obj, str):
f = ROOT.TFile.Open(obj)
d = {}
for key in f.GetListOfKeys():
d[key.GetName()] = Extract(key.ReadObj())
return d
if isinstance(obj, ROOT.TVectorD):
n = obj.GetNoElements()
a = np.empty(n)
for i in xrange(n):
a[i] = obj[i]
return a
if isinstance(obj, ROOT.TMatrixD) or isinstance(obj, ROOT.TMatrixDSym):
a = np.empty((obj.GetNcols(),obj.GetNrows()))
for i in xrange(obj.GetNcols()):
for j in xrange(obj.GetNrows()):
a[i,j] = obj(i,j)
return a
raise ValueError("Extract cannot handle object %s yet, please take a look at pyik.rootext and implement it"%(type(obj)))
def ToVector(array):
from aru import Vector
n = len(array)
res = Vector(n)
for i in xrange(n):
res[i] = array[i]
return res
def centers(x):
"""
Computes the centers of an array of bin edges.
Parameters
----------
x: array-like
A 1-d array containing lower bin edges.
Returns
-------
c: array of dtype float
Returns the centers of the bins.
hw: array of dtype float
Returns the half-width of the bins.
Examples
--------
>>> c,hw = centers([0.0,1.0,2.0])
>>> print c, hw
[ 0.5 1.5] [ 0.5 0.5]
Authors
-------
Hans Dembinski <hans.dembinski@kit.edu>
"""
n = len(x)-1
c = np.empty(n)
hw = np.empty(n)
for i in xrange(len(x)-1):
hw[i] = 0.5*(x[i+1]-x[i])
c[i] = x[i] + hw[i]
return c,hw
class ToyModel:
def __init__(self,norms,mus,sigmas):
self.norms = np.array(norms)
self.norms /= np.sum(self.norms)
self.mus = mus
self.sigmas = sigmas
def __call__(self,x):
result = 0.0
n = len(self.norms)
for i in xrange(n):
result += self.norms[i]*norm(self.mus[i],self.sigmas[i]).pdf(x)
return result
def rvs(self, nEvents):
n = len(self.norms)
ps = np.zeros(n)
for i in xrange(n):
ps[i:] += self.norms[i]
ps /= np.sum(self.norms)
counts = np.zeros(n,dtype=int)
for i in xrange(nEvents):
for j,p in enumerate(ps):
uniran = np.random.rand()
if uniran < p:
counts[j] += 1
break
rvs = np.array([])
for i in xrange(n):
rvs = np.append(rvs,norm(self.mus[i],self.sigmas[i]).rvs(counts[i]))
return rvs
def MinimumMeanSquaredErrorFit(obj, starts):
from aru import Vector, Matrix
nBasis = obj.GetBasisSize()
foldedCache = obj.GetFoldedCache()
foldedMuCache = obj.GetFoldedMuCache()
nUnbinned = foldedCache.GetShape(0)
nBinned = foldedMuCache.GetShape(0)
nEventsForHistogram = obj.GetNEventsForHistogram()
fmatrix = obj.GetFMatrix()
# start values
c_coefs = Vector(nBasis)
for i in xrange(nBasis): c_coefs[i] = float(starts[i])
c_cov = Matrix(nBasis)
def MeanSquaredError(sqrtw):
w = sqrtw*sqrtw
obj.SetWeight(w)
obj.Minimize(c_coefs)
obj.CovarianceStat(c_cov, c_coefs)
obj.UpdateReference(c_coefs)
result = 0.0
if w != 0.0:
for i in xrange(nBasis):
for j in xrange(i,nBasis):
result += (1 if i==j else 2)*(c_cov[i][j]+c_coefs[i]*c_coefs[j])*fmatrix[i][j]
for i in xrange(nUnbinned):
folded = 0.0
for k in xrange(nBasis):
folded += c_coefs[k]*foldedCache[i][k]
result -= 2*folded
for ib in xrange(nBinned):
hw = obj.GetHistogramWeight(ib)
if hw<nEventsForHistogram: continue
foldedMu = 0.0
for k in xrange(nBasis):
foldedMu += c_coefs[k]*foldedMuCache[ib][k]
result -= 2*hw*foldedMu/obj.GetHistogramStep(ib)
print "iterating (%.5e): current weight = %g"%(result,w)
return result
from scipy.optimize import brent
sqrtw = brent(MeanSquaredError, brack=(0,1), tol=1e-2)
w = sqrtw*sqrtw
obj.SetWeight(w)
obj.Minimize(c_coefs)
return c_coefs
def GetScaledHistogram(data,bins,range=None):
ws, xedges = np.histogram(data,bins=bins,range=range)
if type(bins) is not int:
bins = len(xedges)-1
xs = centers(xedges)[0]
werrs = np.sqrt(ws)
factor = bins/float(xedges[-1]-xedges[0]) # due to binning
ws = np.asarray(ws,np.float)
ws *= factor
werrs *= factor
return xs, ws, werrs
-def MakeSigmaPatch(basis, coef, cov, xknot):
+def GetSigma(basis, cov, xs):
- nover = 10
-
- xs = []
- for i in xrange(len(xknot)-1):
- x0 = xknot[i]
- x1 = xknot[i+1]
-
- dx = (x1-x0)/nover
-
- for j in xrange(nover-1):
- xs.append(x0+j*dx)
- xs.append(xknot[-1])
-
- def CalcSigma(basis,cov,x):
+ def Sigma(x):
n = basis.GetSize()
s2 = 0.0
for l in xrange(n):
- for m in xrange(n):
- s2 += basis[l](x)*basis[m](x)*cov[l][m]
+ for m in xrange(l,n):
+ s2 += (1 if l==m else 2)*basis[l](x)*basis[m](x)*cov[l][m]
if s2 < 0:
+ print s2,"< 0! at",x
s2 = 0
return sqrt(s2)
- y1 = [ basis(coef,x) for x in xs ]
-
- y2 = [ CalcSigma(basis,cov,x) for x in xs ]
-
- xy = []
-
- n = len(xs)
- # upper
- for i in xrange(n):
- xy.append([ xs[i], y1[i]+y2[i] ])
- # lower
- for i in xrange(n-1,0,-1):
- xy.append([ xs[i], y1[i]-y2[i] ])
-
- return np.array(xy)
+ return np.vectorize(Sigma)(xs)
def JackknifeShifts(obj,c_coefs):
from aru import TMatrixDSym
nBasis = obj.GetBasisSize()
grad0 = Extract(obj.Gradient(c_coefs))
c_hesse1 = TMatrixDSym(nBasis)
obj.HesseStat(c_hesse1, c_coefs)
c_hesse2 = TMatrixDSym(nBasis)
obj.HesseReg(c_hesse2, c_coefs)
hesse0 = Extract(c_hesse1) + obj.GetWeight()*Extract(c_hesse2)
foldedCache = obj.GetFoldedCache
foldedMuCache = obj.GetFoldedMuCache
shifts = []
coefs = Extract(c_coefs)
for i in xrange(obj.GetUnbinnedSize()):
folded = 0.0
for k in xrange(nBasis):
folded += coefs[k]*foldedCache(k,i)
grad = np.copy(grad0)
hesse = np.copy(hesse0)
for k in xrange(nBasis):
grad[k] += foldedCache(k,i)/folded
for l in xrange(k,nBasis):
delta = foldedCache(k,i)*foldedCache(l,i)/folded**2
hesse[k,l] -= delta
if k!=l:
hesse[l,k] -= delta
u,s,vt = np.linalg.svd(hesse)
hesseInv = np.zeros((nBasis,nBasis))
for k in xrange(nBasis):
for l in xrange(k,nBasis):
for m in xrange(nBasis):
hesseInv[k,l] = vt[k,m]*u[l,m]/s[m]
if k!=l:
hesseInv[l,k] = hesseInv[k,l]
shifts.append(-np.dot(hesseInv,grad))
for ib in xrange(obj.GetBinnedSize()):
hw = obj.GetHistogramWeight(ib)
if hw==0:continue
foldedMu = 0.0
for k in xrange(nBasis):
foldedMu += coefs[k]*foldedMuCache(k,ib)
grad = np.copy(grad0)
hesse = np.copy(hesse0)
for k in xrange(nBasis):
grad[k] += hw*foldedMuCache(k,i)/foldedMu
for l in xrange(k,nBasis):
delta = hw*foldedMuCache(k,i)*foldedMuCache(l,i)/foldedMu**2
hesse[k,l] -= delta
if k!=l:
hesse[l,k] -= delta
u,s,vt = np.linalg.svd(hesse)
hesseInv = np.zeros((nBasis,nBasis))
for k in xrange(nBasis):
for l in xrange(k,nBasis):
for m in xrange(nBasis):
hesseInv[k,l] = vt[k,m]*u[l,m]/s[m]
if k!=l:
hesseInv[l,k] = hesseInv[k,l]
shifts.append(-np.dot(hesseInv,grad))
return shifts
def GetEmpiricalDensity(kernel,unfolded,data):
xa = unfolded.GetStart()
xb = unfolded.GetStop()
result = 0.0
for y in data:
x = kernel.X(y)
if xa <= x and x < xb:
result += 1.0/kernel.Efficiency(y)
return result/(xb-xa)
class ARU(object):
"""
Class with a simple interface for unfolding data with ARU.
Parameters
----------
kernel: VKernel
Instance of the detector kernel, derived from Aru::VKernel.
xknots: std.vector("double")
STL vector of doubles containing the knot positions.
Author
------
Hans Dembinski <hans.dembinski@kit.edu>
"""
def __init__(self, kernel, xknots):
from aru import SplineFunction1D,FoldedSplineFunction1D,KnotVector
self.kernel = kernel
self.unfolded = SplineFunction1D(KnotVector(ToVector(xknots)))
self.folded = FoldedSplineFunction1D(kernel, self.unfolded)
self.referenceCoefs = None
self.weight = None
def Unfold(self, data, nEventsForBinning=100):
"""
Perform the unfolding.
Parameters
----------
data: std.vector("double")
STL vector of doubles containing the observations.
Returns
-------
coefs: std.vector("double")
STL vector of doubles containing the spline coefficients (solution).
cov: TMatrixDSym
Covariance matrix of the spline coefficients (solution).
"""
from aru import ObjectiveFunction, Vector, Matrix
nBasis = self.unfolded.GetSize()
print "creating objective function..."
objective = ObjectiveFunction(data, self.kernel, self.folded, self.unfolded, 4, nEventsForBinning)
starts = objective.GetStartValues()
print "fitting..."
coefs = MinimumMeanSquaredErrorFit(objective, starts)
self.refCoefs = Vector(objective.GetReferenceCoefficients())
self.weight = objective.GetWeight()
cov = Matrix(nBasis)
cov2 = Matrix(nBasis)
objective.CovarianceStat(cov, coefs)
objective.CovarianceReg(cov2, coefs)
cov += cov2
self.objective = objective
return coefs, cov
def GetUnfoldedSpline(self):
return self.unfolded
def GetFoldedSpline(self):
return self.folded
def GetReferenceCoefficients(self):
if self.refCoefs is None:
raise StandardError("no reference computed yet")
return self.refCoefs
def GetWeight(self):
if self.weight is None:
raise StandardError("no weight computed yet")
return self.weight

File Metadata

Mime Type
text/x-diff
Expires
Sat, May 3, 6:36 AM (1 d, 17 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
4983094
Default Alt Text
(28 KB)

Event Timeline