Report problems to ATLAS LXR Team (with time and IP address indicated)

The LXR Cross Referencer

source navigation ]
diff markup ]
identifier search ]
general search ]
 
 
Architecture: linux ]
Version: head ] [ nightly ] [ GaudiDev ]
  Links to LXR source navigation pages for stable releases [ 12.*.* ]   [ 13.*.* ]   [ 14.*.* ]   [ 15.*.* ] 

001 /***************************************************************************
002                            LifetimeTag.cxx  -  Description
003                              -------------------
004     begin   : 10.03.04
005     authors : Andreas Wildauer (CERN PH-ATC), Fredrik Akesson (CERN PH-ATC)
006     email   : andreas.wildauer@cern.ch, fredrik.akesson@cern.ch
007     changes :
008 
009  ***************************************************************************/
010 #include "JetTagTools/LifetimeTag.h"
011 
012 #include "CLHEP/Vector/ThreeVector.h"
013 #include "JetEvent/Jet.h"
014 #include "GaudiKernel/IToolSvc.h"
015 #include "GaudiKernel/MsgStream.h"
016 #include "Particle/TrackParticle.h"
017 #include "JetTagInfo/LifetimeInfo.h"
018 #include "Navigation/NavigationToken.h"
019 
020 #include "JetTagTools/LikelihoodTool.h"
021 #include "JetTagTools/HistoHelperRoot.h"
022 
023 #include "ITrackToVertex/ITrackToVertex.h"
024 #include "GaudiKernel/ITHistSvc.h"
025 #include "JetTagEvent/TrackAssociation.h"
026 
027 // needed for ref mode
028 #include "JetTagInfo/TruthInfo.h"
029 
030 namespace Analysis
031 {
032 typedef std::multimap<double, const Rec::TrackParticle*>::iterator TrkMMIter;
033 
034 LifetimeTag::LifetimeTag(const std::string& t, const std::string& n, const IInterface* p)
035         : AlgTool(t,n,p),
036         m_runModus("analysis"),
037         m_histoHelperSig(0),
038         m_histoHelperBkg(0),
039         m_trackToVertexTool("Reco::TrackToVertex"),
040         m_priVtx(0),
041         m_likelihoodTool("Analysis::LikelihoodTool"),
042         m_useVariables(std::vector<std::string>()),
043         m_lifetimeMode("2D"),
044         m_minpt(1.*GeV),
045         m_maxd0wrtPrimVtx(1.*mm),
046         m_maxz0wrtPrimVtx(1.5*mm),
047         m_precisionHits(9),
048         m_PixelHits(2),
049         m_BLayerHits(1)
050 {
051     declareInterface<ITagTool>(this);
052     declareProperty("Runmodus",       m_runModus);
053     declareProperty("useVariables",  m_useVariables);
054     declareProperty("minpt", m_minpt);
055     declareProperty("maxd0wrtPrimVtx", m_maxd0wrtPrimVtx);
056     declareProperty("maxz0wrtPrimVtx", m_maxz0wrtPrimVtx);
057     declareProperty("PrecisionHits", m_precisionHits);
058     declareProperty("PixelHits",     m_PixelHits);
059     declareProperty("BLayerHits",    m_BLayerHits);
060     declareProperty("LifetimeModus", m_lifetimeMode);
061     declareProperty("LikelihoodTool", m_likelihoodTool);
062     declareProperty("TrackToVertexTool",  m_trackToVertexTool);
063     
064     ITHistSvc* myHistoSvc(0);
065     MsgStream mLog(msgSvc(), name());
066 
067     if( service( "THistSvc", myHistoSvc ).isSuccess() )
068     {
069         mLog << MSG::DEBUG << name() << ": HistoSvc loaded successfully." << endreq;
070         m_histoHelperSig = new HistoHelperRoot(myHistoSvc);
071         m_histoHelperBkg = new HistoHelperRoot(myHistoSvc);
072         m_histoHelperSig->setCheckOverflows(true);
073         m_histoHelperBkg->setCheckOverflows(true);
074     }
075     else mLog << MSG::ERROR << name() << ": HistoSvc could NOT be loaded." << endreq;
076 }
077 
078 LifetimeTag::~LifetimeTag()
079 {
080   delete m_histoHelperSig;
081   delete m_histoHelperBkg;
082 }
083 
084 StatusCode LifetimeTag::initialize()
085 {
086     MsgStream mLog(msgSvc(), name());
087     m_printParameterSettings();
088 
089     /* ----------------------------------------------------------------------------------- */
090     /*                 READ IN REFHISTOS WITH AIDA IF IN ANALYSIS MODE                     */
091     /* ----------------------------------------------------------------------------------- */
092     if (m_runModus == "analysis")
093     {
094       /// retrieve the Likelihood tool
095       if ( m_likelihoodTool.retrieve().isFailure() ) {
096         mLog << MSG::FATAL << "failed to retrieve tool " << m_likelihoodTool << endreq;
097         return StatusCode::FAILURE;
098       } else {
099         mLog << MSG::INFO << "retrieved tool " << m_likelihoodTool << endreq;
100       }
101       m_likelihoodTool->readInHistosFromFile("SigCali/");
102       m_likelihoodTool->readInHistosFromFile("BkgCali/");
103       m_likelihoodTool->printStatus();
104     }
105 
106     /* Retrieve TrackToVertex extrapolator tool */
107     if ( m_trackToVertexTool.retrieve().isFailure() ) {
108       mLog << MSG::FATAL << "failed to retrieve tool " << m_trackToVertexTool << endreq;
109       return StatusCode::FAILURE;
110     } else {
111       mLog << MSG::INFO << "retrieved tool " << m_trackToVertexTool << endreq;
112     }
113 
114     /* ----------------------------------------------------------------------------------- */
115     /*                         BOOK HISTOS IF IN REFERENCE MODE                            */
116     /* ----------------------------------------------------------------------------------- */
117     const std::string& lm = m_lifetimeMode; // just to make the book lines shorter ...
118     if (m_runModus=="reference")
119     {
120       if (lm == "1D") 
121       {
122         m_histoHelperBkg->bookHisto("/BkgCali/significance1D", "track significance 1D", 200, -10., 13.);
123         m_histoHelperSig->bookHisto("/SigCali/significance1D", "track significance 1D", 200, -10., 13.);
124       }
125       else if (lm == "2D") 
126       {
127         m_histoHelperBkg->bookHisto("/BkgCali/significance2D", "track significance 2D", 200, -20., 40.);
128         m_histoHelperSig->bookHisto("/SigCali/significance2D", "track significance 2D", 200, -20., 40.);
129       }
130     }
131     return StatusCode::SUCCESS;
132 }
133 
134 
135 StatusCode LifetimeTag::finalize()
136 {
137 //     MsgStream mLog(msgSvc(), name());
138 //     mLog << MSG::DEBUG << name() << ": Finalizing successfully" << endreq;
139     return StatusCode::SUCCESS;
140 }
141 
142 void LifetimeTag::tagJet(Jet& jetToTag)
143 {
144     MsgStream mLog(msgSvc(), name());
145 
146     std::vector<const Rec::TrackParticle*> myJetToTag;
147     std::multimap<double, const Rec::TrackParticle*> myTrackSIP;
148     std::multimap<double, const Rec::TrackParticle*> myTrackSignificance;
149 
150     /* Create the info class and append it to the Jet */
151     std::string instanceName(name());
152     LifetimeInfo * lifeInfo = new LifetimeInfo(instanceName.erase(0,8));
153     jetToTag.addInfo(lifeInfo);
154 
155     /* Extract the TrackParticles from the jet and apply preselection on the track.*/
156     std::vector<const Rec::TrackParticle*>* trackVector = jetToTag.getAssociation<TrackAssociation>("Tracks")->tracks();
157     for (std::vector<const Rec::TrackParticle*>::iterator jetItr = trackVector->begin(); jetItr != trackVector->end() ; ++jetItr )
158     {
159         if (m_preselect(*jetItr)==true) myJetToTag.push_back(*jetItr);
160     }
161     delete trackVector; trackVector=0;
162 
163     /* Return if there are not enough tracks left after preselection. */
164     if (myJetToTag.size()<2)
165     {
166         mLog << MSG::VERBOSE << "Jet does not have enough tracks: " << myJetToTag.size() << endreq;
167         return;
168     }
169 
170     /* Calculate the impact significance with a lifetime sign. Check if the closest
171     point of approach between the jet axis and the track is downstream: i.e. on
172     the hemisphere of the jet (which starts at the prim.vertex) or upstream: i.e.
173     on the other side of the jet hemisphere. In the following algorithm the jet
174     is defined as: vec(p) + s*vec(u) where: vec(p) is the position of the primary
175     vertex and vec(u) is the direction of the jet. And the track as: vec(q) + t*vec(v)
176     where: vec(q) is the position of the perigee of the track and vec(v) the
177     direction of the track momentum at the perigee. */
178 
179     /* here you can replace the jetDirection with the vector from the primary to the
180     secondary vertex (u = SV - PV). */
181     std::cout.precision(5);
182     Hep3Vector jetDirection = m_jetMomentum(myJetToTag);
183     Hep3Vector unit = jetDirection.unit();
184 
185     mLog << MSG::VERBOSE << "Jetdirection: (" << unit[0] << ", " << unit[1] << ", " << unit[2] << ") "  << endreq;
186 
187     for (std::vector<const Rec::TrackParticle*>::iterator trkItr = myJetToTag.begin(); trkItr != myJetToTag.end(); ++trkItr)
188     {
189         const Trk::MeasuredPerigee* perigee = m_trackToVertexTool->perigeeAtVertex(**trkItr, m_priVtx->recVertex().position());
190 
191         double trackSigD0 = perigee->localErrorMatrix().error(Trk::d0);
192         double trackSigZ0 = perigee->localErrorMatrix().error(Trk::z0);
193         if (trackSigD0<=0. || trackSigZ0<=0.)
194         {
195             mLog << MSG::WARNING << "Error on d0 or z0 negative!!" << endreq;
196             continue;
197         }
198 
199         double signOfIP = m_calculateSignOfIP(perigee, unit);
200 
201         double d0wrtPriVtx( perigee->parameters()[Trk::d0] );
202         double z0wrtPriVtx( perigee->parameters()[Trk::z0] );
203 
204         double sIP(0.);
205         double significance(0.);
206 
207         // calculate errors as given in delphi paper
208         // marseille does it the same way
209         if (m_lifetimeMode == "1D")
210         {
211             sIP = signOfIP*fabs(z0wrtPriVtx);
212 
213             // error on zIP:
214             double trackSigTheta = perigee->localErrorMatrix().error(Trk::theta);
215             double sinTheta = (*trkItr)->sinTh();
216             double cosTheta = (*trkItr)->cosTh();
217             double deltaZ = perigee->parameters()[Trk::z0];
218             z0wrtPriVtx = deltaZ*sinTheta;
219 
220             double dZIPdTheta = deltaZ*cosTheta;
221             double dZIPdz0 = sinTheta;
222             double dZIPdzV = -sinTheta;
223             double DTheta2 = dZIPdTheta*dZIPdTheta*trackSigTheta*trackSigTheta;
224             double DZ02 = dZIPdz0*dZIPdz0*trackSigZ0*trackSigZ0;
225             double DZV2 = dZIPdzV*dZIPdzV*m_priVtx->recVertex().errorPosition().covariance()[2][2];
226             double DThetaZ0 = 2.*dZIPdTheta*dZIPdz0*perigee->localErrorMatrix().covValue(Trk::theta,Trk::z0);
227             double newZ0Err = DTheta2 + DZ02 + DZV2 + DThetaZ0;
228             double z0ErrwrtPriVtx = (newZ0Err>0 ? sqrt(newZ0Err) : -10e-9);
229 
230             significance= signOfIP*fabs(z0wrtPriVtx/z0ErrwrtPriVtx);
231         }
232         else if (m_lifetimeMode == "2D")
233         {
234           sIP = signOfIP*fabs(d0wrtPriVtx);
235 
236           // error on IP:
237           double trackPhi = perigee->parameters()[Trk::phi];
238           double dIPdx = sin(trackPhi);
239           double dIPdy = -cos(trackPhi);
240           double DD0 = trackSigD0*trackSigD0;
241           double DXX = dIPdx*dIPdx*m_priVtx->recVertex().errorPosition().covariance()[0][0];
242           double DYY = dIPdy*dIPdy*m_priVtx->recVertex().errorPosition().covariance()[1][1];
243           double DXY = 2.*dIPdx*dIPdy*m_priVtx->recVertex().errorPosition().covariance()[0][1];
244           double newD0Err = DD0 + DXX + DYY + DXY;
245           double d0ErrwrtPriVtx = (newD0Err>0 ? sqrt(newD0Err) : -10e-9);
246           significance= signOfIP*fabs(d0wrtPriVtx/d0ErrwrtPriVtx);
247         }
248         else if (m_lifetimeMode == "3D")
249         {
250           double d0squared(d0wrtPriVtx*d0wrtPriVtx);
251           double z0squared(z0wrtPriVtx*z0wrtPriVtx);
252 
253           double a0wrtPriVtx( sqrt(d0squared+z0squared) ); // 3D impact parameter
254           double trackSigA0(1./a0wrtPriVtx * sqrt(d0squared*trackSigD0*trackSigD0 + z0squared*trackSigZ0*trackSigZ0));
255 
256           sIP = signOfIP*fabs(a0wrtPriVtx);
257           significance= signOfIP*fabs(a0wrtPriVtx/trackSigA0);
258         }
259         else
260         {
261             mLog << MSG::WARNING << "No correct LifetimeTagMode chosen: " <<m_lifetimeMode << endreq;
262         }
263 
264         delete perigee;
265         myTrackSIP.insert(std::make_pair(sIP,(*trkItr)));
266         myTrackSignificance.insert(std::make_pair(significance,(*trkItr)));
267     } // end for loop over particles in the jet
268 
269     // push the ordered sigend IP and significance back into a FloatVec
270     std::vector<double> sigImpPar;
271     sigImpPar.clear();
272     for (TrkMMIter i=myTrackSIP.begin(); i!=myTrackSIP.end(); i++)
273         sigImpPar.push_back((*i).first);
274     std::vector<double> signific;
275     signific.clear();
276     for (TrkMMIter i=myTrackSignificance.begin(); i!=myTrackSignificance.end(); i++)
277         signific.push_back((*i).first);
278 
279     lifeInfo->setIP(sigImpPar);
280     lifeInfo->setSignificance(signific);
281 
282     if (m_likelihoodTool!=0)
283     {
284 
285       mLog << MSG::VERBOSE << "Significances for this Jet:" << endreq;
286       for (std::vector<double>::iterator itr = signific.begin() ; itr != signific.end() ; itr++)
287       {
288         mLog << MSG::VERBOSE << *itr << endreq;
289       }
290       m_likelihoodTool->setLhVariableValue("significance"+m_lifetimeMode, signific);
291 
292       mLog << MSG::VERBOSE << "Starting LH calculation: " << endreq;
293 
294       lifeInfo->setTagLikelihood(m_likelihoodTool->calculateLikelihood());
295       lifeInfo->setWeight(m_likelihoodTool->calculateWeight());
296     }
297 
298     /* Check if we are in reference histogram production mode. Fill the reference
299     histogram with the signed impact parameters.
300     The histogram for the integratedNegativeIP distributions is filled at the very
301     end of the job (since it needs a finished negativeIP histo) */
302     if (m_runModus=="reference")
303     {
304         if (jetToTag.pt() > 15.*GeV && fabs(jetToTag.eta()) < 2.5)
305         {
306           // need to know some truth stuff now
307           const TruthInfo* truthInfo = jetToTag.tagInfo<TruthInfo>("TruthInfo");
308           if (truthInfo != 0)
309           {
310             HistoHelperRoot* histoHelper(0);
311             std::string hDir;
312             double rmin(0.);
313             if (truthInfo->jetTruthLabel() == "N/A")
314             {
315               // jetcleaning: no b or c in vicinity of light jet ...
316               rmin = truthInfo->deltaRMinTo("C");
317               if (rmin < truthInfo->deltaRMinTo("B")) rmin = truthInfo->deltaRMinTo("B");
318               if (rmin > 0.8) {
319                 histoHelper = m_histoHelperBkg;
320                 hDir = "/BkgCali/";
321               }
322             }
323             if (truthInfo->jetTruthLabel()=="B") {
324               histoHelper = m_histoHelperSig;
325               hDir = "/SigCali/";
326             }
327             if (histoHelper != 0)
328             {
329               for (std::vector<double>::iterator i=signific.begin(); i!=signific.end();i++)
330               {
331                 histoHelper->fillHisto(hDir+"significance"+m_lifetimeMode,(*i));
332               }
333             }
334           } else
335           {
336             mLog << MSG::WARNING << "LifetimeTag" << m_lifetimeMode << " TruthLabel == 0!!!" << endreq;
337           }
338         }
339     }
340 
341     /* Tagging done. Make info object valid, i.e. tag was ok. Fill the JetTag and return ... */
342     lifeInfo->makeValid();
343     return;
344 }
345 
346 void LifetimeTag::finalizeHistos()
347 {
348   if (m_runModus=="reference")
349   {
350     m_histoHelperSig->normalizeHistos();
351     m_histoHelperBkg->normalizeHistos();
352 //     m_histoHelperSig->smoothHistos("significance"+m_lifetimeMode);
353   }
354   return;
355 }
356 
357 /* ------------------------------------------------------------------------------ */
358 /*                        Private Helper Functions                                */
359 /* ------------------------------------------------------------------------------ */
360 bool LifetimeTag::m_preselect(const Rec::TrackParticle *trkPrt)
361 {
362     MsgStream mLog(msgSvc(), name());
363     const Trk::MeasuredPerigee* perigee = m_trackToVertexTool->perigeeAtVertex(*trkPrt, m_priVtx->recVertex().position());
364 
365     double d0wrtPriVtx( perigee->parameters()[Trk::d0] );
366     double z0wrtPriVtx( perigee->parameters()[Trk::z0] );
367 
368     delete perigee;
369 
370     ///////////////////
371 
372 
373     // next comment is not true anymore with the above lines ...
374     // have to check what TrackToVertexTool does when there is no PrimVtx
375     ///////
376     // this means that there was no primary vertex and the TrackParticle
377     // has been created with d0wrtPrimVtx == 0
378     // should not happen here anymore because BJetBuilder would stop before
379     // and go to the next event ... just to make sure!
380     if (d0wrtPriVtx == 0.)
381     {
382         //std::cout << "d0 to vtx is 0 ... " << trkPrt->d0wrtPrimVtx() << std::endl;
383         return false;
384     }
385 
386     mLog << MSG::DEBUG << name() << " m_preselect(): trkPrt->pt(): " << trkPrt->pt() << endreq;
387     mLog << MSG::DEBUG << name() << " m_preselect(): d0 to primary vertex: " << d0wrtPriVtx << endreq;
388     mLog << MSG::DEBUG << name() << " m_preselect(): z0 to primary vertex: " << z0wrtPriVtx << endreq;
389 
390     if (trkPrt->pt()<m_minpt)
391         return false;
392 
393     if (fabs(d0wrtPriVtx)>m_maxd0wrtPrimVtx)
394         return false;
395     if (fabs(z0wrtPriVtx)>m_maxz0wrtPrimVtx)
396         return false;
397 
398     int SCTHits   = trkPrt->trackSummary()->get
399                     (Trk::numberOfSCTHits);
400     int PixelHits = trkPrt->trackSummary()->get
401                     (Trk::numberOfPixelHits);
402 
403     mLog << MSG::DEBUG << name() << " m_preselect(): SCTHits " << SCTHits << endreq;
404     mLog << MSG::DEBUG << name() << " m_preselect(): PixelHits: " << PixelHits << endreq;
405 
406     if ((SCTHits+PixelHits)<m_precisionHits)
407         return false;
408     if (PixelHits<m_PixelHits)
409         return false;
410 
411     int BLayerHits= trkPrt->trackSummary()->get
412                     (Trk::numberOfBLayerHits);
413     mLog << MSG::DEBUG << name() << " m_preselect(): BLayerHits: " << BLayerHits << endreq;
414 
415     if (BLayerHits<m_BLayerHits)
416         return false;
417     return true;
418 }
419 
420 Hep3Vector LifetimeTag::m_jetMomentum(const std::vector<const Rec::TrackParticle*>& tracksInJet)
421 {
422     Hep3Vector jetDir;
423     double px(0.);
424     double py(0.);
425     double pz(0.);
426     /* Calculate the sum of the charged momenta in the jet. TODO: Use the jet momentum
427     of the jet, including clusters instead. */
428     for (std::vector<const Rec::TrackParticle*>::const_iterator i=tracksInJet.begin(); i!=tracksInJet.end(); ++i)
429     {
430         px += (*i)->measuredPerigee()->momentum()[Trk::px];
431         py += (*i)->measuredPerigee()->momentum()[Trk::py];
432         pz += (*i)->measuredPerigee()->momentum()[Trk::pz];
433     }
434     jetDir.set(px,py,pz);
435     return jetDir;
436 }
437 
438 void LifetimeTag::m_printParameterSettings()
439 {
440     MsgStream log(msgSvc(), name());
441     log << MSG::INFO << name() << " initialize(): Parametersettings " << endreq;
442     log << MSG::INFO << "I am in " << m_runModus << " modus." << endreq;
443     log << MSG::INFO << "I am using the following variables:" << endreq;
444     for (std::vector<std::string>::iterator i = m_useVariables.begin();
445             i!=m_useVariables.end() ; ++i)
446     {
447         log << MSG::INFO << (*i) << endreq;
448     }
449     log << MSG::INFO << "Track quality cuts:" << endreq;
450     log << MSG::INFO << "pt            >  " << m_minpt << "\t MeV " << endreq;
451     log << MSG::INFO << "d0wrtPrimVtx  <  " << m_maxd0wrtPrimVtx << "\t mm " << endreq;
452     log << MSG::INFO << "z0wrtPrimVtx  <  " << m_maxz0wrtPrimVtx << "\t mm " << endreq;
453     log << MSG::INFO << "PrecisionHits >= " << m_precisionHits << endreq;
454     log << MSG::INFO << "PixelHits     >= " << m_PixelHits << endreq;
455     log << MSG::INFO << "BLayerHits    >= " << m_BLayerHits << endreq;
456 }
457 
458 double LifetimeTag::m_calculateSignOfIP(
459     const Trk::MeasuredPerigee* perigee, Hep3Vector& unit)
460 {
461     MsgStream mLog(msgSvc(), name());
462 
463     double sign(0.);
464 
465 // these quantities are wrt Primary Vertex
466     if (m_lifetimeMode == "2D")
467     {
468       double trackD0(perigee->parameters()[Trk::d0]);
469       double trackPhi(perigee->parameters()[Trk::phi]);
470       sign = sinf( atan2(unit.y(),unit.x()) - trackPhi )*trackD0;
471     }
472     if (m_lifetimeMode == "1D")
473     {
474       double trackTheta  = perigee->parameters()[Trk::theta];
475       double trackEta = -logf(tanf(trackTheta/2.));
476       double trackZ0  = perigee->parameters()[Trk::z0];
477       HepLorentzVector jetP4(unit);
478       double jetEta = jetP4.pseudoRapidity();
479       sign = (jetEta - trackEta)*trackZ0;
480     }
481     return (sign>=0. ? 1. : -1.);
482 
483 //     Hep3Vector q(-trackD0*sin(trackPhi), trackD0*cos(trackPhi), trackZ0);
484 //     mLog << MSG::VERBOSE << "Perigee position of track: ("
485 //     << q[0] << " ," << q[1] << " ," << q[2] << ")" << endreq;
486     /* Below one should change this to use the PxPyPzE interface of the TrackParticle
487     instead of the momentum() method from the perigee. */
488 ///////// TP global perigee
489 //     Hep3Vector trackDir( (*trkItr)->measuredPerigee()->momentum()[Trk::px],
490 //        (*trkItr)->measuredPerigee()->momentum()[Trk::py],
491 //        (*trkItr)->measuredPerigee()->momentum()[Trk::pz] );
492 ///////// or extrapolated to pri vtx
493 //     Hep3Vector trackDir( perigee->momentum()[Trk::px],
494 //                          perigee->momentum()[Trk::py],
495 //                          perigee->momentum()[Trk::pz] );
496 /////////////
497 //     Hep3Vector v = trackDir.unit();
498 //     mLog << MSG::VERBOSE << "Dir of track at the perigee: ("
499 //     << v[0] << " ," << v[1] << " ," << v[2] << ")" << endreq;
500 
501 //     Hep3Vector diff = m_priVtx->position() - q;
502 
503 //     double A1 = unit*v;
504 //     double A2 = v*v;
505 
506 //     double s = ( A1*(v*diff) - A2*(unit*diff) ) / ( (unit*unit)*A2 - A1*A1 );
507 
508 //     delete perigee;
509 //     return (s>=0.?1.:-1.);
510 }
511 
512 }
513 

source navigation ] diff markup ] identifier search ] general search ]

Due to the LXR bug, the updates fail sometimes to remove references to deleted files. The Saturday's full rebuilds fix these problems
This page was automatically generated by the LXR engine. Valid HTML 4.01!