Changeset 84a097e in git for modules/VertexFinderDA4D.cc
- Timestamp:
- Dec 2, 2019, 6:55:22 PM (5 years ago)
- Branches:
- Timing
- Children:
- 2ad823e, 6fc566b
- Parents:
- c614dd7
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
modules/VertexFinderDA4D.cc
rc614dd7 r84a097e 3 3 * Cluster vertices from tracks using deterministic annealing and timing information 4 4 * 5 * \authors M. Selvaggi, L. Gray5 * \authors O. Cerri 6 6 * 7 7 */ 8 8 9 9 10 #include "modules/VertexFinderDA4D.h" … … 13 14 #include "classes/DelphesPileUpReader.h" 14 15 16 #include "ExRootAnalysis/ExRootResult.h" 17 #include "ExRootAnalysis/ExRootFilter.h" 15 18 #include "ExRootAnalysis/ExRootClassifier.h" 16 #include "ExRootAnalysis/ExRootFilter.h" 17 #include "ExRootAnalysis/ExRootResult.h" 18 19 20 #include "TMath.h" 21 #include "TString.h" 22 #include "TFormula.h" 23 #include "TRandom3.h" 24 #include "TObjArray.h" 19 25 #include "TDatabasePDG.h" 20 #include "TFormula.h"21 26 #include "TLorentzVector.h" 22 #include "TMath.h"23 27 #include "TMatrixT.h" 24 #include "TObjArray.h" 25 #include "TRandom3.h" 28 #include "TLatex.h" 29 #include "TVector3.h" 30 31 #include "TAxis.h" 32 #include "TGraphErrors.h" 33 #include "TCanvas.h" 26 34 #include "TString.h" 27 #include "TVector3.h" 28 35 #include "TLegend.h" 36 #include "TFile.h" 37 #include "TColor.h" 38 #include "TLegend.h" 39 40 #include <utility> 29 41 #include <algorithm> 42 #include <stdexcept> 30 43 #include <iostream> 31 #include <stdexcept>32 #include <utility>33 44 #include <vector> 34 45 35 46 using namespace std; 36 47 37 static const Double_t mm = 1.; 38 static const Double_t m = 1000. * mm; 39 static const Double_t ns = 1.; 40 static const Double_t s = 1.e+9 * ns; 41 static const Double_t c_light = 2.99792458e+8 * m / s; 42 43 struct track_t 44 { 45 double z; // z-coordinate at point of closest approach to the beamline 46 double t; // t-coordinate at point of closest approach to the beamline 47 double dz2; // square of the error of z(pca) 48 double dtz; // covariance of z-t 49 double dt2; // square of the error of t(pca) 50 Candidate *tt; // a pointer to the Candidate Track 51 double Z; // Z[i] for DA clustering 52 double pi; // track weight 53 double pt; 54 double eta; 55 double phi; 56 }; 57 58 struct vertex_t 59 { 60 double z; 61 double t; 62 double pk; // vertex weight for "constrained" clustering 63 // --- temporary numbers, used during update 64 double ei; 65 double sw; 66 double swz; 67 double swt; 68 double se; 69 // ---for Tc 70 double swE; 71 double Tc; 72 }; 73 74 static bool split(double beta, std::vector<track_t> &tks, std::vector<vertex_t> &y); 75 static double update1(double beta, std::vector<track_t> &tks, std::vector<vertex_t> &y); 76 static double update2(double beta, std::vector<track_t> &tks, std::vector<vertex_t> &y, double &rho0, const double dzCutOff); 77 static void dump(const double beta, const std::vector<vertex_t> &y, const std::vector<track_t> &tks); 78 static bool merge(std::vector<vertex_t> &); 79 static bool merge(std::vector<vertex_t> &, double &); 80 static bool purge(std::vector<vertex_t> &, std::vector<track_t> &, double &, const double, const double); 81 static void splitAll(std::vector<vertex_t> &y); 82 static double beta0(const double betamax, std::vector<track_t> &tks, std::vector<vertex_t> &y, const double coolingFactor); 83 static double Eik(const track_t &t, const vertex_t &k); 84 85 static bool recTrackLessZ1(const track_t &tk1, const track_t &tk2) 86 { 87 return tk1.z < tk2.z; 88 } 89 90 using namespace std; 48 namespace vtx_DAZT 49 { 50 static const Double_t c_light = 2.99792458e+8; // [m/s] 51 } 52 using namespace vtx_DAZT; 91 53 92 54 //------------------------------------------------------------------------------ 93 55 94 VertexFinderDA4D::VertexFinderDA4D() : 95 fVerbose(0), fMinPT(0), fVertexSpaceSize(0), fVertexTimeSize(0), 96 fUseTc(0), fBetaMax(0), fBetaStop(0), fCoolingFactor(0), 97 fMaxIterations(0), fDzCutOff(0), fD0CutOff(0), fDtCutOff(0) 98 { 56 VertexFinderDA4D::VertexFinderDA4D() 57 { 58 fVerbose = 0; 59 fMaxIterations = 0; 60 fBetaMax = 0; 61 fBetaStop = 0; 62 fBetaPurge = 0; 63 fVertexZSize = 0; 64 fVertexTSize = 0; 65 fCoolingFactor = 0; 66 fDzCutOff = 0; 67 fD0CutOff = 0; 68 fDtCutOff = 0; 69 fPtMin = 0; 70 fPtMax = 0; 71 fD2Merge = 0; 72 fMuOutlayer = 0; 73 fMinTrackProb = 0; 99 74 } 100 75 … … 109 84 void VertexFinderDA4D::Init() 110 85 { 111 112 fVerbose = GetBool("Verbose", 1); 113 fMinPT = GetDouble("MinPT", 0.1); 114 fVertexSpaceSize = GetDouble("VertexSpaceSize", 0.5); //in mm 115 fVertexTimeSize = GetDouble("VertexTimeSize", 10E-12); //in s 116 fUseTc = GetBool("UseTc", 1); 117 fBetaMax = GetDouble("BetaMax ", 0.1); 118 fBetaStop = GetDouble("BetaStop", 1.0); 119 fCoolingFactor = GetDouble("CoolingFactor", 0.8); 120 fMaxIterations = GetInt("MaxIterations", 100); 121 fDzCutOff = GetDouble("DzCutOff", 40); // Adaptive Fitter uses 30 mm but that appears to be a bit tight here sometimes 122 fD0CutOff = GetDouble("D0CutOff", 30); 123 fDtCutOff = GetDouble("DtCutOff", 100E-12); // dummy 124 125 // convert stuff in cm, ns 126 fVertexSpaceSize /= 10.0; 127 fVertexTimeSize *= 1E9; 128 fDzCutOff /= 10.0; // Adaptive Fitter uses 3.0 but that appears to be a bit tight here sometimes 129 fD0CutOff /= 10.0; 86 fVerbose = GetInt("Verbose", 0); 87 88 fMaxIterations = GetInt("MaxIterations", 100); 89 fMaxVertexNumber = GetInt("MaxVertexNumber", 500); 90 91 fBetaMax = GetDouble("BetaMax", 1.5); 92 fBetaPurge = GetDouble("BetaPurge", 1.); 93 fBetaStop = GetDouble("BetaStop", 0.2); 94 95 fVertexZSize = GetDouble("VertexZSize", 0.1); //in mm 96 fVertexTSize = 1E12*GetDouble("VertexTimeSize", 15E-12); //Convert from [s] to [ps] 97 98 fCoolingFactor = GetDouble("CoolingFactor", 0.8); // Multiply T so to cooldown must be <1 99 100 fDzCutOff = GetDouble("DzCutOff", 40); // For the moment 3*DzCutOff is hard cut off for the considered tracks 101 fD0CutOff = GetDouble("D0CutOff", .5); // d0/sigma_d0, used to compute the pi (weight) of the track 102 fDtCutOff = GetDouble("DtCutOff", 160); // [ps], 3*DtCutOff is hard cut off for tracks 103 fPtMin = GetDouble("PtMin", 0.5); // Minimum pt accepted for tracks 104 fPtMax = GetDouble("PtMax", 50); // Maximum pt accepted for tracks 105 106 107 fD2UpdateLim = GetDouble("D2UpdateLim", .5); // ((dz/ZSize)^2+(dt/TSize)^2)/nv limit for merging vertices 108 fD2Merge = GetDouble("D2Merge", 4.0); // (dz/ZSize)^2+(dt/TSize)^2 limit for merging vertices 109 fMuOutlayer = GetDouble("MuOutlayer", 4); // Outlayer rejection exponent 110 fMinTrackProb = GetDouble("MinTrackProb", 0.6); // Minimum probability to be assigned at a vertex 111 fMinNTrack = GetInt("MinNTrack", 10); // Minimum number of tracks per vertex 112 113 fFigFolderPath = GetString("DebugFigPath", "."); 130 114 131 115 fInputArray = ImportArray(GetString("InputArray", "TrackSmearing/tracks")); 132 116 fItInputArray = fInputArray->MakeIterator(); 133 117 134 f OutputArray = ExportArray(GetString("OutputArray", "tracks"));118 fTrackOutputArray = ExportArray(GetString("TrackOutputArray", "tracks")); 135 119 fVertexOutputArray = ExportArray(GetString("VertexOutputArray", "vertices")); 120 121 fInputGenVtx = ImportArray(GetString("InputGenVtx", "PileUpMerger/vertices")); 122 fItInputGenVtx = fInputGenVtx->MakeIterator(); 123 124 if (fBetaMax < fBetaPurge) 125 { 126 fBetaPurge = fBetaMax; 127 if (fVerbose) 128 { 129 cout << "BetaPurge set to " << fBetaPurge << endl; 130 } 131 } 132 133 if (fBetaPurge < fBetaStop) 134 { 135 fBetaStop = fBetaPurge; 136 if (fVerbose) 137 { 138 cout << "BetaPurge set to " << fBetaPurge << endl; 139 } 140 } 136 141 } 137 142 … … 147 152 void VertexFinderDA4D::Process() 148 153 { 149 Candidate *candidate, *track;150 TObjArray *ClusterArray;151 ClusterArray = new TObjArray;152 TIterator *ItClusterArray;153 Int_t ivtx = 0;154 155 154 fInputArray->Sort(); 156 155 157 TLorentzVector pos, mom; 156 if (fVerbose) 157 { 158 cout<< endl << " Start processing vertices with VertexFinderDA4D" << endl; 159 cout<<" Found "<<fInputArray->GetEntriesFast()<<" input tracks"<<endl; 160 } 161 162 // clusterize tracks 163 TObjArray *ClusterArray = new TObjArray; 164 clusterize(*ClusterArray); 165 166 if(fVerbose>10) 167 { 168 unsigned int N = fEnergy_rec.size(); 169 TGraph* gr1 = new TGraph(N, &fBeta_rec[0], &fNvtx_rec[0]); 170 gr1->SetName("gr1"); 171 gr1->GetXaxis()->SetTitle("beta"); 172 gr1->GetYaxis()->SetTitle("# Vtx"); 173 TGraph* gr2 = new TGraph(N, &fBeta_rec[0], &fEnergy_rec[0]); 174 gr2->SetName("gr2"); 175 gr2->GetXaxis()->SetTitle("beta"); 176 gr2->GetYaxis()->SetTitle("Total Energy"); 177 TGraph* gr3 = new TGraph(N, &fNvtx_rec[0], &fEnergy_rec[0]); 178 gr3->SetName("gr3"); 179 gr3->GetXaxis()->SetTitle("# Vtx"); 180 gr3->GetYaxis()->SetTitle("Total Energy"); 181 182 auto f = new TFile("~/Desktop/debug/EnergyStat.root", "recreate"); 183 gr1->Write("gr1"); 184 gr2->Write("gr2"); 185 gr3->Write("gr3"); 186 187 f->Close(); 188 } 189 190 if (fVerbose){std::cout << " clustering returned "<< ClusterArray->GetEntriesFast() << " clusters from " << fInputArray->GetEntriesFast() << " input tracks" <<std::endl;} 191 192 // //loop over vertex candidates 193 TIterator * ItClusterArray = ClusterArray->MakeIterator(); 194 ItClusterArray->Reset(); 195 Candidate *candidate; 196 unsigned int k = 0; 197 while((candidate = static_cast<Candidate*>(ItClusterArray->Next()))) 198 { 199 if(fVerbose) 200 { 201 cout << Form("Cluster %d has %d tracks ", k, candidate->GetCandidates()->GetEntriesFast()) << endl; 202 } 203 if(candidate->ClusterNDF>0) 204 { 205 // Estimate the vertex resolution 206 // loop over tracks belonging to this vertex 207 TIter it1(candidate->GetCandidates()); 208 it1.Reset(); 209 210 Candidate *track; 211 double sum_Dt_2 = 0; 212 double sum_Dz_2 = 0; 213 double sum_wt = 0; 214 double sum_wz = 0; 215 while((track = static_cast<Candidate*>(it1.Next()))) 216 { 217 double dz = candidate->Position.Z() - track->Zd; 218 double dt = candidate->Position.T() - track->Td; 219 220 double wz = track->VertexingWeight/(track->ErrorDZ*track->ErrorDZ); 221 double wt = track->VertexingWeight/(track->ErrorT*track->ErrorT); 222 223 sum_Dt_2 += wt*dt*dt; 224 sum_Dz_2 += wz*dz*dz; 225 sum_wt += wt; 226 sum_wz += wz; 227 } 228 229 double sigma_z = sqrt(sum_Dz_2/sum_wz); 230 double sigma_t = sqrt(sum_Dt_2/sum_wt); 231 candidate->PositionError.SetXYZT(0.0, 0.0, sigma_z , sigma_t); 232 if(fVerbose > 3) 233 { 234 cout << "k: " << k << endl; 235 cout << "Sigma z: " << sigma_z*1E3 << " um" << endl; 236 cout << "Sigma t: " << sigma_t*1E9/c_light << " ps" << endl; 237 } 238 239 fVertexOutputArray->Add(candidate); 240 k++; 241 } 242 }// end of cluster loop 243 244 delete ClusterArray; 245 } 246 247 //------------------------------------------------------------------------------ 248 249 void VertexFinderDA4D::clusterize(TObjArray &clusters) 250 { 251 tracks_t tks; 252 fill(tks); 253 unsigned int nt=tks.getSize(); 158 254 if(fVerbose) 159 255 { 160 cout << " start processing vertices ..." << endl; 161 cout << " Found " << fInputArray->GetEntriesFast() << " input tracks" << endl; 162 //loop over input tracks 163 fItInputArray->Reset(); 164 while((candidate = static_cast<Candidate *>(fItInputArray->Next()))) 165 { 166 pos = candidate->InitialPosition; 167 mom = candidate->Momentum; 168 169 cout << "pt: " << mom.Pt() << ", eta: " << mom.Eta() << ", phi: " << mom.Phi() << ", z: " << candidate->DZ / 10 << endl; 170 } 171 } 172 173 // clusterize tracks in Z 174 clusterize(*fInputArray, *ClusterArray); 175 176 if(fVerbose) 177 { 178 std::cout << " clustering returned " << ClusterArray->GetEntriesFast() << " clusters from " << fInputArray->GetEntriesFast() << " selected tracks" << std::endl; 179 } 180 181 //loop over vertex candidates 182 ItClusterArray = ClusterArray->MakeIterator(); 183 ItClusterArray->Reset(); 184 while((candidate = static_cast<Candidate *>(ItClusterArray->Next()))) 185 { 186 187 double meantime = 0.; 188 double expv_x2 = 0.; 189 double normw = 0.; 190 double errtime = 0; 191 192 double meanpos = 0.; 193 double meanerr2 = 0.; 194 double normpos = 0.; 195 double errpos = 0.; 196 197 double sumpt2 = 0.; 198 199 int itr = 0; 200 201 if(fVerbose) cout << "this vertex has: " << candidate->GetCandidates()->GetEntriesFast() << " tracks" << endl; 202 203 // loop over tracks belonging to this vertex 204 TIter it1(candidate->GetCandidates()); 205 it1.Reset(); 206 207 while((track = static_cast<Candidate *>(it1.Next()))) 208 { 209 210 itr++; 211 // TBC: the time is in ns for now TBC 212 double t = track->InitialPosition.T() / c_light; 213 double dt = track->ErrorT / c_light; 214 const double time = t; 215 const double inverr = 1.0 / dt; 216 meantime += time * inverr; 217 expv_x2 += time * time * inverr; 218 normw += inverr; 219 220 // compute error position TBC 221 const double pt = track->Momentum.Pt(); 222 const double z = track->DZ / 10.0; 223 const double err_pt = track->ErrorPT; 224 const double err_z = track->ErrorDZ; 225 226 const double wi = (pt / (err_pt * err_z)) * (pt / (err_pt * err_z)); 227 meanpos += z * wi; 228 229 meanerr2 += err_z * err_z * wi; 230 normpos += wi; 231 sumpt2 += pt * pt; 232 233 // while we are here store cluster index in tracks 234 track->ClusterIndex = ivtx; 235 } 236 237 meantime = meantime / normw; 238 expv_x2 = expv_x2 / normw; 239 errtime = TMath::Sqrt((expv_x2 - meantime * meantime) / itr); 240 meanpos = meanpos / normpos; 241 meanerr2 = meanerr2 / normpos; 242 errpos = TMath::Sqrt(meanerr2 / itr); 243 244 candidate->Position.SetXYZT(0.0, 0.0, meanpos * 10.0, meantime * c_light); 245 candidate->PositionError.SetXYZT(0.0, 0.0, errpos * 10.0, errtime * c_light); 246 candidate->SumPT2 = sumpt2; 247 candidate->ClusterNDF = itr; 248 candidate->ClusterIndex = ivtx; 249 250 fVertexOutputArray->Add(candidate); 251 252 ivtx++; 253 254 if(fVerbose) 255 { 256 std::cout << "x,y,z"; 257 std::cout << ",t"; 258 std::cout << "=" << candidate->Position.X() / 10.0 << " " << candidate->Position.Y() / 10.0 << " " << candidate->Position.Z() / 10.0; 259 std::cout << " " << candidate->Position.T() / c_light; 260 261 std::cout << std::endl; 262 std::cout << "sumpt2 " << candidate->SumPT2 << endl; 263 264 std::cout << "ex,ey,ez"; 265 std::cout << ",et"; 266 std::cout << "=" << candidate->PositionError.X() / 10.0 << " " << candidate->PositionError.Y() / 10.0 << " " << candidate->PositionError.Z() / 10.0; 267 std::cout << " " << candidate->PositionError.T() / c_light; 268 std::cout << std::endl; 269 } 270 } // end of cluster loop 271 272 if(fVerbose) 273 { 274 std::cout << "PrimaryVertexProducerAlgorithm::vertices candidates =" << ClusterArray->GetEntriesFast() << std::endl; 275 } 276 277 //TBC maybe this can be done later 278 // sort vertices by pt**2 vertex (aka signal vertex tagging) 279 /*if(pvs.size()>1){ 280 sort(pvs.begin(), pvs.end(), VertexHigherPtSquared()); 281 } 282 */ 283 284 delete ClusterArray; 256 cout << "Tracks added: " << nt << endl; 257 } 258 if (nt == 0) return; 259 260 261 262 vertex_t vtx; // the vertex prototypes 263 vtx.ZSize = fVertexZSize; 264 vtx.TSize = fVertexTSize; 265 // initialize:single vertex at infinite temperature 266 vtx.addItem(0, 0, 1); 267 268 // Fit the vertex at T=inf and return the starting temperature 269 double beta=beta0(tks, vtx); 270 271 if( fVerbose > 1 ) 272 { 273 cout << "Cluster position at T=inf: z = " << vtx.z[0] << " mm , t = " << vtx.t[0] << " ps" << " pk = " << vtx.pk[0] << endl; 274 cout << Form("Beta Start = %2.1e", beta) << endl; 275 } 276 277 if( fVerbose > 10 ) plot_status(beta, vtx, tks, 0, "Ast"); 278 279 if( fVerbose > 2){cout << "Cool down untill reaching the temperature to finish increasing the number of vertexes" << endl;} 280 281 double rho0=0.0; // start with no outlier rejection 282 283 unsigned int last_round = 0; 284 while(last_round < 2) 285 { 286 287 unsigned int niter=0; 288 double delta2 = 0; 289 do { 290 delta2 = update(beta, tks, vtx, rho0); 291 292 if( fVerbose > 10 ) plot_status(beta, vtx, tks, niter, "Bup"); 293 if (fVerbose > 3) 294 { 295 cout << "Update " << niter << " : " << delta2 << endl; 296 } 297 niter++; 298 } 299 while (delta2 > fD2UpdateLim && niter < fMaxIterations); 300 301 302 unsigned int n_it = 0; 303 while(merge(vtx, fD2Merge) && n_it < fMaxIterations) 304 { 305 unsigned int niter=0; 306 double delta2 = 0; 307 do { 308 delta2 = update(beta, tks, vtx, rho0); 309 niter++; 310 } 311 while (delta2 > fD2UpdateLim && niter < fMaxIterations); 312 n_it++; 313 314 if( fVerbose > 10 ) plot_status(beta, vtx, tks, n_it, "Cme"); 315 } 316 317 beta /= fCoolingFactor; 318 319 if( beta < fBetaStop ) 320 { 321 split(beta, vtx, tks); 322 if( fVerbose > 10 ) plot_status(beta, vtx, tks, 0, "Asp"); 323 } 324 else 325 { 326 beta = fBetaStop; 327 last_round++; 328 } 329 330 if(fVerbose > 3) 331 { 332 cout << endl << endl << " ----- Beta = " << beta << " --------" << endl; 333 cout << "Nv: " << vtx.getSize() << endl; 334 } 335 } 336 337 if( fVerbose > 4) 338 { 339 for(unsigned int k = 0; k < vtx.getSize(); k++) 340 { 341 cout << Form("Vertex %d next beta_c = %.3f", k, vtx.beta_c[k]) << endl; 342 } 343 } 344 345 if(fVerbose > 2) {cout << "Adiabatic switch on of outlayr rejection" << endl;} 346 rho0 = 1./nt; 347 const double N_cycles = 10; 348 for(unsigned int f = 1; f <= N_cycles; f++) 349 { 350 unsigned int niter=0; 351 double delta2 = 0; 352 do { 353 delta2 = update(beta, tks, vtx, rho0 * f/N_cycles); 354 niter++; 355 } 356 while (delta2 > 0.3*fD2UpdateLim && niter < fMaxIterations); 357 if( fVerbose > 10 ) plot_status(beta, vtx, tks, f, "Dadout"); 358 } 359 360 do { 361 beta /= fCoolingFactor; 362 if(beta > fBetaPurge) beta = fBetaPurge; 363 unsigned int i_pu = 0; 364 for(int min_trk = 2; min_trk<=fMinNTrack; min_trk++) 365 { 366 while( purge(vtx, tks, rho0, beta, fMinTrackProb, min_trk) ) 367 { 368 unsigned int niter=0; 369 double delta2 = 0; 370 do { 371 delta2 = update(beta, tks, vtx, rho0); 372 niter++; 373 } 374 while (delta2 > fD2UpdateLim && niter < fMaxIterations); 375 if( fVerbose > 10 ) plot_status(beta, vtx, tks, i_pu, Form("Eprg%d",min_trk)); 376 i_pu++; 377 } 378 } 379 380 unsigned int n_it = 0; 381 while(merge(vtx, fD2Merge) && n_it < fMaxIterations) 382 { 383 unsigned int niter=0; 384 double delta2 = 0; 385 do { 386 delta2 = update(beta, tks, vtx, rho0); 387 niter++; 388 } 389 while (delta2 > fD2UpdateLim && niter < fMaxIterations); 390 n_it++; 391 392 if( fVerbose > 10 ) plot_status(beta, vtx, tks, n_it, "Cme"); 393 } 394 } while( beta < fBetaPurge ); 395 396 397 if(fVerbose > 2){cout << "Cooldown untill the limit before assigning track to vertices" << endl;} 398 last_round = 0; 399 while(last_round < 2) 400 { 401 unsigned int niter=0; 402 double delta2 = 0; 403 do { 404 delta2 = update(beta, tks, vtx, rho0); 405 niter++; 406 if( fVerbose > 10 ) plot_status(beta, vtx, tks, 0, "Bup"); 407 } 408 while (delta2 > 0.3*fD2UpdateLim && niter < fMaxIterations); 409 410 beta /= fCoolingFactor; 411 if ( beta >= fBetaMax ) 412 { 413 beta = fBetaMax; 414 last_round++; 415 } 416 } 417 418 419 // Build the cluster candidates 420 for(unsigned int k = 0; k < vtx.getSize(); k++) 421 { 422 DelphesFactory *factory = GetFactory(); 423 Candidate * candidate = factory->NewCandidate(); 424 425 candidate->ClusterIndex = k; 426 candidate->Position.SetXYZT(0.0, 0.0, vtx.z[k] , vtx.t[k]*1E-9*c_light); 427 candidate->PositionError.SetXYZT(0.0, 0.0, fVertexZSize , fVertexTSize*1E-9*c_light); 428 candidate->SumPT2 = 0; 429 candidate->SumPt = 0; 430 candidate->ClusterNDF = 0; 431 432 clusters.Add(candidate); 433 } 434 435 436 // Assign each track to the most probable vertex 437 double Z_init = rho0 * exp(-beta * fMuOutlayer * fMuOutlayer); // Add fDtCutOff here toghether with this 438 vector<double> pk_exp_mBetaE = Compute_pk_exp_mBetaE(beta, vtx, tks, Z_init); 439 for(unsigned int i = 0; i< tks.getSize(); i++) 440 { 441 if(tks.w[i] <= 0) continue; 442 443 double p_max = 0; 444 unsigned int k_max = 0; 445 446 for(unsigned int k = 0; k < vtx.getSize(); k++) 447 { 448 unsigned int idx = k*nt + i; 449 if(pk_exp_mBetaE[idx] == 0 || tks.Z[i] == 0 || vtx.pk[k] == 0) 450 { 451 continue; 452 } 453 454 double pv_max = vtx.pk[k] / (vtx.pk[k] + rho0 * exp(-beta * fMuOutlayer* fMuOutlayer)); 455 double p = pk_exp_mBetaE[idx] / tks.Z[i]; 456 457 p /= pv_max; 458 459 if(p > p_max) 460 { 461 p_max = p; 462 k_max = k; 463 } 464 } 465 466 if(p_max > fMinTrackProb) 467 { 468 tks.tt[i]->ClusterIndex = k_max; 469 tks.tt[i]->InitialPosition.SetT(1E-9*vtx.t[k_max]*c_light); 470 tks.tt[i]->InitialPosition.SetZ(vtx.z[k_max]); 471 472 ((Candidate *) clusters.At(k_max))->AddCandidate(tks.tt[i]); 473 ((Candidate *) clusters.At(k_max))->SumPT2 += tks.tt[i]->Momentum.Pt()*tks.tt[i]->Momentum.Pt(); 474 ((Candidate *) clusters.At(k_max))->SumPt += tks.tt[i]->Momentum.Pt(); 475 ((Candidate *) clusters.At(k_max))->ClusterNDF += 1; 476 } 477 else 478 { 479 tks.tt[i]->ClusterIndex = -1; 480 tks.tt[i]->InitialPosition.SetT(1E3*1000000*c_light); 481 tks.tt[i]->InitialPosition.SetZ(1E8); 482 } 483 fTrackOutputArray->Add(tks.tt[i]); 484 } 485 486 if(fVerbose > 10) plot_status_end(vtx, tks); 487 285 488 } 286 489 287 490 //------------------------------------------------------------------------------ 288 289 void VertexFinderDA4D::clusterize(const TObjArray &tracks, TObjArray &clusters) 290 { 291 if(fVerbose) 292 { 293 cout << "###################################################" << endl; 294 cout << "# VertexFinderDA4D::clusterize nt=" << tracks.GetEntriesFast() << endl; 295 cout << "###################################################" << endl; 296 } 297 298 vector<Candidate *> pv = vertices(); 299 300 if(fVerbose) 301 { 302 cout << "# VertexFinderDA4D::clusterize pv.size=" << pv.size() << endl; 303 } 304 if(pv.size() == 0) 305 { 306 return; 307 } 308 309 // convert into vector of candidates 310 //TObjArray *ClusterArray = pv.begin()->GetCandidates(); 311 //Candidate *aCluster = static_cast<Candidate*>(&(pv.at(0))); 312 Candidate *aCluster = pv.at(0); 313 314 // fill into clusters and merge 315 316 if(fVerbose) 317 { 318 std::cout << '\t' << 0; 319 std::cout << ' ' << (*pv.begin())->Position.Z() / 10.0 << ' ' << (*pv.begin())->Position.T() / c_light << std::endl; 320 } 321 322 for(vector<Candidate *>::iterator k = pv.begin() + 1; k != pv.end(); k++) 323 { 324 if(fVerbose) 325 { 326 std::cout << '\t' << std::distance(pv.begin(), k); 327 std::cout << ' ' << (*k)->Position.Z() << ' ' << (*k)->Position.T() << std::endl; 328 } 329 330 // TBC - check units here 331 if(std::abs((*k)->Position.Z() - (*(k - 1))->Position.Z()) / 10.0 > (2 * fVertexSpaceSize) || std::abs((*k)->Position.T() - (*(k - 1))->Position.Z()) / c_light > 2 * 0.010) 332 { 333 // close a cluster 334 clusters.Add(aCluster); 335 //aCluster.clear(); 336 } 337 //for(unsigned int i=0; i<k->GetCandidates().GetEntriesFast(); i++){ 338 aCluster = *k; 339 //} 340 } 341 clusters.Add(aCluster); 342 343 if(fVerbose) 344 { 345 std::cout << "# VertexFinderDA4D::clusterize clusters.size=" << clusters.GetEntriesFast() << std::endl; 346 } 491 // Definition of the distance metrci between track and vertex 492 double VertexFinderDA4D::Energy(double t_z, double v_z, double dz2_o, double t_t, double v_t, double dt2_o) 493 { 494 return (t_z - v_z)*(t_z - v_z)* dz2_o + (t_t - v_t)*(t_t - v_t)*dt2_o; 347 495 } 348 496 349 497 //------------------------------------------------------------------------------ 350 351 vector<Candidate *> VertexFinderDA4D::vertices() 352 { 498 // Fill tks with the input candidates array 499 void VertexFinderDA4D::fill(tracks_t &tks) 500 { 501 tks.sum_w_o_dt2 = 0; 502 tks.sum_w_o_dz2 = 0; 503 tks.sum_w = 0; 504 353 505 Candidate *candidate; 354 UInt_t clusterIndex = 0; 355 vector<Candidate *> clusters; 356 357 vector<track_t> tks; 358 track_t tr; 359 Double_t z, dz, t, l, dt, d0, d0error; 360 361 // loop over input tracks 506 362 507 fItInputArray->Reset(); 363 while((candidate = static_cast<Candidate *>(fItInputArray->Next()))) 364 { 365 //TBC everything in cm 366 z = candidate->DZ / 10; 367 tr.z = z; 368 dz = candidate->ErrorDZ / 10; 369 tr.dz2 = dz * dz // track error 370 //TBC: beamspot size induced error, take 0 for now. 371 // + (std::pow(beamspot.BeamWidthX()*cos(phi),2.)+std::pow(beamspot.BeamWidthY()*sin(phi),2.))/std::pow(tantheta,2.) // beam-width induced 372 + fVertexSpaceSize * fVertexSpaceSize; // intrinsic vertex size, safer for outliers and short lived decays 373 374 // TBC: the time is in ns for now TBC 375 //t = candidate->Position.T()/c_light; 376 t = candidate->InitialPosition.T() / c_light; 377 l = candidate->L / c_light; 508 while((candidate = static_cast<Candidate*>(fItInputArray->Next()))) 509 { 510 unsigned int discard = 0; 511 378 512 double pt = candidate->Momentum.Pt(); 379 double eta = candidate->Momentum.Eta(); 380 double phi = candidate->Momentum.Phi(); 381 382 tr.pt = pt; 383 tr.eta = eta; 384 tr.phi = phi; 385 tr.t = t; // 386 tr.dtz = 0.; 387 dt = candidate->ErrorT / c_light; 388 tr.dt2 = dt * dt + fVertexTimeSize * fVertexTimeSize; // the ~injected~ timing error plus a small minimum vertex size in time 389 if(fD0CutOff > 0) 390 { 391 392 d0 = TMath::Abs(candidate->D0) / 10.0; 393 d0error = candidate->ErrorD0 / 10.0; 394 395 tr.pi = 1. / (1. + exp((d0 * d0) / (d0error * d0error) - fD0CutOff * fD0CutOff)); // reduce weight for high ip tracks 513 if(pt<fPtMin || pt>fPtMax) discard = 1; 514 515 // ------------- Compute cloasest approach Z ---------------- 516 double z = candidate->DZ; // [mm] 517 518 candidate->Zd = candidate->DZ; //Set the cloasest approach z 519 if(fabs(z) > 3*fDzCutOff) discard = 1; 520 521 // ------------- Compute cloasest approach T ---------------- 522 //Asumme pion mass which is the most common particle 523 double M = 0.139570; 524 candidate->Mass = M; 525 double p = pt * sqrt(1 + candidate->CtgTheta*candidate->CtgTheta); 526 double e = sqrt(p*p + M*M); 527 528 double t = candidate->Position.T()*1.E9/c_light; // from [mm] to [ps] 529 if(t <= -9999) discard = 1; // Means that the time information has not been added 530 531 // DEBUG Here backpropagete for the whole length and not noly for z. Could improve resolution 532 // double bz = pt * candidate->CtgTheta/e; 533 // t += (z - candidate->Position.Z())*1E9/(c_light*bz); 534 535 // Use full path Length 536 t -= candidate->L*1E9/(c_light*p/e); 537 538 candidate->Td = t*1E-9*c_light; 539 if(fabs(t) > 3*fDtCutOff) discard = 1; 540 541 // auto genp = (Candidate*) candidate->GetCandidates()->At(0); 542 // cout << "Eta: " << candidate->Position.Eta() << endl; 543 // cout << genp->Momentum.Pt() << " -- " << candidate->Momentum.Pt() << endl; 544 // cout << genp->Momentum.Pz() << " -- " << candidate->Momentum.Pz() << endl; 545 // cout << genp->Momentum.P() << " -- " << p << endl; 546 // cout << genp->Momentum.E() << " -- " << e << endl; 547 // cout << Form("bz_true: %.4f -- bz_gen: %.4f", genp->Momentum.Pz()/genp->Momentum.E(), bz) << endl; 548 549 double dz2_o = candidate->ErrorDZ*candidate->ErrorDZ; 550 dz2_o += fVertexZSize*fVertexZSize; 551 // when needed add beam spot width (x-y)?? mha? 552 dz2_o = 1/dz2_o; //Multipling is faster than dividing all the times 553 554 double dt2_o = candidate->ErrorT*1.E9/c_light; // [ps] 555 dt2_o *= dt2_o; 556 dt2_o += fVertexTSize*fVertexTSize; // [ps^2] 557 // Ideally we should also add the induced uncertantiy from dz, z_out, pt, ctgthetaand all the other thing used above (total around 5ps). For the moment we compensae using a high value for vertex time. 558 dt2_o = 1/dt2_o; 559 560 double w; 561 if(fD0CutOff > 0 && candidate->ErrorD0 > 0) 562 { 563 double d0_sig = fabs(candidate->D0/candidate->ErrorD0); 564 w = exp(d0_sig*d0_sig - fD0CutOff*fD0CutOff); 565 w = 1./(1. + w); 566 if (w < 1E-4) discard = 1; 396 567 } 397 568 else 398 569 { 399 tr.pi = 1.; 400 } 401 tr.tt = &(*candidate); 402 tr.Z = 1.; 403 404 // TBC now putting track selection here (> fPTMin) 405 if(tr.pi > 1e-3 && tr.pt > fMinPT) 406 { 407 tks.push_back(tr); 408 } 409 } 410 411 //print out input tracks 412 413 if(fVerbose) 414 { 415 std::cout << " start processing vertices ..." << std::endl; 416 std::cout << " Found " << tks.size() << " input tracks" << std::endl; 417 //loop over input tracks 418 419 for(std::vector<track_t>::const_iterator it = tks.begin(); it != tks.end(); it++) 420 { 421 double z = it->z; 422 double pt = it->pt; 423 double eta = it->eta; 424 double phi = it->phi; 425 double t = it->t; 426 427 std::cout << "pt: " << pt << ", eta: " << eta << ", phi: " << phi << ", z: " << z << ", t: " << t << std::endl; 428 } 429 } 430 431 unsigned int nt = tks.size(); 432 double rho0 = 0.0; // start with no outlier rejection 433 434 if(tks.empty()) return clusters; 435 436 vector<vertex_t> y; // the vertex prototypes 437 438 // initialize:single vertex at infinite temperature 439 vertex_t vstart; 440 vstart.z = 0.; 441 vstart.t = 0.; 442 vstart.pk = 1.; 443 y.push_back(vstart); 444 int niter = 0; // number of iterations 445 446 // estimate first critical temperature 447 double beta = beta0(fBetaMax, tks, y, fCoolingFactor); 448 niter = 0; 449 while((update1(beta, tks, y) > 1.e-6) && (niter++ < fMaxIterations)) 450 { 451 } 452 453 // annealing loop, stop when T<Tmin (i.e. beta>1/Tmin) 454 while(beta < fBetaMax) 455 { 456 457 if(fUseTc) 458 { 459 update1(beta, tks, y); 460 while(merge(y, beta)) 570 w = 1; 571 } 572 candidate->VertexingWeight = w; 573 574 575 if(discard) 576 { 577 candidate->ClusterIndex = -1; 578 candidate->InitialPosition.SetT(1E3*1000000*c_light); 579 candidate->InitialPosition.SetZ(1E8); 580 fTrackOutputArray->Add(candidate); 581 } 582 else 583 { 584 tks.sum_w_o_dt2 += w * dt2_o; 585 tks.sum_w_o_dz2 += w * dz2_o; 586 tks.sum_w += w; 587 tks.addItem(z, t, dz2_o, dt2_o, &(*candidate), w, candidate->PID); //PROVA: rimuovi &(*---) 588 } 589 590 } 591 592 if(fVerbose > 1) 593 { 594 cout << "----->Filled tracks" << endl; 595 cout << "M z dz t dt w" << endl; 596 for(unsigned int i = 0; i < tks.getSize(); i++) 597 { 598 cout << Form("%d\t%1.1e\t%1.1e\t%1.1e\t%1.1e\t%1.1e", tks.PID[i], tks.z[i], 1/sqrt(tks.dz2_o[i]), tks.t[i], 1/sqrt(tks.dt2_o[i]), tks.w[i]) << endl; 599 } 600 } 601 602 return; 603 } 604 605 //------------------------------------------------------------------------------ 606 // Compute higher phase transition temperature 607 double VertexFinderDA4D::beta0(tracks_t & tks, vertex_t &vtx) 608 { 609 if(vtx.getSize() != 1) 610 { 611 throw std::invalid_argument( "Unexpected number of vertices" ); 612 } 613 614 unsigned int nt = tks.getSize(); 615 616 //Set vertex position at T=inf as the weighted average of the tracks 617 double sum_wz = 0, sum_wt = 0; 618 for(unsigned int i = 0; i < nt; i++) 619 { 620 sum_wz += tks.w[i] * tks.z[i] * tks.dz2_o[i]; 621 sum_wt += tks.w[i] * tks.t[i] * tks.dt2_o[i]; 622 } 623 vtx.t[0] = sum_wt / tks.sum_w_o_dt2; 624 vtx.z[0] = sum_wz / tks.sum_w_o_dz2; 625 626 // Compute the posterior distribution covariance matrix elements 627 double s_zz = 0, s_tt = 0, s_tz = 0; 628 for(unsigned int i = 0; i < nt; i++) 629 { 630 double dz = (tks.z[i] - vtx.z[0]) * tks.dz_o[i]; 631 double dt = (tks.t[i] - vtx.t[0]) * tks.dt_o[i]; 632 633 s_zz += tks.w[i] * dz * dz; 634 s_tt += tks.w[i] * dt * dt; 635 s_tz += tks.w[i] * dt * dz; 636 } 637 s_tt /= tks.sum_w; 638 s_zz /= tks.sum_w; 639 s_tz /= tks.sum_w; 640 641 // Copute the max eighenvalue 642 double beta_c = (s_tt - s_zz)*(s_tt - s_zz) + 4*s_tz*s_tz; 643 beta_c = 1. / (s_tt + s_zz + sqrt(beta_c)); 644 645 double out; 646 if (beta_c < fBetaMax) 647 { 648 // Cool down up to a step before the phase transition 649 out = beta_c * sqrt(fCoolingFactor); 650 } 651 else 652 { 653 out = fBetaMax * fCoolingFactor; 654 } 655 656 return out; 657 } 658 659 //------------------------------------------------------------------------------ 660 // Compute the new vertexes position and mass (probability) -- mass constrained annealing without noise 661 // Compute and store the posterior covariance matrix elements 662 // Returns the squared sum of changes of vertexex position normalized by the vertex size declared in the init 663 double VertexFinderDA4D::update(double beta, tracks_t &tks, vertex_t &vtx, double rho0) 664 { 665 unsigned int nt = tks.getSize(); 666 unsigned int nv = vtx.getSize(); 667 668 //initialize sums 669 double Z_init = rho0 * exp(-beta * fMuOutlayer * fMuOutlayer); 670 671 // Compute all the energies (aka distances) and normalization partition function 672 vector<double> pk_exp_mBetaE = Compute_pk_exp_mBetaE(beta, vtx, tks, Z_init); 673 674 double sum_pk = 0; 675 double delta2_max = 0; 676 for (unsigned int k = 0; k < nv; k++) 677 { 678 // Compute the new vertex positions and masses 679 double pk_new = 0; 680 double sw_z = 0, sw_t = 0; 681 // Compute the posterior covariance matrix Elements 682 double szz = 0, stt = 0, stz = 0; 683 double sum_wt = 0, sum_wz = 0; 684 double sum_ptt = 0, sum_pzz = 0, sum_ptz = 0; 685 686 687 for (unsigned int i = 0; i < nt; i++) 688 { 689 unsigned int idx = k*nt + i; 690 691 if(pk_exp_mBetaE[idx] == 0 || tks.Z[i] == 0) 461 692 { 462 update1(beta, tks, y); 463 } 464 split(beta, tks, y); 465 beta = beta / fCoolingFactor; 693 continue; 694 } 695 696 double p_ygx = pk_exp_mBetaE[idx] / tks.Z[i]; //p(y|x), Gibbs distribution 697 if(std::isnan(p_ygx) || std::isinf(p_ygx) || p_ygx > 1) 698 { 699 cout << Form("%1.6e %1.6e", pk_exp_mBetaE[idx], tks.Z[i]); 700 throw std::invalid_argument(Form("p_ygx is %.8f", p_ygx)); 701 } 702 pk_new += tks.w[i] * p_ygx; 703 704 double wt = tks.w[i] * p_ygx * tks.dt2_o[i]; 705 sw_t += wt * tks.t[i]; 706 sum_wt += wt; 707 708 double wz = tks.w[i] * p_ygx * tks.dz2_o[i]; 709 sw_z += wz * tks.z[i]; 710 sum_wz += wz; 711 712 // Add the track contribution to the covariance matrix 713 double p_xgy = p_ygx * tks.w[i] / vtx.pk[k]; 714 double dt = (tks.t[i] - vtx.t[k]) * tks.dt_o[i]; 715 double dz = (tks.z[i] - vtx.z[k]) * tks.dz_o[i]; 716 717 double wtt = p_xgy * tks.dt2_o[i]; 718 double wzz = p_xgy * tks.dz2_o[i]; 719 double wtz = p_xgy * tks.dt_o[i] * tks.dz_o[i]; 720 721 stt += wtt * dt * dt; 722 szz += wzz * dz * dz; 723 stz += wtz * dt * dz; 724 725 sum_ptt += wtt; 726 sum_pzz += wzz; 727 sum_ptz += wtz; 728 } 729 if(pk_new == 0) 730 { 731 vtx.removeItem(k); 732 k--; 733 // throw std::invalid_argument(Form("pk_new is %.8f", pk_new)); 466 734 } 467 735 else 468 736 { 469 beta = beta / fCoolingFactor; 470 splitAll(y); 471 } 472 473 // make sure we are not too far from equilibrium before cooling further 474 niter = 0; 475 while((update1(beta, tks, y) > 1.e-6) && (niter++ < fMaxIterations)) 476 { 477 } 478 } 479 480 if(fUseTc) 481 { 482 // last round of splitting, make sure no critical clusters are left 483 update1(beta, tks, y); 484 while(merge(y, beta)) 485 { 486 update1(beta, tks, y); 487 } 488 unsigned int ntry = 0; 489 while(split(beta, tks, y) && (ntry++ < 10)) 490 { 491 niter = 0; 492 while((update1(beta, tks, y) > 1.e-6) && (niter++ < fMaxIterations)) 737 pk_new /= tks.sum_w; 738 sum_pk += pk_new; 739 740 stt /= sum_ptt; 741 szz /= sum_pzz; 742 stz /= sum_ptz; 743 744 double new_t = sw_t/sum_wt; 745 double new_z = sw_z/sum_wz; 746 if(std::isnan(new_z) || std::isnan(new_t)) 493 747 { 494 } 495 merge(y, beta); 496 update1(beta, tks, y); 497 } 748 cout << endl << endl; 749 cout << Form("t: %.3e / %.3e", sw_t, sum_wt) << endl; 750 cout << Form("z: %.3e / %.3e", sw_z, sum_wz) << endl; 751 cout << "pk " << k << " " << vtx.pk[k] << endl; 752 throw std::invalid_argument("new_z is nan"); 753 } 754 755 double z_displ = (new_z - vtx.z[k])/fVertexZSize; 756 double t_displ = (new_t - vtx.t[k])/fVertexTSize; 757 double delta2 = z_displ*z_displ + t_displ*t_displ; 758 759 if (delta2 > delta2_max) delta2_max = delta2; 760 761 vtx.z[k] = new_z; 762 vtx.t[k] = new_t; 763 vtx.pk[k] = pk_new; 764 vtx.szz[k] = szz; 765 vtx.stt[k] = stt; 766 vtx.stz[k] = stz; 767 } 768 } 769 770 if(fabs((sum_pk - 1.) > 1E-4)) 771 { 772 cout << "sum_pk " << sum_pk << endl; 773 for (unsigned int k = 0; k < nv; k++) 774 { 775 cout << Form("%d: %1.4e", k, vtx.pk[k]) << endl; 776 } 777 throw std::invalid_argument("Sum of masses not unitary"); 778 } 779 // if(fVerbose > 3) 780 // { 781 // cout << "===Update over" << endl; 782 // for (unsigned int k = 0; k < nv; k++) 783 // { 784 // cout << k << endl; 785 // cout << "z: " << vtx.z[k] << " , t: " << vtx.t[k] << " , p: " << vtx.pk[k] << endl; 786 // cout << " | " << vtx.szz[k] << " " << vtx.stz[k] << "|" << endl; 787 // cout << " | " << vtx.stz[k] << " " << vtx.stt[k] << "|" << endl << endl; 788 // } 789 // cout << "=======" << endl; 790 // } 791 792 return delta2_max; 793 } 794 795 //------------------------------------------------------------------------------ 796 // Split critical vertices (beta_c < beta) 797 // Returns true if at least one cluster was split 798 bool VertexFinderDA4D::split(double &beta, vertex_t &vtx, tracks_t & tks) 799 { 800 bool split = false; 801 802 auto pair_bc_k = vtx.ComputeAllBeta_c(fVerbose); 803 804 // If minimum beta_c is higher than beta, no split is necessaire 805 if( pair_bc_k.first > beta ) 806 { 807 split = false; 498 808 } 499 809 else 500 810 { 501 // merge collapsed clusters 502 while(merge(y, beta)) 503 { 504 update1(beta, tks, y); 505 } 506 if(fVerbose) 507 { 508 cout << "dump after 1st merging " << endl; 509 dump(beta, y, tks); 510 } 511 } 512 513 // switch on outlier rejection 514 rho0 = 1. / nt; 515 for(vector<vertex_t>::iterator k = y.begin(); k != y.end(); k++) 516 { 517 k->pk = 1.; 518 } // democratic 519 niter = 0; 520 while((update2(beta, tks, y, rho0, fDzCutOff) > 1.e-8) && (niter++ < fMaxIterations)) 521 { 522 } 523 if(fVerbose) 524 { 525 cout << "rho0=" << rho0 << " niter=" << niter << endl; 526 dump(beta, y, tks); 527 } 528 529 // merge again (some cluster split by outliers collapse here) 530 while(merge(y)) 531 { 532 } 533 if(fVerbose) 534 { 535 cout << "dump after 2nd merging " << endl; 536 dump(beta, y, tks); 537 } 538 539 // continue from freeze-out to Tstop (=1) without splitting, eliminate insignificant vertices 540 while(beta <= fBetaStop) 541 { 542 while(purge(y, tks, rho0, beta, fDzCutOff)) 543 { 544 niter = 0; 545 while((update2(beta, tks, y, rho0, fDzCutOff) > 1.e-6) && (niter++ < fMaxIterations)) 811 const unsigned int nv = vtx.getSize(); 812 for(unsigned int k = 0; k < nv; k++) 813 { 814 if( fVerbose > 3 ) 546 815 { 547 } 548 } 549 beta /= fCoolingFactor; 550 niter = 0; 551 while((update2(beta, tks, y, rho0, fDzCutOff) > 1.e-6) && (niter++ < fMaxIterations)) 552 { 553 } 554 } 555 556 // // new, one last round of cleaning at T=Tstop 557 // while(purge(y,tks,rho0, beta)){ 558 // niter=0; while((update2(beta, tks,y,rho0, fDzCutOff) > 1.e-6) && (niter++ < fMaxIterations)){ } 559 // } 560 561 if(fVerbose) 562 { 563 cout << "Final result, rho0=" << rho0 << endl; 564 dump(beta, y, tks); 565 } 566 567 // select significant tracks and use a TransientVertex as a container 568 //GlobalError dummyError; 569 570 // ensure correct normalization of probabilities, should make double assginment reasonably impossible 571 for(unsigned int i = 0; i < nt; i++) 572 { 573 tks[i].Z = rho0 * exp(-beta * (fDzCutOff * fDzCutOff)); 574 for(vector<vertex_t>::iterator k = y.begin(); k != y.end(); k++) 575 { 576 tks[i].Z += k->pk * exp(-beta * Eik(tks[i], *k)); 577 } 578 } 579 580 for(vector<vertex_t>::iterator k = y.begin(); k != y.end(); k++) 581 { 582 583 DelphesFactory *factory = GetFactory(); 584 candidate = factory->NewCandidate(); 585 586 //cout<<"new vertex"<<endl; 587 //GlobalPoint pos(0, 0, k->z); 588 double time = k->t; 589 double z = k->z; 590 //vector< reco::TransientTrack > vertexTracks; 591 //double max_track_time_err2 = 0; 592 double mean = 0.; 593 double expv_x2 = 0.; 594 double normw = 0.; 595 for(unsigned int i = 0; i < nt; i++) 596 { 597 const double invdt = 1.0 / std::sqrt(tks[i].dt2); 598 if(tks[i].Z > 0) 816 cout << "vtx " << k << " beta_c = " << vtx.beta_c[k] << endl; 817 } 818 if(vtx.beta_c[k] <= beta) 599 819 { 600 double p = k->pk * exp(-beta * Eik(tks[i], *k)) / tks[i].Z; 601 if((tks[i].pi > 0) && (p > 0.5)) 820 double z_old = vtx.z[k]; 821 double t_old = vtx.t[k]; 822 double pk_old = vtx.pk[k]; 823 824 // Compute splitting direction: given by the max eighenvalue eighenvector 825 double zn = (vtx.szz[k] - vtx.stt[k])*(vtx.szz[k] - vtx.stt[k]) + 4*vtx.stz[k]*vtx.stz[k]; 826 zn = vtx.szz[k] - vtx.stt[k] + sqrt(zn); 827 double tn = 2*vtx.stz[k]; 828 double norm = hypot(zn, tn); 829 tn /= norm; 830 zn /= norm; 831 832 // Estimate subcluster positions and weight 833 double p1=0, z1=0, t1=0, wz1=0, wt1=0; 834 double p2=0, z2=0, t2=0, wz2=0, wt2=0; 835 const unsigned int nt = tks.getSize(); 836 for(unsigned int i=0; i<nt; ++i) 602 837 { 603 //std::cout << "pushing back " << i << ' ' << tks[i].tt << std::endl; 604 //vertexTracks.push_back(*(tks[i].tt)); tks[i].Z=0; 605 606 candidate->AddCandidate(tks[i].tt); 607 tks[i].Z = 0; 608 609 mean += tks[i].t * invdt * p; 610 expv_x2 += tks[i].t * tks[i].t * invdt * p; 611 normw += invdt * p; 612 } // setting Z=0 excludes double assignment 613 } 614 } 615 616 mean = mean / normw; 617 expv_x2 = expv_x2 / normw; 618 const double time_var = expv_x2 - mean * mean; 619 const double crappy_error_guess = std::sqrt(time_var); 620 /*GlobalError dummyErrorWithTime(0, 621 0,0, 622 0,0,0, 623 0,0,0,crappy_error_guess);*/ 624 //TransientVertex v(pos, time, dummyErrorWithTime, vertexTracks, 5); 625 626 candidate->ClusterIndex = clusterIndex++; 627 ; 628 candidate->Position.SetXYZT(0.0, 0.0, z * 10.0, time * c_light); 629 630 // TBC - fill error later ... 631 candidate->PositionError.SetXYZT(0.0, 0.0, 0.0, crappy_error_guess * c_light); 632 633 clusterIndex++; 634 clusters.push_back(candidate); 635 } 636 637 return clusters; 638 } 639 640 //------------------------------------------------------------------------------ 641 642 static double Eik(const track_t &t, const vertex_t &k) 643 { 644 return std::pow(t.z - k.z, 2.) / t.dz2 + std::pow(t.t - k.t, 2.) / t.dt2; 645 } 646 647 //------------------------------------------------------------------------------ 648 649 static void dump(const double beta, const vector<vertex_t> &y, const vector<track_t> &tks0) 650 { 651 // copy and sort for nicer printout 652 vector<track_t> tks; 653 for(vector<track_t>::const_iterator t = tks0.begin(); t != tks0.end(); t++) 654 { 655 tks.push_back(*t); 656 } 657 std::stable_sort(tks.begin(), tks.end(), recTrackLessZ1); 658 659 cout << "-----DAClusterizerInZT::dump ----" << endl; 660 cout << " beta=" << beta << endl; 661 cout << " z= "; 662 cout.precision(4); 663 for(vector<vertex_t>::const_iterator k = y.begin(); k != y.end(); k++) 664 { 665 //cout << setw(8) << fixed << k->z; 666 } 667 cout << endl 668 << " t= "; 669 for(vector<vertex_t>::const_iterator k = y.begin(); k != y.end(); k++) 670 { 671 //cout << setw(8) << fixed << k->t; 672 } 673 //cout << endl << "T=" << setw(15) << 1./beta <<" Tc= "; 674 for(vector<vertex_t>::const_iterator k = y.begin(); k != y.end(); k++) 675 { 676 //cout << setw(8) << fixed << k->Tc ; 677 } 678 679 cout << endl 680 << " pk="; 681 double sumpk = 0; 682 for(vector<vertex_t>::const_iterator k = y.begin(); k != y.end(); k++) 683 { 684 //cout << setw(8) << setprecision(3) << fixed << k->pk; 685 sumpk += k->pk; 686 } 687 cout << endl; 688 689 double E = 0, F = 0; 690 cout << endl; 691 cout << "---- z +/- dz t +/- dt ip +/-dip pt phi eta weights ----" << endl; 692 cout.precision(4); 693 for(unsigned int i = 0; i < tks.size(); i++) 694 { 695 if(tks[i].Z > 0) 696 { 697 F -= log(tks[i].Z) / beta; 698 } 699 double tz = tks[i].z; 700 double tt = tks[i].t; 701 //cout << setw (3)<< i << ")" << setw (8) << fixed << setprecision(4)<< tz << " +/-" << setw (6)<< sqrt(tks[i].dz2) 702 // << setw(8) << fixed << setprecision(4) << tt << " +/-" << setw(6) << std::sqrt(tks[i].dt2) ; 703 704 double sump = 0.; 705 for(vector<vertex_t>::const_iterator k = y.begin(); k != y.end(); k++) 706 { 707 if((tks[i].pi > 0) && (tks[i].Z > 0)) 708 { 709 //double p=pik(beta,tks[i],*k); 710 double p = k->pk * std::exp(-beta * Eik(tks[i], *k)) / tks[i].Z; 711 if(p > 0.0001) 838 if (tks.Z[i] > 0) 839 { 840 double lr = (tks.t[i] - vtx.t[k]) * tn + (tks.z[i]-vtx.z[k]) * zn; 841 // winner-takes-all, usually overestimates splitting 842 double tl = lr < 0 ? 1.: 0.; 843 double tr = 1. - tl; 844 845 // soften it, especially at low T 846 // double arg = lr * sqrt(beta * ( zn*zn*tks.dz2_o[i] + tn*tn*tks.dt2_o[i] ) ); 847 // if(abs(arg) < 20) 848 // { 849 // double t = exp(-arg); 850 // tl = t/(t+1.); 851 // tr = 1/(t+1.); 852 // } 853 854 double p = vtx.pk[k] * tks.w[i]; 855 p *= exp(-beta * Energy(tks.z[i], vtx.z[k], tks.dz2_o[i], tks.t[i], vtx.t[k], tks.dt2_o[i])) / tks.Z[i]; 856 double wt = p*tks.dt2_o[i]; 857 double wz = p*tks.dz2_o[i]; 858 p1 += p*tl; z1 += wz*tl*tks.z[i]; t1 += wt*tl*tks.t[i]; wz1 += wz*tl; wt1 += wt*tl; 859 p2 += p*tr; z2 += wz*tr*tks.z[i]; t2 += wt*tr*tks.t[i]; wz2 += wz*tr; wt2 += wt*tr; 860 } 861 } 862 863 if(wz1 > 0 && wt1 > 0 && wz2 > 0 && wt2 > 0) 712 864 { 713 //cout << setw (8) << setprecision(3) << p; 865 t1 /= wt1; 866 z1 /= wz1; 867 t2 /= wt2; 868 z2 /= wz2; 869 870 if( fVerbose > 3 ) 871 { 872 double aux = (z1-z2)*(z1-z2)/(fVertexZSize*fVertexZSize) + (t1-t2)*(t1-t2)/(fVertexTSize*fVertexTSize); 873 cout << "weighted split: delta = " << sqrt(aux) << endl; 874 } 714 875 } 715 876 else 716 877 { 717 cout << " . "; 878 continue; 879 // plot_split_crush(zn, tn, vtx, tks, k); 880 // throw std::invalid_argument( "0 division" ); 718 881 } 719 E += p * Eik(tks[i], *k); 720 sump += p; 721 } 722 else 882 883 while(vtx.NearestCluster(t1, z1) != k || vtx.NearestCluster(t2, z2) != k) 884 { 885 t1 = 0.5 * (t1 + t_old); 886 z1 = 0.5 * (z1 + z_old); 887 t2 = 0.5 * (t2 + t_old); 888 z2 = 0.5 * (z2 + z_old); 889 } 890 891 // Compute final distance and split if the distance is enough 892 double delta2 = (z1-z2)*(z1-z2)/(fVertexZSize*fVertexZSize) + (t1-t2)*(t1-t2)/(fVertexTSize*fVertexTSize); 893 if(delta2 > fD2Merge) 894 { 895 split = true; 896 vtx.t[k] = t1; 897 vtx.z[k] = z1; 898 vtx.pk[k] = p1 * pk_old/(p1+p2); 899 900 double new_t = t2; 901 double new_z = z2; 902 double new_pk = p2 * pk_old/(p1+p2); 903 904 vtx.addItem(new_z, new_t, new_pk); 905 906 if( fVerbose > 3 ) 907 { 908 cout << "===Split happened on vtx " << k << endl; 909 cout << "OLD z: " << z_old << " , t: " << t_old << " , pk: " << pk_old << endl; 910 cout << "NEW+ z: " << vtx.z[k] << " , t: " << vtx.t[k] << " , pk: " << vtx.pk[k] << endl; 911 cout << "NEW- z: " << new_z << " , t: " << new_t << " , pk: " << new_pk << endl; 912 } 913 } 914 } 915 } 916 } 917 return split; 918 } 919 920 921 //------------------------------------------------------------------------------ 922 // Merge vertexes closer than declared dimensions 923 bool VertexFinderDA4D::merge(vertex_t & vtx, double d2_merge = 2) 924 { 925 bool merged = false; 926 927 if(vtx.getSize() < 2) return merged; 928 929 bool last_merge = false; 930 do { 931 double min_d2 = d2_merge; 932 unsigned int k1_min, k2_min; 933 for(unsigned int k1 = 0; k1 < vtx.getSize(); k1++) 934 { 935 for(unsigned int k2 = k1+1; k2 < vtx.getSize();k2++) 723 936 { 724 cout << " "; 725 } 726 } 727 cout << endl; 728 } 729 cout << endl 730 << "T=" << 1 / beta << " E=" << E << " n=" << y.size() << " F= " << F << endl 731 << "----------" << endl; 937 double d2_tmp = vtx.DistanceSquare(k1, k2); 938 if(d2_tmp < min_d2) 939 { 940 min_d2 = d2_tmp; 941 k1_min = k1; 942 k2_min = k2; 943 } 944 } 945 } 946 947 if(min_d2 < d2_merge) 948 { 949 vtx.mergeItems(k1_min, k2_min); 950 last_merge = true; 951 merged = true; 952 } 953 else last_merge = false; 954 } while(last_merge); 955 956 return merged; 957 } 958 959 // ----------------------------------------------------------------------------- 960 // Compute all the energies and set the partition function normalization for each track 961 vector<double> VertexFinderDA4D::Compute_pk_exp_mBetaE(double beta, vertex_t &vtx, tracks_t &tks, double Z_init) 962 { 963 unsigned int nt = tks.getSize(); 964 unsigned int nv = vtx.getSize(); 965 966 vector<double> pk_exp_mBetaE(nt * nv); 967 for (unsigned int k = 0; k < nv; k++) 968 { 969 for (unsigned int i = 0; i < nt; i++) 970 { 971 if(k == 0) tks.Z[i] = Z_init; 972 973 double aux = Energy(tks.z[i], vtx.z[k], tks.dz2_o[i], tks.t[i], vtx.t[k], tks.dt2_o[i]); 974 aux = vtx.pk[k] * exp(-beta * aux); 975 // if(aux < 1E-10) continue; 976 tks.Z[i] += aux; 977 978 unsigned int idx = k*nt + i; 979 pk_exp_mBetaE[idx] = aux; 980 } 981 } 982 return pk_exp_mBetaE; 732 983 } 733 984 734 985 //------------------------------------------------------------------------------ 735 736 static double update1(double beta, vector<track_t> &tks, vector<vertex_t> &y) 737 { 738 //update weights and vertex positions 739 // mass constrained annealing without noise 740 // returns the squared sum of changes of vertex positions 741 742 unsigned int nt = tks.size(); 743 744 //initialize sums 745 double sumpi = 0; 746 for(vector<vertex_t>::iterator k = y.begin(); k != y.end(); ++k) 747 { 748 k->sw = 0.; 749 k->swz = 0.; 750 k->swt = 0.; 751 k->se = 0.; 752 k->swE = 0.; 753 k->Tc = 0.; 754 } 755 756 // loop over tracks 757 for(unsigned int i = 0; i < nt; i++) 758 { 759 760 // update pik and Zi 761 double Zi = 0.; 762 for(vector<vertex_t>::iterator k = y.begin(); k != y.end(); ++k) 763 { 764 k->ei = std::exp(-beta * Eik(tks[i], *k)); // cache exponential for one track at a time 765 Zi += k->pk * k->ei; 766 } 767 tks[i].Z = Zi; 768 769 // normalization for pk 770 if(tks[i].Z > 0) 771 { 772 sumpi += tks[i].pi; 773 // accumulate weighted z and weights for vertex update 774 for(vector<vertex_t>::iterator k = y.begin(); k != y.end(); ++k) 986 // Eliminate clusters with only one significant/unique track 987 bool VertexFinderDA4D::purge(vertex_t & vtx, tracks_t & tks, double & rho0, const double beta, double min_prob, double min_trk) 988 { 989 const unsigned int nv = vtx.getSize(); 990 const unsigned int nt = tks.getSize(); 991 992 if (nv < 2) 993 return false; 994 995 double sumpmin = nt; 996 unsigned int k0 = nv; 997 998 int nUnique = 0; 999 double sump = 0; 1000 1001 double Z_init = rho0 * exp(-beta * fMuOutlayer * fMuOutlayer); // Add fDtCutOff here toghether with this 1002 vector<double> pk_exp_mBetaE = Compute_pk_exp_mBetaE(beta, vtx, tks, Z_init); 1003 1004 for (unsigned int k = 0; k < nv; ++k) { 1005 1006 nUnique = 0; 1007 sump = 0; 1008 1009 double pmax = vtx.pk[k] / (vtx.pk[k] + rho0 * exp(-beta * fMuOutlayer* fMuOutlayer)); 1010 double pcut = min_prob * pmax; 1011 1012 for (unsigned int i = 0; i < nt; ++i) { 1013 unsigned int idx = k*nt + i; 1014 1015 if(pk_exp_mBetaE[idx] == 0 || tks.Z[i] == 0) 775 1016 { 776 k->se += tks[i].pi * k->ei / Zi; 777 const double w = k->pk * tks[i].pi * k->ei / (Zi * (tks[i].dz2 * tks[i].dt2)); 778 k->sw += w; 779 k->swz += w * tks[i].z; 780 k->swt += w * tks[i].t; 781 k->swE += w * Eik(tks[i], *k); 782 } 783 } 784 else 785 { 786 sumpi += tks[i].pi; 787 } 788 789 } // end of track loop 790 791 // now update z and pk 792 double delta = 0; 793 for(vector<vertex_t>::iterator k = y.begin(); k != y.end(); k++) 794 { 795 if(k->sw > 0) 796 { 797 const double znew = k->swz / k->sw; 798 const double tnew = k->swt / k->sw; 799 delta += std::pow(k->z - znew, 2.) + std::pow(k->t - tnew, 2.); 800 k->z = znew; 801 k->t = tnew; 802 k->Tc = 2. * k->swE / k->sw; 803 } 804 else 805 { 806 // cout << " a cluster melted away ? pk=" << k->pk << " sumw=" << k->sw << endl 807 k->Tc = -1; 808 } 809 810 k->pk = k->pk * k->se / sumpi; 811 } 812 813 // return how much the prototypes moved 814 return delta; 815 } 816 817 //------------------------------------------------------------------------------ 818 819 static double update2(double beta, vector<track_t> &tks, vector<vertex_t> &y, double &rho0, double dzCutOff) 820 { 821 // MVF style, no more vertex weights, update tracks weights and vertex positions, with noise 822 // returns the squared sum of changes of vertex positions 823 824 unsigned int nt = tks.size(); 825 826 //initialize sums 827 for(vector<vertex_t>::iterator k = y.begin(); k != y.end(); k++) 828 { 829 k->sw = 0.; 830 k->swz = 0.; 831 k->swt = 0.; 832 k->se = 0.; 833 k->swE = 0.; 834 k->Tc = 0.; 835 } 836 837 // loop over tracks 838 for(unsigned int i = 0; i < nt; i++) 839 { 840 841 // update pik and Zi and Ti 842 double Zi = rho0 * std::exp(-beta * (dzCutOff * dzCutOff)); // cut-off (eventually add finite size in time) 843 //double Ti = 0.; // dt0*std::exp(-beta*fDtCutOff); 844 for(vector<vertex_t>::iterator k = y.begin(); k != y.end(); k++) 845 { 846 k->ei = std::exp(-beta * Eik(tks[i], *k)); // cache exponential for one track at a time 847 Zi += k->pk * k->ei; 848 } 849 tks[i].Z = Zi; 850 851 // normalization 852 if(tks[i].Z > 0) 853 { 854 // accumulate weighted z and weights for vertex update 855 for(vector<vertex_t>::iterator k = y.begin(); k != y.end(); k++) 856 { 857 k->se += tks[i].pi * k->ei / Zi; 858 double w = k->pk * tks[i].pi * k->ei / (Zi * (tks[i].dz2 * tks[i].dt2)); 859 k->sw += w; 860 k->swz += w * tks[i].z; 861 k->swt += w * tks[i].t; 862 k->swE += w * Eik(tks[i], *k); 863 } 864 } 865 866 } // end of track loop 867 868 // now update z 869 double delta = 0; 870 for(vector<vertex_t>::iterator k = y.begin(); k != y.end(); k++) 871 { 872 if(k->sw > 0) 873 { 874 const double znew = k->swz / k->sw; 875 const double tnew = k->swt / k->sw; 876 delta += std::pow(k->z - znew, 2.) + std::pow(k->t - tnew, 2.); 877 k->z = znew; 878 k->t = tnew; 879 k->Tc = 2 * k->swE / k->sw; 880 } 881 else 882 { 883 // cout << " a cluster melted away ? pk=" << k->pk << " sumw=" << k->sw << endl; 884 k->Tc = 0; 885 } 886 } 887 888 // return how much the prototypes moved 889 return delta; 890 } 891 892 //------------------------------------------------------------------------------ 893 894 static bool merge(vector<vertex_t> &y) 895 { 896 // merge clusters that collapsed or never separated, return true if vertices were merged, false otherwise 897 898 if(y.size() < 2) return false; 899 900 for(vector<vertex_t>::iterator k = y.begin(); (k + 1) != y.end(); k++) 901 { 902 if(std::abs((k + 1)->z - k->z) < 1.e-3 && std::abs((k + 1)->t - k->t) < 1.e-3) 903 { // with fabs if only called after freeze-out (splitAll() at highter T) 904 double rho = k->pk + (k + 1)->pk; 905 if(rho > 0) 906 { 907 k->z = (k->pk * k->z + (k + 1)->z * (k + 1)->pk) / rho; 908 k->t = (k->pk * k->t + (k + 1)->t * (k + 1)->pk) / rho; 909 } 910 else 911 { 912 k->z = 0.5 * (k->z + (k + 1)->z); 913 k->t = 0.5 * (k->t + (k + 1)->t); 914 } 915 k->pk = rho; 916 917 y.erase(k + 1); 918 return true; 919 } 920 } 921 922 return false; 923 } 924 925 //------------------------------------------------------------------------------ 926 927 static bool merge(vector<vertex_t> &y, double &beta) 928 { 929 // merge clusters that collapsed or never separated, 930 // only merge if the estimated critical temperature of the merged vertex is below the current temperature 931 // return true if vertices were merged, false otherwise 932 if(y.size() < 2) return false; 933 934 for(vector<vertex_t>::iterator k = y.begin(); (k + 1) != y.end(); k++) 935 { 936 if(std::abs((k + 1)->z - k->z) < 2.e-3 && std::abs((k + 1)->t - k->t) < 2.e-3) 937 { 938 double rho = k->pk + (k + 1)->pk; 939 double swE = k->swE + (k + 1)->swE - k->pk * (k + 1)->pk / rho * (std::pow((k + 1)->z - k->z, 2.) + std::pow((k + 1)->t - k->t, 2.)); 940 double Tc = 2 * swE / (k->sw + (k + 1)->sw); 941 942 if(Tc * beta < 1) 943 { 944 if(rho > 0) 945 { 946 k->z = (k->pk * k->z + (k + 1)->z * (k + 1)->pk) / rho; 947 k->t = (k->pk * k->t + (k + 1)->t * (k + 1)->pk) / rho; 948 } 949 else 950 { 951 k->z = 0.5 * (k->z + (k + 1)->z); 952 k->t = 0.5 * (k->t + (k + 1)->t); 953 } 954 k->pk = rho; 955 k->sw += (k + 1)->sw; 956 k->swE = swE; 957 k->Tc = Tc; 958 y.erase(k + 1); 959 return true; 960 } 961 } 962 } 963 964 return false; 965 } 966 967 //------------------------------------------------------------------------------ 968 969 static bool purge(vector<vertex_t> &y, vector<track_t> &tks, double &rho0, const double beta, const double dzCutOff) 970 { 971 // eliminate clusters with only one significant/unique track 972 if(y.size() < 2) return false; 973 974 unsigned int nt = tks.size(); 975 double sumpmin = nt; 976 vector<vertex_t>::iterator k0 = y.end(); 977 for(vector<vertex_t>::iterator k = y.begin(); k != y.end(); k++) 978 { 979 int nUnique = 0; 980 double sump = 0; 981 double pmax = k->pk / (k->pk + rho0 * exp(-beta * dzCutOff * dzCutOff)); 982 for(unsigned int i = 0; i < nt; i++) 983 { 984 if(tks[i].Z > 0) 985 { 986 double p = k->pk * std::exp(-beta * Eik(tks[i], *k)) / tks[i].Z; 987 sump += p; 988 if((p > 0.9 * pmax) && (tks[i].pi > 0)) 989 { 990 nUnique++; 991 } 992 } 993 } 994 995 if((nUnique < 2) && (sump < sumpmin)) 996 { 1017 continue; 1018 } 1019 1020 double p = pk_exp_mBetaE[idx] / tks.Z[i]; 1021 sump += p; 1022 if( ( p > pcut ) & ( tks.w[i] > 0 ) ) nUnique++; 1023 } 1024 1025 if ((nUnique < min_trk) && (sump < sumpmin)) { 997 1026 sumpmin = sump; 998 1027 k0 = k; 999 1028 } 1000 } 1001 1002 if(k0 != y.end()) 1003 { 1004 //cout << "eliminating prototype at " << k0->z << "," << k0->t << " with sump=" << sumpmin << endl; 1005 //rho0+=k0->pk; 1006 y.erase(k0); 1029 1030 } 1031 1032 if (k0 != nv) { 1033 if (fVerbose > 5) { 1034 std::cout << Form("eliminating prototype at z = %.3f mm, t = %.0f ps", vtx.z[k0], vtx.t[k0]) << " with sump=" << sumpmin 1035 << " rho*nt =" << vtx.pk[k0]*nt 1036 << endl; 1037 } 1038 vtx.removeItem(k0); 1007 1039 return true; 1008 } 1009 else 1010 { 1040 } else { 1011 1041 return false; 1012 1042 } 1013 1043 } 1014 1044 1015 //------------------------------------------------------------------------------ 1016 1017 static double beta0(double betamax, vector<track_t> &tks, vector<vertex_t> &y, const double coolingFactor) 1018 { 1019 1020 double T0 = 0; // max Tc for beta=0 1021 // estimate critical temperature from beta=0 (T=inf) 1022 unsigned int nt = tks.size(); 1023 1024 for(vector<vertex_t>::iterator k = y.begin(); k != y.end(); k++) 1025 { 1026 1027 // vertex fit at T=inf 1028 double sumwz = 0.; 1029 double sumwt = 0.; 1030 double sumw = 0.; 1031 for(unsigned int i = 0; i < nt; i++) 1032 { 1033 double w = tks[i].pi / (tks[i].dz2 * tks[i].dt2); 1034 sumwz += w * tks[i].z; 1035 sumwt += w * tks[i].t; 1036 sumw += w; 1037 } 1038 k->z = sumwz / sumw; 1039 k->t = sumwt / sumw; 1040 1041 // estimate Tcrit, eventually do this in the same loop 1042 double a = 0, b = 0; 1043 for(unsigned int i = 0; i < nt; i++) 1044 { 1045 double dx = tks[i].z - (k->z); 1046 double dt = tks[i].t - (k->t); 1047 double w = tks[i].pi / (tks[i].dz2 * tks[i].dt2); 1048 a += w * (std::pow(dx, 2.) / tks[i].dz2 + std::pow(dt, 2.) / tks[i].dt2); 1049 b += w; 1050 } 1051 double Tc = 2. * a / b; // the critical temperature of this vertex 1052 if(Tc > T0) T0 = Tc; 1053 } // vertex loop (normally there should be only one vertex at beta=0) 1054 1055 if(T0 > 1. / betamax) 1056 { 1057 return betamax / pow(coolingFactor, int(std::log(T0 * betamax) / std::log(coolingFactor)) - 1); 1058 } 1059 else 1060 { 1061 // ensure at least one annealing step 1062 return betamax / coolingFactor; 1063 } 1064 } 1065 1066 //------------------------------------------------------------------------------ 1067 1068 static bool split(double beta, vector<track_t> &tks, vector<vertex_t> &y) 1069 { 1070 // split only critical vertices (Tc >~ T=1/beta <==> beta*Tc>~1) 1071 // an update must have been made just before doing this (same beta, no merging) 1072 // returns true if at least one cluster was split 1073 1074 const double epsilon = 1e-3; // split all single vertices by 10 um 1075 bool split = false; 1076 1077 // avoid left-right biases by splitting highest Tc first 1078 1079 std::vector<std::pair<double, unsigned int> > critical; 1080 for(unsigned int ik = 0; ik < y.size(); ik++) 1081 { 1082 if(beta * y[ik].Tc > 1.) 1083 { 1084 critical.push_back(make_pair(y[ik].Tc, ik)); 1085 } 1086 } 1087 std::stable_sort(critical.begin(), critical.end(), std::greater<std::pair<double, unsigned int> >()); 1088 1089 for(unsigned int ic = 0; ic < critical.size(); ic++) 1090 { 1091 unsigned int ik = critical[ic].second; 1092 // estimate subcluster positions and weight 1093 double p1 = 0, z1 = 0, t1 = 0, w1 = 0; 1094 double p2 = 0, z2 = 0, t2 = 0, w2 = 0; 1095 //double sumpi=0; 1096 for(unsigned int i = 0; i < tks.size(); i++) 1097 { 1098 if(tks[i].Z > 0) 1099 { 1100 //sumpi+=tks[i].pi; 1101 double p = y[ik].pk * exp(-beta * Eik(tks[i], y[ik])) / tks[i].Z * tks[i].pi; 1102 double w = p / (tks[i].dz2 * tks[i].dt2); 1103 if(tks[i].z < y[ik].z) 1104 { 1105 p1 += p; 1106 z1 += w * tks[i].z; 1107 t1 += w * tks[i].t; 1108 w1 += w; 1109 } 1110 else 1111 { 1112 p2 += p; 1113 z2 += w * tks[i].z; 1114 t2 += w * tks[i].t; 1115 w2 += w; 1116 } 1117 } 1118 } 1119 if(w1 > 0) 1120 { 1121 z1 = z1 / w1; 1122 t1 = t1 / w1; 1045 1046 // ----------------------------------------------------------------------------- 1047 // Plot status 1048 void VertexFinderDA4D::plot_status(double beta, vertex_t &vtx, tracks_t &tks, int n_it, const char* flag) 1049 { 1050 vector<int> vtx_color = {2,4,8,1,5,6,9,14,46,3}; 1051 while(vtx.getSize() > vtx_color.size()) vtx_color.push_back(40); 1052 1053 vector<double> t_PV, dt_PV, z_PV, dz_PV; 1054 vector<double> t_PU, dt_PU, z_PU, dz_PU; 1055 1056 double ETot = 0; 1057 vector<double> pk_exp_mBetaE = Compute_pk_exp_mBetaE(beta, vtx, tks, 0); 1058 1059 for(unsigned int i = 0; i < tks.getSize(); i++) 1060 { 1061 for(unsigned int k = 0; k < vtx.getSize(); k++) 1062 { 1063 unsigned int idx = k*tks.getSize() + i; 1064 if(pk_exp_mBetaE[idx] == 0) continue; 1065 1066 double p_ygx = pk_exp_mBetaE[idx] / tks.Z[i]; 1067 1068 ETot += tks.w[i] * p_ygx * Energy(tks.z[i], vtx.z[k], tks.dz2_o[i], tks.t[i], vtx.t[k], tks.dt2_o[i]); 1069 } 1070 1071 if(tks.tt[i]->IsPU) 1072 { 1073 t_PU.push_back(tks.t[i]); 1074 dt_PU.push_back(1./tks.dt_o[i]); 1075 z_PU.push_back(tks.z[i]); 1076 dz_PU.push_back(1./tks.dz_o[i]); 1123 1077 } 1124 1078 else 1125 1079 { 1126 z1 = y[ik].z - epsilon; 1127 t1 = y[ik].t - epsilon; 1128 } 1129 if(w2 > 0) 1130 { 1131 z2 = z2 / w2; 1132 t2 = t2 / w2; 1133 } 1134 else 1135 { 1136 z2 = y[ik].z + epsilon; 1137 t2 = y[ik].t + epsilon; 1138 } 1139 1140 // reduce split size if there is not enough room 1141 if((ik > 0) && (y[ik - 1].z >= z1)) 1142 { 1143 z1 = 0.5 * (y[ik].z + y[ik - 1].z); 1144 t1 = 0.5 * (y[ik].t + y[ik - 1].t); 1145 } 1146 if((ik + 1 < y.size()) && (y[ik + 1].z <= z2)) 1147 { 1148 z2 = 0.5 * (y[ik].z + y[ik + 1].z); 1149 t2 = 0.5 * (y[ik].t + y[ik + 1].t); 1150 } 1151 1152 // split if the new subclusters are significantly separated 1153 if((z2 - z1) > epsilon || std::abs(t2 - t1) > epsilon) 1154 { 1155 split = true; 1156 vertex_t vnew; 1157 vnew.pk = p1 * y[ik].pk / (p1 + p2); 1158 y[ik].pk = p2 * y[ik].pk / (p1 + p2); 1159 vnew.z = z1; 1160 vnew.t = t1; 1161 y[ik].z = z2; 1162 y[ik].t = t2; 1163 y.insert(y.begin() + ik, vnew); 1164 1165 // adjust remaining pointers 1166 for(unsigned int jc = ic; jc < critical.size(); jc++) 1167 { 1168 if(critical[jc].second > ik) 1169 { 1170 critical[jc].second++; 1171 } 1172 } 1173 } 1174 } 1175 1176 // stable_sort(y.begin(), y.end(), clusterLessZ); 1177 return split; 1178 } 1179 1180 //------------------------------------------------------------------------------ 1181 1182 void splitAll(vector<vertex_t> &y) 1183 { 1184 1185 const double epsilon = 1e-3; // split all single vertices by 10 um 1186 const double zsep = 2 * epsilon; // split vertices that are isolated by at least zsep (vertices that haven't collapsed) 1187 const double tsep = 2 * epsilon; // check t as well 1188 1189 vector<vertex_t> y1; 1190 1191 for(vector<vertex_t>::iterator k = y.begin(); k != y.end(); k++) 1192 { 1193 if(((k == y.begin()) || (k - 1)->z < k->z - zsep) && (((k + 1) == y.end()) || (k + 1)->z > k->z + zsep)) 1194 { 1195 // isolated prototype, split 1196 vertex_t vnew; 1197 vnew.z = k->z - epsilon; 1198 vnew.t = k->t - epsilon; 1199 (*k).z = k->z + epsilon; 1200 (*k).t = k->t + epsilon; 1201 vnew.pk = 0.5 * (*k).pk; 1202 (*k).pk = 0.5 * (*k).pk; 1203 y1.push_back(vnew); 1204 y1.push_back(*k); 1205 } 1206 else if(y1.empty() || (y1.back().z < k->z - zsep) || (y1.back().t < k->t - tsep)) 1207 { 1208 y1.push_back(*k); 1209 } 1210 else 1211 { 1212 y1.back().z -= epsilon; 1213 y1.back().t -= epsilon; 1214 k->z += epsilon; 1215 k->t += epsilon; 1216 y1.push_back(*k); 1217 } 1218 } // vertex loop 1219 1220 y = y1; 1221 } 1080 t_PV.push_back(tks.t[i]); 1081 dt_PV.push_back(1./tks.dt_o[i]); 1082 z_PV.push_back(tks.z[i]); 1083 dz_PV.push_back(1./tks.dz_o[i]); 1084 } 1085 } 1086 1087 1088 ETot /= tks.sum_w; 1089 fEnergy_rec.push_back(ETot); 1090 fBeta_rec.push_back(beta); 1091 fNvtx_rec.push_back(vtx.getSize()); 1092 1093 double t_min = TMath::Min( TMath::MinElement(t_PV.size(), &t_PV[0]), TMath::MinElement(t_PU.size(), &t_PU[0]) ); 1094 t_min = TMath::Min(t_min, TMath::MinElement(vtx.getSize(), &(vtx.t[0])) ) - fVertexTSize; 1095 double t_max = TMath::Max( TMath::MaxElement(t_PV.size(), &t_PV[0]), TMath::MaxElement(t_PU.size(), &t_PU[0]) ); 1096 t_max = TMath::Max(t_max, TMath::MaxElement(vtx.getSize(), &(vtx.t[0])) ) + fVertexTSize; 1097 1098 double z_min = TMath::Min( TMath::MinElement(z_PV.size(), &z_PV[0]), TMath::MinElement(z_PU.size(), &z_PU[0]) ); 1099 z_min = TMath::Min(z_min, TMath::MinElement(vtx.getSize(), &(vtx.z[0])) ) - 5; 1100 double z_max = TMath::Max( TMath::MaxElement(z_PV.size(), &z_PV[0]), TMath::MaxElement(z_PU.size(), &z_PU[0]) ); 1101 z_max = TMath::Max(z_max, TMath::MaxElement(vtx.getSize(), &(vtx.z[0])) ) + 5; 1102 1103 auto c_2Dspace = new TCanvas("c_2Dspace", "c_2Dspace", 800, 600); 1104 1105 TGraphErrors* gr_PVtks = new TGraphErrors(t_PV.size(), &t_PV[0], &z_PV[0], &dt_PV[0], &dz_PV[0]); 1106 gr_PVtks->SetTitle(Form("Clustering space - #beta = %.6f", beta)); 1107 gr_PVtks->GetXaxis()->SetTitle("t CA [ps]"); 1108 gr_PVtks->GetXaxis()->SetLimits(t_min, t_max); 1109 gr_PVtks->GetYaxis()->SetTitle("z CA [mm]"); 1110 gr_PVtks->GetYaxis()->SetRangeUser(z_min, z_max); 1111 gr_PVtks->SetMarkerStyle(4); 1112 gr_PVtks->SetMarkerColor(8); 1113 gr_PVtks->SetLineColor(8); 1114 gr_PVtks->Draw("APE1"); 1115 1116 TGraphErrors* gr_PUtks = new TGraphErrors(t_PU.size(), &t_PU[0], &z_PU[0], &dt_PU[0], &dz_PU[0]); 1117 gr_PUtks->SetMarkerStyle(3); 1118 gr_PUtks->Draw("PE1"); 1119 1120 TGraph* gr_vtx = new TGraph(vtx.getSize(), &(vtx.t[0]), &(vtx.z[0])); 1121 gr_vtx->SetMarkerStyle(28); 1122 gr_vtx->SetMarkerColor(2); 1123 gr_vtx->SetMarkerSize(2.); 1124 gr_vtx->Draw("PE1"); 1125 1126 fItInputGenVtx->Reset(); 1127 TGraph* gr_genvtx = new TGraph(fInputGenVtx->GetEntriesFast()); 1128 Candidate *candidate; 1129 unsigned int k = 0; 1130 while((candidate = static_cast<Candidate*>(fItInputGenVtx->Next()))) 1131 { 1132 gr_genvtx->SetPoint(k, candidate->Position.T()*1E9/c_light, candidate->Position.Z()); 1133 k++; 1134 } 1135 gr_genvtx->SetMarkerStyle(33); 1136 gr_genvtx->SetMarkerColor(6); 1137 gr_genvtx->SetMarkerSize(2.); 1138 gr_genvtx->Draw("PE1"); 1139 1140 // auto leg = new TLegend(0.1, 0.1); 1141 // leg->AddEntry(gr_PVtks, "PV tks", "ep"); 1142 // leg->AddEntry(gr_PUtks, "PU tks", "ep"); 1143 // leg->AddEntry(gr_vtx, "Cluster center", "p"); 1144 // leg->Draw(); 1145 1146 c_2Dspace->SetGrid(); 1147 c_2Dspace->SaveAs(fFigFolderPath + Form("/c_2Dspace_beta%010.0f-%s%d.png", 1E7*beta, flag, n_it)); 1148 1149 delete c_2Dspace; 1150 } 1151 1152 // ----------------------------------------------------------------------------- 1153 // Plot status at the end 1154 void VertexFinderDA4D::plot_status_end(vertex_t &vtx, tracks_t &tks) 1155 { 1156 unsigned int nv = vtx.getSize(); 1157 1158 // Define colors in a meaningfull way 1159 vector<int> MyPalette(nv); 1160 1161 const int Number = 3; 1162 double Red[Number] = { 1.00, 0.00, 0.00}; 1163 double Green[Number] = { 0.00, 1.00, 0.00}; 1164 double Blue[Number] = { 1.00, 0.00, 1.00}; 1165 double Length[Number] = { 0.00, 0.50, 1.00 }; 1166 int FI = TColor::CreateGradientColorTable(Number,Length,Red,Green,Blue,nv); 1167 for (unsigned int i=0;i<nv;i++) MyPalette[i] = FI+i; 1168 1169 TCanvas * c_out = new TCanvas("c_out", "c_out", 800, 600); 1170 double t_min = TMath::Min( TMath::MinElement(tks.getSize(), &tks.t[0]), TMath::MinElement(vtx.getSize(), &(vtx.t[0])) ) - 2*fVertexTSize; 1171 double t_max = TMath::Max(TMath::MaxElement(tks.getSize(), &tks.t[0]), TMath::MaxElement(vtx.getSize(), &(vtx.t[0])) ) + 2*fVertexTSize; 1172 1173 double z_min = TMath::Min( TMath::MinElement(tks.getSize(), &tks.z[0]), TMath::MinElement(vtx.getSize(), &(vtx.z[0])) ) - 15; 1174 double z_max = TMath::Max( TMath::MaxElement(tks.getSize(), &tks.z[0]), TMath::MaxElement(vtx.getSize(), &(vtx.z[0])) ) + 15; 1175 1176 // Draw tracks 1177 for(unsigned int i = 0; i < tks.getSize(); i++) 1178 { 1179 double dt[] = {1./tks.dt_o[i]}; 1180 double dz[] = {1./tks.dz_o[i]}; 1181 TGraphErrors* gr = new TGraphErrors(1, &(tks.t[i]), &(tks.z[i]), dt, dz); 1182 1183 gr->SetNameTitle(Form("gr%d",i), Form("gr%d",i)); 1184 1185 int marker = tks.tt[i]->IsPU? 1 : 4; 1186 gr->SetMarkerStyle(marker); 1187 1188 int idx = tks.tt[i]->ClusterIndex; 1189 int color = idx>=0 ? MyPalette[idx] : 13; 1190 gr->SetMarkerColor(color); 1191 gr->SetLineColor(color); 1192 1193 int line_style = idx>=0 ? 1 : 3; 1194 gr->SetLineStyle(line_style); 1195 1196 if(i==0) 1197 { 1198 gr->SetTitle(Form("Clustering space - Tot Vertexes = %d", nv)); 1199 gr->GetXaxis()->SetTitle("t CA [ps]"); 1200 gr->GetXaxis()->SetLimits(t_min, t_max); 1201 gr->GetYaxis()->SetTitle("z CA [mm]"); 1202 gr->GetYaxis()->SetRangeUser(z_min, z_max); 1203 gr->Draw("APE1"); 1204 } 1205 else gr->Draw("PE1"); 1206 } 1207 1208 // Draw vertices 1209 for(unsigned int k = 0; k < vtx.getSize(); k++) 1210 { 1211 TGraph* gr = new TGraph(1, &(vtx.t[k]), &(vtx.z[k])); 1212 1213 gr->SetNameTitle(Form("grv%d",k), Form("grv%d",k)); 1214 1215 gr->SetMarkerStyle(41); 1216 gr->SetMarkerSize(2.); 1217 gr->SetMarkerColor(MyPalette[k]); 1218 1219 gr->Draw("P"); 1220 } 1221 1222 fItInputGenVtx->Reset(); 1223 TGraph* gr_genvtx = new TGraph(fInputGenVtx->GetEntriesFast()); 1224 TGraph* gr_genPV = new TGraph(1); 1225 Candidate *candidate; 1226 unsigned int k = 0; 1227 while((candidate = static_cast<Candidate*>(fItInputGenVtx->Next()))) 1228 { 1229 if(k == 0 ) { 1230 gr_genPV->SetPoint(k, candidate->Position.T()*1E9/c_light, candidate->Position.Z()); 1231 } 1232 else gr_genvtx->SetPoint(k, candidate->Position.T()*1E9/c_light, candidate->Position.Z()); 1233 1234 k++; 1235 } 1236 gr_genvtx->SetMarkerStyle(20); 1237 gr_genvtx->SetMarkerColorAlpha(kBlack, 0.8); 1238 gr_genvtx->SetMarkerSize(.8); 1239 gr_genvtx->Draw("PE1"); 1240 gr_genPV->SetMarkerStyle(33); 1241 gr_genPV->SetMarkerColorAlpha(kBlack, 1); 1242 gr_genPV->SetMarkerSize(2.5); 1243 gr_genPV->Draw("PE1"); 1244 1245 // auto note = new TLatex(); 1246 // note->DrawLatexNDC(0.5, 0.8, Form("#splitline{Vertexes Reco = %d }{Vertexes gen = %d}", vtx.getSize(), k) ); 1247 1248 c_out->SetGrid(); 1249 c_out->SaveAs(fFigFolderPath + Form("/c_final.root")); 1250 delete c_out; 1251 } 1252 1253 // ----------------------------------------------------------------------------- 1254 // Plot splitting 1255 void VertexFinderDA4D::plot_split_crush(double zn, double tn, vertex_t &vtx, tracks_t &tks, int i_vtx) 1256 { 1257 vector<double> t, dt, z, dz; 1258 1259 for(unsigned int i = 0; i < tks.getSize(); i++) 1260 { 1261 t.push_back(tks.t[i]); 1262 dt.push_back(1./tks.dt_o[i]); 1263 z.push_back(tks.z[i]); 1264 dz.push_back(1./tks.dz_o[i]); 1265 } 1266 1267 1268 double t_min = TMath::Min(TMath::MinElement(t.size(), &t[0]), TMath::MinElement(vtx.getSize(), &(vtx.t[0])) ) - 50; 1269 double t_max = TMath::Max(TMath::MaxElement(t.size(), &t[0]), TMath::MaxElement(vtx.getSize(), &(vtx.t[0])) ) + 50; 1270 1271 double z_min = TMath::Min(TMath::MinElement(z.size(), &z[0]), TMath::MinElement(vtx.getSize(), &(vtx.z[0])) ) - 5; 1272 double z_max = TMath::Max(TMath::MaxElement(z.size(), &z[0]), TMath::MaxElement(vtx.getSize(), &(vtx.z[0])) ) + 5; 1273 1274 auto c_2Dspace = new TCanvas("c_2Dspace", "c_2Dspace", 800, 600); 1275 1276 TGraphErrors* gr_PVtks = new TGraphErrors(t.size(), &t[0], &z[0], &dt[0], &dz[0]); 1277 gr_PVtks->SetTitle(Form("Clustering space")); 1278 gr_PVtks->GetXaxis()->SetTitle("t CA [ps]"); 1279 gr_PVtks->GetXaxis()->SetLimits(t_min, t_max); 1280 gr_PVtks->GetYaxis()->SetTitle("z CA [mm]"); 1281 gr_PVtks->GetYaxis()->SetRangeUser(z_min, z_max); 1282 gr_PVtks->SetMarkerStyle(4); 1283 gr_PVtks->SetMarkerColor(1); 1284 gr_PVtks->SetLineColor(1); 1285 gr_PVtks->Draw("APE1"); 1286 1287 TGraph* gr_vtx = new TGraph(1, &(vtx.t[i_vtx]), &(vtx.z[i_vtx])); 1288 gr_vtx->SetMarkerStyle(28); 1289 gr_vtx->SetMarkerColor(2); 1290 gr_vtx->SetMarkerSize(2.); 1291 gr_vtx->Draw("PE1"); 1292 1293 double t_pos[] = {vtx.t[i_vtx], vtx.t[i_vtx]+100}; 1294 double t_neg[] = {vtx.t[i_vtx], vtx.t[i_vtx]-100}; 1295 double z_pos[] = {vtx.z[i_vtx], vtx.z[i_vtx]+(zn/tn)*100}; 1296 double z_neg[] = {vtx.z[i_vtx], vtx.z[i_vtx]-(zn/tn)*100}; 1297 1298 TGraph* gr_pos = new TGraph(2, &t_pos[0], &z_pos[0]); 1299 gr_pos->SetLineColor(8); 1300 gr_pos->SetMarkerColor(8); 1301 gr_pos->Draw("PL"); 1302 TGraph* gr_neg = new TGraph(2, &t_neg[0], &z_neg[0]); 1303 gr_neg->SetLineColor(4); 1304 gr_neg->SetMarkerColor(4); 1305 gr_neg->Draw("PL"); 1306 1307 1308 c_2Dspace->SetGrid(); 1309 c_2Dspace->SaveAs(fFigFolderPath + Form("/crush_splitting.png")); 1310 1311 delete c_2Dspace; 1312 }
Note:
See TracChangeset
for help on using the changeset viewer.