ATLAS Offline Software
LArCalorimeter/LArSamplesMon/src/Residual.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
3 */
4 
6 
7 #include "TMath.h"
8 #include <algorithm>
12 
13 #include "TRandom.h"
14 #include "TH1D.h"
15 
16 #include <iostream>
17 using std::cout;
18 using std::endl;
19 
20 using namespace LArSamples;
21 
22 
23 Residual::Residual(const TVectorD& deltas, int run, int event, double adcMax, double time)
24  : m_deltas(deltas), m_run(run), m_event(event),
25  m_adcMax(adcMax), m_time(time)
26 {
28 }
29 
30 
32 {
34 }
35 
36 
37 TVectorD Residual::scaledDeltas() const
38 {
39  TVectorD vect = deltas();
40  vect *= 1/adcMax();
41  return vect;
42 }
43 
44 
45 double Residual::scaledDelta(short i) const
46 {
47  if (!isInRange(i) || adcMax() <= 0) return 0;
48  return deltas()(i)/adcMax();
49 }
50 
51 
53 {
54  TVectorD vect(lwb(), upb() + 1);
55  vect.SetSub(lwb(), scaledDeltas());
56  vect(upb() + 1) = time();
57  return vect;
58 }
59 
60 
61 bool ResidualCompare::operator()(const Residual& r1, const Residual& r2) const
62 {
63  if (!r1.hasSameRange(r2)) {
64  cout << "WARNING : residuals have different ranges, this may crash the sorting..." << endl;
65  return false;
66  }
67 
68  // Very, very important! Since samples are integers, it *will* happen that some residuals will have *identical* deltas.
69  // It turns out that (at least in the way used here), operator<(double, double) is not a strict weak ordering: we will
70  // have cases where residual1[4] == residual2[4], and then we will have residual1[4] < residual2[4] and residual2[4] < residual1[4]
71  // both true, which will confuse std::sort and cause it to crash... so add this safety (lesson of 2 days of debugging)
72  // Note: if we write a<<b iff a < b - epsilon, then << is indeed a strict weak ordering so all is fine. It does mean there
73  // will be "sorting errors", i.e. residuals that differ by less than epsilon may be sorted the wrong way. But that's fine for our usage.
74  const double epsilon = 1E-5;
75 // cout << "Comparing sample " << m_sampling << ", = "
76 // << (m_sampling == r1.upb() + 1 ? r1.time() : r1.scaledDelta(m_sampling)) << " >/< "
77 // << (m_sampling == r2.upb() + 1 ? r2.time() : r2.scaledDelta(m_sampling)) << " "
78 // << ((m_sampling == r1.upb() + 1 ? r1.time() : r1.scaledDelta(m_sampling)) < (m_sampling == r2.upb() + 1 ? r2.time() : r2.scaledDelta(m_sampling))) << endl;
79 
80  if (r1.isInRange(m_sampling)) return r1.scaledDelta(m_sampling) < r2.scaledDelta(m_sampling) - epsilon;
81  if (m_sampling == r1.upb() + 1) return r1.time() < r2.time() - epsilon;
82  cout << "WARNING : comparison on an unknown sample, this may crash the sorting..." << endl;
83  return false;
84 }
85 
86 
87 bool Residuals::medianVars(TVectorD& medians, TVectorD& widths) const
88 {
89  if (size() == 0) return false;
90  medians.ResizeTo(lwb(), upb() + 1);
91  widths.ResizeTo (lwb(), upb() + 1);
92 
93  double halfSigmaQuantile = TMath::Prob(1,1)/2;
94  double medianQuantile = 0.5;
95 
96  std::vector<Residual> sortedResiduals = m_residuals;
97 
98  for (short i = lwb(); i <= upb() + 1; i++) {
99 // cout << "test-sorting sample " << i << " (n = " << m_residuals.size() << ")" << endl;
100 // std::vector<const Residual*> testSort(m_residuals.size());
101 // ResidualCompare comparer(i);
102 // for (unsigned int i1 = 0; i1 < m_residuals.size(); i1++) {
103 // const Residual& res1 = m_residuals[i1];
104 // unsigned int nBefore = 0;
105 // for (unsigned int i2 = 0; i2 < m_residuals.size(); i2++) {
106 // if (i1 == i2) continue;
107 // const Residual& res2 = m_residuals[i2];
108 // //cout << "comparing " << i1 << " " << i2 << endl;
109 // if (comparer(res2, res1)) nBefore++;
110 // if ((i1 == 3617 || i1 == 3886) && comparer(res2, res1))
111 // cout << i2 << " is bfore " << i1 << " " << res2.scaledDelta(i) << " < " << res1.scaledDelta(i)
112 // << (res2.scaledDelta(i) < res1.scaledDelta(i)) << " " << (res2.scaledDelta(i) < res1.scaledDelta(i) - 1E-3) << endl;
113 // }
114 // cout << "index " << i1 << " : nBefore = " << nBefore << " " << res1.scaledDelta(i) << endl;
115 // while (testSort[nBefore]) { nBefore++; if (nBefore == testSort.size()) cout << "ERROR!!! " << i1 << endl; }
116 // testSort[nBefore] = &res1;
117 // }
118 // cout << "done sorting" << endl;
119 // for (unsigned int i1 = 0; i1 < testSort.size(); i1++) {
120 // const Residual* res1 = testSort[i1];
121 // if (!res1) cout << "ERROR : null at index " << i1 << endl;
122 // for (unsigned int i2 = 0; i2 < i1; i2++) {
123 // const Residual* res2 = testSort[i2];
124 // if (comparer(*res1, *res2)) cout << "Wrong order " << i1 << " " << i2 << endl;
125 // }
126 // }
127 // cout << "done checking" << endl;
128  std::sort(sortedResiduals.begin(), sortedResiduals.end(), ResidualCompare(i));
129  Residual& medianRes = sortedResiduals[(unsigned int)(sortedResiduals.size()*medianQuantile)];
130  Residual& loHalfSigmaRes = sortedResiduals[(unsigned int)(sortedResiduals.size()*halfSigmaQuantile)];
131  Residual& hiHalfSigmaRes = sortedResiduals[(unsigned int)(sortedResiduals.size()*(1 - halfSigmaQuantile))];
132  double median = (i < upb() + 1 ? medianRes.scaledDelta(i) : medianRes.time()) ;
133  double loHalfSigma = (i < upb() + 1 ? loHalfSigmaRes.scaledDelta(i) : loHalfSigmaRes.time());
134  double hiHalfSigma = (i < upb() + 1 ? hiHalfSigmaRes.scaledDelta(i) : hiHalfSigmaRes.time());
135  //cout << loHalfSigma << " " << median << " " << hiHalfSigma << endl;
136  medians[i] = median;
137  widths[i] = (hiHalfSigma - median > median - loHalfSigma ? median - loHalfSigma : hiHalfSigma - median);
138  }
139  return true;
140 }
141 
142 
143 Residuals* Residuals::truncate(double nWidthsRes, double nWidthsTime, unsigned int nMax) const
144 {
145  if (size() == 0) return new Residuals();
146  TVectorD medians, widths;
147 
148  if (nMax > 0) {
149  Residuals* original = new Residuals();
150  for (unsigned int i = 0; i < nMax; i++) original->add(*residual(i));
151  if (!original->medianVars(medians, widths)) { delete original; return nullptr;}
152  delete original;
153  }
154  else {
155  if (!medianVars(medians, widths)) return nullptr;
156  }
157  Residuals* truncated = new Residuals();
158 
159  for (const Residual& residual : m_residuals) {
160  bool pass = true;
161  if (nMax > 0 && truncated->size() == nMax) break;
162  for (short i = lwb(); i <= upb(); i++) {
163  if (nWidthsRes > 0 && TMath::Abs(residual.scaledDelta(i) - medians[i]) > nWidthsRes*widths[i]) {
164  pass = false;
165  break;
166  }
167  }
168  if (!pass) continue;
169  if (nWidthsTime > 0 && TMath::Abs(residual.time() - medians[upb() + 1]) > nWidthsTime*widths[upb() + 1]) continue;
170  truncated->add(residual);
171  }
172  return truncated;
173 }
174 
175 
176 TH1D* Residuals::histogram(short sample, const TString& name, int nBins, double xMin, double xMax) const
177 {
178  TH1D* h = new TH1D(name, "", nBins, xMin, xMax);
179  for (const Residual& residual : m_residuals)
180  h->Fill(sample <= upb() ? residual.scaledDelta(sample) : residual.time());
181  return h;
182 }
183 
184 
186 {
187  if (size() == 0) return nullptr;
188 
189  ResidualCalculator* calc = new ResidualCalculator(lwb(), upb(), weigh);
190  for (const Residual& residual : m_residuals)
191  calc->fill(residual);
192 
193  return calc;
194 }
195 
196 
197 int ResidualCalculator::find(int r, int e) const
198 {
199  for (unsigned int i = 0; i < size(); i++)
200  if (event(i) == e && run(i) == r) return i;
201  return -1;
202 }
203 
204 
206 {
207  m_runs.push_back(r);
208  m_events.push_back(e);
209  return true;
210 }
211 
212 
214 {
215  if (find(residual.run(), residual.event()) >= 0) return true;
216  add(residual.run(), residual.event());
217  return fill_with_weight(residual, +1);
218 }
219 
220 
222 {
223  //std::pair<int, int> ev(residual.run(), residual.event());
224  //std::map< std::pair<int, int>, bool>::iterator findEv = m_events.find(ev);
225  //if (findEv == m_events.end()) return true;
226  //cout << "Will remove run = " << ev.first << ", event = " << ev.second << endl;
227  //m_events.erase(findEv);
228  int index = find(residual.run(), residual.event());
229  if (index == -1) return true;
230  m_events[index] = -1;
231  m_runs[index] = -1;
232  return fill_with_weight(residual, -1);
233 }
234 
235 
237 {
238  TVectorD xi = regresser()->means().GetSub(lwb(), upb(), "I");
239  CovMatrix xiErr = regresser()->meanErrorMatrix().GetSub(lwb(), upb(), lwb(), upb(), "I");
240  double tbar = regresser()->mean(upb() + 1);
241 
242  double denom = regresser()->covarianceMatrix()(upb() + 1, upb() + 1);
243  if (denom < 1E-6) {
244  TVectorD xip(lwb(), upb());
245  CovMatrix xipErr(lwb(), upb());
246  // happens for size==2 if we are removing one of the residuals.
247  if (size() > 2) cout << "WARNING: variance of t < 1E-6, returning correction without derivative term. (V = " << denom << ", N = " << size() << ")" << endl;
248  return new ShapeErrorData(xi, xip, xiErr, xipErr, tbar, regresser()->nEntries());
249  }
250 
251  TVectorD xip = TVectorD(regresser()->covarianceMatrix()[upb() + 1]).GetSub(lwb(), upb(), "I");
252  xip *= -1/denom;
253 
254  TVectorD xipErrVect = TVectorD(regresser()->covarianceMatrixErrors()[upb() + 1]).GetSub(lwb(), upb(), "I");
255  xipErrVect *= 1/denom;
256  CovMatrix xipErr(lwb(), upb());
257  for (int k1 = lwb(); k1 <= upb(); k1++) xipErr(k1, k1) = TMath::Power(xipErrVect(k1), 2);
258 
259  return new ShapeErrorData(xi, xip, xiErr, xipErr, tbar, regresser()->nEntries());
260 }
261 
262 
264 {
265  if (!weigh()) return 1;
266  return TMath::Power(residual.adcMax(), 2);
267 }
268 
269 
271 {
272  w *= weight(residual);
273  return m_regresser.fill(residual.scaledDeltasAndTime(), w);
274 }
275 
276 
278 {
279  if (!m_regresser.append(*other.regresser())) return false;
280  //for (std::map< std::pair<int, int >, bool >::const_iterator event = other.events().begin();
281  // event != other.events().end(); event++)
282  // m_events[event->first] = event->second;
283  for (unsigned int i = 0; i < other.size(); i++) add(other.run(i), other.event(i));
284  return true;
285 }
286 
287 
289 {
290  TString str = "\n";
291  /*for (std::map< std::pair<int, int>, bool>::const_iterator ev = m_events.begin();
292  ev != m_events.end(); ev++)
293  str += Form("run %6d event %10d\n", ev->first.first, ev->first.second);
294  */
295  for (unsigned int i = 0; i < size(); i++)
296  str += Form("run %6d event %10d\n", run(i), event(i));
297 
298  return str;
299 }
300 
301 
303 {
304  Residuals testVect;
305  TRandom r;
306  for (unsigned int i = 0; i < 100000; i++) {
307  TVectorD d(5);
308  //for (unsigned short j = 0; j < 5; j++) d(j) = 0.01*i;
309  for (unsigned short j = 0; j < 5; j++) d(j) = r.Gaus(0, 1);
310  testVect.add(Residual(d, i, i, i, i));
311  }
312 
313 // TVectorD m,w;
314 // if (!getMedianVars(testVect, m, w)) return false;
315 // m.Print();
316 // w.Print();
317 
318  Residuals* truncated = testVect.truncate(2);
319  if (!truncated) return false;
320 
321  TH1D* h = truncated->histogram(0, "h", 100, -5, 5);
322  delete truncated;
323  h->Draw();
324  return true;
325 }
326 
LArSamples::ResidualCalculator::m_runs
std::vector< int > m_runs
Definition: LArCalorimeter/LArSamplesMon/LArSamplesMon/Residual.h:143
LArSamples::ResidualCalculator::m_regresser
Averager m_regresser
Definition: LArCalorimeter/LArSamplesMon/LArSamplesMon/Residual.h:141
AllowedVariables::e
e
Definition: AsgElectronSelectorTool.cxx:37
beamspotman.r
def r
Definition: beamspotman.py:676
LArSamples::Residual::test
static bool test()
Definition: LArCalorimeter/LArSamplesMon/src/Residual.cxx:302
LArSamples::ResidualCalculator::fill_with_weight
bool fill_with_weight(const Residual &residual, double w)
Definition: LArCalorimeter/LArSamplesMon/src/Residual.cxx:270
LArSamples::ResidualCalculator::lwb
int lwb() const
Definition: LArCalorimeter/LArSamplesMon/LArSamplesMon/Residual.h:114
LArSamples::ResidualCalculator::find
int find(int run, int event) const
Definition: LArCalorimeter/LArSamplesMon/src/Residual.cxx:197
CaloCellPos2Ntuple.int
int
Definition: CaloCellPos2Ntuple.py:24
LArSamples::Residuals::residual
const Residual * residual(unsigned int i) const
Definition: LArCalorimeter/LArSamplesMon/LArSamplesMon/Residual.h:81
ClusterSeg::residual
@ residual
Definition: ClusterNtuple.h:20
LArSamples::CovMatrix
TMatrixTSym< double > CovMatrix
Definition: LArCalorimeter/LArCafJobs/LArCafJobs/Definitions.h:11
LArSamples::Residuals::m_residuals
std::vector< Residual > m_residuals
Definition: LArCalorimeter/LArSamplesMon/LArSamplesMon/Residual.h:96
index
Definition: index.py:1
hist_file_dump.d
d
Definition: hist_file_dump.py:137
LArSamples::Residuals::medianVars
bool medianVars(TVectorD &medians, TVectorD &widths) const
Definition: LArCalorimeter/LArSamplesMon/src/Residual.cxx:87
LArSamples::ResidualCalculator::weigh
bool weigh() const
Definition: LArCalorimeter/LArSamplesMon/LArSamplesMon/Residual.h:120
Residual.h
LArSamples::Residual::scaledDeltas
TVectorD scaledDeltas() const
Definition: LArCalorimeter/LArSamplesMon/src/Residual.cxx:37
ClassCounts.h
LArSamples::Averager::append
bool append(const Averager &other)
Definition: Averager.cxx:94
LArSamples::Averager::fill
bool fill(const TVectorD &values, double w=1)
Definition: Averager.cxx:69
LArSamples::ResidualCalculator::fill
bool fill(const Residual &residual)
Definition: LArCalorimeter/LArSamplesMon/src/Residual.cxx:213
LArSamples::Averager::mean
double mean(unsigned int i) const
Definition: Averager.cxx:191
InDet::median
float median(std::vector< float > &Vec)
Definition: BTagVrtSec.cxx:35
LArSamples
Definition: AbsShape.h:24
LArSamples::ResidualCalculator::regresser
const Averager * regresser() const
Definition: LArCalorimeter/LArSamplesMon/LArSamplesMon/Residual.h:119
LArSamples::ResidualCalculator::remove
bool remove(const Residual &residual)
Definition: LArCalorimeter/LArSamplesMon/src/Residual.cxx:221
LArSamples::Residual::scaledDeltasAndTime
TVectorD scaledDeltasAndTime() const
Definition: LArCalorimeter/LArSamplesMon/src/Residual.cxx:52
LArSamples::ResidualCalculator::m_events
std::vector< int > m_events
Definition: LArCalorimeter/LArSamplesMon/LArSamplesMon/Residual.h:143
LArSamples::ResidualCalculator::size
unsigned int size() const
Definition: LArCalorimeter/LArSamplesMon/LArSamplesMon/Residual.h:117
LArSamples::ResidualCalculator
Definition: LArCalorimeter/LArSamplesMon/LArSamplesMon/Residual.h:101
LArSamples::ResidualCalculator::run
int run(unsigned int i) const
Definition: LArCalorimeter/LArSamplesMon/LArSamplesMon/Residual.h:131
Averager.h
LArSamples::ResidualCalculator::weight
double weight(const Residual &residual) const
Definition: LArCalorimeter/LArSamplesMon/src/Residual.cxx:263
LArSamples::Residual::~Residual
virtual ~Residual()
Definition: LArCalorimeter/LArSamplesMon/src/Residual.cxx:31
LArSamples::Averager::means
TVectorD means() const
Definition: Averager.cxx:112
LArSamples::Averager::meanErrorMatrix
CovMatrix meanErrorMatrix() const
Definition: Averager.cxx:138
LArSamples::IndexRange::isInRange
bool isInRange(int i) const
Definition: IndexRange.h:27
event
POOL::TEvent event(POOL::TEvent::kClassAccess)
FullCPAlgorithmsTest_eljob.sample
sample
Definition: FullCPAlgorithmsTest_eljob.py:113
lumiFormat.i
int i
Definition: lumiFormat.py:85
h
LArSamples::Averager::covarianceMatrix
CovMatrix covarianceMatrix() const
Definition: Averager.cxx:153
extractSporadic.h
list h
Definition: extractSporadic.py:97
LArSamples::ClassCounts::decrementInstanceCount
void decrementInstanceCount() const
Definition: LArCafJobs/LArCafJobs/ClassCounts.h:33
LArSamples::Residual::upb
int upb() const
Definition: LArCalorimeter/LArSamplesMon/LArSamplesMon/Residual.h:49
LArSamples::ResidualCalculator::append
bool append(const ResidualCalculator &other)
Definition: LArCalorimeter/LArSamplesMon/src/Residual.cxx:277
LArSamples::Residual::scaledDelta
double scaledDelta(short i) const
Definition: LArCalorimeter/LArSamplesMon/src/Residual.cxx:45
run
Definition: run.py:1
LArSamples::ResidualCalculator::shapeErrorData
ShapeErrorData * shapeErrorData() const
Definition: LArCalorimeter/LArSamplesMon/src/Residual.cxx:236
LArSamples::Residuals::calculator
ResidualCalculator * calculator(bool weigh=false) const
Definition: LArCalorimeter/LArSamplesMon/src/Residual.cxx:185
LArSamples::Residual::lwb
int lwb() const
Definition: LArCalorimeter/LArSamplesMon/LArSamplesMon/Residual.h:48
LArSamples::Residual
storage of a pulse shape residual set
Definition: LArCalorimeter/LArSamplesMon/LArSamplesMon/Residual.h:29
compute_lumi.denom
denom
Definition: compute_lumi.py:76
LArSamples::Residuals
Definition: LArCalorimeter/LArSamplesMon/LArSamplesMon/Residual.h:72
dumpTgcDigiJitter.nBins
list nBins
Definition: dumpTgcDigiJitter.py:29
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:228
LArSamples::ClassCounts::incrementInstanceCount
void incrementInstanceCount() const
Definition: LArCafJobs/LArCafJobs/ClassCounts.h:32
VP1PartSpect::E
@ E
Definition: VP1PartSpectFlags.h:21
LArSamples::Residuals::truncate
Residuals * truncate(double nWidthsRes, double nWidthsTime=-1, unsigned int nMax=0) const
Definition: LArCalorimeter/LArSamplesMon/src/Residual.cxx:143
DeMoScan.index
string index
Definition: DeMoScan.py:364
InDetDD::other
@ other
Definition: InDetDD_Defs.h:16
python.CaloScaleNoiseConfig.str
str
Definition: CaloScaleNoiseConfig.py:78
LArSamples::Residuals::size
unsigned int size() const
Definition: LArCalorimeter/LArSamplesMon/LArSamplesMon/Residual.h:80
LArSamples::Residual::Residual
Residual(const TVectorD &deltas=TVectorD(), int run=0, int event=0, double adcMax=-1, double time=0)
Definition: LArCalorimeter/LArSamplesMon/src/Residual.cxx:23
LArSamples::Residuals::add
bool add(const Residual &residual)
Definition: LArCalorimeter/LArSamplesMon/LArSamplesMon/Residual.h:86
LArSamples::ResidualCompare::operator()
bool operator()(const Residual &r1, const Residual &r2) const
Definition: LArCalorimeter/LArSamplesMon/src/Residual.cxx:61
LArSamples::ResidualCompare::m_sampling
int m_sampling
Definition: LArCalorimeter/LArSamplesMon/LArSamplesMon/Residual.h:66
LArSamples::ResidualCalculator::upb
int upb() const
Definition: LArCalorimeter/LArSamplesMon/LArSamplesMon/Residual.h:115
LArSamples::ResidualCalculator::description
TString description() const
Definition: LArCalorimeter/LArSamplesMon/src/Residual.cxx:288
str
Definition: BTagTrackIpAccessor.cxx:11
ShapeErrorData.h
LArSamples::Residuals::upb
int upb() const
Definition: LArCalorimeter/LArSamplesMon/LArSamplesMon/Residual.h:84
LArSamples::ShapeErrorData
Definition: ShapeErrorData.h:19
LArSamples::Residuals::histogram
TH1D * histogram(short sample, const TString &name, int nBins, double xMin, double xMax) const
Definition: LArCalorimeter/LArSamplesMon/src/Residual.cxx:176
python.IoTestsLib.w
def w
Definition: IoTestsLib.py:200
dqBeamSpot.nEntries
int nEntries
Definition: dqBeamSpot.py:73
LArSamples::ResidualCalculator::add
bool add(int run, int event)
Definition: LArCalorimeter/LArSamplesMon/src/Residual.cxx:205
beamspotnt.calc
calc
Definition: bin/beamspotnt.py:1252
LArSamples::Residuals::lwb
int lwb() const
Definition: LArCalorimeter/LArSamplesMon/LArSamplesMon/Residual.h:83
LArSamples::ResidualCompare
Definition: LArCalorimeter/LArSamplesMon/LArSamplesMon/Residual.h:61
LArSamples::Residual::time
double time() const
Definition: LArCalorimeter/LArSamplesMon/LArSamplesMon/Residual.h:42
LArSamples::ResidualCalculator::event
int event(unsigned int i) const
Definition: LArCalorimeter/LArSamplesMon/LArSamplesMon/Residual.h:132
LArSamples::Residuals::Residuals
Residuals()
Definition: LArCalorimeter/LArSamplesMon/LArSamplesMon/Residual.h:74
LArSamples::Residual::adcMax
double adcMax() const
Definition: LArCalorimeter/LArSamplesMon/LArSamplesMon/Residual.h:41
LArSamples::Residual::deltas
const TVectorD & deltas() const
Definition: LArCalorimeter/LArSamplesMon/LArSamplesMon/Residual.h:38