19 #include "AthLinks/ElementLink.h"
37 return StatusCode::FAILURE;
48 return StatusCode::FAILURE;
61 return StatusCode::SUCCESS;
69 m_muonCollectionKey(
"Muons"),
70 m_TrkParticleCollection(
"TrackParticleCandidate"),
71 m_iVertexFitter(
"Trk::TrkVKalVrtFitter"),
72 m_iV0VertexFitter(
"Trk::V0VertexFitter"),
73 m_trkSelector(
"InDet::TrackSelectorTool")
75 declareInterface<FourMuonTool>(
this);
100 pairVxContainer->setStore(pairVxAuxContainer);
104 quadVxContainer->setStore(quadVxAuxContainer);
115 ATH_MSG_DEBUG(
"ID TrackParticle container size "<< importedTrackCollection->
size());
118 std::vector<const xAOD::Muon*> theMuonsAfterSelection;
120 unsigned int nCombMuons = 0;
121 unsigned int nSegmentTaggedMuons = 0;
123 for (
auto muItr=importedMuonCollection->
begin(); muItr!=importedMuonCollection->
end(); ++muItr) {
124 if ( *muItr == NULL )
continue;
125 muonDecorator(**muItr) = -1;
126 if ( ((*muItr)->muonType() !=
xAOD::Muon::Combined ) && ((*muItr)->muonType() != xAOD::Muon::SegmentTagged ) )
continue;
127 if (!(*muItr)->inDetTrackParticleLink().isValid())
continue;
128 auto& link = (*muItr)->inDetTrackParticleLink();
130 if ( muonTrk==NULL)
continue;
133 if ( fabs(muonTrk->
pt())<
m_ptCut )
continue;
136 if ( (*muItr)->muonType() == xAOD::Muon::SegmentTagged ) ++nSegmentTaggedMuons;
137 theMuonsAfterSelection.push_back(*muItr);
139 unsigned int nSelectedMuons = theMuonsAfterSelection.size();
140 ATH_MSG_DEBUG(
"Number of muons after selection: " << nSelectedMuons);
142 ATH_MSG_DEBUG(
"and " << nSegmentTaggedMuons <<
" are segment tagged");
143 if ( (nSelectedMuons < 4) || (nCombMuons < 1) ) {
145 return StatusCode::SUCCESS;
156 std::sort(theMuonsAfterSelection.begin(), theMuonsAfterSelection.end(), [](
const xAOD::Muon *
a,
const xAOD::Muon *
b) {
157 return b->pt() < a->pt();
161 unsigned int muonIndex(0);
162 for (
auto selMuon : theMuonsAfterSelection) {
163 muonDecorator(*selMuon) = muonIndex;
168 std::vector<Combination> quadruplets;
169 std::vector<Combination>
pairs;
171 if (quadruplets.size()==0) {
173 return StatusCode::SUCCESS;
184 std::vector<const xAOD::TrackParticle*> theTracks = (*pairItr).trackParticles(
"pair1");
186 if (pairVxCandidate != 0) {
188 indexDecorator(*pairVxCandidate) = (*pairItr).combinationIndices();
189 chargeDecorator(*pairVxCandidate) = (*pairItr).combinationCharges();
193 std::vector<const xAOD::Muon*> theStoredMuons;
194 theStoredMuons = (*pairItr).muons;
195 helper.setMuons(theStoredMuons,importedMuonCollection.
get());
197 pairVxContainer->
push_back(pairVxCandidate);
198 ATH_MSG_DEBUG(
"..... indices: " << (*pairItr).combinationIndices() <<
199 " charges: " << (*pairItr).combinationCharges() <<
210 std::vector<const xAOD::TrackParticle*> theDCTracks; theDCTracks.clear();
213 theDCTracks = (*quadItr).trackParticles(
"DC");
224 if (dcVxCandidate != 0) {
226 indexDecorator(*dcVxCandidate) = (*quadItr).combinationIndices();
227 chargeDecorator(*dcVxCandidate) = (*quadItr).combinationCharges();
235 const std::vector<const xAOD::Muon*> &theStoredMuons = (*quadItr).muons;
236 helper.setMuons(theStoredMuons,importedMuonCollection.
get());
238 quadVxContainer->
push_back(dcVxCandidate);
239 ATH_MSG_DEBUG(
"..... indices: " << (*quadItr).combinationIndices() <<
240 " charges: " << (*quadItr).combinationCharges() <<
241 " chi2(DC): " << dcChi2);
250 return StatusCode::SUCCESS;;
267 if(concreteVertexFitter == 0) {
268 ATH_MSG_FATAL(
"The vertex fitter passed is not a V0 Vertex Fitter");
282 return myVxCandidate;
295 std::vector<std::vector<unsigned int> > quadIndices =
mFromN(4,
length);
307 std::vector<std::vector<unsigned int> > allCombinations;
308 std::vector<unsigned int> mainList;
309 std::vector<unsigned int> combination;
310 for (
unsigned int i=0;
i<
N; ++
i) mainList.push_back(
i);
312 return allCombinations;
317 std::vector<unsigned int> &combination,
318 std::vector<unsigned int> &mainList,
319 std::vector<std::vector<unsigned int> > &allCombinations) {
321 allCombinations.push_back(combination);
325 for (
unsigned int i=
offset;
i<=mainList.size()-
k; ++
i) {
326 combination.push_back(mainList[
i]);
328 combination.pop_back();
339 std::vector<std::pair<unsigned int, unsigned int> > uniquePairs;
340 std::vector<std::vector<unsigned int> > doublets =
mFromN(2,
length);
341 for (std::vector<std::vector<unsigned int> >::
iterator it=doublets.begin();
it!=doublets.end(); ++
it) {
342 std::pair<unsigned int, unsigned int> tmpPair = std::make_pair((*it).at(0),(*it).at(1));
343 uniquePairs.push_back(tmpPair);
358 std::vector<Combination> &
pairs,
359 std::vector<Combination> &quadruplets,
360 unsigned int nSelectedMuons) {
362 std::vector<std::vector<unsigned int> > quadrupletIndices =
getQuadIndices(nSelectedMuons);
363 std::vector<std::pair<unsigned int, unsigned int> > pairIndices =
getPairIndices(nSelectedMuons);
366 std::vector<std::vector<unsigned int> >
::iterator quadItr;
367 for (quadItr=quadrupletIndices.begin(); quadItr!=quadrupletIndices.end(); ++quadItr) {
368 const std::vector<unsigned int> &
quad = (*quadItr);
369 std::vector<const xAOD::Muon*> theMuons = {muonsIn[
quad[0]],muonsIn[
quad[1]],muonsIn[
quad[2]],muonsIn[
quad[3]]};
372 tmpQuad.
muons = std::move(theMuons);
374 quadruplets.emplace_back(std::move(tmpQuad));
376 if (quadruplets.size() == 0)
return;
379 std::vector<std::pair<unsigned int, unsigned int> >
::iterator pairItr;
380 for (pairItr=pairIndices.begin(); pairItr!=pairIndices.end(); ++pairItr) {
381 std::pair<unsigned int, unsigned int> pair = (*pairItr);
383 std::vector<const xAOD::Muon*> theMuons = {muonsIn[pair.first],muonsIn[pair.second]};
384 tmpPair.
muons = std::move(theMuons);
386 pairs.emplace_back(std::move(tmpPair));
410 if (charges && quality)
accept =
true;