A trajectory is made from the primary vertex with the smallest impact parameter χ2 to the daughter K+ along the direction of the reconstructed B+ candidate momentum. The MT-DOCA is the distance of closest approach (DOCA) between the daughter K+ and this trajectory.
Edited
Designs
Child items
0
Show closed items
No child items are currently assigned. Use child items to break down this issue into smaller parts.
Linked items
0
Link issues together to show that they're related or that one is blocking others.
Learn more.
Related merge requests
9
When these merge requests are accepted, this issue will be closed automatically.
In short, it starts from the mother particle, gets a daughter, clones the mother particle and moves it to the PV of the daughter, and then determines the docachi2 between the mother and daughter trajectories. The key methods are:
502 { 503 if ( !p ) { 504 Error( "Invalid particle, return 'InvalidDistance'" ).ignore(); 505 return LoKi::Constants::InvalidDistance; 506 } 508 const LHCb::Particle* daughter = LoKi::Child::child( p, getIndex() ); 509 if ( !daughter ) { 510 Error( "Invalid daughter particle, return 'InvalidDistance'" ).ignore(); 511 return LoKi::Constants::InvalidDistance; 512 } 513 514 // clone the mother and move it to the PV 515 auto tempMother = moveMother( p, daughter ); 516 517 // evaluate the result 518 return chi2( tempMother.get(), daughter ); 519 }
and
463 { 464 // clone the mother and move it to the PV 465 std::unique_ptr<LHCb::Particle> tempMother( mother->clone() ); 466 467 const LHCb::VertexBase* aPV = bestVertex( daughter ); 468 // Update the position errors 469 tempMother->setReferencePoint( aPV->position() ); 470 tempMother->setPosCovMatrix( aPV->covMatrix() ); 471 472 // Cleanup and return 473 // delete aPV ; 474 return tempMother; 475 }
The biggest stumbling block is that we do not know how to access a child particle for use in a functor, as in line 508. The only examples we have seen of accessing a child are to apply another functor to it, as in the example of F.CHILD(1, F.PT), which I do not believe works in this case. Secondarily we do not know if the operations in the moveMother function exist. Is the functionality we need in ThOr, and if so can someone comment on how we use it or point us towards an example?
Out of curiosity what is the physics motivation for this functor as opposed to selecting on the IPCHI2 of the parent particle with respect to its associated PV or some similar quantity?
We are selecting a Kaon consistent with having been emitted from a B decay in the absence of a reconstructible secondary vertex. This is necessary to beat down the enormous combinatorial background to B->K+pi0. Perhaps I am missing something but it's not obvious to me how the parent IPCHI2 would help us with that.
there is no example of the copying of a v2 particle, but if you make a branch if constexpr(is_legacy_particle<p>) in your functor implementation, you can access the child and copy the mother exactly as in the loki functor implemnetation. see the CHILD functor implementation in Adapters.h
Hi @nnolte, thanks for the helpful response! I'm working on the implementation of MTDOCACHI2, and I have a couple of questions at the moment. Am I correct in assuming a legacy particle is the same as a v1 particle? How can we ensure that the kaon is a v1/legacy particle? Do the pion and B also need to be v1 particles to ensure compatibility?
Does the implementation of this functor really need the entire particle to be copied? Or is it sufficient to 'parallel transport' the vertex position and momentum vectors (and note that momenta are invariant under tranlations...), and the particle just happens to be a 'lazy' way of packaging those? In general, it would be good to determine what the 'minimal' information is which is actually needed instead of just copying 'everything' and modifying some parts.
@graven From a physics standpoint I think it's only necessary to translate the position and momentum. From a technical standpoint the distance calculator for docachi2 expects two particles. If you know of a more optimal way to provide the distance calculator with the original particle but the new information we could certainly do that. Unless that functionality is already available I would propose to continue with the current approach while it is being developed in order to make sure we can also optimize the cuts and rate before the February deadline.
@ejiang "legacy" or "v1" is the same as LHCb::Particle (i.e. the Run1/2 model). This model only talks to other v1 particles (or tracks), so all other particles in your line are indeed also v1 particles. I don't think you need to put in specific efforts to ensure that v1 is used, as this is the default. And if for some reason other particles happen to appear somewhere, things will blow up anyway.
Hi @nnolte, I've been working on the functor for MTDOCACHI2 (the code for the functor is here with the initialization here. I've been running into this error:
In file included from Phys/FunctorCache/FunctorTestCache_srcs/FUNCTORS_FunctorFactory_0001.cpp:7: ../Phys/FunctorCore/include/Functors/Composite.h: In member function ‘auto Functors::detail::MotherTrajectoryDistanceOfClosestApproachChi2::operator()(const DistanceCalculator&, const Particle&) const’: ../Phys/FunctorCore/include/Functors/Composite.h:111:11: error: ‘LoKi’ has not been declared 111 | LoKi::Particles::MTDOCA::result_type LoKi::Particles::MTDOCA::operator()(LoKi::Particles::MTDOCA::argument pMother ) const {
I was wondering how to resolve it? All the code is under the branch if constexpr(is_legacy_particle<p>), which I had interpreted might allow us to access old methods in the LoKi implementation. Are there header files I should be including, or is there something else I'm missing that would resolve this? Thanks again!
Hi @ejiang,
I think most of the code inside the if constexpr (Sel::Utils::is_legacy_particle<Particle>) { needs to go. Maybe first you can check that the machinery works if you simply comment that code out and put return 1.0?
Assuming that is OK, then we can start trying to build the actual code to do the MTDOCA calculation.
I think you need to look at how methods from Sel::Utils are used elsewhere in Composite.h for inspiration.
Maybe don't worry about this for now, but I think we'll also want to move away from using if constexpr(. Somewhere there is a "prefer ADL over if constexpr..." issue from @graven, though many of us (myself included) need to catch up on what that means in practice
Hi @mvesteri and all, the code is now working with the body set simply to return 1.0 (see here and here). I just wanted to check my interpretation of your response, which is that we don’t want to be using any of the old LoKi methods, but rather some of the newer methods written for ThOr, and in Niklas’s comment above “you can access the child and copy the mother exactly as in the loki functor implemnetation” was referring not to the literal LoKi methods, but rather to ThOr methods with identical structure. Is this correct? I'd also appreciate it if anyone (maybe @nnolte?) happened to know the exact ThOr methods that would allow us to a) access the child of a composite particle and b) move the mother particle to the primary vertex. Thanks again!
i don't think there is a thor method to do the "move mother particle to primary vertex" in thor.
access the child of a composite particle is happening inside the CHILD functor, which you can find in Adapters.h.
It's along the lines of composite.daughtersVector()[i].
yeah that should work. Keep in mind that you can use the LHCb::Particle in ThOr in the same way as in loki (e.g. use methods of the particle). ThOr is however also supposed to work with the other particle model (v2::Particle), so the other if constexpr branch will also have to be filled eventually.
Hi experts--thanks for all the help so far, we are able to access the child of the composite particle with @nnolte's help, working version of the code here. However, we need to use the getBestPV function which takes the primary vertices as input--and when we try to add in the primary vertices here, we reach some difficult segfaults (attached). We think the error has to do with how parameters are inputted into the functor and templates, especially in lines 293-296:
Notably, the template here does not match the template in the detail namespace, where there is one before the structure and one before the operator, similar to how these variables were declared in Composite.h and Combination.h.
`template <typename DistanceCalculator, typename T, T N>
struct MotherTrajectoryDistanceOfClosestApproachChi2 : public Function {
Another possible problem is that we don't return our final value inside a wrapper, like other functors in Composite.h. Attempting to do so also gives errors, but different ones. Would greatly appreciate some help if anyone is a template expert out there!
What happens if the only content of your operator() function is auto const& bestPV = Sel::getBestPV( composite, vertices );? Note that this uses ADL and doesn't need to be inside the if constexpr...
If this fails then I'd be interested to see what you put in the Phys/FunctorCore/python/Functors/__init__.py
Hi @mvesteri, thanks again for the help! Implementing your suggestion (see code here) gives a segmentation fault error (I believe the same one as before). The content of my Phys/FunctorCore/python/Functors/__init__.py can be found here.
Sorry for the delay. I'm not sure why you want/need the bind(.. line. E.g., you could start from a clone of the FlightDistanceChi2ToVertex functor just above yours. Check that it compiles and works at runtime before changing anything else. Then you want to try and replace the line return Sel::Utils::flightDistanceChi2( composite, bestPV ); with the specifics of MTDOCACHI2.
The first step is presumably to access the state of child-1 - @graven you mentioned that you are working on that?
I'm waiting for Rec!2656 (closed) to be merged first, as otherwise it will conflict -- and there is still a possible performance regression in Rec!2690 (merged) which also has to be merged first (as any access to the states of the children will build upon / require the changes in Rec!2690 (merged)).
Hi @mvesteri, thanks for your help. We have successfully been able to extract the child as well as move the composite particle thanks to @nnolte, everything from lines 141-145 in the current code works at runtime.
The only thing that remains is to access the distance calculator, which is why we have the bind(... line. We take inspiration from the Lifetime functor, which accesses DefaultLifetimeFitter_t, analogously to how we would like to access DefaultDistanceCalculator_t (see lines 264-266 and 275-277). The current code fails with segfault, and the relevant line of the (attached) log output is:
afs/cern.ch/work/e/ejiang/public/stack/Rec/InstallArea/x86_64_v2-centos7-gcc11-opt/include/Functors/Composite.h:220:51: [0m[0;1;30mnote: [0mdefault constructor of 'MotherTrajectoryDistanceOfClosestApproachChi2' is implicitly deleted because field 'dist_calc' has no default constructor[0m Functors::detail::DefaultDistanceCalculator_t dist_calc;mc_output.log
This is the same error as if I kept 139-148. Replacing DefaultDistanceCalculator with DefaultLifetimeFitter allows the code to run at runtime. We think this error comes because in SelTools/DistanceCalculator.h, DistanceCalculator does not initialize its argument:
Right now, everything works at runtime except for the distance calculator, and so we are trying to figure out how to properly pass the distance calculator to the functor. Any help would be greatly appreciated!
The DistanceCalculator and LifetimeFitters were implemented a differently, so the way you feed in the top level information is a bit different. See ,e.g., the implementation of DOCA here. I don't think you need to template over DistanceCalculator in the same way in your case, and can likely just replace the template parameter there with DefaultDistanceCalculator_t.
Thank you @mvesteri and @agilman for your help, we were able to progress to accessing the DistanceCalculator (code)! Unfortunately, there seems to be a problem in using it. The full log is attached, and the relevant lines of the error are:
[0m[1m/afs/cern.ch/work/e/ejiang/public/stack3/LHCb/InstallArea/x86_64_v2-centos7-gcc11-opt/include/LHCbMath/MatVec.h:611:30: [0m[0;1;30mnote: [0mcandidate template ignored: could not match 'MatSym' against 'SMatrix'[0m [[gnu::pure]] MatSym<T, V> similarity( const Mat<T, V, U>& M, const MatSym<T, U>& S ) { [0;1;32m ^ [0m[1m/afs/cern.ch/work/e/ejiang/public/stack3/LHCb/InstallArea/x86_64_v2-centos7-gcc11-opt/include/LHCbMath/MatVec.h:617:19: [0m[0;1;30mnote: [0mcandidate template ignored: could not match 'Vec' against 'Mat'[0m [[gnu::pure]] T similarity( const Vec<T, N>& V, const MatSym<T, N>& S ) { [0;1;32m ^ [0m[1m/afs/cern.ch/work/e/ejiang/public/stack3/LHCb/InstallArea/x86_64_v2-centos7-gcc11-opt/include/LHCbMath/MatVec.h:623:19: [0m[0;1;30mnote: [0mcandidate template ignored: could not match 'Vec' against 'Mat'[0m [[gnu::pure]] T similarity( const Vec<T, N>& V, const Mat<T, N>& M ) { [0;1;32m ^ [0m[1m/afs/cern.ch/work/e/ejiang/public/stack3/LHCb/InstallArea/x86_64_v2-centos7-gcc11-opt/include/LHCbMath/MatVec.h:628:22: [0m[0;1;30mnote: [0mcandidate template ignored: could not match 'Vec3' against 'Mat'[0m [[gnu::pure]] auto similarity( const Vec3<T>& v, const Matrix& mat ) { [0;1;32m ^ [0mIn file included from input_line_30:9: In file included from /afs/cern.ch/work/e/ejiang/public/stack3/Rec/InstallArea/x86_64_v2-centos7-gcc11-opt/include/Functors/TrackLike.h:16: In file included from /afs/cern.ch/work/e/ejiang/public/stack3/Rec/InstallArea/x86_64_v2-centos7-gcc11-opt/include/Functors/Utilities.h:14: In file included from /afs/cern.ch/work/e/ejiang/public/stack3/Rec/InstallArea/x86_64_v2-centos7-gcc11-opt/include/SelTools/DistanceCalculator.h:15: [1m/afs/cern.ch/work/e/ejiang/public/stack3/Rec/InstallArea/x86_64_v2-centos7-gcc11-opt/include/SelTools/Utilities.h:57:53: [0m[0;1;31merror: [0m[1mno member named 'threeMomCovMatrix' in 'LHCb::Particle'[0m s.covTT() = LHCb::LinAlg::similarity( Jtxmom, p.threeMomCovMatrix() ); [0;1;32m ~ ^ [0m[1m/afs/cern.ch/work/e/ejiang/public/stack3/Rec/InstallArea/x86_64_v2-centos7-gcc11-opt/include/SelTools/Utilities.h:58:27: [0m[0;1;31merror: [0m[1mno member named 'threeMomPosCovMatrix' in 'LHCb::Particle'[0m s.covXT() = Jxpos * p.threeMomPosCovMatrix().transpose() * Jtxmom.transpose(); [0;1;32m ~ ^
Not sure why this is happening, since we ran the tutorial example line to include DOCACHI2 which accesses the same method of DistanceCalculator and works fine, so it seems to be not a problem with the distance calculator itself but with our code. We are working with a freshly made stack. Is there anything in our code that looks incorrect?
Just to update here, the most recent error we've been getting looks like this:
In file included from /afs/cern.ch/work/e/ejiang/public/stack3/Rec/InstallArea/x86_64_v2-centos7-gcc11-opt/include/SelTools/DistanceCalculator.h:15: /afs/cern.ch/work/e/ejiang/public/stack3/Rec/InstallArea/x86_64_v2-centos7-gcc11-opt/include/SelTools/Utilities.h:57:53: error: no member named 'threeMomCovMatrix' in 'LHCb::Particle' s.covTT() = LHCb::LinAlg::similarity( Jtxmom, p.threeMomCovMatrix() ); ~ ^ /afs/cern.ch/work/e/ejiang/public/stack3/Rec/InstallArea/x86_64_v2-centos7-gcc11-opt/include/SelTools/Utilities.h:58:27: error: no member named 'threeMomPosCovMatrix' in 'LHCb::Particle' s.covXT() = Jxpos * p.threeMomPosCovMatrix().transpose() * Jtxmom.transpose(); and ^ /afs/cern.ch/work/e/ejiang/public/stack3/LHCb/InstallArea/x86_64_v2-centos7-gcc11-opt/include/LHCbMath/MatVec.h:611:30: note: candidate template ignored: could not match 'MatSym' against 'SMatrix' [[gnu::pure]] MatSym<T, V> similarity( const Mat<T, V, U>& M, const MatSym<T, U>& S ) {
I've confirmed with @nnolte on Mattermost that this is a compatibility error between v1 particles and the distance calculator here. v1 particles have a distance calculator, but it is a Gaudi tool. The ParticleCombiner algorithm which should call MTDOCACHI2 also has a toolhandle to the DistanceCalculator, but it is private. I am unsure as to how I should proceed, would greatly appreciate any advice @nnolte@graven@agilman@mvesteri . Most recent code is here as usual.
Thanks for the help @agilman. Just to update, MTDOCACHI2 is now able to accept and use the distance calculator without errors. However, it returns infinity, I assume because the calculation in SelTools/Utilities.h hasn't been implemented yet? Anyways, thank you for all your hard work!
I don't think this can be due to SelTools/Utilities.h, which performs a fairly simple function of getting the position and momentum of a particle and outputting it as a state-like object. The bits I commented out there was left-over code of someone performing a sanity check, as far as I can tell.
in SelTools/Utilities.h, especially the last 3 lines where they set the covariant matrix of the state. I think this may be the root of the problem, because when I print s.posSlopeCovMatrix() it gives a matrix of zeros, leading to a divide by zero in the distance calculator. Printing out the covariant matrix of the mother particle before it enters stateVectorFromComposite gives a nonzero matrix. Am I correct in thinking the last 3 lines of the code above is supposed to initialize the covariant matrix of the state? I've tried to implement them myself, although I've been stuck on the error in the attached log. Thanks again for all your help. utils_error.log
Ah, indeed, well-spotted. There are some other issues that need resolving in the commented code, I'll ping you here once I get a fix in on that branch.
Relevant merge request here, will be moved from draft once I figure out how to give it the index of the child as an input parameter. @agilman@graven I saw that !2656 has been closed due to being superseded by !2709. Will !2709 (merged) also implement the changes from !2656 (merged) which allow the DistanceCalculator to accept LHCb::particle?
Trying to follow the example of functors in Combination.h, I tried to add a template parameter int N in the Functors::Composite namespace. Full code shown here--the problematic lines are
and result in the attached error, which makes sense, since C++ doesn't allow partial specialization of function templates. My question is what would be the best alternative to partial specialization here that would allow me to pass both an integer and the typename VContainer? Another question I have is once I figure out how to pass the integer through the template, what parameters should I give DataDepWrapper? Any help is appreciated, maybe @graven@agilman@nnolte or others?
Hi @graven, thanks for the pointer, the code now is able to compile. Unfortunately, at runtime I get this extremely strange error--
/afs/cern.ch/work/e/ejiang/public/stack_2_24/Rec/InstallArea/x86_64_v2-centos7-gcc11-opt/include/Functors/Composite.h:222:10: note: candidate function template not viable: requires 2 arguments, but 1 was provided auto MotherTrajectoryDistanceOfClosestApproachChi2( std::integral_constant<int, N>, std::string vertex_location ) { ^
I'm not sure which function template it's talking about, since every template in this line has two arguments--any ideas?runtime_error.log Full log attached.
can you point me at the latest version of your code? I suspect something is inconsistent in the specified grammar on the python side, as it generated the wrong C++ code -- but I can only tell if I can check the code itself...
why not make a branch and corresponding MR on gitlab.cern.ch so that anyone can just check out the code? That would also make it easier to comment on specific lines in the code... and you'll have to do that anyway in order to get the code merged into the LHCb master
Attached is the log, the main issue is these lines:
/afs/cern.ch/work/e/ejiang/public/stack_2_24/Rec/InstallArea/x86_64_v2-centos7-gcc11-opt/include/Functors/Utilities.h:53:7: error: constructor for 'Functors::detail::DataDepWrapper<Functors::Function, Functors::detail::MotherTrajectoryDistanceOfClosestApproachChi2<1>, std::vector<LHCb::Event::v2::RecVertex, std::scoped_allocator_adaptor<LHCb::Allocators::EventLocal<LHCb::Event::v2::RecVertex>> > >' must explicitly initialize the member 'm_f' which does not have a default constructor DataDepWrapper( CArgs&&... tes_locs ) : m_tes_locs{std::forward<CArgs>( tes_locs )...} {} ^
I assume this has to do with me not initializing DataDepWrapper properly, although I haven't been able to figure out what exactly the issue is.