Fork me on GitHub

source: git/modules/VertexFinderDA4D.cc@ 4154bbd

ImprovedOutputFile Timing dual_readout llp
Last change on this file since 4154bbd was 4154bbd, checked in by Pavel Demin <pavel.demin@…>, 8 years ago

adapt vertexing modules to ROOT 5.34 and GCC 4.4

  • Property mode set to 100644
File size: 31.6 KB
Line 
1/** \class VertexFinderDA4D
2 *
3 * Cluster vertices from tracks using deterministic annealing and timing information
4 *
5 * \authors M. Selvaggi, L. Gray
6 *
7 */
8
9
10#include "modules/VertexFinderDA4D.h"
11#include "classes/DelphesClasses.h"
12#include "classes/DelphesFactory.h"
13#include "classes/DelphesFormula.h"
14#include "classes/DelphesPileUpReader.h"
15
16#include "ExRootAnalysis/ExRootResult.h"
17#include "ExRootAnalysis/ExRootFilter.h"
18#include "ExRootAnalysis/ExRootClassifier.h"
19
20#include "TMath.h"
21#include "TString.h"
22#include "TFormula.h"
23#include "TRandom3.h"
24#include "TObjArray.h"
25#include "TDatabasePDG.h"
26#include "TLorentzVector.h"
27#include "TMatrixT.h"
28#include "TVector3.h"
29
30#include <utility>
31#include <algorithm>
32#include <stdexcept>
33#include <iostream>
34#include <vector>
35
36using namespace std;
37
38static const Double_t mm = 1.;
39static const Double_t m = 1000.*mm;
40static const Double_t ns = 1.;
41static const Double_t s = 1.e+9 *ns;
42static const Double_t c_light = 2.99792458e+8 * m/s;
43
44struct track_t
45{
46 double z; // z-coordinate at point of closest approach to the beamline
47 double t; // t-coordinate at point of closest approach to the beamline
48 double dz2; // square of the error of z(pca)
49 double dtz; // covariance of z-t
50 double dt2; // square of the error of t(pca)
51 Candidate *tt; // a pointer to the Candidate Track
52 double Z; // Z[i] for DA clustering
53 double pi; // track weight
54 double pt;
55 double eta;
56 double phi;
57};
58
59struct vertex_t
60{
61 double z;
62 double t;
63 double pk; // vertex weight for "constrained" clustering
64 // --- temporary numbers, used during update
65 double ei;
66 double sw;
67 double swz;
68 double swt;
69 double se;
70 // ---for Tc
71 double swE;
72 double Tc;
73};
74
75static bool split(double beta, std::vector<track_t> &tks, std::vector<vertex_t> &y);
76static double update1(double beta, std::vector<track_t> &tks, std::vector<vertex_t> &y);
77static double update2(double beta, std::vector<track_t> &tks, std::vector<vertex_t> &y, double &rho0, const double dzCutOff);
78static void dump(const double beta, const std::vector<vertex_t> & y, const std::vector<track_t> & tks);
79static bool merge(std::vector<vertex_t> &);
80static bool merge(std::vector<vertex_t> &, double &);
81static bool purge(std::vector<vertex_t> &, std::vector<track_t> & , double &, const double, const double);
82static void splitAll(std::vector<vertex_t> &y);
83static double beta0(const double betamax, std::vector<track_t> &tks, std::vector<vertex_t> &y, const double coolingFactor);
84static double Eik(const track_t &t, const vertex_t &k);
85
86static bool recTrackLessZ1(const track_t & tk1, const track_t & tk2)
87{
88 return tk1.z < tk2.z;
89}
90
91using namespace std;
92
93//------------------------------------------------------------------------------
94
95VertexFinderDA4D::VertexFinderDA4D() :
96 fVerbose(0), fMinPT(0), fVertexSpaceSize(0), fVertexTimeSize(0),
97 fUseTc(0), fBetaMax(0), fBetaStop(0), fCoolingFactor(0),
98 fMaxIterations(0), fDzCutOff(0), fD0CutOff(0), fDtCutOff(0)
99{
100}
101
102//------------------------------------------------------------------------------
103
104VertexFinderDA4D::~VertexFinderDA4D()
105{
106}
107
108//------------------------------------------------------------------------------
109
110void VertexFinderDA4D::Init()
111{
112
113 fVerbose = GetBool("Verbose", 1);
114 fMinPT = GetDouble("MinPT", 0.1);
115 fVertexSpaceSize = GetDouble("VertexSpaceSize", 0.5); //in mm
116 fVertexTimeSize = GetDouble("VertexTimeSize", 10E-12); //in s
117 fUseTc = GetBool("UseTc", 1);
118 fBetaMax = GetDouble("BetaMax ", 0.1);
119 fBetaStop = GetDouble("BetaStop", 1.0);
120 fCoolingFactor = GetDouble("CoolingFactor", 0.8);
121 fMaxIterations = GetInt("MaxIterations", 100);
122 fDzCutOff = GetDouble("DzCutOff", 40); // Adaptive Fitter uses 30 mm but that appears to be a bit tight here sometimes
123 fD0CutOff = GetDouble("D0CutOff", 30);
124 fDtCutOff = GetDouble("DtCutOff", 100E-12); // dummy
125
126 // convert stuff in cm, ns
127 fVertexSpaceSize /= 10.0;
128 fVertexTimeSize *= 1E9;
129 fDzCutOff /= 10.0; // Adaptive Fitter uses 3.0 but that appears to be a bit tight here sometimes
130 fD0CutOff /= 10.0;
131
132 fInputArray = ImportArray(GetString("InputArray", "TrackSmearing/tracks"));
133 fItInputArray = fInputArray->MakeIterator();
134
135 fOutputArray = ExportArray(GetString("OutputArray", "tracks"));
136 fVertexOutputArray = ExportArray(GetString("VertexOutputArray", "vertices"));
137}
138
139//------------------------------------------------------------------------------
140
141void VertexFinderDA4D::Finish()
142{
143 if(fItInputArray) delete fItInputArray;
144}
145
146//------------------------------------------------------------------------------
147
148void VertexFinderDA4D::Process()
149{
150 Candidate *candidate, *track;
151 TObjArray *ClusterArray;
152 ClusterArray = new TObjArray;
153 TIterator *ItClusterArray;
154 Int_t ivtx = 0;
155
156 fInputArray->Sort();
157
158 TLorentzVector pos, mom;
159 if (fVerbose)
160 {
161 cout<<" start processing vertices ..."<<endl;
162 cout<<" Found "<<fInputArray->GetEntriesFast()<<" input tracks"<<endl;
163 //loop over input tracks
164 fItInputArray->Reset();
165 while((candidate = static_cast<Candidate*>(fItInputArray->Next())))
166 {
167 pos = candidate->InitialPosition;
168 mom = candidate->Momentum;
169
170 cout<<"pt: "<<mom.Pt()<<", eta: "<<mom.Eta()<<", phi: "<<mom.Phi()<<", z: "<<candidate->DZ/10<<endl;
171 }
172 }
173
174 // clusterize tracks in Z
175 clusterize(*fInputArray, *ClusterArray);
176
177 if (fVerbose){std::cout << " clustering returned "<< ClusterArray->GetEntriesFast() << " clusters from " << fInputArray->GetEntriesFast() << " selected tracks" <<std::endl;}
178
179 //loop over vertex candidates
180 ItClusterArray = ClusterArray->MakeIterator();
181 ItClusterArray->Reset();
182 while((candidate = static_cast<Candidate*>(ItClusterArray->Next())))
183 {
184
185 double meantime = 0.;
186 double expv_x2 = 0.;
187 double normw = 0.;
188 double errtime = 0;
189
190 double meanpos = 0.;
191 double meanerr2 = 0.;
192 double normpos = 0.;
193 double errpos = 0.;
194
195 double sumpt2 = 0.;
196
197 int itr = 0;
198
199 if(fVerbose)cout<<"this vertex has: "<<candidate->GetCandidates()->GetEntriesFast()<<" tracks"<<endl;
200
201 // loop over tracks belonging to this vertex
202 TIter it1(candidate->GetCandidates());
203 it1.Reset();
204
205 while((track = static_cast<Candidate*>(it1.Next())))
206 {
207
208 itr++;
209 // TBC: the time is in ns for now TBC
210 double t = track->InitialPosition.T()/c_light;
211 double dt = track->ErrorT/c_light;
212 const double time = t;
213 const double inverr = 1.0/dt;
214 meantime += time*inverr;
215 expv_x2 += time*time*inverr;
216 normw += inverr;
217
218 // compute error position TBC
219 const double pt = track->Momentum.Pt();
220 const double z = track->DZ/10.0;
221 const double err_pt = track->ErrorPT;
222 const double err_z = track->ErrorDZ;
223
224 const double wi = (pt/(err_pt*err_z))*(pt/(err_pt*err_z));
225 meanpos += z*wi;
226
227 meanerr2 += err_z*err_z*wi;
228 normpos += wi;
229 sumpt2 += pt*pt;
230
231 // while we are here store cluster index in tracks
232 track->ClusterIndex = ivtx;
233 }
234
235 meantime = meantime/normw;
236 expv_x2 = expv_x2/normw;
237 errtime = TMath::Sqrt((expv_x2 - meantime*meantime)/itr);
238
239 meanpos = meanpos/normpos;
240 meanerr2 = meanerr2/normpos;
241 errpos = TMath::Sqrt(meanerr2/itr);
242
243 candidate->Position.SetXYZT(0.0, 0.0, meanpos*10.0 , meantime*c_light);
244 candidate->PositionError.SetXYZT(0.0, 0.0, errpos*10.0 , errtime*c_light);
245 candidate->SumPT2 = sumpt2;
246 candidate->ClusterNDF = itr;
247 candidate->ClusterIndex = ivtx;
248
249 fVertexOutputArray->Add(candidate);
250
251 ivtx++;
252
253 if (fVerbose){
254 std::cout << "x,y,z";
255 std::cout << ",t";
256 std::cout << "=" << candidate->Position.X()/10.0 <<" " << candidate->Position.Y()/10.0 << " " << candidate->Position.Z()/10.0;
257 std::cout << " " << candidate->Position.T()/c_light;
258
259 std::cout << std::endl;
260 std::cout << "sumpt2 " << candidate->SumPT2<<endl;
261 }
262 }// end of cluster loop
263
264
265 if(fVerbose){
266 std::cout << "PrimaryVertexProducerAlgorithm::vertices candidates =" << ClusterArray->GetEntriesFast() << std::endl;
267 }
268
269 //TBC maybe this can be done later
270 // sort vertices by pt**2 vertex (aka signal vertex tagging)
271 /*if(pvs.size()>1){
272 sort(pvs.begin(), pvs.end(), VertexHigherPtSquared());
273 }
274 */
275
276 delete ClusterArray;
277
278}
279
280//------------------------------------------------------------------------------
281
282void VertexFinderDA4D::clusterize(const TObjArray &tracks, TObjArray &clusters)
283{
284 if(fVerbose) {
285 cout << "###################################################" << endl;
286 cout << "# VertexFinderDA4D::clusterize nt="<<tracks.GetEntriesFast() << endl;
287 cout << "###################################################" << endl;
288 }
289
290 vector< Candidate* > pv = vertices();
291
292 if(fVerbose){ cout << "# VertexFinderDA4D::clusterize pv.size="<<pv.size() << endl; }
293 if (pv.size()==0){ return; }
294
295 // convert into vector of candidates
296 //TObjArray *ClusterArray = pv.begin()->GetCandidates();
297 //Candidate *aCluster = static_cast<Candidate*>(&(pv.at(0)));
298 Candidate *aCluster = pv.at(0);
299
300 // fill into clusters and merge
301
302
303 if( fVerbose ) {
304 std::cout << '\t' << 0;
305 std::cout << ' ' << (*pv.begin())->Position.Z()/10.0 << ' ' << (*pv.begin())->Position.T()/c_light << std::endl;
306 }
307
308 for(vector<Candidate*>::iterator k=pv.begin()+1; k!=pv.end(); k++){
309 if( fVerbose ) {
310 std::cout << '\t' << std::distance(pv.begin(),k);
311 std::cout << ' ' << (*k)->Position.Z() << ' ' << (*k)->Position.T() << std::endl;
312 }
313
314
315 // TBC - check units here
316 if ( std::abs((*k)->Position.Z() - (*(k-1))->Position.Z())/10.0 > (2*fVertexSpaceSize) ||
317 std::abs((*k)->Position.T() - (*(k-1))->Position.Z())/c_light > 2*0.010 ) {
318 // close a cluster
319 clusters.Add(aCluster);
320 //aCluster.clear();
321 }
322 //for(unsigned int i=0; i<k->GetCandidates().GetEntriesFast(); i++){
323 aCluster = *k;
324 //}
325
326 }
327 clusters.Add(aCluster);
328
329 if(fVerbose) { std::cout << "# VertexFinderDA4D::clusterize clusters.size="<<clusters.GetEntriesFast() << std::endl; }
330
331}
332
333//------------------------------------------------------------------------------
334
335vector< Candidate* > VertexFinderDA4D::vertices()
336{
337 Candidate *candidate;
338 UInt_t clusterIndex = 0;
339 vector< Candidate* > clusters;
340
341 vector<track_t> tks;
342 track_t tr;
343 Double_t z, dz, t, l, dt, d0, d0error;
344
345 // loop over input tracks
346 fItInputArray->Reset();
347 while((candidate = static_cast<Candidate*>(fItInputArray->Next())))
348 {
349 //TBC everything in cm
350 z = candidate->DZ/10;
351 tr.z = z;
352 dz = candidate->ErrorDZ/10;
353 tr.dz2 = dz*dz // track error
354 //TBC: beamspot size induced error, take 0 for now.
355 // + (std::pow(beamspot.BeamWidthX()*cos(phi),2.)+std::pow(beamspot.BeamWidthY()*sin(phi),2.))/std::pow(tantheta,2.) // beam-width induced
356 + fVertexSpaceSize*fVertexSpaceSize; // intrinsic vertex size, safer for outliers and short lived decays
357
358 // TBC: the time is in ns for now TBC
359 //t = candidate->Position.T()/c_light;
360 t = candidate->InitialPosition.T()/c_light;
361 l = candidate->L/c_light;
362 double pt = candidate->Momentum.Pt();
363 double eta = candidate->Momentum.Eta();
364 double phi = candidate->Momentum.Phi();
365
366 tr.pt = pt;
367 tr.eta = eta;
368 tr.phi = phi;
369 tr.t = t; //
370 tr.dtz = 0.;
371 dt = candidate->ErrorT/c_light;
372 tr.dt2 = dt*dt + fVertexTimeSize*fVertexTimeSize; // the ~injected~ timing error plus a small minimum vertex size in time
373 if(fD0CutOff>0)
374 {
375
376 d0 = TMath::Abs(candidate->D0)/10.0;
377 d0error = candidate->ErrorD0/10.0;
378
379 tr.pi=1./(1.+exp((d0*d0)/(d0error*d0error) - fD0CutOff*fD0CutOff)); // reduce weight for high ip tracks
380
381 }
382 else
383 {
384 tr.pi=1.;
385 }
386 tr.tt=&(*candidate);
387 tr.Z=1.;
388
389 // TBC now putting track selection here (> fPTMin)
390 if(tr.pi > 1e-3 && tr.pt > fMinPT)
391 {
392 tks.push_back(tr);
393 }
394 }
395
396 //print out input tracks
397
398 if(fVerbose)
399 {
400 std::cout<<" start processing vertices ..."<<std::endl;
401 std::cout<<" Found "<<tks.size()<<" input tracks"<<std::endl;
402 //loop over input tracks
403
404
405 for(std::vector<track_t>::const_iterator it=tks.begin(); it!=tks.end(); it++){
406 double z = it->z;
407 double pt=it->pt;
408 double eta=it->eta;
409 double phi=it->phi;
410 double t = it->t;
411
412 std::cout<<"pt: "<<pt<<", eta: "<<eta<<", phi: "<<phi<<", z: "<<z<<", t: "<<t<<std::endl;
413 }
414 }
415
416 unsigned int nt=tks.size();
417 double rho0=0.0; // start with no outlier rejection
418
419 if (tks.empty()) return clusters;
420
421 vector<vertex_t> y; // the vertex prototypes
422
423 // initialize:single vertex at infinite temperature
424 vertex_t vstart;
425 vstart.z=0.;
426 vstart.t=0.;
427 vstart.pk=1.;
428 y.push_back(vstart);
429 int niter=0; // number of iterations
430
431 // estimate first critical temperature
432 double beta=beta0(fBetaMax, tks, y, fCoolingFactor);
433 niter=0; while((update1(beta, tks,y)>1.e-6) && (niter++ < fMaxIterations)){ }
434
435 // annealing loop, stop when T<Tmin (i.e. beta>1/Tmin)
436 while(beta<fBetaMax){
437
438 if(fUseTc){
439 update1(beta, tks,y);
440 while(merge(y,beta)){update1(beta, tks,y);}
441 split(beta, tks,y);
442 beta=beta/fCoolingFactor;
443 }else{
444 beta=beta/fCoolingFactor;
445 splitAll(y);
446 }
447
448 // make sure we are not too far from equilibrium before cooling further
449 niter=0; while((update1(beta, tks,y)>1.e-6) && (niter++ < fMaxIterations)){ }
450
451 }
452
453 if(fUseTc){
454 // last round of splitting, make sure no critical clusters are left
455 update1(beta, tks,y);
456 while(merge(y,beta)){update1(beta, tks,y);}
457 unsigned int ntry=0;
458 while( split(beta, tks,y) && (ntry++<10) ){
459 niter=0;
460 while((update1(beta, tks,y)>1.e-6) && (niter++ < fMaxIterations)){}
461 merge(y,beta);
462 update1(beta, tks,y);
463 }
464 }else{
465 // merge collapsed clusters
466 while(merge(y,beta)){update1(beta, tks,y);}
467 if(fVerbose ){ cout << "dump after 1st merging " << endl; dump(beta,y,tks);}
468 }
469
470 // switch on outlier rejection
471 rho0=1./nt; for(vector<vertex_t>::iterator k=y.begin(); k!=y.end(); k++){ k->pk =1.; } // democratic
472 niter=0; while((update2(beta, tks,y,rho0, fDzCutOff) > 1.e-8) && (niter++ < fMaxIterations)){ }
473 if(fVerbose ){ cout << "rho0=" << rho0 << " niter=" << niter << endl; dump(beta,y,tks);}
474
475
476 // merge again (some cluster split by outliers collapse here)
477 while(merge(y)){}
478 if(fVerbose ){ cout << "dump after 2nd merging " << endl; dump(beta,y,tks);}
479
480
481 // continue from freeze-out to Tstop (=1) without splitting, eliminate insignificant vertices
482 while(beta<=fBetaStop){
483 while(purge(y,tks,rho0, beta, fDzCutOff)){
484 niter=0; while((update2(beta, tks, y, rho0, fDzCutOff) > 1.e-6) && (niter++ < fMaxIterations)){ }
485 }
486 beta/=fCoolingFactor;
487 niter=0; while((update2(beta, tks, y, rho0, fDzCutOff) > 1.e-6) && (niter++ < fMaxIterations)){ }
488 }
489
490
491// // new, one last round of cleaning at T=Tstop
492// while(purge(y,tks,rho0, beta)){
493// niter=0; while((update2(beta, tks,y,rho0, fDzCutOff) > 1.e-6) && (niter++ < fMaxIterations)){ }
494// }
495
496
497 if(fVerbose){
498 cout << "Final result, rho0=" << rho0 << endl;
499 dump(beta,y,tks);
500 }
501
502
503 // select significant tracks and use a TransientVertex as a container
504 //GlobalError dummyError;
505
506 // ensure correct normalization of probabilities, should make double assginment reasonably impossible
507 for(unsigned int i=0; i<nt; i++){
508 tks[i].Z=rho0*exp(-beta*( fDzCutOff*fDzCutOff));
509 for(vector<vertex_t>::iterator k=y.begin(); k!=y.end(); k++){
510 tks[i].Z += k->pk * exp(-beta*Eik(tks[i],*k));
511 }
512 }
513
514 for(vector<vertex_t>::iterator k=y.begin(); k!=y.end(); k++){
515
516 DelphesFactory *factory = GetFactory();
517 candidate = factory->NewCandidate();
518
519 //cout<<"new vertex"<<endl;
520 //GlobalPoint pos(0, 0, k->z);
521 double time = k->t;
522 double z = k->z;
523 //vector< reco::TransientTrack > vertexTracks;
524 //double max_track_time_err2 = 0;
525 double mean = 0.;
526 double expv_x2 = 0.;
527 double normw = 0.;
528 for(unsigned int i=0; i<nt; i++){
529 const double invdt = 1.0/std::sqrt(tks[i].dt2);
530 if(tks[i].Z>0){
531 double p = k->pk * exp(-beta*Eik(tks[i],*k)) / tks[i].Z;
532 if( (tks[i].pi>0) && ( p > 0.5 ) ){
533 //std::cout << "pushing back " << i << ' ' << tks[i].tt << std::endl;
534 //vertexTracks.push_back(*(tks[i].tt)); tks[i].Z=0;
535
536 candidate->AddCandidate(tks[i].tt); tks[i].Z=0;
537
538 mean += tks[i].t*invdt*p;
539 expv_x2 += tks[i].t*tks[i].t*invdt*p;
540 normw += invdt*p;
541 } // setting Z=0 excludes double assignment
542 }
543 }
544
545 mean = mean/normw;
546 expv_x2 = expv_x2/normw;
547 const double time_var = expv_x2 - mean*mean;
548 const double crappy_error_guess = std::sqrt(time_var);
549 /*GlobalError dummyErrorWithTime(0,
550 0,0,
551 0,0,0,
552 0,0,0,crappy_error_guess);*/
553 //TransientVertex v(pos, time, dummyErrorWithTime, vertexTracks, 5);
554
555
556 candidate->ClusterIndex = clusterIndex++;;
557 candidate->Position.SetXYZT(0.0, 0.0, z*10.0 , time*c_light);
558
559 // TBC - fill error later ...
560 candidate->PositionError.SetXYZT(0.0, 0.0, 0.0 , crappy_error_guess*c_light);
561
562 clusterIndex++;
563 clusters.push_back(candidate);
564 }
565
566
567 return clusters;
568
569}
570
571//------------------------------------------------------------------------------
572
573static double Eik(const track_t & t, const vertex_t &k)
574{
575 return std::pow(t.z-k.z,2.)/t.dz2 + std::pow(t.t - k.t,2.)/t.dt2;
576}
577
578//------------------------------------------------------------------------------
579
580static void dump(const double beta, const vector<vertex_t> &y, const vector<track_t> &tks0)
581{
582 // copy and sort for nicer printout
583 vector<track_t> tks;
584 for(vector<track_t>::const_iterator t=tks0.begin(); t!=tks0.end(); t++){tks.push_back(*t); }
585 std::stable_sort(tks.begin(), tks.end(), recTrackLessZ1);
586
587 cout << "-----DAClusterizerInZT::dump ----" << endl;
588 cout << " beta=" << beta << endl;
589 cout << " z= ";
590 cout.precision(4);
591 for(vector<vertex_t>::const_iterator k=y.begin(); k!=y.end(); k++){
592 //cout << setw(8) << fixed << k->z;
593 }
594 cout << endl << " t= ";
595 for(vector<vertex_t>::const_iterator k=y.begin(); k!=y.end(); k++){
596 //cout << setw(8) << fixed << k->t;
597 }
598 //cout << endl << "T=" << setw(15) << 1./beta <<" Tc= ";
599 for(vector<vertex_t>::const_iterator k=y.begin(); k!=y.end(); k++){
600 //cout << setw(8) << fixed << k->Tc ;
601 }
602
603 cout << endl << " pk=";
604 double sumpk=0;
605 for(vector<vertex_t>::const_iterator k=y.begin(); k!=y.end(); k++){
606 //cout << setw(8) << setprecision(3) << fixed << k->pk;
607 sumpk+=k->pk;
608 }
609 cout << endl;
610
611 double E=0, F=0;
612 cout << endl;
613 cout << "---- z +/- dz t +/- dt ip +/-dip pt phi eta weights ----" << endl;
614 cout.precision(4);
615 for(unsigned int i=0; i<tks.size(); i++){
616 if (tks[i].Z>0){ F-=log(tks[i].Z)/beta;}
617 double tz= tks[i].z;
618 double tt= tks[i].t;
619 //cout << setw (3)<< i << ")" << setw (8) << fixed << setprecision(4)<< tz << " +/-" << setw (6)<< sqrt(tks[i].dz2)
620 // << setw(8) << fixed << setprecision(4) << tt << " +/-" << setw(6) << std::sqrt(tks[i].dt2) ;
621
622 double sump=0.;
623 for(vector<vertex_t>::const_iterator k=y.begin(); k!=y.end(); k++){
624 if((tks[i].pi>0)&&(tks[i].Z>0)){
625 //double p=pik(beta,tks[i],*k);
626 double p=k->pk * std::exp(-beta*Eik(tks[i],*k)) / tks[i].Z;
627 if( p > 0.0001){
628 //cout << setw (8) << setprecision(3) << p;
629 }else{
630 cout << " . ";
631 }
632 E+=p*Eik(tks[i],*k);
633 sump+=p;
634 }else{
635 cout << " ";
636 }
637 }
638 cout << endl;
639 }
640 cout << endl << "T=" << 1/beta << " E=" << E << " n="<< y.size() << " F= " << F << endl << "----------" << endl;
641}
642
643//------------------------------------------------------------------------------
644
645static double update1(double beta, vector<track_t> &tks, vector<vertex_t> &y)
646{
647 //update weights and vertex positions
648 // mass constrained annealing without noise
649 // returns the squared sum of changes of vertex positions
650
651 unsigned int nt=tks.size();
652
653 //initialize sums
654 double sumpi=0;
655 for(vector<vertex_t>::iterator k=y.begin(); k!=y.end(); ++k){
656 k->sw=0.; k->swz=0.; k->swt = 0.; k->se=0.;
657 k->swE=0.; k->Tc=0.;
658 }
659
660
661 // loop over tracks
662 for(unsigned int i=0; i<nt; i++){
663
664 // update pik and Zi
665 double Zi = 0.;
666 for(vector<vertex_t>::iterator k=y.begin(); k!=y.end(); ++k){
667 k->ei = std::exp(-beta*Eik(tks[i],*k));// cache exponential for one track at a time
668 Zi += k->pk * k->ei;
669 }
670 tks[i].Z=Zi;
671
672 // normalization for pk
673 if (tks[i].Z>0){
674 sumpi += tks[i].pi;
675 // accumulate weighted z and weights for vertex update
676 for(vector<vertex_t>::iterator k=y.begin(); k!=y.end(); ++k){
677 k->se += tks[i].pi* k->ei / Zi;
678 const double w = k->pk * tks[i].pi* k->ei / ( Zi * ( tks[i].dz2 * tks[i].dt2 ) );
679 k->sw += w;
680 k->swz += w * tks[i].z;
681 k->swt += w * tks[i].t;
682 k->swE += w * Eik(tks[i],*k);
683 }
684 }else{
685 sumpi += tks[i].pi;
686 }
687
688
689 } // end of track loop
690
691
692 // now update z and pk
693 double delta=0;
694 for(vector<vertex_t>::iterator k=y.begin(); k!=y.end(); k++){
695 if ( k->sw > 0){
696 const double znew = k->swz/k->sw;
697 const double tnew = k->swt/k->sw;
698 delta += std::pow(k->z-znew,2.) + std::pow(k->t-tnew,2.);
699 k->z = znew;
700 k->t = tnew;
701 k->Tc = 2.*k->swE/k->sw;
702 }else{
703 // cout << " a cluster melted away ? pk=" << k->pk << " sumw=" << k->sw << endl
704 k->Tc=-1;
705 }
706
707 k->pk = k->pk * k->se / sumpi;
708 }
709
710 // return how much the prototypes moved
711 return delta;
712}
713
714//------------------------------------------------------------------------------
715
716static double update2(double beta, vector<track_t> &tks, vector<vertex_t> &y, double &rho0, double dzCutOff)
717{
718 // MVF style, no more vertex weights, update tracks weights and vertex positions, with noise
719 // returns the squared sum of changes of vertex positions
720
721 unsigned int nt=tks.size();
722
723 //initialize sums
724 for(vector<vertex_t>::iterator k=y.begin(); k!=y.end(); k++){
725 k->sw = 0.; k->swz = 0.; k->swt = 0.; k->se = 0.;
726 k->swE = 0.; k->Tc=0.;
727 }
728
729
730 // loop over tracks
731 for(unsigned int i=0; i<nt; i++){
732
733 // update pik and Zi and Ti
734 double Zi = rho0*std::exp(-beta*(dzCutOff*dzCutOff));// cut-off (eventually add finite size in time)
735 //double Ti = 0.; // dt0*std::exp(-beta*fDtCutOff);
736 for(vector<vertex_t>::iterator k=y.begin(); k!=y.end(); k++){
737 k->ei = std::exp(-beta*Eik(tks[i],*k));// cache exponential for one track at a time
738 Zi += k->pk * k->ei;
739 }
740 tks[i].Z=Zi;
741
742 // normalization
743 if (tks[i].Z>0){
744 // accumulate weighted z and weights for vertex update
745 for(vector<vertex_t>::iterator k=y.begin(); k!=y.end(); k++){
746 k->se += tks[i].pi* k->ei / Zi;
747 double w = k->pk * tks[i].pi * k->ei /( Zi * ( tks[i].dz2 * tks[i].dt2 ) );
748 k->sw += w;
749 k->swz += w * tks[i].z;
750 k->swt += w * tks[i].t;
751 k->swE += w * Eik(tks[i],*k);
752 }
753 }
754
755 } // end of track loop
756
757 // now update z
758 double delta=0;
759 for(vector<vertex_t>::iterator k=y.begin(); k!=y.end(); k++){
760 if ( k->sw > 0){
761 const double znew=k->swz/k->sw;
762 const double tnew=k->swt/k->sw;
763 delta += std::pow(k->z-znew,2.) + std::pow(k->t-tnew,2.);
764 k->z = znew;
765 k->t = tnew;
766 k->Tc = 2*k->swE/k->sw;
767 }else{
768 // cout << " a cluster melted away ? pk=" << k->pk << " sumw=" << k->sw << endl;
769 k->Tc = 0;
770 }
771
772 }
773
774 // return how much the prototypes moved
775 return delta;
776}
777
778//------------------------------------------------------------------------------
779
780static bool merge(vector<vertex_t> &y)
781{
782 // merge clusters that collapsed or never separated, return true if vertices were merged, false otherwise
783
784 if(y.size()<2) return false;
785
786 for(vector<vertex_t>::iterator k=y.begin(); (k+1)!=y.end(); k++){
787 if( std::abs( (k+1)->z - k->z ) < 1.e-3 &&
788 std::abs( (k+1)->t - k->t ) < 1.e-3 ){ // with fabs if only called after freeze-out (splitAll() at highter T)
789 double rho = k->pk + (k+1)->pk;
790 if(rho>0){
791 k->z = ( k->pk * k->z + (k+1)->z * (k+1)->pk)/rho;
792 k->t = ( k->pk * k->t + (k+1)->t * (k+1)->pk)/rho;
793 }else{
794 k->z = 0.5*(k->z + (k+1)->z);
795 k->t = 0.5*(k->t + (k+1)->t);
796 }
797 k->pk = rho;
798
799 y.erase(k+1);
800 return true;
801 }
802 }
803
804 return false;
805}
806
807//------------------------------------------------------------------------------
808
809static bool merge(vector<vertex_t> &y, double &beta)
810{
811 // merge clusters that collapsed or never separated,
812 // only merge if the estimated critical temperature of the merged vertex is below the current temperature
813 // return true if vertices were merged, false otherwise
814 if(y.size()<2) return false;
815
816 for(vector<vertex_t>::iterator k=y.begin(); (k+1)!=y.end(); k++){
817 if ( std::abs((k+1)->z - k->z) < 2.e-3 &&
818 std::abs((k+1)->t - k->t) < 2.e-3 ) {
819 double rho=k->pk + (k+1)->pk;
820 double swE=k->swE+(k+1)->swE - k->pk * (k+1)->pk / rho * ( std::pow((k+1)->z - k->z,2.) +
821 std::pow((k+1)->t - k->t,2.) );
822 double Tc=2*swE/(k->sw+(k+1)->sw);
823
824 if(Tc*beta<1){
825 if(rho>0){
826 k->z = ( k->pk * k->z + (k+1)->z * (k+1)->pk)/rho;
827 k->t = ( k->pk * k->t + (k+1)->t * (k+1)->pk)/rho;
828 }else{
829 k->z = 0.5*(k->z + (k+1)->z);
830 k->t = 0.5*(k->t + (k+1)->t);
831 }
832 k->pk = rho;
833 k->sw += (k+1)->sw;
834 k->swE = swE;
835 k->Tc = Tc;
836 y.erase(k+1);
837 return true;
838 }
839 }
840 }
841
842 return false;
843}
844
845//------------------------------------------------------------------------------
846
847static bool purge(vector<vertex_t> &y, vector<track_t> &tks, double & rho0, const double beta, const double dzCutOff)
848{
849 // eliminate clusters with only one significant/unique track
850 if(y.size()<2) return false;
851
852 unsigned int nt=tks.size();
853 double sumpmin=nt;
854 vector<vertex_t>::iterator k0=y.end();
855 for(vector<vertex_t>::iterator k=y.begin(); k!=y.end(); k++){
856 int nUnique=0;
857 double sump=0;
858 double pmax=k->pk/(k->pk+rho0*exp(-beta*dzCutOff*dzCutOff));
859 for(unsigned int i=0; i<nt; i++){
860 if(tks[i].Z > 0){
861 double p = k->pk * std::exp(-beta*Eik(tks[i],*k)) / tks[i].Z ;
862 sump+=p;
863 if( (p > 0.9*pmax) && (tks[i].pi>0) ){ nUnique++; }
864 }
865 }
866
867 if((nUnique<2)&&(sump<sumpmin)){
868 sumpmin=sump;
869 k0=k;
870 }
871 }
872
873 if(k0!=y.end()){
874 //cout << "eliminating prototype at " << k0->z << "," << k0->t << " with sump=" << sumpmin << endl;
875 //rho0+=k0->pk;
876 y.erase(k0);
877 return true;
878 }else{
879 return false;
880 }
881}
882
883//------------------------------------------------------------------------------
884
885static double beta0(double betamax, vector<track_t> &tks, vector<vertex_t> &y, const double coolingFactor)
886{
887
888 double T0=0; // max Tc for beta=0
889 // estimate critical temperature from beta=0 (T=inf)
890 unsigned int nt=tks.size();
891
892 for(vector<vertex_t>::iterator k=y.begin(); k!=y.end(); k++){
893
894 // vertex fit at T=inf
895 double sumwz=0.;
896 double sumwt=0.;
897 double sumw=0.;
898 for(unsigned int i=0; i<nt; i++){
899 double w = tks[i].pi/(tks[i].dz2 * tks[i].dt2);
900 sumwz += w*tks[i].z;
901 sumwt += w*tks[i].t;
902 sumw += w;
903 }
904 k->z = sumwz/sumw;
905 k->t = sumwt/sumw;
906
907 // estimate Tcrit, eventually do this in the same loop
908 double a=0, b=0;
909 for(unsigned int i=0; i<nt; i++){
910 double dx = tks[i].z-(k->z);
911 double dt = tks[i].t-(k->t);
912 double w = tks[i].pi/(tks[i].dz2 * tks[i].dt2);
913 a += w*(std::pow(dx,2.)/tks[i].dz2 + std::pow(dt,2.)/tks[i].dt2);
914 b += w;
915 }
916 double Tc= 2.*a/b; // the critical temperature of this vertex
917 if(Tc>T0) T0=Tc;
918 }// vertex loop (normally there should be only one vertex at beta=0)
919
920 if (T0>1./betamax){
921 return betamax/pow(coolingFactor, int(std::log(T0*betamax)/std::log(coolingFactor))-1 );
922 }else{
923 // ensure at least one annealing step
924 return betamax/coolingFactor;
925 }
926}
927
928//------------------------------------------------------------------------------
929
930static bool split(double beta, vector<track_t> &tks, vector<vertex_t> &y)
931{
932 // split only critical vertices (Tc >~ T=1/beta <==> beta*Tc>~1)
933 // an update must have been made just before doing this (same beta, no merging)
934 // returns true if at least one cluster was split
935
936 const double epsilon = 1e-3; // split all single vertices by 10 um
937 bool split = false;
938
939 // avoid left-right biases by splitting highest Tc first
940
941 std::vector<std::pair<double, unsigned int> > critical;
942 for(unsigned int ik=0; ik<y.size(); ik++){
943 if (beta*y[ik].Tc > 1.){
944 critical.push_back( make_pair(y[ik].Tc, ik));
945 }
946 }
947 std::stable_sort(critical.begin(), critical.end(), std::greater<std::pair<double, unsigned int> >() );
948
949 for(unsigned int ic=0; ic<critical.size(); ic++){
950 unsigned int ik=critical[ic].second;
951 // estimate subcluster positions and weight
952 double p1=0, z1=0, t1=0, w1=0;
953 double p2=0, z2=0, t2=0, w2=0;
954 //double sumpi=0;
955 for(unsigned int i=0; i<tks.size(); i++){
956 if(tks[i].Z>0){
957 //sumpi+=tks[i].pi;
958 double p=y[ik].pk * exp(-beta*Eik(tks[i],y[ik])) / tks[i].Z*tks[i].pi;
959 double w=p/(tks[i].dz2 * tks[i].dt2);
960 if(tks[i].z < y[ik].z){
961 p1+=p; z1+=w*tks[i].z; t1+=w*tks[i].t; w1+=w;
962 }else{
963 p2+=p; z2+=w*tks[i].z; t2+=w*tks[i].t; w2+=w;
964 }
965 }
966 }
967 if(w1>0){ z1=z1/w1; t1=t1/w1;} else{ z1=y[ik].z-epsilon; t1=y[ik].t-epsilon; }
968 if(w2>0){ z2=z2/w2; t2=t2/w2;} else{ z2=y[ik].z+epsilon; t2=y[ik].t+epsilon;}
969
970 // reduce split size if there is not enough room
971 if( ( ik > 0 ) && ( y[ik-1].z>=z1 ) ){ z1=0.5*(y[ik].z+y[ik-1].z); t1=0.5*(y[ik].t+y[ik-1].t); }
972 if( ( ik+1 < y.size()) && ( y[ik+1].z<=z2 ) ){ z2=0.5*(y[ik].z+y[ik+1].z); t2=0.5*(y[ik].t+y[ik+1].t); }
973
974 // split if the new subclusters are significantly separated
975 if( (z2-z1)>epsilon || std::abs(t2-t1) > epsilon){
976 split=true;
977 vertex_t vnew;
978 vnew.pk = p1*y[ik].pk/(p1+p2);
979 y[ik].pk= p2*y[ik].pk/(p1+p2);
980 vnew.z = z1;
981 vnew.t = t1;
982 y[ik].z = z2;
983 y[ik].t = t2;
984 y.insert(y.begin()+ik, vnew);
985
986 // adjust remaining pointers
987 for(unsigned int jc=ic; jc<critical.size(); jc++){
988 if (critical[jc].second>ik) {critical[jc].second++;}
989 }
990 }
991 }
992
993 // stable_sort(y.begin(), y.end(), clusterLessZ);
994 return split;
995}
996
997//------------------------------------------------------------------------------
998
999void splitAll(vector<vertex_t> &y)
1000{
1001
1002
1003 const double epsilon=1e-3; // split all single vertices by 10 um
1004 const double zsep=2*epsilon; // split vertices that are isolated by at least zsep (vertices that haven't collapsed)
1005 const double tsep=2*epsilon; // check t as well
1006
1007 vector<vertex_t> y1;
1008
1009 for(vector<vertex_t>::iterator k=y.begin(); k!=y.end(); k++){
1010 if ( ( (k==y.begin())|| (k-1)->z < k->z - zsep) && (((k+1)==y.end() )|| (k+1)->z > k->z + zsep)) {
1011 // isolated prototype, split
1012 vertex_t vnew;
1013 vnew.z = k->z - epsilon;
1014 vnew.t = k->t - epsilon;
1015 (*k).z = k->z + epsilon;
1016 (*k).t = k->t + epsilon;
1017 vnew.pk= 0.5* (*k).pk;
1018 (*k).pk= 0.5* (*k).pk;
1019 y1.push_back(vnew);
1020 y1.push_back(*k);
1021
1022 }else if( y1.empty() || (y1.back().z < k->z -zsep) || (y1.back().t < k->t - tsep) ){
1023 y1.push_back(*k);
1024 }else{
1025 y1.back().z -= epsilon;
1026 y1.back().t -= epsilon;
1027 k->z += epsilon;
1028 k->t += epsilon;
1029 y1.push_back(*k);
1030 }
1031 }// vertex loop
1032
1033 y=y1;
1034}
1035
1036
1037
Note: See TracBrowser for help on using the repository browser.