Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • gpietrzy/Rec
  • nbehling/Rec
  • rrabadan/Rec
  • hyeung/Rec
  • smokhnen/Rec
  • padeken/Rec
  • peilian/Rec
  • lambda-hse/Rec
  • mstahl/Rec
  • kklimasz/Rec
  • mimazure/Rec
  • aszabels/Rec
  • wkrzemie/Rec
  • aalvesju/Rec
  • fkeizer/Rec
  • valassi/Rec
  • raaij/Rec
  • sstahl/Rec
  • jonrob/Rec
  • dcampora/Rec
  • graven/Rec
  • lhcb/Rec
22 results
Show changes
Commits on Source (147)
Showing
with 810 additions and 779 deletions
......@@ -11,7 +11,7 @@
cmake_minimum_required(VERSION 3.15)
project(Rec VERSION 35.21
project(Rec VERSION 36.2
LANGUAGES CXX)
# Enable testing with CTest/CDash
......@@ -77,7 +77,7 @@ lhcb_add_subdirectories(
Phys/DaVinciTypes
Phys/DecayTreeFitter
Phys/ExtraInfoTools
Phys/FunctionalFlavourTagging
Phys/FlavourTagging
Phys/GenericVertexFinder
Phys/JetAccessories
Phys/KalmanFilter
......
......@@ -33,23 +33,23 @@ constexpr bool isLeadingBX( std::uint16_t eventType ) {
}
constexpr bool isTrailingBX( std::uint16_t eventType ) {
return eventType & static_cast<std::uint16_t>( LHCb::ODIN::EventTypes::TriggerMaskPhysics );
return eventType & static_cast<std::uint16_t>( LHCb::ODIN::EventTypes::et_bit_10 );
}
constexpr bool isEmptyBeforeIsolatedBX( std::uint16_t eventType ) {
return eventType & static_cast<std::uint16_t>( LHCb::ODIN::EventTypes::TriggerMaskNoBias );
return eventType & static_cast<std::uint16_t>( LHCb::ODIN::EventTypes::et_bit_11 );
}
constexpr bool isEmptyAfterIsolatedBX( std::uint16_t eventType ) {
return eventType & static_cast<std::uint16_t>( LHCb::ODIN::EventTypes::TriggerMaskBeam1Gas );
return eventType & static_cast<std::uint16_t>( LHCb::ODIN::EventTypes::et_bit_12 );
}
constexpr bool isEmptyBeforeLeadingBX( std::uint16_t eventType ) {
return eventType & static_cast<std::uint16_t>( LHCb::ODIN::EventTypes::TriggerMaskBeam2Gas );
return eventType & static_cast<std::uint16_t>( LHCb::ODIN::EventTypes::et_bit_13 );
}
constexpr bool isEmptyAfterTrailingBX( std::uint16_t eventType ) {
return eventType & static_cast<std::uint16_t>( LHCb::ODIN::EventTypes::SequencerTrigger );
return eventType & static_cast<std::uint16_t>( LHCb::ODIN::EventTypes::et_bit_14 );
}
template <typename T>
......
......@@ -15,9 +15,9 @@ Muon/MuonInterfaces
gaudi_add_library(MuonInterfacesLib
SOURCES
src/Lib/MuonHit.cpp
src/Lib/MuonNeuron.cpp
src/Lib/MuonTrack.cpp
src/Lib/MuonCluster.cpp
src/Lib/Neuron.cpp
src/Lib/NNMuonTrack.cpp
LINK
PUBLIC
Gaudi::GaudiKernel
......@@ -26,6 +26,7 @@ gaudi_add_library(MuonInterfacesLib
LHCb::LHCbMathLib
LHCb::MuonDetLib
LHCb::TrackEvent
LHCb::MuonDAQLib
ROOT::GenVector
ROOT::MathCore
)
......
......@@ -11,26 +11,13 @@
#ifndef DICT_MUONINTERFACESDICT_H
#define DICT_MUONINTERFACESDICT_H 1
#include "MuonInterfaces/IMuonClusterRec.h"
#include "MuonInterfaces/IMuonHitDecode.h"
#include "MuonInterfaces/IMuonPadRec.h"
#include "MuonInterfaces/IMuonTrackMomRec.h"
#include "MuonInterfaces/IMuonTrackRec.h"
#include "MuonInterfaces/MuonHit.h"
#include "MuonInterfaces/MuonLogHit.h"
#include "MuonInterfaces/MuonLogPad.h"
#include "MuonInterfaces/MuonNeuron.h"
#include "MuonInterfaces/MuonTrack.h"
#include "MuonInterfaces/Neuron.h"
MuonLogHit l1;
MuonLogPad x1;
MuonHit m1;
MuonTrack t1;
MuonNeuron n1( nullptr, nullptr );
std::vector<MuonLogHit*> k1;
std::vector<MuonLogPad*> z1;
std::vector<MuonHit*> v1;
std::vector<MuonTrack*> h1;
std::vector<MuonNeuron*> w1;
#endif // DICT_MUONINTERFACESDICT_H
......@@ -10,21 +10,10 @@
-->
<lcgdict>
<class name = "IMuonHitDecode"/>
<class name = "IMuonPadRec"/>
<class name = "IMuonClusterRec"/>
<class name = "IMuonTrackRec"/>
<class name = "IMuonTrackMomRec"/>
<class name="MuonLogHit"/>
<class name="MuonLogPad"/>
<class name="MuonHit"/>
<class name="MuonTrack"/>
<class name="MuonNeuron"/>
<class name="std::vector<MuonLogHit*>"/>
<class name="std::vector<MuonLogPad*>"/>
<class name="std::vector<MuonHit*>"/>
<class name="std::vector<MuonTrack*>"/>
<class name="std::vector<MuonNeuron*>"/>
</lcgdict>
......
/*****************************************************************************\
* (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. *
\*****************************************************************************/
#pragma once
#include "MuonDet/DeMuonDetector.h"
#include "GaudiKernel/IAlgTool.h"
#include <vector>
class MuonHit;
class MuonLogPad;
class IMuonFastPosTool;
/**
* Interface to clustering algorithm for standalone muon reconstruction
* @author Giacomo GRAZIANI
* @date 2009-10-15
*/
struct IMuonClusterRec : extend_interfaces<IAlgTool> {
DeclareInterfaceID( IMuonClusterRec, 4, 0 );
virtual std::vector<MuonHit> clusters( const std::vector<MuonLogPad>& pads,
DeMuonDetector const& muonDetector ) const = 0;
};
/*****************************************************************************\
* (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. *
\*****************************************************************************/
#ifndef MUONID_IMUONCLUSTERREC2_H
#define MUONID_IMUONCLUSTERREC2_H 1
// Include files
// from STL
#include <memory>
#include <vector>
// from Gaudi
#include "GaudiKernel/IAlgTool.h"
#include "Kernel/STLExtensions.h"
#include "MuonInterfaces/IMuonPadRec.h"
struct ClusterVars {
std::array<int, 4> ncl{};
std::array<float, 4> avg_cs{};
};
/** @class IMuonClusterRec2 IMuonClusterRec2.h MuonInterfaces/IMuonClusterRec2.h
*
* Interface to clustering algorithm
* @author Marco Santimaria
* @date 2017-06-23
*/
struct IMuonClusterRec2 : extend_interfaces<IAlgTool> {
DeclareInterfaceID( IMuonClusterRec2, 1, 0 );
virtual ClusterVars clusters( LHCb::span<const MuonLogPad> pads ) const = 0;
};
#endif // MUONID_IMUONCLUSTERREC2_H
/*****************************************************************************\
* (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. *
\*****************************************************************************/
#pragma once
#include "Detector/Muon/TileID.h"
#include "Event/RawBank.h"
#include "MuonDet/DeMuonDetector.h"
#include "GaudiKernel/IAlgTool.h"
#include <vector>
class MuonLogHit;
/**
* @date 2008-01-25
*/
class IMuonHitDecode : public extend_interfaces<IAlgTool> {
public:
DeclareInterfaceID( IMuonHitDecode, 3, 0 );
/// list of decoded hits
virtual std::vector<MuonLogHit> hits( LHCb::RawBank::View const&, const DeMuonDetector& muonDetector ) const = 0;
virtual float tdc2ns( float TDCtime ) { return (float)( ( TDCtime - 7.5 ) * 25. / 16. ); }
virtual float tdc2ns_diff( float TDCdelta ) { return (float)( TDCdelta * 25. / 16. ); }
// specific for Online Monitoring
virtual int banksSize( LHCb::RawBank::BankType bankType, std::vector<int>& sizes ) = 0;
virtual unsigned int odeErrorWord( int T1, int BX ) = 0;
virtual int bankVersion() = 0;
virtual void dumpRawBanks() = 0;
virtual void dumpFrame( int Tell1, int ODE ) = 0;
virtual bool mappingIsOld() = 0;
virtual int l0id() = 0;
virtual int bcn() = 0;
virtual int cbcn() = 0;
virtual void setMultiBunch( int bxPerSide ) = 0;
virtual void unsetMultiBunch() = 0;
virtual bool multiBunch() = 0;
virtual int mbExtraBXPerside() = 0;
virtual bool centralBX() = 0;
virtual bool firstBX() = 0;
virtual bool lastBX() = 0;
virtual LHCb::Detector::Muon::TileID tileFromODE( int ODEnumber, int ODEchannel ) = 0;
virtual int odeIndex( int ODEnumber ) = 0;
virtual int channelsPerQuadrant( int station, int region ) = 0;
virtual int nPadX( int s ) = 0;
virtual int nPadY( int s ) = 0;
virtual int nPadXvy( int s, int r ) = 0;
virtual int nPadYvx( int s, int r ) = 0;
virtual float padSizeX( int station, int region ) = 0;
virtual float padSizeY( int station, int region ) = 0;
virtual float padSizeXvy( int station, int region ) = 0;
virtual float padSizeYvx( int station, int region ) = 0;
virtual LHCb::Detector::Muon::TileID tileFromLogCh( unsigned int q, unsigned int s, unsigned int r, short int io,
unsigned int ch ) = 0;
virtual bool completeEvent() = 0;
virtual void setCompleteEventMask( int mask ) { m_ceMask = mask; }
private:
int m_ceMask;
};
/*****************************************************************************\
* (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. *
\*****************************************************************************/
#ifndef MUONTOOLS_IMUONTIMECOR_H
#define MUONTOOLS_IMUONTIMECOR_H 1
// Include files
// from STL
#include <string>
// from Gaudi
#include "Detector/Muon/TileID.h"
#include "GaudiKernel/IAlgTool.h"
/** @class IMuonTimeCor IMuonTimeCor.h MuonTools/IMuonTimeCor.h
*
*
* @author Alessia Satta
* @date 2009-12-22
*/
struct IMuonTimeCor : extend_interfaces<IAlgTool> {
// Return the interface ID
DeclareInterfaceID( IMuonTimeCor, 2, 0 );
virtual StatusCode getCorrection( LHCb::Detector::Muon::TileID tile, int& cor ) = 0;
virtual StatusCode getOutCorrection( LHCb::Detector::Muon::TileID tile, int& cor ) = 0;
virtual StatusCode setOutCorrection( LHCb::Detector::Muon::TileID tile, int cor ) = 0;
virtual StatusCode writeOutCorrection() = 0;
virtual StatusCode writeCorrection() = 0;
};
#endif // MUONTOOLS_IMUONTIMECOR_H
/*****************************************************************************\
* (c) Copyright 2000-2022 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. *
\*****************************************************************************/
#ifndef MUONINTERFACES_IMUONTRACKMOMREC_H
#define MUONINTERFACES_IMUONTRACKMOMREC_H 1
// Include files
// from STL
#include <string>
// from Gaudi
#include "GaudiKernel/IAlgTool.h"
// from LHCb
#include "Event/Track.h"
class MuonTrack;
/** @class IMuonTrackMomRec IMuonTrackMomRec.h MuonInterfaces/IMuonTrackMomRec.h
*
*
* @author Giacomo Graziani
* @date 2010-02-10
*/
struct IMuonTrackMomRec : extend_interfaces<IAlgTool> {
// Return the interface ID
DeclareInterfaceID( IMuonTrackMomRec, 4, 0 );
virtual std::unique_ptr<LHCb::Track> recMomentum( MuonTrack& track ) const = 0;
virtual double getBdl() const = 0;
};
#endif // MUONINTERFACES_IMUONTRACKMOMREC_H
/*****************************************************************************\
* (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. *
\*****************************************************************************/
#pragma once
#include "Event/RawEvent.h"
#include "MuonDet/DeMuonDetector.h"
#include "GaudiKernel/IAlgTool.h"
#include <vector>
class MuonHit;
class MuonTrack;
class MuonNeuron;
/**
* @author Giovanni Passaleva / Giacomo Graziani
* @date 2008-04-11
*/
struct IMuonTrackRec : extend_interfaces<IAlgTool> {
DeclareInterfaceID( IMuonTrackRec, 3, 0 );
virtual std::tuple<std::vector<MuonHit>, std::vector<MuonTrack>, bool> const
tracks( LHCb::RawBank::View const&, const DeMuonDetector& ) const = 0;
virtual void setZref( double Zref ) = 0;
virtual void setPhysicsTiming( bool PhysTiming ) = 0;
virtual void setAssumeCosmics( bool AssumeCosmics ) = 0;
virtual void setAssumePhysics( bool AssumePhysics ) = 0;
};
......@@ -8,39 +8,39 @@
* granted to it by virtue of its status as an Intergovernmental Organization *
* or submit itself to any jurisdiction. *
\*****************************************************************************/
#ifndef MUONHIT_H
#define MUONHIT_H 1
#pragma once
#include <vector>
#include "Detector/Muon/TileID.h"
#include "Math/GenVector/PositionVector3D.h"
#include "Math/GenVector/VectorUtil.h"
#include "Math/Point3D.h"
#include "Math/Vector3D.h"
#include "MuonInterfaces/MuonLogPad.h"
class MuonLogHit;
class IMuonFastPosTool;
/** @class MuonHit MuonHit.h
* represents hits for muon track (cluster of muon logical pads)
/** @class MuonPad MuonPad.h
*
* @author Giovanni Passaleva, Giacomo Graziani
* @date 2007-10-26
* Muon pad class for standalone muon track reconstruction
* @author Alessia
* @date 2022-09-29
*/
#include "Detector/Muon/TileID.h"
#include "GaudiKernel/Vector3DTypes.h"
#include "MuonDAQ/CommonMuonHit.h"
#include "MuonDAQ/MuonHitContainer.h"
#include "MuonDet/DeMuonDetector.h"
#include "MuonInterfaces/MuonPad.h"
#include <ostream>
#include <vector>
namespace MuonClusterContainerLocation {
inline const std::string Default = "Muon/MuonClusters";
}
class MuonHit final : public ROOT::Math::PositionVector3D<ROOT::Math::Cartesian3D<double>> {
class MuonCluster final {
public:
MuonHit();
/// constructor for empty cluster
MuonHit( IMuonFastPosTool const* posTool );
/// constructor from a MuonPad
MuonHit( const MuonLogPad* mp, IMuonFastPosTool const* posTool );
/// standard constructor
MuonCluster() = default;
/// constructor from pad
MuonCluster( const MuonPad* pad, const DeMuonDetector::TilePosition pad_position ) {
createFromPad( pad, pad_position );
}
// public member functions
/// add a logical pad to this cluster
void addPad( const MuonLogPad* mp );
/// add a pad to this cluster
void addPad( const MuonPad* pad, const DeMuonDetector::TilePosition pad_position );
/// store a progressive hit number for debugging
void setHitID( int id );
......@@ -48,10 +48,11 @@ public:
int hitPID() const { return m_pid; }
int hitMother() const { return m_mamy_pid; }
/// return the logical channels used for this cluster
std::vector<const MuonLogHit*> getHits() const;
std::vector<const CommonMuonHit*> getHits() const;
/// return the MuonTileIDs of the logical channels used for this cluster
std::vector<LHCb::Detector::Muon::TileID> getTiles() const;
/// get the raw times of logical channels in this cluster
std::vector<float> getTimes() const;
std::array<double, 3> hitTile_Size() const; /// half-sizes of the tile(s) underlying this hit
double hitTile_dX() const /// dx half-size of the tile underlying this hit
......@@ -74,9 +75,9 @@ public:
/// retireve the hit ID
int hitID() const { return m_hit_ID; }
/// return the hit station
int station() const { return m_pads.empty() ? -1 : (int)m_pads[0]->tile().station(); }
int station() const { return m_pads.empty() ? -1 : m_pads[0]->tile().station(); }
/// return the hit region
int region() const { return m_pads.empty() ? -1 : (int)m_pads[0]->tile().region(); }
int region() const { return m_pads.empty() ? -1 : m_pads[0]->tile().region(); }
/// return the (first) MuonTileID of the underlying logical pad
LHCb::Detector::Muon::TileID tile() const {
return !m_pads.empty() ? m_pads.front()->tile() : LHCb::Detector::Muon::TileID{};
......@@ -86,55 +87,67 @@ public:
/// check if this is a true logical and not an uncrossed log. channel
bool isTruePad() const { return !m_pads.empty() && m_pads.front()->truepad(); }
/// return the (first) associated MuonLogPad object
const MuonLogPad* logPad() const { return !m_pads.empty() ? m_pads[0] : nullptr; }
/// return the associated MuonLogPad objects
const std::vector<const MuonLogPad*>& logPads() const { return m_pads; }
/// return the (first) associated MuonPad object
const MuonPad* pad() const { return !m_pads.empty() ? m_pads[0] : nullptr; }
/// return the associated MuonPad objects
const std::vector<const MuonPad*>& pads() const { return m_pads; }
/// return the MuonTileIDs of the logical pads used for this cluster
std::vector<LHCb::Detector::Muon::TileID> getLogPadTiles() const;
std::vector<LHCb::Detector::Muon::TileID> getPadTiles() const;
/// number of logical pads in this hit
int npads() const { return m_pads.size(); }
int clsizeX() const { return m_xsize; } /// cluster size in X
int clsizeY() const { return m_ysize; } /// cluster size in Y
double dX() const { return m_dx; } /// error on X position
double dY() const { return m_dy; } /// error on Y position
double dZ() const { return m_dz; } /// error on Z position
double minX() const { return m_hit_minx; }
double maxX() const { return m_hit_maxx; }
double minY() const { return m_hit_miny; }
double maxY() const { return m_hit_maxy; }
double minZ() const { return m_hit_minz; }
double maxZ() const { return m_hit_maxz; }
int npads() const { return m_pads.size(); }
int clsizeX() const { return m_xsize; } /// cluster size in X
int clsizeY() const { return m_ysize; } /// cluster size in Y
double dX() const { return m_dx; } /// error on X position
double dY() const { return m_dy; } /// error on Y position
double dZ() const { return m_dz; } /// error on Z position
double minX() const { return m_hit_minx; }
double maxX() const { return m_hit_maxx; }
double minY() const { return m_hit_miny; }
double maxY() const { return m_hit_maxy; }
double minZ() const { return m_hit_minz; }
double maxZ() const { return m_hit_maxz; }
double X() const { return m_position.X(); }
double Y() const { return m_position.Y(); }
double Z() const { return m_position.Z(); }
Gaudi::XYZVector pos() const { return m_position; }
MuonCluster& SetXYZ( double x, double y, double z ) {
m_position = {x, y, z};
return *this;
}
private:
void createFromPad( const MuonLogPad* mp );
void createFromPad( const MuonPad* pad, const DeMuonDetector::TilePosition pad_position );
void recomputeTime();
private:
IMuonFastPosTool const* m_posTool = nullptr;
std::vector<const MuonLogPad*> m_pads;
std::vector<double> m_padx;
std::vector<double> m_pady;
std::vector<double> m_padz;
double m_dx = 0;
double m_dy = 0;
double m_dz = 0;
double m_hit_minx = 0;
double m_hit_maxx = 0;
double m_hit_miny = 0;
double m_hit_maxy = 0;
double m_hit_minz = 0;
double m_hit_maxz = 0;
float m_time = 0;
float m_dtime = 0;
float m_mintime = 0;
float m_maxtime = 0;
int m_pid = 0;
int m_mamy_pid = 0;
int m_hit_ID = -1;
int m_xsize = 0;
int m_ysize = 0;
int m_zsize = 0;
std::vector<const MuonPad*> m_pads;
std::vector<double> m_padx;
std::vector<double> m_pady;
std::vector<double> m_padz;
Gaudi::XYZVector m_position{};
double m_dx = 0;
double m_dy = 0;
double m_dz = 0;
double m_hit_minx = 0;
double m_hit_maxx = 0;
double m_hit_miny = 0;
double m_hit_maxy = 0;
double m_hit_minz = 0;
double m_hit_maxz = 0;
float m_time = 0;
float m_dtime = 0;
float m_mintime = 0;
float m_maxtime = 0;
int m_pid = 0;
int m_mamy_pid = 0;
int m_hit_ID = -1;
int m_xsize = 0;
int m_ysize = 0;
int m_zsize = 0;
};
#endif // MUONHIT_H
using MuonClusters = std::vector<MuonCluster, LHCb::Allocators::EventLocal<MuonCluster>>;
typedef std::vector<const MuonCluster*> ConstMuonClusters;
typedef const Gaudi::Range_<MuonClusters> MuonClusterRange;
typedef const Gaudi::Range_<ConstMuonClusters> ConstMuonClusterRange;
......@@ -19,28 +19,28 @@ public:
MuonLogHit() = default;
/// constructor from tile
explicit MuonLogHit( LHCb::Detector::Muon::TileID tile ) : m_tile( tile ) {}
inline LHCb::Detector::Muon::TileID tile() const { return m_tile; }
inline int odeNumber() const { return m_ODEnumber; }
inline void setOdeNumber( unsigned int& OdeNumber ) { m_ODEnumber = (int)OdeNumber; }
inline int odeChannel() const { return m_ODEchannel; }
inline void setOdeChannel( unsigned int& OdeChannel ) { m_ODEchannel = (int)OdeChannel; }
inline int odeIndex() const { return m_ODEindex; }
inline void setOdeIndex( short int& OdeIndex ) { m_ODEindex = (int)OdeIndex; }
inline float time() const { // avoid bias due to bins 0 and 1 being added in bin 1
LHCb::Detector::Muon::TileID tile() const { return m_tile; }
int odeNumber() const { return m_ODEnumber; }
void setOdeNumber( unsigned int& OdeNumber ) { m_ODEnumber = (int)OdeNumber; }
int odeChannel() const { return m_ODEchannel; }
void setOdeChannel( unsigned int& OdeChannel ) { m_ODEchannel = (int)OdeChannel; }
int odeIndex() const { return m_ODEindex; }
void setOdeIndex( short int& OdeIndex ) { m_ODEindex = (int)OdeIndex; }
float time() const { // avoid bias due to bins 0 and 1 being added in bin 1
return (float)( ( m_time + 50 * 16 ) % 16 == 1 ? m_time - 0.499 : m_time );
}
inline int rawtime() const { return m_time; }
inline bool intime() const { return ( m_time > -1 && m_time < 16 ); }
inline int bx() { return ( ( m_time + 160 ) / 16 - 10 ); }
int rawtime() const { return m_time; }
bool intime() const { return ( m_time > -1 && m_time < 16 ); }
int bx() { return ( ( m_time + 160 ) / 16 - 10 ); }
inline void setTime( int TDCtime ) { m_time = TDCtime; }
inline std::string odeName() const {
void setTime( int TDCtime ) { m_time = TDCtime; }
std::string odeName() const {
std::stringstream sname;
sname << "Q" << ( m_tile.quarter() + 1 ) << "M" << ( m_tile.station() + 1 ) << "R" << ( m_tile.region() + 1 ) << "_"
<< m_ODEindex;
return sname.str();
}
inline int odeHwID() const {
int odeHwID() const {
return ( m_tile.quarter() + 1 ) * 1000 + ( m_tile.station() + 1 ) * 100 + ( m_tile.region() + 1 ) * 10 + m_ODEindex;
}
......
......@@ -43,57 +43,66 @@ public:
assignTimes( hit1->time(), hit2->time() );
}
// public member functions
typedef enum { NOX = 0, XONEFE = 1, XTWOFE = 2, UNPAIRED = 3 } LogPadType;
enum class Type { NOX = 0, XONEFE = 1, XTWOFE = 2, UNPAIRED = 3 };
/// returns the type of logical pad (uncrossed, crossed with 1 or 2 FE channels, or unpaired log. channel)
inline LogPadType type() const {
if ( !m_truepad ) return UNPAIRED;
LogPadType t = XONEFE;
Type type() const {
if ( !m_truepad ) return Type::UNPAIRED;
if ( m_tile.station() == 0 || ( m_tile.station() > 2 && m_tile.region() == 0 ) ) {
t = NOX; // single log. channel
return Type::NOX; // single log. channel
} else {
if ( m_tile.station() > 0 && m_tile.station() < 3 && m_tile.region() < 2 )
t = XTWOFE; // double readout for M23R12
return Type::XTWOFE; // double readout for M23R12
}
return t;
return Type::XONEFE;
}
inline LHCb::Detector::Muon::TileID tile() const { return m_tile; }
LHCb::Detector::Muon::TileID tile() const { return m_tile; }
inline void assignTimes( float t1, float t2 ) {
void assignTimes( float t1, float t2 ) {
m_time = 0.5 * ( t1 + t2 );
m_dtime = 0.5 * ( t1 - t2 );
}
inline void shiftTimes( float d1, float d2 ) {
void shiftTimes( float d1, float d2 ) {
if ( !m_padhits.second ) return;
float t1 = ( m_padhits.first )->time() + d1;
float t2 = ( m_padhits.second )->time() + d2;
assignTimes( t1, t2 );
}
inline void shiftTime( float delay ) { m_time += delay; }
void shiftTime( float delay ) { m_time += delay; }
/// return the pad time (averaged for crossed pads), in TDC bits
inline float time() const { return m_time; }
inline float timeX() const {
LogPadType t = type();
return (float)( ( t == XONEFE || t == XTWOFE ) ? m_time + m_dtime : -9999. );
float time() const { return m_time; }
float timeX() const {
switch ( type() ) {
case Type::XONEFE:
case Type::XTWOFE:
return m_time + m_dtime;
default:
return std::numeric_limits<float>::lowest();
}
}
inline float timeY() const {
LogPadType t = type();
return (float)( ( t == XONEFE || t == XTWOFE ) ? m_time - m_dtime : -9999. );
float timeY() const {
switch ( type() ) {
case Type::XONEFE:
case Type::XTWOFE:
return m_time - m_dtime;
default:
return std::numeric_limits<float>::lowest();
}
}
/// return the half difference of the two hit times for crossed pads, in TDC bits
inline float dtime() const { return m_dtime; }
float dtime() const { return m_dtime; }
/// true if this is the crossing of two logical channels
inline bool crossed() const { return m_crossed; }
bool crossed() const { return m_crossed; }
/// true if it's a real logical pad (if false, it's an unpaired logical channel)
inline bool truepad() const { return m_truepad; }
inline void settruepad() { m_truepad = true; }
inline bool intime() const { return m_intime; }
inline MuonLogHit* getHit( unsigned int i ) { return i == 0 ? m_padhits.first : i == 1 ? m_padhits.second : nullptr; }
inline std::vector<MuonLogHit*> getHits() const {
bool truepad() const { return m_truepad; }
void settruepad() { m_truepad = true; }
bool intime() const { return m_intime; }
MuonLogHit* getHit( unsigned int i ) { return i == 0 ? m_padhits.first : i == 1 ? m_padhits.second : nullptr; }
std::vector<MuonLogHit*> getHits() const {
return m_padhits.second ? std::vector<MuonLogHit*>{m_padhits.first, m_padhits.second}
: std::vector<MuonLogHit*>( 1, m_padhits.first );
}
......
/*****************************************************************************\
* (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. *
\*****************************************************************************/
#pragma once
#include "Math/GenVector/VectorUtil.h"
#include "Math/Point3D.h"
#include "Math/Vector3D.h"
#include "MuonInterfaces/MuonHit.h"
#include <iostream>
#include <list>
/**
* A MuonNeuron is an object that describes the neurons used in the NNET
* pattern recognition in the Muon Detector. A Neuron is an oriented segment
* conventionally pointing outward the intteraction point. It is built out
* of pairs of MuonHits belonging to different Muon stations. It is
* characterised by a tail, a head, a set of neurons to which it is connected
* to and the corresponding weights.
* By convention, station and region of a neuron are those of the tail
*
* @author Giovanni Passaleva
* @date 2007-08-21
*/
class MuonNeuron final {
public:
MuonNeuron( MuonHit* h, MuonHit* t );
MuonNeuron( MuonHit* h, MuonHit* t, int s, int r );
MuonNeuron( MuonHit* h, MuonHit* t, int hID, int tID, int s, int r );
/// public member functions
/// return neuron head
MuonHit* head() const { return m_head; }
/// returns the neuron tail
MuonHit* tail() const { return m_tail; }
/// return the neuorn station.
inline int station() const { return m_station; }
/// return neuron region
inline int region() const { return m_region; }
/// calculate the neuron length in terms of crossed stations
int stationDifference();
/// return neuron length
double len() const;
/// return neuron length along z
double deltaZ() const;
double deltaZ( const int st ) const;
/// return neuron length in xz projection
double lenXZ() const;
/// return neuron length in yz projection
double lenYZ() const;
/// angle with another neuron in space
double angle( const MuonNeuron& n );
/// angle with another neuron in XZ
double angleXZ( const MuonNeuron& n );
/// angle with another neuron in YZ
double angleYZ( const MuonNeuron& n );
/// check if this is th with n
bool tailHead( const MuonNeuron& n ) const;
/// check if this is ht with n
bool headTail( const MuonNeuron& n ) const;
/// check if this is tt with n
bool tailTail( const MuonNeuron& n ) const;
/// check if this is hh with n
bool headHead( const MuonNeuron& n ) const;
/// check if this is connected to n
bool connectedTo( const MuonNeuron& n ) const;
/// return the neuron projection in the xz plan
ROOT::Math::XYZVector projXZ();
/// return the neuron projection in the yz plan
ROOT::Math::XYZVector projYZ();
/// store the neuron weights
void setWeight( MuonNeuron* n, double ww );
/// return the neuron weights
std::list<std::pair<MuonNeuron*, double>> getWeights();
/// retain only the best HT and TH weights
void cleanupWeights();
/// kill double length neurons if there is a unit length one
void killDoubleLength();
void killDoubleLength( const float angcut );
/// set a neuron status
void setStatus( double st );
/// return neuron status
double status();
/// Neuron ID, a progressive number for debugging purposes
void setNeuronID( int id );
/// retireve ID
int neuronID();
/// assign an ID to head and tail points
void setHeadTailID( int hID, int tID );
/// retireve head and tail IDs. First = head, Second = tail
std::pair<int, int> headTailID();
private:
MuonHit* m_head = nullptr;
MuonHit* m_tail = nullptr;
ROOT::Math::XYZVector m_neuron;
ROOT::Math::XYZVector m_neuronXZ;
ROOT::Math::XYZVector m_neuronYZ;
std::pair<const MuonNeuron*, double> m_weight;
std::list<std::pair<MuonNeuron*, double>> m_weight_list;
double m_status{1.0};
int m_station{-1};
int m_region{-1};
int m_headID{-1};
int m_tailID{-1};
int m_ID{-1};
//
void removeWeight( MuonNeuron* pn );
};
/*****************************************************************************\
* (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. *
\*****************************************************************************/
#pragma once
/** @class MuonPad MuonPad.h
*
* Muon pad class for standalone muon track reconstruction
* @author Alessia
* @date 2022-09-29
*/
#include "Detector/Muon/TileID.h"
#include "MuonDAQ/CommonMuonHit.h"
#include "MuonDAQ/MuonHitContainer.h"
#include "MuonDet/DeMuonDetector.h"
#include "MuonLogPad.h"
#include <iostream>
#include <ostream>
#include <vector>
namespace MuonPadContainerLocation {
inline const std::string Default = "Muon/MuonPads";
}
class MuonPad final {
public:
using LogPadType = MuonLogPad::Type;
/// standard constructor
MuonPad() = default;
/// constructor for uncrossed pad
MuonPad( const CommonMuonHit* hit, bool truepad, LogPadType type )
: m_tile{hit->tile()}, m_truepad{truepad}, m_muonhit{hit}, m_type{type} {
// range of TDC: [0;15] 1 bin corresponds to 25/16 ns
constexpr int lowerTDCvalue = -1;
constexpr int upperTDCvalue = 16;
// do some gimnastic to fill strips or pads
if ( hit->uncrossed() ) {
m_crossed = false;
m_subtiles[0] = ( hit->subtiles() )[0];
m_time = hit->time();
if ( m_time > lowerTDCvalue && m_time < upperTDCvalue ) m_intime = true;
} else {
m_crossed = true;
m_subtiles[0] = ( hit->subtiles() )[0];
m_subtiles[1] = ( hit->subtiles() )[1];
assignTimes( hit->time(), hit->time() - hit->deltaTime() );
int t2 = hit->time() - hit->deltaTime();
if ( ( (int)hit->time() > lowerTDCvalue && (int)hit->time() < upperTDCvalue ) &&
( t2 > lowerTDCvalue && t2 < upperTDCvalue ) )
m_intime = true;
}
}
// public member functions
/// returns the type of logical pad (uncrossed, crossed with 1 or 2 FE channels, or unpaired log. channel)
LogPadType type() const { return m_type; }
LHCb::Detector::Muon::TileID tile() const { return m_tile; }
void assignTimes( float t1, float t2 ) {
m_time = 0.5 * ( t1 + t2 );
m_dtime = 0.5 * ( t1 - t2 );
}
/// return the pad time (averaged for crossed pads), in TDC bits
float time() const { return m_time; }
float timeX() const {
switch ( type() ) {
case LogPadType::XONEFE:
case LogPadType::XTWOFE:
return m_time + m_dtime;
default:
return std::numeric_limits<float>::lowest();
}
}
float timeY() const {
switch ( type() ) {
case LogPadType::XONEFE:
case LogPadType::XTWOFE:
return m_time - m_dtime;
default:
return std::numeric_limits<float>::lowest();
}
}
/// return the half difference of the two hit times for crossed pads, in TDC bits
float dtime() const { return m_dtime; }
/// true if this is the crossing of two logical channels
bool crossed() const { return m_crossed; }
/// true if it's a real logical pad (if false, it's an unpaired logical channel)
bool truepad() const { return m_truepad; }
void settruepad() { m_truepad = true; }
bool intime() const { return m_intime; }
LHCb::Detector::Muon::TileID getHitTile( unsigned int i ) {
if ( i == 0 ) return m_subtiles[0];
if ( i == 1 ) return m_subtiles[1];
return LHCb::Detector::Muon::TileID();
}
const CommonMuonHit* getHit() const { return m_muonhit; }
private:
bool m_crossed = false;
LHCb::Detector::Muon::TileID m_tile = {};
std::array<LHCb::Detector::Muon::TileID, 2> m_subtiles{{}};
float m_time = 0;
float m_dtime = 0;
bool m_truepad = false;
bool m_intime = false;
const CommonMuonHit* m_muonhit{nullptr};
LogPadType m_type = LogPadType::UNPAIRED;
};
using MuonPads = std::vector<MuonPad, LHCb::Allocators::EventLocal<MuonPad>>;
using ConstMuonPads = std::vector<const MuonPad*>;
using MuonPadRange = const Gaudi::Range_<MuonPads>;
using ConstMuonPadRange = const Gaudi::Range_<ConstMuonPads>;
......@@ -8,17 +8,26 @@
* granted to it by virtue of its status as an Intergovernmental Organization *
* or submit itself to any jurisdiction. *
\*****************************************************************************/
#ifndef MUONTRACKRECMUONTRACK_H
#define MUONTRACKRECMUONTRACK_H 1
#pragma once
// Include files
#include "MuonInterfaces/MuonHit.h"
#include "MuonInterfaces/MuonCluster.h"
#include <GaudiKernel/Point4DTypes.h>
#include <GaudiKernel/StatusCode.h>
#include <GaudiKernel/Vector3DTypes.h>
#include "GaudiKernel/Range.h"
#include "Kernel/EventLocalAllocator.h"
#include "Kernel/STLExtensions.h"
#include "Detector/Muon/TileID.h"
#include "MuonDet/DeMuonDetector.h"
#include <cmath>
#include <iostream>
#include <map>
#include <ostream>
#include <vector>
/** @class MuonTrack MuonTrack.h
*
* A MuonTrack is an object containing a list of MuonHits belonging to a muon
......@@ -29,35 +38,29 @@
* @date 2007-08-21
*/
#ifndef MUONTRACKRECNMSPC
namespace MuonTrackRec {
extern double muspeed;
extern double Zref;
extern bool PhysTiming;
extern bool IsCosmic;
extern bool IsPhysics;
} // namespace MuonTrackRec
#endif // MUONTRACKRECNMSPC
namespace NNMuonTrackContainerLocation {
inline const std::string Default = "Muon/NNMuonTracks";
}
class MuonTrack final {
class NNMuonTrack final {
public:
/// Standard constructor
MuonTrack() = default;
NNMuonTrack() = default;
/// public member functions
/// insert a hit in the track
void insert( const int id, MuonHit* xyz ) { m_muonTrack.emplace( id, xyz ); };
void insert( const int id, const MuonCluster* xyz ) { m_muonTrack.emplace( id, xyz ); };
/// store the best hit candidates in each station
void setBestCandidate( std::vector<const MuonHit*> bcand ) { m_bestcand = std::move( bcand ); }
void setBestCandidate( std::vector<const MuonCluster*> bcand ) { m_bestcand = std::move( bcand ); }
/// retrieve the array of best candidates. Best candidates
/// are sorted by station by construction
std::vector<const MuonHit*> bestCandidate() const { return m_bestcand; };
std::vector<const MuonCluster*> bestCandidate() const { return m_bestcand; };
/// set the clone flag
void setClone() { m_isClone = true; }
/// get the Clone flag
bool isClone() const { return m_isClone; }
/// return a vector with hits
std::vector<const MuonHit*> getHits() const;
std::vector<const MuonCluster*> getHits() const;
/// get the track span i.e. the max length in station units
int getSpan() const;
/// get the number of stations giving a hit to this track
......@@ -65,101 +68,87 @@ public:
// linear chi2 fit. Track is fitted separately in XZ, YZ, TZ (assuming speed of light)
StatusCode linFit();
// add XTalk tracks
StatusCode AddXTalk( const std::vector<MuonHit>& trackhits, float cut = 1.5, int m_skipStation = -1 );
StatusCode AddXTalk( const MuonClusters* trackhits, float cut = 1.5, int m_skipStation = -1 );
// linear fit to get particle speed
StatusCode speedFit();
inline double chi2x() const { return m_chi2x; } /// chi2/dof XZ
inline double chi2y() const { return m_chi2y; } /// chi2/dof YZ
StatusCode speedFit();
double chi2x() const { return m_chi2x; } /// chi2/dof XZ
double chi2y() const { return m_chi2y; } /// chi2/dof YZ
// slope XZ
inline double sx() const { return m_sx; }
double sx() const { return m_sx; }
// intercept XZ
inline double bx() const { return m_bx; }
double bx() const { return m_bx; }
// slope YZ
inline double sy() const { return m_sy; }
double sy() const { return m_sy; }
// direction (+1 forward or -1 backward)
double sz() const;
// intercept YZ
inline double by() const { return m_by; }
double by() const { return m_by; }
// track t0
inline double t0() const { return m_t0; }
double t0() const { return m_t0; }
// estimated error on time
inline double sigmat() const { return m_sigmat; }
double sigmat() const { return m_sigmat; }
// fitted speed (in c units)
inline double speed() {
if ( !m_speedFitted ) speedFit().ignore( /* AUTOMATICALLY ADDED FOR gaudi/Gaudi!763 */ );
double speed() {
if ( !m_speedFitted ) speedFit().ignore();
return m_speed;
}
// error on fitted speed (in c units)
inline double sigmaspeed() const { return m_sigmaspeed; }
double sigmaspeed() const { return m_sigmaspeed; }
// errors on the above parameters
inline double errsx() const { return m_errsx; }
inline double errbx() const { return m_errbx; }
inline double covbsx() const { return m_covbsx; }
inline double errsy() const { return m_errsy; }
inline double errby() const { return m_errby; }
inline double covbsy() const { return m_covbsy; }
inline double errt0() const { return m_errt0; }
double errsx() const { return m_errsx; }
double errbx() const { return m_errbx; }
double covbsx() const { return m_covbsx; }
double errsy() const { return m_errsy; }
double errby() const { return m_errby; }
double covbsy() const { return m_covbsy; }
double errt0() const { return m_errt0; }
// polar angles wrt beam axis (taking into account track direction)
inline double theta() const { return acos( sz() / sqrt( m_sx * m_sx + m_sy * m_sy + 1 ) ); }
inline double phi() const { return atan2( m_sy, m_sx ); }
double theta() const { return std::acos( sz() / std::sqrt( m_sx * m_sx + m_sy * m_sy + 1 ) ); }
double phi() const { return std::atan2( m_sy, m_sx ); }
// polar angles wrt vertical axis (pointing down)
inline double thetaVert() const { return acos( -( m_sy / sz() ) / sqrt( m_sx * m_sx + m_sy * m_sy + 1 ) ); }
inline double phiVert() const { return atan2( m_sx, sz() ); }
double thetaVert() const { return std::acos( -( m_sy / sz() ) / std::sqrt( m_sx * m_sx + m_sy * m_sy + 1 ) ); }
double phiVert() const { return std::atan2( m_sx, sz() ); }
// track extrapolation
void extrap( double Z, Gaudi::XYZTPoint& Pos, Gaudi::XYZTPoint* PosErr = NULL );
void extrap( double Z, Gaudi::XYZTPoint& Pos, Gaudi::XYZTPoint* PosErr = nullptr );
// residuals
Gaudi::XYZTPoint& residuals( MuonHit& hit );
Gaudi::XYZTPoint& residuals( const MuonCluster& hit );
// corrected time of i-th hit (i from 0)
double correctedTime( const MuonHit& hit ) const;
double correctedTime( const MuonCluster& hit ) const;
/// cluster size (total, and in the x/y views) associated to a given hit
/// (only if first hit of a given station, to avoid double counting)
int clsize( const MuonHit* hit, int& xsize, int& ysize ) const;
/// track momentum variables; setters
inline void setP( double p ) { m_trackP = p; }
inline void setPt( double pt ) { m_trackPt = pt; }
inline void setqOverP( double qp ) { m_trackqOverP = qp; }
inline void setMomentum( Gaudi::XYZVector mom ) { m_trackMomentum = mom; }
/// track momentum variables; getters
inline double p() const { return m_trackP; }
inline double pt() const { return m_trackPt; }
inline double qOverP() const { return m_trackqOverP; }
inline Gaudi::XYZVector momentum() const { return m_trackMomentum; }
int clsize( const MuonCluster* hit, int& xsize, int& ysize ) const;
private:
double correctTOF( double rawT, double X, double Y, double Z ) const;
double correctTime( double rawT, double X, double Y, double Z ) const;
typedef std::map<int, MuonHit*>::value_type MuonTkVtype;
std::map<int, MuonHit*> m_muonTrack;
std::vector<const MuonHit*> m_bestcand;
bool m_isClone = false;
double m_chi2x = -1.;
double m_chi2y = -1.;
double m_sx = -1.;
double m_bx = -1.;
double m_sy = -1.;
double m_by = -1.;
double m_errsx = -1.;
double m_errbx = -1.;
double m_covbsx = -1.;
double m_errsy = -1.;
double m_errby = -1.;
double m_covbsy = -1.;
double m_t0 = -1.;
double m_errt0 = -1.;
double m_sigmat = -1.;
double m_speed = 0.;
double m_sigmaspeed = 0.;
bool m_speedFitted = false;
Gaudi::XYZTPoint m_point;
// track momentum tracks
double m_trackP = 0.;
double m_trackPt = 0.;
double m_trackqOverP = 0.;
Gaudi::XYZVector m_trackMomentum = {0., 0., 0.};
//
double correctTOF( double rawT, double X, double Y, double Z ) const;
double correctTime( double rawT, double X, double Y, double Z ) const;
std::map<int, const MuonCluster*> m_muonTrack;
std::vector<const MuonCluster*> m_bestcand;
bool m_isClone = false;
double m_chi2x = -1.;
double m_chi2y = -1.;
double m_sx = -1.;
double m_bx = -1.;
double m_sy = -1.;
double m_by = -1.;
double m_errsx = -1.;
double m_errbx = -1.;
double m_covbsx = -1.;
double m_errsy = -1.;
double m_errby = -1.;
double m_covbsy = -1.;
double m_t0 = -1.;
double m_errt0 = -1.;
double m_sigmat = -1.;
double m_speed = 0.;
double m_sigmaspeed = 0.;
bool m_speedFitted = false;
Gaudi::XYZTPoint m_point;
};
#endif // MUONTRACKRECMUONTRACK_H
using NNMuonTracks = std::vector<NNMuonTrack, LHCb::Allocators::EventLocal<NNMuonTrack>>;
using ConstNNMuonTracks = std::vector<const NNMuonTrack*>;
using NNMuonTrackRange = const Gaudi::Range_<NNMuonTracks>;
using ConstNNMuonTrackRange = const Gaudi::Range_<ConstNNMuonTracks>;
/*****************************************************************************\
* (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. *
\*****************************************************************************/
#pragma once
#include "Math/GenVector/VectorUtil.h"
#include "Math/Point3D.h"
#include "Math/Vector3D.h"
#include "MuonInterfaces/MuonCluster.h"
#include <iostream>
#include <list>
/**
* A Neuron is an object that describes the neurons used in the NNET
* pattern recognition in the Muon Detector. A Neuron is an oriented segment
* conventionally pointing outward the intteraction point. It is built out
* of pairs of MuonHits belonging to different Muon stations. It is
* characterised by a tail, a head, a set of neurons to which it is connected
* to and the corresponding weights.
* By convention, station and region of a neuron are those of the tail
*
* @author Giovanni Passaleva
* @date 2007-08-21
*/
namespace LHCb::Muon {
class Neuron final {
public:
Neuron( const MuonCluster* h, const MuonCluster* t );
Neuron( const MuonCluster* h, const MuonCluster* t, int s, int r );
Neuron( const MuonCluster* h, const MuonCluster* t, int hID, int tID, int s, int r );
/// public member functions
/// return neuron head
const MuonCluster* head() const { return m_head; }
/// returns the neuron tail
const MuonCluster* tail() const { return m_tail; }
/// return the neuorn station.
int station() const { return m_station; }
/// return neuron region
int region() const { return m_region; }
/// calculate the neuron length in terms of crossed stations
int stationDifference();
/// return neuron length
double len() const;
/// return neuron length along z
// double deltaZ() const;
// double deltaZ( const int st ) const;
/// return neuron length in xz projection
double lenXZ() const;
/// return neuron length in yz projection
double lenYZ() const;
/// angle with another neuron in space
double angle( const Neuron& n );
/// angle with another neuron in XZ
double angleXZ( const Neuron& n );
/// angle with another neuron in YZ
double angleYZ( const Neuron& n );
/// check if this is th with n
bool tailHead( const Neuron& n ) const;
/// check if this is ht with n
bool headTail( const Neuron& n ) const;
/// check if this is tt with n
bool tailTail( const Neuron& n ) const;
/// check if this is hh with n
bool headHead( const Neuron& n ) const;
/// check if this is connected to n
bool connectedTo( const Neuron& n ) const;
/// return the neuron projection in the xz plan
ROOT::Math::XYZVector projXZ();
/// return the neuron projection in the yz plan
ROOT::Math::XYZVector projYZ();
/// store the neuron weights
void setWeight( Neuron* n, double ww );
/// return the neuron weights
const std::list<std::pair<Neuron*, double>>& getWeights() const;
/// retain only the best HT and TH weights
void cleanupWeights();
/// kill double length neurons if there is a unit length one
void killDoubleLength();
void killDoubleLength( const float angcut );
/// set a neuron status
void setStatus( double st );
/// return neuron status
double status();
/// Neuron ID, a progressive number for debugging purposes
void setNeuronID( int id );
/// retireve ID
int neuronID();
/// assign an ID to head and tail points
void setHeadTailID( int hID, int tID );
/// retireve head and tail IDs. First = head, Second = tail
std::pair<int, int> headTailID();
private:
const MuonCluster* m_head = nullptr;
const MuonCluster* m_tail = nullptr;
ROOT::Math::XYZVector m_neuron;
ROOT::Math::XYZVector m_neuronXZ;
ROOT::Math::XYZVector m_neuronYZ;
std::pair<const Neuron*, double> m_weight;
std::list<std::pair<Neuron*, double>> m_weight_list;
double m_status{1.0};
int m_station{-1};
int m_region{-1};
int m_headID{-1};
int m_tailID{-1};
int m_ID{-1};
//
void removeWeight( Neuron* pn );
};
} // namespace LHCb::Muon
/*****************************************************************************\
* (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. *
* (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. *
\*****************************************************************************/
// Include files
#include "MuonInterfaces/MuonHit.h"
#include "MuonDet/IMuonFastPosTool.h"
#include "MuonInterfaces/MuonLogHit.h"
#include "MuonInterfaces/MuonCluster.h"
#include "MuonInterfaces/MuonPad.h"
#include <cmath>
namespace {
double recomputePos( const std::vector<double>& data, double& dpos, int& clsize, double step ) {
double recomputeClusterPos( const std::vector<double>& data, double& dpos, int& clsize, double step ) {
int np = 0;
double sum = 0., sum2 = 0.;
for ( auto ip = data.begin(); ip != data.end(); ++ip ) {
......@@ -36,77 +35,32 @@ namespace {
}
} // namespace
MuonHit::MuonHit() = default;
MuonHit::MuonHit( IMuonFastPosTool const* posTool ) : m_posTool( posTool ) {}
//=============================================================================
// Constructor from a MuonLogPad
//=============================================================================
MuonHit::MuonHit( const MuonLogPad* mp, IMuonFastPosTool const* posTool )
: ROOT::Math::XYZPoint( 0., 0., 0. ), m_posTool( posTool ) {
createFromPad( mp );
}
void MuonHit::createFromPad( const MuonLogPad* mp ) {
void MuonCluster::createFromPad( const MuonPad* pad, const DeMuonDetector::TilePosition pos ) {
m_pads.clear();
if ( mp->type() == MuonLogPad::UNPAIRED ) return;
auto pos = m_posTool->calcTilePos( mp->tile() );
if ( pos ) {
m_pads.push_back( mp );
m_padx.push_back( pos->x() );
m_pady.push_back( pos->y() );
m_padz.push_back( pos->z() );
if ( pad->type() == MuonPad::LogPadType::UNPAIRED ) return;
if ( pos.z() > 0 ) {
m_pads.push_back( pad );
m_padx.push_back( pos.x() );
m_pady.push_back( pos.y() );
m_padz.push_back( pos.z() );
static const auto isqrt_12 = 1.0 / std::sqrt( 12. );
m_dx = isqrt_12 * pos->dX();
m_dy = isqrt_12 * pos->dY();
m_dz = isqrt_12 * pos->dZ();
m_hit_minx = pos->x() - pos->dX();
m_hit_maxx = pos->x() + pos->dX();
m_hit_miny = pos->y() - pos->dY();
m_hit_maxy = pos->y() + pos->dY();
m_hit_minz = pos->z() - pos->dZ();
m_hit_maxz = pos->z() + pos->dZ();
SetXYZ( pos->x(), pos->y(), pos->z() );
m_dx = isqrt_12 * pos.dX();
m_dy = isqrt_12 * pos.dY();
m_dz = isqrt_12 * pos.dZ();
m_hit_minx = pos.x() - pos.dX();
m_hit_maxx = pos.x() + pos.dX();
m_hit_miny = pos.y() - pos.dY();
m_hit_maxy = pos.y() + pos.dY();
m_hit_minz = pos.z() - pos.dZ();
m_hit_maxz = pos.z() + pos.dZ();
SetXYZ( pos.x(), pos.y(), pos.z() );
m_xsize = m_ysize = 1;
recomputeTime();
}
}
//=============================================================================
// public member functions
//
void MuonHit::addPad( const MuonLogPad* mp ) {
if ( mp->type() == MuonLogPad::UNPAIRED ) return;
if ( m_pads.empty() ) {
createFromPad( mp );
} else {
auto pos = m_posTool->calcTilePos( mp->tile() );
if ( pos ) {
m_pads.push_back( mp );
m_padx.push_back( pos->x() );
m_pady.push_back( pos->y() );
m_padz.push_back( pos->z() );
if ( ( pos->x() - pos->dX() ) < m_hit_minx ) m_hit_minx = pos->x() - pos->dX();
if ( ( pos->x() + pos->dX() ) > m_hit_maxx ) m_hit_maxx = pos->x() + pos->dX();
if ( ( pos->y() - pos->dY() ) < m_hit_miny ) m_hit_miny = pos->y() - pos->dY();
if ( ( pos->y() + pos->dY() ) > m_hit_maxy ) m_hit_maxy = pos->y() + pos->dY();
if ( ( pos->z() - pos->dZ() ) < m_hit_minz ) m_hit_minz = pos->z() - pos->dZ();
if ( ( pos->z() + pos->dZ() ) > m_hit_maxz ) m_hit_maxz = pos->z() + pos->dZ();
auto x = recomputePos( m_padx, m_dx, m_xsize, pos->dX() );
auto y = recomputePos( m_pady, m_dy, m_ysize, pos->dY() );
auto z = recomputePos( m_padz, m_dz, m_zsize, 10 * pos->dZ() );
SetXYZ( x, y, z );
recomputeTime();
}
}
}
void MuonHit::recomputeTime() {
void MuonCluster::recomputeTime() {
int np = 0;
float sum = 0., sum2 = 0.;
m_mintime = 999.;
......@@ -121,7 +75,7 @@ void MuonHit::recomputeTime() {
};
for ( const auto& pad : m_pads ) {
if ( pad->type() == MuonLogPad::XTWOFE ) { // consider the two measurements as independent
if ( pad->type() == MuonPad::LogPadType::XTWOFE ) { // consider the two measurements as independent
accumulate( pad->timeX() );
accumulate( pad->timeY() );
} else {
......@@ -138,55 +92,72 @@ void MuonHit::recomputeTime() {
}
}
void MuonCluster::addPad( const MuonPad* mp, const DeMuonDetector::TilePosition pos ) {
if ( mp->type() == MuonPad::LogPadType::UNPAIRED ) return;
if ( m_pads.empty() ) {
createFromPad( mp, pos );
} else {
if ( pos.z() > 0 ) {
m_pads.push_back( mp );
m_padx.push_back( pos.x() );
m_pady.push_back( pos.y() );
m_padz.push_back( pos.z() );
if ( ( pos.x() - pos.dX() ) < m_hit_minx ) m_hit_minx = pos.x() - pos.dX();
if ( ( pos.x() + pos.dX() ) > m_hit_maxx ) m_hit_maxx = pos.x() + pos.dX();
if ( ( pos.y() - pos.dY() ) < m_hit_miny ) m_hit_miny = pos.y() - pos.dY();
if ( ( pos.y() + pos.dY() ) > m_hit_maxy ) m_hit_maxy = pos.y() + pos.dY();
if ( ( pos.z() - pos.dZ() ) < m_hit_minz ) m_hit_minz = pos.z() - pos.dZ();
if ( ( pos.z() + pos.dZ() ) > m_hit_maxz ) m_hit_maxz = pos.z() + pos.dZ();
auto x = recomputeClusterPos( m_padx, m_dx, m_xsize, pos.dX() );
auto y = recomputeClusterPos( m_pady, m_dy, m_ysize, pos.dY() );
auto z = recomputeClusterPos( m_padz, m_dz, m_zsize, 10 * pos.dZ() );
SetXYZ( x, y, z );
recomputeTime();
}
}
}
/// return tile sizes
std::array<double, 3> MuonHit::hitTile_Size() const {
std::array<double, 3> MuonCluster::hitTile_Size() const {
return {( m_hit_maxx - m_hit_minx ) / 2., ( m_hit_maxy - m_hit_miny ) / 2., ( m_hit_maxz - m_hit_minz ) / 2.};
}
/// store a progressive hit number for debugging
void MuonHit::setHitID( int id ) {
void MuonCluster::setHitID( int id ) {
if ( id != 0 ) m_hit_ID = id;
}
std::vector<const MuonLogHit*> MuonHit::getHits() const {
std::vector<const MuonLogHit*> out;
std::vector<const CommonMuonHit*> MuonCluster::getHits() const {
std::vector<const CommonMuonHit*> out;
for ( const auto& pad : m_pads ) {
auto padhits = pad->getHits();
out.insert( out.end(), padhits.begin(), padhits.end() );
auto padhits = pad->getHit();
out.insert( out.end(), padhits );
}
return out;
}
std::vector<LHCb::Detector::Muon::TileID> MuonHit::getTiles() const {
std::vector<LHCb::Detector::Muon::TileID> tiles;
for ( const auto& pad : m_pads ) {
auto padhits = pad->getHits();
std::transform( padhits.begin(), padhits.end(), std::back_inserter( tiles ),
[]( const MuonLogHit* mlh ) { return mlh->tile(); } );
}
return tiles;
}
std::vector<LHCb::Detector::Muon::TileID> MuonHit::getLogPadTiles() const {
std::vector<LHCb::Detector::Muon::TileID> MuonCluster::getPadTiles() const {
std::vector<LHCb::Detector::Muon::TileID> tiles;
tiles.reserve( m_pads.size() );
std::transform( m_pads.begin(), m_pads.end(), std::back_inserter( tiles ),
[]( const MuonLogPad* mlp ) { return mlp->tile(); } );
[]( const MuonPad* mlp ) { return mlp->tile(); } );
return tiles;
}
std::vector<float> MuonHit::getTimes() const {
std::vector<float> MuonCluster::getTimes() const {
auto hits = getHits();
std::vector<float> times;
times.reserve( hits.size() );
std::transform( hits.begin(), hits.end(), std::back_inserter( times ),
[]( const MuonLogHit* mlh ) { return mlh->time(); } );
[]( const CommonMuonHit* mlh ) { return mlh->time(); } );
return times;
}
LHCb::Detector::Muon::TileID MuonHit::centerTile() const {
LHCb::Detector::Muon::TileID MuonCluster::centerTile() const {
if ( m_pads.size() == 1 ) return m_pads.front()->tile();
double d2min = 9999999.;
double d2min = std::numeric_limits<double>::max();
LHCb::Detector::Muon::TileID out;
for ( unsigned int ip = 0; ip < m_pads.size(); ip++ ) {
auto d2 = std::pow( m_padx[ip] - X(), 2 ) + std::pow( m_pady[ip] - Y(), 2 ) + std::pow( m_padz[ip] - Z(), 2 );
......@@ -195,10 +166,5 @@ LHCb::Detector::Muon::TileID MuonHit::centerTile() const {
out = m_pads[ip]->tile();
}
}
if ( !out.isDefined() ) {
for ( unsigned int ip = 0; ip < m_pads.size(); ip++ ) {
std::cout << m_padx[ip] << " " << m_pady[ip] << " " << m_padz[ip] << std::endl;
}
}
return out;
}
/*****************************************************************************\
* (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. *
\*****************************************************************************/
#include "MuonInterfaces/MuonNeuron.h"
MuonNeuron::MuonNeuron( MuonHit* h, MuonHit* t ) : m_head( h ), m_tail( t ) {
m_neuron = *t - *h;
m_neuronXZ.SetX( m_neuron.X() );
m_neuronXZ.SetY( 0. );
m_neuronXZ.SetZ( m_neuron.Z() );
m_neuronYZ.SetX( 0. );
m_neuronYZ.SetY( m_neuron.Y() );
m_neuronYZ.SetZ( m_neuron.Z() );
}
MuonNeuron::MuonNeuron( MuonHit* h, MuonHit* t, int s, int r )
: m_head( h ), m_tail( t ), m_station( s ), m_region( r ) {
m_neuron = *t - *h;
m_neuronXZ.SetX( m_neuron.X() );
m_neuronXZ.SetY( 0. );
m_neuronXZ.SetZ( m_neuron.Z() );
m_neuronYZ.SetX( 0. );
m_neuronYZ.SetY( m_neuron.Y() );
m_neuronYZ.SetZ( m_neuron.Z() );
}
MuonNeuron::MuonNeuron( MuonHit* h, MuonHit* t, int hID, int tID, int s, int r )
: m_head( h ), m_tail( t ), m_station( s ), m_region( r ), m_headID( hID ), m_tailID( tID ) {
m_neuron = *t - *h;
m_neuronXZ.SetX( m_neuron.X() );
m_neuronXZ.SetY( 0. );
m_neuronXZ.SetZ( m_neuron.Z() );
m_neuronYZ.SetX( 0. );
m_neuronYZ.SetY( m_neuron.Y() );
m_neuronYZ.SetZ( m_neuron.Z() );
}
/// clean up weights
void MuonNeuron::cleanupWeights() {
double wmaxTH = -9999;
double wmaxHT = -9999;
MuonNeuron* pmaxTH = nullptr;
MuonNeuron* pmaxHT = nullptr;
auto iw = m_weight_list.begin();
while ( ( iw != m_weight_list.end() ) && ( !m_weight_list.empty() ) ) {
MuonNeuron* ConnNeur = iw->first;
if ( tailHead( *ConnNeur ) ) {
if ( iw->second >= wmaxTH ) {
wmaxTH = iw->second;
pmaxTH = iw->first;
}
iw = m_weight_list.erase( iw );
( *ConnNeur ).removeWeight( this );
} else if ( headTail( *ConnNeur ) ) {
if ( iw->second >= wmaxHT ) {
wmaxHT = iw->second;
pmaxHT = iw->first;
}
iw = m_weight_list.erase( iw );
( *ConnNeur ).removeWeight( this );
} else {
iw++;
}
}
if ( pmaxTH ) {
setWeight( pmaxTH, wmaxTH );
pmaxTH->setWeight( this, wmaxTH );
}
if ( pmaxHT ) {
setWeight( pmaxHT, wmaxHT );
pmaxHT->setWeight( this, wmaxHT );
}
}
/// kill double length neurons if there is a unit length one
void MuonNeuron::killDoubleLength() {
// first check if there is at least 1 unit length neuron connected to this
auto iw = std::find_if( m_weight_list.begin(), m_weight_list.end(),
[]( const std::pair<MuonNeuron*, double>& w ) { return w.first->stationDifference() == 1; } );
bool go = ( iw != m_weight_list.end() );
if ( !go ) return;
iw = m_weight_list.begin();
while ( ( iw != m_weight_list.end() ) && ( !m_weight_list.empty() ) ) {
MuonNeuron* ConnNeur = iw->first;
if ( headHead( *ConnNeur ) || tailTail( *ConnNeur ) ) {
if ( ConnNeur->stationDifference() > 1 ) {
iw = m_weight_list.erase( iw );
( *ConnNeur ).removeWeight( this );
} else {
iw++;
}
} else {
iw++;
}
}
}
//
void MuonNeuron::removeWeight( MuonNeuron* pn ) {
auto iw = std::find_if( m_weight_list.begin(), m_weight_list.end(),
[&]( const std::pair<MuonNeuron*, double>& n ) { return n.first == pn; } );
if ( iw != m_weight_list.end() ) m_weight_list.erase( iw );
}
/// kill double length neurons if there is a unit length one
void MuonNeuron::killDoubleLength( const float angcut ) {
MuonNeuron* ConnNeur = 0;
MuonNeuron* ConnNeur1 = 0;
MuonNeuron* ConnNeur2 = 0;
if ( this->stationDifference() != 1 ) return;
// find L2 neurons in HH or TT and kill them if angleXZ smaller than 0.1
auto iw = m_weight_list.begin();
while ( ( iw != m_weight_list.end() ) && ( !m_weight_list.empty() ) ) {
ConnNeur = iw->first;
if ( headHead( *ConnNeur ) || tailTail( *ConnNeur ) ) {
if ( ConnNeur->stationDifference() > 1 && this->angleXZ( *ConnNeur ) < angcut ) {
iw = m_weight_list.erase( iw );
ConnNeur->removeWeight( this );
} else {
iw++;
}
} else {
iw++;
}
}
// find L1 neurons in HT. Then search for L2 neurons in HT close in angleXZ
// to the L1 one and kill them if angleXZ smaller than 0.1
auto iw1 = m_weight_list.begin();
while ( ( iw1 != m_weight_list.end() ) && ( !m_weight_list.empty() ) ) {
ConnNeur1 = iw1->first;
if ( headTail( *ConnNeur1 ) && ConnNeur1->stationDifference() == 1 ) {
// ok found an L1 HT with this. now search for an L2 HT
auto iw2 = m_weight_list.begin();
while ( ( iw2 != m_weight_list.end() ) && ( !m_weight_list.empty() ) ) {
ConnNeur2 = iw2->first;
if ( headTail( *ConnNeur2 ) && ConnNeur2->stationDifference() > 1 &&
ConnNeur2->angleXZ( *ConnNeur1 ) < angcut ) {
iw2 = m_weight_list.erase( iw2 ); // remove L2 from the list
ConnNeur2->removeWeight( this ); // remove this from L2
} else {
iw2++; // next one
}
}
iw1++;
} else {
iw1++; // look for next L1
}
}
// find L1 neurons in TH. Then search for L2 neurons in TH close in angleXZ
// to the L1 one and kill them if angleXZ smaller than 0.1
iw1 = m_weight_list.begin();
while ( ( iw1 != m_weight_list.end() ) && ( !m_weight_list.empty() ) ) {
ConnNeur1 = iw1->first;
if ( tailHead( *ConnNeur1 ) && ConnNeur1->stationDifference() == 1 ) {
// ok found an L1 HT with this. now search for an L2 HT
auto iw2 = m_weight_list.begin();
while ( ( iw2 != m_weight_list.end() ) && ( !m_weight_list.empty() ) ) {
ConnNeur2 = iw2->first;
if ( tailHead( *ConnNeur2 ) && ConnNeur2->stationDifference() > 1 &&
ConnNeur2->angleXZ( *ConnNeur1 ) < angcut ) {
iw2 = m_weight_list.erase( iw2 ); // remove L2 from the list
ConnNeur2->removeWeight( this ); // remove this from L2
} else {
iw2++; // next one
}
}
iw1++;
} else {
iw1++; // look for next L1
}
}
}
/// neuron length in terms of stations crossed
int MuonNeuron::stationDifference() { return ( m_head->station() - m_tail->station() ); }
/// return neuron length
double MuonNeuron::len() const { return sqrt( m_neuron.Mag2() ); }
/// return neuron length along Z
double MuonNeuron::deltaZ() const { return ( m_head->Z() - m_tail->Z() ); }
/// return distance along Z between the neuron station and the closest one
double MuonNeuron::deltaZ( const int st ) const {
double zsta[5] = {12100, 15200, 16400, 17600, 18800};
return ( zsta[st] - m_tail->Z() );
}
/// return neuron length in the xz plane
double MuonNeuron::lenXZ() const { return sqrt( m_neuronXZ.Mag2() ); }
/// return neuron length in the yz plane
double MuonNeuron::lenYZ() const { return sqrt( m_neuronYZ.Mag2() ); }
/// angle with another neuron in space
double MuonNeuron::angle( const MuonNeuron& n ) { return ROOT::Math::VectorUtil::Angle( m_neuron, n.m_neuron ); }
/// angle with another neuron in XZ
double MuonNeuron::angleXZ( const MuonNeuron& n ) { return ROOT::Math::VectorUtil::Angle( m_neuronXZ, n.m_neuronXZ ); }
/// angle with another neuron in YZ
double MuonNeuron::angleYZ( const MuonNeuron& n ) { return ROOT::Math::VectorUtil::Angle( m_neuronYZ, n.m_neuronYZ ); }
/// check if this is th with n
bool MuonNeuron::tailHead( const MuonNeuron& n ) const { return ( m_tail->hitID() == n.m_head->hitID() ); }
/// check if this is ht with n
bool MuonNeuron::headTail( const MuonNeuron& n ) const { return ( m_head->hitID() == n.m_tail->hitID() ); }
/// check if this is tt with n
bool MuonNeuron::tailTail( const MuonNeuron& n ) const { return ( m_tail->hitID() == n.m_tail->hitID() ); }
/// check if this is hh with n
bool MuonNeuron::headHead( const MuonNeuron& n ) const { return ( m_head->hitID() == n.m_head->hitID() ); }
/// check if this is connected to n
bool MuonNeuron::connectedTo( const MuonNeuron& n ) const {
return ( tailTail( n ) || headHead( n ) || tailHead( n ) || headTail( n ) );
}
/// return the neuron projection XZ
ROOT::Math::XYZVector MuonNeuron::projXZ() { return m_neuronXZ; }
/// return the neuron projection YZ
ROOT::Math::XYZVector MuonNeuron::projYZ() { return m_neuronYZ; }
/// store the weights
void MuonNeuron::setWeight( MuonNeuron* n, double ww ) {
m_weight.first = n;
m_weight.second = ww;
m_weight_list.emplace_back( n, ww );
}
/// retireve the weights
std::list<std::pair<MuonNeuron*, double>> MuonNeuron::getWeights() { return m_weight_list; }
/// set neuron status
void MuonNeuron::setStatus( double st ) { m_status = st; }
/// return neuron status
double MuonNeuron::status() { return m_status; }
/// Neuron ID
void MuonNeuron::setNeuronID( int id ) { m_ID = id; }
/// retireve ID
int MuonNeuron::neuronID() { return m_ID; }
/// assign an ID to head and tail points
void MuonNeuron::setHeadTailID( int hID, int tID ) {
m_headID = hID;
m_tailID = tID;
}
/// retireve head and tail IDs. First = head, Second = tail
std::pair<int, int> MuonNeuron::headTailID() {
std::pair<int, int> tmp;
tmp.first = m_headID;
tmp.second = m_tailID;
return tmp;
}