SND@LHC Software
Loading...
Searching...
No Matches
DAF.cc
Go to the documentation of this file.
1/* Copyright 2008-2013, Technische Universitaet Muenchen, Ludwig-Maximilians-Universität München
2 Authors: Christian Hoeppner & Sebastian Neubert & Johannes Rauch & Tobias Schlüter
3
4 This file is part of GENFIT.
5
6 GENFIT is free software: you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License as published
8 by the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 GENFIT is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License
17 along with GENFIT. If not, see <http://www.gnu.org/licenses/>.
18*/
19
20#include "DAF.h"
21#include "Exception.h"
22#include "KalmanFitterInfo.h"
23#include "KalmanFitter.h"
25#include "KalmanFitStatus.h"
26#include "Tools.h"
27#include "Track.h"
28#include "TrackPoint.h"
29
30#include <assert.h>
31#include <cmath>
32
33//root stuff
34#include <TMath.h>
35#include <Math/QuantFuncMathCore.h>
36#include <TBuffer.h>
37
38
39
40namespace genfit {
41
42DAF::DAF(bool useRefKalman, double deltaPval, double deltaWeight)
43 : AbsKalmanFitter(10, deltaPval), deltaWeight_(deltaWeight)
44{
45 if (useRefKalman) {
46 kalman_.reset(new KalmanFitterRefTrack());
47 static_cast<KalmanFitterRefTrack*>(kalman_.get())->setRefitAll();
48 }
49 else
50 kalman_.reset(new KalmanFitter());
51
53 kalman_->setMaxIterations(1);
54
55 setAnnealingScheme(100, 0.1, 5); // also sets maxIterations_
56 setProbCut(0.01);
57}
58
59DAF::DAF(AbsKalmanFitter* kalman, double deltaPval, double deltaWeight)
60 : AbsKalmanFitter(10, deltaPval), deltaWeight_(deltaWeight)
61{
62 kalman_.reset(kalman);
63 kalman_->setMultipleMeasurementHandling(weightedAverage); // DAF makes no sense otherwise
64 kalman_->setMaxIterations(1);
65
66 if (dynamic_cast<KalmanFitterRefTrack*>(kalman_.get()) != NULL) {
67 static_cast<KalmanFitterRefTrack*>(kalman_.get())->setRefitAll();
68 }
69
70 setAnnealingScheme(100, 0.1, 5); // also sets maxIterations_
71 setProbCut(0.01);
72}
73
74
75void DAF::processTrackWithRep(Track* tr, const AbsTrackRep* rep, bool resortHits) {
76
77 if (debugLvl_ > 0) {
78 std::cout<<"DAF::processTrack //////////////////////////////////////////////////////////////// \n";
79 }
80
81 KalmanFitStatus* status = 0;
82 bool oneLastIter = false;
83
84 double lastPval = -1;
85
86 for(unsigned int iBeta = 0;; ++iBeta) {
87
88 if (debugLvl_ > 0) {
89 std::cout<<"DAF::processTrack, trackRep " << rep << ", iteration " << iBeta+1 << ", beta = " << betas_.at(iBeta) << "\n";
90 }
91
92 kalman_->processTrackWithRep(tr, rep, resortHits);
93
94 status = static_cast<KalmanFitStatus*>(tr->getFitStatus(rep));
95 status->setIsFittedWithDaf();
96 status->setNumIterations(iBeta+1);
97
98
99 // check break conditions
100
101 if (! status->isFitted()){
102 if (debugLvl_ > 0) {
103 std::cout << "DAF::Kalman could not fit!\n";
104 }
105 status->setIsFitted(false);
106 break;
107 }
108
109 if( oneLastIter == true){
110 if (debugLvl_ > 0) {
111 std::cout << "DAF::break after one last iteration\n";
112 }
113 status->setIsFitConvergedFully(status->getNFailedPoints() == 0);
114 status->setIsFitConvergedPartially();
115 break;
116 }
117
118 if(iBeta >= maxIterations_-1){
119 status->setIsFitConvergedFully(false);
120 status->setIsFitConvergedPartially(false);
121 if (debugLvl_ > 0) {
122 std::cout << "DAF::number of max iterations reached!\n";
123 }
124 break;
125 }
126
127
128 // get and update weights
129 bool converged(false);
130 try{
131 converged = calcWeights(tr, rep, betas_.at(iBeta));
132 if (!converged && iBeta >= minIterations_-1 &&
133 status->getBackwardPVal() != 0 && fabs(lastPval - status->getBackwardPVal()) < this->deltaPval_) {
134 if (debugLvl_ > 0) {
135 std::cout << "converged by Pval = " << status->getBackwardPVal() << " even though weights changed at iBeta = " << iBeta << std::endl;
136 }
137 converged = true;
138 }
139 lastPval = status->getBackwardPVal();
140 } catch(Exception& e) {
141 std::cerr<<e.what();
142 e.info();
143 //std::cerr << "calc weights failed" << std::endl;
144 //mini_trk->getTrackRep(0)->setStatusFlag(1);
145 status->setIsFitted(false);
146 status->setIsFitConvergedFully(false);
147 status->setIsFitConvergedPartially(false);
148 break;
149 }
150
151 // check if converged
152 if (iBeta >= minIterations_-1 && converged) {
153 if (debugLvl_ > 0) {
154 std::cout << "DAF::convergence reached in iteration " << iBeta+1 << " -> Do one last iteration with updated weights.\n";
155 }
156 oneLastIter = true;
157 status->setIsFitConvergedFully(status->getNFailedPoints() == 0);
158 status->setIsFitConvergedPartially();
159 }
160
161 } // end loop over betas
162
163
164 if (status->getForwardPVal() == 0. &&
165 status->getBackwardPVal() == 0.) {
166 status->setIsFitConvergedFully(false);
167 status->setIsFitConvergedPartially(false);
168 }
169
170}
171
172
173void DAF::setProbCut(const double prob_cut){
174 for ( int i = 1; i != 6; ++i){
175 addProbCut(prob_cut, i);
176 }
177}
178
179void DAF::addProbCut(const double prob_cut, const int measDim){
180 if ( prob_cut > 1.0 || prob_cut < 0.0){
181 Exception exc("DAF::addProbCut prob_cut is not between 0 and 1",__LINE__,__FILE__);
182 exc.setFatal();
183 throw exc;
184 }
185 if ( measDim < 1){
186 Exception exc("DAF::addProbCut measDim must be > 0",__LINE__,__FILE__);
187 exc.setFatal();
188 throw exc;
189 }
190 chi2Cuts_[measDim] = ROOT::Math::chisquared_quantile_c( prob_cut, measDim);
191}
192
193
194void DAF::setBetas(double b1,double b2,double b3,double b4,double b5,double b6,double b7,double b8,double b9,double b10){
195 betas_.clear();
196 assert(b1>0);betas_.push_back(b1);
197 if(b2>0){
198 assert(b2<=b1);betas_.push_back(b2);
199 if(b3>=0.) {
200 assert(b3<=b2);betas_.push_back(b3);
201 if(b4>=0.) {
202 assert(b4<=b3);betas_.push_back(b4);
203 if(b5>=0.) {
204 assert(b5<=b4);betas_.push_back(b5);
205 if(b6>=0.) {
206 assert(b6<=b5);betas_.push_back(b6);
207 if(b7>=0.) {
208 assert(b7<=b6);betas_.push_back(b7);
209 if(b8>=0.) {
210 assert(b8<=b7);betas_.push_back(b8);
211 if(b9>=0.) {
212 assert(b9<=b8);betas_.push_back(b9);
213 if(b10>=0.) {
214 assert(b10<=b9);betas_.push_back(b10);
215 }
216 }
217 }
218 }
219 }
220 }
221 }
222 }
223 }
224 minIterations_ = betas_.size();
225 maxIterations_ = betas_.size() + 4;
226 betas_.resize(maxIterations_,betas_.back()); //make sure main loop has a maximum of maxIterations_ and also make sure the last beta value is used for if more iterations are needed then the ones set by the user.
227}
228
229
230void DAF::setAnnealingScheme(double bStart, double bFinal, unsigned int nSteps) {
231 // The betas are calculated as a geometric series that takes nSteps
232 // steps to go from bStart to bFinal.
233 assert(bStart > bFinal);
234 assert(bFinal > 1.E-10);
235 assert(nSteps > 1);
236
237 minIterations_ = nSteps;
238 maxIterations_ = nSteps + 4;
239
240 betas_.clear();
241
242 for (unsigned int i=0; i<nSteps; ++i) {
243 betas_.push_back(bStart * pow(bFinal / bStart, i / (nSteps - 1.)));
244 }
245
246 betas_.resize(maxIterations_,betas_.back()); //make sure main loop has a maximum of 10 iterations and also make sure the last beta value is used for if more iterations are needed then the ones set by the user.
247
248 /*for (unsigned int i=0; i<betas_.size(); ++i) {
249 std::cout<< betas_.at(i) << ", ";
250 }*/
251}
252
253
254bool DAF::calcWeights(Track* tr, const AbsTrackRep* rep, double beta) {
255
256 if (debugLvl_ > 0) {
257 std::cout<<"DAF::calcWeights \n";
258 }
259
260 bool converged(true);
261 double maxAbsChange(0);
262
263 const std::vector< TrackPoint* >& trackPoints = tr->getPointsWithMeasurement();
264 for (std::vector< TrackPoint* >::const_iterator tp = trackPoints.begin(); tp != trackPoints.end(); ++tp) {
265 if (! (*tp)->hasFitterInfo(rep)) {
266 continue;
267 }
268 AbsFitterInfo* fi = (*tp)->getFitterInfo(rep);
269 if (dynamic_cast<KalmanFitterInfo*>(fi) == NULL){
270 Exception exc("DAF::getWeights ==> can only use KalmanFitterInfos",__LINE__,__FILE__);
271 throw exc;
272 }
273 KalmanFitterInfo* kfi = static_cast<KalmanFitterInfo*>(fi);
274
275 if (kfi->areWeightsFixed()) {
276 if (debugLvl_ > 0) {
277 std::cout<<"weights are fixed, continue \n";
278 }
279 continue;
280 }
281
282 unsigned int nMeas = kfi->getNumMeasurements();
283
284 std::vector<double> phi(nMeas, 0.);
285 double phi_sum = 0;
286 double phi_cut = 0;
287 for(unsigned int j=0; j<nMeas; j++) {
288
289 try{
290 const MeasurementOnPlane& residual = kfi->getResidual(j, true, true);
291 const TVectorD& resid(residual.getState());
292 TMatrixDSym Vinv(residual.getCov());
293 double detV;
294 tools::invertMatrix(Vinv, &detV); // can throw an Exception
295 int hitDim = resid.GetNrows();
296 // Needed for normalization, special cases for the two common cases,
297 // shouldn't matter, but the original code made some efforts to make
298 // this calculation faster, and it's not complex ...
299 double twoPiN = 2.*M_PI;
300 if (hitDim == 2)
301 twoPiN *= twoPiN;
302 else if (hitDim > 2)
303 twoPiN = pow(twoPiN, hitDim);
304
305 double chi2 = Vinv.Similarity(resid);
306 if (debugLvl_ > 1) {
307 std::cout<<"chi2 = " << chi2 << "\n";
308 }
309
310 double norm = 1./sqrt(twoPiN * detV);
311
312 phi[j] = norm*exp(-0.5*chi2/beta);
313 phi_sum += phi[j];
314 //std::cerr << "hitDim " << hitDim << " fchi2Cuts[hitDim] " << fchi2Cuts[hitDim] << std::endl;
315 double cutVal = chi2Cuts_[hitDim];
316 assert(cutVal>1.E-6);
317 //the following assumes that in the competing hits could have different V otherwise calculation could be simplified
318 phi_cut += norm*exp(-0.5*cutVal/beta);
319 }
320 catch(Exception& e) {
321 std::cerr << e.what();
322 e.info();
323 }
324 }
325
326 for(unsigned int j=0; j<nMeas; j++) {
327 double weight = phi[j]/(phi_sum+phi_cut);
328
329 // check convergence
330 double absChange(fabs(weight - kfi->getMeasurementOnPlane(j)->getWeight()));
331 if (converged && absChange > deltaWeight_) {
332 converged = false;
333 if (absChange > maxAbsChange)
334 maxAbsChange = absChange;
335 }
336
337 if (debugLvl_ > 0) {
338 if (debugLvl_ > 1 || absChange > deltaWeight_) {
339 std::cout<<"\t old weight: " << kfi->getMeasurementOnPlane(j)->getWeight();
340 std::cout<<"\t new weight: " << weight;
341 }
342 }
343
344 kfi->getMeasurementOnPlane(j)->setWeight(weight);
345 }
346 }
347
348 if (debugLvl_ > 0) {
349 std::cout << "\t ";
350 std::cout << "max abs weight change = " << maxAbsChange << "\n";
351 }
352
353 return converged;
354}
355
356
357// Customized from generated Streamer.
358void DAF::Streamer(TBuffer &R__b)
359{
360 // Stream an object of class genfit::DAF.
361
362 //This works around a msvc bug and should be harmless on other platforms
363 typedef ::genfit::DAF thisClass;
364 UInt_t R__s, R__c;
365 if (R__b.IsReading()) {
366 Version_t R__v = R__b.ReadVersion(&R__s, &R__c); if (R__v) { }
367 //This works around a msvc bug and should be harmless on other platforms
368 typedef genfit::AbsKalmanFitter baseClass0;
369 baseClass0::Streamer(R__b);
370 R__b >> deltaWeight_;
371 // weights_ are only of intermediate use -> not saved
372 {
373 std::vector<double> &R__stl = betas_;
374 R__stl.clear();
375 int R__i, R__n;
376 R__b >> R__n;
377 R__stl.reserve(R__n);
378 for (R__i = 0; R__i < R__n; R__i++) {
379 double R__t;
380 R__b >> R__t;
381 R__stl.push_back(R__t);
382 }
383 }
384 {
385 std::map<int,double> &R__stl = chi2Cuts_;
386 R__stl.clear();
387 int R__i, R__n;
388 R__b >> R__n;
389 for (R__i = 0; R__i < R__n; R__i++) {
390 int R__t;
391 R__b >> R__t;
392 double R__t2;
393 R__b >> R__t2;
394 typedef int Value_t;
395 std::pair<Value_t const, double > R__t3(R__t,R__t2);
396 R__stl.insert(R__t3);
397 }
398 }
400 R__b >> p;
401 kalman_.reset(p);
402 R__b.CheckByteCount(R__s, R__c, thisClass::IsA());
403 } else {
404 R__c = R__b.WriteVersion(thisClass::IsA(), kTRUE);
405 //This works around a msvc bug and should be harmless on other platforms
406 typedef genfit::AbsKalmanFitter baseClass0;
407 baseClass0::Streamer(R__b);
408 R__b << deltaWeight_;
409 {
410 std::vector<double> &R__stl = betas_;
411 int R__n=int(R__stl.size());
412 R__b << R__n;
413 if(R__n) {
414 std::vector<double>::iterator R__k;
415 for (R__k = R__stl.begin(); R__k != R__stl.end(); ++R__k) {
416 R__b << (*R__k);
417 }
418 }
419 }
420 {
421 std::map<int,double> &R__stl = chi2Cuts_;
422 int R__n=int(R__stl.size());
423 R__b << R__n;
424 if(R__n) {
425 std::map<int,double>::iterator R__k;
426 for (R__k = R__stl.begin(); R__k != R__stl.end(); ++R__k) {
427 R__b << ((*R__k).first );
428 R__b << ((*R__k).second);
429 }
430 }
431 }
432 R__b << kalman_.get();
433 R__b.SetByteCount(R__c, kTRUE);
434 }
435}
436
437} /* End of namespace genfit */
This class collects all information needed and produced by a specific AbsFitter and is specific to on...
unsigned int debugLvl_
Definition AbsFitter.h:55
Abstract base class for Kalman fitter and derived fitting algorithms.
unsigned int maxIterations_
Maximum number of iterations to attempt. Forward and backward are counted as one iteration.
void setMultipleMeasurementHandling(eMultipleMeasurementHandling mmh)
How should multiple measurements be handled?
unsigned int minIterations_
Minimum number of iterations to attempt. Forward and backward are counted as one iteration.
AbsKalmanFitter(unsigned int maxIterations=4, double deltaPval=1e-3, double blowUpFactor=1e3)
Abstract base class for a track representation.
Definition AbsTrackRep.h:66
Determinstic Annealing Filter (DAF) implementation.
Definition DAF.h:48
std::vector< double > betas_
Definition DAF.h:119
void setBetas(double b1, double b2=-1, double b3=-1., double b4=-1., double b5=-1., double b6=-1., double b7=-1., double b8=-1., double b9=-1., double b10=-1.)
Configure the annealing scheme.
Definition DAF.cc:194
bool calcWeights(Track *trk, const AbsTrackRep *rep, double beta)
Calculate and set the weights for the next fitting pass. Return if convergence is met....
Definition DAF.cc:254
void setAnnealingScheme(double bStart, double bFinal, unsigned int nSteps)
Configure the annealing scheme.
Definition DAF.cc:230
void addProbCut(const double prob_cut, const int measDim)
Set the probability cut for the weight calculation for the hits for a specific measurement dimensiona...
Definition DAF.cc:179
std::map< int, double > chi2Cuts_
Definition DAF.h:120
DAF(const DAF &)
double deltaWeight_
Definition DAF.h:118
void setProbCut(const double prob_cut)
Set the probability cut for the weight calculation for the hits.
Definition DAF.cc:173
void processTrackWithRep(Track *tr, const AbsTrackRep *rep, bool resortHits=false)
Process a track using the DAF.
Definition DAF.cc:75
boost::scoped_ptr< AbsKalmanFitter > kalman_
Definition DAF.h:122
Exception class for error handling in GENFIT (provides storage for diagnostic information)
Definition Exception.h:48
void setFatal(bool b=true)
Set fatal flag.
Definition Exception.h:61
virtual const char * what() const
Standard error message handling for exceptions. use like "std::cerr << e.what();".
Definition Exception.cc:51
void info()
Print information in the exception object.
Definition Exception.cc:59
FitStatus for use with AbsKalmanFitter implementations.
Collects information needed and produced by a AbsKalmanFitter implementations and is specific to one ...
MeasurementOnPlane getResidual(unsigned int iMeasurement=0, bool biased=false, bool onlyMeasurementErrors=true) const
Get unbiased (default) or biased residual from ith measurement.
unsigned int getNumMeasurements() const
bool areWeightsFixed() const
Are the weights fixed?
MeasurementOnPlane * getMeasurementOnPlane(int i=0) const
Kalman filter implementation with linearization around a reference track.
Simple Kalman filter implementation.
const TMatrixDSym & getCov() const
Measured coordinates on a plane.
void setWeight(double weight)
const TVectorD & getState() const
Collection of TrackPoint objects, AbsTrackRep objects and FitStatus objects.
Definition Track.h:71
const std::vector< genfit::TrackPoint * > & getPointsWithMeasurement() const
Definition Track.h:111
FitStatus * getFitStatus(const AbsTrackRep *rep=NULL) const
Get FitStatus for a AbsTrackRep. Per default, return FitStatus for cardinalRep.
Definition Track.h:149
void invertMatrix(const TMatrixDSym &mat, TMatrixDSym &inv, double *determinant=NULL)
Invert a matrix, throwing an Exception when inversion fails. Optional calculation of determinant.
Definition Tools.cc:38
Matrix inversion tools.
Definition AbsBField.h:29