CheckOverlap.cpp 11 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
/*****************************************************************************\
* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
*                                                                             *
* This software is distributed under the terms of the GNU General Public      *
* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
*                                                                             *
* In applying this licence, CERN does not waive the privileges and immunities *
* granted to it by virtue of its status as an Intergovernmental Organization  *
* or submit itself to any jurisdiction.                                       *
\*****************************************************************************/
Marco Clemencic's avatar
v19r1  
Marco Clemencic committed
11
12
13
14
15

// Include files

// from LHCb
#include "Kernel/IParticlePropertySvc.h"
Gitlab CI's avatar
Gitlab CI committed
16
#include "Kernel/ParticleProperty.h"
Marco Clemencic's avatar
v19r1  
Marco Clemencic committed
17
18
19
20
21
22
23
24
25
26
27

// local
#include "CheckOverlap.h"

//-----------------------------------------------------------------------------
// Implementation file for class : CheckOverlap: CheckOverlap.cpp
//
// 28/06/2002
//-----------------------------------------------------------------------------

// Declaration of the Tool Factory
28
DECLARE_COMPONENT( CheckOverlap )
Marco Clemencic's avatar
v19r1  
Marco Clemencic committed
29

30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
namespace detail {
  template <typename... Particles>
  bool find_overlap_in_basics( Particles const*... particles ) {
    static_assert( ( std::is_same_v<Particles, LHCb::ProtoParticle> && ... ),
                   "All Particles must be LHCb::ProtoParticle" );
    std::array ps{particles...};
    for ( auto i = 0u; i < ps.size(); ++i ) {
      for ( auto j = i + 1; j < ps.size(); ++j ) {
        if ( ps[i] == ps[j] || ( ps[i]->track() != nullptr && ps[i]->track() == ps[j]->track() ) ) { return true; }
      }
    }
    return false;
  }
} // namespace detail

Marco Clemencic's avatar
v19r1  
Marco Clemencic committed
45
46
47
//=============================================================================
// Standard constructor, initializes variables
//=============================================================================
Gitlab CI's avatar
Gitlab CI committed
48
CheckOverlap::CheckOverlap( const std::string& type, const std::string& name, const IInterface* parent )
Niklas Stefan Nolte's avatar
Niklas Stefan Nolte committed
49
    : base( type, name, parent ), m_ppSvc( nullptr ) {}
Marco Clemencic's avatar
v19r1  
Marco Clemencic committed
50
51
52
53
54
55
56
57
58
59
60
61

//===========================================================================
/// Check for duplicate use of a protoparticle to produce particles.
/// Continue a previous check using the contents of the vector of pointers
/// to protoparticles.(Most intended for internal use by the recursive calls).
/// Arguments: parts is a vector of pointer to particles.
///            proto is a vector of pointers to protoparticles.
//  Real checking method. Scans the tree headed by parts. Add each
//  protoparticle to proto if it is a new one. Return true otherwise.
//  If called directly by the user, it will continue a previous check,
//  not start a new one!
//===========================================================================
Gitlab CI's avatar
Gitlab CI committed
62
bool CheckOverlap::foundOverlap( const LHCb::Particle::ConstVector&       parts,
Niklas Stefan Nolte's avatar
Niklas Stefan Nolte committed
63
                                 std::vector<const LHCb::ProtoParticle*>& proto ) const {
Gitlab CI's avatar
Gitlab CI committed
64
65
  if ( msgLevel( MSG::VERBOSE ) )
    verbose() << "foundOverlap(parts, protos) " << parts.size() << " " << proto.size() << endmsg;
Marco Clemencic's avatar
v19r1  
Marco Clemencic committed
66
  const bool sc = addOrigins( parts, proto );
Gitlab CI's avatar
Gitlab CI committed
67
68
  if ( !sc ) { Exception( "Unable to get origin vector of particle vector" ); }
  if ( msgLevel( MSG::VERBOSE ) ) verbose() << "searching overlap" << endmsg;
Marco Clemencic's avatar
v19r1  
Marco Clemencic committed
69
70
71
72
73
74
  return searchOverlap( proto );
}

//===========================================================================
// Check duplicate entries
//===========================================================================
Niklas Stefan Nolte's avatar
Niklas Stefan Nolte committed
75
bool CheckOverlap::searchOverlap( std::vector<const LHCb::ProtoParticle*>& proto ) const {
Gitlab CI's avatar
Gitlab CI committed
76
  if ( msgLevel( MSG::VERBOSE ) ) verbose() << "searchOverlap(protos)" << endmsg;
Marco Clemencic's avatar
v19r1  
Marco Clemencic committed
77
78
  // It its a simple particle made from protoparticle. Check.

Gitlab CI's avatar
Gitlab CI committed
79
80
81
82
83
  for ( std::vector<const LHCb::ProtoParticle*>::const_iterator i = proto.begin(); i != proto.end(); ++i ) {
    auto itrack = ( *i )->track();
    for ( std::vector<const LHCb::ProtoParticle*>::const_iterator j = i; j != proto.end(); ++j ) {
      if ( j == i ) continue;
      auto jtrack = ( *j )->track();
84
85
86
      // We should only perform a track comparison with non-null track
      // pointers, else we will determine all neutrals and composites to
      // overlap with each other (they have nullptr tracks)
Gitlab CI's avatar
Gitlab CI committed
87
88
89
90
      bool compare_tracks = ( itrack != nullptr ) && ( jtrack != nullptr );
      if ( *i == *j || ( compare_tracks && itrack == jtrack ) ) {
        if ( msgLevel( MSG::VERBOSE ) ) verbose() << "Found overlap " << *i << endmsg;
        return true;
Marco Clemencic's avatar
v19r1  
Marco Clemencic committed
91
92
93
      }
    }
  }
Gitlab CI's avatar
Gitlab CI committed
94
  if ( msgLevel( MSG::VERBOSE ) ) verbose() << "Found no overlap" << endmsg;
Marco Clemencic's avatar
v19r1  
Marco Clemencic committed
95
96
97
  return false;
}
//===========================================================================
Niklas Stefan Nolte's avatar
Niklas Stefan Nolte committed
98
bool CheckOverlap::foundOverlap( const LHCb::Particle::ConstVector& parts ) const {
Gitlab CI's avatar
Gitlab CI committed
99
  if ( msgLevel( MSG::VERBOSE ) ) verbose() << "foundOverlap(LHCb::Particle::ConstVector)" << endmsg;
Niklas Stefan Nolte's avatar
Niklas Stefan Nolte committed
100
101
  std::vector<const LHCb::ProtoParticle*> proto{};
  proto.reserve( 10 );
Marco Clemencic's avatar
v19r1  
Marco Clemencic committed
102
103
104
  return foundOverlap( parts, proto );
}
//===========================================================================
Niklas Stefan Nolte's avatar
Niklas Stefan Nolte committed
105
bool CheckOverlap::foundOverlap( const LHCb::Particle* particle1 ) const {
Gitlab CI's avatar
Gitlab CI committed
106
107
  if ( msgLevel( MSG::VERBOSE ) ) verbose() << "foundOverlap(1)" << endmsg;
  if ( !particle1 ) Exception( "Null pointer" );
Niklas Stefan Nolte's avatar
Niklas Stefan Nolte committed
108
109
110
  const LHCb::Particle::ConstVector       parts( 1, particle1 );
  std::vector<const LHCb::ProtoParticle*> proto{};
  proto.reserve( 10 );
Marco Clemencic's avatar
v19r1  
Marco Clemencic committed
111
112
113
  return foundOverlap( parts, proto );
}
//===========================================================================
Niklas Stefan Nolte's avatar
Niklas Stefan Nolte committed
114
bool CheckOverlap::foundOverlap( const LHCb::Particle* particle1, const LHCb::Particle* particle2 ) const {
Gitlab CI's avatar
Gitlab CI committed
115
116
  if ( msgLevel( MSG::VERBOSE ) ) verbose() << "foundOverlap(2)" << endmsg;
  if ( !particle1 || !particle2 ) Exception( "Null pointer" );
117
118
119
  if ( particle1->proto() != nullptr && particle2->proto() != nullptr ) {
    return detail::find_overlap_in_basics( particle1->proto(), particle2->proto() );
  }
Niklas Stefan Nolte's avatar
Niklas Stefan Nolte committed
120
  LHCb::Particle::ConstVector parts( 2 );
Marco Clemencic's avatar
v19r1  
Marco Clemencic committed
121
122
  parts[0] = particle1;
  parts[1] = particle2;
Niklas Stefan Nolte's avatar
Niklas Stefan Nolte committed
123
124
  std::vector<const LHCb::ProtoParticle*> proto{};
  proto.reserve( 10 );
Marco Clemencic's avatar
v19r1  
Marco Clemencic committed
125
126
127
  return foundOverlap( parts, proto );
}
//===========================================================================
Gitlab CI's avatar
Gitlab CI committed
128
bool CheckOverlap::foundOverlap( const LHCb::Particle* particle1, const LHCb::Particle* particle2,
Niklas Stefan Nolte's avatar
Niklas Stefan Nolte committed
129
                                 const LHCb::Particle* particle3 ) const {
Gitlab CI's avatar
Gitlab CI committed
130
131
  if ( msgLevel( MSG::VERBOSE ) ) verbose() << "foundOverlap(3)" << endmsg;
  if ( !particle1 || !particle2 || !particle3 ) Exception( "Null pointer" );
132
133
134
  if ( particle1->proto() != nullptr && particle2->proto() != nullptr && particle3->proto() != nullptr ) {
    return detail::find_overlap_in_basics( particle1->proto(), particle2->proto(), particle3->proto() );
  }
Niklas Stefan Nolte's avatar
Niklas Stefan Nolte committed
135
  LHCb::Particle::ConstVector parts( 3 );
Gitlab CI's avatar
Gitlab CI committed
136
137
138
  parts[0] = particle1;
  parts[1] = particle2;
  parts[2] = particle3;
Niklas Stefan Nolte's avatar
Niklas Stefan Nolte committed
139
140
  std::vector<const LHCb::ProtoParticle*> proto{};
  proto.reserve( 10 );
Marco Clemencic's avatar
v19r1  
Marco Clemencic committed
141
142
143
  return foundOverlap( parts, proto );
}
//===========================================================================
Gitlab CI's avatar
Gitlab CI committed
144
bool CheckOverlap::foundOverlap( const LHCb::Particle* particle1, const LHCb::Particle* particle2,
Niklas Stefan Nolte's avatar
Niklas Stefan Nolte committed
145
                                 const LHCb::Particle* particle3, const LHCb::Particle* particle4 ) const {
Gitlab CI's avatar
Gitlab CI committed
146
147
  if ( msgLevel( MSG::VERBOSE ) ) verbose() << "foundOverlap(4)" << endmsg;
  if ( !particle1 || !particle2 || !particle3 || !particle4 ) Exception( "Null pointer" );
148
149
150
151
152
  if ( particle1->proto() != nullptr && particle2->proto() != nullptr && particle3->proto() != nullptr &&
       particle4->proto() != nullptr ) {
    return detail::find_overlap_in_basics( particle1->proto(), particle2->proto(), particle3->proto(),
                                           particle4->proto() );
  }
Niklas Stefan Nolte's avatar
Niklas Stefan Nolte committed
153
  LHCb::Particle::ConstVector parts( 4 );
Gitlab CI's avatar
Gitlab CI committed
154
155
156
157
  parts[0] = particle1;
  parts[1] = particle2;
  parts[2] = particle3;
  parts[3] = particle4;
Niklas Stefan Nolte's avatar
Niklas Stefan Nolte committed
158
159
  std::vector<const LHCb::ProtoParticle*> proto{};
  proto.reserve( 10 );
Marco Clemencic's avatar
v19r1  
Marco Clemencic committed
160
161
162
163
164
165
  return foundOverlap( parts, proto );
}
//===========================================================================
// Check for duplicate use of a protoparticle to produce decay tree of
// any particle in vector. Removes found particles from vector.
//===========================================================================
Niklas Stefan Nolte's avatar
Niklas Stefan Nolte committed
166
StatusCode CheckOverlap::removeOverlap( LHCb::Particle::Vector& PV ) const {
Gitlab CI's avatar
Gitlab CI committed
167
  if ( msgLevel( MSG::VERBOSE ) ) verbose() << "removeOverlap( LHCb::Particle::Vector)" << endmsg;
Marco Clemencic's avatar
v19r1  
Marco Clemencic committed
168
  LHCb::Particle::Vector Out;
Gitlab CI's avatar
Gitlab CI committed
169
170
171
  Out.reserve( PV.size() );
  for ( LHCb::Particle::Vector::const_iterator i = PV.begin(); i != PV.end(); ++i ) {
    if ( !foundOverlap( *i ) ) Out.push_back( *i );
Marco Clemencic's avatar
v19r1  
Marco Clemencic committed
172
  }
Gitlab CI's avatar
Gitlab CI committed
173
174
  PV = Out;
  return StatusCode::SUCCESS;
Marco Clemencic's avatar
v19r1  
Marco Clemencic committed
175
176
}
//===========================================================================
Niklas Stefan Nolte's avatar
Niklas Stefan Nolte committed
177
StatusCode CheckOverlap::removeOverlap( LHCb::Particle::ConstVector& PV ) const {
Gitlab CI's avatar
Gitlab CI committed
178
179
180
181
182
  if ( msgLevel( MSG::VERBOSE ) ) verbose() << "removeOverlap(LHCb::Particle::ConstVector)" << endmsg;
  LHCb::Particle::ConstVector Out;
  Out.reserve( PV.size() );
  for ( LHCb::Particle::ConstVector::const_iterator i = PV.begin(); i != PV.end(); ++i ) {
    if ( !foundOverlap( *i ) ) Out.push_back( *i );
Marco Clemencic's avatar
v19r1  
Marco Clemencic committed
183
  }
Gitlab CI's avatar
Gitlab CI committed
184
185
  PV = Out;
  return StatusCode::SUCCESS;
Marco Clemencic's avatar
v19r1  
Marco Clemencic committed
186
187
188
189
}
//=============================================================================
// Replace resonance by daughters in vector, helper to the Tree methods
//=============================================================================
Gitlab CI's avatar
Gitlab CI committed
190
bool CheckOverlap::addOrigins( const LHCb::Particle::ConstVector&       parts,
Niklas Stefan Nolte's avatar
Niklas Stefan Nolte committed
191
                               std::vector<const LHCb::ProtoParticle*>& protos ) const {
Gitlab CI's avatar
Gitlab CI committed
192
  if ( msgLevel( MSG::VERBOSE ) ) verbose() << "addOrigins() " << parts.size() << endmsg;
Marco Clemencic's avatar
v19r1  
Marco Clemencic committed
193

Gitlab CI's avatar
Gitlab CI committed
194
  for ( LHCb::Particle::ConstVector::const_iterator c = parts.begin(); c != parts.end(); ++c ) {
Marco Clemencic's avatar
v19r1  
Marco Clemencic committed
195

Gitlab CI's avatar
Gitlab CI committed
196
197
    if ( msgLevel( MSG::VERBOSE ) )
      verbose() << "Particle " << ( *c )->particleID().pid() << " " << ( *c )->momentum() << endmsg;
Marco Clemencic's avatar
v19r1  
Marco Clemencic committed
198

Gitlab CI's avatar
Gitlab CI committed
199
200
201
202
203
204
205
206
207
    if ( ( *c )->proto() ) {
      if ( msgLevel( MSG::VERBOSE ) ) verbose() << "has an origin " << ( *c )->proto() << endmsg;
      protos.push_back( ( *c )->proto() );
    } else if ( !( ( *c )->daughters().empty() ) ) {
      if ( msgLevel( MSG::VERBOSE ) ) verbose() << "has a daughters " << ( *c )->daughters().size() << endmsg;
      const LHCb::Particle::ConstVector& dau = ( *c )->daughtersVector();
      const bool                         sc  = addOrigins( dau, protos );
      if ( !sc ) return sc;
    } else {
Niklas Stefan Nolte's avatar
Niklas Stefan Nolte committed
208
      if ( m_ppSvc == nullptr ) { throw GaudiException{"", "", StatusCode::FAILURE}; }
Gitlab CI's avatar
Gitlab CI committed
209
210
211
212
213
214
215
      const LHCb::ParticleProperty* pp = m_ppSvc->find( ( *c )->particleID() );
      if ( 0 != pp ) {
        Warning( pp->particle() + " has no proto nor endVertex. Assuming it's from MC.", StatusCode{10}, 1 ).ignore();
      } else {
        err() << "Particle with unknown PID " << ( *c )->particleID().pid() << " has no endVertex. "
              << "Assuming it's from MC" << endmsg;
      }
Marco Clemencic's avatar
v19r1  
Marco Clemencic committed
216
217
218
    }
  }

Gitlab CI's avatar
Gitlab CI committed
219
220
  if ( msgLevel( MSG::VERBOSE ) ) verbose() << "addOrigins() left " << protos.size() << endmsg;
  return true;
Marco Clemencic's avatar
v19r1  
Marco Clemencic committed
221
}