Skip to content
Snippets Groups Projects
Commit 7969203b authored by FU Chengdong's avatar FU Chengdong
Browse files

first import from ILCSoft & merge KiTrack and KiTrackMarlin

parent 476340b1
No related branches found
No related tags found
No related merge requests found
Showing
with 1492 additions and 0 deletions
gaudi_subdir(KiTrack v0r0)
find_package(ROOT REQUIRED)
find_package(CLHEP REQUIRED)
#find_package(DD4hep REQUIRED)
find_package(GSL REQUIRED)
find_package(EDM4HEP REQUIRED)
find_package(LCIO REQUIRED)
gaudi_depends_on_subdirs(Service/TrackSystemSvc Utilities/DataHelper)
set(KiTrackLib_srcs src/KiTrack/*.cc src/Criteria/*.cc src/ILDImpl/*.cc src/Tools/*.cc)
#gaudi_install_headers(src)
include_directories(src)
gaudi_add_library(KiTrackLib ${KiTrackLib_srcs}
PUBLIC_HEADERS KiTrack
LINK_LIBRARIES DataHelperLib TrackSystemSvcLib ROOT CLHEP GSL EDM4HEP::edm4hep LCIO
# DD4hep
)
#ifndef Criteria_h
#define Criteria_h
/*
#include "Criteria/Crit2_RZRatio.h"
#include "Criteria/Crit2_StraightTrackRatio.h"
#include "Criteria/Crit2_DeltaPhi.h"
#include "Criteria/Crit2_HelixWithIP.h"
#include "Criteria/Crit2_DeltaRho.h"
#include "Criteria/Crit3_ChangeRZRatio.h"
#include "Criteria/Crit3_PT.h"
#include "Criteria/Crit3_2DAngle.h"
#include "Criteria/Crit3_2DAngleTimesR.h"
#include "Criteria/Crit3_3DAngle.h"
#include "Criteria/Crit3_3DAngleTimesR.h"
#include "Criteria/Crit3_IPCircleDist.h"
#include "Criteria/Crit3_IPCircleDistTimesR.h"
#include "Criteria/Crit4_2DAngleChange.h"
#include "Criteria/Crit4_3DAngleChange.h"
#include "Criteria/Crit4_3DAngleChangeNormed.h"
#include "Criteria/Crit4_DistToExtrapolation.h"
#include "Criteria/Crit4_PhiZRatioChange.h"
#include "Criteria/Crit4_DistOfCircleCenters.h"
#include "Criteria/Crit4_NoZigZag.h"
#include "Criteria/Crit4_RChange.h"
// Criteria for Mini - Vector based Cellular Automaton for VXD
#include "Criteria/Crit2_DeltaPhi_MV.h"
#include "Criteria/Crit2_Distance_MV.h"
#include "Criteria/Crit2_DeltaTheta_MV.h"
#include "Criteria/Crit3_NoZigZag_MV.h"
#include "Criteria/Crit3_PT_MV.h"
*/
#include <vector>
#include <set>
#include <string>
namespace KiTrack{
class ICriterion;
/*
* Information about all Criteria.
*
* For example bundles the includes.
*
* Author: Robin Glattauer, HEPHY
*/
class Criteria {
public:
/** @return a vector of strings that represent all types of criteria stored.
* For example: "2Hit" or "3Hit" or "4Hit"
*/
static std::set< std::string > getTypes();
/** @return a vector of all Criteria of a certain type
*
* @param type the type of Criteria, that is wanted (e.g. "2Hit")
*/
static std::set< std::string > getCriteriaNames( std::string type );
/** @return the names of all Criteria in a set
*/
static std::set< std::string > getAllCriteriaNames();
/** A convenience method to get all the criteria in a vector (gives the same result as getAllCriteriaNames, but
* instead of a set, returns it as a vector)
*
* @return the names of all Criteria in a vector
*/
static std::vector< std::string > getAllCriteriaNamesVec();
/**
* Creates a Criterion with the name and the min and max values
*
* @return a "new" Criterion (i.e. needs to be deleted later on)
*/
static ICriterion* createCriterion( std::string critName , float min=0. , float max=0. ) ;
/**
* Sets values for the passed referneced floats left and right. They indicate how
* the specified criterion should be cut, if necessary. Say you want for example
* a 99% quantile, so that 99% of your true tracks are within it.
* A criterion like the angle between two segments then needs to define a boarder like:
* between an angle of 1° and of 9° there will be 99%.
* So 1% is outside. But should 1% be the ones with a bigger angle or with a smaller angle or should
* this be 50:50?
*
* This is defined by left and right. Left is the proportion, that is taken away on the left side and
* right is the one that is taken away on the right side.
* In the case of an angle we will most probably have lots around 0° and a long tail to the right, so
* left = 0 and right = 1 seems like a good idea.
* Standard is of course 0.5 and 0.5
*/
static void getLeftRight( std::string critName, float & left, float & right );
};
}
#endif
#ifndef ICriterion_h
#define ICriterion_h
#include <vector>
#include <map>
#include <string>
#include "KiTrack/Segment.h"
#include "KiTrack/KiTrackExceptions.h"
namespace KiTrack{
/** An Interface for Criteria.
*
* A Criterion is a class, that is able to take two Segments and check whether they are compatible or not.
*/
class ICriterion{
public:
/** @return If the two Segments are compatible with each other, i.e. could be combined to a longer Segment or a
* track.
*/
virtual bool areCompatible( Segment* parent , Segment* child ) = 0;
/** @return A map, where the calculated values are stored. The keys are the names of the values.
*/
std::map < std::string , float > getMapOfValues() {return _map_name_value; };
virtual ~ICriterion(){};
/** Sets, whether the calculated values shall be saved in a map
*/
void setSaveValues( bool saveValues ){ _saveValues = saveValues;}
/** @return the name of the criterion */
std::string getName(){return _name;}
/** @return the type of the criterion */
std::string getType(){return _type;}
protected:
std::map < std::string , float > _map_name_value{};
bool _saveValues{};
std::string _name{};
std::string _type{};
};
}
#endif
#ifndef FTDHit01_h
#define FTDHit01_h
#include "ILDImpl/IFTDHit.h"
namespace KiTrackMarlin{
/** A class for hits in the FTD (the 01 is just for historical reasons and may be renamed)
*
* - The side is according to CellID0.
* - Layer is set according to CellID0 +1 (so we can use layer 0 for the IP)
* - Module is set according to CellID0.
* - Sensor is set according to CellID0 -1. (because currently sensors of the FTD start with 1 in the CellID0, if this changes, this has to be modified)
*/
class FTDHit01 : public IFTDHit{
public:
FTDHit01( edm4hep::TrackerHit trackerHit , const SectorSystemFTD* const sectorSystemFTD );
};
}
#endif
#ifndef FTDHitSimple_h
#define FTDHitSimple_h
#include "KiTrack/IHit.h"
#include "ILDImpl/SectorSystemFTD.h"
namespace KiTrackMarlin{
/** A hit
*/
class FTDHitSimple : public IHit{
public:
FTDHitSimple( float x , float y , float z , int side, unsigned layer , unsigned module, unsigned sensor, const SectorSystemFTD* const sectorSystemFTD );
virtual const ISectorSystem* getSectorSystem() const { return _sectorSystemFTD; };
virtual ~FTDHitSimple(){}
private:
int _side;
unsigned _layer;
unsigned _module;
unsigned _sensor;
const SectorSystemFTD* _sectorSystemFTD;
void calculateSector(){ _sector = _sectorSystemFTD->getSector( _side, _layer , _module , _sensor ); }
};
}
#endif
#ifndef FTDNeighborPetalSecCon_h
#define FTDNeighborPetalSecCon_h
#include "KiTrack/ISectorConnector.h"
#include "ILDImpl/SectorSystemFTD.h"
namespace KiTrackMarlin{
/** Used to connect two sectors.
*
* Allows:
*
* - Connections to the neighbouring petals (the one to the left and the one to the right on the same layer and side)
*
*/
class FTDNeighborPetalSecCon : public ISectorConnector{
public:
/**
*
*/
FTDNeighborPetalSecCon ( const SectorSystemFTD* sectorSystemFTD );
virtual std::set <int> getTargetSectors ( int sector );
virtual ~FTDNeighborPetalSecCon(){};
private:
const SectorSystemFTD* _sectorSystemFTD;
};
}
#endif
#ifndef FTDSectorConnector_h
#define FTDSectorConnector_h
#include "KiTrack/ISectorConnector.h"
#include "ILDImpl/SectorSystemFTD.h"
namespace KiTrackMarlin{
/** Used to connect two sectors on the FTD.
*
*
* Allows:
*
* - going to layers on the inside (how far see constructor)
* - going to same petal or petals around (how far see constructor)
* - jumping to the IP (from where see constructor)
*/
class FTDSectorConnector : public ISectorConnector{
public:
/** @param layerStepMax the maximum distance of the next layer on the inside
*
* @param petalStepMax the maximum distance of the next petal (in + and - direction )
*
* @param lastLayerToIP the highest layer from where a direct jump to the IP is allowed
*/
FTDSectorConnector ( const SectorSystemFTD* sectorSystemFTD , unsigned layerStepMax , unsigned petalStepMax , unsigned lastLayerToIP);
/** @return a set of all sectors that are connected to the passed sector */
virtual std::set <int> getTargetSectors ( int sector );
virtual ~FTDSectorConnector(){};
private:
const SectorSystemFTD* _sectorSystemFTD;
unsigned _layerStepMax;
unsigned _petalStepMax;
unsigned _lastLayerToIP;
};
}
#endif
#ifndef FTDTrack_h
#define FTDTrack_h
//#include "IMPL/TrackImpl.h"
//#include "MarlinTrk/IMarlinTrkSystem.h"
//#include "MarlinTrk/IMarlinTrack.h"
#include "edm4hep/Track.h"
#include "TrackSystemSvc/IMarlinTrkSystem.h"
#include <vector>
#include "ILDImpl/IFTDHit.h"
#include "KiTrack/ITrack.h"
#include "Tools/Fitter.h"
namespace KiTrackMarlin{
/** A class for ITracks containing an lcio::Track at core
*/
class FTDTrack : public ITrack {
public:
/** @param trkSystem An IMarlinTrkSystem, which is needed for fitting of the tracks
*/
FTDTrack( MarlinTrk::IMarlinTrkSystem* trkSystem );
/** @param hits The hits the track consists of
* @param trkSystem An IMarlinTrkSystem, which is needed for fitting of the tracks
*/
FTDTrack( std::vector< IFTDHit* > hits , MarlinTrk::IMarlinTrkSystem* trkSystem );
FTDTrack( const FTDTrack& f );
FTDTrack & operator= (const FTDTrack & f);
/** @return a track in the lcio format
*/
edm4hep::Track* getLcioTrack(){ return ( _lcioTrack );}
void addHit( IFTDHit* hit );
virtual double getNdf() const { return _lcioTrack->getNdf(); }
virtual double getChi2() const { return _lcioTrack->getChi2(); }
virtual double getChi2Prob() const { return _chi2Prob; }
virtual std::vector< IHit* > getHits() const { std::vector<IHit*> hits;
for(unsigned i=0; i<_hits.size();i++) hits.push_back( _hits[i] );
return hits; }
virtual double getQI() const;
/** Fits the track and sets chi2, Ndf etc.
*/
virtual void fit() ;
virtual ~FTDTrack(){ delete _lcioTrack; }
protected:
/** the hits the track consists of
*/
std::vector< IFTDHit* > _hits;
edm4hep::Track* _lcioTrack;
// for fitting
MarlinTrk::IMarlinTrkSystem* _trkSystem;
double _chi2Prob;
};
}
#endif
#ifndef IFTDHit_h
#define IFTDHit_h
#include "edm4hep/TrackerHit.h"
#include "KiTrack/IHit.h"
#include "ILDImpl/SectorSystemFTD.h"
namespace KiTrackMarlin{
/** An interface for a hit for the ILD using an lcio TrackerHit as basis.
*
* It comes along with a side, layer, module and a sensor.
*/
class IFTDHit : public IHit{
public:
edm4hep::TrackerHit* getTrackerHit() { return &_trackerHit; };
int getSide() { return _side; }
unsigned getModule() { return _module; }
unsigned getSensor() { return _sensor; }
void setSide( int side ){ _side = side; calculateSector();}
void setLayer( unsigned layer ){ _layer = layer; calculateSector();}
void setModule( unsigned module ){ _module = module; calculateSector();}
void setSensor( unsigned sensor ){ _layer = sensor; calculateSector();}
virtual const ISectorSystem* getSectorSystem() const { return _sectorSystemFTD; };
protected:
edm4hep::TrackerHit _trackerHit;
int _side;
unsigned _layer;
unsigned _module;
unsigned _sensor;
const SectorSystemFTD* _sectorSystemFTD;
/** Calculates and sets the sector number
*/
void calculateSector(){ _sector = _sectorSystemFTD->getSector( _side, _layer , _module , _sensor ); }
};
}
#endif
#ifndef SectorSystemFTD_h
#define SectorSystemFTD_h
#include "KiTrack/ISectorSystem.h"
using namespace KiTrack;
namespace KiTrackMarlin{
/** A Sector System class for the Forward Tracking Disks FTD in the ILD.
*
* It calculates sectors from the side, layer, sensor and module and vice versa.
*
* @param side: +1 for forward, -1 for backward
*
* @param layer: layer of FTD: 0 is the layer of the IP, 1 is the first FTD disk and so on.
*
* @param module: module
*
* @param sensor: the sensor on the module
*
*
*/
class SectorSystemFTD : public ISectorSystem{
public:
/**Constructor
*
* @param nLayers the number of possible layers. The layers from 0 to n-1 will be available. Keep in mind,
* that layer 0 is used for the IP.
*
* @param nModules the number of modules per disk.
*
* @param nSensors the number of sensors on one module.
*/
SectorSystemFTD( unsigned nLayers , unsigned nModules , unsigned nSensors );
/** Calculates the sector number corresponding to the passed parameters
*/
int getSector( int side, unsigned layer , unsigned module , unsigned sensor ) const ;
/** Virtual, because this method is demanded by the Interface ISectorSystem
*
* @return the layer corresponding to the passed sector number
*/
virtual unsigned getLayer( int sector ) const ;
/** @return some information on the sector as string */
virtual std::string getInfoOnSector( int sector ) const;
/** @return the side the sector is on (+1 = forward, -1 = backward)
*/
int getSide( int sector ) const ;
/** @return the module of the sector
*/
unsigned getModule( int sector ) const ;
/** @return the sensor of the sector
*/
unsigned getSensor( int sector ) const ;
unsigned getNumberOfModules() const { return _nModules; }
unsigned getNumberOfSensors() const { return _nSensors; }
virtual ~SectorSystemFTD(){}
private:
unsigned _nModules;
unsigned _nSensors;
int _sectorMax;
void checkSectorIsInRange( int sector ) const ;
};
}
#endif
#ifndef SectorSystemVXD_h
#define SectorSystemVXD_h
#include "KiTrack/ISectorSystem.h"
#include <vector>
using namespace KiTrack;
namespace KiTrackMarlin{
/** A Sector System class for the Forward Tracking Disks FTD in the ILD.
*
* It calculates sectors from the side, layer, sensor and module and vice versa.
*
* @param side: +1 for forward, -1 for backward
*
* @param layer: layer of FTD: 0 is the layer of the IP, 1 is the first FTD disk and so on.
*
* @param module: module
*
* @param sensor: the sensor on the module
*
*
*/
class SectorSystemVXD : public ISectorSystem{
public:
/**Constructor
*
* @param nLayers the number of possible layers. The layers from 0 to n-1 will be available. Keep in mind,
* that layer 0 is used for the IP.
*
* @param nModules the number of modules per disk.
*
* @param nSensors the number of sensors on one module.
*/
SectorSystemVXD( unsigned nLayers , unsigned nDivisionsInPhi , unsigned nDivisionsInTheta );
/** Virtual, because this method is demanded by the Interface ISectorSystem
*
* @return the layer corresponding to the passed sector number
*/
virtual unsigned getLayer( int sector ) const ;
virtual unsigned getPhi( int sector ) const ;
virtual unsigned getTheta( int sector ) const ;
/** @return some information on the sector as string */
virtual std::string getInfoOnSector( int sector) const;
/** Calculates the sector number corresponding to the passed parameters
*/
int getSector( int layer, int phi, int theta ) const ;
int getSector( int layer, double phi, double cosTheta ) const ;
unsigned getPhiSectors() const ;
unsigned getThetaSectors() const ;
unsigned getNLayers() const ;
virtual ~SectorSystemVXD(){}
private:
int _sectorMax;
unsigned _nLayers;
unsigned _nDivisionsInPhi ;
unsigned _nDivisionsInTheta ;
void checkSectorIsInRange( int sector ) const ;
};
}
#endif
#ifndef VXDHitSimple_h
#define VXDHitSimple_h
#include "KiTrack/IHit.h"
#include "ILDImpl/SectorSystemVXD.h"
namespace KiTrackMarlin{
/** A hit
*/
class VXDHitSimple : public IHit{
public:
VXDHitSimple( float x , float y , float z , int layer , int phi, int theta, const SectorSystemVXD* const sectorSystemVXD );
virtual const ISectorSystem* getSectorSystem() const { return _sectorSystemVXD; };
virtual ~VXDHitSimple(){}
private:
int _layer;
int _phi;
int _theta;
const SectorSystemVXD* _sectorSystemVXD;
//void calculateSector(){ _sector = _sectorSystemVXD->getSector( _side, _layer , _module , _sensor ); }
};
}
#endif
#ifndef Automaton_h
#define Automaton_h
#include <vector>
#include "KiTrack/Segment.h"
#include "Criteria/ICriterion.h"
namespace KiTrack{
/** A class for the cellular automaton.
*
* For detailed info on the Cellular Automaton and its use for track reconstruction see
* <a href="../CellularAutomaton.pdf">Introduction to the Cellular Automaton</a>
*
* <h3>About the class </h3>
*
* This Cellular Automaton is specifically designed for track reconstruction, so it differs in the functionality
* from other Cellular Automata, like those used for simulation of biological cells.
*
* The basic information on how the CA works and what it needs is describet in the pdf above. Here I'll only sum up
* the basics of this class.
*
* The cells the Cellular Automaton deals with are here called segments as we deal with track reconstruction.
* These are the main information entities the CA deals with and therefore the most important member variable is
* a container of these segments. (For more details on the segments see the doxygen of the Segment class)
* To sum it up: Segments consist of hits. So they are a bit like tracks. Or if they only consist of one single hit
* (so called 1-hit-segments) then they are like hits.
* But there a few features that distinguish them from hits or tracks
* - They can have parents and children. These are simply segments on top or below them. The idea is, that all
* segments on the inside are stored as children if they could belong to the same track. And the same for all segments
* on the outside possible belonging to the same track (the parents). So if we start at a segment and go to a child
* and on to a grandchild and so on, we follow a possible track. If we erase those connections we decrease the number
* of possible tracks.
* - Segments must have a layer marking where it is. (layer 0: inside, higher layers further outside). This is a
* feature needed by the Automaton. Because it is an algorithm with discrete entities, we need some sort of discrete
* ordering. (If we for example had a Cellular Automaton for simulation of 2 dimensional cells and we arranged the
* cells for example on a chessboard, we always know the next cells. Here we have a 1 dimensional situation so we use
* layers)
* - Segments have states: this is simply an integer number (an unsigned to be more precise). It is needed by the
* Automaton to find connections that go all the way through (see pdf!)
*
* The Segments can be added via the addSegment() method and are stored layerwise.
*
* Once the Segments are all stored in the Cellular Automaton it can perform.
* Via the method doAutomaton() it raises the states of the Segments until no change happens anymore.
* When this is done Segments not connected all the way through can be discarded by the method
* cleanBadStates(). This reduces the number of possible tracks.
*
* To get an initial Cellular Automaton to start with, the class SegmentBuilder can be used.
* (It takes hits builds segments from them and establishes the first parent-child relations)
*
* In order to sort out even more it is possible to go to longer segments. So instead of checking 1-hit-segments,
* we can have a look at 2-hit-segments or 3-hit-segments. (And sort out much more along the way)
* For this the method lengthenSegments() is used. It combines connected segments and creates segments from them,
* that are exactly one hit longer. And then it is again time for connecting them.
* (I distinguish here between connecting: "storing the link" and combining: "making 1 new segment out of two others")
*
* When segments are connected only connections that make sense are made. This is really important! If we don't make
* assumptions here, what Segments could belong together (i.e. could form a sensible track) we get lost in combinatorics.
* For this the so called Criteria are used. Via the method addCriterion() (or addCriteria() ) they can be added
* to the Cellular Automaton. All a Criterion does (see the Criterion doxygen for more info) is to say whether two
* Segments would give a good match. These criteria can be anything that makes sense in distinguishing between
* real tracks and combinatorial background. For example if the segments are already long enough (already little tracks)
* one can compare the radius of their helices or the angle under which they meet and so on.
*
* Once we have longer segments we can again use the doAutomaton() method and then cleanBadStates(). Then we lenghten
* them once more and so on.
*
* Between two such runs, one should of course clear the old Criteria with clearCriteria and reset the states of the
* Segments with resetStates().
*
* That's it. In the end, when nothing more is to be done in the Cellular Automaton, we need to extract the track
* candidates, it found. This is done via the getTracks() method.
*
*/
class Automaton{
public:
Automaton(): _nConnections(0){}
/**
* delete all the segments
*/
~Automaton();
/** Adds a segment to the automaton.\
* Take care to set the layer of the segment before adding!
*/
void addSegment ( Segment* segment );
/**Lengthens the segments by one via adding the first hit of the next segment it is connected to
* to it.
* Also connects those longer segments with each other. ( one becomes a parent and one a child )
* Segments that don't have connected segments to use to get longer, will die here.
*/
void lengthenSegments();
/**Adds a criteria to the automaton. So it will be used, when the methods doAutomaton()
* or cleanBadConnections() are called.
*/
void addCriterion ( ICriterion* criterion ){ _criteria.push_back( criterion ); }
void addCriteria ( std::vector< ICriterion* > criteria ){ _criteria.insert( _criteria.end() , criteria.begin() , criteria.end() ); }
void clearCriteria() { _criteria.clear(); };
/** Does iteration until the states of the segments don't change anymore.
*
* In one iteration all segments are checked, if they have a neighbor.
* A neighbor:
* - has the same state
* - fulfills all the criteria (this is automatically provided, because in lengthenSegments only connections that fullfill the Criteria are made)
*
* If it has a neighbor its state will be raised by one at the end of the iteration.
* (At the end only in theory: in the program it will be during the iteration, but
* in a way, that it doesn't affect other segments)
*
* When after an iteration the states didn't change, it stops.
*/
void doAutomaton();
/**
* Erases all segments that don't have a state corresponding to their layer.
*
* After the automaton is performed every segment, that has a neighbor, that has a neighbor, that...
* ...that reaches layer 0 should have a state equal to its layer. All the others are not connected
* to layer 0. All those get deleted by this method.
* (Of course all the connections to them are erased as well)
*/
void cleanBadStates();
/**
* Erase alls connections between segments, that don't satisfy the criteria.
*/
void cleanBadConnections();
/**Resets all the states of the segmens to 0 by calling the resetState() method of the segment
* Also sets all segments back to active.
*/
void resetStates();
/** Get all the possible tracks in the automaton.
*
* Tracks are built by starting from segments which don't have a parent (and are therefore the begin of a track).
* For all children they have a new own track is created. The children themselves have children again, so the
* tracks split up again.
* If we have for example a segment with 3 children, which each have 5 children, which each have 7 children,
* we will get 1*3*5*7=105 tracks.
*
* @return All tracks that are possible with the given segments and their connections. Tracks are returned
* as a vector of hits. So the output will be a vector of a vector of hits
*
* @param minHits the minimum number of hits that a track needs to have. All possible tracks,
* that have less won't be considered as tracks and won't be returned.
*
*/
//std::vector < std::vector< IHit* > > getTracks( unsigned minHits = 3 );
std::vector < std::vector< IHit* > > getTracks( unsigned minHits = 2 ); // YV, 2 mini-vector hits can form a track
/**Returns all the tracks starting from this segment.
* It is a recursive method and gets invoked by getTracks.
*/
//std::vector < std::vector< IHit* > > getTracksOfSegment ( Segment* segment, std::vector< IHit* > hits , unsigned minHits = 3 );
std::vector < std::vector< IHit* > > getTracksOfSegment ( Segment* segment, std::vector< IHit* > hits , unsigned minHits = 2 ); // YV, 2 mini-vector hits can form a track
/**
* @return All the segments currently saved in the automaton
*/
std::vector <const Segment*> getSegments() const;
unsigned getNumberOfConnections(){ return _nConnections; }
private:
/** Here the segments are stored.
* The vector corresponds to the layer.
* The list corresponds to the segments on the layer.
* _segments[2] is a list with all segments on layer 2.
*
* The segments will be deleted by the Automaton in the destructor
*
*/
std::vector < std::list < Segment* > > _segments{};
/** A vector containing all the criteria, that are used in the Automaton
*/
std::vector < ICriterion* > _criteria{};
unsigned _nConnections{};
};
}
#endif
#ifndef HopfieldNeuralNet_h
#define HopfieldNeuralNet_h
#include <vector>
#include "KiTrackExceptions.h"
namespace KiTrack{
/**
* Represents a Hopfield Neural Network
*
* See <a href="../SubsetHopfieldNN.pdf">this</a> for detailed info.
*
* Author: Robin Glattauer, HEPHY
*/
class HopfieldNeuralNet {
public:
/**
* @param G A matrix of the correlations between the neurons.
* True means two neurons are incompatible. False means, they are
* compatible. (the diagonal elements are 0 by definition and any entry there will be ignored and set to 0)
*
* @param QI A vector containing the qualtity indicators of the neurons (i.e. their power to amplify or
* weaken other neurons). Quality should be indicated by a value between 0 and 1. 1 being the highest quality.
*
* @param states The states of the neurons. Should be between 0 and 1.
*
* @param omega Controls the influence of the quality indicator on the activation of the neuron. Needs to be
* between 0 and 1. 0 means, no influence from the quality of the neurons -> system tends to biggest compatible
* set. 1 means highest influence from the quality of the neurons -> the highest quality neurons tend to win.
*/
HopfieldNeuralNet( std::vector < std::vector <bool> > G , std::vector < double > QI , std::vector < double > states , double omega) ;
/** Does one iteration of the neuronal network.
*
* \f$ \vec{y} = W \times \vec{state} + \vec{w_0} \f$
*
* \f$ \vec{state}_{new} = activationFunction(\vec{y}) \f$
*
* @return Whether the Neural Network is considered as stable
*/
bool doIteration();
/**
* Sets the temperature of the Neural Network (The HNN is cooled down in every iteration)
*/
void setT (double T) { _T = T;};
/**
* Sets the temperature at infinity. The temperature will converge to this
* value after infinite iterations.
*/
void setTInf (double TInf) {_TInf = TInf;};
/**
* Set the threshhold value below which the HNN is seen as "stable". As long as any Neuron changes its state
* by a value bigger than this, the HNN is not considered stable. When all Neurons change their states so little,
* that none of the changes exceeds this threshold, then the HNN is stable.
*/
void setLimitForStable (double limit) { _limitForStable = limit; };
/** @return the vector of the states
*/
std::vector <double> getStates(){ return _States; };
protected:
/** the matrix of the weights*/
std::vector < std::vector <double> > _W{};
/** states describing how active a neuron is*/
std::vector < double > _States{};
std::vector < double > _w0{};
/** temperature */
double _T{};
/** temperature after infinite iterations */
double _TInf{};
/** indicates if the neuronal network is stable.
* this is true when the change after one iteration
* of any neuron is not bigger than the value _limitForStable.
*/
bool _isStable{};
/** The upper limit for change of a neuron, if it should be considered stabel.*/
double _limitForStable{};
/** Omega controls the influence of the quality indicator on the activation of the neuron.
*/
double _omega{};
/** the order of the neurons to be updated. So it should of course reach from 0 to the number of neurons -1.
* (4 , 2, 0 1, 3) will for example mean: update first the neuron 4, then the neuron 2, then 0 and so on
*/
std::vector <unsigned> _order{};
/** Calculates the activation function
*
* @param state the state
* @param T the temperature
* @return the activation function corresponding to the input values: g(x) = 1/2* (1 + tanh( x/T ))
*/
double activationFunction ( double state , double T );
};
}
#endif
#ifndef IHit_h
#define IHit_h
#include "KiTrack/ISectorSystem.h"
namespace KiTrack{
/** An Interface for hits.
*
* They have of course a position, accessible with getX(), getY() and getZ().
*
* Also a hit has a sector. A sector is just an integer, telling where the hit lies. For example
* a sector 141 could mean 1st layer, 4th module, 1st sensor. But how information is encoded is dealt
* with in the SectorSystem classes (see ISectorSystem for the Abstract Base Class ).
*/
class IHit{
public:
/** @return the x position */
float getX() const { return _x; }
/** @return the y position */
float getY() const { return _y; }
/** @return the z position */
float getZ() const { return _z; }
/** @return the sector, where the hit lies n */
int getSector() const { return _sector; }
/** @return the used SectorSystem that encodes the sector of the hit*/
virtual const ISectorSystem* getSectorSystem() const =0;
/** @return the layer of the hit */
unsigned getLayer() const {return getSectorSystem()->getLayer( _sector ); }
/** @return whether the hit is virtual (not a real hit). */
bool isVirtual() const { return _isVirtual; };
void setIsVirtual( bool isVirtual ){ _isVirtual = isVirtual; };
/** @return the distance to an other hit */
float distTo( IHit* otherHit );
/** @return a string containing the position of the hit */
std::string getPositionInfo();
/** to be used with mini-vectors: @return 3D angle */ //YV
double get3DAngle( IHit* /*otherHit*/) const { return _3DAngle ; }
/** to be used with mini-vectors: @return azimuth angle */ //YV
double getPhi() const { return _phiMV ; }
/** to be used with mini-vectors: @return polar angle */ //YV
double getTheta() const { return _thetaMV ; }
virtual ~IHit(){}
protected:
float _x{};
float _y{};
float _z{};
double _3DAngle{}; //YV
double _phiMV{}; //YV
double _thetaMV{}; //YV
int _sector{};
bool _isVirtual{};
};
}
#endif
#ifndef ISectorConnector_h
#define ISectorConnector_h
#include <set>
namespace KiTrack{
/** Abstract Base Class for SectorConnectors.
*
* A SectorConnector is pretty simple: you put in a sector (int) and get back a bunch of other sectors in a set.
* What it can be used for: Suppose you want to search for the path of a particle through a detector
* and you know what possible ways it can go, than you can create a SectorConnector to emulate that.
* So if you have a hit in sector 43 (whatever 43 means) and you think, that from there the particle will
* only go to either sector 46, 47 or 48, then you would write a SectorConnector that will return
* a set of 46,47,48 when the method getTargetSectors( 43 ) is called.
*/
class ISectorConnector{
public:
/** @return a set of sectors somehow linked to the passed one */
virtual std::set <int> getTargetSectors ( int ) = 0;
virtual ~ISectorConnector(){};
};
}
#endif
#ifndef ISectorSystem_h
#define ISectorSystem_h
#include <string>
#include "KiTrack/KiTrackExceptions.h"
namespace KiTrack{
/** An interface for Sector Systems.
*
* A sector is a code for a place. So it can for example equal a sensor somewhere in a detector or be something
* abstract like the IP.
*
* A sector system is able to take a sector (integer number) and give back information
* about it. This can be things like the number of the sensor or the rough distance from the IP or such
* things. Or even neighbouring sectors.
* But this is all dependent on the circumstances of the detectors and their representation.
*
* What all SectorSystems have in common is the layer: SectorSystems must be able to
* return the layer of a sector and how many layers there are all in all.
*/
class ISectorSystem{
public:
/** @return the layer of the corresponding sector. */
virtual unsigned getLayer( int sector ) const =0;
/** @return the number of layers in the sector system. */
unsigned getNumberOfLayers() const { return _nLayers; };
/** @return some information on the sector as string */
virtual std::string getInfoOnSector( int sector ) const = 0;
virtual ~ISectorSystem(){}
protected:
unsigned _nLayers{};
};
}
#endif
#ifndef ITrack_h
#define ITrack_h
#include <vector>
#include "KiTrack/IHit.h"
namespace KiTrack{
/** Abstract Base Class for tracks.
*/
class ITrack{
public:
/** @return a vector of the hits of the track
*/
virtual std::vector< IHit*> getHits() const = 0;
/** @return an indicator for the quality of the track. Usually between 0 and 1 */
virtual double getQI() const = 0;
/** Fits the track. */
virtual void fit() = 0;
/** @return the degrees of freedom of the fit. This must only be called after fit() has been used */
virtual double getNdf() const = 0;
/** @return the chi squared value of the fit. This must only be called after fit() has been used */
virtual double getChi2() const = 0;
/** @return the chi squared probability of the fit. This must only be called after fit() has been used */
virtual double getChi2Prob() const = 0;
virtual ~ITrack(){}
};
}
#endif
#ifndef KiTrackExceptions_h
#define KiTrackExceptions_h
#include <string>
#include <exception>
//Exceptions for the KiTrack namespace
namespace KiTrack {
/**Base exception class for KiTrack - all other exceptions extend this.
* @author R. Glattauer, HEPHY
*
*/
class KiTrackException : public std::exception {
protected:
std::string message{} ;
KiTrackException(){ /*no_op*/ ; }
public:
virtual ~KiTrackException() { /*no_op*/; }
KiTrackException( const std::string& text ){
message = "KiTrack::Exception: " + text ;
}
virtual const char* what() const noexcept { return message.c_str() ; }
};
/**Out of range exception, used when the user tries to access layers oder sensors, that are not implemented
* @author R. Glattauer, HEPHY
*/
class OutOfRange : public KiTrackException{
protected:
OutOfRange() { /*no_op*/ ; }
public:
virtual ~OutOfRange() { /*no_op*/; }
OutOfRange( std::string text ){
message = "KiTrack::OutOfRange: " + text ;
}
};
/**Invalid Parameter exception.
* @author R. Glattauer, HEPHY
*/
class InvalidParameter : public KiTrackException{
protected:
InvalidParameter() { /*no_op*/ ; }
public:
virtual ~InvalidParameter() { /*no_op*/; }
InvalidParameter( std::string text ){
message = "KiTrack::InvalidParameter: " + text ;
}
};
/**Wrong segment length exception.
* @author R. Glattauer, HEPHY
*/
class BadSegmentLength : public KiTrackException{
protected:
BadSegmentLength() { /*no_op*/ ; }
public:
virtual ~BadSegmentLength() { /*no_op*/; }
BadSegmentLength( std::string text ){
message = "KiTrack::BadSegmentLength: " + text ;
}
};
/**Unknown criterion exception.
* @author R. Glattauer, HEPHY
*/
class UnknownCriterion : public KiTrackException{
protected:
UnknownCriterion() { /*no_op*/ ; }
public:
virtual ~UnknownCriterion() { /*no_op*/; }
UnknownCriterion( std::string text ){
message = "KiTrack::UnknownCriterion: " + text ;
}
};
}
#endif
#ifndef Segment_h
#define Segment_h
#include <vector>
#include <list>
#include <string>
#include "KiTrack/IHit.h"
namespace KiTrack{
/** A Segment is something like a track or a part of a track: it consists of hits linked together.
*
* The simplest Segment consists of only one single hit (the truly smallest part of a track),
* a 1-hit-segment.
* A segment of two hits (a 2-hit-segment) is the next bigger version and so on.
*
* Segments are used by the Cellular Automaton (see class Automaton), which uses them to find tracks.
*
* The main difference to a hit (in case of 1-hit-segments) or a track (in case of segments with more hits) is, that
* the segments can have connection to other Segments. They can have children and parents.
* Children are connected Segments on the inside, Parents are connected Segments on the outside.
*
* Inside and outside are w.r.t. the layer a segment is on. Every Segment has a layer (getLayer(), setLayer() ). The
* layer indicates the place of the segment (whereever that place is. e.g. a detector ). Layer 0 usually means inside
* and higher layers are further outside.
*
* Also every Segment has a state. It is another feature requested by the Cellular Automaton. It gives the CA the possibility
* to check the quality of a Segment and manipulate it (the higher the state, usually the better; but for details on
* the states in the Cellular Autoamton see the <a href="../CellularAutomaton.pdf">Introduction to the Cellular Automaton</a> )
*
* Segments can skip layers (a 1-hit-segment can't, since it is just a hit and can only be on one layer, but a
* 2-hit-segment could already be the connection between layer 2 and layer 4, thus skipping a layer).
* For this the state is not only an integer, but a vector of integers representing states for every layer.
* (the 2-hit-segment skipping layer number 3 can therefore be imagined as two 2-hit-segments, each of them having
* a seperate state )
*
*/
class Segment {
public:
Segment( std::vector <IHit*> hits);
Segment( IHit* hit);
void deleteParent ( Segment* delParent ){ _parents.remove( delParent );};
void deleteChild ( Segment* delChild ){ _children.remove( delChild );};
std::list <Segment*> getChildren() { return _children;};
std::list <Segment*> getParents() { return _parents;};
std::vector <IHit*> getHits()const {return _hits;};
void addChild( Segment* child ){ _children.push_back(child); };
void addParent( Segment* parent ){ _parents.push_back(parent); };
unsigned getLayer()const { return _layer; };
void setLayer( unsigned layer ) { _layer = layer; };
std::vector<int>& getState() { return _state; };
void raiseState() { if (_state.size() > 0) _state[0]++; };
int getInnerState()const { return _state[0];};
int getOuterState()const { return _state.back();};
void resetState();
void setSkippedLayers( unsigned skippedLayers ){ _state.resize( skippedLayers + 1 );}
bool isActive() const { return _active;}
void setActive( bool active ){ _active = active; }
/** @return infos about the segment */
std::string getInfo();
private:
std::list <Segment*> _children{};
std::list <Segment*> _parents{};
std::vector <IHit*> _hits{};
std::vector<int> _state{};
unsigned _layer{};
bool _active{};
};
} //end of KiTrack Namespace
#endif
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment