Go to the documentation of this file.00001 #include "../interface/JacknifeQuantile.h"
00002 #include <cmath>
00003 #include <stdexcept>
00004 #include <iostream>
00005 #include <algorithm>
00006 #include <Math/QuantFuncMathMore.h>
00007 #include <RooAbsData.h>
00008 #include <RooRealVar.h>
00009
00010 QuantileCalculator::QuantileCalculator()
00011 {
00012 }
00013
00014 QuantileCalculator::~QuantileCalculator()
00015 {
00016 }
00017
00018 QuantileCalculator::QuantileCalculator(const std::vector<double> &values, const std::vector<double> &weights)
00019 {
00020 import<double>(values, weights);
00021 }
00022
00023 QuantileCalculator::QuantileCalculator(const std::vector<float> &values, const std::vector<float> &weights)
00024 {
00025 import<float>(values, weights);
00026 }
00027
00028 QuantileCalculator::QuantileCalculator(const RooAbsData &data, const char *varName, int firstEntry, int lastEntry)
00029 {
00030 if (lastEntry == -1) lastEntry = data.numEntries();
00031 const RooArgSet *set = data.get();
00032 const RooRealVar *x = dynamic_cast<const RooRealVar *>(set->find(varName));
00033 if (x == 0) {
00034 set->Print("V");
00035 throw std::logic_error("Parameter of interest not in the idataset");
00036 }
00037 sumw_.resize(1, 0.0);
00038 if (firstEntry < lastEntry) {
00039 points_.resize(lastEntry - firstEntry);
00040 for (int i = firstEntry, j = 0; i < lastEntry; ++i, ++j) {
00041 data.get(i);
00042 points_[j].x = x->getVal();
00043 points_[j].w = data.weight();
00044 sumw_[0] += points_[j].w;
00045 }
00046 }
00047 }
00048
00049 void QuantileCalculator::randomizePoints()
00050 {
00051 std::random_shuffle(points_.begin(), points_.end());
00052 }
00053
00054 std::pair<double,double> QuantileCalculator::quantileAndError(double quantile, Method method)
00055 {
00056 if (method == Simple) {
00057 std::sort(points_.begin(), points_.end());
00058 quantiles(quantile, false);
00059 return std::pair<double,double>(quantiles_[0], 0);
00060 } else if (method == Sectioning || method == Jacknife) {
00061 int m = guessPartitions(points_.size(), quantile);
00062 partition(m, (method == Jacknife));
00063 std::sort(points_.begin(), points_.end());
00064 quantiles(quantile, (method == Jacknife));
00065 double avg = 0;
00066 for (int i = 0; i < m; ++i) {
00067 avg += quantiles_[i];
00068 }
00069 avg /= m;
00070 double rms = 0;
00071 for (int i = 0; i < m; ++i) {
00072 rms += (quantiles_[i] - avg)*(quantiles_[i] - avg);
00073 }
00074 rms = sqrt(rms/(m*(m-1)));
00075 double onesigma = ROOT::Math::tdistribution_quantile_c(0.16, m-1);
00076 return std::pair<double,double>(avg, rms * onesigma);
00077 }
00078 return std::pair<double,double>(0,-1);
00079 }
00080
00081 int QuantileCalculator::guessPartitions(int size, double quantile)
00082 {
00083
00084 double smallnum = size * std::min(quantile, 1-quantile);
00085
00086
00087 int n = 5;
00088 std::cout << " ..... will split the " << size << " events in " << n << " subsets, smallnum is " << smallnum << std::endl;
00089 return n;
00090 }
00091
00092 template<typename T>
00093 void QuantileCalculator::import(const std::vector<T> &values, const std::vector<T> &weights)
00094 {
00095 int n = values.size();
00096 points_.resize(values.size());
00097 sumw_.resize(1); sumw_[0] = 0.0;
00098 for (int i = 0; i < n; ++i) {
00099 points_[i].x = values[i];
00100 points_[i].w = weights.empty() ? 1 : weights[i];
00101 points_[i].set = 0;
00102 sumw_[0] += points_[i].w;
00103 }
00104 }
00105
00106
00107 void QuantileCalculator::partition(int m, bool doJacknife)
00108 {
00109 int n = points_.size();
00110 sumw_.resize(m+1);
00111 std::fill(sumw_.begin(), sumw_.end(), 0.0);
00112 double alpha = double(m)/n;
00113 for (int i = 0, j = 0; i < n; ++i) {
00114 j = floor(i*alpha);
00115 points_[i].set = j;
00116 sumw_[j] += points_[i].w;
00117 }
00118 if (doJacknife) {
00119
00120
00121
00122 for (int j = 0; j < m; ++j) sumw_[m] += sumw_[j];
00123
00124 for (int j = 0; j < m; ++j) sumw_[j] = (sumw_[m] - sumw_[j]);
00125 }
00126 }
00127
00128 void QuantileCalculator::quantiles(double quantile, bool doJacknife)
00129 {
00130 int m = sumw_.size()-1;
00131 int n = points_.size();
00132 quantiles_.resize(m+1);
00133 for (int j = 0; j <= m; ++j) {
00134 double runningSum = 0;
00135 double threshold = quantile * sumw_[j];
00136 int ilow = 0, ihigh = n-1;
00137 for (int i = 0; i < n; ++i) {
00138 if ((points_[i].set == j) == doJacknife) continue;
00139
00140 if (runningSum + points_[i].w <= threshold) {
00141 runningSum += points_[i].w;
00142 ilow = i;
00143 } else {
00144 ihigh = i;
00145 break;
00146 }
00147 }
00148 if (runningSum == threshold) {
00149 quantiles_[j] = points_[ilow].x;
00150 } else {
00151 quantiles_[j] = 0.5*(points_[ilow].x + points_[ihigh].x);
00152 }
00153 }
00154 for (int j = 0; j <= m; ++j) {
00155
00156 }
00157 if (doJacknife) {
00158
00159 for (int j = 0; j < m; ++j) {
00160 quantiles_[j] = m * quantiles_[m] - (m-1) * quantiles_[j];
00161 printf(" ... jacknife quantile of section %d: %6.3f\n", j, quantiles_[j]);
00162 }
00163 }
00164 }